summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2009-04-13 03:08:11 +0000
committergonzo <gonzo@FreeBSD.org>2009-04-13 03:08:11 +0000
commit16b2e4b851fc13d49105bf544ef5f7d89526ed3a (patch)
tree35d65244575c98974af52810da6153780138e0d6
parent2288c0b1828fa2a4aad02035be45876fc1eca752 (diff)
parent67227c12c0e0a27755a06861b476815955bd8b2b (diff)
downloadFreeBSD-src-16b2e4b851fc13d49105bf544ef5f7d89526ed3a.zip
FreeBSD-src-16b2e4b851fc13d49105bf544ef5f7d89526ed3a.tar.gz
- Merge from HEAD
-rw-r--r--MAINTAINERS2
-rw-r--r--Makefile4
-rw-r--r--Makefile.inc1135
-rw-r--r--ObsoleteFiles.inc45
-rw-r--r--UPDATING65
-rw-r--r--bin/cat/Makefile1
-rw-r--r--bin/sh/alias.c66
-rw-r--r--bin/sh/eval.c3
-rw-r--r--bin/sh/miscbltin.c80
-rw-r--r--cddl/Makefile.inc2
-rw-r--r--cddl/lib/libzpool/Makefile4
-rw-r--r--cddl/usr.bin/ztest/Makefile4
-rw-r--r--cddl/usr.sbin/zdb/Makefile4
-rw-r--r--contrib/bind9/CHANGES5
-rw-r--r--contrib/bind9/lib/dns/validator.c79
-rw-r--r--contrib/bind9/version4
-rw-r--r--contrib/csup/rcsfile.c157
-rw-r--r--contrib/csup/rcsfile.h4
-rw-r--r--contrib/csup/rcsparse.c2
-rw-r--r--contrib/csup/updater.c57
-rw-r--r--contrib/gcc/c-cppbuiltin.c8
-rw-r--r--contrib/gcc/c-decl.c206
-rw-r--r--contrib/gcc/c-opts.c12
-rw-r--r--contrib/gcc/c-tree.h1
-rw-r--r--contrib/gcc/c-typeck.c13
-rw-r--r--contrib/gcc/doc/extend.texi115
-rw-r--r--contrib/gdb/FREEBSD-Xlist119
-rw-r--r--contrib/libpcap/CHANGES63
-rw-r--r--contrib/libpcap/CREDITS210
-rw-r--r--contrib/libpcap/FILES124
-rw-r--r--contrib/libpcap/FREEBSD-Xlist7
-rw-r--r--contrib/libpcap/INSTALL.txt77
-rw-r--r--contrib/libpcap/Makefile.in366
-rw-r--r--contrib/libpcap/README42
-rw-r--r--contrib/libpcap/README.Win3246
-rw-r--r--contrib/libpcap/README.aix78
-rw-r--r--contrib/libpcap/README.dag114
-rw-r--r--contrib/libpcap/README.hpux254
-rw-r--r--contrib/libpcap/README.linux88
-rw-r--r--contrib/libpcap/README.macosx43
-rw-r--r--contrib/libpcap/README.septel50
-rw-r--r--contrib/libpcap/README.tru6449
-rw-r--r--contrib/libpcap/VERSION2
-rw-r--r--contrib/libpcap/acsite.m4505
-rw-r--r--contrib/libpcap/atmuni31.h14
-rw-r--r--contrib/libpcap/bpf/net/bpf_filter.c163
-rw-r--r--contrib/libpcap/bpf_dump.c4
-rw-r--r--contrib/libpcap/bpf_image.c2
-rwxr-xr-xcontrib/libpcap/chmod_bpf19
-rw-r--r--contrib/libpcap/config.h.in54
-rwxr-xr-xcontrib/libpcap/configure2302
-rwxr-xr-xcontrib/libpcap/configure.in426
-rw-r--r--contrib/libpcap/dlpisubs.c349
-rw-r--r--contrib/libpcap/dlpisubs.h28
-rw-r--r--contrib/libpcap/doc/pcap.html997
-rw-r--r--contrib/libpcap/doc/pcap.txt1680
-rw-r--r--contrib/libpcap/doc/pcap.xml746
-rw-r--r--contrib/libpcap/etherent.c4
-rw-r--r--contrib/libpcap/ethertype.h2
-rw-r--r--contrib/libpcap/fad-getad.c2
-rw-r--r--contrib/libpcap/fad-gifc.c3
-rw-r--r--contrib/libpcap/fad-glifc.c6
-rw-r--r--contrib/libpcap/fad-sita.c61
-rw-r--r--contrib/libpcap/fad-win32.c11
-rw-r--r--contrib/libpcap/filtertest.c254
-rw-r--r--contrib/libpcap/findalldevstest.c131
-rw-r--r--contrib/libpcap/gencode.c2411
-rw-r--r--contrib/libpcap/gencode.h9
-rw-r--r--contrib/libpcap/grammar.y198
-rw-r--r--contrib/libpcap/ieee80211.h146
-rw-r--r--contrib/libpcap/inet.c67
-rw-r--r--contrib/libpcap/missing/snprintf.c632
-rwxr-xr-xcontrib/libpcap/mkdep2
-rw-r--r--contrib/libpcap/nametoaddr.c16
-rw-r--r--contrib/libpcap/net/bpf_filter.c666
-rw-r--r--contrib/libpcap/optimize.c26
-rw-r--r--contrib/libpcap/packaging/pcap.spec.in15
-rw-r--r--contrib/libpcap/pcap-bpf.c1829
-rw-r--r--contrib/libpcap/pcap-bpf.h797
-rw-r--r--contrib/libpcap/pcap-bt-linux.c372
-rw-r--r--contrib/libpcap/pcap-bt-linux.h40
-rw-r--r--contrib/libpcap/pcap-config.154
-rw-r--r--contrib/libpcap/pcap-config.in16
-rw-r--r--contrib/libpcap/pcap-dag.c695
-rw-r--r--contrib/libpcap/pcap-dag.h90
-rw-r--r--contrib/libpcap/pcap-dlpi.c554
-rw-r--r--contrib/libpcap/pcap-dos.c89
-rw-r--r--contrib/libpcap/pcap-enet.c4
-rw-r--r--contrib/libpcap/pcap-filter.manmisc949
-rw-r--r--contrib/libpcap/pcap-filter.manmisc.in949
-rw-r--r--contrib/libpcap/pcap-int.h165
-rw-r--r--contrib/libpcap/pcap-libdlpi.c370
-rw-r--r--contrib/libpcap/pcap-linktype.manmisc282
-rw-r--r--contrib/libpcap/pcap-linktype.manmisc.in282
-rw-r--r--contrib/libpcap/pcap-linux.c2511
-rw-r--r--contrib/libpcap/pcap-namedb.h59
-rw-r--r--contrib/libpcap/pcap-nit.c78
-rw-r--r--contrib/libpcap/pcap-nit.h19
-rw-r--r--contrib/libpcap/pcap-null.c7
-rw-r--r--contrib/libpcap/pcap-pf.c93
-rw-r--r--contrib/libpcap/pcap-pf.h19
-rw-r--r--contrib/libpcap/pcap-savefile.manfile127
-rw-r--r--contrib/libpcap/pcap-savefile.manfile.in127
-rw-r--r--contrib/libpcap/pcap-septel.c51
-rw-r--r--contrib/libpcap/pcap-septel.h4
-rw-r--r--contrib/libpcap/pcap-sita.c980
-rw-r--r--contrib/libpcap/pcap-sita.h10
-rw-r--r--contrib/libpcap/pcap-sita.html943
-rw-r--r--contrib/libpcap/pcap-snit.c72
-rw-r--r--contrib/libpcap/pcap-snoop.c121
-rw-r--r--contrib/libpcap/pcap-stdinc.h26
-rw-r--r--contrib/libpcap/pcap-usb-linux.c730
-rw-r--r--contrib/libpcap/pcap-usb-linux.h40
-rw-r--r--contrib/libpcap/pcap-win32.c258
-rw-r--r--contrib/libpcap/pcap.31332
-rw-r--r--contrib/libpcap/pcap.3pcap386
-rw-r--r--contrib/libpcap/pcap.3pcap.in386
-rw-r--r--contrib/libpcap/pcap.c522
-rw-r--r--contrib/libpcap/pcap.h281
-rw-r--r--contrib/libpcap/pcap/bluetooth.h48
-rw-r--r--contrib/libpcap/pcap/bpf.h934
-rw-r--r--contrib/libpcap/pcap/namedb.h89
-rw-r--r--contrib/libpcap/pcap/pcap.h (renamed from contrib/libpcap/pcap1.h)261
-rw-r--r--contrib/libpcap/pcap/sll.h (renamed from contrib/libpcap/sll.h)11
-rw-r--r--contrib/libpcap/pcap/usb.h90
-rw-r--r--contrib/libpcap/pcap/vlan.h (renamed from usr.sbin/sliplogin/pathnames.h)28
-rw-r--r--contrib/libpcap/pcap_activate.3pcap89
-rw-r--r--contrib/libpcap/pcap_breakloop.3pcap105
-rw-r--r--contrib/libpcap/pcap_can_set_rfmon.3pcap60
-rw-r--r--contrib/libpcap/pcap_close.3pcap41
-rw-r--r--contrib/libpcap/pcap_compile.3pcap72
-rw-r--r--contrib/libpcap/pcap_compile.3pcap.in72
-rw-r--r--contrib/libpcap/pcap_create.3pcap74
-rw-r--r--contrib/libpcap/pcap_datalink.3pcap41
-rw-r--r--contrib/libpcap/pcap_datalink.3pcap.in41
-rw-r--r--contrib/libpcap/pcap_datalink_name_to_val.3pcap48
-rw-r--r--contrib/libpcap/pcap_datalink_val_to_name.3pcap44
-rw-r--r--contrib/libpcap/pcap_dump.3pcap53
-rw-r--r--contrib/libpcap/pcap_dump_close.3pcap39
-rw-r--r--contrib/libpcap/pcap_dump_file.3pcap40
-rw-r--r--contrib/libpcap/pcap_dump_flush.3pcap45
-rw-r--r--contrib/libpcap/pcap_dump_ftell.3pcap44
-rw-r--r--contrib/libpcap/pcap_dump_open.3pcap87
-rw-r--r--contrib/libpcap/pcap_dump_open.3pcap.in87
-rw-r--r--contrib/libpcap/pcap_file.3pcap59
-rw-r--r--contrib/libpcap/pcap_fileno.3pcap47
-rw-r--r--contrib/libpcap/pcap_findalldevs.3pcap156
-rw-r--r--contrib/libpcap/pcap_free_datalinks.3pcap41
-rw-r--r--contrib/libpcap/pcap_freealldevs.3pcap40
-rw-r--r--contrib/libpcap/pcap_freecode.3pcap45
-rw-r--r--contrib/libpcap/pcap_get_selectable_fd.3pcap114
-rw-r--r--contrib/libpcap/pcap_geterr.3pcap53
-rw-r--r--contrib/libpcap/pcap_inject.3pcap90
-rw-r--r--contrib/libpcap/pcap_is_swapped.3pcap42
-rw-r--r--contrib/libpcap/pcap_lib_version.3pcap41
-rw-r--r--contrib/libpcap/pcap_list_datalinks.3pcap58
-rw-r--r--contrib/libpcap/pcap_list_datalinks.3pcap.in58
-rw-r--r--contrib/libpcap/pcap_lookupdev.3pcap62
-rw-r--r--contrib/libpcap/pcap_lookupnet.3pcap65
-rw-r--r--contrib/libpcap/pcap_loop.3pcap150
-rw-r--r--contrib/libpcap/pcap_major_version.3pcap54
-rw-r--r--contrib/libpcap/pcap_next_ex.3pcap90
-rw-r--r--contrib/libpcap/pcap_offline_filter.3pcap57
-rw-r--r--contrib/libpcap/pcap_open_dead.3pcap52
-rw-r--r--contrib/libpcap/pcap_open_dead.3pcap.in52
-rw-r--r--contrib/libpcap/pcap_open_live.3pcap89
-rw-r--r--contrib/libpcap/pcap_open_offline.3pcap78
-rw-r--r--contrib/libpcap/pcap_open_offline.3pcap.in78
-rw-r--r--contrib/libpcap/pcap_set_buffer_size.3pcap47
-rw-r--r--contrib/libpcap/pcap_set_datalink.3pcap52
-rw-r--r--contrib/libpcap/pcap_set_promisc.3pcap48
-rw-r--r--contrib/libpcap/pcap_set_rfmon.3pcap49
-rw-r--r--contrib/libpcap/pcap_set_snaplen.3pcap46
-rw-r--r--contrib/libpcap/pcap_set_timeout.3pcap47
-rw-r--r--contrib/libpcap/pcap_setdirection.3pcap71
-rw-r--r--contrib/libpcap/pcap_setfilter.3pcap54
-rw-r--r--contrib/libpcap/pcap_setnonblock.3pcap75
-rw-r--r--contrib/libpcap/pcap_snapshot.3pcap44
-rw-r--r--contrib/libpcap/pcap_stats.3pcap59
-rw-r--r--contrib/libpcap/pcap_statustostr.3pcap43
-rw-r--r--contrib/libpcap/pcap_strerror.3pcap42
-rwxr-xr-xcontrib/libpcap/runlex.sh235
-rw-r--r--contrib/libpcap/savefile.c285
-rw-r--r--contrib/libpcap/scanner.l21
-rw-r--r--contrib/tcpdump/CHANGES44
-rw-r--r--contrib/tcpdump/CREDITS295
-rw-r--r--contrib/tcpdump/FILES251
-rw-r--r--contrib/tcpdump/FREEBSD-Xlist3
-rw-r--r--contrib/tcpdump/INSTALL.txt (renamed from contrib/tcpdump/INSTALL)8
-rw-r--r--contrib/tcpdump/Makefile-devel-adds22
-rw-r--r--contrib/tcpdump/Makefile.in219
-rw-r--r--contrib/tcpdump/PLATFORMS9
-rw-r--r--contrib/tcpdump/README14
-rw-r--r--contrib/tcpdump/Readme.Win3224
-rw-r--r--contrib/tcpdump/TODO6
-rw-r--r--contrib/tcpdump/VERSION2
-rw-r--r--contrib/tcpdump/addrtoname.c14
-rw-r--r--contrib/tcpdump/addrtoname.h13
-rw-r--r--contrib/tcpdump/af.c2
-rw-r--r--contrib/tcpdump/af.h2
-rw-r--r--contrib/tcpdump/aodv.h2
-rw-r--r--contrib/tcpdump/appletalk.h2
-rw-r--r--contrib/tcpdump/arcnet.h2
-rw-r--r--contrib/tcpdump/atm.h3
-rw-r--r--contrib/tcpdump/atmuni31.h14
-rwxr-xr-xcontrib/tcpdump/bgp.h2
-rw-r--r--contrib/tcpdump/bootp.h2
-rw-r--r--contrib/tcpdump/bpf_dump.c4
-rw-r--r--contrib/tcpdump/chdlc.h2
-rw-r--r--contrib/tcpdump/checksum.c137
-rw-r--r--contrib/tcpdump/config.h.in6
-rwxr-xr-xcontrib/tcpdump/configure589
-rwxr-xr-xcontrib/tcpdump/configure.in161
-rw-r--r--contrib/tcpdump/dccp.h6
-rw-r--r--contrib/tcpdump/decnet.h2
-rw-r--r--contrib/tcpdump/enc.h2
-rw-r--r--contrib/tcpdump/ether.h2
-rw-r--r--contrib/tcpdump/ethertype.h18
-rw-r--r--contrib/tcpdump/extract.h6
-rw-r--r--contrib/tcpdump/fddi.h2
-rw-r--r--contrib/tcpdump/gmpls.c26
-rw-r--r--contrib/tcpdump/gmpls.h12
-rw-r--r--contrib/tcpdump/gmt2local.c2
-rw-r--r--contrib/tcpdump/gmt2local.h2
-rw-r--r--contrib/tcpdump/icmp6.h4
-rw-r--r--contrib/tcpdump/ieee802_11.h2
-rw-r--r--contrib/tcpdump/ieee802_11_radio.h2
-rw-r--r--contrib/tcpdump/igrp.h2
-rw-r--r--contrib/tcpdump/interface.h32
-rw-r--r--contrib/tcpdump/ip.h2
-rw-r--r--contrib/tcpdump/ip6.h4
-rw-r--r--contrib/tcpdump/ipfc.h2
-rwxr-xr-xcontrib/tcpdump/ipproto.c2
-rw-r--r--contrib/tcpdump/ipproto.h3
-rw-r--r--contrib/tcpdump/ipsec_doi.h2
-rw-r--r--contrib/tcpdump/ipx.h2
-rw-r--r--contrib/tcpdump/isakmp.h149
-rw-r--r--contrib/tcpdump/l2tp.h2
-rwxr-xr-xcontrib/tcpdump/l2vpn.c2
-rwxr-xr-xcontrib/tcpdump/l2vpn.h2
-rw-r--r--contrib/tcpdump/lane.h2
-rw-r--r--contrib/tcpdump/lbl/os-osf4.h2
-rw-r--r--contrib/tcpdump/lbl/os-solaris2.h2
-rw-r--r--contrib/tcpdump/lbl/os-sunos4.h2
-rw-r--r--contrib/tcpdump/lbl/os-ultrix4.h2
-rw-r--r--contrib/tcpdump/llc.h4
-rw-r--r--contrib/tcpdump/machdep.c2
-rw-r--r--contrib/tcpdump/machdep.h2
-rwxr-xr-xcontrib/tcpdump/makemib2
-rw-r--r--contrib/tcpdump/missing/addrinfo.h2
-rw-r--r--contrib/tcpdump/missing/datalinks.c2
-rw-r--r--contrib/tcpdump/missing/dlnames.c2
-rw-r--r--contrib/tcpdump/missing/getaddrinfo.c2
-rw-r--r--contrib/tcpdump/missing/getnameinfo.c2
-rw-r--r--contrib/tcpdump/missing/inet_aton.c4
-rw-r--r--contrib/tcpdump/missing/inet_ntop.c4
-rw-r--r--contrib/tcpdump/missing/inet_pton.c4
-rw-r--r--contrib/tcpdump/missing/snprintf.c4
-rw-r--r--contrib/tcpdump/missing/strdup.c2
-rw-r--r--contrib/tcpdump/missing/strlcat.c2
-rw-r--r--contrib/tcpdump/missing/strlcpy.c2
-rw-r--r--contrib/tcpdump/missing/strsep.c2
-rw-r--r--contrib/tcpdump/mpls.h2
-rw-r--r--contrib/tcpdump/nameser.h2
-rw-r--r--contrib/tcpdump/netbios.h2
-rw-r--r--contrib/tcpdump/netdissect.h12
-rw-r--r--contrib/tcpdump/nfs.h19
-rw-r--r--contrib/tcpdump/nfsfh.h2
-rwxr-xr-xcontrib/tcpdump/nlpid.c2
-rw-r--r--contrib/tcpdump/nlpid.h2
-rw-r--r--contrib/tcpdump/ntp.h2
-rw-r--r--contrib/tcpdump/oakley.h2
-rw-r--r--contrib/tcpdump/ospf.h68
-rw-r--r--contrib/tcpdump/ospf6.h77
-rw-r--r--contrib/tcpdump/oui.c5
-rw-r--r--contrib/tcpdump/oui.h5
-rw-r--r--contrib/tcpdump/parsenfsfh.c2
-rw-r--r--contrib/tcpdump/pcap-missing.h2
-rw-r--r--contrib/tcpdump/pcap_dump_ftell.c2
-rw-r--r--contrib/tcpdump/pmap_prot.h3
-rw-r--r--contrib/tcpdump/ppp.h2
-rw-r--r--contrib/tcpdump/print-802_11.c51
-rw-r--r--contrib/tcpdump/print-ah.c2
-rw-r--r--contrib/tcpdump/print-aodv.c2
-rw-r--r--contrib/tcpdump/print-ap1394.c6
-rw-r--r--contrib/tcpdump/print-arcnet.c2
-rw-r--r--contrib/tcpdump/print-arp.c285
-rw-r--r--contrib/tcpdump/print-ascii.c2
-rw-r--r--contrib/tcpdump/print-atalk.c2
-rw-r--r--contrib/tcpdump/print-atm.c163
-rw-r--r--contrib/tcpdump/print-beep.c2
-rw-r--r--contrib/tcpdump/print-bfd.c2
-rw-r--r--contrib/tcpdump/print-bgp.c457
-rw-r--r--contrib/tcpdump/print-bootp.c16
-rw-r--r--contrib/tcpdump/print-bt.c78
-rw-r--r--contrib/tcpdump/print-cdp.c2
-rw-r--r--contrib/tcpdump/print-cfm.c641
-rw-r--r--contrib/tcpdump/print-chdlc.c2
-rw-r--r--contrib/tcpdump/print-cip.c2
-rw-r--r--contrib/tcpdump/print-cnfp.c2
-rw-r--r--contrib/tcpdump/print-dccp.c71
-rw-r--r--contrib/tcpdump/print-decnet.c2
-rw-r--r--contrib/tcpdump/print-dhcp6.c133
-rw-r--r--contrib/tcpdump/print-domain.c39
-rw-r--r--contrib/tcpdump/print-dtp.c123
-rw-r--r--contrib/tcpdump/print-dvmrp.c2
-rw-r--r--contrib/tcpdump/print-eap.c274
-rw-r--r--contrib/tcpdump/print-egp.c16
-rw-r--r--contrib/tcpdump/print-eigrp.c2
-rw-r--r--contrib/tcpdump/print-enc.c17
-rw-r--r--contrib/tcpdump/print-esp.c2
-rw-r--r--contrib/tcpdump/print-ether.c24
-rw-r--r--contrib/tcpdump/print-fddi.c2
-rw-r--r--contrib/tcpdump/print-fr.c115
-rw-r--r--contrib/tcpdump/print-frag6.c2
-rw-r--r--contrib/tcpdump/print-gre.c2
-rw-r--r--contrib/tcpdump/print-hsrp.c2
-rw-r--r--contrib/tcpdump/print-icmp.c4
-rw-r--r--contrib/tcpdump/print-icmp6.c6
-rw-r--r--contrib/tcpdump/print-igmp.c2
-rw-r--r--contrib/tcpdump/print-igrp.c2
-rw-r--r--contrib/tcpdump/print-ip.c4
-rw-r--r--contrib/tcpdump/print-ip6.c2
-rw-r--r--contrib/tcpdump/print-ip6opts.c2
-rw-r--r--contrib/tcpdump/print-ipcomp.c2
-rw-r--r--contrib/tcpdump/print-ipfc.c2
-rw-r--r--contrib/tcpdump/print-ipx.c2
-rw-r--r--contrib/tcpdump/print-isakmp.c1740
-rw-r--r--contrib/tcpdump/print-isoclns.c156
-rw-r--r--contrib/tcpdump/print-juniper.c467
-rw-r--r--contrib/tcpdump/print-krb.c2
-rw-r--r--contrib/tcpdump/print-l2tp.c2
-rw-r--r--contrib/tcpdump/print-lane.c2
-rw-r--r--contrib/tcpdump/print-ldp.c35
-rw-r--r--contrib/tcpdump/print-llc.c28
-rw-r--r--contrib/tcpdump/print-lldp.c1107
-rw-r--r--contrib/tcpdump/print-lmp.c28
-rw-r--r--contrib/tcpdump/print-lspping.c13
-rw-r--r--contrib/tcpdump/print-lwapp.c360
-rw-r--r--contrib/tcpdump/print-lwres.c2
-rw-r--r--contrib/tcpdump/print-mobile.c2
-rw-r--r--contrib/tcpdump/print-mobility.c2
-rw-r--r--contrib/tcpdump/print-mpcp.c274
-rw-r--r--contrib/tcpdump/print-mpls.c2
-rw-r--r--contrib/tcpdump/print-msdp.c2
-rw-r--r--contrib/tcpdump/print-netbios.c2
-rw-r--r--contrib/tcpdump/print-nfs.c26
-rw-r--r--contrib/tcpdump/print-ntp.c2
-rw-r--r--contrib/tcpdump/print-null.c5
-rw-r--r--contrib/tcpdump/print-ospf.c778
-rw-r--r--contrib/tcpdump/print-ospf6.c596
-rw-r--r--contrib/tcpdump/print-pflog.c7
-rw-r--r--contrib/tcpdump/print-pgm.c2
-rw-r--r--contrib/tcpdump/print-pim.c2
-rw-r--r--contrib/tcpdump/print-ppp.c2
-rw-r--r--contrib/tcpdump/print-pppoe.c2
-rw-r--r--contrib/tcpdump/print-pptp.c2
-rw-r--r--contrib/tcpdump/print-radius.c2
-rw-r--r--contrib/tcpdump/print-raw.c2
-rw-r--r--contrib/tcpdump/print-rip.c19
-rw-r--r--contrib/tcpdump/print-ripng.c2
-rw-r--r--contrib/tcpdump/print-rrcp.c137
-rw-r--r--contrib/tcpdump/print-rsvp.c2
-rw-r--r--contrib/tcpdump/print-rt6.c2
-rw-r--r--contrib/tcpdump/print-rx.c332
-rw-r--r--contrib/tcpdump/print-sctp.c2
-rw-r--r--contrib/tcpdump/print-sflow.c577
-rw-r--r--contrib/tcpdump/print-sip.c2
-rw-r--r--contrib/tcpdump/print-sl.c2
-rw-r--r--contrib/tcpdump/print-sll.c2
-rw-r--r--contrib/tcpdump/print-slow.c465
-rw-r--r--contrib/tcpdump/print-smb.c45
-rw-r--r--contrib/tcpdump/print-snmp.c2
-rw-r--r--contrib/tcpdump/print-stp.c2
-rw-r--r--contrib/tcpdump/print-sunatm.c2
-rw-r--r--contrib/tcpdump/print-sunrpc.c2
-rw-r--r--contrib/tcpdump/print-symantec.c2
-rwxr-xr-xcontrib/tcpdump/print-syslog.c2
-rw-r--r--contrib/tcpdump/print-tcp.c1285
-rw-r--r--contrib/tcpdump/print-telnet.c2
-rw-r--r--contrib/tcpdump/print-tftp.c6
-rw-r--r--contrib/tcpdump/print-timed.c2
-rw-r--r--contrib/tcpdump/print-token.c2
-rw-r--r--contrib/tcpdump/print-udld.c173
-rw-r--r--contrib/tcpdump/print-udp.c12
-rw-r--r--contrib/tcpdump/print-vjc.c2
-rw-r--r--contrib/tcpdump/print-vqp.c209
-rw-r--r--contrib/tcpdump/print-vrrp.c2
-rw-r--r--contrib/tcpdump/print-vtp.c378
-rw-r--r--contrib/tcpdump/print-wb.c2
-rw-r--r--contrib/tcpdump/print-zephyr.c11
-rw-r--r--contrib/tcpdump/route6d.h2
-rw-r--r--contrib/tcpdump/rpc_auth.h3
-rw-r--r--contrib/tcpdump/rpc_msg.h3
-rw-r--r--contrib/tcpdump/rx.h2
-rw-r--r--contrib/tcpdump/sctpConstants.h2
-rw-r--r--contrib/tcpdump/sctpHeader.h2
-rw-r--r--contrib/tcpdump/setsignal.c2
-rw-r--r--contrib/tcpdump/setsignal.h2
-rw-r--r--contrib/tcpdump/slcompress.h2
-rw-r--r--contrib/tcpdump/slip.h2
-rw-r--r--contrib/tcpdump/sll.h6
-rw-r--r--contrib/tcpdump/smb.h2
-rw-r--r--contrib/tcpdump/smbutil.c2
-rw-r--r--contrib/tcpdump/strcasecmp.c2
-rw-r--r--contrib/tcpdump/tcp.h44
-rw-r--r--contrib/tcpdump/tcpdump-stdinc.h2
-rw-r--r--contrib/tcpdump/tcpdump.1864
-rw-r--r--contrib/tcpdump/tcpdump.c385
-rw-r--r--contrib/tcpdump/telnet.h4
-rw-r--r--contrib/tcpdump/tests/.cvsignore11
-rw-r--r--contrib/tcpdump/tests/02-sunrise-sunset-esp.puu34
-rw-r--r--contrib/tcpdump/tests/08-sunrise-sunset-aes.puu36
-rw-r--r--contrib/tcpdump/tests/08-sunrise-sunset-esp2.puu43
-rw-r--r--contrib/tcpdump/tests/alltests.sh12
-rw-r--r--contrib/tcpdump/tests/bgp_vpn_attrset.out18
-rwxr-xr-xcontrib/tcpdump/tests/bgp_vpn_attrset.sh11
-rw-r--r--contrib/tcpdump/tests/eapon1.gdbinit1
-rw-r--r--contrib/tcpdump/tests/eapon1.out114
-rw-r--r--contrib/tcpdump/tests/eapon1.puu368
-rwxr-xr-xcontrib/tcpdump/tests/eapon1.sh13
-rw-r--r--contrib/tcpdump/tests/eapon2.puu66
-rw-r--r--contrib/tcpdump/tests/esp-secrets.txt5
-rw-r--r--contrib/tcpdump/tests/esp0.out8
-rw-r--r--contrib/tcpdump/tests/esp0.sh12
-rw-r--r--contrib/tcpdump/tests/esp1.gdbinit1
-rw-r--r--contrib/tcpdump/tests/esp1.out8
-rw-r--r--contrib/tcpdump/tests/esp1.sh13
-rw-r--r--contrib/tcpdump/tests/esp2.gdbinit1
-rw-r--r--contrib/tcpdump/tests/esp2.out8
-rw-r--r--contrib/tcpdump/tests/esp2.sh13
-rw-r--r--contrib/tcpdump/tests/esp3.gdbinit1
-rw-r--r--contrib/tcpdump/tests/esp3.sh12
-rw-r--r--contrib/tcpdump/tests/esp4.gdbinit2
-rw-r--r--contrib/tcpdump/tests/esp4.sh13
-rw-r--r--contrib/tcpdump/tests/esp5.gdbinit3
-rw-r--r--contrib/tcpdump/tests/esp5.out8
-rw-r--r--contrib/tcpdump/tests/esp5.sh13
-rw-r--r--contrib/tcpdump/tests/espudp1.out8
-rw-r--r--contrib/tcpdump/tests/espudp1.puu35
-rw-r--r--contrib/tcpdump/tests/espudp1.sh13
-rw-r--r--contrib/tcpdump/tests/isakmp-delete-segfault.puu20
-rw-r--r--contrib/tcpdump/tests/isakmp-identification-segfault.puu11
-rw-r--r--contrib/tcpdump/tests/isakmp-pointer-loop.puu6
-rw-r--r--contrib/tcpdump/tests/isakmp1.out1
-rw-r--r--contrib/tcpdump/tests/isakmp1.sh12
-rw-r--r--contrib/tcpdump/tests/isakmp2.out1
-rw-r--r--contrib/tcpdump/tests/isakmp2.sh12
-rw-r--r--contrib/tcpdump/tests/isakmp3.out2
-rw-r--r--contrib/tcpdump/tests/isakmp3.sh13
-rw-r--r--contrib/tcpdump/tests/isakmp4.out35
-rw-r--r--contrib/tcpdump/tests/isakmp4.sh13
-rw-r--r--contrib/tcpdump/tests/isakmp4500.puu155
-rw-r--r--contrib/tcpdump/tests/lmp.out191
-rw-r--r--contrib/tcpdump/tests/lmp.puu42
-rwxr-xr-xcontrib/tcpdump/tests/lmp.sh14
-rw-r--r--contrib/tcpdump/tests/mpls-ldp-hello.out9
-rw-r--r--contrib/tcpdump/tests/mpls-ldp-hello.puu6
-rwxr-xr-xcontrib/tcpdump/tests/mpls-ldp-hello.sh14
-rw-r--r--contrib/tcpdump/tests/ospf-gmpls.out83
-rw-r--r--contrib/tcpdump/tests/ospf-gmpls.puu18
-rwxr-xr-xcontrib/tcpdump/tests/ospf-gmpls.sh14
-rw-r--r--contrib/tcpdump/tests/print-A.out193
-rw-r--r--contrib/tcpdump/tests/print-AA.out193
-rw-r--r--contrib/tcpdump/tests/print-X.out409
-rw-r--r--contrib/tcpdump/tests/print-XX.out419
-rw-r--r--contrib/tcpdump/tests/print-capX.out409
-rw-r--r--contrib/tcpdump/tests/print-capXX.out419
-rw-r--r--contrib/tcpdump/tests/print-flags.puu151
-rwxr-xr-xcontrib/tcpdump/tests/print-flags.sh12
-rw-r--r--contrib/tcpdump/tests/print-x.out409
-rw-r--r--contrib/tcpdump/tests/print-xx.out419
-rw-r--r--contrib/tcpdump/tftp.h4
-rw-r--r--contrib/tcpdump/timed.h9
-rw-r--r--contrib/tcpdump/token.h2
-rw-r--r--contrib/tcpdump/udp.h6
-rw-r--r--contrib/tcpdump/util.c109
-rw-r--r--contrib/tcpdump/vfprintf.c2
-rw-r--r--contrib/wpa/hostapd/wme.h2
-rw-r--r--contrib/wpa/wpa_supplicant/ctrl_iface_unix.c20
-rw-r--r--contrib/wpa/wpa_supplicant/wpa_supplicant.conf21
-rw-r--r--etc/defaults/rc.conf3
-rw-r--r--etc/mail/aliases1
-rw-r--r--etc/mtree/BSD.include.dist2
-rwxr-xr-xetc/netstart1
-rw-r--r--etc/network.subr10
-rwxr-xr-xetc/rc.d/ipfw14
-rw-r--r--gnu/usr.bin/cc/Makefile.inc1
-rw-r--r--include/arpa/inet.h2
-rw-r--r--include/ctype.h2
-rw-r--r--include/db.h68
-rw-r--r--include/dlfcn.h1
-rw-r--r--include/grp.h4
-rw-r--r--include/mpool.h38
-rw-r--r--include/ndbm.h4
-rw-r--r--include/netdb.h54
-rw-r--r--include/pthread.h6
-rw-r--r--include/pwd.h5
-rw-r--r--include/setjmp.h2
-rw-r--r--include/signal.h15
-rw-r--r--include/stdio.h6
-rw-r--r--include/stdlib.h4
-rw-r--r--include/string.h4
-rw-r--r--include/unistd.h9
-rw-r--r--lib/libarchive/Makefile11
-rw-r--r--lib/libarchive/archive.h4
-rw-r--r--lib/libarchive/archive_check_magic.c4
-rw-r--r--lib/libarchive/archive_entry.c2
-rw-r--r--lib/libarchive/archive_entry.h4
-rw-r--r--lib/libarchive/archive_read_disk.3308
-rw-r--r--lib/libarchive/archive_read_disk_set_standard_lookup.c10
-rw-r--r--lib/libarchive/archive_read_support_compression_program.c101
-rw-r--r--lib/libarchive/archive_read_support_format_empty.c12
-rw-r--r--lib/libarchive/archive_string.c301
-rw-r--r--lib/libarchive/archive_string.h6
-rw-r--r--lib/libarchive/archive_write_disk.c24
-rw-r--r--lib/libarchive/archive_write_disk_set_standard_lookup.c4
-rw-r--r--lib/libarchive/archive_write_set_compression_program.c2
-rw-r--r--lib/libarchive/archive_write_set_format_mtree.c6
-rw-r--r--lib/libarchive/test/main.c12
-rw-r--r--lib/libarchive/test/test.h13
-rw-r--r--lib/libarchive/test/test_read_compress_program.c50
-rw-r--r--lib/libarchive/test/test_read_disk.c6
-rw-r--r--lib/libarchive/test/test_read_extract.c6
-rw-r--r--lib/libarchive/test/test_tar_large.c35
-rw-r--r--lib/libarchive/test/test_write_disk.c18
-rw-r--r--lib/libarchive/test/test_write_disk_failures.c2
-rw-r--r--lib/libarchive/test/test_write_disk_hardlink.c21
-rw-r--r--lib/libarchive/test/test_write_disk_perms.c4
-rw-r--r--lib/libarchive/test/test_write_disk_secure.c4
-rw-r--r--lib/libc/Makefile1
-rw-r--r--lib/libc/db/README8
-rw-r--r--lib/libc/db/Symbol.map6
-rw-r--r--lib/libc/db/btree/bt_debug.c36
-rw-r--r--lib/libc/db/btree/bt_open.c37
-rw-r--r--lib/libc/db/btree/bt_page.c2
-rw-r--r--lib/libc/db/btree/bt_put.c4
-rw-r--r--lib/libc/db/btree/bt_split.c7
-rw-r--r--lib/libc/db/db/db.c4
-rw-r--r--lib/libc/db/hash/README5
-rw-r--r--lib/libc/db/hash/hash.c72
-rw-r--r--lib/libc/db/hash/hash.h8
-rw-r--r--lib/libc/db/hash/hash_bigkey.c27
-rw-r--r--lib/libc/db/hash/hash_buf.c39
-rw-r--r--lib/libc/db/hash/hash_func.c106
-rw-r--r--lib/libc/db/hash/hash_log2.c5
-rw-r--r--lib/libc/db/hash/hash_page.c68
-rw-r--r--lib/libc/db/man/mpool.332
-rw-r--r--lib/libc/db/mpool/Makefile.inc2
-rw-r--r--lib/libc/db/mpool/mpool-compat.c (renamed from sys/dev/usb/usb_sw_transfer.h)47
-rw-r--r--lib/libc/db/mpool/mpool.c109
-rw-r--r--lib/libc/db/recno/rec_close.c4
-rw-r--r--lib/libc/db/recno/rec_put.c2
-rw-r--r--lib/libc/gen/Makefile.inc2
-rw-r--r--lib/libc/gen/Symbol.map2
-rw-r--r--lib/libc/gen/dlfcn.c8
-rw-r--r--lib/libc/gen/dlfunc.c30
-rw-r--r--lib/libc/gen/dlopen.311
-rw-r--r--lib/libc/gen/getcap.c12
-rw-r--r--lib/libc/i386/sys/Makefile.inc7
-rw-r--r--lib/libc/net/getaddrinfo.c287
-rw-r--r--lib/libc/nls/Makefile.inc25
-rw-r--r--lib/libc/nls/be_BY.UTF-8.msg249
-rw-r--r--lib/libc/nls/ca_ES.ISO8859-1.msg267
-rw-r--r--lib/libc/nls/de_DE.ISO8859-1.msg249
-rw-r--r--lib/libc/nls/el_GR.ISO8859-7.msg249
-rw-r--r--lib/libc/nls/es_ES.ISO8859-1.msg249
-rw-r--r--lib/libc/nls/fi_FI.ISO8859-1.msg233
-rw-r--r--lib/libc/nls/fr_FR.ISO8859-1.msg249
-rw-r--r--lib/libc/nls/hu_HU.ISO8859-2.msg249
-rw-r--r--lib/libc/nls/it_IT.ISO8859-15.msg231
-rw-r--r--lib/libc/nls/mn_MN.UTF-8.msg249
-rw-r--r--lib/libc/nls/nl_NL.ISO8859-1.msg267
-rw-r--r--lib/libc/nls/no_NO.ISO8859-1.msg231
-rw-r--r--lib/libc/nls/pt_BR.ISO8859-1.msg249
-rw-r--r--lib/libc/nls/ru_RU.KOI8-R.msg8
-rw-r--r--lib/libc/nls/sk_SK.ISO8859-2.msg267
-rw-r--r--lib/libc/nls/sv_SE.ISO8859-1.msg233
-rw-r--r--lib/libc/nls/uk_UA.UTF-8.msg249
-rw-r--r--lib/libc/rpc/clnt_bcast.c2
-rw-r--r--lib/libc/rpc/getnetconfig.c12
-rw-r--r--lib/libc/stdio/getdelim.c6
-rw-r--r--lib/libc/stdio/getline.34
-rw-r--r--lib/libc/string/memchr.33
-rw-r--r--lib/libc/string/memcmp.33
-rw-r--r--lib/libc/string/memcpy.33
-rw-r--r--lib/libc/string/memmove.33
-rw-r--r--lib/libc/string/memset.33
-rw-r--r--lib/libc/string/strcasecmp.33
-rw-r--r--lib/libc/string/strcat.33
-rw-r--r--lib/libc/string/strchr.33
-rw-r--r--lib/libc/string/strcmp.33
-rw-r--r--lib/libc/string/strcpy.33
-rw-r--r--lib/libc/string/strdup.35
-rw-r--r--lib/libc/string/strlcpy.33
-rw-r--r--lib/libc/string/strlen.34
-rw-r--r--lib/libc/string/strpbrk.33
-rw-r--r--lib/libc/string/strspn.33
-rw-r--r--lib/libc/string/strstr.33
-rw-r--r--lib/libc/sys/Symbol.map6
-rw-r--r--lib/libc/sys/ptrace.220
-rw-r--r--lib/libkvm/kvm_powerpc.c225
-rw-r--r--lib/libpcap/Makefile141
-rw-r--r--lib/libpcap/config.h51
-rw-r--r--lib/libpmc/pmc.h3
-rw-r--r--lib/libpmc/pmclog.h3
-rw-r--r--lib/libstand/gets.c2
-rw-r--r--lib/libthr/Makefile1
-rw-r--r--lib/libthr/thread/thr_fork.c5
-rw-r--r--lib/libufs/block.c8
-rw-r--r--lib/libusb/libusb.3446
-rw-r--r--lib/libusb/libusb20.h2
-rw-r--r--lib/msun/src/math.h5
-rw-r--r--lib/msun/src/math_private.h45
-rw-r--r--lib/msun/src/s_cimag.c4
-rw-r--r--lib/msun/src/s_cimagf.c4
-rw-r--r--lib/msun/src/s_cimagl.c4
-rw-r--r--libexec/bootpd/rtmsg.c2
-rw-r--r--libexec/ftpd/extern.h29
-rw-r--r--libexec/ftpd/ftpcmd.y27
-rw-r--r--libexec/ftpd/ftpd.c3
-rw-r--r--libexec/rtld-elf/Symbol.map1
-rw-r--r--libexec/rtld-elf/map_object.c19
-rw-r--r--libexec/rtld-elf/rtld.126
-rw-r--r--libexec/rtld-elf/rtld.c200
-rw-r--r--libexec/rtld-elf/rtld.h5
-rw-r--r--release/doc/en_US.ISO8859-1/hardware/article.sgml4
-rw-r--r--release/doc/ja_JP.eucJP/hardware/common/dev.sgml2
-rw-r--r--release/doc/ru_RU.KOI8-R/hardware/common/dev.sgml2
-rw-r--r--release/doc/share/misc/dev.archlist.txt2
-rw-r--r--release/doc/zh_CN.GB2312/hardware/article.sgml2
-rw-r--r--release/picobsd/bridge/PICOBSD14
-rw-r--r--release/picobsd/bridge/config3
-rw-r--r--release/picobsd/bridge/crunch.conf259
-rwxr-xr-xrelease/picobsd/build/picobsd304
-rw-r--r--release/picobsd/floppy.tree/etc/rc11
-rw-r--r--release/picobsd/mfs_tree/etc/rc2
-rw-r--r--release/picobsd/tinyware/simple_httpd/Makefile1
-rw-r--r--release/picobsd/tinyware/simple_httpd/simple_httpd.c5
-rw-r--r--release/sparc64/mkisoimages.sh4
-rw-r--r--rescue/rescue/Makefile2
-rw-r--r--sbin/Makefile6
-rw-r--r--sbin/fdisk_pc98/fdisk.c6
-rw-r--r--sbin/geom/class/label/glabel.810
-rw-r--r--sbin/gvinum/gvinum.8181
-rw-r--r--sbin/gvinum/gvinum.c619
-rw-r--r--sbin/ifconfig/ifclone.c4
-rw-r--r--sbin/ifconfig/ifconfig.c22
-rw-r--r--sbin/ifconfig/ifgroup.c4
-rw-r--r--sbin/ifconfig/ifieee80211.c10
-rw-r--r--sbin/ipfw/dummynet.c317
-rw-r--r--sbin/ipfw/ipfw.8438
-rw-r--r--sbin/ipfw/ipfw2.c9
-rw-r--r--sbin/ipfw/ipfw2.h2
-rw-r--r--sbin/ipfw/main.c2
-rw-r--r--sbin/newfs_msdos/newfs_msdos.836
-rw-r--r--sbin/newfs_msdos/newfs_msdos.c95
-rw-r--r--sbin/recoverdisk/recoverdisk.c1
-rw-r--r--sbin/route/route.c30
-rw-r--r--sbin/routed/Makefile4
-rw-r--r--sbin/routed/defs.h222
-rw-r--r--sbin/routed/if.c92
-rw-r--r--sbin/routed/input.c6
-rw-r--r--sbin/routed/main.c45
-rw-r--r--sbin/routed/output.c25
-rw-r--r--sbin/routed/parms.c24
-rw-r--r--sbin/routed/radix.c36
-rw-r--r--sbin/routed/radix.h22
-rw-r--r--sbin/routed/rdisc.c15
-rw-r--r--sbin/routed/table.c23
-rw-r--r--sbin/routed/trace.c16
-rw-r--r--sbin/slattach/Makefile12
-rw-r--r--sbin/slattach/slattach.8271
-rw-r--r--sbin/slattach/slattach.c599
-rw-r--r--sbin/startslip/Makefile9
-rw-r--r--sbin/startslip/startslip.1213
-rw-r--r--sbin/startslip/startslip.c595
-rw-r--r--share/man/man3/pthread.314
-rw-r--r--share/man/man4/Makefile12
-rw-r--r--share/man/man4/amdtemp.4 (renamed from share/man/man4/k8temp.4)27
-rw-r--r--share/man/man4/ath.426
-rw-r--r--share/man/man4/ath_hal.412
-rw-r--r--share/man/man4/bce.416
-rw-r--r--share/man/man4/ed.450
-rw-r--r--share/man/man4/fla.459
-rw-r--r--share/man/man4/lagg.413
-rw-r--r--share/man/man4/lo.431
-rw-r--r--share/man/man4/malo.44
-rw-r--r--share/man/man4/man4.i386/fe.48
-rw-r--r--share/man/man4/man4.powerpc/pmu.419
-rw-r--r--share/man/man4/pccbb.44
-rw-r--r--share/man/man4/ppp.484
-rw-r--r--share/man/man4/sl.482
-rw-r--r--share/man/man4/textdump.44
-rw-r--r--share/man/man4/uath.4189
-rw-r--r--share/man/man4/usb.41
-rw-r--r--share/man/man4/uscanner.4164
-rw-r--r--share/man/man4/wlan.45
-rw-r--r--share/man/man4/wpi.42
-rw-r--r--share/man/man5/devfs.rules.54
-rw-r--r--share/man/man5/rc.conf.510
-rw-r--r--share/man/man5/src.conf.511
-rw-r--r--share/man/man7/operator.712
-rw-r--r--share/man/man8/diskless.81
-rw-r--r--share/man/man8/nanobsd.810
-rw-r--r--share/man/man9/Makefile5
-rw-r--r--share/man/man9/VOP_ACCESS.934
-rw-r--r--share/man/man9/VOP_ATTRIB.962
-rw-r--r--share/man/man9/VOP_CREATE.961
-rw-r--r--share/man/man9/VOP_FSYNC.955
-rw-r--r--share/man/man9/VOP_INACTIVE.932
-rw-r--r--share/man/man9/VOP_IOCTL.910
-rw-r--r--share/man/man9/VOP_LEASE.961
-rw-r--r--share/man/man9/VOP_LINK.931
-rw-r--r--share/man/man9/VOP_LOCK.966
-rw-r--r--share/man/man9/VOP_LOOKUP.9254
-rw-r--r--share/man/man9/VOP_OPENCLOSE.912
-rw-r--r--share/man/man9/VOP_RDWR.9135
-rw-r--r--share/man/man9/VOP_READDIR.964
-rw-r--r--share/man/man9/VOP_READLINK.915
-rw-r--r--share/man/man9/VOP_REMOVE.921
-rw-r--r--share/man/man9/VOP_RENAME.9199
-rw-r--r--share/man/man9/VOP_VPTOCNP.924
-rw-r--r--share/man/man9/acl.960
-rw-r--r--share/man/man9/bus_dma.918
-rw-r--r--share/man/man9/refcount.996
-rw-r--r--share/man/man9/vm_map_lock.96
-rw-r--r--share/misc/committers-ports.dot3
-rw-r--r--share/misc/committers-src.dot2
-rw-r--r--share/misc/iso316648
-rw-r--r--share/misc/operator36
-rw-r--r--share/mk/bsd.cpu.mk2
-rw-r--r--share/mk/bsd.own.mk1
-rw-r--r--share/mk/bsd.sys.mk17
-rw-r--r--share/skel/dot.login2
-rw-r--r--share/skel/dot.profile2
-rw-r--r--share/timedef/Makefile5
-rw-r--r--share/zoneinfo/africa81
-rw-r--r--share/zoneinfo/asia25
-rw-r--r--share/zoneinfo/northamerica24
-rw-r--r--share/zoneinfo/southamerica49
-rw-r--r--sys/amd64/acpica/Makefile33
-rw-r--r--sys/amd64/acpica/acpi_machdep.c28
-rw-r--r--sys/amd64/acpica/acpi_switch.S190
-rw-r--r--sys/amd64/acpica/acpi_wakecode.S286
-rw-r--r--sys/amd64/acpica/acpi_wakeup.c376
-rwxr-xr-xsys/amd64/acpica/genwakecode.sh6
-rwxr-xr-xsys/amd64/acpica/genwakedata.sh9
-rw-r--r--sys/amd64/amd64/amd64_mem.c28
-rw-r--r--sys/amd64/amd64/apic_vector.S17
-rw-r--r--sys/amd64/amd64/cpu_switch.S213
-rw-r--r--sys/amd64/amd64/db_interface.c10
-rw-r--r--sys/amd64/amd64/db_trace.c8
-rw-r--r--sys/amd64/amd64/elf_machdep.c6
-rw-r--r--sys/amd64/amd64/exception.S197
-rw-r--r--sys/amd64/amd64/fpu.c24
-rw-r--r--sys/amd64/amd64/genassym.c38
-rw-r--r--sys/amd64/amd64/machdep.c369
-rw-r--r--sys/amd64/amd64/mp_machdep.c60
-rw-r--r--sys/amd64/amd64/pmap.c22
-rw-r--r--sys/amd64/amd64/sys_machdep.c581
-rw-r--r--sys/amd64/amd64/trap.c95
-rw-r--r--sys/amd64/amd64/vm_machdep.c102
-rw-r--r--sys/amd64/conf/GENERIC3
-rw-r--r--sys/amd64/conf/NOTES4
-rw-r--r--sys/amd64/ia32/ia32_exception.S5
-rw-r--r--sys/amd64/ia32/ia32_misc.c (renamed from sys/mips/atheros/uart_cpu_ar71xx.c)75
-rw-r--r--sys/amd64/ia32/ia32_reg.c35
-rw-r--r--sys/amd64/ia32/ia32_signal.c87
-rw-r--r--sys/amd64/ia32/ia32_sigtramp.S4
-rw-r--r--sys/amd64/include/apicvar.h1
-rw-r--r--sys/amd64/include/asmacros.h7
-rw-r--r--sys/amd64/include/cpufunc.h101
-rw-r--r--sys/amd64/include/elf.h6
-rw-r--r--sys/amd64/include/endian.h42
-rw-r--r--sys/amd64/include/frame.h11
-rw-r--r--sys/amd64/include/md_var.h13
-rw-r--r--sys/amd64/include/pcb.h19
-rw-r--r--sys/amd64/include/pcpu.h12
-rw-r--r--sys/amd64/include/pmap.h12
-rw-r--r--sys/amd64/include/proc.h21
-rw-r--r--sys/amd64/include/reg.h8
-rw-r--r--sys/amd64/include/segments.h42
-rw-r--r--sys/amd64/include/signal.h14
-rw-r--r--sys/amd64/include/smp.h2
-rw-r--r--sys/amd64/include/sysarch.h30
-rw-r--r--sys/amd64/include/ucontext.h24
-rw-r--r--sys/amd64/linux32/linux.h4
-rw-r--r--sys/amd64/linux32/linux32_locore.s4
-rw-r--r--sys/amd64/linux32/linux32_machdep.c9
-rw-r--r--sys/amd64/linux32/linux32_sysvec.c86
-rw-r--r--sys/amd64/pci/pci_cfgreg.c2
-rw-r--r--sys/arm/arm/elf_machdep.c6
-rw-r--r--sys/arm/arm/locore.S4
-rw-r--r--sys/arm/arm/trap.c5
-rw-r--r--sys/arm/at91/files.at912
-rw-r--r--sys/arm/conf/AVILA1
-rw-r--r--sys/arm/conf/CAMBRIA1
-rw-r--r--sys/arm/conf/HL2001
-rw-r--r--sys/arm/conf/KB920X1
-rw-r--r--sys/arm/include/atomic.h19
-rw-r--r--sys/arm/include/elf.h3
-rw-r--r--sys/arm/include/vmparam.h2
-rw-r--r--sys/boot/forth/loader.conf4
-rw-r--r--sys/boot/i386/libi386/Makefile4
-rw-r--r--sys/boot/i386/libi386/bioscd.c112
-rw-r--r--sys/boot/i386/libi386/biosdisk.c8
-rw-r--r--sys/boot/i386/libi386/libi386.h8
-rw-r--r--sys/boot/i386/libi386/smbios.c376
-rw-r--r--sys/boot/pc98/libpc98/Makefile5
-rw-r--r--sys/boot/pc98/libpc98/bioscd.c102
-rw-r--r--sys/boot/pc98/libpc98/biosdisk.c69
-rw-r--r--sys/boot/pc98/libpc98/time.c31
-rw-r--r--sys/boot/pc98/loader/Makefile1
-rw-r--r--sys/boot/pc98/loader/main.c19
-rw-r--r--sys/cddl/compat/opensolaris/sys/vnode.h1
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c2
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c2
-rw-r--r--sys/compat/freebsd32/freebsd32.h6
-rw-r--r--sys/compat/freebsd32/freebsd32_ioctl.c20
-rw-r--r--sys/compat/freebsd32/freebsd32_ioctl.h6
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c3
-rw-r--r--sys/compat/freebsd32/freebsd32_proto.h8
-rw-r--r--sys/compat/freebsd32/freebsd32_syscall.h4
-rw-r--r--sys/compat/freebsd32/freebsd32_syscalls.c4
-rw-r--r--sys/compat/freebsd32/freebsd32_sysent.c4
-rw-r--r--sys/compat/freebsd32/syscalls.master2
-rw-r--r--sys/compat/ia32/ia32_signal.h4
-rw-r--r--sys/compat/ia32/ia32_sysvec.c27
-rw-r--r--sys/compat/linprocfs/linprocfs.c72
-rw-r--r--sys/compat/linux/linux_emul.h2
-rw-r--r--sys/compat/linux/linux_file.c9
-rw-r--r--sys/compat/linux/linux_futex.c18
-rw-r--r--sys/compat/linux/linux_futex.h2
-rw-r--r--sys/compat/ndis/subr_ntoskrnl.c19
-rw-r--r--sys/compat/ndis/subr_usbd.c353
-rw-r--r--sys/compat/svr4/svr4_sysvec.c1
-rw-r--r--sys/conf/Makefile.mips48
-rw-r--r--sys/conf/NOTES18
-rw-r--r--sys/conf/files158
-rw-r--r--sys/conf/files.amd6418
-rw-r--r--sys/conf/files.i3868
-rw-r--r--sys/conf/files.ia641
-rw-r--r--sys/conf/files.mips4
-rw-r--r--sys/conf/files.pc982
-rw-r--r--sys/conf/files.powerpc13
-rw-r--r--sys/conf/ldscript.mips2
-rw-r--r--sys/conf/newvers.sh8
-rw-r--r--sys/conf/options5
-rw-r--r--sys/conf/options.mips4
-rw-r--r--sys/contrib/dev/uath/ar5523.bin.uu3359
-rw-r--r--sys/contrib/pf/net/pf.c28
-rw-r--r--sys/dev/acpi_support/acpi_asus.c36
-rw-r--r--sys/dev/acpica/acpi.c113
-rw-r--r--sys/dev/acpica/acpi_cpu.c6
-rw-r--r--sys/dev/acpica/acpi_ec.c2
-rw-r--r--sys/dev/acpica/acpivar.h1
-rw-r--r--sys/dev/age/if_age.c234
-rw-r--r--sys/dev/age/if_agereg.h3
-rw-r--r--sys/dev/agp/agp.c2
-rw-r--r--sys/dev/agp/agp_amd64.c4
-rw-r--r--sys/dev/agp/agp_i810.c6
-rw-r--r--sys/dev/agp/agp_intel.c4
-rw-r--r--sys/dev/agp/agp_via.c4
-rw-r--r--sys/dev/amdtemp/amdtemp.c (renamed from sys/dev/k8temp/k8temp.c)207
-rw-r--r--sys/dev/ata/ata-pci.c15
-rw-r--r--sys/dev/ata/ata-pci.h8
-rw-r--r--sys/dev/ata/ata-queue.c3
-rw-r--r--sys/dev/ata/ata-sata.c177
-rw-r--r--sys/dev/ata/chipsets/ata-ahci.c159
-rw-r--r--sys/dev/ata/chipsets/ata-intel.c2
-rw-r--r--sys/dev/ata/chipsets/ata-jmicron.c28
-rw-r--r--sys/dev/ata/chipsets/ata-marvell.c2
-rw-r--r--sys/dev/ata/chipsets/ata-nvidia.c2
-rw-r--r--sys/dev/ata/chipsets/ata-promise.c4
-rw-r--r--sys/dev/ata/chipsets/ata-serverworks.c23
-rw-r--r--sys/dev/ata/chipsets/ata-siliconimage.c4
-rw-r--r--sys/dev/ata/chipsets/ata-sis.c2
-rw-r--r--sys/dev/ata/chipsets/ata-via.c2
-rw-r--r--sys/dev/ath/ah_osdep.c29
-rw-r--r--sys/dev/ath/ath_hal/ah.h2
-rw-r--r--sys/dev/ath/ath_hal/ah_internal.h6
-rw-r--r--sys/dev/ath/ath_hal/ar5210/ar5210_attach.c1
-rw-r--r--sys/dev/ath/ath_hal/ar5211/ar5211_attach.c1
-rw-r--r--sys/dev/ath/ath_hal/ar5212/ar5212_attach.c1
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416.h7
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_attach.c303
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_reset.c661
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar9280.c361
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar9280.h40
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar9280_attach.c738
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar9280v1.ini582
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar9280v2.ini941
-rw-r--r--sys/dev/ath/if_ath.c513
-rw-r--r--sys/dev/ath/if_athvar.h60
-rw-r--r--sys/dev/atkbdc/psm.c23
-rw-r--r--sys/dev/bge/if_bge.c84
-rw-r--r--sys/dev/bge/if_bgereg.h21
-rw-r--r--sys/dev/cardbus/cardbus_cis.c20
-rw-r--r--sys/dev/cxgb/cxgb_main.c23
-rw-r--r--sys/dev/cxgb/cxgb_offload.c3
-rw-r--r--sys/dev/cxgb/cxgb_sge.c1
-rw-r--r--sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c2
-rw-r--r--sys/dev/dc/dcphy.c14
-rw-r--r--sys/dev/dc/pnphy.c17
-rw-r--r--sys/dev/dcons/dcons_os.c6
-rw-r--r--sys/dev/drm/ati_pcigart.c19
-rw-r--r--sys/dev/drm/drmP.h23
-rw-r--r--sys/dev/drm/drm_bufs.c4
-rw-r--r--sys/dev/drm/drm_drv.c10
-rw-r--r--sys/dev/drm/drm_irq.c89
-rw-r--r--sys/dev/drm/drm_linux_list.h4
-rw-r--r--sys/dev/drm/drm_lock.c9
-rw-r--r--sys/dev/drm/drm_pci.c2
-rw-r--r--sys/dev/drm/drm_pciids.h4
-rw-r--r--sys/dev/drm/drm_scatter.c9
-rw-r--r--sys/dev/drm/drm_vm.c10
-rw-r--r--sys/dev/drm/i915_dma.c27
-rw-r--r--sys/dev/drm/i915_drv.c5
-rw-r--r--sys/dev/drm/i915_drv.h7
-rw-r--r--sys/dev/drm/i915_irq.c190
-rw-r--r--sys/dev/drm/i915_reg.h51
-rw-r--r--sys/dev/drm/i915_suspend.c28
-rw-r--r--sys/dev/drm/mga_irq.c3
-rw-r--r--sys/dev/drm/r300_cmdbuf.c10
-rw-r--r--sys/dev/drm/r300_reg.h5
-rw-r--r--sys/dev/drm/r600_cp.c232
-rw-r--r--sys/dev/drm/radeon_cp.c141
-rw-r--r--sys/dev/drm/radeon_drv.h1
-rw-r--r--sys/dev/drm/radeon_irq.c4
-rw-r--r--sys/dev/e1000/e1000_80003es2lan.c69
-rw-r--r--sys/dev/e1000/e1000_82540.c6
-rw-r--r--sys/dev/e1000/e1000_82541.c6
-rw-r--r--sys/dev/e1000/e1000_82571.c367
-rw-r--r--sys/dev/e1000/e1000_82575.c387
-rw-r--r--sys/dev/e1000/e1000_82575.h101
-rw-r--r--sys/dev/e1000/e1000_api.c39
-rw-r--r--sys/dev/e1000/e1000_api.h6
-rw-r--r--sys/dev/e1000/e1000_defines.h26
-rw-r--r--sys/dev/e1000/e1000_hw.h59
-rw-r--r--sys/dev/e1000/e1000_ich8lan.c187
-rw-r--r--sys/dev/e1000/e1000_ich8lan.h37
-rw-r--r--sys/dev/e1000/e1000_mac.c117
-rw-r--r--sys/dev/e1000/e1000_mac.h8
-rw-r--r--sys/dev/e1000/e1000_nvm.c34
-rw-r--r--sys/dev/e1000/e1000_nvm.h3
-rw-r--r--sys/dev/e1000/e1000_phy.c46
-rw-r--r--sys/dev/e1000/e1000_phy.h21
-rw-r--r--sys/dev/e1000/e1000_regs.h16
-rw-r--r--sys/dev/e1000/if_em.c176
-rw-r--r--sys/dev/e1000/if_igb.c998
-rw-r--r--sys/dev/e1000/if_igb.h51
-rw-r--r--sys/dev/ed/ax88x90reg.h2
-rw-r--r--sys/dev/ed/dl100xxreg.h13
-rw-r--r--sys/dev/ed/if_ed.c111
-rw-r--r--sys/dev/ed/if_ed_cbus.c3
-rw-r--r--sys/dev/ed/if_ed_isa.c3
-rw-r--r--sys/dev/ed/if_ed_pccard.c583
-rw-r--r--sys/dev/ed/if_ed_pci.c11
-rw-r--r--sys/dev/ed/if_ed_wd80x3.c9
-rw-r--r--sys/dev/ed/if_edreg.h26
-rw-r--r--sys/dev/ed/if_edvar.h9
-rw-r--r--sys/dev/ep/if_ep.c26
-rw-r--r--sys/dev/ep/if_ep_pccard.c15
-rw-r--r--sys/dev/ep/if_epreg.h12
-rw-r--r--sys/dev/ep/if_epvar.h1
-rw-r--r--sys/dev/fe/if_fe_pccard.c14
-rw-r--r--sys/dev/firewire/firewire.c90
-rw-r--r--sys/dev/firewire/sbp.h2
-rw-r--r--sys/dev/hptiop/hptiop.h2
-rw-r--r--sys/dev/hptmv/access601.h19
-rw-r--r--sys/dev/hptmv/amd64-elf.raid.o.uu3764
-rw-r--r--sys/dev/hptmv/array.h10
-rw-r--r--sys/dev/hptmv/command.h8
-rw-r--r--sys/dev/hptmv/entry.c395
-rw-r--r--sys/dev/hptmv/global.h12
-rw-r--r--sys/dev/hptmv/gui_lib.c555
-rw-r--r--sys/dev/hptmv/hptintf.h44
-rw-r--r--sys/dev/hptmv/hptproc.c11
-rw-r--r--sys/dev/hptmv/i386-elf.raid.o.uu2749
-rw-r--r--sys/dev/hptmv/ioctl.c57
-rw-r--r--sys/dev/hptmv/mvOs.h6
-rw-r--r--sys/dev/hptmv/mvSata.h55
-rw-r--r--sys/dev/hptmv/mvStorageDev.h3
-rw-r--r--sys/dev/hptmv/osbsd.h30
-rw-r--r--sys/dev/hptmv/raid5n.h6
-rw-r--r--sys/dev/hptmv/readme.txt39
-rw-r--r--sys/dev/hptmv/vdevice.h60
-rw-r--r--sys/dev/ichwd/ichwd.c63
-rw-r--r--sys/dev/if_ndis/if_ndis.c12
-rw-r--r--sys/dev/if_ndis/if_ndis_usb.c4
-rw-r--r--sys/dev/if_ndis/if_ndisvar.h4
-rw-r--r--sys/dev/ipmi/ipmi_linux.c113
-rw-r--r--sys/dev/ipw/if_ipw.c20
-rw-r--r--sys/dev/iwi/if_iwi.c27
-rw-r--r--sys/dev/iwn/if_iwn.c29
-rw-r--r--sys/dev/ixgbe/LICENSE2
-rw-r--r--sys/dev/ixgbe/README6
-rw-r--r--sys/dev/ixgbe/ixgbe.c840
-rw-r--r--sys/dev/ixgbe/ixgbe.h82
-rw-r--r--sys/dev/ixgbe/ixgbe_82598.c611
-rw-r--r--sys/dev/ixgbe/ixgbe_82599.c2444
-rw-r--r--sys/dev/ixgbe/ixgbe_api.c140
-rw-r--r--sys/dev/ixgbe/ixgbe_api.h54
-rw-r--r--sys/dev/ixgbe/ixgbe_common.c525
-rw-r--r--sys/dev/ixgbe/ixgbe_common.h16
-rw-r--r--sys/dev/ixgbe/ixgbe_osdep.h9
-rw-r--r--sys/dev/ixgbe/ixgbe_phy.c782
-rw-r--r--sys/dev/ixgbe/ixgbe_phy.h23
-rw-r--r--sys/dev/ixgbe/ixgbe_type.h930
-rw-r--r--sys/dev/kbd/kbdreg.h8
-rw-r--r--sys/dev/kbdmux/kbdmux.c8
-rw-r--r--sys/dev/malo/if_malo.c46
-rw-r--r--sys/dev/malo/if_malo_pci.c14
-rw-r--r--sys/dev/malo/if_malohal.c5
-rw-r--r--sys/dev/mii/axphy.c207
-rw-r--r--sys/dev/mii/axphyreg.h (renamed from sys/mips/atheros/apbvar.h)26
-rw-r--r--sys/dev/mii/miidevs4
-rw-r--r--sys/dev/msk/if_msk.c60
-rw-r--r--sys/dev/my/if_my.c2
-rw-r--r--sys/dev/ofw/ofw_standard.c2
-rw-r--r--sys/dev/ofw/openfirm.c4
-rw-r--r--sys/dev/pccard/pccarddevs10
-rw-r--r--sys/dev/pci/pci.c5
-rw-r--r--sys/dev/pci/pci_pci.c32
-rw-r--r--sys/dev/pci/pcib_private.h4
-rw-r--r--sys/dev/powermac_nvram/powermac_nvram.c14
-rw-r--r--sys/dev/ral/rt2560.c37
-rw-r--r--sys/dev/ral/rt2560var.h2
-rw-r--r--sys/dev/ral/rt2661.c55
-rw-r--r--sys/dev/ral/rt2661var.h2
-rw-r--r--sys/dev/re/if_re.c2
-rw-r--r--sys/dev/sound/pci/hda/hdac.c80
-rw-r--r--sys/dev/sound/usb/uaudio.c70
-rw-r--r--sys/dev/syscons/syscons.c9
-rw-r--r--sys/dev/syscons/teken/teken.c2
-rw-r--r--sys/dev/syscons/teken/teken_subr.h9
-rw-r--r--sys/dev/twa/tw_cl_init.c2
-rw-r--r--sys/dev/twa/tw_osl.h6
-rw-r--r--sys/dev/twa/tw_osl_freebsd.c12
-rw-r--r--sys/dev/uart/uart_cpu_powerpc.c28
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c15
-rw-r--r--sys/dev/usb/bluetooth/ng_ubt.c102
-rw-r--r--sys/dev/usb/bluetooth/ubtbcmfw.c12
-rw-r--r--sys/dev/usb/controller/at91dci.c295
-rw-r--r--sys/dev/usb/controller/at91dci.h6
-rw-r--r--sys/dev/usb/controller/at91dci_atmelarm.c10
-rw-r--r--sys/dev/usb/controller/atmegadci.c475
-rw-r--r--sys/dev/usb/controller/atmegadci.h13
-rw-r--r--sys/dev/usb/controller/atmegadci_atmelarm.c4
-rw-r--r--sys/dev/usb/controller/ehci.c248
-rw-r--r--sys/dev/usb/controller/ehci.h6
-rw-r--r--sys/dev/usb/controller/ehci_ixp4xx.c4
-rw-r--r--sys/dev/usb/controller/ehci_mbus.c4
-rw-r--r--sys/dev/usb/controller/ehci_pci.c6
-rw-r--r--sys/dev/usb/controller/musb_otg.c261
-rw-r--r--sys/dev/usb/controller/musb_otg.h6
-rw-r--r--sys/dev/usb/controller/musb_otg_atmelarm.c6
-rw-r--r--sys/dev/usb/controller/ohci.c267
-rw-r--r--sys/dev/usb/controller/ohci.h6
-rw-r--r--sys/dev/usb/controller/ohci_atmelarm.c6
-rw-r--r--sys/dev/usb/controller/ohci_pci.c6
-rw-r--r--sys/dev/usb/controller/uhci.c298
-rw-r--r--sys/dev/usb/controller/uhci.h26
-rw-r--r--sys/dev/usb/controller/uhci_pci.c6
-rw-r--r--sys/dev/usb/controller/usb_controller.c108
-rw-r--r--sys/dev/usb/controller/uss820dci.c290
-rw-r--r--sys/dev/usb/controller/uss820dci.h2
-rw-r--r--sys/dev/usb/controller/uss820dci_atmelarm.c6
-rw-r--r--sys/dev/usb/image/uscanner.c641
-rw-r--r--sys/dev/usb/input/uhid.c30
-rw-r--r--sys/dev/usb/input/ukbd.c20
-rw-r--r--sys/dev/usb/input/ums.c380
-rw-r--r--sys/dev/usb/misc/udbp.c32
-rw-r--r--sys/dev/usb/net/if_aue.c20
-rw-r--r--sys/dev/usb/net/if_axe.c22
-rw-r--r--sys/dev/usb/net/if_cdce.c95
-rw-r--r--sys/dev/usb/net/if_cdcereg.h7
-rw-r--r--sys/dev/usb/net/if_cue.c14
-rw-r--r--sys/dev/usb/net/if_kue.c16
-rw-r--r--sys/dev/usb/net/if_rue.c22
-rw-r--r--sys/dev/usb/net/if_udav.c22
-rw-r--r--sys/dev/usb/serial/u3g.c13
-rw-r--r--sys/dev/usb/serial/uark.c12
-rw-r--r--sys/dev/usb/serial/ubsa.c18
-rw-r--r--sys/dev/usb/serial/ubser.c17
-rw-r--r--sys/dev/usb/serial/uchcom.c18
-rw-r--r--sys/dev/usb/serial/ucycom.c16
-rw-r--r--sys/dev/usb/serial/ufoma.c33
-rw-r--r--sys/dev/usb/serial/uftdi.c12
-rw-r--r--sys/dev/usb/serial/ugensa.c13
-rw-r--r--sys/dev/usb/serial/uipaq.c12
-rw-r--r--sys/dev/usb/serial/ulpt.c22
-rw-r--r--sys/dev/usb/serial/umct.c19
-rw-r--r--sys/dev/usb/serial/umodem.c21
-rw-r--r--sys/dev/usb/serial/umoscom.c18
-rw-r--r--sys/dev/usb/serial/uplcom.c22
-rw-r--r--sys/dev/usb/serial/usb_serial.c10
-rw-r--r--sys/dev/usb/serial/usb_serial.h2
-rw-r--r--sys/dev/usb/serial/uslcom.c12
-rw-r--r--sys/dev/usb/serial/uvisor.c24
-rw-r--r--sys/dev/usb/serial/uvscom.c18
-rw-r--r--sys/dev/usb/storage/umass.c166
-rw-r--r--sys/dev/usb/storage/urio.c30
-rw-r--r--sys/dev/usb/storage/ustorage_fs.c302
-rw-r--r--sys/dev/usb/template/usb_template.c1
-rw-r--r--sys/dev/usb/usb.h6
-rw-r--r--sys/dev/usb/usb_bus.h27
-rw-r--r--sys/dev/usb/usb_busdma.c124
-rw-r--r--sys/dev/usb/usb_busdma.h83
-rw-r--r--sys/dev/usb/usb_compat_linux.c47
-rw-r--r--sys/dev/usb/usb_compat_linux.h22
-rw-r--r--sys/dev/usb/usb_controller.h20
-rw-r--r--sys/dev/usb/usb_core.h229
-rw-r--r--sys/dev/usb/usb_debug.c1
-rw-r--r--sys/dev/usb/usb_debug.h5
-rw-r--r--sys/dev/usb/usb_defs.h26
-rw-r--r--sys/dev/usb/usb_dev.c231
-rw-r--r--sys/dev/usb/usb_dev.h25
-rw-r--r--sys/dev/usb/usb_device.c766
-rw-r--r--sys/dev/usb/usb_device.h53
-rw-r--r--sys/dev/usb/usb_dynamic.c1
-rw-r--r--sys/dev/usb/usb_endian.h14
-rw-r--r--sys/dev/usb/usb_generic.c136
-rw-r--r--sys/dev/usb/usb_handle_request.c5
-rw-r--r--sys/dev/usb/usb_hid.c17
-rw-r--r--sys/dev/usb/usb_hid.h12
-rw-r--r--sys/dev/usb/usb_hub.c160
-rw-r--r--sys/dev/usb/usb_hub.h7
-rw-r--r--sys/dev/usb/usb_lookup.c4
-rw-r--r--sys/dev/usb/usb_lookup.h4
-rw-r--r--sys/dev/usb/usb_mbuf.c4
-rw-r--r--sys/dev/usb/usb_mbuf.h10
-rw-r--r--sys/dev/usb/usb_msctest.c64
-rw-r--r--sys/dev/usb/usb_parse.c147
-rw-r--r--sys/dev/usb/usb_parse.h29
-rw-r--r--sys/dev/usb/usb_process.c2
-rw-r--r--sys/dev/usb/usb_process.h4
-rw-r--r--sys/dev/usb/usb_request.c168
-rw-r--r--sys/dev/usb/usb_request.h10
-rw-r--r--sys/dev/usb/usb_sw_transfer.c170
-rw-r--r--sys/dev/usb/usb_transfer.c412
-rw-r--r--sys/dev/usb/usb_transfer.h43
-rw-r--r--sys/dev/usb/usb_util.c25
-rw-r--r--sys/dev/usb/usb_util.h3
-rw-r--r--sys/dev/usb/usbdevs10
-rw-r--r--sys/dev/usb/wlan/if_rum.c48
-rw-r--r--sys/dev/usb/wlan/if_rumvar.h1
-rw-r--r--sys/dev/usb/wlan/if_uath.c2862
-rw-r--r--sys/dev/usb/wlan/if_uathreg.h601
-rw-r--r--sys/dev/usb/wlan/if_uathvar.h237
-rw-r--r--sys/dev/usb/wlan/if_ural.c48
-rw-r--r--sys/dev/usb/wlan/if_uralvar.h2
-rw-r--r--sys/dev/usb/wlan/if_zyd.c44
-rw-r--r--sys/dev/usb/wlan/usb_wlan.h1
-rw-r--r--sys/dev/wi/if_wi.c51
-rw-r--r--sys/dev/wpi/if_wpi.c44
-rw-r--r--sys/dev/wpi/if_wpireg.h2
-rw-r--r--sys/dev/xen/balloon/balloon.c8
-rw-r--r--sys/dev/xen/console/console.c3
-rw-r--r--sys/fs/devfs/devfs_vnops.c1
-rw-r--r--sys/fs/fifofs/fifo_vnops.c1
-rw-r--r--sys/fs/nullfs/null_vnops.c10
-rw-r--r--sys/fs/pseudofs/pseudofs_vnops.c24
-rw-r--r--sys/fs/unionfs/union_subr.c14
-rw-r--r--sys/fs/unionfs/union_vnops.c24
-rw-r--r--sys/geom/eli/g_eli.c57
-rw-r--r--sys/geom/label/g_label.c3
-rw-r--r--sys/geom/label/g_label.h3
-rw-r--r--sys/geom/label/g_label_ufs.c56
-rw-r--r--sys/geom/part/g_part.c25
-rw-r--r--sys/geom/part/g_part_apm.c12
-rw-r--r--sys/geom/part/g_part_bsd.c5
-rw-r--r--sys/geom/part/g_part_ebr.c22
-rw-r--r--sys/geom/part/g_part_gpt.c4
-rw-r--r--sys/geom/part/g_part_mbr.c4
-rw-r--r--sys/geom/part/g_part_pc98.c5
-rw-r--r--sys/geom/vinum/geom_vinum.c1010
-rw-r--r--sys/geom/vinum/geom_vinum.h120
-rw-r--r--sys/geom/vinum/geom_vinum_create.c614
-rw-r--r--sys/geom/vinum/geom_vinum_drive.c659
-rw-r--r--sys/geom/vinum/geom_vinum_events.c217
-rw-r--r--sys/geom/vinum/geom_vinum_init.c701
-rw-r--r--sys/geom/vinum/geom_vinum_list.c35
-rw-r--r--sys/geom/vinum/geom_vinum_move.c106
-rw-r--r--sys/geom/vinum/geom_vinum_plex.c1425
-rw-r--r--sys/geom/vinum/geom_vinum_raid5.c380
-rw-r--r--sys/geom/vinum/geom_vinum_raid5.h28
-rw-r--r--sys/geom/vinum/geom_vinum_rename.c245
-rw-r--r--sys/geom/vinum/geom_vinum_rm.c351
-rw-r--r--sys/geom/vinum/geom_vinum_share.c137
-rw-r--r--sys/geom/vinum/geom_vinum_share.h6
-rw-r--r--sys/geom/vinum/geom_vinum_state.c206
-rw-r--r--sys/geom/vinum/geom_vinum_subr.c889
-rw-r--r--sys/geom/vinum/geom_vinum_var.h143
-rw-r--r--sys/geom/vinum/geom_vinum_volume.c422
-rw-r--r--sys/gnu/fs/xfs/FreeBSD/xfs_buf.c4
-rw-r--r--sys/i386/conf/GENERIC1
-rw-r--r--sys/i386/conf/NOTES13
-rw-r--r--sys/i386/conf/XBOX1
-rw-r--r--sys/i386/cpufreq/hwpstate.c515
-rw-r--r--sys/i386/i386/elf_machdep.c6
-rw-r--r--sys/i386/i386/i686_mem.c28
-rw-r--r--sys/i386/i386/k6_mem.c1
-rw-r--r--sys/i386/i386/machdep.c468
-rw-r--r--sys/i386/i386/pmap.c2
-rw-r--r--sys/i386/i386/vm_machdep.c6
-rw-r--r--sys/i386/include/cpufunc.h87
-rw-r--r--sys/i386/include/elf.h6
-rw-r--r--sys/i386/include/endian.h42
-rw-r--r--sys/i386/include/pmap.h3
-rw-r--r--sys/i386/include/signal.h6
-rw-r--r--sys/i386/include/ucontext.h7
-rw-r--r--sys/i386/include/vmparam.h4
-rw-r--r--sys/i386/include/xen/xenpmap.h2
-rw-r--r--sys/i386/include/xen/xenvar.h2
-rw-r--r--sys/i386/isa/npx.c38
-rw-r--r--sys/i386/linux/linux_sysvec.c16
-rw-r--r--sys/i386/pci/pci_cfgreg.c2
-rw-r--r--sys/i386/xen/pmap.c66
-rw-r--r--sys/i386/xen/xen_machdep.c36
-rw-r--r--sys/ia64/ia32/ia32_misc.c (renamed from sys/mips/alchemy/uart_cpu_alchemy.c)57
-rw-r--r--sys/ia64/ia64/elf_machdep.c6
-rw-r--r--sys/ia64/include/elf.h6
-rw-r--r--sys/kern/imgact_elf.c154
-rw-r--r--sys/kern/kern_acct.c1
-rw-r--r--sys/kern/kern_alq.c1
-rw-r--r--sys/kern/kern_environment.c10
-rw-r--r--sys/kern/kern_exec.c31
-rw-r--r--sys/kern/kern_jail.c24
-rw-r--r--sys/kern/kern_ktrace.c1
-rw-r--r--sys/kern/kern_lock.c13
-rw-r--r--sys/kern/kern_mutex.c25
-rw-r--r--sys/kern/kern_poll.c2
-rw-r--r--sys/kern/kern_rwlock.c6
-rw-r--r--sys/kern/kern_shutdown.c9
-rw-r--r--sys/kern/kern_sig.c1
-rw-r--r--sys/kern/kern_sx.c9
-rw-r--r--sys/kern/kern_tc.c31
-rw-r--r--sys/kern/kern_thread.c3
-rw-r--r--sys/kern/kern_time.c15
-rw-r--r--sys/kern/kern_umtx.c50
-rw-r--r--sys/kern/kern_vimage.c144
-rw-r--r--sys/kern/sched_ule.c13
-rw-r--r--sys/kern/subr_bus.c8
-rw-r--r--sys/kern/subr_lock.c110
-rw-r--r--sys/kern/subr_param.c29
-rw-r--r--sys/kern/subr_rtc.c34
-rw-r--r--sys/kern/subr_smp.c48
-rw-r--r--sys/kern/sysv_sem.c1
-rw-r--r--sys/kern/tty.c24
-rw-r--r--sys/kern/uipc_domain.c21
-rw-r--r--sys/kern/uipc_sem.c12
-rw-r--r--sys/kern/uipc_syscalls.c2
-rw-r--r--sys/kern/uipc_usrreq.c4
-rw-r--r--sys/kern/vfs_acl.c3
-rw-r--r--sys/kern/vfs_bio.c196
-rw-r--r--sys/kern/vfs_cache.c274
-rw-r--r--sys/kern/vfs_default.c1
-rw-r--r--sys/kern/vfs_extattr.c4
-rw-r--r--sys/kern/vfs_lookup.c25
-rw-r--r--sys/kern/vfs_mount.c17
-rw-r--r--sys/kern/vfs_subr.c1
-rw-r--r--sys/kern/vfs_syscalls.c24
-rw-r--r--sys/kern/vfs_vnops.c9
-rw-r--r--sys/kern/vnode_if.src10
-rw-r--r--sys/mips/alchemy/alchemy_machdep.c157
-rw-r--r--sys/mips/alchemy/aureg.h373
-rw-r--r--sys/mips/alchemy/files.alchemy7
-rw-r--r--sys/mips/alchemy/obio.c501
-rw-r--r--sys/mips/alchemy/std.alchemy8
-rw-r--r--sys/mips/alchemy/uart_bus_alchemy.c87
-rw-r--r--sys/mips/atheros/apb.c433
-rw-r--r--sys/mips/atheros/ar71xx_machdep.c161
-rw-r--r--sys/mips/atheros/ar71xx_ohci.c205
-rw-r--r--sys/mips/atheros/ar71xx_pci.c429
-rw-r--r--sys/mips/atheros/ar71xxreg.h317
-rw-r--r--sys/mips/atheros/files.ar71xx9
-rw-r--r--sys/mips/atheros/if_arge.c1657
-rw-r--r--sys/mips/atheros/if_argevar.h138
-rw-r--r--sys/mips/atheros/uart_bus_ar71xx.c79
-rw-r--r--sys/mips/conf/ADM51201
-rw-r--r--sys/mips/conf/ALCHEMY66
-rw-r--r--sys/mips/conf/AR71XX37
-rw-r--r--sys/mips/conf/AR71XX.hints25
-rw-r--r--sys/mips/conf/MALTA1
-rw-r--r--sys/mips/conf/QEMU1
-rw-r--r--sys/mips/conf/SENTRY511
-rw-r--r--sys/mips/include/bus.h5
-rw-r--r--sys/mips/include/elf.h6
-rw-r--r--sys/mips/mips/elf64_machdep.c6
-rw-r--r--sys/mips/mips/elf_machdep.c3
-rw-r--r--sys/mips/mips/elf_trampoline.c133
-rw-r--r--sys/mips/mips/inckern.S34
-rw-r--r--sys/mips/mips/nexus.c39
-rw-r--r--sys/mips/sentry5/files.sentry57
-rw-r--r--sys/mips/sentry5/siba_cc.c (renamed from sys/dev/siba/siba_cc.c)0
-rw-r--r--sys/mips/sentry5/siba_mips.c (renamed from sys/dev/siba/siba_mips.c)0
-rw-r--r--sys/mips/sentry5/siba_sdram.c (renamed from sys/dev/siba/siba_sdram.c)0
-rw-r--r--sys/modules/Makefile16
-rw-r--r--sys/modules/amdtemp/Makefile8
-rw-r--r--sys/modules/ath/Makefile4
-rw-r--r--sys/modules/cpufreq/Makefile2
-rw-r--r--sys/modules/dtrace/Makefile1
-rw-r--r--sys/modules/dtrace/dtnfsclient/Makefile13
-rw-r--r--sys/modules/dtrace/dtraceall/dtraceall.c1
-rw-r--r--sys/modules/geom/geom_vinum/Makefile4
-rw-r--r--sys/modules/ip6_mroute_mod/Makefile19
-rw-r--r--sys/modules/ip_mroute_mod/Makefile9
-rw-r--r--sys/modules/ipmi/Makefile2
-rw-r--r--sys/modules/ipmi/ipmi_linux/Makefile8
-rw-r--r--sys/modules/ixgbe/Makefile3
-rw-r--r--sys/modules/k8temp/Makefile8
-rw-r--r--sys/modules/linprocfs/Makefile1
-rw-r--r--sys/modules/mii/Makefile3
-rw-r--r--sys/modules/netgraph/Makefile7
-rw-r--r--sys/modules/nfsclient/Makefile2
-rw-r--r--sys/modules/nfssvc/Makefile9
-rw-r--r--sys/modules/opensolaris/Makefile2
-rw-r--r--sys/modules/usb/Makefile4
-rw-r--r--sys/modules/usb/uath/Makefile10
-rw-r--r--sys/modules/usb/usb/Makefile2
-rw-r--r--sys/modules/usb/uscanner/Makefile36
-rw-r--r--sys/net/bpf.h88
-rw-r--r--sys/net/bsd_comp.c1117
-rw-r--r--sys/net/if.c155
-rw-r--r--sys/net/if_bridge.c20
-rw-r--r--sys/net/if_gif.c46
-rw-r--r--sys/net/if_loop.c51
-rw-r--r--sys/net/if_ppp.c1733
-rw-r--r--sys/net/if_ppp.h139
-rw-r--r--sys/net/if_pppvar.h113
-rw-r--r--sys/net/if_sl.c1110
-rw-r--r--sys/net/if_slvar.h83
-rw-r--r--sys/net/if_spppsubr.c2
-rw-r--r--sys/net/if_tap.c5
-rw-r--r--sys/net/if_var.h11
-rw-r--r--sys/net/ppp_comp.h153
-rw-r--r--sys/net/ppp_deflate.c680
-rw-r--r--sys/net/ppp_tty.c1076
-rw-r--r--sys/net/route.c45
-rw-r--r--sys/net/vnet.h2
-rw-r--r--sys/net80211/ieee80211.c29
-rw-r--r--sys/net80211/ieee80211.h81
-rw-r--r--sys/net80211/ieee80211_adhoc.c32
-rw-r--r--sys/net80211/ieee80211_ddb.c1
-rw-r--r--sys/net80211/ieee80211_freebsd.c12
-rw-r--r--sys/net80211/ieee80211_freebsd.h14
-rw-r--r--sys/net80211/ieee80211_hostap.c40
-rw-r--r--sys/net80211/ieee80211_input.c81
-rw-r--r--sys/net80211/ieee80211_input.h3
-rw-r--r--sys/net80211/ieee80211_ioctl.c112
-rw-r--r--sys/net80211/ieee80211_ioctl.h3
-rw-r--r--sys/net80211/ieee80211_node.c19
-rw-r--r--sys/net80211/ieee80211_node.h2
-rw-r--r--sys/net80211/ieee80211_output.c342
-rw-r--r--sys/net80211/ieee80211_proto.c33
-rw-r--r--sys/net80211/ieee80211_proto.h7
-rw-r--r--sys/net80211/ieee80211_scan.c1
-rw-r--r--sys/net80211/ieee80211_scan.h2
-rw-r--r--sys/net80211/ieee80211_scan_sta.c14
-rw-r--r--sys/net80211/ieee80211_sta.c94
-rw-r--r--sys/net80211/ieee80211_superg.c872
-rw-r--r--sys/net80211/ieee80211_superg.h104
-rw-r--r--sys/net80211/ieee80211_tdma.c159
-rw-r--r--sys/net80211/ieee80211_tdma.h50
-rw-r--r--sys/net80211/ieee80211_var.h26
-rw-r--r--sys/net80211/ieee80211_wds.c48
-rw-r--r--sys/netinet/icmp6.h5
-rw-r--r--sys/netinet/icmp_var.h5
-rw-r--r--sys/netinet/if_ether.c27
-rw-r--r--sys/netinet/igmp.c104
-rw-r--r--sys/netinet/igmp.h2
-rw-r--r--sys/netinet/igmp_var.h5
-rw-r--r--sys/netinet/in.c20
-rw-r--r--sys/netinet/in.h4
-rw-r--r--sys/netinet/in_gif.c6
-rw-r--r--sys/netinet/in_mcast.c35
-rw-r--r--sys/netinet/in_pcb.c38
-rw-r--r--sys/netinet/in_pcb.h60
-rw-r--r--sys/netinet/ip_carp.c40
-rw-r--r--sys/netinet/ip_carp.h5
-rw-r--r--sys/netinet/ip_divert.c10
-rw-r--r--sys/netinet/ip_dummynet.c130
-rw-r--r--sys/netinet/ip_dummynet.h36
-rw-r--r--sys/netinet/ip_fastfwd.c34
-rw-r--r--sys/netinet/ip_fw.h6
-rw-r--r--sys/netinet/ip_fw2.c53
-rw-r--r--sys/netinet/ip_fw_pfil.c6
-rw-r--r--sys/netinet/ip_icmp.c34
-rw-r--r--sys/netinet/ip_input.c122
-rw-r--r--sys/netinet/ip_ipsec.c2
-rw-r--r--sys/netinet/ip_mroute.c1229
-rw-r--r--sys/netinet/ip_mroute.h29
-rw-r--r--sys/netinet/ip_options.c4
-rw-r--r--sys/netinet/ip_output.c30
-rw-r--r--sys/netinet/ip_var.h5
-rw-r--r--sys/netinet/libalias/alias.c16
-rw-r--r--sys/netinet/libalias/alias_cuseeme.c2
-rw-r--r--sys/netinet/libalias/alias_dummy.c2
-rw-r--r--sys/netinet/libalias/alias_ftp.c2
-rw-r--r--sys/netinet/libalias/alias_irc.c2
-rw-r--r--sys/netinet/libalias/alias_mod.c34
-rw-r--r--sys/netinet/libalias/alias_mod.h8
-rw-r--r--sys/netinet/libalias/alias_nbt.c12
-rw-r--r--sys/netinet/libalias/alias_pptp.c4
-rw-r--r--sys/netinet/libalias/alias_skinny.c2
-rw-r--r--sys/netinet/libalias/alias_smedia.c2
-rw-r--r--sys/netinet/pim_var.h5
-rw-r--r--sys/netinet/raw_ip.c10
-rw-r--r--sys/netinet/sctp.h2
-rw-r--r--sys/netinet/sctp_constants.h4
-rw-r--r--sys/netinet/sctp_indata.c586
-rw-r--r--sys/netinet/sctp_input.c9
-rw-r--r--sys/netinet/sctp_output.c2108
-rw-r--r--sys/netinet/sctp_pcb.c12
-rw-r--r--sys/netinet/sctp_structs.h6
-rw-r--r--sys/netinet/sctp_sysctl.c1
-rw-r--r--sys/netinet/sctp_sysctl.h2
-rw-r--r--sys/netinet/sctp_timer.c4
-rw-r--r--sys/netinet/sctp_uio.h13
-rw-r--r--sys/netinet/sctp_usrreq.c6
-rw-r--r--sys/netinet/sctp_var.h4
-rw-r--r--sys/netinet/sctputil.c261
-rw-r--r--sys/netinet/sctputil.h3
-rw-r--r--sys/netinet/tcp_hostcache.c18
-rw-r--r--sys/netinet/tcp_input.c118
-rw-r--r--sys/netinet/tcp_output.c32
-rw-r--r--sys/netinet/tcp_reass.c28
-rw-r--r--sys/netinet/tcp_sack.c9
-rw-r--r--sys/netinet/tcp_subr.c120
-rw-r--r--sys/netinet/tcp_syncache.c48
-rw-r--r--sys/netinet/tcp_timer.c28
-rw-r--r--sys/netinet/tcp_timewait.c36
-rw-r--r--sys/netinet/tcp_usrreq.c64
-rw-r--r--sys/netinet/tcp_var.h5
-rw-r--r--sys/netinet/udp_usrreq.c24
-rw-r--r--sys/netinet/udp_var.h5
-rw-r--r--sys/netinet/vinet.h9
-rw-r--r--sys/netinet6/frag6.c10
-rw-r--r--sys/netinet6/icmp6.c54
-rw-r--r--sys/netinet6/in6.c2
-rw-r--r--sys/netinet6/in6_ifattach.c2
-rw-r--r--sys/netinet6/in6_pcb.c8
-rw-r--r--sys/netinet6/in6_src.c8
-rw-r--r--sys/netinet6/ip6_input.c50
-rw-r--r--sys/netinet6/ip6_mroute.c396
-rw-r--r--sys/netinet6/ip6_mroute.h2
-rw-r--r--sys/netinet6/mld6.c6
-rw-r--r--sys/netinet6/nd6.c4
-rw-r--r--sys/netinet6/nd6_nbr.c12
-rw-r--r--sys/netinet6/nd6_rtr.c8
-rw-r--r--sys/netinet6/raw_ip6.c2
-rw-r--r--sys/netinet6/scope6.c6
-rw-r--r--sys/netinet6/udp6_usrreq.c20
-rw-r--r--sys/netipsec/ipsec.c26
-rw-r--r--sys/netipsec/key.c38
-rw-r--r--sys/netipsec/xform_ah.c26
-rw-r--r--sys/netipsec/xform_esp.c30
-rw-r--r--sys/netipsec/xform_ipcomp.c25
-rw-r--r--sys/netipsec/xform_ipip.c26
-rw-r--r--sys/netnatm/natm.c17
-rw-r--r--sys/nfs/nfs_nfssvc.c153
-rw-r--r--sys/nfs/nfssvc.h (renamed from sys/net/slip.h)55
-rw-r--r--sys/nfs4client/nfs4_socket.c2
-rw-r--r--sys/nfs4client/nfs4_vnops.c52
-rw-r--r--sys/nfsclient/nfs.h6
-rw-r--r--sys/nfsclient/nfs_bio.c7
-rw-r--r--sys/nfsclient/nfs_kdtrace.c545
-rw-r--r--sys/nfsclient/nfs_kdtrace.h120
-rw-r--r--sys/nfsclient/nfs_krpc.c88
-rw-r--r--sys/nfsclient/nfs_socket.c2
-rw-r--r--sys/nfsclient/nfs_subs.c74
-rw-r--r--sys/nfsclient/nfs_vnops.c150
-rw-r--r--sys/nfsclient/nfsnode.h10
-rw-r--r--sys/nfsserver/nfs.h16
-rw-r--r--sys/nfsserver/nfs_srvkrpc.c20
-rw-r--r--sys/nfsserver/nfs_srvsubs.c17
-rw-r--r--sys/nfsserver/nfs_syscalls.c20
-rw-r--r--sys/pc98/conf/GENERIC1
-rw-r--r--sys/pc98/conf/NOTES5
-rw-r--r--sys/pc98/pc98/machdep.c453
-rw-r--r--sys/pci/intpm.c16
-rw-r--r--sys/powerpc/aim/machdep.c179
-rw-r--r--sys/powerpc/aim/mmu_oea.c9
-rw-r--r--sys/powerpc/aim/mmu_oea64.c2443
-rw-r--r--sys/powerpc/aim/mp_cpudep.c7
-rw-r--r--sys/powerpc/aim/ofw_machdep.c89
-rw-r--r--sys/powerpc/aim/swtch.S6
-rw-r--r--sys/powerpc/aim/trap_subr.S78
-rw-r--r--sys/powerpc/aim/uio_machdep.c124
-rw-r--r--sys/powerpc/aim/uma_machdep.c17
-rw-r--r--sys/powerpc/aim/vm_machdep.c145
-rw-r--r--sys/powerpc/booke/machdep.c3
-rw-r--r--sys/powerpc/booke/pmap.c216
-rw-r--r--sys/powerpc/conf/GENERIC1
-rw-r--r--sys/powerpc/include/elf.h3
-rw-r--r--sys/powerpc/include/hid.h3
-rw-r--r--sys/powerpc/include/intr.h77
-rw-r--r--sys/powerpc/include/md_var.h2
-rw-r--r--sys/powerpc/include/pmap.h12
-rw-r--r--sys/powerpc/include/sf_buf.h43
-rw-r--r--sys/powerpc/include/spr.h46
-rw-r--r--sys/powerpc/include/sysarch.h43
-rw-r--r--sys/powerpc/include/vmparam.h7
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.c7
-rw-r--r--sys/powerpc/mpc85xx/mpc85xx.h1
-rw-r--r--sys/powerpc/mpc85xx/ocpbus.c15
-rw-r--r--sys/powerpc/ofw/ofw_real.c922
-rw-r--r--sys/powerpc/ofw/ofw_syscons.c33
-rw-r--r--sys/powerpc/powermac/ata_macio.c4
-rw-r--r--sys/powerpc/powermac/cpcht.c625
-rw-r--r--sys/powerpc/powermac/cpchtvar.h58
-rw-r--r--sys/powerpc/powerpc/bus_machdep.c49
-rw-r--r--sys/powerpc/powerpc/cpu.c4
-rw-r--r--sys/powerpc/powerpc/dump_machdep.c303
-rw-r--r--sys/powerpc/powerpc/elf_machdep.c6
-rw-r--r--sys/powerpc/powerpc/mem.c17
-rw-r--r--sys/powerpc/powerpc/mmu_if.m64
-rw-r--r--sys/powerpc/powerpc/pmap_dispatch.c35
-rw-r--r--sys/powerpc/powerpc/uio_machdep.c (renamed from sys/powerpc/booke/uio_machdep.c)0
-rw-r--r--sys/security/mac/mac_atalk.c8
-rw-r--r--sys/security/mac/mac_audit.c10
-rw-r--r--sys/security/mac/mac_cred.c34
-rw-r--r--sys/security/mac/mac_framework.c185
-rw-r--r--sys/security/mac/mac_inet.c73
-rw-r--r--sys/security/mac/mac_inet6.c25
-rw-r--r--sys/security/mac/mac_internal.h99
-rw-r--r--sys/security/mac/mac_net.c39
-rw-r--r--sys/security/mac/mac_pipe.c22
-rw-r--r--sys/security/mac/mac_posix_sem.c18
-rw-r--r--sys/security/mac/mac_posix_shm.c19
-rw-r--r--sys/security/mac/mac_priv.c4
-rw-r--r--sys/security/mac/mac_process.c10
-rw-r--r--sys/security/mac/mac_socket.c60
-rw-r--r--sys/security/mac/mac_syscalls.c12
-rw-r--r--sys/security/mac/mac_system.c14
-rw-r--r--sys/security/mac/mac_sysv_msg.c31
-rw-r--r--sys/security/mac/mac_sysv_sem.c17
-rw-r--r--sys/security/mac/mac_sysv_shm.c22
-rw-r--r--sys/security/mac/mac_vfs.c35
-rw-r--r--sys/security/mac_biba/mac_biba.c4
-rw-r--r--sys/security/mac_bsdextended/mac_bsdextended.c4
-rw-r--r--sys/security/mac_mls/mac_mls.c4
-rw-r--r--sys/security/mac_portacl/mac_portacl.c4
-rw-r--r--sys/sparc64/central/central.c11
-rw-r--r--sys/sparc64/conf/GENERIC1
-rw-r--r--sys/sparc64/ebus/ebus.c8
-rw-r--r--sys/sparc64/fhc/fhc.c54
-rw-r--r--sys/sparc64/include/elf.h6
-rw-r--r--sys/sparc64/include/trap.h2
-rw-r--r--sys/sparc64/isa/isa.c3
-rw-r--r--sys/sparc64/isa/ofw_isa.c2
-rw-r--r--sys/sparc64/pci/apb.c4
-rw-r--r--sys/sparc64/pci/ofw_pcib.c4
-rw-r--r--sys/sparc64/pci/ofw_pcibus.c16
-rw-r--r--sys/sparc64/pci/psycho.c109
-rw-r--r--sys/sparc64/pci/psychovar.h4
-rw-r--r--sys/sparc64/pci/schizo.c22
-rw-r--r--sys/sparc64/sbus/dma_sbus.c11
-rw-r--r--sys/sparc64/sbus/sbus.c74
-rw-r--r--sys/sparc64/sbus/sbusvar.h26
-rw-r--r--sys/sparc64/sparc64/db_disasm.c10
-rw-r--r--sys/sparc64/sparc64/eeprom.c2
-rw-r--r--sys/sparc64/sparc64/elf_machdep.c6
-rw-r--r--sys/sparc64/sparc64/jbusppm.c2
-rw-r--r--sys/sparc64/sparc64/mp_machdep.c14
-rw-r--r--sys/sparc64/sparc64/nexus.c8
-rw-r--r--sys/sparc64/sparc64/rtc.c2
-rw-r--r--sys/sparc64/sparc64/sc_machdep.c2
-rw-r--r--sys/sparc64/sparc64/schppm.c2
-rw-r--r--sys/sparc64/sparc64/trap.c18
-rw-r--r--sys/sparc64/sparc64/upa.c27
-rw-r--r--sys/sun4v/conf/GENERIC1
-rw-r--r--sys/sun4v/include/elf.h6
-rw-r--r--sys/sun4v/include/trap.h2
-rw-r--r--sys/sun4v/sun4v/trap.c16
-rw-r--r--sys/sys/_pthreadtypes.h3
-rw-r--r--sys/sys/aio.h5
-rw-r--r--sys/sys/buf.h3
-rw-r--r--sys/sys/dtrace_bsd.h52
-rw-r--r--sys/sys/elf_common.h7
-rw-r--r--sys/sys/imgact.h3
-rw-r--r--sys/sys/imgact_elf.h11
-rw-r--r--sys/sys/jail.h11
-rw-r--r--sys/sys/kernel.h1
-rw-r--r--sys/sys/kerneldump.h11
-rw-r--r--sys/sys/lock_profile.h23
-rw-r--r--sys/sys/mbuf.h1
-rw-r--r--sys/sys/memrange.h2
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/proc.h2
-rw-r--r--sys/sys/sem.h2
-rw-r--r--sys/sys/shm.h2
-rw-r--r--sys/sys/smp.h3
-rw-r--r--sys/sys/stat.h7
-rw-r--r--sys/sys/syslog.h2
-rw-r--r--sys/sys/termios.h4
-rw-r--r--sys/sys/time.h18
-rw-r--r--sys/sys/uio.h2
-rw-r--r--sys/sys/vimage.h90
-rw-r--r--sys/sys/vnode.h62
-rw-r--r--sys/tools/vnode_if.awk12
-rw-r--r--sys/ufs/ffs/ffs_snapshot.c1
-rw-r--r--sys/ufs/ffs/ffs_softdep.c2
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c6
-rw-r--r--sys/ufs/ffs/ffs_vnops.c153
-rw-r--r--sys/ufs/ufs/inode.h3
-rw-r--r--sys/vm/vm_extern.h13
-rw-r--r--sys/vm/vm_map.c16
-rw-r--r--sys/vm/vm_map.h2
-rw-r--r--sys/vm/vm_mmap.c12
-rw-r--r--sys/vm/vm_reserv.c8
-rw-r--r--sys/vm/vm_unix.c2
-rw-r--r--sys/xen/evtchn/evtchn.c2
-rw-r--r--sys/xen/reboot.c8
-rw-r--r--tools/build/options/WITHOUT_SLIP4
-rw-r--r--tools/regression/bin/sh/builtins/alias.03
-rw-r--r--tools/regression/bin/sh/builtins/alias.0.stdout5
-rw-r--r--tools/regression/bin/sh/builtins/read1.026
-rw-r--r--tools/regression/bin/sh/builtins/read1.0.stdout20
-rw-r--r--tools/regression/include/tgmath/Makefile3
-rw-r--r--tools/regression/lib/libc/stdio/test-getdelim.c4
-rw-r--r--tools/regression/mac/mac_portacl/LICENSE27
-rwxr-xr-xtools/regression/mac/mac_portacl/misc.sh97
-rwxr-xr-xtools/regression/mac/mac_portacl/nobody.t67
-rwxr-xr-xtools/regression/mac/mac_portacl/root.t51
-rw-r--r--tools/tools/nanobsd/rescue/AMD641
-rw-r--r--tools/tools/nanobsd/rescue/I3861
-rw-r--r--tools/tools/sysbuild/sysbuild.sh10
-rw-r--r--usr.bin/ar/ar.c7
-rw-r--r--usr.bin/calendar/calendars/calendar.freebsd2
-rw-r--r--usr.bin/cut/cut.12
-rw-r--r--usr.bin/kdump/kdump.c3
-rw-r--r--usr.bin/locate/locate/fastfind.c2
-rw-r--r--usr.bin/locate/locate/util.c6
-rw-r--r--usr.bin/login/login.c4
-rw-r--r--usr.bin/make/globals.h1
-rw-r--r--usr.bin/make/main.c38
-rw-r--r--usr.bin/make/make.12
-rw-r--r--usr.bin/make/make.c26
-rw-r--r--usr.bin/ministat/ministat.c8
-rw-r--r--usr.bin/ncal/ncal.16
-rw-r--r--usr.bin/ncal/ncal.c84
-rw-r--r--usr.bin/netstat/inet.c2
-rw-r--r--usr.bin/netstat/main.c9
-rw-r--r--usr.bin/netstat/mroute.c306
-rw-r--r--usr.bin/netstat/netstat.h2
-rw-r--r--usr.bin/su/su.c14
-rw-r--r--usr.bin/systat/netstat.c2
-rw-r--r--usr.sbin/Makefile15
-rw-r--r--usr.sbin/chown/chgrp.12
-rw-r--r--usr.sbin/eeprom/ofw_options.c38
-rw-r--r--usr.sbin/fifolog/fifolog_create/fifolog.14
-rw-r--r--usr.sbin/gstat/gstat.820
-rw-r--r--usr.sbin/gstat/gstat.c10
-rw-r--r--usr.sbin/jexec/jexec.c28
-rw-r--r--usr.sbin/mergemaster/mergemaster.864
-rwxr-xr-xusr.sbin/mergemaster/mergemaster.sh36
-rw-r--r--usr.sbin/portsnap/phttpget/phttpget.c6
-rw-r--r--usr.sbin/pppd/Makefile56
-rw-r--r--usr.sbin/pppd/RELNOTES726
-rw-r--r--usr.sbin/pppd/auth.c1637
-rw-r--r--usr.sbin/pppd/cbcp.c411
-rw-r--r--usr.sbin/pppd/cbcp.h26
-rw-r--r--usr.sbin/pppd/ccp.c1113
-rw-r--r--usr.sbin/pppd/ccp.h50
-rw-r--r--usr.sbin/pppd/chap.c870
-rw-r--r--usr.sbin/pppd/chap.h124
-rw-r--r--usr.sbin/pppd/chap_ms.c335
-rw-r--r--usr.sbin/pppd/chap_ms.h33
-rw-r--r--usr.sbin/pppd/demand.c348
-rw-r--r--usr.sbin/pppd/eui64.c46
-rw-r--r--usr.sbin/pppd/eui64.h98
-rw-r--r--usr.sbin/pppd/fsm.c798
-rw-r--r--usr.sbin/pppd/fsm.h144
-rw-r--r--usr.sbin/pppd/ipcp.c1531
-rw-r--r--usr.sbin/pppd/ipcp.h70
-rw-r--r--usr.sbin/pppd/ipv6cp.c1422
-rw-r--r--usr.sbin/pppd/ipv6cp.h129
-rw-r--r--usr.sbin/pppd/ipxcp.c1399
-rw-r--r--usr.sbin/pppd/ipxcp.h71
-rw-r--r--usr.sbin/pppd/lcp.c1859
-rw-r--r--usr.sbin/pppd/lcp.h88
-rw-r--r--usr.sbin/pppd/magic.c87
-rw-r--r--usr.sbin/pppd/magic.h23
-rw-r--r--usr.sbin/pppd/main.c1723
-rw-r--r--usr.sbin/pppd/options.c2683
-rw-r--r--usr.sbin/pppd/patchlevel.h6
-rw-r--r--usr.sbin/pppd/pathnames.h37
-rw-r--r--usr.sbin/pppd/pppd.81247
-rw-r--r--usr.sbin/pppd/pppd.h509
-rw-r--r--usr.sbin/pppd/sys-bsd.c1697
-rw-r--r--usr.sbin/pppd/upap.c618
-rw-r--r--usr.sbin/pppd/upap.h87
-rw-r--r--usr.sbin/pppstats/Makefile6
-rw-r--r--usr.sbin/pppstats/pppstats.8218
-rw-r--r--usr.sbin/pppstats/pppstats.c519
-rw-r--r--usr.sbin/sliplogin/Makefile11
-rw-r--r--usr.sbin/sliplogin/sliplogin.8317
-rw-r--r--usr.sbin/sliplogin/sliplogin.c544
-rw-r--r--usr.sbin/slstat/Makefile9
-rw-r--r--usr.sbin/slstat/slstat.8125
-rw-r--r--usr.sbin/slstat/slstat.c243
-rw-r--r--usr.sbin/sysinstall/config.c8
-rw-r--r--usr.sbin/sysinstall/devices.c1
-rw-r--r--usr.sbin/sysinstall/dispatch.c205
-rw-r--r--usr.sbin/sysinstall/menus.c17
-rw-r--r--usr.sbin/sysinstall/modules.c15
-rw-r--r--usr.sbin/sysinstall/sysinstall.814
-rw-r--r--usr.sbin/sysinstall/sysinstall.h4
-rw-r--r--usr.sbin/sysinstall/user.c1
-rw-r--r--usr.sbin/tcpdump/tcpdump/Makefile21
-rw-r--r--usr.sbin/uathload/Makefile18
-rw-r--r--usr.sbin/uathload/uathload.869
-rw-r--r--usr.sbin/uathload/uathload.c233
-rw-r--r--usr.sbin/usbconfig/usbconfig.c1
1717 files changed, 98262 insertions, 85669 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index b7983f0..d80dee6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -76,7 +76,7 @@ groff ru Recommends pre-commit review.
share/mk ru This is a vital component of the build system, so I
offer a pre-commit review for anything non-trivial.
ipfw ipfw Pre-commit review preferred. send to ipfw@freebsd.org
-drm anholt Just keep me informed of changes, try not to break it.
+drm rnoland Just keep me informed of changes, try not to break it.
libufs jmallett Willing to handle problems, help with work.
fdc(4) joerg Just keep me informed of changes, try not to break it.
sppp(4) joerg Just keep me informed of changes, try not to break it.
diff --git a/Makefile b/Makefile
index bd9a5f2..ebaeb6d 100644
--- a/Makefile
+++ b/Makefile
@@ -88,7 +88,7 @@ TGTS= all all-man buildenv buildenvvars buildkernel buildworld \
obj objlink regress rerelease showconfig tags toolchain update \
_worldtmp _legacy _bootstrap-tools _cleanobj _obj \
_build-tools _cross-tools _includes _libraries _depend \
- build32 distribute32 install32
+ build32 distribute32 install32 xdev xdev-build xdev-install
TGTS+= ${SUBDIR_TARGETS}
BITGTS= files includes
@@ -279,7 +279,7 @@ tinderbox:
# existing system is.
#
.if make(universe) || make(tinderbox)
-TARGETS?=amd64 arm i386 ia64 pc98 powerpc sparc64 sun4v
+TARGETS?=amd64 arm i386 ia64 mips pc98 powerpc sparc64 sun4v
.if defined(DOING_TINDERBOX)
FAILFILE=tinderbox.failed
diff --git a/Makefile.inc1 b/Makefile.inc1
index 14c8663..9f411f3 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -232,7 +232,7 @@ BMAKE= MAKEOBJDIRPREFIX=${WORLDTMP} \
BOOTSTRAPPING=${OSRELDATE} \
SSP_CFLAGS= \
-DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT -DWITHOUT_MAN \
- -DWITHOUT_NLS -DNO_PIC -DWITHOUT_PROFILE -DNO_SHARED \
+ -DNO_PIC -DWITHOUT_PROFILE -DNO_SHARED \
-DNO_CPU_CFLAGS -DNO_WARNS -DNO_CTF
# build-tools stage
@@ -291,7 +291,7 @@ LIB32WMAKEENV= MAKEOBJDIRPREFIX=${OBJTREE}/lib32 \
SHLIBDIR=/usr/lib32
LIB32WMAKE= ${LIB32WMAKEENV} ${MAKE} -DNO_CPU_CFLAGS -DCOMPAT_32BIT \
- -DWITHOUT_BIND -DWITHOUT_MAN -DWITHOUT_NLS -DWITHOUT_INFO \
+ -DWITHOUT_BIND -DWITHOUT_MAN -DWITHOUT_INFO \
-DWITHOUT_HTML -DNO_CTF DESTDIR=${LIB32TMP}
LIB32IMAKE= ${LIB32WMAKE:NINSTALL=*:NDESTDIR=*} -DNO_INCS
.endif
@@ -344,30 +344,13 @@ _worldtmp:
rm -f ${OBJTREE}${.CURDIR}/usr.bin/truss/ioctl.c
.endif
.for _dir in \
- usr/bin usr/games usr/include/sys usr/lib \
- usr/libexec usr/sbin usr/share/dict \
- usr/share/groff_font/devX100 \
- usr/share/groff_font/devX100-12 \
- usr/share/groff_font/devX75 \
- usr/share/groff_font/devX75-12 \
- usr/share/groff_font/devascii \
- usr/share/groff_font/devcp1047 \
- usr/share/groff_font/devdvi \
- usr/share/groff_font/devhtml \
- usr/share/groff_font/devkoi8-r \
- usr/share/groff_font/devlatin1 \
- usr/share/groff_font/devlbp \
- usr/share/groff_font/devlj4 \
- usr/share/groff_font/devps \
- usr/share/groff_font/devutf8 \
- usr/share/tmac/mdoc usr/share/tmac/mm
- mkdir -p ${WORLDTMP}/legacy/${_dir}
-.endfor
-.for _dir in \
- lib usr/bin usr/include usr/lib/compat/aout usr/libdata/ldscripts \
- usr/libexec usr/sbin usr/share/misc
+ lib usr legacy/usr
mkdir -p ${WORLDTMP}/${_dir}
.endfor
+ mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
+ -p ${WORLDTMP}/legacy/usr >/dev/null
+ mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
+ -p ${WORLDTMP}/usr >/dev/null
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
-p ${WORLDTMP}/usr/include >/dev/null
ln -sf ${.CURDIR}/sys ${WORLDTMP}
@@ -429,7 +412,7 @@ _libraries:
@echo "--------------------------------------------------------------"
${_+_}cd ${.CURDIR}; \
${WMAKE} -DNO_FSCHG -DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT \
- -DWITHOUT_MAN -DWITHOUT_NLS -DWITHOUT_PROFILE libraries
+ -DWITHOUT_MAN -DWITHOUT_PROFILE libraries
_depend:
@echo
@echo "--------------------------------------------------------------"
@@ -448,10 +431,9 @@ build32:
@echo "--------------------------------------------------------------"
@echo ">>> stage 5.1: building 32 bit shim libraries"
@echo "--------------------------------------------------------------"
-.for _dir in \
- usr/include usr/lib32 usr/share/misc
- mkdir -p ${LIB32TMP}/${_dir}
-.endfor
+ mkdir -p ${LIB32TMP}/usr/lib32
+ mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
+ -p ${LIB32TMP}/usr >/dev/null
mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
-p ${LIB32TMP}/usr/include >/dev/null
mkdir -p ${WORLDTMP}
@@ -612,8 +594,12 @@ installcheck_UGID:
#
# Required install tools to be saved in a scratch dir for safety.
#
+.if ${MK_INFO} != "no"
+_install-info= install-info
+.endif
+
ITOOLS= [ awk cap_mkdb cat chflags chmod chown \
- date echo egrep find grep install-info \
+ date echo egrep find grep ${_install-info} \
ln lockf make mkdir mtree mv pwd_mkdb rm sed sh sysctl \
test true uname wc zic
@@ -1328,3 +1314,92 @@ check-old: check-old-files check-old-libs check-old-dirs
#
showconfig:
@${MAKE} -n -f bsd.own.mk -V dummy -dg1 | grep ^MK_ | sort
+
+
+###############
+
+.if defined(XDEV) && defined(XDEV_ARCH)
+
+NOFUN=-DNO_FSCHG -DWITHOUT_HTML -DWITHOUT_INFO -DNO_LINT \
+ -DWITHOUT_MAN -DWITHOUT_NLS -DWITHOUT_PROFILE \
+ -DWITHOUT_KERBEROS -DWITHOUT_RESCUE -DNO_WARNS
+
+XDDIR=${XDEV}-freebsd
+XDTP=/usr/${XDDIR}
+CDBENV=MAKEOBJDIRPREFIX=${MAKEOBJDIRPREFIX}/${XDDIR} \
+ TARGET=${XDEV} TARGET_ARCH=${XDEV_ARCH}
+CDENV= ${CDBENV} \
+ _SHLIBDIRPREFIX=${XDTP} \
+ TOOLS_PREFIX=${XDTP}
+CD2ENV=${CDENV} \
+ MACHINE=${XDEV} MACHINE_ARCH=${XDEV_ARCH}
+
+CDTMP= ${MAKEOBJDIRPREFIX}/${XDEV}/${.CURDIR}/tmp
+CDMAKE=${CDENV} ${MAKE} ${NOFUN}
+CD2MAKE=${CD2ENV} PATH=${CDTMP}/usr/bin:${XDTP}/usr/bin:${PATH} ${MAKE} ${NOFUN}
+XDDESTDIR=${DESTDIR}${XDTP}
+.if !defined(OSREL)
+OSREL!= uname -r | sed -e 's/[-(].*//'
+.endif
+
+.ORDER: xdev-build xdev-install
+xdev: xdev-build xdev-install
+
+.ORDER: _xb-build-tools _xb-cross-tools
+xdev-build: _xb-build-tools _xb-cross-tools
+
+_xb-build-tools:
+ ${_+_}cd ${.CURDIR}; \
+ ${CDBENV} ${MAKE} -f Makefile.inc1 ${NOFUN} build-tools
+
+_xb-cross-tools:
+.for _tool in \
+ gnu/usr.bin/binutils \
+ gnu/usr.bin/cc
+ ${_+_}@${ECHODIR} "===> xdev ${_tool} (obj,depend,all)"; \
+ cd ${.CURDIR}/${_tool}; \
+ ${CDMAKE} DIRPRFX=${_tool}/ obj; \
+ ${CDMAKE} DIRPRFX=${_tool}/ depend; \
+ ${CDMAKE} DIRPRFX=${_tool}/ all
+.endfor
+
+_xi-mtree:
+ ${_+_}@${ECHODIR} "mtree populating ${XDDESTDIR}"
+ mkdir -p ${XDDESTDIR}
+ mtree -deU -f ${.CURDIR}/etc/mtree/BSD.root.dist \
+ -p ${XDDESTDIR} >/dev/null
+ mtree -deU -f ${.CURDIR}/etc/mtree/BSD.usr.dist \
+ -p ${XDDESTDIR}/usr >/dev/null
+ mtree -deU -f ${.CURDIR}/etc/mtree/BSD.include.dist \
+ -p ${XDDESTDIR}/usr/include >/dev/null
+
+.ORDER: _xi-mtree _xi-cross-tools _xi-includes _xi-libraries _xi-links
+xdev-install: _xi-mtree _xi-cross-tools _xi-includes _xi-libraries _xi-links
+
+_xi-cross-tools:
+ @echo "_xi-cross-tools"
+.for _tool in \
+ gnu/usr.bin/binutils \
+ gnu/usr.bin/cc
+ ${_+_}@${ECHODIR} "===> xdev ${_tool} (install)"; \
+ cd ${.CURDIR}/${_tool}; \
+ ${CDMAKE} DIRPRFX=${_tool}/ install DESTDIR=${XDDESTDIR}
+.endfor
+
+_xi-includes:
+ ${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 par-includes \
+ DESTDIR=${XDDESTDIR}
+
+_xi-libraries:
+ ${_+_}cd ${.CURDIR}; ${CD2MAKE} -f Makefile.inc1 libraries \
+ DESTDIR=${XDDESTDIR}
+
+_xi-links:
+ ${_+_}cd ${XDDESTDIR}/usr/bin; \
+ for i in *; do \
+ ln -sf ../../${XDTP}/usr/bin/$$i \
+ ../../../../usr/bin/${XDDIR}-$$i; \
+ ln -sf ../../${XDTP}/usr/bin/$$i \
+ ../../../../usr/bin/${XDDIR}${OSREL}-$$i; \
+ done
+.endif
diff --git a/ObsoleteFiles.inc b/ObsoleteFiles.inc
index ca00df5..72fe442 100644
--- a/ObsoleteFiles.inc
+++ b/ObsoleteFiles.inc
@@ -14,14 +14,57 @@
# The file is partitioned: OLD_FILES first, then OLD_LIBS and OLD_DIRS last.
#
+# 20090410: VOP_LEASE.9 removed
+OLD_FILES+=usr/share/man/man9/VOP_LEASE.9.gz
+# 20090405: removal of if_ppp(4) and if_sl(4)
+OLD_FILES+=sbin/slattach rescue/slattach
+OLD_FILES+=sbin/startslip rescue/startslip
+OLD_FILES+=usr/include/net/if_ppp.h
+OLD_FILES+=usr/include/net/if_pppvar.h
+OLD_FILES+=usr/include/net/if_slvar.h
+OLD_FILES+=usr/include/net/ppp_comp.h
+OLD_FILES+=usr/include/net/slip.h
+OLD_FILES+=usr/sbin/sliplogin
+OLD_FILES+=usr/sbin/slstat
+OLD_FILES+=usr/sbin/pppd
+OLD_FILES+=usr/sbin/pppstats
+OLD_FILES+=usr/share/man/man1/startslip.1.gz
+OLD_FILES+=usr/share/man/man4/if_ppp.4.gz
+OLD_FILES+=usr/share/man/man4/if_sl.4.gz
+OLD_FILES+=usr/share/man/man4/ppp.4.gz
+OLD_FILES+=usr/share/man/man4/sl.4.gz
+OLD_FILES+=usr/share/man/man8/pppd.8.gz
+OLD_FILES+=usr/share/man/man8/pppstats.8.gz
+OLD_FILES+=usr/share/man/man8/slattach.8.gz
+OLD_FILES+=usr/share/man/man8/slip.8.gz
+OLD_FILES+=usr/share/man/man8/sliplogin.8.gz
+OLD_FILES+=usr/share/man/man8/slstat.8.gz
+# 20090321: libpcap upgraded to 1.0.0
+OLD_LIBS+=lib/libpcap.so.5
+.if ${TARGET_ARCH} == "amd64"
+OLD_LIBS+=usr/lib32/libpcap.so.5
+.endif
+# 20090319: uscanner(4) has been removed
+OLD_FILES+=usr/share/man/man4/uscanner.4.gz
+# 20090313: k8temp(4) renamed to amdtemp(4)
+OLD_FILES+=usr/share/man/man4/k8temp.4.gz
# 20090308: libusb.so.1 renamed
OLD_LIBS+=usr/lib/libusb20.so.1
OLD_FILES+=usr/lib/libusb20.a
OLD_FILES+=usr/lib/libusb20.so
OLD_FILES+=usr/lib/libusb20_p.a
OLD_FILES+=usr/include/libusb20_compat01.h
+.if ${TARGET_ARCH} == "amd64"
+OLD_LIBS+=usr/lib32/libusb20.so.1
+OLD_FILES+=usr/lib32/libusb20.a
+OLD_FILES+=usr/lib32/libusb20.so
+OLD_FILES+=usr/lib32/libusb20_p.a
+.endif
# 20090226: libmp(3) functions renamed
OLD_LIBS+=usr/lib/libmp.so.6
+.if ${TARGET_ARCH} == "amd64"
+OLD_LIBS+=usr/lib32/libmp.so.6
+.endif
# 20090223: changeover of USB stacks
OLD_FILES+=usr/include/dev/usb2/include/ufm2_ioctl.h
OLD_FILES+=usr/include/dev/usb2/include/urio2_ioctl.h
@@ -1436,6 +1479,8 @@ OLD_FILES+=lib/geom/geom_concat.so.1
OLD_FILES+=lib/geom/geom_label.so.1
OLD_FILES+=lib/geom/geom_nop.so.1
OLD_FILES+=lib/geom/geom_stripe.so.1
+# 20040713: fla(4) removed.
+OLD_FILES+=usr/share/man/man4/fla.4.gz
# 200407XX
OLD_FILES+=usr/sbin/kernbb
OLD_FILES+=usr/sbin/ntp-genkeys
diff --git a/UPDATING b/UPDATING
index 7d66660..e5110f0 100644
--- a/UPDATING
+++ b/UPDATING
@@ -22,6 +22,71 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.x IS SLOW:
to maximize performance. (To disable malloc debugging, run
ln -s aj /etc/malloc.conf.)
+20090408:
+ Do not use Giant for kbdmux(4) locking. This is wrong and
+ apparently causing more problems than it solves. This will
+ re-open the issue where interrupt handlers may race with
+ kbdmux(4) in polling mode. Typical symptoms include (but
+ not limited to) duplicated and/or missing characters when
+ low level console functions (such as gets) are used while
+ interrupts are enabled (for example geli password prompt,
+ mountroot prompt etc.). Disabling kbdmux(4) may help.
+
+20090407:
+ The size of structs vnet_net, vnet_inet and vnet_ipfw has changed;
+ kernel modules referencing any of the above need to be recompiled.
+ Bump __FreeBSD_version to 800075.
+
+20090320:
+ GEOM_PART has become the default partition slicer for storage devices,
+ replacing GEOM_MBR, GEOM_BSD, GEOM_PC98 and GEOM_GPT slicers. It
+ introduces some changes:
+
+ MSDOS/EBR: the devices created from MSDOS extended partition entries
+ (EBR) can be named differently than with GEOM_MBR and are now symlinks
+ to devices with offset-based names. fstabs may need to be modified.
+
+ BSD: the "geometry does not match label" warning is harmless in most
+ cases but it points to problems in file system misalignment with
+ disk geometry. The "c" partition is now implicit, covers the whole
+ top-level drive and cannot be (mis)used by users.
+
+ General: Kernel dumps are now not allowed to be written to devices
+ whose partition types indicate they are meant to be used for file
+ systems (or, in case of MSDOS partitions, as something else than
+ the "386BSD" type).
+
+ Most of these changes date approximately from 200812.
+
+20090319:
+ The uscanner(4) driver has been removed from the kernel. This follows
+ Linux removing theirs in 2.6 and making libusb the default interface
+ (supported by sane).
+
+20090319:
+ The multicast forwarding code has been cleaned up. netstat(1)
+ only relies on KVM now for printing bandwidth upcall meters.
+ The IPv4 and IPv6 modules are split into ip_mroute_mod and
+ ip6_mroute_mod respectively. The config(5) options for statically
+ compiling this code remain the same, i.e. 'options MROUTING'.
+
+20090315:
+ Support for the IFF_NEEDSGIANT network interface flag has been
+ removed, which means that non-MPSAFE network device drivers are no
+ longer supported. In particular, if_ar, if_sr, and network device
+ drivers from the old (legacy) USB stack can no longer be built or
+ used.
+
+20090313:
+ POSIX.1 Native Language Support (NLS) has been enabled in libc and
+ a bunch of new language catalog files have also been added.
+ This means that some common libc messages are now localized and
+ they depend on the LC_MESSAGES environmental variable.
+
+20090313:
+ The k8temp(4) driver has been renamed to amdtemp(4) since
+ support for K10 and K11 CPU families was added.
+
20090309:
IGMPv3 and Source-Specific Multicast (SSM) have been merged
to the IPv4 stack. VIMAGE hooks are in but not yet used.
diff --git a/bin/cat/Makefile b/bin/cat/Makefile
index 672a4ee..689dd4d 100644
--- a/bin/cat/Makefile
+++ b/bin/cat/Makefile
@@ -2,5 +2,6 @@
# $FreeBSD$
PROG= cat
+WARNS?= 6
.include <bsd.prog.mk>
diff --git a/bin/sh/alias.c b/bin/sh/alias.c
index a4a4035..ea7ce55 100644
--- a/bin/sh/alias.c
+++ b/bin/sh/alias.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#define ATABSIZE 39
STATIC struct alias *atab[ATABSIZE];
+STATIC int aliases;
STATIC void setalias(char *, char *);
STATIC int unalias(const char *);
@@ -106,6 +107,7 @@ setalias(char *name, char *val)
ap->flag = 0;
ap->next = *app;
*app = ap;
+ aliases++;
INTON;
}
@@ -135,6 +137,7 @@ unalias(const char *name)
ckfree(ap);
INTON;
}
+ aliases--;
return (0);
}
}
@@ -168,6 +171,7 @@ rmaliases(void)
ckfree(tmp);
}
}
+ aliases = 0;
INTON;
}
@@ -187,9 +191,47 @@ lookupalias(char *name, int check)
return (NULL);
}
-/*
- * TODO - sort output
- */
+static int
+comparealiases(const void *p1, const void *p2)
+{
+ const struct alias *const *a1 = p1;
+ const struct alias *const *a2 = p2;
+
+ return strcmp((*a1)->name, (*a2)->name);
+}
+
+static void
+printalias(const struct alias *a)
+{
+ char *p;
+
+ out1fmt("%s=", a->name);
+ /* Don't print the space added above. */
+ p = a->val + strlen(a->val) - 1;
+ *p = '\0';
+ out1qstr(a->val);
+ *p = ' ';
+ out1c('\n');
+}
+
+static void
+printaliases(void)
+{
+ int i, j;
+ struct alias **sorted, *ap;
+
+ sorted = ckmalloc(aliases * sizeof(*sorted));
+ j = 0;
+ for (i = 0; i < ATABSIZE; i++)
+ for (ap = atab[i]; ap; ap = ap->next)
+ if (*ap->name != '\0')
+ sorted[j++] = ap;
+ qsort(sorted, aliases, sizeof(*sorted), comparealiases);
+ for (i = 0; i < aliases; i++)
+ printalias(sorted[i]);
+ ckfree(sorted);
+}
+
int
aliascmd(int argc, char **argv)
{
@@ -198,16 +240,7 @@ aliascmd(int argc, char **argv)
struct alias *ap;
if (argc == 1) {
- int i;
-
- for (i = 0; i < ATABSIZE; i++)
- for (ap = atab[i]; ap; ap = ap->next) {
- if (*ap->name != '\0') {
- out1fmt("alias %s=", ap->name);
- out1qstr(ap->val);
- out1c('\n');
- }
- }
+ printaliases();
return (0);
}
while ((n = *++argv) != NULL) {
@@ -215,11 +248,8 @@ aliascmd(int argc, char **argv)
if ((ap = lookupalias(n, 0)) == NULL) {
outfmt(out2, "alias: %s not found\n", n);
ret = 1;
- } else {
- out1fmt("alias %s=", n);
- out1qstr(ap->val);
- out1c('\n');
- }
+ } else
+ printalias(ap);
else {
*v++ = '\0';
setalias(n, v);
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index f6b702b..26e2148 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -166,7 +166,8 @@ evalstring(char *s)
setstackmark(&smark);
setinputstring(s, 1);
while ((n = parsecmd(0)) != NEOF) {
- evaltree(n, 0);
+ if (n != NULL)
+ evaltree(n, 0);
popstackmark(&smark);
}
popfile();
diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c
index 88b7515..2480c0d 100644
--- a/bin/sh/miscbltin.c
+++ b/bin/sh/miscbltin.c
@@ -73,6 +73,16 @@ int ulimitcmd(int, char **);
* ordinary characters.
*
* This uses unbuffered input, which may be avoidable in some cases.
+ *
+ * Note that if IFS=' :' then read x y should work so that:
+ * 'a b' x='a', y='b'
+ * ' a b ' x='a', y='b'
+ * ':b' x='', y='b'
+ * ':' x='', y=''
+ * '::' x='', y=''
+ * ': :' x='', y=''
+ * ':::' x='', y='::'
+ * ':b c:' x='', y='b c:'
*/
int
@@ -88,6 +98,8 @@ readcmd(int argc __unused, char **argv __unused)
int startword;
int status;
int i;
+ int is_ifs;
+ int saveall = 0;
struct timeval tv;
char *tvptr;
fd_set ifds;
@@ -135,7 +147,7 @@ readcmd(int argc __unused, char **argv __unused)
if (*(ap = argptr) == NULL)
error("arg count");
if ((ifs = bltinlookup("IFS", 1)) == NULL)
- ifs = nullstr;
+ ifs = " \t\n";
if (tv.tv_sec >= 0) {
/*
@@ -167,7 +179,7 @@ readcmd(int argc __unused, char **argv __unused)
}
status = 0;
- startword = 1;
+ startword = 2;
backslash = 0;
STARTSTACKSTR(p);
for (;;) {
@@ -189,22 +201,68 @@ readcmd(int argc __unused, char **argv __unused)
}
if (c == '\n')
break;
- if (startword && *ifs == ' ' && strchr(ifs, c)) {
+ if (strchr(ifs, c))
+ is_ifs = strchr(" \t\n", c) ? 1 : 2;
+ else
+ is_ifs = 0;
+
+ if (startword != 0) {
+ if (is_ifs == 1) {
+ /* Ignore leading IFS whitespace */
+ if (saveall)
+ STPUTC(c, p);
+ continue;
+ }
+ if (is_ifs == 2 && startword == 1) {
+ /* Only one non-whitespace IFS per word */
+ startword = 2;
+ if (saveall)
+ STPUTC(c, p);
+ continue;
+ }
+ }
+
+ if (is_ifs == 0) {
+ /* append this character to the current variable */
+ startword = 0;
+ if (saveall)
+ /* Not just a spare terminator */
+ saveall++;
+ STPUTC(c, p);
continue;
}
- startword = 0;
- if (ap[1] != NULL && strchr(ifs, c) != NULL) {
- STACKSTRNUL(p);
- setvar(*ap, stackblock(), 0);
- ap++;
- startword = 1;
- STARTSTACKSTR(p);
- } else {
+
+ /* end of variable... */
+ startword = is_ifs;
+
+ if (ap[1] == NULL) {
+ /* Last variable needs all IFS chars */
+ saveall++;
STPUTC(c, p);
+ continue;
}
+
+ STACKSTRNUL(p);
+ setvar(*ap, stackblock(), 0);
+ ap++;
+ STARTSTACKSTR(p);
}
STACKSTRNUL(p);
+
+ /* Remove trailing IFS chars */
+ for (; stackblock() <= --p; *p = 0) {
+ if (!strchr(ifs, *p))
+ break;
+ if (strchr(" \t\n", *p))
+ /* Always remove whitespace */
+ continue;
+ if (saveall > 1)
+ /* Don't remove non-whitespace unless it was naked */
+ break;
+ }
setvar(*ap, stackblock(), 0);
+
+ /* Set any remaining args to "" */
while (*++ap != NULL)
setvar(*ap, nullstr, 0);
return status;
diff --git a/cddl/Makefile.inc b/cddl/Makefile.inc
index 99ef333..4161c27 100644
--- a/cddl/Makefile.inc
+++ b/cddl/Makefile.inc
@@ -6,3 +6,5 @@ OPENSOLARIS_SYS_DISTDIR= ${.CURDIR}/../../../sys/cddl/contrib/opensolaris
IGNORE_PRAGMA= YES
CFLAGS+= -DNEED_SOLARIS_BOOLEAN
+
+CSTD?= gnu89
diff --git a/cddl/lib/libzpool/Makefile b/cddl/lib/libzpool/Makefile
index 26d5499..54ab6c0 100644
--- a/cddl/lib/libzpool/Makefile
+++ b/cddl/lib/libzpool/Makefile
@@ -33,8 +33,6 @@ SRCS= ${ZFS_COMMON_SRCS} ${ZFS_SHARED_SRCS} \
${KERNEL_SRCS} ${LIST_SRCS} ${ATOMIC_SRCS} \
${UNICODE_SRCS}
-CFLAGS+= -std=c99
-
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/lib/libumem
@@ -60,4 +58,6 @@ LDADD= -lpthread -lz
# atomic.S doesn't like profiling.
NO_PROFILE=
+CSTD= c99
+
.include <bsd.lib.mk>
diff --git a/cddl/usr.bin/ztest/Makefile b/cddl/usr.bin/ztest/Makefile
index cc0bca4..67ade45ad 100644
--- a/cddl/usr.bin/ztest/Makefile
+++ b/cddl/usr.bin/ztest/Makefile
@@ -5,8 +5,6 @@
PROG= ztest
NO_MAN=
-CFLAGS+= -std=c99
-
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
CFLAGS+= -I${.CURDIR}/../../compat/opensolaris/include
CFLAGS+= -I${.CURDIR}/../../compat/opensolaris/lib/libumem
@@ -21,4 +19,6 @@ DPADD= ${LIBM} ${LIBNVPAIR} ${LIBUMEM} ${LIBZPOOL} \
${LIBPTHREAD} ${LIBZ} ${LIBAVL}
LDADD= -lm -lnvpair -lumem -lzpool -lpthread -lz -lavl
+CSTD= c99
+
.include <bsd.prog.mk>
diff --git a/cddl/usr.sbin/zdb/Makefile b/cddl/usr.sbin/zdb/Makefile
index f0c1b22..35ad2a1 100644
--- a/cddl/usr.sbin/zdb/Makefile
+++ b/cddl/usr.sbin/zdb/Makefile
@@ -6,8 +6,6 @@ PROG= zdb
MAN= zdb.8
SRCS= zdb.c zdb_il.c
-CFLAGS+= -std=c99
-
CFLAGS+= -I${.CURDIR}/../../../sys/cddl/compat/opensolaris
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include
CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/lib/libumem
@@ -25,4 +23,6 @@ DPADD= ${LIBAVL} ${LIBGEOM} ${LIBM} ${LIBNVPAIR} ${LIBPTHREAD} ${LIBUMEM} \
${LIBUUTIL} ${LIBZ} ${LIBZFS} ${LIBZPOOL}
LDADD= -lavl -lgeom -lm -lnvpair -lpthread -lumem -luutil -lz -lzfs -lzpool
+CSTD= c99
+
.include <bsd.prog.mk>
diff --git a/contrib/bind9/CHANGES b/contrib/bind9/CHANGES
index f3d53ee..8d1f22b 100644
--- a/contrib/bind9/CHANGES
+++ b/contrib/bind9/CHANGES
@@ -1,3 +1,8 @@
+ --- 9.4.3-P2 released ---
+
+2579. [bug] DNSSEC lookaside validation failed to handle unknown
+ algorithms. [RT #19479]
+
--- 9.4.3-P1 released ---
2522. [security] Handle -1 from DSA_do_verify().
diff --git a/contrib/bind9/lib/dns/validator.c b/contrib/bind9/lib/dns/validator.c
index e686336..685434b 100644
--- a/contrib/bind9/lib/dns/validator.c
+++ b/contrib/bind9/lib/dns/validator.c
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: validator.c,v 1.119.18.41 2008/08/21 04:59:42 marka Exp $ */
+/* $Id: validator.c,v 1.119.18.41.2.1 2009/03/17 02:23:49 marka Exp $ */
/*! \file */
@@ -211,6 +211,37 @@ exit_check(dns_validator_t *val) {
return (ISC_TRUE);
}
+/*
+ * Check that we have atleast one supported algorithm in the DLV RRset.
+ */
+static inline isc_boolean_t
+dlv_algorithm_supported(dns_validator_t *val) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_dlv_t dlv;
+ isc_result_t result;
+
+ for (result = dns_rdataset_first(&val->dlv);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(&val->dlv)) {
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(&val->dlv, &rdata);
+ result = dns_rdata_tostruct(&rdata, &dlv, NULL);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+
+ if (!dns_resolver_algorithm_supported(val->view->resolver,
+ val->event->name,
+ dlv.algorithm))
+ continue;
+
+ if (dlv.digest_type != DNS_DSDIGEST_SHA256 &&
+ dlv.digest_type != DNS_DSDIGEST_SHA1)
+ continue;
+
+ return (ISC_TRUE);
+ }
+ return (ISC_FALSE);
+}
+
/*%
* Look in the NSEC record returned from a DS query to see if there is
* a NS RRset at this name. If it is found we are at a delegation point.
@@ -2297,19 +2328,36 @@ dlvfetched(isc_task_t *task, isc_event_t *event) {
sizeof(namebuf));
dns_rdataset_clone(&val->frdataset, &val->dlv);
val->havedlvsep = ISC_TRUE;
- validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
- dlv_validator_start(val);
+ if (dlv_algorithm_supported(val)) {
+ validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
+ namebuf);
+ dlv_validator_start(val);
+ } else {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "DLV %s found with no supported algorithms",
+ namebuf);
+ markanswer(val);
+ validator_done(val, ISC_R_SUCCESS);
+ }
} else if (eresult == DNS_R_NXRRSET ||
eresult == DNS_R_NXDOMAIN ||
eresult == DNS_R_NCACHENXRRSET ||
eresult == DNS_R_NCACHENXDOMAIN) {
- result = finddlvsep(val, ISC_TRUE);
+ result = finddlvsep(val, ISC_TRUE);
if (result == ISC_R_SUCCESS) {
- dns_name_format(dns_fixedname_name(&val->dlvsep),
- namebuf, sizeof(namebuf));
- validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found",
- namebuf);
- dlv_validator_start(val);
+ if (dlv_algorithm_supported(val)) {
+ dns_name_format(dns_fixedname_name(&val->dlvsep),
+ namebuf, sizeof(namebuf));
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "DLV %s found", namebuf);
+ dlv_validator_start(val);
+ } else {
+ validator_log(val, ISC_LOG_DEBUG(3),
+ "DLV %s found with no supported "
+ "algorithms", namebuf);
+ markanswer(val);
+ validator_done(val, ISC_R_SUCCESS);
+ }
} else if (result == ISC_R_NOTFOUND) {
validator_log(val, ISC_LOG_DEBUG(3), "DLV not found");
markanswer(val);
@@ -2372,9 +2420,16 @@ startfinddlvsep(dns_validator_t *val, dns_name_t *unsecure) {
}
dns_name_format(dns_fixedname_name(&val->dlvsep), namebuf,
sizeof(namebuf));
- validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
- dlv_validator_start(val);
- return (DNS_R_WAIT);
+ if (dlv_algorithm_supported(val)) {
+ validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found", namebuf);
+ dlv_validator_start(val);
+ return (DNS_R_WAIT);
+ }
+ validator_log(val, ISC_LOG_DEBUG(3), "DLV %s found with no supported "
+ "algorithms", namebuf);
+ markanswer(val);
+ validator_done(val, ISC_R_SUCCESS);
+ return (ISC_R_SUCCESS);
}
/*%
diff --git a/contrib/bind9/version b/contrib/bind9/version
index e956921..1eb5a69 100644
--- a/contrib/bind9/version
+++ b/contrib/bind9/version
@@ -1,4 +1,4 @@
-# $Id: version,v 1.29.134.23.2.1 2008/12/24 00:21:22 marka Exp $
+# $Id: version,v 1.29.134.23.2.2 2009/03/17 02:23:49 marka Exp $
#
# This file must follow /bin/sh rules. It is imported directly via
# configure.
@@ -7,4 +7,4 @@ MAJORVER=9
MINORVER=4
PATCHVER=3
RELEASETYPE=-P
-RELEASEVER=1
+RELEASEVER=2
diff --git a/contrib/csup/rcsfile.c b/contrib/csup/rcsfile.c
index 0d823e8..2e86a88 100644
--- a/contrib/csup/rcsfile.c
+++ b/contrib/csup/rcsfile.c
@@ -140,7 +140,7 @@ static void rcsfile_insertsorteddelta(struct rcsfile *,
struct delta *);
static struct stream *rcsfile_getdeltatext(struct rcsfile *, struct delta *,
struct buf **);
-static void rcsdelta_writestring(char *, size_t, struct stream *);
+static int rcsdelta_writestring(char *, size_t, struct stream *);
static void rcsdelta_insertbranch(struct delta *, struct branch *);
/* Space formatting of RCS file. */
@@ -308,14 +308,19 @@ rcsfile_write(struct rcsfile *rf, struct stream *dest)
/* First write head. */
d = LIST_FIRST(&rf->trunk->deltalist);
- stream_printf(dest, "head%s%s;\n", head_space, d->revnum);
+ if (stream_printf(dest, "head%s%s;\n", head_space, d->revnum) < 0)
+ return (-1);
/* Write branch, if we have. */
- if (rf->branch != NULL)
- stream_printf(dest, "branch%s%s;\n", branch_space, rf->branch);
+ if (rf->branch != NULL) {
+ if (stream_printf(dest, "branch%s%s;\n", branch_space,
+ rf->branch) < 0)
+ return (-1);
+ }
/* Write access. */
- stream_printf(dest, "access");
+ if (stream_printf(dest, "access") < 0)
+ return (-1);
#if 0
if (!STAILQ_EMPTY(&rf->accesslist)) {
/*
@@ -324,32 +329,44 @@ rcsfile_write(struct rcsfile *rf, struct stream *dest)
*/
}
#endif
- stream_printf(dest, ";\n");
+ if (stream_printf(dest, ";\n") < 0)
+ return (-1);
/* Write out taglist. */
- stream_printf(dest, "symbols");
+ if (stream_printf(dest, "symbols") < 0)
+ return (-1);
if (!STAILQ_EMPTY(&rf->taglist)) {
STAILQ_FOREACH(t, &rf->taglist, tag_next) {
- stream_printf(dest, "\n%s%s:%s", tag_space, t->tag,
- t->revnum);
+ if (stream_printf(dest, "\n%s%s:%s", tag_space, t->tag,
+ t->revnum) < 0)
+ return (-1);
}
}
- stream_printf(dest, ";\n");
/* Write out locks and strict. */
- stream_printf(dest, "locks;");
- if (rf->strictlock)
- stream_printf(dest, " strict;");
- stream_printf(dest, "\n");
+ if (stream_printf(dest, ";\nlocks;") < 0)
+ return (-1);
+ if (rf->strictlock) {
+ if (stream_printf(dest, " strict;") < 0)
+ return (-1);
+ }
+ if (stream_printf(dest, "\n") < 0)
+ return (-1);
/* Write out the comment. */
- if (rf->comment != NULL)
- stream_printf(dest, "comment%s%s;\n", comment_space, rf->comment);
- if (rf->expand != EXPAND_DEFAULT)
- stream_printf(dest, "expand%s@%s@;\n", expand_space,
- keyword_encode_expand(rf->expand));
+ if (rf->comment != NULL) {
+ if (stream_printf(dest, "comment%s%s;\n", comment_space,
+ rf->comment) < 0)
+ return (-1);
+ }
+ if (rf->expand != EXPAND_DEFAULT) {
+ if (stream_printf(dest, "expand%s@%s@;\n", expand_space,
+ keyword_encode_expand(rf->expand)) < 0)
+ return (-1);
+ }
- stream_printf(dest, "\n\n");
+ if (stream_printf(dest, "\n\n") < 0)
+ return (-1);
/*
* Write out deltas. We use a stack where we push the appropriate deltas
@@ -364,14 +381,18 @@ rcsfile_write(struct rcsfile *rf, struct stream *dest)
/* Do not write out placeholders just to be safe. */
if (d->placeholder)
continue;
- stream_printf(dest, "%s\n", d->revnum);
- stream_printf(dest, "date%s%s;%sauthor %s;%sstate",
+ if (stream_printf(dest, "%s\n", d->revnum) < 0)
+ return (-1);
+ if (stream_printf(dest, "date%s%s;%sauthor %s;%sstate",
date_space, d->revdate, auth_space, d->author,
- state_space);
- if (d->state != NULL)
- stream_printf(dest, " %s", d->state);
- stream_printf(dest, ";\n");
- stream_printf(dest, "branches");
+ state_space) < 0)
+ return (-1);
+ if (d->state != NULL) {
+ if (stream_printf(dest, " %s", d->state) < 0)
+ return (-1);
+ }
+ if (stream_printf(dest, ";\nbranches") < 0)
+ return (-1);
/*
* Write out our branches. Add them to a reversed list for use
* later when we write out the text.
@@ -385,30 +406,36 @@ rcsfile_write(struct rcsfile *rf, struct stream *dest)
/* Push branch heads on stack. */
STAILQ_FOREACH(d_tmp, &deltalist_inverted, delta_prev) {
- if (d_tmp == NULL)
- err(1, "empty branch!");
- stream_printf(dest, "\n%s%s", branches_space,
- d_tmp->revnum);
+ if (d_tmp == NULL) {
+ lprintf(2, "Empty branch!\n");
+ return (-1);
+ }
+ if (stream_printf(dest, "\n%s%s", branches_space,
+ d_tmp->revnum) < 0)
+ return (-1);
}
- stream_printf(dest, ";\n");
- stream_printf(dest, "next%s", next_space);
+ if (stream_printf(dest, ";\nnext%s", next_space) < 0)
+ return (-1);
/* Push next delta on stack. */
d_next = LIST_NEXT(d, delta_next);
if (d_next != NULL) {
- stream_printf(dest, "%s", d_next->revnum);
+ if (stream_printf(dest, "%s", d_next->revnum) < 0)
+ return (-1);
STAILQ_INSERT_HEAD(&deltastack, d_next, stack_next);
}
- stream_printf(dest, ";\n\n");
+ if (stream_printf(dest, ";\n\n") < 0)
+ return (-1);
}
- stream_printf(dest, "\n");
/* Write out desc. */
- stream_printf(dest, "desc\n@@");
+ if (stream_printf(dest, "\ndesc\n@@") < 0)
+ return (-1);
d = LIST_FIRST(&rf->trunk->deltalist);
/* Write out deltatexts. */
error = rcsfile_write_deltatext(rf, dest);
- stream_printf(dest, "\n");
+ if (stream_printf(dest, "\n") < 0)
+ return (-1);
return (error);
}
@@ -438,21 +465,25 @@ rcsfile_write_deltatext(struct rcsfile *rf, struct stream *dest)
/* Do not write out placeholders just to be safe. */
if (d->placeholder)
return (0);
- stream_printf(dest, "\n\n\n%s\n", d->revnum);
- stream_printf(dest, "log\n@");
+ if (stream_printf(dest, "\n\n\n%s\n", d->revnum) < 0)
+ return (-1);
+ if (stream_printf(dest, "log\n@") < 0)
+ return (-1);
in = stream_open_buf(d->log);
line = stream_getln(in, &size);
while (line != NULL) {
- stream_write(dest, line, size);
+ if (stream_write(dest, line, size) == -1)
+ return (-1);
line = stream_getln(in, &size);
}
stream_close(in);
- stream_printf(dest, "@\n");
- stream_printf(dest, "text\n@");
+ if (stream_printf(dest, "@\ntext\n@") < 0)
+ return (-1);
error = rcsfile_puttext(rf, dest, d, d->prev);
if (error)
return (error);
- stream_printf(dest, "@");
+ if (stream_printf(dest, "@") < 0)
+ return (-1);
LIST_INIT(&branchlist_datesorted);
d_next = LIST_NEXT(d, delta_next);
@@ -535,7 +566,10 @@ rcsfile_puttext(struct rcsfile *rf, struct stream *dest, struct delta *d,
in = stream_open_buf(d->text);
line = stream_getln(in, &size);
while (line != NULL) {
- stream_write(dest, line, size);
+ if (stream_write(dest, line, size) == -1) {
+ error = -1;
+ goto cleanup;
+ }
line = stream_getln(in, &size);
}
stream_close(in);
@@ -549,7 +583,10 @@ rcsfile_puttext(struct rcsfile *rf, struct stream *dest, struct delta *d,
}
line = stream_getln(orig, &size);
while (line != NULL) {
- stream_write(dest, line, size);
+ if (stream_write(dest, line, size) == -1) {
+ error = -1;
+ goto cleanup;
+ }
line = stream_getln(orig, &size);
}
stream_close(orig);
@@ -1261,6 +1298,7 @@ int
rcsdelta_addlog(struct delta *d, char *log, int len)
{
struct stream *dest;
+ int nbytes;
assert(d != NULL);
/* Strip away '@' at beginning and end. */
@@ -1268,9 +1306,9 @@ rcsdelta_addlog(struct delta *d, char *log, int len)
len--;
log[len - 1] = '\0';
dest = stream_open_buf(d->log);
- stream_write(dest, log, len - 1);
+ nbytes = stream_write(dest, log, len - 1);
stream_close(dest);
- return (0);
+ return ((nbytes == -1) ? -1 : 0);
}
/* Add deltatext to a delta. Assume the delta already exists. */
@@ -1278,6 +1316,7 @@ int
rcsdelta_addtext(struct delta *d, char *text, int len)
{
struct stream *dest;
+ int nbytes;
assert(d != NULL);
/* Strip away '@' at beginning and end. */
@@ -1286,36 +1325,40 @@ rcsdelta_addtext(struct delta *d, char *text, int len)
text[len - 1] = '\0';
dest = stream_open_buf(d->text);
- stream_write(dest, text, len - 1);
+ nbytes = stream_write(dest, text, len - 1);
stream_close(dest);
- return (0);
+ return ((nbytes == -1) ? -1 : 0);
}
/* Add a deltatext logline to a delta. */
-void
+int
rcsdelta_appendlog(struct delta *d, char *logline, size_t size)
{
struct stream *dest;
+ int error;
assert(d != NULL);
dest = stream_open_buf(d->log);
- rcsdelta_writestring(logline, size, dest);
+ error = rcsdelta_writestring(logline, size, dest);
stream_close(dest);
+ return (error);
}
/* Add a deltatext textline to a delta. */
-void
+int
rcsdelta_appendtext(struct delta *d, char *textline, size_t size)
{
struct stream *dest;
+ int error;
assert(d != NULL);
dest = stream_open_buf(d->text);
- rcsdelta_writestring(textline, size, dest);
+ error = rcsdelta_writestring(textline, size, dest);
stream_close(dest);
+ return (error);
}
-static void
+static int
rcsdelta_writestring(char *textline, size_t size, struct stream *dest)
{
char buf[3];
@@ -1332,8 +1375,10 @@ rcsdelta_writestring(char *textline, size_t size, struct stream *dest)
buf[2] = '\0';
count = 2;
}
- stream_write(dest, buf, count);
+ if (stream_write(dest, buf, count) == -1)
+ return (-1);
}
+ return (0);
}
/* Set delta state. */
diff --git a/contrib/csup/rcsfile.h b/contrib/csup/rcsfile.h
index 7eb38be..5fa9f31 100644
--- a/contrib/csup/rcsfile.h
+++ b/contrib/csup/rcsfile.h
@@ -65,8 +65,8 @@ void rcsfile_importdelta(struct rcsfile *, char *, char *, char *,
int rcsdelta_addlog(struct delta *, char *, int);
int rcsdelta_addtext(struct delta *, char *, int);
-void rcsdelta_appendlog(struct delta *, char *, size_t);
-void rcsdelta_appendtext(struct delta *, char *, size_t);
+int rcsdelta_appendlog(struct delta *, char *, size_t);
+int rcsdelta_appendtext(struct delta *, char *, size_t);
void rcsdelta_setstate(struct delta *, char *);
void rcsdelta_truncatetext(struct delta *, off_t);
void rcsdelta_truncatelog(struct delta *, off_t);
diff --git a/contrib/csup/rcsparse.c b/contrib/csup/rcsparse.c
index 682f113..5ea690c 100644
--- a/contrib/csup/rcsparse.c
+++ b/contrib/csup/rcsparse.c
@@ -309,7 +309,7 @@ parse_deltatexts(struct rcsfile *rf, yyscan_t *sp, int token)
error = 0;
/* In case we don't have deltatexts. */
if (token != NUM)
- return (token);
+ return (-1);
do {
/* num */
assert(token == NUM);
diff --git a/contrib/csup/updater.c b/contrib/csup/updater.c
index 40122ac..ad9fbcf 100644
--- a/contrib/csup/updater.c
+++ b/contrib/csup/updater.c
@@ -1385,8 +1385,11 @@ updater_addfile(struct updater *up, struct file_update *fup, char *attr,
do {
nread = stream_read(up->rd, buf, (BUFSIZE > remains ?
remains : BUFSIZE));
+ if (nread == -1)
+ return (UPDATER_ERR_PROTO);
remains -= nread;
- stream_write(to, buf, nread);
+ if (stream_write(to, buf, nread) == -1)
+ goto bad;
} while (remains > 0);
stream_close(to);
line = stream_getln(up->rd, NULL);
@@ -1411,9 +1414,11 @@ updater_addfile(struct updater *up, struct file_update *fup, char *attr,
FA_MODTIME | FA_MASK);
error = updater_updatefile(up, fup, md5, isfixup);
fup->wantmd5 = NULL; /* So that it doesn't get freed. */
- if (error)
- return (error);
- return (0);
+ return (error);
+bad:
+ xasprintf(&up->errmsg, "%s: Cannot write: %s", fup->temppath,
+ strerror(errno));
+ return (UPDATER_ERR_MSG);
}
static int
@@ -1469,7 +1474,9 @@ updater_checkout(struct updater *up, struct file_update *fup, int isfixup)
if (nbytes == -1)
goto bad;
}
- stream_write(to, line, size);
+ nbytes = stream_write(to, line, size);
+ if (nbytes == -1)
+ goto bad;
line = stream_getln(up->rd, &size);
first = 0;
}
@@ -1661,6 +1668,7 @@ updater_rcsedit(struct updater *up, struct file_update *fup, char *name,
else
lprintf(1, " Touch %s", fup->coname);
/* Install new attributes. */
+ fattr_umask(sr->sr_serverattr, coll->co_umask);
fattr_install(sr->sr_serverattr, fup->destpath, NULL);
if (fup->attic)
lprintf(1, " -> Attic");
@@ -1681,8 +1689,11 @@ updater_rcsedit(struct updater *up, struct file_update *fup, char *name,
error = rcsfile_write(rf, dest);
stream_close(dest);
rcsfile_free(rf);
- if (error)
- lprintf(-1, "Error writing %s\n", name);
+ if (error) {
+ xasprintf(&up->errmsg, "%s: Cannot write: %s", fup->temppath,
+ strerror(errno));
+ return (UPDATER_ERR_MSG);
+ }
finish:
sr->sr_clientattr = fattr_frompath(path, FATTR_NOFOLLOW);
@@ -1767,7 +1778,9 @@ updater_addelta(struct rcsfile *rf, struct stream *rd, char *cmdline)
size--;
logline++;
}
- rcsdelta_appendlog(d, logline, size);
+ if (rcsdelta_appendlog(d, logline, size)
+ < 0)
+ return (-1);
logline = stream_getln(rd, &size);
}
break;
@@ -1798,7 +1811,9 @@ updater_addelta(struct rcsfile *rf, struct stream *rd, char *cmdline)
size--;
textline++;
}
- rcsdelta_appendtext(d, textline, size);
+ if (rcsdelta_appendtext(d, textline,
+ size) < 0)
+ return (-1);
textline = stream_getln(rd, &size);
}
break;
@@ -1838,8 +1853,15 @@ updater_append_file(struct updater *up, struct file_update *fup, off_t pos)
stream_filter_start(to, STREAM_FILTER_MD5, md5);
/* First write the existing content. */
- while ((nread = read(fd, buf, BUFSIZE)) > 0)
- stream_write(to, buf, nread);
+ while ((nread = read(fd, buf, BUFSIZE)) > 0) {
+ if (stream_write(to, buf, nread) == -1)
+ goto bad;
+ }
+ if (nread == -1) {
+ xasprintf(&up->errmsg, "%s: Error reading: %s",
+ strerror(errno));
+ return (UPDATER_ERR_MSG);
+ }
close(fd);
bytes = fattr_filesize(fa) - pos;
@@ -1847,8 +1869,11 @@ updater_append_file(struct updater *up, struct file_update *fup, off_t pos)
do {
nread = stream_read(up->rd, buf,
(BUFSIZE > bytes) ? bytes : BUFSIZE);
+ if (nread == -1)
+ return (UPDATER_ERR_PROTO);
bytes -= nread;
- stream_write(to, buf, nread);
+ if (stream_write(to, buf, nread) == -1)
+ goto bad;
} while (bytes > 0);
stream_close(to);
@@ -1874,9 +1899,11 @@ updater_append_file(struct updater *up, struct file_update *fup, off_t pos)
FA_MODTIME | FA_MASK);
error = updater_updatefile(up, fup, md5, 0);
fup->wantmd5 = NULL; /* So that it doesn't get freed. */
- if (error)
- return (error);
- return (0);
+ return (error);
+bad:
+ xasprintf(&up->errmsg, "%s: Cannot write: %s", fup->temppath,
+ strerror(errno));
+ return (UPDATER_ERR_MSG);
}
/*
diff --git a/contrib/gcc/c-cppbuiltin.c b/contrib/gcc/c-cppbuiltin.c
index 45e2acb..906ef55 100644
--- a/contrib/gcc/c-cppbuiltin.c
+++ b/contrib/gcc/c-cppbuiltin.c
@@ -1,5 +1,6 @@
/* Define builtin-in macros for the C family front ends.
- Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -484,7 +485,10 @@ c_cpp_builtins (cpp_reader *pfile)
/* Misc. */
builtin_define_with_value ("__VERSION__", version_string, 1);
- cpp_define (pfile, "__GNUC_GNU_INLINE__");
+ if (flag_gnu89_inline)
+ cpp_define (pfile, "__GNUC_GNU_INLINE__");
+ else
+ cpp_define (pfile, "__GNUC_STDC_INLINE__");
/* Definitions for LP64 model. */
if (TYPE_PRECISION (long_integer_type_node) == 64
diff --git a/contrib/gcc/c-decl.c b/contrib/gcc/c-decl.c
index 5c46615..64a6fa8 100644
--- a/contrib/gcc/c-decl.c
+++ b/contrib/gcc/c-decl.c
@@ -1,6 +1,6 @@
/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
@@ -20,6 +20,9 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
/* $FreeBSD$ */
+/* Merged C99 inline changes from gcc trunk 122565 2007-03-05 */
+/* Fixed problems with compiling inline-25.c and inline-26.c */
+/* XXX still fails inline-29.c, inline-31.c, and inline-32.c */
/* Process declarations and symbol lookup for C front end.
Also constructs types; the standard scalar types at initialization,
@@ -156,10 +159,6 @@ int current_function_returns_abnormally;
static int warn_about_return_type;
-/* Nonzero when starting a function declared `extern inline'. */
-
-static int current_extern_inline;
-
/* Nonzero when the current toplevel function contains a declaration
of a nested function which is never defined. */
@@ -799,11 +798,22 @@ pop_scope (void)
&& DECL_ABSTRACT_ORIGIN (p) != p)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
if (!DECL_EXTERNAL (p)
- && DECL_INITIAL (p) == 0)
+ && DECL_INITIAL (p) == 0
+ && scope != file_scope
+ && scope != external_scope)
{
error ("nested function %q+D declared but never defined", p);
undef_nested_function = true;
}
+ /* C99 6.7.4p6: "a function with external linkage... declared
+ with an inline function specifier ... shall also be defined in the
+ same translation unit." */
+ else if (DECL_DECLARED_INLINE_P (p)
+ && TREE_PUBLIC (p)
+ && !DECL_INITIAL (p)
+ && !flag_gnu89_inline)
+ pedwarn ("inline function %q+D declared but never defined", p);
+
goto common_symbol;
case VAR_DECL:
@@ -1294,10 +1304,11 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
/* Function declarations can either be 'static' or 'extern' (no
qualifier is equivalent to 'extern' - C99 6.2.2p5) and therefore
- can never conflict with each other on account of linkage (6.2.2p4).
- Multiple definitions are not allowed (6.9p3,5) but GCC permits
- two definitions if one is 'extern inline' and one is not. The non-
- extern-inline definition supersedes the extern-inline definition. */
+ can never conflict with each other on account of linkage
+ (6.2.2p4). Multiple definitions are not allowed (6.9p3,5) but
+ gnu89 mode permits two definitions if one is 'extern inline' and
+ one is not. The non- extern-inline definition supersedes the
+ extern-inline definition. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
@@ -1323,16 +1334,18 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
{
/* If both decls are in the same TU and the new declaration
isn't overriding an extern inline reject the new decl.
- When we handle c99 style inline rules we'll want to reject
- the following:
-
- DECL_EXTERN_INLINE (olddecl)
- && !DECL_EXTERN_INLINE (newdecl)
-
- if they're in the same translation unit. Until we implement
- the full semantics we accept the construct. */
- if (!(DECL_EXTERN_INLINE (olddecl)
- && !DECL_EXTERN_INLINE (newdecl))
+ In c99, no overriding is allowed in the same translation
+ unit. */
+ if ((!DECL_EXTERN_INLINE (olddecl)
+ || DECL_EXTERN_INLINE (newdecl)
+ || (!flag_gnu89_inline
+ && (!DECL_DECLARED_INLINE_P (olddecl)
+ || !lookup_attribute ("gnu_inline",
+ DECL_ATTRIBUTES (olddecl)))
+ && (!DECL_DECLARED_INLINE_P (newdecl)
+ || !lookup_attribute ("gnu_inline",
+ DECL_ATTRIBUTES (newdecl))))
+ )
&& same_translation_unit_p (newdecl, olddecl))
{
error ("redefinition of %q+D", newdecl);
@@ -1392,6 +1405,23 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
warned = true;
}
}
+
+ /* Make sure gnu_inline attribute is either not present, or
+ present on all inline decls. */
+ if (DECL_DECLARED_INLINE_P (olddecl)
+ && DECL_DECLARED_INLINE_P (newdecl))
+ {
+ bool newa = lookup_attribute ("gnu_inline",
+ DECL_ATTRIBUTES (newdecl)) != NULL;
+ bool olda = lookup_attribute ("gnu_inline",
+ DECL_ATTRIBUTES (olddecl)) != NULL;
+ if (newa != olda)
+ {
+ error ("%<gnu_inline%> attribute present on %q+D",
+ newa ? newdecl : olddecl);
+ error ("%Jbut not here", newa ? olddecl : newdecl);
+ }
+ }
}
else if (TREE_CODE (newdecl) == VAR_DECL)
{
@@ -1523,9 +1553,13 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
??? Should we still warn about this now we have unit-at-a-time
mode and can get it right?
Definitely don't complain if the decls are in different translation
- units. */
+ units.
+ C99 permits this, so don't warn in that case. (The function
+ may not be inlined everywhere in function-at-a-time mode, but
+ we still shouldn't warn.) */
if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl)
- && same_translation_unit_p (olddecl, newdecl))
+ && same_translation_unit_p (olddecl, newdecl)
+ && flag_gnu89_inline)
{
if (TREE_USED (olddecl))
{
@@ -1602,12 +1636,13 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
static void
merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
{
- int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
- && DECL_INITIAL (newdecl) != 0);
- int new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL
- && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0);
- int old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
- && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0);
+ bool new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
+ && DECL_INITIAL (newdecl) != 0);
+ bool new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL
+ && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0);
+ bool old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
+ && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0);
+ bool extern_changed = false;
/* For real parm decl following a forward decl, rechain the old decl
in its new location and clear TREE_ASM_WRITTEN (it's not a
@@ -1750,6 +1785,20 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
}
}
+ /* In c99, 'extern' declaration before (or after) 'inline' means this
+ function is not DECL_EXTERNAL, unless 'gnu_inline' attribute
+ is present. */
+ if (TREE_CODE (newdecl) == FUNCTION_DECL
+ && !flag_gnu89_inline
+ && (DECL_DECLARED_INLINE_P (newdecl)
+ || DECL_DECLARED_INLINE_P (olddecl))
+ && (!DECL_DECLARED_INLINE_P (newdecl)
+ || !DECL_DECLARED_INLINE_P (olddecl)
+ || !DECL_EXTERNAL (olddecl))
+ && DECL_EXTERNAL (newdecl)
+ && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (newdecl)))
+ DECL_EXTERNAL (newdecl) = 0;
+
if (DECL_EXTERNAL (newdecl))
{
TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
@@ -1842,6 +1891,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
}
}
+ extern_changed = DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl);
+
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
But preserve OLDDECL's DECL_UID and DECL_CONTEXT. */
{
@@ -1884,6 +1935,13 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
|| (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl))))
make_decl_rtl (olddecl);
+
+ /* If we changed a function from DECL_EXTERNAL to !DECL_EXTERNAL,
+ and the definition is coming from the old version, cgraph needs
+ to be called again. */
+ if (extern_changed && !new_is_definition
+ && TREE_CODE (olddecl) == FUNCTION_DECL && DECL_INITIAL (olddecl))
+ cgraph_finalize_function (olddecl, false);
}
/* Handle when a new declaration NEWDECL has the same name as an old
@@ -3274,6 +3332,18 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
/* Set attributes here so if duplicate decl, will have proper attributes. */
decl_attributes (&decl, attributes, 0);
+ /* Handle gnu_inline attribute. */
+ if (declspecs->inline_p
+ && !flag_gnu89_inline
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl)))
+ {
+ if (declspecs->storage_class == csc_auto && current_scope != file_scope)
+ ;
+ else if (declspecs->storage_class != csc_static)
+ DECL_EXTERNAL (decl) = !DECL_EXTERNAL (decl);
+ }
+
if (TREE_CODE (decl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (decl)))
{
@@ -3301,6 +3371,18 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
decl);
+ /* C99 6.7.4p3: An inline definition of a function with external
+ linkage shall not contain a definition of a modifiable object
+ with static storage duration... */
+ if (TREE_CODE (decl) == VAR_DECL
+ && current_scope != file_scope
+ && TREE_STATIC (decl)
+ && !TREE_READONLY (decl)
+ && DECL_DECLARED_INLINE_P (current_function_decl)
+ && DECL_EXTERNAL (current_function_decl))
+ pedwarn ("%q+D is static but declared in inline function %qD "
+ "which is not static", decl, current_function_decl);
+
/* Add this decl to the current scope.
TEM may equal DECL or it may be a previous decl of the same name. */
tem = pushdecl (decl);
@@ -4755,8 +4837,16 @@ grokdeclarator (const struct c_declarator *declarator,
GCC to signify a forward declaration of a nested function. */
if (storage_class == csc_auto && current_scope != file_scope)
DECL_EXTERNAL (decl) = 0;
+ /* In C99, a function which is declared 'inline' with 'extern'
+ is not an external reference (which is confusing). It
+ means that the later definition of the function must be output
+ in this file, C99 6.7.4p6. In GNU C89, a function declared
+ 'extern inline' is an external reference. */
+ else if (declspecs->inline_p && storage_class != csc_static)
+ DECL_EXTERNAL (decl) = ((storage_class == csc_extern)
+ == flag_gnu89_inline);
else
- DECL_EXTERNAL (decl) = 1;
+ DECL_EXTERNAL (decl) = !initialized;
/* Record absence of global scope for `static' or `auto'. */
TREE_PUBLIC (decl)
@@ -4786,11 +4876,7 @@ grokdeclarator (const struct c_declarator *declarator,
the abstract origin pointing between the declarations,
which will confuse dwarf2out. */
if (initialized)
- {
- DECL_INLINE (decl) = 1;
- if (storage_class == csc_extern)
- current_extern_inline = 1;
- }
+ DECL_INLINE (decl) = 1;
}
/* If -finline-functions, assume it can be inlined. This does
two things: let the function be deferred until it is actually
@@ -5288,12 +5374,15 @@ start_struct (enum tree_code code, tree name)
error ("nested redefinition of %<union %E%>", name);
else
error ("nested redefinition of %<struct %E%>", name);
+ /* Don't create structures that contain themselves. */
+ ref = NULL_TREE;
}
}
- else
- {
- /* Otherwise create a forward-reference just so the tag is in scope. */
+ /* Otherwise create a forward-reference just so the tag is in scope. */
+
+ if (ref == NULL_TREE || TREE_CODE (ref) != code)
+ {
ref = make_node (code);
pushtag (name, ref);
}
@@ -5985,7 +6074,6 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
current_function_returns_null = 0;
current_function_returns_abnormally = 0;
warn_about_return_type = 0;
- current_extern_inline = 0;
c_switch_stack = NULL;
nstack_se = XOBNEW (&parser_obstack, struct c_label_context_se);
@@ -6025,6 +6113,16 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
warning (OPT_Wattributes, "inline function %q+D given attribute noinline",
decl1);
+ /* Handle gnu_inline attribute. */
+ if (declspecs->inline_p
+ && !flag_gnu89_inline
+ && TREE_CODE (decl1) == FUNCTION_DECL
+ && lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1)))
+ {
+ if (declspecs->storage_class != csc_static)
+ DECL_EXTERNAL (decl1) = !DECL_EXTERNAL (decl1);
+ }
+
announce_function (decl1);
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
@@ -6137,36 +6235,6 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
warning (OPT_Wmissing_declarations,
"%q+D was used with no declaration before its definition", decl1);
- /* This is a definition, not a reference.
- So normally clear DECL_EXTERNAL.
- However, `extern inline' acts like a declaration
- except for defining how to inline. So set DECL_EXTERNAL in that case. */
- DECL_EXTERNAL (decl1) = current_extern_inline;
-
- /* C99 specified different behaviour for non-static inline
- functions, compared with the traditional GNU behaviour. We don't
- support the C99 behaviour, but we do warn about non-static inline
- functions here. The warning can be disabled via an explicit use
- of -fgnu89-inline, or by using the gnu_inline attribute. */
- if (DECL_DECLARED_INLINE_P (decl1)
- && TREE_PUBLIC (decl1)
- && flag_isoc99
- && flag_gnu89_inline != 1
- && !lookup_attribute ("gnu_inline", DECL_ATTRIBUTES (decl1))
- && diagnostic_report_warnings_p ())
- {
- static bool info = false;
-
- warning (0, "C99 inline functions are not supported; using GNU89");
- if (!info)
- {
- warning (0,
- "to disable this warning use -fgnu89-inline or "
- "the gnu_inline function attribute");
- info = true;
- }
- }
-
/* This function exists in static storage.
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
@@ -6942,7 +7010,6 @@ c_push_function_context (struct function *f)
p->returns_null = current_function_returns_null;
p->returns_abnormally = current_function_returns_abnormally;
p->warn_about_return_type = warn_about_return_type;
- p->extern_inline = current_extern_inline;
}
/* Restore the variables used during compilation of a C function. */
@@ -6971,7 +7038,6 @@ c_pop_function_context (struct function *f)
current_function_returns_null = p->returns_null;
current_function_returns_abnormally = p->returns_abnormally;
warn_about_return_type = p->warn_about_return_type;
- current_extern_inline = p->extern_inline;
f->language = NULL;
}
diff --git a/contrib/gcc/c-opts.c b/contrib/gcc/c-opts.c
index d27959f..3e89ec2 100644
--- a/contrib/gcc/c-opts.c
+++ b/contrib/gcc/c-opts.c
@@ -21,6 +21,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA. */
/* $FreeBSD$ */
+/* Merged C99 inline changes from gcc trunk 122565 2007-03-05 */
#include "config.h"
#include "system.h"
@@ -1008,11 +1009,12 @@ c_common_post_options (const char **pfilename)
if (flag_inline_functions)
flag_inline_trees = 2;
- /* We recognize -fgnu89-inline in preparation for 4.3 where the
- option will be meaningful. Here we just reject
- -fno-gnu89-inline, since we don't support it. */
- if (!flag_gnu89_inline)
- error ("-fno-gnu89-inline is not supported");
+ /* By default we use C99 inline semantics in GNU99 or C99 mode. C99
+ inline semantics are not supported in GNU89 or C89 mode. */
+ if (flag_gnu89_inline == -1)
+ flag_gnu89_inline = !flag_isoc99;
+ else if (!flag_gnu89_inline && !flag_isoc99)
+ error ("-fno-gnu89-inline is only supported in GNU99 or C99 mode");
/* If we are given more than one input file, we must use
unit-at-a-time mode. */
diff --git a/contrib/gcc/c-tree.h b/contrib/gcc/c-tree.h
index 5139215..7e2c81f 100644
--- a/contrib/gcc/c-tree.h
+++ b/contrib/gcc/c-tree.h
@@ -384,7 +384,6 @@ struct language_function GTY(())
int returns_null;
int returns_abnormally;
int warn_about_return_type;
- int extern_inline;
};
/* Save lists of labels used or defined in particular contexts.
diff --git a/contrib/gcc/c-typeck.c b/contrib/gcc/c-typeck.c
index 912fd27..b2906ee 100644
--- a/contrib/gcc/c-typeck.c
+++ b/contrib/gcc/c-typeck.c
@@ -2109,6 +2109,19 @@ build_external_ref (tree id, int fun, location_t loc)
if (context != 0 && context != current_function_decl)
DECL_NONLOCAL (ref) = 1;
}
+ /* C99 6.7.4p3: An inline definition of a function with external
+ linkage ... shall not contain a reference to an identifier with
+ internal linkage. */
+ else if (current_function_decl != 0
+ && DECL_DECLARED_INLINE_P (current_function_decl)
+ && DECL_EXTERNAL (current_function_decl)
+ && VAR_OR_FUNCTION_DECL_P (ref)
+ && DECL_FILE_SCOPE_P (ref)
+ && pedantic
+ && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
+ && ! TREE_PUBLIC (ref))
+ pedwarn ("%H%qD is static but used in inline function %qD "
+ "which is not static", &loc, ref, current_function_decl);
return ref;
}
diff --git a/contrib/gcc/doc/extend.texi b/contrib/gcc/doc/extend.texi
index 0ba7c29..7d3c010 100644
--- a/contrib/gcc/doc/extend.texi
+++ b/contrib/gcc/doc/extend.texi
@@ -3829,66 +3829,54 @@ These attributes mainly are intended to support the @code{__vector},
@cindex open coding
@cindex macros, inline alternative
-By declaring a function @code{inline}, you can direct GCC to
+By declaring a function inline, you can direct GCC to make
+calls to that function faster. One way GCC can achieve this is to
integrate that function's code into the code for its callers. This
makes execution faster by eliminating the function-call overhead; in
-addition, if any of the actual argument values are constant, their known
-values may permit simplifications at compile time so that not all of the
-inline function's code needs to be included. The effect on code size is
-less predictable; object code may be larger or smaller with function
-inlining, depending on the particular case. Inlining of functions is an
-optimization and it really ``works'' only in optimizing compilation. If
-you don't use @option{-O}, no function is really inline.
-
-Inline functions are included in the ISO C99 standard, but there are
-currently substantial differences between what GCC implements and what
-the ISO C99 standard requires. GCC will fully support C99 inline
-functions in version 4.3. The traditional GCC handling of inline
-functions will still be available with @option{-std=gnu89},
-@option{-fgnu89-inline} or when @code{gnu_inline} attribute is present
-on all inline declarations. The preprocessor macros
-@code{__GNUC_GNU_INLINE__} and @code{__GNUC_STDC_INLINE__} may be used
-to determine the handling of @code{inline} during a particular
-compilation (@pxref{Common Predefined Macros,,,cpp,The C
-Preprocessor}).
+addition, if any of the actual argument values are constant, their
+known values may permit simplifications at compile time so that not
+all of the inline function's code needs to be included. The effect on
+code size is less predictable; object code may be larger or smaller
+with function inlining, depending on the particular case. You can
+also direct GCC to try to integrate all ``simple enough'' functions
+into their callers with the option @option{-finline-functions}.
+
+GCC implements three different semantics of declaring a function
+inline. One is available with @option{-std=gnu89}, another when
+@option{-std=c99} or @option{-std=gnu99}, and the third is used when
+compiling C++.
To declare a function inline, use the @code{inline} keyword in its
declaration, like this:
@smallexample
-inline int
+static inline int
inc (int *a)
@{
(*a)++;
@}
@end smallexample
-(If you are writing a header file to be included in ISO C programs, write
-@code{__inline__} instead of @code{inline}. @xref{Alternate Keywords}.)
-You can also make all ``simple enough'' functions inline with the option
-@option{-finline-functions}.
+If you are writing a header file to be included in ISO C89 programs, write
+@code{__inline__} instead of @code{inline}. @xref{Alternate Keywords}.
-@opindex Winline
-Note that certain usages in a function definition can make it unsuitable
-for inline substitution. Among these usages are: use of varargs, use of
-alloca, use of variable sized data types (@pxref{Variable Length}),
-use of computed goto (@pxref{Labels as Values}), use of nonlocal goto,
-and nested functions (@pxref{Nested Functions}). Using @option{-Winline}
-will warn when a function marked @code{inline} could not be substituted,
-and will give the reason for the failure.
+The three types of inlining behave similarly in two important cases:
+when the @code{inline} keyword is used on a @code{static} function,
+like the example above, and when a function is first declared without
+using the @code{inline} keyword and then is defined with
+@code{inline}, like this:
-Note that in C and Objective-C, unlike C++, the @code{inline} keyword
-does not affect the linkage of the function.
+@smallexample
+extern int inc (int *a);
+inline int
+inc (int *a)
+@{
+ (*a)++;
+@}
+@end smallexample
-@cindex automatic @code{inline} for C++ member fns
-@cindex @code{inline} automatic for C++ member fns
-@cindex member fns, automatically @code{inline}
-@cindex C++ member fns, automatically @code{inline}
-@opindex fno-default-inline
-GCC automatically inlines member functions defined within the class
-body of C++ programs even if they are not explicitly declared
-@code{inline}. (You can override this with @option{-fno-default-inline};
-@pxref{C++ Dialect Options,,Options Controlling C++ Dialect}.)
+In both of these common cases, the program behaves the same as if you
+had not used the @code{inline} keyword, except for its speed.
@cindex inline functions, omission of
@opindex fkeep-inline-functions
@@ -3904,6 +3892,27 @@ nonintegrated call, then the function is compiled to assembler code as
usual. The function must also be compiled as usual if the program
refers to its address, because that can't be inlined.
+@cindex automatic @code{inline} for C++ member fns
+@cindex @code{inline} automatic for C++ member fns
+@cindex member fns, automatically @code{inline}
+@cindex C++ member fns, automatically @code{inline}
+@opindex fno-default-inline
+As required by ISO C++, GCC considers member functions defined within
+the body of a class to be marked inline even if they are
+not explicitly declared with the @code{inline} keyword. You can
+override this with @option{-fno-default-inline}; @pxref{C++ Dialect
+Options,,Options Controlling C++ Dialect}.
+
+GCC does not inline any functions when not optimizing unless you specify
+the @samp{always_inline} attribute for the function, like this:
+
+@smallexample
+/* @r{Prototype.} */
+inline void foo (const char) __attribute__((always_inline));
+@end smallexample
+
+The remainder of this section is specific to GNU C89 inlining.
+
@cindex non-static inline function
When an inline function is not @code{static}, then the compiler must assume
that there may be calls from other source files; since a global symbol can
@@ -3926,24 +3935,6 @@ The definition in the header file will cause most calls to the function
to be inlined. If any uses of the function remain, they will refer to
the single copy in the library.
-Since GCC 4.3 will implement ISO C99 semantics for
-inline functions, it is simplest to use @code{static inline} only
-to guarantee compatibility. (The
-existing semantics will remain available when @option{-std=gnu89} is
-specified, but eventually the default will be @option{-std=gnu99};
-that will implement the C99 semantics, though it does not do so in
-versions of GCC before 4.3. After the default changes, the existing
-semantics will still be available via the @option{-fgnu89-inline}
-option or the @code{gnu_inline} function attribute.)
-
-GCC does not inline any functions when not optimizing unless you specify
-the @samp{always_inline} attribute for the function, like this:
-
-@smallexample
-/* @r{Prototype.} */
-inline void foo (const char) __attribute__((always_inline));
-@end smallexample
-
@node Extended Asm
@section Assembler Instructions with C Expression Operands
@cindex extended @code{asm}
diff --git a/contrib/gdb/FREEBSD-Xlist b/contrib/gdb/FREEBSD-Xlist
index 26d286a..53f455c 100644
--- a/contrib/gdb/FREEBSD-Xlist
+++ b/contrib/gdb/FREEBSD-Xlist
@@ -1,60 +1,69 @@
$FreeBSD$
-gdb-6.1.1/bfd/*
-gdb-6.1.1/config/*
-gdb-6.1.1/etc/*
-gdb-6.1.1/gdb/avr*
-gdb-6.1.1/gdb/config/avr/*
-gdb-6.1.1/gdb/config/cris/*
-gdb-6.1.1/gdb/config/d10v/*
-gdb-6.1.1/gdb/config/djgpp/*
-gdb-6.1.1/gdb/config/frv/*
-gdb-6.1.1/gdb/config/h8300/*
-gdb-6.1.1/gdb/config/m32r/*
-gdb-6.1.1/gdb/config/m68hc11/*
-gdb-6.1.1/gdb/config/m68k/*
-gdb-6.1.1/gdb/config/mcore/*
-gdb-6.1.1/gdb/config/mn10300/*
-gdb-6.1.1/gdb/config/ns32k/*
-gdb-6.1.1/gdb/config/pa/*
-gdb-6.1.1/gdb/config/sh/*
-gdb-6.1.1/gdb/config/v850/*
-gdb-6.1.1/gdb/config/vax/*
-gdb-6.1.1/gdb/config/xstormy16/*
-gdb-6.1.1/gdb/cris*
-gdb-6.1.1/gdb/d10v*
-gdb-6.1.1/gdb/frv*
-gdb-6.1.1/gdb/h8300*
-gdb-6.1.1/gdb/*m32r*
-gdb-6.1.1/gdb/m68*
-gdb-6.1.1/gdb/mcore*
-gdb-6.1.1/gdb/mn10300*
-gdb-6.1.1/gdb/nlm/*
-gdb-6.1.1/gdb/ns32k*
-gdb-6.1.1/gdb/osf-share/*
-gdb-6.1.1/gdb/hppa*
-gdb-6.1.1/gdb/rdi-share/*
-gdb-6.1.1/gdb/sh*
-gdb-6.1.1/gdb/testsuite/*
-gdb-6.1.1/gdb/v850*
-gdb-6.1.1/gdb/vax*
-gdb-6.1.1/gdb/vx-share/*
-gdb-6.1.1/gdb/xstormy16*
-gdb-6.1.1/include/aout/*
-gdb-6.1.1/include/coff/*
-gdb-6.1.1/include/elf/*
-gdb-6.1.1/include/mpw/*
-gdb-6.1.1/include/nlm/*
-gdb-6.1.1/include/opcode/*
-gdb-6.1.1/intl/*
-gdb-6.1.1/libiberty/*
-gdb-6.1.1/mmalloc/*
-gdb-6.1.1/opcodes/*
-gdb-6.1.1/readline/*
-gdb-6.1.1/sim/*
-gdb-6.1.1/texinfo/*
-gdb-6.1.1/utils/*
+gdb-*/bfd/*
+gdb-*/config/*
+gdb-*/etc/*
+gdb-*/gdb/avr*
+gdb-*/gdb/config/avr/*
+gdb-*/gdb/config/cris/*
+gdb-*/gdb/config/d10v/*
+gdb-*/gdb/config/djgpp/*
+gdb-*/gdb/config/frv/*
+gdb-*/gdb/config/h8300/*
+gdb-*/gdb/config/m32r/*
+gdb-*/gdb/config/m68hc11/*
+gdb-*/gdb/config/m68k/*
+gdb-*/gdb/config/mcore/*
+gdb-*/gdb/config/mn10300/*
+gdb-*/gdb/config/ns32k/*
+gdb-*/gdb/config/pa/*
+gdb-*/gdb/config/sh/*
+gdb-*/gdb/config/v850/*
+gdb-*/gdb/config/vax/*
+gdb-*/gdb/config/xstormy16/*
+gdb-*/gdb/cris*
+gdb-*/gdb/d10v*
+gdb-*/gdb/frv*
+gdb-*/gdb/h8300*
+gdb-*/gdb/iq2000*
+gdb-*/gdb/i386nbsd*
+gdb-*/gdb/m32c*
+gdb-*/gdb/*m32r*
+gdb-*/gdb/m68*
+gdb-*/gdb/m88*
+gdb-*/gdb/mcore*
+gdb-*/gdb/mn10300*
+gdb-*/gdb/mt-*
+gdb-*/gdb/nlm/*
+gdb-*/gdb/ns32k*
+gdb-*/gdb/osf-share/*
+gdb-*/gdb/ppcobsd*
+gdb-*/gdb/hppa*
+gdb-*/gdb/rdi-share/*
+gdb-*/gdb/sh*
+gdb-*/gdb/testsuite/*
+gdb-*/gdb/v850*
+gdb-*/gdb/vax*
+gdb-*/gdb/vx-share/*
+gdb-*/gdb/xstormy16*
+gdb-*/gdb/xtensa*
+gdb-*/include/aout/*
+gdb-*/include/coff/*
+gdb-*/include/elf/*
+gdb-*/include/mpw/*
+gdb-*/include/nlm/*
+gdb-*/include/opcode/*
+gdb-*/intl/*
+gdb-*/libiberty/*
+gdb-*/mmalloc/*
+gdb-*/opcodes/*
+gdb-*/readline/*
+gdb-*/regformats/reg-cris*
+gdb-*/sim/*
+gdb-*/texinfo/*
+gdb-*/utils/*
*ChangeLog*
*Makefile*
+*TODO*
*aix*
*config.*
*configure*
@@ -63,4 +72,6 @@ gdb-6.1.1/utils/*
*interix*
*irix*
*linux*
+*mingw*
*osf1*
+*win32*
diff --git a/contrib/libpcap/CHANGES b/contrib/libpcap/CHANGES
index 536e1a2..dc4e006 100644
--- a/contrib/libpcap/CHANGES
+++ b/contrib/libpcap/CHANGES
@@ -1,28 +1,41 @@
-@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.59.2.13 2007/09/12 22:40:04 ken Exp $ (LBL)
-
-Mon. September 10, 2007. ken@xelerance.com. Summary for 0.9.8 libpcap release
- Change build process to put public libpcap headers into pcap subir
- DLT: Add value for IPMI IPMB packets
- DLT: Add value for u10 Networks boards
- Require <net/pfvar.h> for pf definitions - allows reading of pflog formatted
- libpcap files on an OS other than where the file was generated
-
-Wed. July 23, 2007. mcr@xelerance.com. Summary for 0.9.7 libpcap release
-
- FIXED version file to be 0.9.7 instead of 0.9.5.
- added flags/configuration for cloning bpf device.
- added DLT_MTP2_WITH_PHDR support (PPI)
- "fix" the "memory leak" in icode_to_fcode() -- documentation bug
- Various link-layer types, with a pseudo-header, for SITA http://www.sita.aero/
- introduces support for the DAG ERF type TYPE_COLOR_MC_HDLC_POS.
- Basic BPF filtering support for DLT_MTP2_WITH_PHDR is also added.
- check for IPv4 and IPv6, even for DLT_RAW
- add support for DLT_JUNIPER_ISM
- Pick up changes from NetBSD: many from tron, christos, drochner
- Allocate DLT_ for 802.15.4 without any header munging, for Mikko Saarnivala.
- Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header
-
-Wed. April 25, 2007. ken@xelerance.com. Summary for 0.9.6 libpcap release
+@(#) $Header: /tcpdump/master/libpcap/CHANGES,v 1.67.2.4 2008-10-28 00:27:42 ken Exp $ (LBL)
+
+Mon. October 27, 2008. ken@netfunctional.ca. Summary for 1.0.0 libpcap release
+ Compile with IPv6 support by default
+ Compile with large file support on by default
+ Add pcap-config script, which deals with -I/-L flags for compiling
+ DLT: Add IPMB
+ DLT: Add LAPD
+ DLT: Add AX25 (AX.25 w/KISS header)
+ DLT: Add JUNIPER_ST
+ 802.15.4 support
+ Variable length 802.11 header support
+ X2E data type support
+ SITA ACN Interface support - see README.sita
+ Support for zerocopy BPF on platforms that support it
+ Better support for dealing with VLAN tagging/stripping on Linux
+ Fix dynamic library support on OSX
+ Return PCAP_ERROR_IFACE_NOT_UP if the interface isn't 'UP', so applications
+ can print better diagnostic information
+ Return PCAP_ERROR_PERM_DENIED if we don't have permission to open a device, so
+ applications can tell the user they need to go play with permissions
+ On Linux, ignore ENETDOWN so we can continue to capture packets if the
+ interface goes down and comes back up again.
+ On Linux, support new tpacket frame headers (2.6.27+)
+ On Mac OS X, add scripts for changing permissions on /dev/pbf* and launchd plist
+ On Solaris, support 'passive mode' on systems that support it
+ Fixes to autoconf and general build environment
+ Man page reorganization + cleanup
+ Autogenerate VERSION numbers better
+
+Mon. September 10, 2007. ken@xelerance.com. Summary for 0.9.8 libpcap release
+ Change build process to put public libpcap headers into pcap subir
+ DLT: Add value for IPMI IPMB packets
+ DLT: Add value for u10 Networks boards
+ Require <net/pfvar.h> for pf definitions - allows reading of pflog formatted
+ libpcap files on an OS other than where the file was generated
+
+Wed. April 25, 2007. ken@xelerance.com. Summary for 0.9.6 libpcap release
Put the public libpcap headers into a pcap subdirectory in both the
source directory and the target include directory, and have include
diff --git a/contrib/libpcap/CREDITS b/contrib/libpcap/CREDITS
index 2e54aab..2cd7207 100644
--- a/contrib/libpcap/CREDITS
+++ b/contrib/libpcap/CREDITS
@@ -1,108 +1,126 @@
This file lists people who have contributed to libpcap:
The current maintainers:
- Bill Fenner <fenner@research.att.com>
- Fulvio Risso <risso@polito.it>
- Guy Harris <guy@alum.mit.edu>
- Hannes Gredler <hannes@juniper.net>
- Jun-ichiro itojun Hagino <itojun@iijlab.net>
- Michael Richardson <mcr@sandelman.ottawa.on.ca>
+ Bill Fenner <fenner at research dot att dot com>
+ Fulvio Risso <risso at polito dot it>
+ Guy Harris <guy at alum dot mit dot edu>
+ Hannes Gredler <hannes at juniper dot net>
+ Michael Richardson <mcr at sandelman dot ottawa dot on dot ca>
Additional people who have contributed patches:
- Alan Bawden <Alan@LCS.MIT.EDU>
- Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
- Albert Chin <china@thewrittenword.com>
- Andrew Brown <atatat@atatdot.net>
- Antti Kantee <pooka@netbsd.org>
- Arkadiusz Miskiewicz <misiek@pld.org.pl>
- Armando L. Caro Jr. <acaro@mail.eecis.udel.edu>
- Assar Westerlund <assar@sics.se>
- Brian Ginsbach <ginsbach@cray.com>
- Charles M. Hannum <mycroft@netbsd.org>
- Chris G. Demetriou <cgd@netbsd.org>
- Chris Lightfoot <cwrl@users.sourceforge.net>
- Chris Pepper <pepper@mail.reppep.com>
- Daniele Orlandi <daniele@orlandi.com>
- Darren Reed <darrenr@reed.wattle.id.au>
- David Kaelbling <drk@sgi.com>
- David Young <dyoung@ojctech.com>
- Dean Gaudet <dean@arctic.org>
- Don Ebright <Don.Ebright@compuware.com>
- Dug Song <dugsong@monkey.org>
- Eric Anderson <anderse@hpl.hp.com>
- Erik de Castro Lopo <erik.de.castro.lopo@sensorynetworks.com>
- Florent Drouin <Florent.Drouin@alcatel-lucent.fr>
- Franz Schaefer <schaefer@mond.at>
- Gianluca Varenni <varenni@netgroup-serv.polito.it>
- Gilbert Hoyek <gil_hoyek@hotmail.com>
- Gisle Vanem <giva@bgnett.no>
- Graeme Hewson <ghewson@cix.compulink.co.uk>
- Greg Stark <gsstark@mit.edu>
- Greg Troxel <gdt@ir.bbn.com>
- Guillaume Pelat <endymion_@users.sourceforge.net>
- Hyung Sik Yoon <hsyn@kr.ibm.com>
- Igor Khristophorov <igor@atdot.org>
- Jan-Philip Velders <jpv@veldersjes.net>
- Jason R. Thorpe <thorpej@netbsd.org>
- Javier Achirica <achirica@ttd.net>
- Jean Tourrilhes <jt@hpl.hp.com>
- Jefferson Ogata <jogata@nodc.noaa.gov>
- Jesper Peterson <jesper@endace.com>
- John Bankier <jbankier@rainfinity.com>
- Jon Lindgren <jonl@yubyub.net>
- Juergen Schoenwaelder <schoenw@ibr.cs.tu-bs.de>
- Jung-uk Kim <jkim@FreeBSD.org>
- Kazushi Sugyo <sugyo@pb.jp.nec.com>
- Klaus Klein <kleink@netbsd.org>
- Koryn Grant <koryn@endace.com>
- Krzysztof Halasa <khc@pm.waw.pl>
- Lorenzo Cavallaro <sullivan@sikurezza.org>
- Loris Degioanni <loris@netgroup-serv.polito.it>
- Love Hörnquist-Åstrand <lha@stacken.kth.se>
- Maciej W. Rozycki <macro@ds2.pg.gda.pl>
- Marcus Felipe Pereira <marcus@task.com.br>
- Mark C. Brown <mbrown@hp.com>
- Mark Pizzolato <List-tcpdump-workers@subscriptions.pizzolato.net>
- Martin Husemann <martin@netbsd.org>
- Matthew Luckie <mjl@luckie.org.nz>
- Max Laier <max@love2party.net>
- Mike Kershaw <dragorn@kismetwireless.net>
- Mike Wiacek <mike@iroot.net>
- Monroe Williams <monroe@pobox.com>
- Nicolas Dade <ndade@nsd.dyndns.org>
- Octavian Cerna <tavy@ylabs.com>
- Olaf Kirch <okir@caldera.de>
- Ollie Wild <aaw@users.sourceforge.net>
- Onno van der Linden <onno@simplex.nl>
- Patrick Marie <mycroft@virgaria.org>
- Paul Mundt <lethal@linux-sh.org>
- Pavel Kankovsky <kan@dcit.cz>
- Pawel Pokrywka <publicpp@gmail.com>
- Peter Fales <peter@fales-lorenz.net>
- Peter Jeremy <peter.jeremy@alcatel.com.au>
- Phil Wood <cpw@lanl.gov>
- Rafal Maszkowski <rzm@icm.edu.pl>
- <rcb-isis@users.sourceforge.net>
- Rick Jones <raj@cup.hp.com>
- Scott Barron <sb125499@ohiou.edu>
- Scott Gifford <sgifford@tir.com>
- Sebastian Krahmer <krahmer@cs.uni-potsdam.de>
- Shaun Clowes <delius@progsoc.uts.edu.au>
- Solomon Peachy <pizza@shaftnet.org>
- Stefan Hudson <hudson@mbay.net>
- Stephen Donnelly <stephen@endace.com>
- Takashi Yamamoto <yamt@mwd.biglobe.ne.jp>
- Tanaka Shin-ya <zstanaka@archer.livedoor.com>
- Tony Li <tli@procket.com>
- Torsten Landschoff <torsten@debian.org>
- Uns Lider <unslider@miranda.org>
- Uwe Girlich <Uwe.Girlich@philosys.de>
- Xianjie Zhang <xzhang@cup.hp.com>
+ Alan Bawden <Alan at LCS dot MIT dot EDU>
+ Alexander 'Leo' Bergolth <Leo dot Bergolth at wu-wien dot ac dot at>
+ Alexey Kuznetsov <kuznet at ms2 dot inr dot ac dot ru>
+ Albert Chin <china at thewrittenword dot com>
+ Andrew Brown <atatat at atatdot dot net>
+ Antti Kantee <pooka at netbsd dot org>
+ Arien Vijn <arienvijn at sourceforge dot net>
+ Arkadiusz Miskiewicz <misiek at pld dot org dot pl>
+ Armando L. Caro Jr. <acaro at mail dot eecis dot udel dot edu>
+ Assar Westerlund <assar at sics dot se>
+ Brian Ginsbach <ginsbach at cray dot com>
+ Charles M. Hannum <mycroft at netbsd dot org>
+ Chris G. Demetriou <cgd at netbsd dot org>
+ Chris Lightfoot <cwrl at users dot sourceforge dot net>
+ Chris Pepper <pepper at mail dot reppep dot com>
+ Christian Peron <csjp at freebsd dot org>
+ Daniele Orlandi <daniele at orlandi dot com>
+ Darren Reed <darrenr at reed dot wattle dot id dot au>
+ David Kaelbling <drk at sgi dot com>
+ David Young <dyoung at ojctech dot com>
+ Dean Gaudet <dean at arctic dot org>
+ Don Ebright <Don dot Ebright at compuware dot com>
+ Dug Song <dugsong at monkey dot org>
+ Eric Anderson <anderse at hpl dot hp dot com>
+ Erik de Castro Lopo <erik dot de dot castro dot lopo at sensorynetworks dot com>
+ Florent Drouin <Florent dot Drouin at alcatel-lucent dot fr>
+ Franz Schaefer <schaefer at mond dot at>
+ Fulko Hew <fulko dot hew at gmail dot com>
+ Gianluca Varenni <varenni at netgroup-serv dot polito dot it>
+ Gilbert Hoyek <gil_hoyek at hotmail dot com>
+ Gisle Vanem <gvanem at broadpark dot no>
+ Gisle Vanem <giva at bgnett dot no>
+ Graeme Hewson <ghewson at cix dot compulink dot co dot uk>
+ Greg Stark <gsstark at mit dot edu>
+ Greg Troxel <gdt at ir dot bbn dot com>
+ Gregor Maier <gregor at net dot in dot tum dot de>
+ Guillaume Pelat <endymion_ at users dot sourceforge dot net>
+ Hagen Paul Pfeifer <hagen at jauu dot net>
+ Hyung Sik Yoon <hsyn at kr dot ibm dot com>
+ Igor Khristophorov <igor at atdot dot org>
+ Jan-Philip Velders <jpv at veldersjes dot net>
+ Jason R. Thorpe <thorpej at netbsd dot org>
+ Javier Achirica <achirica at ttd dot net>
+ Jean Tourrilhes <jt at hpl dot hp dot com>
+ Jefferson Ogata <jogata at nodc dot noaa dot gov>
+ Jesper Peterson <jesper at endace dot com>
+ Joerg Mayer <jmayer at loplof dot de>
+ John Bankier <jbankier at rainfinity dot com>
+ Jon Lindgren <jonl at yubyub dot net>
+ Juergen Schoenwaelder <schoenw at ibr dot cs dot tu-bs dot de>
+ Jung-uk Kim <jkim at FreeBSD dot org>
+ Kazushi Sugyo <sugyo at pb dot jp dot nec dot com>
+ Klaus Klein <kleink at netbsd dot org>
+ Koryn Grant <koryn at endace dot com>
+ Kris Katterjohn <katterjohn at gmail dot com>
+ Krzysztof Halasa <khc at pm dot waw dot pl>
+ Lorenzo Cavallaro <sullivan at sikurezza dot org>
+ Loris Degioanni <loris at netgroup-serv dot polito dot it>
+ Love Hörnquist-Åstrand <lha at stacken dot kth dot se>
+ Luis Martin Garcia <luis dot mgarc at gmail dot com>
+ Maciej W. Rozycki <macro at ds2 dot pg dot gda dot pl>
+ Marcus Felipe Pereira <marcus at task dot com dot br>
+ Mark C. Brown <mbrown at hp dot com>
+ Mark Pizzolato <List-tcpdump-workers at subscriptions dot pizzolato dot net>
+ Martin Husemann <martin at netbsd dot org>
+ Matthew Luckie <mjl at luckie dot org dot nz>
+ Max Laier <max at love2party dot net>
+ Mike Frysinger <vapier at gmail dot com>
+ Mike Kershaw <dragorn at kismetwireless dot net>
+ Mike Wiacek <mike at iroot dot net>
+ Monroe Williams <monroe at pobox dot com>
+ Nicolas Dade <ndade at nsd dot dyndns dot org>
+ Octavian Cerna <tavy at ylabs dot com>
+ Olaf Kirch <okir at caldera dot de>
+ Ollie Wild <aaw at users dot sourceforge dot net>
+ Onno van der Linden <onno at simplex dot nl>
+ Paolo Abeni <paolo dot abeni at email dot it>
+ Patrick Marie <mycroft at virgaria dot org>
+ Patrick McHardy <kaber at trash not net>
+ Paul Mundt <lethal at linux-sh dot org>
+ Pavel Kankovsky <kan at dcit dot cz>
+ Pawel Pokrywka <publicpp at gmail dot com>
+ Peter Fales <peter at fales-lorenz dot net>
+ Peter Jeremy <peter dot jeremy at alcatel dot com dot au>
+ Phil Wood <cpw at lanl dot gov>
+ Rafal Maszkowski <rzm at icm dot edu dot pl>
+ <rcb-isis at users dot sourceforge dot net>
+ Richard Stearn <richard at rns-stearn dot demon dot co dot uk>
+ Rick Jones <raj at cup dot hp dot com>
+ Sagun Shakya <sagun dot shakya at sun dot com>
+ Scott Barron <sb125499 at ohiou dot edu>
+ Scott Gifford <sgifford at tir dot com>
+ Sebastian Krahmer <krahmer at cs dot uni-potsdam dot de>
+ Sepherosa Ziehau <sepherosa at gmail dot com>
+ Shaun Clowes <delius at progsoc dot uts dot edu dot au>
+ Solomon Peachy <pizza at shaftnet dot org>
+ Stefan Hudson <hudson at mbay dot net>
+ Stephen Donnelly <stephen at endace dot com>
+ Takashi Yamamoto <yamt at mwd dot biglobe dot ne dot jp>
+ Tanaka Shin-ya <zstanaka at archer dot livedoor dot com>
+ Tony Li <tli at procket dot com>
+ Torsten Landschoff <torsten at debian dot org>
+ Uns Lider <unslider at miranda dot org>
+ Uwe Girlich <Uwe dot Girlich at philosys dot de>
+ Xianjie Zhang <xzhang at cup dot hp dot com>
Yen Yen Lim
- Yoann Vandoorselaere <yoann@prelude-ids.org>
+ Yoann Vandoorselaere <yoann at prelude-ids dot org>
The original LBL crew:
Steve McCanne
Craig Leres
Van Jacobson
+
+Past maintainers:
+ Jun-ichiro itojun Hagino <itojun at iijlab dot net>
diff --git a/contrib/libpcap/FILES b/contrib/libpcap/FILES
deleted file mode 100644
index 68c204a..0000000
--- a/contrib/libpcap/FILES
+++ /dev/null
@@ -1,124 +0,0 @@
-CHANGES
-ChmodBPF/ChmodBPF
-ChmodBPF/StartupParameters.plist
-CREDITS
-FILES
-INSTALL.txt
-LICENSE
-Makefile.in
-README
-README.aix
-README.dag
-README.hpux
-README.linux
-README.macosx
-README.septel
-README.tru64
-README.Win32
-SUNOS4/nit_if.o.sparc
-SUNOS4/nit_if.o.sun3
-SUNOS4/nit_if.o.sun4c.4.0.3c
-TODO
-VERSION
-acconfig.h
-aclocal.m4
-arcnet.h
-atmuni31.h
-bpf/net/bpf_filter.c
-bpf_dump.c
-bpf_image.c
-config.guess
-config.h.in
-config.sub
-configure
-configure.in
-etherent.c
-ethertype.h
-fad-getad.c
-fad-gifc.c
-fad-glifc.c
-fad-null.c
-fad-win32.c
-gencode.c
-gencode.h
-grammar.y
-inet.c
-install-sh
-lbl/os-aix4.h
-lbl/os-hpux11.h
-lbl/os-osf4.h
-lbl/os-osf5.h
-lbl/os-solaris2.h
-lbl/os-sunos4.h
-lbl/os-ultrix4.h
-llc.h
-missing/snprintf.c
-mkdep
-msdos/bin2c.c
-msdos/common.dj
-msdos/makefile
-msdos/makefile.dj
-msdos/makefile.wc
-msdos/ndis2.c
-msdos/ndis2.h
-msdos/ndis_0.asm
-msdos/pkt_rx0.asm
-msdos/pkt_rx1.s
-msdos/pktdrvr.c
-msdos/pktdrvr.h
-msdos/readme.dos
-nametoaddr.c
-nlpid.h
-optimize.c
-packaging/pcap.spec
-packaging/pcap.spec.in
-pcap-bpf.c
-pcap-bpf.h
-pcap-dag.c
-pcap-dag.h
-pcap-dlpi.c
-pcap-dos.c
-pcap-dos.h
-pcap-enet.c
-pcap-int.h
-pcap-linux.c
-pcap-namedb.h
-pcap-nit.c
-pcap-nit.h
-pcap-null.c
-pcap-pf.c
-pcap-pf.h
-pcap-septel.c
-pcap-septel.h
-pcap-stdinc.h
-pcap-snit.c
-pcap-snoop.c
-pcap-win32.c
-pcap.3
-pcap.c
-pcap.h
-ppp.h
-savefile.c
-scanner.l
-sll.h
-sunatmpos.h
-Win32/Include/Gnuc.h
-Win32/Include/addrinfo.h
-Win32/Include/bittypes.h
-Win32/Include/cdecl_ext.h
-Win32/Include/inetprivate.h
-Win32/Include/ip6_misc.h
-Win32/Include/sockstorage.h
-Win32/Include/arpa/nameser.h
-Win32/Include/net/if.h
-Win32/Include/net/netdb.h
-Win32/Include/net/paths.h
-Win32/Src/ffs.c
-Win32/Src/getaddrinfo.c
-Win32/Src/getnetbynm.c
-Win32/Src/getnetent.c
-Win32/Src/getopt.c
-Win32/Src/getservent.c
-Win32/Src/inet_aton.c
-Win32/Src/inet_net.c
-Win32/Src/inet_pton.c
diff --git a/contrib/libpcap/FREEBSD-Xlist b/contrib/libpcap/FREEBSD-Xlist
new file mode 100644
index 0000000..948318c
--- /dev/null
+++ b/contrib/libpcap/FREEBSD-Xlist
@@ -0,0 +1,7 @@
+$FreeBSD$
+*/README.*
+*/msdos
+*/SUNOS4
+*/Win32
+*/ChmodBPF
+*/*.plist
diff --git a/contrib/libpcap/INSTALL.txt b/contrib/libpcap/INSTALL.txt
index 76445a7..c7cfd22 100644
--- a/contrib/libpcap/INSTALL.txt
+++ b/contrib/libpcap/INSTALL.txt
@@ -1,4 +1,4 @@
-@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.12.2.2 2007/09/12 19:17:24 guy Exp $ (LBL)
+@(#) $Header: /tcpdump/master/libpcap/INSTALL.txt,v 1.21.2.8 2008-06-12 20:25:38 guy Exp $ (LBL)
To build libpcap, run "./configure" (a shell script). The configure
script will determine your system attributes and generate an
@@ -211,8 +211,7 @@ Read the README.aix file for information on installing libpcap and
configuring your system to be able to support libpcap.
If you use NeXTSTEP, you will not be able to build libpcap from this
-release. We hope to support this operating system in some future
-release of libpcap.
+release.
If you use SINIX, you should be able to build libpcap from this
release. It is known to compile and run on SINIX-Y/N 5.42 with the C-DS
@@ -229,22 +228,22 @@ Another workaround is to use flex and bison.
If you use SCO, you might have trouble building libpcap from this
release. We do not have a machine running SCO and have not had reports
-of anyone successfully building on it. Since SCO apparently supports
-DLPI, it's possible the current version works. Meanwhile, SCO provides
-a tcpdump binary as part of their "Network/Security Tools" package:
-
- http://www.sco.com/technology/internet/goodies/#SECURITY
-
-There is also a README that explains how to enable packet capture.
-
-If you use UnixWare, you will not be able to build libpcap from this
-release. We hope to support this operating system in some future
-release of libpcap. Meanwhile, there appears to be an UnixWare port of
-libpcap 0.0 (and tcpdump 3.0) in:
-
- ftp://ftp1.freebird.org/pub/mirror/freebird/internet/systools/
-
-UnixWare appears to use a hacked version of DLPI.
+of anyone successfully building on it; the current release of libpcap
+does not compile on SCO OpenServer 5. Although SCO apparently supports
+DLPI to some extent, the DLPI in OpenServer 5 is very non-standard, and
+it appears that completely new code would need to be written to capture
+network traffic. SCO do not appear to provide tcpdump binaries for
+OpenServer 5 or OpenServer 6 as part of SCO Skunkware:
+
+ http://www.sco.com/skunkware/
+
+If you use UnixWare, you might be able to build libpcap from this
+release, or you might not. We do not have a machine running UnixWare,
+so we have not tested it; however, SCO provide packages for libpcap
+0.6.2 and tcpdump 3.7.1 in the UnixWare 7/Open UNIX 8 part of SCO
+Skunkware, and the source package for libpcap 0.6.2 is not changed from
+the libpcap 0.6.2 source release, so this release of libpcap might also
+build without changes on UnixWare 7.
If linking tcpdump fails with "Undefined: _alloca" when using bison on
a Sun4, your version of bison is broken. In any case version 1.16 or
@@ -298,7 +297,6 @@ CHANGES - description of differences between releases
ChmodBPF/* - Mac OS X startup item to set ownership and permissions
on /dev/bpf*
CREDITS - people that have helped libpcap along
-FILES - list of files exported as part of the distribution
INSTALL.txt - this file
LICENSE - the license under which tcpdump is distributed
Makefile.in - compilation rules (input to the configure script)
@@ -309,6 +307,7 @@ README.hpux - notes on using libpcap on HP-UX
README.linux - notes on using libpcap on Linux
README.macosx - notes on using libpcap on Mac OS X
README.septel - notes on using libpcap to capture on Intel/Septel devices
+README.sita - notes on using libpcap to capture on SITA devices
README.tru64 - notes on using libpcap on Digital/Tru64 UNIX
README.Win32 - notes on using libpcap on Win32 systems (with WinPcap)
SUNOS4 - pre-SunOS 4.1 replacement kernel nit modules
@@ -326,16 +325,22 @@ config.h.in - autoconf input
config.sub - autoconf support
configure - configure script (run this first)
configure.in - configure script source
+dlpisubs.c - DLPI-related functions for pcap-dlpi.c and pcap-libdlpi.c
+dlpisubs.h - DLPI-related function declarations
etherent.c - /etc/ethers support routines
ethertype.h - Ethernet protocol types and names definitions
fad-getad.c - pcap_findalldevs() for systems with getifaddrs()
fad-gifc.c - pcap_findalldevs() for systems with only SIOCGIFLIST
fad-glifc.c - pcap_findalldevs() for systems with SIOCGLIFCONF
fad-null.c - pcap_findalldevs() for systems without capture support
+fad-sita.c - pcap_findalldevs() for systems with SITA support
fad-win32.c - pcap_findalldevs() for WinPcap
+filtertest.c - test program for BPF compiler
+findalldevstest.c - test program for pcap_findalldevs()
gencode.c - BPF code generation routines
gencode.h - BPF code generation definitions
grammar.y - filter string grammar
+ieee80211.h - 802.11 definitions
inet.c - network routines
install-sh - BSD style install script
lbl/os-*.h - OS-dependent defines and prototypes
@@ -348,8 +353,16 @@ nlpid.h - OSI network layer protocol identifier definitions
net - symlink to bpf/net
optimize.c - BPF optimization routines
packaging - packaging information for building libpcap RPMs
+pcap/bluetooth.h - public definition of DLT_BLUETOOTH_HCI_H4_WITH_PHDR header
+pcap/bpf.h - BPF definitions
+pcap/namedb.h - public libpcap name database definitions
+pcap/pcap.h - public libpcap definitions
+pcap/sll.h - public definition of DLT_LINUX_SLL header
+pcap/usb.h - public definition of DLT_USB header
pcap-bpf.c - BSD Packet Filter support
-pcap-bpf.h - BPF definitions
+pcap-bpf.h - header for backwards compatibility
+pcap-bt-linux.c - Bluetooth capture support for Linux
+pcap-bt-linux.h - Bluetooth capture support for Linux
pcap-dag.c - Endace DAG device capture support
pcap-dag.h - Endace DAG device capture support
pcap-dlpi.c - Data Link Provider Interface support
@@ -357,26 +370,34 @@ pcap-dos.c - MS-DOS capture support
pcap-dos.h - headers for MS-DOS capture support
pcap-enet.c - enet support
pcap-int.h - internal libpcap definitions
+pcap-libdlpi.c - Data Link Provider Interface support for systems with libdlpi
pcap-linux.c - Linux packet socket support
-pcap-namedb.h - public libpcap name database definitions
+pcap-namedb.h - header for backwards compatibility
pcap-nit.c - SunOS Network Interface Tap support
pcap-nit.h - SunOS Network Interface Tap definitions
pcap-null.c - dummy monitor support (allows offline use of libpcap)
pcap-pf.c - Ultrix and Digital/Tru64 UNIX Packet Filter support
pcap-pf.h - Ultrix and Digital/Tru64 UNIX Packet Filter definitions
-pcap-septel.c - INTEL/Septel device capture support
-pcap-septel.h - INTEL/Septel device capture support
+pcap-septel.c - Intel/Septel device capture support
+pcap-septel.h - Intel/Septel device capture support
+pcap-sita.c - SITA device capture support
+pcap-sita.h - SITA device capture support
+pcap-sita.html - SITA device capture documentation
pcap-stdinc.h - includes and #defines for compiling on Win32 systems
pcap-snit.c - SunOS 4.x STREAMS-based Network Interface Tap support
pcap-snoop.c - IRIX Snoop network monitoring support
+pcap-usb-linux.c - USB capture support for Linux
+pcap-usb-linux.h - USB capture support for Linux
pcap-win32.c - WinPcap capture support
-pcap.3 - manual entry
+pcap.3pcap - manual entry for the library
pcap.c - pcap utility routines
-pcap.h - public libpcap definitions
+pcap.h - header for backwards compatibility
+pcap_*.3pcap - manual entries for library functions
+pcap-filter.4 - manual entry for filter syntax
+pcap-linktype.4 - manual entry for link-layer header types
ppp.h - Point to Point Protocol definitions
-rawss7.h - information on DLT_ types for SS7
+runlex.sh - wrapper for Lex/Flex
savefile.c - offline support
scanner.l - filter string scanner
-sll.h - definitions for Linux cooked mode fake link-layer header
sunatmpos.h - definitions for SunATM capturing
Win32 - headers and routines for building on Win32 systems
diff --git a/contrib/libpcap/Makefile.in b/contrib/libpcap/Makefile.in
index 98396ec..5c4d679 100644
--- a/contrib/libpcap/Makefile.in
+++ b/contrib/libpcap/Makefile.in
@@ -17,7 +17,7 @@
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
-# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.99.2.2 2007/07/24 02:35:15 mcr Exp $ (LBL)
+# @(#) $Header: /tcpdump/master/libpcap/Makefile.in,v 1.108.2.28 2008-10-23 22:13:21 guy Exp $ (LBL)
#
# Various configurable paths (remember to edit Makefile.in, not Makefile)
@@ -26,11 +26,14 @@
# Top level hierarchy
prefix = @prefix@
exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+# Pathname of directory to install the configure program
+bindir = @bindir@
# Pathname of directory to install the include files
includedir = @includedir@
# Pathname of directory to install the library
libdir = @libdir@
-# Pathname of directory to install the man page
+# Pathname of directory to install the man pages
mandir = @mandir@
# VPATH
@@ -47,6 +50,7 @@ INCLS = -I. @V_INCLS@
DEFS = @DEFS@ @V_DEFS@
LIBS = @V_LIBS@
DAGLIBS = @DAGLIBS@
+DEPLIBS = @DEPLIBS@
DYEXT = @DYEXT@
PROG=libpcap
@@ -73,7 +77,7 @@ YACC = @V_YACC@
@rm -f $@
$(CC) $(CFLAGS) -c $(srcdir)/$*.c
-PSRC = pcap-@V_PCAP@.c
+PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@
FSRC = fad-@V_FINDALLDEVS@.c
SSRC = @SSRC@
CSRC = pcap.c inet.c gencode.c optimize.c nametoaddr.c \
@@ -86,10 +90,31 @@ SRC = $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(GENSRC)
# We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
# hack the extra indirection
OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS)
-HDR = pcap.h pcap-int.h pcap-namedb.h pcap-nit.h pcap-pf.h \
- ethertype.h gencode.h gnuc.h
+HDR = \
+ acconfig.h \
+ arcnet.h \
+ atmuni31.h \
+ ethertype.h \
+ gencode.h \
+ ieee80211.h \
+ llc.h \
+ nlpid.h \
+ pcap/bluetooth.h \
+ pcap/bpf.h \
+ pcap/namedb.h \
+ pcap/pcap.h \
+ pcap/sll.h \
+ pcap/usb.h \
+ pcap/vlan.h \
+ pcap.h \
+ pcap-int.h \
+ pcap-namedb.h \
+ pcap-stdinc.h \
+ ppp.h \
+ sunatmpos.h
+
GENHDR = \
- tokdefs.h version.h
+ scanner.h tokdefs.h version.h
TAGHDR = \
pcap-bpf.h
@@ -99,11 +124,198 @@ TAGFILES = \
CLEANFILES = $(OBJ) libpcap.a $(GENSRC) $(GENHDR) lex.yy.c
-all: libpcap.a
+MAN1 = pcap-config.1
+
+MAN3PCAP_EXPAND = \
+ pcap.3pcap.in \
+ pcap_compile.3pcap.in \
+ pcap_datalink.3pcap.in \
+ pcap_dump_open.3pcap.in \
+ pcap_list_datalinks.3pcap.in \
+ pcap_open_dead.3pcap.in \
+ pcap_open_offline.3pcap.in
+
+MAN3PCAP_NOEXPAND = \
+ pcap_activate.3pcap \
+ pcap_breakloop.3pcap \
+ pcap_can_set_rfmon.3pcap \
+ pcap_close.3pcap \
+ pcap_create.3pcap \
+ pcap_datalink_name_to_val.3pcap \
+ pcap_datalink_val_to_name.3pcap \
+ pcap_dump.3pcap \
+ pcap_dump_close.3pcap \
+ pcap_dump_file.3pcap \
+ pcap_dump_flush.3pcap \
+ pcap_dump_ftell.3pcap \
+ pcap_file.3pcap \
+ pcap_fileno.3pcap \
+ pcap_findalldevs.3pcap \
+ pcap_freealldevs.3pcap \
+ pcap_freecode.3pcap \
+ pcap_free_datalinks.3pcap \
+ pcap_get_selectable_fd.3pcap \
+ pcap_geterr.3pcap \
+ pcap_inject.3pcap \
+ pcap_is_swapped.3pcap \
+ pcap_lib_version.3pcap \
+ pcap_lookupdev.3pcap \
+ pcap_lookupnet.3pcap \
+ pcap_loop.3pcap \
+ pcap_major_version.3pcap \
+ pcap_next_ex.3pcap \
+ pcap_offline_filter.3pcap \
+ pcap_open_live.3pcap \
+ pcap_set_buffer_size.3pcap \
+ pcap_set_datalink.3pcap \
+ pcap_set_promisc.3pcap \
+ pcap_set_rfmon.3pcap \
+ pcap_set_snaplen.3pcap \
+ pcap_set_timeout.3pcap \
+ pcap_setdirection.3pcap \
+ pcap_setfilter.3pcap \
+ pcap_setnonblock.3pcap \
+ pcap_snapshot.3pcap \
+ pcap_stats.3pcap \
+ pcap_statustostr.3pcap \
+ pcap_strerror.3pcap
+
+MAN3PCAP = $(MAN3PCAP_NOEXPAND) $(MAN3PCAP_EXPAND:.in=)
+
+MANFILE = \
+ pcap-savefile.manfile.in
+
+MANMISC = \
+ pcap-filter.manmisc.in \
+ pcap-linktype.manmisc.in
+
+EXTRA_DIST = \
+ CHANGES \
+ ChmodBPF/ChmodBPF \
+ ChmodBPF/StartupParameters.plist \
+ CREDITS \
+ INSTALL.txt \
+ LICENSE \
+ Makefile.in \
+ README \
+ README.aix \
+ README.dag \
+ README.hpux \
+ README.linux \
+ README.macosx \
+ README.septel \
+ README.sita \
+ README.tru64 \
+ README.Win32 \
+ SUNOS4/nit_if.o.sparc \
+ SUNOS4/nit_if.o.sun3 \
+ SUNOS4/nit_if.o.sun4c.4.0.3c \
+ TODO \
+ VERSION \
+ aclocal.m4 \
+ bpf/net/bpf_filter.c \
+ chmod_bpf \
+ config.guess \
+ config.h.in \
+ config.sub \
+ configure \
+ configure.in \
+ dlpisubs.c \
+ dlpisubs.h \
+ fad-getad.c \
+ fad-gifc.c \
+ fad-glifc.c \
+ fad-null.c \
+ fad-sita.c \
+ fad-win32.c \
+ filtertest.c \
+ findalldevstest.c \
+ grammar.y \
+ install-sh \
+ lbl/os-aix4.h \
+ lbl/os-hpux11.h \
+ lbl/os-osf4.h \
+ lbl/os-osf5.h \
+ lbl/os-solaris2.h \
+ lbl/os-sunos4.h \
+ lbl/os-ultrix4.h \
+ missing/snprintf.c \
+ mkdep \
+ msdos/bin2c.c \
+ msdos/common.dj \
+ msdos/makefile \
+ msdos/makefile.dj \
+ msdos/makefile.wc \
+ msdos/ndis2.c \
+ msdos/ndis2.h \
+ msdos/ndis_0.asm \
+ msdos/pkt_rx0.asm \
+ msdos/pkt_rx1.s \
+ msdos/pktdrvr.c \
+ msdos/pktdrvr.h \
+ msdos/readme.dos \
+ net/bpf_filter.c \
+ org.tcpdump.chmod_bpf.plist \
+ packaging/pcap.spec.in \
+ pcap-bpf.c \
+ pcap-bpf.h \
+ pcap-bt-linux.c \
+ pcap-bt-linux.h \
+ pcap-config.in \
+ pcap-dag.c \
+ pcap-dag.h \
+ pcap-dlpi.c \
+ pcap-dos.c \
+ pcap-dos.h \
+ pcap-enet.c \
+ pcap-int.h \
+ pcap-libdlpi.c \
+ pcap-linux.c \
+ pcap-namedb.h \
+ pcap-nit.c \
+ pcap-null.c \
+ pcap-pf.c \
+ pcap-septel.c \
+ pcap-septel.h \
+ pcap-sita.h \
+ pcap-sita.c \
+ pcap-sita.html \
+ pcap-snit.c \
+ pcap-snoop.c \
+ pcap-usb-linux.c \
+ pcap-usb-linux.h \
+ pcap-win32.c \
+ runlex.sh \
+ scanner.l \
+ Win32/Include/Gnuc.h \
+ Win32/Include/addrinfo.h \
+ Win32/Include/bittypes.h \
+ Win32/Include/cdecl_ext.h \
+ Win32/Include/inetprivate.h \
+ Win32/Include/ip6_misc.h \
+ Win32/Include/sockstorage.h \
+ Win32/Include/arpa/nameser.h \
+ Win32/Include/net/if.h \
+ Win32/Include/net/netdb.h \
+ Win32/Include/net/paths.h \
+ Win32/Prj/libpcap.dsp \
+ Win32/Prj/libpcap.dsw \
+ Win32/Src/ffs.c \
+ Win32/Src/gai_strerror.c \
+ Win32/Src/getaddrinfo.c \
+ Win32/Src/getnetbynm.c \
+ Win32/Src/getnetent.c \
+ Win32/Src/getopt.c \
+ Win32/Src/getservent.c \
+ Win32/Src/inet_aton.c \
+ Win32/Src/inet_net.c \
+ Win32/Src/inet_pton.c
+
+all: libpcap.a pcap-config
libpcap.a: $(OBJ)
@rm -f $@
- ar rc $@ $(OBJ) $(LIBS)
+ $(AR) rc $@ $(OBJ) $(LIBS)
$(RANLIB) $@
shared: libpcap.$(DYEXT)
@@ -114,19 +326,27 @@ shared: libpcap.$(DYEXT)
#
libpcap.so: $(OBJ)
@rm -f $@
- $(CC) -shared -o $@.`cat VERSION` $(OBJ) $(DAGLIBS)
+ $(CC) -shared -Wl,-soname,$@.1 -o $@.`cat $(srcdir)/VERSION` $(OBJ) $(DAGLIBS)
-# the following rule succeeds, but the result is untested.
+#
+# The following rule succeeds, but the result is untested.
+#
+# XXX - OS X installs the library as "libpcap.A.dylib", with that as the
+# install_name, and sets the current version to 1 as well. VERSION
+# might contain a not-purely-numeric version number, but
+# -current_version requires a purely numeric version, so this won't
+# work with top-of-tree builds.
+#
libpcap.dylib: $(OBJ)
rm -f libpcap*.dylib
- $(CC) -dynamiclib -undefined error -o libpcap.`cat VERSION`.dylib $(OBJ) \
- -install_name $(libdir)/libpcap.0.dylib -compatibility_version `cat VERSION` \
- -current_version `cat VERSION`
-
+ $(CC) -dynamiclib -undefined error -o libpcap.`cat $(srcdir)/VERSION`.dylib $(OBJ) \
+ -install_name $(libdir)/libpcap.A.dylib \
+ -compatibility_version 1 \
+ -current_version `sed 's/[^0-9.].*$$//' $(srcdir)/VERSION`
scanner.c: $(srcdir)/scanner.l
@rm -f $@
- $(LEX) -t $< > $$$$.$@; mv $$$$.$@ $@
+ ./runlex.sh $(LEX) -o$@ $<
scanner.o: scanner.c tokdefs.h
$(CC) $(CFLAGS) -c scanner.c
@@ -172,43 +392,135 @@ bpf_filter.c: $(srcdir)/bpf/net/bpf_filter.c
bpf_filter.o: bpf_filter.c
$(CC) $(CFLAGS) -c bpf_filter.c
-install: libpcap.a
+#
+# Generate the pcap-config script.
+#
+pcap-config: pcap-config.in Makefile
+ @rm -f $@ $@.tmp
+ sed -e 's|@includedir[@]|$(includedir)|g' \
+ -e 's|@libdir[@]|$(libdir)|g' \
+ -e 's|@DEPLIBS[@]|$(DEPLIBS)|g' \
+ pcap-config.in >$@.tmp
+ mv $@.tmp $@
+ chmod a+x $@
+
+#
+# Test programs - not built by default, and not installed.
+#
+filtertest: filtertest.c libpcap.a
+ $(CC) $(CFLAGS) -I. -L. -o filtertest filtertest.c libpcap.a
+
+findalldevstest: findalldevstest.c libpcap.a
+ $(CC) $(CFLAGS) -I. -L. -o findalldevstest findalldevstest.c libpcap.a
+
+install: libpcap.a pcap-config
[ -d $(DESTDIR)$(libdir) ] || \
(mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
$(INSTALL_DATA) libpcap.a $(DESTDIR)$(libdir)/libpcap.a
$(RANLIB) $(DESTDIR)$(libdir)/libpcap.a
[ -d $(DESTDIR)$(includedir) ] || \
(mkdir -p $(DESTDIR)$(includedir); chmod 755 $(DESTDIR)$(includedir))
+ [ -d $(DESTDIR)$(includedir)/pcap ] || \
+ (mkdir -p $(DESTDIR)$(includedir)/pcap; chmod 755 $(DESTDIR)$(includedir)/pcap)
+ [ -d $(DESTDIR)$(mandir)/man1 ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man1; chmod 755 $(DESTDIR)$(mandir)/man1)
+ [ -d $(DESTDIR)$(mandir)/man3 ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man3; chmod 755 $(DESTDIR)$(mandir)/man3)
+ [ -d $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@ ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@)
+ [ -d $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@ ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@)
+ $(INSTALL_DATA) $(srcdir)/pcap/pcap.h \
+ $(DESTDIR)$(includedir)/pcap/pcap.h
+ $(INSTALL_DATA) $(srcdir)/pcap/bpf.h \
+ $(DESTDIR)$(includedir)/pcap/bpf.h
+ $(INSTALL_DATA) $(srcdir)/pcap/namedb.h \
+ $(DESTDIR)$(includedir)/pcap/namedb.h
+ $(INSTALL_DATA) $(srcdir)/pcap/sll.h \
+ $(DESTDIR)$(includedir)/pcap/sll.h
+ $(INSTALL_DATA) $(srcdir)/pcap/usb.h \
+ $(DESTDIR)$(includedir)/pcap/usb.h
$(INSTALL_DATA) $(srcdir)/pcap.h $(DESTDIR)$(includedir)/pcap.h
$(INSTALL_DATA) $(srcdir)/pcap-bpf.h \
$(DESTDIR)$(includedir)/pcap-bpf.h
$(INSTALL_DATA) $(srcdir)/pcap-namedb.h \
$(DESTDIR)$(includedir)/pcap-namedb.h
- [ -d $(DESTDIR)$(mandir)/man3 ] || \
- (mkdir -p $(DESTDIR)$(mandir)/man3; chmod 755 $(DESTDIR)$(mandir)/man3)
- $(INSTALL_DATA) $(srcdir)/pcap.3 \
- $(DESTDIR)$(mandir)/man3/pcap.3
+ $(INSTALL_PROGRAM) pcap-config $(DESTDIR)$(bindir)/pcap-config
+ for i in $(MAN1); do \
+ $(INSTALL_DATA) $(srcdir)/$$i \
+ $(DESTDIR)$(mandir)/man1/$$i; done
+ for i in $(MAN3PCAP); do \
+ $(INSTALL_DATA) $(srcdir)/$$i \
+ $(DESTDIR)$(mandir)/man3/$$i; done
+ ln $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_name.3pcap \
+ $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
+ ln $(DESTDIR)$(mandir)/man3/pcap_dump_open.3pcap \
+ $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
+ ln $(DESTDIR)$(mandir)/man3/pcap_geterr.3pcap \
+ $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
+ ln $(DESTDIR)$(mandir)/man3/pcap_inject.3pcap \
+ $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
+ ln $(DESTDIR)$(mandir)/man3/pcap_loop.3pcap \
+ $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
+ ln $(DESTDIR)$(mandir)/man3/pcap_major_version.3pcap \
+ $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
+ ln $(DESTDIR)$(mandir)/man3/pcap_next_ex.3pcap \
+ $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
+ ln $(DESTDIR)$(mandir)/man3/pcap_open_offline.3pcap \
+ $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
+ ln $(DESTDIR)$(mandir)/man3/pcap_setnonblock.3pcap \
+ $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
+ for i in $(MANFILE); do \
+ $(INSTALL_DATA) $(srcdir)/`echo $$i | sed 's/.manfile.in/.manfile/'` \
+ $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+ for i in $(MANMISC); do \
+ $(INSTALL_DATA) $(srcdir)/`echo $$i | sed 's/.manmisc.in/.manmisc/'` \
+ $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@/`echo $$i | sed 's/.manmisc.in/.@MAN_MISC_INFO@/'`; done
install-shared: install-shared-$(DYEXT)
install-shared-so: libpcap.so
$(INSTALL_PROGRAM) libpcap.so.`cat VERSION` $(DESTDIR)$(libdir)/libpcap.so.`cat VERSION`
install-shared-dylib: libpcap.dylib
$(INSTALL_PROGRAM) libpcap.`cat VERSION`.dylib $(DESTDIR)$(libdir)/libpcap.`cat VERSION`.dylib
- VER=`cat VERSION`; cd $(DESTDIR)$(libdir) && ln -sf libpcap.$$VER.dylib libpcap.0.dylib; ln -sf libpcap.0.dylib libpcap.dylib
+ VER=`cat VERSION`; cd $(DESTDIR)$(libdir) && ln -sf libpcap.$$VER.dylib libpcap.A.dylib; ln -sf libpcap.A.dylib libpcap.dylib
uninstall:
rm -f $(DESTDIR)$(libdir)/libpcap.a
+ rm -f $(DESTDIR)$(includedir)/pcap/pcap.h
+ rm -f $(DESTDIR)$(includedir)/pcap/bpf.h
+ rm -f $(DESTDIR)$(includedir)/pcap/namedb.h
+ rm -f $(DESTDIR)$(includedir)/pcap/sll.h
+ rm -f $(DESTDIR)$(includedir)/pcap/usb.h
+ -rmdir $(DESTDIR)$(includedir)/pcap
rm -f $(DESTDIR)$(includedir)/pcap.h
rm -f $(DESTDIR)$(includedir)/pcap-bpf.h
rm -f $(DESTDIR)$(includedir)/pcap-namedb.h
- rm -f $(DESTDIR)$(mandir)/man3/pcap.3
+ for i in $(MAN1); do \
+ rm -f $(DESTDIR)$(mandir)/man1/$$i; done
+ for i in $(MAN3PCAP); do \
+ rm -f $(DESTDIR)$(mandir)/man3/$$i; done
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
+ for i in $(MANFILE); do \
+ rm -f $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+ for i in $(MANMISC); do \
+ rm -f $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@/`echo $$i | sed 's/.manmisc.in/.@MAN_MISC_INFO@/'`; done
clean:
rm -f $(CLEANFILES) libpcap*.dylib libpcap.so*
distclean: clean
rm -f Makefile config.cache config.log config.status \
- config.h gnuc.h os-proto.h bpf_filter.c stamp-h stamp-h.in
+ config.h gnuc.h os-proto.h bpf_filter.c pcap-config \
+ stamp-h stamp-h.in
+ rm -f $(MAN3PCAP_EXPAND:.in=) $(MANFILE:.in=) $(MANMISC:.in=)
rm -rf autom4te.cache
tags: $(TAGFILES)
@@ -220,8 +532,12 @@ packaging/pcap.spec: packaging/pcap.spec.in VERSION
releasetar:
@cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \
- list="" ; make distclean; cd ..; mkdir -p n; cd n; ln -s ../$$dir $$name; \
- tar -c -z -f $$name.tar.gz $$name/. ;
+ mkdir $$name; \
+ tar cf - $(CSRC) $(HDR) $(MAN1) $(MAN3PCAP_EXPAND) \
+ $(MAN3PCAP_NOEXPAND) $(MANFILE) $(MANMISC) $(EXTRA_DIST) | \
+ (cd $$name; tar xf -); \
+ tar -c -z -f $$name.tar.gz $$name; \
+ rm -rf $$name
depend: $(GENSRC) $(GENHDR) bpf_filter.c
./mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC)
diff --git a/contrib/libpcap/README b/contrib/libpcap/README
index 90571a1..ee1a141 100644
--- a/contrib/libpcap/README
+++ b/contrib/libpcap/README
@@ -1,20 +1,22 @@
-@(#) $Header: /tcpdump/master/libpcap/README,v 1.30 2004/10/12 02:02:28 guy Exp $ (LBL)
+@(#) $Header: /tcpdump/master/libpcap/README,v 1.30.4.3 2008-10-17 10:39:20 ken Exp $ (LBL)
-LIBPCAP 0.9
-Now maintained by "The Tcpdump Group"
-See www.tcpdump.org
+LIBPCAP 1.0.0
-Please send inquiries/comments/reports to tcpdump-workers@tcpdump.org
+www.tcpdump.org
+
+Please send inquiries/comments/reports to:
+ tcpdump-workers@lists.tcpdump.org
Anonymous CVS is available via:
cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master login
(password "anoncvs")
cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout libpcap
-Version 0.9 of LIBPCAP can be retrieved with the CVS tag "libpcap_0_9rel1":
- cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_0_9rel1 libpcap
+Version 1.0.0 of LIBPCAP can be retrieved with the CVS tag "libpcap_1_0":
+ cvs -d :pserver:tcpdump@cvs.tcpdump.org:/tcpdump/master checkout -r libpcap_1_0 libpcap
-Please send patches against the master copy to patches@tcpdump.org.
+Please submit patches against the master copy to the libpcap project on
+sourceforge.net.
formerly from Lawrence Berkeley National Laboratory
Network Research Group <libpcap@ee.lbl.gov>
@@ -30,8 +32,6 @@ require this functionality, we've created this system-independent API
to ease in porting and to alleviate the need for several
system-dependent packet capture modules in each application.
-Note well: this interface is new and is likely to change.
-
For some platforms there are README.{system} files that discuss issues
with the OS's interface for packet capture on those platforms, such as
how to enable support for that interface in the OS, if it's not built in
@@ -77,16 +77,28 @@ Linux, in the 2.2 kernel and later kernels, has a "Socket Filter"
mechanism that accepts BPF filters; see the README.linux file for
information on configuring that option.
+Note to Linux distributions and *BSD systems that include libpcap:
+
+There's now a rule to make a shared library, which should work on Linux
+and *BSD (and OS X).
+
+It sets the soname of the library to "libpcap.so.1"; this is what it
+should be, *NOT* libpcap.so.1.0 or libpcap.so.1.0.0 or something such as
+that.
+
+We've been maintaining binary compatibility between libpcap releases for
+quite a while; there's no reason to tie a binary linked with libpcap to
+a particular release of libpcap.
+
Problems, bugs, questions, desirable enhancements, etc. should be sent
-to the address "tcpdump-workers@tcpdump.org". Bugs, support requests,
-and feature requests may also be submitted on the SourceForge site for
-libpcap at
+to the address "tcpdump-workers@lists.tcpdump.org". Bugs, support
+requests, and feature requests may also be submitted on the SourceForge
+site for libpcap at
http://sourceforge.net/projects/libpcap/
Source code contributions, etc. should be sent to the email address
-"patches@tcpdump.org", or submitted as patches on the SourceForge site
-for libpcap.
+submitted as patches on the SourceForge site for libpcap.
Current versions can be found at www.tcpdump.org, or the SourceForge
site for libpcap.
diff --git a/contrib/libpcap/README.Win32 b/contrib/libpcap/README.Win32
deleted file mode 100644
index 3116d5e..0000000
--- a/contrib/libpcap/README.Win32
+++ /dev/null
@@ -1,46 +0,0 @@
-Under Win32, libpcap is integrated in the WinPcap packet capture system.
-WinPcap provides a framework that allows libpcap to capture the packets
-under Windows 95, Windows 98, Windows ME, Windows NT 4, Windows 2000
-and Windows XP.
-WinPcap binaries and source code can be found at http://winpcap.polito.it:
-they include also a developer's pack with all the necessary to compile
-libpcap-based applications under Windows.
-
-How to compile libpcap with Visual Studio
------------------------------------------
-
-In order to compile libpcap you will need:
-
-- version 6 (or higher) of Microsoft Visual Studio
-- The November 2001 (or later) edition of Microsoft Platform
-Software Development Kit (SDK), that contains some necessary includes
-for IPv6 support. You can download it from http://www.microsoft.com/sdk
-- the latest WinPcap sources from http://winpcap.polito.it/install
-
-The WinPcap source code already contains a recent (usually the latest
-stable) version of libpcap. If you need to compile a different one,
-simply download it from www.tcpdump.org and copy the sources in the
-winpcap\wpcap\libpcap folder of the WinPcap distribution. If you want to
-compile a libpcap source retrieved from the tcpdump.org CVS, you will
-have to create the scanner and the grammar by hand (with lex and yacc)
-or with the cygnus makefile, since The Visual Studio project is not able
-to build them.
-
-Open the project file winpcap\wpcap\prj\wpcap.dsw with Visual Studio and
-build wpcap.dll. wpcap.lib, the library file to link with the applications,
-will be generated in winpcap\wpcap\lib\. wpcap.dll will be generated in
-winpcap\wpcap\prj\release or winpcap\wpcap\prj\debug depending on the type
-of binary that is being created.
-
-How to compile libpcap with Cygnus
-----------------------------------
-
-To build wpcap.dll, cd to the directory WPCAP/PRJ of the WinPcap source code
-distribution and type "make". libwpcap.a, the library file to link with the
-applications, will be generated in winpcap\wpcap\lib\. wpcap.dll will be
-generated in winpcap\wpcap\prj.
-
-Remember, you CANNOT use the MSVC-generated .lib files with gcc, use
-libwpcap.a instead.
-
-"make install" installs wpcap.dll in the Windows system folder.
diff --git a/contrib/libpcap/README.aix b/contrib/libpcap/README.aix
deleted file mode 100644
index dcddb61..0000000
--- a/contrib/libpcap/README.aix
+++ /dev/null
@@ -1,78 +0,0 @@
-Using BPF:
-
-(1) AIX 4.x's version of BPF is undocumented and somewhat unstandard; the
- current BPF support code includes changes that should work around
- that; it appears to compile and work on at least one AIX 4.3.3
- machine.
-
- Note that the BPF driver and the "/dev/bpf" devices might not exist
- on your machine; AIX's tcpdump loads the driver and creates the
- devices if they don't already exist. Our libpcap should do the
- same, and the configure script should detect that it's on an AIX
- system and choose BPF even if the devices aren't there.
-
-(2) If libpcap doesn't compile on your machine when configured to use
- BPF, or if the workarounds fail to make it work correctly, you
- should send to tcpdump-workers@tcpdump.org a detailed bug report (if
- the compile fails, send us the compile error messages; if it
- compiles but fails to work correctly, send us as detailed as
- possible a description of the symptoms, including indications of the
- network link-layer type being wrong or time stamps being wrong).
-
- If you fix the problems yourself, please send to patches@tcpdump.org
- a patch, so we can incorporate them into the next release.
-
- If you don't fix the problems yourself, you can, as a workaround,
- make libpcap use DLPI instead of BPF.
-
- This can be done by specifying the flag:
-
- --with-pcap=dlpi
-
- to the "configure" script for libpcap.
-
-If you use DLPI:
-
-(1) It is a good idea to have the latest version of the DLPI driver on
- your system, since certain versions may be buggy and cause your AIX
- system to crash. DLPI is included in the fileset bos.rte.tty. I
- found that the DLPI driver that came with AIX 4.3.2 was buggy, and
- had to upgrade to bos.rte.tty 4.3.2.4:
-
- lslpp -l bos.rte.tty
-
- bos.rte.tty 4.3.2.4 COMMITTED Base TTY Support and Commands
-
- Updates for AIX filesets can be obtained from:
- ftp://service.software.ibm.com/aix/fixes/
-
- These updates can be installed with the smit program.
-
-(2) After compiling libpcap, you need to make sure that the DLPI driver
- is loaded. Type:
-
- strload -q -d dlpi
-
- If the result is:
-
- dlpi: yes
-
- then the DLPI driver is loaded correctly.
-
- If it is:
-
- dlpi: no
-
- Then you need to type:
-
- strload -f /etc/dlpi.conf
-
- Check again with strload -q -d dlpi that the dlpi driver is loaded.
-
- Alternatively, you can uncomment the lines for DLPI in
- /etc/pse.conf and reboot the machine; this way DLPI will always
- be loaded when you boot your system.
-
-(3) There appears to be a problem in the DLPI code in some versions of
- AIX, causing a warning about DL_PROMISC_MULTI failing; this might
- be responsible for DLPI not being able to capture outgoing packets.
diff --git a/contrib/libpcap/README.dag b/contrib/libpcap/README.dag
deleted file mode 100644
index acf97ed..0000000
--- a/contrib/libpcap/README.dag
+++ /dev/null
@@ -1,114 +0,0 @@
-
-The following instructions apply if you have a Linux or FreeBSD platform and
-want libpcap to support the DAG range of passive network monitoring cards from
-Endace (http://www.endace.com, see below for further contact details).
-
-1) Install and build the DAG software distribution by following the
-instructions supplied with that package. Current Endace customers can download
-the DAG software distibution from https://www.endace.com
-
-2) Configure libcap. To allow the 'configure' script to locate the DAG
-software distribution use the '--with-dag' option:
-
- ./configure --with-dag=DIR
-
-Where DIR is the root of the DAG software distribution, for example
-/var/src/dag. If the DAG software is correctly detected 'configure' will
-report:
-
- checking whether we have DAG API... yes
-
-If 'configure' reports that there is no DAG API, the directory may have been
-incorrectly specified or the DAG software was not built before configuring
-libpcap.
-
-See also the libpcap INSTALL.txt file for further libpcap configuration
-options.
-
-Building libpcap at this stage will include support for both the native packet
-capture stream (linux or bpf) and for capturing from DAG cards. To build
-libpcap with only DAG support specify the capture type as 'dag' when
-configuring libpcap:
-
- ./configure --with-dag=DIR --with-pcap=dag
-
-Applications built with libpcap configured in this way will only detect DAG
-cards and will not capture from the native OS packet stream.
-
-----------------------------------------------------------------------
-
-Libpcap when built for DAG cards against dag-2.5.1 or later releases:
-
-Timeouts are supported. pcap_dispatch() will return after to_ms milliseconds
-regardless of how many packets are received. If to_ms is zero pcap_dispatch()
-will block waiting for data indefinitely.
-
-pcap_dispatch() will block on and process a minimum of 64kB of data (before
-filtering) for efficiency. This can introduce high latencies on quiet
-interfaces unless a timeout value is set. The timeout expiring will override
-the 64kB minimum causing pcap_dispatch() to process any available data and
-return.
-
-pcap_setnonblock is supported. When nonblock is set, pcap_dispatch() will
-check once for available data, process any data available up to count, then
-return immediately.
-
-pcap_findalldevs() is supported, e.g. dag0, dag1...
-
-Some DAG cards can provide more than one 'stream' of received data.
-This can be data from different physical ports, or separated by filtering
-or load balancing mechanisms. Receive streams have even numbers, e.g.
-dag0:0, dag0:2 etc. Specifying transmit streams for capture is not supported.
-
-pcap_setfilter() is supported, BPF programs run in userspace.
-
-pcap_setdirection() is not supported. Only received traffic is captured.
-DAG cards normally do not have IP or link layer addresses assigned as
-they are used to passively monitor links.
-
-pcap_breakloop() is supported.
-
-pcap_datalink() and pcap_list_datalinks() are supported. The DAG card does
-not attempt to set the correct datalink type automatically where more than
-one type is possible.
-
-pcap_stats() is supported. ps_drop is the number of packets dropped due to
-RX stream buffer overflow, this count is before filters are applied (it will
-include packets that would have been dropped by the filter). The RX stream
-buffer size is user configurable outside libpcap, typically 16-512MB.
-
-pcap_get_selectable_fd() is not supported, as DAG cards do not support
-poll/select methods.
-
-pcap_inject() and pcap_sendpacket() are not supported.
-
-Some DAG cards now support capturing to multiple virtual interfaces, called
-streams. Capture streams have even numbers. These are available via libpcap
-as separate interfaces, e.g. dag0:0, dag0:2, dag0:4 etc. dag0:0 is the same
-as dag0. These are visible via pcap_findalldevs().
-
-libpcap now does NOT set the card's hardware snaplen (slen). This must now be
-set using the appropriate DAG coniguration program, e.g. dagthree, dagfour,
-dagsix, dagconfig. This is because the snaplen is currently shared between
-all of the streams. In future this may change if per-stream slen is
-implemented.
-
-DAG cards by default capture entire packets including the L2
-CRC/FCS. If the card is not configured to discard the CRC/FCS, this
-can confuse applications that use libpcap if they're not prepared for
-packets to have an FCS. Libpcap now reads the environment variable
-ERF_FCS_BITS to determine how many bits of CRC/FCS to strip from the
-end of the captured frame. This defaults to 32 for use with
-Ethernet. If the card is configured to strip the CRC/FCS, then set
-ERF_FCS_BITS=0. If used with a HDLC/PoS/PPP/Frame Relay link with 16
-bit CRC/FCS, then set ERF_FCS_BITS=16.
-
-----------------------------------------------------------------------
-
-Please submit bug reports via <support@endace.com>.
-
-Please also visit our Web site at:
-
- http://www.endace.com/
-
-For more information about Endace DAG cards contact <sales@endace.com>.
diff --git a/contrib/libpcap/README.hpux b/contrib/libpcap/README.hpux
deleted file mode 100644
index 88c27f8..0000000
--- a/contrib/libpcap/README.hpux
+++ /dev/null
@@ -1,254 +0,0 @@
-For HP-UX 11i (11.11) and later, there are no known issues with
-promiscuous mode under HP-UX. If you are using a earlier version of
-HP-UX and cannot upgrade, please continue reading.
-
-HP-UX patches to fix packet capture problems
-
-Note that packet-capture programs such as tcpdump may, on HP-UX, not be
-able to see packets sent from the machine on which they're running.
-Some articles on groups.google.com discussing this are:
-
- http://groups.google.com/groups?selm=82ld3v%2480i%241%40mamenchi.zrz.TU-Berlin.DE
-
-which says:
-
- Newsgroups: comp.sys.hp.hpux
- Subject: Re: Did someone made tcpdump working on 10.20 ?
- Date: 12/08/1999
- From: Lutz Jaenicke <jaenicke@emserv1.ee.TU-Berlin.DE>
-
- In article <82ks5i$5vc$1@news1.dti.ne.jp>, mtsat <mtsat@iris.dti.ne.jp>
- wrote:
- >Hello,
- >
- >I downloaded and compiled tcpdump3.4 a couple of week ago. I tried to use
- >it, but I can only see incoming data, never outgoing.
- >Someone (raj) explained me that a patch was missing, and that this patch
- >must me "patched" (poked) in order to see outbound data in promiscuous mode.
- >Many things to do .... So the question is : did someone has already this
- >"ready to use" PHNE_**** patch ?
-
- Two things:
- 1. You do need a late "LAN products cumulative patch" (e.g. PHNE_18173
- for s700/10.20).
- 2. You must use
-echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem
- You can insert this e.g. into /sbin/init.d/lan
-
- Best regards,
- Lutz
-
-and
-
- http://groups.google.com/groups?selm=88cf4t%24p03%241%40web1.cup.hp.com
-
-which says:
-
- Newsgroups: comp.sys.hp.hpux
- Subject: Re: tcpdump only shows incoming packets
- Date: 02/15/2000
- From: Rick Jones <foo@bar.baz.invalid>
-
- Harald Skotnes <harald@cc.uit.no> wrote:
- > I am running HPUX 11.0 on a C200 hanging on a 100Mb switch. I have
- > compiled libpcap-0.4 an tcpdump-3.4 and it seems to work. But at a
- > closer look I only get to see the incoming packets not the
- > outgoing. I have tried tcpflow-0.12 which also uses libpcap and the
- > same thing happens. Could someone please give me a hint on how to
- > get this right?
-
- Search/Read the archives ?-)
-
- What you are seeing is expected, un-patched, behaviour for an HP-UX
- system. On 11.00, you need to install the latest lancommon/DLPI
- patches, and then the latest driver patch for the interface(s) in use.
- At that point, a miracle happens and you should start seeing outbound
- traffic.
-
-[That article also mentions the patch that appears below.]
-
-and
-
- http://groups.google.com/groups?selm=38AA973E.96BE7DF7%40cc.uit.no
-
-which says:
-
- Newsgroups: comp.sys.hp.hpux
- Subject: Re: tcpdump only shows incoming packets
- Date: 02/16/2000
- From: Harald Skotnes <harald@cc.uit.no>
-
- Rick Jones wrote:
-
- ...
-
- > What you are seeing is expected, un-patched, behaviour for an HP-UX
- > system. On 11.00, you need to install the latest lancommon/DLPI
- > patches, and then the latest driver patch for the interface(s) in
- > use. At that point, a miracle happens and you should start seeing
- > outbound traffic.
-
- Thanks a lot. I have this problem on several machines running HPUX
- 10.20 and 11.00. The machines where patched up before y2k so did not
- know what to think. Anyway I have now installed PHNE_19766,
- PHNE_19826, PHNE_20008, PHNE_20735 on the C200 and now I can see the
- outbound traffic too. Thanks again.
-
-(although those patches may not be the ones to install - there may be
-later patches).
-
-And another message to tcpdump-workers@tcpdump.org, from Rick Jones:
-
- Date: Mon, 29 Apr 2002 15:59:55 -0700
- From: Rick Jones
- To: tcpdump-workers@tcpdump.org
- Subject: Re: [tcpdump-workers] I Can't Capture the Outbound Traffic
-
- ...
-
- http://itrc.hp.com/ would be one place to start in a search for the most
- up-to-date patches for DLPI and the lan driver(s) used on your system (I
- cannot guess because 9000/800 is too generic - one hs to use the "model"
- command these days and/or an ioscan command (see manpage) to guess what
- the drivers (btlan[3456], gelan, etc) might be involved in addition to
- DLPI.
-
- Another option is to upgrade to 11i as outbound promiscuous mode support
- is there in the base OS, no patches required.
-
-Another posting:
-
- http://groups.google.com/groups?selm=7d6gvn%24b3%241%40ocean.cup.hp.com
-
-indicates that you need to install the optional STREAMS product to do
-captures on HP-UX 9.x:
-
- Newsgroups: comp.sys.hp.hpux
- Subject: Re: tcpdump HP/UX 9.x
- Date: 03/22/1999
- From: Rick Jones <foo@bar.baz>
-
- Dave Barr (barr@cis.ohio-state.edu) wrote:
- : Has anyone ported tcpdump (or something similar) to HP/UX 9.x?
-
- I'm reasonably confident that any port of tcpdump to 9.X would require
- the (then optional) STREAMS product. This would bring DLPI, which is
- what one uses to access interfaces in promiscuous mode.
-
- I'm not sure that HP even sells the 9.X STREAMS product any longer,
- since HP-UX 9.X is off the pricelist (well, maybe 9.10 for the old 68K
- devices).
-
- Your best bet is to be up on 10.20 or better if that is at all
- possible. If your hardware is supported by it, I'd go with HP-UX 11.
- If you want to see the system's own outbound traffic, you'll never get
- that functionality on 9.X, but it might happen at some point for 10.20
- and 11.X.
-
- rick jones
-
-(as per other messages cited here, the ability to see the system's own
-outbound traffic did happen).
-
-Rick Jones reports that HP-UX 11i needs no patches for outbound
-promiscuous mode support.
-
-An additional note, from Jost Martin, for HP-UX 10.20:
-
- Q: How do I get ethereral on HPUX to capture the _outgoing_ packets
- of an interface
- A: You need to get PHNE_20892,PHNE_20725 and PHCO_10947 (or
- newer, this is as of 4.4.00) and its dependencies. Then you can
- enable the feature as descibed below:
-
- Patch Name: PHNE_20892
- Patch Description: s700 10.20 PCI 100Base-T cumulative patch
- To trace the outbound packets, please do the following
- to turn on a global promiscuous switch before running
- the promiscuous applications like snoop or tcpdump:
-
- adb -w /stand/vmunix /dev/mem
- lanc_outbound_promisc_flag/W 1
- (adb will echo the result showing that the flag has
- been changed)
- $quit
- (Thanks for this part to HP-support, Ratingen)
-
- The attached hack does this and some security-related stuff
- (thanks to hildeb@www.stahl.bau.tu-bs.de (Ralf Hildebrandt) who
- posted the security-part some time ago)
-
- <<hack_ip_stack>>
-
- (Don't switch IP-forwarding off, if you need it !)
- Install the hack as /sbin/init.d/hacl_ip_stack (adjust
- permissions !) and make a sequencing-symlink
- /sbin/rc2.d/S350hack_ip_stack pointing to this script.
- Now all this is done on every reboot.
-
-According to Rick Jones, the global promiscuous switch also has to be
-turned on for HP-UX 11.00, but not for 11i - and, in fact, the switch
-doesn't even exist on 11i.
-
-Here's the "hack_ip_stack" script:
-
------------------------------------Cut Here-------------------------------------
-#!/sbin/sh
-#
-# nettune: hack kernel parms for safety
-
-OKAY=0
-ERROR=-1
-
-# /usr/contrib/bin fuer nettune auf Pfad
-PATH=/sbin:/usr/sbin:/usr/bin:/usr/contrib/bin
-export PATH
-
-
-##########
-# main #
-##########
-
-case $1 in
- start_msg)
- print "Tune IP-Stack for security"
- exit $OKAY
- ;;
-
- stop_msg)
- print "This action is not applicable"
- exit $OKAY
- ;;
-
- stop)
- exit $OKAY
- ;;
-
- start)
- ;; # fall through
-
- *)
- print "USAGE: $0 {start_msg | stop_msg | start | stop}" >&2
- exit $ERROR
- ;;
- esac
-
-###########
-# start #
-###########
-
-#
-# tcp-Sequence-Numbers nicht mehr inkrementieren sondern random
-# Syn-Flood-Protection an
-# ip_forwarding aus
-# Source-Routing aus
-# Ausgehende Packets an ethereal/tcpdump etc.
-
-/usr/contrib/bin/nettune -s tcp_random_seq 2 || exit $ERROR
-/usr/contrib/bin/nettune -s hp_syn_protect 1 || exit $ERROR
-/usr/contrib/bin/nettune -s ip_forwarding 0 || exit $ERROR
-echo 'ip_block_source_routed/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem || exit $ERROR
-echo 'lanc_outbound_promisc_flag/W 1' | adb -w /stand/vmunix /dev/mem || exit $ERROR
-
-exit $OKAY
------------------------------------Cut Here-------------------------------------
diff --git a/contrib/libpcap/README.linux b/contrib/libpcap/README.linux
deleted file mode 100644
index dd95913..0000000
--- a/contrib/libpcap/README.linux
+++ /dev/null
@@ -1,88 +0,0 @@
-In order for libpcap to be able to capture packets on a Linux system,
-the "packet" protocol must be supported by your kernel. If it is not,
-you may get error messages such as
-
- modprobe: can't locate module net-pf-17
-
-in "/var/adm/messages", or may get messages such as
-
- socket: Address family not supported by protocol
-
-from applications using libpcap.
-
-You must configure the kernel with the CONFIG_PACKET option for this
-protocol; the following note is from the Linux "Configure.help" file for
-the 2.0[.x] kernel:
-
- Packet socket
- CONFIG_PACKET
- The Packet protocol is used by applications which communicate
- directly with network devices without an intermediate network
- protocol implemented in the kernel, e.g. tcpdump. If you want them
- to work, choose Y.
-
- This driver is also available as a module called af_packet.o ( =
- code which can be inserted in and removed from the running kernel
- whenever you want). If you want to compile it as a module, say M
- here and read Documentation/modules.txt; if you use modprobe or
- kmod, you may also want to add "alias net-pf-17 af_packet" to
- /etc/modules.conf.
-
-and the note for the 2.2[.x] kernel says:
-
- Packet socket
- CONFIG_PACKET
- The Packet protocol is used by applications which communicate
- directly with network devices without an intermediate network
- protocol implemented in the kernel, e.g. tcpdump. If you want them
- to work, choose Y. This driver is also available as a module called
- af_packet.o ( = code which can be inserted in and removed from the
- running kernel whenever you want). If you want to compile it as a
- module, say M here and read Documentation/modules.txt. You will
- need to add 'alias net-pf-17 af_packet' to your /etc/conf.modules
- file for the module version to function automatically. If unsure,
- say Y.
-
-In addition, there is an option that, in 2.2 and later kernels, will
-allow packet capture filters specified to programs such as tcpdump to be
-executed in the kernel, so that packets that don't pass the filter won't
-be copied from the kernel to the program, rather than having all packets
-copied to the program and libpcap doing the filtering in user mode.
-
-Copying packets from the kernel to the program consumes a significant
-amount of CPU, so filtering in the kernel can reduce the overhead of
-capturing packets if a filter has been specified that discards a
-significant number of packets. (If no filter is specified, it makes no
-difference whether the filtering isn't performed in the kernel or isn't
-performed in user mode. :-))
-
-The option for this is the CONFIG_FILTER option; the "Configure.help"
-file says:
-
- Socket filtering
- CONFIG_FILTER
- The Linux Socket Filter is derived from the Berkeley Packet Filter.
- If you say Y here, user-space programs can attach a filter to any
- socket and thereby tell the kernel that it should allow or disallow
- certain types of data to get through the socket. Linux Socket
- Filtering works on all socket types except TCP for now. See the text
- file linux/Documentation/networking/filter.txt for more information.
- If unsure, say N.
-
-
-Statistics:
-Statistics reported by pcap are platform specific. The statistics
-reported by pcap_stats on Linux are as follows:
-
-2.2.x
-=====
-ps_recv Number of packets that were accepted by the pcap filter
-ps_drops Always 0, this statistic is not gatherd on this platform
-
-2.4.x
-=====
-ps_rec Number of packets that were accepted by the pcap filter
-ps_drops Number of packets that had passed filtering but were not
- passed on to pcap due to things like buffer shortage, etc.
- This is useful because these are packets you are interested in
- but won't be reported by, for example, tcpdump output.
diff --git a/contrib/libpcap/README.macosx b/contrib/libpcap/README.macosx
deleted file mode 100644
index 25794d8..0000000
--- a/contrib/libpcap/README.macosx
+++ /dev/null
@@ -1,43 +0,0 @@
-As with other systems using BPF, Mac OS X allows users with read access
-to the BPF devices to capture packets with libpcap and allows users with
-write access to the BPF devices to send packets with libpcap.
-
-On some systems that use BPF, the BPF devices live on the root file
-system, and the permissions and/or ownership on those devices can be
-changed to give users other than root permission to read or write those
-devices.
-
-On newer versions of FreeBSD, the BPF devices live on devfs, and devfs
-can be configured to set the permissions and/or ownership of those
-devices to give users other than root permission to read or write those
-devices.
-
-On Mac OS X, the BPF devices live on devfs, but the OS X version of
-devfs is based on an older (non-default) FreeBSD devfs, and that version
-of devfs cannot be configured to set the permissions and/or ownership of
-those devices.
-
-Therefore, we supply a "startup item" for OS X that will change the
-ownership of the BPF devices so that the "admin" group owns them, and
-will change the permission of the BPF devices to rw-rw----, so that all
-users in the "admin" group - i.e., all users with "Allow user to
-administer this computer" turned on - have both read and write access to
-them.
-
-The startup item is in the ChmodBPF directory in the source tree. A
-/Library/StartupItems directory should be created if it doesn't already
-exist, and the ChmodBPF directory should be copied to the
-/Library/StartupItems directory (copy the entire directory, so that
-there's a /Library/StartupItems/ChmodBPF directory, containing all the
-files in the source tree's ChmodBPF directory; don't copy the individual
-items in that directory to /Library/StartupItems).
-
-If you want to give a particular user permission to access the BPF
-devices, rather than giving all administrative users permission to
-access them, you can have the ChmodBPF/ChmodBPF script change the
-ownership of /dev/bpf* without changing the permissions. If you want to
-give a particular user permission to read and write the BPF devices and
-give the administrative users permission to read but not write the BPF
-devices, you can have the script change the owner to that user, the
-group to "admin", and the permissions to rw-r-----. Other possibilities
-are left as an exercise for the reader.
diff --git a/contrib/libpcap/README.septel b/contrib/libpcap/README.septel
deleted file mode 100644
index fbc88df..0000000
--- a/contrib/libpcap/README.septel
+++ /dev/null
@@ -1,50 +0,0 @@
-The following instructions apply if you have a Linux platform and want
-libpcap to support the Septel range of passive network monitoring cards
-from Intel (http://www.intel.com)
-
-1) Install and build the Septel software distribution by following the
-instructions supplied with that package.
-
-2) Configure libcap. To allow the 'configure' script to locate the Septel
-software distribution use the '--with-septel' option:
-
- ./configure --with-septel=DIR
-
-where DIR is the root of the Septel software distribution, for example
-/var/src/septel.
-
-By default (if you write only ./configure --with-septel) it takes
-./../septel as argument for DIR.
-
-If the Septel software is correctly detected 'configure' will
-report:
-
- checking whether we have Septel API... yes
-
-If 'configure' reports that there is no Septel API, the directory may have been
-incorrectly specified or the Septel software was not built before configuring
-libpcap.
-
-See also the libpcap INSTALL.txt file for further libpcap configuration
-options.
-
-Building libpcap at this stage will include support for both the native
-packet capture stream and for capturing from Septel cards. To build
-libpcap with only Septel support specify the capture type as 'septel'
-when configuring libpcap:
-
- ./configure --with-septel=DIR --with-pcap=septel
-
-Applications built with libpcap configured in this way will only detect Septel
-cards and will not capture from the native OS packet stream.
-
-Note: As mentioned in pcap-septel.c we should first edit the system.txt
-file to change the user part example (UPE) module id to 0xdd instead of
-0x2d for technical reason. So this change in system.txt is crutial and
-things will go wrong if it's not done. System.txt along with config.txt
-are configuration files that are edited by the user before running the
-gctload program that uses these files for initialising modules and
-configuring parameters.
-
-----------------------------------------------------------------------
-for more information please contact me : gil_hoyek@hotmail.com
diff --git a/contrib/libpcap/README.tru64 b/contrib/libpcap/README.tru64
deleted file mode 100644
index 7fe1ef0..0000000
--- a/contrib/libpcap/README.tru64
+++ /dev/null
@@ -1,49 +0,0 @@
-The following instructions are applicable to Tru64 UNIX
-(formerly Digital UNIX (formerly DEC OSF/1)) version 4.0, and
-probably to later versions as well; at least some options apply to
-Digital UNIX 3.2 - perhaps all do.
-
-In order to use kernel packet filtering on this system, you have
-to configure it in such a way:
-
-Kernel configuration
---------------------
-
-The packet filtering kernel option must be enabled at kernel
-installation. If it was not the case, you can rebuild the kernel with
-"doconfig -c" after adding the following line in the kernel
-configuration file (/sys/conf/<HOSTNAME>):
-
- option PACKETFILTER
-
-or use "doconfig" without any arguments to add the packet filter driver
-option via the kernel option menu (see the system administration
-documentation for information on how to do this).
-
-Device configuration
---------------------
-
-Devices used for packet filtering must be created thanks to
-the following command (executed in the /dev directory):
-
- ./MAKEDEV pfilt
-
-Interface configuration
------------------------
-
-In order to capture all packets on a network, you may want to allow
-applications to put the interface on that network into "local copy"
-mode, so that tcpdump can see packets sent by the host on which it's
-running as well as packets received by that host, and to put the
-interface into "promiscuous" mode, so that tcpdump can see packets on
-the network segment not sent to the host on which it's running, by using
-the pfconfig(1) command:
-
- pfconfig +c +p <network_device>
-
-or allow application to put any interface into "local copy" or
-"promiscuous" mode by using the command:
-
- pfconfig +c +p -a
-
-Note: all instructions given require root privileges.
diff --git a/contrib/libpcap/VERSION b/contrib/libpcap/VERSION
index e3e1807..3eefcb9 100644
--- a/contrib/libpcap/VERSION
+++ b/contrib/libpcap/VERSION
@@ -1 +1 @@
-0.9.8
+1.0.0
diff --git a/contrib/libpcap/acsite.m4 b/contrib/libpcap/acsite.m4
deleted file mode 100644
index 746faf1..0000000
--- a/contrib/libpcap/acsite.m4
+++ /dev/null
@@ -1,505 +0,0 @@
-dnl @(#) $Header: acsite.m4,v 1.41 96/11/29 15:30:40 leres Exp $ (LBL)
-dnl
-dnl Copyright (c) 1995, 1996
-dnl The Regents of the University of California. All rights reserved.
-dnl
-dnl Redistribution and use in source and binary forms, with or without
-dnl modification, are permitted provided that: (1) source code distributions
-dnl retain the above copyright notice and this paragraph in its entirety, (2)
-dnl distributions including binary code include the above copyright notice and
-dnl this paragraph in its entirety in the documentation or other materials
-dnl provided with the distribution, and (3) all advertising materials mentioning
-dnl features or use of this software display the following acknowledgement:
-dnl ``This product includes software developed by the University of California,
-dnl Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
-dnl the University nor the names of its contributors may be used to endorse
-dnl or promote products derived from this software without specific prior
-dnl written permission.
-dnl THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
-dnl WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
-dnl MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-dnl
-dnl LBL autoconf macros
-dnl
-
-dnl
-dnl Determine which compiler we're using (cc or gcc)
-dnl If using gcc, determine the version number
-dnl If using cc, require that it support ansi prototypes
-dnl If using gcc, use -O2 (otherwise use -O)
-dnl If using cc, explicitly specify /usr/local/include
-dnl
-dnl usage:
-dnl
-dnl AC_LBL_C_INIT(copt, incls)
-dnl
-dnl results:
-dnl
-dnl $1 (copt set)
-dnl $2 (incls set)
-dnl CC
-dnl ac_cv_gcc_vers
-dnl LBL_CFLAGS
-dnl
-dnl XXX need to add test to make sure ac_prog_cc hasn't been called
-AC_DEFUN(AC_LBL_C_INIT,
- [AC_PREREQ(2.12)
- $1=-O
- $2=""
- if test "${CFLAGS+set}" = set; then
- LBL_CFLAGS="$CFLAGS"
- fi
- if test -z "$CC" ; then
- case "$target_os" in
-
- bsdi*)
- AC_CHECK_PROG(SHLICC2, shlicc2, yes, no)
- if test $SHLICC2 = yes ; then
- CC=shlicc2
- export CC
- fi
- ;;
- esac
- fi
- AC_PROG_CC
- if test $ac_cv_prog_gcc = yes ; then
- if test "$SHLICC2" = yes ; then
- ac_cv_gcc_vers=2
- $1=-O2
- else
- AC_MSG_CHECKING(gcc version)
- AC_CACHE_VAL(ac_cv_gcc_vers,
- ac_cv_gcc_vers=`$CC -v 2>&1 | \
- sed -n -e '$s/.* //' -e '$s/\..*//p'`)
- AC_MSG_RESULT($ac_cv_gcc_vers)
- if test $ac_cv_gcc_vers -gt 1 ; then
- $1=-O2
- fi
- fi
- else
- AC_MSG_CHECKING(that $CC handles ansi prototypes)
- AC_CACHE_VAL(ac_cv_cc_ansi_prototypes,
- AC_TRY_COMPILE(
- [#include <sys/types.h>],
- [int frob(int, char *)],
- ac_cv_cc_ansi_prototypes=yes,
- ac_cv_cc_ansi_prototypes=no))
- AC_MSG_RESULT($ac_cv_cc_ansi_prototypes)
- if test $ac_cv_cc_ansi_prototypes = no ; then
- case "$target_os" in
-
- hpux*)
- AC_MSG_CHECKING(for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE))
- savedcflags="$CFLAGS"
- CFLAGS="-Aa -D_HPUX_SOURCE $CFLAGS"
- AC_CACHE_VAL(ac_cv_cc_hpux_cc_aa,
- AC_TRY_COMPILE(
- [#include <sys/types.h>],
- [int frob(int, char *)],
- ac_cv_cc_hpux_cc_aa=yes,
- ac_cv_cc_hpux_cc_aa=no))
- AC_MSG_RESULT($ac_cv_cc_hpux_cc_aa)
- if test $ac_cv_cc_hpux_cc_aa = no ; then
- AC_MSG_ERROR(see the INSTALL for more info)
- fi
- CFLAGS="$savedcflags"
- V_CCOPT="-Aa $V_CCOPT"
- AC_DEFINE(_HPUX_SOURCE)
- ;;
-
- *)
- AC_MSG_ERROR(see the INSTALL for more info)
- ;;
- esac
- fi
- $2=-I/usr/local/include
-
- case "$target_os" in
-
- irix*)
- V_CCOPT="$V_CCOPT -xansi -signed -g3"
- ;;
-
- osf*)
- V_CCOPT="$V_CCOPT -g3"
- ;;
-
- ultrix*)
- AC_MSG_CHECKING(that Ultrix $CC hacks const in prototypes)
- AC_CACHE_VAL(ac_cv_cc_const_proto,
- AC_TRY_COMPILE(
- [#include <sys/types.h>],
- [struct a { int b; };
- void c(const struct a *)],
- ac_cv_cc_const_proto=yes,
- ac_cv_cc_const_proto=no))
- AC_MSG_RESULT($ac_cv_cc_const_proto)
- if test $ac_cv_cc_const_proto = no ; then
- AC_DEFINE(const,)
- fi
- ;;
- esac
- fi
-])
-
-dnl
-dnl Use pfopen.c if available and pfopen() not in standard libraries
-dnl Require libpcap
-dnl Look for libpcap in ..
-dnl Use the installed libpcap if there is no local version
-dnl
-dnl usage:
-dnl
-dnl AC_LBL_LIBPCAP(pcapdep, incls)
-dnl
-dnl results:
-dnl
-dnl $1 (pcapdep set)
-dnl $2 (incls appended)
-dnl LIBS
-dnl
-AC_DEFUN(AC_LBL_LIBPCAP,
- [pfopen=/usr/examples/packetfilter/pfopen.c
- if test -f $pfopen ; then
- AC_CHECK_FUNCS(pfopen)
- if test $ac_cv_func_pfopen = "no" ; then
- AC_MSG_RESULT(Using $pfopen)
- LIBS="$LIBS $pfopen"
- fi
- fi
- AC_MSG_CHECKING(for local pcap library)
- libpcap=FAIL
- lastdir=FAIL
- places=`ls .. | sed -e 's,/$,,' -e 's,^,../,' | \
- egrep '/libpcap-[[0-9]]*\.[[0-9]]*(\.[[0-9]]*)?([[ab]][[0-9]]*)?$'`
- for dir in $places ../libpcap libpcap ; do
- basedir=`echo $dir | sed -e 's/[[ab]][[0-9]]*$//'`
- if test $lastdir = $basedir ; then
- dnl skip alphas when an actual release is present
- continue;
- fi
- lastdir=$dir
- if test -r $dir/pcap.c ; then
- libpcap=$dir/libpcap.a
- d=$dir
- dnl continue and select the last one that exists
- fi
- done
- if test $libpcap = FAIL ; then
- AC_MSG_RESULT(not found)
- AC_CHECK_LIB(pcap, main, libpcap="-lpcap")
- if test $libpcap = FAIL ; then
- AC_MSG_ERROR(see the INSTALL doc for more info)
- fi
- else
- $1=$libpcap
- $2="-I$d $$2"
- AC_MSG_RESULT($libpcap)
- fi
- LIBS="$libpcap $LIBS"])
-
-dnl
-dnl Define RETSIGTYPE and RETSIGVAL
-dnl
-dnl usage:
-dnl
-dnl AC_LBL_TYPE_SIGNAL
-dnl
-dnl results:
-dnl
-dnl RETSIGTYPE (defined)
-dnl RETSIGVAL (defined)
-dnl
-AC_DEFUN(AC_LBL_TYPE_SIGNAL,
- [AC_TYPE_SIGNAL
- if test "$ac_cv_type_signal" = void ; then
- AC_DEFINE(RETSIGVAL,)
- else
- AC_DEFINE(RETSIGVAL,(0))
- fi
- case "$target_os" in
-
- irix*)
- AC_DEFINE(_BSD_SIGNALS)
- ;;
-
- *)
- AC_CHECK_FUNCS(sigset)
- if test $ac_cv_func_sigset = yes ; then
- AC_DEFINE(signal, sigset)
- fi
- ;;
- esac])
-
-dnl
-dnl If using gcc, see if fixincludes should be run
-dnl
-dnl usage:
-dnl
-dnl AC_LBL_FIXINCLUDES
-dnl
-AC_DEFUN(AC_LBL_FIXINCLUDES,
- [if test $ac_cv_prog_gcc = yes ; then
- AC_MSG_CHECKING(if fixincludes is needed)
- AC_CACHE_VAL(ac_cv_gcc_fixincludes,
- AC_TRY_COMPILE(
- [/*
- * This generates a "duplicate case value" when fixincludes
- * has not be run.
- */
-# include <sys/types.h>
-# include <sys/time.h>
-# include <sys/ioctl.h>
-# ifdef HAVE_SYS_IOCCOM_H
-# include <sys/ioccom.h>
-# endif],
- [switch (0) {
- case _IO('A', 1):;
- case _IO('B', 1):;
- }],
- ac_cv_gcc_fixincludes=yes,
- ac_cv_gcc_fixincludes=no))
- AC_MSG_RESULT($ac_cv_gcc_fixincludes)
- if test $ac_cv_gcc_fixincludes = no ; then
- # Don't cache failure
- unset ac_cv_gcc_fixincludes
- AC_MSG_ERROR(see the INSTALL for more info)
- fi
- fi])
-
-dnl
-dnl Check for flex, default to lex
-dnl Require flex 2.4 or higher
-dnl Check for bison, default to yacc
-dnl Default to lex/yacc if both flex and bison are not available
-dnl Define the yy prefix string if using flex and bison
-dnl
-dnl usage:
-dnl
-dnl AC_LBL_LEX_AND_YACC(lex, yacc, yyprefix)
-dnl
-dnl results:
-dnl
-dnl $1 (lex set)
-dnl $2 (yacc appended)
-dnl $3 (optional flex and bison -P prefix)
-dnl
-AC_DEFUN(AC_LBL_LEX_AND_YACC,
- [AC_CHECK_PROGS($1, flex, lex)
- if test "$$1" = flex ; then
- # The -V flag was added in 2.4
- AC_MSG_CHECKING(for flex 2.4 or higher)
- AC_CACHE_VAL(ac_cv_flex_v24,
- if flex -V >/dev/null 2>&1; then
- ac_cv_flex_v24=yes
- else
- ac_cv_flex_v24=no
- fi)
- AC_MSG_RESULT($ac_cv_flex_v24)
- if test $ac_cv_flex_v24 = no ; then
- s="2.4 or higher required"
- AC_MSG_WARN(ignoring obsolete flex executable ($s))
- $1=lex
- fi
- fi
- AC_CHECK_PROGS($2, bison, yacc)
- if test "$$2" = bison ; then
- $2="$$2 -y"
- fi
- if test "$$1" != lex -a "$$2" = yacc -o "$$1" = lex -a "$$2" != yacc ; then
- AC_MSG_WARN(don't have both flex and bison; reverting to lex/yacc)
- $1=lex
- $2=yacc
- fi
- if test "$$1" = flex -a -n "$3" ; then
- $1="$$1 -P$3"
- $2="$$2 -p $3"
- fi])
-
-dnl
-dnl Checks to see if union wait is used with WEXITSTATUS()
-dnl
-dnl usage:
-dnl
-dnl AC_LBL_UNION_WAIT
-dnl
-dnl results:
-dnl
-dnl DECLWAITSTATUS (defined)
-dnl
-AC_DEFUN(AC_LBL_UNION_WAIT,
- [AC_MSG_CHECKING(if union wait is used)
- AC_CACHE_VAL(ac_cv_union_wait,
- AC_TRY_COMPILE([
-# include <sys/types.h>
-# include <sys/wait.h>],
- [int status;
- u_int i = WEXITSTATUS(status);
- u_int j = waitpid(0, &status, 0);],
- ac_cv_union_wait=no,
- ac_cv_union_wait=yes))
- AC_MSG_RESULT($ac_cv_union_wait)
- if test $ac_cv_union_wait = yes ; then
- AC_DEFINE(DECLWAITSTATUS,union wait)
- else
- AC_DEFINE(DECLWAITSTATUS,int)
- fi])
-
-dnl
-dnl Checks to see if the sockaddr struct has the 4.4 BSD sa_len member
-dnl
-dnl usage:
-dnl
-dnl AC_LBL_SOCKADDR_SA_LEN
-dnl
-dnl results:
-dnl
-dnl HAVE_SOCKADDR_SA_LEN (defined)
-dnl
-AC_DEFUN(AC_LBL_SOCKADDR_SA_LEN,
- [AC_MSG_CHECKING(if sockaddr struct has sa_len member)
- AC_CACHE_VAL(ac_cv_sockaddr_has_sa_len,
- AC_TRY_COMPILE([
-# include <sys/types.h>
-# include <sys/socket.h>],
- [u_int i = sizeof(((struct sockaddr *)0)->sa_len)],
- ac_cv_sockaddr_has_sa_len=yes,
- ac_cv_sockaddr_has_sa_len=no))
- AC_MSG_RESULT($ac_cv_sockaddr_has_sa_len)
- if test $ac_cv_sockaddr_has_sa_len = yes ; then
- AC_DEFINE(HAVE_SOCKADDR_SA_LEN)
- fi])
-
-dnl
-dnl Checks to see if -R is used
-dnl
-dnl usage:
-dnl
-dnl AC_LBL_HAVE_RUN_PATH
-dnl
-dnl results:
-dnl
-dnl ac_cv_have_run_path (yes or no)
-dnl
-AC_DEFUN(AC_LBL_HAVE_RUN_PATH,
- [AC_MSG_CHECKING(for ${CC-cc} -R)
- AC_CACHE_VAL(ac_cv_have_run_path,
- [echo 'main(){}' > conftest.c
- ${CC-cc} -o conftest conftest.c -R/a1/b2/c3 >conftest.out 2>&1
- if test ! -s conftest.out ; then
- ac_cv_have_run_path=yes
- else
- ac_cv_have_run_path=no
- fi
- rm -f conftest*])
- AC_MSG_RESULT($ac_cv_have_run_path)
- ])
-
-dnl
-dnl Checks to see if unaligned memory accesses fail
-dnl
-dnl usage:
-dnl
-dnl AC_LBL_UNALIGNED_ACCESS
-dnl
-dnl results:
-dnl
-dnl LBL_ALIGN (DEFINED)
-dnl
-AC_DEFUN(AC_LBL_UNALIGNED_ACCESS,
- [AC_MSG_CHECKING(if unaligned accesses fail)
- AC_CACHE_VAL(ac_cv_unaligned_fail,
- [case "$target_cpu" in
-
- alpha|hp*|mips|sparc)
- ac_cv_unaligned_fail=yes
- ;;
-
- *)
- cat >conftest.c <<EOF
-# include <sys/types.h>
-# include <sys/wait.h>
-# include <stdio.h>
- unsigned char a[[5]] = { 1, 2, 3, 4, 5 };
- main() {
- unsigned int i;
- pid_t pid;
- int status;
- /* avoid "core dumped" message */
- pid = fork();
- if (pid < 0)
- exit(2);
- if (pid > 0) {
- /* parent */
- pid = waitpid(pid, &status, 0);
- if (pid < 0)
- exit(3);
- exit(!WIFEXITED(status));
- }
- /* child */
- i = *(unsigned int *)&a[[1]];
- printf("%d\n", i);
- exit(0);
- }
-EOF
- ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \
- conftest.c $LIBS >/dev/null 2>&1
- if test ! -x conftest ; then
- dnl failed to compile for some reason
- ac_cv_unaligned_fail=yes
- else
- ./conftest >conftest.out
- if test ! -s conftest.out ; then
- ac_cv_unaligned_fail=yes
- else
- ac_cv_unaligned_fail=no
- fi
- fi
- rm -f conftest* core core.conftest
- ;;
- esac])
- AC_MSG_RESULT($ac_cv_unaligned_fail)
- if test $ac_cv_unaligned_fail = yes ; then
- AC_DEFINE(LBL_ALIGN)
- fi])
-
-dnl
-dnl If using gcc and the file .devel exists:
-dnl Compile with -g (if supported) and -Wall
-dnl If using gcc 2, do extra prototype checking
-dnl If an os prototype include exists, symlink os-proto.h to it
-dnl
-dnl usage:
-dnl
-dnl AC_LBL_DEVEL(copt)
-dnl
-dnl results:
-dnl
-dnl $1 (copt appended)
-dnl HAVE_OS_PROTO_H (defined)
-dnl os-proto.h (symlinked)
-dnl
-AC_DEFUN(AC_LBL_DEVEL,
- [rm -f os-proto.h
- if test "${LBL_CFLAGS+set}" = set; then
- $1="$$1 ${LBL_CFLAGS}"
- fi
- if test $ac_cv_prog_gcc = yes -a -f .devel ; then
- if test "${LBL_CFLAGS+set}" != set; then
- if test "$ac_cv_prog_cc_g" = yes ; then
- $1="-g $$1"
- fi
- $1="$$1 -Wall"
- if test $ac_cv_gcc_vers -gt 1 ; then
- $1="$$1 -Wmissing-prototypes -Wstrict-prototypes"
- fi
- fi
- os=`echo $target_os | sed -e 's/\([[0-9]][[0-9]]*\)[[^0-9]].*$/\1/'`
- name="lbl/os-$os.h"
- if test -f $name ; then
- ln -s $name os-proto.h
- AC_DEFINE(HAVE_OS_PROTO_H)
- else
- AC_MSG_WARN(can't find $name)
- fi
- fi])
diff --git a/contrib/libpcap/atmuni31.h b/contrib/libpcap/atmuni31.h
index 877ed68..11242b8 100644
--- a/contrib/libpcap/atmuni31.h
+++ b/contrib/libpcap/atmuni31.h
@@ -29,18 +29,18 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
- * @(#) $Header: /tcpdump/master/libpcap/atmuni31.h,v 1.1 2002/07/11 09:06:32 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/atmuni31.h,v 1.1.6.2 2007/10/22 19:30:14 guy Exp $ (LBL)
*/
/* Based on UNI3.1 standard by ATM Forum */
/* ATM traffic types based on VPI=0 and (the following VCI */
-#define PPC 0x05 /* Point-to-point signal msg */
-#define BCC 0x02 /* Broadcast signal msg */
-#define OAMF4SC 0x03 /* Segment OAM F4 flow cell */
-#define OAMF4EC 0x04 /* End-to-end OAM F4 flow cell */
-#define METAC 0x01 /* Meta signal msg */
-#define ILMIC 0x10 /* ILMI msg */
+#define VCI_PPC 0x05 /* Point-to-point signal msg */
+#define VCI_BCC 0x02 /* Broadcast signal msg */
+#define VCI_OAMF4SC 0x03 /* Segment OAM F4 flow cell */
+#define VCI_OAMF4EC 0x04 /* End-to-end OAM F4 flow cell */
+#define VCI_METAC 0x01 /* Meta signal msg */
+#define VCI_ILMIC 0x10 /* ILMI msg */
/* Q.2931 signalling messages */
#define CALL_PROCEED 0x02 /* call proceeding */
diff --git a/contrib/libpcap/bpf/net/bpf_filter.c b/contrib/libpcap/bpf/net/bpf_filter.c
index 40df32a..77002dc 100644
--- a/contrib/libpcap/bpf/net/bpf_filter.c
+++ b/contrib/libpcap/bpf/net/bpf_filter.c
@@ -40,7 +40,7 @@
#if !(defined(lint) || defined(KERNEL) || defined(_KERNEL))
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.44 2003/11/15 23:24:07 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.45.2.1 2008/01/02 04:22:16 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -71,7 +71,7 @@ static const char rcsid[] _U_ =
#endif /* WIN32 */
-#include <pcap-bpf.h>
+#include <pcap/bpf.h>
#if !defined(KERNEL) && !defined(_KERNEL)
#include <stdlib.h>
@@ -512,54 +512,155 @@ bpf_filter(pc, p, wirelen, buflen)
}
}
-
/*
* Return true if the 'fcode' is a valid filter program.
* The constraints are that each jump be forward and to a valid
- * code. The code must terminate with either an accept or reject.
- * 'valid' is an array for use by the routine (it must be at least
- * 'len' bytes long).
+ * code, that memory accesses are within valid ranges (to the
+ * extent that this can be checked statically; loads of packet
+ * data have to be, and are, also checked at run time), and that
+ * the code terminates with either an accept or reject.
*
* The kernel needs to be able to verify an application's filter code.
* Otherwise, a bogus program could easily crash the system.
*/
int
bpf_validate(f, len)
- struct bpf_insn *f;
+ const struct bpf_insn *f;
int len;
{
- register int i;
- register struct bpf_insn *p;
+ u_int i, from;
+ const struct bpf_insn *p;
+
+ if (len < 1)
+ return 0;
+ /*
+ * There's no maximum program length in userland.
+ */
+#if defined(KERNEL) || defined(_KERNEL)
+ if (len > BPF_MAXINSNS)
+ return 0;
+#endif
for (i = 0; i < len; ++i) {
+ p = &f[i];
+ switch (BPF_CLASS(p->code)) {
/*
- * Check that that jumps are forward, and within
- * the code block.
+ * Check that memory operations use valid addresses.
*/
- p = &f[i];
- if (BPF_CLASS(p->code) == BPF_JMP) {
- register int from = i + 1;
-
- if (BPF_OP(p->code) == BPF_JA) {
- if (from + p->k >= (unsigned)len)
+ case BPF_LD:
+ case BPF_LDX:
+ switch (BPF_MODE(p->code)) {
+ case BPF_IMM:
+ break;
+ case BPF_ABS:
+ case BPF_IND:
+ case BPF_MSH:
+ /*
+ * There's no maximum packet data size
+ * in userland. The runtime packet length
+ * check suffices.
+ */
+#if defined(KERNEL) || defined(_KERNEL)
+ /*
+ * More strict check with actual packet length
+ * is done runtime.
+ */
+ if (p->k >= bpf_maxbufsize)
return 0;
+#endif
+ break;
+ case BPF_MEM:
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+ break;
+ case BPF_LEN:
+ break;
+ default:
+ return 0;
}
- else if (from + p->jt >= len || from + p->jf >= len)
+ break;
+ case BPF_ST:
+ case BPF_STX:
+ if (p->k >= BPF_MEMWORDS)
return 0;
- }
- /*
- * Check that memory operations use valid addresses.
- */
- if ((BPF_CLASS(p->code) == BPF_ST ||
- (BPF_CLASS(p->code) == BPF_LD &&
- (p->code & 0xe0) == BPF_MEM)) &&
- (p->k >= BPF_MEMWORDS || p->k < 0))
- return 0;
- /*
- * Check for constant division by 0.
- */
- if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
+ break;
+ case BPF_ALU:
+ switch (BPF_OP(p->code)) {
+ case BPF_ADD:
+ case BPF_SUB:
+ case BPF_MUL:
+ case BPF_OR:
+ case BPF_AND:
+ case BPF_LSH:
+ case BPF_RSH:
+ case BPF_NEG:
+ break;
+ case BPF_DIV:
+ /*
+ * Check for constant division by 0.
+ */
+ if (BPF_RVAL(p->code) == BPF_K && p->k == 0)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case BPF_JMP:
+ /*
+ * Check that jumps are within the code block,
+ * and that unconditional branches don't go
+ * backwards as a result of an overflow.
+ * Unconditional branches have a 32-bit offset,
+ * so they could overflow; we check to make
+ * sure they don't. Conditional branches have
+ * an 8-bit offset, and the from address is <=
+ * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
+ * is sufficiently small that adding 255 to it
+ * won't overflow.
+ *
+ * We know that len is <= BPF_MAXINSNS, and we
+ * assume that BPF_MAXINSNS is < the maximum size
+ * of a u_int, so that i + 1 doesn't overflow.
+ *
+ * For userland, we don't know that the from
+ * or len are <= BPF_MAXINSNS, but we know that
+ * from <= len, and, except on a 64-bit system,
+ * it's unlikely that len, if it truly reflects
+ * the size of the program we've been handed,
+ * will be anywhere near the maximum size of
+ * a u_int. We also don't check for backward
+ * branches, as we currently support them in
+ * userland for the protochain operation.
+ */
+ from = i + 1;
+ switch (BPF_OP(p->code)) {
+ case BPF_JA:
+#if defined(KERNEL) || defined(_KERNEL)
+ if (from + p->k < from || from + p->k >= len)
+#else
+ if (from + p->k >= len)
+#endif
+ return 0;
+ break;
+ case BPF_JEQ:
+ case BPF_JGT:
+ case BPF_JGE:
+ case BPF_JSET:
+ if (from + p->jt >= len || from + p->jf >= len)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case BPF_RET:
+ break;
+ case BPF_MISC:
+ break;
+ default:
return 0;
+ }
}
return BPF_CLASS(f[len - 1].code) == BPF_RET;
}
diff --git a/contrib/libpcap/bpf_dump.c b/contrib/libpcap/bpf_dump.c
index 303602e..630fa5c 100644
--- a/contrib/libpcap/bpf_dump.c
+++ b/contrib/libpcap/bpf_dump.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/bpf_dump.c,v 1.14 2003/11/15 23:23:57 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/bpf_dump.c,v 1.14.4.1 2008/01/02 04:22:16 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -33,7 +33,7 @@ static const char rcsid[] _U_ =
void
bpf_dump(struct bpf_program *p, int option)
{
- struct bpf_insn *insn;
+ const struct bpf_insn *insn;
int i;
int n = p->bf_len;
diff --git a/contrib/libpcap/bpf_image.c b/contrib/libpcap/bpf_image.c
index 2e76128..265cb7d 100644
--- a/contrib/libpcap/bpf_image.c
+++ b/contrib/libpcap/bpf_image.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/bpf_image.c,v 1.26.2.1 2007/06/11 09:52:04 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/bpf_image.c,v 1.27.2.1 2008/01/02 04:22:16 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/libpcap/chmod_bpf b/contrib/libpcap/chmod_bpf
new file mode 100755
index 0000000..0a30d99
--- /dev/null
+++ b/contrib/libpcap/chmod_bpf
@@ -0,0 +1,19 @@
+#! /bin/sh
+
+#
+# Unfortunately, Mac OS X's devfs is based on the old FreeBSD
+# one, not the current one, so there's no way to configure it
+# to create BPF devices with particular owners or groups.
+# This startup item will make it owned by the admin group,
+# with permissions rw-rw----, so that anybody in the admin
+# group can use programs that capture or send raw packets.
+#
+# Change this as appropriate for your site, e.g. to make
+# it owned by a particular user without changing the permissions,
+# so only that user and the super-user can capture or send raw
+# packets, or give it the permissions rw-r-----, so that
+# only the super-user can send raw packets but anybody in the
+# admin group can capture packets.
+#
+chgrp admin /dev/bpf*
+chmod g+rw /dev/bpf*
diff --git a/contrib/libpcap/config.h.in b/contrib/libpcap/config.h.in
index 8aa879c..403cbfa 100644
--- a/contrib/libpcap/config.h.in
+++ b/contrib/libpcap/config.h.in
@@ -19,6 +19,9 @@
/* define if you have dag_get_erf_types() */
#undef HAVE_DAG_GET_ERF_TYPES
+/* define if you have dag_get_stream_erf_types() */
+#undef HAVE_DAG_GET_STREAM_ERF_TYPES
+
/* define if you have streams capable DAG API */
#undef HAVE_DAG_STREAMS_API
@@ -29,9 +32,15 @@
/* define if you have a /dev/dlpi */
#undef HAVE_DEV_DLPI
+/* if passive_req_t primitive exists */
+#undef HAVE_DLPI_PASSIVE
+
/* Define to 1 if you have the `ether_hostton' function. */
#undef HAVE_ETHER_HOSTTON
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#undef HAVE_FSEEKO
+
/* on HP-UX 10.20 or later */
#undef HAVE_HPUX10_20_OR_LATER
@@ -44,9 +53,18 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
+/* if libdlpi exists */
+#undef HAVE_LIBDLPI
+
/* Define to 1 if you have the <limits.h> header file. */
#undef HAVE_LIMITS_H
+/* if tp_vlan_tci exists */
+#undef HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
+
+/* Define to 1 if you have the <linux/wireless.h> header file. */
+#undef HAVE_LINUX_WIRELESS_H
+
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
@@ -56,6 +74,9 @@
/* Define to 1 if you have the <netinet/if_ether.h> header file. */
#undef HAVE_NETINET_IF_ETHER_H
+/* Define to 1 if you have the <net/if_media.h> header file. */
+#undef HAVE_NET_IF_MEDIA_H
+
/* Define to 1 if you have the <net/pfvar.h> header file. */
#undef HAVE_NET_PFVAR_H
@@ -65,6 +86,9 @@
/* Define to 1 if you have the <paths.h> header file. */
#undef HAVE_PATHS_H
+/* define if net/pfvar.h defines PF_NAT through PF_NORDR */
+#undef HAVE_PF_NAT_THROUGH_PF_NORDR
+
/* define if you have a /proc/net/dev */
#undef HAVE_PROC_NET_DEV
@@ -80,6 +104,9 @@
/* if struct sockaddr_storage exists */
#undef HAVE_SOCKADDR_STORAGE
+/* define if socklen_t is defined */
+#undef HAVE_SOCKLEN_T
+
/* On solaris */
#undef HAVE_SOLARIS
@@ -134,6 +161,9 @@
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
+/* define if the system supports zerocopy BPF */
+#undef HAVE_ZEROCOPY_BPF
+
/* define if your compiler has __attribute__ */
#undef HAVE___ATTRIBUTE__
@@ -143,6 +173,9 @@
/* if unaligned access fails */
#undef LBL_ALIGN
+/* path for device for USB sniffing */
+#undef LINUX_USB_MON_DEV
+
/* Define to 1 if netinet/ether.h declares `ether_hostton' */
#undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
@@ -170,15 +203,33 @@
/* /dev/dlpi directory */
#undef PCAP_DEV_PREFIX
+/* target host supports Bluetooth sniffing */
+#undef PCAP_SUPPORT_BT
+
+/* target host supports USB sniffing */
+#undef PCAP_SUPPORT_USB
+
+/* include ACN support */
+#undef SITA
+
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Enable parser debugging */
#undef YYDEBUG
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
/* needed on HP-UX */
#undef _HPUX_SOURCE
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#undef _LARGEFILE_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
/* define on AIX to get certain functions */
#undef _SUN
@@ -194,5 +245,8 @@
/* if we have u_int32_t */
#undef u_int32_t
+/* if we have u_int64_t */
+#undef u_int64_t
+
/* if we have u_int8_t */
#undef u_int8_t
diff --git a/contrib/libpcap/configure b/contrib/libpcap/configure
index 38e035e..bd8da0b 100755
--- a/contrib/libpcap/configure
+++ b/contrib/libpcap/configure
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.in Revision: 1.120.2.13 .
+# From configure.in Revision: 1.138.2.22 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.61.
#
@@ -684,10 +684,16 @@ V_INCLS
V_LIBS
V_PCAP
V_FINDALLDEVS
-V_RANLIB
SSRC
DYEXT
DAGLIBS
+DEPLIBS
+MAN_FILE_FORMATS
+MAN_MISC_INFO
+PCAP_SUPPORT_USB
+USB_SRC
+PCAP_SUPPORT_BT
+BT_SRC
INSTALL_PROGRAM
INSTALL_SCRIPT
INSTALL_DATA
@@ -1275,8 +1281,9 @@ if test -n "$ac_init_help"; then
Optional Features:
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-largefile omit support for large files
--disable-protochain disable \"protochain\" insn
- --enable-ipv6 build IPv6-capable version
+ --enable-ipv6 build IPv6-capable version [default=yes, if getaddrinfo available]
--enable-optimizer-dbg build optimizer debugging code
--enable-yydebug build parser debugging code
@@ -1284,6 +1291,7 @@ Optional Packages:
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
--without-gcc don't use gcc
+ --with-sita include SITA support
--with-pcap=TYPE use packet capture TYPE
--with-dag[=DIR] include Endace DAG support ("yes", "no" or DIR; default="yes" on BSD and Linux if present)
--with-dag-includes=DIR Endace DAG include directory
@@ -1902,7 +1910,7 @@ fi
LBL_CFLAGS="$CFLAGS"
fi
if test -z "$CC" ; then
- case "$target_os" in
+ case "$host_os" in
bsdi*)
# Extract the first word of "shlicc2", so it can be a program name with args.
@@ -2949,7 +2957,7 @@ fi
{ echo "$as_me:$LINENO: result: $ac_cv_lbl_cc_ansi_prototypes" >&5
echo "${ECHO_T}$ac_cv_lbl_cc_ansi_prototypes" >&6; }
if test $ac_cv_lbl_cc_ansi_prototypes = no ; then
- case "$target_os" in
+ case "$host_os" in
hpux*)
{ echo "$as_me:$LINENO: checking for HP-UX ansi compiler ($CC -Aa -D_HPUX_SOURCE)" >&5
@@ -3028,7 +3036,7 @@ echo "$as_me: error: see the INSTALL doc for more info" >&2;}
V_INCLS="$V_INCLS -I/usr/local/include"
LDFLAGS="$LDFLAGS -L/usr/local/lib"
- case "$target_os" in
+ case "$host_os" in
irix*)
V_CCOPT="$V_CCOPT -xansi -signed -g3"
@@ -3450,6 +3458,543 @@ cat >>confdefs.h <<\_ACEOF
_ACEOF
fi
+{ echo "$as_me:$LINENO: checking for u_int64_t using $CC" >&5
+echo $ECHO_N "checking for u_int64_t using $CC... $ECHO_C" >&6; }
+ if test "${ac_cv_lbl_have_u_int64_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+# include "confdefs.h"
+# include <sys/types.h>
+# if STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+# endif
+int
+main ()
+{
+u_int64_t i
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_lbl_have_u_int64_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lbl_have_u_int64_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { echo "$as_me:$LINENO: result: $ac_cv_lbl_have_u_int64_t" >&5
+echo "${ECHO_T}$ac_cv_lbl_have_u_int64_t" >&6; }
+ if test $ac_cv_lbl_have_u_int64_t = no ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define u_int64_t unsigned long long
+_ACEOF
+
+ fi
+
+#
+# Try to arrange for large file support.
+#
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then
+ enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+ { echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5
+echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_largefile_CC+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_sys_largefile_CC=no
+ if test "$GCC" != yes; then
+ ac_save_CC=$CC
+ while :; do
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ CC="$CC -n32"
+ rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sys_largefile_CC=' -n32'; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+ break
+ done
+ CC=$ac_save_CC
+ rm -f conftest.$ac_ext
+ fi
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6; }
+ if test "$ac_cv_sys_largefile_CC" != no; then
+ CC=$CC$ac_cv_sys_largefile_CC
+ fi
+
+ { echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_file_offset_bits+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sys_file_offset_bits=no; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sys_file_offset_bits=64; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_file_offset_bits=unknown
+ break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5
+echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -f conftest*
+ if test $ac_cv_sys_file_offset_bits = unknown; then
+ { echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5
+echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_large_files+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sys_large_files=no; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sys_large_files=1; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_large_files=unknown
+ break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5
+echo "${ECHO_T}$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -f conftest*
+ fi
+fi
+
+{ echo "$as_me:$LINENO: checking for _LARGEFILE_SOURCE value needed for large files" >&5
+echo $ECHO_N "checking for _LARGEFILE_SOURCE value needed for large files... $ECHO_C" >&6; }
+if test "${ac_cv_sys_largefile_source+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ while :; do
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_sys_largefile_source=no; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#define _LARGEFILE_SOURCE 1
+#include <stdio.h>
+int
+main ()
+{
+return fseeko (stdin, 0, 0) && (fseeko) (stdin, 0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_sys_largefile_source=1; break
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_cv_sys_largefile_source=unknown
+ break
+done
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_source" >&5
+echo "${ECHO_T}$ac_cv_sys_largefile_source" >&6; }
+case $ac_cv_sys_largefile_source in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source
+_ACEOF
+;;
+esac
+rm -f conftest*
+
+# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
+# in glibc 2.1.3, but that breaks too many other things.
+# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
+if test $ac_cv_sys_largefile_source != unknown; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_FSEEKO 1
+_ACEOF
+
+fi
+
ac_ext=c
ac_cpp='$CPP $CPPFLAGS'
@@ -4290,6 +4835,66 @@ fi
done
+if test "$ac_cv_header_net_pfvar_h" = yes; then
+ #
+ # Check for various PF actions.
+ #
+ { echo "$as_me:$LINENO: checking whether net/pfvar.h defines PF_NAT through PF_NORDR" >&5
+echo $ECHO_N "checking whether net/pfvar.h defines PF_NAT through PF_NORDR... $ECHO_C" >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/socket.h>
+ #include <net/if.h>
+ #include <net/pfvar.h>
+int
+main ()
+{
+return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_PF_NAT_THROUGH_PF_NORDR 1
+_ACEOF
+
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
for ac_header in netinet/if_ether.h
do
@@ -5622,6 +6227,26 @@ fi
{ echo "$as_me:$LINENO: result: ${enable_protochain}" >&5
echo "${ECHO_T}${enable_protochain}" >&6; }
+#
+# SITA support is mutually exclusive with native capture support;
+# "--with-sita" selects SITA support.
+#
+
+# Check whether --with-sita was given.
+if test "${with_sita+set}" = set; then
+ withval=$with_sita;
+
+cat >>confdefs.h <<\_ACEOF
+#define SITA 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: Enabling SITA ACN support" >&5
+echo "$as_me: Enabling SITA ACN support" >&6;}
+ V_PCAP=sita
+ V_FINDALLDEVS=sita
+
+else
+
if test -z "$with_pcap" && test "$cross_compiling" = yes; then
{ { echo "$as_me:$LINENO: error: pcap type not determined when cross-compiling; use --with-pcap=..." >&5
echo "$as_me: error: pcap type not determined when cross-compiling; use --with-pcap=..." >&2;}
@@ -5682,6 +6307,829 @@ fi
{ echo "$as_me:$LINENO: result: $V_PCAP" >&5
echo "${ECHO_T}$V_PCAP" >&6; }
+#
+# Do capture-mechanism-dependent tests.
+#
+case "$V_PCAP" in
+dlpi)
+ #
+ # Checks to see if Solaris has the public libdlpi(3LIB) library.
+ # Note: The existence of /usr/include/libdlpi.h does not mean it is the
+ # public libdlpi(3LIB) version. Before libdlpi was made public, a
+ # private version also existed, which did not have the same APIs.
+ # Due to a gcc bug, the default search path for 32-bit libraries does
+ # not include /lib, we add it explicitly here.
+ # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485].
+ # Also, due to the bug above applications that link to libpcap with
+ # libdlpi will have to add "-L/lib" option to "configure".
+ #
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="$LIBS -L/lib"
+ { echo "$as_me:$LINENO: checking for dlpi_walk in -ldlpi" >&5
+echo $ECHO_N "checking for dlpi_walk in -ldlpi... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dlpi_dlpi_walk+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldlpi $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlpi_walk ();
+int
+main ()
+{
+return dlpi_walk ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dlpi_dlpi_walk=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dlpi_dlpi_walk=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dlpi_dlpi_walk" >&5
+echo "${ECHO_T}$ac_cv_lib_dlpi_dlpi_walk" >&6; }
+if test $ac_cv_lib_dlpi_dlpi_walk = yes; then
+ LIBS="-ldlpi $LIBS"
+ V_PCAP=libdlpi
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LIBDLPI 1
+_ACEOF
+
+else
+ V_PCAP=dlpi
+fi
+
+ LDFLAGS=$saved_ldflags
+
+ #
+ # Checks whether <sys/dlpi.h> is usable, to catch weird SCO
+ # versions of DLPI.
+ #
+ { echo "$as_me:$LINENO: checking whether <sys/dlpi.h> is usable" >&5
+echo $ECHO_N "checking whether <sys/dlpi.h> is usable... $ECHO_C" >&6; }
+ if test "${ac_cv_sys_dlpi_usable+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <sys/dlpi.h>
+
+int
+main ()
+{
+int i = DL_PROMISC_PHYS;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_sys_dlpi_usable=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_sys_dlpi_usable=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { echo "$as_me:$LINENO: result: $ac_cv_sys_dlpi_usable" >&5
+echo "${ECHO_T}$ac_cv_sys_dlpi_usable" >&6; }
+ if test $ac_cv_sys_dlpi_usable = no ; then
+ { { echo "$as_me:$LINENO: error: <sys/dlpi.h> is not usable on this system; it probably has a non-standard DLPI" >&5
+echo "$as_me: error: <sys/dlpi.h> is not usable on this system; it probably has a non-standard DLPI" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+ #
+ # Check whether we have a /dev/dlpi device or have multiple devices.
+ #
+ { echo "$as_me:$LINENO: checking for /dev/dlpi device" >&5
+echo $ECHO_N "checking for /dev/dlpi device... $ECHO_C" >&6; }
+ if test -c /dev/dlpi ; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DEV_DLPI 1
+_ACEOF
+
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ dir="/dev/dlpi"
+ { echo "$as_me:$LINENO: checking for $dir directory" >&5
+echo $ECHO_N "checking for $dir directory... $ECHO_C" >&6; }
+ if test -d $dir ; then
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define PCAP_DEV_PREFIX "$dir"
+_ACEOF
+
+ else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ fi
+ fi
+
+ #
+ # This check is for Solaris with DLPI support for passive modes.
+ # See dlpi(7P) for more details.
+ #
+ { echo "$as_me:$LINENO: checking if dl_passive_req_t struct exists" >&5
+echo $ECHO_N "checking if dl_passive_req_t struct exists... $ECHO_C" >&6; }
+ if test "${ac_cv_lbl_has_dl_passive_req_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+# include <sys/types.h>
+# include <sys/dlpi.h>
+int
+main ()
+{
+u_int i = sizeof(dl_passive_req_t)
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_lbl_has_dl_passive_req_t=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lbl_has_dl_passive_req_t=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { echo "$as_me:$LINENO: result: $ac_cv_lbl_has_dl_passive_req_t" >&5
+echo "${ECHO_T}$ac_cv_lbl_has_dl_passive_req_t" >&6; }
+ if test $ac_cv_lbl_has_dl_passive_req_t = yes ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DLPI_PASSIVE 1
+_ACEOF
+
+ fi
+ ;;
+
+linux)
+ { echo "$as_me:$LINENO: checking Linux kernel version" >&5
+echo $ECHO_N "checking Linux kernel version... $ECHO_C" >&6; }
+ if test "$cross_compiling" = yes; then
+ if test "${ac_cv_linux_vers+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_linux_vers=unknown
+fi
+
+ else
+ if test "${ac_cv_linux_vers+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_linux_vers=`uname -r 2>&1 | \
+ sed -n -e '$s/.* //' -e '$s/\..*//p'`
+fi
+
+ fi
+ { echo "$as_me:$LINENO: result: $ac_cv_linux_vers" >&5
+echo "${ECHO_T}$ac_cv_linux_vers" >&6; }
+ if test $ac_cv_linux_vers = unknown ; then
+ { { echo "$as_me:$LINENO: error: cannot determine linux version when cross-compiling" >&5
+echo "$as_me: error: cannot determine linux version when cross-compiling" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ if test $ac_cv_linux_vers -lt 2 ; then
+ { { echo "$as_me:$LINENO: error: version 2 or higher required; see the INSTALL doc for more info" >&5
+echo "$as_me: error: version 2 or higher required; see the INSTALL doc for more info" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+for ac_header in linux/wireless.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <sys/socket.h>
+#include <net/if.h>
+#include <linux/types.h>
+
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ eval "$as_ac_Header=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ for ac_header in
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ { echo "$as_me:$LINENO: checking if if_packet.h has tpacket_stats defined" >&5
+echo $ECHO_N "checking if if_packet.h has tpacket_stats defined... $ECHO_C" >&6; }
+ if test "${ac_cv_lbl_tpacket_stats+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+# include <linux/if_packet.h>
+int
+main ()
+{
+struct tpacket_stats stats
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_lbl_tpacket_stats=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lbl_tpacket_stats=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { echo "$as_me:$LINENO: result: $ac_cv_lbl_tpacket_stats" >&5
+echo "${ECHO_T}$ac_cv_lbl_tpacket_stats" >&6; }
+ if test $ac_cv_lbl_tpacket_stats = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_TPACKET_STATS 1
+_ACEOF
+
+ fi
+ { echo "$as_me:$LINENO: checking if tpacket_auxdata struct has tp_vlan_tci member" >&5
+echo $ECHO_N "checking if tpacket_auxdata struct has tp_vlan_tci member... $ECHO_C" >&6; }
+ if test "${ac_cv_lbl_dl_hp_ppa_info_t_has_dl_module_id_1+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+# include <linux/if_packet.h>
+int
+main ()
+{
+u_int i = sizeof(((struct tpacket_auxdata *)0)->tp_vlan_tci)
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { echo "$as_me:$LINENO: result: $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci" >&5
+echo "${ECHO_T}$ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci" >&6; }
+ if test $ac_cv_lbl_linux_tpacket_auxdata_tp_vlan_tci = yes ; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI 1
+_ACEOF
+
+ fi
+ ;;
+
+bpf)
+ #
+ # Check whether we have the *BSD-style ioctls.
+ #
+
+for ac_header in net/if_media.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ { echo "$as_me:$LINENO: checking whether the system supports zerocopy BPF" >&5
+echo $ECHO_N "checking whether the system supports zerocopy BPF... $ECHO_C" >&6; }
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/socket.h>
+ #include <sys/ioctl.h>
+ #include <net/if.h>
+ #include <net/bpf.h>
+int
+main ()
+{
+return (BIOCROTZBUF + BPF_BUFMODE_ZBUF);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ZEROCOPY_BPF 1
+_ACEOF
+
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ;;
+
+dag)
+ V_DEFS="$V_DEFS -DDAG_ONLY"
+ ;;
+
+septel)
+ V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+ ;;
+
+null)
+ { echo "$as_me:$LINENO: WARNING: cannot determine packet capture interface" >&5
+echo "$as_me: WARNING: cannot determine packet capture interface" >&2;}
+ { echo "$as_me:$LINENO: WARNING: (see the INSTALL doc for more info)" >&5
+echo "$as_me: WARNING: (see the INSTALL doc for more info)" >&2;}
+ ;;
+esac
+
if test "$V_PCAP" = null
then
#
@@ -5940,142 +7388,7 @@ else
#
case "$V_PCAP" in
- dlpi)
- #
- # This might be Solaris 8 or later, with
- # SIOCGLIFCONF, or it might be some other OS
- # or some older version of Solaris, with
- # just SIOCGIFCONF.
- #
- { echo "$as_me:$LINENO: checking whether we have SIOCGLIFCONF" >&5
-echo $ECHO_N "checking whether we have SIOCGLIFCONF... $ECHO_C" >&6; }
- if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
-else
- cat >conftest.$ac_ext <<_ACEOF
-/* confdefs.h. */
-_ACEOF
-cat confdefs.h >>conftest.$ac_ext
-cat >>conftest.$ac_ext <<_ACEOF
-/* end confdefs.h. */
-#include <sys/param.h>
- #include <sys/file.h>
- #include <sys/ioctl.h>
- #include <sys/socket.h>
- #include <sys/sockio.h>
-int
-main ()
-{
-ioctl(0, SIOCGLIFCONF, (char *)0);
- ;
- return 0;
-}
-_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
-case "(($ac_try" in
- *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
- *) ac_try_echo=$ac_try;;
-esac
-eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
- ac_status=$?
- grep -v '^ *+' conftest.er1 >conftest.err
- rm -f conftest.er1
- cat conftest.err >&5
- echo "$as_me:$LINENO: \$? = $ac_status" >&5
- (exit $ac_status); } && {
- test -z "$ac_c_werror_flag" ||
- test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_lbl_have_siocglifconf=yes
-else
- echo "$as_me: failed program was:" >&5
-sed 's/^/| /' conftest.$ac_ext >&5
-
- ac_cv_lbl_have_siocglifconf=no
-fi
-
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-
- { echo "$as_me:$LINENO: result: $ac_cv_lbl_have_siocglifconf" >&5
-echo "${ECHO_T}$ac_cv_lbl_have_siocglifconf" >&6; }
- if test $ac_cv_lbl_have_siocglifconf = yes ; then
- V_FINDALLDEVS=glifc
- else
- V_FINDALLDEVS=gifc
- fi
- ;;
-
- *)
- #
- # Assume we just have SIOCGIFCONF.
- # (XXX - on at least later Linux kernels, there's
- # another mechanism, and we should be using that
- # instead.)
- #
- V_FINDALLDEVS=gifc
- ;;
- esac
-fi
-
-fi
-
-{ echo "$as_me:$LINENO: checking if --enable-ipv6 option is specified" >&5
-echo $ECHO_N "checking if --enable-ipv6 option is specified... $ECHO_C" >&6; }
-# Check whether --enable-ipv6 was given.
-if test "${enable_ipv6+set}" = set; then
- enableval=$enable_ipv6;
-fi
-
-if test "$enable_ipv6" = "yes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define INET6 1
-_ACEOF
-
-fi
-{ echo "$as_me:$LINENO: result: ${enable_ipv6-no}" >&5
-echo "${ECHO_T}${enable_ipv6-no}" >&6; }
-
-{ echo "$as_me:$LINENO: checking whether to build optimizer debugging code" >&5
-echo $ECHO_N "checking whether to build optimizer debugging code... $ECHO_C" >&6; }
-# Check whether --enable-optimizer-dbg was given.
-if test "${enable_optimizer_dbg+set}" = set; then
- enableval=$enable_optimizer_dbg;
-fi
-
-if test "$enable_optimizer_dbg" = "yes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define BDEBUG 1
-_ACEOF
-
-fi
-{ echo "$as_me:$LINENO: result: ${enable_optimizer_dbg-no}" >&5
-echo "${ECHO_T}${enable_optimizer_dbg-no}" >&6; }
-
-{ echo "$as_me:$LINENO: checking whether to build parser debugging code" >&5
-echo $ECHO_N "checking whether to build parser debugging code... $ECHO_C" >&6; }
-# Check whether --enable-yydebug was given.
-if test "${enable_yydebug+set}" = set; then
- enableval=$enable_yydebug;
-fi
-
-if test "$enable_yydebug" = "yes"; then
-
-cat >>confdefs.h <<\_ACEOF
-#define YYDEBUG 1
-_ACEOF
-
-fi
-{ echo "$as_me:$LINENO: result: ${enable_yydebug-no}" >&5
-echo "${ECHO_T}${enable_yydebug-no}" >&6; }
-
-case "$V_PCAP" in
-
-dlpi)
+ dlpi|libdlpi)
for ac_header in sys/bufmod.h sys/dlpi_ext.h
@@ -6217,71 +7530,161 @@ fi
done
- { echo "$as_me:$LINENO: checking for /dev/dlpi device" >&5
-echo $ECHO_N "checking for /dev/dlpi device... $ECHO_C" >&6; }
- if test -c /dev/dlpi ; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
-
-cat >>confdefs.h <<\_ACEOF
-#define HAVE_DEV_DLPI 1
+ #
+ # This might be Solaris 8 or later, with
+ # SIOCGLIFCONF, or it might be some other OS
+ # or some older version of Solaris, with
+ # just SIOCGIFCONF.
+ #
+ { echo "$as_me:$LINENO: checking whether we have SIOCGLIFCONF" >&5
+echo $ECHO_N "checking whether we have SIOCGLIFCONF... $ECHO_C" >&6; }
+ if test "${ac_cv_lbl_have_siocglifconf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <sys/param.h>
+ #include <sys/file.h>
+ #include <sys/ioctl.h>
+ #include <sys/socket.h>
+ #include <sys/sockio.h>
+int
+main ()
+{
+ioctl(0, SIOCGLIFCONF, (char *)0);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_cv_lbl_have_siocglifconf=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- dir="/dev/dlpi"
- { echo "$as_me:$LINENO: checking for $dir directory" >&5
-echo $ECHO_N "checking for $dir directory... $ECHO_C" >&6; }
- if test -d $dir ; then
- { echo "$as_me:$LINENO: result: yes" >&5
-echo "${ECHO_T}yes" >&6; }
+ ac_cv_lbl_have_siocglifconf=no
+fi
-cat >>confdefs.h <<_ACEOF
-#define PCAP_DEV_PREFIX "$dir"
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { echo "$as_me:$LINENO: result: $ac_cv_lbl_have_siocglifconf" >&5
+echo "${ECHO_T}$ac_cv_lbl_have_siocglifconf" >&6; }
+ if test $ac_cv_lbl_have_siocglifconf = yes ; then
+ V_FINDALLDEVS=glifc
+ else
+ V_FINDALLDEVS=gifc
+ fi
+ #
+ # Needed for common functions used by pcap-[dlpi,libdlpi].c
+ #
+ SSRC="dlpisubs.c"
+ ;;
+
+ *)
+ #
+ # Assume we just have SIOCGIFCONF.
+ # (XXX - on at least later Linux kernels, there's
+ # another mechanism, and we should be using that
+ # instead.)
+ #
+ V_FINDALLDEVS=gifc
+ ;;
+ esac
+fi
+
+fi
+
+fi
+
+
+{ echo "$as_me:$LINENO: checking for socklen_t" >&5
+echo $ECHO_N "checking for socklen_t... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
- else
- { echo "$as_me:$LINENO: result: no" >&5
-echo "${ECHO_T}no" >&6; }
- fi
- fi
- ;;
+ #include <sys/types.h>
+ #include <sys/socket.h>
-linux)
- { echo "$as_me:$LINENO: checking Linux kernel version" >&5
-echo $ECHO_N "checking Linux kernel version... $ECHO_C" >&6; }
- if test "$cross_compiling" = yes; then
- if test "${ac_cv_linux_vers+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+int
+main ()
+{
+ socklen_t x;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ have_socklen_t=yes
else
- ac_cv_linux_vers=unknown
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ have_socklen_t=no
fi
- else
- if test "${ac_cv_linux_vers+set}" = set; then
- echo $ECHO_N "(cached) $ECHO_C" >&6
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+if test "x$have_socklen_t" = "xyes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_SOCKLEN_T 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: $have_socklen_t" >&5
+echo "${ECHO_T}$have_socklen_t" >&6; }
+
+# Check whether --enable-ipv6 was given.
+if test "${enable_ipv6+set}" = set; then
+ enableval=$enable_ipv6;
else
- ac_cv_linux_vers=`uname -r 2>&1 | \
- sed -n -e '$s/.* //' -e '$s/\..*//p'`
+ enable_ipv6=ifavailable
fi
- fi
- { echo "$as_me:$LINENO: result: $ac_cv_linux_vers" >&5
-echo "${ECHO_T}$ac_cv_linux_vers" >&6; }
- if test $ac_cv_linux_vers = unknown ; then
- { { echo "$as_me:$LINENO: error: cannot determine linux version when cross-compiling" >&5
-echo "$as_me: error: cannot determine linux version when cross-compiling" >&2;}
- { (exit 1); exit 1; }; }
- fi
- if test $ac_cv_linux_vers -lt 2 ; then
- { { echo "$as_me:$LINENO: error: version 2 or higher required; see the INSTALL doc for more info" >&5
-echo "$as_me: error: version 2 or higher required; see the INSTALL doc for more info" >&2;}
- { (exit 1); exit 1; }; }
- fi
- { echo "$as_me:$LINENO: checking if if_packet.h has tpacket_stats defined" >&5
-echo $ECHO_N "checking if if_packet.h has tpacket_stats defined... $ECHO_C" >&6; }
- if test "${ac_cv_lbl_tpacket_stats+set}" = set; then
+if test "$enable_ipv6" != "no"; then
+ { echo "$as_me:$LINENO: checking for getaddrinfo" >&5
+echo $ECHO_N "checking for getaddrinfo... $ECHO_C" >&6; }
+if test "${ac_cv_func_getaddrinfo+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
cat >conftest.$ac_ext <<_ACEOF
@@ -6290,24 +7693,53 @@ _ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
+/* Define getaddrinfo to an innocuous variant, in case <limits.h> declares getaddrinfo.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define getaddrinfo innocuous_getaddrinfo
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char getaddrinfo (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef getaddrinfo
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getaddrinfo ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_getaddrinfo || defined __stub___getaddrinfo
+choke me
+#endif
-# include <linux/if_packet.h>
int
main ()
{
-struct tpacket_stats stats
+return getaddrinfo ();
;
return 0;
}
_ACEOF
-rm -f conftest.$ac_objext
-if { (ac_try="$ac_compile"
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
- (eval "$ac_compile") 2>conftest.er1
+ (eval "$ac_link") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
@@ -6316,45 +7748,76 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
- } && test -s conftest.$ac_objext; then
- ac_cv_lbl_tpacket_stats=yes
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_func_getaddrinfo=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
- ac_cv_lbl_tpacket_stats=no
+ ac_cv_func_getaddrinfo=no
fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
fi
+{ echo "$as_me:$LINENO: result: $ac_cv_func_getaddrinfo" >&5
+echo "${ECHO_T}$ac_cv_func_getaddrinfo" >&6; }
+if test $ac_cv_func_getaddrinfo = yes; then
- { echo "$as_me:$LINENO: result: $ac_cv_lbl_tpacket_stats" >&5
-echo "${ECHO_T}$ac_cv_lbl_tpacket_stats" >&6; }
- if test $ac_cv_lbl_tpacket_stats = yes; then
cat >>confdefs.h <<\_ACEOF
-#define HAVE_TPACKET_STATS 1
+#define INET6 1
_ACEOF
- fi
- ;;
-dag)
- V_DEFS="$V_DEFS -DDAG_ONLY"
- ;;
+else
-septel)
- V_DEFS="$V_DEFS -DSEPTEL_ONLY"
- ;;
+ if test "$enable_ipv6" != "ifavailable"; then
+ { { echo "$as_me:$LINENO: error: --enable-ipv6 was given, but getaddrinfo isn't available
+See \`config.log' for more details." >&5
+echo "$as_me: error: --enable-ipv6 was given, but getaddrinfo isn't available
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
-null)
- { echo "$as_me:$LINENO: WARNING: cannot determine packet capture interface" >&5
-echo "$as_me: WARNING: cannot determine packet capture interface" >&2;}
- { echo "$as_me:$LINENO: WARNING: (see the INSTALL doc for more info)" >&5
-echo "$as_me: WARNING: (see the INSTALL doc for more info)" >&2;}
- ;;
+fi
-esac
+fi
+
+{ echo "$as_me:$LINENO: checking whether to build optimizer debugging code" >&5
+echo $ECHO_N "checking whether to build optimizer debugging code... $ECHO_C" >&6; }
+# Check whether --enable-optimizer-dbg was given.
+if test "${enable_optimizer_dbg+set}" = set; then
+ enableval=$enable_optimizer_dbg;
+fi
+
+if test "$enable_optimizer_dbg" = "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define BDEBUG 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: ${enable_optimizer_dbg-no}" >&5
+echo "${ECHO_T}${enable_optimizer_dbg-no}" >&6; }
+
+{ echo "$as_me:$LINENO: checking whether to build parser debugging code" >&5
+echo $ECHO_N "checking whether to build parser debugging code... $ECHO_C" >&6; }
+# Check whether --enable-yydebug was given.
+if test "${enable_yydebug+set}" = set; then
+ enableval=$enable_yydebug;
+fi
+
+if test "$enable_yydebug" = "yes"; then
+
+cat >>confdefs.h <<\_ACEOF
+#define YYDEBUG 1
+_ACEOF
+
+fi
+{ echo "$as_me:$LINENO: result: ${enable_yydebug-no}" >&5
+echo "${ECHO_T}${enable_yydebug-no}" >&6; }
{ echo "$as_me:$LINENO: checking whether we have /proc/net/dev" >&5
echo $ECHO_N "checking whether we have /proc/net/dev... $ECHO_C" >&6; }
@@ -6491,11 +7954,11 @@ echo $ECHO_N "checking dagapi.o... $ECHO_C" >&6; }
dagapi_obj=$dag_lib_dir/dagapi.o
elif test -r $dag_lib_dir/libdag.a; then
# 2.5.x.
- ar x $dag_lib_dir/libdag.a dagapi.o
+ ar x $dag_lib_dir/libdag.a dagapi.o 2>/dev/null
if test -r ./dagapi.o; then
dagapi_obj=./dagapi.o
else
- ar x $dag_lib_dir/libdag.a libdag_la-dagapi.o
+ ar x $dag_lib_dir/libdag.a libdag_la-dagapi.o 2>/dev/null
if test -r ./libdag_la-dagapi.o; then
dagapi_obj=./libdag_la-dagapi.o
fi
@@ -6525,11 +7988,11 @@ echo $ECHO_N "checking dagopts.o... $ECHO_C" >&6; }
dagopts_obj=$dag_lib_dir/dagopts.o
elif test -r $dag_lib_dir/libdag.a; then
# 2.5.x.
- ar x $dag_lib_dir/libdag.a dagopts.o
+ ar x $dag_lib_dir/libdag.a dagopts.o 2>/dev/null
if test -r ./dagopts.o; then
dagopts_obj=./dagopts.o
else
- ar x $dag_lib_dir/libdag.a libdag_la-dagopts.o
+ ar x $dag_lib_dir/libdag.a libdag_la-dagopts.o 2>/dev/null
if test -r ./libdag_la-dagopts.o; then
dagopts_obj=./libdag_la-dagopts.o
fi
@@ -6557,11 +8020,11 @@ echo $ECHO_N "checking dagreg.o... $ECHO_C" >&6; }
dagreg_obj=$dag_lib_dir/dagreg.o
elif test -r $dag_lib_dir/libdag.a; then
# Extract from libdag.a.
- ar x $dag_lib_dir/libdag.a dagreg.o
+ ar x $dag_lib_dir/libdag.a dagreg.o 2>/dev/null
if test -r ./dagreg.o; then
dagreg_obj=./dagreg.o
else
- ar x $dag_lib_dir/libdag.a libdag_la-dagreg.o
+ ar x $dag_lib_dir/libdag.a libdag_la-dagreg.o 2>/dev/null
if test -r ./libdag_la-dagreg.o; then
dagreg_obj=./libdag_la-dagreg.o
fi
@@ -6653,9 +8116,9 @@ fi
{ echo "$as_me:$LINENO: result: $ac_cv_lib_dag_dag_attach_stream" >&5
echo "${ECHO_T}$ac_cv_lib_dag_dag_attach_stream" >&6; }
if test $ac_cv_lib_dag_dag_attach_stream = yes; then
- dag_version="2.5.x"
+ dag_streams="1"
else
- dag_version="2.4.x"
+ dag_streams="0"
fi
{ echo "$as_me:$LINENO: checking for dag_get_erf_types in -ldag" >&5
@@ -6726,12 +8189,81 @@ cat >>confdefs.h <<\_ACEOF
#define HAVE_DAG_GET_ERF_TYPES 1
_ACEOF
+fi
+
+ { echo "$as_me:$LINENO: checking for dag_get_stream_erf_types in -ldag" >&5
+echo $ECHO_N "checking for dag_get_stream_erf_types in -ldag... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dag_dag_get_stream_erf_types+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldag $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dag_get_stream_erf_types ();
+int
+main ()
+{
+return dag_get_stream_erf_types ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dag_dag_get_stream_erf_types=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dag_dag_get_stream_erf_types=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dag_dag_get_stream_erf_types" >&5
+echo "${ECHO_T}$ac_cv_lib_dag_dag_get_stream_erf_types" >&6; }
+if test $ac_cv_lib_dag_dag_get_stream_erf_types = yes; then
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_DAG_GET_STREAM_ERF_TYPES 1
+_ACEOF
fi
LDFLAGS=$saved_ldflags
- if test "$dag_version" = 2.5.x; then
+ if test "$dag_streams" = 1; then
cat >>confdefs.h <<\_ACEOF
#define HAVE_DAG_STREAMS_API 1
@@ -6740,14 +8272,6 @@ _ACEOF
DAGLIBS="-ldag"
fi
- # See if we can find a specific version string.
- { echo "$as_me:$LINENO: checking the DAG API version" >&5
-echo $ECHO_N "checking the DAG API version... $ECHO_C" >&6; }
- if test -r "$dag_root/VERSION"; then
- dag_version="`cat $dag_root/VERSION`"
- fi
- { echo "$as_me:$LINENO: result: $dag_version" >&5
-echo "${ECHO_T}$dag_version" >&6; }
cat >>confdefs.h <<\_ACEOF
#define HAVE_DAG_API 1
@@ -6755,7 +8279,12 @@ _ACEOF
fi
+{ echo "$as_me:$LINENO: checking whether we have the DAG API" >&5
+echo $ECHO_N "checking whether we have the DAG API... $ECHO_C" >&6; }
+
if test $ac_cv_lbl_dag_api = no; then
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
if test "$want_dag" = yes; then
# User wanted DAG support but we couldn't find it.
{ { echo "$as_me:$LINENO: error: DAG API requested, but not found at $dag_root: use --without-dag" >&5
@@ -6770,6 +8299,9 @@ echo "$as_me: error: DAG API requested, but not found at $dag_root: use --withou
echo "$as_me: error: Specifying the capture type as \"dag\" requires the DAG API to be present; use the --with-dag options to specify the location. (Try \"./configure --help\" for more information.)" >&2;}
{ (exit 1); exit 1; }; }
fi
+else
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
fi
@@ -7044,7 +8576,14 @@ echo "$as_me: error: Your operating system's lex is insufficient to compile
fi
fi
+#
+# Assume a.out/ELF convention for shared library names (".so"), and
+# V7/BSD convention for man pages (file formats in section 5,
+# miscellaneous info in section 7).
+#
DYEXT="so"
+MAN_FILE_FORMATS=5
+MAN_MISC_INFO=7
case "$host_os" in
aix*)
@@ -7053,6 +8592,15 @@ cat >>confdefs.h <<\_ACEOF
#define _SUN 1
_ACEOF
+
+ # We need "-lodm" and "-lcfg", as libpcap requires them on
+ # AIX.
+ DEPLIBS="-lodm -lcfg"
+ ;;
+
+darwin*)
+ DYEXT="dylib"
+ V_CCOPT="$V_CCOPT -fno-common"
;;
hpux9*)
@@ -7061,12 +8609,30 @@ cat >>confdefs.h <<\_ACEOF
#define HAVE_HPUX9 1
_ACEOF
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
;;
hpux10.0*)
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
;;
hpux10.1*)
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
;;
hpux*)
@@ -7075,6 +8641,32 @@ cat >>confdefs.h <<\_ACEOF
#define HAVE_HPUX10_20_OR_LATER 1
_ACEOF
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+irix*)
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+linux*)
+ V_CCOPT="$V_CCOPT -fPIC"
+ ;;
+
+osf*)
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
;;
sinix*)
@@ -7143,17 +8735,13 @@ cat >>confdefs.h <<\_ACEOF
#define HAVE_SOLARIS 1
_ACEOF
- ;;
-darwin*)
- DYEXT="dylib"
- V_CCOPT="$V_CCOPT -fno-common"
- ;;
-
-linux*)
- V_CCOPT="$V_CCOPT -fPIC"
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
;;
-
esac
if test -n "$ac_tool_prefix"; then
@@ -7269,7 +8857,7 @@ rm -f os-proto.h
fi
fi
else
- case "$target_os" in
+ case "$host_os" in
irix6*)
V_CCOPT="$V_CCOPT -n32"
@@ -7279,7 +8867,7 @@ rm -f os-proto.h
;;
esac
fi
- os=`echo $target_os | sed -e 's/\([0-9][0-9]*\)[^0-9].*$/\1/'`
+ os=`echo $host_os | sed -e 's/\([0-9][0-9]*\)[^0-9].*$/\1/'`
name="lbl/os-$os.h"
if test -f $name ; then
ln -s $name os-proto.h
@@ -7514,7 +9102,7 @@ else
# know it does work, and have the script just fail on other
# cpu types and update it when such a failure occurs.
#
- alpha*|arm*|hp*|mips*|sh*|sparc*|ia64|nv1)
+ alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1)
ac_cv_lbl_unaligned_fail=yes
;;
@@ -7598,6 +9186,194 @@ ln -s ${srcdir}/bpf/net net
+
+
+{ echo "$as_me:$LINENO: checking for USB sniffing support" >&5
+echo $ECHO_N "checking for USB sniffing support... $ECHO_C" >&6; }
+case "$host_os" in
+linux*)
+
+cat >>confdefs.h <<\_ACEOF
+#define PCAP_SUPPORT_USB 1
+_ACEOF
+
+ USB_SRC=pcap-usb-linux.c
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
+ if test $? -ne 0 ; then
+ ac_usb_dev_name="usbmon"
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define LINUX_USB_MON_DEV "/dev/$ac_usb_dev_name"
+_ACEOF
+
+ { echo "$as_me:$LINENO: Device for USB sniffing is /dev/$ac_usb_dev_name" >&5
+echo "$as_me: Device for USB sniffing is /dev/$ac_usb_dev_name" >&6;}
+ ;;
+*)
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ ;;
+esac
+
+
+
+case "$host_os" in
+linux*)
+ if test "${ac_cv_header_bluetooth_bluetooth_h+set}" = set; then
+ { echo "$as_me:$LINENO: checking for bluetooth/bluetooth.h" >&5
+echo $ECHO_N "checking for bluetooth/bluetooth.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_bluetooth_bluetooth_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_bluetooth_bluetooth_h" >&5
+echo "${ECHO_T}$ac_cv_header_bluetooth_bluetooth_h" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking bluetooth/bluetooth.h usability" >&5
+echo $ECHO_N "checking bluetooth/bluetooth.h usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <bluetooth/bluetooth.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking bluetooth/bluetooth.h presence" >&5
+echo $ECHO_N "checking bluetooth/bluetooth.h presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <bluetooth/bluetooth.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: bluetooth/bluetooth.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: bluetooth/bluetooth.h: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: bluetooth/bluetooth.h: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: bluetooth/bluetooth.h: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: bluetooth/bluetooth.h: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: bluetooth/bluetooth.h: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: bluetooth/bluetooth.h: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: bluetooth/bluetooth.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: bluetooth/bluetooth.h: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for bluetooth/bluetooth.h" >&5
+echo $ECHO_N "checking for bluetooth/bluetooth.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_bluetooth_bluetooth_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_header_bluetooth_bluetooth_h=$ac_header_preproc
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_bluetooth_bluetooth_h" >&5
+echo "${ECHO_T}$ac_cv_header_bluetooth_bluetooth_h" >&6; }
+
+fi
+if test $ac_cv_header_bluetooth_bluetooth_h = yes; then
+
+
+cat >>confdefs.h <<\_ACEOF
+#define PCAP_SUPPORT_BT 1
+_ACEOF
+
+ BT_SRC=pcap-bt-linux.c
+ { echo "$as_me:$LINENO: Bluetooth sniffing is supported" >&5
+echo "$as_me: Bluetooth sniffing is supported" >&6;}
+
+else
+ { echo "$as_me:$LINENO: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&5
+echo "$as_me: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&6;}
+
+fi
+
+
+ ;;
+*)
+ { echo "$as_me:$LINENO: no Bluetooth sniffing support" >&5
+echo "$as_me: no Bluetooth sniffing support" >&6;}
+ ;;
+esac
+
+
+
# Find a good install program. We prefer a C program (faster),
# so one script is as good as another. But avoid the broken or
# incompatible versions:
@@ -7682,7 +9458,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
ac_config_headers="$ac_config_headers config.h"
-ac_config_files="$ac_config_files Makefile"
+ac_config_files="$ac_config_files Makefile pcap-filter.manmisc pcap-linktype.manmisc pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap pcap_list_datalinks.3pcap pcap_open_dead.3pcap pcap_open_offline.3pcap"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -8239,6 +10015,16 @@ do
case $ac_config_target in
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "pcap-filter.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-filter.manmisc" ;;
+ "pcap-linktype.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-linktype.manmisc" ;;
+ "pcap-savefile.manfile") CONFIG_FILES="$CONFIG_FILES pcap-savefile.manfile" ;;
+ "pcap.3pcap") CONFIG_FILES="$CONFIG_FILES pcap.3pcap" ;;
+ "pcap_compile.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_compile.3pcap" ;;
+ "pcap_datalink.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_datalink.3pcap" ;;
+ "pcap_dump_open.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_dump_open.3pcap" ;;
+ "pcap_list_datalinks.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_list_datalinks.3pcap" ;;
+ "pcap_open_dead.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_dead.3pcap" ;;
+ "pcap_open_offline.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_offline.3pcap" ;;
*) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
@@ -8370,17 +10156,23 @@ V_INCLS!$V_INCLS$ac_delim
V_LIBS!$V_LIBS$ac_delim
V_PCAP!$V_PCAP$ac_delim
V_FINDALLDEVS!$V_FINDALLDEVS$ac_delim
-V_RANLIB!$V_RANLIB$ac_delim
SSRC!$SSRC$ac_delim
DYEXT!$DYEXT$ac_delim
DAGLIBS!$DAGLIBS$ac_delim
+DEPLIBS!$DEPLIBS$ac_delim
+MAN_FILE_FORMATS!$MAN_FILE_FORMATS$ac_delim
+MAN_MISC_INFO!$MAN_MISC_INFO$ac_delim
+PCAP_SUPPORT_USB!$PCAP_SUPPORT_USB$ac_delim
+USB_SRC!$USB_SRC$ac_delim
+PCAP_SUPPORT_BT!$PCAP_SUPPORT_BT$ac_delim
+BT_SRC!$BT_SRC$ac_delim
INSTALL_PROGRAM!$INSTALL_PROGRAM$ac_delim
INSTALL_SCRIPT!$INSTALL_SCRIPT$ac_delim
INSTALL_DATA!$INSTALL_DATA$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 78; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 84; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/contrib/libpcap/configure.in b/contrib/libpcap/configure.in
index 5cd8b14..7d12309 100755
--- a/contrib/libpcap/configure.in
+++ b/contrib/libpcap/configure.in
@@ -1,4 +1,4 @@
-dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.120.2.13 2007/09/12 19:17:24 guy Exp $ (LBL)
+dnl @(#) $Header: /tcpdump/master/libpcap/configure.in,v 1.138.2.22 2008-10-24 07:30:18 guy Exp $ (LBL)
dnl
dnl Copyright (c) 1994, 1995, 1996, 1997
dnl The Regents of the University of California. All rights reserved.
@@ -6,7 +6,7 @@ dnl
dnl Process this file with autoconf to produce a configure script.
dnl
-AC_REVISION($Revision: 1.120.2.13 $)
+AC_REVISION($Revision: 1.138.2.22 $)
AC_PREREQ(2.50)
AC_INIT(pcap.c)
@@ -19,6 +19,13 @@ AC_C___ATTRIBUTE__
AC_LBL_CHECK_TYPE(u_int8_t, u_char)
AC_LBL_CHECK_TYPE(u_int16_t, u_short)
AC_LBL_CHECK_TYPE(u_int32_t, u_int)
+AC_LBL_CHECK_TYPE(u_int64_t, unsigned long long)
+
+#
+# Try to arrange for large file support.
+#
+AC_SYS_LARGEFILE
+AC_FUNC_FSEEKO
dnl
dnl libpcap doesn't itself use <sys/ioccom.h>; however, the test program
@@ -30,6 +37,24 @@ AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h limits.h paths.h)
AC_CHECK_HEADERS(net/pfvar.h, , , [#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>])
+if test "$ac_cv_header_net_pfvar_h" = yes; then
+ #
+ # Check for various PF actions.
+ #
+ AC_MSG_CHECKING(whether net/pfvar.h defines PF_NAT through PF_NORDR)
+ AC_TRY_COMPILE(
+ [#include <sys/types.h>
+ #include <sys/socket.h>
+ #include <net/if.h>
+ #include <net/pfvar.h>],
+ [return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_PF_NAT_THROUGH_PF_NORDR, 1,
+ [define if net/pfvar.h defines PF_NAT through PF_NORDR])
+ ],
+ AC_MSG_RESULT(no))
+fi
AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include <sys/types.h>
#include <sys/socket.h>])
if test "$ac_cv_header_netinet_if_ether_h" != yes; then
@@ -172,6 +197,18 @@ if test "$enable_protochain" = "disabled"; then
fi
AC_MSG_RESULT(${enable_protochain})
+#
+# SITA support is mutually exclusive with native capture support;
+# "--with-sita" selects SITA support.
+#
+AC_ARG_WITH(sita, [ --with-sita include SITA support],
+[
+ AC_DEFINE(SITA,1,[include ACN support])
+ AC_MSG_NOTICE(Enabling SITA ACN support)
+ V_PCAP=sita
+ V_FINDALLDEVS=sita
+],
+[
dnl
dnl Not all versions of test support -c (character special) but it's a
dnl better way of testing since the device might be protected. So we
@@ -227,6 +264,140 @@ else
fi
AC_MSG_RESULT($V_PCAP)
+#
+# Do capture-mechanism-dependent tests.
+#
+case "$V_PCAP" in
+dlpi)
+ #
+ # Checks to see if Solaris has the public libdlpi(3LIB) library.
+ # Note: The existence of /usr/include/libdlpi.h does not mean it is the
+ # public libdlpi(3LIB) version. Before libdlpi was made public, a
+ # private version also existed, which did not have the same APIs.
+ # Due to a gcc bug, the default search path for 32-bit libraries does
+ # not include /lib, we add it explicitly here.
+ # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485].
+ # Also, due to the bug above applications that link to libpcap with
+ # libdlpi will have to add "-L/lib" option to "configure".
+ #
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="$LIBS -L/lib"
+ AC_CHECK_LIB(dlpi, dlpi_walk,
+ LIBS="-ldlpi $LIBS"
+ V_PCAP=libdlpi
+ AC_DEFINE(HAVE_LIBDLPI,1,[if libdlpi exists]),
+ V_PCAP=dlpi)
+ LDFLAGS=$saved_ldflags
+
+ #
+ # Checks whether <sys/dlpi.h> is usable, to catch weird SCO
+ # versions of DLPI.
+ #
+ AC_MSG_CHECKING(whether <sys/dlpi.h> is usable)
+ AC_CACHE_VAL(ac_cv_sys_dlpi_usable,
+ AC_TRY_COMPILE(
+ [
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <sys/dlpi.h>
+ ],
+ [int i = DL_PROMISC_PHYS;],
+ ac_cv_sys_dlpi_usable=yes,
+ ac_cv_sys_dlpi_usable=no))
+ AC_MSG_RESULT($ac_cv_sys_dlpi_usable)
+ if test $ac_cv_sys_dlpi_usable = no ; then
+ AC_MSG_ERROR(<sys/dlpi.h> is not usable on this system; it probably has a non-standard DLPI)
+ fi
+
+ #
+ # Check whether we have a /dev/dlpi device or have multiple devices.
+ #
+ AC_MSG_CHECKING(for /dev/dlpi device)
+ if test -c /dev/dlpi ; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_DEV_DLPI, 1, [define if you have a /dev/dlpi])
+ else
+ AC_MSG_RESULT(no)
+ dir="/dev/dlpi"
+ AC_MSG_CHECKING(for $dir directory)
+ if test -d $dir ; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE_UNQUOTED(PCAP_DEV_PREFIX, "$dir", [/dev/dlpi directory])
+ else
+ AC_MSG_RESULT(no)
+ fi
+ fi
+
+ #
+ # This check is for Solaris with DLPI support for passive modes.
+ # See dlpi(7P) for more details.
+ #
+ AC_LBL_DL_PASSIVE_REQ_T
+ ;;
+
+linux)
+ AC_MSG_CHECKING(Linux kernel version)
+ if test "$cross_compiling" = yes; then
+ AC_CACHE_VAL(ac_cv_linux_vers,
+ ac_cv_linux_vers=unknown)
+ else
+ AC_CACHE_VAL(ac_cv_linux_vers,
+ ac_cv_linux_vers=`uname -r 2>&1 | \
+ sed -n -e '$s/.* //' -e '$s/\..*//p'`)
+ fi
+ AC_MSG_RESULT($ac_cv_linux_vers)
+ if test $ac_cv_linux_vers = unknown ; then
+ AC_MSG_ERROR(cannot determine linux version when cross-compiling)
+ fi
+ if test $ac_cv_linux_vers -lt 2 ; then
+ AC_MSG_ERROR(version 2 or higher required; see the INSTALL doc for more info)
+ fi
+ AC_CHECK_HEADERS(linux/wireless.h, [], [],
+ [
+#include <sys/socket.h>
+#include <net/if.h>
+#include <linux/types.h>
+ ])
+ AC_CHECK_HEADERS()
+ AC_LBL_TPACKET_STATS
+ AC_LBL_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI
+ ;;
+
+bpf)
+ #
+ # Check whether we have the *BSD-style ioctls.
+ #
+ AC_CHECK_HEADERS(net/if_media.h)
+
+ AC_MSG_CHECKING(whether the system supports zerocopy BPF)
+ AC_TRY_COMPILE(
+ [#include <sys/socket.h>
+ #include <sys/ioctl.h>
+ #include <net/if.h>
+ #include <net/bpf.h>],
+ [return (BIOCROTZBUF + BPF_BUFMODE_ZBUF);],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_ZEROCOPY_BPF, 1,
+ [define if the system supports zerocopy BPF])
+ ],
+ AC_MSG_RESULT(no))
+ ;;
+
+dag)
+ V_DEFS="$V_DEFS -DDAG_ONLY"
+ ;;
+
+septel)
+ V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+ ;;
+
+null)
+ AC_MSG_WARN(cannot determine packet capture interface)
+ AC_MSG_WARN((see the INSTALL doc for more info))
+ ;;
+esac
+
dnl
dnl Now figure out how we get a list of interfaces and addresses,
dnl if we support capturing. Don't bother if we don't support
@@ -273,7 +444,8 @@ else
#
case "$V_PCAP" in
- dlpi)
+ dlpi|libdlpi)
+ AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
#
# This might be Solaris 8 or later, with
# SIOCGLIFCONF, or it might be some other OS
@@ -297,6 +469,10 @@ else
else
V_FINDALLDEVS=gifc
fi
+ #
+ # Needed for common functions used by pcap-[dlpi,libdlpi].c
+ #
+ SSRC="dlpisubs.c"
;;
*)
@@ -310,13 +486,35 @@ else
;;
esac])
fi
+])
-AC_MSG_CHECKING(if --enable-ipv6 option is specified)
-AC_ARG_ENABLE(ipv6, [ --enable-ipv6 build IPv6-capable version])
-if test "$enable_ipv6" = "yes"; then
- AC_DEFINE(INET6,1,[IPv6])
+AC_MSG_CHECKING(for socklen_t)
+AC_TRY_COMPILE([
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ ],
+ [ socklen_t x; ],
+ have_socklen_t=yes,
+ have_socklen_t=no)
+if test "x$have_socklen_t" = "xyes"; then
+ AC_DEFINE(HAVE_SOCKLEN_T, 1, [define if socklen_t is defined])
+fi
+AC_MSG_RESULT($have_socklen_t)
+
+AC_ARG_ENABLE(ipv6, [ --enable-ipv6 build IPv6-capable version @<:@default=yes, if getaddrinfo available@:>@],
+ [],
+ [enable_ipv6=ifavailable])
+if test "$enable_ipv6" != "no"; then
+ AC_CHECK_FUNC(getaddrinfo,
+ [
+ AC_DEFINE(INET6,1,[IPv6])
+ ],
+ [
+ if test "$enable_ipv6" != "ifavailable"; then
+ AC_MSG_FAILURE([--enable-ipv6 was given, but getaddrinfo isn't available])
+ fi
+ ])
fi
-AC_MSG_RESULT(${enable_ipv6-no})
AC_MSG_CHECKING(whether to build optimizer debugging code)
AC_ARG_ENABLE(optimizer-dbg, [ --enable-optimizer-dbg build optimizer debugging code])
@@ -332,62 +530,6 @@ if test "$enable_yydebug" = "yes"; then
fi
AC_MSG_RESULT(${enable_yydebug-no})
-case "$V_PCAP" in
-
-dlpi)
- AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
- AC_MSG_CHECKING(for /dev/dlpi device)
- if test -c /dev/dlpi ; then
- AC_MSG_RESULT(yes)
- AC_DEFINE(HAVE_DEV_DLPI, 1, [define if you have a /dev/dlpi])
- else
- AC_MSG_RESULT(no)
- dir="/dev/dlpi"
- AC_MSG_CHECKING(for $dir directory)
- if test -d $dir ; then
- AC_MSG_RESULT(yes)
- AC_DEFINE_UNQUOTED(PCAP_DEV_PREFIX, "$dir", [/dev/dlpi directory])
- else
- AC_MSG_RESULT(no)
- fi
- fi
- ;;
-
-linux)
- AC_MSG_CHECKING(Linux kernel version)
- if test "$cross_compiling" = yes; then
- AC_CACHE_VAL(ac_cv_linux_vers,
- ac_cv_linux_vers=unknown)
- else
- AC_CACHE_VAL(ac_cv_linux_vers,
- ac_cv_linux_vers=`uname -r 2>&1 | \
- sed -n -e '$s/.* //' -e '$s/\..*//p'`)
- fi
- AC_MSG_RESULT($ac_cv_linux_vers)
- if test $ac_cv_linux_vers = unknown ; then
- AC_MSG_ERROR(cannot determine linux version when cross-compiling)
- fi
- if test $ac_cv_linux_vers -lt 2 ; then
- AC_MSG_ERROR(version 2 or higher required; see the INSTALL doc for more info)
- fi
- AC_LBL_TPACKET_STATS
- ;;
-
-dag)
- V_DEFS="$V_DEFS -DDAG_ONLY"
- ;;
-
-septel)
- V_DEFS="$V_DEFS -DSEPTEL_ONLY"
- ;;
-
-null)
- AC_MSG_WARN(cannot determine packet capture interface)
- AC_MSG_WARN((see the INSTALL doc for more info))
- ;;
-
-esac
-
AC_MSG_CHECKING(whether we have /proc/net/dev)
if test -r /proc/net/dev ; then
ac_cv_lbl_proc_net_dev=yes
@@ -498,11 +640,11 @@ if test $ac_cv_lbl_dag_api = yes; then
dagapi_obj=$dag_lib_dir/dagapi.o
elif test -r $dag_lib_dir/libdag.a; then
# 2.5.x.
- ar x $dag_lib_dir/libdag.a dagapi.o
+ ar x $dag_lib_dir/libdag.a dagapi.o 2>/dev/null
if test -r ./dagapi.o; then
dagapi_obj=./dagapi.o
else
- ar x $dag_lib_dir/libdag.a libdag_la-dagapi.o
+ ar x $dag_lib_dir/libdag.a libdag_la-dagapi.o 2>/dev/null
if test -r ./libdag_la-dagapi.o; then
dagapi_obj=./libdag_la-dagapi.o
fi
@@ -529,11 +671,11 @@ if test $ac_cv_lbl_dag_api = yes; then
dagopts_obj=$dag_lib_dir/dagopts.o
elif test -r $dag_lib_dir/libdag.a; then
# 2.5.x.
- ar x $dag_lib_dir/libdag.a dagopts.o
+ ar x $dag_lib_dir/libdag.a dagopts.o 2>/dev/null
if test -r ./dagopts.o; then
dagopts_obj=./dagopts.o
else
- ar x $dag_lib_dir/libdag.a libdag_la-dagopts.o
+ ar x $dag_lib_dir/libdag.a libdag_la-dagopts.o 2>/dev/null
if test -r ./libdag_la-dagopts.o; then
dagopts_obj=./libdag_la-dagopts.o
fi
@@ -558,11 +700,11 @@ if test $ac_cv_lbl_dag_api = yes; then
dagreg_obj=$dag_lib_dir/dagreg.o
elif test -r $dag_lib_dir/libdag.a; then
# Extract from libdag.a.
- ar x $dag_lib_dir/libdag.a dagreg.o
+ ar x $dag_lib_dir/libdag.a dagreg.o 2>/dev/null
if test -r ./dagreg.o; then
dagreg_obj=./dagreg.o
else
- ar x $dag_lib_dir/libdag.a libdag_la-dagreg.o
+ ar x $dag_lib_dir/libdag.a libdag_la-dagreg.o 2>/dev/null
if test -r ./libdag_la-dagreg.o; then
dagreg_obj=./libdag_la-dagreg.o
fi
@@ -590,27 +732,25 @@ if test $ac_cv_lbl_dag_api = yes; then
# included if there's a found-action (arg 3).
saved_ldflags=$LDFLAGS
LDFLAGS="-L$dag_lib_dir"
- AC_CHECK_LIB([dag], [dag_attach_stream], [dag_version="2.5.x"], [dag_version="2.4.x"])
+ AC_CHECK_LIB([dag], [dag_attach_stream], [dag_streams="1"], [dag_streams="0"])
AC_CHECK_LIB([dag],[dag_get_erf_types], [
- AC_DEFINE(HAVE_DAG_GET_ERF_TYPES, 1, [define if you have dag_get_erf_types()])]
- )
+ AC_DEFINE(HAVE_DAG_GET_ERF_TYPES, 1, [define if you have dag_get_erf_types()])])
+ AC_CHECK_LIB([dag],[dag_get_stream_erf_types], [
+ AC_DEFINE(HAVE_DAG_GET_STREAM_ERF_TYPES, 1, [define if you have dag_get_stream_erf_types()])])
LDFLAGS=$saved_ldflags
- if test "$dag_version" = 2.5.x; then
+ if test "$dag_streams" = 1; then
AC_DEFINE(HAVE_DAG_STREAMS_API, 1, [define if you have streams capable DAG API])
DAGLIBS="-ldag"
fi
- # See if we can find a specific version string.
- AC_MSG_CHECKING([the DAG API version])
- if test -r "$dag_root/VERSION"; then
- dag_version="`cat $dag_root/VERSION`"
- fi
- AC_MSG_RESULT([$dag_version])
AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API])
fi
+AC_MSG_CHECKING(whether we have the DAG API)
+
if test $ac_cv_lbl_dag_api = no; then
+ AC_MSG_RESULT(no)
if test "$want_dag" = yes; then
# User wanted DAG support but we couldn't find it.
AC_MSG_ERROR([DAG API requested, but not found at $dag_root: use --without-dag])
@@ -621,6 +761,8 @@ if test $ac_cv_lbl_dag_api = no; then
# found.
AC_MSG_ERROR([Specifying the capture type as "dag" requires the DAG API to be present; use the --with-dag options to specify the location. (Try "./configure --help" for more information.)])
fi
+else
+ AC_MSG_RESULT(yes)
fi
AC_ARG_WITH(septel, [ --with-septel[[=DIR]] include Septel support (located in directory DIR, if supplied). [default=yes, on Linux, if present]],
@@ -724,22 +866,56 @@ if test "$V_LEX" = lex ; then
fi
fi
+#
+# Assume a.out/ELF convention for shared library names (".so"), and
+# V7/BSD convention for man pages (file formats in section 5,
+# miscellaneous info in section 7).
+#
DYEXT="so"
+MAN_FILE_FORMATS=5
+MAN_MISC_INFO=7
case "$host_os" in
aix*)
dnl Workaround to enable certain features
AC_DEFINE(_SUN,1,[define on AIX to get certain functions])
+
+ # We need "-lodm" and "-lcfg", as libpcap requires them on
+ # AIX.
+ DEPLIBS="-lodm -lcfg"
+ ;;
+
+darwin*)
+ DYEXT="dylib"
+ V_CCOPT="$V_CCOPT -fno-common"
;;
hpux9*)
AC_DEFINE(HAVE_HPUX9,1,[on HP-UX 9.x])
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
;;
hpux10.0*)
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
;;
hpux10.1*)
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
;;
hpux*)
@@ -750,6 +926,32 @@ hpux*)
dnl for 32-bit PA-RISC, but should be left as "so" for
dnl 64-bit PA-RISC or, I suspect, IA-64.
AC_DEFINE(HAVE_HPUX10_20_OR_LATER,1,[on HP-UX 10.20 or later])
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+irix*)
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+linux*)
+ V_CCOPT="$V_CCOPT -fPIC"
+ ;;
+
+osf*)
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
;;
sinix*)
@@ -768,17 +970,13 @@ sinix*)
solaris*)
AC_DEFINE(HAVE_SOLARIS,1,[On solaris])
- ;;
-darwin*)
- DYEXT="dylib"
- V_CCOPT="$V_CCOPT -fno-common"
- ;;
-
-linux*)
- V_CCOPT="$V_CCOPT -fPIC"
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
;;
-
esac
AC_PROG_RANLIB
@@ -809,17 +1007,63 @@ AC_SUBST(V_LIBS)
AC_SUBST(V_LEX)
AC_SUBST(V_PCAP)
AC_SUBST(V_FINDALLDEVS)
-AC_SUBST(V_RANLIB)
AC_SUBST(V_YACC)
AC_SUBST(SSRC)
AC_SUBST(DYEXT)
AC_SUBST(DAGLIBS)
+AC_SUBST(DEPLIBS)
+AC_SUBST(MAN_FILE_FORMATS)
+AC_SUBST(MAN_MISC_INFO)
+
+dnl check for USB sniffing support
+AC_MSG_CHECKING(for USB sniffing support)
+case "$host_os" in
+linux*)
+ AC_DEFINE(PCAP_SUPPORT_USB, 1, [target host supports USB sniffing])
+ USB_SRC=pcap-usb-linux.c
+ AC_MSG_RESULT(yes)
+ ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
+ if test $? -ne 0 ; then
+ ac_usb_dev_name="usbmon"
+ fi
+ AC_DEFINE_UNQUOTED(LINUX_USB_MON_DEV, "/dev/$ac_usb_dev_name", [path for device for USB sniffing])
+ AC_MSG_NOTICE(Device for USB sniffing is /dev/$ac_usb_dev_name)
+ ;;
+*)
+ AC_MSG_RESULT(no)
+ ;;
+esac
+AC_SUBST(PCAP_SUPPORT_USB)
+AC_SUBST(USB_SRC)
+
+dnl check for bluetooth sniffing support
+case "$host_os" in
+linux*)
+ AC_CHECK_HEADER(bluetooth/bluetooth.h,
+ [
+ AC_DEFINE(PCAP_SUPPORT_BT, 1, [target host supports Bluetooth sniffing])
+ BT_SRC=pcap-bt-linux.c
+ AC_MSG_NOTICE(Bluetooth sniffing is supported)
+ ],
+ AC_MSG_NOTICE(Bluetooth sniffing is not supported; install bluez-lib devel to enable it)
+ )
+ ;;
+*)
+ AC_MSG_NOTICE(no Bluetooth sniffing support)
+ ;;
+esac
+AC_SUBST(PCAP_SUPPORT_BT)
+AC_SUBST(BT_SRC)
AC_PROG_INSTALL
AC_CONFIG_HEADER(config.h)
-AC_OUTPUT(Makefile)
+AC_OUTPUT(Makefile pcap-filter.manmisc pcap-linktype.manmisc
+ pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap
+ pcap_datalink.3pcap pcap_dump_open.3pcap
+ pcap_list_datalinks.3pcap pcap_open_dead.3pcap
+ pcap_open_offline.3pcap)
if test -f .devel ; then
make depend
diff --git a/contrib/libpcap/dlpisubs.c b/contrib/libpcap/dlpisubs.c
new file mode 100644
index 0000000..441b8c0
--- /dev/null
+++ b/contrib/libpcap/dlpisubs.c
@@ -0,0 +1,349 @@
+/*
+ * This code is derived from code formerly in pcap-dlpi.c, originally
+ * contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), University College
+ * London, and subsequently modified by Guy Harris (guy@alum.mit.edu),
+ * Mark Pizzolato <List-tcpdump-workers@subscriptions.pizzolato.net>,
+ * Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
+ */
+
+/*
+ * This file contains dlpi/libdlpi related common functions used
+ * by pcap-[dlpi,libdlpi].c.
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/libpcap/dlpisubs.c,v 1.1.2.2 2008-04-04 19:39:05 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_SYS_BUFMOD_H
+ /*
+ * Size of a bufmod chunk to pass upstream; that appears to be the
+ * biggest value to which you can set it, and setting it to that value
+ * (which is bigger than what appears to be the Solaris default of 8192)
+ * reduces the number of packet drops.
+ */
+#define CHUNKSIZE 65536
+
+ /*
+ * Size of the buffer to allocate for packet data we read; it must be
+ * large enough to hold a chunk.
+ */
+#define PKTBUFSIZE CHUNKSIZE
+
+#else /* HAVE_SYS_BUFMOD_H */
+
+ /*
+ * Size of the buffer to allocate for packet data we read; this is
+ * what the value used to be - there's no particular reason why it
+ * should be tied to MAXDLBUF, but we'll leave it as this for now.
+ */
+#define PKTBUFSIZE (MAXDLBUF * sizeof(bpf_u_int32))
+
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_BUFMOD_H
+#include <sys/bufmod.h>
+#endif
+#include <sys/dlpi.h>
+#include <sys/stream.h>
+
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stropts.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+#include "dlpisubs.h"
+
+static void pcap_stream_err(const char *, int, char *);
+
+/*
+ * Get the packet statistics.
+ */
+int
+pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
+{
+
+ /*
+ * "ps_recv" counts packets handed to the filter, not packets
+ * that passed the filter. As filtering is done in userland,
+ * this would not include packets dropped because we ran out
+ * of buffer space; in order to make this more like other
+ * platforms (Linux 2.4 and later, BSDs with BPF), where the
+ * "packets received" count includes packets received but dropped
+ * due to running out of buffer space, and to keep from confusing
+ * applications that, for example, compute packet drop percentages,
+ * we also make it count packets dropped by "bufmod" (otherwise we
+ * might run the risk of the packet drop count being bigger than
+ * the received-packet count).
+ *
+ * "ps_drop" counts packets dropped by "bufmod" because of
+ * flow control requirements or resource exhaustion; it doesn't
+ * count packets dropped by the interface driver, or packets
+ * dropped upstream. As filtering is done in userland, it counts
+ * packets regardless of whether they would've passed the filter.
+ *
+ * These statistics don't include packets not yet read from
+ * the kernel by libpcap, but they may include packets not
+ * yet read from libpcap by the application.
+ */
+ *ps = p->md.stat;
+
+ /*
+ * Add in the drop count, as per the above comment.
+ */
+ ps->ps_recv += ps->ps_drop;
+ return (0);
+}
+
+/*
+ * Loop through the packets and call the callback for each packet.
+ * Return the number of packets read.
+ */
+int
+pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
+ int count, u_char *bufp, int len)
+{
+ int n, caplen, origlen;
+ u_char *ep, *pk;
+ struct pcap_pkthdr pkthdr;
+#ifdef HAVE_SYS_BUFMOD_H
+ struct sb_hdr *sbp;
+#ifdef LBL_ALIGN
+ struct sb_hdr sbhdr;
+#endif
+#endif
+
+ /* Loop through packets */
+ ep = bufp + len;
+ n = 0;
+
+#ifdef HAVE_SYS_BUFMOD_H
+ while (bufp < ep) {
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return -2 to indicate
+ * that we were told to break out of the loop, otherwise
+ * leave the flag set, so that the *next* call will break
+ * out of the loop without having read any packets, and
+ * return the number of packets we've processed so far.
+ */
+ if (p->break_loop) {
+ if (n == 0) {
+ p->break_loop = 0;
+ return (-2);
+ } else {
+ p->bp = bufp;
+ p->cc = ep - bufp;
+ return (n);
+ }
+ }
+#ifdef LBL_ALIGN
+ if ((long)bufp & 3) {
+ sbp = &sbhdr;
+ memcpy(sbp, bufp, sizeof(*sbp));
+ } else
+#endif
+ sbp = (struct sb_hdr *)bufp;
+ p->md.stat.ps_drop = sbp->sbh_drops;
+ pk = bufp + sizeof(*sbp);
+ bufp += sbp->sbh_totlen;
+ origlen = sbp->sbh_origlen;
+ caplen = sbp->sbh_msglen;
+#else
+ origlen = len;
+ caplen = min(p->snapshot, len);
+ pk = bufp;
+ bufp += caplen;
+#endif
+ ++p->md.stat.ps_recv;
+ if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
+#ifdef HAVE_SYS_BUFMOD_H
+ pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
+ pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;
+#else
+ (void) gettimeofday(&pkthdr.ts, NULL);
+#endif
+ pkthdr.len = origlen;
+ pkthdr.caplen = caplen;
+ /* Insure caplen does not exceed snapshot */
+ if (pkthdr.caplen > p->snapshot)
+ pkthdr.caplen = p->snapshot;
+ (*callback)(user, &pkthdr, pk);
+ if (++n >= count && count >= 0) {
+ p->cc = ep - bufp;
+ p->bp = bufp;
+ return (n);
+ }
+ }
+#ifdef HAVE_SYS_BUFMOD_H
+ }
+#endif
+ p->cc = 0;
+ return (n);
+}
+
+/*
+ * Process the mac type. Returns -1 if no matching mac type found, otherwise 0.
+ */
+int
+pcap_process_mactype(pcap_t *p, u_int mactype)
+{
+ int retv = 0;
+
+ switch (mactype) {
+
+ case DL_CSMACD:
+ case DL_ETHER:
+ p->linktype = DLT_EN10MB;
+ p->offset = 2;
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ p->dlt_list = (u_int *)malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
+ break;
+
+ case DL_FDDI:
+ p->linktype = DLT_FDDI;
+ p->offset = 3;
+ break;
+
+ case DL_TPR:
+ /* XXX - what about DL_TPB? Is that Token Bus? */
+ p->linktype = DLT_IEEE802;
+ p->offset = 2;
+ break;
+
+#ifdef HAVE_SOLARIS
+ case DL_IPATM:
+ p->linktype = DLT_SUNATM;
+ p->offset = 0; /* works for LANE and LLC encapsulation */
+ break;
+#endif
+
+ default:
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype %u",
+ mactype);
+ retv = -1;
+ }
+
+ return (retv);
+}
+
+#ifdef HAVE_SYS_BUFMOD_H
+/*
+ * Push and configure the buffer module. Returns -1 for error, otherwise 0.
+ */
+int
+pcap_conf_bufmod(pcap_t *p, int snaplen, int timeout)
+{
+ int retv = 0;
+
+ bpf_u_int32 ss, chunksize;
+
+ /* Non-standard call to get the data nicely buffered. */
+ if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
+ pcap_stream_err("I_PUSH bufmod", errno, p->errbuf);
+ retv = -1;
+ }
+
+ ss = snaplen;
+ if (ss > 0 &&
+ strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
+ pcap_stream_err("SBIOCSSNAP", errno, p->errbuf);
+ retv = -1;
+ }
+
+ /* Set up the bufmod timeout. */
+ if (timeout != 0) {
+ struct timeval to;
+
+ to.tv_sec = timeout / 1000;
+ to.tv_usec = (timeout * 1000) % 1000000;
+ if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
+ pcap_stream_err("SBIOCSTIME", errno, p->errbuf);
+ retv = -1;
+ }
+ }
+
+ /* Set the chunk length. */
+ chunksize = CHUNKSIZE;
+ if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize)
+ != 0) {
+ pcap_stream_err("SBIOCSCHUNKP", errno, p->errbuf);
+ retv = -1;
+ }
+
+ return (retv);
+}
+#endif /* HAVE_SYS_BUFMOD_H */
+
+/*
+ * Allocate data buffer. Returns -1 if memory allocation fails, else 0.
+ */
+int
+pcap_alloc_databuf(pcap_t *p)
+{
+ p->bufsize = PKTBUFSIZE;
+ p->buffer = (u_char *)malloc(p->bufsize + p->offset);
+ if (p->buffer == NULL) {
+ strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Issue a STREAMS I_STR ioctl. Returns -1 on error, otherwise
+ * length of returned data on success.
+ */
+int
+strioctl(int fd, int cmd, int len, char *dp)
+{
+ struct strioctl str;
+ int retv;
+
+ str.ic_cmd = cmd;
+ str.ic_timout = -1;
+ str.ic_len = len;
+ str.ic_dp = dp;
+ if ((retv = ioctl(fd, I_STR, &str)) < 0)
+ return (retv);
+
+ return (str.ic_len);
+}
+
+/*
+ * Write stream error message to errbuf.
+ */
+static void
+pcap_stream_err(const char *func, int err, char *errbuf)
+{
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", func, pcap_strerror(err));
+}
diff --git a/contrib/libpcap/dlpisubs.h b/contrib/libpcap/dlpisubs.h
new file mode 100644
index 0000000..67acd29
--- /dev/null
+++ b/contrib/libpcap/dlpisubs.h
@@ -0,0 +1,28 @@
+/*
+ * @(#) $Header: /tcpdump/master/libpcap/dlpisubs.h,v 1.1.2.2 2008-04-04 19:39:05 guy Exp $
+ */
+
+#ifndef dlpisubs_h
+#define dlpisubs_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Functions used by dlpisubs.c.
+ */
+int pcap_stats_dlpi(pcap_t *, struct pcap_stat *);
+int pcap_process_pkts(pcap_t *, pcap_handler, u_char *, int, u_char *, int);
+int pcap_process_mactype(pcap_t *, u_int);
+#ifdef HAVE_SYS_BUFMOD_H
+int pcap_conf_bufmod(pcap_t *, int, int);
+#endif
+int pcap_alloc_databuf(pcap_t *);
+int strioctl(int, int, int, char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/libpcap/doc/pcap.html b/contrib/libpcap/doc/pcap.html
deleted file mode 100644
index 94e3514..0000000
--- a/contrib/libpcap/doc/pcap.html
+++ /dev/null
@@ -1,997 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
-<html lang="en"><head><title>PCAP New Generation Dump File Format</title>
-<meta name="description" content="PCAP New Generation Dump File Format">
-<meta name="keywords" content="Internet-Draft, Libpcap, dump file format">
-<meta name="generator" content="xml2rfc v1.22 (http://xml.resource.org/)">
-<style type='text/css'>
-<!--
- body {
- font-family: verdana, charcoal, helvetica, arial, sans-serif;
- font-size: small ; color: #000000 ; background-color: #ffffff ; }
- .title { color: #990000; font-size: x-large ;
- font-weight: bold; text-align: right;
- font-family: helvetica, monaco, "MS Sans Serif", arial, sans-serif;
- background-color: transparent; }
- .filename { color: #666666; font-size: 18px; line-height: 28px;
- font-weight: bold; text-align: right;
- font-family: helvetica, arial, sans-serif;
- background-color: transparent; }
- td.rfcbug { background-color: #000000 ; width: 30px ; height: 30px ;
- text-align: justify; vertical-align: middle ; padding-top: 2px ; }
- td.rfcbug span.RFC { color: #666666; font-weight: bold; text-decoration: none;
- background-color: #000000 ;
- font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
- font-size: x-small ; }
- td.rfcbug span.hotText { color: #ffffff; font-weight: normal; text-decoration: none;
- text-align: center ;
- font-family: charcoal, monaco, geneva, "MS Sans Serif", helvetica, verdana, sans-serif;
- font-size: x-small ; background-color: #000000; }
-
- A { font-weight: bold; }
- A:link { color: #990000; background-color: transparent ; }
- A:visited { color: #333333; background-color: transparent ; }
- A:active { color: #333333; background-color: transparent ; }
-
- p { margin-left: 2em; margin-right: 2em; }
- p.copyright { font-size: x-small ; }
- p.toc { font-size: small ; font-weight: bold ; margin-left: 3em ;}
-
- span.emph { font-style: italic; }
- span.strong { font-weight: bold; }
- span.verb { font-family: "Courier New", Courier, monospace ; }
-
- ol.text { margin-left: 2em; margin-right: 2em; }
- ul.text { margin-left: 2em; margin-right: 2em; }
- li { margin-left: 3em; }
-
- pre { margin-left: 3em; color: #333333; background-color: transparent;
- font-family: "Courier New", Courier, monospace ; font-size: small ;
- }
-
- h3 { color: #333333; font-size: medium ;
- font-family: helvetica, arial, sans-serif ;
- background-color: transparent; }
- h4 { font-size: small; font-family: helvetica, arial, sans-serif ; }
-
- table.bug { width: 30px ; height: 15px ; }
- td.bug { color: #ffffff ; background-color: #990000 ;
- text-align: center ; width: 30px ; height: 15px ;
- }
- td.bug A.link2 { color: #ffffff ; font-weight: bold;
- text-decoration: none;
- font-family: monaco, charcoal, geneva, "MS Sans Serif", helvetica, sans-serif;
- font-size: x-small ; background-color: transparent }
-
- td.header { color: #ffffff; font-size: x-small ;
- font-family: arial, helvetica, sans-serif; vertical-align: top;
- background-color: #666666 ; width: 33% ; }
- td.author { font-weight: bold; margin-left: 4em; font-size: x-small ; }
- td.author-text { font-size: x-small; }
- table.data { vertical-align: top ; border-collapse: collapse ;
- border-style: solid solid solid solid ;
- border-color: black black black black ;
- font-size: small ; text-align: center ; }
- table.data th { font-weight: bold ;
- border-style: solid solid solid solid ;
- border-color: black black black black ; }
- table.data td {
- border-style: solid solid solid solid ;
- border-color: #333333 #333333 #333333 #333333 ; }
-
- hr { height: 1px }
--->
-</style>
-</head>
-<body>
-<table summary="layout" cellpadding="0" cellspacing="2" class="bug" align="right"><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></table>
-<table summary="layout" width="66%" border="0" cellpadding="0" cellspacing="0"><tr><td><table summary="layout" width="100%" border="0" cellpadding="2" cellspacing="1">
-<tr><td class="header">Network Working Group</td><td class="header">L. Degioanni</td></tr>
-<tr><td class="header">Internet-Draft</td><td class="header">F. Risso</td></tr>
-<tr><td class="header">Expires: August 30, 2004</td><td class="header">Politecnico di Torino</td></tr>
-<tr><td class="header">&nbsp;</td><td class="header">March 2004</td></tr>
-</table></td></tr></table>
-<div align="right"><span class="title"><br />PCAP New Generation Dump File Format</span></div>
-<div align="right"><span class="title"><br />pcap</span></div>
-
-<h3>Status of this Memo</h3>
-<p>
-This document is an Internet-Draft and is
-in full conformance with all provisions of Section 10 of RFC2026.</p>
-<p>
-Internet-Drafts are working documents of the Internet Engineering
-Task Force (IETF), its areas, and its working groups.
-Note that other groups may also distribute working documents as
-Internet-Drafts.</p>
-<p>
-Internet-Drafts are draft documents valid for a maximum of six months
-and may be updated, replaced, or obsoleted by other documents at any time.
-It is inappropriate to use Internet-Drafts as reference material or to cite
-them other than as "work in progress."</p>
-<p>
-The list of current Internet-Drafts can be accessed at
-<a href='http://www.ietf.org/ietf/1id-abstracts.txt'>http://www.ietf.org/ietf/1id-abstracts.txt</a>.</p>
-<p>
-The list of Internet-Draft Shadow Directories can be accessed at
-<a href='http://www.ietf.org/shadow.html'>http://www.ietf.org/shadow.html</a>.</p>
-<p>
-This Internet-Draft will expire on August 30, 2004.</p>
-
-<h3>Copyright Notice</h3>
-<p>
-Copyright (C) The Internet Society (2004). All Rights Reserved.</p>
-
-<h3>Abstract</h3>
-
-<p>This document describes a format to dump captured packets on a file. This format is extensible and it is currently proposed for implementation in the libpcap/WinPcap packet capture library.
-</p><a name="toc"></a><br /><hr />
-<h3>Table of Contents</h3>
-<p class="toc">
-<a href="#anchor1">1.</a>&nbsp;
-Objectives<br />
-<a href="#anchor2">2.</a>&nbsp;
-General File Structure<br />
-<a href="#sectionblock">2.1</a>&nbsp;
-General Block Structure<br />
-<a href="#anchor3">2.2</a>&nbsp;
-Block Types<br />
-<a href="#anchor4">2.3</a>&nbsp;
-Block Hierarchy and Precedence<br />
-<a href="#anchor5">2.4</a>&nbsp;
-Data format<br />
-<a href="#anchor6">3.</a>&nbsp;
-Block Definition<br />
-<a href="#sectionshb">3.1</a>&nbsp;
-Section Header Block (mandatory)<br />
-<a href="#sectionidb">3.2</a>&nbsp;
-Interface Description Block (mandatory)<br />
-<a href="#sectionpb">3.3</a>&nbsp;
-Packet Block (optional)<br />
-<a href="#anchor7">3.4</a>&nbsp;
-Simple Packet Block (optional)<br />
-<a href="#anchor8">3.5</a>&nbsp;
-Name Resolution Block (optional)<br />
-<a href="#anchor9">3.6</a>&nbsp;
-Interface Statistics Block (optional)<br />
-<a href="#sectionopt">4.</a>&nbsp;
-Options<br />
-<a href="#anchor10">5.</a>&nbsp;
-Experimental Blocks (deserved to a further investigation)<br />
-<a href="#anchor11">5.1</a>&nbsp;
-Other Packet Blocks (experimental)<br />
-<a href="#anchor12">5.2</a>&nbsp;
-Compression Block (experimental)<br />
-<a href="#anchor13">5.3</a>&nbsp;
-Encryption Block (experimental)<br />
-<a href="#anchor14">5.4</a>&nbsp;
-Fixed Length Block (experimental)<br />
-<a href="#anchor15">5.5</a>&nbsp;
-Directory Block (experimental)<br />
-<a href="#anchor16">5.6</a>&nbsp;
-Traffic Statistics and Monitoring Blocks (experimental)<br />
-<a href="#anchor17">5.7</a>&nbsp;
-Event/Security Block (experimental)<br />
-<a href="#anchor18">6.</a>&nbsp;
-Conclusions<br />
-<a href="#anchor19">7.</a>&nbsp;
-Most important open issues<br />
-<a href="#rfc.copyright">&#167;</a>&nbsp;
-Intellectual Property and Copyright Statements<br />
-</p>
-<br clear="all" />
-
-<a name="anchor1"></a><br /><hr />
-<table summary="layout" cellpadding="0" cellspacing="2" class="bug" align="right"><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></table>
-<a name="rfc.section.1"></a><h3>1.&nbsp;Objectives</h3>
-
-<p>The problem of exchanging packet traces becomes more and more critical every day; unfortunately, no standard solutions exist for this task right now. One of the most accepted packet interchange formats is the one defined by libpcap, which is rather old and does not fit for some of the nowadays applications especially in terms of extensibility.
-</p>
-<p>This document proposes a new format for dumping packet traces. The following goals are being pursued:
-</p>
-<ul class="text">
-<li>Extensibility: aside of some common functionalities, third parties should be able to enrich the information embedded in the file with proprietary extensions, which will be ignored by tools that are not able to understand them.
-</li>
-<li>Portability: a capture trace must contain all the information needed to read data independently from network, hardware and operating system of the machine that made the capture.
-</li>
-<li>Merge/Append data: it should be possible to add data at the end of a given file, and the resulting file must still be readable.
-</li>
-</ul>
-<a name="anchor2"></a><br /><hr />
-<table summary="layout" cellpadding="0" cellspacing="2" class="bug" align="right"><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></table>
-<a name="rfc.section.2"></a><h3>2.&nbsp;General File Structure</h3>
-
-<a name="rfc.section.2.1"></a><h4><a name="sectionblock">2.1</a>&nbsp;General Block Structure</h4>
-
-<p>A capture file is organized in blocks, that are appended one to another to form the file. All the blocks share a common format, which is shown in <a href="#formatblock">Figure 1</a>.
-</p><br /><hr />
-<a name="formatblock"></a>
-<pre>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Block Type |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Block Total Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / Block Body /
- / /* variable length, aligned to 32 bits */ /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Block Total Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-</pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Basic block structure.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>The fields have the following meaning:
-</p>
-<ul class="text">
-<li>Block Type (32 bits): unique value that identifies the block. Values whose Most Significant Bit (MSB) is equal to 1 are reserved for local use. They allow to save private data to the file and to extend the file format.
-</li>
-<li>Block Total Length: total size of this block, in bytes. For instance, a block that does not have a body has a length of 12 bytes.
-</li>
-<li>Block Body: content of the block.
-</li>
-<li>Block Total Length: total size of this block, in bytes. This field is duplicated for permitting backward file navigation.
-</li>
-</ul>
-<p>This structure, shared among all blocks, makes easy to process a file and to skip unneeded or unknown blocks. Blocks can be nested one inside the others (NOTE: needed?). Some of the blocks are mandatory, i.e. a dump file is not valid if they are not present, other are optional.
-</p>
-<p>The structure of the blocks allows to define other blocks if needed. A parser that does non understand them can simply ignore their content.
-</p>
-<a name="rfc.section.2.2"></a><h4><a name="anchor3">2.2</a>&nbsp;Block Types</h4>
-
-<p>The currently defined blocks are the following:
-</p>
-<ol class="text">
-<li>Section Header Block: it defines the most important characteristics of the capture file.
-</li>
-<li>Interface Description Block: it defines the most important characteristics of the interface(s) used for capturing traffic.
-</li>
-<li>Packet Block: it contains a single captured packet, or a portion of it.
-</li>
-<li>Simple Packet Block: it contains a single captured packet, or a portion of it, with only a minimal set of information about it.
-</li>
-<li>Name Resolution Block: it defines the mapping from numeric addresses present in the packet dump and the canonical name counterpart.
-</li>
-<li>Capture Statistics Block: it defines how to store some statistical data (e.g. packet dropped, etc) which can be useful to undestand the conditions in which the capture has been made.
-</li>
-<li>Compression Marker Block: TODO
-</li>
-<li>Encryption Marker Block: TODO
-</li>
-<li>Fixed Length Marker Block: TODO
-</li>
-</ol>
-<p>The following blocks instead are considered interesting but the authors believe that they deserve more in-depth discussion before being defined:
-</p>
-<ol class="text">
-<li>Further Packet Blocks
-</li>
-<li>Directory Block
-</li>
-<li>Traffic Statistics and Monitoring Blocks
-</li>
-<li>Alert and Security Blocks
-</li>
-</ol>
-<p>TODO Currently standardized Block Type codes are specified in Appendix 1.
-</p>
-<a name="rfc.section.2.3"></a><h4><a name="anchor4">2.3</a>&nbsp;Block Hierarchy and Precedence</h4>
-
-<p>The file must begin with a Section Header Block. However, more than one Section Header Block can be present on the dump, each one covering the data following it till the next one (or the end of file). A Section includes the data delimited by two Section Header Blocks (or by a Section Header Block and the end of the file), including the first Section Header Block.
-</p>
-<p>In case an application cannot read a Section because of different version number, it must skip everything until the next Section Header Block. Note that, in order to properly skip the blocks until the next section, all blocks must have the fields Type and Length at the beginning. This is a mandatory requirement that must be maintained in future versions of the block format.
-</p>
-<p><a href="#fssample-SHB">Figure 2</a> shows two valid files: the first has a typical configuration, with a single Section Header that covers the whole file. The second one contains three headers, and is normally the result of file concatenation. An application that understands only version 1.0 of the file format skips the intermediate section and restart processing the packets after the third Section Header.
-</p><br /><hr />
-<a name="fssample-SHB"></a>
-<pre>
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | SHB v1.0 | Data |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Typical configuration with a single Section Header Block
-
-
- |-- 1st Section --|-- 2nd Section --|-- 3rd Section --|
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | SHB v1.0 | Data | SHB V1.1 | Data | SHB V1.0 | Data |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Configuration with three different Section Header Blocks
-</pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;File structure example: the Section Header Block.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>NOTE: TO BE COMPLETED with some examples of other blocks
-</p>
-<a name="rfc.section.2.4"></a><h4><a name="anchor5">2.4</a>&nbsp;Data format</h4>
-
-<p>Data contained in each section will always be saved according to the characteristics (little endian / big endian) of the dumping machine. This refers to all fields that are saved as numbers and that span over two or more bytes.
-</p>
-<p>The approach of having each section saved in the native format of the generating host is more efficient because it avoids translation of data when reading / writing on the host itself, which is the most common case when generating/processing capture dumps.
-</p>
-<p>TODO Probably we have to specify something more here. Is what we're saying enough to avoid any kind of ambiguity?.
-</p>
-<a name="anchor6"></a><br /><hr />
-<table summary="layout" cellpadding="0" cellspacing="2" class="bug" align="right"><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></table>
-<a name="rfc.section.3"></a><h3>3.&nbsp;Block Definition</h3>
-
-<p>This section details the format of the body of the blocks currently defined.
-</p>
-<a name="rfc.section.3.1"></a><h4><a name="sectionshb">3.1</a>&nbsp;Section Header Block (mandatory)</h4>
-
-<p>The Section Header Block is mandatory. It identifies the beginning of a section of the capture dump file. Its format is shown in <a href="#formatSHB">Figure 3</a>.
-</p><br /><hr />
-<a name="formatSHB"></a>
-<pre>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Magic |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Major | Minor |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-</pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Section Header Block format.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>The meaning of the fields is:
-</p>
-<ul class="text">
-<li>Magic: magic number, whose value is the hexadecimal number 0x1A2B3C4D. This number can be used to distinguish section that have been saved on little-endian machines from the one saved on big-endian machines.
-</li>
-<li>Major: number of the current mayor version of the format. Current value is 1.
-</li>
-<li>Minor: number of the current minor version of the format. Current value is 0.
-</li>
-<li>Options: optionally, a list of options (formatted according to the rules defined in <a href="#sectionopt">Section 4</a>) can be present.
-</li>
-</ul>
-<p>Aside form the options defined in <a href="#sectionopt">Section 4</a>, the following options are valid within this block:
-</p><a name="InterfaceOptions1"></a>
-<table class="data" align="center" border="1" cellpadding="2" cellspacing="2">
-<tr>
-<th align="left" width="25%">Name</th>
-<th align="left" width="25%">Code</th>
-<th align="left" width="25%">Length</th>
-<th align="left" width="25%">Description</th>
-</tr>
-<tr>
-<td align="left">Hardware</td>
-<td align="left">2</td>
-<td align="left">variable</td>
-<td align="left">An ascii string containing the description of the hardware used to create this section.</td>
-</tr>
-<tr>
-<td align="left">Operating System</td>
-<td align="left">3</td>
-<td align="left">variable</td>
-<td align="left">An ascii string containing the name of the operating system used to create this section.</td>
-</tr>
-<tr>
-<td align="left">User Application</td>
-<td align="left">3</td>
-<td align="left">variable</td>
-<td align="left">An ascii string containing the name of the application used to create this section.</td>
-</tr>
-</table>
-
-<p>The Section Header Block does not contain data but it rather identifies a list of blocks (interfaces, packets) that are logically correlated. This block does not contain any reference to the size of the section it is currently delimiting, therefore the reader cannot skip a whole section at once. In case a section must be skipped, the user has to repeatedly skip all the blocks contained within it; this makes the parsing of the file slower but it permits to append several capture dumps at the same file.
-</p>
-<a name="rfc.section.3.2"></a><h4><a name="sectionidb">3.2</a>&nbsp;Interface Description Block (mandatory)</h4>
-
-<p>The Interface Description Block is mandatory. This block is needed to specify the characteristics of the network interface on which the capture has been made. In order to properly associate the captured data to the corresponding interface, the Interface Description Block must be defined before any other block that uses it; therefore, this block is usually placed immediately after the Section Header Block.
-</p>
-<p>An Interface Description Block is valid only inside the section which it belongs to. The structure of a Interface Description Block is shown in <a href="#formatidb">Figure 4</a>.
-</p><br /><hr />
-<a name="formatidb"></a>
-<pre>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Interface ID | LinkType |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | SnapLen |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Interface Description Block format.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>The meaning of the fields is:
-</p>
-<ul class="text">
-<li>Interface ID: a progressive number that identifies uniquely any interface inside current section. Two Interface Description Blocks can have the same Interface ID only if they are in different sections of the file. The Interface ID is referenced by the packet blocks.
-</li>
-<li>LinkType: a value that defines the link layer type of this interface.
-</li>
-<li>SnapLen: maximum number of bytes dumped from each packet. The portion of each packet that exceeds this value will not be stored in the file.
-</li>
-<li>Options: optionally, a list of options (formatted according to the rules defined in <a href="#sectionopt">Section 4</a>) can be present.
-</li>
-</ul>
-<p>In addition to the options defined in <a href="#sectionopt">Section 4</a>, the following options are valid within this block:
-</p><a name="InterfaceOptions2"></a>
-<table class="data" align="center" border="1" cellpadding="2" cellspacing="2">
-<tr>
-<th align="left" width="25%">Name</th>
-<th align="left" width="25%">Code</th>
-<th align="left" width="25%">Length</th>
-<th align="left" width="25%">Description</th>
-</tr>
-<tr>
-<td align="left">if_name</td>
-<td align="left">2</td>
-<td align="left">Variable</td>
-<td align="left">Name of the device used to capture data.</td>
-</tr>
-<tr>
-<td align="left">if_IPv4addr</td>
-<td align="left">3</td>
-<td align="left">8</td>
-<td align="left">Interface network address and netmask.</td>
-</tr>
-<tr>
-<td align="left">if_IPv6addr</td>
-<td align="left">4</td>
-<td align="left">17</td>
-<td align="left">Interface network address and prefix length (stored in the last byte).</td>
-</tr>
-<tr>
-<td align="left">if_MACaddr</td>
-<td align="left">5</td>
-<td align="left">6</td>
-<td align="left">Interface Hardware MAC address (48 bits).</td>
-</tr>
-<tr>
-<td align="left">if_EUIaddr</td>
-<td align="left">6</td>
-<td align="left">8</td>
-<td align="left">Interface Hardware EUI address (64 bits), if available.</td>
-</tr>
-<tr>
-<td align="left">if_speed</td>
-<td align="left">7</td>
-<td align="left">8</td>
-<td align="left">Interface speed (in bps).</td>
-</tr>
-<tr>
-<td align="left">if_tsaccur</td>
-<td align="left">8</td>
-<td align="left">1</td>
-<td align="left">Precision of timestamps. If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as a negative power of 10 (e.g. 6 means microsecond accuracy). If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as negative power of 2 (e.g. 10 means 1/1024 of second). If this option is not present, a precision of 10^-6 is assumed.</td>
-</tr>
-<tr>
-<td align="left">if_tzone</td>
-<td align="left">9</td>
-<td align="left">4</td>
-<td align="left">Time zone for GMT support (TODO: specify better).</td>
-</tr>
-<tr>
-<td align="left">if_flags</td>
-<td align="left">10</td>
-<td align="left">4</td>
-<td align="left">Interface flags. (TODO: specify better. Possible flags: promiscuous, inbound/outbound, traffic filtered during capture).</td>
-</tr>
-<tr>
-<td align="left">if_filter</td>
-<td align="left">11</td>
-<td align="left">variable</td>
-<td align="left">The filter (e.g. "capture only TCP traffic") used to capture traffic. The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more). More details about this format will be presented in Appendix XXX (TODO).</td>
-</tr>
-<tr>
-<td align="left">if_opersystem</td>
-<td align="left">12</td>
-<td align="left">variable</td>
-<td align="left">An ascii string containing the name of the operating system of the machine that hosts this interface. This can be different from the same information that can be contained by the Section Header Block (<a href="#sectionshb">Section 3.1</a>) because the capture can have been done on a remote machine.</td>
-</tr>
-</table>
-
-<a name="rfc.section.3.3"></a><h4><a name="sectionpb">3.3</a>&nbsp;Packet Block (optional)</h4>
-
-<p>A Packet Block is the standard container for storing the packets coming from the network. The Packet Block is optional because packets can be stored either by means of this block or the Simple Packet Block, which can be used to speed up dump generation. The format of a packet block is shown in <a href="#formatpb">Figure 5</a>.
-</p><br /><hr />
-<a name="formatpb"></a>
-<pre>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Interface ID | Drops Count |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Timestamp (High) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Timestamp (Low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Captured Len |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Packet Len |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | |
- | Packet Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-</pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Packet Block format.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>The Packet Block has the following fields:
-</p>
-<ul class="text">
-<li>Interface ID: Specifies the interface this packet comes from, and corresponds to the ID of one of the Interface Description Blocks present in this section of the file (see <a href="#formatidb">Figure 4</a>).
-</li>
-<li>Drops Count: a local drop counter. It specified the number of packets lost (by the interface and the operating system) between this packet and the preceding one. The value xFFFF (in hexadecimal) is reserved for those systems in which this information is not available.
-</li>
-<li>Timestamp (High): the most significative part of the timestamp. in standard Unix format, i.e. from 1/1/1970.
-</li>
-<li>Timestamp (Low): the less significative part of the timestamp. The way to interpret this field is specified by the 'ts_accur' option (see <a href="#formatidb">Figure 4</a>) of the Interface Description block referenced by this packet. If the Interface Description block does not contain a 'ts_accur' option, then this field is expressed in microseconds.
-</li>
-<li>Captured Len: number of bytes captured from the packet (i.e. the length of the Packet Data field). It will be the minimum value among the actual Packet Length and the snapshot length (defined in <a href="#formatidb">Figure 4</a>).
-</li>
-<li>Packet Len: actual length of the packet when it was transmitted on the network. Can be different from Captured Len if the user wants only a snapshot of the packet.
-</li>
-<li>Packet Data: the data coming from the network, including link-layer headers. The length of this field is Captured Len. The format of the link-layer headers depends on the LinkType field specified in the Interface Description Block (see <a href="#sectionidb">Section 3.2</a>) and it is specified in Appendix XXX (TODO).
-</li>
-<li>Options: optionally, a list of options (formatted according to the rules defined in <a href="#sectionopt">Section 4</a>) can be present.
-</li>
-</ul>
-<p>
-</p>
-<a name="rfc.section.3.4"></a><h4><a name="anchor7">3.4</a>&nbsp;Simple Packet Block (optional)</h4>
-
-<p>The Simple Packet Block is a lightweight container for storing the packets coming from the network. Its presence is optional.
-</p>
-<p>A Simple Packet Block is similar to a Packet Block (see <a href="#sectionpb">Section 3.3</a>), but it is smaller, simpler to process and contains only a minimal set of information. This block is preferred to the standard Packet Block when performance or space occupation are critical factors, such as in sustained traffic dump applications. A capture file can contain both Packet Blocks and Simple Packet Blocks: for example, a capture tool could switch from Packet Blocks to Simple Packet Blocks when the hardware resources become critical.
-</p>
-<p>The Simple Packet Block does not contain the Interface ID field. Therefore, it must be assumed that all the Simple Packet Blocks have been captured on the interface previously specified in the Interface Description Block.
-</p>
-<p><a href="#formatpbs">Figure 6</a> shows the format of the Simple Packet Block.
-</p><br /><hr />
-<a name="formatpbs"></a>
-<pre>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Packet Len |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | |
- | Packet Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Simple Packet Block format.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>The Packet Block has the following fields:
-</p>
-<ul class="text">
-<li>Packet Len: actual length of the packet when it was transmitted on the network. Can be different from captured len if the packet has been truncated.
-</li>
-<li>Packet data: the data coming from the network, including link-layers headers. The length of this field can be derived from the field Block Total Length, present in the Block Header.
-</li>
-</ul>
-<p>The Simple Packet Block does not contain the timestamp because this is one of the most costly operations on PCs. Additionally, there are applications that do not require it; e.g. an Intrusion Detection System is interested in packets, not in their timestamp.
-</p>
-<p>The Simple Packet Block is very efficient in term of disk space: a snapshot of length 100 bytes requires only 16 bytes of overhead, which corresponds to an efficiency of more than 86%.
-</p>
-<a name="rfc.section.3.5"></a><h4><a name="anchor8">3.5</a>&nbsp;Name Resolution Block (optional)</h4>
-
-<p>The Name Resolution Block is used to support the correlation of numeric addresses (present in the captured packets) and their corresponding canonical names and it is optional. Having the literal names saved in the file, this prevents the need of a name resolution in a delayed time, when the association between names and addresses can be different from the one in use at capture time. Moreover, The Name Resolution Block avoids the need of issuing a lot of DNS requests every time the trace capture is opened, and allows to have name resolution also when reading the capture with a machine not connected to the network.
-</p>
-<p>The format of the Name Resolution Block is shown in <a href="#formatnrb">Figure 7</a>.
-</p><br /><hr />
-<a name="formatnrb"></a>
-<pre>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Record Type | Record Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Record Value |
- | /* variable length, byte-aligned */ |
- | + + + + + + + + + + + + + + + + + + + + + + + + +
- | | | | |
- +-+-+-+-+-+-+-+-+ + + + + + + + + + + + + + + + + + + + + + + + +
- . . . other records . . .
- | Record Type == end_of_recs | Record Length == 00 |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Name Resolution Block format.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>A Name Resolution Block is a zero-terminated list of records (in the TLV format), each of which contains an association between a network address and a name. There are three possible types of records:
-</p><a name="nrrecords"></a>
-<table class="data" align="center" border="1" cellpadding="2" cellspacing="2">
-<tr>
-<th align="left" width="25%">Name</th>
-<th align="left" width="25%">Code</th>
-<th align="left" width="25%">Length</th>
-<th align="left" width="25%">Description</th>
-</tr>
-<tr>
-<td align="left">end_of_recs</td>
-<td align="left">0</td>
-<td align="left">0</td>
-<td align="left">End of records</td>
-</tr>
-<tr>
-<td align="left">ip4_rec</td>
-<td align="left">1</td>
-<td align="left">Variable</td>
-<td align="left">Specifies an IPv4 address (contained in the first 4 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address.</td>
-</tr>
-<tr>
-<td align="left">ip6_rec</td>
-<td align="left">1</td>
-<td align="left">Variable</td>
-<td align="left">Specifies an IPv6 address (contained in the first 16 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address.</td>
-</tr>
-</table>
-
-<p>After the list or Name Resolution Records, optionally, a list of options (formatted according to the rules defined in <a href="#sectionopt">Section 4</a>) can be present.
-</p>
-<p>A Name Resolution Block is normally placed at the beginning of the file, but no assumptions can be taken about its position. Name Resolution Blocks can be added in a second time by tools that process the file, like network analyzers.
-</p>
-<p>In addiction to the options defined in <a href="#sectionopt">Section 4</a>, the following options are valid within this block:
-</p><table class="data" align="center" border="1" cellpadding="2" cellspacing="2">
-<tr>
-<th align="left" width="25%">Name</th>
-<th align="left" width="25%">Code</th>
-<th align="left" width="25%">Length</th>
-<th align="left" width="25%">Description</th>
-</tr>
-<tr>
-<td align="left">ns_dnsname</td>
-<td align="left">2</td>
-<td align="left">Variable</td>
-<td align="left">An ascii string containing the name of the machine (DNS server) used to perform the name resolution.</td>
-</tr>
-</table>
-
-<a name="rfc.section.3.6"></a><h4><a name="anchor9">3.6</a>&nbsp;Interface Statistics Block (optional)</h4>
-
-<p>The Interface Statistics Block contains the capture statistics for a given interface and it is optional. The statistics are referred to the interface defined in the current Section identified by the Interface ID field.
-</p>
-<p>The format of the Interface Statistics Block is shown in <a href="#formatisb">Figure 8</a>.
-</p><br /><hr />
-<a name="formatisb"></a>
-<pre>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | IfRecv |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | IfDrop |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | FilterAccept |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | OSDrop |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | UsrDelivered |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Interface ID | Reserved |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Interface Statistics Block format.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>The fields have the following meaning:
-</p>
-<ul class="text">
-<li>IfRecv: number of packets received from the interface during the capture. This number is reported as a 64 bits value, in which the most significat bits are located in the first four bytes of the field.
-</li>
-<li>IfDrop: number of packets dropped by the interface during the capture due to lack of resources.
-</li>
-<li>FilterAccept: number of packets accepeted by filter during current capture.
-</li>
-<li>OSDrop: number of packets dropped by the operating system during the capture.
-</li>
-<li>UsrDelivered: number of packets delivered to the user. UsrDelivered can be different from the value 'FilterAccept - OSDropped' because some packets could still lay in the OS buffers when the capture ended.
-</li>
-<li>Interface ID: reference to an Interface Description Block.
-</li>
-<li>Reserved: Reserved to future use.
-</li>
-<li>Options: optionally, a list of options (formatted according to the rules defined in <a href="#sectionopt">Section 4</a>) can be present.
-</li>
-</ul>
-<p>In addiction to the options defined in <a href="#sectionopt">Section 4</a>, the following options are valid within this block:
-</p><table class="data" align="center" border="1" cellpadding="2" cellspacing="2">
-<tr>
-<th align="left" width="25%">Name</th>
-<th align="left" width="25%">Code</th>
-<th align="left" width="25%">Length</th>
-<th align="left" width="25%">Description</th>
-</tr>
-<tr>
-<td align="left">isb_starttime</td>
-<td align="left">2</td>
-<td align="left">8</td>
-<td align="left">Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds.</td>
-</tr>
-<tr>
-<td align="left">isb_endtime</td>
-<td align="left">3</td>
-<td align="left">8</td>
-<td align="left">Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds.</td>
-</tr>
-</table>
-
-<a name="sectionopt"></a><br /><hr />
-<table summary="layout" cellpadding="0" cellspacing="2" class="bug" align="right"><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></table>
-<a name="rfc.section.4"></a><h3>4.&nbsp;Options</h3>
-
-<p>Almost all blocks have the possibility to embed optional fields. Optional fields can be used to insert some information that may be useful when reading data, but that it is not really needed for packet processing. Therefore, each tool can be either read the content of the optional fields (if any), or skip them at once.
-</p>
-<p>Skipping all the optional fields at once is straightforward because most of the blocks have a fixed length, therefore the field Block Length (present in the General Block Structure, see <a href="#sectionblock">Section 2.1</a>) can be used to skip everything till the next block.
-</p>
-<p>Options are a list of Type - Length - Value fields, each one containing a single value:
-</p>
-<ul class="text">
-<li>Option Type (2 bytes): it contains the code that specifies the type of the current TLV record. Option types whose Most Significant Bit is equal to one are reserved for local use; therefore, there is no guarantee that the code used is unique among all capture files (generated by other applications). In case of vendor-specific extensions that have to be identified uniquely, vendors must request an Option Code whose MSB is equal to zero.
-</li>
-<li>Option Length (2 bytes): it contains the length of the following 'Option Value' field.
-</li>
-<li>Option Value (variable length): it contains the value of the given option. The length of this field as been specified by the Option Length field.
-</li>
-</ul>
-<p>Options may be repeated several times (e.g. an interface that has several IP addresses associated to it). The option list is terminated by a special code which is the 'End of Option'.
-</p>
-<p>The format of the optional fields is shown in <a href="#formatopt">Figure 9</a>.
-</p><br /><hr />
-<a name="formatopt"></a>
-<pre>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Option Code | Option Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Option Value |
- | /* variable length, byte-aligned */ |
- | + + + + + + + + + + + + + + + + + + + + + + + + +
- | / / / |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / . . . other options . . . /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Option Code == opt_endofopt | Option Length == 0 |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Options format.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>The following codes can always be present in any optional field:
-</p><table class="data" align="center" border="1" cellpadding="2" cellspacing="2">
-<tr>
-<th align="left" width="25%">Name</th>
-<th align="left" width="25%">Code</th>
-<th align="left" width="25%">Length</th>
-<th align="left" width="25%">Description</th>
-</tr>
-<tr>
-<td align="left">opt_endofopt</td>
-<td align="left">0</td>
-<td align="left">0</td>
-<td align="left">End of options: it is used to delimit the end of the optional fields. This block cannot be repeated within a given list of options.</td>
-</tr>
-<tr>
-<td align="left">opt_comment</td>
-<td align="left">1</td>
-<td align="left">variable</td>
-<td align="left">Comment: it is an ascii string containing a comment that is associated to the current block.</td>
-</tr>
-</table>
-
-<a name="anchor10"></a><br /><hr />
-<table summary="layout" cellpadding="0" cellspacing="2" class="bug" align="right"><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></table>
-<a name="rfc.section.5"></a><h3>5.&nbsp;Experimental Blocks (deserved to a further investigation)</h3>
-
-<a name="rfc.section.5.1"></a><h4><a name="anchor11">5.1</a>&nbsp;Other Packet Blocks (experimental)</h4>
-
-<p>Can some other packet blocks (besides the two described in the previous paragraphs) be useful?
-</p>
-<a name="rfc.section.5.2"></a><h4><a name="anchor12">5.2</a>&nbsp;Compression Block (experimental)</h4>
-
-<p>The Compression Block is optional. A file can contain an arbitrary number of these blocks. A Compression Block, as the name says, is used to store compressed data. Its format is shown in <a href="#formatcb">Figure 10</a>.
-</p><br /><hr />
-<a name="formatcb"></a>
-<pre>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Compr. Type | |
- +-+-+-+-+-+-+-+-+ |
- | |
- | Compressed Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Compression Block format.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>The fields have the following meaning:
-</p>
-<ul class="text">
-<li>Compression Type: specifies the compression algorithm. Possible values for this field are 0 (uncompressed), 1 (Lempel Ziv), 2 (Gzip), other?? Probably some kind of dumb and fast compression algorithm could be effective with some types of traffic (for example web), but which?
-</li>
-<li>Compressed Data: data of this block. Once decompressed, it is made of other blocks.
-</li>
-</ul>
-<a name="rfc.section.5.3"></a><h4><a name="anchor13">5.3</a>&nbsp;Encryption Block (experimental)</h4>
-
-<p>The Encryption Block is optional. A file can contain an arbitrary number of these blocks. An Encryption Block is used to sotre encrypted data. Its format is shown in <a href="#formateb">Figure 11</a>.
-</p><br /><hr />
-<a name="formateb"></a>
-<pre>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Encr. Type | |
- +-+-+-+-+-+-+-+-+ |
- | |
- | Compressed Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Encryption Block format.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>The fields have the following meaning:
-</p>
-<ul class="text">
-<li>Compression Type: specifies the encryption algorithm. Possible values for this field are ??? NOTE: this block should probably contain other fields, depending on the encryption algorithm. To be define precisely.
-</li>
-<li>Encrypted Data: data of this block. Once decripted, it consists of other blocks.
-</li>
-</ul>
-<a name="rfc.section.5.4"></a><h4><a name="anchor14">5.4</a>&nbsp;Fixed Length Block (experimental)</h4>
-
-<p>The Fixed Length Block is optional. A file can contain an arbitrary number of these blocks. A Fixed Length Block can be used to optimize the access to the file. Its format is shown in <a href="#formatflm">Figure 12</a>.
-A Fixed Length Block stores records with constant size. It contains a set of Blocks (normally Packet Blocks or Simple Packet Blocks), of wihich it specifies the size. Knowing this size a priori helps to scan the file and to load some portions of it without truncating a block, and is particularly useful with cell-based networks like ATM.
-</p><br /><hr />
-<a name="formatflm"></a>
-<pre>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Cell Size | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- | |
- | Fixed Size Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </pre>
-<table border="0" cellpadding="0" cellspacing="2" align="center"><tr><td align="center"><font face="monaco, MS Sans Serif" size="1"><b>&nbsp;Fixed Length Block format.&nbsp;</b></font><br /></td></tr></table><hr size="1" shade="0">
-
-<p>The fields have the following meaning:
-</p>
-<ul class="text">
-<li>Cell size: the size of the blocks contained in the data field.
-</li>
-<li>Fixed Size Data: data of this block.
-</li>
-</ul>
-<a name="rfc.section.5.5"></a><h4><a name="anchor15">5.5</a>&nbsp;Directory Block (experimental)</h4>
-
-<p>If present, this block contains the following information:
-</p>
-<ul class="text">
-<li>number of indexed packets (N)
-</li>
-<li>table with position and length of any indexed packet (N entries)
-</li>
-</ul>
-<p>A directory block must be followed by at least N packets, otherwise it must be considered invalid. It can be used to efficiently load portions of the file to memory and to support operations on memory mapped files. This block can be added by tools like network analyzers as a consequence of file processing.
-</p>
-<a name="rfc.section.5.6"></a><h4><a name="anchor16">5.6</a>&nbsp;Traffic Statistics and Monitoring Blocks (experimental)</h4>
-
-<p>One or more blocks could be defined to contain network statistics or traffic monitoring information. They could be use to store data collected from RMON or Netflow probes, or from other network monitoring tools.
-</p>
-<a name="rfc.section.5.7"></a><h4><a name="anchor17">5.7</a>&nbsp;Event/Security Block (experimental)</h4>
-
-<p>This block could be used to store events. Events could contain generic information (for example network load over 50%, server down...) or security alerts. An event could be:
-</p>
-<ul class="text">
-<li>skipped, if the application doesn't know how to do with it
-</li>
-<li>processed independently by the packets. In other words, the applications skips the packets and processes only the alerts
-</li>
-<li>processed in relation to packets: for example, a security tool could load only the packets of the file that are near a security alert; a monitorg tool could skip the packets captured while the server was down.
-</li>
-</ul>
-<a name="anchor18"></a><br /><hr />
-<table summary="layout" cellpadding="0" cellspacing="2" class="bug" align="right"><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></table>
-<a name="rfc.section.6"></a><h3>6.&nbsp;Conclusions</h3>
-
-<p>The file format proposed in this document should be very versatile and satisfy a wide range of applications.
-In the simplest case, it can contain a raw dump of the network data, made of a series of Simple Packet Blocks.
-In the most complex case, it can be used as a repository for heterogeneous information.
-In every case, the file remains easy to parse and an application can always skip the data it is not interested in; at the same time, different applications can share the file, and each of them can benfit of the information produced by the others.
-Two or more files can be concatenated obtaining another valid file.
-</p>
-<a name="anchor19"></a><br /><hr />
-<table summary="layout" cellpadding="0" cellspacing="2" class="bug" align="right"><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></table>
-<a name="rfc.section.7"></a><h3>7.&nbsp;Most important open issues</h3>
-
-<ul class="text">
-<li>Data, in the file, must be byte or word aligned? Currently, the structure of this document is not consistent with respect to this point.
-</li>
-</ul><a name="rfc.copyright"></a><br /><hr />
-<table summary="layout" cellpadding="0" cellspacing="2" class="bug" align="right"><tr><td class="bug"><a href="#toc" class="link2">&nbsp;TOC&nbsp;</a></td></tr></table>
-<h3>Intellectual Property Statement</h3>
-<p class='copyright'>
-The IETF takes no position regarding the validity or scope of
-any intellectual property or other rights that might be claimed
-to pertain to the implementation or use of the technology
-described in this document or the extent to which any license
-under such rights might or might not be available; neither does
-it represent that it has made any effort to identify any such
-rights. Information on the IETF's procedures with respect to
-rights in standards-track and standards-related documentation
-can be found in BCP-11. Copies of claims of rights made
-available for publication and any assurances of licenses to
-be made available, or the result of an attempt made
-to obtain a general license or permission for the use of such
-proprietary rights by implementors or users of this
-specification can be obtained from the IETF Secretariat.</p>
-<p class='copyright'>
-The IETF invites any interested party to bring to its
-attention any copyrights, patents or patent applications, or
-other proprietary rights which may cover technology that may be
-required to practice this standard. Please address the
-information to the IETF Executive Director.</p>
-<h3>Full Copyright Statement</h3>
-<p class='copyright'>
-Copyright (C) The Internet Society (2004). All Rights Reserved.</p>
-<p class='copyright'>
-This document and translations of it may be copied and furnished to
-others, and derivative works that comment on or otherwise explain it
-or assist in its implementation may be prepared, copied, published and
-distributed, in whole or in part, without restriction of any kind,
-provided that the above copyright notice and this paragraph are
-included on all such copies and derivative works. However, this
-document itself may not be modified in any way, such as by removing
-the copyright notice or references to the Internet Society or other
-Internet organizations, except as needed for the purpose of
-developing Internet standards in which case the procedures for
-copyrights defined in the Internet Standards process must be
-followed, or as required to translate it into languages other than
-English.</p>
-<p class='copyright'>
-The limited permissions granted above are perpetual and will not be
-revoked by the Internet Society or its successors or assignees.</p>
-<p class='copyright'>
-This document and the information contained herein is provided on an
-&quot;AS IS&quot; basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
-TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
-BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
-HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
-MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.</p>
-<h3>Acknowledgment</h3>
-<p class='copyright'>
-Funding for the RFC Editor function is currently provided by the
-Internet Society.</p>
-</body></html>
diff --git a/contrib/libpcap/doc/pcap.txt b/contrib/libpcap/doc/pcap.txt
deleted file mode 100644
index cfa6645..0000000
--- a/contrib/libpcap/doc/pcap.txt
+++ /dev/null
@@ -1,1680 +0,0 @@
-
-
-Network Working Group L. Degioanni
-Internet-Draft F. Risso
-Expires: August 30, 2004 Politecnico di Torino
- March 2004
-
-
- PCAP New Generation Dump File Format
- pcap
-
-Status of this Memo
-
- This document is an Internet-Draft and is in full conformance with
- all provisions of Section 10 of RFC2026.
-
- Internet-Drafts are working documents of the Internet Engineering
- Task Force (IETF), its areas, and its working groups. Note that other
- groups may also distribute working documents as Internet-Drafts.
-
- Internet-Drafts are draft documents valid for a maximum of six months
- and may be updated, replaced, or obsoleted by other documents at any
- time. It is inappropriate to use Internet-Drafts as reference
- material or to cite them other than as "work in progress."
-
- The list of current Internet-Drafts can be accessed at http://
- www.ietf.org/ietf/1id-abstracts.txt.
-
- The list of Internet-Draft Shadow Directories can be accessed at
- http://www.ietf.org/shadow.html.
-
- This Internet-Draft will expire on August 30, 2004.
-
-Copyright Notice
-
- Copyright (C) The Internet Society (2004). All Rights Reserved.
-
-Abstract
-
- This document describes a format to dump captured packets on a file.
- This format is extensible and it is currently proposed for
- implementation in the libpcap/WinPcap packet capture library.
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 1]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
-Table of Contents
-
- 1. Objectives . . . . . . . . . . . . . . . . . . . . . . . . . . 3
- 2. General File Structure . . . . . . . . . . . . . . . . . . . . 4
- 2.1 General Block Structure . . . . . . . . . . . . . . . . . . . 4
- 2.2 Block Types . . . . . . . . . . . . . . . . . . . . . . . . . 5
- 2.3 Block Hierarchy and Precedence . . . . . . . . . . . . . . . . 5
- 2.4 Data format . . . . . . . . . . . . . . . . . . . . . . . . . 6
- 3. Block Definition . . . . . . . . . . . . . . . . . . . . . . . 8
- 3.1 Section Header Block (mandatory) . . . . . . . . . . . . . . . 8
- 3.2 Interface Description Block (mandatory) . . . . . . . . . . . 9
- 3.3 Packet Block (optional) . . . . . . . . . . . . . . . . . . . 13
- 3.4 Simple Packet Block (optional) . . . . . . . . . . . . . . . . 15
- 3.5 Name Resolution Block (optional) . . . . . . . . . . . . . . . 16
- 3.6 Interface Statistics Block (optional) . . . . . . . . . . . . 18
- 4. Options . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
- 5. Experimental Blocks (deserved to a further investigation) . . 23
- 5.1 Other Packet Blocks (experimental) . . . . . . . . . . . . . . 23
- 5.2 Compression Block (experimental) . . . . . . . . . . . . . . . 23
- 5.3 Encryption Block (experimental) . . . . . . . . . . . . . . . 23
- 5.4 Fixed Length Block (experimental) . . . . . . . . . . . . . . 24
- 5.5 Directory Block (experimental) . . . . . . . . . . . . . . . . 25
- 5.6 Traffic Statistics and Monitoring Blocks (experimental) . . . 25
- 5.7 Event/Security Block (experimental) . . . . . . . . . . . . . 25
- 6. Conclusions . . . . . . . . . . . . . . . . . . . . . . . . . 27
- 7. Most important open issues . . . . . . . . . . . . . . . . . . 28
- Intellectual Property and Copyright Statements . . . . . . . . 29
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 2]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
-1. Objectives
-
- The problem of exchanging packet traces becomes more and more
- critical every day; unfortunately, no standard solutions exist for
- this task right now. One of the most accepted packet interchange
- formats is the one defined by libpcap, which is rather old and does
- not fit for some of the nowadays applications especially in terms of
- extensibility.
-
- This document proposes a new format for dumping packet traces. The
- following goals are being pursued:
-
- o Extensibility: aside of some common functionalities, third parties
- should be able to enrich the information embedded in the file with
- proprietary extensions, which will be ignored by tools that are
- not able to understand them.
-
- o Portability: a capture trace must contain all the information
- needed to read data independently from network, hardware and
- operating system of the machine that made the capture.
-
- o Merge/Append data: it should be possible to add data at the end of
- a given file, and the resulting file must still be readable.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 3]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
-2. General File Structure
-
-2.1 General Block Structure
-
- A capture file is organized in blocks, that are appended one to
- another to form the file. All the blocks share a common format, which
- is shown in Figure 1.
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Block Type |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Block Total Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / Block Body /
- / /* variable length, aligned to 32 bits */ /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Block Total Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Figure 1: Basic block structure.
-
- The fields have the following meaning:
-
- o Block Type (32 bits): unique value that identifies the block.
- Values whose Most Significant Bit (MSB) is equal to 1 are reserved
- for local use. They allow to save private data to the file and to
- extend the file format.
-
- o Block Total Length: total size of this block, in bytes. For
- instance, a block that does not have a body has a length of 12
- bytes.
-
- o Block Body: content of the block.
-
- o Block Total Length: total size of this block, in bytes. This field
- is duplicated for permitting backward file navigation.
-
- This structure, shared among all blocks, makes easy to process a file
- and to skip unneeded or unknown blocks. Blocks can be nested one
- inside the others (NOTE: needed?). Some of the blocks are mandatory,
- i.e. a dump file is not valid if they are not present, other are
- optional.
-
- The structure of the blocks allows to define other blocks if needed.
- A parser that does non understand them can simply ignore their
- content.
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 4]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
-2.2 Block Types
-
- The currently defined blocks are the following:
-
- 1. Section Header Block: it defines the most important
- characteristics of the capture file.
-
- 2. Interface Description Block: it defines the most important
- characteristics of the interface(s) used for capturing traffic.
-
- 3. Packet Block: it contains a single captured packet, or a portion
- of it.
-
- 4. Simple Packet Block: it contains a single captured packet, or a
- portion of it, with only a minimal set of information about it.
-
- 5. Name Resolution Block: it defines the mapping from numeric
- addresses present in the packet dump and the canonical name
- counterpart.
-
- 6. Capture Statistics Block: it defines how to store some
- statistical data (e.g. packet dropped, etc) which can be useful
- to undestand the conditions in which the capture has been made.
-
- 7. Compression Marker Block: TODO
-
- 8. Encryption Marker Block: TODO
-
- 9. Fixed Length Marker Block: TODO
-
- The following blocks instead are considered interesting but the
- authors believe that they deserve more in-depth discussion before
- being defined:
-
- 1. Further Packet Blocks
-
- 2. Directory Block
-
- 3. Traffic Statistics and Monitoring Blocks
-
- 4. Alert and Security Blocks
-
- TODO Currently standardized Block Type codes are specified in
- Appendix 1.
-
-2.3 Block Hierarchy and Precedence
-
- The file must begin with a Section Header Block. However, more than
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 5]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- one Section Header Block can be present on the dump, each one
- covering the data following it till the next one (or the end of
- file). A Section includes the data delimited by two Section Header
- Blocks (or by a Section Header Block and the end of the file),
- including the first Section Header Block.
-
- In case an application cannot read a Section because of different
- version number, it must skip everything until the next Section Header
- Block. Note that, in order to properly skip the blocks until the next
- section, all blocks must have the fields Type and Length at the
- beginning. This is a mandatory requirement that must be maintained in
- future versions of the block format.
-
- Figure 2 shows two valid files: the first has a typical
- configuration, with a single Section Header that covers the whole
- file. The second one contains three headers, and is normally the
- result of file concatenation. An application that understands only
- version 1.0 of the file format skips the intermediate section and
- restart processing the packets after the third Section Header.
-
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | SHB v1.0 | Data |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Typical configuration with a single Section Header Block
-
-
- |-- 1st Section --|-- 2nd Section --|-- 3rd Section --|
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | SHB v1.0 | Data | SHB V1.1 | Data | SHB V1.0 | Data |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Configuration with three different Section Header Blocks
-
- Figure 2: File structure example: the Section Header Block.
-
- NOTE: TO BE COMPLETED with some examples of other blocks
-
-2.4 Data format
-
- Data contained in each section will always be saved according to the
- characteristics (little endian / big endian) of the dumping machine.
- This refers to all fields that are saved as numbers and that span
- over two or more bytes.
-
- The approach of having each section saved in the native format of the
- generating host is more efficient because it avoids translation of
- data when reading / writing on the host itself, which is the most
- common case when generating/processing capture dumps.
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 6]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- TODO Probably we have to specify something more here. Is what we're
- saying enough to avoid any kind of ambiguity?.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 7]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
-3. Block Definition
-
- This section details the format of the body of the blocks currently
- defined.
-
-3.1 Section Header Block (mandatory)
-
- The Section Header Block is mandatory. It identifies the beginning of
- a section of the capture dump file. Its format is shown in Figure 3.
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Magic |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Major | Minor |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Figure 3: Section Header Block format.
-
- The meaning of the fields is:
-
- o Magic: magic number, whose value is the hexadecimal number
- 0x1A2B3C4D. This number can be used to distinguish section that
- have been saved on little-endian machines from the one saved on
- big-endian machines.
-
- o Major: number of the current mayor version of the format. Current
- value is 1.
-
- o Minor: number of the current minor version of the format. Current
- value is 0.
-
- o Options: optionally, a list of options (formatted according to the
- rules defined in Section 4) can be present.
-
- Aside form the options defined in Section 4, the following options
- are valid within this block:
-
- +----------------+----------------+----------------+----------------+
- | Name | Code | Length | Description |
- +----------------+----------------+----------------+----------------+
- | Hardware | 2 | variable | An ascii |
- | | | | string |
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 8]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- | | | | containing the |
- | | | | description of |
- | | | | the hardware |
- | | | | used to create |
- | | | | this section. |
- | | | | |
- | Operating | 3 | variable | An ascii |
- | System | | | string |
- | | | | containing the |
- | | | | name of the |
- | | | | operating |
- | | | | system used to |
- | | | | create this |
- | | | | section. |
- | | | | |
- | User | 3 | variable | An ascii |
- | Application | | | string |
- | | | | containing the |
- | | | | name of the |
- | | | | application |
- | | | | used to create |
- | | | | this section. |
- +----------------+----------------+----------------+----------------+
-
- Table 1
-
- The Section Header Block does not contain data but it rather
- identifies a list of blocks (interfaces, packets) that are logically
- correlated. This block does not contain any reference to the size of
- the section it is currently delimiting, therefore the reader cannot
- skip a whole section at once. In case a section must be skipped, the
- user has to repeatedly skip all the blocks contained within it; this
- makes the parsing of the file slower but it permits to append several
- capture dumps at the same file.
-
-3.2 Interface Description Block (mandatory)
-
- The Interface Description Block is mandatory. This block is needed to
- specify the characteristics of the network interface on which the
- capture has been made. In order to properly associate the captured
- data to the corresponding interface, the Interface Description Block
- must be defined before any other block that uses it; therefore, this
- block is usually placed immediately after the Section Header Block.
-
- An Interface Description Block is valid only inside the section which
- it belongs to. The structure of a Interface Description Block is
- shown in Figure 4.
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 9]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Interface ID | LinkType |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | SnapLen |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Figure 4: Interface Description Block format.
-
- The meaning of the fields is:
-
- o Interface ID: a progressive number that identifies uniquely any
- interface inside current section. Two Interface Description Blocks
- can have the same Interface ID only if they are in different
- sections of the file. The Interface ID is referenced by the packet
- blocks.
-
- o LinkType: a value that defines the link layer type of this
- interface.
-
- o SnapLen: maximum number of bytes dumped from each packet. The
- portion of each packet that exceeds this value will not be stored
- in the file.
-
- o Options: optionally, a list of options (formatted according to the
- rules defined in Section 4) can be present.
-
- In addition to the options defined in Section 4, the following
- options are valid within this block:
-
- +----------------+----------------+----------------+----------------+
- | Name | Code | Length | Description |
- +----------------+----------------+----------------+----------------+
- | if_name | 2 | Variable | Name of the |
- | | | | device used to |
- | | | | capture data. |
- | | | | |
- | if_IPv4addr | 3 | 8 | Interface |
- | | | | network |
- | | | | address and |
- | | | | netmask. |
- | | | | |
- | if_IPv6addr | 4 | 17 | Interface |
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 10]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- | | | | network |
- | | | | address and |
- | | | | prefix length |
- | | | | (stored in the |
- | | | | last byte). |
- | | | | |
- | if_MACaddr | 5 | 6 | Interface |
- | | | | Hardware MAC |
- | | | | address (48 |
- | | | | bits). |
- | | | | |
- | if_EUIaddr | 6 | 8 | Interface |
- | | | | Hardware EUI |
- | | | | address (64 |
- | | | | bits), if |
- | | | | available. |
- | | | | |
- | if_speed | 7 | 8 | Interface |
- | | | | speed (in |
- | | | | bps). |
- | | | | |
- | if_tsaccur | 8 | 1 | Precision of |
- | | | | timestamps. If |
- | | | | the Most |
- | | | | Significant |
- | | | | Bit is equal |
- | | | | to zero, the |
- | | | | remaining bits |
- | | | | indicates the |
- | | | | accuracy as as |
- | | | | a negative |
- | | | | power of 10 |
- | | | | (e.g. 6 means |
- | | | | microsecond |
- | | | | accuracy). If |
- | | | | the Most |
- | | | | Significant |
- | | | | Bit is equal |
- | | | | to zero, the |
- | | | | remaining bits |
- | | | | indicates the |
- | | | | accuracy as as |
- | | | | negative power |
- | | | | of 2 (e.g. 10 |
- | | | | means 1/1024 |
- | | | | of second). If |
- | | | | this option is |
- | | | | not present, a |
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 11]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- | | | | precision of |
- | | | | 10^-6 is |
- | | | | assumed. |
- | | | | |
- | if_tzone | 9 | 4 | Time zone for |
- | | | | GMT support |
- | | | | (TODO: specify |
- | | | | better). |
- | | | | |
- | if_flags | 10 | 4 | Interface |
- | | | | flags. (TODO: |
- | | | | specify |
- | | | | better. |
- | | | | Possible |
- | | | | flags: |
- | | | | promiscuous, |
- | | | | inbound/outbou |
- | | | | nd, traffic |
- | | | | filtered |
- | | | | during |
- | | | | capture). |
- | | | | |
- | if_filter | 11 | variable | The filter |
- | | | | (e.g. "capture |
- | | | | only TCP |
- | | | | traffic") used |
- | | | | to capture |
- | | | | traffic. The |
- | | | | first byte of |
- | | | | the Option |
- | | | | Data keeps a |
- | | | | code of the |
- | | | | filter used |
- | | | | (e.g. if this |
- | | | | is a libpcap |
- | | | | string, or BPF |
- | | | | bytecode, and |
- | | | | more). More |
- | | | | details about |
- | | | | this format |
- | | | | will be |
- | | | | presented in |
- | | | | Appendix XXX |
- | | | | (TODO). |
- | | | | |
- | if_opersystem | 12 | variable | An ascii |
- | | | | string |
- | | | | containing the |
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 12]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- | | | | name of the |
- | | | | operating |
- | | | | system of the |
- | | | | machine that |
- | | | | hosts this |
- | | | | interface. |
- | | | | This can be |
- | | | | different from |
- | | | | the same |
- | | | | information |
- | | | | that can be |
- | | | | contained by |
- | | | | the Section |
- | | | | Header Block |
- | | | | (Section 3.1) |
- | | | | because the |
- | | | | capture can |
- | | | | have been done |
- | | | | on a remote |
- | | | | machine. |
- +----------------+----------------+----------------+----------------+
-
- Table 2
-
-
-3.3 Packet Block (optional)
-
- A Packet Block is the standard container for storing the packets
- coming from the network. The Packet Block is optional because packets
- can be stored either by means of this block or the Simple Packet
- Block, which can be used to speed up dump generation. The format of a
- packet block is shown in Figure 5.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 13]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Interface ID | Drops Count |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Timestamp (High) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Timestamp (Low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Captured Len |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Packet Len |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | |
- | Packet Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Figure 5: Packet Block format.
-
- The Packet Block has the following fields:
-
- o Interface ID: Specifies the interface this packet comes from, and
- corresponds to the ID of one of the Interface Description Blocks
- present in this section of the file (see Figure 4).
-
- o Drops Count: a local drop counter. It specified the number of
- packets lost (by the interface and the operating system) between
- this packet and the preceding one. The value xFFFF (in
- hexadecimal) is reserved for those systems in which this
- information is not available.
-
- o Timestamp (High): the most significative part of the timestamp. in
- standard Unix format, i.e. from 1/1/1970.
-
- o Timestamp (Low): the less significative part of the timestamp. The
- way to interpret this field is specified by the 'ts_accur' option
- (see Figure 4) of the Interface Description block referenced by
- this packet. If the Interface Description block does not contain a
- 'ts_accur' option, then this field is expressed in microseconds.
-
- o Captured Len: number of bytes captured from the packet (i.e. the
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 14]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- length of the Packet Data field). It will be the minimum value
- among the actual Packet Length and the snapshot length (defined in
- Figure 4).
-
- o Packet Len: actual length of the packet when it was transmitted on
- the network. Can be different from Captured Len if the user wants
- only a snapshot of the packet.
-
- o Packet Data: the data coming from the network, including
- link-layer headers. The length of this field is Captured Len. The
- format of the link-layer headers depends on the LinkType field
- specified in the Interface Description Block (see Section 3.2) and
- it is specified in Appendix XXX (TODO).
-
- o Options: optionally, a list of options (formatted according to the
- rules defined in Section 4) can be present.
-
-
-3.4 Simple Packet Block (optional)
-
- The Simple Packet Block is a lightweight container for storing the
- packets coming from the network. Its presence is optional.
-
- A Simple Packet Block is similar to a Packet Block (see Section 3.3),
- but it is smaller, simpler to process and contains only a minimal set
- of information. This block is preferred to the standard Packet Block
- when performance or space occupation are critical factors, such as in
- sustained traffic dump applications. A capture file can contain both
- Packet Blocks and Simple Packet Blocks: for example, a capture tool
- could switch from Packet Blocks to Simple Packet Blocks when the
- hardware resources become critical.
-
- The Simple Packet Block does not contain the Interface ID field.
- Therefore, it must be assumed that all the Simple Packet Blocks have
- been captured on the interface previously specified in the Interface
- Description Block.
-
- Figure 6 shows the format of the Simple Packet Block.
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 15]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Packet Len |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | |
- | Packet Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Figure 6: Simple Packet Block format.
-
- The Packet Block has the following fields:
-
- o Packet Len: actual length of the packet when it was transmitted on
- the network. Can be different from captured len if the packet has
- been truncated.
-
- o Packet data: the data coming from the network, including
- link-layers headers. The length of this field can be derived from
- the field Block Total Length, present in the Block Header.
-
- The Simple Packet Block does not contain the timestamp because this
- is one of the most costly operations on PCs. Additionally, there are
- applications that do not require it; e.g. an Intrusion Detection
- System is interested in packets, not in their timestamp.
-
- The Simple Packet Block is very efficient in term of disk space: a
- snapshot of length 100 bytes requires only 16 bytes of overhead,
- which corresponds to an efficiency of more than 86%.
-
-3.5 Name Resolution Block (optional)
-
- The Name Resolution Block is used to support the correlation of
- numeric addresses (present in the captured packets) and their
- corresponding canonical names and it is optional. Having the literal
- names saved in the file, this prevents the need of a name resolution
- in a delayed time, when the association between names and addresses
- can be different from the one in use at capture time. Moreover, The
- Name Resolution Block avoids the need of issuing a lot of DNS
- requests every time the trace capture is opened, and allows to have
- name resolution also when reading the capture with a machine not
- connected to the network.
-
- The format of the Name Resolution Block is shown in Figure 7.
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 16]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Record Type | Record Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Record Value |
- | /* variable length, byte-aligned */ |
- | + + + + + + + + + + + + + + + + + + + + + + + + +
- | | | | |
- +-+-+-+-+-+-+-+-+ + + + + + + + + + + + + + + + + + + + + + + + +
- . . . other records . . .
- | Record Type == end_of_recs | Record Length == 00 |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Figure 7: Name Resolution Block format.
-
- A Name Resolution Block is a zero-terminated list of records (in the
- TLV format), each of which contains an association between a network
- address and a name. There are three possible types of records:
-
- +----------------+----------------+----------------+----------------+
- | Name | Code | Length | Description |
- +----------------+----------------+----------------+----------------+
- | end_of_recs | 0 | 0 | End of records |
- | | | | |
- | ip4_rec | 1 | Variable | Specifies an |
- | | | | IPv4 address |
- | | | | (contained in |
- | | | | the first 4 |
- | | | | bytes), |
- | | | | followed by |
- | | | | one or more |
- | | | | zero-terminate |
- | | | | d strings |
- | | | | containing the |
- | | | | DNS entries |
- | | | | for that |
- | | | | address. |
- | | | | |
- | ip6_rec | 1 | Variable | Specifies an |
- | | | | IPv6 address |
- | | | | (contained in |
- | | | | the first 16 |
- | | | | bytes), |
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 17]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- | | | | followed by |
- | | | | one or more |
- | | | | zero-terminate |
- | | | | d strings |
- | | | | containing the |
- | | | | DNS entries |
- | | | | for that |
- | | | | address. |
- +----------------+----------------+----------------+----------------+
-
- Table 3
-
- After the list or Name Resolution Records, optionally, a list of
- options (formatted according to the rules defined in Section 4) can
- be present.
-
- A Name Resolution Block is normally placed at the beginning of the
- file, but no assumptions can be taken about its position. Name
- Resolution Blocks can be added in a second time by tools that process
- the file, like network analyzers.
-
- In addiction to the options defined in Section 4, the following
- options are valid within this block:
-
- +----------------+----------------+----------------+----------------+
- | Name | Code | Length | Description |
- +----------------+----------------+----------------+----------------+
- | ns_dnsname | 2 | Variable | An ascii |
- | | | | string |
- | | | | containing the |
- | | | | name of the |
- | | | | machine (DNS |
- | | | | server) used |
- | | | | to perform the |
- | | | | name |
- | | | | resolution. |
- +----------------+----------------+----------------+----------------+
-
-
-3.6 Interface Statistics Block (optional)
-
- The Interface Statistics Block contains the capture statistics for a
- given interface and it is optional. The statistics are referred to
- the interface defined in the current Section identified by the
- Interface ID field.
-
- The format of the Interface Statistics Block is shown in Figure 8.
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 18]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | IfRecv |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | IfDrop |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | FilterAccept |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | OSDrop |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | UsrDelivered |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Interface ID | Reserved |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Figure 8: Interface Statistics Block format.
-
- The fields have the following meaning:
-
- o IfRecv: number of packets received from the interface during the
- capture. This number is reported as a 64 bits value, in which the
- most significat bits are located in the first four bytes of the
- field.
-
- o IfDrop: number of packets dropped by the interface during the
- capture due to lack of resources.
-
- o FilterAccept: number of packets accepeted by filter during current
- capture.
-
- o OSDrop: number of packets dropped by the operating system during
- the capture.
-
- o UsrDelivered: number of packets delivered to the user.
- UsrDelivered can be different from the value 'FilterAccept -
- OSDropped' because some packets could still lay in the OS buffers
- when the capture ended.
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 19]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- o Interface ID: reference to an Interface Description Block.
-
- o Reserved: Reserved to future use.
-
- o Options: optionally, a list of options (formatted according to the
- rules defined in Section 4) can be present.
-
- In addiction to the options defined in Section 4, the following
- options are valid within this block:
-
- +----------------+----------------+----------------+----------------+
- | Name | Code | Length | Description |
- +----------------+----------------+----------------+----------------+
- | isb_starttime | 2 | 8 | Time in which |
- | | | | the capture |
- | | | | started; time |
- | | | | will be stored |
- | | | | in two blocks |
- | | | | of four bytes |
- | | | | each, |
- | | | | containing the |
- | | | | timestamp in |
- | | | | seconds and |
- | | | | nanoseconds. |
- | | | | |
- | isb_endtime | 3 | 8 | Time in which |
- | | | | the capture |
- | | | | started; time |
- | | | | will be stored |
- | | | | in two blocks |
- | | | | of four bytes |
- | | | | each, |
- | | | | containing the |
- | | | | timestamp in |
- | | | | seconds and |
- | | | | nanoseconds. |
- +----------------+----------------+----------------+----------------+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 20]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
-4. Options
-
- Almost all blocks have the possibility to embed optional fields.
- Optional fields can be used to insert some information that may be
- useful when reading data, but that it is not really needed for packet
- processing. Therefore, each tool can be either read the content of
- the optional fields (if any), or skip them at once.
-
- Skipping all the optional fields at once is straightforward because
- most of the blocks have a fixed length, therefore the field Block
- Length (present in the General Block Structure, see Section 2.1) can
- be used to skip everything till the next block.
-
- Options are a list of Type - Length - Value fields, each one
- containing a single value:
-
- o Option Type (2 bytes): it contains the code that specifies the
- type of the current TLV record. Option types whose Most
- Significant Bit is equal to one are reserved for local use;
- therefore, there is no guarantee that the code used is unique
- among all capture files (generated by other applications). In case
- of vendor-specific extensions that have to be identified uniquely,
- vendors must request an Option Code whose MSB is equal to zero.
-
- o Option Length (2 bytes): it contains the length of the following
- 'Option Value' field.
-
- o Option Value (variable length): it contains the value of the given
- option. The length of this field as been specified by the Option
- Length field.
-
- Options may be repeated several times (e.g. an interface that has
- several IP addresses associated to it). The option list is terminated
- by a special code which is the 'End of Option'.
-
- The format of the optional fields is shown in Figure 9.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 21]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Option Code | Option Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Option Value |
- | /* variable length, byte-aligned */ |
- | + + + + + + + + + + + + + + + + + + + + + + + + +
- | / / / |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / . . . other options . . . /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Option Code == opt_endofopt | Option Length == 0 |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Figure 9: Options format.
-
- The following codes can always be present in any optional field:
-
- +----------------+----------------+----------------+----------------+
- | Name | Code | Length | Description |
- +----------------+----------------+----------------+----------------+
- | opt_endofopt | 0 | 0 | End of |
- | | | | options: it is |
- | | | | used to |
- | | | | delimit the |
- | | | | end of the |
- | | | | optional |
- | | | | fields. This |
- | | | | block cannot |
- | | | | be repeated |
- | | | | within a given |
- | | | | list of |
- | | | | options. |
- | | | | |
- | opt_comment | 1 | variable | Comment: it is |
- | | | | an ascii |
- | | | | string |
- | | | | containing a |
- | | | | comment that |
- | | | | is associated |
- | | | | to the current |
- | | | | block. |
- +----------------+----------------+----------------+----------------+
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 22]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
-5. Experimental Blocks (deserved to a further investigation)
-
-5.1 Other Packet Blocks (experimental)
-
- Can some other packet blocks (besides the two described in the
- previous paragraphs) be useful?
-
-5.2 Compression Block (experimental)
-
- The Compression Block is optional. A file can contain an arbitrary
- number of these blocks. A Compression Block, as the name says, is
- used to store compressed data. Its format is shown in Figure 10.
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Compr. Type | |
- +-+-+-+-+-+-+-+-+ |
- | |
- | Compressed Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Figure 10: Compression Block format.
-
- The fields have the following meaning:
-
- o Compression Type: specifies the compression algorithm. Possible
- values for this field are 0 (uncompressed), 1 (Lempel Ziv), 2
- (Gzip), other?? Probably some kind of dumb and fast compression
- algorithm could be effective with some types of traffic (for
- example web), but which?
-
- o Compressed Data: data of this block. Once decompressed, it is made
- of other blocks.
-
-
-5.3 Encryption Block (experimental)
-
- The Encryption Block is optional. A file can contain an arbitrary
- number of these blocks. An Encryption Block is used to sotre
- encrypted data. Its format is shown in Figure 11.
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 23]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Encr. Type | |
- +-+-+-+-+-+-+-+-+ |
- | |
- | Compressed Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Figure 11: Encryption Block format.
-
- The fields have the following meaning:
-
- o Compression Type: specifies the encryption algorithm. Possible
- values for this field are ??? NOTE: this block should probably
- contain other fields, depending on the encryption algorithm. To be
- define precisely.
-
- o Encrypted Data: data of this block. Once decripted, it consists of
- other blocks.
-
-
-5.4 Fixed Length Block (experimental)
-
- The Fixed Length Block is optional. A file can contain an arbitrary
- number of these blocks. A Fixed Length Block can be used to optimize
- the access to the file. Its format is shown in Figure 12. A Fixed
- Length Block stores records with constant size. It contains a set of
- Blocks (normally Packet Blocks or Simple Packet Blocks), of wihich it
- specifies the size. Knowing this size a priori helps to scan the file
- and to load some portions of it without truncating a block, and is
- particularly useful with cell-based networks like ATM.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 24]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Cell Size | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- | |
- | Fixed Size Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Figure 12: Fixed Length Block format.
-
- The fields have the following meaning:
-
- o Cell size: the size of the blocks contained in the data field.
-
- o Fixed Size Data: data of this block.
-
-
-5.5 Directory Block (experimental)
-
- If present, this block contains the following information:
-
- o number of indexed packets (N)
-
- o table with position and length of any indexed packet (N entries)
-
- A directory block must be followed by at least N packets, otherwise
- it must be considered invalid. It can be used to efficiently load
- portions of the file to memory and to support operations on memory
- mapped files. This block can be added by tools like network analyzers
- as a consequence of file processing.
-
-5.6 Traffic Statistics and Monitoring Blocks (experimental)
-
- One or more blocks could be defined to contain network statistics or
- traffic monitoring information. They could be use to store data
- collected from RMON or Netflow probes, or from other network
- monitoring tools.
-
-5.7 Event/Security Block (experimental)
-
- This block could be used to store events. Events could contain
- generic information (for example network load over 50%, server
- down...) or security alerts. An event could be:
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 25]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- o skipped, if the application doesn't know how to do with it
-
- o processed independently by the packets. In other words, the
- applications skips the packets and processes only the alerts
-
- o processed in relation to packets: for example, a security tool
- could load only the packets of the file that are near a security
- alert; a monitorg tool could skip the packets captured while the
- server was down.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 26]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
-6. Conclusions
-
- The file format proposed in this document should be very versatile
- and satisfy a wide range of applications. In the simplest case, it
- can contain a raw dump of the network data, made of a series of
- Simple Packet Blocks. In the most complex case, it can be used as a
- repository for heterogeneous information. In every case, the file
- remains easy to parse and an application can always skip the data it
- is not interested in; at the same time, different applications can
- share the file, and each of them can benfit of the information
- produced by the others. Two or more files can be concatenated
- obtaining another valid file.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 27]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
-7. Most important open issues
-
- o Data, in the file, must be byte or word aligned? Currently, the
- structure of this document is not consistent with respect to this
- point.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 28]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
-Intellectual Property Statement
-
- The IETF takes no position regarding the validity or scope of any
- intellectual property or other rights that might be claimed to
- pertain to the implementation or use of the technology described in
- this document or the extent to which any license under such rights
- might or might not be available; neither does it represent that it
- has made any effort to identify any such rights. Information on the
- IETF's procedures with respect to rights in standards-track and
- standards-related documentation can be found in BCP-11. Copies of
- claims of rights made available for publication and any assurances of
- licenses to be made available, or the result of an attempt made to
- obtain a general license or permission for the use of such
- proprietary rights by implementors or users of this specification can
- be obtained from the IETF Secretariat.
-
- The IETF invites any interested party to bring to its attention any
- copyrights, patents or patent applications, or other proprietary
- rights which may cover technology that may be required to practice
- this standard. Please address the information to the IETF Executive
- Director.
-
-
-Full Copyright Statement
-
- Copyright (C) The Internet Society (2004). All Rights Reserved.
-
- This document and translations of it may be copied and furnished to
- others, and derivative works that comment on or otherwise explain it
- or assist in its implementation may be prepared, copied, published
- and distributed, in whole or in part, without restriction of any
- kind, provided that the above copyright notice and this paragraph are
- included on all such copies and derivative works. However, this
- document itself may not be modified in any way, such as by removing
- the copyright notice or references to the Internet Society or other
- Internet organizations, except as needed for the purpose of
- developing Internet standards in which case the procedures for
- copyrights defined in the Internet Standards process must be
- followed, or as required to translate it into languages other than
- English.
-
- The limited permissions granted above are perpetual and will not be
- revoked by the Internet Society or its successors or assignees.
-
- This document and the information contained herein is provided on an
- "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
- TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
- BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 29]
-
-Internet-Draft PCAP New Generation Dump File Format March 2004
-
-
- HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
- MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
-
-
-Acknowledgment
-
- Funding for the RFC Editor function is currently provided by the
- Internet Society.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Degioanni & Risso Expires August 30, 2004 [Page 30]
-
diff --git a/contrib/libpcap/doc/pcap.xml b/contrib/libpcap/doc/pcap.xml
deleted file mode 100644
index ebbf321..0000000
--- a/contrib/libpcap/doc/pcap.xml
+++ /dev/null
@@ -1,746 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
-
-<!DOCTYPE rfc SYSTEM "rfc2629.dtd">
-<?rfc toc="yes"?>
-<rfc ipr="full2026" docname="draft-libpcap-dump-format-00.txt">
- <front>
- <title>PCAP New Generation Dump File Format</title>
- <author initials="L." surname="Degioanni" fullname="Loris Degioanni">
- <organization>Politecnico di Torino</organization>
- <address>
- <postal>
- <street>Corso Duca degli Abruzzi, 24</street>
- <city>Torino</city>
- <code>10129</code>
- <country>Italy</country>
- </postal>
- <phone>+39 011 564 7008</phone>
- <email>loris.degioanni@polito.it</email>
- <uri>http://netgroup.polito.it/loris/</uri>
- </address>
- </author>
- <author initials="F." surname="Risso" fullname="Fulvio Risso">
- <organization>Politecnico di Torino</organization>
- <address>
- <postal>
- <street>Corso Duca degli Abruzzi, 24</street>
- <city>Torino</city>
- <code>10129</code>
- <country>Italy</country>
- </postal>
- <phone>+39 011 564 7008</phone>
- <email>fulvio.risso@polito.it</email>
- <uri>http://netgroup.polito.it/fulvio.risso/</uri>
- </address>
- </author>
-
- <!-- Other authors go here -->
-
- <date month="March" year="2004"/>
- <area>General</area>
-<!--
- <workgroup>
--->
- <keyword>Internet-Draft</keyword>
- <keyword>Libpcap, dump file format</keyword>
- <abstract>
-<t>This document describes a format to dump captured packets on a file. This format is extensible and it is currently proposed for implementation in the libpcap/WinPcap packet capture library.</t>
- </abstract>
-<!--
- <note ...>
--->
- </front>
- <middle>
-
-<section title="Objectives">
-<t>The problem of exchanging packet traces becomes more and more critical every day; unfortunately, no standard solutions exist for this task right now. One of the most accepted packet interchange formats is the one defined by libpcap, which is rather old and does not fit for some of the nowadays applications especially in terms of extensibility.</t>
-<t>This document proposes a new format for dumping packet traces. The following goals are being pursued:</t>
-<list style="symbols">
-<t>Extensibility: aside of some common functionalities, third parties should be able to enrich the information embedded in the file with proprietary extensions, which will be ignored by tools that are not able to understand them.</t>
-<t>Portability: a capture trace must contain all the information needed to read data independently from network, hardware and operating system of the machine that made the capture.</t>
-<t>Merge/Append data: it should be possible to add data at the end of a given file, and the resulting file must still be readable.</t>
-</list>
-
-</section>
-
-
-<section title="General File Structure">
-
-<section anchor="sectionblock" title="General Block Structure">
-<t>A capture file is organized in blocks, that are appended one to another to form the file. All the blocks share a common format, which is shown in <xref target="formatblock"/>.</t>
-
-<figure anchor="formatblock" title="Basic block structure.">
-<artwork>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Block Type |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Block Total Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / Block Body /
- / /* variable length, aligned to 32 bits */ /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Block Total Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-</artwork>
-</figure>
-
-<t>The fields have the following meaning:</t>
-
-<list style="symbols">
-<t>Block Type (32 bits): unique value that identifies the block. Values whose Most Significant Bit (MSB) is equal to 1 are reserved for local use. They allow to save private data to the file and to extend the file format.</t>
-<t>Block Total Length: total size of this block, in bytes. For instance, a block that does not have a body has a length of 12 bytes.</t>
-<t>Block Body: content of the block.</t>
-<t>Block Total Length: total size of this block, in bytes. This field is duplicated for permitting backward file navigation.</t>
-</list>
-
-<t>This structure, shared among all blocks, makes easy to process a file and to skip unneeded or unknown blocks. Blocks can be nested one inside the others (NOTE: needed?). Some of the blocks are mandatory, i.e. a dump file is not valid if they are not present, other are optional.</t>
-<t>The structure of the blocks allows to define other blocks if needed. A parser that does non understand them can simply ignore their content.</t>
-</section>
-
-<section title="Block Types">
-<t>The currently defined blocks are the following:</t>
-<list style="numbers">
-<t>Section Header Block: it defines the most important characteristics of the capture file.</t>
-<t>Interface Description Block: it defines the most important characteristics of the interface(s) used for capturing traffic.</t>
-<t>Packet Block: it contains a single captured packet, or a portion of it.</t>
-<t>Simple Packet Block: it contains a single captured packet, or a portion of it, with only a minimal set of information about it.</t>
-<t>Name Resolution Block: it defines the mapping from numeric addresses present in the packet dump and the canonical name counterpart.</t>
-<t>Capture Statistics Block: it defines how to store some statistical data (e.g. packet dropped, etc) which can be useful to undestand the conditions in which the capture has been made.</t>
-<t>Compression Marker Block: TODO</t>
-<t>Encryption Marker Block: TODO</t>
-<t>Fixed Length Marker Block: TODO</t>
-</list>
-
-<t>The following blocks instead are considered interesting but the authors believe that they deserve more in-depth discussion before being defined:</t>
-<list style="numbers">
-<t>Further Packet Blocks</t>
-<t>Directory Block</t>
-<t>Traffic Statistics and Monitoring Blocks</t>
-<t>Alert and Security Blocks</t>
-</list>
-
-<t>TODO Currently standardized Block Type codes are specified in Appendix 1.</t>
-
-</section>
-
-<section title="Block Hierarchy and Precedence">
-<t>The file must begin with a Section Header Block. However, more than one Section Header Block can be present on the dump, each one covering the data following it till the next one (or the end of file). A Section includes the data delimited by two Section Header Blocks (or by a Section Header Block and the end of the file), including the first Section Header Block.</t>
-<t>In case an application cannot read a Section because of different version number, it must skip everything until the next Section Header Block. Note that, in order to properly skip the blocks until the next section, all blocks must have the fields Type and Length at the beginning. This is a mandatory requirement that must be maintained in future versions of the block format.</t>
-<t><xref target="fssample-SHB"/> shows two valid files: the first has a typical configuration, with a single Section Header that covers the whole file. The second one contains three headers, and is normally the result of file concatenation. An application that understands only version 1.0 of the file format skips the intermediate section and restart processing the packets after the third Section Header.</t>
-
-<figure anchor="fssample-SHB" title="File structure example: the Section Header Block.">
-<artwork>
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | SHB v1.0 | Data |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Typical configuration with a single Section Header Block
-
-
- |-- 1st Section --|-- 2nd Section --|-- 3rd Section --|
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | SHB v1.0 | Data | SHB V1.1 | Data | SHB V1.0 | Data |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- Configuration with three different Section Header Blocks
-</artwork>
-</figure>
-
-<t>NOTE: TO BE COMPLETED with some examples of other blocks</t>
-
-</section>
-
-<section title="Data format">
-<t>Data contained in each section will always be saved according to the characteristics (little endian / big endian) of the dumping machine. This refers to all fields that are saved as numbers and that span over two or more bytes.</t>
-<t>The approach of having each section saved in the native format of the generating host is more efficient because it avoids translation of data when reading / writing on the host itself, which is the most common case when generating/processing capture dumps.</t>
-<t>TODO Probably we have to specify something more here. Is what we're saying enough to avoid any kind of ambiguity?.</t>
-</section>
-
-</section>
-
-
-
-
-<section title="Block Definition">
-<t>This section details the format of the body of the blocks currently defined.</t>
-
-<section anchor="sectionshb" title="Section Header Block (mandatory)">
-<t>The Section Header Block is mandatory. It identifies the beginning of a section of the capture dump file. Its format is shown in <xref target="formatSHB"/>.</t>
-<figure anchor="formatSHB" title="Section Header Block format.">
-<artwork>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Magic |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Major | Minor |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-</artwork>
-</figure>
-
-<t>The meaning of the fields is:</t>
-<list style="symbols">
-<t>Magic: magic number, whose value is the hexadecimal number 0x1A2B3C4D. This number can be used to distinguish section that have been saved on little-endian machines from the one saved on big-endian machines.</t>
-<t>Major: number of the current mayor version of the format. Current value is 1.</t>
-<t>Minor: number of the current minor version of the format. Current value is 0.</t>
-<t>Options: optionally, a list of options (formatted according to the rules defined in <xref target="sectionopt"/>) can be present.</t>
-</list>
-
-<t>Aside form the options defined in <xref target="sectionopt"/>, the following options are valid within this block:</t>
-
-<texttable anchor="InterfaceOptions1">
- <ttcol>Name</ttcol>
- <ttcol>Code</ttcol>
- <ttcol>Length</ttcol>
- <ttcol>Description</ttcol>
-
- <c>Hardware</c>
- <c>2</c>
- <c>variable</c>
- <c>An ascii string containing the description of the hardware used to create this section.</c>
-
- <c>Operating System</c>
- <c>3</c>
- <c>variable</c>
- <c>An ascii string containing the name of the operating system used to create this section.</c>
-
- <c>User Application</c>
- <c>3</c>
- <c>variable</c>
- <c>An ascii string containing the name of the application used to create this section.</c>
-</texttable>
-
-
-<t>The Section Header Block does not contain data but it rather identifies a list of blocks (interfaces, packets) that are logically correlated. This block does not contain any reference to the size of the section it is currently delimiting, therefore the reader cannot skip a whole section at once. In case a section must be skipped, the user has to repeatedly skip all the blocks contained within it; this makes the parsing of the file slower but it permits to append several capture dumps at the same file.</t>
-</section>
-
-<section anchor="sectionidb" title="Interface Description Block (mandatory)">
-<t>The Interface Description Block is mandatory. This block is needed to specify the characteristics of the network interface on which the capture has been made. In order to properly associate the captured data to the corresponding interface, the Interface Description Block must be defined before any other block that uses it; therefore, this block is usually placed immediately after the Section Header Block.</t>
-
-<t>An Interface Description Block is valid only inside the section which it belongs to. The structure of a Interface Description Block is shown in <xref target="formatidb"/>.</t>
-
-<figure anchor="formatidb" title="Interface Description Block format.">
-<artwork>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Interface ID | LinkType |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | SnapLen |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </artwork>
-</figure>
-
-<t>The meaning of the fields is:</t>
-<list style="symbols">
-<t>Interface ID: a progressive number that identifies uniquely any interface inside current section. Two Interface Description Blocks can have the same Interface ID only if they are in different sections of the file. The Interface ID is referenced by the packet blocks.</t>
-<t>LinkType: a value that defines the link layer type of this interface.</t>
-<t>SnapLen: maximum number of bytes dumped from each packet. The portion of each packet that exceeds this value will not be stored in the file.</t>
-<t>Options: optionally, a list of options (formatted according to the rules defined in <xref target="sectionopt"/>) can be present.</t>
-</list>
-
-<t>In addition to the options defined in <xref target="sectionopt"/>, the following options are valid within this block:</t>
-
-<texttable anchor="InterfaceOptions2">
- <ttcol>Name</ttcol>
- <ttcol>Code</ttcol>
- <ttcol>Length</ttcol>
- <ttcol>Description</ttcol>
-
- <c>if_name</c>
- <c>2</c>
- <c>Variable</c>
- <c>Name of the device used to capture data.</c>
-
- <c>if_IPv4addr</c>
- <c>3</c>
- <c>8</c>
- <c>Interface network address and netmask.</c>
-
- <c>if_IPv6addr</c>
- <c>4</c>
- <c>17</c>
- <c>Interface network address and prefix length (stored in the last byte).</c>
-
- <c>if_MACaddr</c>
- <c>5</c>
- <c>6</c>
- <c>Interface Hardware MAC address (48 bits).</c>
-
- <c>if_EUIaddr</c>
- <c>6</c>
- <c>8</c>
- <c>Interface Hardware EUI address (64 bits), if available.</c>
-
- <c>if_speed</c>
- <c>7</c>
- <c>8</c>
- <c>Interface speed (in bps).</c>
-
- <c>if_tsaccur</c>
- <c>8</c>
- <c>1</c>
- <c>Precision of timestamps. If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as a negative power of 10 (e.g. 6 means microsecond accuracy). If the Most Significant Bit is equal to zero, the remaining bits indicates the accuracy as as negative power of 2 (e.g. 10 means 1/1024 of second). If this option is not present, a precision of 10^-6 is assumed.</c>
-
- <c>if_tzone</c>
- <c>9</c>
- <c>4</c>
- <c>Time zone for GMT support (TODO: specify better).</c>
-
- <c>if_flags</c>
- <c>10</c>
- <c>4</c>
- <c>Interface flags. (TODO: specify better. Possible flags: promiscuous, inbound/outbound, traffic filtered during capture).</c>
-
- <c>if_filter</c>
- <c>11</c>
- <c>variable</c>
- <c>The filter (e.g. "capture only TCP traffic") used to capture traffic. The first byte of the Option Data keeps a code of the filter used (e.g. if this is a libpcap string, or BPF bytecode, and more). More details about this format will be presented in Appendix XXX (TODO).</c>
-
- <c>if_opersystem</c>
- <c>12</c>
- <c>variable</c>
- <c>An ascii string containing the name of the operating system of the machine that hosts this interface. This can be different from the same information that can be contained by the Section Header Block (<xref target="sectionshb"/>) because the capture can have been done on a remote machine.</c>
-
-</texttable>
-
-</section>
-
-
-
-<section anchor="sectionpb" title="Packet Block (optional)">
-<t>A Packet Block is the standard container for storing the packets coming from the network. The Packet Block is optional because packets can be stored either by means of this block or the Simple Packet Block, which can be used to speed up dump generation. The format of a packet block is shown in <xref target="formatpb"/>.</t>
-
-<figure anchor="formatpb" title="Packet Block format.">
-<artwork>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Interface ID | Drops Count |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Timestamp (High) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Timestamp (Low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Captured Len |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Packet Len |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | |
- | Packet Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-</artwork>
-</figure>
-
-<t>The Packet Block has the following fields:</t>
-
-<list style="symbols">
-<t>Interface ID: Specifies the interface this packet comes from, and corresponds to the ID of one of the Interface Description Blocks present in this section of the file (see <xref target="formatidb"/>).</t>
-<t>Drops Count: a local drop counter. It specified the number of packets lost (by the interface and the operating system) between this packet and the preceding one. The value xFFFF (in hexadecimal) is reserved for those systems in which this information is not available.</t>
-<t>Timestamp (High): the most significative part of the timestamp. in standard Unix format, i.e. from 1/1/1970.</t>
-<t>Timestamp (Low): the less significative part of the timestamp. The way to interpret this field is specified by the 'ts_accur' option (see <xref target="formatidb"/>) of the Interface Description block referenced by this packet. If the Interface Description block does not contain a 'ts_accur' option, then this field is expressed in microseconds.</t>
-<t>Captured Len: number of bytes captured from the packet (i.e. the length of the Packet Data field). It will be the minimum value among the actual Packet Length and the snapshot length (defined in <xref target="formatidb"/>).</t>
-<t>Packet Len: actual length of the packet when it was transmitted on the network. Can be different from Captured Len if the user wants only a snapshot of the packet.</t>
-<t>Packet Data: the data coming from the network, including link-layer headers. The length of this field is Captured Len. The format of the link-layer headers depends on the LinkType field specified in the Interface Description Block (see <xref target="sectionidb"/>) and it is specified in Appendix XXX (TODO).</t>
-<t>Options: optionally, a list of options (formatted according to the rules defined in <xref target="sectionopt"/>) can be present.</t>
-</list>
-
-<t></t>
-</section>
-
-
-<section title="Simple Packet Block (optional)">
-<t>The Simple Packet Block is a lightweight container for storing the packets coming from the network. Its presence is optional.</t>
-<t>A Simple Packet Block is similar to a Packet Block (see <xref target="sectionpb"/>), but it is smaller, simpler to process and contains only a minimal set of information. This block is preferred to the standard Packet Block when performance or space occupation are critical factors, such as in sustained traffic dump applications. A capture file can contain both Packet Blocks and Simple Packet Blocks: for example, a capture tool could switch from Packet Blocks to Simple Packet Blocks when the hardware resources become critical.</t>
-<t>The Simple Packet Block does not contain the Interface ID field. Therefore, it must be assumed that all the Simple Packet Blocks have been captured on the interface previously specified in the Interface Description Block.</t>
-<t><xref target="formatpbs"/> shows the format of the Simple Packet Block.</t>
-
-<figure anchor="formatpbs" title="Simple Packet Block format.">
-<artwork>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Packet Len |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | |
- | Packet Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </artwork>
-</figure>
-
-<t>The Packet Block has the following fields:</t>
-<list style="symbols">
-<t>Packet Len: actual length of the packet when it was transmitted on the network. Can be different from captured len if the packet has been truncated.</t>
-<t>Packet data: the data coming from the network, including link-layers headers. The length of this field can be derived from the field Block Total Length, present in the Block Header.</t>
-</list>
-
-<t>The Simple Packet Block does not contain the timestamp because this is one of the most costly operations on PCs. Additionally, there are applications that do not require it; e.g. an Intrusion Detection System is interested in packets, not in their timestamp.</t>
-
-<t>The Simple Packet Block is very efficient in term of disk space: a snapshot of length 100 bytes requires only 16 bytes of overhead, which corresponds to an efficiency of more than 86%.</t>
-
-</section>
-
-
-
-<section title="Name Resolution Block (optional)">
-<t>The Name Resolution Block is used to support the correlation of numeric addresses (present in the captured packets) and their corresponding canonical names and it is optional. Having the literal names saved in the file, this prevents the need of a name resolution in a delayed time, when the association between names and addresses can be different from the one in use at capture time. Moreover, The Name Resolution Block avoids the need of issuing a lot of DNS requests every time the trace capture is opened, and allows to have name resolution also when reading the capture with a machine not connected to the network.</t>
-<t>The format of the Name Resolution Block is shown in <xref target="formatnrb"/>.</t>
-
-<figure anchor="formatnrb" title="Name Resolution Block format.">
-<artwork>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Record Type | Record Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Record Value |
- | /* variable length, byte-aligned */ |
- | + + + + + + + + + + + + + + + + + + + + + + + + +
- | | | | |
- +-+-+-+-+-+-+-+-+ + + + + + + + + + + + + + + + + + + + + + + + +
- . . . other records . . .
- | Record Type == end_of_recs | Record Length == 00 |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </artwork>
-</figure>
-
-<t>A Name Resolution Block is a zero-terminated list of records (in the TLV format), each of which contains an association between a network address and a name. There are three possible types of records:</t>
-
-<texttable anchor="nrrecords">
- <ttcol>Name</ttcol>
- <ttcol>Code</ttcol>
- <ttcol>Length</ttcol>
- <ttcol>Description</ttcol>
-
- <c>end_of_recs</c>
- <c>0</c>
- <c>0</c>
- <c>End of records</c>
-
- <c>ip4_rec</c>
- <c>1</c>
- <c>Variable</c>
- <c>Specifies an IPv4 address (contained in the first 4 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address.</c>
-
- <c>ip6_rec</c>
- <c>1</c>
- <c>Variable</c>
- <c>Specifies an IPv6 address (contained in the first 16 bytes), followed by one or more zero-terminated strings containing the DNS entries for that address.</c>
-</texttable>
-
-<t>After the list or Name Resolution Records, optionally, a list of options (formatted according to the rules defined in <xref target="sectionopt"/>) can be present.</t>
-
-<t>A Name Resolution Block is normally placed at the beginning of the file, but no assumptions can be taken about its position. Name Resolution Blocks can be added in a second time by tools that process the file, like network analyzers.</t>
-
-<t>In addiction to the options defined in <xref target="sectionopt"/>, the following options are valid within this block:</t>
-
-<texttable>
- <ttcol>Name</ttcol>
- <ttcol>Code</ttcol>
- <ttcol>Length</ttcol>
- <ttcol>Description</ttcol>
-
- <c>ns_dnsname</c>
- <c>2</c>
- <c>Variable</c>
- <c>An ascii string containing the name of the machine (DNS server) used to perform the name resolution.</c>
-</texttable>
-
-</section>
-
-
-<section title="Interface Statistics Block (optional)">
-<t>The Interface Statistics Block contains the capture statistics for a given interface and it is optional. The statistics are referred to the interface defined in the current Section identified by the Interface ID field.</t>
-<t>The format of the Interface Statistics Block is shown in <xref target="formatisb"/>.</t>
-
-<figure anchor="formatisb" title="Interface Statistics Block format.">
-<artwork>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | IfRecv |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | IfDrop |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | FilterAccept |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | OSDrop |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | UsrDelivered |
- | (high + low) |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Interface ID | Reserved |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / Options (variable) /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </artwork>
-</figure>
-
-<t>The fields have the following meaning:</t>
-
-<list style="symbols">
-<t>IfRecv: number of packets received from the interface during the capture. This number is reported as a 64 bits value, in which the most significat bits are located in the first four bytes of the field.</t>
-<t>IfDrop: number of packets dropped by the interface during the capture due to lack of resources.</t>
-<t>FilterAccept: number of packets accepeted by filter during current capture.</t>
-<t>OSDrop: number of packets dropped by the operating system during the capture.</t>
-<t>UsrDelivered: number of packets delivered to the user. UsrDelivered can be different from the value 'FilterAccept - OSDropped' because some packets could still lay in the OS buffers when the capture ended.</t>
-<t>Interface ID: reference to an Interface Description Block.</t>
-<t>Reserved: Reserved to future use.</t>
-<t>Options: optionally, a list of options (formatted according to the rules defined in <xref target="sectionopt"/>) can be present.</t>
-</list>
-
-<t>In addiction to the options defined in <xref target="sectionopt"/>, the following options are valid within this block:</t>
-
-<texttable>
- <ttcol>Name</ttcol>
- <ttcol>Code</ttcol>
- <ttcol>Length</ttcol>
- <ttcol>Description</ttcol>
-
- <c>isb_starttime</c>
- <c>2</c>
- <c>8</c>
- <c>Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds.</c>
-
- <c>isb_endtime</c>
- <c>3</c>
- <c>8</c>
- <c>Time in which the capture started; time will be stored in two blocks of four bytes each, containing the timestamp in seconds and nanoseconds.</c>
-</texttable>
-
-</section>
-</section>
-
-
-
-<section anchor="sectionopt" title="Options">
-<t>Almost all blocks have the possibility to embed optional fields. Optional fields can be used to insert some information that may be useful when reading data, but that it is not really needed for packet processing. Therefore, each tool can be either read the content of the optional fields (if any), or skip them at once.</t>
-<t>Skipping all the optional fields at once is straightforward because most of the blocks have a fixed length, therefore the field Block Length (present in the General Block Structure, see <xref target="sectionblock"/>) can be used to skip everything till the next block.</t>
-
-<t>Options are a list of Type - Length - Value fields, each one containing a single value:</t>
-
-<list style="symbols">
-<t>Option Type (2 bytes): it contains the code that specifies the type of the current TLV record. Option types whose Most Significant Bit is equal to one are reserved for local use; therefore, there is no guarantee that the code used is unique among all capture files (generated by other applications). In case of vendor-specific extensions that have to be identified uniquely, vendors must request an Option Code whose MSB is equal to zero.</t>
-<t>Option Length (2 bytes): it contains the length of the following 'Option Value' field.</t>
-<t>Option Value (variable length): it contains the value of the given option. The length of this field as been specified by the Option Length field.</t>
-</list>
-
-<t>Options may be repeated several times (e.g. an interface that has several IP addresses associated to it). The option list is terminated by a special code which is the 'End of Option'.</t>
-
-<t>The format of the optional fields is shown in <xref target="formatopt"/>.</t>
-
-<figure anchor="formatopt" title="Options format.">
-<artwork>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Option Code | Option Length |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Option Value |
- | /* variable length, byte-aligned */ |
- | + + + + + + + + + + + + + + + + + + + + + + + + +
- | / / / |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- / /
- / . . . other options . . . /
- / /
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Option Code == opt_endofopt | Option Length == 0 |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </artwork>
-</figure>
-
-<t>The following codes can always be present in any optional field:</t>
-
-<texttable>
- <ttcol>Name</ttcol>
- <ttcol>Code</ttcol>
- <ttcol>Length</ttcol>
- <ttcol>Description</ttcol>
-
- <c>opt_endofopt</c>
- <c>0</c>
- <c>0</c>
- <c>End of options: it is used to delimit the end of the optional fields. This block cannot be repeated within a given list of options.</c>
-
- <c>opt_comment</c>
- <c>1</c>
- <c>variable</c>
- <c>Comment: it is an ascii string containing a comment that is associated to the current block.</c>
-</texttable>
-
-</section>
-
-
-
-
-<section title="Experimental Blocks (deserved to a further investigation)">
-
-<section title="Other Packet Blocks (experimental)">
-<t>Can some other packet blocks (besides the two described in the previous paragraphs) be useful?</t>
-</section>
-
-<section title="Compression Block (experimental)">
-<t>The Compression Block is optional. A file can contain an arbitrary number of these blocks. A Compression Block, as the name says, is used to store compressed data. Its format is shown in <xref target="formatcb"/>.</t>
-
-<figure anchor="formatcb" title="Compression Block format.">
-<artwork>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Compr. Type | |
- +-+-+-+-+-+-+-+-+ |
- | |
- | Compressed Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </artwork>
-</figure>
-
-<t>The fields have the following meaning:</t>
-
-<list style="symbols">
-<t>Compression Type: specifies the compression algorithm. Possible values for this field are 0 (uncompressed), 1 (Lempel Ziv), 2 (Gzip), other?? Probably some kind of dumb and fast compression algorithm could be effective with some types of traffic (for example web), but which?</t>
-<t>Compressed Data: data of this block. Once decompressed, it is made of other blocks.</t>
-</list>
-
-</section>
-
-
-<section title="Encryption Block (experimental)">
-<t>The Encryption Block is optional. A file can contain an arbitrary number of these blocks. An Encryption Block is used to sotre encrypted data. Its format is shown in <xref target="formateb"/>.</t>
-
-<figure anchor="formateb" title="Encryption Block format.">
-<artwork>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Encr. Type | |
- +-+-+-+-+-+-+-+-+ |
- | |
- | Compressed Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </artwork>
-</figure>
-
-<t>The fields have the following meaning:</t>
-<list style="symbols">
-<t>Compression Type: specifies the encryption algorithm. Possible values for this field are ??? NOTE: this block should probably contain other fields, depending on the encryption algorithm. To be define precisely.</t>
-<t>Encrypted Data: data of this block. Once decripted, it consists of other blocks.</t>
-</list>
-
-</section>
-
-
-<section title="Fixed Length Block (experimental)">
-<t>The Fixed Length Block is optional. A file can contain an arbitrary number of these blocks. A Fixed Length Block can be used to optimize the access to the file. Its format is shown in <xref target="formatflm"/>.
-A Fixed Length Block stores records with constant size. It contains a set of Blocks (normally Packet Blocks or Simple Packet Blocks), of wihich it specifies the size. Knowing this size a priori helps to scan the file and to load some portions of it without truncating a block, and is particularly useful with cell-based networks like ATM.</t>
-
-<figure anchor="formatflm" title="Fixed Length Block format.">
-<artwork>
- 0 1 2 3
- 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | Cell Size | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- | |
- | Fixed Size Data |
- | |
- | /* variable length, byte-aligned */ |
- | |
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- </artwork>
-</figure>
-
-<t>The fields have the following meaning:</t>
-<list style="symbols">
-<t>Cell size: the size of the blocks contained in the data field.</t>
-<t>Fixed Size Data: data of this block.</t>
-</list>
-
-</section>
-
-<section title="Directory Block (experimental)">
-<t>If present, this block contains the following information:</t>
-<list style="symbols">
-<t>number of indexed packets (N)</t>
-<t>table with position and length of any indexed packet (N entries)</t>
-</list>
-
-<t>A directory block must be followed by at least N packets, otherwise it must be considered invalid. It can be used to efficiently load portions of the file to memory and to support operations on memory mapped files. This block can be added by tools like network analyzers as a consequence of file processing.</t>
-</section>
-
-<section title="Traffic Statistics and Monitoring Blocks (experimental)">
-<t>One or more blocks could be defined to contain network statistics or traffic monitoring information. They could be use to store data collected from RMON or Netflow probes, or from other network monitoring tools.</t>
-</section>
-
-<section title="Event/Security Block (experimental)">
-<t>This block could be used to store events. Events could contain generic information (for example network load over 50%, server down...) or security alerts. An event could be:</t>
-
-<list style="symbols">
-<t>skipped, if the application doesn't know how to do with it</t>
-<t>processed independently by the packets. In other words, the applications skips the packets and processes only the alerts</t>
-<t>processed in relation to packets: for example, a security tool could load only the packets of the file that are near a security alert; a monitorg tool could skip the packets captured while the server was down.</t>
-</list>
-
-</section>
-
-</section>
-
-
-
-
-<section title="Conclusions">
-<t>The file format proposed in this document should be very versatile and satisfy a wide range of applications.
-In the simplest case, it can contain a raw dump of the network data, made of a series of Simple Packet Blocks.
-In the most complex case, it can be used as a repository for heterogeneous information.
-In every case, the file remains easy to parse and an application can always skip the data it is not interested in; at the same time, different applications can share the file, and each of them can benfit of the information produced by the others.
-Two or more files can be concatenated obtaining another valid file.</t>
-</section>
-
-
-<section title="Most important open issues">
-<list style="symbols">
-<t>Data, in the file, must be byte or word aligned? Currently, the structure of this document is not consistent with respect to this point.</t>
-</list>
-</section>
-
-</middle>
-
-</rfc>
diff --git a/contrib/libpcap/etherent.c b/contrib/libpcap/etherent.c
index 9d29955..27e5502 100644
--- a/contrib/libpcap/etherent.c
+++ b/contrib/libpcap/etherent.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/etherent.c,v 1.22 2003/11/15 23:23:57 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/etherent.c,v 1.23 2006/10/04 18:09:22 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -37,7 +37,7 @@ static const char rcsid[] _U_ =
#include "pcap-int.h"
-#include <pcap-namedb.h>
+#include <pcap/namedb.h>
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
diff --git a/contrib/libpcap/ethertype.h b/contrib/libpcap/ethertype.h
index 2d21c6d..867d33e 100644
--- a/contrib/libpcap/ethertype.h
+++ b/contrib/libpcap/ethertype.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/libpcap/ethertype.h,v 1.13.2.1 2005/09/05 09:08:03 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/ethertype.h,v 1.14 2005/09/05 09:06:58 guy Exp $ (LBL)
*/
/*
diff --git a/contrib/libpcap/fad-getad.c b/contrib/libpcap/fad-getad.c
index 8101165..2ce6d70 100644
--- a/contrib/libpcap/fad-getad.c
+++ b/contrib/libpcap/fad-getad.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.10.2.2 2007/09/14 00:45:17 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.12 2007/09/14 00:44:55 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/libpcap/fad-gifc.c b/contrib/libpcap/fad-gifc.c
index 985d2c0..ef04bd9 100644
--- a/contrib/libpcap/fad-gifc.c
+++ b/contrib/libpcap/fad-gifc.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.8.2.2 2005/06/29 06:43:31 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.11.2.1 2008-08-06 07:35:01 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -42,7 +42,6 @@ static const char rcsid[] _U_ =
#endif
#include <sys/param.h>
-#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_SOCKIO_H
diff --git a/contrib/libpcap/fad-glifc.c b/contrib/libpcap/fad-glifc.c
index 8a86a3d..9e92bc3 100644
--- a/contrib/libpcap/fad-glifc.c
+++ b/contrib/libpcap/fad-glifc.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.5.2.1 2005/04/19 00:54:16 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.6.2.1 2008/01/30 09:36:09 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -75,9 +75,9 @@ struct rtentry; /* declarations in <net/if.h> */
* The list, as returned through "alldevsp", may be null if no interfaces
* were up and could be opened.
*
- * This is the implementation used on platforms that have SIOCLGIFCONF
+ * This is the implementation used on platforms that have SIOCGLIFCONF
* but don't have "getifaddrs()". (Solaris 8 and later; we use
- * SIOCLGIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
+ * SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
*/
int
pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
diff --git a/contrib/libpcap/fad-sita.c b/contrib/libpcap/fad-sita.c
new file mode 100644
index 0000000..2619045
--- /dev/null
+++ b/contrib/libpcap/fad-sita.c
@@ -0,0 +1,61 @@
+/*
+ * fad-sita.c: Packet capture interface additions for SITA ACN devices
+ *
+ * Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc <fulko.hew@sita.aero>
+ *
+ * License: BSD
+ *
+ * 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. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+ /* $Id: fad-sita.c */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include "pcap-int.h"
+
+#include "pcap-sita.h"
+
+extern pcap_if_t *acn_if_list; /* pcap's list of available interfaces */
+
+int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) {
+
+ //printf("pcap_findalldevs()\n"); // fulko
+
+ *alldevsp = 0; /* initialize the returned variables before we do anything */
+ strcpy(errbuf, "");
+ if (acn_parse_hosts_file(errbuf)) /* scan the hosts file for potential IOPs */
+ {
+ //printf("pcap_findalldevs() returning BAD after parsehosts\n"); // fulko
+ return -1;
+ }
+ //printf("pcap_findalldevs() got hostlist now finding devs\n"); // fulko
+ if (acn_findalldevs(errbuf)) /* then ask the IOPs for their monitorable devices */
+ {
+ //printf("pcap_findalldevs() returning BAD after findalldevs\n"); // fulko
+ return -1;
+ }
+ *alldevsp = acn_if_list;
+ acn_if_list = 0; /* then forget our list head, because someone will call pcap_freealldevs() to empty the malloc'ed stuff */
+ //printf("pcap_findalldevs() returning ZERO OK\n"); // fulko
+ return 0;
+}
diff --git a/contrib/libpcap/fad-win32.c b/contrib/libpcap/fad-win32.c
index 4d2c01e..19839c8 100644
--- a/contrib/libpcap/fad-win32.c
+++ b/contrib/libpcap/fad-win32.c
@@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.11.2.3 2006/02/22 17:09:32 gianluca Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.15 2007/09/25 20:34:36 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -301,6 +301,15 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
name += strlen(name) + 1;
desc += strlen(desc) + 1;
}
+
+ if (ret != -1) {
+ /*
+ * We haven't had any errors yet; do any platform-specific
+ * operations to add devices.
+ */
+ if (pcap_platform_finddevs(&devlist, errbuf) < 0)
+ ret = -1;
+ }
if (ret == -1) {
/*
diff --git a/contrib/libpcap/filtertest.c b/contrib/libpcap/filtertest.c
new file mode 100644
index 0000000..cfa69ea
--- /dev/null
+++ b/contrib/libpcap/filtertest.c
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ * 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: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char copyright[] _U_ =
+ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/libpcap/filtertest.c,v 1.2 2005/08/08 17:50:13 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifndef HAVE___ATTRIBUTE__
+#define __attribute__(x)
+#endif
+
+static char *program_name;
+
+/* Forwards */
+static void usage(void) __attribute__((noreturn));
+static void error(const char *, ...)
+ __attribute__((noreturn, format (printf, 1, 2)));
+
+extern int optind;
+extern int opterr;
+extern char *optarg;
+
+/*
+ * On Windows, we need to open the file in binary mode, so that
+ * we get all the bytes specified by the size we get from "fstat()".
+ * On UNIX, that's not necessary. O_BINARY is defined on Windows;
+ * we define it as 0 if it's not defined, so it does nothing.
+ */
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static char *
+read_infile(char *fname)
+{
+ register int i, fd, cc;
+ register char *cp;
+ struct stat buf;
+
+ fd = open(fname, O_RDONLY|O_BINARY);
+ if (fd < 0)
+ error("can't open %s: %s", fname, pcap_strerror(errno));
+
+ if (fstat(fd, &buf) < 0)
+ error("can't stat %s: %s", fname, pcap_strerror(errno));
+
+ cp = malloc((u_int)buf.st_size + 1);
+ if (cp == NULL)
+ error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
+ fname, pcap_strerror(errno));
+ cc = read(fd, cp, (u_int)buf.st_size);
+ if (cc < 0)
+ error("read %s: %s", fname, pcap_strerror(errno));
+ if (cc != buf.st_size)
+ error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
+
+ close(fd);
+ /* replace "# comment" with spaces */
+ for (i = 0; i < cc; i++) {
+ if (cp[i] == '#')
+ while (i < cc && cp[i] != '\n')
+ cp[i++] = ' ';
+ }
+ cp[cc] = '\0';
+ return (cp);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+ register char **p;
+ register u_int len = 0;
+ char *buf;
+ char *src, *dst;
+
+ p = argv;
+ if (*p == 0)
+ return 0;
+
+ while (*p)
+ len += strlen(*p++) + 1;
+
+ buf = (char *)malloc(len);
+ if (buf == NULL)
+ error("copy_argv: malloc");
+
+ p = argv;
+ dst = buf;
+ while ((src = *p++) != NULL) {
+ while ((*dst++ = *src++) != '\0')
+ ;
+ dst[-1] = ' ';
+ }
+ dst[-1] = '\0';
+
+ return buf;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *cp;
+ int op;
+ int dflag;
+ char *infile;
+ int Oflag;
+ long snaplen;
+ int dlt;
+ char *cmdbuf;
+ pcap_t *pd;
+ struct bpf_program fcode;
+
+#ifdef WIN32
+ if(wsockinit() != 0) return 1;
+#endif /* WIN32 */
+
+ dflag = 1;
+ infile = NULL;
+ Oflag = 1;
+ snaplen = 68;
+
+ if ((cp = strrchr(argv[0], '/')) != NULL)
+ program_name = cp + 1;
+ else
+ program_name = argv[0];
+
+ opterr = 0;
+ while ((op = getopt(argc, argv, "dF:Os:")) != -1) {
+ switch (op) {
+
+ case 'd':
+ ++dflag;
+ break;
+
+ case 'F':
+ infile = optarg;
+ break;
+
+ case 'O':
+ Oflag = 0;
+ break;
+
+ case 's': {
+ char *end;
+
+ snaplen = strtol(optarg, &end, 0);
+ if (optarg == end || *end != '\0'
+ || snaplen < 0 || snaplen > 65535)
+ error("invalid snaplen %s", optarg);
+ else if (snaplen == 0)
+ snaplen = 65535;
+ break;
+ }
+
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (optind >= argc) {
+ usage();
+ /* NOTREACHED */
+ }
+
+ dlt = pcap_datalink_name_to_val(argv[optind]);
+ if (dlt < 0)
+ error("invalid data link type %s", argv[optind]);
+
+ if (infile)
+ cmdbuf = read_infile(infile);
+ else
+ cmdbuf = copy_argv(&argv[optind+1]);
+
+ pd = pcap_open_dead(dlt, snaplen);
+ if (pd == NULL)
+ error("Can't open fake pcap_t");
+
+ if (pcap_compile(pd, &fcode, cmdbuf, Oflag, 0) < 0)
+ error("%s", pcap_geterr(pd));
+ bpf_dump(&fcode, dflag);
+ pcap_close(pd);
+ exit(0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "%s, with %s\n", program_name,
+ pcap_lib_version());
+ (void)fprintf(stderr,
+ "Usage: %s [-dO] [ -F file ] [ -s snaplen ] dlt [ expression ]\n",
+ program_name);
+ exit(1);
+}
diff --git a/contrib/libpcap/findalldevstest.c b/contrib/libpcap/findalldevstest.c
new file mode 100644
index 0000000..ec7c950
--- /dev/null
+++ b/contrib/libpcap/findalldevstest.c
@@ -0,0 +1,131 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <pcap.h>
+
+static void ifprint(pcap_if_t *d);
+static char *iptos(bpf_u_int32 in);
+
+int main(int argc, char **argv)
+{
+ pcap_if_t *alldevs;
+ pcap_if_t *d;
+ char *s;
+ bpf_u_int32 net, mask;
+
+ char errbuf[PCAP_ERRBUF_SIZE+1];
+ if (pcap_findalldevs(&alldevs, errbuf) == -1)
+ {
+ fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
+ exit(1);
+ }
+ for(d=alldevs;d;d=d->next)
+ {
+ ifprint(d);
+ }
+
+ if ( (s = pcap_lookupdev(errbuf)) == NULL)
+ {
+ fprintf(stderr,"Error in pcap_lookupdev: %s\n",errbuf);
+ }
+ else
+ {
+ printf("Preferred device name: %s\n",s);
+ }
+
+ if (pcap_lookupnet(s, &net, &mask, errbuf) < 0)
+ {
+ fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
+ }
+ else
+ {
+ printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask));
+ }
+
+ exit(0);
+}
+
+static void ifprint(pcap_if_t *d)
+{
+ pcap_addr_t *a;
+#ifdef INET6
+ char ntop_buf[INET6_ADDRSTRLEN];
+#endif
+
+ printf("%s\n",d->name);
+ if (d->description)
+ printf("\tDescription: %s\n",d->description);
+ printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no");
+
+ for(a=d->addresses;a;a=a->next) {
+ switch(a->addr->sa_family)
+ {
+ case AF_INET:
+ printf("\tAddress Family: AF_INET\n");
+ if (a->addr)
+ printf("\t\tAddress: %s\n",
+ inet_ntoa(((struct sockaddr_in *)(a->addr))->sin_addr));
+ if (a->netmask)
+ printf("\t\tNetmask: %s\n",
+ inet_ntoa(((struct sockaddr_in *)(a->netmask))->sin_addr));
+ if (a->broadaddr)
+ printf("\t\tBroadcast Address: %s\n",
+ inet_ntoa(((struct sockaddr_in *)(a->broadaddr))->sin_addr));
+ if (a->dstaddr)
+ printf("\t\tDestination Address: %s\n",
+ inet_ntoa(((struct sockaddr_in *)(a->dstaddr))->sin_addr));
+ break;
+#ifdef INET6
+ case AF_INET6:
+ printf("\tAddress Family: AF_INET6\n");
+ if (a->addr)
+ printf("\t\tAddress: %s\n",
+ inet_ntop(AF_INET6,
+ ((struct sockaddr_in6 *)(a->addr))->sin6_addr.s6_addr,
+ ntop_buf, sizeof ntop_buf));
+ if (a->netmask)
+ printf("\t\tNetmask: %s\n",
+ inet_ntop(AF_INET6,
+ ((struct sockaddr_in6 *)(a->netmask))->sin6_addr.s6_addr,
+ ntop_buf, sizeof ntop_buf));
+ if (a->broadaddr)
+ printf("\t\tBroadcast Address: %s\n",
+ inet_ntop(AF_INET6,
+ ((struct sockaddr_in6 *)(a->broadaddr))->sin6_addr.s6_addr,
+ ntop_buf, sizeof ntop_buf));
+ if (a->dstaddr)
+ printf("\t\tDestination Address: %s\n",
+ inet_ntop(AF_INET6,
+ ((struct sockaddr_in6 *)(a->dstaddr))->sin6_addr.s6_addr,
+ ntop_buf, sizeof ntop_buf));
+ break;
+#endif
+ default:
+ printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family);
+ break;
+ }
+ }
+ printf("\n");
+}
+
+/* From tcptraceroute */
+#define IPTOSBUFFERS 12
+static char *iptos(bpf_u_int32 in)
+{
+ static char output[IPTOSBUFFERS][3*4+3+1];
+ static short which;
+ u_char *p;
+
+ p = (u_char *)&in;
+ which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
+ sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ return output[which];
+}
diff --git a/contrib/libpcap/gencode.c b/contrib/libpcap/gencode.c
index b2d8222..0fb9499 100644
--- a/contrib/libpcap/gencode.c
+++ b/contrib/libpcap/gencode.c
@@ -23,7 +23,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.53 2007/09/12 19:17:24 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.290.2.16 2008-09-22 20:16:01 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -70,10 +70,11 @@ static const char rcsid[] _U_ =
#include "nlpid.h"
#include "llc.h"
#include "gencode.h"
+#include "ieee80211.h"
#include "atmuni31.h"
#include "sunatmpos.h"
#include "ppp.h"
-#include "sll.h"
+#include "pcap/sll.h"
#include "arcnet.h"
#ifdef HAVE_NET_PFVAR_H
#include <sys/socket.h>
@@ -89,7 +90,7 @@ static const char rcsid[] _U_ =
#include <netdb.h> /* for "struct addrinfo" */
#endif /* WIN32 */
#endif /*INET6*/
-#include <pcap-namedb.h>
+#include <pcap/namedb.h>
#define ETHERMTU 1500
@@ -107,8 +108,8 @@ static const char rcsid[] _U_ =
static jmp_buf top_ctx;
static pcap_t *bpf_pcap;
-#ifdef WIN32
/* Hack for updating VLAN, MPLS, and PPPoE offsets. */
+#ifdef WIN32
static u_int orig_linktype = (u_int)-1, orig_nl = (u_int)-1, label_stack_depth = (u_int)-1;
#else
static u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U;
@@ -136,6 +137,7 @@ bpf_error(const char *fmt, ...)
static void init_linktype(pcap_t *);
+static void init_regs(void);
static int alloc_reg(void);
static void free_reg(int);
@@ -147,7 +149,8 @@ static struct block *root;
*/
enum e_offrel {
OR_PACKET, /* relative to the beginning of the packet */
- OR_LINK, /* relative to the link-layer header */
+ OR_LINK, /* relative to the beginning of the link-layer header */
+ OR_MACPL, /* relative to the end of the MAC-layer header */
OR_NET, /* relative to the network-layer header */
OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */
OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */
@@ -192,6 +195,7 @@ static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *);
static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32,
bpf_u_int32, bpf_u_int32, int, bpf_int32);
static struct slist *gen_load_llrel(u_int, u_int);
+static struct slist *gen_load_macplrel(u_int, u_int);
static struct slist *gen_load_a(enum e_offrel, u_int, u_int);
static struct slist *gen_loadx_iphdrlen(void);
static struct block *gen_uncond(int);
@@ -199,12 +203,16 @@ static inline struct block *gen_true(void);
static inline struct block *gen_false(void);
static struct block *gen_ether_linktype(int);
static struct block *gen_linux_sll_linktype(int);
-static void insert_radiotap_load_llprefixlen(struct block *);
-static void insert_ppi_load_llprefixlen(struct block *);
-static void insert_load_llprefixlen(struct block *);
+static struct slist *gen_load_prism_llprefixlen(void);
+static struct slist *gen_load_avs_llprefixlen(void);
+static struct slist *gen_load_radiotap_llprefixlen(void);
+static struct slist *gen_load_ppi_llprefixlen(void);
+static void insert_compute_vloffsets(struct block *);
static struct slist *gen_llprefixlen(void);
+static struct slist *gen_off_macpl(void);
+static int ethertype_to_ppptype(int);
static struct block *gen_linktype(int);
-static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int);
+static struct block *gen_snap(bpf_u_int32, bpf_u_int32);
static struct block *gen_llc_linktype(int);
static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
#ifdef INET6
@@ -249,6 +257,7 @@ static struct slist *xfer_to_x(struct arth *);
static struct slist *xfer_to_a(struct arth *);
static struct block *gen_mac_multicast(int);
static struct block *gen_len(int, int);
+static struct block *gen_check_802_11_data_frame(void);
static struct block *gen_ppi_dlt_check(void);
static struct block *gen_msg_abbrev(int type);
@@ -371,6 +380,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
n_errors = 0;
root = NULL;
bpf_pcap = p;
+ init_regs();
if (setjmp(top_ctx)) {
lex_cleanup();
freechunks();
@@ -486,24 +496,11 @@ merge(b0, b1)
*p = b1;
}
-
void
finish_parse(p)
struct block *p;
{
struct block *ppi_dlt_check;
-
- ppi_dlt_check = gen_ppi_dlt_check();
-
- if (ppi_dlt_check != NULL)
- {
- gen_and(ppi_dlt_check, p);
- }
-
- backpatch(p, gen_retblk(snaplen));
- p->sense = !p->sense;
- backpatch(p, gen_retblk(0));
- root = p->head;
/*
* Insert before the statements of the first (root) block any
@@ -514,14 +511,30 @@ finish_parse(p)
* statements of all blocks that use those lengths and that
* have no predecessors that use them, so that we only compute
* the lengths if we need them. There might be even better
- * approaches than that. However, as we're currently only
- * handling variable-length radiotap headers, and as all
- * filtering expressions other than raw link[M:N] tests
- * require the length of that header, doing more for that
- * header length isn't really worth the effort.
+ * approaches than that.
+ *
+ * However, those strategies would be more complicated, and
+ * as we don't generate code to compute a length if the
+ * program has no tests that use the length, and as most
+ * tests will probably use those lengths, we would just
+ * postpone computing the lengths so that it's not done
+ * for tests that fail early, and it's not clear that's
+ * worth the effort.
*/
+ insert_compute_vloffsets(p->head);
+
+ /*
+ * For DLT_PPI captures, generate a check of the per-packet
+ * DLT value to make sure it's DLT_IEEE802_11.
+ */
+ ppi_dlt_check = gen_ppi_dlt_check();
+ if (ppi_dlt_check != NULL)
+ gen_and(ppi_dlt_check, p);
- insert_load_llprefixlen(root);
+ backpatch(p, gen_retblk(snaplen));
+ p->sense = !p->sense;
+ backpatch(p, gen_retblk(0));
+ root = p->head;
}
void
@@ -684,13 +697,7 @@ gen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
* Various code constructs need to know the layout of the data link
* layer. These variables give the necessary offsets from the beginning
* of the packet data.
- *
- * If the link layer has variable_length headers, the offsets are offsets
- * from the end of the link-link-layer header, and "reg_ll_size" is
- * the register number for a register containing the length of the
- * link-layer header. Otherwise, "reg_ll_size" is -1.
*/
-static int reg_ll_size;
/*
* This is the offset of the beginning of the link-layer header from
@@ -703,13 +710,49 @@ static int reg_ll_size;
static u_int off_ll;
/*
- * This is the offset of the beginning of the MAC-layer header.
+ * If there's a variable-length header preceding the link-layer header,
+ * "reg_off_ll" is the register number for a register containing the
+ * length of that header, and therefore the offset of the link-layer
+ * header from the beginning of the raw packet data. Otherwise,
+ * "reg_off_ll" is -1.
+ */
+static int reg_off_ll;
+
+/*
+ * This is the offset of the beginning of the MAC-layer header from
+ * the beginning of the link-layer header.
* It's usually 0, except for ATM LANE, where it's the offset, relative
* to the beginning of the raw packet data, of the Ethernet header.
*/
static u_int off_mac;
/*
+ * This is the offset of the beginning of the MAC-layer payload,
+ * from the beginning of the raw packet data.
+ *
+ * I.e., it's the sum of the length of the link-layer header (without,
+ * for example, any 802.2 LLC header, so it's the MAC-layer
+ * portion of that header), plus any prefix preceding the
+ * link-layer header.
+ */
+static u_int off_macpl;
+
+/*
+ * This is 1 if the offset of the beginning of the MAC-layer payload
+ * from the beginning of the link-layer header is variable-length.
+ */
+static int off_macpl_is_variable;
+
+/*
+ * If the link layer has variable_length headers, "reg_off_macpl"
+ * is the register number for a register containing the length of the
+ * link-layer header plus the length of any variable-length header
+ * preceding the link-layer header. Otherwise, "reg_off_macpl"
+ * is -1.
+ */
+static int reg_off_macpl;
+
+/*
* "off_linktype" is the offset to information in the link-layer header
* giving the packet type. This offset is relative to the beginning
* of the link-layer header (i.e., it doesn't include off_ll).
@@ -732,6 +775,13 @@ static u_int off_mac;
static u_int off_linktype;
/*
+ * TRUE if "pppoes" appeared in the filter; it causes link-layer type
+ * checks to check the PPP header, assumed to follow a LAN-style link-
+ * layer header and a PPPoE session header.
+ */
+static int is_pppoes = 0;
+
+/*
* TRUE if the link layer includes an ATM pseudo-header.
*/
static int is_atm = 0;
@@ -770,8 +820,8 @@ static u_int off_payload;
/*
* These are offsets to the beginning of the network-layer header.
- * They are relative to the beginning of the link-layer header (i.e.,
- * they don't include off_ll).
+ * They are relative to the beginning of the MAC-layer payload (i.e.,
+ * they don't include off_ll or off_macpl).
*
* If the link layer never uses 802.2 LLC:
*
@@ -818,6 +868,11 @@ init_linktype(p)
off_payload = -1;
/*
+ * And that we're not doing PPPoE.
+ */
+ is_pppoes = 0;
+
+ /*
* And assume we're not doing SS7.
*/
off_li = -1;
@@ -827,34 +882,40 @@ init_linktype(p)
off_sls = -1;
/*
- * Also assume it's not 802.11 with a fixed-length radio header.
+ * Also assume it's not 802.11.
*/
off_ll = 0;
+ off_macpl = 0;
+ off_macpl_is_variable = 0;
orig_linktype = -1;
orig_nl = -1;
label_stack_depth = 0;
- reg_ll_size = -1;
+ reg_off_ll = -1;
+ reg_off_macpl = -1;
switch (linktype) {
case DLT_ARCNET:
off_linktype = 2;
- off_nl = 6; /* XXX in reality, variable! */
- off_nl_nosnap = 6; /* no 802.2 LLC */
+ off_macpl = 6;
+ off_nl = 0; /* XXX in reality, variable! */
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_ARCNET_LINUX:
off_linktype = 4;
- off_nl = 8; /* XXX in reality, variable! */
- off_nl_nosnap = 8; /* no 802.2 LLC */
+ off_macpl = 8;
+ off_nl = 0; /* XXX in reality, variable! */
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_EN10MB:
off_linktype = 12;
- off_nl = 14; /* Ethernet II */
- off_nl_nosnap = 17; /* 802.3+802.2 */
+ off_macpl = 14; /* Ethernet header length */
+ off_nl = 0; /* Ethernet II */
+ off_nl_nosnap = 3; /* 802.3+802.2 */
return;
case DLT_SLIP:
@@ -863,29 +924,33 @@ init_linktype(p)
* header is hacked into our SLIP driver.
*/
off_linktype = -1;
- off_nl = 16;
- off_nl_nosnap = 16; /* no 802.2 LLC */
+ off_macpl = 16;
+ off_nl = 0;
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_SLIP_BSDOS:
/* XXX this may be the same as the DLT_PPP_BSDOS case */
off_linktype = -1;
/* XXX end */
- off_nl = 24;
- off_nl_nosnap = 24; /* no 802.2 LLC */
+ off_macpl = 24;
+ off_nl = 0;
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_NULL:
case DLT_LOOP:
off_linktype = 0;
- off_nl = 4;
- off_nl_nosnap = 4; /* no 802.2 LLC */
+ off_macpl = 4;
+ off_nl = 0;
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_ENC:
off_linktype = 0;
- off_nl = 12;
- off_nl_nosnap = 12; /* no 802.2 LLC */
+ off_macpl = 12;
+ off_nl = 0;
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_PPP:
@@ -893,8 +958,9 @@ init_linktype(p)
case DLT_C_HDLC: /* BSD/OS Cisco HDLC */
case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */
off_linktype = 2;
- off_nl = 4;
- off_nl_nosnap = 4; /* no 802.2 LLC */
+ off_macpl = 4;
+ off_nl = 0;
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_PPP_ETHER:
@@ -903,14 +969,16 @@ init_linktype(p)
* only covers session state.
*/
off_linktype = 6;
- off_nl = 8;
- off_nl_nosnap = 8; /* no 802.2 LLC */
+ off_macpl = 8;
+ off_nl = 0;
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_PPP_BSDOS:
off_linktype = 5;
- off_nl = 24;
- off_nl_nosnap = 24; /* no 802.2 LLC */
+ off_macpl = 24;
+ off_nl = 0;
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_FDDI:
@@ -926,12 +994,12 @@ init_linktype(p)
#ifdef PCAP_FDDIPAD
off_linktype += pcap_fddipad;
#endif
- off_nl = 21; /* FDDI+802.2+SNAP */
- off_nl_nosnap = 16; /* FDDI+802.2 */
+ off_macpl = 13; /* FDDI MAC header length */
#ifdef PCAP_FDDIPAD
- off_nl += pcap_fddipad;
- off_nl_nosnap += pcap_fddipad;
+ off_macpl += pcap_fddipad;
#endif
+ off_nl = 8; /* 802.2+SNAP */
+ off_nl_nosnap = 3; /* 802.2 */
return;
case DLT_IEEE802:
@@ -959,11 +1027,15 @@ init_linktype(p)
* 8 - figure out which byte that is).
*/
off_linktype = 14;
- off_nl = 22; /* Token Ring+802.2+SNAP */
- off_nl_nosnap = 17; /* Token Ring+802.2 */
+ off_macpl = 14; /* Token Ring MAC header length */
+ off_nl = 8; /* 802.2+SNAP */
+ off_nl_nosnap = 3; /* 802.2 */
return;
case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
/*
* 802.11 doesn't really have a link-level type field.
* We set "off_linktype" to the offset of the LLC header.
@@ -972,90 +1044,37 @@ init_linktype(p)
* is being used and pick out the encapsulated Ethernet type.
* XXX - should we generate code to check for SNAP?
*
- * XXX - the header is actually variable-length. We
- * assume a 24-byte link-layer header, as appears in
- * data frames in networks with no bridges. If the
- * fromds and tods 802.11 header bits are both set,
- * it's actually supposed to be 30 bytes.
+ * We also handle variable-length radio headers here.
+ * The Prism header is in theory variable-length, but in
+ * practice it's always 144 bytes long. However, some
+ * drivers on Linux use ARPHRD_IEEE80211_PRISM, but
+ * sometimes or always supply an AVS header, so we
+ * have to check whether the radio header is a Prism
+ * header or an AVS header, so, in practice, it's
+ * variable-length.
*/
off_linktype = 24;
- off_nl = 32; /* 802.11+802.2+SNAP */
- off_nl_nosnap = 27; /* 802.11+802.2 */
- return;
-
- case DLT_PRISM_HEADER:
- /*
- * Same as 802.11, but with an additional header before
- * the 802.11 header, containing a bunch of additional
- * information including radio-level information.
- *
- * The header is 144 bytes long.
- *
- * XXX - same variable-length header problem; at least
- * the Prism header is fixed-length.
- */
- off_ll = 144;
- off_linktype = 24;
- off_nl = 32; /* Prism+802.11+802.2+SNAP */
- off_nl_nosnap = 27; /* Prism+802.11+802.2 */
- return;
-
- case DLT_IEEE802_11_RADIO_AVS:
- /*
- * Same as 802.11, but with an additional header before
- * the 802.11 header, containing a bunch of additional
- * information including radio-level information.
- *
- * The header is 64 bytes long, at least in its
- * current incarnation.
- *
- * XXX - same variable-length header problem, only
- * more so; this header is also variable-length,
- * with the length being the 32-bit big-endian
- * number at an offset of 4 from the beginning
- * of the radio header. We should handle that the
- * same way we handle the length at the beginning
- * of the radiotap header.
- *
- * XXX - in Linux, do any drivers that supply an AVS
- * header supply a link-layer type other than
- * ARPHRD_IEEE80211_PRISM? If so, we should map that
- * to DLT_IEEE802_11_RADIO_AVS; if not, or if there are
- * any drivers that supply an AVS header but supply
- * an ARPHRD value of ARPHRD_IEEE80211_PRISM, we'll
- * have to check the header in the generated code to
- * determine whether it's Prism or AVS.
- */
- off_ll = 64;
- off_linktype = 24;
- off_nl = 32; /* Radio+802.11+802.2+SNAP */
- off_nl_nosnap = 27; /* Radio+802.11+802.2 */
+ off_macpl = 0; /* link-layer header is variable-length */
+ off_macpl_is_variable = 1;
+ off_nl = 8; /* 802.2+SNAP */
+ off_nl_nosnap = 3; /* 802.2 */
return;
-
- /*
- * At the moment we treat PPI as normal Radiotap encoded
- * packets. The difference is in the function that generates
- * the code at the beginning to compute the header length.
- * Since this code generator of PPI supports bare 802.11
- * encapsulation only (i.e. the encapsulated DLT should be
- * DLT_IEEE802_11) we generate code to check for this too.
- */
case DLT_PPI:
- case DLT_IEEE802_11_RADIO:
- /*
- * Same as 802.11, but with an additional header before
- * the 802.11 header, containing a bunch of additional
- * information including radio-level information.
- *
- * The radiotap header is variable length, and we
- * generate code to compute its length and store it
- * in a register. These offsets are relative to the
- * beginning of the 802.11 header.
+ /*
+ * At the moment we treat PPI the same way that we treat
+ * normal Radiotap encoded packets. The difference is in
+ * the function that generates the code at the beginning
+ * to compute the header length. Since this code generator
+ * of PPI supports bare 802.11 encapsulation only (i.e.
+ * the encapsulated DLT should be DLT_IEEE802_11) we
+ * generate code to check for this too.
*/
off_linktype = 24;
- off_nl = 32; /* 802.11+802.2+SNAP */
- off_nl_nosnap = 27; /* 802.11+802.2 */
+ off_macpl = 0; /* link-layer header is variable-length */
+ off_macpl_is_variable = 1;
+ off_nl = 8; /* 802.2+SNAP */
+ off_nl_nosnap = 3; /* 802.2 */
return;
case DLT_ATM_RFC1483:
@@ -1072,6 +1091,7 @@ init_linktype(p)
* PPPo{A,E} and a PPP protocol of IP and....
*/
off_linktype = 0;
+ off_macpl = 0; /* packet begins with LLC header */
off_nl = 8; /* 802.2+SNAP */
off_nl_nosnap = 3; /* 802.2 */
return;
@@ -1085,23 +1105,26 @@ init_linktype(p)
off_vpi = SUNATM_VPI_POS;
off_vci = SUNATM_VCI_POS;
off_proto = PROTO_POS;
- off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */
+ off_mac = -1; /* assume LLC-encapsulated, so no MAC-layer header */
off_payload = SUNATM_PKT_BEGIN_POS;
off_linktype = off_payload;
- off_nl = off_payload+8; /* 802.2+SNAP */
- off_nl_nosnap = off_payload+3; /* 802.2 */
+ off_macpl = off_payload; /* if LLC-encapsulated */
+ off_nl = 8; /* 802.2+SNAP */
+ off_nl_nosnap = 3; /* 802.2 */
return;
case DLT_RAW:
off_linktype = -1;
+ off_macpl = 0;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_LINUX_SLL: /* fake header for Linux cooked socket */
off_linktype = 14;
- off_nl = 16;
- off_nl_nosnap = 16; /* no 802.2 LLC */
+ off_macpl = 16;
+ off_nl = 0;
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_LTALK:
@@ -1111,6 +1134,7 @@ init_linktype(p)
* "long" DDP packet following.
*/
off_linktype = -1;
+ off_macpl = 0;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
return;
@@ -1127,8 +1151,9 @@ init_linktype(p)
* 2625 says SNAP should be used.
*/
off_linktype = 16;
- off_nl = 24; /* IPFC+802.2+SNAP */
- off_nl_nosnap = 19; /* IPFC+802.2 */
+ off_macpl = 16;
+ off_nl = 8; /* 802.2+SNAP */
+ off_nl_nosnap = 3; /* 802.2 */
return;
case DLT_FRELAY:
@@ -1137,6 +1162,7 @@ init_linktype(p)
* frames (NLPID of 0x80).
*/
off_linktype = -1;
+ off_macpl = 0;
off_nl = 0;
off_nl_nosnap = 0; /* no 802.2 LLC */
return;
@@ -1148,14 +1174,16 @@ init_linktype(p)
*/
case DLT_MFR:
off_linktype = -1;
+ off_macpl = 0;
off_nl = 4;
off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */
return;
case DLT_APPLE_IP_OVER_IEEE1394:
off_linktype = 16;
- off_nl = 18;
- off_nl_nosnap = 18; /* no 802.2 LLC */
+ off_macpl = 18;
+ off_nl = 0;
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
case DLT_LINUX_IRDA:
@@ -1163,6 +1191,7 @@ init_linktype(p)
* Currently, only raw "link[N:M]" filtering is supported.
*/
off_linktype = -1;
+ off_macpl = -1;
off_nl = -1;
off_nl_nosnap = -1;
return;
@@ -1172,21 +1201,24 @@ init_linktype(p)
* Currently, only raw "link[N:M]" filtering is supported.
*/
off_linktype = -1;
+ off_macpl = -1;
off_nl = -1;
off_nl_nosnap = -1;
return;
case DLT_SYMANTEC_FIREWALL:
off_linktype = 6;
- off_nl = 44; /* Ethernet II */
- off_nl_nosnap = 44; /* XXX - what does it do with 802.3 packets? */
+ off_macpl = 44;
+ off_nl = 0; /* Ethernet II */
+ off_nl_nosnap = 0; /* XXX - what does it do with 802.3 packets? */
return;
#ifdef HAVE_NET_PFVAR_H
case DLT_PFLOG:
off_linktype = 0;
- off_nl = PFLOG_HDRLEN;
- off_nl_nosnap = PFLOG_HDRLEN; /* no 802.2 LLC */
+ off_macpl = PFLOG_HDRLEN;
+ off_nl = 0;
+ off_nl_nosnap = 0; /* no 802.2 LLC */
return;
#endif
@@ -1197,26 +1229,30 @@ init_linktype(p)
case DLT_JUNIPER_CHDLC:
case DLT_JUNIPER_FRELAY:
off_linktype = 4;
- off_nl = 4;
+ off_macpl = 4;
+ off_nl = 0;
off_nl_nosnap = -1; /* no 802.2 LLC */
return;
case DLT_JUNIPER_ATM1:
- off_linktype = 4; /* in reality variable between 4-8 */
- off_nl = 4;
- off_nl_nosnap = 14;
+ off_linktype = 4; /* in reality variable between 4-8 */
+ off_macpl = 4; /* in reality variable between 4-8 */
+ off_nl = 0;
+ off_nl_nosnap = 10;
return;
case DLT_JUNIPER_ATM2:
- off_linktype = 8; /* in reality variable between 8-12 */
- off_nl = 8;
- off_nl_nosnap = 18;
+ off_linktype = 8; /* in reality variable between 8-12 */
+ off_macpl = 8; /* in reality variable between 8-12 */
+ off_nl = 0;
+ off_nl_nosnap = 10;
return;
/* frames captured on a Juniper PPPoE service PIC
* contain raw ethernet frames */
case DLT_JUNIPER_PPPOE:
case DLT_JUNIPER_ETHER:
+ off_macpl = 14;
off_linktype = 16;
off_nl = 18; /* Ethernet II */
off_nl_nosnap = 21; /* 802.3+802.2 */
@@ -1224,36 +1260,56 @@ init_linktype(p)
case DLT_JUNIPER_PPPOE_ATM:
off_linktype = 4;
- off_nl = 6;
- off_nl_nosnap = -1; /* no 802.2 LLC */
+ off_macpl = 6;
+ off_nl = 0;
+ off_nl_nosnap = -1; /* no 802.2 LLC */
return;
case DLT_JUNIPER_GGSN:
off_linktype = 6;
- off_nl = 12;
- off_nl_nosnap = -1; /* no 802.2 LLC */
+ off_macpl = 12;
+ off_nl = 0;
+ off_nl_nosnap = -1; /* no 802.2 LLC */
return;
case DLT_JUNIPER_ES:
off_linktype = 6;
- off_nl = -1; /* not really a network layer but raw IP adresses */
+ off_macpl = -1; /* not really a network layer but raw IP addresses */
+ off_nl = -1; /* not really a network layer but raw IP addresses */
off_nl_nosnap = -1; /* no 802.2 LLC */
return;
case DLT_JUNIPER_MONITOR:
off_linktype = 12;
- off_nl = 12; /* raw IP/IP6 header */
+ off_macpl = 12;
+ off_nl = 0; /* raw IP/IP6 header */
off_nl_nosnap = -1; /* no 802.2 LLC */
return;
case DLT_JUNIPER_SERVICES:
off_linktype = 12;
+ off_macpl = -1; /* L3 proto location dep. on cookie type */
off_nl = -1; /* L3 proto location dep. on cookie type */
off_nl_nosnap = -1; /* no 802.2 LLC */
return;
case DLT_JUNIPER_VP:
off_linktype = 18;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_JUNIPER_ST:
+ off_linktype = 18;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_JUNIPER_ISM:
+ off_linktype = 8;
+ off_macpl = -1;
off_nl = -1;
off_nl_nosnap = -1;
return;
@@ -1265,6 +1321,7 @@ init_linktype(p)
off_dpc = 4;
off_sls = 7;
off_linktype = -1;
+ off_macpl = -1;
off_nl = -1;
off_nl_nosnap = -1;
return;
@@ -1276,6 +1333,19 @@ init_linktype(p)
off_dpc = 8;
off_sls = 11;
off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_ERF:
+ off_li = 22;
+ off_sio = 23;
+ off_opc = 24;
+ off_dpc = 24;
+ off_sls = 27;
+ off_linktype = -1;
+ off_macpl = -1;
off_nl = -1;
off_nl_nosnap = -1;
return;
@@ -1283,8 +1353,9 @@ init_linktype(p)
#ifdef DLT_PFSYNC
case DLT_PFSYNC:
off_linktype = -1;
- off_nl = 4;
- off_nl_nosnap = 4;
+ off_macpl = 4;
+ off_nl = 0;
+ off_nl_nosnap = 0;
return;
#endif
@@ -1293,6 +1364,7 @@ init_linktype(p)
* Currently, only raw "link[N:M]" filtering is supported.
*/
off_linktype = -1;
+ off_macpl = -1;
off_nl = -1;
off_nl_nosnap = -1;
return;
@@ -1302,6 +1374,7 @@ init_linktype(p)
* Currently, only raw "link[N:M]" filtering is supported.
*/
off_linktype = -1;
+ off_macpl = -1;
off_nl = -1;
off_nl_nosnap = -1;
return;
@@ -1311,6 +1384,118 @@ init_linktype(p)
* Currently, only raw "link[N:M]" filtering is supported.
*/
off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_USB_LINUX:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_CAN20B:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_IEEE802_15_4_LINUX:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_IEEE802_16_MAC_CPS_RADIO:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_IEEE802_15_4:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_SITA:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_RAIF1:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_IPMB:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_macpl = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
+ case DLT_AX25_KISS:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1; /* variable, min 15, max 71 steps of 7 */
+ off_macpl = -1;
+ off_nl = -1; /* variable, min 16, max 71 steps of 7 */
+ off_nl_nosnap = -1; /* no 802.2 LLC */
+ off_mac = 1; /* step over the kiss length byte */
+ return;
+
+ case DLT_IEEE802_15_4_NONASK_PHY:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ off_linktype = -1;
+ off_macpl = -1;
off_nl = -1;
off_nl_nosnap = -1;
return;
@@ -1364,6 +1549,45 @@ gen_load_llrel(offset, size)
return s;
}
+/*
+ * Load a value relative to the beginning of the MAC-layer payload.
+ */
+static struct slist *
+gen_load_macplrel(offset, size)
+ u_int offset, size;
+{
+ struct slist *s, *s2;
+
+ s = gen_off_macpl();
+
+ /*
+ * If s is non-null, the offset of the MAC-layer payload is
+ * variable, and s points to a list of instructions that
+ * arrange that the X register contains that offset.
+ *
+ * Otherwise, the offset of the MAC-layer payload is constant,
+ * and is in off_macpl.
+ */
+ if (s != NULL) {
+ /*
+ * The offset of the MAC-layer payload is in the X
+ * register. Do an indirect load, to use the X register
+ * as an offset.
+ */
+ s2 = new_stmt(BPF_LD|BPF_IND|size);
+ s2->s.k = offset;
+ sappend(s, s2);
+ } else {
+ /*
+ * The offset of the MAC-layer payload is constant,
+ * and is in off_macpl; load the value at that offset
+ * plus the specified offset.
+ */
+ s = new_stmt(BPF_LD|BPF_ABS|size);
+ s->s.k = off_macpl + offset;
+ }
+ return s;
+}
/*
* Load a value relative to the beginning of the specified header.
@@ -1386,12 +1610,16 @@ gen_load_a(offrel, offset, size)
s = gen_load_llrel(offset, size);
break;
+ case OR_MACPL:
+ s = gen_load_macplrel(offset, size);
+ break;
+
case OR_NET:
- s = gen_load_llrel(off_nl + offset, size);
+ s = gen_load_macplrel(off_nl + offset, size);
break;
case OR_NET_NOSNAP:
- s = gen_load_llrel(off_nl_nosnap + offset, size);
+ s = gen_load_macplrel(off_nl_nosnap + offset, size);
break;
case OR_TRAN_IPV4:
@@ -1404,21 +1632,22 @@ gen_load_a(offrel, offset, size)
s = gen_loadx_iphdrlen();
/*
- * Load the item at {offset of the link-layer header} +
- * {offset, relative to the start of the link-layer
- * header, of the IPv4 header} + {length of the IPv4 header} +
+ * Load the item at {offset of the MAC-layer payload} +
+ * {offset, relative to the start of the MAC-layer
+ * paylod, of the IPv4 header} + {length of the IPv4 header} +
* {specified offset}.
*
- * (If the link-layer is variable-length, it's included
- * in the value in the X register, and off_ll is 0.)
+ * (If the offset of the MAC-layer payload is variable,
+ * it's included in the value in the X register, and
+ * off_macpl is 0.)
*/
s2 = new_stmt(BPF_LD|BPF_IND|size);
- s2->s.k = off_ll + off_nl + offset;
+ s2->s.k = off_macpl + off_nl + offset;
sappend(s, s2);
break;
case OR_TRAN_IPV6:
- s = gen_load_llrel(off_nl + 40 + offset, size);
+ s = gen_load_macplrel(off_nl + 40 + offset, size);
break;
default:
@@ -1438,12 +1667,15 @@ gen_loadx_iphdrlen()
{
struct slist *s, *s2;
- s = gen_llprefixlen();
+ s = gen_off_macpl();
if (s != NULL) {
/*
* There's a variable-length prefix preceding the
- * link-layer header. "s" points to a list of statements
- * that put the length of that prefix into the X register.
+ * link-layer header, or the link-layer header is itself
+ * variable-length. "s" points to a list of statements
+ * that put the offset of the MAC-layer payload into
+ * the X register.
+ *
* The 4*([k]&0xf) addressing mode can't be used, as we
* don't have a constant offset, so we have to load the
* value in question into the A register and add to it
@@ -1461,22 +1693,24 @@ gen_loadx_iphdrlen()
/*
* The A register now contains the length of the
- * IP header. We need to add to it the length
- * of the prefix preceding the link-layer
- * header, which is still in the X register, and
- * move the result into the X register.
+ * IP header. We need to add to it the offset of
+ * the MAC-layer payload, which is still in the X
+ * register, and move the result into the X register.
*/
sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
sappend(s, new_stmt(BPF_MISC|BPF_TAX));
} else {
/*
* There is no variable-length header preceding the
- * link-layer header; add in off_ll, which, if there's
- * a fixed-length header preceding the link-layer header,
- * is the length of that header.
+ * link-layer header, and the link-layer header is
+ * fixed-length; load the length of the IPv4 header,
+ * which is at an offset of off_nl from the beginning
+ * of the MAC-layer payload, and thus at an offset
+ * of off_mac_pl + off_nl from the beginning of the
+ * raw packet data.
*/
s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
- s->s.k = off_ll + off_nl;
+ s->s.k = off_macpl + off_nl;
}
return s;
}
@@ -1550,7 +1784,7 @@ gen_ether_linktype(proto)
*/
b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
gen_not(b0);
- b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32)
+ b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)
((proto << 8) | proto));
gen_and(b0, b1);
return b1;
@@ -1588,17 +1822,15 @@ gen_ether_linktype(proto)
* This generates code to check both for the
* IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
*/
- b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
- (bpf_int32)LLCSAP_IPX);
- b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H,
- (bpf_int32)0xFFFF);
+ b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
+ b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)0xFFFF);
gen_or(b0, b1);
/*
* Now we add code to check for SNAP frames with
* ETHERTYPE_IPX, i.e. Ethernet_SNAP.
*/
- b0 = gen_snap(0x000000, ETHERTYPE_IPX, 14);
+ b0 = gen_snap(0x000000, ETHERTYPE_IPX);
gen_or(b0, b1);
/*
@@ -1653,9 +1885,9 @@ gen_ether_linktype(proto)
* type of ETHERTYPE_AARP (Appletalk ARP).
*/
if (proto == ETHERTYPE_ATALK)
- b1 = gen_snap(0x080007, ETHERTYPE_ATALK, 14);
+ b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
else /* proto == ETHERTYPE_AARP */
- b1 = gen_snap(0x000000, ETHERTYPE_AARP, 14);
+ b1 = gen_snap(0x000000, ETHERTYPE_AARP);
gen_and(b0, b1);
/*
@@ -1732,7 +1964,7 @@ gen_linux_sll_linktype(proto)
* (i.e., other SAP values)?
*/
b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
- b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_H, (bpf_int32)
+ b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)
((proto << 8) | proto));
gen_and(b0, b1);
return b1;
@@ -1763,10 +1995,8 @@ gen_linux_sll_linktype(proto)
* then put a check for LINUX_SLL_P_802_2 frames
* before it.
*/
- b0 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
- (bpf_int32)LLCSAP_IPX);
- b1 = gen_snap(0x000000, ETHERTYPE_IPX,
- off_linktype + 2);
+ b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
+ b1 = gen_snap(0x000000, ETHERTYPE_IPX);
gen_or(b0, b1);
b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
gen_and(b0, b1);
@@ -1814,11 +2044,9 @@ gen_linux_sll_linktype(proto)
* type of ETHERTYPE_AARP (Appletalk ARP).
*/
if (proto == ETHERTYPE_ATALK)
- b1 = gen_snap(0x080007, ETHERTYPE_ATALK,
- off_linktype + 2);
+ b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
else /* proto == ETHERTYPE_AARP */
- b1 = gen_snap(0x000000, ETHERTYPE_AARP,
- off_linktype + 2);
+ b1 = gen_snap(0x000000, ETHERTYPE_AARP);
gen_and(b0, b1);
/*
@@ -1842,7 +2070,7 @@ gen_linux_sll_linktype(proto)
*/
b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
LINUX_SLL_P_802_2);
- b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
+ b1 = gen_cmp(OR_LINK, off_macpl, BPF_B,
(bpf_int32)proto);
gen_and(b0, b1);
return b1;
@@ -1862,18 +2090,169 @@ gen_linux_sll_linktype(proto)
}
}
-static void
-insert_radiotap_load_llprefixlen(b)
- struct block *b;
+static struct slist *
+gen_load_prism_llprefixlen()
{
struct slist *s1, *s2;
+ struct slist *sjeq_avs_cookie;
+ struct slist *sjcommon;
+
+ /*
+ * This code is not compatible with the optimizer, as
+ * we are generating jmp instructions within a normal
+ * slist of instructions
+ */
+ no_optimize = 1;
/*
- * Prepend to the statements in this block code to load the
- * length of the radiotap header into the register assigned
- * to hold that length, if one has been assigned.
+ * Generate code to load the length of the radio header into
+ * the register assigned to hold that length, if one has been
+ * assigned. (If one hasn't been assigned, no code we've
+ * generated uses that prefix, so we don't need to generate any
+ * code to load it.)
+ *
+ * Some Linux drivers use ARPHRD_IEEE80211_PRISM but sometimes
+ * or always use the AVS header rather than the Prism header.
+ * We load a 4-byte big-endian value at the beginning of the
+ * raw packet data, and see whether, when masked with 0xFFFFF000,
+ * it's equal to 0x80211000. If so, that indicates that it's
+ * an AVS header (the masked-out bits are the version number).
+ * Otherwise, it's a Prism header.
+ *
+ * XXX - the Prism header is also, in theory, variable-length,
+ * but no known software generates headers that aren't 144
+ * bytes long.
*/
- if (reg_ll_size != -1) {
+ if (reg_off_ll != -1) {
+ /*
+ * Load the cookie.
+ */
+ s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+ s1->s.k = 0;
+
+ /*
+ * AND it with 0xFFFFF000.
+ */
+ s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
+ s2->s.k = 0xFFFFF000;
+ sappend(s1, s2);
+
+ /*
+ * Compare with 0x80211000.
+ */
+ sjeq_avs_cookie = new_stmt(JMP(BPF_JEQ));
+ sjeq_avs_cookie->s.k = 0x80211000;
+ sappend(s1, sjeq_avs_cookie);
+
+ /*
+ * If it's AVS:
+ *
+ * The 4 bytes at an offset of 4 from the beginning of
+ * the AVS header are the length of the AVS header.
+ * That field is big-endian.
+ */
+ s2 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+ s2->s.k = 4;
+ sappend(s1, s2);
+ sjeq_avs_cookie->s.jt = s2;
+
+ /*
+ * Now jump to the code to allocate a register
+ * into which to save the header length and
+ * store the length there. (The "jump always"
+ * instruction needs to have the k field set;
+ * it's added to the PC, so, as we're jumping
+ * over a single instruction, it should be 1.)
+ */
+ sjcommon = new_stmt(JMP(BPF_JA));
+ sjcommon->s.k = 1;
+ sappend(s1, sjcommon);
+
+ /*
+ * Now for the code that handles the Prism header.
+ * Just load the length of the Prism header (144)
+ * into the A register. Have the test for an AVS
+ * header branch here if we don't have an AVS header.
+ */
+ s2 = new_stmt(BPF_LD|BPF_W|BPF_IMM);
+ s2->s.k = 144;
+ sappend(s1, s2);
+ sjeq_avs_cookie->s.jf = s2;
+
+ /*
+ * Now allocate a register to hold that value and store
+ * it. The code for the AVS header will jump here after
+ * loading the length of the AVS header.
+ */
+ s2 = new_stmt(BPF_ST);
+ s2->s.k = reg_off_ll;
+ sappend(s1, s2);
+ sjcommon->s.jf = s2;
+
+ /*
+ * Now move it into the X register.
+ */
+ s2 = new_stmt(BPF_MISC|BPF_TAX);
+ sappend(s1, s2);
+
+ return (s1);
+ } else
+ return (NULL);
+}
+
+static struct slist *
+gen_load_avs_llprefixlen()
+{
+ struct slist *s1, *s2;
+
+ /*
+ * Generate code to load the length of the AVS header into
+ * the register assigned to hold that length, if one has been
+ * assigned. (If one hasn't been assigned, no code we've
+ * generated uses that prefix, so we don't need to generate any
+ * code to load it.)
+ */
+ if (reg_off_ll != -1) {
+ /*
+ * The 4 bytes at an offset of 4 from the beginning of
+ * the AVS header are the length of the AVS header.
+ * That field is big-endian.
+ */
+ s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+ s1->s.k = 4;
+
+ /*
+ * Now allocate a register to hold that value and store
+ * it.
+ */
+ s2 = new_stmt(BPF_ST);
+ s2->s.k = reg_off_ll;
+ sappend(s1, s2);
+
+ /*
+ * Now move it into the X register.
+ */
+ s2 = new_stmt(BPF_MISC|BPF_TAX);
+ sappend(s1, s2);
+
+ return (s1);
+ } else
+ return (NULL);
+}
+
+static struct slist *
+gen_load_radiotap_llprefixlen()
+{
+ struct slist *s1, *s2;
+
+ /*
+ * Generate code to load the length of the radiotap header into
+ * the register assigned to hold that length, if one has been
+ * assigned. (If one hasn't been assigned, no code we've
+ * generated uses that prefix, so we don't need to generate any
+ * code to load it.)
+ */
+ if (reg_off_ll != -1) {
/*
* The 2 bytes at offsets of 2 and 3 from the beginning
* of the radiotap header are the length of the radiotap
@@ -1908,7 +2287,7 @@ insert_radiotap_load_llprefixlen(b)
* it.
*/
s2 = new_stmt(BPF_ST);
- s2->s.k = reg_ll_size;
+ s2->s.k = reg_off_ll;
sappend(s1, s2);
/*
@@ -1917,13 +2296,9 @@ insert_radiotap_load_llprefixlen(b)
s2 = new_stmt(BPF_MISC|BPF_TAX);
sappend(s1, s2);
- /*
- * Now append all the existing statements in this
- * block to these statements.
- */
- sappend(s1, b->stmts);
- b->stmts = s1;
- }
+ return (s1);
+ } else
+ return (NULL);
}
/*
@@ -1932,21 +2307,21 @@ insert_radiotap_load_llprefixlen(b)
* the code at the beginning to compute the header length.
* Since this code generator of PPI supports bare 802.11
* encapsulation only (i.e. the encapsulated DLT should be
- * DLT_IEEE802_11) we generate code to check for this too.
+ * DLT_IEEE802_11) we generate code to check for this too;
+ * that's done in finish_parse().
*/
-static void
-insert_ppi_load_llprefixlen(b)
- struct block *b;
+static struct slist *
+gen_load_ppi_llprefixlen()
{
struct slist *s1, *s2;
/*
- * Prepend to the statements in this block code to load the
- * length of the radiotap header into the register assigned
- * to hold that length, if one has been assigned.
+ * Generate code to load the length of the radiotap header
+ * into the register assigned to hold that length, if one has
+ * been assigned.
*/
- if (reg_ll_size != -1) {
- /*
+ if (reg_off_ll != -1) {
+ /*
* The 2 bytes at offsets of 2 and 3 from the beginning
* of the radiotap header are the length of the radiotap
* header; unfortunately, it's little-endian, so we have
@@ -1980,7 +2355,7 @@ insert_ppi_load_llprefixlen(b)
* it.
*/
s2 = new_stmt(BPF_ST);
- s2->s.k = reg_ll_size;
+ s2->s.k = reg_off_ll;
sappend(s1, s2);
/*
@@ -1989,16 +2364,295 @@ insert_ppi_load_llprefixlen(b)
s2 = new_stmt(BPF_MISC|BPF_TAX);
sappend(s1, s2);
+ return (s1);
+ } else
+ return (NULL);
+}
+
+/*
+ * Load a value relative to the beginning of the link-layer header after the 802.11
+ * header, i.e. LLC_SNAP.
+ * The link-layer header doesn't necessarily begin at the beginning
+ * of the packet data; there might be a variable-length prefix containing
+ * radio information.
+ */
+static struct slist *
+gen_load_802_11_header_len(struct slist *s, struct slist *snext)
+{
+ struct slist *s2;
+ struct slist *sjset_data_frame_1;
+ struct slist *sjset_data_frame_2;
+ struct slist *sjset_qos;
+ struct slist *sjset_radiotap_flags;
+ struct slist *sjset_radiotap_tsft;
+ struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
+ struct slist *s_roundup;
+
+ if (reg_off_macpl == -1) {
/*
- * Now append all the existing statements in this
- * block to these statements.
+ * No register has been assigned to the offset of
+ * the MAC-layer payload, which means nobody needs
+ * it; don't bother computing it - just return
+ * what we already have.
*/
- sappend(s1, b->stmts);
- b->stmts = s1;
+ return (s);
+ }
+ /*
+ * This code is not compatible with the optimizer, as
+ * we are generating jmp instructions within a normal
+ * slist of instructions
+ */
+ no_optimize = 1;
+
+ /*
+ * If "s" is non-null, it has code to arrange that the X register
+ * contains the length of the prefix preceding the link-layer
+ * header.
+ *
+ * Otherwise, the length of the prefix preceding the link-layer
+ * header is "off_ll".
+ */
+ if (s == NULL) {
+ /*
+ * There is no variable-length header preceding the
+ * link-layer header.
+ *
+ * Load the length of the fixed-length prefix preceding
+ * the link-layer header (if any) into the X register,
+ * and store it in the reg_off_macpl register.
+ * That length is off_ll.
+ */
+ s = new_stmt(BPF_LDX|BPF_IMM);
+ s->s.k = off_ll;
}
+
+ /*
+ * The X register contains the offset of the beginning of the
+ * link-layer header; add 24, which is the minimum length
+ * of the MAC header for a data frame, to that, and store it
+ * in reg_off_macpl, and then load the Frame Control field,
+ * which is at the offset in the X register, with an indexed load.
+ */
+ s2 = new_stmt(BPF_MISC|BPF_TXA);
+ sappend(s, s2);
+ s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
+ s2->s.k = 24;
+ sappend(s, s2);
+ s2 = new_stmt(BPF_ST);
+ s2->s.k = reg_off_macpl;
+ sappend(s, s2);
+
+ s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
+ s2->s.k = 0;
+ sappend(s, s2);
+
+ /*
+ * Check the Frame Control field to see if this is a data frame;
+ * a data frame has the 0x08 bit (b3) in that field set and the
+ * 0x04 bit (b2) clear.
+ */
+ sjset_data_frame_1 = new_stmt(JMP(BPF_JSET));
+ sjset_data_frame_1->s.k = 0x08;
+ sappend(s, sjset_data_frame_1);
+
+ /*
+ * If b3 is set, test b2, otherwise go to the first statement of
+ * the rest of the program.
+ */
+ sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(JMP(BPF_JSET));
+ sjset_data_frame_2->s.k = 0x04;
+ sappend(s, sjset_data_frame_2);
+ sjset_data_frame_1->s.jf = snext;
+
+ /*
+ * If b2 is not set, this is a data frame; test the QoS bit.
+ * Otherwise, go to the first statement of the rest of the
+ * program.
+ */
+ sjset_data_frame_2->s.jt = snext;
+ sjset_data_frame_2->s.jf = sjset_qos = new_stmt(JMP(BPF_JSET));
+ sjset_qos->s.k = 0x80; /* QoS bit */
+ sappend(s, sjset_qos);
+
+ /*
+ * If it's set, add 2 to reg_off_macpl, to skip the QoS
+ * field.
+ * Otherwise, go to the first statement of the rest of the
+ * program.
+ */
+ sjset_qos->s.jt = s2 = new_stmt(BPF_LD|BPF_MEM);
+ s2->s.k = reg_off_macpl;
+ sappend(s, s2);
+ s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
+ s2->s.k = 2;
+ sappend(s, s2);
+ s2 = new_stmt(BPF_ST);
+ s2->s.k = reg_off_macpl;
+ sappend(s, s2);
+
+ /*
+ * If we have a radiotap header, look at it to see whether
+ * there's Atheros padding between the MAC-layer header
+ * and the payload.
+ *
+ * Note: all of the fields in the radiotap header are
+ * little-endian, so we byte-swap all of the values
+ * we test against, as they will be loaded as big-endian
+ * values.
+ */
+ if (linktype == DLT_IEEE802_11_RADIO) {
+ /*
+ * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
+ * in the presence flag?
+ */
+ sjset_qos->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_W);
+ s2->s.k = 4;
+ sappend(s, s2);
+
+ sjset_radiotap_flags = new_stmt(JMP(BPF_JSET));
+ sjset_radiotap_flags->s.k = SWAPLONG(0x00000002);
+ sappend(s, sjset_radiotap_flags);
+
+ /*
+ * If not, skip all of this.
+ */
+ sjset_radiotap_flags->s.jf = snext;
+
+ /*
+ * Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set?
+ */
+ sjset_radiotap_tsft = sjset_radiotap_flags->s.jt =
+ new_stmt(JMP(BPF_JSET));
+ sjset_radiotap_tsft->s.k = SWAPLONG(0x00000001);
+ sappend(s, sjset_radiotap_tsft);
+
+ /*
+ * If IEEE80211_RADIOTAP_TSFT is set, the flags field is
+ * at an offset of 16 from the beginning of the raw packet
+ * data (8 bytes for the radiotap header and 8 bytes for
+ * the TSFT field).
+ *
+ * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
+ * is set.
+ */
+ sjset_radiotap_tsft->s.jt = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+ s2->s.k = 16;
+ sappend(s, s2);
+
+ sjset_tsft_datapad = new_stmt(JMP(BPF_JSET));
+ sjset_tsft_datapad->s.k = 0x20;
+ sappend(s, sjset_tsft_datapad);
+
+ /*
+ * If IEEE80211_RADIOTAP_TSFT is not set, the flags field is
+ * at an offset of 8 from the beginning of the raw packet
+ * data (8 bytes for the radiotap header).
+ *
+ * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
+ * is set.
+ */
+ sjset_radiotap_tsft->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
+ s2->s.k = 8;
+ sappend(s, s2);
+
+ sjset_notsft_datapad = new_stmt(JMP(BPF_JSET));
+ sjset_notsft_datapad->s.k = 0x20;
+ sappend(s, sjset_notsft_datapad);
+
+ /*
+ * In either case, if IEEE80211_RADIOTAP_F_DATAPAD is
+ * set, round the length of the 802.11 header to
+ * a multiple of 4. Do that by adding 3 and then
+ * dividing by and multiplying by 4, which we do by
+ * ANDing with ~3.
+ */
+ s_roundup = new_stmt(BPF_LD|BPF_MEM);
+ s_roundup->s.k = reg_off_macpl;
+ sappend(s, s_roundup);
+ s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
+ s2->s.k = 3;
+ sappend(s, s2);
+ s2 = new_stmt(BPF_ALU|BPF_AND|BPF_IMM);
+ s2->s.k = ~3;
+ sappend(s, s2);
+ s2 = new_stmt(BPF_ST);
+ s2->s.k = reg_off_macpl;
+ sappend(s, s2);
+
+ sjset_tsft_datapad->s.jt = s_roundup;
+ sjset_tsft_datapad->s.jf = snext;
+ sjset_notsft_datapad->s.jt = s_roundup;
+ sjset_notsft_datapad->s.jf = snext;
+ } else
+ sjset_qos->s.jf = snext;
+
+ return s;
}
-
+
+static void
+insert_compute_vloffsets(b)
+ struct block *b;
+{
+ struct slist *s;
+
+ /*
+ * For link-layer types that have a variable-length header
+ * preceding the link-layer header, generate code to load
+ * the offset of the link-layer header into the register
+ * assigned to that offset, if any.
+ */
+ switch (linktype) {
+
+ case DLT_PRISM_HEADER:
+ s = gen_load_prism_llprefixlen();
+ break;
+
+ case DLT_IEEE802_11_RADIO_AVS:
+ s = gen_load_avs_llprefixlen();
+ break;
+
+ case DLT_IEEE802_11_RADIO:
+ s = gen_load_radiotap_llprefixlen();
+ break;
+
+ case DLT_PPI:
+ s = gen_load_ppi_llprefixlen();
+ break;
+
+ default:
+ s = NULL;
+ break;
+ }
+
+ /*
+ * For link-layer types that have a variable-length link-layer
+ * header, generate code to load the offset of the MAC-layer
+ * payload into the register assigned to that offset, if any.
+ */
+ switch (linktype) {
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ s = gen_load_802_11_header_len(s, b->stmts);
+ break;
+ }
+
+ /*
+ * If we have any offset-loading code, append all the
+ * existing statements in the block to those statements,
+ * and make the resulting list the list of statements
+ * for the block.
+ */
+ if (s != NULL) {
+ sappend(s, b->stmts);
+ b->stmts = s;
+ }
+}
+
static struct block *
gen_ppi_dlt_check(void)
{
@@ -2025,42 +2679,61 @@ gen_ppi_dlt_check(void)
return b;
}
-static void
-insert_load_llprefixlen(b)
- struct block *b;
+static struct slist *
+gen_prism_llprefixlen(void)
{
- switch (linktype) {
+ struct slist *s;
+
+ if (reg_off_ll == -1) {
+ /*
+ * We haven't yet assigned a register for the length
+ * of the radio header; allocate one.
+ */
+ reg_off_ll = alloc_reg();
+ }
- /*
- * At the moment we treat PPI as normal Radiotap encoded
- * packets. The difference is in the function that generates
- * the code at the beginning to compute the header length.
- * Since this code generator of PPI supports bare 802.11
- * encapsulation only (i.e. the encapsulated DLT should be
- * DLT_IEEE802_11) we generate code to check for this too.
+ /*
+ * Load the register containing the radio length
+ * into the X register.
*/
- case DLT_PPI:
- insert_ppi_load_llprefixlen(b);
- break;
+ s = new_stmt(BPF_LDX|BPF_MEM);
+ s->s.k = reg_off_ll;
+ return s;
+}
- case DLT_IEEE802_11_RADIO:
- insert_radiotap_load_llprefixlen(b);
- break;
+static struct slist *
+gen_avs_llprefixlen(void)
+{
+ struct slist *s;
+
+ if (reg_off_ll == -1) {
+ /*
+ * We haven't yet assigned a register for the length
+ * of the AVS header; allocate one.
+ */
+ reg_off_ll = alloc_reg();
}
-}
+ /*
+ * Load the register containing the AVS length
+ * into the X register.
+ */
+ s = new_stmt(BPF_LDX|BPF_MEM);
+ s->s.k = reg_off_ll;
+ return s;
+}
static struct slist *
gen_radiotap_llprefixlen(void)
{
struct slist *s;
- if (reg_ll_size == -1) {
+ if (reg_off_ll == -1) {
/*
* We haven't yet assigned a register for the length
* of the radiotap header; allocate one.
*/
- reg_ll_size = alloc_reg();
+ reg_off_ll = alloc_reg();
}
/*
@@ -2068,7 +2741,7 @@ gen_radiotap_llprefixlen(void)
* into the X register.
*/
s = new_stmt(BPF_LDX|BPF_MEM);
- s->s.k = reg_ll_size;
+ s->s.k = reg_off_ll;
return s;
}
@@ -2085,25 +2758,23 @@ gen_ppi_llprefixlen(void)
{
struct slist *s;
- if (reg_ll_size == -1) {
+ if (reg_off_ll == -1) {
/*
* We haven't yet assigned a register for the length
* of the radiotap header; allocate one.
*/
- reg_ll_size = alloc_reg();
+ reg_off_ll = alloc_reg();
}
/*
- * Load the register containing the radiotap length
+ * Load the register containing the PPI length
* into the X register.
*/
s = new_stmt(BPF_LDX|BPF_MEM);
- s->s.k = reg_ll_size;
+ s->s.k = reg_off_ll;
return s;
}
-
-
/*
* Generate code to compute the link-layer header length, if necessary,
* putting it into the X register, and to return either a pointer to a
@@ -2115,19 +2786,110 @@ gen_llprefixlen(void)
{
switch (linktype) {
- case DLT_PPI:
- return gen_ppi_llprefixlen();
+ case DLT_PRISM_HEADER:
+ return gen_prism_llprefixlen();
+
+ case DLT_IEEE802_11_RADIO_AVS:
+ return gen_avs_llprefixlen();
-
case DLT_IEEE802_11_RADIO:
return gen_radiotap_llprefixlen();
+ case DLT_PPI:
+ return gen_ppi_llprefixlen();
+
default:
return NULL;
}
}
/*
+ * Generate code to load the register containing the offset of the
+ * MAC-layer payload into the X register; if no register for that offset
+ * has been allocated, allocate it first.
+ */
+static struct slist *
+gen_off_macpl(void)
+{
+ struct slist *s;
+
+ if (off_macpl_is_variable) {
+ if (reg_off_macpl == -1) {
+ /*
+ * We haven't yet assigned a register for the offset
+ * of the MAC-layer payload; allocate one.
+ */
+ reg_off_macpl = alloc_reg();
+ }
+
+ /*
+ * Load the register containing the offset of the MAC-layer
+ * payload into the X register.
+ */
+ s = new_stmt(BPF_LDX|BPF_MEM);
+ s->s.k = reg_off_macpl;
+ return s;
+ } else {
+ /*
+ * That offset isn't variable, so we don't need to
+ * generate any code.
+ */
+ return NULL;
+ }
+}
+
+/*
+ * Map an Ethernet type to the equivalent PPP type.
+ */
+static int
+ethertype_to_ppptype(proto)
+ int proto;
+{
+ switch (proto) {
+
+ case ETHERTYPE_IP:
+ proto = PPP_IP;
+ break;
+
+#ifdef INET6
+ case ETHERTYPE_IPV6:
+ proto = PPP_IPV6;
+ break;
+#endif
+
+ case ETHERTYPE_DN:
+ proto = PPP_DECNET;
+ break;
+
+ case ETHERTYPE_ATALK:
+ proto = PPP_APPLE;
+ break;
+
+ case ETHERTYPE_NS:
+ proto = PPP_NS;
+ break;
+
+ case LLCSAP_ISONS:
+ proto = PPP_OSI;
+ break;
+
+ case LLCSAP_8021D:
+ /*
+ * I'm assuming the "Bridging PDU"s that go
+ * over PPP are Spanning Tree Protocol
+ * Bridging PDUs.
+ */
+ proto = PPP_BRPDU;
+ break;
+
+ case LLCSAP_IPX:
+ proto = PPP_IPX;
+ break;
+ }
+ return (proto);
+}
+
+/*
* Generate code to match a particular packet type by matching the
* link-layer type field or fields in the 802.2 LLC header.
*
@@ -2145,12 +2907,12 @@ gen_linktype(proto)
switch (proto) {
case ETHERTYPE_IP:
case PPP_IP:
- /* FIXME add other L3 proto IDs */
+ /* FIXME add other L3 proto IDs */
return gen_mpls_linktype(Q_IP);
case ETHERTYPE_IPV6:
case PPP_IPV6:
- /* FIXME add other L3 proto IDs */
+ /* FIXME add other L3 proto IDs */
return gen_mpls_linktype(Q_IPV6);
default:
@@ -2159,6 +2921,25 @@ gen_linktype(proto)
}
}
+ /*
+ * Are we testing PPPoE packets?
+ */
+ if (is_pppoes) {
+ /*
+ * The PPPoE session header is part of the
+ * MAC-layer payload, so all references
+ * should be relative to the beginning of
+ * that payload.
+ */
+
+ /*
+ * We use Ethernet protocol types inside libpcap;
+ * map them to the corresponding PPP protocol types.
+ */
+ proto = ethertype_to_ppptype(proto);
+ return gen_cmp(OR_MACPL, off_linktype, BPF_H, (bpf_int32)proto);
+ }
+
switch (linktype) {
case DLT_EN10MB:
@@ -2181,13 +2962,41 @@ gen_linktype(proto)
}
break;
- case DLT_PPI:
- case DLT_FDDI:
- case DLT_IEEE802:
case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
case DLT_IEEE802_11_RADIO:
- case DLT_PRISM_HEADER:
+ case DLT_PPI:
+ /*
+ * Check that we have a data frame.
+ */
+ b0 = gen_check_802_11_data_frame();
+
+ /*
+ * Now check for the specified link-layer type.
+ */
+ b1 = gen_llc_linktype(proto);
+ gen_and(b0, b1);
+ return b1;
+ /*NOTREACHED*/
+ break;
+
+ case DLT_FDDI:
+ /*
+ * XXX - check for asynchronous frames, as per RFC 1103.
+ */
+ return gen_llc_linktype(proto);
+ /*NOTREACHED*/
+ break;
+
+ case DLT_IEEE802:
+ /*
+ * XXX - check for LLC PDUs, as per IEEE 802.5.
+ */
+ return gen_llc_linktype(proto);
+ /*NOTREACHED*/
+ break;
+
case DLT_ATM_RFC1483:
case DLT_ATM_CLIP:
case DLT_IP_OVER_FC:
@@ -2272,47 +3081,9 @@ gen_linktype(proto)
* We use Ethernet protocol types inside libpcap;
* map them to the corresponding PPP protocol types.
*/
- switch (proto) {
-
- case ETHERTYPE_IP:
- proto = PPP_IP;
- break;
-
-#ifdef INET6
- case ETHERTYPE_IPV6:
- proto = PPP_IPV6;
- break;
-#endif
-
- case ETHERTYPE_DN:
- proto = PPP_DECNET;
- break;
-
- case ETHERTYPE_ATALK:
- proto = PPP_APPLE;
- break;
-
- case ETHERTYPE_NS:
- proto = PPP_NS;
- break;
-
- case LLCSAP_ISONS:
- proto = PPP_OSI;
- break;
-
- case LLCSAP_8021D:
- /*
- * I'm assuming the "Bridging PDU"s that go
- * over PPP are Spanning Tree Protocol
- * Bridging PDUs.
- */
- proto = PPP_BRPDU;
- break;
-
- case LLCSAP_IPX:
- proto = PPP_IPX;
- break;
- }
+ proto = ethertype_to_ppptype(proto);
+ return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
+ /*NOTREACHED*/
break;
case DLT_PPP_BSDOS:
@@ -2323,6 +3094,10 @@ gen_linktype(proto)
switch (proto) {
case ETHERTYPE_IP:
+ /*
+ * Also check for Van Jacobson-compressed IP.
+ * XXX - do this for other forms of PPP?
+ */
b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP);
b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC);
gen_or(b0, b1);
@@ -2330,42 +3105,12 @@ gen_linktype(proto)
gen_or(b1, b0);
return b0;
-#ifdef INET6
- case ETHERTYPE_IPV6:
- proto = PPP_IPV6;
- /* more to go? */
- break;
-#endif
-
- case ETHERTYPE_DN:
- proto = PPP_DECNET;
- break;
-
- case ETHERTYPE_ATALK:
- proto = PPP_APPLE;
- break;
-
- case ETHERTYPE_NS:
- proto = PPP_NS;
- break;
-
- case LLCSAP_ISONS:
- proto = PPP_OSI;
- break;
-
- case LLCSAP_8021D:
- /*
- * I'm assuming the "Bridging PDU"s that go
- * over PPP are Spanning Tree Protocol
- * Bridging PDUs.
- */
- proto = PPP_BRPDU;
- break;
-
- case LLCSAP_IPX:
- proto = PPP_IPX;
- break;
+ default:
+ proto = ethertype_to_ppptype(proto);
+ return gen_cmp(OR_LINK, off_linktype, BPF_H,
+ (bpf_int32)proto);
}
+ /*NOTREACHED*/
break;
case DLT_NULL:
@@ -2554,6 +3299,9 @@ gen_linktype(proto)
/*NOTREACHED*/
break;
+ case DLT_MFR:
+ bpf_error("Multi-link Frame Relay link-layer type filtering not implemented");
+
case DLT_JUNIPER_MFR:
case DLT_JUNIPER_MLFR:
case DLT_JUNIPER_MLPPP:
@@ -2570,6 +3318,8 @@ gen_linktype(proto)
case DLT_JUNIPER_FRELAY:
case DLT_JUNIPER_CHDLC:
case DLT_JUNIPER_VP:
+ case DLT_JUNIPER_ST:
+ case DLT_JUNIPER_ISM:
/* just lets verify the magic number for now -
* on ATM we may have up to 6 different encapsulations on the wire
* and need a lot of heuristics to figure out that the payload
@@ -2585,8 +3335,51 @@ gen_linktype(proto)
case DLT_DOCSIS:
bpf_error("DOCSIS link-layer type filtering not implemented");
+ case DLT_MTP2:
+ case DLT_MTP2_WITH_PHDR:
+ bpf_error("MTP2 link-layer type filtering not implemented");
+
+ case DLT_ERF:
+ bpf_error("ERF link-layer type filtering not implemented");
+
+#ifdef DLT_PFSYNC
+ case DLT_PFSYNC:
+ bpf_error("PFSYNC link-layer type filtering not implemented");
+#endif
+
case DLT_LINUX_LAPD:
bpf_error("LAPD link-layer type filtering not implemented");
+
+ case DLT_USB:
+ case DLT_USB_LINUX:
+ bpf_error("USB link-layer type filtering not implemented");
+
+ case DLT_BLUETOOTH_HCI_H4:
+ case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
+ bpf_error("Bluetooth link-layer type filtering not implemented");
+
+ case DLT_CAN20B:
+ bpf_error("CAN20B link-layer type filtering not implemented");
+
+ case DLT_IEEE802_15_4:
+ case DLT_IEEE802_15_4_LINUX:
+ case DLT_IEEE802_15_4_NONASK_PHY:
+ bpf_error("IEEE 802.15.4 link-layer type filtering not implemented");
+
+ case DLT_IEEE802_16_MAC_CPS_RADIO:
+ bpf_error("IEEE 802.16 link-layer type filtering not implemented");
+
+ case DLT_SITA:
+ bpf_error("SITA link-layer type filtering not implemented");
+
+ case DLT_RAIF1:
+ bpf_error("RAIF1 link-layer type filtering not implemented");
+
+ case DLT_IPMB:
+ bpf_error("IPMB link-layer type filtering not implemented");
+
+ case DLT_AX25_KISS:
+ bpf_error("AX.25 link-layer type filtering not implemented");
}
/*
@@ -2604,12 +3397,7 @@ gen_linktype(proto)
/*
* Any type not handled above should always have an Ethernet
- * type at an offset of "off_linktype". (PPP is partially
- * handled above - the protocol type is mapped from the
- * Ethernet and LLC types we use internally to the corresponding
- * PPP type - but the PPP type is always specified by a value
- * at "off_linktype", so we don't have to do the code generation
- * above.)
+ * type at an offset of "off_linktype".
*/
return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
}
@@ -2622,10 +3410,9 @@ gen_linktype(proto)
* code and protocol type in the SNAP header.
*/
static struct block *
-gen_snap(orgcode, ptype, offset)
+gen_snap(orgcode, ptype)
bpf_u_int32 orgcode;
bpf_u_int32 ptype;
- u_int offset;
{
u_char snapblock[8];
@@ -2637,7 +3424,7 @@ gen_snap(orgcode, ptype, offset)
snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */
snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */
snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */
- return gen_bcmp(OR_LINK, offset, 8, snapblock);
+ return gen_bcmp(OR_MACPL, 0, 8, snapblock);
}
/*
@@ -2670,7 +3457,7 @@ gen_llc_linktype(proto)
* DSAP, as we do for other types <= ETHERMTU
* (i.e., other SAP values)?
*/
- return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_u_int32)
+ return gen_cmp(OR_MACPL, 0, BPF_H, (bpf_u_int32)
((proto << 8) | proto));
case LLCSAP_IPX:
@@ -2678,7 +3465,7 @@ gen_llc_linktype(proto)
* XXX - are there ever SNAP frames for IPX on
* non-Ethernet 802.x networks?
*/
- return gen_cmp(OR_LINK, off_linktype, BPF_B,
+ return gen_cmp(OR_MACPL, 0, BPF_B,
(bpf_int32)LLCSAP_IPX);
case ETHERTYPE_ATALK:
@@ -2691,7 +3478,7 @@ gen_llc_linktype(proto)
* XXX - check for an organization code of
* encapsulated Ethernet as well?
*/
- return gen_snap(0x080007, ETHERTYPE_ATALK, off_linktype);
+ return gen_snap(0x080007, ETHERTYPE_ATALK);
default:
/*
@@ -2703,8 +3490,7 @@ gen_llc_linktype(proto)
* This is an LLC SAP value, so check
* the DSAP.
*/
- return gen_cmp(OR_LINK, off_linktype, BPF_B,
- (bpf_int32)proto);
+ return gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)proto);
} else {
/*
* This is an Ethernet type; we assume that it's
@@ -2719,15 +3505,13 @@ gen_llc_linktype(proto)
* organization code of 0x000000 (encapsulated
* Ethernet), we'd do
*
- * return gen_snap(0x000000, proto,
- * off_linktype);
+ * return gen_snap(0x000000, proto);
*
* here; for now, we don't, as per the above.
* I don't know whether it's worth the extra CPU
* time to do the right check or not.
*/
- return gen_cmp(OR_LINK, off_linktype+6, BPF_H,
- (bpf_int32)proto);
+ return gen_cmp(OR_MACPL, 6, BPF_H, (bpf_int32)proto);
}
}
}
@@ -2936,7 +3720,8 @@ gen_thostop(eaddr, dir)
}
/*
- * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN)
+ * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) and
+ * various 802.11 + radio headers.
*/
static struct block *
gen_wlanhostop(eaddr, dir)
@@ -2946,6 +3731,16 @@ gen_wlanhostop(eaddr, dir)
register struct block *b0, *b1, *b2;
register struct slist *s;
+#ifdef ENABLE_WLAN_FILTERING_PATCH
+ /*
+ * TODO GV 20070613
+ * We need to disable the optimizer because the optimizer is buggy
+ * and wipes out some LD instructions generated by the below
+ * code to validate the Frame Control bits
+ */
+ no_optimize = 1;
+#endif /* ENABLE_WLAN_FILTERING_PATCH */
+
switch (dir) {
case Q_SRC:
/*
@@ -3043,7 +3838,7 @@ gen_wlanhostop(eaddr, dir)
* Now check for a data frame.
* I.e, check "link[0] & 0x08".
*/
- gen_load_a(OR_LINK, 0, BPF_B);
+ s = gen_load_a(OR_LINK, 0, BPF_B);
b1 = new_block(JMP(BPF_JSET));
b1->s.k = 0x08;
b1->stmts = s;
@@ -3212,6 +4007,55 @@ gen_wlanhostop(eaddr, dir)
gen_and(b1, b0);
return b0;
+ /*
+ * XXX - add RA, TA, and BSSID keywords?
+ */
+ case Q_ADDR1:
+ return (gen_bcmp(OR_LINK, 4, 6, eaddr));
+
+ case Q_ADDR2:
+ /*
+ * Not present in CTS or ACK control frames.
+ */
+ b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+ IEEE80211_FC0_TYPE_MASK);
+ gen_not(b0);
+ b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+ IEEE80211_FC0_SUBTYPE_MASK);
+ gen_not(b1);
+ b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+ IEEE80211_FC0_SUBTYPE_MASK);
+ gen_not(b2);
+ gen_and(b1, b2);
+ gen_or(b0, b2);
+ b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
+ gen_and(b2, b1);
+ return b1;
+
+ case Q_ADDR3:
+ /*
+ * Not present in control frames.
+ */
+ b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+ IEEE80211_FC0_TYPE_MASK);
+ gen_not(b0);
+ b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_ADDR4:
+ /*
+ * Present only if the direction mask has both "From DS"
+ * and "To DS" set. Neither control frames nor management
+ * frames should have both of those set, so we don't
+ * check the frame type.
+ */
+ b0 = gen_mcmp(OR_LINK, 1, BPF_B,
+ IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
+ b1 = gen_bcmp(OR_LINK, 24, 6, eaddr);
+ gen_and(b0, b1);
+ return b1;
+
case Q_AND:
b0 = gen_wlanhostop(eaddr, Q_SRC);
b1 = gen_wlanhostop(eaddr, Q_DST);
@@ -3654,48 +4498,48 @@ gen_gateway(eaddr, alist, proto, dir)
case Q_IP:
case Q_ARP:
case Q_RARP:
- switch (linktype) {
- case DLT_EN10MB:
- b0 = gen_ehostop(eaddr, Q_OR);
- break;
- case DLT_FDDI:
- b0 = gen_fhostop(eaddr, Q_OR);
- break;
+ switch (linktype) {
+ case DLT_EN10MB:
+ b0 = gen_ehostop(eaddr, Q_OR);
+ break;
+ case DLT_FDDI:
+ b0 = gen_fhostop(eaddr, Q_OR);
+ break;
case DLT_IEEE802:
- b0 = gen_thostop(eaddr, Q_OR);
- break;
+ b0 = gen_thostop(eaddr, Q_OR);
+ break;
case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
- case DLT_PPI:
case DLT_IEEE802_11_RADIO:
- case DLT_PRISM_HEADER:
- b0 = gen_wlanhostop(eaddr, Q_OR);
- break;
- case DLT_SUNATM:
- if (is_lane) {
- /*
- * Check that the packet doesn't begin with an
- * LE Control marker. (We've already generated
- * a test for LANE.)
- */
- b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
- 0xFF00);
- gen_not(b1);
+ case DLT_PPI:
+ b0 = gen_wlanhostop(eaddr, Q_OR);
+ break;
+ case DLT_SUNATM:
+ if (is_lane) {
+ /*
+ * Check that the packet doesn't begin with an
+ * LE Control marker. (We've already generated
+ * a test for LANE.)
+ */
+ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
+ BPF_H, 0xFF00);
+ gen_not(b1);
- /*
- * Now check the MAC address.
- */
- b0 = gen_ehostop(eaddr, Q_OR);
- gen_and(b1, b0);
- }
- break;
+ /*
+ * Now check the MAC address.
+ */
+ b0 = gen_ehostop(eaddr, Q_OR);
+ gen_and(b1, b0);
+ }
+ break;
case DLT_IP_OVER_FC:
- b0 = gen_ipfchostop(eaddr, Q_OR);
- break;
- default:
- bpf_error(
+ b0 = gen_ipfchostop(eaddr, Q_OR);
+ break;
+ default:
+ bpf_error(
"'gateway' supported only on ethernet/FDDI/token ring/802.11/Fibre Channel");
- }
+ }
b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST);
while (*alist) {
tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR,
@@ -4460,7 +5304,8 @@ gen_protochain(v, proto, dir)
}
/*
- * We don't handle variable-length radiotap here headers yet.
+ * We don't handle variable-length prefixes before the link-layer
+ * header, or variable-length link-layer headers, here yet.
* We might want to add BPF instructions to do the protochain
* work, to simplify that and, on platforms that have a BPF
* interpreter with the new instructions, let the filtering
@@ -4469,11 +5314,15 @@ gen_protochain(v, proto, dir)
* branches, and backward branch support is unlikely to appear
* in kernel BPF engines.)
*/
- if (linktype == DLT_IEEE802_11_RADIO)
- bpf_error("'protochain' not supported with radiotap headers");
+ switch (linktype) {
- if (linktype == DLT_PPI)
- bpf_error("'protochain' not supported with PPI headers");
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ bpf_error("'protochain' not supported with 802.11");
+ }
no_optimize = 1; /*this code is not compatible with optimzer yet */
@@ -4492,11 +5341,11 @@ gen_protochain(v, proto, dir)
/* A = ip->ip_p */
s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
- s[i]->s.k = off_ll + off_nl + 9;
+ s[i]->s.k = off_macpl + off_nl + 9;
i++;
/* X = ip->ip_hl << 2 */
s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
- s[i]->s.k = off_ll + off_nl;
+ s[i]->s.k = off_macpl + off_nl;
i++;
break;
#ifdef INET6
@@ -4505,7 +5354,7 @@ gen_protochain(v, proto, dir)
/* A = ip6->ip_nxt */
s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
- s[i]->s.k = off_ll + off_nl + 6;
+ s[i]->s.k = off_macpl + off_nl + 6;
i++;
/* X = sizeof(struct ip6_hdr) */
s[i] = new_stmt(BPF_LDX|BPF_IMM);
@@ -4585,7 +5434,7 @@ gen_protochain(v, proto, dir)
i++;
/* A = P[X + packet head] */
s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_ll + off_nl;
+ s[i]->s.k = off_macpl + off_nl;
i++;
/* MEM[reg2] = A */
s[i] = new_stmt(BPF_ST);
@@ -4603,7 +5452,7 @@ gen_protochain(v, proto, dir)
i++;
/* A = P[X + packet head]; */
s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_ll + off_nl;
+ s[i]->s.k = off_macpl + off_nl;
i++;
/* A += 1 */
s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
@@ -4662,7 +5511,7 @@ gen_protochain(v, proto, dir)
i++;
/* A = P[X + packet head]; */
s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_ll + off_nl;
+ s[i]->s.k = off_macpl + off_nl;
i++;
/* MEM[reg2] = A */
s[i] = new_stmt(BPF_ST);
@@ -4680,7 +5529,7 @@ gen_protochain(v, proto, dir)
i++;
/* A = P[X + packet head] */
s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
- s[i]->s.k = off_ll + off_nl;
+ s[i]->s.k = off_macpl + off_nl;
i++;
/* A += 2 */
s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
@@ -4734,6 +5583,31 @@ gen_protochain(v, proto, dir)
#endif
}
+static struct block *
+gen_check_802_11_data_frame()
+{
+ struct slist *s;
+ struct block *b0, *b1;
+
+ /*
+ * A data frame has the 0x08 bit (b3) in the frame control field set
+ * and the 0x04 bit (b2) clear.
+ */
+ s = gen_load_a(OR_LINK, 0, BPF_B);
+ b0 = new_block(JMP(BPF_JSET));
+ b0->s.k = 0x08;
+ b0->stmts = s;
+
+ s = gen_load_a(OR_LINK, 0, BPF_B);
+ b1 = new_block(JMP(BPF_JSET));
+ b1->s.k = 0x04;
+ b1->stmts = s;
+ gen_not(b1);
+
+ gen_and(b1, b0);
+
+ return b0;
+}
/*
* Generate code that checks whether the packet is a packet for protocol
@@ -5021,9 +5895,9 @@ gen_scode(name, q)
return b;
case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
case DLT_IEEE802_11_RADIO_AVS:
case DLT_IEEE802_11_RADIO:
- case DLT_PRISM_HEADER:
case DLT_PPI:
eaddr = pcap_ether_hostton(name);
if (eaddr == NULL)
@@ -5252,7 +6126,6 @@ gen_scode(name, q)
else
bpf_error("unknown protocol: %s", name);
-
case Q_UNDEF:
syntax();
/* NOTREACHED */
@@ -5489,44 +6362,44 @@ gen_ecode(eaddr, q)
struct block *b, *tmp;
if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
- switch (linktype) {
- case DLT_EN10MB:
- return gen_ehostop(eaddr, (int)q.dir);
- case DLT_FDDI:
- return gen_fhostop(eaddr, (int)q.dir);
- case DLT_IEEE802:
- return gen_thostop(eaddr, (int)q.dir);
- case DLT_IEEE802_11:
- case DLT_IEEE802_11_RADIO_AVS:
- case DLT_IEEE802_11_RADIO:
- case DLT_PRISM_HEADER:
- case DLT_PPI:
- return gen_wlanhostop(eaddr, (int)q.dir);
- case DLT_SUNATM:
- if (is_lane) {
- /*
- * Check that the packet doesn't begin with an
- * LE Control marker. (We've already generated
- * a test for LANE.)
- */
- tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
- 0xFF00);
- gen_not(tmp);
-
- /*
- * Now check the MAC address.
- */
- b = gen_ehostop(eaddr, (int)q.dir);
- gen_and(tmp, b);
- return b;
- }
- break;
- case DLT_IP_OVER_FC:
- return gen_ipfchostop(eaddr, (int)q.dir);
- default:
- bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
- break;
- }
+ switch (linktype) {
+ case DLT_EN10MB:
+ return gen_ehostop(eaddr, (int)q.dir);
+ case DLT_FDDI:
+ return gen_fhostop(eaddr, (int)q.dir);
+ case DLT_IEEE802:
+ return gen_thostop(eaddr, (int)q.dir);
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ return gen_wlanhostop(eaddr, (int)q.dir);
+ case DLT_SUNATM:
+ if (is_lane) {
+ /*
+ * Check that the packet doesn't begin with an
+ * LE Control marker. (We've already generated
+ * a test for LANE.)
+ */
+ tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
+ 0xFF00);
+ gen_not(tmp);
+
+ /*
+ * Now check the MAC address.
+ */
+ b = gen_ehostop(eaddr, (int)q.dir);
+ gen_and(tmp, b);
+ return b;
+ }
+ break;
+ case DLT_IP_OVER_FC:
+ return gen_ipfchostop(eaddr, (int)q.dir);
+ default:
+ bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+ break;
+ }
}
bpf_error("ethernet address used in non-ether expression");
/* NOTREACHED */
@@ -5693,14 +6566,14 @@ gen_load(proto, inst, size)
* XXX - are there any cases where we want
* off_nl_nosnap?
*/
- s = gen_llprefixlen();
+ s = gen_off_macpl();
/*
* If "s" is non-null, it has code to arrange that the
- * X register contains the length of the prefix preceding
- * the link-layer header. Add to it the offset computed
- * into the register specified by "index", and move that
- * into the X register. Otherwise, just load into the X
+ * X register contains the offset of the MAC-layer
+ * payload. Add to it the offset computed into the
+ * register specified by "index", and move that into
+ * the X register. Otherwise, just load into the X
* register the offset computed into the register specifed
* by "index".
*/
@@ -5714,13 +6587,17 @@ gen_load(proto, inst, size)
/*
* Load the item at the sum of the offset we've put in the
* X register, the offset of the start of the network
- * layer header, and the offset of the start of the link
- * layer header (which is 0 if the radio header is
- * variable-length; that header length is what we put
- * into the X register and then added to the index).
+ * layer header from the beginning of the MAC-layer
+ * payload, and the purported offset of the start of the
+ * MAC-layer payload (which might be 0 if there's a
+ * variable-length prefix before the link-layer header
+ * or the link-layer header itself is variable-length;
+ * the variable-length offset of the start of the
+ * MAC-layer payload is what we put into the X register
+ * and then added to the index).
*/
tmp = new_stmt(BPF_LD|BPF_IND|size);
- tmp->s.k = off_ll + off_nl;
+ tmp->s.k = off_macpl + off_nl;
sappend(s, tmp);
sappend(inst->s, s);
@@ -5761,22 +6638,24 @@ gen_load(proto, inst, size)
/*
* The X register now contains the sum of the length
* of any variable-length header preceding the link-layer
- * header and the length of the network-layer header.
+ * header, any variable-length link-layer header, and the
+ * length of the network-layer header.
+ *
* Load into the A register the offset relative to
* the beginning of the transport layer header,
* add the X register to that, move that to the
* X register, and load with an offset from the
* X register equal to the offset of the network
* layer header relative to the beginning of
- * the link-layer header plus the length of any
- * fixed-length header preceding the link-layer
- * header.
+ * the MAC-layer payload plus the fixed-length
+ * portion of the offset of the MAC-layer payload
+ * from the beginning of the raw packet data.
*/
sappend(s, xfer_to_a(inst));
sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
sappend(s, new_stmt(BPF_MISC|BPF_TAX));
sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
- tmp->s.k = off_ll + off_nl;
+ tmp->s.k = off_macpl + off_nl;
sappend(inst->s, s);
/*
@@ -5943,6 +6822,16 @@ static int regused[BPF_MEMWORDS];
static int curreg;
/*
+ * Initialize the table of used registers and the current register.
+ */
+static void
+init_regs()
+{
+ curreg = 0;
+ memset(regused, 0, sizeof regused);
+}
+
+/*
* Return the next free register.
*/
static int
@@ -6073,46 +6962,46 @@ gen_broadcast(proto)
case Q_DEFAULT:
case Q_LINK:
- switch (linktype) {
- case DLT_ARCNET:
- case DLT_ARCNET_LINUX:
- return gen_ahostop(abroadcast, Q_DST);
- case DLT_EN10MB:
- return gen_ehostop(ebroadcast, Q_DST);
- case DLT_FDDI:
- return gen_fhostop(ebroadcast, Q_DST);
- case DLT_IEEE802:
- return gen_thostop(ebroadcast, Q_DST);
- case DLT_IEEE802_11:
- case DLT_IEEE802_11_RADIO_AVS:
- case DLT_IEEE802_11_RADIO:
- case DLT_PPI:
- case DLT_PRISM_HEADER:
- return gen_wlanhostop(ebroadcast, Q_DST);
- case DLT_IP_OVER_FC:
- return gen_ipfchostop(ebroadcast, Q_DST);
- case DLT_SUNATM:
- if (is_lane) {
- /*
- * Check that the packet doesn't begin with an
- * LE Control marker. (We've already generated
- * a test for LANE.)
- */
- b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
- 0xFF00);
- gen_not(b1);
+ switch (linktype) {
+ case DLT_ARCNET:
+ case DLT_ARCNET_LINUX:
+ return gen_ahostop(abroadcast, Q_DST);
+ case DLT_EN10MB:
+ return gen_ehostop(ebroadcast, Q_DST);
+ case DLT_FDDI:
+ return gen_fhostop(ebroadcast, Q_DST);
+ case DLT_IEEE802:
+ return gen_thostop(ebroadcast, Q_DST);
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ return gen_wlanhostop(ebroadcast, Q_DST);
+ case DLT_IP_OVER_FC:
+ return gen_ipfchostop(ebroadcast, Q_DST);
+ case DLT_SUNATM:
+ if (is_lane) {
+ /*
+ * Check that the packet doesn't begin with an
+ * LE Control marker. (We've already generated
+ * a test for LANE.)
+ */
+ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
+ BPF_H, 0xFF00);
+ gen_not(b1);
- /*
- * Now check the MAC address.
- */
- b0 = gen_ehostop(ebroadcast, Q_DST);
- gen_and(b1, b0);
- return b0;
- }
- break;
- default:
- bpf_error("not a broadcast link");
- }
+ /*
+ * Now check the MAC address.
+ */
+ b0 = gen_ehostop(ebroadcast, Q_DST);
+ gen_and(b1, b0);
+ return b0;
+ }
+ break;
+ default:
+ bpf_error("not a broadcast link");
+ }
break;
case Q_IP:
@@ -6160,167 +7049,167 @@ gen_multicast(proto)
case Q_DEFAULT:
case Q_LINK:
- switch (linktype) {
- case DLT_ARCNET:
- case DLT_ARCNET_LINUX:
- /* all ARCnet multicasts use the same address */
- return gen_ahostop(abroadcast, Q_DST);
- case DLT_EN10MB:
- /* ether[0] & 1 != 0 */
- return gen_mac_multicast(0);
- case DLT_FDDI:
- /*
- * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
- *
- * XXX - was that referring to bit-order issues?
- */
- /* fddi[1] & 1 != 0 */
- return gen_mac_multicast(1);
- case DLT_IEEE802:
- /* tr[2] & 1 != 0 */
- return gen_mac_multicast(2);
- case DLT_IEEE802_11:
- case DLT_IEEE802_11_RADIO_AVS:
- case DLT_PPI:
- case DLT_IEEE802_11_RADIO:
- case DLT_PRISM_HEADER:
- /*
- * Oh, yuk.
- *
- * For control frames, there is no DA.
- *
- * For management frames, DA is at an
- * offset of 4 from the beginning of
- * the packet.
- *
- * For data frames, DA is at an offset
- * of 4 from the beginning of the packet
- * if To DS is clear and at an offset of
- * 16 from the beginning of the packet
- * if To DS is set.
- */
-
- /*
- * Generate the tests to be done for data frames.
- *
- * First, check for To DS set, i.e. "link[1] & 0x01".
- */
- s = gen_load_a(OR_LINK, 1, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
- b1->s.k = 0x01; /* To DS */
- b1->stmts = s;
-
- /*
- * If To DS is set, the DA is at 16.
- */
- b0 = gen_mac_multicast(16);
- gen_and(b1, b0);
-
- /*
- * Now, check for To DS not set, i.e. check
- * "!(link[1] & 0x01)".
- */
- s = gen_load_a(OR_LINK, 1, BPF_B);
- b2 = new_block(JMP(BPF_JSET));
- b2->s.k = 0x01; /* To DS */
- b2->stmts = s;
- gen_not(b2);
-
- /*
- * If To DS is not set, the DA is at 4.
- */
- b1 = gen_mac_multicast(4);
- gen_and(b2, b1);
-
- /*
- * Now OR together the last two checks. That gives
- * the complete set of checks for data frames.
- */
- gen_or(b1, b0);
-
- /*
- * Now check for a data frame.
- * I.e, check "link[0] & 0x08".
- */
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
- b1->s.k = 0x08;
- b1->stmts = s;
-
- /*
- * AND that with the checks done for data frames.
- */
- gen_and(b1, b0);
-
- /*
- * If the high-order bit of the type value is 0, this
- * is a management frame.
- * I.e, check "!(link[0] & 0x08)".
- */
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b2 = new_block(JMP(BPF_JSET));
- b2->s.k = 0x08;
- b2->stmts = s;
- gen_not(b2);
-
- /*
- * For management frames, the DA is at 4.
- */
- b1 = gen_mac_multicast(4);
- gen_and(b2, b1);
-
- /*
- * OR that with the checks done for data frames.
- * That gives the checks done for management and
- * data frames.
- */
- gen_or(b1, b0);
-
- /*
- * If the low-order bit of the type value is 1,
- * this is either a control frame or a frame
- * with a reserved type, and thus not a
- * frame with an SA.
- *
- * I.e., check "!(link[0] & 0x04)".
- */
- s = gen_load_a(OR_LINK, 0, BPF_B);
- b1 = new_block(JMP(BPF_JSET));
- b1->s.k = 0x04;
- b1->stmts = s;
- gen_not(b1);
-
- /*
- * AND that with the checks for data and management
- * frames.
- */
- gen_and(b1, b0);
- return b0;
- case DLT_IP_OVER_FC:
- b0 = gen_mac_multicast(2);
- return b0;
- case DLT_SUNATM:
- if (is_lane) {
+ switch (linktype) {
+ case DLT_ARCNET:
+ case DLT_ARCNET_LINUX:
+ /* all ARCnet multicasts use the same address */
+ return gen_ahostop(abroadcast, Q_DST);
+ case DLT_EN10MB:
+ /* ether[0] & 1 != 0 */
+ return gen_mac_multicast(0);
+ case DLT_FDDI:
/*
- * Check that the packet doesn't begin with an
- * LE Control marker. (We've already generated
- * a test for LANE.)
+ * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
+ *
+ * XXX - was that referring to bit-order issues?
*/
- b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
- 0xFF00);
+ /* fddi[1] & 1 != 0 */
+ return gen_mac_multicast(1);
+ case DLT_IEEE802:
+ /* tr[2] & 1 != 0 */
+ return gen_mac_multicast(2);
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ /*
+ * Oh, yuk.
+ *
+ * For control frames, there is no DA.
+ *
+ * For management frames, DA is at an
+ * offset of 4 from the beginning of
+ * the packet.
+ *
+ * For data frames, DA is at an offset
+ * of 4 from the beginning of the packet
+ * if To DS is clear and at an offset of
+ * 16 from the beginning of the packet
+ * if To DS is set.
+ */
+
+ /*
+ * Generate the tests to be done for data frames.
+ *
+ * First, check for To DS set, i.e. "link[1] & 0x01".
+ */
+ s = gen_load_a(OR_LINK, 1, BPF_B);
+ b1 = new_block(JMP(BPF_JSET));
+ b1->s.k = 0x01; /* To DS */
+ b1->stmts = s;
+
+ /*
+ * If To DS is set, the DA is at 16.
+ */
+ b0 = gen_mac_multicast(16);
+ gen_and(b1, b0);
+
+ /*
+ * Now, check for To DS not set, i.e. check
+ * "!(link[1] & 0x01)".
+ */
+ s = gen_load_a(OR_LINK, 1, BPF_B);
+ b2 = new_block(JMP(BPF_JSET));
+ b2->s.k = 0x01; /* To DS */
+ b2->stmts = s;
+ gen_not(b2);
+
+ /*
+ * If To DS is not set, the DA is at 4.
+ */
+ b1 = gen_mac_multicast(4);
+ gen_and(b2, b1);
+
+ /*
+ * Now OR together the last two checks. That gives
+ * the complete set of checks for data frames.
+ */
+ gen_or(b1, b0);
+
+ /*
+ * Now check for a data frame.
+ * I.e, check "link[0] & 0x08".
+ */
+ s = gen_load_a(OR_LINK, 0, BPF_B);
+ b1 = new_block(JMP(BPF_JSET));
+ b1->s.k = 0x08;
+ b1->stmts = s;
+
+ /*
+ * AND that with the checks done for data frames.
+ */
+ gen_and(b1, b0);
+
+ /*
+ * If the high-order bit of the type value is 0, this
+ * is a management frame.
+ * I.e, check "!(link[0] & 0x08)".
+ */
+ s = gen_load_a(OR_LINK, 0, BPF_B);
+ b2 = new_block(JMP(BPF_JSET));
+ b2->s.k = 0x08;
+ b2->stmts = s;
+ gen_not(b2);
+
+ /*
+ * For management frames, the DA is at 4.
+ */
+ b1 = gen_mac_multicast(4);
+ gen_and(b2, b1);
+
+ /*
+ * OR that with the checks done for data frames.
+ * That gives the checks done for management and
+ * data frames.
+ */
+ gen_or(b1, b0);
+
+ /*
+ * If the low-order bit of the type value is 1,
+ * this is either a control frame or a frame
+ * with a reserved type, and thus not a
+ * frame with an SA.
+ *
+ * I.e., check "!(link[0] & 0x04)".
+ */
+ s = gen_load_a(OR_LINK, 0, BPF_B);
+ b1 = new_block(JMP(BPF_JSET));
+ b1->s.k = 0x04;
+ b1->stmts = s;
gen_not(b1);
- /* ether[off_mac] & 1 != 0 */
- b0 = gen_mac_multicast(off_mac);
+ /*
+ * AND that with the checks for data and management
+ * frames.
+ */
gen_and(b1, b0);
return b0;
- }
- break;
- default:
- break;
- }
- /* Link not known to support multicasts */
- break;
+ case DLT_IP_OVER_FC:
+ b0 = gen_mac_multicast(2);
+ return b0;
+ case DLT_SUNATM:
+ if (is_lane) {
+ /*
+ * Check that the packet doesn't begin with an
+ * LE Control marker. (We've already generated
+ * a test for LANE.)
+ */
+ b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
+ BPF_H, 0xFF00);
+ gen_not(b1);
+
+ /* ether[off_mac] & 1 != 0 */
+ b0 = gen_mac_multicast(off_mac);
+ gen_and(b1, b0);
+ return b0;
+ }
+ break;
+ default:
+ break;
+ }
+ /* Link not known to support multicasts */
+ break;
case Q_IP:
b0 = gen_linktype(ETHERTYPE_IP);
@@ -6417,6 +7306,8 @@ gen_inbound(dir)
case DLT_JUNIPER_FRELAY:
case DLT_JUNIPER_CHDLC:
case DLT_JUNIPER_VP:
+ case DLT_JUNIPER_ST:
+ case DLT_JUNIPER_ISM:
/* juniper flags (including direction) are stored
* the byte after the 3-byte magic number */
if (dir) {
@@ -6426,7 +7317,7 @@ gen_inbound(dir)
/* match incoming packets */
b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01);
}
- break;
+ break;
default:
bpf_error("inbound/outbound not supported on linktype %d",
@@ -6445,13 +7336,12 @@ gen_pf_ifname(const char *ifname)
struct block *b0;
u_int len, off;
- if (linktype == DLT_PFLOG) {
- len = sizeof(((struct pfloghdr *)0)->ifname);
- off = offsetof(struct pfloghdr, ifname);
- } else {
- bpf_error("ifname not supported on linktype 0x%x", linktype);
+ if (linktype != DLT_PFLOG) {
+ bpf_error("ifname supported only on PF linktype");
/* NOTREACHED */
}
+ len = sizeof(((struct pfloghdr *)0)->ifname);
+ off = offsetof(struct pfloghdr, ifname);
if (strlen(ifname) >= len) {
bpf_error("ifname interface names can only be %d characters",
len-1);
@@ -6468,14 +7358,16 @@ gen_pf_ruleset(char *ruleset)
struct block *b0;
if (linktype != DLT_PFLOG) {
- bpf_error("ruleset not supported on linktype 0x%x", linktype);
+ bpf_error("ruleset supported only on PF linktype");
/* NOTREACHED */
}
+
if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) {
bpf_error("ruleset names can only be %ld characters",
(long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1));
/* NOTREACHED */
}
+
b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset),
strlen(ruleset), (const u_char *)ruleset);
return (b0);
@@ -6487,14 +7379,13 @@ gen_pf_rnr(int rnr)
{
struct block *b0;
- if (linktype == DLT_PFLOG) {
- b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W,
- (bpf_int32)rnr);
- } else {
- bpf_error("rnr not supported on linktype 0x%x", linktype);
+ if (linktype != DLT_PFLOG) {
+ bpf_error("rnr supported only on PF linktype");
/* NOTREACHED */
}
+ b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W,
+ (bpf_int32)rnr);
return (b0);
}
@@ -6505,7 +7396,7 @@ gen_pf_srnr(int srnr)
struct block *b0;
if (linktype != DLT_PFLOG) {
- bpf_error("srnr not supported on linktype 0x%x", linktype);
+ bpf_error("srnr supported only on PF linktype");
/* NOTREACHED */
}
@@ -6520,14 +7411,13 @@ gen_pf_reason(int reason)
{
struct block *b0;
- if (linktype == DLT_PFLOG) {
- b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B,
- (bpf_int32)reason);
- } else {
- bpf_error("reason not supported on linktype 0x%x", linktype);
+ if (linktype != DLT_PFLOG) {
+ bpf_error("reason supported only on PF linktype");
/* NOTREACHED */
}
+ b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B,
+ (bpf_int32)reason);
return (b0);
}
@@ -6537,14 +7427,13 @@ gen_pf_action(int action)
{
struct block *b0;
- if (linktype == DLT_PFLOG) {
- b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B,
- (bpf_int32)action);
- } else {
- bpf_error("action not supported on linktype 0x%x", linktype);
+ if (linktype != DLT_PFLOG) {
+ bpf_error("action supported only on PF linktype");
/* NOTREACHED */
}
+ b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B,
+ (bpf_int32)action);
return (b0);
}
#else /* !HAVE_NET_PFVAR_H */
@@ -6597,14 +7486,75 @@ gen_pf_action(int action)
}
#endif /* HAVE_NET_PFVAR_H */
+/* IEEE 802.11 wireless header */
+struct block *
+gen_p80211_type(int type, int mask)
+{
+ struct block *b0;
+
+ switch (linktype) {
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ b0 = gen_mcmp(OR_LINK, 0, BPF_B, (bpf_int32)type,
+ (bpf_int32)mask);
+ break;
+
+ default:
+ bpf_error("802.11 link-layer types supported only on 802.11");
+ /* NOTREACHED */
+ }
+
+ return (b0);
+}
+
+struct block *
+gen_p80211_fcdir(int fcdir)
+{
+ struct block *b0;
+
+ switch (linktype) {
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ break;
+
+ default:
+ bpf_error("frame direction supported only with 802.11 headers");
+ /* NOTREACHED */
+ }
+
+ b0 = gen_mcmp(OR_LINK, 1, BPF_B, (bpf_int32)fcdir,
+ (bpf_u_int32)IEEE80211_FC1_DIR_MASK);
+
+ return (b0);
+}
+
struct block *
gen_acode(eaddr, q)
register const u_char *eaddr;
struct qual q;
{
- if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
- if (linktype == DLT_ARCNET || linktype == DLT_ARCNET_LINUX)
- return gen_ahostop(eaddr, (int)q.dir);
+ switch (linktype) {
+
+ case DLT_ARCNET:
+ case DLT_ARCNET_LINUX:
+ if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
+ q.proto == Q_LINK)
+ return (gen_ahostop(eaddr, (int)q.dir));
+ else {
+ bpf_error("ARCnet address used in non-arc expression");
+ /* NOTREACHED */
+ }
+ break;
+
+ default:
+ bpf_error("aid supported only on ARCnet");
+ /* NOTREACHED */
}
bpf_error("ARCnet address used in non-arc expression");
/* NOTREACHED */
@@ -6657,10 +7607,11 @@ gen_vlan(vlan_num)
bpf_error("no VLAN match after MPLS");
/*
- * Change the offsets to point to the type and data fields within
- * the VLAN packet. Just increment the offsets, so that we
- * can support a hierarchy, e.g. "vlan 300 && vlan 200" to
- * capture VLAN 200 encapsulated within VLAN 100.
+ * Check for a VLAN packet, and then change the offsets to point
+ * to the type and data fields within the VLAN packet. Just
+ * increment the offsets, so that we can support a hierarchy, e.g.
+ * "vlan 300 && vlan 200" to capture VLAN 200 encapsulated within
+ * VLAN 100.
*
* XXX - this is a bit of a kludge. If we were to split the
* compiler into a parser that parses an expression and
@@ -6686,15 +7637,29 @@ gen_vlan(vlan_num)
* be done assuming a VLAN, even though the "or" could be viewed
* as meaning "or, if this isn't a VLAN packet...".
*/
- orig_linktype = off_linktype; /* save original values */
orig_nl = off_nl;
switch (linktype) {
case DLT_EN10MB:
+ /* check for VLAN */
+ b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
+ (bpf_int32)ETHERTYPE_8021Q);
+
+ /* If a specific VLAN is requested, check VLAN id */
+ if (vlan_num >= 0) {
+ b1 = gen_mcmp(OR_MACPL, 0, BPF_H,
+ (bpf_int32)vlan_num, 0x0fff);
+ gen_and(b0, b1);
+ b0 = b1;
+ }
+
+ off_macpl += 4;
off_linktype += 4;
+#if 0
off_nl_nosnap += 4;
off_nl += 4;
+#endif
break;
default:
@@ -6703,17 +7668,6 @@ gen_vlan(vlan_num)
/*NOTREACHED*/
}
- /* check for VLAN */
- b0 = gen_cmp(OR_LINK, orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q);
-
- /* If a specific VLAN is requested, check VLAN id */
- if (vlan_num >= 0) {
- b1 = gen_mcmp(OR_LINK, orig_nl, BPF_H, (bpf_int32)vlan_num,
- 0x0fff);
- gen_and(b0, b1);
- b0 = b1;
- }
-
return (b0);
}
@@ -6739,7 +7693,7 @@ gen_mpls(label_num)
if (label_stack_depth > 0) {
/* just match the bottom-of-stack bit clear */
- b0 = gen_mcmp(OR_LINK, orig_nl-2, BPF_B, 0, 0x01);
+ b0 = gen_mcmp(OR_MACPL, orig_nl-2, BPF_B, 0, 0x01);
} else {
/*
* Indicate that we're checking MPLS-encapsulated headers,
@@ -6774,7 +7728,7 @@ gen_mpls(label_num)
/* If a specific MPLS label is requested, check it */
if (label_num >= 0) {
label_num = label_num << 12; /* label is shifted 12 bits on the wire */
- b1 = gen_mcmp(OR_LINK, orig_nl, BPF_W, (bpf_int32)label_num,
+ b1 = gen_mcmp(OR_MACPL, orig_nl, BPF_W, (bpf_int32)label_num,
0xfffff000); /* only compare the first 20 bits */
gen_and(b0, b1);
b0 = b1;
@@ -6808,7 +7762,8 @@ gen_pppoes()
/*
* Change the offsets to point to the type and data fields within
- * the PPP packet.
+ * the PPP packet, and note that this is PPPoE rather than
+ * raw PPP.
*
* XXX - this is a bit of a kludge. If we were to split the
* compiler into a parser that parses an expression and
@@ -6836,24 +7791,28 @@ gen_pppoes()
*/
orig_linktype = off_linktype; /* save original values */
orig_nl = off_nl;
+ is_pppoes = 1;
/*
* The "network-layer" protocol is PPPoE, which has a 6-byte
- * PPPoE header, followed by PPP payload, so we set the
- * offsets to the network layer offset plus 6 bytes for
- * the PPPoE header plus the values appropriate for PPP when
- * encapsulated in Ethernet (which means there's no HDLC
- * encapsulation).
+ * PPPoE header, followed by a PPP packet.
+ *
+ * There is no HDLC encapsulation for the PPP packet (it's
+ * encapsulated in PPPoES instead), so the link-layer type
+ * starts at the first byte of the PPP packet. For PPPoE,
+ * that offset is relative to the beginning of the total
+ * link-layer payload, including any 802.2 LLC header, so
+ * it's 6 bytes past off_nl.
*/
- off_linktype = orig_nl + 6;
- off_nl = orig_nl + 6 + 2;
- off_nl_nosnap = orig_nl + 6 + 2;
+ off_linktype = off_nl + 6;
/*
- * Set the link-layer type to PPP, as all subsequent tests will
- * be on the encapsulated PPP header.
+ * The network-layer offsets are relative to the beginning
+ * of the MAC-layer payload; that's past the 6-byte
+ * PPPoE header and the 2-byte PPP header.
*/
- linktype = DLT_PPP;
+ off_nl = 6+2;
+ off_nl_nosnap = 6+2;
return b0;
}
@@ -6999,8 +7958,9 @@ gen_atmtype_abbrev(type)
is_lane = 1;
off_mac = off_payload + 2; /* MAC header */
off_linktype = off_mac + 12;
- off_nl = off_mac + 14; /* Ethernet II */
- off_nl_nosnap = off_mac + 17; /* 802.3+802.2 */
+ off_macpl = off_mac + 14; /* Ethernet */
+ off_nl = 0; /* Ethernet II */
+ off_nl_nosnap = 3; /* 802.3+802.2 */
break;
case A_LLC:
@@ -7033,6 +7993,7 @@ gen_mtp2type_abbrev(type)
case M_FISU:
if ( (linktype != DLT_MTP2) &&
+ (linktype != DLT_ERF) &&
(linktype != DLT_MTP2_WITH_PHDR) )
bpf_error("'fisu' supported only on MTP2");
/* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
@@ -7041,6 +8002,7 @@ gen_mtp2type_abbrev(type)
case M_LSSU:
if ( (linktype != DLT_MTP2) &&
+ (linktype != DLT_ERF) &&
(linktype != DLT_MTP2_WITH_PHDR) )
bpf_error("'lssu' supported only on MTP2");
b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
@@ -7050,6 +8012,7 @@ gen_mtp2type_abbrev(type)
case M_MSU:
if ( (linktype != DLT_MTP2) &&
+ (linktype != DLT_ERF) &&
(linktype != DLT_MTP2_WITH_PHDR) )
bpf_error("'msu' supported only on MTP2");
b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
diff --git a/contrib/libpcap/gencode.h b/contrib/libpcap/gencode.h
index 9363a42..5fdec28 100644
--- a/contrib/libpcap/gencode.h
+++ b/contrib/libpcap/gencode.h
@@ -19,7 +19,7 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $FreeBSD$
- * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.60.2.11 2007/06/11 09:52:04 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.70.2.1 2007/11/18 02:04:55 guy Exp $ (LBL)
*/
/*
@@ -133,6 +133,10 @@
#define Q_DST 2
#define Q_OR 3
#define Q_AND 4
+#define Q_ADDR1 5
+#define Q_ADDR2 6
+#define Q_ADDR3 7
+#define Q_ADDR4 8
#define Q_DEFAULT 0
#define Q_UNDEF 255
@@ -313,6 +317,9 @@ struct block *gen_pf_reason(int);
struct block *gen_pf_action(int);
struct block *gen_pf_dir(int);
+struct block *gen_p80211_type(int, int);
+struct block *gen_p80211_fcdir(int);
+
void bpf_optimize(struct block **);
void bpf_error(const char *, ...)
__attribute__((noreturn, format (printf, 1, 2)));
diff --git a/contrib/libpcap/grammar.y b/contrib/libpcap/grammar.y
index 9d9b202..cc81984 100644
--- a/contrib/libpcap/grammar.y
+++ b/contrib/libpcap/grammar.y
@@ -23,7 +23,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.86.2.9 2007/09/12 19:17:25 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.99.2.2 2007/11/18 02:04:55 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -58,7 +58,8 @@ struct rtentry;
#include <net/pfvar.h>
#include <net/if_pflog.h>
#endif
-#include <pcap-namedb.h>
+#include "ieee80211.h"
+#include <pcap/namedb.h>
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
@@ -68,6 +69,92 @@ struct rtentry;
(q).dir = (d),\
(q).addr = (a)
+struct tok {
+ int v; /* value */
+ const char *s; /* string */
+};
+
+static const struct tok ieee80211_types[] = {
+ { IEEE80211_FC0_TYPE_DATA, "data" },
+ { IEEE80211_FC0_TYPE_MGT, "mgt" },
+ { IEEE80211_FC0_TYPE_MGT, "management" },
+ { IEEE80211_FC0_TYPE_CTL, "ctl" },
+ { IEEE80211_FC0_TYPE_CTL, "control" },
+ { 0, NULL }
+};
+static const struct tok ieee80211_mgt_subtypes[] = {
+ { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assocreq" },
+ { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assoc-req" },
+ { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assocresp" },
+ { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assoc-resp" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassocreq" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassoc-req" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassocresp" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassoc-resp" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probereq" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probe-req" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "proberesp" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "probe-resp" },
+ { IEEE80211_FC0_SUBTYPE_BEACON, "beacon" },
+ { IEEE80211_FC0_SUBTYPE_ATIM, "atim" },
+ { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassoc" },
+ { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassociation" },
+ { IEEE80211_FC0_SUBTYPE_AUTH, "auth" },
+ { IEEE80211_FC0_SUBTYPE_AUTH, "authentication" },
+ { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauth" },
+ { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauthentication" },
+ { 0, NULL }
+};
+static const struct tok ieee80211_ctl_subtypes[] = {
+ { IEEE80211_FC0_SUBTYPE_PS_POLL, "ps-poll" },
+ { IEEE80211_FC0_SUBTYPE_RTS, "rts" },
+ { IEEE80211_FC0_SUBTYPE_CTS, "cts" },
+ { IEEE80211_FC0_SUBTYPE_ACK, "ack" },
+ { IEEE80211_FC0_SUBTYPE_CF_END, "cf-end" },
+ { IEEE80211_FC0_SUBTYPE_CF_END_ACK, "cf-end-ack" },
+ { 0, NULL }
+};
+static const struct tok ieee80211_data_subtypes[] = {
+ { IEEE80211_FC0_SUBTYPE_DATA, "data" },
+ { IEEE80211_FC0_SUBTYPE_CF_ACK, "data-cf-ack" },
+ { IEEE80211_FC0_SUBTYPE_CF_POLL, "data-cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_CF_ACPL, "data-cf-ack-poll" },
+ { IEEE80211_FC0_SUBTYPE_NODATA, "null" },
+ { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK, "cf-ack" },
+ { IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "cf-ack-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_DATA, "qos-data" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACK, "qos-data-cf-ack" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_POLL, "qos-data-cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACPL, "qos-data-cf-ack-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA, "qos" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "qos-cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "qos-cf-ack-poll" },
+ { 0, NULL }
+};
+struct type2tok {
+ int type;
+ const struct tok *tok;
+};
+static const struct type2tok ieee80211_type_subtypes[] = {
+ { IEEE80211_FC0_TYPE_MGT, ieee80211_mgt_subtypes },
+ { IEEE80211_FC0_TYPE_CTL, ieee80211_ctl_subtypes },
+ { IEEE80211_FC0_TYPE_DATA, ieee80211_data_subtypes },
+ { 0, NULL }
+};
+
+static int
+str2tok(const char *str, const struct tok *toks)
+{
+ int i;
+
+ for (i = 0; toks[i].s != NULL; i++) {
+ if (pcap_strcasecmp(toks[i].s, str) == 0)
+ return (toks[i].v);
+ }
+ return (-1);
+}
+
int n_errors = 0;
static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
@@ -114,6 +201,16 @@ pfaction_to_num(const char *action)
else if (pcap_strcasecmp(action, "drop") == 0 ||
pcap_strcasecmp(action, "block") == 0)
return (PF_DROP);
+#if HAVE_PF_NAT_THROUGH_PF_NORDR
+ else if (pcap_strcasecmp(action, "rdr") == 0)
+ return (PF_RDR);
+ else if (pcap_strcasecmp(action, "nat") == 0)
+ return (PF_NAT);
+ else if (pcap_strcasecmp(action, "binat") == 0)
+ return (PF_BINAT);
+ else if (pcap_strcasecmp(action, "nordr") == 0)
+ return (PF_NORDR);
+#endif
else {
bpf_error("unknown PF action");
/*NOTREACHED*/
@@ -125,6 +222,9 @@ pfreason_to_num(const char *reason)
{
bpf_error("libpcap was compiled on a machine without pf support");
/*NOTREACHED*/
+
+ /* this is to make the VC compiler happy */
+ return -1;
}
static int
@@ -132,6 +232,9 @@ pfaction_to_num(const char *action)
{
bpf_error("libpcap was compiled on a machine without pf support");
/*NOTREACHED*/
+
+ /* this is to make the VC compiler happy */
+ return -1;
}
#endif /* HAVE_NET_PFVAR_H */
%}
@@ -158,7 +261,7 @@ pfaction_to_num(const char *action)
%type <a> arth narth
%type <i> byteop pname pnum relop irelop
%type <blk> and or paren not null prog
-%type <rblk> other pfvar
+%type <rblk> other pfvar p80211
%type <i> atmtype atmmultitype
%type <blk> atmfield
%type <blk> atmfieldvalue atmvalue atmlistvalue
@@ -174,6 +277,7 @@ pfaction_to_num(const char *action)
%token TK_BROADCAST TK_MULTICAST
%token NUM INBOUND OUTBOUND
%token PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION
+%token TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4
%token LINK
%token GEQ LEQ NEQ
%token ID EID HID HID6 AID
@@ -197,7 +301,7 @@ pfaction_to_num(const char *action)
%type <e> EID
%type <e> AID
%type <s> HID HID6
-%type <i> NUM action reason
+%type <i> NUM action reason type subtype type_subtype dir
%left OR AND
%nonassoc '!'
@@ -239,6 +343,14 @@ nid: ID { $$.b = gen_scode($1, $$.q = $<blk>0.q); }
| HID {
/* Decide how to parse HID based on proto */
$$.q = $<blk>0.q;
+ if ($$.q.addr == Q_PORT)
+ bpf_error("'port' modifier applied to ip host");
+ else if ($$.q.addr == Q_PORTRANGE)
+ bpf_error("'portrange' modifier applied to ip host");
+ else if ($$.q.addr == Q_PROTO)
+ bpf_error("'proto' modifier applied to ip host");
+ else if ($$.q.addr == Q_PROTOCHAIN)
+ bpf_error("'protochain' modifier applied to ip host");
$$.b = gen_ncode($1, 0, $$.q);
}
| HID6 '/' NUM {
@@ -326,6 +438,10 @@ dqual: SRC { $$ = Q_SRC; }
| DST OR SRC { $$ = Q_OR; }
| SRC AND DST { $$ = Q_AND; }
| DST AND SRC { $$ = Q_AND; }
+ | ADDR1 { $$ = Q_ADDR1; }
+ | ADDR2 { $$ = Q_ADDR2; }
+ | ADDR3 { $$ = Q_ADDR3; }
+ | ADDR4 { $$ = Q_ADDR4; }
;
/* address type qualifiers */
aqual: HOST { $$ = Q_HOST; }
@@ -389,6 +505,7 @@ other: pqual TK_BROADCAST { $$ = gen_broadcast($1); }
| PPPOED { $$ = gen_pppoed(); }
| PPPOES { $$ = gen_pppoes(); }
| pfvar { $$ = $1; }
+ | pqual p80211 { $$ = $2; }
;
pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); }
@@ -399,6 +516,79 @@ pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); }
| PF_ACTION action { $$ = gen_pf_action($2); }
;
+p80211: TYPE type SUBTYPE subtype
+ { $$ = gen_p80211_type($2 | $4,
+ IEEE80211_FC0_TYPE_MASK |
+ IEEE80211_FC0_SUBTYPE_MASK);
+ }
+ | TYPE type { $$ = gen_p80211_type($2,
+ IEEE80211_FC0_TYPE_MASK);
+ }
+ | SUBTYPE type_subtype { $$ = gen_p80211_type($2,
+ IEEE80211_FC0_TYPE_MASK |
+ IEEE80211_FC0_SUBTYPE_MASK);
+ }
+ | DIR dir { $$ = gen_p80211_fcdir($2); }
+ ;
+
+type: NUM
+ | ID { $$ = str2tok($1, ieee80211_types);
+ if ($$ == -1)
+ bpf_error("unknown 802.11 type name");
+ }
+ ;
+
+subtype: NUM
+ | ID { const struct tok *types = NULL;
+ int i;
+ for (i = 0;; i++) {
+ if (ieee80211_type_subtypes[i].tok == NULL) {
+ /* Ran out of types */
+ bpf_error("unknown 802.11 type");
+ break;
+ }
+ if ($<i>-1 == ieee80211_type_subtypes[i].type) {
+ types = ieee80211_type_subtypes[i].tok;
+ break;
+ }
+ }
+
+ $$ = str2tok($1, types);
+ if ($$ == -1)
+ bpf_error("unknown 802.11 subtype name");
+ }
+ ;
+
+type_subtype: ID { int i;
+ for (i = 0;; i++) {
+ if (ieee80211_type_subtypes[i].tok == NULL) {
+ /* Ran out of types */
+ bpf_error("unknown 802.11 type name");
+ break;
+ }
+ $$ = str2tok($1, ieee80211_type_subtypes[i].tok);
+ if ($$ != -1) {
+ $$ |= ieee80211_type_subtypes[i].type;
+ break;
+ }
+ }
+ }
+ ;
+
+dir: NUM
+ | ID { if (pcap_strcasecmp($1, "nods") == 0)
+ $$ = IEEE80211_FC1_DIR_NODS;
+ else if (pcap_strcasecmp($1, "tods") == 0)
+ $$ = IEEE80211_FC1_DIR_TODS;
+ else if (pcap_strcasecmp($1, "fromds") == 0)
+ $$ = IEEE80211_FC1_DIR_FROMDS;
+ else if (pcap_strcasecmp($1, "dstods") == 0)
+ $$ = IEEE80211_FC1_DIR_DSTODS;
+ else
+ bpf_error("unknown 802.11 direction");
+ }
+ ;
+
reason: NUM { $$ = $1; }
| ID { $$ = pfreason_to_num($1); }
;
diff --git a/contrib/libpcap/ieee80211.h b/contrib/libpcap/ieee80211.h
new file mode 100644
index 0000000..d79f0f8
--- /dev/null
+++ b/contrib/libpcap/ieee80211.h
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _NET80211_IEEE80211_H_
+#define _NET80211_IEEE80211_H_
+
+/*
+ * 802.11 protocol definitions.
+ */
+
+#define IEEE80211_FC0_VERSION_MASK 0x03
+#define IEEE80211_FC0_VERSION_SHIFT 0
+#define IEEE80211_FC0_VERSION_0 0x00
+#define IEEE80211_FC0_TYPE_MASK 0x0c
+#define IEEE80211_FC0_TYPE_SHIFT 2
+#define IEEE80211_FC0_TYPE_MGT 0x00
+#define IEEE80211_FC0_TYPE_CTL 0x04
+#define IEEE80211_FC0_TYPE_DATA 0x08
+
+#define IEEE80211_FC0_SUBTYPE_MASK 0xf0
+#define IEEE80211_FC0_SUBTYPE_SHIFT 4
+/* for TYPE_MGT */
+#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00
+#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10
+#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20
+#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30
+#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40
+#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50
+#define IEEE80211_FC0_SUBTYPE_BEACON 0x80
+#define IEEE80211_FC0_SUBTYPE_ATIM 0x90
+#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0
+#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0
+#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0
+/* for TYPE_CTL */
+#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0
+#define IEEE80211_FC0_SUBTYPE_RTS 0xb0
+#define IEEE80211_FC0_SUBTYPE_CTS 0xc0
+#define IEEE80211_FC0_SUBTYPE_ACK 0xd0
+#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0
+#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0
+/* for TYPE_DATA (bit combination) */
+#define IEEE80211_FC0_SUBTYPE_DATA 0x00
+#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10
+#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20
+#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30
+#define IEEE80211_FC0_SUBTYPE_NODATA 0x40
+#define IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK 0x50
+#define IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL 0x60
+#define IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL 0x70
+#define IEEE80211_FC0_SUBTYPE_QOS 0x80
+#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0
+
+#define IEEE80211_FC1_DIR_MASK 0x03
+#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */
+#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */
+#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */
+#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */
+
+#define IEEE80211_FC1_MORE_FRAG 0x04
+#define IEEE80211_FC1_RETRY 0x08
+#define IEEE80211_FC1_PWR_MGT 0x10
+#define IEEE80211_FC1_MORE_DATA 0x20
+#define IEEE80211_FC1_WEP 0x40
+#define IEEE80211_FC1_ORDER 0x80
+
+#define IEEE80211_SEQ_FRAG_MASK 0x000f
+#define IEEE80211_SEQ_FRAG_SHIFT 0
+#define IEEE80211_SEQ_SEQ_MASK 0xfff0
+#define IEEE80211_SEQ_SEQ_SHIFT 4
+
+#define IEEE80211_NWID_LEN 32
+
+#define IEEE80211_QOS_TXOP 0x00ff
+/* bit 8 is reserved */
+#define IEEE80211_QOS_ACKPOLICY 0x60
+#define IEEE80211_QOS_ACKPOLICY_S 5
+#define IEEE80211_QOS_ESOP 0x10
+#define IEEE80211_QOS_ESOP_S 4
+#define IEEE80211_QOS_TID 0x0f
+
+#define IEEE80211_MGT_SUBTYPE_NAMES { \
+ "assoc-req", "assoc-resp", \
+ "reassoc-req", "reassoc-resp", \
+ "probe-req", "probe-resp", \
+ "reserved#6", "reserved#7", \
+ "beacon", "atim", \
+ "disassoc", "auth", \
+ "deauth", "reserved#13", \
+ "reserved#14", "reserved#15" \
+}
+
+#define IEEE80211_CTL_SUBTYPE_NAMES { \
+ "reserved#0", "reserved#1", \
+ "reserved#2", "reserved#3", \
+ "reserved#3", "reserved#5", \
+ "reserved#6", "reserved#7", \
+ "reserved#8", "reserved#9", \
+ "ps-poll", "rts", \
+ "cts", "ack", \
+ "cf-end", "cf-end-ack" \
+}
+
+#define IEEE80211_DATA_SUBTYPE_NAMES { \
+ "data", "data-cf-ack", \
+ "data-cf-poll", "data-cf-ack-poll", \
+ "null", "cf-ack", \
+ "cf-poll", "cf-ack-poll", \
+ "qos-data", "qos-data-cf-ack", \
+ "qos-data-cf-poll", "qos-data-cf-ack-poll", \
+ "qos", "reserved#13", \
+ "qos-cf-poll", "qos-cf-ack-poll" \
+}
+
+#define IEEE80211_TYPE_NAMES { "mgt", "ctl", "data", "reserved#4" }
+
+#endif /* _NET80211_IEEE80211_H_ */
diff --git a/contrib/libpcap/inet.c b/contrib/libpcap/inet.c
index 8a44728..aad8796 100644
--- a/contrib/libpcap/inet.c
+++ b/contrib/libpcap/inet.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.66.2.6 2007/06/11 09:52:04 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.75.2.4 2008-04-20 18:19:24 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -356,6 +356,40 @@ add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
return (0);
}
+/*
+ * XXX - on FreeBSDs that support it, should it get the sysctl named
+ * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
+ * of the adapter? Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
+ * with my Cisco 350 card, so the name isn't entirely descriptive. The
+ * "dev.an.0.%pnpinfo" has a better description, although one might argue
+ * that the problem is really a driver bug - if it can find out that it's
+ * a Cisco 340 or 350, rather than an old Aironet card, it should use
+ * that in the description.
+ *
+ * Do NetBSD, DragonflyBSD, or OpenBSD support this as well? OpenBSD
+ * lets you get a description, but it's not generated by the OS, it's
+ * set with another ioctl that ifconfig supports; we use that to get
+ * the description in OpenBSD.
+ *
+ * In OS X, the System Configuration framework can apparently return
+ * names in 10.4 and later; it also appears that freedesktop.org's HAL
+ * offers an "info.product" string, but the HAL specification says
+ * it "should not be used in any UI" and "subsystem/capability
+ * specific properties" should be used instead. Using that would
+ * require that libpcap applications be linked with the frameworks/
+ * libraries in question, which would be a bit of a pain unless we
+ * offer, for example, a pkg-config:
+ *
+ * http://pkg-config.freedesktop.org/wiki/
+ *
+ * script, so applications can just use that script to find out what
+ * libraries you need to link with when linking with libpcap.
+ * pkg-config is GPLed; I don't know whether that would prevent its
+ * use with a BSD-licensed library such as libpcap.
+ *
+ * Do any other UN*Xes, or desktop environments support getting a
+ * description?
+ */
int
add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
struct sockaddr *addr, size_t addr_size,
@@ -365,9 +399,32 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
char *errbuf)
{
pcap_if_t *curdev;
+ char *description = NULL;
pcap_addr_t *curaddr, *prevaddr, *nextaddr;
+#ifdef SIOCGIFDESCR
+ struct ifreq ifrdesc;
+ char ifdescr[IFDESCRSIZE];
+ int s;
+#endif
- if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
+#ifdef SIOCGIFDESCR
+ /*
+ * Get the description for the interface.
+ */
+ memset(&ifrdesc, 0, sizeof ifrdesc);
+ strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
+ ifrdesc.ifr_data = (caddr_t)&ifdescr;
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s >= 0) {
+ if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0 &&
+ strlen(ifrdesc.ifr_data) != 0)
+ description = ifrdesc.ifr_data;
+ close(s);
+ }
+#endif
+
+ if (add_or_find_if(&curdev, alldevs, name, flags, description,
+ errbuf) == -1) {
/*
* Error - give up.
*/
@@ -608,6 +665,12 @@ pcap_lookupnet(device, netp, maskp, errbuf)
#ifdef HAVE_SEPTEL_API
|| strstr(device, "septel") != NULL
#endif
+#ifdef PCAP_SUPPORT_BT
+ || strstr(device, "bluetooth") != NULL
+#endif
+#ifdef PCAP_SUPPORT_USB
+ || strstr(device, "usb") != NULL
+#endif
) {
*netp = *maskp = 0;
return 0;
diff --git a/contrib/libpcap/missing/snprintf.c b/contrib/libpcap/missing/snprintf.c
new file mode 100644
index 0000000..9c0a6ee
--- /dev/null
+++ b/contrib/libpcap/missing/snprintf.c
@@ -0,0 +1,632 @@
+/*
+ * Copyright (c) 1995-1999 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * 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 Institute 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 INSTITUTE 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 INSTITUTE 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.
+ */
+
+/* $Id: snprintf.c,v 1.1 2004/04/05 22:43:51 guy Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/libpcap/missing/snprintf.c,v 1.1 2004/04/05 22:43:51 guy Exp $";
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#include <pcap-int.h>
+
+enum format_flags {
+ minus_flag = 1,
+ plus_flag = 2,
+ space_flag = 4,
+ alternate_flag = 8,
+ zero_flag = 16
+};
+
+/*
+ * Common state
+ */
+
+struct state {
+ unsigned char *str;
+ unsigned char *s;
+ unsigned char *theend;
+ size_t sz;
+ size_t max_sz;
+ int (*append_char)(struct state *, unsigned char);
+ int (*reserve)(struct state *, size_t);
+ /* XXX - methods */
+};
+
+#ifndef HAVE_VSNPRINTF
+static int
+sn_reserve (struct state *state, size_t n)
+{
+ return state->s + n > state->theend;
+}
+
+static int
+sn_append_char (struct state *state, unsigned char c)
+{
+ if (sn_reserve (state, 1)) {
+ return 1;
+ } else {
+ *state->s++ = c;
+ return 0;
+ }
+}
+#endif
+
+#if 0
+static int
+as_reserve (struct state *state, size_t n)
+{
+ if (state->s + n > state->theend) {
+ int off = state->s - state->str;
+ unsigned char *tmp;
+
+ if (state->max_sz && state->sz >= state->max_sz)
+ return 1;
+
+ state->sz = max(state->sz * 2, state->sz + n);
+ if (state->max_sz)
+ state->sz = min(state->sz, state->max_sz);
+ tmp = realloc (state->str, state->sz);
+ if (tmp == NULL)
+ return 1;
+ state->str = tmp;
+ state->s = state->str + off;
+ state->theend = state->str + state->sz - 1;
+ }
+ return 0;
+}
+
+static int
+as_append_char (struct state *state, unsigned char c)
+{
+ if(as_reserve (state, 1))
+ return 1;
+ else {
+ *state->s++ = c;
+ return 0;
+ }
+}
+#endif
+
+static int
+append_number(struct state *state,
+ unsigned long num, unsigned base, char *rep,
+ int width, int prec, int flags, int minusp)
+{
+ int len = 0;
+ int i;
+
+ /* given precision, ignore zero flag */
+ if(prec != -1)
+ flags &= ~zero_flag;
+ else
+ prec = 1;
+ /* zero value with zero precision -> "" */
+ if(prec == 0 && num == 0)
+ return 0;
+ do{
+ if((*state->append_char)(state, rep[num % base]))
+ return 1;
+ len++;
+ num /= base;
+ }while(num);
+ prec -= len;
+ /* pad with prec zeros */
+ while(prec-- > 0){
+ if((*state->append_char)(state, '0'))
+ return 1;
+ len++;
+ }
+ /* add length of alternate prefix (added later) to len */
+ if(flags & alternate_flag && (base == 16 || base == 8))
+ len += base / 8;
+ /* pad with zeros */
+ if(flags & zero_flag){
+ width -= len;
+ if(minusp || (flags & space_flag) || (flags & plus_flag))
+ width--;
+ while(width-- > 0){
+ if((*state->append_char)(state, '0'))
+ return 1;
+ len++;
+ }
+ }
+ /* add alternate prefix */
+ if(flags & alternate_flag && (base == 16 || base == 8)){
+ if(base == 16)
+ if((*state->append_char)(state, rep[10] + 23)) /* XXX */
+ return 1;
+ if((*state->append_char)(state, '0'))
+ return 1;
+ }
+ /* add sign */
+ if(minusp){
+ if((*state->append_char)(state, '-'))
+ return 1;
+ len++;
+ } else if(flags & plus_flag) {
+ if((*state->append_char)(state, '+'))
+ return 1;
+ len++;
+ } else if(flags & space_flag) {
+ if((*state->append_char)(state, ' '))
+ return 1;
+ len++;
+ }
+ if(flags & minus_flag)
+ /* swap before padding with spaces */
+ for(i = 0; i < len / 2; i++){
+ char c = state->s[-i-1];
+ state->s[-i-1] = state->s[-len+i];
+ state->s[-len+i] = c;
+ }
+ width -= len;
+ while(width-- > 0){
+ if((*state->append_char)(state, ' '))
+ return 1;
+ len++;
+ }
+ if(!(flags & minus_flag))
+ /* swap after padding with spaces */
+ for(i = 0; i < len / 2; i++){
+ char c = state->s[-i-1];
+ state->s[-i-1] = state->s[-len+i];
+ state->s[-len+i] = c;
+ }
+
+ return 0;
+}
+
+static int
+append_string (struct state *state,
+ unsigned char *arg,
+ int width,
+ int prec,
+ int flags)
+{
+ if(prec != -1)
+ width -= prec;
+ else
+ width -= strlen((char *)arg);
+ if(!(flags & minus_flag))
+ while(width-- > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+ if (prec != -1) {
+ while (*arg && prec--)
+ if ((*state->append_char) (state, *arg++))
+ return 1;
+ } else {
+ while (*arg)
+ if ((*state->append_char) (state, *arg++))
+ return 1;
+ }
+ if(flags & minus_flag)
+ while(width-- > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+ return 0;
+}
+
+static int
+append_char(struct state *state,
+ unsigned char arg,
+ int width,
+ int flags)
+{
+ while(!(flags & minus_flag) && --width > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+
+ if((*state->append_char) (state, arg))
+ return 1;
+ while((flags & minus_flag) && --width > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * This can't be made into a function...
+ */
+
+#define PARSE_INT_FORMAT(res, arg, unsig) \
+if (long_flag) \
+ res = (unsig long)va_arg(arg, unsig long); \
+else if (short_flag) \
+ res = (unsig short)va_arg(arg, unsig int); \
+else \
+ res = (unsig int)va_arg(arg, unsig int)
+
+/*
+ * zyxprintf - return 0 or -1
+ */
+
+static int
+xyzprintf (struct state *state, const char *char_format, va_list ap)
+{
+ const unsigned char *format = (const unsigned char *)char_format;
+ unsigned char c;
+
+ while((c = *format++)) {
+ if (c == '%') {
+ int flags = 0;
+ int width = 0;
+ int prec = -1;
+ int long_flag = 0;
+ int short_flag = 0;
+
+ /* flags */
+ while((c = *format++)){
+ if(c == '-')
+ flags |= minus_flag;
+ else if(c == '+')
+ flags |= plus_flag;
+ else if(c == ' ')
+ flags |= space_flag;
+ else if(c == '#')
+ flags |= alternate_flag;
+ else if(c == '0')
+ flags |= zero_flag;
+ else
+ break;
+ }
+
+ if((flags & space_flag) && (flags & plus_flag))
+ flags ^= space_flag;
+
+ if((flags & minus_flag) && (flags & zero_flag))
+ flags ^= zero_flag;
+
+ /* width */
+ if (isdigit(c))
+ do {
+ width = width * 10 + c - '0';
+ c = *format++;
+ } while(isdigit(c));
+ else if(c == '*') {
+ width = va_arg(ap, int);
+ c = *format++;
+ }
+
+ /* precision */
+ if (c == '.') {
+ prec = 0;
+ c = *format++;
+ if (isdigit(c))
+ do {
+ prec = prec * 10 + c - '0';
+ c = *format++;
+ } while(isdigit(c));
+ else if (c == '*') {
+ prec = va_arg(ap, int);
+ c = *format++;
+ }
+ }
+
+ /* size */
+
+ if (c == 'h') {
+ short_flag = 1;
+ c = *format++;
+ } else if (c == 'l') {
+ long_flag = 1;
+ c = *format++;
+ }
+
+ switch (c) {
+ case 'c' :
+ if(append_char(state, va_arg(ap, int), width, flags))
+ return -1;
+ break;
+ case 's' :
+ if (append_string(state,
+ va_arg(ap, unsigned char*),
+ width,
+ prec,
+ flags))
+ return -1;
+ break;
+ case 'd' :
+ case 'i' : {
+ long arg;
+ unsigned long num;
+ int minusp = 0;
+
+ PARSE_INT_FORMAT(arg, ap, signed);
+
+ if (arg < 0) {
+ minusp = 1;
+ num = -arg;
+ } else
+ num = arg;
+
+ if (append_number (state, num, 10, "0123456789",
+ width, prec, flags, minusp))
+ return -1;
+ break;
+ }
+ case 'u' : {
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 10, "0123456789",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'o' : {
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 010, "01234567",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'x' : {
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 0x10, "0123456789abcdef",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'X' :{
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 0x10, "0123456789ABCDEF",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'p' : {
+ unsigned long arg = (unsigned long)va_arg(ap, void*);
+
+ if (append_number (state, arg, 0x10, "0123456789ABCDEF",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'n' : {
+ int *arg = va_arg(ap, int*);
+ *arg = state->s - state->str;
+ break;
+ }
+ case '\0' :
+ --format;
+ /* FALLTHROUGH */
+ case '%' :
+ if ((*state->append_char)(state, c))
+ return -1;
+ break;
+ default :
+ if ( (*state->append_char)(state, '%')
+ || (*state->append_char)(state, c))
+ return -1;
+ break;
+ }
+ } else
+ if ((*state->append_char) (state, c))
+ return -1;
+ }
+ return 0;
+}
+
+#ifndef HAVE_SNPRINTF
+int
+snprintf (char *str, size_t sz, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = vsnprintf (str, sz, format, args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+
+ tmp = malloc (sz);
+ if (tmp == NULL)
+ abort ();
+
+ ret2 = vsprintf (tmp, format, args);
+ if (ret != ret2 || strcmp(str, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ va_end(args);
+ return ret;
+}
+#endif
+
+#if 0
+#ifndef HAVE_ASPRINTF
+int
+asprintf (char **ret, const char *format, ...)
+{
+ va_list args;
+ int val;
+
+ va_start(args, format);
+ val = vasprintf (ret, format, args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+ tmp = malloc (val + 1);
+ if (tmp == NULL)
+ abort ();
+
+ ret2 = vsprintf (tmp, format, args);
+ if (val != ret2 || strcmp(*ret, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ va_end(args);
+ return val;
+}
+#endif
+
+#ifndef HAVE_ASNPRINTF
+int
+asnprintf (char **ret, size_t max_sz, const char *format, ...)
+{
+ va_list args;
+ int val;
+
+ va_start(args, format);
+ val = vasnprintf (ret, max_sz, format, args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+ tmp = malloc (val + 1);
+ if (tmp == NULL)
+ abort ();
+
+ ret2 = vsprintf (tmp, format, args);
+ if (val != ret2 || strcmp(*ret, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ va_end(args);
+ return val;
+}
+#endif
+
+#ifndef HAVE_VASPRINTF
+int
+vasprintf (char **ret, const char *format, va_list args)
+{
+ return vasnprintf (ret, 0, format, args);
+}
+#endif
+
+
+#ifndef HAVE_VASNPRINTF
+int
+vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
+{
+ int st;
+ size_t len;
+ struct state state;
+
+ state.max_sz = max_sz;
+ state.sz = 1;
+ state.str = malloc(state.sz);
+ if (state.str == NULL) {
+ *ret = NULL;
+ return -1;
+ }
+ state.s = state.str;
+ state.theend = state.s + state.sz - 1;
+ state.append_char = as_append_char;
+ state.reserve = as_reserve;
+
+ st = xyzprintf (&state, format, args);
+ if (st) {
+ free (state.str);
+ *ret = NULL;
+ return -1;
+ } else {
+ char *tmp;
+
+ *state.s = '\0';
+ len = state.s - state.str;
+ tmp = realloc (state.str, len+1);
+ if (tmp == NULL) {
+ free (state.str);
+ *ret = NULL;
+ return -1;
+ }
+ *ret = tmp;
+ return len;
+ }
+}
+#endif
+#endif
+
+#ifndef HAVE_VSNPRINTF
+int
+vsnprintf (char *str, size_t sz, const char *format, va_list args)
+{
+ struct state state;
+ int ret;
+ unsigned char *ustr = (unsigned char *)str;
+
+ state.max_sz = 0;
+ state.sz = sz;
+ state.str = ustr;
+ state.s = ustr;
+ state.theend = ustr + sz - 1;
+ state.append_char = sn_append_char;
+ state.reserve = sn_reserve;
+
+ ret = xyzprintf (&state, format, args);
+ *state.s = '\0';
+ if (ret)
+ return sz;
+ else
+ return state.s - state.str;
+}
+#endif
+
diff --git a/contrib/libpcap/mkdep b/contrib/libpcap/mkdep
index 2a9c221..b41a00e 100755
--- a/contrib/libpcap/mkdep
+++ b/contrib/libpcap/mkdep
@@ -13,7 +13,7 @@
# @(#)mkdep.sh 5.11 (Berkeley) 5/5/88
#
-PATH=/bin:/usr/bin:/usr/ucb:/usr/local:/usr/local/bin
+PATH=/bin:/usr/bin:/usr/ucb:/usr/local:/usr/local/bin:/usr/sfw/bin
export PATH
MAKE=Makefile # default makefile name is "Makefile"
diff --git a/contrib/libpcap/nametoaddr.c b/contrib/libpcap/nametoaddr.c
index 791c281..479f1fd 100644
--- a/contrib/libpcap/nametoaddr.c
+++ b/contrib/libpcap/nametoaddr.c
@@ -26,7 +26,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.77.2.4 2007/06/11 09:52:05 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.82.2.1 2008/02/06 10:21:47 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -82,7 +82,7 @@ struct rtentry; /* declarations in <net/if.h> */
#include "pcap-int.h"
#include "gencode.h"
-#include <pcap-namedb.h>
+#include <pcap/namedb.h>
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
@@ -409,7 +409,15 @@ __pcap_atodn(const char *s, bpf_u_int32 *addr)
}
/*
- * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
+ * Convert 's', which can have the one of the forms:
+ *
+ * "xx:xx:xx:xx:xx:xx"
+ * "xx.xx.xx.xx.xx.xx"
+ * "xx-xx-xx-xx-xx-xx"
+ * "xxxx.xxxx.xxxx"
+ * "xxxxxxxxxxxx"
+ *
+ * (or various mixes of ':', '.', and '-') into a new
* ethernet address. Assumes 's' is well formed.
*/
u_char *
@@ -421,7 +429,7 @@ pcap_ether_aton(const char *s)
e = ep = (u_char *)malloc(6);
while (*s) {
- if (*s == ':')
+ if (*s == ':' || *s == '.' || *s == '-')
s += 1;
d = xdtoi(*s++);
if (isxdigit((unsigned char)*s)) {
diff --git a/contrib/libpcap/net/bpf_filter.c b/contrib/libpcap/net/bpf_filter.c
new file mode 100644
index 0000000..a2733d1
--- /dev/null
+++ b/contrib/libpcap/net/bpf_filter.c
@@ -0,0 +1,666 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.c 7.5 (Berkeley) 7/15/91
+ */
+
+#if !(defined(lint) || defined(KERNEL) || defined(_KERNEL))
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.45.2.1 2008/01/02 04:22:16 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+
+#include <pcap-stdinc.h>
+
+#else /* WIN32 */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+
+#define SOLARIS (defined(sun) && (defined(__SVR4) || defined(__svr4__)))
+#if defined(__hpux) || SOLARIS
+# include <sys/sysmacros.h>
+# include <sys/stream.h>
+# define mbuf msgb
+# define m_next b_cont
+# define MLEN(m) ((m)->b_wptr - (m)->b_rptr)
+# define mtod(m,t) ((t)(m)->b_rptr)
+#else
+# define MLEN(m) ((m)->m_len)
+#endif
+
+#endif /* WIN32 */
+
+#include <pcap/bpf.h>
+
+#if !defined(KERNEL) && !defined(_KERNEL)
+#include <stdlib.h>
+#endif
+
+#define int32 bpf_int32
+#define u_int32 bpf_u_int32
+
+#ifndef LBL_ALIGN
+/*
+ * XXX - IA-64? If not, this probably won't work on Win64 IA-64
+ * systems, unless LBL_ALIGN is defined elsewhere for them.
+ * XXX - SuperH? If not, this probably won't work on WinCE SuperH
+ * systems, unless LBL_ALIGN is defined elsewhere for them.
+ */
+#if defined(sparc) || defined(__sparc__) || defined(mips) || \
+ defined(ibm032) || defined(__alpha) || defined(__hpux) || \
+ defined(__arm__)
+#define LBL_ALIGN
+#endif
+#endif
+
+#ifndef LBL_ALIGN
+#ifndef WIN32
+#include <netinet/in.h>
+#endif
+
+#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p))
+#define EXTRACT_LONG(p) (ntohl(*(u_int32 *)p))
+#else
+#define EXTRACT_SHORT(p)\
+ ((u_short)\
+ ((u_short)*((u_char *)p+0)<<8|\
+ (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+ ((u_int32)*((u_char *)p+0)<<24|\
+ (u_int32)*((u_char *)p+1)<<16|\
+ (u_int32)*((u_char *)p+2)<<8|\
+ (u_int32)*((u_char *)p+3)<<0)
+#endif
+
+#if defined(KERNEL) || defined(_KERNEL)
+# if !defined(__hpux) && !SOLARIS
+#include <sys/mbuf.h>
+# endif
+#define MINDEX(len, _m, _k) \
+{ \
+ len = MLEN(m); \
+ while ((_k) >= len) { \
+ (_k) -= len; \
+ (_m) = (_m)->m_next; \
+ if ((_m) == 0) \
+ return 0; \
+ len = MLEN(m); \
+ } \
+}
+
+static int
+m_xword(m, k, err)
+ register struct mbuf *m;
+ register int k, *err;
+{
+ register int len;
+ register u_char *cp, *np;
+ register struct mbuf *m0;
+
+ MINDEX(len, m, k);
+ cp = mtod(m, u_char *) + k;
+ if (len - k >= 4) {
+ *err = 0;
+ return EXTRACT_LONG(cp);
+ }
+ m0 = m->m_next;
+ if (m0 == 0 || MLEN(m0) + len - k < 4)
+ goto bad;
+ *err = 0;
+ np = mtod(m0, u_char *);
+ switch (len - k) {
+
+ case 1:
+ return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
+
+ case 2:
+ return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
+
+ default:
+ return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
+ }
+ bad:
+ *err = 1;
+ return 0;
+}
+
+static int
+m_xhalf(m, k, err)
+ register struct mbuf *m;
+ register int k, *err;
+{
+ register int len;
+ register u_char *cp;
+ register struct mbuf *m0;
+
+ MINDEX(len, m, k);
+ cp = mtod(m, u_char *) + k;
+ if (len - k >= 2) {
+ *err = 0;
+ return EXTRACT_SHORT(cp);
+ }
+ m0 = m->m_next;
+ if (m0 == 0)
+ goto bad;
+ *err = 0;
+ return (cp[0] << 8) | mtod(m0, u_char *)[0];
+ bad:
+ *err = 1;
+ return 0;
+}
+#endif
+
+/*
+ * Execute the filter program starting at pc on the packet p
+ * wirelen is the length of the original packet
+ * buflen is the amount of data present
+ * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0,
+ * 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 const struct bpf_insn *pc;
+ register const u_char *p;
+ u_int wirelen;
+ register u_int buflen;
+{
+ register u_int32 A, X;
+ register int k;
+ int32 mem[BPF_MEMWORDS];
+#if defined(KERNEL) || defined(_KERNEL)
+ struct mbuf *m, *n;
+ int merr, len;
+
+ if (buflen == 0) {
+ m = (struct mbuf *)p;
+ p = mtod(m, u_char *);
+ buflen = MLEN(m);
+ } else
+ m = NULL;
+#endif
+
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (u_int)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+#if defined(KERNEL) || defined(_KERNEL)
+ return 0;
+#else
+ abort();
+#endif
+ case BPF_RET|BPF_K:
+ return (u_int)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (u_int)A;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(int32) > buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+ if (m == NULL)
+ return 0;
+ A = m_xword(m, k, &merr);
+ if (merr != 0)
+ return 0;
+ continue;
+#else
+ return 0;
+#endif
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(short) > buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+ if (m == NULL)
+ return 0;
+ A = m_xhalf(m, k, &merr);
+ if (merr != 0)
+ return 0;
+ continue;
+#else
+ return 0;
+#endif
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = pc->k;
+ if (k >= buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+ if (m == NULL)
+ return 0;
+ n = m;
+ MINDEX(len, n, k);
+ A = mtod(n, u_char *)[k];
+ continue;
+#else
+ return 0;
+#endif
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(int32) > buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+ if (m == NULL)
+ return 0;
+ A = m_xword(m, k, &merr);
+ if (merr != 0)
+ return 0;
+ continue;
+#else
+ return 0;
+#endif
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(short) > buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+ if (m == NULL)
+ return 0;
+ A = m_xhalf(m, k, &merr);
+ if (merr != 0)
+ return 0;
+ continue;
+#else
+ return 0;
+#endif
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ if (k >= buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+ if (m == NULL)
+ return 0;
+ n = m;
+ MINDEX(len, n, k);
+ A = mtod(n, u_char *)[k];
+ continue;
+#else
+ return 0;
+#endif
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if (k >= buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+ if (m == NULL)
+ return 0;
+ n = m;
+ MINDEX(len, n, k);
+ X = (mtod(n, char *)[k] & 0xf) << 2;
+ continue;
+#else
+ return 0;
+#endif
+ }
+ X = (p[pc->k] & 0xf) << 2;
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += (A > pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += (A >= pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += (A == pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ A = -A;
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+ }
+ }
+}
+
+/*
+ * Return true if the 'fcode' is a valid filter program.
+ * The constraints are that each jump be forward and to a valid
+ * code, that memory accesses are within valid ranges (to the
+ * extent that this can be checked statically; loads of packet
+ * data have to be, and are, also checked at run time), and that
+ * the code terminates with either an accept or reject.
+ *
+ * The kernel needs to be able to verify an application's filter code.
+ * Otherwise, a bogus program could easily crash the system.
+ */
+int
+bpf_validate(f, len)
+ const struct bpf_insn *f;
+ int len;
+{
+ u_int i, from;
+ const struct bpf_insn *p;
+
+ if (len < 1)
+ return 0;
+ /*
+ * There's no maximum program length in userland.
+ */
+#if defined(KERNEL) || defined(_KERNEL)
+ if (len > BPF_MAXINSNS)
+ return 0;
+#endif
+
+ for (i = 0; i < len; ++i) {
+ p = &f[i];
+ switch (BPF_CLASS(p->code)) {
+ /*
+ * Check that memory operations use valid addresses.
+ */
+ case BPF_LD:
+ case BPF_LDX:
+ switch (BPF_MODE(p->code)) {
+ case BPF_IMM:
+ break;
+ case BPF_ABS:
+ case BPF_IND:
+ case BPF_MSH:
+ /*
+ * There's no maximum packet data size
+ * in userland. The runtime packet length
+ * check suffices.
+ */
+#if defined(KERNEL) || defined(_KERNEL)
+ /*
+ * More strict check with actual packet length
+ * is done runtime.
+ */
+ if (p->k >= bpf_maxbufsize)
+ return 0;
+#endif
+ break;
+ case BPF_MEM:
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+ break;
+ case BPF_LEN:
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case BPF_ST:
+ case BPF_STX:
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+ break;
+ case BPF_ALU:
+ switch (BPF_OP(p->code)) {
+ case BPF_ADD:
+ case BPF_SUB:
+ case BPF_MUL:
+ case BPF_OR:
+ case BPF_AND:
+ case BPF_LSH:
+ case BPF_RSH:
+ case BPF_NEG:
+ break;
+ case BPF_DIV:
+ /*
+ * Check for constant division by 0.
+ */
+ if (BPF_RVAL(p->code) == BPF_K && p->k == 0)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case BPF_JMP:
+ /*
+ * Check that jumps are within the code block,
+ * and that unconditional branches don't go
+ * backwards as a result of an overflow.
+ * Unconditional branches have a 32-bit offset,
+ * so they could overflow; we check to make
+ * sure they don't. Conditional branches have
+ * an 8-bit offset, and the from address is <=
+ * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
+ * is sufficiently small that adding 255 to it
+ * won't overflow.
+ *
+ * We know that len is <= BPF_MAXINSNS, and we
+ * assume that BPF_MAXINSNS is < the maximum size
+ * of a u_int, so that i + 1 doesn't overflow.
+ *
+ * For userland, we don't know that the from
+ * or len are <= BPF_MAXINSNS, but we know that
+ * from <= len, and, except on a 64-bit system,
+ * it's unlikely that len, if it truly reflects
+ * the size of the program we've been handed,
+ * will be anywhere near the maximum size of
+ * a u_int. We also don't check for backward
+ * branches, as we currently support them in
+ * userland for the protochain operation.
+ */
+ from = i + 1;
+ switch (BPF_OP(p->code)) {
+ case BPF_JA:
+#if defined(KERNEL) || defined(_KERNEL)
+ if (from + p->k < from || from + p->k >= len)
+#else
+ if (from + p->k >= len)
+#endif
+ return 0;
+ break;
+ case BPF_JEQ:
+ case BPF_JGT:
+ case BPF_JGE:
+ case BPF_JSET:
+ if (from + p->jt >= len || from + p->jf >= len)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case BPF_RET:
+ break;
+ case BPF_MISC:
+ break;
+ default:
+ return 0;
+ }
+ }
+ return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
diff --git a/contrib/libpcap/optimize.c b/contrib/libpcap/optimize.c
index d39273b..475313f 100644
--- a/contrib/libpcap/optimize.c
+++ b/contrib/libpcap/optimize.c
@@ -22,7 +22,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.85.2.3 2007/09/12 21:29:45 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.90.2.1 2008/01/02 04:22:16 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -53,6 +53,10 @@ extern int _w32_ffs (int mask);
#define ffs _w32_ffs
#endif
+#if defined(WIN32) && defined (_MSC_VER)
+int ffs(int mask);
+#endif
+
/*
* Represents a deleted instruction.
*/
@@ -906,6 +910,17 @@ opt_peep(b)
JF(b) = JT(b);
}
/*
+ * If we're comparing against the index register, and the index
+ * register is a known constant, we can just compare against that
+ * constant.
+ */
+ val = b->val[X_ATOM];
+ if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_X) {
+ bpf_int32 v = vmap[val].const_val;
+ b->s.code &= ~BPF_X;
+ b->s.k = v;
+ }
+ /*
* If the accumulator is a known constant, we can compute the
* comparison result.
*/
@@ -2277,6 +2292,15 @@ install_bpf_program(pcap_t *p, struct bpf_program *fp)
size_t prog_size;
/*
+ * Validate the program.
+ */
+ if (!bpf_validate(fp->bf_insns, fp->bf_len)) {
+ snprintf(p->errbuf, sizeof(p->errbuf),
+ "BPF program is not valid");
+ return (-1);
+ }
+
+ /*
* Free up any already installed program.
*/
pcap_freecode(&p->fcode);
diff --git a/contrib/libpcap/packaging/pcap.spec.in b/contrib/libpcap/packaging/pcap.spec.in
index 388427e..9e63dac 100644
--- a/contrib/libpcap/packaging/pcap.spec.in
+++ b/contrib/libpcap/packaging/pcap.spec.in
@@ -15,7 +15,7 @@ URL: http://www.tcpdump.org
Packet-capture library LIBPCAP @VERSION@
Now maintained by "The Tcpdump Group"
See http://www.tcpdump.org
-Please send inquiries/comments/reports to tcpdump-workers@tcpdump.org
+Please send inquiries/comments/reports to tcpdump-workers@lists.tcpdump.org
%prep
%setup
@@ -29,10 +29,6 @@ make
%install
rm -rf $RPM_BUILD_ROOT
-mkdir -p $RPM_BUILD_ROOT/usr/{lib,include}
-mkdir -p $RPM_BUILD_ROOT/usr/share/man
-mkdir -p $RPM_BUILD_ROOT/usr/include/net
-mkdir -p $RPM_BUILD_ROOT/usr/man/man3
make install DESTDIR=$RPM_BUILD_ROOT mandir=/usr/share/man
cd $RPM_BUILD_ROOT/usr/lib
V1=`echo @VERSION@ | sed 's/\\.[^\.]*$//g'`
@@ -45,12 +41,6 @@ else
ln -sf libpcap.so.$V1 libpcap.so
fi
-#install -m 755 -o root libpcap.a $RPM_BUILD_ROOT/usr/lib
-#install -m 644 -o root pcap.3 $RPM_BUILD_ROOT/usr/man/man3
-#install -m 644 -o root pcap.h $RPM_BUILD_ROOT/usr/include
-#install -m 644 -o root pcap-bpf.h $RPM_BUILD_ROOT/usr/include/net
-#install -m 644 -o root pcap-namedb.h $RPM_BUILD_ROOT/usr/include
-
%clean
rm -rf $RPM_BUILD_ROOT
@@ -59,7 +49,10 @@ rm -rf $RPM_BUILD_ROOT
%doc LICENSE CHANGES INSTALL.txt README.linux TODO VERSION CREDITS packaging/pcap.spec
/usr/lib/libpcap.a
/usr/share/man/man3/*
+/usr/share/man/man5/*
+/usr/share/man/man7/*
/usr/include/pcap.h
+/usr/include/pcap/*.h
/usr/include/pcap-bpf.h
/usr/include/pcap-namedb.h
/usr/lib/libpcap.so*
diff --git a/contrib/libpcap/pcap-bpf.c b/contrib/libpcap/pcap-bpf.c
index d398ec7..8f35e4c 100644
--- a/contrib/libpcap/pcap-bpf.c
+++ b/contrib/libpcap/pcap-bpf.c
@@ -22,7 +22,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.86.2.12 2007/06/15 17:57:27 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.99.2.17 2008-09-16 18:43:02 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -30,7 +30,9 @@ static const char rcsid[] _U_ =
#endif
#include <sys/param.h> /* optionally get BSD define */
+#ifdef HAVE_ZEROCOPY_BPF
#include <sys/mman.h>
+#endif
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
@@ -38,12 +40,16 @@ static const char rcsid[] _U_ =
#include <sys/ioctl.h>
#include <sys/utsname.h>
+#ifdef HAVE_ZEROCOPY_BPF
+#include <machine/atomic.h>
+#endif
+
#include <net/if.h>
#ifdef _AIX
/*
- * Make "pcap.h" not include "pcap-bpf.h"; we are going to include the
+ * Make "pcap.h" not include "pcap/bpf.h"; we are going to include the
* native OS version, as we need "struct bpf_config" from it.
*/
#define PCAP_DONT_INCLUDE_PCAP_BPF_H
@@ -87,10 +93,6 @@ static int odmlockid = 0;
#endif /* _AIX */
-#ifdef BIOCSETBUFMODE
-#include <machine/atomic.h>
-#endif
-
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
@@ -99,6 +101,10 @@ static int odmlockid = 0;
#include <string.h>
#include <unistd.h>
+#ifdef HAVE_NET_IF_MEDIA_H
+# include <net/if_media.h>
+#endif
+
#include "pcap-int.h"
#ifdef HAVE_DAG_API
@@ -109,42 +115,114 @@ static int odmlockid = 0;
#include "os-proto.h"
#endif
-#include "gencode.h" /* for "no_optimize" */
+#ifdef BIOCGDLTLIST
+# if (defined(HAVE_NET_IF_MEDIA_H) && defined(IFM_IEEE80211)) && !defined(__APPLE__)
+#define HAVE_BSD_IEEE80211
+# endif
+
+# if defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)
+static int find_802_11(struct bpf_dltlist *);
+
+# ifdef HAVE_BSD_IEEE80211
+static int monitor_mode(pcap_t *, int);
+# endif
+# if defined(__APPLE__)
+static void remove_en(pcap_t *);
+static void remove_802_11(pcap_t *);
+# endif
+
+# endif /* defined(__APPLE__) || defined(HAVE_BSD_IEEE80211) */
+
+#endif /* BIOCGDLTLIST */
+
+/*
+ * We include the OS's <net/bpf.h>, not our "pcap/bpf.h", so we probably
+ * don't get DLT_DOCSIS defined.
+ */
+#ifndef DLT_DOCSIS
+#define DLT_DOCSIS 143
+#endif
+
+/*
+ * On OS X, we don't even get any of the 802.11-plus-radio-header DLT_'s
+ * defined, even though some of them are used by various Airport drivers.
+ */
+#ifndef DLT_PRISM_HEADER
+#define DLT_PRISM_HEADER 119
+#endif
+#ifndef DLT_AIRONET_HEADER
+#define DLT_AIRONET_HEADER 120
+#endif
+#ifndef DLT_IEEE802_11_RADIO
+#define DLT_IEEE802_11_RADIO 127
+#endif
+#ifndef DLT_IEEE802_11_RADIO_AVS
+#define DLT_IEEE802_11_RADIO_AVS 163
+#endif
+
+static int pcap_can_set_rfmon_bpf(pcap_t *p);
+static int pcap_activate_bpf(pcap_t *p);
static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp);
static int pcap_setdirection_bpf(pcap_t *, pcap_direction_t);
static int pcap_set_datalink_bpf(pcap_t *p, int dlt);
+#ifdef HAVE_ZEROCOPY_BPF
+/*
+ * For zerocopy bpf, we need to override the setnonblock/getnonblock routines
+ * so we don't call select(2) if the pcap handle is in non-blocking mode. We
+ * preserve the timeout supplied by pcap_open functions to make sure it
+ * does not get clobbered if the pcap handle moves between blocking and non-
+ * blocking mode.
+ */
static int
-pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps)
-{
- struct bpf_stat s;
-
+pcap_getnonblock_zbuf(pcap_t *p, char *errbuf)
+{
/*
- * "ps_recv" counts packets handed to the filter, not packets
- * that passed the filter. This includes packets later dropped
- * because we ran out of buffer space.
- *
- * "ps_drop" counts packets dropped inside the BPF device
- * because we ran out of buffer space. It doesn't count
- * packets dropped by the interface driver. It counts
- * only packets that passed the filter.
- *
- * Both statistics include packets not yet read from the kernel
- * by libpcap, and thus not yet seen by the application.
+ * Use a negative value for the timeout to represent that the
+ * pcap handle is in non-blocking mode.
*/
- if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
- pcap_strerror(errno));
- return (-1);
- }
+ return (p->md.timeout < 0);
+}
- ps->ps_recv = s.bs_recv;
- ps->ps_drop = s.bs_drop;
+static int
+pcap_setnonblock_zbuf(pcap_t *p, int nonblock, char *errbuf)
+{
+ /*
+ * Map each value to the corresponding 2's complement, to
+ * preserve the timeout value provided with pcap_set_timeout.
+ * (from pcap-linux.c).
+ */
+ if (nonblock) {
+ if (p->md.timeout > 0)
+ p->md.timeout = p->md.timeout * -1 - 1;
+ } else
+ if (p->md.timeout < 0)
+ p->md.timeout = (p->md.timeout + 1) * -1;
return (0);
}
-#ifdef BIOCGETBUFMODE
+/*
+ * Zero-copy specific close method. Un-map the shared buffers then call
+ * pcap_cleanup_live_common.
+ */
+static void
+pcap_cleanup_zbuf(pcap_t *p)
+{
+ /*
+ * Delete the mappings. Note that p->buffer gets initialized to one
+ * of the mmapped regions in this case, so do not try and free it
+ * directly; null it out so that pcap_cleanup_live_common() doesn't
+ * try to free it.
+ */
+ if (p->md.zbuf1 != MAP_FAILED && p->md.zbuf1 != NULL)
+ (void) munmap(p->md.zbuf1, p->md.zbufsize);
+ if (p->md.zbuf2 != MAP_FAILED && p->md.zbuf2 != NULL)
+ (void) munmap(p->md.zbuf2, p->md.zbufsize);
+ p->buffer = NULL;
+ pcap_cleanup_live_common(p);
+}
+
/*
* Zero-copy BPF buffer routines to check for and acknowledge BPF data in
* shared memory buffers.
@@ -159,23 +237,23 @@ pcap_next_zbuf_shm(pcap_t *p, int *cc)
{
struct bpf_zbuf_header *bzh;
- if (p->zbuffer == p->zbuf2 || p->zbuffer == NULL) {
- bzh = (struct bpf_zbuf_header *)p->zbuf1;
+ if (p->md.zbuffer == p->md.zbuf2 || p->md.zbuffer == NULL) {
+ bzh = (struct bpf_zbuf_header *)p->md.zbuf1;
if (bzh->bzh_user_gen !=
atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
- p->bzh = bzh;
- p->zbuffer = (u_char *)p->zbuf1;
- p->buffer = p->zbuffer + sizeof(*bzh);
+ p->md.bzh = bzh;
+ p->md.zbuffer = (u_char *)p->md.zbuf1;
+ p->buffer = p->md.zbuffer + sizeof(*bzh);
*cc = bzh->bzh_kernel_len;
return (1);
}
- } else if (p->zbuffer == p->zbuf1) {
- bzh = (struct bpf_zbuf_header *)p->zbuf2;
+ } else if (p->md.zbuffer == p->md.zbuf1) {
+ bzh = (struct bpf_zbuf_header *)p->md.zbuf2;
if (bzh->bzh_user_gen !=
atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
- p->bzh = bzh;
- p->zbuffer = (u_char *)p->zbuf2;
- p->buffer = p->zbuffer + sizeof(*bzh);
+ p->md.bzh = bzh;
+ p->md.zbuffer = (u_char *)p->md.zbuf2;
+ p->buffer = p->md.zbuffer + sizeof(*bzh);
*cc = bzh->bzh_kernel_len;
return (1);
}
@@ -199,7 +277,7 @@ pcap_next_zbuf(pcap_t *p, int *cc)
struct timespec cur;
fd_set r_set;
int data, r;
- int tmout, expire;
+ int expire, tmout;
#define TSTOMILLI(ts) (((ts)->tv_sec * 1000) + ((ts)->tv_nsec / 1000000))
/*
@@ -217,50 +295,53 @@ pcap_next_zbuf(pcap_t *p, int *cc)
* our timeout is less then or equal to zero, handle it like a
* regular timeout.
*/
- tmout = p->to_ms;
+ tmout = p->md.timeout;
if (tmout)
(void) clock_gettime(CLOCK_MONOTONIC, &cur);
- if (p->interrupted && p->to_ms) {
- expire = TSTOMILLI(&p->firstsel) + p->to_ms;
+ if (p->md.interrupted && p->md.timeout) {
+ expire = TSTOMILLI(&p->md.firstsel) + p->md.timeout;
tmout = expire - TSTOMILLI(&cur);
#undef TSTOMILLI
if (tmout <= 0) {
- p->interrupted = 0;
+ p->md.interrupted = 0;
data = pcap_next_zbuf_shm(p, cc);
if (data)
return (data);
if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
(void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCROTZBUF: %s", strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
return (pcap_next_zbuf_shm(p, cc));
}
}
/*
* No data in the buffer, so must use select() to wait for data or
- * the next timeout.
+ * the next timeout. Note that we only call select if the handle
+ * is in blocking mode.
*/
- FD_ZERO(&r_set);
- FD_SET(p->fd, &r_set);
- if (tmout != 0) {
- tv.tv_sec = tmout / 1000;
- tv.tv_usec = (tmout * 1000) % 1000000;
- }
- r = select(p->fd + 1, &r_set, NULL, NULL, p->to_ms != 0 ? &tv :
- NULL);
- if (r < 0 && errno == EINTR) {
- if (!p->interrupted && p->to_ms) {
- p->interrupted = 1;
- p->firstsel = cur;
+ if (p->md.timeout >= 0) {
+ FD_ZERO(&r_set);
+ FD_SET(p->fd, &r_set);
+ if (tmout != 0) {
+ tv.tv_sec = tmout / 1000;
+ tv.tv_usec = (tmout * 1000) % 1000000;
+ }
+ r = select(p->fd + 1, &r_set, NULL, NULL,
+ p->md.timeout != 0 ? &tv : NULL);
+ if (r < 0 && errno == EINTR) {
+ if (!p->md.interrupted && p->md.timeout) {
+ p->md.interrupted = 1;
+ p->md.firstsel = cur;
+ }
+ return (0);
+ } else if (r < 0) {
+ (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "select: %s", strerror(errno));
+ return (PCAP_ERROR);
}
- return (0);
- } else if (r < 0) {
- (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "select: %s", strerror(errno));
- return (-1);
}
- p->interrupted = 0;
+ p->md.interrupted = 0;
/*
* Check again for data, which may exist now that we've either been
* woken up as a result of data or timed out. Try the "there's data"
@@ -269,7 +350,6 @@ pcap_next_zbuf(pcap_t *p, int *cc)
data = pcap_next_zbuf_shm(p, cc);
if (data)
return (data);
-
/*
* Try forcing a buffer rotation to dislodge timed out or immediate
* data.
@@ -277,7 +357,7 @@ pcap_next_zbuf(pcap_t *p, int *cc)
if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
(void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCROTZBUF: %s", strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
return (pcap_next_zbuf_shm(p, cc));
}
@@ -290,13 +370,353 @@ static int
pcap_ack_zbuf(pcap_t *p)
{
- atomic_store_rel_int(&p->bzh->bzh_user_gen, p->bzh->bzh_kernel_gen);
- p->bzh = NULL;
+ atomic_store_rel_int(&p->md.bzh->bzh_user_gen,
+ p->md.bzh->bzh_kernel_gen);
+ p->md.bzh = NULL;
p->buffer = NULL;
return (0);
}
#endif
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+#ifdef HAVE_DAG_API
+ if (strstr(device, "dag"))
+ return (dag_create(device, ebuf));
+#endif /* HAVE_DAG_API */
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_bpf;
+ p->can_set_rfmon_op = pcap_can_set_rfmon_bpf;
+ return (p);
+}
+
+static int
+bpf_open(pcap_t *p)
+{
+ int fd;
+#ifdef HAVE_CLONING_BPF
+ static const char device[] = "/dev/bpf";
+#else
+ int n = 0;
+ char device[sizeof "/dev/bpf0000000000"];
+#endif
+
+#ifdef _AIX
+ /*
+ * Load the bpf driver, if it isn't already loaded,
+ * and create the BPF device entries, if they don't
+ * already exist.
+ */
+ if (bpf_load(p->errbuf) == PCAP_ERROR)
+ return (PCAP_ERROR);
+#endif
+
+#ifdef HAVE_CLONING_BPF
+ if ((fd = open(device, O_RDWR)) == -1 &&
+ (errno != EACCES || (fd = open(device, O_RDONLY)) == -1)) {
+ if (errno == EACCES)
+ fd = PCAP_ERROR_PERM_DENIED;
+ else
+ fd = PCAP_ERROR;
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "(cannot open device) %s: %s", device, pcap_strerror(errno));
+ }
+#else
+ /*
+ * Go through all the minors and find one that isn't in use.
+ */
+ do {
+ (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+ /*
+ * Initially try a read/write open (to allow the inject
+ * method to work). If that fails due to permission
+ * issues, fall back to read-only. This allows a
+ * non-root user to be granted specific access to pcap
+ * capabilities via file permissions.
+ *
+ * XXX - we should have an API that has a flag that
+ * controls whether to open read-only or read-write,
+ * so that denial of permission to send (or inability
+ * to send, if sending packets isn't supported on
+ * the device in question) can be indicated at open
+ * time.
+ */
+ fd = open(device, O_RDWR);
+ if (fd == -1 && errno == EACCES)
+ fd = open(device, O_RDONLY);
+ } while (fd < 0 && errno == EBUSY);
+
+ /*
+ * XXX better message for all minors used
+ */
+ if (fd < 0) {
+ if (errno == EACCES)
+ fd = PCAP_ERROR_PERM_DENIED;
+ else
+ fd = PCAP_ERROR;
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "(no devices found) %s: %s",
+ device, pcap_strerror(errno));
+ }
+#endif
+
+ return (fd);
+}
+
+#ifdef BIOCGDLTLIST
+static int
+get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
+{
+ memset(bdlp, 0, sizeof(*bdlp));
+ if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) == 0) {
+ u_int i;
+ int is_ethernet;
+
+ bdlp->bfl_list = (u_int *) malloc(sizeof(u_int) * (bdlp->bfl_len + 1));
+ if (bdlp->bfl_list == NULL) {
+ (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ return (PCAP_ERROR);
+ }
+
+ if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) < 0) {
+ (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "BIOCGDLTLIST: %s", pcap_strerror(errno));
+ free(bdlp->bfl_list);
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * OK, for real Ethernet devices, add DLT_DOCSIS to the
+ * list, so that an application can let you choose it,
+ * in case you're capturing DOCSIS traffic that a Cisco
+ * Cable Modem Termination System is putting out onto
+ * an Ethernet (it doesn't put an Ethernet header onto
+ * the wire, it puts raw DOCSIS frames out on the wire
+ * inside the low-level Ethernet framing).
+ *
+ * A "real Ethernet device" is defined here as a device
+ * that has a link-layer type of DLT_EN10MB and that has
+ * no alternate link-layer types; that's done to exclude
+ * 802.11 interfaces (which might or might not be the
+ * right thing to do, but I suspect it is - Ethernet <->
+ * 802.11 bridges would probably badly mishandle frames
+ * that don't have Ethernet headers).
+ */
+ if (v == DLT_EN10MB) {
+ is_ethernet = 1;
+ for (i = 0; i < bdlp->bfl_len; i++) {
+ if (bdlp->bfl_list[i] != DLT_EN10MB) {
+ is_ethernet = 0;
+ break;
+ }
+ }
+ if (is_ethernet) {
+ /*
+ * We reserved one more slot at the end of
+ * the list.
+ */
+ bdlp->bfl_list[bdlp->bfl_len] = DLT_DOCSIS;
+ bdlp->bfl_len++;
+ }
+ }
+ } else {
+ /*
+ * EINVAL just means "we don't support this ioctl on
+ * this device"; don't treat it as an error.
+ */
+ if (errno != EINVAL) {
+ (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "BIOCGDLTLIST: %s", pcap_strerror(errno));
+ return (PCAP_ERROR);
+ }
+ }
+ return (0);
+}
+#endif
+
+static int
+pcap_can_set_rfmon_bpf(pcap_t *p)
+{
+#if defined(__APPLE__)
+ struct utsname osinfo;
+ struct ifreq ifr;
+ int fd;
+#ifdef BIOCGDLTLIST
+ struct bpf_dltlist bdl;
+#endif
+
+ /*
+ * The joys of monitor mode on OS X.
+ *
+ * Prior to 10.4, it's not supported at all.
+ *
+ * In 10.4, if adapter enN supports monitor mode, there's a
+ * wltN adapter corresponding to it; you open it, instead of
+ * enN, to get monitor mode. You get whatever link-layer
+ * headers it supplies.
+ *
+ * In 10.5, and, we assume, later releases, if adapter enN
+ * supports monitor mode, it offers, among its selectable
+ * DLT_ values, values that let you get the 802.11 header;
+ * selecting one of those values puts the adapter into monitor
+ * mode (i.e., you can't get 802.11 headers except in monitor
+ * mode, and you can't get Ethernet headers in monitor mode).
+ */
+ if (uname(&osinfo) == -1) {
+ /*
+ * Can't get the OS version; just say "no".
+ */
+ return (0);
+ }
+ /*
+ * We assume osinfo.sysname is "Darwin", because
+ * __APPLE__ is defined. We just check the version.
+ */
+ if (osinfo.release[0] < '8' && osinfo.release[1] == '.') {
+ /*
+ * 10.3 (Darwin 7.x) or earlier.
+ * Monitor mode not supported.
+ */
+ return (0);
+ }
+ if (osinfo.release[0] == '8' && osinfo.release[1] == '.') {
+ /*
+ * 10.4 (Darwin 8.x). s/en/wlt/, and check
+ * whether the device exists.
+ */
+ if (strncmp(p->opt.source, "en", 2) != 0) {
+ /*
+ * Not an enN device; no monitor mode.
+ */
+ return (0);
+ }
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd == -1) {
+ (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "socket: %s", pcap_strerror(errno));
+ return (PCAP_ERROR);
+ }
+ strlcpy(ifr.ifr_name, "wlt", sizeof(ifr.ifr_name));
+ strlcat(ifr.ifr_name, p->opt.source + 2, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+ /*
+ * No such device?
+ */
+ close(fd);
+ return (0);
+ }
+ close(fd);
+ return (1);
+ }
+
+#ifdef BIOCGDLTLIST
+ /*
+ * Everything else is 10.5 or later; for those,
+ * we just open the enN device, and check whether
+ * we have any 802.11 devices.
+ *
+ * First, open a BPF device.
+ */
+ fd = bpf_open(p);
+ if (fd < 0)
+ return (fd);
+
+ /*
+ * Now bind to the device.
+ */
+ (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+ if (errno == ENETDOWN) {
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ close(fd);
+ return (PCAP_ERROR_IFACE_NOT_UP);
+ } else {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSETIF: %s: %s",
+ p->opt.source, pcap_strerror(errno));
+ close(fd);
+ return (PCAP_ERROR);
+ }
+ }
+
+ /*
+ * We know the default link type -- now determine all the DLTs
+ * this interface supports. If this fails with EINVAL, it's
+ * not fatal; we just don't get to use the feature later.
+ * (We don't care about DLT_DOCSIS, so we pass DLT_NULL
+ * as the default DLT for this adapter.)
+ */
+ if (get_dlt_list(fd, DLT_NULL, &bdl, p->errbuf) == PCAP_ERROR) {
+ close(fd);
+ return (PCAP_ERROR);
+ }
+ if (find_802_11(&bdl) != -1) {
+ /*
+ * We have an 802.11 DLT, so we can set monitor mode.
+ */
+ free(bdl.bfl_list);
+ close(fd);
+ return (1);
+ }
+ free(bdl.bfl_list);
+#endif /* BIOCGDLTLIST */
+ return (0);
+#elif defined(HAVE_BSD_IEEE80211)
+ int ret;
+
+ ret = monitor_mode(p, 0);
+ if (ret == PCAP_ERROR_RFMON_NOTSUP)
+ return (0); /* not an error, just a "can't do" */
+ if (ret == 0)
+ return (1); /* success */
+ return (ret);
+#else
+ return (0);
+#endif
+}
+
+static int
+pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps)
+{
+ struct bpf_stat s;
+
+ /*
+ * "ps_recv" counts packets handed to the filter, not packets
+ * that passed the filter. This includes packets later dropped
+ * because we ran out of buffer space.
+ *
+ * "ps_drop" counts packets dropped inside the BPF device
+ * because we ran out of buffer space. It doesn't count
+ * packets dropped by the interface driver. It counts
+ * only packets that passed the filter.
+ *
+ * Both statistics include packets not yet read from the kernel
+ * by libpcap, and thus not yet seen by the application.
+ */
+ if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
+ pcap_strerror(errno));
+ return (PCAP_ERROR);
+ }
+
+ ps->ps_recv = s.bs_recv;
+ ps->ps_drop = s.bs_drop;
+ return (0);
+}
+
static int
pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
@@ -304,15 +724,13 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
int n = 0;
register u_char *bp, *ep;
u_char *datap;
- struct bpf_insn *fcode;
-#ifdef BIOCSETBUFMODE
- int i;
-#endif
#ifdef PCAP_FDDIPAD
register int pad;
#endif
+#ifdef HAVE_ZEROCOPY_BPF
+ int i;
+#endif
- fcode = p->md.use_bpf ? NULL : p->fcode.bf_insns;
again:
/*
* Has "pcap_breakloop()" been called?
@@ -320,11 +738,11 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
if (p->break_loop) {
/*
* Yes - clear the flag that indicates that it
- * has, and return -2 to indicate that we were
- * told to break out of the loop.
+ * has, and return PCAP_ERROR_BREAK to indicate
+ * that we were told to break out of the loop.
*/
p->break_loop = 0;
- return (-2);
+ return (PCAP_ERROR_BREAK);
}
cc = p->cc;
if (p->cc == 0) {
@@ -336,19 +754,20 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
* data and update cc to reflect the data found in the
* buffer.
*/
-#ifdef BIOCSETBUFMODE
- if (p->zerocopy) {
+#ifdef HAVE_ZEROCOPY_BPF
+ if (p->md.zerocopy) {
if (p->buffer != NULL)
pcap_ack_zbuf(p);
i = pcap_next_zbuf(p, &cc);
if (i == 0)
goto again;
if (i < 0)
- return (-1);
+ return (PCAP_ERROR);
} else
#endif
+ {
cc = read(p->fd, (char *)p->buffer, p->bufsize);
-
+ }
if (cc < 0) {
/* Don't choke when we get ptraced */
switch (errno) {
@@ -363,16 +782,16 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
*
* For some unknown reason the uiomove()
* operation in the bpf kernel extension
- * used to copy the buffer into user
+ * used to copy the buffer into user
* space sometimes returns EFAULT. I have
* no idea why this is the case given that
- * a kernel debugger shows the user buffer
- * is correct. This problem appears to
- * be mostly mitigated by the memset of
- * the buffer before it is first used.
+ * a kernel debugger shows the user buffer
+ * is correct. This problem appears to
+ * be mostly mitigated by the memset of
+ * the buffer before it is first used.
* Very strange.... Shaun Clowes
*
- * In any case this means that we shouldn't
+ * In any case this means that we shouldn't
* treat EFAULT as a fatal error; as we
* don't have an API for returning
* a "some packets were dropped since
@@ -380,8 +799,8 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
* we just ignore EFAULT and keep reading.
*/
goto again;
-#endif
-
+#endif
+
case EWOULDBLOCK:
return (0);
#if defined(sun) && !defined(BSD)
@@ -401,7 +820,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
bp = p->buffer;
} else
@@ -421,16 +840,17 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
/*
* Has "pcap_breakloop()" been called?
* If so, return immediately - if we haven't read any
- * packets, clear the flag and return -2 to indicate
- * that we were told to break out of the loop, otherwise
- * leave the flag set, so that the *next* call will break
- * out of the loop without having read any packets, and
- * return the number of packets we've processed so far.
+ * packets, clear the flag and return PCAP_ERROR_BREAK
+ * to indicate that we were told to break out of the loop,
+ * otherwise leave the flag set, so that the *next* call
+ * will break out of the loop without having read any
+ * packets, and return the number of packets we've
+ * processed so far.
*/
if (p->break_loop) {
if (n == 0) {
p->break_loop = 0;
- return (-2);
+ return (PCAP_ERROR_BREAK);
} else {
p->bp = bp;
p->cc = ep - bp;
@@ -443,7 +863,8 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
datap = bp + hdrlen;
/*
* Short-circuit evaluation: if using BPF filter
- * in kernel, no need to do it now.
+ * in kernel, no need to do it now - we already know
+ * the packet passed the filter.
*
#ifdef PCAP_FDDIPAD
* Note: the filter code was generated assuming
@@ -453,8 +874,8 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
* skipping that padding.
#endif
*/
- if (fcode == NULL ||
- bpf_filter(fcode, datap, bhp->bh_datalen, caplen)) {
+ if (p->md.use_bpf ||
+ bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
struct pcap_pkthdr pkthdr;
pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec;
@@ -532,7 +953,7 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
(void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"send: can't turn off BIOCSHDRCMPLT: %s",
pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
/*
@@ -544,13 +965,13 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
if (ret == -1) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
return (ret);
}
#ifdef _AIX
-static int
+static int
bpf_odminit(char *errbuf)
{
char *errstr;
@@ -561,7 +982,7 @@ bpf_odminit(char *errbuf)
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_initialize failed: %s",
errstr);
- return (-1);
+ return (PCAP_ERROR);
}
if ((odmlockid = odm_lock("/etc/objrepos/config_lock", ODM_WAIT)) == -1) {
@@ -570,13 +991,13 @@ bpf_odminit(char *errbuf)
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_lock of /etc/objrepos/config_lock failed: %s",
errstr);
- return (-1);
+ return (PCAP_ERROR);
}
return (0);
}
-static int
+static int
bpf_odmcleanup(char *errbuf)
{
char *errstr;
@@ -587,7 +1008,7 @@ bpf_odmcleanup(char *errbuf)
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_unlock failed: %s",
errstr);
- return (-1);
+ return (PCAP_ERROR);
}
if (odm_terminate() == -1) {
@@ -596,7 +1017,7 @@ bpf_odmcleanup(char *errbuf)
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_terminate failed: %s",
errstr);
- return (-1);
+ return (PCAP_ERROR);
}
return (0);
@@ -621,14 +1042,14 @@ bpf_load(char *errbuf)
if (bpfloadedflag)
return (0);
- if (bpf_odminit(errbuf) != 0)
- return (-1);
+ if (bpf_odminit(errbuf) == PCAP_ERROR)
+ return (PCAP_ERROR);
major = genmajor(BPF_NAME);
if (major == -1) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: genmajor failed: %s", pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
minors = getminor(major, &numminors, BPF_NAME);
@@ -638,19 +1059,19 @@ bpf_load(char *errbuf)
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: genminor failed: %s",
pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
}
- if (bpf_odmcleanup(errbuf))
- return (-1);
+ if (bpf_odmcleanup(errbuf) == PCAP_ERROR)
+ return (PCAP_ERROR);
rc = stat(BPF_NODE "0", &sbuf);
if (rc == -1 && errno != ENOENT) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: can't stat %s: %s",
BPF_NODE "0", pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
if (rc == -1 || getmajor(sbuf.st_rdev) != major) {
@@ -661,7 +1082,7 @@ bpf_load(char *errbuf)
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: can't mknod %s: %s",
buf, pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
}
}
@@ -677,7 +1098,7 @@ bpf_load(char *errbuf)
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: could not load driver: %s",
strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
}
@@ -685,115 +1106,229 @@ bpf_load(char *errbuf)
cfg_km.cmd = CFG_INIT;
cfg_km.kmid = cfg_ld.kmid;
cfg_km.mdilen = sizeof(cfg_bpf);
- cfg_km.mdiptr = (void *)&cfg_bpf;
+ cfg_km.mdiptr = (void *)&cfg_bpf;
for (i = 0; i < BPF_MINORS; i++) {
cfg_bpf.devno = domakedev(major, i);
if (sysconfig(SYS_CFGKMOD, (void *)&cfg_km, sizeof(cfg_km)) == -1) {
snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: could not configure driver: %s",
strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
}
-
+
bpfloadedflag = 1;
return (0);
}
#endif
-static inline int
-bpf_open(pcap_t *p, char *errbuf)
+/*
+ * Turn off rfmon mode if necessary.
+ */
+static void
+pcap_cleanup_bpf(pcap_t *p)
{
- int fd;
-#ifdef HAVE_CLONING_BPF
- static const char device[] = "/dev/bpf";
-#else
- int n = 0;
- char device[sizeof "/dev/bpf0000000000"];
+#ifdef HAVE_BSD_IEEE80211
+ int sock;
+ struct ifmediareq req;
+ struct ifreq ifr;
#endif
-#ifdef _AIX
- /*
- * Load the bpf driver, if it isn't already loaded,
- * and create the BPF device entries, if they don't
- * already exist.
- */
- if (bpf_load(errbuf) == -1)
- return (-1);
-#endif
+ if (p->md.must_clear != 0) {
+ /*
+ * There's something we have to do when closing this
+ * pcap_t.
+ */
+#ifdef HAVE_BSD_IEEE80211
+ if (p->md.must_clear & MUST_CLEAR_RFMON) {
+ /*
+ * We put the interface into rfmon mode;
+ * take it out of rfmon mode.
+ *
+ * XXX - if somebody else wants it in rfmon
+ * mode, this code cannot know that, so it'll take
+ * it out of rfmon mode.
+ */
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ fprintf(stderr,
+ "Can't restore interface flags (socket() failed: %s).\n"
+ "Please adjust manually.\n",
+ strerror(errno));
+ } else {
+ memset(&req, 0, sizeof(req));
+ strncpy(req.ifm_name, p->md.device,
+ sizeof(req.ifm_name));
+ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+ fprintf(stderr,
+ "Can't restore interface flags (SIOCGIFMEDIA failed: %s).\n"
+ "Please adjust manually.\n",
+ strerror(errno));
+ } else {
+ if (req.ifm_current & IFM_IEEE80211_MONITOR) {
+ /*
+ * Rfmon mode is currently on;
+ * turn it off.
+ */
+ memset(&ifr, 0, sizeof(ifr));
+ (void)strncpy(ifr.ifr_name,
+ p->md.device,
+ sizeof(ifr.ifr_name));
+ ifr.ifr_media =
+ req.ifm_current & ~IFM_IEEE80211_MONITOR;
+ if (ioctl(sock, SIOCSIFMEDIA,
+ &ifr) == -1) {
+ fprintf(stderr,
+ "Can't restore interface flags (SIOCSIFMEDIA failed: %s).\n"
+ "Please adjust manually.\n",
+ strerror(errno));
+ }
+ }
+ }
+ close(sock);
+ }
+ }
+#endif /* HAVE_BSD_IEEE80211 */
-#ifdef HAVE_CLONING_BPF
- if ((fd = open(device, O_RDWR)) == -1 &&
- (errno != EACCES || (fd = open(device, O_RDONLY)) == -1))
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "(cannot open device) %s: %s", device, pcap_strerror(errno));
-#else
- /*
- * Go through all the minors and find one that isn't in use.
- */
- do {
- (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
/*
- * Initially try a read/write open (to allow the inject
- * method to work). If that fails due to permission
- * issues, fall back to read-only. This allows a
- * non-root user to be granted specific access to pcap
- * capabilities via file permissions.
- *
- * XXX - we should have an API that has a flag that
- * controls whether to open read-only or read-write,
- * so that denial of permission to send (or inability
- * to send, if sending packets isn't supported on
- * the device in question) can be indicated at open
- * time.
+ * Take this pcap out of the list of pcaps for which we
+ * have to take the interface out of some mode.
*/
- fd = open(device, O_RDWR);
- if (fd == -1 && errno == EACCES)
- fd = open(device, O_RDONLY);
- } while (fd < 0 && errno == EBUSY);
+ pcap_remove_from_pcaps_to_close(p);
+ p->md.must_clear = 0;
+ }
+#ifdef HAVE_ZEROCOPY_BPF
/*
- * XXX better message for all minors used
+ * In zero-copy mode, p->buffer is just a pointer into one of the two
+ * memory-mapped buffers, so no need to free it.
*/
- if (fd < 0)
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "(no devices found) %s: %s",
- device, pcap_strerror(errno));
+ if (p->md.zerocopy) {
+ if (p->md.zbuf1 != MAP_FAILED && p->md.zbuf1 != NULL)
+ munmap(p->md.zbuf1, p->md.zbufsize);
+ if (p->md.zbuf2 != MAP_FAILED && p->md.zbuf2 != NULL)
+ munmap(p->md.zbuf2, p->md.zbufsize);
+ }
#endif
-
- return (fd);
+ if (p->md.device != NULL) {
+ free(p->md.device);
+ p->md.device = NULL;
+ }
+ pcap_cleanup_live_common(p);
}
-/*
- * We include the OS's <net/bpf.h>, not our "pcap-bpf.h", so we probably
- * don't get DLT_DOCSIS defined.
- */
-#ifndef DLT_DOCSIS
-#define DLT_DOCSIS 143
+static int
+check_setif_failure(pcap_t *p, int error)
+{
+#ifdef __APPLE__
+ int fd;
+ struct ifreq ifr;
+ int err;
#endif
-pcap_t *
-pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
- char *ebuf)
+ if (error == ENXIO) {
+ /*
+ * No such device exists.
+ */
+#ifdef __APPLE__
+ if (p->opt.rfmon && strncmp(p->opt.source, "wlt", 3) == 0) {
+ /*
+ * Monitor mode was requested, and we're trying
+ * to open a "wltN" device. Assume that this
+ * is 10.4 and that we were asked to open an
+ * "enN" device; if that device exists, return
+ * "monitor mode not supported on the device".
+ */
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd != -1) {
+ strlcpy(ifr.ifr_name, "en",
+ sizeof(ifr.ifr_name));
+ strlcat(ifr.ifr_name, p->opt.source + 3,
+ sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+ /*
+ * We assume this failed because
+ * the underlying device doesn't
+ * exist.
+ */
+ err = PCAP_ERROR_NO_SUCH_DEVICE;
+ strcpy(p->errbuf, "");
+ } else {
+ /*
+ * The underlying "enN" device
+ * exists, but there's no
+ * corresponding "wltN" device;
+ * that means that the "enN"
+ * device doesn't support
+ * monitor mode, probably because
+ * it's an Ethernet device rather
+ * than a wireless device.
+ */
+ err = PCAP_ERROR_RFMON_NOTSUP;
+ }
+ close(fd);
+ } else {
+ /*
+ * We can't find out whether there's
+ * an underlying "enN" device, so
+ * just report "no such device".
+ */
+ err = PCAP_ERROR_NO_SUCH_DEVICE;
+ strcpy(p->errbuf, "");
+ }
+ return (err);
+ }
+#endif
+ /*
+ * No such device.
+ */
+ strcpy(p->errbuf, "");
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+ } else if (errno == ENETDOWN) {
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ return (PCAP_ERROR_IFACE_NOT_UP);
+ } else {
+ /*
+ * Some other error; fill in the error string, and
+ * return PCAP_ERROR.
+ */
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
+ p->opt.source, pcap_strerror(errno));
+ return (PCAP_ERROR);
+ }
+}
+
+static int
+pcap_activate_bpf(pcap_t *p)
{
+ int status = 0;
int fd;
struct ifreq ifr;
struct bpf_version bv;
+#ifdef __APPLE__
+ int sockfd;
+ char *wltdev = NULL;
+#endif
#ifdef BIOCGDLTLIST
struct bpf_dltlist bdl;
+#if defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)
+ int new_dlt;
#endif
+#endif /* BIOCGDLTLIST */
#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
u_int spoof_eth_src = 1;
#endif
u_int v;
- pcap_t *p;
struct bpf_insn total_insn;
struct bpf_program total_prog;
struct utsname osinfo;
-#ifdef BIOCSETBUFMODE
- struct bpf_zbuf bz;
- u_int bufmode, zbufmax;
-#endif
#ifdef HAVE_DAG_API
if (strstr(device, "dag")) {
@@ -803,35 +1338,135 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#ifdef BIOCGDLTLIST
memset(&bdl, 0, sizeof(bdl));
+ int have_osinfo = 0;
+#ifdef HAVE_ZEROCOPY_BPF
+ struct bpf_zbuf bz;
+ u_int bufmode, zbufmax;
#endif
- p = (pcap_t *)malloc(sizeof(*p));
- if (p == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- return (NULL);
- }
- memset(p, 0, sizeof(*p));
- fd = bpf_open(p, ebuf);
- if (fd < 0)
+ fd = bpf_open(p);
+ if (fd < 0) {
+ status = fd;
goto bad;
+ }
p->fd = fd;
- p->snapshot = snaplen;
if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
if (bv.bv_major != BPF_MAJOR_VERSION ||
bv.bv_minor < BPF_MINOR_VERSION) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"kernel bpf filter out of date");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ p->md.device = strdup(p->opt.source);
+ if (p->md.device == NULL) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
-#ifdef BIOCSETBUFMODE
+ /*
+ * Try finding a good size for the buffer; 32768 may be too
+ * big, so keep cutting it in half until we find a size
+ * that works, or run out of sizes to try. If the default
+ * is larger, don't make it smaller.
+ *
+ * XXX - there should be a user-accessible hook to set the
+ * initial buffer size.
+ * Attempt to find out the version of the OS on which we're running.
+ */
+ if (uname(&osinfo) == 0)
+ have_osinfo = 1;
+
+#ifdef __APPLE__
+ /*
+ * See comment in pcap_can_set_rfmon_bpf() for an explanation
+ * of why we check the version number.
+ */
+ if (p->opt.rfmon) {
+ if (have_osinfo) {
+ /*
+ * We assume osinfo.sysname is "Darwin", because
+ * __APPLE__ is defined. We just check the version.
+ */
+ if (osinfo.release[0] < '8' &&
+ osinfo.release[1] == '.') {
+ /*
+ * 10.3 (Darwin 7.x) or earlier.
+ */
+ status = PCAP_ERROR_RFMON_NOTSUP;
+ goto bad;
+ }
+ if (osinfo.release[0] == '8' &&
+ osinfo.release[1] == '.') {
+ /*
+ * 10.4 (Darwin 8.x). s/en/wlt/
+ */
+ if (strncmp(p->opt.source, "en", 2) != 0) {
+ /*
+ * Not an enN device; check
+ * whether the device even exists.
+ */
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd != -1) {
+ strlcpy(ifr.ifr_name,
+ p->opt.source,
+ sizeof(ifr.ifr_name));
+ if (ioctl(sockfd, SIOCGIFFLAGS,
+ (char *)&ifr) < 0) {
+ /*
+ * We assume this
+ * failed because
+ * the underlying
+ * device doesn't
+ * exist.
+ */
+ status = PCAP_ERROR_NO_SUCH_DEVICE;
+ strcpy(p->errbuf, "");
+ } else
+ status = PCAP_ERROR_RFMON_NOTSUP;
+ close(sockfd);
+ } else {
+ /*
+ * We can't find out whether
+ * the device exists, so just
+ * report "no such device".
+ */
+ status = PCAP_ERROR_NO_SUCH_DEVICE;
+ strcpy(p->errbuf, "");
+ }
+ goto bad;
+ }
+ wltdev = malloc(strlen(p->opt.source) + 2);
+ if (wltdev == NULL) {
+ (void)snprintf(p->errbuf,
+ PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ strcpy(wltdev, "wlt");
+ strcat(wltdev, p->opt.source + 2);
+ free(p->opt.source);
+ p->opt.source = wltdev;
+ }
+ /*
+ * Everything else is 10.5 or later; for those,
+ * we just open the enN device, and set the DLT.
+ */
+ }
+ }
+#endif /* __APPLE__ */
+#ifdef HAVE_ZEROCOPY_BPF
/*
* If the BPF extension to set buffer mode is present, try setting
* the mode to zero-copy. If that fails, use regular buffering. If
@@ -839,104 +1474,156 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
*/
bufmode = BPF_BUFMODE_ZBUF;
if (ioctl(fd, BIOCSETBUFMODE, (caddr_t)&bufmode) == 0) {
- p->zerocopy = 1;
+ /*
+ * We have zerocopy BPF; use it.
+ */
+ p->md.zerocopy = 1;
+
+ /*
+ * Set the cleanup and set/get nonblocking mode ops
+ * as appropriate for zero-copy mode.
+ */
+ p->cleanup_op = pcap_cleanup_zbuf;
+ p->setnonblock_op = pcap_setnonblock_zbuf;
+ p->getnonblock_op = pcap_getnonblock_zbuf;
/*
* How to pick a buffer size: first, query the maximum buffer
* size supported by zero-copy. This also lets us quickly
* determine whether the kernel generally supports zero-copy.
- * Then, query the default buffer size, which reflects kernel
+ * Then, if a buffer size was specified, use that, otherwise
+ * query the default buffer size, which reflects kernel
* policy for a desired default. Round to the nearest page
* size.
*/
if (ioctl(fd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s",
pcap_strerror(errno));
goto bad;
}
- if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) || v < 32768)
- v = 32768;
+
+ if (p->opt.buffer_size != 0) {
+ /*
+ * A buffer size was explicitly specified; use it.
+ */
+ v = p->opt.buffer_size;
+ } else {
+ if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) ||
+ v < 32768)
+ v = 32768;
+ }
#ifndef roundup
-#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
#endif
- p->zbufsize = roundup(v, getpagesize());
- if (p->zbufsize > zbufmax)
- p->zbufsize = zbufmax;
- p->zbuf1 = mmap(NULL, p->zbufsize, PROT_READ | PROT_WRITE,
+ p->md.zbufsize = roundup(v, getpagesize());
+ if (p->md.zbufsize > zbufmax)
+ p->md.zbufsize = zbufmax;
+ p->md.zbuf1 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE,
MAP_ANON, -1, 0);
- p->zbuf2 = mmap(NULL, p->zbufsize, PROT_READ | PROT_WRITE,
+ p->md.zbuf2 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE,
MAP_ANON, -1, 0);
- if (p->zbuf1 == MAP_FAILED || p->zbuf2 == MAP_FAILED) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "mmap: %s",
+ if (p->md.zbuf1 == MAP_FAILED || p->md.zbuf2 == MAP_FAILED) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
pcap_strerror(errno));
goto bad;
}
bzero(&bz, sizeof(bz));
- bz.bz_bufa = p->zbuf1;
- bz.bz_bufb = p->zbuf2;
- bz.bz_buflen = p->zbufsize;
+ bz.bz_bufa = p->md.zbuf1;
+ bz.bz_bufb = p->md.zbuf2;
+ bz.bz_buflen = p->md.zbufsize;
if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s",
pcap_strerror(errno));
goto bad;
}
- (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
- device, pcap_strerror(errno));
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
+ p->opt.source, pcap_strerror(errno));
goto bad;
}
- v = p->zbufsize - sizeof(struct bpf_zbuf_header);
- } else {
+ v = p->md.zbufsize - sizeof(struct bpf_zbuf_header);
+ } else
#endif
-
+ {
/*
- * Try finding a good size for the buffer; 32768 may be too
- * big, so keep cutting it in half until we find a size
- * that works, or run out of sizes to try. If the default
- * is larger, don't make it smaller.
- *
- * XXX - there should be a user-accessible hook to set the
- * initial buffer size.
+ * We don't have zerocopy BPF.
+ * Set the buffer size.
*/
- if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) || v < 32768)
- v = 32768;
- for ( ; v != 0; v >>= 1) {
- /* Ignore the return value - this is because the call
- * fails on BPF systems that don't have kernel
- * malloc. And if the call fails, it's no big deal,
- * we just continue to use the standard buffer size.
+ if (p->opt.buffer_size != 0) {
+ /*
+ * A buffer size was explicitly specified; use it.
*/
- (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
+ if (ioctl(fd, BIOCSBLEN,
+ (caddr_t)&p->opt.buffer_size) < 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSBLEN: %s: %s", p->opt.source,
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
- (void)strncpy(ifr.ifr_name, device,
+ /*
+ * Now bind to the device.
+ */
+ (void)strncpy(ifr.ifr_name, p->opt.source,
sizeof(ifr.ifr_name));
- if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0)
- break; /* that size worked; we're done */
-
- if (errno != ENOBUFS) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "BIOCSETIF: %s: %s",
- device, pcap_strerror(errno));
+ if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+ status = check_setif_failure(p, errno);
goto bad;
}
- }
+ } else {
+ /*
+ * No buffer size was explicitly specified.
+ *
+ * Try finding a good size for the buffer; 32768 may
+ * be too big, so keep cutting it in half until we
+ * find a size that works, or run out of sizes to try.
+ * If the default is larger, don't make it smaller.
+ */
+ if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) ||
+ v < 32768)
+ v = 32768;
+ for ( ; v != 0; v >>= 1) {
+ /*
+ * Ignore the return value - this is because the
+ * call fails on BPF systems that don't have
+ * kernel malloc. And if the call fails, it's
+ * no big deal, we just continue to use the
+ * standard buffer size.
+ */
+ (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
- if (v == 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "BIOCSBLEN: %s: No buffer size worked", device);
- goto bad;
+ (void)strncpy(ifr.ifr_name, p->opt.source,
+ sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0)
+ break; /* that size worked; we're done */
+
+ if (errno != ENOBUFS) {
+ status = check_setif_failure(p, errno);
+ goto bad;
+ }
+ }
+
+ if (v == 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSBLEN: %s: No buffer size worked",
+ p->opt.source);
+ status = PCAP_ERROR;
+ goto bad;
+ }
}
-#ifdef BIOCSETBUFMODE
}
#endif
/* Get the data link layer type. */
if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
+
#ifdef _AIX
/*
* AIX's BPF returns IFF_ types, not DLT_ types, in BIOCGDLT.
@@ -964,8 +1651,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
/*
* We don't know what to map this to yet.
*/
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
v);
+ status = PCAP_ERROR;
goto bad;
}
#endif
@@ -990,13 +1678,6 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
break;
}
#endif
-#ifdef PCAP_FDDIPAD
- if (v == DLT_FDDI)
- p->fddipad = PCAP_FDDIPAD;
- else
- p->fddipad = 0;
-#endif
- p->linktype = v;
#ifdef BIOCGDLTLIST
/*
@@ -1004,68 +1685,144 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* this interface supports. If this fails with EINVAL, it's
* not fatal; we just don't get to use the feature later.
*/
- if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) == 0) {
- u_int i;
- int is_ethernet;
+ if (get_dlt_list(fd, v, &bdl, p->errbuf) == -1) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ p->dlt_count = bdl.bfl_len;
+ p->dlt_list = bdl.bfl_list;
- bdl.bfl_list = (u_int *) malloc(sizeof(u_int) * (bdl.bfl_len + 1));
- if (bdl.bfl_list == NULL) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- goto bad;
+#ifdef __APPLE__
+ /*
+ * Monitor mode fun, continued.
+ *
+ * For 10.5 and, we're assuming, later releases, as noted above,
+ * 802.1 adapters that support monitor mode offer both DLT_EN10MB,
+ * DLT_IEEE802_11, and possibly some 802.11-plus-radio-information
+ * DLT_ value. Choosing one of the 802.11 DLT_ values will turn
+ * monitor mode on.
+ *
+ * Therefore, if the user asked for monitor mode, we filter out
+ * the DLT_EN10MB value, as you can't get that in monitor mode,
+ * and, if the user didn't ask for monitor mode, we filter out
+ * the 802.11 DLT_ values, because selecting those will turn
+ * monitor mode on. Then, for monitor mode, if an 802.11-plus-
+ * radio DLT_ value is offered, we try to select that, otherwise
+ * we try to select DLT_IEEE802_11.
+ */
+ if (have_osinfo) {
+ if (isdigit((unsigned)osinfo.release[0]) &&
+ (osinfo.release[0] == '9' ||
+ isdigit((unsigned)osinfo.release[1]))) {
+ /*
+ * 10.5 (Darwin 9.x), or later.
+ */
+ new_dlt = find_802_11(&bdl);
+ if (new_dlt != -1) {
+ /*
+ * We have at least one 802.11 DLT_ value,
+ * so this is an 802.11 interface.
+ * new_dlt is the best of the 802.11
+ * DLT_ values in the list.
+ */
+ if (p->opt.rfmon) {
+ /*
+ * Our caller wants monitor mode.
+ * Purge DLT_EN10MB from the list
+ * of link-layer types, as selecting
+ * it will keep monitor mode off.
+ */
+ remove_en(p);
+
+ /*
+ * If the new mode we want isn't
+ * the default mode, attempt to
+ * select the new mode.
+ */
+ if (new_dlt != v) {
+ if (ioctl(p->fd, BIOCSDLT,
+ &new_dlt) != -1) {
+ /*
+ * We succeeded;
+ * make this the
+ * new DLT_ value.
+ */
+ v = new_dlt;
+ }
+ }
+ } else {
+ /*
+ * Our caller doesn't want
+ * monitor mode. Unless this
+ * is being done by pcap_open_live(),
+ * purge the 802.11 link-layer types
+ * from the list, as selecting
+ * one of them will turn monitor
+ * mode on.
+ */
+ if (!p->oldstyle)
+ remove_802_11(p);
+ }
+ } else {
+ if (p->opt.rfmon) {
+ /*
+ * The caller requested monitor
+ * mode, but we have no 802.11
+ * link-layer types, so they
+ * can't have it.
+ */
+ status = PCAP_ERROR_RFMON_NOTSUP;
+ goto bad;
+ }
+ }
}
-
- if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) < 0) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "BIOCGDLTLIST: %s", pcap_strerror(errno));
- free(bdl.bfl_list);
+ }
+#elif defined(HAVE_BSD_IEEE80211)
+ /*
+ * *BSD with the new 802.11 ioctls.
+ * Do we want monitor mode?
+ */
+ if (p->opt.rfmon) {
+ /*
+ * Try to put the interface into monitor mode.
+ */
+ status = monitor_mode(p, 1);
+ if (status != 0) {
+ /*
+ * We failed.
+ */
goto bad;
}
/*
- * OK, for real Ethernet devices, add DLT_DOCSIS to the
- * list, so that an application can let you choose it,
- * in case you're capturing DOCSIS traffic that a Cisco
- * Cable Modem Termination System is putting out onto
- * an Ethernet (it doesn't put an Ethernet header onto
- * the wire, it puts raw DOCSIS frames out on the wire
- * inside the low-level Ethernet framing).
- *
- * A "real Ethernet device" is defined here as a device
- * that has a link-layer type of DLT_EN10MB and that has
- * no alternate link-layer types; that's done to exclude
- * 802.11 interfaces (which might or might not be the
- * right thing to do, but I suspect it is - Ethernet <->
- * 802.11 bridges would probably badly mishandle frames
- * that don't have Ethernet headers).
+ * We're in monitor mode.
+ * Try to find the best 802.11 DLT_ value and, if we
+ * succeed, try to switch to that mode if we're not
+ * already in that mode.
*/
- if (p->linktype == DLT_EN10MB) {
- is_ethernet = 1;
- for (i = 0; i < bdl.bfl_len; i++) {
- if (bdl.bfl_list[i] != DLT_EN10MB) {
- is_ethernet = 0;
- break;
+ new_dlt = find_802_11(&bdl);
+ if (new_dlt != -1) {
+ /*
+ * We have at least one 802.11 DLT_ value.
+ * new_dlt is the best of the 802.11
+ * DLT_ values in the list.
+ *
+ * If the new mode we want isn't the default mode,
+ * attempt to select the new mode.
+ */
+ if (new_dlt != v) {
+ if (ioctl(p->fd, BIOCSDLT, &new_dlt) != -1) {
+ /*
+ * We succeeded; make this the
+ * new DLT_ value.
+ */
+ v = new_dlt;
}
}
- if (is_ethernet) {
- /*
- * We reserved one more slot at the end of
- * the list.
- */
- bdl.bfl_list[bdl.bfl_len] = DLT_DOCSIS;
- bdl.bfl_len++;
- }
- }
- p->dlt_count = bdl.bfl_len;
- p->dlt_list = bdl.bfl_list;
- } else {
- if (errno != EINVAL) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "BIOCGDLTLIST: %s", pcap_strerror(errno));
- goto bad;
}
}
-#endif
+#endif /* various platforms */
+#endif /* BIOCGDLTLIST */
/*
* If this is an Ethernet device, and we don't have a DLT_ list,
@@ -1075,7 +1832,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* some other way of determining whether it's an Ethernet or 802.11
* device.)
*/
- if (p->linktype == DLT_EN10MB && p->dlt_count == 0) {
+ if (v == DLT_EN10MB && p->dlt_count == 0) {
p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
/*
* If that fails, just leave the list empty.
@@ -1086,7 +1843,14 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->dlt_count = 2;
}
}
-
+#ifdef PCAP_FDDIPAD
+ if (v == DLT_FDDI)
+ p->fddipad = PCAP_FDDIPAD;
+ else
+ p->fddipad = 0;
+#endif
+ p->linktype = v;
+
#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
/*
* Do a BIOCSHDRCMPLT, if defined, to turn that flag on, so
@@ -1098,31 +1862,33 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* BSDs - check CVS log for "bpf.c"?
*/
if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSHDRCMPLT: %s", pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
#endif
/* set timeout */
- p->to_ms = to_ms;
- if (to_ms != 0 && !p->zerocopy) {
+#ifdef HAVE_ZEROCOPY_BPF
+ if (p->md.timeout != 0 && !p->md.zerocopy) {
+#else
+ if (p->md.timeout) {
+#endif
/*
* XXX - is this seconds/nanoseconds in AIX?
* (Treating it as such doesn't fix the timeout
* problem described below.)
*/
struct timeval to;
- to.tv_sec = to_ms / 1000;
- to.tv_usec = (to_ms * 1000) % 1000000;
+ to.tv_sec = p->md.timeout / 1000;
+ to.tv_usec = (p->md.timeout * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
}
-#ifdef BIOCSETBUFMODE
- p->timeout = to_ms;
-#endif
#ifdef _AIX
#ifdef BIOCIMMEDIATE
@@ -1174,42 +1940,46 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
*/
v = 1;
if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
#endif /* BIOCIMMEDIATE */
#endif /* _AIX */
- if (promisc) {
- /* set promiscuous mode, okay if it fails */
+ if (p->opt.promisc) {
+ /* set promiscuous mode, just warn if it fails */
if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s",
pcap_strerror(errno));
+ status = PCAP_WARNING_PROMISC_NOTSUP;
}
}
if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
p->bufsize = v;
-#ifdef BIOCSETBUFMODE
- if (!p->zerocopy) {
+#ifdef HAVE_ZEROCOPY_BPF
+ if (!p->md.zerocopy) {
#endif
- p->buffer = (u_char *)malloc(p->bufsize);
- if (p->buffer == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- goto bad;
- }
+ p->buffer = (u_char *)malloc(p->bufsize);
+ if (p->buffer == NULL) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
#ifdef _AIX
- /* For some strange reason this seems to prevent the EFAULT
- * problems we have experienced from AIX BPF. */
- memset(p->buffer, 0x0, p->bufsize);
+ /* For some strange reason this seems to prevent the EFAULT
+ * problems we have experienced from AIX BPF. */
+ memset(p->buffer, 0x0, p->bufsize);
#endif
-#ifdef BIOCSETBUFMODE
+#ifdef HAVE_ZEROCOPY_BPF
}
#endif
@@ -1225,13 +1995,14 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
total_insn.code = (u_short)(BPF_RET | BPF_K);
total_insn.jt = 0;
total_insn.jf = 0;
- total_insn.k = snaplen;
+ total_insn.k = p->snapshot;
total_prog.bf_len = 1;
total_prog.bf_insns = &total_insn;
if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
@@ -1272,7 +2043,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* XXX - what about AIX?
*/
p->selectable_fd = p->fd; /* assume select() works until we know otherwise */
- if (uname(&osinfo) == 0) {
+ if (have_osinfo) {
/*
* We can check what OS this is.
*/
@@ -1291,30 +2062,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
p->stats_op = pcap_stats_bpf;
- p->close_op = pcap_close_common;
+ p->cleanup_op = pcap_cleanup_bpf;
- return (p);
+ return (status);
bad:
-
- (void)close(fd);
-#ifdef BIOCSETBUFMODE
- /*
- * In zero-copy mode, p->buffer is just a pointer into one of the two
- * memory-mapped buffers, so no need to free it.
- */
- if (p->zerocopy) {
- if (p->zbuf1 != MAP_FAILED && p->zbuf1 != NULL)
- munmap(p->zbuf1, p->zbufsize);
- if (p->zbuf2 != MAP_FAILED && p->zbuf2 != NULL)
- munmap(p->zbuf2, p->zbufsize);
- } else
-#endif
- if (p->buffer != NULL)
- free(p->buffer);
- if (p->dlt_list != NULL)
- free(p->dlt_list);
- free(p);
- return (NULL);
+ pcap_cleanup_bpf(p);
+ return (status);
}
int
@@ -1328,25 +2081,314 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
return (0);
}
+#ifdef HAVE_BSD_IEEE80211
static int
-pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
+monitor_mode(pcap_t *p, int set)
{
+ int sock;
+ struct ifmediareq req;
+ int *media_list;
+ int i;
+ int can_do;
+ struct ifreq ifr;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s",
+ pcap_strerror(errno));
+ return (PCAP_ERROR);
+ }
+
+ memset(&req, 0, sizeof req);
+ strncpy(req.ifm_name, p->opt.source, sizeof req.ifm_name);
+
/*
- * It looks that BPF code generated by gen_protochain() is not
- * compatible with some of kernel BPF code (for example BSD/OS 3.1).
- * Take a safer side for now.
+ * Find out how many media types we have.
*/
- if (no_optimize) {
+ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
/*
- * XXX - what if we already have a filter in the kernel?
+ * Can't get the media types.
*/
- if (install_bpf_program(p, fp) < 0)
- return (-1);
- p->md.use_bpf = 0; /* filtering in userland */
- return (0);
+ if (errno == EINVAL) {
+ /*
+ * Interface doesn't support SIOC{G,S}IFMEDIA.
+ */
+ close(sock);
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA 1: %s",
+ pcap_strerror(errno));
+ close(sock);
+ return (PCAP_ERROR);
+ }
+ if (req.ifm_count == 0) {
+ /*
+ * No media types.
+ */
+ close(sock);
+ return (PCAP_ERROR_RFMON_NOTSUP);
}
/*
+ * Allocate a buffer to hold all the media types, and
+ * get the media types.
+ */
+ media_list = malloc(req.ifm_count * sizeof(int));
+ if (media_list == NULL) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ close(sock);
+ return (PCAP_ERROR);
+ }
+ req.ifm_ulist = media_list;
+ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s",
+ pcap_strerror(errno));
+ free(media_list);
+ close(sock);
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * Look for an 802.11 "automatic" media type.
+ * We assume that all 802.11 adapters have that media type,
+ * and that it will carry the monitor mode supported flag.
+ */
+ can_do = 0;
+ for (i = 0; i < req.ifm_count; i++) {
+ if (IFM_TYPE(media_list[i]) == IFM_IEEE80211
+ && IFM_SUBTYPE(media_list[i]) == IFM_AUTO) {
+ /* OK, does it do monitor mode? */
+ if (media_list[i] & IFM_IEEE80211_MONITOR) {
+ can_do = 1;
+ break;
+ }
+ }
+ }
+ free(media_list);
+ if (!can_do) {
+ /*
+ * This adapter doesn't support monitor mode.
+ */
+ close(sock);
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+
+ if (set) {
+ /*
+ * Don't just check whether we can enable monitor mode,
+ * do so, if it's not already enabled.
+ */
+ if ((req.ifm_current & IFM_IEEE80211_MONITOR) == 0) {
+ /*
+ * Monitor mode isn't currently on, so turn it on,
+ * and remember that we should turn it off when the
+ * pcap_t is closed.
+ */
+
+ /*
+ * If we haven't already done so, arrange to have
+ * "pcap_close_all()" called when we exit.
+ */
+ if (!pcap_do_addexit(p)) {
+ /*
+ * "atexit()" failed; don't put the interface
+ * in monitor mode, just give up.
+ */
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "atexit failed");
+ close(sock);
+ return (PCAP_ERROR);
+ }
+ memset(&ifr, 0, sizeof(ifr));
+ (void)strncpy(ifr.ifr_name, p->opt.source,
+ sizeof(ifr.ifr_name));
+ ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR;
+ if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "SIOCSIFMEDIA: %s", pcap_strerror(errno));
+ close(sock);
+ return (PCAP_ERROR);
+ }
+
+ p->md.must_clear |= MUST_CLEAR_RFMON;
+
+ /*
+ * Add this to the list of pcaps to close when we exit.
+ */
+ pcap_add_to_pcaps_to_close(p);
+ }
+ }
+ return (0);
+}
+#endif /* HAVE_BSD_IEEE80211 */
+
+#if defined(BIOCGDLTLIST) && (defined(__APPLE__) || defined(HAVE_BSD_IEEE80211))
+/*
+ * Check whether we have any 802.11 link-layer types; return the best
+ * of the 802.11 link-layer types if we find one, and return -1
+ * otherwise.
+ *
+ * DLT_IEEE802_11_RADIO, with the radiotap header, is considered the
+ * best 802.11 link-layer type; any of the other 802.11-plus-radio
+ * headers are second-best; 802.11 with no radio information is
+ * the least good.
+ */
+static int
+find_802_11(struct bpf_dltlist *bdlp)
+{
+ int new_dlt;
+ int i;
+
+ /*
+ * Scan the list of DLT_ values, looking for 802.11 values,
+ * and, if we find any, choose the best of them.
+ */
+ new_dlt = -1;
+ for (i = 0; i < bdlp->bfl_len; i++) {
+ switch (bdlp->bfl_list[i]) {
+
+ case DLT_IEEE802_11:
+ /*
+ * 802.11, but no radio.
+ *
+ * Offer this, and select it as the new mode
+ * unless we've already found an 802.11
+ * header with radio information.
+ */
+ if (new_dlt == -1)
+ new_dlt = bdlp->bfl_list[i];
+ break;
+
+ case DLT_PRISM_HEADER:
+ case DLT_AIRONET_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ /*
+ * 802.11 with radio, but not radiotap.
+ *
+ * Offer this, and select it as the new mode
+ * unless we've already found the radiotap DLT_.
+ */
+ if (new_dlt != DLT_IEEE802_11_RADIO)
+ new_dlt = bdlp->bfl_list[i];
+ break;
+
+ case DLT_IEEE802_11_RADIO:
+ /*
+ * 802.11 with radiotap.
+ *
+ * Offer this, and select it as the new mode.
+ */
+ new_dlt = bdlp->bfl_list[i];
+ break;
+
+ default:
+ /*
+ * Not 802.11.
+ */
+ break;
+ }
+ }
+
+ return (new_dlt);
+}
+#endif /* defined(BIOCGDLTLIST) && (defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)) */
+
+#if defined(__APPLE__) && defined(BIOCGDLTLIST)
+/*
+ * Remove DLT_EN10MB from the list of DLT_ values.
+ */
+static void
+remove_en(pcap_t *p)
+{
+ int i, j;
+
+ /*
+ * Scan the list of DLT_ values and discard DLT_EN10MB.
+ */
+ j = 0;
+ for (i = 0; i < p->dlt_count; i++) {
+ switch (p->dlt_list[i]) {
+
+ case DLT_EN10MB:
+ /*
+ * Don't offer this one.
+ */
+ continue;
+
+ default:
+ /*
+ * Just copy this mode over.
+ */
+ break;
+ }
+
+ /*
+ * Copy this DLT_ value to its new position.
+ */
+ p->dlt_list[j] = p->dlt_list[i];
+ j++;
+ }
+
+ /*
+ * Set the DLT_ count to the number of entries we copied.
+ */
+ p->dlt_count = j;
+}
+
+/*
+ * Remove DLT_EN10MB from the list of DLT_ values, and look for the
+ * best 802.11 link-layer type in that list and return it.
+ * Radiotap is better than anything else; 802.11 with any other radio
+ * header is better than 802.11 with no radio header.
+ */
+static void
+remove_802_11(pcap_t *p)
+{
+ int i, j;
+
+ /*
+ * Scan the list of DLT_ values and discard 802.11 values.
+ */
+ j = 0;
+ for (i = 0; i < p->dlt_count; i++) {
+ switch (p->dlt_list[i]) {
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_AIRONET_HEADER:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_IEEE802_11_RADIO_AVS:
+ /*
+ * 802.11. Don't offer this one.
+ */
+ continue;
+
+ default:
+ /*
+ * Just copy this mode over.
+ */
+ break;
+ }
+
+ /*
+ * Copy this DLT_ value to its new position.
+ */
+ p->dlt_list[j] = p->dlt_list[i];
+ j++;
+ }
+
+ /*
+ * Set the DLT_ count to the number of entries we copied.
+ */
+ p->dlt_count = j;
+}
+#endif /* defined(__APPLE__) && defined(BIOCGDLTLIST) */
+
+static int
+pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
+{
+ /*
* Free any user-mode filter we might happen to have installed.
*/
pcap_freecode(&p->fcode);
@@ -1354,20 +2396,51 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
/*
* Try to install the kernel filter.
*/
- if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
+ if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) == 0) {
+ /*
+ * It worked.
+ */
+ p->md.use_bpf = 1; /* filtering in the kernel */
+
+ /*
+ * Discard any previously-received packets, as they might
+ * have passed whatever filter was formerly in effect, but
+ * might not pass this filter (BIOCSETF discards packets
+ * buffered in the kernel, so you can lose packets in any
+ * case).
+ */
+ p->cc = 0;
+ return (0);
+ }
+
+ /*
+ * We failed.
+ *
+ * If it failed with EINVAL, that's probably because the program
+ * is invalid or too big. Validate it ourselves; if we like it
+ * (we currently allow backward branches, to support protochain),
+ * run it in userland. (There's no notion of "too big" for
+ * userland.)
+ *
+ * Otherwise, just give up.
+ * XXX - if the copy of the program into the kernel failed,
+ * we will get EINVAL rather than, say, EFAULT on at least
+ * some kernels.
+ */
+ if (errno != EINVAL) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
pcap_strerror(errno));
return (-1);
}
- p->md.use_bpf = 1; /* filtering in the kernel */
/*
- * Discard any previously-received packets, as they might have
- * passed whatever filter was formerly in effect, but might
- * not pass this filter (BIOCSETF discards packets buffered
- * in the kernel, so you can lose packets in any case).
+ * install_bpf_program() validates the program.
+ *
+ * XXX - what if we already have a filter in the kernel?
*/
- p->cc = 0;
+ if (install_bpf_program(p, fp) < 0)
+ return (-1);
+ p->md.use_bpf = 0; /* filtering in userland */
return (0);
}
diff --git a/contrib/libpcap/pcap-bpf.h b/contrib/libpcap/pcap-bpf.h
index 62c493b..5fe129d 100644
--- a/contrib/libpcap/pcap-bpf.h
+++ b/contrib/libpcap/pcap-bpf.h
@@ -35,800 +35,13 @@
* 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: /tcpdump/master/libpcap/pcap-bpf.h,v 1.34.2.24 2007/09/19 02:52:12 guy Exp $ (LBL)
- */
-
-/*
- * This is libpcap's cut-down version of bpf.h; it includes only
- * the stuff needed for the code generator and the userland BPF
- * interpreter, and the libpcap APIs for setting filters, etc..
- *
- * "pcap-bpf.c" will include the native OS version, as it deals with
- * the OS's BPF implementation.
- *
- * XXX - should this all just be moved to "pcap.h"?
- */
-
-#ifndef BPF_MAJOR_VERSION
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* BSD style release date */
-#define BPF_RELEASE 199606
-
-#ifdef MSDOS /* must be 32-bit */
-typedef long bpf_int32;
-typedef unsigned long bpf_u_int32;
-#else
-typedef int bpf_int32;
-typedef u_int bpf_u_int32;
-#endif
-
-/*
- * Alignment macros. BPF_WORDALIGN rounds up to the next
- * even multiple of BPF_ALIGNMENT.
- */
-#ifndef __NetBSD__
-#define BPF_ALIGNMENT sizeof(bpf_int32)
-#else
-#define BPF_ALIGNMENT sizeof(long)
-#endif
-#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
-
-#define BPF_MAXINSNS 512
-#define BPF_MAXBUFSIZE 0x8000
-#define BPF_MINBUFSIZE 32
-
-/*
- * Structure for "pcap_compile()", "pcap_setfilter()", etc..
- */
-struct bpf_program {
- u_int bf_len;
- struct bpf_insn *bf_insns;
-};
-
-/*
- * Struct return by BIOCVERSION. This represents the version number of
- * the filter language described by the instruction encodings below.
- * 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
- * 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.
- */
-struct bpf_version {
- u_short bv_major;
- u_short bv_minor;
-};
-/* Current version number of filter architecture. */
-#define BPF_MAJOR_VERSION 1
-#define BPF_MINOR_VERSION 1
-
-/*
- * Data-link level type codes.
- *
- * Do *NOT* add new values to this list without asking
- * "tcpdump-workers@tcpdump.org" for a value. Otherwise, you run the
- * risk of using a value that's already being used for some other purpose,
- * and of having tools that read libpcap-format captures not being able
- * to handle captures with your new DLT_ value, with no hope that they
- * will ever be changed to do so (as that would destroy their ability
- * to read captures using that value for that other purpose).
- */
-
-/*
- * These are the types that are the same on all platforms, and that
- * have been defined by <net/bpf.h> for ages.
- */
-#define DLT_NULL 0 /* BSD loopback encapsulation */
-#define DLT_EN10MB 1 /* Ethernet (10Mb) */
-#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
-#define DLT_AX25 3 /* Amateur Radio AX.25 */
-#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
-#define DLT_CHAOS 5 /* Chaos */
-#define DLT_IEEE802 6 /* 802.5 Token Ring */
-#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
-#define DLT_SLIP 8 /* Serial Line IP */
-#define DLT_PPP 9 /* Point-to-point Protocol */
-#define DLT_FDDI 10 /* FDDI */
-
-/*
- * These are types that are different on some platforms, and that
- * have been defined by <net/bpf.h> for ages. We use #ifdefs to
- * detect the BSDs that define them differently from the traditional
- * libpcap <net/bpf.h>
- *
- * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
- * but I don't know what the right #define is for BSD/OS.
- */
-#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */
-
-#ifdef __OpenBSD__
-#define DLT_RAW 14 /* raw IP */
-#else
-#define DLT_RAW 12 /* raw IP */
-#endif
-
-/*
- * Given that the only OS that currently generates BSD/OS SLIP or PPP
- * is, well, BSD/OS, arguably everybody should have chosen its values
- * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
- * didn't. So it goes.
- */
-#if defined(__NetBSD__) || defined(__FreeBSD__)
-#ifndef DLT_SLIP_BSDOS
-#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
-#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
-#endif
-#else
-#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
-#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
-#endif
-
-/*
- * 17 is used for DLT_OLD_PFLOG in OpenBSD;
- * OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below.
- * 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else.
- */
-
-#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
-
-/*
- * Apparently Redback uses this for its SmartEdge 400/800. I hope
- * nobody else decided to use it, too.
- */
-#define DLT_REDBACK_SMARTEDGE 32
-
-/*
- * These values are defined by NetBSD; other platforms should refrain from
- * using them for other purposes, so that NetBSD savefiles with link
- * types of 50 or 51 can be read as this type on all platforms.
- */
-#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
-#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
-
-/*
- * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
- * a link-layer type of 99 for the tcpdump it supplies. The link-layer
- * header has 6 bytes of unknown data, something that appears to be an
- * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
- * I've seen.
- */
-#define DLT_SYMANTEC_FIREWALL 99
-
-/*
- * Values between 100 and 103 are used in capture file headers as
- * link-layer types corresponding to DLT_ types that differ
- * between platforms; don't use those values for new DLT_ new types.
- */
-
-/*
- * This value was defined by libpcap 0.5; platforms that have defined
- * it with a different value should define it here with that value -
- * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
- * whatever value that happens to be, so programs will correctly
- * handle files with that link type regardless of the value of
- * DLT_C_HDLC.
- *
- * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
- * compatibility with programs written for BSD/OS.
- *
- * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
- * for source compatibility with programs written for libpcap 0.5.
- */
-#define DLT_C_HDLC 104 /* Cisco HDLC */
-#define DLT_CHDLC DLT_C_HDLC
-
-#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
-
-/*
- * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
- * except when it isn't. (I.e., sometimes it's just raw IP, and
- * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL,
- * so that we don't have to worry about the link-layer header.)
- */
-
-/*
- * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
- * with other values.
- * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
- * (DLCI, etc.).
- */
-#define DLT_FRELAY 107
-
-/*
- * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
- * that the AF_ type in the link-layer header is in network byte order.
- *
- * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
- * we don't use 12 for it in OSes other than OpenBSD.
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-bpf.h,v 1.50 2007/04/01 21:43:55 guy Exp $ (LBL)
*/
-#ifdef __OpenBSD__
-#define DLT_LOOP 12
-#else
-#define DLT_LOOP 108
-#endif
/*
- * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
- * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
- * than OpenBSD.
- */
-#ifdef __OpenBSD__
-#define DLT_ENC 13
-#else
-#define DLT_ENC 109
-#endif
-
-/*
- * Values between 110 and 112 are reserved for use in capture file headers
- * as link-layer types corresponding to DLT_ types that might differ
- * between platforms; don't use those values for new DLT_ types
- * other than the corresponding DLT_ types.
- */
-
-/*
- * This is for Linux cooked sockets.
- */
-#define DLT_LINUX_SLL 113
-
-/*
- * Apple LocalTalk hardware.
- */
-#define DLT_LTALK 114
-
-/*
- * Acorn Econet.
- */
-#define DLT_ECONET 115
-
-/*
- * Reserved for use with OpenBSD ipfilter.
- */
-#define DLT_IPFILTER 116
-
-/*
- * OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023
- * in SuSE 6.3, so we can't use 17 for it in capture-file headers.
- *
- * XXX: is there a conflict with DLT_PFSYNC 18 as well?
- */
-#ifdef __OpenBSD__
-#define DLT_OLD_PFLOG 17
-#define DLT_PFSYNC 18
-#endif
-#define DLT_PFLOG 117
-
-/*
- * Registered for Cisco-internal use.
- */
-#define DLT_CISCO_IOS 118
-
-/*
- * For 802.11 cards using the Prism II chips, with a link-layer
- * header including Prism monitor mode information plus an 802.11
- * header.
- */
-#define DLT_PRISM_HEADER 119
-
-/*
- * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
- * (see Doug Ambrisko's FreeBSD patches).
- */
-#define DLT_AIRONET_HEADER 120
-
-/*
- * Reserved for Siemens HiPath HDLC.
- */
-#define DLT_HHDLC 121
-
-/*
- * This is for RFC 2625 IP-over-Fibre Channel.
- *
- * This is not for use with raw Fibre Channel, where the link-layer
- * header starts with a Fibre Channel frame header; it's for IP-over-FC,
- * where the link-layer header starts with an RFC 2625 Network_Header
- * field.
- */
-#define DLT_IP_OVER_FC 122
-
-/*
- * This is for Full Frontal ATM on Solaris with SunATM, with a
- * pseudo-header followed by an AALn PDU.
+ * For backwards compatibility.
*
- * There may be other forms of Full Frontal ATM on other OSes,
- * with different pseudo-headers.
- *
- * If ATM software returns a pseudo-header with VPI/VCI information
- * (and, ideally, packet type information, e.g. signalling, ILMI,
- * LANE, LLC-multiplexed traffic, etc.), it should not use
- * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
- * and the like don't have to infer the presence or absence of a
- * pseudo-header and the form of the pseudo-header.
- */
-#define DLT_SUNATM 123 /* Solaris+SunATM */
-
-/*
- * Reserved as per request from Kent Dahlgren <kent@praesum.com>
- * for private use.
- */
-#define DLT_RIO 124 /* RapidIO */
-#define DLT_PCI_EXP 125 /* PCI Express */
-#define DLT_AURORA 126 /* Xilinx Aurora link layer */
-
-/*
- * Header for 802.11 plus a number of bits of link-layer information
- * including radio information, used by some recent BSD drivers as
- * well as the madwifi Atheros driver for Linux.
- */
-#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
-
-/*
- * Reserved for the TZSP encapsulation, as per request from
- * Chris Waters <chris.waters@networkchemistry.com>
- * TZSP is a generic encapsulation for any other link type,
- * which includes a means to include meta-information
- * with the packet, e.g. signal strength and channel
- * for 802.11 packets.
- */
-#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
-
-/*
- * BSD's ARCNET headers have the source host, destination host,
- * and type at the beginning of the packet; that's what's handed
- * up to userland via BPF.
- *
- * Linux's ARCNET headers, however, have a 2-byte offset field
- * between the host IDs and the type; that's what's handed up
- * to userland via PF_PACKET sockets.
- *
- * We therefore have to have separate DLT_ values for them.
- */
-#define DLT_ARCNET_LINUX 129 /* ARCNET */
-
-/*
- * Juniper-private data link types, as per request from
- * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
- * for passing on chassis-internal metainformation such as
- * QOS profiles, etc..
- */
-#define DLT_JUNIPER_MLPPP 130
-#define DLT_JUNIPER_MLFR 131
-#define DLT_JUNIPER_ES 132
-#define DLT_JUNIPER_GGSN 133
-#define DLT_JUNIPER_MFR 134
-#define DLT_JUNIPER_ATM2 135
-#define DLT_JUNIPER_SERVICES 136
-#define DLT_JUNIPER_ATM1 137
-
-/*
- * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
- * <dieter@apple.com>. The header that's presented is an Ethernet-like
- * header:
- *
- * #define FIREWIRE_EUI64_LEN 8
- * struct firewire_header {
- * u_char firewire_dhost[FIREWIRE_EUI64_LEN];
- * u_char firewire_shost[FIREWIRE_EUI64_LEN];
- * u_short firewire_type;
- * };
- *
- * with "firewire_type" being an Ethernet type value, rather than,
- * for example, raw GASP frames being handed up.
- */
-#define DLT_APPLE_IP_OVER_IEEE1394 138
-
-/*
- * Various SS7 encapsulations, as per a request from Jeff Morriss
- * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
- */
-#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */
-#define DLT_MTP2 140 /* MTP2, without pseudo-header */
-#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */
-#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */
-
-/*
- * DOCSIS MAC frames.
+ * Note to OS vendors: do NOT get rid of this file! Some applications
+ * might expect to be able to include <pcap-bpf.h>.
*/
-#define DLT_DOCSIS 143
-
-/*
- * Linux-IrDA packets. Protocol defined at http://www.irda.org.
- * Those packets include IrLAP headers and above (IrLMP...), but
- * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
- * framing can be handled by the hardware and depend on the bitrate.
- * This is exactly the format you would get capturing on a Linux-IrDA
- * interface (irdaX), but not on a raw serial port.
- * Note the capture is done in "Linux-cooked" mode, so each packet include
- * a fake packet header (struct sll_header). This is because IrDA packet
- * decoding is dependant on the direction of the packet (incomming or
- * outgoing).
- * When/if other platform implement IrDA capture, we may revisit the
- * issue and define a real DLT_IRDA...
- * Jean II
- */
-#define DLT_LINUX_IRDA 144
-
-/*
- * Reserved for IBM SP switch and IBM Next Federation switch.
- */
-#define DLT_IBM_SP 145
-#define DLT_IBM_SN 146
-
-/*
- * Reserved for private use. If you have some link-layer header type
- * that you want to use within your organization, with the capture files
- * using that link-layer header type not ever be sent outside your
- * organization, you can use these values.
- *
- * No libpcap release will use these for any purpose, nor will any
- * tcpdump release use them, either.
- *
- * Do *NOT* use these in capture files that you expect anybody not using
- * your private versions of capture-file-reading tools to read; in
- * particular, do *NOT* use them in products, otherwise you may find that
- * people won't be able to use tcpdump, or snort, or Ethereal, or... to
- * read capture files from your firewall/intrusion detection/traffic
- * monitoring/etc. appliance, or whatever product uses that DLT_ value,
- * and you may also find that the developers of those applications will
- * not accept patches to let them read those files.
- *
- * Also, do not use them if somebody might send you a capture using them
- * for *their* private type and tools using them for *your* private type
- * would have to read them.
- *
- * Instead, ask "tcpdump-workers@tcpdump.org" for a new DLT_ value,
- * as per the comment above, and use the type you're given.
- */
-#define DLT_USER0 147
-#define DLT_USER1 148
-#define DLT_USER2 149
-#define DLT_USER3 150
-#define DLT_USER4 151
-#define DLT_USER5 152
-#define DLT_USER6 153
-#define DLT_USER7 154
-#define DLT_USER8 155
-#define DLT_USER9 156
-#define DLT_USER10 157
-#define DLT_USER11 158
-#define DLT_USER12 159
-#define DLT_USER13 160
-#define DLT_USER14 161
-#define DLT_USER15 162
-
-/*
- * For future use with 802.11 captures - defined by AbsoluteValue
- * Systems to store a number of bits of link-layer information
- * including radio information:
- *
- * http://www.shaftnet.org/~pizza/software/capturefrm.txt
- *
- * but it might be used by some non-AVS drivers now or in the
- * future.
- */
-#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
- * for passing on chassis-internal metainformation such as
- * QOS profiles, etc..
- */
-#define DLT_JUNIPER_MONITOR 164
-
-/*
- * Reserved for BACnet MS/TP.
- */
-#define DLT_BACNET_MS_TP 165
-
-/*
- * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
- *
- * This is used in some OSes to allow a kernel socket filter to distinguish
- * between incoming and outgoing packets, on a socket intended to
- * supply pppd with outgoing packets so it can do dial-on-demand and
- * hangup-on-lack-of-demand; incoming packets are filtered out so they
- * don't cause pppd to hold the connection up (you don't want random
- * input packets such as port scans, packets from old lost connections,
- * etc. to force the connection to stay up).
- *
- * The first byte of the PPP header (0xff03) is modified to accomodate
- * the direction - 0x00 = IN, 0x01 = OUT.
- */
-#define DLT_PPP_PPPD 166
-
-/*
- * Names for backwards compatibility with older versions of some PPP
- * software; new software should use DLT_PPP_PPPD.
- */
-#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
-#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
- * for passing on chassis-internal metainformation such as
- * QOS profiles, cookies, etc..
- */
-#define DLT_JUNIPER_PPPOE 167
-#define DLT_JUNIPER_PPPOE_ATM 168
-
-#define DLT_GPRS_LLC 169 /* GPRS LLC */
-#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
-#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
-
-/*
- * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
- * monitoring equipment.
- */
-#define DLT_GCOM_T1E1 172
-#define DLT_GCOM_SERIAL 173
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>. The DLT_ is used
- * for internal communication to Physical Interface Cards (PIC)
- */
-#define DLT_JUNIPER_PIC_PEER 174
-
-/*
- * Link types requested by Gregor Maier <gregor@endace.com> of Endace
- * Measurement Systems. They add an ERF header (see
- * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
- * the link-layer header.
- */
-#define DLT_ERF_ETH 175 /* Ethernet */
-#define DLT_ERF_POS 176 /* Packet-over-SONET */
-
-/*
- * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
- * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
- * includes additional information before the LAPD header, so it's
- * not necessarily a generic LAPD header.
- */
-#define DLT_LINUX_LAPD 177
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ are used for prepending meta-information
- * like interface index, interface name
- * before standard Ethernet, PPP, Frelay & C-HDLC Frames
- */
-#define DLT_JUNIPER_ETHER 178
-#define DLT_JUNIPER_PPP 179
-#define DLT_JUNIPER_FRELAY 180
-#define DLT_JUNIPER_CHDLC 181
-
-/*
- * Multi Link Frame Relay (FRF.16)
- */
-#define DLT_MFR 182
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for internal communication with a
- * voice Adapter Card (PIC)
- */
-#define DLT_JUNIPER_VP 183
-
-/*
- * Arinc 429 frames.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Every frame contains a 32bit A429 label.
- * More documentation on Arinc 429 can be found at
- * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
- */
-#define DLT_A429 184
-
-/*
- * Arinc 653 Interpartition Communication messages.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Please refer to the A653-1 standard for more information.
- */
-#define DLT_A653_ICM 185
-
-/*
- * USB packets, beginning with a USB setup header; requested by
- * Paolo Abeni <paolo.abeni@email.it>.
- */
-#define DLT_USB 186
-
-/*
- * Bluetooth HCI UART transport layer (part H:4); requested by
- * Paolo Abeni.
- */
-#define DLT_BLUETOOTH_HCI_H4 187
-
-/*
- * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
- * <cruz_petagay@bah.com>.
- */
-#define DLT_IEEE802_16_MAC_CPS 188
-
-/*
- * USB packets, beginning with a Linux USB header; requested by
- * Paolo Abeni <paolo.abeni@email.it>.
- */
-#define DLT_USB_LINUX 189
-
-/*
- * Controller Area Network (CAN) v. 2.0B packets.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- * Used to dump CAN packets coming from a CAN Vector board.
- * More documentation on the CAN v2.0B frames can be found at
- * http://www.can-cia.org/downloads/?269
- */
-#define DLT_CAN20B 190
-
-/*
- * IEEE 802.15.4, with address fields padded, as is done by Linux
- * drivers; requested by Juergen Schimmer.
- */
-#define DLT_IEEE802_15_4_LINUX 191
-
-/*
- * Per Packet Information encapsulated packets.
- * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
- */
-#define DLT_PPI 192
-
-/*
- * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
- * requested by Charles Clancy.
- */
-#define DLT_IEEE802_16_MAC_CPS_RADIO 193
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for internal communication with a
- * integrated service module (ISM).
- */
-#define DLT_JUNIPER_ISM 194
-
-/*
- * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
- * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
- */
-#define DLT_IEEE802_15_4 195
-
-/*
- * Various link-layer types, with a pseudo-header, for SITA
- * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
- */
-#define DLT_SITA 196
-
-/*
- * Various link-layer types, with a pseudo-header, for Endace DAG cards;
- * encapsulates Endace ERF records. Requested by Stephen Donnelly
- * <stephen@endace.com>.
- */
-#define DLT_ERF 197
-
-/*
- * Special header prepended to Ethernet packets when capturing from a
- * u10 Networks board. Requested by Phil Mulholland
- * <phil@u10networks.com>.
- */
-#define DLT_RAIF1 198
-
-/*
- * IPMB packet for IPMI, beginning with the I2C slave address, followed
- * by the netFn and LUN, etc.. Requested by Chanthy Toeung
- * <chanthy.toeung@ca.kontron.com>.
- */
-#define DLT_IPMB 199
-
-/*
- * Juniper-private data link type, as per request from
- * Hannes Gredler <hannes@juniper.net>.
- * The DLT_ is used for capturing data on a secure tunnel interface.
- */
-#define DLT_JUNIPER_ST 200
-
-/*
- * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
- * that includes direction information; requested by Paolo Abeni.
- */
-#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
-
-
-/*
- * The instruction encodings.
- */
-/* instruction classes */
-#define BPF_CLASS(code) ((code) & 0x07)
-#define BPF_LD 0x00
-#define BPF_LDX 0x01
-#define BPF_ST 0x02
-#define BPF_STX 0x03
-#define BPF_ALU 0x04
-#define BPF_JMP 0x05
-#define BPF_RET 0x06
-#define BPF_MISC 0x07
-
-/* ld/ldx fields */
-#define BPF_SIZE(code) ((code) & 0x18)
-#define BPF_W 0x00
-#define BPF_H 0x08
-#define BPF_B 0x10
-#define BPF_MODE(code) ((code) & 0xe0)
-#define BPF_IMM 0x00
-#define BPF_ABS 0x20
-#define BPF_IND 0x40
-#define BPF_MEM 0x60
-#define BPF_LEN 0x80
-#define BPF_MSH 0xa0
-
-/* alu/jmp fields */
-#define BPF_OP(code) ((code) & 0xf0)
-#define BPF_ADD 0x00
-#define BPF_SUB 0x10
-#define BPF_MUL 0x20
-#define BPF_DIV 0x30
-#define BPF_OR 0x40
-#define BPF_AND 0x50
-#define BPF_LSH 0x60
-#define BPF_RSH 0x70
-#define BPF_NEG 0x80
-#define BPF_JA 0x00
-#define BPF_JEQ 0x10
-#define BPF_JGT 0x20
-#define BPF_JGE 0x30
-#define BPF_JSET 0x40
-#define BPF_SRC(code) ((code) & 0x08)
-#define BPF_K 0x00
-#define BPF_X 0x08
-
-/* ret - BPF_K and BPF_X also apply */
-#define BPF_RVAL(code) ((code) & 0x18)
-#define BPF_A 0x10
-
-/* misc */
-#define BPF_MISCOP(code) ((code) & 0xf8)
-#define BPF_TAX 0x00
-#define BPF_TXA 0x80
-
-/*
- * The instruction data structure.
- */
-struct bpf_insn {
- u_short code;
- u_char jt;
- u_char jf;
- bpf_int32 k;
-};
-
-/*
- * Macros for insn array initializers.
- */
-#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
-#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
-
-#if __STDC__ || defined(__cplusplus)
-extern int bpf_validate(struct bpf_insn *, int);
-extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
-#else
-extern int bpf_validate();
-extern u_int bpf_filter();
-#endif
-
-/*
- * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
- */
-#define BPF_MEMWORDS 16
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+#include <pcap/bpf.h>
diff --git a/contrib/libpcap/pcap-bt-linux.c b/contrib/libpcap/pcap-bt-linux.c
new file mode 100644
index 0000000..2c619ff
--- /dev/null
+++ b/contrib/libpcap/pcap-bt-linux.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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
+ * OWNER 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.
+ *
+ * Bluetooth sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-bt-linux.c,v 1.9.2.6 2008-07-01 07:06:37 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcap-int.h"
+#include "pcap-bt-linux.h"
+#include "pcap/bluetooth.h"
+
+#ifdef NEED_STRERROR_H
+#include "strerror.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+#define BT_IFACE "bluetooth"
+#define BT_CTRL_SIZE 128
+
+/* forward declaration */
+static int bt_activate(pcap_t *);
+static int bt_read_linux(pcap_t *, int , pcap_handler , u_char *);
+static int bt_inject_linux(pcap_t *, const void *, size_t);
+static int bt_setfilter_linux(pcap_t *, struct bpf_program *);
+static int bt_setdirection_linux(pcap_t *, pcap_direction_t);
+static int bt_stats_linux(pcap_t *, struct pcap_stat *);
+
+int
+bt_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
+{
+ pcap_if_t *found_dev = *alldevsp;
+ struct hci_dev_list_req *dev_list;
+ struct hci_dev_req *dev_req;
+ int i, sock;
+ int ret = 0;
+
+ sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (sock < 0)
+ {
+ /* if bluetooth is not supported this this is not fatal*/
+ if (errno == EAFNOSUPPORT)
+ return 0;
+ snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't open raw Bluetooth socket %d:%s",
+ errno, strerror(errno));
+ return -1;
+ }
+
+ dev_list = malloc(HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list));
+ if (!dev_list)
+ {
+ snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't allocate %zu bytes for Bluetooth device list",
+ HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list));
+ ret = -1;
+ goto done;
+ }
+
+ dev_list->dev_num = HCI_MAX_DEV;
+
+ if (ioctl(sock, HCIGETDEVLIST, (void *) dev_list) < 0)
+ {
+ snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't get Bluetooth device list via ioctl %d:%s",
+ errno, strerror(errno));
+ ret = -1;
+ goto free;
+ }
+
+ dev_req = dev_list->dev_req;
+ for (i = 0; i < dev_list->dev_num; i++, dev_req++) {
+ char dev_name[20], dev_descr[30];
+
+ snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id);
+ snprintf(dev_descr, 30, "Bluetooth adapter number %d", i);
+
+ if (pcap_add_if(&found_dev, dev_name, 0,
+ dev_descr, err_str) < 0)
+ {
+ ret = -1;
+ break;
+ }
+
+ }
+
+free:
+ free(dev_list);
+
+done:
+ close(sock);
+ return ret;
+}
+
+pcap_t *
+bt_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = bt_activate;
+ return (p);
+}
+
+static int
+bt_activate(pcap_t* handle)
+{
+ struct sockaddr_hci addr;
+ int opt;
+ int dev_id;
+ struct hci_filter flt;
+ int err = PCAP_ERROR;
+
+ /* get bt interface id */
+ if (sscanf(handle->opt.source, BT_IFACE"%d", &dev_id) != 1)
+ {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't get Bluetooth device index from %s",
+ handle->opt.source);
+ return PCAP_ERROR;
+ }
+
+ /* Initialize some components of the pcap structure. */
+ handle->bufsize = handle->snapshot+BT_CTRL_SIZE+sizeof(pcap_bluetooth_h4_header);
+ handle->offset = BT_CTRL_SIZE;
+ handle->linktype = DLT_BLUETOOTH_HCI_H4_WITH_PHDR;
+
+ handle->read_op = bt_read_linux;
+ handle->inject_op = bt_inject_linux;
+ handle->setfilter_op = bt_setfilter_linux;
+ handle->setdirection_op = bt_setdirection_linux;
+ handle->set_datalink_op = NULL; /* can't change data link type */
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->stats_op = bt_stats_linux;
+ handle->md.ifindex = dev_id;
+
+ /* Create HCI socket */
+ handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (handle->fd < 0) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't create raw socket %d:%s",
+ errno, strerror(errno));
+ return PCAP_ERROR;
+ }
+
+ handle->buffer = malloc(handle->bufsize);
+ if (!handle->buffer) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate dump buffer: %s",
+ pcap_strerror(errno));
+ goto close_fail;
+ }
+
+ opt = 1;
+ if (setsockopt(handle->fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't enable data direction info %d:%s",
+ errno, strerror(errno));
+ goto close_fail;
+ }
+
+ opt = 1;
+ if (setsockopt(handle->fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't enable time stamp %d:%s",
+ errno, strerror(errno));
+ goto close_fail;
+ }
+
+ /* Setup filter, do not call hci function to avoid dependence on
+ * external libs */
+ memset(&flt, 0, sizeof(flt));
+ memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask));
+ memset((void *) &flt.event_mask, 0xff, sizeof(flt.event_mask));
+ if (setsockopt(handle->fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't set filter %d:%s",
+ errno, strerror(errno));
+ goto close_fail;
+ }
+
+
+ /* Bind socket to the HCI device */
+ addr.hci_family = AF_BLUETOOTH;
+ addr.hci_dev = handle->md.ifindex;
+ if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d %d:%s",
+ handle->md.ifindex, errno, strerror(errno));
+ goto close_fail;
+ }
+
+ if (handle->opt.rfmon) {
+ /*
+ * Monitor mode doesn't apply to Bluetooth devices.
+ */
+ err = PCAP_ERROR_RFMON_NOTSUP;
+ goto close_fail;
+ }
+
+ if (handle->opt.buffer_size == 0) {
+ /*
+ * Set the socket buffer size to the specified value.
+ */
+ if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
+ &handle->opt.buffer_size,
+ sizeof(handle->opt.buffer_size)) == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "SO_RCVBUF: %s", pcap_strerror(errno));
+ goto close_fail;
+ }
+ }
+
+ handle->selectable_fd = handle->fd;
+ return 0;
+
+close_fail:
+ pcap_cleanup_live_common(handle);
+ return err;
+}
+
+static int
+bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+ struct cmsghdr *cmsg;
+ struct msghdr msg;
+ struct iovec iv;
+ struct pcap_pkthdr pkth;
+ pcap_bluetooth_h4_header* bthdr;
+
+ bthdr = (pcap_bluetooth_h4_header*) &handle->buffer[handle->offset];
+ iv.iov_base = &handle->buffer[handle->offset+sizeof(pcap_bluetooth_h4_header)];
+ iv.iov_len = handle->snapshot;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = &iv;
+ msg.msg_iovlen = 1;
+ msg.msg_control = handle->buffer;
+ msg.msg_controllen = handle->offset;
+
+ /* ignore interrupt system call error */
+ do {
+ pkth.caplen = recvmsg(handle->fd, &msg, 0);
+ if (handle->break_loop)
+ {
+ handle->break_loop = 0;
+ return -2;
+ }
+ } while ((pkth.caplen == -1) && (errno == EINTR));
+
+
+ if (pkth.caplen < 0) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't receive packet %d:%s",
+ errno, strerror(errno));
+ return -1;
+ }
+
+ /* get direction and timestamp*/
+ cmsg = CMSG_FIRSTHDR(&msg);
+ int in=0;
+ while (cmsg) {
+ switch (cmsg->cmsg_type) {
+ case HCI_CMSG_DIR:
+ in = *((int *) CMSG_DATA(cmsg));
+ break;
+ case HCI_CMSG_TSTAMP:
+ pkth.ts = *((struct timeval *) CMSG_DATA(cmsg));
+ break;
+ }
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ }
+ if ((in && (handle->direction == PCAP_D_OUT)) ||
+ ((!in) && (handle->direction == PCAP_D_IN)))
+ return 0;
+
+ bthdr->direction = htonl(in != 0);
+ pkth.caplen+=sizeof(pcap_bluetooth_h4_header);
+ pkth.len = pkth.caplen;
+ callback(user, &pkth, &handle->buffer[handle->offset]);
+ return 1;
+}
+
+static int
+bt_inject_linux(pcap_t *handle, const void *buf, size_t size)
+{
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
+ "bluetooth devices");
+ return (-1);
+}
+
+
+static int
+bt_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+ int ret;
+ struct hci_dev_info dev_info;
+ struct hci_dev_stats * s = &dev_info.stat;
+ dev_info.dev_id = handle->md.ifindex;
+
+ /* ingnore eintr */
+ do {
+ ret = ioctl(handle->fd, HCIGETDEVINFO, (void *)&dev_info);
+ } while ((ret == -1) && (errno == EINTR));
+
+ if (ret < 0) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can get stats"
+ " via ioctl %d:%s", errno, strerror(errno));
+ return (-1);
+
+ }
+
+ /* we receive both rx and tx frames, so comulate all stats */
+ stats->ps_recv = s->evt_rx + s->acl_rx + s->sco_rx + s->cmd_tx +
+ s->acl_tx +s->sco_tx;
+ stats->ps_drop = s->err_rx + s->err_tx;
+ stats->ps_ifdrop = 0;
+ return 0;
+}
+
+static int
+bt_setfilter_linux(pcap_t *p, struct bpf_program *fp)
+{
+ return 0;
+}
+
+
+static int
+bt_setdirection_linux(pcap_t *p, pcap_direction_t d)
+{
+ p->direction = d;
+ return 0;
+}
diff --git a/contrib/libpcap/pcap-bt-linux.h b/contrib/libpcap/pcap-bt-linux.h
new file mode 100644
index 0000000..87d22a6
--- /dev/null
+++ b/contrib/libpcap/pcap-bt-linux.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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
+ * OWNER 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.
+ *
+ * Bluetooth sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-bt-linux.h,v 1.4.2.1 2008-04-04 19:39:05 guy Exp $ (LBL)
+ */
+
+/*
+ * Prototypes for Bluetooth-related functions
+ */
+int bt_platform_finddevs(pcap_if_t **alldevsp, char *err_str);
+pcap_t *bt_create(const char *device, char *ebuf);
diff --git a/contrib/libpcap/pcap-config.1 b/contrib/libpcap/pcap-config.1
new file mode 100644
index 0000000..a99b379
--- /dev/null
+++ b/contrib/libpcap/pcap-config.1
@@ -0,0 +1,54 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap-config.1,v 1.1.2.2 2008-09-23 18:06:01 guy Exp $ (LBL)
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-CONFIG 1 "23 September 2008"
+.SH NAME
+pcap-config \- write libpcap compiler and linker flags to standard output
+.SH SYNOPSIS
+.na
+.B pcap-config
+[
+.B \-\-cflags | \-\-libs
+]
+.ad
+.SH DESCRIPTION
+.LP
+When run with the
+.B \-\-cflags
+option,
+.I pcap-config
+writes to the standard output the
+.B \-I
+compiler flags required to include libpcap's header files.
+When run with the
+.B \-\-libs
+option,
+.I pcap-config
+writes to the standard output the
+.B \-L
+and
+.B \-l
+linker required to link with libpcap, including
+.B \-l
+flags for libraries required by libpcap.
+.SH "SEE ALSO"
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap-config.in b/contrib/libpcap/pcap-config.in
new file mode 100644
index 0000000..19f2114
--- /dev/null
+++ b/contrib/libpcap/pcap-config.in
@@ -0,0 +1,16 @@
+#! /bin/sh
+
+#
+# Script to give the appropriate compiler flags and linker flags
+# to use when building code that uses libpcap.
+#
+case "$1" in
+
+--cflags)
+ echo "-I @includedir@"
+ ;;
+
+--libs)
+ echo "-L @libdir@ -lpcap @DEPLIBS@"
+ ;;
+esac
diff --git a/contrib/libpcap/pcap-dag.c b/contrib/libpcap/pcap-dag.c
index 3ef2508..039d926 100644
--- a/contrib/libpcap/pcap-dag.c
+++ b/contrib/libpcap/pcap-dag.c
@@ -17,7 +17,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.21.2.7 2007/06/22 06:43:58 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-dag.c,v 1.31.2.8 2008-04-14 20:41:51 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -46,6 +46,8 @@ struct rtentry; /* declarations in <net/if.h> */
#include "dagnew.h"
#include "dagapi.h"
+#include "pcap-dag.h"
+
#define ATM_CELL_SIZE 52
#define ATM_HDR_SIZE 4
@@ -83,10 +85,9 @@ static const unsigned short endian_test_word = 0x0100;
#ifdef DAG_ONLY
/* This code is required when compiling for a DAG device only. */
-#include "pcap-dag.h"
/* Replace dag function names with pcap equivalent. */
-#define dag_open_live pcap_open_live
+#define dag_create pcap_create
#define dag_platform_finddevs pcap_platform_finddevs
#endif /* DAG_ONLY */
@@ -124,7 +125,7 @@ delete_pcap_dag(pcap_t *p)
*/
static void
-dag_platform_close(pcap_t *p)
+dag_platform_cleanup(pcap_t *p)
{
if (p != NULL) {
@@ -138,10 +139,14 @@ dag_platform_close(pcap_t *p)
if(dag_stop(p->fd) < 0)
fprintf(stderr,"dag_stop: %s\n", strerror(errno));
#endif /* HAVE_DAG_STREAMS_API */
- if(dag_close(p->fd) < 0)
- fprintf(stderr,"dag_close: %s\n", strerror(errno));
+ if(p->fd != -1) {
+ if(dag_close(p->fd) < 0)
+ fprintf(stderr,"dag_close: %s\n", strerror(errno));
+ p->fd = -1;
+ }
+ delete_pcap_dag(p);
+ pcap_cleanup_live_common(p);
}
- delete_pcap_dag(p);
/* Note: don't need to call close(p->fd) here as dag_close(p->fd) does this. */
}
@@ -150,7 +155,7 @@ atexit_handler(void)
{
while (pcap_dags != NULL) {
if (pcap_dags->pid == getpid()) {
- dag_platform_close(pcap_dags->p);
+ dag_platform_cleanup(pcap_dags->p);
} else {
delete_pcap_dag(pcap_dags->p);
}
@@ -180,6 +185,38 @@ new_pcap_dag(pcap_t *p)
return 0;
}
+static unsigned int
+dag_erf_ext_header_count(uint8_t * erf, size_t len)
+{
+ uint32_t hdr_num = 0;
+ uint8_t hdr_type;
+
+ /* basic sanity checks */
+ if ( erf == NULL )
+ return 0;
+ if ( len < 16 )
+ return 0;
+
+ /* check if we have any extension headers */
+ if ( (erf[8] & 0x80) == 0x00 )
+ return 0;
+
+ /* loop over the extension headers */
+ do {
+
+ /* sanity check we have enough bytes */
+ if ( len <= (24 + (hdr_num * 8)) )
+ return hdr_num;
+
+ /* get the header type */
+ hdr_type = erf[(16 + (hdr_num * 8))];
+ hdr_num++;
+
+ } while ( hdr_type & 0x80 );
+
+ return hdr_num;
+}
+
/*
* Read at most max_packets from the capture stream and call the callback
* for each of them. Returns the number of packets handled, -1 if an
@@ -191,6 +228,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
unsigned int processed = 0;
int flags = p->md.dag_offset_flags;
unsigned int nonblocking = flags & DAGF_NONBLOCK;
+ unsigned int num_ext_hdr = 0;
/* Get the next bufferful of packets (if necessary). */
while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) {
@@ -220,7 +258,9 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
* If non-block is specified it will return immediately. The user
* is then responsible for efficiency.
*/
- p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom));
+ if ( NULL == (p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom))) ) {
+ return -1;
+ }
#else
/* dag_offset does not support timeouts */
p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags);
@@ -244,18 +284,18 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
/* Process the packets. */
while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) {
-
+
unsigned short packet_len = 0;
int caplen = 0;
struct pcap_pkthdr pcap_header;
-
+
#ifdef HAVE_DAG_STREAMS_API
dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom);
#else
dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom);
#endif /* HAVE_DAG_STREAMS_API */
- u_char *dp = ((u_char *)header) + dag_record_size;
+ u_char *dp = ((u_char *)header); /* + dag_record_size; */
unsigned short rlen;
/*
@@ -279,146 +319,17 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
p->md.dag_mem_bottom += rlen;
- switch(header->type) {
- case TYPE_ATM:
-#ifdef TYPE_AAL5
- case TYPE_AAL5:
- if (header->type == TYPE_AAL5) {
- packet_len = ntohs(header->wlen);
- caplen = rlen - dag_record_size;
- }
-#endif
-#ifdef TYPE_MC_ATM
- case TYPE_MC_ATM:
- if (header->type == TYPE_MC_ATM) {
- caplen = packet_len = ATM_CELL_SIZE;
- dp+=4;
- }
-#endif
-#ifdef TYPE_MC_AAL5
- case TYPE_MC_AAL5:
- if (header->type == TYPE_MC_AAL5) {
- packet_len = ntohs(header->wlen);
- caplen = rlen - dag_record_size - 4;
- dp+=4;
- }
-#endif
- if (header->type == TYPE_ATM) {
- caplen = packet_len = ATM_CELL_SIZE;
- }
- if (p->linktype == DLT_SUNATM) {
- struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
- unsigned long rawatm;
-
- rawatm = ntohl(*((unsigned long *)dp));
- sunatm->vci = htons((rawatm >> 4) & 0xffff);
- sunatm->vpi = (rawatm >> 20) & 0x00ff;
- sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) |
- ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
- ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
- ((dp[ATM_HDR_SIZE] == 0xaa &&
- dp[ATM_HDR_SIZE+1] == 0xaa &&
- dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));
-
- } else {
- packet_len -= ATM_HDR_SIZE;
- caplen -= ATM_HDR_SIZE;
- dp += ATM_HDR_SIZE;
- }
- break;
-
-#ifdef TYPE_DSM_COLOR_ETH
- case TYPE_DSM_COLOR_ETH:
-#endif
-#ifdef TYPE_COLOR_ETH
- case TYPE_COLOR_ETH:
-#endif
- case TYPE_ETH:
- packet_len = ntohs(header->wlen);
- packet_len -= (p->md.dag_fcs_bits >> 3);
- caplen = rlen - dag_record_size - 2;
- if (caplen > packet_len) {
- caplen = packet_len;
- }
- dp += 2;
- break;
-#ifdef TYPE_DSM_COLOR_HDLC_POS
- case TYPE_DSM_COLOR_HDLC_POS:
-#endif
-#ifdef TYPE_COLOR_HDLC_POS
- case TYPE_COLOR_HDLC_POS:
-#endif
- case TYPE_HDLC_POS:
- packet_len = ntohs(header->wlen);
- packet_len -= (p->md.dag_fcs_bits >> 3);
- caplen = rlen - dag_record_size;
- if (caplen > packet_len) {
- caplen = packet_len;
- }
- break;
-#ifdef TYPE_COLOR_MC_HDLC_POS
- case TYPE_COLOR_MC_HDLC_POS:
-#endif
-#ifdef TYPE_MC_HDLC
- case TYPE_MC_HDLC:
- packet_len = ntohs(header->wlen);
- packet_len -= (p->md.dag_fcs_bits >> 3);
- caplen = rlen - dag_record_size - 4;
- if (caplen > packet_len) {
- caplen = packet_len;
- }
- /* jump the MC_HDLC_HEADER */
- dp += 4;
- if (p->linktype == DLT_MTP2_WITH_PHDR) {
- /* Add the MTP2 Pseudo Header */
- caplen += MTP2_HDR_LEN;
- packet_len += MTP2_HDR_LEN;
-
- TempPkt[MTP2_SENT_OFFSET] = 0;
- TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN;
- *(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01);
- *(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff);
- memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen);
- dp = TempPkt;
- }
- break;
-#endif
- default:
- /* Unhandled ERF type.
- * Ignore rather than generating error
- */
- continue;
- }
-
- if (caplen > p->snapshot)
- caplen = p->snapshot;
-
/* Count lost packets. */
- switch(header->type) {
-#ifdef TYPE_COLOR_HDLC_POS
- /* in this type the color value overwrites the lctr */
+ switch((header->type & 0x7f)) {
+ /* in these types the color value overwrites the lctr */
case TYPE_COLOR_HDLC_POS:
- break;
-#endif
-#ifdef TYPE_COLOR_ETH
- /* in this type the color value overwrites the lctr */
case TYPE_COLOR_ETH:
- break;
-#endif
-#ifdef TYPE_DSM_COLOR_HDLC_POS
- /* in this type the color value overwrites the lctr */
case TYPE_DSM_COLOR_HDLC_POS:
- break;
-#endif
-#ifdef TYPE_DSM_COLOR_ETH
- /* in this type the color value overwrites the lctr */
case TYPE_DSM_COLOR_ETH:
- break;
-#endif
-#ifdef TYPE_COLOR_MC_HDLC_POS
case TYPE_COLOR_MC_HDLC_POS:
+ case TYPE_COLOR_HASH_ETH:
+ case TYPE_COLOR_HASH_POS:
break;
-#endif
default:
if (header->lctr) {
@@ -429,10 +340,178 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
}
}
+
+ if ((header->type & 0x7f) == TYPE_PAD) {
+ continue;
+ }
+
+ num_ext_hdr = dag_erf_ext_header_count(dp, rlen);
+
+ /* ERF encapsulation */
+ /* The Extensible Record Format is not dropped for this kind of encapsulation,
+ * and will be handled as a pseudo header by the decoding application.
+ * The information carried in the ERF header and in the optional subheader (if present)
+ * could be merged with the libpcap information, to offer a better decoding.
+ * The packet length is
+ * o the length of the packet on the link (header->wlen),
+ * o plus the length of the ERF header (dag_record_size), as the length of the
+ * pseudo header will be adjusted during the decoding,
+ * o plus the length of the optional subheader (if present).
+ *
+ * The capture length is header.rlen and the byte stuffing for alignment will be dropped
+ * if the capture length is greater than the packet length.
+ */
+ if (p->linktype == DLT_ERF) {
+ packet_len = ntohs(header->wlen) + dag_record_size;
+ caplen = rlen;
+ switch ((header->type & 0x7f)) {
+ case TYPE_MC_AAL5:
+ case TYPE_MC_ATM:
+ case TYPE_MC_HDLC:
+ packet_len += 4; /* MC header */
+ break;
+
+ case TYPE_COLOR_HASH_ETH:
+ case TYPE_DSM_COLOR_ETH:
+ case TYPE_COLOR_ETH:
+ case TYPE_ETH:
+ packet_len += 2; /* ETH header */
+ break;
+ } /* switch type */
+
+ /* Include ERF extension headers */
+ packet_len += (8 * num_ext_hdr);
+
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ } else {
+ /* Other kind of encapsulation according to the header Type */
+
+ /* Skip over generic ERF header */
+ dp += dag_record_size;
+ /* Skip over extension headers */
+ dp += 8 * num_ext_hdr;
+
+ switch((header->type & 0x7f)) {
+ case TYPE_ATM:
+ case TYPE_AAL5:
+ if (header->type == TYPE_AAL5) {
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size;
+ }
+ case TYPE_MC_ATM:
+ if (header->type == TYPE_MC_ATM) {
+ caplen = packet_len = ATM_CELL_SIZE;
+ dp+=4;
+ }
+ case TYPE_MC_AAL5:
+ if (header->type == TYPE_MC_AAL5) {
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size - 4;
+ dp+=4;
+ }
+ if (header->type == TYPE_ATM) {
+ caplen = packet_len = ATM_CELL_SIZE;
+ }
+ if (p->linktype == DLT_SUNATM) {
+ struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
+ unsigned long rawatm;
+
+ rawatm = ntohl(*((unsigned long *)dp));
+ sunatm->vci = htons((rawatm >> 4) & 0xffff);
+ sunatm->vpi = (rawatm >> 20) & 0x00ff;
+ sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) |
+ ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
+ ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
+ ((dp[ATM_HDR_SIZE] == 0xaa &&
+ dp[ATM_HDR_SIZE+1] == 0xaa &&
+ dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));
+
+ } else {
+ packet_len -= ATM_HDR_SIZE;
+ caplen -= ATM_HDR_SIZE;
+ dp += ATM_HDR_SIZE;
+ }
+ break;
+
+ case TYPE_COLOR_HASH_ETH:
+ case TYPE_DSM_COLOR_ETH:
+ case TYPE_COLOR_ETH:
+ case TYPE_ETH:
+ packet_len = ntohs(header->wlen);
+ packet_len -= (p->md.dag_fcs_bits >> 3);
+ caplen = rlen - dag_record_size - 2;
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ dp += 2;
+ break;
+
+ case TYPE_COLOR_HASH_POS:
+ case TYPE_DSM_COLOR_HDLC_POS:
+ case TYPE_COLOR_HDLC_POS:
+ case TYPE_HDLC_POS:
+ packet_len = ntohs(header->wlen);
+ packet_len -= (p->md.dag_fcs_bits >> 3);
+ caplen = rlen - dag_record_size;
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ break;
+
+ case TYPE_COLOR_MC_HDLC_POS:
+ case TYPE_MC_HDLC:
+ packet_len = ntohs(header->wlen);
+ packet_len -= (p->md.dag_fcs_bits >> 3);
+ caplen = rlen - dag_record_size - 4;
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ /* jump the MC_HDLC_HEADER */
+ dp += 4;
+#ifdef DLT_MTP2_WITH_PHDR
+ if (p->linktype == DLT_MTP2_WITH_PHDR) {
+ /* Add the MTP2 Pseudo Header */
+ caplen += MTP2_HDR_LEN;
+ packet_len += MTP2_HDR_LEN;
+
+ TempPkt[MTP2_SENT_OFFSET] = 0;
+ TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN;
+ *(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01);
+ *(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff);
+ memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen);
+ dp = TempPkt;
+ }
+#endif
+ break;
+
+ case TYPE_IPV4:
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size;
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ break;
+
+ default:
+ /* Unhandled ERF type.
+ * Ignore rather than generating error
+ */
+ continue;
+ } /* switch type */
+
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+
+ } /* ERF encapsulation */
+
+ if (caplen > p->snapshot)
+ caplen = p->snapshot;
/* Run the packet filter if there is one. */
if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
-
+
/* convert between timestamp formats */
register unsigned long long ts;
@@ -463,7 +542,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
/* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
processed++;
- if (processed == cnt)
+ if (processed == cnt && cnt > 0)
{
/* Reached the user-specified limit. */
return cnt;
@@ -485,23 +564,24 @@ dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
/*
* Get a handle for a live capture from the given DAG device. Passing a NULL
* device will result in a failure. The promisc flag is ignored because DAG
- * cards are always promiscuous. The to_ms parameter is also ignored as it is
- * not supported in hardware.
+ * cards are always promiscuous. The to_ms parameter is used in setting the
+ * API polling parameters.
*
* snaplen is now also ignored, until we get per-stream slen support. Set
- * slen with approprite DAG tool BEFORE pcap_open_live().
+ * slen with approprite DAG tool BEFORE pcap_activate().
*
* See also pcap(3).
*/
-pcap_t *
-dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+static int dag_activate(pcap_t* handle)
{
+#if 0
char conf[30]; /* dag configure string */
- pcap_t *handle;
+#endif
char *s;
int n;
daginf_t* daginf;
char * newDev = NULL;
+ char * device = handle->opt.source;
#ifdef HAVE_DAG_STREAMS_API
uint32_t mindata;
struct timeval maxwait;
@@ -509,44 +589,35 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
#endif
if (device == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
- return NULL;
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "device is NULL: %s", pcap_strerror(errno));
+ return -1;
}
- /* Allocate a handle for this session. */
- handle = malloc(sizeof(*handle));
- if (handle == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno));
- return NULL;
- }
-
/* Initialize some components of the pcap structure. */
-
- memset(handle, 0, sizeof(*handle));
#ifdef HAVE_DAG_STREAMS_API
newDev = (char *)malloc(strlen(device) + 16);
if (newDev == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
goto fail;
}
/* Parse input name to get dag device and stream number if provided */
if (dag_parse_name(device, newDev, strlen(device) + 16, &handle->md.dag_stream) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno));
goto fail;
}
device = newDev;
if (handle->md.dag_stream%2) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n");
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n");
goto fail;
}
#else
if (strncmp(device, "/dev/", 5) != 0) {
newDev = (char *)malloc(strlen(device) + 5);
if (newDev == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno));
goto fail;
}
strcpy(newDev, "/dev/");
@@ -557,14 +628,14 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
/* setup device parameters */
if((handle->fd = dag_open((char *)device)) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_open %s: %s", device, pcap_strerror(errno));
goto fail;
}
#ifdef HAVE_DAG_STREAMS_API
/* Open requested stream. Can fail if already locked or on error */
if (dag_attach_stream(handle->fd, handle->md.dag_stream, 0, 0) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno));
goto failclose;
}
@@ -573,7 +644,7 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
*/
if (dag_get_stream_poll(handle->fd, handle->md.dag_stream,
&mindata, &maxwait, &poll) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno));
goto faildetach;
}
@@ -583,21 +654,21 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
*/
mindata = 65536;
- /* Obey to_ms if supplied. This is a good idea!
+ /* Obey md.timeout (was to_ms) if supplied. This is a good idea!
* Recommend 10-100ms. Calls will time out even if no data arrived.
*/
- maxwait.tv_sec = to_ms/1000;
- maxwait.tv_usec = (to_ms%1000) * 1000;
+ maxwait.tv_sec = handle->md.timeout/1000;
+ maxwait.tv_usec = (handle->md.timeout%1000) * 1000;
if (dag_set_stream_poll(handle->fd, handle->md.dag_stream,
mindata, &maxwait, &poll) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno));
goto faildetach;
}
#else
if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno));
goto failclose;
}
@@ -611,28 +682,28 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
/* set the card snap length to the specified snaplen parameter */
/* This is a really bad idea, as different cards have different
* valid slen ranges. Should fix in Config API. */
- if (snaplen == 0 || snaplen > MAX_DAG_SNAPLEN) {
- snaplen = MAX_DAG_SNAPLEN;
+ if (handle->snapshot == 0 || handle->snapshot > MAX_DAG_SNAPLEN) {
+ handle->snapshot = MAX_DAG_SNAPLEN;
} else if (snaplen < MIN_DAG_SNAPLEN) {
- snaplen = MIN_DAG_SNAPLEN;
+ handle->snapshot = MIN_DAG_SNAPLEN;
}
/* snap len has to be a multiple of 4 */
snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3);
if(dag_configure(handle->fd, conf) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno));
goto faildetach;
}
#endif
#ifdef HAVE_DAG_STREAMS_API
if(dag_start_stream(handle->fd, handle->md.dag_stream) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno));
goto faildetach;
}
#else
if(dag_start(handle->fd) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start %s: %s\n", device, pcap_strerror(errno));
goto failclose;
}
#endif /* HAVE_DAG_STREAMS_API */
@@ -644,40 +715,58 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
*/
handle->md.dag_mem_bottom = 0;
handle->md.dag_mem_top = 0;
- handle->md.dag_fcs_bits = 32;
- /* Query the card first for special cases. */
+ /*
+ * Find out how many FCS bits we should strip.
+ * First, query the card to see if it strips the FCS.
+ */
daginf = dag_info(handle->fd);
- if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code))
- {
+ if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code)) {
/* DAG 4.2S and 4.23S already strip the FCS. Stripping the final word again truncates the packet. */
handle->md.dag_fcs_bits = 0;
- }
- /* Then allow an environment variable to override. */
- if ((s = getenv("ERF_FCS_BITS")) != NULL) {
- if ((n = atoi(s)) == 0 || n == 16|| n == 32) {
- handle->md.dag_fcs_bits = n;
- } else {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "pcap_open_live %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n);
- goto failstop;
+ /* Note that no FCS will be supplied. */
+ handle->linktype_ext = LT_FCS_DATALINK_EXT(0);
+ } else {
+ /*
+ * Start out assuming it's 32 bits.
+ */
+ handle->md.dag_fcs_bits = 32;
+
+ /* Allow an environment variable to override. */
+ if ((s = getenv("ERF_FCS_BITS")) != NULL) {
+ if ((n = atoi(s)) == 0 || n == 16 || n == 32) {
+ handle->md.dag_fcs_bits = n;
+ } else {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n);
+ goto failstop;
+ }
+ }
+
+ /*
+ * Did the user request that they not be stripped?
+ */
+ if ((s = getenv("ERF_DONT_STRIP_FCS")) != NULL) {
+ /* Yes. Note the number of bytes that will be
+ supplied. */
+ handle->linktype_ext = LT_FCS_DATALINK_EXT(handle->md.dag_fcs_bits/16);
+
+ /* And don't strip them. */
+ handle->md.dag_fcs_bits = 0;
}
}
- handle->snapshot = snaplen;
- handle->md.dag_timeout = to_ms;
+ handle->md.dag_timeout = handle->md.timeout;
handle->linktype = -1;
- if (dag_get_datalink(handle) < 0) {
- strcpy(ebuf, handle->errbuf);
+ if (dag_get_datalink(handle) < 0)
goto failstop;
- }
handle->bufsize = 0;
if (new_pcap_dag(handle) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "new_pcap_dag %s: %s\n", device, pcap_strerror(errno));
goto failstop;
}
@@ -698,54 +787,50 @@ dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebu
handle->getnonblock_op = pcap_getnonblock_fd;
handle->setnonblock_op = dag_setnonblock;
handle->stats_op = dag_stats;
- handle->close_op = dag_platform_close;
+ handle->cleanup_op = dag_platform_cleanup;
handle->md.stat.ps_drop = 0;
handle->md.stat.ps_recv = 0;
- return handle;
+ return 0;
#ifdef HAVE_DAG_STREAMS_API
failstop:
- if (handle != NULL) {
- if (dag_stop_stream(handle->fd, handle->md.dag_stream) < 0)
- fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
+ if (dag_stop_stream(handle->fd, handle->md.dag_stream) < 0) {
+ fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
}
faildetach:
- if (handle != NULL) {
- if (dag_detach_stream(handle->fd, handle->md.dag_stream) < 0)
- fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
- }
-#else
+ if (dag_detach_stream(handle->fd, handle->md.dag_stream) < 0)
+ fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
+#else
failstop:
- if (handle != NULL) {
- if (dag_stop(p->fd) < 0)
- fprintf(stderr,"dag_stop: %s\n", strerror(errno));
- }
+ if (dag_stop(handle->fd) < 0)
+ fprintf(stderr,"dag_stop: %s\n", strerror(errno));
#endif /* HAVE_DAG_STREAMS_API */
failclose:
- if (handle != NULL) {
- if (dag_close(handle->fd) < 0)
- fprintf(stderr,"dag_close: %s\n", strerror(errno));
- }
- if (handle != NULL)
- delete_pcap_dag(handle);
-
+ if (dag_close(handle->fd) < 0)
+ fprintf(stderr,"dag_close: %s\n", strerror(errno));
+ delete_pcap_dag(handle);
+
fail:
+ pcap_cleanup_live_common(handle);
if (newDev != NULL) {
free((char *)newDev);
}
- if (handle != NULL) {
- /*
- * Get rid of any link-layer type list we allocated.
- */
- if (handle->dlt_list != NULL) {
- free(handle->dlt_list);
- }
- free(handle);
- }
- return NULL;
+ return PCAP_ERROR;
+}
+
+pcap_t *dag_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return NULL;
+
+ p->activate_op = dag_activate;
+ return p;
}
static int
@@ -762,10 +847,13 @@ dag_stats(pcap_t *p, struct pcap_stat *ps) {
}
/*
- * Simply submit all possible dag names as candidates.
- * pcap_add_if() internally tests each candidate with pcap_open_live(),
- * so any non-existent devices are dropped.
- * For 2.5 try all rx stream names as well.
+ * Previously we just generated a list of all possible names and let
+ * pcap_add_if() attempt to open each one, but with streams this adds up
+ * to 81 possibilities which is inefficient.
+ *
+ * Since we know more about the devices we can prune the tree here.
+ * pcap_add_if() will still retest each device but the total number of
+ * open attempts will still be much less than the naive approach.
*/
int
dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
@@ -773,30 +861,46 @@ dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf)
char name[12]; /* XXX - pick a size */
int ret = 0;
int c;
+ char dagname[DAGNAME_BUFSIZE];
+ int dagstream;
+ int dagfd;
/* Try all the DAGs 0-9 */
for (c = 0; c < 9; c++) {
snprintf(name, 12, "dag%d", c);
- if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
- /*
- * Failure.
- */
- ret = -1;
- }
-#ifdef HAVE_DAG_STREAMS_API
+ if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream))
{
- int stream;
- for(stream=0;stream<16;stream+=2) {
- snprintf(name, 10, "dag%d:%d", c, stream);
- if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
- /*
- * Failure.
- */
- ret = -1;
- }
- }
+ return -1;
}
+ if ( (dagfd = dag_open(dagname)) >= 0 ) {
+ if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
+ /*
+ * Failure.
+ */
+ ret = -1;
+ }
+#ifdef HAVE_DAG_STREAMS_API
+ {
+ int stream, rxstreams;
+ rxstreams = dag_rx_get_stream_count(dagfd);
+ for(stream=0;stream<16;stream+=2) {
+ if (0 == dag_attach_stream(dagfd, stream, 0, 0)) {
+ dag_detach_stream(dagfd, stream);
+
+ snprintf(name, 10, "dag%d:%d", c, stream);
+ if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) {
+ /*
+ * Failure.
+ */
+ ret = -1;
+ }
+ }
+ }
+ }
#endif /* HAVE_DAG_STREAMS_API */
+ dag_close(dagfd);
+ }
+
}
return (ret);
}
@@ -885,7 +989,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf)
static int
dag_get_datalink(pcap_t *p)
{
- int index=0;
+ int index=0, dlt_index=0;
uint8_t types[255];
memset(types, 0, 255);
@@ -897,7 +1001,16 @@ dag_get_datalink(pcap_t *p)
p->linktype = 0;
-#ifdef HAVE_DAG_GET_ERF_TYPES
+#ifdef HAVE_DAG_GET_STREAM_ERF_TYPES
+ /* Get list of possible ERF types for this card */
+ if (dag_get_stream_erf_types(p->fd, p->md.dag_stream, types, 255) < 0) {
+ snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno));
+ return (-1);
+ }
+
+ while (types[index]) {
+
+#elif defined HAVE_DAG_GET_ERF_TYPES
/* Get list of possible ERF types for this card */
if (dag_get_erf_types(p->fd, types, 255) < 0) {
snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno));
@@ -911,31 +1024,26 @@ dag_get_datalink(pcap_t *p)
{
#endif
- switch(types[index]) {
+ switch((types[index] & 0x7f)) {
case TYPE_HDLC_POS:
-#ifdef TYPE_COLOR_HDLC_POS
case TYPE_COLOR_HDLC_POS:
-#endif
-#ifdef TYPE_DSM_COLOR_HDLC_POS
case TYPE_DSM_COLOR_HDLC_POS:
-#endif
+ case TYPE_COLOR_HASH_POS:
+
if (p->dlt_list != NULL) {
- p->dlt_list[index++] = DLT_CHDLC;
- p->dlt_list[index++] = DLT_PPP_SERIAL;
- p->dlt_list[index++] = DLT_FRELAY;
+ p->dlt_list[dlt_index++] = DLT_CHDLC;
+ p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
+ p->dlt_list[dlt_index++] = DLT_FRELAY;
}
if(!p->linktype)
p->linktype = DLT_CHDLC;
break;
case TYPE_ETH:
-#ifdef TYPE_COLOR_ETH
case TYPE_COLOR_ETH:
-#endif
-#ifdef TYPE_DSM_COLOR_ETH
case TYPE_DSM_COLOR_ETH:
-#endif
+ case TYPE_COLOR_HASH_ETH:
/*
* This is (presumably) a real Ethernet capture; give it a
* link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
@@ -947,61 +1055,66 @@ dag_get_datalink(pcap_t *p)
* Ethernet framing).
*/
if (p->dlt_list != NULL) {
- p->dlt_list[index++] = DLT_EN10MB;
- p->dlt_list[index++] = DLT_DOCSIS;
+ p->dlt_list[dlt_index++] = DLT_EN10MB;
+ p->dlt_list[dlt_index++] = DLT_DOCSIS;
}
if(!p->linktype)
p->linktype = DLT_EN10MB;
break;
case TYPE_ATM:
-#ifdef TYPE_AAL5
case TYPE_AAL5:
-#endif
-#ifdef TYPE_MC_ATM
case TYPE_MC_ATM:
-#endif
-#ifdef TYPE_MC_AAL5
case TYPE_MC_AAL5:
-#endif
if (p->dlt_list != NULL) {
- p->dlt_list[index++] = DLT_ATM_RFC1483;
- p->dlt_list[index++] = DLT_SUNATM;
+ p->dlt_list[dlt_index++] = DLT_ATM_RFC1483;
+ p->dlt_list[dlt_index++] = DLT_SUNATM;
}
if(!p->linktype)
p->linktype = DLT_ATM_RFC1483;
break;
-#ifdef TYPE_COLOR_MC_HDLC_POS
case TYPE_COLOR_MC_HDLC_POS:
-#endif
-#ifdef TYPE_MC_HDLC
case TYPE_MC_HDLC:
if (p->dlt_list != NULL) {
- p->dlt_list[index++] = DLT_CHDLC;
- p->dlt_list[index++] = DLT_PPP_SERIAL;
- p->dlt_list[index++] = DLT_FRELAY;
- p->dlt_list[index++] = DLT_MTP2;
- p->dlt_list[index++] = DLT_MTP2_WITH_PHDR;
+ p->dlt_list[dlt_index++] = DLT_CHDLC;
+ p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
+ p->dlt_list[dlt_index++] = DLT_FRELAY;
+ p->dlt_list[dlt_index++] = DLT_MTP2;
+ p->dlt_list[dlt_index++] = DLT_MTP2_WITH_PHDR;
+ p->dlt_list[dlt_index++] = DLT_LAPD;
}
if(!p->linktype)
p->linktype = DLT_CHDLC;
break;
-#endif
- case TYPE_LEGACY:
+ case TYPE_IPV4:
if(!p->linktype)
- p->linktype = DLT_NULL;
+ p->linktype = DLT_RAW;
break;
+ case TYPE_LEGACY:
+ case TYPE_MC_RAW:
+ case TYPE_MC_RAW_CHANNEL:
+ case TYPE_IP_COUNTER:
+ case TYPE_TCP_FLOW_COUNTER:
+ case TYPE_INFINIBAND:
+ case TYPE_IPV6:
default:
- snprintf(p->errbuf, sizeof(p->errbuf), "unknown DAG linktype %d", types[index]);
- return (-1);
+ /* Libpcap cannot deal with these types yet */
+ /* Add no DLTs, but still covered by DLT_ERF */
+ break;
} /* switch */
+ index++;
}
- p->dlt_count = index;
+ p->dlt_list[dlt_index++] = DLT_ERF;
+
+ p->dlt_count = dlt_index;
+
+ if(!p->linktype)
+ p->linktype = DLT_ERF;
return p->linktype;
}
diff --git a/contrib/libpcap/pcap-dag.h b/contrib/libpcap/pcap-dag.h
index eff01d6..7ba272b 100644
--- a/contrib/libpcap/pcap-dag.h
+++ b/contrib/libpcap/pcap-dag.h
@@ -7,8 +7,94 @@
*
* Author: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
*
- * @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.3.4.1 2005/07/07 06:56:04 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-dag.h,v 1.4.2.3 2008-04-04 19:39:06 guy Exp $ (LBL)
*/
-pcap_t *dag_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf);
+pcap_t *dag_create(const char *, char *);
int dag_platform_finddevs(pcap_if_t **devlistp, char *errbuf);
+
+#ifndef TYPE_AAL5
+#define TYPE_AAL5 4
+#endif
+
+#ifndef TYPE_MC_HDLC
+#define TYPE_MC_HDLC 5
+#endif
+
+#ifndef TYPE_MC_RAW
+#define TYPE_MC_RAW 6
+#endif
+
+#ifndef TYPE_MC_ATM
+#define TYPE_MC_ATM 7
+#endif
+
+#ifndef TYPE_MC_RAW_CHANNEL
+#define TYPE_MC_RAW_CHANNEL 8
+#endif
+
+#ifndef TYPE_MC_AAL5
+#define TYPE_MC_AAL5 9
+#endif
+
+#ifndef TYPE_COLOR_HDLC_POS
+#define TYPE_COLOR_HDLC_POS 10
+#endif
+
+#ifndef TYPE_COLOR_ETH
+#define TYPE_COLOR_ETH 11
+#endif
+
+#ifndef TYPE_MC_AAL2
+#define TYPE_MC_AAL2 12
+#endif
+
+#ifndef TYPE_IP_COUNTER
+#define TYPE_IP_COUNTER 13
+#endif
+
+#ifndef TYPE_TCP_FLOW_COUNTER
+#define TYPE_TCP_FLOW_COUNTER 14
+#endif
+
+#ifndef TYPE_DSM_COLOR_HDLC_POS
+#define TYPE_DSM_COLOR_HDLC_POS 15
+#endif
+
+#ifndef TYPE_DSM_COLOR_ETH
+#define TYPE_DSM_COLOR_ETH 16
+#endif
+
+#ifndef TYPE_COLOR_MC_HDLC_POS
+#define TYPE_COLOR_MC_HDLC_POS 17
+#endif
+
+#ifndef TYPE_AAL2
+#define TYPE_AAL2 18
+#endif
+
+#ifndef TYPE_COLOR_HASH_POS
+#define TYPE_COLOR_HASH_POS 19
+#endif
+
+#ifndef TYPE_COLOR_HASH_ETH
+#define TYPE_COLOR_HASH_ETH 20
+#endif
+
+#ifndef TYPE_INFINIBAND
+#define TYPE_INFINIBAND 21
+#endif
+
+#ifndef TYPE_IPV4
+#define TYPE_IPV4 22
+#endif
+
+#ifndef TYPE_IPV6
+#define TYPE_IPV6 23
+#endif
+
+
+
+#ifndef TYPE_PAD
+#define TYPE_PAD 48
+#endif
diff --git a/contrib/libpcap/pcap-dlpi.c b/contrib/libpcap/pcap-dlpi.c
index 8ea7850..695e48a 100644
--- a/contrib/libpcap/pcap-dlpi.c
+++ b/contrib/libpcap/pcap-dlpi.c
@@ -22,7 +22,7 @@
* University College London, and subsequently modified by
* Guy Harris (guy@alum.mit.edu), Mark Pizzolato
* <List-tcpdump-workers@subscriptions.pizzolato.net>,
- * and Mark C. Brown (mbrown@hp.com).
+ * Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
*/
/*
@@ -70,7 +70,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.108.2.7 2006/04/04 05:33:02 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.116.2.11 2008-04-14 20:41:51 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -121,6 +121,7 @@ static const char rcsid[] _U_ =
#endif
#include "pcap-int.h"
+#include "dlpisubs.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
@@ -136,33 +137,6 @@ static const char rcsid[] _U_ =
#define MAXDLBUF 8192
-#ifdef HAVE_SYS_BUFMOD_H
-
-/*
- * Size of a bufmod chunk to pass upstream; that appears to be the biggest
- * value to which you can set it, and setting it to that value (which
- * is bigger than what appears to be the Solaris default of 8192)
- * reduces the number of packet drops.
- */
-#define CHUNKSIZE 65536
-
-/*
- * Size of the buffer to allocate for packet data we read; it must be
- * large enough to hold a chunk.
- */
-#define PKTBUFSIZE CHUNKSIZE
-
-#else /* HAVE_SYS_BUFMOD_H */
-
-/*
- * Size of the buffer to allocate for packet data we read; this is
- * what the value used to be - there's no particular reason why it
- * should be tied to MAXDLBUF, but we'll leave it as this for now.
- */
-#define PKTBUFSIZE (MAXDLBUF * sizeof(bpf_u_int32))
-
-#endif
-
/* Forwards */
static char *split_dname(char *, int *, char *);
static int dl_doattach(int, int, char *);
@@ -176,6 +150,11 @@ static int dlpromisconreq(int, bpf_u_int32, char *);
static int dlokack(int, const char *, char *, char *);
static int dlinforeq(int, char *);
static int dlinfoack(int, char *, char *);
+
+#ifdef HAVE_DLPI_PASSIVE
+static void dlpassive(int, char *);
+#endif
+
#ifdef DL_HP_RAWDLS
static int dlrawdatareq(int, const u_char *, int);
#endif
@@ -186,9 +165,6 @@ static char *dlprim(bpf_u_int32);
static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *);
#endif
static int send_request(int, char *, int, char *, char *);
-#ifdef HAVE_SYS_BUFMOD_H
-static int strioctl(int, int, int, char *);
-#endif
#ifdef HAVE_HPUX9
static int dlpi_kread(int, off_t, void *, u_int, char *);
#endif
@@ -196,42 +172,6 @@ static int dlpi_kread(int, off_t, void *, u_int, char *);
static int get_dlpi_ppa(int, const char *, int, char *);
#endif
-static int
-pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
-{
-
- /*
- * "ps_recv" counts packets handed to the filter, not packets
- * that passed the filter. As filtering is done in userland,
- * this would not include packets dropped because we ran out
- * of buffer space; in order to make this more like other
- * platforms (Linux 2.4 and later, BSDs with BPF), where the
- * "packets received" count includes packets received but dropped
- * due to running out of buffer space, and to keep from confusing
- * applications that, for example, compute packet drop percentages,
- * we also make it count packets dropped by "bufmod" (otherwise we
- * might run the risk of the packet drop count being bigger than
- * the received-packet count).
- *
- * "ps_drop" counts packets dropped by "bufmod" because of
- * flow control requirements or resource exhaustion; it doesn't
- * count packets dropped by the interface driver, or packets
- * dropped upstream. As filtering is done in userland, it counts
- * packets regardless of whether they would've passed the filter.
- *
- * These statistics don't include packets not yet read from
- * the kernel by libpcap, but they may include packets not
- * yet read from libpcap by the application.
- */
- *ps = p->md.stat;
-
- /*
- * Add in the drop count, as per the above comment.
- */
- ps->ps_recv += ps->ps_drop;
- return (0);
-}
-
/* XXX Needed by HP-UX (at least) */
static bpf_u_int32 ctlbuf[MAXDLBUF];
static struct strbuf ctl = {
@@ -243,18 +183,10 @@ static struct strbuf ctl = {
static int
pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
- register int cc, n, caplen, origlen;
- register u_char *bp, *ep, *pk;
- register struct bpf_insn *fcode;
-#ifdef HAVE_SYS_BUFMOD_H
- register struct sb_hdr *sbp;
-#ifdef LBL_ALIGN
- struct sb_hdr sbhdr;
-#endif
-#endif
+ int cc;
+ u_char *bp;
int flags;
struct strbuf data;
- struct pcap_pkthdr pkthdr;
flags = 0;
cc = p->cc;
@@ -302,74 +234,7 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
} else
bp = p->bp;
- /* Loop through packets */
- fcode = p->fcode.bf_insns;
- ep = bp + cc;
- n = 0;
-#ifdef HAVE_SYS_BUFMOD_H
- while (bp < ep) {
- /*
- * Has "pcap_breakloop()" been called?
- * If so, return immediately - if we haven't read any
- * packets, clear the flag and return -2 to indicate
- * that we were told to break out of the loop, otherwise
- * leave the flag set, so that the *next* call will break
- * out of the loop without having read any packets, and
- * return the number of packets we've processed so far.
- */
- if (p->break_loop) {
- if (n == 0) {
- p->break_loop = 0;
- return (-2);
- } else {
- p->bp = bp;
- p->cc = ep - bp;
- return (n);
- }
- }
-#ifdef LBL_ALIGN
- if ((long)bp & 3) {
- sbp = &sbhdr;
- memcpy(sbp, bp, sizeof(*sbp));
- } else
-#endif
- sbp = (struct sb_hdr *)bp;
- p->md.stat.ps_drop = sbp->sbh_drops;
- pk = bp + sizeof(*sbp);
- bp += sbp->sbh_totlen;
- origlen = sbp->sbh_origlen;
- caplen = sbp->sbh_msglen;
-#else
- origlen = cc;
- caplen = min(p->snapshot, cc);
- pk = bp;
- bp += caplen;
-#endif
- ++p->md.stat.ps_recv;
- if (bpf_filter(fcode, pk, origlen, caplen)) {
-#ifdef HAVE_SYS_BUFMOD_H
- pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
- pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;
-#else
- (void)gettimeofday(&pkthdr.ts, NULL);
-#endif
- pkthdr.len = origlen;
- pkthdr.caplen = caplen;
- /* Insure caplen does not exceed snapshot */
- if (pkthdr.caplen > p->snapshot)
- pkthdr.caplen = p->snapshot;
- (*callback)(user, &pkthdr, pk);
- if (++n >= cnt && cnt >= 0) {
- p->cc = ep - bp;
- p->bp = bp;
- return (n);
- }
- }
-#ifdef HAVE_SYS_BUFMOD_H
- }
-#endif
- p->cc = 0;
- return (n);
+ return (pcap_process_pkts(p, callback, user, cnt, bp, cc));
}
static int
@@ -449,26 +314,26 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
#endif /* HAVE_SOLARIS */
static void
-pcap_close_dlpi(pcap_t *p)
+pcap_cleanup_dlpi(pcap_t *p)
{
- pcap_close_common(p);
- if (p->send_fd >= 0)
+ if (p->send_fd >= 0) {
close(p->send_fd);
+ p->send_fd = -1;
+ }
+ pcap_cleanup_live_common(p);
}
-pcap_t *
-pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
- char *ebuf)
+static int
+pcap_activate_dlpi(pcap_t *p)
{
register char *cp;
- register pcap_t *p;
int ppa;
#ifdef HAVE_SOLARIS
int isatm = 0;
#endif
register dl_info_ack_t *infop;
#ifdef HAVE_SYS_BUFMOD_H
- bpf_u_int32 ss, chunksize;
+ bpf_u_int32 ss;
#ifdef HAVE_SOLARIS
register char *release;
bpf_u_int32 osmajor, osminor, osmicro;
@@ -479,23 +344,15 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#ifndef HAVE_DEV_DLPI
char dname2[100];
#endif
-
- p = (pcap_t *)malloc(sizeof(*p));
- if (p == NULL) {
- strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
- return (NULL);
- }
- memset(p, 0, sizeof(*p));
- p->fd = -1; /* indicate that it hasn't been opened yet */
- p->send_fd = -1;
+ int status = PCAP_ERROR;
#ifdef HAVE_DEV_DLPI
/*
** Remove any "/dev/" on the front of the device.
*/
- cp = strrchr(device, '/');
+ cp = strrchr(p->opt.source, '/');
if (cp == NULL)
- strlcpy(dname, device, sizeof(dname));
+ strlcpy(dname, p->opt.source, sizeof(dname));
else
strlcpy(dname, cp + 1, sizeof(dname));
@@ -503,9 +360,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* Split the device name into a device type name and a unit number;
* chop off the unit number, so "dname" is just a device type name.
*/
- cp = split_dname(dname, &ppa, ebuf);
- if (cp == NULL)
+ cp = split_dname(dname, &ppa, p->errbuf);
+ if (cp == NULL) {
+ status = PCAP_ERROR_NO_SUCH_DEVICE;
goto bad;
+ }
*cp = '\0';
/*
@@ -521,7 +380,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
*/
cp = "/dev/dlpi";
if ((p->fd = open(cp, O_RDWR)) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ if (errno == EPERM || errno == EACCES)
+ status = PCAP_ERROR_PERM_DENIED;
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"%s: %s", cp, pcap_strerror(errno));
goto bad;
}
@@ -545,9 +406,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* Get a table of all PPAs for that device, and search that
* table for the specified device type name and unit number.
*/
- ppa = get_dlpi_ppa(p->fd, dname, ppa, ebuf);
- if (ppa < 0)
+ ppa = get_dlpi_ppa(p->fd, dname, ppa, p->errbuf);
+ if (ppa < 0) {
+ status = ppa;
goto bad;
+ }
#else
/*
* If the device name begins with "/", assume it begins with
@@ -555,19 +418,21 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* otherwise, concatenate the device directory name and the
* device name.
*/
- if (*device == '/')
- strlcpy(dname, device, sizeof(dname));
+ if (*p->opt.source == '/')
+ strlcpy(dname, p->opt.source, sizeof(dname));
else
snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
- device);
+ p->opt.source);
/*
* Get the unit number, and a pointer to the end of the device
* type name.
*/
- cp = split_dname(dname, &ppa, ebuf);
- if (cp == NULL)
+ cp = split_dname(dname, &ppa, p->errbuf);
+ if (cp == NULL) {
+ status = PCAP_ERROR_NO_SUCH_DEVICE;
goto bad;
+ }
/*
* Make a copy of the device pathname, and then remove the unit
@@ -579,7 +444,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
/* Try device without unit number */
if ((p->fd = open(dname, O_RDWR)) < 0) {
if (errno != ENOENT) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,
+ if (errno == EACCES)
+ status = PCAP_ERROR_PERM_DENIED;
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dname,
pcap_strerror(errno));
goto bad;
}
@@ -587,10 +454,18 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
/* Try again with unit number */
if ((p->fd = open(dname2, O_RDWR)) < 0) {
if (errno == ENOENT) {
+ status = PCAP_ERROR_NO_SUCH_DEVICE;
+
/*
- * We just report "No DLPI device found"
- * with the device name, so people don't
- * get confused and think, for example,
+ * We provide an error message even
+ * for this error, for diagnostic
+ * purposes (so that, for example,
+ * the app can show the message if the
+ * user requests it).
+ *
+ * In it, we just report "No DLPI device
+ * found" with the device name, so people
+ * don't get confused and think, for example,
* that if they can't capture on "lo0"
* on Solaris the fix is to change libpcap
* (or the application that uses it) to
@@ -602,10 +477,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* for the loopback interface is just a
* symptom of that inability.
*/
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "%s: No DLPI device found", device);
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: No DLPI device found", p->opt.source);
} else {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s",
+ if (errno == EACCES)
+ status = PCAP_ERROR_PERM_DENIED;
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
dname2, pcap_strerror(errno));
}
goto bad;
@@ -615,13 +492,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
}
#endif
- p->snapshot = snaplen;
-
/*
** Attach if "style 2" provider
*/
- if (dlinforeq(p->fd, ebuf) < 0 ||
- dlinfoack(p->fd, (char *)buf, ebuf) < 0)
+ if (dlinforeq(p->fd, p->errbuf) < 0 ||
+ dlinfoack(p->fd, (char *)buf, p->errbuf) < 0)
goto bad;
infop = &((union DL_primitives *)buf)->info_ack;
#ifdef HAVE_SOLARIS
@@ -629,16 +504,33 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
isatm = 1;
#endif
if (infop->dl_provider_style == DL_STYLE2) {
- if (dl_doattach(p->fd, ppa, ebuf) < 0)
+ status = dl_doattach(p->fd, ppa, p->errbuf);
+ if (status < 0)
goto bad;
#ifdef DL_HP_RAWDLS
if (p->send_fd >= 0) {
- if (dl_doattach(p->send_fd, ppa, ebuf) < 0)
+ if (dl_doattach(p->send_fd, ppa, p->errbuf) < 0)
goto bad;
}
#endif
}
+ if (p->opt.rfmon) {
+ /*
+ * This device exists, but we don't support monitor mode
+ * any platforms that support DLPI.
+ */
+ status = PCAP_ERROR_RFMON_NOTSUP;
+ goto bad;
+ }
+
+#ifdef HAVE_DLPI_PASSIVE
+ /*
+ * Enable Passive mode to be able to capture on aggregated link.
+ * Not supported in all Solaris versions.
+ */
+ dlpassive(p->fd, p->errbuf);
+#endif
/*
** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally
** skip if using SINIX)
@@ -663,15 +555,15 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
** assume the SAP value in a DLPI bind is an LLC SAP for network
** types that use 802.2 LLC).
*/
- if ((dlbindreq(p->fd, 1537, ebuf) < 0 &&
- dlbindreq(p->fd, 2, ebuf) < 0) ||
- dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0)
+ if ((dlbindreq(p->fd, 1537, p->errbuf) < 0 &&
+ dlbindreq(p->fd, 2, p->errbuf) < 0) ||
+ dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0)
goto bad;
#elif defined(DL_HP_RAWDLS)
/*
** HP-UX 10.0x and 10.1x.
*/
- if (dl_dohpuxbind(p->fd, ebuf) < 0)
+ if (dl_dohpuxbind(p->fd, p->errbuf) < 0)
goto bad;
if (p->send_fd >= 0) {
/*
@@ -679,7 +571,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
** set it to -1, so that you can't send but can
** still receive?
*/
- if (dl_dohpuxbind(p->send_fd, ebuf) < 0)
+ if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0)
goto bad;
}
#else /* neither AIX nor HP-UX */
@@ -687,8 +579,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other
** OS using DLPI.
**/
- if (dlbindreq(p->fd, 0, ebuf) < 0 ||
- dlbindack(p->fd, (char *)buf, ebuf, NULL) < 0)
+ if (dlbindreq(p->fd, 0, p->errbuf) < 0 ||
+ dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0)
goto bad;
#endif /* AIX vs. HP-UX vs. other */
#endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */
@@ -702,18 +594,18 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
** help, and may break things.
*/
if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "A_PROMISCON_REQ: %s",
- pcap_strerror(errno));
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "A_PROMISCON_REQ: %s", pcap_strerror(errno));
goto bad;
}
} else
#endif
- if (promisc) {
+ if (p->opt.promisc) {
/*
** Enable promiscuous (not necessary on send FD)
*/
- if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 ||
- dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0)
+ if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, p->errbuf) < 0 ||
+ dlokack(p->fd, "promisc_phys", (char *)buf, p->errbuf) < 0)
goto bad;
/*
@@ -722,10 +614,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
** HP-UX or SINIX) (Not necessary on send FD)
*/
#if !defined(__hpux) && !defined(sinix)
- if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 ||
- dlokack(p->fd, "promisc_multi", (char *)buf, ebuf) < 0)
- fprintf(stderr,
- "WARNING: DL_PROMISC_MULTI failed (%s)\n", ebuf);
+ if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, p->errbuf) < 0 ||
+ dlokack(p->fd, "promisc_multi", (char *)buf, p->errbuf) < 0)
+ status = PCAP_WARNING;
#endif
}
/*
@@ -736,17 +627,16 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#ifndef sinix
if (
#ifdef __hpux
- !promisc &&
+ !p->opt.promisc &&
#endif
#ifdef HAVE_SOLARIS
!isatm &&
#endif
- (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 ||
- dlokack(p->fd, "promisc_sap", (char *)buf, ebuf) < 0)) {
+ (dlpromisconreq(p->fd, DL_PROMISC_SAP, p->errbuf) < 0 ||
+ dlokack(p->fd, "promisc_sap", (char *)buf, p->errbuf) < 0)) {
/* Not fatal if promisc since the DL_PROMISC_PHYS worked */
- if (promisc)
- fprintf(stderr,
- "WARNING: DL_PROMISC_SAP failed (%s)\n", ebuf);
+ if (p->opt.promisc)
+ status = PCAP_WARNING;
else
goto bad;
}
@@ -757,7 +647,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
** promiscuous options.
*/
#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER)
- if (dl_dohpuxbind(p->fd, ebuf) < 0)
+ if (dl_dohpuxbind(p->fd, p->errbuf) < 0)
goto bad;
/*
** We don't set promiscuous mode on the send FD, but we'll defer
@@ -770,7 +660,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
** set it to -1, so that you can't send but can
** still receive?
*/
- if (dl_dohpuxbind(p->send_fd, ebuf) < 0)
+ if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0)
goto bad;
}
#endif
@@ -780,63 +670,13 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
** XXX - get SAP length and address length as well, for use
** when sending packets.
*/
- if (dlinforeq(p->fd, ebuf) < 0 ||
- dlinfoack(p->fd, (char *)buf, ebuf) < 0)
+ if (dlinforeq(p->fd, p->errbuf) < 0 ||
+ dlinfoack(p->fd, (char *)buf, p->errbuf) < 0)
goto bad;
infop = &((union DL_primitives *)buf)->info_ack;
- switch (infop->dl_mac_type) {
-
- case DL_CSMACD:
- case DL_ETHER:
- p->linktype = DLT_EN10MB;
- p->offset = 2;
- /*
- * This is (presumably) a real Ethernet capture; give it a
- * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
- * that an application can let you choose it, in case you're
- * capturing DOCSIS traffic that a Cisco Cable Modem
- * Termination System is putting out onto an Ethernet (it
- * doesn't put an Ethernet header onto the wire, it puts raw
- * DOCSIS frames out on the wire inside the low-level
- * Ethernet framing).
- */
- p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
- /*
- * If that fails, just leave the list empty.
- */
- if (p->dlt_list != NULL) {
- p->dlt_list[0] = DLT_EN10MB;
- p->dlt_list[1] = DLT_DOCSIS;
- p->dlt_count = 2;
- }
- break;
-
- case DL_FDDI:
- p->linktype = DLT_FDDI;
- p->offset = 3;
- break;
-
- case DL_TPR:
- /*
- * XXX - what about DL_TPB? Is that Token Bus?
- */
- p->linktype = DLT_IEEE802;
- p->offset = 2;
- break;
-
-#ifdef HAVE_SOLARIS
- case DL_IPATM:
- p->linktype = DLT_SUNATM;
- p->offset = 0; /* works for LANE and LLC encapsulation */
- break;
-#endif
-
- default:
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mac type %lu",
- (unsigned long)infop->dl_mac_type);
+ if (pcap_process_mactype(p, infop->dl_mac_type) != 0)
goto bad;
- }
#ifdef DLIOCRAW
/*
@@ -844,93 +684,56 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
** header.
*/
if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s",
pcap_strerror(errno));
goto bad;
}
#endif
-#ifdef HAVE_SYS_BUFMOD_H
- /*
- ** Another non standard call to get the data nicely buffered
- */
- if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_PUSH bufmod: %s",
- pcap_strerror(errno));
- goto bad;
- }
+ ss = p->snapshot;
/*
- ** Now that the bufmod is pushed lets configure it.
- **
** There is a bug in bufmod(7). When dealing with messages of
** less than snaplen size it strips data from the beginning not
** the end.
**
- ** This bug is supposed to be fixed in 5.3.2. Also, there is a
- ** patch available. Ask for bugid 1149065.
+ ** This bug is fixed in 5.3.2. Also, there is a patch available.
+ ** Ask for bugid 1149065.
*/
- ss = snaplen;
#ifdef HAVE_SOLARIS
release = get_release(&osmajor, &osminor, &osmicro);
if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
getenv("BUFMOD_FIXED") == NULL) {
- fprintf(stderr,
- "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.",
release);
ss = 0;
+ status = PCAP_WARNING;
}
#endif
- if (ss > 0 &&
- strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSSNAP: %s",
- pcap_strerror(errno));
- goto bad;
- }
-
- /*
- ** Set up the bufmod timeout
- */
- if (to_ms != 0) {
- struct timeval to;
- to.tv_sec = to_ms / 1000;
- to.tv_usec = (to_ms * 1000) % 1000000;
- if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSTIME: %s",
- pcap_strerror(errno));
- goto bad;
- }
- }
-
- /*
- ** Set the chunk length.
- */
- chunksize = CHUNKSIZE;
- if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize)
- != 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSCHUNKP: %s",
- pcap_strerror(errno));
+#ifdef HAVE_SYS_BUFMOD_H
+ /* Push and configure bufmod. */
+ if (pcap_conf_bufmod(p, ss, p->md.timeout) != 0)
goto bad;
- }
#endif
/*
** As the last operation flush the read side.
*/
if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
pcap_strerror(errno));
goto bad;
}
- /* Allocate data buffer */
- p->bufsize = PKTBUFSIZE;
- p->buffer = (u_char *)malloc(p->bufsize + p->offset);
- if (p->buffer == NULL) {
- strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
+ /* Allocate data buffer. */
+ if (pcap_alloc_databuf(p) != 0)
goto bad;
- }
+
+ /* Success - but perhaps with a warning */
+ if (status < 0)
+ status = 0;
/*
* "p->fd" is an FD for a STREAMS device, so "select()" and
@@ -946,21 +749,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
p->stats_op = pcap_stats_dlpi;
- p->close_op = pcap_close_dlpi;
+ p->cleanup_op = pcap_cleanup_dlpi;
- return (p);
+ return (status);
bad:
- if (p->fd >= 0)
- close(p->fd);
- if (p->send_fd >= 0)
- close(p->send_fd);
- /*
- * Get rid of any link-layer type list we allocated.
- */
- if (p->dlt_list != NULL)
- free(p->dlt_list);
- free(p);
- return (NULL);
+ pcap_cleanup_dlpi(p);
+ return (status);
}
/*
@@ -1016,10 +810,13 @@ static int
dl_doattach(int fd, int ppa, char *ebuf)
{
bpf_u_int32 buf[MAXDLBUF];
+ int err;
- if (dlattachreq(fd, ppa, ebuf) < 0 ||
- dlokack(fd, "attach", (char *)buf, ebuf) < 0)
- return (-1);
+ if (dlattachreq(fd, ppa, ebuf) < 0)
+ return (PCAP_ERROR);
+ err = dlokack(fd, "attach", (char *)buf, ebuf);
+ if (err < 0)
+ return (err);
return (0);
}
@@ -1159,7 +956,7 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror
if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s",
what, pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
dlp = (union DL_primitives *) ctl.buf;
@@ -1183,27 +980,33 @@ recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: UNIX error - %s",
what, pcap_strerror(dlp->error_ack.dl_unix_errno));
+ if (dlp->error_ack.dl_unix_errno == EACCES)
+ return (PCAP_ERROR_PERM_DENIED);
break;
default:
snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s",
what, dlstrerror(dlp->error_ack.dl_errno));
+ if (dlp->error_ack.dl_errno == DL_BADPPA)
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+ else if (dlp->error_ack.dl_errno == DL_ACCESS)
+ return (PCAP_ERROR_PERM_DENIED);
break;
}
- return (-1);
+ return (PCAP_ERROR);
default:
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: Unexpected primitive ack %s",
what, dlprim(dlp->dl_primitive));
- return (-1);
+ return (PCAP_ERROR);
}
if (ctl.len < size) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"recv_ack: %s: Ack too small (%d < %d)",
what, ctl.len, size);
- return (-1);
+ return (PCAP_ERROR);
}
return (ctl.len);
}
@@ -1486,6 +1289,24 @@ dlinfoack(int fd, char *bufp, char *ebuf)
return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL));
}
+#ifdef HAVE_DLPI_PASSIVE
+/*
+ * Enable DLPI passive mode. We do not care if this request fails, as this
+ * indicates the underlying DLPI device does not support link aggregation.
+ */
+static void
+dlpassive(int fd, char *ebuf)
+{
+ dl_passive_req_t req;
+ bpf_u_int32 buf[MAXDLBUF];
+
+ req.dl_primitive = DL_PASSIVE_REQ;
+
+ if (send_request(fd, (char *)&req, sizeof(req), "dlpassive", ebuf) == 0)
+ (void) dlokack(fd, "dlpassive", (char *)buf, ebuf);
+}
+#endif
+
#ifdef DL_HP_RAWDLS
/*
* There's an ack *if* there's an error.
@@ -1522,26 +1343,6 @@ dlrawdatareq(int fd, const u_char *datap, int datalen)
}
#endif /* DL_HP_RAWDLS */
-#ifdef HAVE_SYS_BUFMOD_H
-static int
-strioctl(int fd, int cmd, int len, char *dp)
-{
- struct strioctl str;
- int rc;
-
- str.ic_cmd = cmd;
- str.ic_timout = -1;
- str.ic_len = len;
- str.ic_dp = dp;
- rc = ioctl(fd, I_STR, &str);
-
- if (rc < 0)
- return (rc);
- else
- return (str.ic_len);
-}
-#endif
-
#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
static char *
get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp)
@@ -1631,7 +1432,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
memset((char *)buf, 0, sizeof(buf));
if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0)
- return (-1);
+ return (PCAP_ERROR);
ctl.maxlen = DL_HP_PPA_ACK_SIZE;
ctl.len = 0;
@@ -1654,7 +1455,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
dlp = (dl_hp_ppa_ack_t *)ctl.buf;
@@ -1662,21 +1463,21 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa unexpected primitive ack 0x%x",
(bpf_u_int32)dlp->dl_primitive);
- return (-1);
+ return (PCAP_ERROR);
}
if (ctl.len < DL_HP_PPA_ACK_SIZE) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa ack too small (%d < %lu)",
ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE);
- return (-1);
+ return (PCAP_ERROR);
}
/* allocate buffer */
if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
ctl.maxlen = dlp->dl_length;
ctl.len = 0;
@@ -1686,14 +1487,14 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno));
free(ppa_data_buf);
- return (-1);
+ return (PCAP_ERROR);
}
if (ctl.len < dlp->dl_length) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"get_dlpi_ppa: hpppa ack too small (%d < %d)",
ctl.len, dlp->dl_length);
free(ppa_data_buf);
- return (-1);
+ return (PCAP_ERROR);
}
ap = (dl_hp_ppa_ack_t *)buf;
@@ -1750,7 +1551,7 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
if (stat(dname, &statbuf) < 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s",
dname, pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
majdev = major(statbuf.st_rdev);
@@ -1767,13 +1568,13 @@ get_dlpi_ppa(register int fd, register const char *device, register int unit,
if (i == ap->dl_count) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"can't find /dev/dlpi PPA for %s%d", device, unit);
- return (-1);
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
}
if (ip->dl_hdw_state == HDW_DEAD) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"%s%d: hardware state: DOWN\n", device, unit);
free(ppa_data_buf);
- return (-1);
+ return (PCAP_ERROR);
}
ppa = ip->dl_ppa;
free(ppa_data_buf);
@@ -1871,3 +1672,18 @@ dlpi_kread(register int fd, register off_t addr,
return (cc);
}
#endif
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->send_fd = -1; /* it hasn't been opened yet */
+
+ p->activate_op = pcap_activate_dlpi;
+ return (p);
+}
diff --git a/contrib/libpcap/pcap-dos.c b/contrib/libpcap/pcap-dos.c
index 0700d6b..7b3c4bd 100644
--- a/contrib/libpcap/pcap-dos.c
+++ b/contrib/libpcap/pcap-dos.c
@@ -1,11 +1,11 @@
/*
* This file is part of DOS-libpcap
- * Ported to DOS/DOSX by G. Vanem <giva@bgnett.no>
+ * Ported to DOS/DOSX by G. Vanem <gvanem@broadpark.no>
*
* pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
* network drivers.
*
- * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1.2.1 2005/05/03 18:54:35 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.2.2.5 2008-04-22 17:16:49 guy Exp $ (LBL)
*/
#include <stdio.h>
@@ -97,9 +97,10 @@ static volatile BOOL exc_occured = 0;
static struct device *handle_to_device [20];
+static int pcap_activate_dos (pcap_t *p);
static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback,
u_char *data);
-static void pcap_close_dos (pcap_t *p);
+static void pcap_cleanup_dos (pcap_t *p);
static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps);
static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len);
static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp);
@@ -142,59 +143,64 @@ static struct device *get_device (int fd)
return handle_to_device [fd-1];
}
+pcap_t *pcap_create (const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_dos;
+ return (p);
+}
+
/*
* Open MAC-driver with name 'device_name' for live capture of
* network packets.
*/
-pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc,
- int timeout_ms, char *errbuf)
+static int pcap_activate_dos (pcap_t *pcap)
{
- struct pcap *pcap;
-
- if (snaplen < ETH_MIN)
- snaplen = ETH_MIN;
+ if (pcap->opt.rfmon) {
+ /*
+ * No monitor mode on DOS.
+ */
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
- if (snaplen > ETH_MAX) /* silently accept and truncate large MTUs */
- snaplen = ETH_MAX;
+ if (pcap->snapshot < ETH_MIN+8)
+ pcap->snapshot = ETH_MIN+8;
- pcap = calloc (sizeof(*pcap), 1);
- if (!pcap)
- {
- strcpy (errbuf, "Not enough memory (pcap)");
- return (NULL);
- }
+ if (pcap->snapshot > ETH_MAX) /* silently accept and truncate large MTUs */
+ pcap->snapshot = ETH_MAX;
- pcap->snapshot = max (ETH_MIN+8, snaplen);
pcap->linktype = DLT_EN10MB; /* !! */
- pcap->inter_packet_wait = timeout_ms;
- pcap->close_op = pcap_close_dos;
+ pcap->cleanup_op = pcap_cleanup_dos;
pcap->read_op = pcap_read_dos;
pcap->stats_op = pcap_stats_dos;
pcap->inject_op = pcap_sendpacket_dos;
pcap->setfilter_op = pcap_setfilter_dos;
- pcap->setdirection_op = NULL; /* Not implemented.*/
+ pcap->setdirection_op = NULL; /* Not implemented.*/
pcap->fd = ++ref_count;
if (pcap->fd == 1) /* first time we're called */
{
- if (!init_watt32(pcap, device_name, errbuf) ||
- !first_init(device_name, errbuf, promisc))
+ if (!init_watt32(pcap, pcap->opt.source, pcap->errbuf) ||
+ !first_init(pcap->opt.source, pcap->errbuf, pcap->opt.promisc))
{
- free (pcap);
- return (NULL);
+ return (PCAP_ERROR);
}
atexit (close_driver);
}
- else if (stricmp(active_dev->name,device_name))
+ else if (stricmp(active_dev->name,pcap->opt.source))
{
- snprintf (errbuf, PCAP_ERRBUF_SIZE,
+ snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
"Cannot use different devices simultaneously "
- "(`%s' vs. `%s')", active_dev->name, device_name);
- free (pcap);
- pcap = NULL;
+ "(`%s' vs. `%s')", active_dev->name, pcap->opt.source);
+ return (PCAP_ERROR);
}
handle_to_device [pcap->fd-1] = active_dev;
- return (pcap);
+ return (0);
}
/*
@@ -205,15 +211,14 @@ static int
pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
{
struct pcap_pkthdr pcap;
- struct bpf_insn *fcode = p->fcode.bf_insns;
struct timeval now, expiry;
BYTE *rx_buf;
int rx_len = 0;
- if (p->inter_packet_wait > 0)
+ if (p->md.timeout > 0)
{
gettimeofday2 (&now, NULL);
- expiry.tv_usec = now.tv_usec + 1000UL * p->inter_packet_wait;
+ expiry.tv_usec = now.tv_usec + 1000UL * p->md.timeout;
expiry.tv_sec = now.tv_sec;
while (expiry.tv_usec >= 1000000L)
{
@@ -258,7 +263,7 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
pcap.len = rx_len;
if (callback &&
- (!fcode || bpf_filter(fcode, rx_buf, pcap.len, pcap.caplen)))
+ (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, rx_buf, pcap.len, pcap.caplen)))
{
filter_count++;
@@ -285,7 +290,7 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
/* If not to wait for a packet or pcap_close() called from
* e.g. SIGINT handler, exit loop now.
*/
- if (p->inter_packet_wait <= 0 || (volatile int)p->fd <= 0)
+ if (p->md.timeout <= 0 || (volatile int)p->fd <= 0)
break;
gettimeofday2 (&now, NULL);
@@ -421,7 +426,7 @@ u_long pcap_filter_packets (void)
/*
* Close pcap device. Not called for offline captures.
*/
-static void pcap_close_dos (pcap_t *p)
+static void pcap_cleanup_dos (pcap_t *p)
{
if (p && !exc_occured)
{
@@ -477,7 +482,7 @@ int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
{
if (!_watt_is_init)
{
- strcpy (errbuf, "pcap_open_offline() or pcap_open_live() must be "
+ strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be "
"called first");
return (-1);
}
@@ -588,7 +593,7 @@ void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
if (p)
{
p->wait_proc = yield;
- p->inter_packet_wait = wait;
+ p->md.timeout = wait;
}
}
@@ -734,13 +739,13 @@ static void exc_handler (int sig)
fprintf (stderr, "Catching signal %d.\n", sig);
}
exc_occured = 1;
- pcap_close_dos (NULL);
+ pcap_cleanup_dos (NULL);
}
#endif /* __DJGPP__ */
/*
- * Open the pcap device for the first client calling pcap_open_live()
+ * Open the pcap device for the first client calling pcap_activate()
*/
static int first_init (const char *name, char *ebuf, int promisc)
{
@@ -991,7 +996,7 @@ int EISA_bus = 0; /* Where is natural place for this? */
* Application config hooks to set various driver parameters.
*/
-static struct config_table debug_tab[] = {
+static const struct config_table debug_tab[] = {
{ "PKT.DEBUG", ARG_ATOI, &pcap_pkt_debug },
{ "PKT.VECTOR", ARG_ATOX_W, NULL },
{ "NDIS.DEBUG", ARG_ATOI, NULL },
diff --git a/contrib/libpcap/pcap-enet.c b/contrib/libpcap/pcap-enet.c
index a484207..e5ea9aa 100644
--- a/contrib/libpcap/pcap-enet.c
+++ b/contrib/libpcap/pcap-enet.c
@@ -8,7 +8,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-enet.c,v 1.8 2003/11/15 23:24:02 guy Exp $";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-enet.c,v 1.9 2006/10/04 18:09:22 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -22,7 +22,7 @@ static const char rcsid[] _U_ =
#include <sys/socket.h>
#include <net/if.h>
-#include <pcap-bpf.h>
+#include <pcap/bpf.h>
#include <net/enet.h>
#include <netinet/in.h>
diff --git a/contrib/libpcap/pcap-filter.manmisc b/contrib/libpcap/pcap-filter.manmisc
new file mode 100644
index 0000000..372bb98
--- /dev/null
+++ b/contrib/libpcap/pcap-filter.manmisc
@@ -0,0 +1,949 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap-filter.manmisc.in,v 1.1.2.2 2008-10-21 07:44:56 guy Exp $ (LBL)
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-FILTER 7 "6 January 2008"
+.SH NAME
+pcap-filter \- packet filter syntax
+.br
+.ad
+.SH DESCRIPTION
+.LP
+.B pcap_compile()
+is used to compile a string into a filter program.
+The resulting filter program can then be applied to
+some stream of packets to determine which packets will be supplied to
+.BR pcap_loop() ,
+.BR pcap_dispatch() ,
+.BR pcap_next() ,
+or
+.BR pcap_next_ex() .
+.LP
+The \fIfilter expression\fP consists of one or more
+.IR primitives .
+Primitives usually consist of an
+.I id
+(name or number) preceded by one or more qualifiers.
+There are three
+different kinds of qualifier:
+.IP \fItype\fP
+qualifiers say what kind of thing the id name or number refers to.
+Possible types are
+.BR host ,
+.B net ,
+.B port
+and
+.BR portrange .
+E.g., `host foo', `net 128.3', `port 20', `portrange 6000-6008'.
+If there is no type
+qualifier,
+.B host
+is assumed.
+.IP \fIdir\fP
+qualifiers specify a particular transfer direction to and/or from
+.IR id .
+Possible directions are
+.BR src ,
+.BR dst ,
+.BR "src or dst" ,
+.BR "src and dst" ,
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.BR addr4 .
+E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'.
+If
+there is no dir qualifier,
+.B "src or dst"
+is assumed.
+The
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.B addr4
+qualifiers are only valid for IEEE 802.11 Wireless LAN link layers.
+For some link layers, such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types, the
+.B inbound
+and
+.B outbound
+qualifiers can be used to specify a desired direction.
+.IP \fIproto\fP
+qualifiers restrict the match to a particular protocol.
+Possible
+protos are:
+.BR ether ,
+.BR fddi ,
+.BR tr ,
+.BR wlan ,
+.BR ip ,
+.BR ip6 ,
+.BR arp ,
+.BR rarp ,
+.BR decnet ,
+.B tcp
+and
+.BR udp .
+E.g., `ether src foo', `arp net 128.3', `tcp port 21', `udp portrange
+7000-7009', `wlan addr2 0:2:3:4:5:6'.
+If there is
+no proto qualifier, all protocols consistent with the type are
+assumed.
+E.g., `src foo' means `(ip or arp or rarp) src foo'
+(except the latter is not legal syntax), `net bar' means `(ip or
+arp or rarp) net bar' and `port 53' means `(tcp or udp) port 53'.
+.LP
+[`fddi' is actually an alias for `ether'; the parser treats them
+identically as meaning ``the data link level used on the specified
+network interface.'' FDDI headers contain Ethernet-like source
+and destination addresses, and often contain Ethernet-like packet
+types, so you can filter on these FDDI fields just as with the
+analogous Ethernet fields.
+FDDI headers also contain other fields,
+but you cannot name them explicitly in a filter expression.
+.LP
+Similarly, `tr' and `wlan' are aliases for `ether'; the previous
+paragraph's statements about FDDI headers also apply to Token Ring
+and 802.11 wireless LAN headers. For 802.11 headers, the destination
+address is the DA field and the source address is the SA field; the
+BSSID, RA, and TA fields aren't tested.]
+.LP
+In addition to the above, there are some special `primitive' keywords
+that don't follow the pattern:
+.BR gateway ,
+.BR broadcast ,
+.BR less ,
+.B greater
+and arithmetic expressions.
+All of these are described below.
+.LP
+More complex filter expressions are built up by using the words
+.BR and ,
+.B or
+and
+.B not
+to combine primitives.
+E.g., `host foo and not port ftp and not port ftp-data'.
+To save typing, identical qualifier lists can be omitted.
+E.g.,
+`tcp dst port ftp or ftp-data or domain' is exactly the same as
+`tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'.
+.LP
+Allowable primitives are:
+.IP "\fBdst host \fIhost\fR"
+True if the IPv4/v6 destination field of the packet is \fIhost\fP,
+which may be either an address or a name.
+.IP "\fBsrc host \fIhost\fR"
+True if the IPv4/v6 source field of the packet is \fIhost\fP.
+.IP "\fBhost \fIhost\fP
+True if either the IPv4/v6 source or destination of the packet is \fIhost\fP.
+.IP
+Any of the above host expressions can be prepended with the keywords,
+\fBip\fP, \fBarp\fP, \fBrarp\fP, or \fBip6\fP as in:
+.in +.5i
+.nf
+\fBip host \fIhost\fR
+.fi
+.in -.5i
+which is equivalent to:
+.in +.5i
+.nf
+\fBether proto \fI\\ip\fB and host \fIhost\fR
+.fi
+.in -.5i
+If \fIhost\fR is a name with multiple IP addresses, each address will
+be checked for a match.
+.IP "\fBether dst \fIehost\fP
+True if the Ethernet destination address is \fIehost\fP.
+\fIEhost\fP
+may be either a name from /etc/ethers or a number (see
+.IR ethers (3N)
+for numeric format).
+.IP "\fBether src \fIehost\fP
+True if the Ethernet source address is \fIehost\fP.
+.IP "\fBether host \fIehost\fP
+True if either the Ethernet source or destination address is \fIehost\fP.
+.IP "\fBgateway\fP \fIhost\fP
+True if the packet used \fIhost\fP as a gateway.
+I.e., the Ethernet
+source or destination address was \fIhost\fP but neither the IP source
+nor the IP destination was \fIhost\fP.
+\fIHost\fP must be a name and
+must be found both by the machine's host-name-to-IP-address resolution
+mechanisms (host name file, DNS, NIS, etc.) and by the machine's
+host-name-to-Ethernet-address resolution mechanism (/etc/ethers, etc.).
+(An equivalent expression is
+.in +.5i
+.nf
+\fBether host \fIehost \fBand not host \fIhost\fR
+.fi
+.in -.5i
+which can be used with either names or numbers for \fIhost / ehost\fP.)
+This syntax does not work in IPv6-enabled configuration at this moment.
+.IP "\fBdst net \fInet\fR"
+True if the IPv4/v6 destination address of the packet has a network
+number of \fInet\fP.
+\fINet\fP may be either a name from the networks database
+(/etc/networks, etc.) or a network number.
+An IPv4 network number can be written as a dotted quad (e.g., 192.168.1.0),
+dotted triple (e.g., 192.168.1), dotted pair (e.g, 172.16), or single
+number (e.g., 10); the netmask is 255.255.255.255 for a dotted quad
+(which means that it's really a host match), 255.255.255.0 for a dotted
+triple, 255.255.0.0 for a dotted pair, or 255.0.0.0 for a single number.
+An IPv6 network number must be written out fully; the netmask is
+ff:ff:ff:ff:ff:ff:ff:ff, so IPv6 "network" matches are really always
+host matches, and a network match requires a netmask length.
+.IP "\fBsrc net \fInet\fR"
+True if the IPv4/v6 source address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR"
+True if either the IPv4/v6 source or destination address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR \fBmask \fInetmask\fR"
+True if the IPv4 address matches \fInet\fR with the specific \fInetmask\fR.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+Note that this syntax is not valid for IPv6 \fInet\fR.
+.IP "\fBnet \fInet\fR/\fIlen\fR"
+True if the IPv4/v6 address matches \fInet\fR with a netmask \fIlen\fR
+bits wide.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+.IP "\fBdst port \fIport\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value of \fIport\fP.
+The \fIport\fP can be a number or a name used in /etc/services (see
+.IR tcp (4P)
+and
+.IR udp (4P)).
+If a name is used, both the port
+number and protocol are checked.
+If a number or ambiguous name is used,
+only the port number is checked (e.g., \fBdst port 513\fR will print both
+tcp/login traffic and udp/who traffic, and \fBport domain\fR will print
+both tcp/domain and udp/domain traffic).
+.IP "\fBsrc port \fIport\fR"
+True if the packet has a source port value of \fIport\fP.
+.IP "\fBport \fIport\fR"
+True if either the source or destination port of the packet is \fIport\fP.
+.IP "\fBdst portrange \fIport1\fB-\fIport2\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value between \fIport1\fP and \fIport2\fP.
+.I port1
+and
+.I port2
+are interpreted in the same fashion as the
+.I port
+parameter for
+.BR port .
+.IP "\fBsrc portrange \fIport1\fB-\fIport2\fR"
+True if the packet has a source port value between \fIport1\fP and
+\fIport2\fP.
+.IP "\fBportrange \fIport1\fB-\fIport2\fR"
+True if either the source or destination port of the packet is between
+\fIport1\fP and \fIport2\fP.
+.IP
+Any of the above port or port range expressions can be prepended with
+the keywords, \fBtcp\fP or \fBudp\fP, as in:
+.in +.5i
+.nf
+\fBtcp src port \fIport\fR
+.fi
+.in -.5i
+which matches only tcp packets whose source port is \fIport\fP.
+.IP "\fBless \fIlength\fR"
+True if the packet has a length less than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen <= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBgreater \fIlength\fR"
+True if the packet has a length greater than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen >= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBip proto \fIprotocol\fR"
+True if the packet is an IPv4 packet (see
+.IR ip (4P))
+of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBicmp\fP, \fBicmp6\fP, \fBigmp\fP, \fBigrp\fP, \fBpim\fP, \fBah\fP,
+\fBesp\fP, \fBvrrp\fP, \fBudp\fP, or \fBtcp\fP.
+Note that the identifiers \fBtcp\fP, \fBudp\fP, and \fBicmp\fP are also
+keywords and must be escaped via backslash (\\), which is \\\\ in the C-shell.
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBip6 proto \fIprotocol\fR"
+True if the packet is an IPv6 packet of protocol type \fIprotocol\fP.
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBip6 protochain \fIprotocol\fR"
+True if the packet is IPv6 packet,
+and contains protocol header with type \fIprotocol\fR
+in its protocol header chain.
+For example,
+.in +.5i
+.nf
+\fBip6 protochain 6\fR
+.fi
+.in -.5i
+matches any IPv6 packet with TCP protocol header in the protocol header chain.
+The packet may contain, for example,
+authentication header, routing header, or hop-by-hop option header,
+between IPv6 header and TCP header.
+The BPF code emitted by this primitive is complex and
+cannot be optimized by the BPF optimizer code, so this can be somewhat
+slow.
+.IP "\fBip protochain \fIprotocol\fR"
+Equivalent to \fBip6 protochain \fIprotocol\fR, but this is for IPv4.
+.IP "\fBether broadcast\fR"
+True if the packet is an Ethernet broadcast packet.
+The \fIether\fP
+keyword is optional.
+.IP "\fBip broadcast\fR"
+True if the packet is an IPv4 broadcast packet.
+It checks for both the all-zeroes and all-ones broadcast conventions,
+and looks up the subnet mask on the interface on which the capture is
+being done.
+.IP
+If the subnet mask of the interface on which the capture is being done
+is not available, either because the interface on which capture is being
+done has no netmask or because the capture is being done on the Linux
+"any" interface, which can capture on more than one interface, this
+check will not work correctly.
+.IP "\fBether multicast\fR"
+True if the packet is an Ethernet multicast packet.
+The \fBether\fP
+keyword is optional.
+This is shorthand for `\fBether[0] & 1 != 0\fP'.
+.IP "\fBip multicast\fR"
+True if the packet is an IPv4 multicast packet.
+.IP "\fBip6 multicast\fR"
+True if the packet is an IPv6 multicast packet.
+.IP "\fBether proto \fIprotocol\fR"
+True if the packet is of ether type \fIprotocol\fR.
+\fIProtocol\fP can be a number or one of the names
+\fBip\fP, \fBip6\fP, \fBarp\fP, \fBrarp\fP, \fBatalk\fP, \fBaarp\fP,
+\fBdecnet\fP, \fBsca\fP, \fBlat\fP, \fBmopdl\fP, \fBmoprc\fP,
+\fBiso\fP, \fBstp\fP, \fBipx\fP, or \fBnetbeui\fP.
+Note these identifiers are also keywords
+and must be escaped via backslash (\\).
+.IP
+[In the case of FDDI (e.g., `\fBfddi protocol arp\fR'), Token Ring
+(e.g., `\fBtr protocol arp\fR'), and IEEE 802.11 wireless LANS (e.g.,
+`\fBwlan protocol arp\fR'), for most of those protocols, the
+protocol identification comes from the 802.2 Logical Link Control (LLC)
+header, which is usually layered on top of the FDDI, Token Ring, or
+802.11 header.
+.IP
+When filtering for most protocol identifiers on FDDI, Token Ring, or
+802.11, the filter checks only the protocol ID field of an LLC header
+in so-called SNAP format with an Organizational Unit Identifier (OUI) of
+0x000000, for encapsulated Ethernet; it doesn't check whether the packet
+is in SNAP format with an OUI of 0x000000.
+The exceptions are:
+.RS
+.TP
+\fBiso\fP
+the filter checks the DSAP (Destination Service Access Point) and
+SSAP (Source Service Access Point) fields of the LLC header;
+.TP
+\fBstp\fP and \fBnetbeui\fP
+the filter checks the DSAP of the LLC header;
+.TP
+\fBatalk\fP
+the filter checks for a SNAP-format packet with an OUI of 0x080007
+and the AppleTalk etype.
+.RE
+.IP
+In the case of Ethernet, the filter checks the Ethernet type field
+for most of those protocols. The exceptions are:
+.RS
+.TP
+\fBiso\fP, \fBstp\fP, and \fBnetbeui\fP
+the filter checks for an 802.3 frame and then checks the LLC header as
+it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBatalk\fP
+the filter checks both for the AppleTalk etype in an Ethernet frame and
+for a SNAP-format packet as it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBaarp\fP
+the filter checks for the AppleTalk ARP etype in either an Ethernet
+frame or an 802.2 SNAP frame with an OUI of 0x000000;
+.TP
+\fBipx\fP
+the filter checks for the IPX etype in an Ethernet frame, the IPX
+DSAP in the LLC header, the 802.3-with-no-LLC-header encapsulation of
+IPX, and the IPX etype in a SNAP frame.
+.RE
+.IP "\fBdecnet src \fIhost\fR"
+True if the DECNET source address is
+.IR host ,
+which may be an address of the form ``10.123'', or a DECNET host
+name.
+[DECNET host name support is only available on ULTRIX systems
+that are configured to run DECNET.]
+.IP "\fBdecnet dst \fIhost\fR"
+True if the DECNET destination address is
+.IR host .
+.IP "\fBdecnet host \fIhost\fR"
+True if either the DECNET source or destination address is
+.IR host .
+.IP "\fBifname \fIinterface\fR"
+True if the packet was logged as coming from the specified interface (applies
+only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBon \fIinterface\fR"
+Synonymous with the
+.B ifname
+modifier.
+.IP "\fBrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrulenum \fInum\fR"
+Synonymous with the
+.B rnr
+modifier.
+.IP "\fBreason \fIcode\fR"
+True if the packet was logged with the specified PF reason code. The known
+codes are:
+.BR match ,
+.BR bad-offset ,
+.BR fragment ,
+.BR short ,
+.BR normalize ,
+and
+.B memory
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrset \fIname\fR"
+True if the packet was logged as matching the specified PF ruleset
+name of an anchored ruleset (applies only to packets logged by OpenBSD's
+or FreeBSD's
+.BR pf (4)).
+.IP "\fBruleset \fIname\fR"
+Synonomous with the
+.B rset
+modifier.
+.IP "\fBsrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+of an anchored ruleset (applies only to packets logged by OpenBSD's or
+FreeBSD's
+.BR pf (4)).
+.IP "\fBsubrulenum \fInum\fR"
+Synonomous with the
+.B srnr
+modifier.
+.IP "\fBaction \fIact\fR"
+True if PF took the specified action when the packet was logged. Known actions
+are:
+.B pass
+and
+.B block
+and, with later versions of
+.BR pf (4)),
+.BR nat ,
+.BR rdr ,
+.B binat
+and
+.B scrub
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBwlan addr1 \fIehost\fR"
+True if the first IEEE 802.11 address is
+.IR ehost .
+.IP "\fBwlan addr2 \fIehost\fR"
+True if the second IEEE 802.11 address, if present, is
+.IR ehost .
+The second address field is used in all frames except for CTS (Clear To
+Send) and ACK (Acknowledgment) control frames.
+.IP "\fBwlan addr3 \fIehost\fR"
+True if the third IEEE 802.11 address, if present, is
+.IR ehost .
+The third address field is used in management and data frames, but not
+in control frames.
+.IP "\fBwlan addr4 \fIehost\fR"
+True if the fourth IEEE 802.11 address, if present, is
+.IR ehost .
+The fourth address field is only used for
+WDS (Wireless Distribution System) frames.
+.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fInetbeui\fP"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+Note that not all applications using
+.BR pcap (3)
+currently know how to parse these protocols.
+.IP "\fBtype \fIwlan_type\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR.
+Valid \fIwlan_type\fRs are:
+\fBmgt\fP,
+\fBctl\fP
+and \fBdata\fP.
+.IP "\fBtype \fIwlan_type \fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR
+and frame subtype matches the specified \fIwlan_subtype\fR.
+.IP
+If the specified \fIwlan_type\fR is \fBmgt\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBassoc-req\fP,
+\fBassoc-resp\fP,
+\fBreassoc-req\fP,
+\fBreassoc-resp\fP,
+\fBprobe-req\fP,
+\fBprobe-resp\fP,
+\fBbeacon\fP,
+\fBatim\fP,
+\fBdisassoc\fP,
+\fBauth\fP and
+\fBdeauth\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBctl\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBps-poll\fP,
+\fBrts\fP,
+\fBcts\fP,
+\fBack\fP,
+\fBcf-end\fP and
+\fBcf-end-ack\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBdata\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBdata\fP,
+\fBdata-cf-ack\fP,
+\fBdata-cf-poll\fP,
+\fBdata-cf-ack-poll\fP,
+\fBnull\fP,
+\fBcf-ack\fP,
+\fBcf-poll\fP,
+\fBcf-ack-poll\fP,
+\fBqos-data\fP,
+\fBqos-data-cf-ack\fP,
+\fBqos-data-cf-poll\fP,
+\fBqos-data-cf-ack-poll\fP,
+\fBqos\fP,
+\fBqos-cf-poll\fP and
+\fBqos-cf-ack-poll\fP.
+.IP "\fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame subtype matches the specified \fIwlan_subtype\fR
+and frame has the type to which the specified \fIwlan_subtype\fR belongs.
+.IP "\fBdir \fIdir\fR"
+True if the IEEE 802.11 frame direction matches the specified
+.IR dir .
+Valid directions are:
+.BR nods ,
+.BR tods ,
+.BR fromds ,
+.BR dstods ,
+or a numeric value.
+.IP "\fBvlan \fI[vlan_id]\fR"
+True if the packet is an IEEE 802.1Q VLAN packet.
+If \fI[vlan_id]\fR is specified, only true if the packet has the specified
+\fIvlan_id\fR.
+Note that the first \fBvlan\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a VLAN packet. The \fBvlan
+\fI[vlan_id]\fR expression may be used more than once, to filter on VLAN
+hierarchies. Each use of that expression increments the filter offsets
+by 4.
+.IP
+For example:
+.in +.5i
+.nf
+\fBvlan 100 && vlan 200\fR
+.fi
+.in -.5i
+filters on VLAN 200 encapsulated within VLAN 100, and
+.in +.5i
+.nf
+\fBvlan && vlan 300 && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in VLAN 300 encapsulated within any
+higher order VLAN.
+.IP "\fBmpls \fI[label_num]\fR"
+True if the packet is an MPLS packet.
+If \fI[label_num]\fR is specified, only true is the packet has the specified
+\fIlabel_num\fR.
+Note that the first \fBmpls\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a MPLS-encapsulated IP packet. The
+\fBmpls \fI[label_num]\fR expression may be used more than once, to
+filter on MPLS hierarchies. Each use of that expression increments the
+filter offsets by 4.
+.IP
+For example:
+.in +.5i
+.nf
+\fBmpls 100000 && mpls 1024\fR
+.fi
+.in -.5i
+filters packets with an outer label of 100000 and an inner label of
+1024, and
+.in +.5i
+.nf
+\fBmpls && mpls 1024 && host 192.9.200.1\fR
+.fi
+.in -.5i
+filters packets to or from 192.9.200.1 with an inner label of 1024 and
+any outer label.
+.IP \fBpppoed\fP
+True if the packet is a PPP-over-Ethernet Discovery packet (Ethernet
+type 0x8863).
+.IP \fBpppoes\fP
+True if the packet is a PPP-over-Ethernet Session packet (Ethernet
+type 0x8864).
+Note that the first \fBpppoes\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a PPPoE session packet.
+.IP
+For example:
+.in +.5i
+.nf
+\fBpppoes && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in PPPoE.
+.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBip proto \fIp\fR\fB or ip6 proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBiso proto \fIprotocol\fR"
+True if the packet is an OSI packet of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBclnp\fP, \fBesis\fP, or \fBisis\fP.
+.IP "\fBclnp\fR, \fBesis\fR, \fBisis\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBiso proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBl1\fR, \fBl2\fR, \fBiih\fR, \fBlsp\fR, \fBsnp\fR, \fBcsnp\fR, \fBpsnp\fR"
+Abbreviations for IS-IS PDU types.
+.IP "\fBvpi\fP \fIn\fR
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual path identifier of
+.IR n .
+.IP "\fBvci\fP \fIn\fR
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual channel identifier of
+.IR n .
+.IP \fBlane\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an ATM LANE packet.
+Note that the first \fBlane\fR keyword encountered in \fIexpression\fR
+changes the tests done in the remainder of \fIexpression\fR
+on the assumption that the packet is either a LANE emulated Ethernet
+packet or a LANE LE Control packet. If \fBlane\fR isn't specified, the
+tests are done under the assumption that the packet is an
+LLC-encapsulated packet.
+.IP \fBllc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an LLC-encapsulated packet.
+.IP \fBoamf4s\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment OAM F4 flow cell (VPI=0 & VCI=3).
+.IP \fBoamf4e\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an end-to-end OAM F4 flow cell (VPI=0 & VCI=4).
+.IP \fBoamf4\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBoam\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBmetac\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit (VPI=0 & VCI=1).
+.IP \fBbcc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a broadcast signaling circuit (VPI=0 & VCI=2).
+.IP \fBsc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit (VPI=0 & VCI=5).
+.IP \fBilmic\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on an ILMI circuit (VPI=0 & VCI=16).
+.IP \fBconnectmsg\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Connect Ack, Release, or Release Done message.
+.IP \fBmetaconnect\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Release, or Release Done message.
+.IP "\fIexpr relop expr\fR"
+True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =,
+!=, and \fIexpr\fR is an arithmetic expression composed of integer
+constants (expressed in standard C syntax), the normal binary operators
+[+, -, *, /, &, |, <<, >>], a length operator, and special packet data
+accessors. Note that all comparisons are unsigned, so that, for example,
+0x80000000 and 0xffffffff are > 0.
+To access
+data inside the packet, use the following syntax:
+.in +.5i
+.nf
+\fIproto\fB [ \fIexpr\fB : \fIsize\fB ]\fR
+.fi
+.in -.5i
+\fIProto\fR is one of \fBether, fddi, tr, wlan, ppp, slip, link,
+ip, arp, rarp, tcp, udp, icmp, ip6\fR or \fBradio\fR, and
+indicates the protocol layer for the index operation.
+(\fBether, fddi, wlan, tr, ppp, slip\fR and \fBlink\fR all refer to the
+link layer. \fBradio\fR refers to the "radio header" added to some
+802.11 captures.)
+Note that \fItcp, udp\fR and other upper-layer protocol types only
+apply to IPv4, not IPv6 (this will be fixed in the future).
+The byte offset, relative to the indicated protocol layer, is
+given by \fIexpr\fR.
+\fISize\fR is optional and indicates the number of bytes in the
+field of interest; it can be either one, two, or four, and defaults to one.
+The length operator, indicated by the keyword \fBlen\fP, gives the
+length of the packet.
+
+For example, `\fBether[0] & 1 != 0\fP' catches all multicast traffic.
+The expression `\fBip[0] & 0xf != 5\fP'
+catches all IPv4 packets with options.
+The expression
+`\fBip[6:2] & 0x1fff = 0\fP'
+catches only unfragmented IPv4 datagrams and frag zero of fragmented
+IPv4 datagrams.
+This check is implicitly applied to the \fBtcp\fP and \fBudp\fP
+index operations.
+For instance, \fBtcp[0]\fP always means the first
+byte of the TCP \fIheader\fP, and never means the first byte of an
+intervening fragment.
+
+Some offsets and field values may be expressed as names rather than
+as numeric values.
+The following protocol header field offsets are
+available: \fBicmptype\fP (ICMP type field), \fBicmpcode\fP (ICMP
+code field), and \fBtcpflags\fP (TCP flags field).
+
+The following ICMP type field values are available: \fBicmp-echoreply\fP,
+\fBicmp-unreach\fP, \fBicmp-sourcequench\fP, \fBicmp-redirect\fP,
+\fBicmp-echo\fP, \fBicmp-routeradvert\fP, \fBicmp-routersolicit\fP,
+\fBicmp-timxceed\fP, \fBicmp-paramprob\fP, \fBicmp-tstamp\fP,
+\fBicmp-tstampreply\fP, \fBicmp-ireq\fP, \fBicmp-ireqreply\fP,
+\fBicmp-maskreq\fP, \fBicmp-maskreply\fP.
+
+The following TCP flags field values are available: \fBtcp-fin\fP,
+\fBtcp-syn\fP, \fBtcp-rst\fP, \fBtcp-push\fP,
+\fBtcp-ack\fP, \fBtcp-urg\fP.
+.LP
+Primitives may be combined using:
+.IP
+A parenthesized group of primitives and operators
+(parentheses are special to the Shell and must be escaped).
+.IP
+Negation (`\fB!\fP' or `\fBnot\fP').
+.IP
+Concatenation (`\fB&&\fP' or `\fBand\fP').
+.IP
+Alternation (`\fB||\fP' or `\fBor\fP').
+.LP
+Negation has highest precedence.
+Alternation and concatenation have equal precedence and associate
+left to right.
+Note that explicit \fBand\fR tokens, not juxtaposition,
+are now required for concatenation.
+.LP
+If an identifier is given without a keyword, the most recent keyword
+is assumed.
+For example,
+.in +.5i
+.nf
+\fBnot host vs and ace\fR
+.fi
+.in -.5i
+is short for
+.in +.5i
+.nf
+\fBnot host vs and host ace\fR
+.fi
+.in -.5i
+which should not be confused with
+.in +.5i
+.nf
+\fBnot ( host vs or ace )\fR
+.fi
+.in -.5i
+.SH EXAMPLES
+.LP
+To select all packets arriving at or departing from \fIsundown\fP:
+.RS
+.nf
+\fBhost sundown\fP
+.fi
+.RE
+.LP
+To select traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR:
+.RS
+.nf
+\fBhost helios and \\( hot or ace \\)\fP
+.fi
+.RE
+.LP
+To select all IP packets between \fIace\fR and any host except \fIhelios\fR:
+.RS
+.nf
+\fBip host ace and not helios\fP
+.fi
+.RE
+.LP
+To select all traffic between local hosts and hosts at Berkeley:
+.RS
+.nf
+.B
+net ucb-ether
+.fi
+.RE
+.LP
+To select all ftp traffic through internet gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and (port ftp or ftp-data)
+.fi
+.RE
+.LP
+To select traffic neither sourced from nor destined for local hosts
+(if you gateway to one other net, this stuff should never make it
+onto your local net).
+.RS
+.nf
+.B
+ip and not net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select the start and end packets (the SYN and FIN packets) of each
+TCP conversation that involves a non-local host.
+.RS
+.nf
+.B
+tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select all IPv4 HTTP packets to and from port 80, i.e. print only
+packets that contain data, not, for example, SYN and FIN packets and
+ACK-only packets. (IPv6 is left as an exercise for the reader.)
+.RS
+.nf
+.B
+tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)
+.fi
+.RE
+.LP
+To select IP packets longer than 576 bytes sent through gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and ip[2:2] > 576
+.fi
+.RE
+.LP
+To select IP broadcast or multicast packets that were
+.I not
+sent via Ethernet broadcast or multicast:
+.RS
+.nf
+.B
+ether[0] & 1 = 0 and ip[16] >= 224
+.fi
+.RE
+.LP
+To select all ICMP packets that are not echo requests/replies (i.e., not
+ping packets):
+.RS
+.nf
+.B
+icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply
+.fi
+.RE
+.SH "SEE ALSO"
+pcap(3PCAP)
+.SH AUTHORS
+The original authors are:
+.LP
+Van Jacobson,
+Craig Leres and
+Steven McCanne, all of the
+Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
+.LP
+It is currently being maintained by tcpdump.org.
+.LP
+The current version of libpcap is available via http:
+.LP
+.RS
+.I http://www.tcpdump.org/
+.RE
+.LP
+The original distribution is available via anonymous ftp:
+.LP
+.RS
+.I ftp://ftp.ee.lbl.gov/tcpdump.tar.Z
+.RE
+.SH BUGS
+Please send problems, bugs, questions, desirable enhancements, etc. to:
+.LP
+.RS
+tcpdump-workers@lists.tcpdump.org
+.RE
+.LP
+Filter expressions on fields other than those in Token Ring headers will
+not correctly handle source-routed Token Ring packets.
+.LP
+Filter expressions on fields other than those in 802.11 headers will not
+correctly handle 802.11 data packets with both To DS and From DS set.
+.LP
+.BR "ip6 proto"
+should chase header chain, but at this moment it does not.
+.BR "ip6 protochain"
+is supplied for this behavior.
+.LP
+Arithmetic expression against transport layer headers, like \fBtcp[0]\fP,
+does not work against IPv6 packets.
+It only looks at IPv4 packets.
diff --git a/contrib/libpcap/pcap-filter.manmisc.in b/contrib/libpcap/pcap-filter.manmisc.in
new file mode 100644
index 0000000..3beec58
--- /dev/null
+++ b/contrib/libpcap/pcap-filter.manmisc.in
@@ -0,0 +1,949 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap-filter.manmisc.in,v 1.1.2.2 2008-10-21 07:44:56 guy Exp $ (LBL)
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-FILTER @MAN_MISC_INFO@ "6 January 2008"
+.SH NAME
+pcap-filter \- packet filter syntax
+.br
+.ad
+.SH DESCRIPTION
+.LP
+.B pcap_compile()
+is used to compile a string into a filter program.
+The resulting filter program can then be applied to
+some stream of packets to determine which packets will be supplied to
+.BR pcap_loop() ,
+.BR pcap_dispatch() ,
+.BR pcap_next() ,
+or
+.BR pcap_next_ex() .
+.LP
+The \fIfilter expression\fP consists of one or more
+.IR primitives .
+Primitives usually consist of an
+.I id
+(name or number) preceded by one or more qualifiers.
+There are three
+different kinds of qualifier:
+.IP \fItype\fP
+qualifiers say what kind of thing the id name or number refers to.
+Possible types are
+.BR host ,
+.B net ,
+.B port
+and
+.BR portrange .
+E.g., `host foo', `net 128.3', `port 20', `portrange 6000-6008'.
+If there is no type
+qualifier,
+.B host
+is assumed.
+.IP \fIdir\fP
+qualifiers specify a particular transfer direction to and/or from
+.IR id .
+Possible directions are
+.BR src ,
+.BR dst ,
+.BR "src or dst" ,
+.BR "src and dst" ,
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.BR addr4 .
+E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'.
+If
+there is no dir qualifier,
+.B "src or dst"
+is assumed.
+The
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.B addr4
+qualifiers are only valid for IEEE 802.11 Wireless LAN link layers.
+For some link layers, such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types, the
+.B inbound
+and
+.B outbound
+qualifiers can be used to specify a desired direction.
+.IP \fIproto\fP
+qualifiers restrict the match to a particular protocol.
+Possible
+protos are:
+.BR ether ,
+.BR fddi ,
+.BR tr ,
+.BR wlan ,
+.BR ip ,
+.BR ip6 ,
+.BR arp ,
+.BR rarp ,
+.BR decnet ,
+.B tcp
+and
+.BR udp .
+E.g., `ether src foo', `arp net 128.3', `tcp port 21', `udp portrange
+7000-7009', `wlan addr2 0:2:3:4:5:6'.
+If there is
+no proto qualifier, all protocols consistent with the type are
+assumed.
+E.g., `src foo' means `(ip or arp or rarp) src foo'
+(except the latter is not legal syntax), `net bar' means `(ip or
+arp or rarp) net bar' and `port 53' means `(tcp or udp) port 53'.
+.LP
+[`fddi' is actually an alias for `ether'; the parser treats them
+identically as meaning ``the data link level used on the specified
+network interface.'' FDDI headers contain Ethernet-like source
+and destination addresses, and often contain Ethernet-like packet
+types, so you can filter on these FDDI fields just as with the
+analogous Ethernet fields.
+FDDI headers also contain other fields,
+but you cannot name them explicitly in a filter expression.
+.LP
+Similarly, `tr' and `wlan' are aliases for `ether'; the previous
+paragraph's statements about FDDI headers also apply to Token Ring
+and 802.11 wireless LAN headers. For 802.11 headers, the destination
+address is the DA field and the source address is the SA field; the
+BSSID, RA, and TA fields aren't tested.]
+.LP
+In addition to the above, there are some special `primitive' keywords
+that don't follow the pattern:
+.BR gateway ,
+.BR broadcast ,
+.BR less ,
+.B greater
+and arithmetic expressions.
+All of these are described below.
+.LP
+More complex filter expressions are built up by using the words
+.BR and ,
+.B or
+and
+.B not
+to combine primitives.
+E.g., `host foo and not port ftp and not port ftp-data'.
+To save typing, identical qualifier lists can be omitted.
+E.g.,
+`tcp dst port ftp or ftp-data or domain' is exactly the same as
+`tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'.
+.LP
+Allowable primitives are:
+.IP "\fBdst host \fIhost\fR"
+True if the IPv4/v6 destination field of the packet is \fIhost\fP,
+which may be either an address or a name.
+.IP "\fBsrc host \fIhost\fR"
+True if the IPv4/v6 source field of the packet is \fIhost\fP.
+.IP "\fBhost \fIhost\fP
+True if either the IPv4/v6 source or destination of the packet is \fIhost\fP.
+.IP
+Any of the above host expressions can be prepended with the keywords,
+\fBip\fP, \fBarp\fP, \fBrarp\fP, or \fBip6\fP as in:
+.in +.5i
+.nf
+\fBip host \fIhost\fR
+.fi
+.in -.5i
+which is equivalent to:
+.in +.5i
+.nf
+\fBether proto \fI\\ip\fB and host \fIhost\fR
+.fi
+.in -.5i
+If \fIhost\fR is a name with multiple IP addresses, each address will
+be checked for a match.
+.IP "\fBether dst \fIehost\fP
+True if the Ethernet destination address is \fIehost\fP.
+\fIEhost\fP
+may be either a name from /etc/ethers or a number (see
+.IR ethers (3N)
+for numeric format).
+.IP "\fBether src \fIehost\fP
+True if the Ethernet source address is \fIehost\fP.
+.IP "\fBether host \fIehost\fP
+True if either the Ethernet source or destination address is \fIehost\fP.
+.IP "\fBgateway\fP \fIhost\fP
+True if the packet used \fIhost\fP as a gateway.
+I.e., the Ethernet
+source or destination address was \fIhost\fP but neither the IP source
+nor the IP destination was \fIhost\fP.
+\fIHost\fP must be a name and
+must be found both by the machine's host-name-to-IP-address resolution
+mechanisms (host name file, DNS, NIS, etc.) and by the machine's
+host-name-to-Ethernet-address resolution mechanism (/etc/ethers, etc.).
+(An equivalent expression is
+.in +.5i
+.nf
+\fBether host \fIehost \fBand not host \fIhost\fR
+.fi
+.in -.5i
+which can be used with either names or numbers for \fIhost / ehost\fP.)
+This syntax does not work in IPv6-enabled configuration at this moment.
+.IP "\fBdst net \fInet\fR"
+True if the IPv4/v6 destination address of the packet has a network
+number of \fInet\fP.
+\fINet\fP may be either a name from the networks database
+(/etc/networks, etc.) or a network number.
+An IPv4 network number can be written as a dotted quad (e.g., 192.168.1.0),
+dotted triple (e.g., 192.168.1), dotted pair (e.g, 172.16), or single
+number (e.g., 10); the netmask is 255.255.255.255 for a dotted quad
+(which means that it's really a host match), 255.255.255.0 for a dotted
+triple, 255.255.0.0 for a dotted pair, or 255.0.0.0 for a single number.
+An IPv6 network number must be written out fully; the netmask is
+ff:ff:ff:ff:ff:ff:ff:ff, so IPv6 "network" matches are really always
+host matches, and a network match requires a netmask length.
+.IP "\fBsrc net \fInet\fR"
+True if the IPv4/v6 source address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR"
+True if either the IPv4/v6 source or destination address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR \fBmask \fInetmask\fR"
+True if the IPv4 address matches \fInet\fR with the specific \fInetmask\fR.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+Note that this syntax is not valid for IPv6 \fInet\fR.
+.IP "\fBnet \fInet\fR/\fIlen\fR"
+True if the IPv4/v6 address matches \fInet\fR with a netmask \fIlen\fR
+bits wide.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+.IP "\fBdst port \fIport\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value of \fIport\fP.
+The \fIport\fP can be a number or a name used in /etc/services (see
+.IR tcp (4P)
+and
+.IR udp (4P)).
+If a name is used, both the port
+number and protocol are checked.
+If a number or ambiguous name is used,
+only the port number is checked (e.g., \fBdst port 513\fR will print both
+tcp/login traffic and udp/who traffic, and \fBport domain\fR will print
+both tcp/domain and udp/domain traffic).
+.IP "\fBsrc port \fIport\fR"
+True if the packet has a source port value of \fIport\fP.
+.IP "\fBport \fIport\fR"
+True if either the source or destination port of the packet is \fIport\fP.
+.IP "\fBdst portrange \fIport1\fB-\fIport2\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value between \fIport1\fP and \fIport2\fP.
+.I port1
+and
+.I port2
+are interpreted in the same fashion as the
+.I port
+parameter for
+.BR port .
+.IP "\fBsrc portrange \fIport1\fB-\fIport2\fR"
+True if the packet has a source port value between \fIport1\fP and
+\fIport2\fP.
+.IP "\fBportrange \fIport1\fB-\fIport2\fR"
+True if either the source or destination port of the packet is between
+\fIport1\fP and \fIport2\fP.
+.IP
+Any of the above port or port range expressions can be prepended with
+the keywords, \fBtcp\fP or \fBudp\fP, as in:
+.in +.5i
+.nf
+\fBtcp src port \fIport\fR
+.fi
+.in -.5i
+which matches only tcp packets whose source port is \fIport\fP.
+.IP "\fBless \fIlength\fR"
+True if the packet has a length less than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen <= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBgreater \fIlength\fR"
+True if the packet has a length greater than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen >= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBip proto \fIprotocol\fR"
+True if the packet is an IPv4 packet (see
+.IR ip (4P))
+of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBicmp\fP, \fBicmp6\fP, \fBigmp\fP, \fBigrp\fP, \fBpim\fP, \fBah\fP,
+\fBesp\fP, \fBvrrp\fP, \fBudp\fP, or \fBtcp\fP.
+Note that the identifiers \fBtcp\fP, \fBudp\fP, and \fBicmp\fP are also
+keywords and must be escaped via backslash (\\), which is \\\\ in the C-shell.
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBip6 proto \fIprotocol\fR"
+True if the packet is an IPv6 packet of protocol type \fIprotocol\fP.
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBip6 protochain \fIprotocol\fR"
+True if the packet is IPv6 packet,
+and contains protocol header with type \fIprotocol\fR
+in its protocol header chain.
+For example,
+.in +.5i
+.nf
+\fBip6 protochain 6\fR
+.fi
+.in -.5i
+matches any IPv6 packet with TCP protocol header in the protocol header chain.
+The packet may contain, for example,
+authentication header, routing header, or hop-by-hop option header,
+between IPv6 header and TCP header.
+The BPF code emitted by this primitive is complex and
+cannot be optimized by the BPF optimizer code, so this can be somewhat
+slow.
+.IP "\fBip protochain \fIprotocol\fR"
+Equivalent to \fBip6 protochain \fIprotocol\fR, but this is for IPv4.
+.IP "\fBether broadcast\fR"
+True if the packet is an Ethernet broadcast packet.
+The \fIether\fP
+keyword is optional.
+.IP "\fBip broadcast\fR"
+True if the packet is an IPv4 broadcast packet.
+It checks for both the all-zeroes and all-ones broadcast conventions,
+and looks up the subnet mask on the interface on which the capture is
+being done.
+.IP
+If the subnet mask of the interface on which the capture is being done
+is not available, either because the interface on which capture is being
+done has no netmask or because the capture is being done on the Linux
+"any" interface, which can capture on more than one interface, this
+check will not work correctly.
+.IP "\fBether multicast\fR"
+True if the packet is an Ethernet multicast packet.
+The \fBether\fP
+keyword is optional.
+This is shorthand for `\fBether[0] & 1 != 0\fP'.
+.IP "\fBip multicast\fR"
+True if the packet is an IPv4 multicast packet.
+.IP "\fBip6 multicast\fR"
+True if the packet is an IPv6 multicast packet.
+.IP "\fBether proto \fIprotocol\fR"
+True if the packet is of ether type \fIprotocol\fR.
+\fIProtocol\fP can be a number or one of the names
+\fBip\fP, \fBip6\fP, \fBarp\fP, \fBrarp\fP, \fBatalk\fP, \fBaarp\fP,
+\fBdecnet\fP, \fBsca\fP, \fBlat\fP, \fBmopdl\fP, \fBmoprc\fP,
+\fBiso\fP, \fBstp\fP, \fBipx\fP, or \fBnetbeui\fP.
+Note these identifiers are also keywords
+and must be escaped via backslash (\\).
+.IP
+[In the case of FDDI (e.g., `\fBfddi protocol arp\fR'), Token Ring
+(e.g., `\fBtr protocol arp\fR'), and IEEE 802.11 wireless LANS (e.g.,
+`\fBwlan protocol arp\fR'), for most of those protocols, the
+protocol identification comes from the 802.2 Logical Link Control (LLC)
+header, which is usually layered on top of the FDDI, Token Ring, or
+802.11 header.
+.IP
+When filtering for most protocol identifiers on FDDI, Token Ring, or
+802.11, the filter checks only the protocol ID field of an LLC header
+in so-called SNAP format with an Organizational Unit Identifier (OUI) of
+0x000000, for encapsulated Ethernet; it doesn't check whether the packet
+is in SNAP format with an OUI of 0x000000.
+The exceptions are:
+.RS
+.TP
+\fBiso\fP
+the filter checks the DSAP (Destination Service Access Point) and
+SSAP (Source Service Access Point) fields of the LLC header;
+.TP
+\fBstp\fP and \fBnetbeui\fP
+the filter checks the DSAP of the LLC header;
+.TP
+\fBatalk\fP
+the filter checks for a SNAP-format packet with an OUI of 0x080007
+and the AppleTalk etype.
+.RE
+.IP
+In the case of Ethernet, the filter checks the Ethernet type field
+for most of those protocols. The exceptions are:
+.RS
+.TP
+\fBiso\fP, \fBstp\fP, and \fBnetbeui\fP
+the filter checks for an 802.3 frame and then checks the LLC header as
+it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBatalk\fP
+the filter checks both for the AppleTalk etype in an Ethernet frame and
+for a SNAP-format packet as it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBaarp\fP
+the filter checks for the AppleTalk ARP etype in either an Ethernet
+frame or an 802.2 SNAP frame with an OUI of 0x000000;
+.TP
+\fBipx\fP
+the filter checks for the IPX etype in an Ethernet frame, the IPX
+DSAP in the LLC header, the 802.3-with-no-LLC-header encapsulation of
+IPX, and the IPX etype in a SNAP frame.
+.RE
+.IP "\fBdecnet src \fIhost\fR"
+True if the DECNET source address is
+.IR host ,
+which may be an address of the form ``10.123'', or a DECNET host
+name.
+[DECNET host name support is only available on ULTRIX systems
+that are configured to run DECNET.]
+.IP "\fBdecnet dst \fIhost\fR"
+True if the DECNET destination address is
+.IR host .
+.IP "\fBdecnet host \fIhost\fR"
+True if either the DECNET source or destination address is
+.IR host .
+.IP "\fBifname \fIinterface\fR"
+True if the packet was logged as coming from the specified interface (applies
+only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBon \fIinterface\fR"
+Synonymous with the
+.B ifname
+modifier.
+.IP "\fBrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrulenum \fInum\fR"
+Synonymous with the
+.B rnr
+modifier.
+.IP "\fBreason \fIcode\fR"
+True if the packet was logged with the specified PF reason code. The known
+codes are:
+.BR match ,
+.BR bad-offset ,
+.BR fragment ,
+.BR short ,
+.BR normalize ,
+and
+.B memory
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrset \fIname\fR"
+True if the packet was logged as matching the specified PF ruleset
+name of an anchored ruleset (applies only to packets logged by OpenBSD's
+or FreeBSD's
+.BR pf (4)).
+.IP "\fBruleset \fIname\fR"
+Synonomous with the
+.B rset
+modifier.
+.IP "\fBsrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+of an anchored ruleset (applies only to packets logged by OpenBSD's or
+FreeBSD's
+.BR pf (4)).
+.IP "\fBsubrulenum \fInum\fR"
+Synonomous with the
+.B srnr
+modifier.
+.IP "\fBaction \fIact\fR"
+True if PF took the specified action when the packet was logged. Known actions
+are:
+.B pass
+and
+.B block
+and, with later versions of
+.BR pf (4)),
+.BR nat ,
+.BR rdr ,
+.B binat
+and
+.B scrub
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBwlan addr1 \fIehost\fR"
+True if the first IEEE 802.11 address is
+.IR ehost .
+.IP "\fBwlan addr2 \fIehost\fR"
+True if the second IEEE 802.11 address, if present, is
+.IR ehost .
+The second address field is used in all frames except for CTS (Clear To
+Send) and ACK (Acknowledgment) control frames.
+.IP "\fBwlan addr3 \fIehost\fR"
+True if the third IEEE 802.11 address, if present, is
+.IR ehost .
+The third address field is used in management and data frames, but not
+in control frames.
+.IP "\fBwlan addr4 \fIehost\fR"
+True if the fourth IEEE 802.11 address, if present, is
+.IR ehost .
+The fourth address field is only used for
+WDS (Wireless Distribution System) frames.
+.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fInetbeui\fP"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+Note that not all applications using
+.BR pcap (3)
+currently know how to parse these protocols.
+.IP "\fBtype \fIwlan_type\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR.
+Valid \fIwlan_type\fRs are:
+\fBmgt\fP,
+\fBctl\fP
+and \fBdata\fP.
+.IP "\fBtype \fIwlan_type \fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR
+and frame subtype matches the specified \fIwlan_subtype\fR.
+.IP
+If the specified \fIwlan_type\fR is \fBmgt\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBassoc-req\fP,
+\fBassoc-resp\fP,
+\fBreassoc-req\fP,
+\fBreassoc-resp\fP,
+\fBprobe-req\fP,
+\fBprobe-resp\fP,
+\fBbeacon\fP,
+\fBatim\fP,
+\fBdisassoc\fP,
+\fBauth\fP and
+\fBdeauth\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBctl\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBps-poll\fP,
+\fBrts\fP,
+\fBcts\fP,
+\fBack\fP,
+\fBcf-end\fP and
+\fBcf-end-ack\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBdata\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBdata\fP,
+\fBdata-cf-ack\fP,
+\fBdata-cf-poll\fP,
+\fBdata-cf-ack-poll\fP,
+\fBnull\fP,
+\fBcf-ack\fP,
+\fBcf-poll\fP,
+\fBcf-ack-poll\fP,
+\fBqos-data\fP,
+\fBqos-data-cf-ack\fP,
+\fBqos-data-cf-poll\fP,
+\fBqos-data-cf-ack-poll\fP,
+\fBqos\fP,
+\fBqos-cf-poll\fP and
+\fBqos-cf-ack-poll\fP.
+.IP "\fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame subtype matches the specified \fIwlan_subtype\fR
+and frame has the type to which the specified \fIwlan_subtype\fR belongs.
+.IP "\fBdir \fIdir\fR"
+True if the IEEE 802.11 frame direction matches the specified
+.IR dir .
+Valid directions are:
+.BR nods ,
+.BR tods ,
+.BR fromds ,
+.BR dstods ,
+or a numeric value.
+.IP "\fBvlan \fI[vlan_id]\fR"
+True if the packet is an IEEE 802.1Q VLAN packet.
+If \fI[vlan_id]\fR is specified, only true if the packet has the specified
+\fIvlan_id\fR.
+Note that the first \fBvlan\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a VLAN packet. The \fBvlan
+\fI[vlan_id]\fR expression may be used more than once, to filter on VLAN
+hierarchies. Each use of that expression increments the filter offsets
+by 4.
+.IP
+For example:
+.in +.5i
+.nf
+\fBvlan 100 && vlan 200\fR
+.fi
+.in -.5i
+filters on VLAN 200 encapsulated within VLAN 100, and
+.in +.5i
+.nf
+\fBvlan && vlan 300 && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in VLAN 300 encapsulated within any
+higher order VLAN.
+.IP "\fBmpls \fI[label_num]\fR"
+True if the packet is an MPLS packet.
+If \fI[label_num]\fR is specified, only true is the packet has the specified
+\fIlabel_num\fR.
+Note that the first \fBmpls\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a MPLS-encapsulated IP packet. The
+\fBmpls \fI[label_num]\fR expression may be used more than once, to
+filter on MPLS hierarchies. Each use of that expression increments the
+filter offsets by 4.
+.IP
+For example:
+.in +.5i
+.nf
+\fBmpls 100000 && mpls 1024\fR
+.fi
+.in -.5i
+filters packets with an outer label of 100000 and an inner label of
+1024, and
+.in +.5i
+.nf
+\fBmpls && mpls 1024 && host 192.9.200.1\fR
+.fi
+.in -.5i
+filters packets to or from 192.9.200.1 with an inner label of 1024 and
+any outer label.
+.IP \fBpppoed\fP
+True if the packet is a PPP-over-Ethernet Discovery packet (Ethernet
+type 0x8863).
+.IP \fBpppoes\fP
+True if the packet is a PPP-over-Ethernet Session packet (Ethernet
+type 0x8864).
+Note that the first \fBpppoes\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a PPPoE session packet.
+.IP
+For example:
+.in +.5i
+.nf
+\fBpppoes && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in PPPoE.
+.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBip proto \fIp\fR\fB or ip6 proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBiso proto \fIprotocol\fR"
+True if the packet is an OSI packet of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBclnp\fP, \fBesis\fP, or \fBisis\fP.
+.IP "\fBclnp\fR, \fBesis\fR, \fBisis\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBiso proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBl1\fR, \fBl2\fR, \fBiih\fR, \fBlsp\fR, \fBsnp\fR, \fBcsnp\fR, \fBpsnp\fR"
+Abbreviations for IS-IS PDU types.
+.IP "\fBvpi\fP \fIn\fR
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual path identifier of
+.IR n .
+.IP "\fBvci\fP \fIn\fR
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual channel identifier of
+.IR n .
+.IP \fBlane\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an ATM LANE packet.
+Note that the first \fBlane\fR keyword encountered in \fIexpression\fR
+changes the tests done in the remainder of \fIexpression\fR
+on the assumption that the packet is either a LANE emulated Ethernet
+packet or a LANE LE Control packet. If \fBlane\fR isn't specified, the
+tests are done under the assumption that the packet is an
+LLC-encapsulated packet.
+.IP \fBllc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an LLC-encapsulated packet.
+.IP \fBoamf4s\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment OAM F4 flow cell (VPI=0 & VCI=3).
+.IP \fBoamf4e\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an end-to-end OAM F4 flow cell (VPI=0 & VCI=4).
+.IP \fBoamf4\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBoam\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBmetac\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit (VPI=0 & VCI=1).
+.IP \fBbcc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a broadcast signaling circuit (VPI=0 & VCI=2).
+.IP \fBsc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit (VPI=0 & VCI=5).
+.IP \fBilmic\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on an ILMI circuit (VPI=0 & VCI=16).
+.IP \fBconnectmsg\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Connect Ack, Release, or Release Done message.
+.IP \fBmetaconnect\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Release, or Release Done message.
+.IP "\fIexpr relop expr\fR"
+True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =,
+!=, and \fIexpr\fR is an arithmetic expression composed of integer
+constants (expressed in standard C syntax), the normal binary operators
+[+, -, *, /, &, |, <<, >>], a length operator, and special packet data
+accessors. Note that all comparisons are unsigned, so that, for example,
+0x80000000 and 0xffffffff are > 0.
+To access
+data inside the packet, use the following syntax:
+.in +.5i
+.nf
+\fIproto\fB [ \fIexpr\fB : \fIsize\fB ]\fR
+.fi
+.in -.5i
+\fIProto\fR is one of \fBether, fddi, tr, wlan, ppp, slip, link,
+ip, arp, rarp, tcp, udp, icmp, ip6\fR or \fBradio\fR, and
+indicates the protocol layer for the index operation.
+(\fBether, fddi, wlan, tr, ppp, slip\fR and \fBlink\fR all refer to the
+link layer. \fBradio\fR refers to the "radio header" added to some
+802.11 captures.)
+Note that \fItcp, udp\fR and other upper-layer protocol types only
+apply to IPv4, not IPv6 (this will be fixed in the future).
+The byte offset, relative to the indicated protocol layer, is
+given by \fIexpr\fR.
+\fISize\fR is optional and indicates the number of bytes in the
+field of interest; it can be either one, two, or four, and defaults to one.
+The length operator, indicated by the keyword \fBlen\fP, gives the
+length of the packet.
+
+For example, `\fBether[0] & 1 != 0\fP' catches all multicast traffic.
+The expression `\fBip[0] & 0xf != 5\fP'
+catches all IPv4 packets with options.
+The expression
+`\fBip[6:2] & 0x1fff = 0\fP'
+catches only unfragmented IPv4 datagrams and frag zero of fragmented
+IPv4 datagrams.
+This check is implicitly applied to the \fBtcp\fP and \fBudp\fP
+index operations.
+For instance, \fBtcp[0]\fP always means the first
+byte of the TCP \fIheader\fP, and never means the first byte of an
+intervening fragment.
+
+Some offsets and field values may be expressed as names rather than
+as numeric values.
+The following protocol header field offsets are
+available: \fBicmptype\fP (ICMP type field), \fBicmpcode\fP (ICMP
+code field), and \fBtcpflags\fP (TCP flags field).
+
+The following ICMP type field values are available: \fBicmp-echoreply\fP,
+\fBicmp-unreach\fP, \fBicmp-sourcequench\fP, \fBicmp-redirect\fP,
+\fBicmp-echo\fP, \fBicmp-routeradvert\fP, \fBicmp-routersolicit\fP,
+\fBicmp-timxceed\fP, \fBicmp-paramprob\fP, \fBicmp-tstamp\fP,
+\fBicmp-tstampreply\fP, \fBicmp-ireq\fP, \fBicmp-ireqreply\fP,
+\fBicmp-maskreq\fP, \fBicmp-maskreply\fP.
+
+The following TCP flags field values are available: \fBtcp-fin\fP,
+\fBtcp-syn\fP, \fBtcp-rst\fP, \fBtcp-push\fP,
+\fBtcp-ack\fP, \fBtcp-urg\fP.
+.LP
+Primitives may be combined using:
+.IP
+A parenthesized group of primitives and operators
+(parentheses are special to the Shell and must be escaped).
+.IP
+Negation (`\fB!\fP' or `\fBnot\fP').
+.IP
+Concatenation (`\fB&&\fP' or `\fBand\fP').
+.IP
+Alternation (`\fB||\fP' or `\fBor\fP').
+.LP
+Negation has highest precedence.
+Alternation and concatenation have equal precedence and associate
+left to right.
+Note that explicit \fBand\fR tokens, not juxtaposition,
+are now required for concatenation.
+.LP
+If an identifier is given without a keyword, the most recent keyword
+is assumed.
+For example,
+.in +.5i
+.nf
+\fBnot host vs and ace\fR
+.fi
+.in -.5i
+is short for
+.in +.5i
+.nf
+\fBnot host vs and host ace\fR
+.fi
+.in -.5i
+which should not be confused with
+.in +.5i
+.nf
+\fBnot ( host vs or ace )\fR
+.fi
+.in -.5i
+.SH EXAMPLES
+.LP
+To select all packets arriving at or departing from \fIsundown\fP:
+.RS
+.nf
+\fBhost sundown\fP
+.fi
+.RE
+.LP
+To select traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR:
+.RS
+.nf
+\fBhost helios and \\( hot or ace \\)\fP
+.fi
+.RE
+.LP
+To select all IP packets between \fIace\fR and any host except \fIhelios\fR:
+.RS
+.nf
+\fBip host ace and not helios\fP
+.fi
+.RE
+.LP
+To select all traffic between local hosts and hosts at Berkeley:
+.RS
+.nf
+.B
+net ucb-ether
+.fi
+.RE
+.LP
+To select all ftp traffic through internet gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and (port ftp or ftp-data)
+.fi
+.RE
+.LP
+To select traffic neither sourced from nor destined for local hosts
+(if you gateway to one other net, this stuff should never make it
+onto your local net).
+.RS
+.nf
+.B
+ip and not net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select the start and end packets (the SYN and FIN packets) of each
+TCP conversation that involves a non-local host.
+.RS
+.nf
+.B
+tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select all IPv4 HTTP packets to and from port 80, i.e. print only
+packets that contain data, not, for example, SYN and FIN packets and
+ACK-only packets. (IPv6 is left as an exercise for the reader.)
+.RS
+.nf
+.B
+tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)
+.fi
+.RE
+.LP
+To select IP packets longer than 576 bytes sent through gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and ip[2:2] > 576
+.fi
+.RE
+.LP
+To select IP broadcast or multicast packets that were
+.I not
+sent via Ethernet broadcast or multicast:
+.RS
+.nf
+.B
+ether[0] & 1 = 0 and ip[16] >= 224
+.fi
+.RE
+.LP
+To select all ICMP packets that are not echo requests/replies (i.e., not
+ping packets):
+.RS
+.nf
+.B
+icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply
+.fi
+.RE
+.SH "SEE ALSO"
+pcap(3PCAP)
+.SH AUTHORS
+The original authors are:
+.LP
+Van Jacobson,
+Craig Leres and
+Steven McCanne, all of the
+Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
+.LP
+It is currently being maintained by tcpdump.org.
+.LP
+The current version of libpcap is available via http:
+.LP
+.RS
+.I http://www.tcpdump.org/
+.RE
+.LP
+The original distribution is available via anonymous ftp:
+.LP
+.RS
+.I ftp://ftp.ee.lbl.gov/tcpdump.tar.Z
+.RE
+.SH BUGS
+Please send problems, bugs, questions, desirable enhancements, etc. to:
+.LP
+.RS
+tcpdump-workers@lists.tcpdump.org
+.RE
+.LP
+Filter expressions on fields other than those in Token Ring headers will
+not correctly handle source-routed Token Ring packets.
+.LP
+Filter expressions on fields other than those in 802.11 headers will not
+correctly handle 802.11 data packets with both To DS and From DS set.
+.LP
+.BR "ip6 proto"
+should chase header chain, but at this moment it does not.
+.BR "ip6 protochain"
+is supplied for this behavior.
+.LP
+Arithmetic expression against transport layer headers, like \fBtcp[0]\fP,
+does not work against IPv6 packets.
+It only looks at IPv4 packets.
diff --git a/contrib/libpcap/pcap-int.h b/contrib/libpcap/pcap-int.h
index aad7369..3a50406 100644
--- a/contrib/libpcap/pcap-int.h
+++ b/contrib/libpcap/pcap-int.h
@@ -31,17 +31,21 @@
* SUCH DAMAGE.
*
* $FreeBSD$
- * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.68.2.11 2007/06/22 06:43:58 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.85.2.9 2008-09-16 00:21:08 guy Exp $ (LBL)
*/
#ifndef pcap_int_h
-#define pcap_int_h
+#define pcap_int_h
+
+#include <pcap/pcap.h>
#ifdef __cplusplus
extern "C" {
#endif
-#include <pcap.h>
+#ifdef HAVE_LIBDLPI
+#include <libdlpi.h>
+#endif
#ifdef WIN32
#include <Packet32.h>
@@ -52,6 +56,23 @@ extern "C" {
#include <io.h>
#endif
+#if (defined(_MSC_VER) && (_MSC_VER <= 1200)) /* we are compiling with Visual Studio 6, that doesn't support the LL suffix*/
+
+/*
+ * Swap byte ordering of unsigned long long timestamp on a big endian
+ * machine.
+ */
+#define SWAPLL(ull) ((ull & 0xff00000000000000) >> 56) | \
+ ((ull & 0x00ff000000000000) >> 40) | \
+ ((ull & 0x0000ff0000000000) >> 24) | \
+ ((ull & 0x000000ff00000000) >> 8) | \
+ ((ull & 0x00000000ff000000) << 8) | \
+ ((ull & 0x0000000000ff0000) << 24) | \
+ ((ull & 0x000000000000ff00) << 40) | \
+ ((ull & 0x00000000000000ff) << 56)
+
+#else /* A recent Visual studio compiler or not VC */
+
/*
* Swap byte ordering of unsigned long long timestamp on a big endian
* machine.
@@ -65,6 +86,8 @@ extern "C" {
((ull & 0x000000000000ff00LL) << 40) | \
((ull & 0x00000000000000ffLL) << 56)
+#endif /* _MSC_VER */
+
/*
* Savefile
*/
@@ -74,16 +97,22 @@ typedef enum {
MAYBE_SWAPPED
} swapped_type_t;
+/*
+ * Used when reading a savefile.
+ */
struct pcap_sf {
FILE *rfile;
int swapped;
- int hdrsize;
+ size_t hdrsize;
swapped_type_t lengths_swapped;
int version_major;
int version_minor;
u_char *base;
};
+/*
+ * Used when doing a live capture.
+ */
struct pcap_md {
struct pcap_stat stat;
/*XXX*/
@@ -94,22 +123,25 @@ struct pcap_md {
long TotMissed; /* missed by i/f during this run */
long OrigMissed; /* missed by i/f before this run */
char *device; /* device name */
+ int timeout; /* timeout for buffering */
+ int must_clear; /* stuff we must clear when we close */
+ struct pcap *next; /* list of open pcaps that need stuff cleared on close */
#ifdef linux
int sock_packet; /* using Linux 2.0 compatible interface */
- int timeout; /* timeout specified to pcap_open_live */
- int clear_promisc; /* must clear promiscuous mode when we close */
int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */
int ifindex; /* interface index of device we're bound to */
int lo_ifindex; /* interface index of the loopback device */
- struct pcap *next; /* list of open promiscuous sock_packet pcaps */
u_int packets_read; /* count of packets read with recvfrom() */
-#endif
+ bpf_u_int32 oldmode; /* mode to restore when turning monitor mode off */
+ u_int tp_version; /* version of tpacket_hdr for mmaped ring */
+ u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */
+#endif /* linux */
#ifdef HAVE_DAG_API
#ifdef HAVE_DAG_STREAMS_API
u_char *dag_mem_bottom; /* DAG card current memory bottom pointer */
u_char *dag_mem_top; /* DAG card current memory top pointer */
-#else
+#else /* HAVE_DAG_STREAMS_API */
void *dag_mem_base; /* DAG card memory base address */
u_int dag_mem_bottom; /* DAG card current memory bottom offset */
u_int dag_mem_top; /* DAG card current memory top offset */
@@ -121,6 +153,41 @@ struct pcap_md {
* Same as in linux above, introduce
* generally? */
#endif /* HAVE_DAG_API */
+#ifdef HAVE_ZEROCOPY_BPF
+ /*
+ * Zero-copy read buffer -- for zero-copy BPF. 'buffer' above will
+ * alternative between these two actual mmap'd buffers as required.
+ * As there is a header on the front size of the mmap'd buffer, only
+ * some of the buffer is exposed to libpcap as a whole via bufsize;
+ * zbufsize is the true size. zbuffer tracks the current zbuf
+ * assocated with buffer so that it can be used to decide which the
+ * next buffer to read will be.
+ */
+ u_char *zbuf1, *zbuf2, *zbuffer;
+ u_int zbufsize;
+ u_int zerocopy;
+ u_int interrupted;
+ struct timespec firstsel;
+ /*
+ * If there's currently a buffer being actively processed, then it is
+ * referenced here; 'buffer' is also pointed at it, but offset by the
+ * size of the header.
+ */
+ struct bpf_zbuf_header *bzh;
+#endif /* HAVE_ZEROCOPY_BPF */
+};
+
+/*
+ * Stuff to clear when we close.
+ */
+#define MUST_CLEAR_PROMISC 0x00000001 /* promiscuous mode */
+#define MUST_CLEAR_RFMON 0x00000002 /* rfmon (monitor) mode */
+
+struct pcap_opt {
+ int buffer_size;
+ char *source;
+ int promisc;
+ int rfmon;
};
/*
@@ -136,21 +203,44 @@ struct pcap_md {
#define PCAP_FDDIPAD 3
#endif
+typedef int (*activate_op_t)(pcap_t *);
+typedef int (*can_set_rfmon_op_t)(pcap_t *);
+typedef int (*read_op_t)(pcap_t *, int cnt, pcap_handler, u_char *);
+typedef int (*inject_op_t)(pcap_t *, const void *, size_t);
+typedef int (*setfilter_op_t)(pcap_t *, struct bpf_program *);
+typedef int (*setdirection_op_t)(pcap_t *, pcap_direction_t);
+typedef int (*set_datalink_op_t)(pcap_t *, int);
+typedef int (*getnonblock_op_t)(pcap_t *, char *);
+typedef int (*setnonblock_op_t)(pcap_t *, int, char *);
+typedef int (*stats_op_t)(pcap_t *, struct pcap_stat *);
+#ifdef WIN32
+typedef int (*setbuff_op_t)(pcap_t *, int);
+typedef int (*setmode_op_t)(pcap_t *, int);
+typedef int (*setmintocopy_op_t)(pcap_t *, int);
+#endif
+typedef void (*cleanup_op_t)(pcap_t *);
+
struct pcap {
#ifdef WIN32
ADAPTER *adapter;
LPPACKET Packet;
- int timeout;
int nonblock;
#else
int fd;
int selectable_fd;
int send_fd;
#endif /* WIN32 */
+
+#ifdef HAVE_LIBDLPI
+ dlpi_handle_t dlpi_hd;
+#endif
int snapshot;
- int linktype;
+ int linktype; /* Network linktype */
+ int linktype_ext; /* Extended information stored in the linktype field of a file */
int tzoff; /* timezone offset */
int offset; /* offset for proper alignment */
+ int activated; /* true if the capture is really started */
+ int oldstyle; /* if we're opening with pcap_open_live() */
int break_loop; /* flag set to force break from packet-reading loop */
@@ -159,12 +249,12 @@ struct pcap {
#endif
#ifdef MSDOS
- int inter_packet_wait; /* offline: wait between packets */
void (*wait_proc)(void); /* call proc while waiting */
#endif
struct pcap_sf sf;
struct pcap_md md;
+ struct pcap_opt opt;
/*
* Read buffer -- for file descriptor read buffer model.
@@ -209,15 +299,27 @@ struct pcap {
/*
* Methods.
*/
- int (*read_op)(pcap_t *, int cnt, pcap_handler, u_char *);
- int (*inject_op)(pcap_t *, const void *, size_t);
- int (*setfilter_op)(pcap_t *, struct bpf_program *);
- int (*setdirection_op)(pcap_t *, pcap_direction_t);
- int (*set_datalink_op)(pcap_t *, int);
- int (*getnonblock_op)(pcap_t *, char *);
- int (*setnonblock_op)(pcap_t *, int, char *);
- int (*stats_op)(pcap_t *, struct pcap_stat *);
- void (*close_op)(pcap_t *);
+ activate_op_t activate_op;
+ can_set_rfmon_op_t can_set_rfmon_op;
+ read_op_t read_op;
+ inject_op_t inject_op;
+ setfilter_op_t setfilter_op;
+ setdirection_op_t setdirection_op;
+ set_datalink_op_t set_datalink_op;
+ getnonblock_op_t getnonblock_op;
+ setnonblock_op_t setnonblock_op;
+ stats_op_t stats_op;
+
+#ifdef WIN32
+ /*
+ * These are, at least currently, specific to the Win32 NPF
+ * driver.
+ */
+ setbuff_op_t setbuff_op;
+ setmode_op_t setmode_op;
+ setmintocopy_op_t setmintocopy_op;
+#endif
+ cleanup_op_t cleanup_op;
/*
* Placeholder for filter code if bpf not in kernel.
@@ -256,8 +358,8 @@ struct pcap_timeval {
*
* introduce a new structure for the new format;
*
- * send mail to "tcpdump-workers@tcpdump.org", requesting a new
- * magic number for your new capture file format, and, when
+ * send mail to "tcpdump-workers@lists.tcpdump.org", requesting
+ * a new magic number for your new capture file format, and, when
* you get the new magic number, put it in "savefile.c";
*
* use that magic number for save files with the changed record
@@ -267,9 +369,12 @@ struct pcap_timeval {
* the old record header as well as files with the new record header
* (using the magic number to determine the header format).
*
- * Then supply the changes to "patches@tcpdump.org", so that future
- * versions of libpcap and programs that use it (such as tcpdump) will
- * be able to read your new capture file format.
+ * Then supply the changes as a patch at
+ *
+ * http://sourceforge.net/projects/libpcap/
+ *
+ * so that future versions of libpcap and programs that use it (such as
+ * tcpdump) will be able to read your new capture file format.
*/
struct pcap_sf_pkthdr {
@@ -324,7 +429,13 @@ int pcap_getnonblock_fd(pcap_t *, char *);
int pcap_setnonblock_fd(pcap_t *p, int, char *);
#endif
-void pcap_close_common(pcap_t *);
+pcap_t *pcap_create_common(const char *, char *);
+int pcap_do_addexit(pcap_t *);
+void pcap_add_to_pcaps_to_close(pcap_t *);
+void pcap_remove_from_pcaps_to_close(pcap_t *);
+void pcap_cleanup_live_common(pcap_t *);
+int pcap_not_initialized(pcap_t *);
+int pcap_check_activated(pcap_t *);
/*
* Internal interfaces for "pcap_findalldevs()".
diff --git a/contrib/libpcap/pcap-libdlpi.c b/contrib/libpcap/pcap-libdlpi.c
new file mode 100644
index 0000000..b61e8ec
--- /dev/null
+++ b/contrib/libpcap/pcap-libdlpi.c
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * 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: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * This code contributed by Sagun Shakya (sagun.shakya@sun.com)
+ */
+/*
+ * Packet capture routines for DLPI using libdlpi under SunOS 5.11.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-libdlpi.c,v 1.1.2.6 2008-04-14 20:41:52 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/bufmod.h>
+#include <sys/stream.h>
+#include <libdlpi.h>
+#include <errno.h>
+#include <memory.h>
+#include <stropts.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcap-int.h"
+#include "dlpisubs.h"
+
+/* Forwards. */
+static int pcap_read_libdlpi(pcap_t *, int, pcap_handler, u_char *);
+static int pcap_inject_libdlpi(pcap_t *, const void *, size_t);
+static void pcap_close_libdlpi(pcap_t *);
+static void pcap_libdlpi_err(const char *, const char *, int, char *);
+
+/*
+ * list_interfaces() will list all the network links that are
+ * available on a system.
+ */
+static boolean_t list_interfaces(const char *, void *);
+
+typedef struct linknamelist {
+ char linkname[DLPI_LINKNAME_MAX];
+ struct linknamelist *lnl_next;
+} linknamelist_t;
+
+typedef struct linkwalk {
+ linknamelist_t *lw_list;
+ int lw_err;
+} linkwalk_t;
+
+/*
+ * The caller of this function should free the memory allocated
+ * for each linknamelist_t "entry" allocated.
+ */
+static boolean_t
+list_interfaces(const char *linkname, void *arg)
+{
+ linkwalk_t *lwp = arg;
+ linknamelist_t *entry;
+
+ if ((entry = calloc(1, sizeof(linknamelist_t))) == NULL) {
+ lwp->lw_err = ENOMEM;
+ return (B_TRUE);
+ }
+ (void) strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX);
+
+ if (lwp->lw_list == NULL) {
+ lwp->lw_list = entry;
+ } else {
+ entry->lnl_next = lwp->lw_list;
+ lwp->lw_list = entry;
+ }
+
+ return (B_FALSE);
+}
+
+static int
+pcap_activate_libdlpi(pcap_t *p)
+{
+ int retv;
+ dlpi_handle_t dh;
+ dlpi_info_t dlinfo;
+ int err = PCAP_ERROR;
+
+ /*
+ * Enable Solaris raw and passive DLPI extensions;
+ * dlpi_open() will not fail if the underlying link does not support
+ * passive mode. See dlpi(7P) for details.
+ */
+ retv = dlpi_open(p->opt.source, &dh, DLPI_RAW|DLPI_PASSIVE);
+ if (retv != DLPI_SUCCESS) {
+ if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK)
+ err = PCAP_ERROR_NO_SUCH_DEVICE;
+ else if (retv == DLPI_SYSERR && errno == EACCES)
+ err = PCAP_ERROR_PERM_DENIED;
+ pcap_libdlpi_err(p->opt.source, "dlpi_open", retv,
+ p->errbuf);
+ return (err);
+ }
+ p->dlpi_hd = dh;
+
+ if (p->opt.rfmon) {
+ /*
+ * This device exists, but we don't support monitor mode
+ * any platforms that support DLPI.
+ */
+ err = PCAP_ERROR_RFMON_NOTSUP;
+ goto bad;
+ }
+
+ /* Bind with DLPI_ANY_SAP. */
+ if ((retv = dlpi_bind(p->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
+ pcap_libdlpi_err(p->opt.source, "dlpi_bind", retv, p->errbuf);
+ goto bad;
+ }
+
+ /* Enable promiscuous mode. */
+ if (p->opt.promisc) {
+ retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_PHYS);
+ if (retv != DLPI_SUCCESS) {
+ pcap_libdlpi_err(p->opt.source,
+ "dlpi_promisc(PHYSICAL)", retv, p->errbuf);
+ goto bad;
+ }
+ } else {
+ /* Try to enable multicast. */
+ retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_MULTI);
+ if (retv != DLPI_SUCCESS) {
+ pcap_libdlpi_err(p->opt.source, "dlpi_promisc(MULTI)",
+ retv, p->errbuf);
+ goto bad;
+ }
+ }
+
+ /* Try to enable SAP promiscuity. */
+ if ((retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_SAP)) != DLPI_SUCCESS) {
+ if (!promisc) {
+ pcap_libdlpi_err(p->opt.source, "dlpi_promisc(SAP)",
+ retv, p->errbuf);
+ goto bad;
+ }
+
+ /* Not fatal, since the DL_PROMISC_PHYS mode worked. */
+ fprintf(stderr, "WARNING: dlpi_promisc(SAP) failed on"
+ " %s:(%s)\n", p->opt.source, dlpi_strerror(retv));
+ }
+
+ /* Determine link type. */
+ if ((retv = dlpi_info(p->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
+ pcap_libdlpi_err(p->opt.source, "dlpi_info", retv, p->errbuf);
+ goto bad;
+ }
+
+ if (pcap_process_mactype(p, dlinfo.di_mactype) != 0)
+ goto bad;
+
+ p->fd = dlpi_fd(p->dlpi_hd);
+
+ /* Push and configure bufmod. */
+ if (pcap_conf_bufmod(p, snaplen, p->md.timeout) != 0)
+ goto bad;
+
+ /*
+ * Flush the read side.
+ */
+ if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s",
+ pcap_strerror(errno));
+ goto bad;
+ }
+
+ /* Allocate data buffer. */
+ if (pcap_alloc_databuf(p) != 0)
+ goto bad;
+
+ /*
+ * "p->fd" is a FD for a STREAMS device, so "select()" and
+ * "poll()" should work on it.
+ */
+ p->selectable_fd = p->fd;
+
+ p->read_op = pcap_read_libdlpi;
+ p->inject_op = pcap_inject_libdlpi;
+ p->setfilter_op = install_bpf_program; /* No kernel filtering */
+ p->setdirection_op = NULL; /* Not implemented */
+ p->set_datalink_op = NULL; /* Can't change data link type */
+ p->getnonblock_op = pcap_getnonblock_fd;
+ p->setnonblock_op = pcap_setnonblock_fd;
+ p->stats_op = pcap_stats_dlpi;
+ p->cleanup_op = pcap_cleanup_libdlpi;
+
+ return (0);
+bad:
+ pcap_cleanup_libdlpi(p);
+ return (err);
+}
+
+/*
+ * In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find
+ * network links that are plumbed and are up. dlpi_walk(3DLPI) will find
+ * additional network links present in the system.
+ */
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+{
+ int retv = 0;
+
+ linknamelist_t *entry, *next;
+ linkwalk_t lw = {NULL, 0};
+ int save_errno;
+
+ /* dlpi_walk() for loopback will be added here. */
+
+ dlpi_walk(list_interfaces, &lw, 0);
+
+ if (lw.lw_err != 0) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "dlpi_walk: %s", pcap_strerror(lw.lw_err));
+ retv = -1;
+ goto done;
+ }
+
+ /* Add linkname if it does not exist on the list. */
+ for (entry = lw.lw_list; entry != NULL; entry = entry->lnl_next) {
+ if (pcap_add_if(alldevsp, entry->linkname, 0, NULL, errbuf) < 0)
+ retv = -1;
+ }
+done:
+ save_errno = errno;
+ for (entry = lw.lw_list; entry != NULL; entry = next) {
+ next = entry->lnl_next;
+ free(entry);
+ }
+ errno = save_errno;
+
+ return (retv);
+}
+
+/*
+ * Read data received on DLPI handle. Returns -2 if told to terminate, else
+ * returns the number of packets read.
+ */
+static int
+pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user)
+{
+ int len;
+ u_char *bufp;
+ size_t msglen;
+ int retv;
+
+ len = p->cc;
+ if (len != 0) {
+ bufp = p->bp;
+ goto process_pkts;
+ }
+ do {
+ /* Has "pcap_breakloop()" been called? */
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that it has,
+ * and return -2 to indicate that we were told to
+ * break out of the loop.
+ */
+ p->break_loop = 0;
+ return (-2);
+ }
+
+ msglen = p->bufsize;
+ bufp = p->buffer + p->offset;
+
+ retv = dlpi_recv(p->dlpi_hd, NULL, NULL, bufp,
+ &msglen, -1, NULL);
+ if (retv != DLPI_SUCCESS) {
+ /*
+ * This is most likely a call to terminate out of the
+ * loop. So, do not return an error message, instead
+ * check if "pcap_breakloop()" has been called above.
+ */
+ if (retv == DL_SYSERR && errno == EINTR) {
+ len = 0;
+ continue;
+ }
+ pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd),
+ "dlpi_recv", retv, p->errbuf);
+ return (-1);
+ }
+ len = msglen;
+ } while (len == 0);
+
+process_pkts:
+ return (pcap_process_pkts(p, callback, user, count, bufp, len));
+}
+
+static int
+pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size)
+{
+ int retv;
+
+ retv = dlpi_send(p->dlpi_hd, NULL, 0, buf, size, NULL);
+ if (retv != DLPI_SUCCESS) {
+ pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd), "dlpi_send", retv,
+ p->errbuf);
+ return (-1);
+ }
+ /*
+ * dlpi_send(3DLPI) does not provide a way to return the number of
+ * bytes sent on the wire. Based on the fact that DLPI_SUCCESS was
+ * returned we are assuming 'size' bytes were sent.
+ */
+ return (size);
+}
+
+/*
+ * Close dlpi handle.
+ */
+static void
+pcap_cleanup_libdlpi(pcap_t *p)
+{
+ if (p->dlpi_hd != NULL) {
+ dlpi_close(p->dlpi_hd);
+ p->dlpi_hd = NULL;
+ p->fd = -1;
+ }
+ pcap_cleanup_live_common(p);
+}
+
+/*
+ * Write error message to buffer.
+ */
+static void
+pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
+{
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
+ func, linkname, dlpi_strerror(err));
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_libdlpi;
+ return (p);
+}
diff --git a/contrib/libpcap/pcap-linktype.manmisc b/contrib/libpcap/pcap-linktype.manmisc
new file mode 100644
index 0000000..ed9dba4
--- /dev/null
+++ b/contrib/libpcap/pcap-linktype.manmisc
@@ -0,0 +1,282 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap-linktype.manmisc.in,v 1.1.2.4 2008-10-27 22:52:05 guy Exp $
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-LINKTYPE 7 "23 October 2008"
+.SH NAME
+pcap-linktype \- link-layer header types supported by libpcap
+.SH DESCRIPTION
+For a live capture or ``savefile'', libpcap supplies, as the return
+value of the
+.BR pcap_datalink (3PCAP)
+routine, a value that indicates the type of link-layer header at the
+beginning of the packets it provides. This is not necessarily the type
+of link-layer header that the packets being captured have on the network
+from which they're being captured; for example, packets from an IEEE
+802.11 network might be provided by libpcap with Ethernet headers that
+the network adapter or the network adapter driver generates from the
+802.11 headers. The names for those values begin with
+.BR DLT_ ,
+so they are sometimes called "DLT_ values".
+.PP
+The values stored in the link-layer header type field in the savefile
+header are, in most but not all cases, the same as the values returned
+by
+.BR pcap_datalink() .
+The names for those values begin with
+.BR LINKTYPE_ .
+.PP
+The link-layer header types supported by libpcap are listed here. The
+value corresponding to
+.B LINKTYPE_
+names are given; the value corresponding to
+.B DLT_
+values are, in some cases, platform dependent, and are not given;
+applications should check for particular
+.B DLT_
+values by name.
+.RS 5
+.TP 5
+.BR DLT_NULL "; " LINKTYPE_NULL = 0
+BSD loopback encapsulation; the link layer header is a 4-byte field, in
+.I host
+byte order, containing a PF_ value from
+.B socket.h
+for the network-layer protocol of the packet.
+.IP
+Note that ``host byte order'' is the byte order of the machine on which
+the packets are captured, and the PF_ values are for the OS of the
+machine on which the packets are captured; if a live capture is being
+done, ``host byte order'' is the byte order of the machine capturing the
+packets, and the PF_ values are those of the OS of the machine capturing
+the packets, but if a ``savefile'' is being read, the byte order and PF_
+values are
+.I not
+necessarily those of the machine reading the capture file.
+.TP 5
+.BR DLT_EN10MB "; " LINKTYPE_ETHERNET = 1
+Ethernet (10Mb, 100Mb, 1000Mb, and up); the
+.B 10MB
+in the
+.B DLT_
+name is historical.
+.TP 5
+.BR DLT_IEEE802 "; " LINKTYPE_TOKEN_RING = 6
+IEEE 802.5 Token Ring; the
+.B IEEE802
+in the
+.B DLT_
+name is historical.
+.TP 5
+.BR DLT_ARCNET "; " LINKTYPE_ARCNET = 7
+ARCNET
+.TP 5
+.BR DLT_SLIP "; " LINKTYPE_SLIP = 8
+SLIP; the link layer header contains, in order:
+.RS 10
+.LP
+a 1-byte flag, which is 0 for packets received by the machine and 1 for
+packets sent by the machine;
+.LP
+a 1-byte field, the upper 4 bits of which indicate the type of packet,
+as per RFC 1144:
+.RS 5
+.TP 5
+0x40
+an unmodified IP datagram (TYPE_IP);
+.TP 5
+0x70
+an uncompressed-TCP IP datagram (UNCOMPRESSED_TCP), with that byte being
+the first byte of the raw IP header on the wire, containing the
+connection number in the protocol field;
+.TP 5
+0x80
+a compressed-TCP IP datagram (COMPRESSED_TCP), with that byte being the
+first byte of the compressed TCP/IP datagram header;
+.RE
+.LP
+for UNCOMPRESSED_TCP, the rest of the modified IP header, and for
+COMPRESSED_TCP, the compressed TCP/IP datagram header;
+.RE
+.RS 5
+.LP
+for a total of 16 bytes; the uncompressed IP datagram follows the header.
+.RE
+.TP 5
+.BR DLT_PPP "; " LINKTYPE_PPP = 9
+PPP; if the first 2 bytes are 0xff and 0x03, it's PPP in HDLC-like
+framing, with the PPP header following those two bytes, otherwise it's
+PPP without framing, and the packet begins with the PPP header.
+.TP 5
+.BR DLT_FDDI "; " LINKTYPE_FDDI = 10
+FDDI
+.TP 5
+.BR DLT_ATM_RFC1483 "; " LINKTYPE_ATM_RFC1483 = 100
+RFC 1483 LLC/SNAP-encapsulated ATM; the packet begins with an IEEE 802.2
+LLC header.
+.TP 5
+.BR DLT_RAW "; " LINKTYPE_RAW = 101
+raw IP; the packet begins with an IP header.
+.TP 5
+.BR DLT_PPP_SERIAL "; " LINKTYPE_PPP_HDLC = 50
+PPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC
+framing, as per section 4.3.1 of RFC 1547; the first byte will be 0xFF
+for PPP in HDLC-like framing, and will be 0x0F or 0x8F for Cisco PPP
+with HDLC framing.
+.TP 5
+.BR DLT_PPP_ETHER "; " LINKTYPE_PPP_ETHER = 51
+PPPoE; the packet begins with a PPPoE header, as per RFC 2516.
+.TP 5
+.BR DLT_C_HDLC "; " LINKTYPE_C_HDLC = 104
+Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547.
+.TP 5
+.BR DLT_IEEE802_11 "; " LINKTYPE_IEEE802_11 = 105
+IEEE 802.11 wireless LAN
+.TP 5
+.BR DLT_FRELAY "; " LINKTYPE_FRELAY = 107
+Frame Relay
+.TP 5
+.BR DLT_LOOP "; " LINKTYPE_LOOP = 108
+OpenBSD loopback encapsulation; the link layer header is a 4-byte field, in
+.I network
+byte order, containing a PF_ value from OpenBSD's
+.B socket.h
+for the network-layer protocol of the packet.
+.IP
+Note that, if a ``savefile'' is being read, those PF_ values are
+.I not
+necessarily those of the machine reading the capture file.
+.TP 5
+.BR DLT_LINUX_SLL "; " LINKTYPE_LINUX_SLL = 113
+Linux "cooked" capture encapsulation; the link layer header contains, in
+order:
+.RS 10
+.LP
+a 2-byte "packet type", in network byte order, which is one of:
+.RS 5
+.TP 5
+0
+packet was sent to us by somebody else
+.TP 5
+1
+packet was broadcast by somebody else
+.TP 5
+2
+packet was multicast, but not broadcast, by somebody else
+.TP 5
+3
+packet was sent by somebody else to somebody else
+.TP 5
+4
+packet was sent by us
+.RE
+.LP
+a 2-byte field, in network byte order, containing a Linux ARPHRD_ value
+for the link layer device type;
+.LP
+a 2-byte field, in network byte order, containing the length of the
+link layer address of the sender of the packet (which could be 0);
+.LP
+an 8-byte field containing that number of bytes of the link layer header
+(if there are more than 8 bytes, only the first 8 are present);
+.LP
+a 2-byte field containing an Ethernet protocol type, in network byte
+order, or containing 1 for Novell 802.3 frames without an 802.2 LLC
+header or 4 for frames beginning with an 802.2 LLC header.
+.RE
+.TP 5
+.BR DLT_LTALK "; " LINKTYPE_LTALK = 104
+Apple LocalTalk; the packet begins with an AppleTalk LLAP header.
+.TP 5
+.BR DLT_PFLOG "; " LINKTYPE_PFLOG = 117
+OpenBSD pflog; the link layer header contains a
+.B "struct pfloghdr"
+structure, as defined by the host on which the file was saved. (This
+differs from operating system to operating system and release to
+release; there is nothing in the file to indicate what the layout of
+that structure is.)
+.TP 5
+.BR DLT_PRISM_HEADER "; " LINKTYPE_PRISM_HEADER = 119
+Prism monitor mode information followed by an 802.11 header.
+.TP 5
+.BR DLT_IP_OVER_FC "; " LINKTYPE_IP_OVER_FC = 122
+RFC 2625 IP-over-Fibre Channel, with the link-layer header being the
+Network_Header as described in that RFC.
+.TP 5
+.BR DLT_SUNATM "; " LINKTYPE_SUNATM = 123
+SunATM devices; the link layer header contains, in order:
+.RS 10
+.LP
+a 1-byte flag field, containing a direction flag in the uppermost bit,
+which is set for packets transmitted by the machine and clear for
+packets received by the machine, and a 4-byte traffic type in the
+low-order 4 bits, which is one of:
+.RS 5
+.TP 5
+0
+raw traffic
+.TP 5
+1
+LANE traffic
+.TP 5
+2
+LLC-encapsulated traffic
+.TP 5
+3
+MARS traffic
+.TP 5
+4
+IFMP traffic
+.TP 5
+5
+ILMI traffic
+.TP 5
+6
+Q.2931 traffic
+.RE
+.LP
+a 1-byte VPI value;
+.LP
+a 2-byte VCI field, in network byte order.
+.RE
+.TP 5
+.BR DLT_IEEE802_11_RADIO "; " LINKTYPE_IEEE802_11_RADIO = 127
+link-layer information followed by an 802.11 header - see
+http://www.shaftnet.org/~pizza/software/capturefrm.txt for a description
+of the link-layer information.
+.TP 5
+.BR DLT_ARCNET_LINUX "; " LINKTYPE_ARCNET_LINUX = 129
+ARCNET, with no exception frames, reassembled packets rather than raw
+frames, and an extra 16-bit offset field between the destination host
+and type bytes.
+.TP 5
+.BR DLT_LINUX_IRDA "; " LINKTYPE_LINUX_IRDA = 144
+Linux-IrDA packets, with a
+.B DLT_LINUX_SLL
+header followed by the IrLAP header.
+.TP 5
+.BR DLT_LINUX_LAPD "; " LINKTYPE_LINUX_LAPD = 177
+LAPD (Q.921) frames, with a
+.B DLT_LINUX_SLL
+header captured via vISDN.
+.RE
+.SH SEE ALSO
+pcap_datalink(3PCAP)
diff --git a/contrib/libpcap/pcap-linktype.manmisc.in b/contrib/libpcap/pcap-linktype.manmisc.in
new file mode 100644
index 0000000..7d33b7f
--- /dev/null
+++ b/contrib/libpcap/pcap-linktype.manmisc.in
@@ -0,0 +1,282 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap-linktype.manmisc.in,v 1.1.2.4 2008-10-27 22:52:05 guy Exp $
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-LINKTYPE @MAN_MISC_INFO@ "23 October 2008"
+.SH NAME
+pcap-linktype \- link-layer header types supported by libpcap
+.SH DESCRIPTION
+For a live capture or ``savefile'', libpcap supplies, as the return
+value of the
+.BR pcap_datalink (3PCAP)
+routine, a value that indicates the type of link-layer header at the
+beginning of the packets it provides. This is not necessarily the type
+of link-layer header that the packets being captured have on the network
+from which they're being captured; for example, packets from an IEEE
+802.11 network might be provided by libpcap with Ethernet headers that
+the network adapter or the network adapter driver generates from the
+802.11 headers. The names for those values begin with
+.BR DLT_ ,
+so they are sometimes called "DLT_ values".
+.PP
+The values stored in the link-layer header type field in the savefile
+header are, in most but not all cases, the same as the values returned
+by
+.BR pcap_datalink() .
+The names for those values begin with
+.BR LINKTYPE_ .
+.PP
+The link-layer header types supported by libpcap are listed here. The
+value corresponding to
+.B LINKTYPE_
+names are given; the value corresponding to
+.B DLT_
+values are, in some cases, platform dependent, and are not given;
+applications should check for particular
+.B DLT_
+values by name.
+.RS 5
+.TP 5
+.BR DLT_NULL "; " LINKTYPE_NULL = 0
+BSD loopback encapsulation; the link layer header is a 4-byte field, in
+.I host
+byte order, containing a PF_ value from
+.B socket.h
+for the network-layer protocol of the packet.
+.IP
+Note that ``host byte order'' is the byte order of the machine on which
+the packets are captured, and the PF_ values are for the OS of the
+machine on which the packets are captured; if a live capture is being
+done, ``host byte order'' is the byte order of the machine capturing the
+packets, and the PF_ values are those of the OS of the machine capturing
+the packets, but if a ``savefile'' is being read, the byte order and PF_
+values are
+.I not
+necessarily those of the machine reading the capture file.
+.TP 5
+.BR DLT_EN10MB "; " LINKTYPE_ETHERNET = 1
+Ethernet (10Mb, 100Mb, 1000Mb, and up); the
+.B 10MB
+in the
+.B DLT_
+name is historical.
+.TP 5
+.BR DLT_IEEE802 "; " LINKTYPE_TOKEN_RING = 6
+IEEE 802.5 Token Ring; the
+.B IEEE802
+in the
+.B DLT_
+name is historical.
+.TP 5
+.BR DLT_ARCNET "; " LINKTYPE_ARCNET = 7
+ARCNET
+.TP 5
+.BR DLT_SLIP "; " LINKTYPE_SLIP = 8
+SLIP; the link layer header contains, in order:
+.RS 10
+.LP
+a 1-byte flag, which is 0 for packets received by the machine and 1 for
+packets sent by the machine;
+.LP
+a 1-byte field, the upper 4 bits of which indicate the type of packet,
+as per RFC 1144:
+.RS 5
+.TP 5
+0x40
+an unmodified IP datagram (TYPE_IP);
+.TP 5
+0x70
+an uncompressed-TCP IP datagram (UNCOMPRESSED_TCP), with that byte being
+the first byte of the raw IP header on the wire, containing the
+connection number in the protocol field;
+.TP 5
+0x80
+a compressed-TCP IP datagram (COMPRESSED_TCP), with that byte being the
+first byte of the compressed TCP/IP datagram header;
+.RE
+.LP
+for UNCOMPRESSED_TCP, the rest of the modified IP header, and for
+COMPRESSED_TCP, the compressed TCP/IP datagram header;
+.RE
+.RS 5
+.LP
+for a total of 16 bytes; the uncompressed IP datagram follows the header.
+.RE
+.TP 5
+.BR DLT_PPP "; " LINKTYPE_PPP = 9
+PPP; if the first 2 bytes are 0xff and 0x03, it's PPP in HDLC-like
+framing, with the PPP header following those two bytes, otherwise it's
+PPP without framing, and the packet begins with the PPP header.
+.TP 5
+.BR DLT_FDDI "; " LINKTYPE_FDDI = 10
+FDDI
+.TP 5
+.BR DLT_ATM_RFC1483 "; " LINKTYPE_ATM_RFC1483 = 100
+RFC 1483 LLC/SNAP-encapsulated ATM; the packet begins with an IEEE 802.2
+LLC header.
+.TP 5
+.BR DLT_RAW "; " LINKTYPE_RAW = 101
+raw IP; the packet begins with an IP header.
+.TP 5
+.BR DLT_PPP_SERIAL "; " LINKTYPE_PPP_HDLC = 50
+PPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC
+framing, as per section 4.3.1 of RFC 1547; the first byte will be 0xFF
+for PPP in HDLC-like framing, and will be 0x0F or 0x8F for Cisco PPP
+with HDLC framing.
+.TP 5
+.BR DLT_PPP_ETHER "; " LINKTYPE_PPP_ETHER = 51
+PPPoE; the packet begins with a PPPoE header, as per RFC 2516.
+.TP 5
+.BR DLT_C_HDLC "; " LINKTYPE_C_HDLC = 104
+Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547.
+.TP 5
+.BR DLT_IEEE802_11 "; " LINKTYPE_IEEE802_11 = 105
+IEEE 802.11 wireless LAN
+.TP 5
+.BR DLT_FRELAY "; " LINKTYPE_FRELAY = 107
+Frame Relay
+.TP 5
+.BR DLT_LOOP "; " LINKTYPE_LOOP = 108
+OpenBSD loopback encapsulation; the link layer header is a 4-byte field, in
+.I network
+byte order, containing a PF_ value from OpenBSD's
+.B socket.h
+for the network-layer protocol of the packet.
+.IP
+Note that, if a ``savefile'' is being read, those PF_ values are
+.I not
+necessarily those of the machine reading the capture file.
+.TP 5
+.BR DLT_LINUX_SLL "; " LINKTYPE_LINUX_SLL = 113
+Linux "cooked" capture encapsulation; the link layer header contains, in
+order:
+.RS 10
+.LP
+a 2-byte "packet type", in network byte order, which is one of:
+.RS 5
+.TP 5
+0
+packet was sent to us by somebody else
+.TP 5
+1
+packet was broadcast by somebody else
+.TP 5
+2
+packet was multicast, but not broadcast, by somebody else
+.TP 5
+3
+packet was sent by somebody else to somebody else
+.TP 5
+4
+packet was sent by us
+.RE
+.LP
+a 2-byte field, in network byte order, containing a Linux ARPHRD_ value
+for the link layer device type;
+.LP
+a 2-byte field, in network byte order, containing the length of the
+link layer address of the sender of the packet (which could be 0);
+.LP
+an 8-byte field containing that number of bytes of the link layer header
+(if there are more than 8 bytes, only the first 8 are present);
+.LP
+a 2-byte field containing an Ethernet protocol type, in network byte
+order, or containing 1 for Novell 802.3 frames without an 802.2 LLC
+header or 4 for frames beginning with an 802.2 LLC header.
+.RE
+.TP 5
+.BR DLT_LTALK "; " LINKTYPE_LTALK = 104
+Apple LocalTalk; the packet begins with an AppleTalk LLAP header.
+.TP 5
+.BR DLT_PFLOG "; " LINKTYPE_PFLOG = 117
+OpenBSD pflog; the link layer header contains a
+.B "struct pfloghdr"
+structure, as defined by the host on which the file was saved. (This
+differs from operating system to operating system and release to
+release; there is nothing in the file to indicate what the layout of
+that structure is.)
+.TP 5
+.BR DLT_PRISM_HEADER "; " LINKTYPE_PRISM_HEADER = 119
+Prism monitor mode information followed by an 802.11 header.
+.TP 5
+.BR DLT_IP_OVER_FC "; " LINKTYPE_IP_OVER_FC = 122
+RFC 2625 IP-over-Fibre Channel, with the link-layer header being the
+Network_Header as described in that RFC.
+.TP 5
+.BR DLT_SUNATM "; " LINKTYPE_SUNATM = 123
+SunATM devices; the link layer header contains, in order:
+.RS 10
+.LP
+a 1-byte flag field, containing a direction flag in the uppermost bit,
+which is set for packets transmitted by the machine and clear for
+packets received by the machine, and a 4-byte traffic type in the
+low-order 4 bits, which is one of:
+.RS 5
+.TP 5
+0
+raw traffic
+.TP 5
+1
+LANE traffic
+.TP 5
+2
+LLC-encapsulated traffic
+.TP 5
+3
+MARS traffic
+.TP 5
+4
+IFMP traffic
+.TP 5
+5
+ILMI traffic
+.TP 5
+6
+Q.2931 traffic
+.RE
+.LP
+a 1-byte VPI value;
+.LP
+a 2-byte VCI field, in network byte order.
+.RE
+.TP 5
+.BR DLT_IEEE802_11_RADIO "; " LINKTYPE_IEEE802_11_RADIO = 127
+link-layer information followed by an 802.11 header - see
+http://www.shaftnet.org/~pizza/software/capturefrm.txt for a description
+of the link-layer information.
+.TP 5
+.BR DLT_ARCNET_LINUX "; " LINKTYPE_ARCNET_LINUX = 129
+ARCNET, with no exception frames, reassembled packets rather than raw
+frames, and an extra 16-bit offset field between the destination host
+and type bytes.
+.TP 5
+.BR DLT_LINUX_IRDA "; " LINKTYPE_LINUX_IRDA = 144
+Linux-IrDA packets, with a
+.B DLT_LINUX_SLL
+header followed by the IrLAP header.
+.TP 5
+.BR DLT_LINUX_LAPD "; " LINKTYPE_LINUX_LAPD = 177
+LAPD (Q.921) frames, with a
+.B DLT_LINUX_SLL
+header captured via vISDN.
+.RE
+.SH SEE ALSO
+pcap_datalink(3PCAP)
diff --git a/contrib/libpcap/pcap-linux.c b/contrib/libpcap/pcap-linux.c
index e9db010..8161af0 100644
--- a/contrib/libpcap/pcap-linux.c
+++ b/contrib/libpcap/pcap-linux.c
@@ -23,11 +23,18 @@
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Modifications: Added PACKET_MMAP support
+ * Paolo Abeni <paolo.abeni@email.it>
+ *
+ * based on previous works of:
+ * Simon Patarin <patarin@cs.unibo.it>
+ * Phil Wood <cpw@lanl.gov>
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.110.2.14 2006/10/12 17:26:58 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.129.2.29 2008-10-28 00:50:39 guy Exp $ (LBL)";
#endif
/*
@@ -77,17 +84,6 @@ static const char rcsid[] _U_ =
#include "config.h"
#endif
-#include "pcap-int.h"
-#include "sll.h"
-
-#ifdef HAVE_DAG_API
-#include "pcap-dag.h"
-#endif /* HAVE_DAG_API */
-
-#ifdef HAVE_SEPTEL_API
-#include "pcap-septel.h"
-#endif /* HAVE_SEPTEL_API */
-
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
@@ -96,10 +92,39 @@ static const char rcsid[] _U_ =
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
+#include <sys/mman.h>
#include <net/if.h>
#include <netinet/in.h>
#include <linux/if_ether.h>
#include <net/if_arp.h>
+#include <poll.h>
+
+/*
+ * Got Wireless Extensions?
+ */
+#ifdef HAVE_LINUX_WIRELESS_H
+#include <linux/wireless.h>
+#endif
+
+#include "pcap-int.h"
+#include "pcap/sll.h"
+#include "pcap/vlan.h"
+
+#ifdef HAVE_DAG_API
+#include "pcap-dag.h"
+#endif /* HAVE_DAG_API */
+
+#ifdef HAVE_SEPTEL_API
+#include "pcap-septel.h"
+#endif /* HAVE_SEPTEL_API */
+
+#ifdef PCAP_SUPPORT_USB
+#include "pcap-usb-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_BT
+#include "pcap-bt-linux.h"
+#endif
/*
* If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET
@@ -141,7 +166,23 @@ static const char rcsid[] _U_ =
*/
# ifdef PACKET_HOST
# define HAVE_PF_PACKET_SOCKETS
+# ifdef PACKET_AUXDATA
+# define HAVE_PACKET_AUXDATA
+# endif /* PACKET_AUXDATA */
# endif /* PACKET_HOST */
+
+
+ /* check for memory mapped access avaibility. We assume every needed
+ * struct is defined if the macro TPACKET_HDRLEN is defined, because it
+ * uses many ring related structs and macros */
+# ifdef TPACKET_HDRLEN
+# define HAVE_PACKET_RING
+# ifdef TPACKET2_HDRLEN
+# define HAVE_TPACKET2
+# else
+# define TPACKET_V1 0
+# endif /* TPACKET2_HDRLEN */
+# endif /* TPACKET_HDRLEN */
#endif /* PF_PACKET */
#ifdef SO_ATTACH_FILTER
@@ -149,7 +190,7 @@ static const char rcsid[] _U_ =
#include <linux/filter.h>
#endif
-#ifndef __GLIBC__
+#ifndef HAVE_SOCKLEN_T
typedef int socklen_t;
#endif
@@ -185,18 +226,43 @@ typedef int socklen_t;
#define BIGGER_THAN_ALL_MTUS (64*1024)
/*
- * Prototypes for internal functions
+ * Prototypes for internal functions and methods.
*/
static void map_arphrd_to_dlt(pcap_t *, int, int);
-static int live_open_old(pcap_t *, const char *, int, int, char *);
-static int live_open_new(pcap_t *, const char *, int, int, char *);
+#ifdef HAVE_PF_PACKET_SOCKETS
+static short int map_packet_type_to_sll_type(short int);
+#endif
+static int pcap_activate_linux(pcap_t *);
+static int activate_old(pcap_t *);
+static int activate_new(pcap_t *);
+static int activate_mmap(pcap_t *);
+static int pcap_can_set_rfmon_linux(pcap_t *);
static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *);
static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
static int pcap_inject_linux(pcap_t *, const void *, size_t);
static int pcap_stats_linux(pcap_t *, struct pcap_stat *);
static int pcap_setfilter_linux(pcap_t *, struct bpf_program *);
static int pcap_setdirection_linux(pcap_t *, pcap_direction_t);
-static void pcap_close_linux(pcap_t *);
+static void pcap_cleanup_linux(pcap_t *);
+
+union thdr {
+ struct tpacket_hdr *h1;
+ struct tpacket2_hdr *h2;
+ void *raw;
+};
+
+#ifdef HAVE_PACKET_RING
+#define RING_GET_FRAME(h) (((union thdr **)h->buffer)[h->offset])
+
+static void destroy_ring(pcap_t *handle);
+static int create_ring(pcap_t *handle);
+static int prepare_tpacket_socket(pcap_t *handle);
+static void pcap_cleanup_linux_mmap(pcap_t *);
+static int pcap_read_linux_mmap(pcap_t *, int, pcap_handler , u_char *);
+static int pcap_setfilter_linux_mmap(pcap_t *, struct bpf_program *);
+static int pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf);
+static int pcap_getnonblock_mmap(pcap_t *p, char *errbuf);
+#endif
/*
* Wrap some ioctl calls
@@ -208,6 +274,9 @@ static int iface_get_mtu(int fd, const char *device, char *ebuf);
static int iface_get_arptype(int fd, const char *device, char *ebuf);
#ifdef HAVE_PF_PACKET_SOCKETS
static int iface_bind(int fd, int ifindex, char *ebuf);
+static int has_wext(int sock_fd, const char *device, char *ebuf);
+static int enter_rfmon_mode_wext(pcap_t *handle, int sock_fd,
+ const char *device);
#endif
static int iface_bind_old(int fd, const char *device, char *ebuf);
@@ -223,52 +292,230 @@ static struct sock_fprog total_fcode
= { 1, &total_insn };
#endif
-/*
- * Get a handle for a live capture from the given device. You can
- * pass NULL as device to get all packages (without link level
- * information of course). If you pass 1 as promisc the interface
- * will be set to promiscous mode (XXX: I think this usage should
- * be deprecated and functions be added to select that later allow
- * modification of that values -- Torsten).
- *
- * See also pcap(3).
- */
pcap_t *
-pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
- char *ebuf)
+pcap_create(const char *device, char *ebuf)
{
- pcap_t *handle;
- int mtu;
- int err;
- int live_open_ok = 0;
- struct utsname utsname;
+ pcap_t *handle;
#ifdef HAVE_DAG_API
if (strstr(device, "dag")) {
- return dag_open_live(device, snaplen, promisc, to_ms, ebuf);
+ return dag_create(device, ebuf);
}
#endif /* HAVE_DAG_API */
#ifdef HAVE_SEPTEL_API
if (strstr(device, "septel")) {
- return septel_open_live(device, snaplen, promisc, to_ms, ebuf);
+ return septel_create(device, ebuf);
}
#endif /* HAVE_SEPTEL_API */
- /* Allocate a handle for this session. */
+#ifdef PCAP_SUPPORT_BT
+ if (strstr(device, "bluetooth")) {
+ return bt_create(device, ebuf);
+ }
+#endif
- handle = malloc(sizeof(*handle));
- if (handle == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
+#ifdef PCAP_SUPPORT_USB
+ if (strstr(device, "usb")) {
+ return usb_create(device, ebuf);
+ }
+#endif
+
+ handle = pcap_create_common(device, ebuf);
+ if (handle == NULL)
return NULL;
+
+ handle->activate_op = pcap_activate_linux;
+ handle->can_set_rfmon_op = pcap_can_set_rfmon_linux;
+ return handle;
+}
+
+static int
+pcap_can_set_rfmon_linux(pcap_t *p)
+{
+#ifdef IW_MODE_MONITOR
+ int sock_fd;
+ struct iwreq ireq;
+#endif
+
+ if (p->opt.source == NULL) {
+ /*
+ * This is equivalent to the "any" device, and we don't
+ * support monitor mode on it.
+ */
+ return 0;
}
- /* Initialize some components of the pcap structure. */
+#ifdef IW_MODE_MONITOR
+ /*
+ * Bleah. There doesn't appear to be an ioctl to use to ask
+ * whether a device supports monitor mode; we'll just do
+ * SIOCGIWMODE and, if it succeeds, assume the device supports
+ * monitor mode.
+ *
+ * Open a socket on which to attempt to get the mode.
+ * (We assume that if we have Wireless Extensions support
+ * we also have PF_PACKET support.)
+ */
+ sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (sock_fd == -1) {
+ (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "socket: %s", pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
- memset(handle, 0, sizeof(*handle));
- handle->snapshot = snaplen;
- handle->md.timeout = to_ms;
+ /*
+ * Attempt to get the current mode.
+ */
+ strncpy(ireq.ifr_ifrn.ifrn_name, p->opt.source,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ if (ioctl(sock_fd, SIOCGIWMODE, &ireq) != -1) {
+ /*
+ * Well, we got the mode; assume we can set it.
+ */
+ close(sock_fd);
+ return 1;
+ }
+ if (errno == ENODEV) {
+ /* The device doesn't even exist. */
+ close(sock_fd);
+ return PCAP_ERROR_NO_SUCH_DEVICE;
+ }
+ close(sock_fd);
+#endif
+ return 0;
+}
+
+/*
+ * With older kernels promiscuous mode is kind of interesting because we
+ * have to reset the interface before exiting. The problem can't really
+ * be solved without some daemon taking care of managing usage counts.
+ * If we put the interface into promiscuous mode, we set a flag indicating
+ * that we must take it out of that mode when the interface is closed,
+ * and, when closing the interface, if that flag is set we take it out
+ * of promiscuous mode.
+ *
+ * Even with newer kernels, we have the same issue with rfmon mode.
+ */
+
+static void pcap_cleanup_linux( pcap_t *handle )
+{
+ struct ifreq ifr;
+#ifdef IW_MODE_MONITOR
+ struct iwreq ireq;
+#endif
+
+ if (handle->md.must_clear != 0) {
+ /*
+ * There's something we have to do when closing this
+ * pcap_t.
+ */
+ if (handle->md.must_clear & MUST_CLEAR_PROMISC) {
+ /*
+ * We put the interface into promiscuous mode;
+ * take it out of promiscuous mode.
+ *
+ * XXX - if somebody else wants it in promiscuous
+ * mode, this code cannot know that, so it'll take
+ * it out of promiscuous mode. That's not fixable
+ * in 2.0[.x] kernels.
+ */
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, handle->md.device,
+ sizeof(ifr.ifr_name));
+ if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
+ fprintf(stderr,
+ "Can't restore interface flags (SIOCGIFFLAGS failed: %s).\n"
+ "Please adjust manually.\n"
+ "Hint: This can't happen with Linux >= 2.2.0.\n",
+ strerror(errno));
+ } else {
+ if (ifr.ifr_flags & IFF_PROMISC) {
+ /*
+ * Promiscuous mode is currently on;
+ * turn it off.
+ */
+ ifr.ifr_flags &= ~IFF_PROMISC;
+ if (ioctl(handle->fd, SIOCSIFFLAGS,
+ &ifr) == -1) {
+ fprintf(stderr,
+ "Can't restore interface flags (SIOCSIFFLAGS failed: %s).\n"
+ "Please adjust manually.\n"
+ "Hint: This can't happen with Linux >= 2.2.0.\n",
+ strerror(errno));
+ }
+ }
+ }
+ }
+
+#ifdef IW_MODE_MONITOR
+ if (handle->md.must_clear & MUST_CLEAR_RFMON) {
+ /*
+ * We put the interface into rfmon mode;
+ * take it out of rfmon mode.
+ *
+ * XXX - if somebody else wants it in rfmon
+ * mode, this code cannot know that, so it'll take
+ * it out of rfmon mode.
+ */
+ strncpy(ireq.ifr_ifrn.ifrn_name, handle->md.device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1]
+ = 0;
+ ireq.u.mode = handle->md.oldmode;
+ if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) {
+ /*
+ * Scientist, you've failed.
+ */
+ fprintf(stderr,
+ "Can't restore interface wireless mode (SIOCSIWMODE failed: %s).\n"
+ "Please adjust manually.\n",
+ strerror(errno));
+ }
+ }
+#endif
+
+ /*
+ * Take this pcap out of the list of pcaps for which we
+ * have to take the interface out of some mode.
+ */
+ pcap_remove_from_pcaps_to_close(handle);
+ }
+
+ if (handle->md.device != NULL) {
+ free(handle->md.device);
+ handle->md.device = NULL;
+ }
+ pcap_cleanup_live_common(handle);
+}
+
+/*
+ * Get a handle for a live capture from the given device. You can
+ * pass NULL as device to get all packages (without link level
+ * information of course). If you pass 1 as promisc the interface
+ * will be set to promiscous mode (XXX: I think this usage should
+ * be deprecated and functions be added to select that later allow
+ * modification of that values -- Torsten).
+ */
+static int
+pcap_activate_linux(pcap_t *handle)
+{
+ const char *device;
+ int status = 0;
+ int activate_ok = 0;
+
+ device = handle->opt.source;
+
+ handle->inject_op = pcap_inject_linux;
+ handle->setfilter_op = pcap_setfilter_linux;
+ handle->setdirection_op = pcap_setdirection_linux;
+ handle->set_datalink_op = NULL; /* can't change data link type */
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->cleanup_op = pcap_cleanup_linux;
+ handle->read_op = pcap_read_linux;
+ handle->stats_op = pcap_stats_linux;
/*
* NULL and "any" are special devices which give us the hint to
@@ -277,21 +524,21 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
if (!device || strcmp(device, "any") == 0) {
device = NULL;
handle->md.device = strdup("any");
- if (promisc) {
- promisc = 0;
+ if (handle->opt.promisc) {
+ handle->opt.promisc = 0;
/* Just a warning. */
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Promiscuous mode not supported on the \"any\" device");
+ status = PCAP_WARNING_PROMISC_NOTSUP;
}
} else
handle->md.device = strdup(device);
if (handle->md.device == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
pcap_strerror(errno) );
- free(handle);
- return NULL;
+ return PCAP_ERROR;
}
/*
@@ -304,118 +551,50 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* trying both methods with the newer method preferred.
*/
- if ((err = live_open_new(handle, device, promisc, to_ms, ebuf)) == 1)
- live_open_ok = 1;
- else if (err == 0) {
+ if ((status = activate_new(handle)) == 1) {
+ activate_ok = 1;
+ /*
+ * Try to use memory-mapped access.
+ */
+ if (activate_mmap(handle) == 1)
+ return 0; /* we succeeded; nothing more to do */
+ }
+ else if (status == 0) {
/* Non-fatal error; try old way */
- if (live_open_old(handle, device, promisc, to_ms, ebuf))
- live_open_ok = 1;
+ if ((status = activate_old(handle)) == 1)
+ activate_ok = 1;
}
- if (!live_open_ok) {
+ if (!activate_ok) {
/*
* Both methods to open the packet socket failed. Tidy
* up and report our failure (ebuf is expected to be
* set by the functions above).
*/
-
- if (handle->md.device != NULL)
- free(handle->md.device);
- free(handle);
- return NULL;
+ goto fail;
}
- /*
- * Compute the buffer size.
- *
- * If we're using SOCK_PACKET, this might be a 2.0[.x] kernel,
- * and might require special handling - check.
- */
- if (handle->md.sock_packet && (uname(&utsname) < 0 ||
- strncmp(utsname.release, "2.0", 3) == 0)) {
+ if (handle->opt.buffer_size != 0) {
/*
- * We're using a SOCK_PACKET structure, and either
- * we couldn't find out what kernel release this is,
- * or it's a 2.0[.x] kernel.
- *
- * In the 2.0[.x] kernel, a "recvfrom()" on
- * a SOCK_PACKET socket, with MSG_TRUNC set, will
- * return the number of bytes read, so if we pass
- * a length based on the snapshot length, it'll
- * return the number of bytes from the packet
- * copied to userland, not the actual length
- * of the packet.
- *
- * This means that, for example, the IP dissector
- * in tcpdump will get handed a packet length less
- * than the length in the IP header, and will
- * complain about "truncated-ip".
- *
- * So we don't bother trying to copy from the
- * kernel only the bytes in which we're interested,
- * but instead copy them all, just as the older
- * versions of libpcap for Linux did.
- *
- * The buffer therefore needs to be big enough to
- * hold the largest packet we can get from this
- * device. Unfortunately, we can't get the MRU
- * of the network; we can only get the MTU. The
- * MTU may be too small, in which case a packet larger
- * than the buffer size will be truncated *and* we
- * won't get the actual packet size.
- *
- * However, if the snapshot length is larger than
- * the buffer size based on the MTU, we use the
- * snapshot length as the buffer size, instead;
- * this means that with a sufficiently large snapshot
- * length we won't artificially truncate packets
- * to the MTU-based size.
- *
- * This mess just one of many problems with packet
- * capture on 2.0[.x] kernels; you really want a
- * 2.2[.x] or later kernel if you want packet capture
- * to work well.
+ * Set the socket buffer size to the specified value.
*/
- mtu = iface_get_mtu(handle->fd, device, ebuf);
- if (mtu == -1) {
- pcap_close_linux(handle);
- free(handle);
- return NULL;
- }
- handle->bufsize = MAX_LINKHEADER_SIZE + mtu;
- if (handle->bufsize < handle->snapshot)
- handle->bufsize = handle->snapshot;
- } else {
- /*
- * This is a 2.2[.x] or later kernel (we know that
- * either because we're not using a SOCK_PACKET
- * socket - PF_PACKET is supported only in 2.2
- * and later kernels - or because we checked the
- * kernel version).
- *
- * We can safely pass "recvfrom()" a byte count
- * based on the snapshot length.
- *
- * If we're in cooked mode, make the snapshot length
- * large enough to hold a "cooked mode" header plus
- * 1 byte of packet data (so we don't pass a byte
- * count of 0 to "recvfrom()").
- */
- if (handle->md.cooked) {
- if (handle->snapshot < SLL_HDR_LEN + 1)
- handle->snapshot = SLL_HDR_LEN + 1;
+ if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
+ &handle->opt.buffer_size,
+ sizeof(handle->opt.buffer_size)) == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "SO_RCVBUF: %s", pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto fail;
}
- handle->bufsize = handle->snapshot;
}
/* Allocate the buffer */
handle->buffer = malloc(handle->bufsize + handle->offset);
if (!handle->buffer) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
- pcap_close_linux(handle);
- free(handle);
- return NULL;
+ status = PCAP_ERROR;
+ goto fail;
}
/*
@@ -424,17 +603,11 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
*/
handle->selectable_fd = handle->fd;
- handle->read_op = pcap_read_linux;
- handle->inject_op = pcap_inject_linux;
- handle->setfilter_op = pcap_setfilter_linux;
- handle->setdirection_op = pcap_setdirection_linux;
- handle->set_datalink_op = NULL; /* can't change data link type */
- handle->getnonblock_op = pcap_getnonblock_fd;
- handle->setnonblock_op = pcap_setnonblock_fd;
- handle->stats_op = pcap_stats_linux;
- handle->close_op = pcap_close_linux;
+ return status;
- return handle;
+fail:
+ pcap_cleanup_linux(handle);
+ return status;
}
/*
@@ -468,7 +641,17 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
#else
struct sockaddr from;
#endif
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
+ struct iovec iov;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr cmsg;
+ char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
+ } cmsg_buf;
+#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
socklen_t fromlen;
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
int packet_len, caplen;
struct pcap_pkthdr pcap_header;
@@ -489,9 +672,36 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
offset = 0;
#endif
- /* Receive a single packet from the kernel */
-
+ /*
+ * Receive a single packet from the kernel.
+ * We ignore EINTR, as that might just be due to a signal
+ * being delivered - if the signal should interrupt the
+ * loop, the signal handler should call pcap_breakloop()
+ * to set handle->break_loop (we ignore it on other
+ * platforms as well).
+ * We also ignore ENETDOWN, so that we can continue to
+ * capture traffic if the interface goes down and comes
+ * back up again; comments in the kernel indicate that
+ * we'll just block waiting for packets if we try to
+ * receive from a socket that delivered ENETDOWN, and,
+ * if we're using a memory-mapped buffer, we won't even
+ * get notified of "network down" events.
+ */
bp = handle->buffer + handle->offset;
+
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
+ msg.msg_name = &from;
+ msg.msg_namelen = sizeof(from);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = &cmsg_buf;
+ msg.msg_controllen = sizeof(cmsg_buf);
+ msg.msg_flags = 0;
+
+ iov.iov_len = handle->bufsize - offset;
+ iov.iov_base = bp + offset;
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+
do {
/*
* Has "pcap_breakloop()" been called?
@@ -505,12 +715,17 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
handle->break_loop = 0;
return -2;
}
+
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
+ packet_len = recvmsg(handle->fd, &msg, MSG_TRUNC);
+#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
fromlen = sizeof(from);
packet_len = recvfrom(
handle->fd, bp + offset,
handle->bufsize - offset, MSG_TRUNC,
(struct sockaddr *) &from, &fromlen);
- } while (packet_len == -1 && errno == EINTR);
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+ } while (packet_len == -1 && (errno == EINTR || errno == ENETDOWN));
/* Check if an error occured */
@@ -518,7 +733,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
if (errno == EAGAIN)
return 0; /* no packet there */
else {
- snprintf(handle->errbuf, sizeof(handle->errbuf),
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"recvfrom: %s", pcap_strerror(errno));
return -1;
}
@@ -586,51 +801,46 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
packet_len += SLL_HDR_LEN;
hdrp = (struct sll_header *)bp;
+ hdrp->sll_pkttype = map_packet_type_to_sll_type(from.sll_pkttype);
+ hdrp->sll_hatype = htons(from.sll_hatype);
+ hdrp->sll_halen = htons(from.sll_halen);
+ memcpy(hdrp->sll_addr, from.sll_addr,
+ (from.sll_halen > SLL_ADDRLEN) ?
+ SLL_ADDRLEN :
+ from.sll_halen);
+ hdrp->sll_protocol = from.sll_protocol;
+ }
- /*
- * Map the PACKET_ value to a LINUX_SLL_ value; we
- * want the same numerical value to be used in
- * the link-layer header even if the numerical values
- * for the PACKET_ #defines change, so that programs
- * that look at the packet type field will always be
- * able to handle DLT_LINUX_SLL captures.
- */
- switch (from.sll_pkttype) {
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ struct tpacket_auxdata *aux;
+ unsigned int len;
+ struct vlan_tag *tag;
- case PACKET_HOST:
- hdrp->sll_pkttype = htons(LINUX_SLL_HOST);
- break;
+ if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
+ cmsg->cmsg_level != SOL_PACKET ||
+ cmsg->cmsg_type != PACKET_AUXDATA)
+ continue;
- case PACKET_BROADCAST:
- hdrp->sll_pkttype = htons(LINUX_SLL_BROADCAST);
- break;
+ aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
+ if (aux->tp_vlan_tci == 0)
+ continue;
- case PACKET_MULTICAST:
- hdrp->sll_pkttype = htons(LINUX_SLL_MULTICAST);
+ len = packet_len > iov.iov_len ? iov.iov_len : packet_len;
+ if (len < 2 * ETH_ALEN)
break;
- case PACKET_OTHERHOST:
- hdrp->sll_pkttype = htons(LINUX_SLL_OTHERHOST);
- break;
+ bp -= VLAN_TAG_LEN;
+ memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN);
- case PACKET_OUTGOING:
- hdrp->sll_pkttype = htons(LINUX_SLL_OUTGOING);
- break;
+ tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN);
+ tag->vlan_tpid = htons(ETH_P_8021Q);
+ tag->vlan_tci = htons(aux->tp_vlan_tci);
- default:
- hdrp->sll_pkttype = -1;
- break;
- }
-
- hdrp->sll_hatype = htons(from.sll_hatype);
- hdrp->sll_halen = htons(from.sll_halen);
- memcpy(hdrp->sll_addr, from.sll_addr,
- (from.sll_halen > SLL_ADDRLEN) ?
- SLL_ADDRLEN :
- from.sll_halen);
- hdrp->sll_protocol = from.sll_protocol;
+ packet_len += VLAN_TAG_LEN;
}
-#endif
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
+#endif /* HAVE_PF_PACKET_SOCKETS */
/*
* XXX: According to the kernel source we should get the real
@@ -681,7 +891,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
/* Fill in our own header data */
if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) {
- snprintf(handle->errbuf, sizeof(handle->errbuf),
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"SIOCGSTAMP: %s", pcap_strerror(errno));
return -1;
}
@@ -915,6 +1125,16 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
return (-1);
#endif /* HAVE_SEPTEL_API */
+#ifdef PCAP_SUPPORT_BT
+ if (bt_platform_finddevs(alldevsp, errbuf) < 0)
+ return (-1);
+#endif
+
+#ifdef PCAP_SUPPORT_USB
+ if (usb_platform_finddevs(alldevsp, errbuf) < 0)
+ return (-1);
+#endif
+
return (0);
}
@@ -934,7 +1154,7 @@ pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter)
return -1;
if (!filter) {
strncpy(handle->errbuf, "setfilter: No filter specified",
- sizeof(handle->errbuf));
+ PCAP_ERRBUF_SIZE);
return -1;
}
@@ -1072,11 +1292,47 @@ pcap_setdirection_linux(pcap_t *handle, pcap_direction_t d)
* We're not using PF_PACKET sockets, so we can't determine
* the direction of the packet.
*/
- snprintf(handle->errbuf, sizeof(handle->errbuf),
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"Setting direction is not supported on SOCK_PACKET sockets");
return -1;
}
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+/*
+ * Map the PACKET_ value to a LINUX_SLL_ value; we
+ * want the same numerical value to be used in
+ * the link-layer header even if the numerical values
+ * for the PACKET_ #defines change, so that programs
+ * that look at the packet type field will always be
+ * able to handle DLT_LINUX_SLL captures.
+ */
+static short int
+map_packet_type_to_sll_type(short int sll_pkttype)
+{
+ switch (sll_pkttype) {
+
+ case PACKET_HOST:
+ return htons(LINUX_SLL_HOST);
+
+ case PACKET_BROADCAST:
+ return htons(LINUX_SLL_BROADCAST);
+
+ case PACKET_MULTICAST:
+ return htons(LINUX_SLL_MULTICAST);
+
+ case PACKET_OTHERHOST:
+ return htons(LINUX_SLL_OTHERHOST);
+
+ case PACKET_OUTGOING:
+ return htons(LINUX_SLL_OUTGOING);
+
+ default:
+ return -1;
+ }
+}
+#endif
+
/*
* Linux uses the ARP hardware type to identify the type of an
* interface. pcap uses the DLT_xxx constants for this. This
@@ -1113,7 +1369,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok)
* XXX - are there any sorts of "fake Ethernet" that have
* ARPHRD_ETHER but that *shouldn't offer DLT_DOCSIS as
* a Cisco CMTS won't put traffic onto it or get traffic
- * bridged onto it? ISDN is handled in "live_open_new()",
+ * bridged onto it? ISDN is handled in "activate_new()",
* as we fall back on cooked mode there; are there any
* others?
*/
@@ -1139,7 +1395,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok)
break;
case ARPHRD_AX25:
- handle->linktype = DLT_AX25;
+ handle->linktype = DLT_AX25_KISS;
break;
case ARPHRD_PRONET:
@@ -1371,6 +1627,17 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok)
handle->linktype = DLT_LINUX_LAPD;
break;
+#ifndef ARPHRD_NONE
+#define ARPHRD_NONE 0xFFFE
+#endif
+ case ARPHRD_NONE:
+ /*
+ * No link-layer header; packets are just IP
+ * packets, so use DLT_RAW.
+ */
+ handle->linktype = DLT_RAW;
+ break;
+
default:
handle->linktype = -1;
break;
@@ -1380,218 +1647,265 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok)
/* ===== Functions to interface to the newer kernels ================== */
/*
- * Try to open a packet socket using the new kernel interface.
- * Returns 0 on failure.
- * FIXME: 0 uses to mean success (Sebastian)
+ * Try to open a packet socket using the new kernel PF_PACKET interface.
+ * Returns 1 on success, 0 on an error that means the new interface isn't
+ * present (so the old SOCK_PACKET interface should be tried), and a
+ * PCAP_ERROR_ value on an error that means that the old mechanism won't
+ * work either (so it shouldn't be tried).
*/
static int
-live_open_new(pcap_t *handle, const char *device, int promisc,
- int to_ms, char *ebuf)
+activate_new(pcap_t *handle)
{
#ifdef HAVE_PF_PACKET_SOCKETS
- int sock_fd = -1, arptype;
- int err;
- int fatal_err = 0;
+ int sock_fd = -1, arptype, val;
+ int err = 0;
struct packet_mreq mr;
+ const char* device = handle->opt.source;
- /* One shot loop used for error handling - bail out with break */
-
- do {
- /*
- * Open a socket with protocol family packet. If a device is
- * given we try to open it in raw mode otherwise we use
- * the cooked interface.
- */
- sock_fd = device ?
- socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
- : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL));
-
- if (sock_fd == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "socket: %s",
- pcap_strerror(errno) );
- break;
- }
+ /*
+ * Open a socket with protocol family packet. If a device is
+ * given we try to open it in raw mode otherwise we use
+ * the cooked interface.
+ */
+ sock_fd = device ?
+ socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
+ : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL));
- /* It seems the kernel supports the new interface. */
- handle->md.sock_packet = 0;
+ if (sock_fd == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
+ pcap_strerror(errno) );
+ return 0; /* try old mechanism */
+ }
- /*
- * Get the interface index of the loopback device.
- * If the attempt fails, don't fail, just set the
- * "md.lo_ifindex" to -1.
- *
- * XXX - can there be more than one device that loops
- * packets back, i.e. devices other than "lo"? If so,
- * we'd need to find them all, and have an array of
- * indices for them, and check all of them in
- * "pcap_read_packet()".
- */
- handle->md.lo_ifindex = iface_get_id(sock_fd, "lo", ebuf);
+ /* It seems the kernel supports the new interface. */
+ handle->md.sock_packet = 0;
- /*
- * Default value for offset to align link-layer payload
- * on a 4-byte boundary.
- */
- handle->offset = 0;
+ /*
+ * Get the interface index of the loopback device.
+ * If the attempt fails, don't fail, just set the
+ * "md.lo_ifindex" to -1.
+ *
+ * XXX - can there be more than one device that loops
+ * packets back, i.e. devices other than "lo"? If so,
+ * we'd need to find them all, and have an array of
+ * indices for them, and check all of them in
+ * "pcap_read_packet()".
+ */
+ handle->md.lo_ifindex = iface_get_id(sock_fd, "lo", handle->errbuf);
- /*
- * What kind of frames do we have to deal with? Fall back
- * to cooked mode if we have an unknown interface type.
- */
+ /*
+ * Default value for offset to align link-layer payload
+ * on a 4-byte boundary.
+ */
+ handle->offset = 0;
- if (device) {
- /* Assume for now we don't need cooked mode. */
- handle->md.cooked = 0;
+ /*
+ * What kind of frames do we have to deal with? Fall back
+ * to cooked mode if we have an unknown interface type
+ * or a type we know doesn't work well in raw mode.
+ */
+ if (device) {
+ /* Assume for now we don't need cooked mode. */
+ handle->md.cooked = 0;
- arptype = iface_get_arptype(sock_fd, device, ebuf);
- if (arptype == -1) {
- fatal_err = 1;
- break;
+ if (handle->opt.rfmon) {
+ /*
+ * We were asked to turn on monitor mode.
+ * Do so before we get the link-layer type,
+ * because entering monitor mode could change
+ * the link-layer type.
+ */
+ err = enter_rfmon_mode_wext(handle, sock_fd, device);
+ if (err < 0) {
+ /* Hard failure */
+ close(sock_fd);
+ return err;
}
- map_arphrd_to_dlt(handle, arptype, 1);
- if (handle->linktype == -1 ||
- handle->linktype == DLT_LINUX_SLL ||
- handle->linktype == DLT_LINUX_IRDA ||
- handle->linktype == DLT_LINUX_LAPD ||
- (handle->linktype == DLT_EN10MB &&
- (strncmp("isdn", device, 4) == 0 ||
- strncmp("isdY", device, 4) == 0))) {
+ if (err == 0) {
/*
- * Unknown interface type (-1), or a
- * device we explicitly chose to run
- * in cooked mode (e.g., PPP devices),
- * or an ISDN device (whose link-layer
- * type we can only determine by using
- * APIs that may be different on different
- * kernels) - reopen in cooked mode.
+ * Nothing worked for turning monitor mode
+ * on.
*/
- if (close(sock_fd) == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "close: %s", pcap_strerror(errno));
- break;
- }
- sock_fd = socket(PF_PACKET, SOCK_DGRAM,
- htons(ETH_P_ALL));
- if (sock_fd == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "socket: %s", pcap_strerror(errno));
- break;
- }
- handle->md.cooked = 1;
+ close(sock_fd);
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+ }
+ arptype = iface_get_arptype(sock_fd, device, handle->errbuf);
+ if (arptype < 0) {
+ close(sock_fd);
+ return arptype;
+ }
+ map_arphrd_to_dlt(handle, arptype, 1);
+ if (handle->linktype == -1 ||
+ handle->linktype == DLT_LINUX_SLL ||
+ handle->linktype == DLT_LINUX_IRDA ||
+ handle->linktype == DLT_LINUX_LAPD ||
+ (handle->linktype == DLT_EN10MB &&
+ (strncmp("isdn", device, 4) == 0 ||
+ strncmp("isdY", device, 4) == 0))) {
+ /*
+ * Unknown interface type (-1), or a
+ * device we explicitly chose to run
+ * in cooked mode (e.g., PPP devices),
+ * or an ISDN device (whose link-layer
+ * type we can only determine by using
+ * APIs that may be different on different
+ * kernels) - reopen in cooked mode.
+ */
+ if (close(sock_fd) == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "close: %s", pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
+ sock_fd = socket(PF_PACKET, SOCK_DGRAM,
+ htons(ETH_P_ALL));
+ if (sock_fd == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "socket: %s", pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
+ handle->md.cooked = 1;
+
+ /*
+ * Get rid of any link-layer type list
+ * we allocated - this only supports cooked
+ * capture.
+ */
+ if (handle->dlt_list != NULL) {
+ free(handle->dlt_list);
+ handle->dlt_list = NULL;
+ handle->dlt_count = 0;
+ }
+ if (handle->linktype == -1) {
/*
- * Get rid of any link-layer type list
- * we allocated - this only supports cooked
- * capture.
+ * Warn that we're falling back on
+ * cooked mode; we may want to
+ * update "map_arphrd_to_dlt()"
+ * to handle the new type.
*/
- if (handle->dlt_list != NULL) {
- free(handle->dlt_list);
- handle->dlt_list = NULL;
- handle->dlt_count = 0;
- }
-
- if (handle->linktype == -1) {
- /*
- * Warn that we're falling back on
- * cooked mode; we may want to
- * update "map_arphrd_to_dlt()"
- * to handle the new type.
- */
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "arptype %d not "
- "supported by libpcap - "
- "falling back to cooked "
- "socket",
- arptype);
- }
- /* IrDA capture is not a real "cooked" capture,
- * it's IrLAP frames, not IP packets. */
- if (handle->linktype != DLT_LINUX_IRDA &&
- handle->linktype != DLT_LINUX_LAPD)
- handle->linktype = DLT_LINUX_SLL;
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "arptype %d not "
+ "supported by libpcap - "
+ "falling back to cooked "
+ "socket",
+ arptype);
}
- handle->md.ifindex = iface_get_id(sock_fd, device, ebuf);
- if (handle->md.ifindex == -1)
- break;
-
- if ((err = iface_bind(sock_fd, handle->md.ifindex,
- ebuf)) < 0) {
- if (err == -2)
- fatal_err = 1;
- break;
- }
- } else {
/*
- * This is cooked mode.
+ * IrDA capture is not a real "cooked" capture,
+ * it's IrLAP frames, not IP packets. The
+ * same applies to LAPD capture.
*/
- handle->md.cooked = 1;
- handle->linktype = DLT_LINUX_SLL;
+ if (handle->linktype != DLT_LINUX_IRDA &&
+ handle->linktype != DLT_LINUX_LAPD)
+ handle->linktype = DLT_LINUX_SLL;
+ }
- /*
- * We're not bound to a device.
- * XXX - true? Or true only if we're using
- * the "any" device?
- * For now, we're using this as an indication
- * that we can't transmit; stop doing that only
- * if we figure out how to transmit in cooked
- * mode.
- */
- handle->md.ifindex = -1;
+ handle->md.ifindex = iface_get_id(sock_fd, device,
+ handle->errbuf);
+ if (handle->md.ifindex == -1) {
+ close(sock_fd);
+ return PCAP_ERROR;
}
+ if ((err = iface_bind(sock_fd, handle->md.ifindex,
+ handle->errbuf)) != 1) {
+ close(sock_fd);
+ if (err < 0)
+ return err;
+ else
+ return 0; /* try old mechanism */
+ }
+ } else {
/*
- * Select promiscuous mode on if "promisc" is set.
- *
- * Do not turn allmulti mode on if we don't select
- * promiscuous mode - on some devices (e.g., Orinoco
- * wireless interfaces), allmulti mode isn't supported
- * and the driver implements it by turning promiscuous
- * mode on, and that screws up the operation of the
- * card as a normal networking interface, and on no
- * other platform I know of does starting a non-
- * promiscuous capture affect which multicast packets
- * are received by the interface.
+ * This is cooked mode.
*/
+ handle->md.cooked = 1;
+ handle->linktype = DLT_LINUX_SLL;
/*
- * Hmm, how can we set promiscuous mode on all interfaces?
- * I am not sure if that is possible at all.
+ * We're not bound to a device.
+ * XXX - true? Or true only if we're using
+ * the "any" device?
+ * For now, we're using this as an indication
+ * that we can't transmit; stop doing that only
+ * if we figure out how to transmit in cooked
+ * mode.
*/
+ handle->md.ifindex = -1;
+ }
- if (device && promisc) {
- memset(&mr, 0, sizeof(mr));
- mr.mr_ifindex = handle->md.ifindex;
- mr.mr_type = PACKET_MR_PROMISC;
- if (setsockopt(sock_fd, SOL_PACKET,
- PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1)
- {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "setsockopt: %s", pcap_strerror(errno));
- break;
- }
- }
+ /*
+ * Select promiscuous mode on if "promisc" is set.
+ *
+ * Do not turn allmulti mode on if we don't select
+ * promiscuous mode - on some devices (e.g., Orinoco
+ * wireless interfaces), allmulti mode isn't supported
+ * and the driver implements it by turning promiscuous
+ * mode on, and that screws up the operation of the
+ * card as a normal networking interface, and on no
+ * other platform I know of does starting a non-
+ * promiscuous capture affect which multicast packets
+ * are received by the interface.
+ */
- /* Save the socket FD in the pcap structure */
+ /*
+ * Hmm, how can we set promiscuous mode on all interfaces?
+ * I am not sure if that is possible at all.
+ */
- handle->fd = sock_fd;
+ if (device && handle->opt.promisc) {
+ memset(&mr, 0, sizeof(mr));
+ mr.mr_ifindex = handle->md.ifindex;
+ mr.mr_type = PACKET_MR_PROMISC;
+ if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
+ &mr, sizeof(mr)) == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "setsockopt: %s", pcap_strerror(errno));
+ close(sock_fd);
+ return PCAP_ERROR;
+ }
+ }
- return 1;
+ /* Enable auxillary data if supported and reserve room for
+ * reconstructing VLAN headers. */
+#ifdef HAVE_PACKET_AUXDATA
+ val = 1;
+ if (setsockopt(sock_fd, SOL_PACKET, PACKET_AUXDATA, &val,
+ sizeof(val)) == -1 && errno != ENOPROTOOPT) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "setsockopt: %s", pcap_strerror(errno));
+ close(sock_fd);
+ return PCAP_ERROR;
+ }
+ handle->offset += VLAN_TAG_LEN;
+#endif /* HAVE_PACKET_AUXDATA */
- } while(0);
+ /*
+ * This is a 2.2[.x] or later kernel (we know that
+ * because we're not using a SOCK_PACKET socket -
+ * PF_PACKET is supported only in 2.2 and later
+ * kernels).
+ *
+ * We can safely pass "recvfrom()" a byte count
+ * based on the snapshot length.
+ *
+ * If we're in cooked mode, make the snapshot length
+ * large enough to hold a "cooked mode" header plus
+ * 1 byte of packet data (so we don't pass a byte
+ * count of 0 to "recvfrom()").
+ */
+ if (handle->md.cooked) {
+ if (handle->snapshot < SLL_HDR_LEN + 1)
+ handle->snapshot = SLL_HDR_LEN + 1;
+ }
+ handle->bufsize = handle->snapshot;
- if (sock_fd != -1)
- close(sock_fd);
+ /* Save the socket FD in the pcap structure */
+ handle->fd = sock_fd;
- if (fatal_err) {
- /*
- * Get rid of any link-layer type list we allocated.
- */
- if (handle->dlt_list != NULL)
- free(handle->dlt_list);
- return -2;
- } else
- return 0;
+ return 1;
#else
strncpy(ebuf,
"New packet capturing interface not supported by build "
@@ -1600,6 +1914,488 @@ live_open_new(pcap_t *handle, const char *device, int promisc,
#endif
}
+static int
+activate_mmap(pcap_t *handle)
+{
+#ifdef HAVE_PACKET_RING
+ int ret;
+
+ if (handle->opt.buffer_size == 0) {
+ /* by default request 2M for the ring buffer */
+ handle->opt.buffer_size = 2*1024*1024;
+ }
+ ret = prepare_tpacket_socket(handle);
+ if (ret == 0)
+ return ret;
+ ret = create_ring(handle);
+ if (ret == 0)
+ return ret;
+
+ /* override some defaults and inherit the other fields from
+ * activate_new
+ * handle->offset is used to get the current position into the rx ring
+ * handle->cc is used to store the ring size */
+ handle->read_op = pcap_read_linux_mmap;
+ handle->cleanup_op = pcap_cleanup_linux_mmap;
+ handle->setfilter_op = pcap_setfilter_linux_mmap;
+ handle->setnonblock_op = pcap_setnonblock_mmap;
+ handle->getnonblock_op = pcap_getnonblock_mmap;
+ handle->selectable_fd = handle->fd;
+ return 1;
+#else /* HAVE_PACKET_RING */
+ return 0;
+#endif /* HAVE_PACKET_RING */
+}
+
+#ifdef HAVE_PACKET_RING
+static int
+prepare_tpacket_socket(pcap_t *handle)
+{
+#ifdef HAVE_TPACKET2
+ socklen_t len;
+ int val;
+#endif
+
+ handle->md.tp_version = TPACKET_V1;
+ handle->md.tp_hdrlen = sizeof(struct tpacket_hdr);
+
+#ifdef HAVE_TPACKET2
+ /* Probe whether kernel supports TPACKET_V2 */
+ val = TPACKET_V2;
+ len = sizeof(val);
+ if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
+ if (errno == ENOPROTOOPT)
+ return 1;
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "can't get TPACKET_V2 header len on socket %d: %d-%s",
+ handle->fd, errno, pcap_strerror(errno));
+ return 0;
+ }
+ handle->md.tp_hdrlen = val;
+
+ val = TPACKET_V2;
+ if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val,
+ sizeof(val)) < 0) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "can't activate TPACKET_V2 on socket %d: %d-%s",
+ handle->fd, errno, pcap_strerror(errno));
+ return 0;
+ }
+ handle->md.tp_version = TPACKET_V2;
+
+ /* Reserve space for VLAN tag reconstruction */
+ val = VLAN_TAG_LEN;
+ if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val,
+ sizeof(val)) < 0) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "can't set up reserve on socket %d: %d-%s",
+ handle->fd, errno, pcap_strerror(errno));
+ return 0;
+ }
+
+#endif /* HAVE_TPACKET2 */
+ return 1;
+}
+
+static void
+compute_ring_block(int frame_size, unsigned *block_size, unsigned *frames_per_block)
+{
+ /* compute the minumum block size that will handle this frame.
+ * The block has to be page size aligned.
+ * The max block size allowed by the kernel is arch-dependent and
+ * it's not explicitly checked here. */
+ *block_size = getpagesize();
+ while (*block_size < frame_size)
+ *block_size <<= 1;
+
+ *frames_per_block = *block_size/frame_size;
+}
+
+static int
+create_ring(pcap_t *handle)
+{
+ unsigned i, j, ringsize, frames_per_block;
+ struct tpacket_req req;
+
+ /* Note that with large snapshot (say 64K) only a few frames
+ * will be available in the ring even with pretty large ring size
+ * (and a lot of memory will be unused).
+ * The snap len should be carefully chosen to achive best
+ * performance */
+ req.tp_frame_size = TPACKET_ALIGN(handle->snapshot +
+ TPACKET_ALIGN(handle->md.tp_hdrlen) +
+ sizeof(struct sockaddr_ll));
+ req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size;
+ compute_ring_block(req.tp_frame_size, &req.tp_block_size, &frames_per_block);
+ req.tp_block_nr = req.tp_frame_nr / frames_per_block;
+
+ /* req.tp_frame_nr is requested to match frames_per_block*req.tp_block_nr */
+ req.tp_frame_nr = req.tp_block_nr * frames_per_block;
+
+ /* ask the kernel to create the ring */
+retry:
+ if (setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,
+ (void *) &req, sizeof(req))) {
+ /* try to reduce requested ring size to prevent memory failure */
+ if ((errno == ENOMEM) && (req.tp_block_nr > 1)) {
+ req.tp_frame_nr >>= 1;
+ req.tp_block_nr = req.tp_frame_nr/frames_per_block;
+ goto retry;
+ }
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't create rx ring on "
+ "packet socket %d: %d-%s", handle->fd, errno,
+ pcap_strerror(errno));
+ return 0;
+ }
+
+ /* memory map the rx ring */
+ ringsize = req.tp_block_nr * req.tp_block_size;
+ handle->bp = mmap(0, ringsize, PROT_READ| PROT_WRITE, MAP_SHARED,
+ handle->fd, 0);
+ if (handle->bp == MAP_FAILED) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't mmap rx ring: %d-%s",
+ errno, pcap_strerror(errno));
+
+ /* clear the allocated ring on error*/
+ destroy_ring(handle);
+ return 0;
+ }
+
+ /* allocate a ring for each frame header pointer*/
+ handle->cc = req.tp_frame_nr;
+ handle->buffer = malloc(handle->cc * sizeof(union thdr *));
+ if (!handle->buffer) {
+ destroy_ring(handle);
+ return 0;
+ }
+
+ /* fill the header ring with proper frame ptr*/
+ handle->offset = 0;
+ for (i=0; i<req.tp_block_nr; ++i) {
+ void *base = &handle->bp[i*req.tp_block_size];
+ for (j=0; j<frames_per_block; ++j, ++handle->offset) {
+ RING_GET_FRAME(handle) = base;
+ base += req.tp_frame_size;
+ }
+ }
+
+ handle->bufsize = req.tp_frame_size;
+ handle->offset = 0;
+ return 1;
+}
+
+/* free all ring related resources*/
+static void
+destroy_ring(pcap_t *handle)
+{
+ /* tell the kernel to destroy the ring*/
+ struct tpacket_req req;
+ memset(&req, 0, sizeof(req));
+ setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,
+ (void *) &req, sizeof(req));
+
+ /* if ring is mapped, unmap it*/
+ if (handle->bp) {
+ /* need to re-compute the ring size */
+ unsigned frames_per_block, block_size;
+ compute_ring_block(handle->bufsize, &block_size, &frames_per_block);
+
+ /* do not perform sanity check here: we can't recover any error */
+ munmap(handle->bp, block_size * handle->cc / frames_per_block);
+ handle->bp = 0;
+ }
+}
+
+static void
+pcap_cleanup_linux_mmap( pcap_t *handle )
+{
+ destroy_ring(handle);
+ pcap_cleanup_linux(handle);
+}
+
+
+static int
+pcap_getnonblock_mmap(pcap_t *p, char *errbuf)
+{
+ /* use negative value of timeout to indicate non blocking ops */
+ return (p->md.timeout<0);
+}
+
+static int
+pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf)
+{
+ /* map each value to the corresponding 2's complement, to
+ * preserve the timeout value provided with pcap_set_timeout */
+ if (nonblock) {
+ if (p->md.timeout > 0)
+ p->md.timeout = p->md.timeout*-1 - 1;
+ } else
+ if (p->md.timeout < 0)
+ p->md.timeout = (p->md.timeout+1)*-1;
+ return 0;
+}
+
+static inline union thdr *
+pcap_get_ring_frame(pcap_t *handle, int status)
+{
+ union thdr h;
+
+ h.raw = RING_GET_FRAME(handle);
+ switch (handle->md.tp_version) {
+ case TPACKET_V1:
+ if (status != (h.h1->tp_status ? TP_STATUS_USER :
+ TP_STATUS_KERNEL))
+ return NULL;
+ break;
+#ifdef HAVE_TPACKET2
+ case TPACKET_V2:
+ if (status != (h.h2->tp_status ? TP_STATUS_USER :
+ TP_STATUS_KERNEL))
+ return NULL;
+ break;
+#endif
+ }
+ return h.raw;
+}
+
+static int
+pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback,
+ u_char *user)
+{
+ int pkts = 0;
+
+ /* wait for frames availability.*/
+ if ((handle->md.timeout >= 0) &&
+ !pcap_get_ring_frame(handle, TP_STATUS_USER)) {
+ struct pollfd pollinfo;
+ int ret;
+
+ pollinfo.fd = handle->fd;
+ pollinfo.events = POLLIN;
+
+ do {
+ /* poll() requires a negative timeout to wait forever */
+ ret = poll(&pollinfo, 1, (handle->md.timeout > 0)?
+ handle->md.timeout: -1);
+ if ((ret < 0) && (errno != EINTR)) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "can't poll on packet socket fd %d: %d-%s",
+ handle->fd, errno, pcap_strerror(errno));
+ return -1;
+ }
+ /* check for break loop condition on interrupted syscall*/
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return -2;
+ }
+ } while (ret < 0);
+ }
+
+ /* non-positive values of max_packets are used to require all
+ * packets currently available in the ring */
+ while ((pkts < max_packets) || (max_packets <= 0)) {
+ int run_bpf;
+ struct sockaddr_ll *sll;
+ struct pcap_pkthdr pcaphdr;
+ unsigned char *bp;
+ union thdr h;
+ unsigned int tp_len;
+ unsigned int tp_mac;
+ unsigned int tp_snaplen;
+ unsigned int tp_sec;
+ unsigned int tp_usec;
+
+ h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
+ if (!h.raw)
+ break;
+
+ switch (handle->md.tp_version) {
+ case TPACKET_V1:
+ tp_len = h.h1->tp_len;
+ tp_mac = h.h1->tp_mac;
+ tp_snaplen = h.h1->tp_snaplen;
+ tp_sec = h.h1->tp_sec;
+ tp_usec = h.h1->tp_usec;
+ break;
+#ifdef HAVE_TPACKET2
+ case TPACKET_V2:
+ tp_len = h.h2->tp_len;
+ tp_mac = h.h2->tp_mac;
+ tp_snaplen = h.h2->tp_snaplen;
+ tp_sec = h.h2->tp_sec;
+ tp_usec = h.h2->tp_nsec / 1000;
+ break;
+#endif
+ default:
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "unsupported tpacket version %d",
+ handle->md.tp_version);
+ return -1;
+ }
+ /* perform sanity check on internal offset. */
+ if (tp_mac + tp_snaplen > handle->bufsize) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "corrupted frame on kernel ring mac "
+ "offset %d + caplen %d > frame len %d",
+ tp_mac, tp_snaplen, handle->bufsize);
+ return -1;
+ }
+
+ /* run filter on received packet
+ * If the kernel filtering is enabled we need to run the
+ * filter until all the frames present into the ring
+ * at filter creation time are processed.
+ * In such case md.use_bpf is used as a counter for the
+ * packet we need to filter.
+ * Note: alternatively it could be possible to stop applying
+ * the filter when the ring became empty, but it can possibly
+ * happen a lot later... */
+ bp = (unsigned char*)h.raw + tp_mac;
+ run_bpf = (!handle->md.use_bpf) ||
+ ((handle->md.use_bpf>1) && handle->md.use_bpf--);
+ if (run_bpf && handle->fcode.bf_insns &&
+ (bpf_filter(handle->fcode.bf_insns, bp,
+ tp_len, tp_snaplen) == 0))
+ goto skip;
+
+ /* check direction and interface index */
+ sll = (void *)h.raw + TPACKET_ALIGN(handle->md.tp_hdrlen);
+ if ((sll->sll_ifindex == handle->md.lo_ifindex) &&
+ (sll->sll_pkttype == PACKET_OUTGOING))
+ goto skip;
+
+ /* get required packet info from ring header */
+ pcaphdr.ts.tv_sec = tp_sec;
+ pcaphdr.ts.tv_usec = tp_usec;
+ pcaphdr.caplen = tp_snaplen;
+ pcaphdr.len = tp_len;
+
+ /* if required build in place the sll header*/
+ if (handle->md.cooked) {
+ struct sll_header *hdrp;
+
+ /*
+ * The kernel should have left us with enough
+ * space for an sll header; back up the packet
+ * data pointer into that space, as that'll be
+ * the beginning of the packet we pass to the
+ * callback.
+ */
+ bp -= SLL_HDR_LEN;
+
+ /*
+ * Let's make sure that's past the end of
+ * the tpacket header, i.e. >=
+ * ((u_char *)thdr + TPACKET_HDRLEN), so we
+ * don't step on the header when we construct
+ * the sll header.
+ */
+ if (bp < (u_char *)h.raw +
+ TPACKET_ALIGN(handle->md.tp_hdrlen) +
+ sizeof(struct sockaddr_ll)) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "cooked-mode frame doesn't have room for sll header");
+ return -1;
+ }
+
+ /*
+ * OK, that worked; construct the sll header.
+ */
+ hdrp = (struct sll_header *)bp;
+ hdrp->sll_pkttype = map_packet_type_to_sll_type(
+ sll->sll_pkttype);
+ hdrp->sll_hatype = htons(sll->sll_hatype);
+ hdrp->sll_halen = htons(sll->sll_halen);
+ memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN);
+ hdrp->sll_protocol = sll->sll_protocol;
+
+ /* update packet len */
+ pcaphdr.caplen += SLL_HDR_LEN;
+ pcaphdr.len += SLL_HDR_LEN;
+ }
+
+#ifdef HAVE_TPACKET2
+ if (handle->md.tp_version == TPACKET_V2 && h.h2->tp_vlan_tci &&
+ tp_snaplen >= 2 * ETH_ALEN) {
+ struct vlan_tag *tag;
+
+ bp -= VLAN_TAG_LEN;
+ memmove(bp, bp + VLAN_TAG_LEN, 2 * ETH_ALEN);
+
+ tag = (struct vlan_tag *)(bp + 2 * ETH_ALEN);
+ tag->vlan_tpid = htons(ETH_P_8021Q);
+ tag->vlan_tci = htons(h.h2->tp_vlan_tci);
+
+ pcaphdr.caplen += VLAN_TAG_LEN;
+ pcaphdr.len += VLAN_TAG_LEN;
+ }
+#endif
+
+ /* pass the packet to the user */
+ pkts++;
+ callback(user, &pcaphdr, bp);
+ handle->md.packets_read++;
+
+skip:
+ /* next packet */
+ switch (handle->md.tp_version) {
+ case TPACKET_V1:
+ h.h1->tp_status = TP_STATUS_KERNEL;
+ break;
+#ifdef HAVE_TPACKET2
+ case TPACKET_V2:
+ h.h2->tp_status = TP_STATUS_KERNEL;
+ break;
+#endif
+ }
+ if (++handle->offset >= handle->cc)
+ handle->offset = 0;
+
+ /* check for break loop condition*/
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return -2;
+ }
+ }
+ return pkts;
+}
+
+static int
+pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter)
+{
+ int n, offset;
+ int ret = pcap_setfilter_linux(handle, filter);
+ if (ret < 0)
+ return ret;
+
+ /* if the kernel filter is enabled, we need to apply the filter on
+ * all packets present into the ring. Get an upper bound of their number
+ */
+ if (!handle->md.use_bpf)
+ return ret;
+
+ /* walk the ring backward and count the free slot */
+ offset = handle->offset;
+ if (--handle->offset < 0)
+ handle->offset = handle->cc - 1;
+ for (n=0; n < handle->cc; ++n) {
+ if (--handle->offset < 0)
+ handle->offset = handle->cc - 1;
+ if (!pcap_get_ring_frame(handle, TP_STATUS_KERNEL))
+ break;
+ }
+
+ /* be careful to not change current ring position */
+ handle->offset = offset;
+
+ /* store the number of packets currently present in the ring */
+ handle->md.use_bpf = 1 + (handle->cc - n);
+ return ret;
+}
+
+#endif /* HAVE_PACKET_RING */
+
+
#ifdef HAVE_PF_PACKET_SOCKETS
/*
* Return the index of the given device name. Fill ebuf and return
@@ -1624,6 +2420,8 @@ iface_get_id(int fd, const char *device, char *ebuf)
/*
* Bind the socket associated with FD to the given device.
+ * Return 1 on success, 0 if we should try a SOCK_PACKET socket,
+ * or a PCAP_ERROR_ value on a hard error.
*/
static int
iface_bind(int fd, int ifindex, char *ebuf)
@@ -1638,9 +2436,20 @@ iface_bind(int fd, int ifindex, char *ebuf)
sll.sll_protocol = htons(ETH_P_ALL);
if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "bind: %s", pcap_strerror(errno));
- return -1;
+ if (errno == ENETDOWN) {
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ return PCAP_ERROR_IFACE_NOT_UP;
+ } else {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "bind: %s", pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
}
/* Any pending errors, e.g., network is down? */
@@ -1648,251 +2457,815 @@ iface_bind(int fd, int ifindex, char *ebuf)
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"getsockopt: %s", pcap_strerror(errno));
- return -2;
+ return 0;
}
- if (err > 0) {
+ if (err == ENETDOWN) {
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ return PCAP_ERROR_IFACE_NOT_UP;
+ } else if (err > 0) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"bind: %s", pcap_strerror(err));
- return -2;
+ return 0;
}
- return 0;
+ return 1;
}
-#endif
-
-
-/* ===== Functions to interface to the older kernels ================== */
-
/*
- * With older kernels promiscuous mode is kind of interesting because we
- * have to reset the interface before exiting. The problem can't really
- * be solved without some daemon taking care of managing usage counts.
- * If we put the interface into promiscuous mode, we set a flag indicating
- * that we must take it out of that mode when the interface is closed,
- * and, when closing the interface, if that flag is set we take it out
- * of promiscuous mode.
+ * Check whether the device supports the Wireless Extensions.
+ * Returns 1 if it does, 0 if it doesn't, PCAP_ERROR_NO_SUCH_DEVICE
+ * if the device doesn't even exist.
*/
+static int
+has_wext(int sock_fd, const char *device, char *ebuf)
+{
+#ifdef IW_MODE_MONITOR
+ struct iwreq ireq;
+
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ if (ioctl(sock_fd, SIOCGIWNAME, &ireq) >= 0)
+ return 1; /* yes */
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "%s: SIOCGIWPRIV: %s", device, pcap_strerror(errno));
+ if (errno == ENODEV)
+ return PCAP_ERROR_NO_SUCH_DEVICE;
+#endif
+ return 0;
+}
/*
- * List of pcaps for which we turned promiscuous mode on by hand.
- * If there are any such pcaps, we arrange to call "pcap_close_all()"
- * when we exit, and have it close all of them to turn promiscuous mode
- * off.
+ * Per me si va ne la citta dolente,
+ * Per me si va ne l'etterno dolore,
+ * ...
+ * Lasciate ogne speranza, voi ch'intrate.
+ *
+ * XXX - airmon-ng does special stuff with the Orinoco driver and the
+ * wlan-ng driver.
*/
-static struct pcap *pcaps_to_close;
+typedef enum {
+ MONITOR_WEXT,
+ MONITOR_HOSTAP,
+ MONITOR_PRISM,
+ MONITOR_PRISM54,
+ MONITOR_ACX100,
+ MONITOR_RT2500,
+ MONITOR_RT2570,
+ MONITOR_RT73,
+ MONITOR_RTL8XXX
+} monitor_type;
/*
- * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to
- * be called on exit.
+ * Use the Wireless Extensions, if we have them, to try to turn monitor mode
+ * on if it's not already on.
+ *
+ * Returns 1 on success, 0 if we don't support the Wireless Extensions
+ * on this device, or a PCAP_ERROR_ value if we do support them but
+ * we weren't able to turn monitor mode on.
*/
-static int did_atexit;
-
-static void pcap_close_all(void)
+static int
+enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
{
- struct pcap *handle;
+#ifdef IW_MODE_MONITOR
+ /*
+ * XXX - at least some adapters require non-Wireless Extensions
+ * mechanisms to turn monitor mode on.
+ *
+ * Atheros cards might require that a separate "monitor virtual access
+ * point" be created, with later versions of the madwifi driver.
+ * airmon-ng does "wlanconfig ath create wlandev {if} wlanmode
+ * monitor -bssid", which apparently spits out a line "athN"
+ * where "athN" is the monitor mode device. To leave monitor
+ * mode, it destroys the monitor mode device.
+ *
+ * Some Intel Centrino adapters might require private ioctls to get
+ * radio headers; the ipw2200 and ipw3945 drivers allow you to
+ * configure a separate "rtapN" interface to capture in monitor
+ * mode without preventing the adapter from operating normally.
+ * (airmon-ng doesn't appear to use that, though.)
+ *
+ * It would be Truly Wonderful if mac80211 and nl80211 cleaned this
+ * up, and if all drivers were converted to mac80211 drivers.
+ *
+ * If interface {if} is a mac80211 driver, the file
+ * /sys/class/net/{if}/phy80211 is a symlink to
+ * /sys/class/ieee80211/{phydev}, for some {phydev}.
+ *
+ * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at
+ * least, has a "wmaster0" device and a "wlan0" device; the
+ * latter is the one with the IP address. Both show up in
+ * "tcpdump -D" output. Capturing on the wmaster0 device
+ * captures with 802.11 headers.
+ *
+ * airmon-ng searches through /sys/class/net for devices named
+ * monN, starting with mon0; as soon as one *doesn't* exist,
+ * it chooses that as the monitor device name. If the "iw"
+ * command exists, it does "iw dev {if} interface add {monif}
+ * type monitor", where {monif} is the monitor device. It
+ * then (sigh) sleeps .1 second, and then configures the
+ * device up. Otherwise, if /sys/class/ieee80211/{phydev}/add_iface
+ * is a file, it writes {mondev}, without a newline, to that file,
+ * and again (sigh) sleeps .1 second, and then iwconfig's that
+ * device into monitor mode and configures it up. Otherwise,
+ * you can't do monitor mode.
+ *
+ * All these devices are "glued" together by having the
+ * /sys/class/net/{device}/phy80211 links pointing to the same
+ * place, so, given a wmaster, wlan, or mon device, you can
+ * find the other devices by looking for devices with
+ * the same phy80211 link.
+ *
+ * To turn monitor mode off, delete the monitor interface,
+ * either with "iw dev {monif} interface del" or by sending
+ * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface
+ *
+ * Note: if you try to create a monitor device named "monN", and
+ * there's already a "monN" device, it fails, as least with
+ * the netlink interface (which is what iw uses), with a return
+ * value of -ENFILE. (Return values are negative errnos.) We
+ * could probably use that to find an unused device.
+ */
+ int err;
+ struct iwreq ireq;
+ struct iw_priv_args *priv;
+ monitor_type montype;
+ int i;
+ __u32 cmd;
+ int args[2];
+ int channel;
- while ((handle = pcaps_to_close) != NULL)
- pcap_close(handle);
-}
+ /*
+ * Does this device *support* the Wireless Extensions?
+ */
+ err = has_wext(sock_fd, device, handle->errbuf);
+ if (err <= 0)
+ return err; /* either it doesn't or the device doesn't even exist */
+ /*
+ * Try to get all the Wireless Extensions private ioctls
+ * supported by this device.
+ *
+ * First, get the size of the buffer we need, by supplying no
+ * buffer and a length of 0. If the device supports private
+ * ioctls, it should return E2BIG, with ireq.u.data.length set
+ * to the length we need. If it doesn't support them, it should
+ * return EOPNOTSUPP.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ ireq.u.data.pointer = args;
+ ireq.u.data.length = 0;
+ ireq.u.data.flags = 0;
+ if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) != -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: SIOCGIWPRIV with a zero-length buffer didn't fail!",
+ device);
+ return PCAP_ERROR;
+ }
+ if (errno == EOPNOTSUPP) {
+ /*
+ * No private ioctls, so we assume that there's only one
+ * DLT_ for monitor mode.
+ */
+ return 0;
+ }
+ if (errno != E2BIG) {
+ /*
+ * Failed.
+ */
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: SIOCGIWPRIV: %s", device, pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
+ priv = malloc(ireq.u.data.length * sizeof (struct iw_priv_args));
+ if (priv == NULL) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
+ ireq.u.data.pointer = priv;
+ if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: SIOCGIWPRIV: %s", device, pcap_strerror(errno));
+ free(priv);
+ return PCAP_ERROR;
+ }
-static void pcap_close_linux( pcap_t *handle )
-{
- struct pcap *p, *prevp;
- struct ifreq ifr;
+ /*
+ * Look for private ioctls to turn monitor mode on or, if
+ * monitor mode is on, to set the header type.
+ */
+ montype = MONITOR_WEXT;
+ cmd = 0;
+ for (i = 0; i < ireq.u.data.length; i++) {
+ if (strcmp(priv[i].name, "monitor_type") == 0) {
+ /*
+ * Hostap driver, use this one.
+ * Set monitor mode first.
+ * You can set it to 0 to get DLT_IEEE80211,
+ * 1 to get DLT_PRISM, or 2 to get
+ * DLT_IEEE80211_RADIO_AVS.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+ break;
+ if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+ break;
+ montype = MONITOR_HOSTAP;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "set_prismhdr") == 0) {
+ /*
+ * Prism54 driver, use this one.
+ * Set monitor mode first.
+ * You can set it to 2 to get DLT_IEEE80211
+ * or 3 or get DLT_PRISM.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+ break;
+ if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+ break;
+ montype = MONITOR_PRISM54;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "forceprismheader") == 0) {
+ /*
+ * RT2570 driver, use this one.
+ * Do this after turning monitor mode on.
+ * You can set it to 1 to get DLT_PRISM or 2
+ * to get DLT_IEEE80211.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+ break;
+ if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+ break;
+ montype = MONITOR_RT2570;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "forceprism") == 0) {
+ /*
+ * RT73 driver, use this one.
+ * Do this after turning monitor mode on.
+ * Its argument is a *string*; you can
+ * set it to "1" to get DLT_PRISM or "2"
+ * to get DLT_IEEE80211.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_CHAR)
+ break;
+ if (priv[i].set_args & IW_PRIV_SIZE_FIXED)
+ break;
+ montype = MONITOR_RT73;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "prismhdr") == 0) {
+ /*
+ * One of the RTL8xxx drivers, use this one.
+ * It can only be done after monitor mode
+ * has been turned on. You can set it to 1
+ * to get DLT_PRISM or 0 to get DLT_IEEE80211.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+ break;
+ if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+ break;
+ montype = MONITOR_RTL8XXX;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "rfmontx") == 0) {
+ /*
+ * RT2500 or RT61 driver, use this one.
+ * It has one one-byte parameter; set
+ * u.data.length to 1 and u.data.pointer to
+ * point to the parameter.
+ * It doesn't itself turn monitor mode on.
+ * You can set it to 1 to allow transmitting
+ * in monitor mode(?) and get DLT_IEEE80211,
+ * or set it to 0 to disallow transmitting in
+ * monitor mode(?) and get DLT_PRISM.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 2)
+ break;
+ montype = MONITOR_RT2500;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "monitor") == 0) {
+ /*
+ * Either ACX100 or hostap, use this one.
+ * It turns monitor mode on.
+ * If it takes two arguments, it's ACX100;
+ * the first argument is 1 for DLT_PRISM
+ * or 2 for DLT_IEEE80211, and the second
+ * argument is the channel on which to
+ * run. If it takes one argument, it's
+ * HostAP, and the argument is 2 for
+ * DLT_IEEE80211 and 3 for DLT_PRISM.
+ *
+ * If we see this, we don't quit, as this
+ * might be a version of the hostap driver
+ * that also supports "monitor_type".
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+ break;
+ switch (priv[i].set_args & IW_PRIV_SIZE_MASK) {
+
+ case 1:
+ montype = MONITOR_PRISM;
+ cmd = priv[i].cmd;
+ break;
+
+ case 2:
+ montype = MONITOR_ACX100;
+ cmd = priv[i].cmd;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ free(priv);
+
+ /*
+ * XXX - ipw3945? islism?
+ */
+
+ /*
+ * Get the old mode.
+ */
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ if (ioctl(sock_fd, SIOCGIWMODE, &ireq) == -1) {
+ /*
+ * We probably won't be able to set the mode, either.
+ */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /*
+ * Is it currently in monitor mode?
+ */
+ if (ireq.u.mode == IW_MODE_MONITOR) {
+ /*
+ * Yes. Just leave things as they are.
+ * We don't offer multiple link-layer types, as
+ * changing the link-layer type out from under
+ * somebody else capturing in monitor mode would
+ * be considered rude.
+ */
+ return 1;
+ }
+ /*
+ * No. We have to put the adapter into rfmon mode.
+ */
+
+ /*
+ * If we haven't already done so, arrange to have
+ * "pcap_close_all()" called when we exit.
+ */
+ if (!pcap_do_addexit(handle)) {
+ /*
+ * "atexit()" failed; don't put the interface
+ * in rfmon mode, just give up.
+ */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
- if (handle->md.clear_promisc) {
+ /*
+ * Save the old mode.
+ */
+ handle->md.oldmode = ireq.u.mode;
+
+ /*
+ * Put the adapter in rfmon mode. How we do this depends
+ * on whether we have a special private ioctl or not.
+ */
+ if (montype == MONITOR_PRISM) {
/*
- * We put the interface into promiscuous mode; take
- * it out of promiscuous mode.
+ * We have the "monitor" private ioctl, but none of
+ * the other private ioctls. Use this, and select
+ * the Prism header.
*
- * XXX - if somebody else wants it in promiscuous mode,
- * this code cannot know that, so it'll take it out
- * of promiscuous mode. That's not fixable in 2.0[.x]
- * kernels.
+ * If it fails, just fall back on SIOCSIWMODE.
*/
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, handle->md.device, sizeof(ifr.ifr_name));
- if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
- fprintf(stderr,
- "Can't restore interface flags (SIOCGIFFLAGS failed: %s).\n"
- "Please adjust manually.\n"
- "Hint: This can't happen with Linux >= 2.2.0.\n",
- strerror(errno));
- } else {
- if (ifr.ifr_flags & IFF_PROMISC) {
- /*
- * Promiscuous mode is currently on; turn it
- * off.
- */
- ifr.ifr_flags &= ~IFF_PROMISC;
- if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
- fprintf(stderr,
- "Can't restore interface flags (SIOCSIFFLAGS failed: %s).\n"
- "Please adjust manually.\n"
- "Hint: This can't happen with Linux >= 2.2.0.\n",
- strerror(errno));
- }
- }
+ memset(&ireq, 0, sizeof ireq);
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ ireq.u.data.length = 1; /* 1 argument */
+ args[0] = 3; /* request Prism header */
+ memcpy(ireq.u.name, args, IFNAMSIZ);
+ if (ioctl(sock_fd, cmd, &ireq) != -1) {
+ /*
+ * Success.
+ * Note that we have to put the old mode back
+ * when we close the device.
+ */
+ handle->md.must_clear |= MUST_CLEAR_RFMON;
+
+ /*
+ * Add this to the list of pcaps to close
+ * when we exit.
+ */
+ pcap_add_to_pcaps_to_close(handle);
+
+ return 1;
}
/*
- * Take this pcap out of the list of pcaps for which we
- * have to take the interface out of promiscuous mode.
+ * Failure. Fall back on SIOCSIWMODE.
*/
- for (p = pcaps_to_close, prevp = NULL; p != NULL;
- prevp = p, p = p->md.next) {
- if (p == handle) {
- /*
- * Found it. Remove it from the list.
- */
- if (prevp == NULL) {
- /*
- * It was at the head of the list.
- */
- pcaps_to_close = p->md.next;
- } else {
- /*
- * It was in the middle of the list.
- */
- prevp->md.next = p->md.next;
- }
- break;
- }
+ }
+
+ /*
+ * First, turn monitor mode on.
+ */
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ ireq.u.mode = IW_MODE_MONITOR;
+ if (ioctl(sock_fd, SIOCSIWMODE, &ireq) == -1) {
+ /*
+ * Scientist, you've failed.
+ */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /*
+ * XXX - airmon-ng does "iwconfig {if} key off" after setting
+ * monitor mode and setting the channel, and then does
+ * "iwconfig up".
+ */
+
+ /*
+ * Now select the appropriate radio header.
+ */
+ switch (montype) {
+
+ case MONITOR_WEXT:
+ /*
+ * We don't have any private ioctl to set the header.
+ */
+ break;
+
+ case MONITOR_HOSTAP:
+ /*
+ * Select the AVS header if we can, otherwise
+ * select the Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ args[0] = 2; /* request AVS header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ if (ioctl(sock_fd, cmd, &ireq) == -1) {
+ /*
+ * Failure - try the Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ args[0] = 1; /* request Prism header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
}
+ break;
+
+ case MONITOR_PRISM:
+ /*
+ * The private ioctl failed.
+ */
+ break;
+
+ case MONITOR_PRISM54:
+ /*
+ * Select the Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ args[0] = 3; /* request Prism header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+
+ case MONITOR_ACX100:
+ /*
+ * Get the current channel.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ if (ioctl(sock_fd, SIOCGIWFREQ, &ireq) == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: SIOCGIWFREQ: %s", device,
+ pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
+ channel = ireq.u.freq.m;
+
+ /*
+ * Select the Prism header, and set the channel to the
+ * current value.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ args[0] = 1; /* request Prism header */
+ args[1] = channel; /* set channel */
+ memcpy(ireq.u.name, args, 2*sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+
+ case MONITOR_RT2500:
+ /*
+ * Disallow transmission - that turns on the
+ * Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ args[0] = 0; /* disallow transmitting */
+ memcpy(ireq.u.name, args, sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+
+ case MONITOR_RT2570:
+ /*
+ * Force the Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ args[0] = 1; /* request Prism header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+
+ case MONITOR_RT73:
+ /*
+ * Force the Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ ireq.u.data.length = 1; /* 1 argument */
+ ireq.u.data.pointer = "1";
+ ireq.u.data.flags = 0;
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+
+ case MONITOR_RTL8XXX:
+ /*
+ * Force the Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ strncpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
+ args[0] = 1; /* request Prism header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
+ break;
}
- if (handle->md.device != NULL)
- free(handle->md.device);
- handle->md.device = NULL;
- pcap_close_common(handle);
+ /*
+ * Note that we have to put the old mode back when we
+ * close the device.
+ */
+ handle->md.must_clear |= MUST_CLEAR_RFMON;
+
+ /*
+ * Add this to the list of pcaps to close when we exit.
+ */
+ pcap_add_to_pcaps_to_close(handle);
+
+ return 1;
+#else
+ /*
+ * We don't have the Wireless Extensions available, so we can't
+ * do monitor mode.
+ */
+ return 0;
+#endif
}
+#endif /* HAVE_PF_PACKET_SOCKETS */
+
+/* ===== Functions to interface to the older kernels ================== */
+
/*
- * Try to open a packet socket using the old kernel interface.
- * Returns 0 on failure.
- * FIXME: 0 uses to mean success (Sebastian)
+ * Try to open a packet socket using the old kernel interface.
+ * Returns 1 on success and a PCAP_ERROR_ value on an error.
*/
static int
-live_open_old(pcap_t *handle, const char *device, int promisc,
- int to_ms, char *ebuf)
+activate_old(pcap_t *handle)
{
int arptype;
struct ifreq ifr;
+ const char *device = handle->opt.source;
+ struct utsname utsname;
+ int mtu;
- do {
- /* Open the socket */
+ /* Open the socket */
- handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
- if (handle->fd == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "socket: %s", pcap_strerror(errno));
- break;
- }
+ handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
+ if (handle->fd == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "socket: %s", pcap_strerror(errno));
+ return PCAP_ERROR_PERM_DENIED;
+ }
- /* It worked - we are using the old interface */
- handle->md.sock_packet = 1;
+ /* It worked - we are using the old interface */
+ handle->md.sock_packet = 1;
- /* ...which means we get the link-layer header. */
- handle->md.cooked = 0;
+ /* ...which means we get the link-layer header. */
+ handle->md.cooked = 0;
- /* Bind to the given device */
+ /* Bind to the given device */
- if (!device) {
- strncpy(ebuf, "pcap_open_live: The \"any\" device isn't supported on 2.0[.x]-kernel systems",
- PCAP_ERRBUF_SIZE);
- break;
- }
- if (iface_bind_old(handle->fd, device, ebuf) == -1)
- break;
+ if (!device) {
+ strncpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems",
+ PCAP_ERRBUF_SIZE);
+ return PCAP_ERROR;
+ }
+ if (iface_bind_old(handle->fd, device, handle->errbuf) == -1)
+ return PCAP_ERROR;
- /*
- * Try to get the link-layer type.
- */
- arptype = iface_get_arptype(handle->fd, device, ebuf);
- if (arptype == -1)
- break;
+ /*
+ * Try to get the link-layer type.
+ */
+ arptype = iface_get_arptype(handle->fd, device, handle->errbuf);
+ if (arptype < 0)
+ return PCAP_ERROR;
- /*
- * Try to find the DLT_ type corresponding to that
- * link-layer type.
- */
- map_arphrd_to_dlt(handle, arptype, 0);
- if (handle->linktype == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "unknown arptype %d", arptype);
- break;
- }
+ /*
+ * Try to find the DLT_ type corresponding to that
+ * link-layer type.
+ */
+ map_arphrd_to_dlt(handle, arptype, 0);
+ if (handle->linktype == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "unknown arptype %d", arptype);
+ return PCAP_ERROR;
+ }
- /* Go to promisc mode if requested */
+ /* Go to promisc mode if requested */
- if (promisc) {
- memset(&ifr, 0, sizeof(ifr));
- strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
- if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "SIOCGIFFLAGS: %s", pcap_strerror(errno));
- break;
- }
- if ((ifr.ifr_flags & IFF_PROMISC) == 0) {
- /*
- * Promiscuous mode isn't currently on,
- * so turn it on, and remember that
- * we should turn it off when the
- * pcap_t is closed.
- */
+ if (handle->opt.promisc) {
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "SIOCGIFFLAGS: %s", pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
+ if ((ifr.ifr_flags & IFF_PROMISC) == 0) {
+ /*
+ * Promiscuous mode isn't currently on,
+ * so turn it on, and remember that
+ * we should turn it off when the
+ * pcap_t is closed.
+ */
+ /*
+ * If we haven't already done so, arrange
+ * to have "pcap_close_all()" called when
+ * we exit.
+ */
+ if (!pcap_do_addexit(handle)) {
/*
- * If we haven't already done so, arrange
- * to have "pcap_close_all()" called when
- * we exit.
+ * "atexit()" failed; don't put
+ * the interface in promiscuous
+ * mode, just give up.
*/
- if (!did_atexit) {
- if (atexit(pcap_close_all) == -1) {
- /*
- * "atexit()" failed; don't
- * put the interface in
- * promiscuous mode, just
- * give up.
- */
- strncpy(ebuf, "atexit failed",
- PCAP_ERRBUF_SIZE);
- break;
- }
- did_atexit = 1;
- }
-
- ifr.ifr_flags |= IFF_PROMISC;
- if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "SIOCSIFFLAGS: %s",
- pcap_strerror(errno));
- break;
- }
- handle->md.clear_promisc = 1;
+ return PCAP_ERROR;
+ }
- /*
- * Add this to the list of pcaps
- * to close when we exit.
- */
- handle->md.next = pcaps_to_close;
- pcaps_to_close = handle;
+ ifr.ifr_flags |= IFF_PROMISC;
+ if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "SIOCSIFFLAGS: %s",
+ pcap_strerror(errno));
+ return PCAP_ERROR;
}
+ handle->md.must_clear |= MUST_CLEAR_PROMISC;
+
+ /*
+ * Add this to the list of pcaps
+ * to close when we exit.
+ */
+ pcap_add_to_pcaps_to_close(handle);
}
+ }
+ /*
+ * Compute the buffer size.
+ *
+ * We're using SOCK_PACKET, so this might be a 2.0[.x]
+ * kernel, and might require special handling - check.
+ */
+ if (uname(&utsname) < 0 ||
+ strncmp(utsname.release, "2.0", 3) == 0) {
/*
- * Default value for offset to align link-layer payload
- * on a 4-byte boundary.
+ * Either we couldn't find out what kernel release
+ * this is, or it's a 2.0[.x] kernel.
+ *
+ * In the 2.0[.x] kernel, a "recvfrom()" on
+ * a SOCK_PACKET socket, with MSG_TRUNC set, will
+ * return the number of bytes read, so if we pass
+ * a length based on the snapshot length, it'll
+ * return the number of bytes from the packet
+ * copied to userland, not the actual length
+ * of the packet.
+ *
+ * This means that, for example, the IP dissector
+ * in tcpdump will get handed a packet length less
+ * than the length in the IP header, and will
+ * complain about "truncated-ip".
+ *
+ * So we don't bother trying to copy from the
+ * kernel only the bytes in which we're interested,
+ * but instead copy them all, just as the older
+ * versions of libpcap for Linux did.
+ *
+ * The buffer therefore needs to be big enough to
+ * hold the largest packet we can get from this
+ * device. Unfortunately, we can't get the MRU
+ * of the network; we can only get the MTU. The
+ * MTU may be too small, in which case a packet larger
+ * than the buffer size will be truncated *and* we
+ * won't get the actual packet size.
+ *
+ * However, if the snapshot length is larger than
+ * the buffer size based on the MTU, we use the
+ * snapshot length as the buffer size, instead;
+ * this means that with a sufficiently large snapshot
+ * length we won't artificially truncate packets
+ * to the MTU-based size.
+ *
+ * This mess just one of many problems with packet
+ * capture on 2.0[.x] kernels; you really want a
+ * 2.2[.x] or later kernel if you want packet capture
+ * to work well.
*/
- handle->offset = 0;
-
- return 1;
+ mtu = iface_get_mtu(handle->fd, device, handle->errbuf);
+ if (mtu == -1)
+ return PCAP_ERROR;
+ handle->bufsize = MAX_LINKHEADER_SIZE + mtu;
+ if (handle->bufsize < handle->snapshot)
+ handle->bufsize = handle->snapshot;
+ } else {
+ /*
+ * This is a 2.2[.x] or later kernel.
+ *
+ * We can safely pass "recvfrom()" a byte count
+ * based on the snapshot length.
+ */
+ handle->bufsize = handle->snapshot;
+ }
- } while (0);
+ /*
+ * Default value for offset to align link-layer payload
+ * on a 4-byte boundary.
+ */
+ handle->offset = 0;
- pcap_close_linux(handle);
- return 0;
+ return 1;
}
/*
@@ -1971,7 +3344,13 @@ iface_get_arptype(int fd, const char *device, char *ebuf)
if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
snprintf(ebuf, PCAP_ERRBUF_SIZE,
"SIOCGIFHWADDR: %s", pcap_strerror(errno));
- return -1;
+ if (errno == ENODEV) {
+ /*
+ * No such device.
+ */
+ return PCAP_ERROR_NO_SUCH_DEVICE;
+ }
+ return PCAP_ERROR;
}
return ifr.ifr_hwaddr.sa_family;
@@ -1995,7 +3374,7 @@ fix_program(pcap_t *handle, struct sock_fprog *fcode)
len = handle->fcode.bf_len;
f = (struct bpf_insn *)malloc(prog_size);
if (f == NULL) {
- snprintf(handle->errbuf, sizeof(handle->errbuf),
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"malloc: %s", pcap_strerror(errno));
return -1;
}
@@ -2167,7 +3546,7 @@ set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode)
if (save_errno != EAGAIN) {
/* Fatal error */
reset_kernel_filter(handle);
- snprintf(handle->errbuf, sizeof(handle->errbuf),
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
"recv: %s", pcap_strerror(save_errno));
return -2;
}
diff --git a/contrib/libpcap/pcap-namedb.h b/contrib/libpcap/pcap-namedb.h
index bbd06b0..e9ef300 100644
--- a/contrib/libpcap/pcap-namedb.h
+++ b/contrib/libpcap/pcap-namedb.h
@@ -31,60 +31,13 @@
* SUCH DAMAGE.
*
* $FreeBSD$
- * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.10 2005/03/17 07:02:32 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.13 2006/10/04 18:13:32 guy Exp $ (LBL)
*/
-#ifndef lib_pcap_namedb_h
-#define lib_pcap_namedb_h
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * As returned by the pcap_next_etherent()
- * XXX this stuff doesn't belong in this interface, but this
- * library already must do name to address translation, so
- * on systems that don't have support for /etc/ethers, we
- * export these hooks since they'll
- */
-struct pcap_etherent {
- u_char addr[6];
- char name[122];
-};
-#ifndef PCAP_ETHERS_FILE
-#define PCAP_ETHERS_FILE "/etc/ethers"
-#endif
-struct pcap_etherent *pcap_next_etherent(FILE *);
-u_char *pcap_ether_hostton(const char*);
-u_char *pcap_ether_aton(const char *);
-
-bpf_u_int32 **pcap_nametoaddr(const char *);
-#ifdef INET6
-struct addrinfo *pcap_nametoaddrinfo(const char *);
-#endif
-bpf_u_int32 pcap_nametonetaddr(const char *);
-
-int pcap_nametoport(const char *, int *, int *);
-int pcap_nametoportrange(const char *, int *, int *, int *);
-int pcap_nametoproto(const char *);
-int pcap_nametoeproto(const char *);
-int pcap_nametollc(const char *);
/*
- * If a protocol is unknown, PROTO_UNDEF is returned.
- * Also, pcap_nametoport() returns the protocol along with the port number.
- * If there are ambiguous entried in /etc/services (i.e. domain
- * can be either tcp or udp) PROTO_UNDEF is returned.
+ * For backwards compatibility.
+ *
+ * Note to OS vendors: do NOT get rid of this file! Some applications
+ * might expect to be able to include <pcap-namedb.h>.
*/
-#define PROTO_UNDEF -1
-
-/* XXX move these to pcap-int.h? */
-int __pcap_atodn(const char *, bpf_u_int32 *);
-int __pcap_atoin(const char *, bpf_u_int32 *);
-u_short __pcap_nametodnaddr(const char *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+#include <pcap/namedb.h>
diff --git a/contrib/libpcap/pcap-nit.c b/contrib/libpcap/pcap-nit.c
index 94c4528..ed04208 100644
--- a/contrib/libpcap/pcap-nit.c
+++ b/contrib/libpcap/pcap-nit.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.57.2.1 2005/05/03 18:54:37 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.58.2.4 2008-04-14 20:41:52 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -99,7 +99,6 @@ static int
pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
register int cc, n;
- register struct bpf_insn *fcode = p->fcode.bf_insns;
register u_char *bp, *cp, *ep;
register struct nit_hdr *nh;
register int caplen;
@@ -175,13 +174,13 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
caplen = nh->nh_wirelen;
if (caplen > p->snapshot)
caplen = p->snapshot;
- if (bpf_filter(fcode, cp, nh->nh_wirelen, caplen)) {
+ if (bpf_filter(p->fcode.bf_insns, cp, nh->nh_wirelen, caplen)) {
struct pcap_pkthdr h;
h.ts = nh->nh_timestamp;
h.len = nh->nh_wirelen;
h.caplen = caplen;
(*callback)(user, &h, cp);
- if (++n >= cnt && cnt >= 0) {
+ if (++n >= cnt && cnt > 0) {
p->cc = ep - bp;
p->bp = bp;
return (n);
@@ -238,51 +237,43 @@ nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
return (0);
}
-static void
-pcap_close_nit(pcap_t *p)
-{
- pcap_close_common(p);
- if (p->device != NULL)
- free(p->device);
-}
-
-pcap_t *
-pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
- char *ebuf)
+static int
+pcap_activate_nit(pcap_t *p)
{
int fd;
struct sockaddr_nit snit;
- register pcap_t *p;
- p = (pcap_t *)malloc(sizeof(*p));
- if (p == NULL) {
- strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
- return (NULL);
+ if (p->opt.rfmon) {
+ /*
+ * No monitor mode on SunOS 3.x or earlier (no
+ * Wi-Fi *devices* for the hardware that supported
+ * them!).
+ */
+ return (PCAP_ERROR_RFMON_NOTSUP);
}
- if (snaplen < 96)
+ if (p->snapshot < 96)
/*
* NIT requires a snapshot length of at least 96.
*/
- snaplen = 96;
+ p->snapshot = 96;
memset(p, 0, sizeof(*p));
p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
if (fd < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
goto bad;
}
snit.snit_family = AF_NIT;
- (void)strncpy(snit.snit_ifname, device, NITIFSIZ);
+ (void)strncpy(snit.snit_ifname, p->opt.source, NITIFSIZ);
if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"bind: %s: %s", snit.snit_ifname, pcap_strerror(errno));
goto bad;
}
- p->snapshot = snaplen;
- nit_setflags(p->fd, promisc, to_ms, ebuf);
+ nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf);
/*
* NIT supports only ethernets.
@@ -292,17 +283,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->bufsize = BUFSPACE;
p->buffer = (u_char *)malloc(p->bufsize);
if (p->buffer == NULL) {
- strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
- goto bad;
- }
-
- /*
- * We need the device name in order to send packets.
- */
- p->device = strdup(device);
- if (p->device == NULL) {
- strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
- free(p->buffer);
+ strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
goto bad;
}
@@ -339,14 +320,23 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
p->stats_op = pcap_stats_nit;
- p->close_op = pcap_close_nit;
- return (p);
+ return (0);
bad:
- if (fd >= 0)
- close(fd);
- free(p);
- return (NULL);
+ return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_nit;
+ return (p);
}
int
diff --git a/contrib/libpcap/pcap-nit.h b/contrib/libpcap/pcap-nit.h
deleted file mode 100644
index 52f5fc4..0000000
--- a/contrib/libpcap/pcap-nit.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 1990, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Lawrence Berkeley Laboratory,
- * Berkeley, CA. The name of the University may not be used to
- * endorse or promote products derived from this software without
- * specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * @(#) $Header: /tcpdump/master/libpcap/pcap-nit.h,v 1.2.1.1 1999/10/07 23:46:40 mcr Exp $ (LBL)
- */
diff --git a/contrib/libpcap/pcap-null.c b/contrib/libpcap/pcap-null.c
index 06e3ab3..f72a0c3 100644
--- a/contrib/libpcap/pcap-null.c
+++ b/contrib/libpcap/pcap-null.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.21 2003/11/15 23:24:03 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.21.4.1 2008-04-04 19:39:06 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -40,10 +40,9 @@ static const char rcsid[] _U_ =
static char nosup[] = "live packet capture not supported on this system";
pcap_t *
-pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
- char *ebuf)
+pcap_activate(pcap_t *p)
{
- (void)strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE);
+ (void)strlcpy(p->errbuf, nosup, PCAP_ERRBUF_SIZE);
return (NULL);
}
diff --git a/contrib/libpcap/pcap-pf.c b/contrib/libpcap/pcap-pf.c
index e733540..be93814 100644
--- a/contrib/libpcap/pcap-pf.c
+++ b/contrib/libpcap/pcap-pf.c
@@ -24,7 +24,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.91.2.2 2005/05/03 18:54:37 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.94.2.3 2008-04-14 20:41:52 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -62,7 +62,7 @@ struct rtentry;
#include <unistd.h>
/*
- * Make "pcap.h" not include "pcap-bpf.h"; we are going to include the
+ * Make "pcap.h" not include "pcap/bpf.h"; we are going to include the
* native OS version, as we need various BPF ioctls from it.
*/
#define PCAP_DONT_INCLUDE_PCAP_BPF_H
@@ -88,7 +88,6 @@ static int
pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
{
register u_char *p, *bp;
- struct bpf_insn *fcode;
register int cc, n, buflen, inc;
register struct enstamp *sp;
#ifdef LBL_ALIGN
@@ -98,7 +97,6 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
register int pad;
#endif
- fcode = pc->md.use_bpf ? NULL : pc->fcode.bf_insns;
again:
cc = pc->cc;
if (cc == 0) {
@@ -187,7 +185,8 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
/*
* Short-circuit evaluation: if using BPF filter
- * in kernel, no need to do it now.
+ * in kernel, no need to do it now - we already know
+ * the packet passed the filter.
*
#ifdef PCAP_FDDIPAD
* Note: the filter code was generated assuming
@@ -197,8 +196,8 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
* skipping that padding.
#endif
*/
- if (fcode == NULL ||
- bpf_filter(fcode, p, sp->ens_count, buflen)) {
+ if (pc->md.use_bpf ||
+ bpf_filter(pc->fcode.bf_insns, p, sp->ens_count, buflen)) {
struct pcap_pkthdr h;
pc->md.TotAccepted++;
h.ts = sp->ens_tstamp;
@@ -285,30 +284,21 @@ pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
}
/*
- * We include the OS's <net/bpf.h>, not our "pcap-bpf.h", so we probably
+ * We include the OS's <net/bpf.h>, not our "pcap/bpf.h", so we probably
* don't get DLT_DOCSIS defined.
*/
#ifndef DLT_DOCSIS
#define DLT_DOCSIS 143
#endif
-pcap_t *
-pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
- char *ebuf)
+static int
+pcap_activate_pf(pcap_t *p)
{
- pcap_t *p;
short enmode;
int backlog = -1; /* request the most */
struct enfilter Filter;
struct endevp devparams;
- p = (pcap_t *)malloc(sizeof(*p));
- if (p == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "pcap_open_live: %s", pcap_strerror(errno));
- return (0);
- }
- memset(p, 0, sizeof(*p));
/*
* Initially try a read/write open (to allow the inject
* method to work). If that fails due to permission
@@ -328,21 +318,21 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* "const char *" as its first argument. That appears to be
* the case, at least on Digital UNIX 4.0.
*/
- p->fd = pfopen(device, O_RDWR);
+ p->fd = pfopen(p->opt.source, O_RDWR);
if (p->fd == -1 && errno == EACCES)
- p->fd = pfopen(device, O_RDONLY);
+ p->fd = pfopen(p->opt.source, O_RDONLY);
if (p->fd < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\
your system may not be properly configured; see the packetfilter(4) man page\n",
- device, pcap_strerror(errno));
+ p->opt.source, pcap_strerror(errno));
goto bad;
}
p->md.OrigMissed = -1;
enmode = ENTSTAMP|ENBATCH|ENNONEXCL;
- if (promisc)
+ if (p->opt.promisc)
enmode |= ENPROMISC;
if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s",
pcap_strerror(errno));
goto bad;
}
@@ -353,13 +343,13 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
#endif
/* set the backlog */
if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s",
pcap_strerror(errno));
goto bad;
}
/* discover interface type */
if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s",
pcap_strerror(errno));
goto bad;
}
@@ -441,8 +431,8 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
* framing", there's not much we can do, as that
* doesn't specify a particular type of header.
*/
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown data-link type %u",
- devparams.end_dev_type);
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "unknown data-link type %u", devparams.end_dev_type);
goto bad;
}
/* set truncation */
@@ -451,32 +441,31 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
p->fddipad = PCAP_FDDIPAD;
/* packetfilter includes the padding in the snapshot */
- snaplen += PCAP_FDDIPAD;
+ p->snapshot += PCAP_FDDIPAD;
} else
p->fddipad = 0;
#endif
- if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&snaplen) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",
+ if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s",
pcap_strerror(errno));
goto bad;
}
- p->snapshot = snaplen;
/* accept all packets */
memset(&Filter, 0, sizeof(Filter));
Filter.enf_Priority = 37; /* anything > 2 */
Filter.enf_FilterLen = 0; /* means "always true" */
if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s",
pcap_strerror(errno));
goto bad;
}
- if (to_ms != 0) {
+ if (p->md.timeout != 0) {
struct timeval timeout;
- timeout.tv_sec = to_ms / 1000;
- timeout.tv_usec = (to_ms * 1000) % 1000000;
+ timeout.tv_sec = p->md.timeout / 1000;
+ timeout.tv_usec = (p->md.timeout * 1000) % 1000000;
if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s",
pcap_strerror(errno));
goto bad;
}
@@ -485,7 +474,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
p->bufsize = BUFSPACE;
p->buffer = (u_char*)malloc(p->bufsize + p->offset);
if (p->buffer == NULL) {
- strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
+ strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
goto bad;
}
@@ -502,19 +491,23 @@ your system may not be properly configured; see the packetfilter(4) man page\n",
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
p->stats_op = pcap_stats_pf;
- p->close_op = pcap_close_common;
- return (p);
+ return (0);
bad:
- if (p->fd >= 0)
- close(p->fd);
- /*
- * Get rid of any link-layer type list we allocated.
- */
- if (p->dlt_list != NULL)
- free(p->dlt_list);
- free(p);
- return (NULL);
+ return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_pf;
+ return (p);
}
int
diff --git a/contrib/libpcap/pcap-pf.h b/contrib/libpcap/pcap-pf.h
deleted file mode 100644
index 60bea83..0000000
--- a/contrib/libpcap/pcap-pf.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright (c) 1990, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Lawrence Berkeley Laboratory,
- * Berkeley, CA. The name of the University may not be used to
- * endorse or promote products derived from this software without
- * specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * @(#) $Header: /tcpdump/master/libpcap/pcap-pf.h,v 1.2.1.1 1999/10/07 23:46:40 mcr Exp $ (LBL)
- */
diff --git a/contrib/libpcap/pcap-savefile.manfile b/contrib/libpcap/pcap-savefile.manfile
new file mode 100644
index 0000000..21fdb2e
--- /dev/null
+++ b/contrib/libpcap/pcap-savefile.manfile
@@ -0,0 +1,127 @@
+'\" t
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap-savefile.manfile.in,v 1.1.2.3 2008-10-24 07:34:06 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-SAVEFILE 5 "21 October 2008"
+.SH NAME
+pcap-savefile \- libpcap savefile format
+.SH DESCRIPTION
+NOTE: applications and libraries should, if possible, use libpcap to
+read savefiles, rather than having their own code to read savefiles.
+If, in the future, a new file format is supported by libpcap,
+applications and libraries using libpcap to read savefiles will be able
+to read the new format of savefiles, but applications and libraries
+using their own code to read savefiles will have to be changed to
+support the new file format.
+.PP
+``Savefiles'' read and written by libpcap and applications using libpcap
+start with a per-file header. The format of the per-file header is:
+.RS
+.TS
+box;
+c s
+c | c
+c s.
+Magic number
+_
+Major version Minor version
+_
+Time zone offset
+_
+Time stamp accuracy
+_
+Snapshot length
+_
+Link-layer header type
+.TE
+.RE
+.PP
+All fields in the per-file header are in the byte order of the host
+writing the file. The first field in the per-file header is a 4-byte
+magic number, with the value 0xa1b2c3d4. The magic number, when read by
+a host with the same byte order as the host that wrote the file, will
+have the value 0xa1b2c3d4, and, when read by a host with the opposite
+byte order as the host that wrote the file, will have the value
+0xd4c3b2a1. That allows software reading the file to determine whether
+the byte order of the host that wrote the file is the same as the byte
+order of the host on which the file is being read, and thus whether the
+values in the per-file and per-packet headers need to be byte-swapped.
+.PP
+Following this are:
+.IP
+A 2-byte file format major version number; the current version number is
+2.
+.IP
+A 2-byte file format minor version number; the current version number is
+4.
+.IP
+A 4-byte time zone offset; this is always 0.
+.IP
+A 4-byte number giving the accuracy of time stamps in the file; this is
+always 0.
+.IP
+A 4-byte number giving the "snapshot length" of the capture; packets
+longer than the snapshot length are truncated to the snapshot length, so
+that, if the snapshot length is
+.IR N ,
+only the first
+.I N
+bytes of a packet longer than
+.I N
+bytes will be saved in the capture.
+.IP
+a 4-byte number giving the link-layer header type for packets in the
+capture; see
+.BR pcap-linktype (7)
+for the
+.B LINKTYPE_
+values that can appear in this field.
+.PP
+Following the per-file header are zero or more packets; each packet
+begins with a per-packet header, which is immediately followed by the
+raw packet data. The format of the per-packet header is:
+.RS
+.TS
+box;
+c.
+Time stamp, seconds value
+_
+Time stamp, microseconds value
+_
+Length of captured packet data
+_
+Un-truncated length of the packet data
+.TE
+.RE
+.PP
+All fields in the per-packet header are in the byte order of the host
+writing the file. The per-packet header begins with a time stamp giving
+the approximate time the packet was captured; the time stamp consists of
+a 4-byte value, giving the time in seconds since January 1, 1970,
+00:00:00 UTC, followed by a 4-byte value, giving the time in
+microseconds since that second. Following that are a 4-byte value
+giving the number of bytes of captured data that follow the per-packet
+header and a 4-byte value giving the number of bytes that would have
+been present had the packet not been truncated by the snapshot length.
+The two lengths will be equal if the number of bytes of packet data are
+less than or equal to the snapshot length.
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(7)
diff --git a/contrib/libpcap/pcap-savefile.manfile.in b/contrib/libpcap/pcap-savefile.manfile.in
new file mode 100644
index 0000000..3b9503f
--- /dev/null
+++ b/contrib/libpcap/pcap-savefile.manfile.in
@@ -0,0 +1,127 @@
+'\" t
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap-savefile.manfile.in,v 1.1.2.3 2008-10-24 07:34:06 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-SAVEFILE @MAN_FILE_FORMATS@ "21 October 2008"
+.SH NAME
+pcap-savefile \- libpcap savefile format
+.SH DESCRIPTION
+NOTE: applications and libraries should, if possible, use libpcap to
+read savefiles, rather than having their own code to read savefiles.
+If, in the future, a new file format is supported by libpcap,
+applications and libraries using libpcap to read savefiles will be able
+to read the new format of savefiles, but applications and libraries
+using their own code to read savefiles will have to be changed to
+support the new file format.
+.PP
+``Savefiles'' read and written by libpcap and applications using libpcap
+start with a per-file header. The format of the per-file header is:
+.RS
+.TS
+box;
+c s
+c | c
+c s.
+Magic number
+_
+Major version Minor version
+_
+Time zone offset
+_
+Time stamp accuracy
+_
+Snapshot length
+_
+Link-layer header type
+.TE
+.RE
+.PP
+All fields in the per-file header are in the byte order of the host
+writing the file. The first field in the per-file header is a 4-byte
+magic number, with the value 0xa1b2c3d4. The magic number, when read by
+a host with the same byte order as the host that wrote the file, will
+have the value 0xa1b2c3d4, and, when read by a host with the opposite
+byte order as the host that wrote the file, will have the value
+0xd4c3b2a1. That allows software reading the file to determine whether
+the byte order of the host that wrote the file is the same as the byte
+order of the host on which the file is being read, and thus whether the
+values in the per-file and per-packet headers need to be byte-swapped.
+.PP
+Following this are:
+.IP
+A 2-byte file format major version number; the current version number is
+2.
+.IP
+A 2-byte file format minor version number; the current version number is
+4.
+.IP
+A 4-byte time zone offset; this is always 0.
+.IP
+A 4-byte number giving the accuracy of time stamps in the file; this is
+always 0.
+.IP
+A 4-byte number giving the "snapshot length" of the capture; packets
+longer than the snapshot length are truncated to the snapshot length, so
+that, if the snapshot length is
+.IR N ,
+only the first
+.I N
+bytes of a packet longer than
+.I N
+bytes will be saved in the capture.
+.IP
+a 4-byte number giving the link-layer header type for packets in the
+capture; see
+.BR pcap-linktype (@MAN_MISC_INFO@)
+for the
+.B LINKTYPE_
+values that can appear in this field.
+.PP
+Following the per-file header are zero or more packets; each packet
+begins with a per-packet header, which is immediately followed by the
+raw packet data. The format of the per-packet header is:
+.RS
+.TS
+box;
+c.
+Time stamp, seconds value
+_
+Time stamp, microseconds value
+_
+Length of captured packet data
+_
+Un-truncated length of the packet data
+.TE
+.RE
+.PP
+All fields in the per-packet header are in the byte order of the host
+writing the file. The per-packet header begins with a time stamp giving
+the approximate time the packet was captured; the time stamp consists of
+a 4-byte value, giving the time in seconds since January 1, 1970,
+00:00:00 UTC, followed by a 4-byte value, giving the time in
+microseconds since that second. Following that are a 4-byte value
+giving the number of bytes of captured data that follow the per-packet
+header and a 4-byte value giving the number of bytes that would have
+been present had the packet not been truncated by the snapshot length.
+The two lengths will be equal if the number of bytes of packet data are
+less than or equal to the snapshot length.
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
diff --git a/contrib/libpcap/pcap-septel.c b/contrib/libpcap/pcap-septel.c
index 5169ec0..c0473bb 100644
--- a/contrib/libpcap/pcap-septel.c
+++ b/contrib/libpcap/pcap-septel.c
@@ -16,7 +16,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-septel.c,v 1.1.2.2 2005/06/21 01:03:23 guy Exp $";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-septel.c,v 1.2.2.2 2008-04-14 20:41:52 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -50,8 +50,8 @@ static const char rcsid[] _U_ =
/* This code is required when compiling for a Septel device only. */
#include "pcap-septel.h"
-/* Replace dag function names with pcap equivalent. */
-#define septel_open_live pcap_open_live
+/* Replace septel function names with pcap equivalent. */
+#define septel_create pcap_create
#define septel_platform_finddevs pcap_platform_finddevs
#endif /* SEPTEL_ONLY */
@@ -59,12 +59,6 @@ static int septel_setfilter(pcap_t *p, struct bpf_program *fp);
static int septel_stats(pcap_t *p, struct pcap_stat *ps);
static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf);
-static void septel_platform_close(pcap_t *p) {
-
-}
-
-
-
/*
* Read at most max_packets from the capture queue and call the callback
* for each of them. Returns the number of packets handled, -1 if an
@@ -199,28 +193,14 @@ septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_)
}
/*
- * Get a handle for a live capture from the given Septel device. Always pass a NULL device
+ * Activate a handle for a live capture from the given Septel device. Always pass a NULL device
* The promisc flag is ignored because Septel cards have built-in tracing.
- * The to_ms parameter is also ignored as it is
- * not supported in hardware.
+ * The timeout is also ignored as it is not supported in hardware.
*
* See also pcap(3).
*/
-pcap_t *septel_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf) {
- pcap_t *handle;
-
- handle = malloc(sizeof(*handle));
- if (handle == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc %s: %s", device, pcap_strerror(errno));
- return NULL;
- }
-
- /* Initialize some components of the pcap structure. */
-
- memset(handle, 0, sizeof(*handle));
-
- handle->snapshot = snaplen;
-
+static pcap_t *septel_activate(pcap_t* handle) {
+ /* Initialize some components of the pcap structure. */
handle->linktype = DLT_MTP2;
handle->bufsize = 0;
@@ -237,16 +217,19 @@ pcap_t *septel_open_live(const char *device, int snaplen, int promisc, int to_ms
handle->getnonblock_op = pcap_getnonblock_fd;
handle->setnonblock_op = septel_setnonblock;
handle->stats_op = septel_stats;
- handle->close_op = septel_platform_close;
- return handle;
+ return 0;
+}
-fail:
- if (handle != NULL) {
- free(handle);
- }
+pcap_t *septel_create(const char *device, char *ebuf) {
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return NULL;
- return NULL;
+ p->activate_op = septel_activate;
+ return p;
}
static int septel_stats(pcap_t *p, struct pcap_stat *ps) {
diff --git a/contrib/libpcap/pcap-septel.h b/contrib/libpcap/pcap-septel.h
index 1de6377..c916797 100644
--- a/contrib/libpcap/pcap-septel.h
+++ b/contrib/libpcap/pcap-septel.h
@@ -8,8 +8,8 @@
* Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY
* (+961 3 485343);
*
- * @(#) $Header: /tcpdump/master/libpcap/pcap-septel.h,v 1.1.2.1 2005/06/20 21:30:19 guy Exp $
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-septel.h,v 1.1.4.1 2008-04-04 19:39:06 guy Exp $
*/
-pcap_t *septel_open_live(const char *device, int snaplen, int promisc, int to_ms, char *ebuf);
+pcap_t *septel_create(const char *device, char *ebuf);
diff --git a/contrib/libpcap/pcap-sita.c b/contrib/libpcap/pcap-sita.c
new file mode 100644
index 0000000..971f8b0
--- /dev/null
+++ b/contrib/libpcap/pcap-sita.c
@@ -0,0 +1,980 @@
+/*
+ * pcap-sita.c: Packet capture interface additions for SITA ACN devices
+ *
+ * Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc <fulko.hew@sita.aero>
+ *
+ * License: BSD
+ *
+ * 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. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+ /* $Id: pcap-sita.c */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "pcap-int.h"
+
+#include "pcap-sita.h"
+
+ /* non-configureable manifests follow */
+
+#define IOP_SNIFFER_PORT 49152 /* TCP port on the IOP used for 'distributed pcap' usage */
+#define MAX_LINE_SIZE 255 /* max size of a buffer/line in /etc/hosts we allow */
+#define MAX_CHASSIS 8 /* number of chassis in an ACN site */
+#define MAX_GEOSLOT 8 /* max number of access units in an ACN site */
+
+#define FIND 0
+#define LIVE 1
+
+typedef struct iface {
+ struct iface *next; /* a pointer to the next interface */
+ char *name; /* this interface's name on Wireshark */
+ char *IOPname; /* this interface's name on an IOP */
+ uint32_t iftype; /* the type of interface (DLT values) */
+} iface_t;
+
+typedef struct unit {
+ char *ip; /* this unit's IP address (as extracted from /etc/hosts) */
+ int fd; /* the connection to this unit (if it exists) */
+ int find_fd; /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */
+ int first_time; /* 0 = just opened via acn_open_live(), ie. the first time, NZ = nth time */
+ struct sockaddr_in *serv_addr; /* the address control block for comms to this unit */
+ int chassis;
+ int geoslot;
+ iface_t *iface; /* a pointer to a linked list of interface structures */
+ char *imsg; /* a pointer to an inbound message */
+ int len; /* the current size of the inbound message */
+} unit_t;
+
+static char *errorString;
+static unit_t units[MAX_CHASSIS+1][MAX_GEOSLOT+1]; /* we use indexes of 1 through 8, but we reserve/waste index 0 */
+static fd_set readfds; /* a place to store the file descriptors for the connections to the IOPs */
+static fd_set working_set;
+static int max_fs;
+static char static_buf[32];
+
+pcap_if_t *acn_if_list; /* pcap's list of available interfaces */
+
+static void dump_interface_list(void) {
+ pcap_if_t *iff;
+ pcap_addr_t *addr;
+ int longest_name_len = 0;
+ char *n, *d, *f;
+ int if_number = 0;
+
+ iff = acn_if_list;
+ while (iff) {
+ if (iff->name && (strlen(iff->name) > longest_name_len)) longest_name_len = strlen(iff->name);
+ iff = iff->next;
+ }
+ iff = acn_if_list;
+ printf("Interface List:\n");
+ while (iff) {
+ n = (iff->name) ? iff->name : "";
+ d = (iff->description) ? iff->description : "";
+ f = (iff->flags == PCAP_IF_LOOPBACK) ? "L" : "";
+ printf("%3d: %*s %s '%s'\n", if_number++, longest_name_len, n, f, d);
+ addr = iff->addresses;
+ while (addr) {
+ printf("%*s ", (5 + longest_name_len), ""); /* add some indentation */
+ printf("%15s ", (addr->addr) ? inet_ntoa(((struct sockaddr_in *)addr->addr)->sin_addr) : "");
+ printf("%15s ", (addr->netmask) ? inet_ntoa(((struct sockaddr_in *)addr->netmask)->sin_addr) : "");
+ printf("%15s ", (addr->broadaddr) ? inet_ntoa(((struct sockaddr_in *)addr->broadaddr)->sin_addr) : "");
+ printf("%15s ", (addr->dstaddr) ? inet_ntoa(((struct sockaddr_in *)addr->dstaddr)->sin_addr) : "");
+ printf("\n");
+ addr = addr->next;
+ }
+ iff = iff->next;
+ }
+}
+
+static void dump(unsigned char *ptr, int i, int indent) {
+ fprintf(stderr, "%*s", indent, " ");
+ for (; i > 0; i--) {
+ fprintf(stderr, "%2.2x ", *ptr++);
+ }
+ fprintf(stderr, "\n");
+}
+
+static void dump_interface_list_p(void) {
+ pcap_if_t *iff;
+ pcap_addr_t *addr;
+ int if_number = 0;
+
+ iff = acn_if_list;
+ printf("Interface Pointer @ %p is %p:\n", &acn_if_list, iff);
+ while (iff) {
+ printf("%3d: %p %p next: %p\n", if_number++, iff->name, iff->description, iff->next);
+ dump((unsigned char *)iff, sizeof(pcap_if_t), 5);
+ addr = iff->addresses;
+ while (addr) {
+ printf(" %p %p %p %p, next: %p\n", addr->addr, addr->netmask, addr->broadaddr, addr->dstaddr, addr->next);
+ dump((unsigned char *)addr, sizeof(pcap_addr_t), 10);
+ addr = addr->next;
+ }
+ iff = iff->next;
+ }
+}
+
+static void dump_unit_table(void) {
+ int chassis, geoslot;
+ iface_t *p;
+
+ printf("%c:%c %s %s\n", 'C', 'S', "fd", "IP Address");
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+ if (units[chassis][geoslot].ip != NULL)
+ printf("%d:%d %2d %s\n", chassis, geoslot, units[chassis][geoslot].fd, units[chassis][geoslot].ip);
+ p = units[chassis][geoslot].iface;
+ while (p) {
+ char *n = (p->name) ? p->name : "";
+ char *i = (p->IOPname) ? p->IOPname : "";
+ p = p->next;
+ printf(" %12s -> %12s\n", i, n);
+ }
+ }
+ }
+}
+
+static int find_unit_by_fd(int fd, int *chassis, int *geoslot, unit_t **unit_ptr) {
+ int c, s;
+
+ for (c = 0; c <= MAX_CHASSIS; c++) {
+ for (s = 0; s <= MAX_GEOSLOT; s++) {
+ if (units[c][s].fd == fd || units[c][s].find_fd == fd) {
+ if (chassis) *chassis = c;
+ if (geoslot) *geoslot = s;
+ if (unit_ptr) *unit_ptr = &units[c][s];
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int read_client_nbytes(int fd, int count, unsigned char *buf) {
+ unit_t *u;
+ int chassis, geoslot;
+ int len;
+
+ find_unit_by_fd(fd, &chassis, &geoslot, &u);
+ while (count) {
+ if ((len = recv(fd, buf, count, 0)) <= 0) return -1; /* read in whatever data was sent to us */
+ count -= len;
+ buf += len;
+ } /* till we have everything we are looking for */
+ return 0;
+}
+
+static void empty_unit_iface(unit_t *u) {
+ iface_t *p, *cur;
+
+ cur = u->iface;
+ while (cur) { /* loop over all the interface entries */
+ if (cur->name) free(cur->name); /* throwing away the contents if they exist */
+ if (cur->IOPname) free(cur->IOPname);
+ p = cur->next;
+ free(cur); /* then throw away the structure itself */
+ cur = p;
+ }
+ u->iface = 0; /* and finally remember that there are no remaining structure */
+}
+
+static void empty_unit(int chassis, int geoslot) {
+ unit_t *u = &units[chassis][geoslot];
+
+ empty_unit_iface(u);
+ if (u->imsg) { /* then if an inbound message buffer exists */
+ u->imsg = (char *)realloc(u->imsg, 1); /* and re-allocate the old large buffer into a new small one */
+ }
+}
+
+static void empty_unit_table(void) {
+ int chassis, geoslot;
+
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+ if (units[chassis][geoslot].ip != NULL) {
+ free(units[chassis][geoslot].ip); /* get rid of the malloc'ed space that holds the IP address */
+ units[chassis][geoslot].ip = 0; /* then set the pointer to NULL */
+ }
+ empty_unit(chassis, geoslot);
+ }
+ }
+}
+
+static char *find_nth_interface_name(int n) {
+ int chassis, geoslot;
+ iface_t *p;
+ char *last_name = 0;
+
+ if (n < 0) n = 0; /* ensure we are working with a valid number */
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+ if (units[chassis][geoslot].ip != NULL) {
+ p = units[chassis][geoslot].iface;
+ while (p) { /* and all interfaces... */
+ if (p->IOPname) last_name = p->name; /* remembering the last name found */
+ if (n-- == 0) return last_name; /* and if we hit the instance requested */
+ p = p->next;
+ }
+ }
+ }
+ }
+ /* if we couldn't fine the selected entry */
+ if (last_name) return last_name; /* ... but we did have at least one entry... return the last entry found */
+ return ""; /* ... but if there wasn't any entry... return an empty string instead */
+}
+
+int acn_parse_hosts_file(char *errbuf) { /* returns: -1 = error, 0 = OK */
+ FILE *fp;
+ char buf[MAX_LINE_SIZE];
+ char *ptr, *ptr2;
+ int pos;
+ int chassis, geoslot;
+ unit_t *u;
+
+ empty_unit_table();
+ if ((fp = fopen("/etc/hosts", "r")) == NULL) { /* try to open the hosts file and if it fails */
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading."); /* return the nohostsfile error response */
+ return -1;
+ }
+ while (fgets(buf, MAX_LINE_SIZE-1, fp)) { /* while looping over the file */
+
+ pos = strcspn(buf, "#\n\r"); /* find the first comment character or EOL */
+ *(buf + pos) = '\0'; /* and clobber it and anything that follows it */
+
+ pos = strspn(buf, " \t"); /* then find the first non-white space */
+ if (pos == strlen(buf)) /* if there is nothing but white space on the line */
+ continue; /* ignore that empty line */
+ ptr = buf + pos; /* and skip over any of that leading whitespace */
+
+ if ((ptr2 = strstr(ptr, "_I_")) == NULL) /* skip any lines that don't have names that look like they belong to IOPs */
+ continue;
+ if (*(ptr2 + 4) != '_') /* and skip other lines that have names that don't look like ACN components */
+ continue;
+ *(ptr + strcspn(ptr, " \t")) = '\0'; /* null terminate the IP address so its a standalone string */
+
+ chassis = *(ptr2 + 3) - '0'; /* extract the chassis number */
+ geoslot = *(ptr2 + 5) - '0'; /* and geo-slot number */
+ if (chassis < 1 || chassis > MAX_CHASSIS ||
+ geoslot < 1 || geoslot > MAX_GEOSLOT) { /* if the chassis and/or slot numbers appear to be bad... */
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'."); /* warn the user */
+ continue; /* and ignore the entry */
+ }
+ if ((ptr2 = (char *)malloc(strlen(ptr) + 1)) == NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ continue;
+ }
+ strcpy(ptr2, ptr); /* copy the IP address into our malloc'ed memory */
+ u = &units[chassis][geoslot];
+ u->ip = ptr2; /* and remember the whole shebang */
+ u->chassis = chassis;
+ u->geoslot = geoslot;
+ }
+ fclose(fp);
+ if (*errbuf) return -1;
+ else return 0;
+}
+
+static int open_with_IOP(unit_t *u, int flag) {
+ int sockfd;
+ char *ip;
+
+ if (u->serv_addr == NULL) {
+ u->serv_addr = malloc(sizeof(struct sockaddr_in));
+ }
+ ip = u->ip;
+ bzero((char *)u->serv_addr, sizeof(struct sockaddr_in));
+ u->serv_addr->sin_family = AF_INET;
+ u->serv_addr->sin_addr.s_addr = inet_addr(ip);
+ u->serv_addr->sin_port = htons(IOP_SNIFFER_PORT);
+
+ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ fprintf(stderr, "pcap can't open a socket for connecting to IOP at %s\n", ip);
+ return 0;
+ }
+ if (connect(sockfd, (struct sockaddr *)u->serv_addr, sizeof(struct sockaddr_in)) < 0) {
+ fprintf(stderr, "pcap can't connect to IOP at %s\n", ip);
+ return 0;
+ }
+ if (flag == LIVE) u->fd = sockfd;
+ else u->find_fd = sockfd;
+ u->first_time = 0;
+ return sockfd; /* return the non-zero file descriptor as a 'success' indicator */
+}
+
+static void close_with_IOP(int chassis, int geoslot, int flag) {
+ int *id;
+
+ if (flag == LIVE) id = &units[chassis][geoslot].fd;
+ else id = &units[chassis][geoslot].find_fd;
+
+ if (*id) { /* this was the last time, so... if we are connected... */
+ close(*id); /* disconnect us */
+ *id = 0; /* and forget that the descriptor exists because we are not open */
+ }
+}
+
+static void pcap_cleanup_acn(pcap_t *handle) {
+ int chassis, geoslot;
+ unit_t *u;
+
+ if (find_unit_by_fd(handle->fd, &chassis, &geoslot, &u) == 0)
+ return;
+ close_with_IOP(chassis, geoslot, LIVE);
+ if (u)
+ u->first_time = 0;
+ pcap_cleanup_live_common(handle);
+}
+
+static void send_to_fd(int fd, int len, unsigned char *str) {
+ int nwritten;
+ int chassis, geoslot;
+
+ while (len > 0) {
+ if ((nwritten = write(fd, str, len)) <= 0) {
+ find_unit_by_fd(fd, &chassis, &geoslot, NULL);
+ if (units[chassis][geoslot].fd == fd) close_with_IOP(chassis, geoslot, LIVE);
+ else if (units[chassis][geoslot].find_fd == fd) close_with_IOP(chassis, geoslot, FIND);
+ empty_unit(chassis, geoslot);
+ return;
+ }
+ len -= nwritten;
+ str += nwritten;
+ }
+}
+
+static void acn_freealldevs(void) {
+
+ pcap_if_t *iff, *next_iff;
+ pcap_addr_t *addr, *next_addr;
+
+ for (iff = acn_if_list; iff != NULL; iff = next_iff) {
+ next_iff = iff->next;
+ for (addr = iff->addresses; addr != NULL; addr = next_addr) {
+ next_addr = addr->next;
+ if (addr->addr) free(addr->addr);
+ if (addr->netmask) free(addr->netmask);
+ if (addr->broadaddr) free(addr->broadaddr);
+ if (addr->dstaddr) free(addr->dstaddr);
+ free(addr);
+ }
+ if (iff->name) free(iff->name);
+ if (iff->description) free(iff->description);
+ free(iff);
+ }
+}
+
+static char *nonUnified_port_num(unit_t *u, int IOPportnum) {
+
+ sprintf(static_buf, "%d_%d", u->chassis, u->geoslot);
+ return static_buf;
+}
+
+static char *unified_port_num(unit_t *u, int IOPportnum) {
+ int portnum;
+
+ portnum = ((u->chassis - 1) * 64) + ((u->geoslot - 1) * 8) + IOPportnum + 1;
+ sprintf(static_buf, "%d", portnum);
+ return static_buf;
+}
+
+static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) {
+ iface_t *iface_ptr, *iface;
+ char *name;
+ char buf[32];
+ char *proto;
+ char *port;
+ int IOPportnum = 0;
+
+ iface = malloc(sizeof(iface_t)); /* get memory for a structure */
+ bzero((char *)iface, sizeof(iface_t));
+
+ iface->iftype = iftype; /* remember the interface type of this interface */
+
+ name = malloc(strlen(IOPname) + 1); /* get memory for the IOP's name */
+ strcpy(name, IOPname); /* and copy it in */
+ iface->IOPname = name; /* and stick it into the structure */
+
+ if (strncmp(IOPname, "lo", 2) == 0) {
+ IOPportnum = atoi(&IOPname[2]);
+ switch (iftype) {
+ case DLT_EN10MB: proto = "lo"; port = nonUnified_port_num(u, IOPportnum); break;
+ default: proto = "???"; port = unified_port_num(u, IOPportnum); break;
+ }
+ } else if (strncmp(IOPname, "eth", 3) == 0) {
+ IOPportnum = atoi(&IOPname[3]);
+ switch (iftype) {
+ case DLT_EN10MB: proto = "eth"; port = nonUnified_port_num(u, IOPportnum); break;
+ default: proto = "???"; port = unified_port_num(u, IOPportnum); break;
+ }
+ } else if (strncmp(IOPname, "wan", 3) == 0) {
+ IOPportnum = atoi(&IOPname[3]);
+ switch (iftype) {
+ case DLT_SITA: proto = "wan"; port = unified_port_num(u, IOPportnum); break;
+ default: proto = "???"; port = unified_port_num(u, IOPportnum); break;
+ }
+ }
+
+ sprintf(buf, "%s_%s", proto, port); /* compose the user's name for that IOP port name */
+ name = malloc(strlen(buf) + 1); /* get memory for that name */
+ strcpy(name, buf); /* and copy it in */
+ iface->name = name; /* and stick it into the structure */
+
+ if (u->iface == 0) { /* if this is the first name */
+ u->iface = iface; /* stick this entry at the head of the list */
+ } else {
+ iface_ptr = u->iface;
+ while (iface_ptr->next) { /* othewise scan the list */
+ iface_ptr = iface_ptr->next; /* till we're at the last entry */
+ }
+ iface_ptr->next = iface; /* then tack this entry on the end of the list */
+ }
+ return iface->name;
+}
+
+static int if_sort(char *s1, char *s2) {
+ char *s1_p2, *s2_p2;
+ char str1[MAX_LINE_SIZE], str2[MAX_LINE_SIZE];
+ int s1_p1_len, s2_p1_len;
+ int retval;
+
+ if ((s1_p2 = strchr(s1, '_'))) { /* if an underscore is found... */
+ s1_p1_len = s1_p2 - s1; /* the prefix length is the difference in pointers */
+ s1_p2++; /* the suffix actually starts _after_ the underscore */
+ } else { /* otherwise... */
+ s1_p1_len = strlen(s1); /* the prefix length is the length of the string itself */
+ s1_p2 = 0; /* and there is no suffix */
+ }
+ if ((s2_p2 = strchr(s2, '_'))) { /* now do the same for the second string */
+ s2_p1_len = s2_p2 - s2;
+ s2_p2++;
+ } else {
+ s2_p1_len = strlen(s2);
+ s2_p2 = 0;
+ }
+ strncpy(str1, s1, (s1_p1_len > sizeof(str1)) ? s1_p1_len : sizeof(str1)); *(str1 + s1_p1_len) = 0;
+ strncpy(str2, s2, (s2_p1_len > sizeof(str2)) ? s2_p1_len : sizeof(str2)); *(str2 + s2_p1_len) = 0;
+ retval = strcmp(str1, str2);
+ if (retval != 0) return retval; /* if they are not identical, then we can quit now and return the indication */
+ return strcmp(s1_p2, s2_p2); /* otherwise we return the result of comparing the 2nd half of the string */
+}
+
+static void sort_if_table(void) {
+ pcap_if_t *p1, *p2, *prev, *temp;
+ int has_swapped;
+
+ if (!acn_if_list) return; /* nothing to do if the list is empty */
+
+ while (1) {
+ p1 = acn_if_list; /* start at the head of the list */
+ prev = 0;
+ has_swapped = 0;
+ while ((p2 = p1->next)) {
+ if (if_sort(p1->name, p2->name) > 0) {
+ if (prev) { /* we are swapping things that are _not_ at the head of the list */
+ temp = p2->next;
+ prev->next = p2;
+ p2->next = p1;
+ p1->next = temp;
+ } else { /* special treatment if we are swapping with the head of the list */
+ temp = p2->next;
+ acn_if_list= p2;
+ p2->next = p1;
+ p1->next = temp;
+ }
+ p1 = p2;
+ prev = p1;
+ has_swapped = 1;
+ }
+ prev = p1;
+ p1 = p1->next;
+ }
+ if (has_swapped == 0)
+ return;
+ }
+ return;
+}
+
+static int process_client_data (char *errbuf) { /* returns: -1 = error, 0 = OK */
+ int chassis, geoslot;
+ unit_t *u;
+ pcap_if_t *iff, *prev_iff;
+ pcap_addr_t *addr, *prev_addr;
+ char *ptr;
+ int address_count;
+ struct sockaddr_in *s;
+ char *newname;
+ bpf_u_int32 interfaceType;
+ unsigned char flags;
+
+ prev_iff = 0;
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { /* now loop over all the devices */
+ u = &units[chassis][geoslot];
+ empty_unit_iface(u);
+ ptr = u->imsg; /* point to the start of the msg for this IOP */
+ while (ptr < (u->imsg + u->len)) {
+ if ((iff = malloc(sizeof(pcap_if_t))) == NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+ bzero((char *)iff, sizeof(pcap_if_t));
+ if (acn_if_list == 0) acn_if_list = iff; /* remember the head of the list */
+ if (prev_iff) prev_iff->next = iff; /* insert a forward link */
+
+ if (*ptr) { /* if there is a count for the name */
+ if ((iff->name = malloc(*ptr + 1)) == NULL) { /* get that amount of space */
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+ memcpy(iff->name, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */
+ *(iff->name + *ptr) = 0; /* and null terminate the string */
+ ptr += *ptr; /* now move the pointer forwards by the length of the count plus the length of the string */
+ }
+ ptr++;
+
+ if (*ptr) { /* if there is a count for the description */
+ if ((iff->description = malloc(*ptr + 1)) == NULL) { /* get that amount of space */
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+ memcpy(iff->description, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */
+ *(iff->description + *ptr) = 0; /* and null terminate the string */
+ ptr += *ptr; /* now move the pointer forwards by the length of the count plus the length of the string */
+ }
+ ptr++;
+
+ interfaceType = ntohl(*(bpf_u_int32 *)ptr);
+ ptr += 4; /* skip over the interface type */
+
+ flags = *ptr++;
+ if (flags) iff->flags = PCAP_IF_LOOPBACK; /* if this is a loopback style interface, lets mark it as such */
+
+ address_count = *ptr++;
+
+ prev_addr = 0;
+ while (address_count--) {
+ if ((addr = malloc(sizeof(pcap_addr_t))) == NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+ bzero((char *)addr, sizeof(pcap_addr_t));
+ if (iff->addresses == 0) iff->addresses = addr;
+ if (prev_addr) prev_addr->next = addr; /* insert a forward link */
+ if (*ptr) { /* if there is a count for the address */
+ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { /* get that amount of space */
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+ bzero((char *)s, sizeof(struct sockaddr_in));
+ addr->addr = (struct sockaddr *)s;
+ s->sin_family = AF_INET;
+ s->sin_addr.s_addr = *(bpf_u_int32 *)(ptr + 1); /* copy the address in */
+ ptr += *ptr; /* now move the pointer forwards according to the specified length of the address */
+ }
+ ptr++; /* then forwards one more for the 'length of the address' field */
+ if (*ptr) { /* process any netmask */
+ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+ bzero((char *)s, sizeof(struct sockaddr_in));
+ addr->netmask = (struct sockaddr *)s;
+ s->sin_family = AF_INET;
+ s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1);
+ ptr += *ptr;
+ }
+ ptr++;
+ if (*ptr) { /* process any broadcast address */
+ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+ bzero((char *)s, sizeof(struct sockaddr_in));
+ addr->broadaddr = (struct sockaddr *)s;
+ s->sin_family = AF_INET;
+ s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1);
+ ptr += *ptr;
+ }
+ ptr++;
+ if (*ptr) { /* process any destination address */
+ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+ bzero((char *)s, sizeof(struct sockaddr_in));
+ addr->dstaddr = (struct sockaddr *)s;
+ s->sin_family = AF_INET;
+ s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1);
+ ptr += *ptr;
+ }
+ ptr++;
+ prev_addr = addr;
+ }
+ prev_iff = iff;
+
+ newname = translate_IOP_to_pcap_name(u, iff->name, interfaceType); /* add a translation entry and get a point to the mangled name */
+ if ((iff->name = realloc(iff->name, strlen(newname) + 1)) == NULL) { /* we now re-write the name stored in the interface list */
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "realloc: %s", pcap_strerror(errno));
+ return -1;
+ }
+ strcpy(iff->name, newname); /* to this new name */
+ }
+ }
+ }
+ return 0;
+}
+
+static int read_client_data (int fd) {
+ unsigned char buf[256];
+ int chassis, geoslot;
+ unit_t *u;
+ int len;
+
+ find_unit_by_fd(fd, &chassis, &geoslot, &u);
+
+ if ((len = recv(fd, buf, sizeof(buf), 0)) <= 0) return 0; /* read in whatever data was sent to us */
+
+ if ((u->imsg = realloc(u->imsg, (u->len + len))) == NULL) /* extend the buffer for the new data */
+ return 0;
+ memcpy((u->imsg + u->len), buf, len); /* append the new data */
+ u->len += len;
+ return 1;
+}
+
+static void wait_for_all_answers(void) {
+ int retval;
+ struct timeval tv;
+ int fd;
+ int chassis, geoslot;
+
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+
+ while (1) {
+ int flag = 0;
+ for (fd = 0; fd <= max_fs; fd++) { /* scan the list of descriptors we may be listening to */
+ if (FD_ISSET(fd, &readfds)) flag = 1; /* and see if there are any still set */
+ }
+ if (flag == 0) return; /* we are done, when they are all gone */
+
+ memcpy(&working_set, &readfds, sizeof(readfds)); /* otherwise, we still have to listen for more stuff, till we timeout */
+ retval = select(max_fs + 1, &working_set, NULL, NULL, &tv);
+ if (retval == -1) { /* an error occured !!!!! */
+ return;
+ } else if (retval == 0) { /* timeout occured, so process what we've got sofar and return */
+ printf("timeout\n");
+ return;
+ } else {
+ for (fd = 0; fd <= max_fs; fd++) { /* scan the list of things to do, and do them */
+ if (FD_ISSET(fd, &working_set)) {
+ if (read_client_data(fd) == 0) { /* if the socket has closed */
+ FD_CLR(fd, &readfds); /* and descriptors we listen to for errors */
+ find_unit_by_fd(fd, &chassis, &geoslot, NULL);
+ close_with_IOP(chassis, geoslot, FIND); /* and close out connection to him */
+ }
+ }
+ }
+ }
+ }
+}
+
+static char *get_error_response(int fd, char *errbuf) { /* return a pointer on error, NULL on no error */
+ char byte;
+ int len = 0;
+
+ while (1) {
+ recv(fd, &byte, 1, 0); /* read another byte in */
+ if (errbuf && (len++ < PCAP_ERRBUF_SIZE)) { /* and if there is still room in the buffer */
+ *errbuf++ = byte; /* stick it in */
+ *errbuf = '\0'; /* ensure the string is null terminated just in case we might exceed the buffer's size */
+ }
+ if (byte == '\0') {
+ if (len > 1) { return errbuf; }
+ else { return NULL; }
+ }
+ }
+}
+
+int acn_findalldevs(char *errbuf) { /* returns: -1 = error, 0 = OK */
+ int chassis, geoslot;
+ unit_t *u;
+
+ FD_ZERO(&readfds);
+ max_fs = 0;
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+ u = &units[chassis][geoslot];
+ if (u->ip && (open_with_IOP(u, FIND))) { /* connect to the remote IOP */
+ send_to_fd(u->find_fd, 1, (unsigned char *)"\0");
+ if (get_error_response(u->find_fd, errbuf))
+ close_with_IOP(chassis, geoslot, FIND);
+ else {
+ if (u->find_fd > max_fs)
+ max_fs = u->find_fd; /* remember the highest number currently in use */
+ FD_SET(u->find_fd, &readfds); /* we are going to want to read this guy's response to */
+ u->len = 0;
+ send_to_fd(u->find_fd, 1, (unsigned char *)"Q"); /* this interface query request */
+ }
+ }
+ }
+ }
+ wait_for_all_answers();
+ if (process_client_data(errbuf))
+ return -1;
+ sort_if_table();
+ return 0;
+}
+
+static int pcap_stats_acn(pcap_t *handle, struct pcap_stat *ps) {
+ unsigned char buf[12];
+
+ send_to_fd(handle->fd, 1, (unsigned char *)"S"); /* send the get_stats command to the IOP */
+
+ if (read_client_nbytes(handle->fd, sizeof(buf), buf) == -1) return -1; /* try reading the required bytes */
+
+ ps->ps_recv = ntohl(*(uint32_t *)&buf[0]); /* break the buffer into its three 32 bit components */
+ ps->ps_drop = ntohl(*(uint32_t *)&buf[4]);
+ ps->ps_ifdrop = ntohl(*(uint32_t *)&buf[8]);
+
+ return 0;
+}
+
+static int acn_open_live(const char *name, char *errbuf, int *linktype) { /* returns 0 on error, else returns the file descriptor */
+ int chassis, geoslot;
+ unit_t *u;
+ iface_t *p;
+ pcap_if_t *alldevsp;
+
+ pcap_findalldevs(&alldevsp, errbuf);
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+ u = &units[chassis][geoslot];
+ if (u->ip != NULL) {
+ p = u->iface;
+ while (p) { /* and all interfaces... */
+ if (p->IOPname && p->name && (strcmp(p->name, name) == 0)) { /* and if we found the interface we want... */
+ *linktype = p->iftype;
+ open_with_IOP(u, LIVE); /* start a connection with that IOP */
+ send_to_fd(u->fd, strlen(p->IOPname)+1, (unsigned char *)p->IOPname); /* send the IOP's interface name, and a terminating null */
+ if (get_error_response(u->fd, errbuf)) {
+ return -1;
+ }
+ return u->fd; /* and return that open descriptor */
+ }
+ p = p->next;
+ }
+ }
+ }
+ }
+ return -1; /* if the interface wasn't found, return an error */
+}
+
+static void acn_start_monitor(int fd, int snaplen, int timeout, int promiscuous, int direction) {
+ unsigned char buf[8];
+ unit_t *u;
+
+ //printf("acn_start_monitor()\n"); // fulko
+ find_unit_by_fd(fd, NULL, NULL, &u);
+ if (u->first_time == 0) {
+ buf[0] = 'M';
+ *(uint32_t *)&buf[1] = htonl(snaplen);
+ buf[5] = timeout;
+ buf[6] = promiscuous;
+ buf[7] = direction;
+ //printf("acn_start_monitor() first time\n"); // fulko
+ send_to_fd(fd, 8, buf); /* send the start monitor command with its parameters to the IOP */
+ u->first_time = 1;
+ }
+ //printf("acn_start_monitor() complete\n"); // fulko
+}
+
+static int pcap_inject_acn(pcap_t *p, const void *buf _U_, size_t size _U_) {
+ strlcpy(p->errbuf, "Sending packets isn't supported on ACN adapters",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+}
+
+static int pcap_setfilter_acn(pcap_t *handle, struct bpf_program *bpf) {
+ int fd = handle->fd;
+ int count;
+ struct bpf_insn *p;
+ uint16_t shortInt;
+ uint32_t longInt;
+
+ send_to_fd(fd, 1, (unsigned char *)"F"); /* BPF filter follows command */
+ count = bpf->bf_len;
+ longInt = htonl(count);
+ send_to_fd(fd, 4, (unsigned char *)&longInt); /* send the instruction sequence count */
+ p = bpf->bf_insns;
+ while (count--) { /* followed by the list of instructions */
+ shortInt = htons(p->code);
+ longInt = htonl(p->k);
+ send_to_fd(fd, 2, (unsigned char *)&shortInt);
+ send_to_fd(fd, 1, (unsigned char *)&p->jt);
+ send_to_fd(fd, 1, (unsigned char *)&p->jf);
+ send_to_fd(fd, 4, (unsigned char *)&longInt);
+ p++;
+ }
+ if (get_error_response(fd, NULL))
+ return -1;
+ return 0;
+}
+
+static int pcap_setdirection_acn(pcap_t *handle, pcap_direction_t d) {
+ snprintf(handle->errbuf, sizeof(handle->errbuf),
+ "Setting direction is not supported on ACN adapters");
+ return -1;
+}
+
+static int acn_read_n_bytes_with_timeout(pcap_t *handle, int count) {
+ struct timeval tv;
+ int retval, fd;
+ fd_set r_fds;
+ fd_set w_fds;
+ u_char *bp;
+ int len = 0;
+ int offset = 0;
+
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+
+ fd = handle->fd;
+ FD_ZERO(&r_fds);
+ FD_SET(fd, &r_fds);
+ memcpy(&w_fds, &r_fds, sizeof(r_fds));
+ bp = handle->bp;
+ while (count) {
+ retval = select(fd + 1, &w_fds, NULL, NULL, &tv);
+ if (retval == -1) { /* an error occured !!!!! */
+// fprintf(stderr, "error during packet data read\n");
+ return -1; /* but we need to return a good indication to prevent unneccessary popups */
+ } else if (retval == 0) { /* timeout occured, so process what we've got sofar and return */
+// fprintf(stderr, "timeout during packet data read\n");
+ return -1;
+ } else {
+ if ((len = recv(fd, (bp + offset), count, 0)) <= 0) {
+// fprintf(stderr, "premature exit during packet data rx\n");
+ return -1;
+ }
+ count -= len;
+ offset += len;
+ }
+ }
+ return 0;
+}
+
+static int pcap_read_acn(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) {
+ #define HEADER_SIZE (4 * 4)
+ unsigned char packet_header[HEADER_SIZE];
+ struct pcap_pkthdr pcap_header;
+
+ //printf("pcap_read_acn()\n"); // fulko
+ acn_start_monitor(handle->fd, handle->snapshot, handle->md.timeout, handle->md.clear_promisc, handle->direction); /* maybe tell him to start monitoring */
+ //printf("pcap_read_acn() after start monitor\n"); // fulko
+
+ handle->bp = packet_header;
+ if (acn_read_n_bytes_with_timeout(handle, HEADER_SIZE) == -1) return 0; /* try to read a packet header in so we can get the sizeof the packet data */
+
+ pcap_header.ts.tv_sec = ntohl(*(uint32_t *)&packet_header[0]); /* tv_sec */
+ pcap_header.ts.tv_usec = ntohl(*(uint32_t *)&packet_header[4]); /* tv_usec */
+ pcap_header.caplen = ntohl(*(uint32_t *)&packet_header[8]); /* caplen */
+ pcap_header.len = ntohl(*(uint32_t *)&packet_header[12]); /* len */
+
+ handle->bp = handle->buffer + handle->offset; /* start off the receive pointer at the right spot */
+ if (acn_read_n_bytes_with_timeout(handle, pcap_header.caplen) == -1) return 0; /* then try to read in the rest of the data */
+
+ callback(user, &pcap_header, handle->bp); /* call the user supplied callback function */
+ return 1;
+}
+
+static int pcap_activate_sita(pcap_t *handle) {
+ int fd;
+
+ if (handle->opt.rfmon) {
+ /*
+ * No monitor mode on SITA devices (they're not Wi-Fi
+ * devices).
+ */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /* Initialize some components of the pcap structure. */
+
+ handle->inject_op = pcap_inject_acn;
+ handle->setfilter_op = pcap_setfilter_acn;
+ handle->setdirection_op = pcap_setdirection_acn;
+ handle->set_datalink_op = NULL; /* can't change data link type */
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->cleanup_op = pcap_cleanup_acn;
+ handle->read_op = pcap_read_acn;
+ handle->stats_op = pcap_stats_acn;
+
+ fd = acn_open_live(handle->opt.source, handle->errbuf,
+ &handle->linktype);
+ if (fd == -1)
+ return PCAP_ERROR;
+ handle->md.clear_promisc = handle->md.promisc;
+ handle->fd = fd;
+ handle->bufsize = handle->snapshot;
+
+ /* Allocate the buffer */
+
+ handle->buffer = malloc(handle->bufsize + handle->offset);
+ if (!handle->buffer) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ pcap_cleanup_acn(handle);
+ return PCAP_ERROR;
+ }
+
+ /*
+ * "handle->fd" is a socket, so "select()" and "poll()"
+ * should work on it.
+ */
+ handle->selectable_fd = handle->fd;
+
+ return 0;
+}
+
+pcap_t *pcap_create(const char *device, char *ebuf) {
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_sita;
+ return (p);
+}
diff --git a/contrib/libpcap/pcap-sita.h b/contrib/libpcap/pcap-sita.h
new file mode 100644
index 0000000..b232ee2
--- /dev/null
+++ b/contrib/libpcap/pcap-sita.h
@@ -0,0 +1,10 @@
+/*
+ * pcap-sita.h: Packet capture interface for SITA WAN devices
+ *
+ * Authors: Fulko Hew (fulko.hew@sita.aero) (+1 905 6815570);
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-sita.h
+ */
+
+extern int acn_parse_hosts_file(char *errbuf);
+extern int acn_findalldevs(char *errbuf);
diff --git a/contrib/libpcap/pcap-sita.html b/contrib/libpcap/pcap-sita.html
new file mode 100644
index 0000000..5f7884f
--- /dev/null
+++ b/contrib/libpcap/pcap-sita.html
@@ -0,0 +1,943 @@
+<HTML><HEAD>
+<STYLE type="text/css">
+<!--
+A { text-decoration:none }
+-->
+</STYLE>
+</HEAD>
+<BODY>
+
+<TABLE WIDTH=100%><TR>
+ <TD ALIGN=LEFT VALIGN=TOP>
+ <FONT SIZE=+0 FACE="COURIER"><B>A "Distributed Pcap" for<BR>Remote Monitoring LANs & WANs</B><BR>
+ (Design Notes for the SITA ACN device)</FONT>
+ </TD>
+ <TD ALIGN=RIGHT VALIGN=TOP>
+ Fulko Hew<BR>SITA INC Canada, Inc.<BR>Revised: October 2, 2007
+ </TD>
+</TR></TABLE>
+
+
+<H3>SUMMARY</H3>
+<UL>
+ <STRONG>Note:</STRONG> This document is part of the libpcap CVS and was derived from 'pcap.3' (circa Aug/07).
+ <P>
+ The ACN provides a customized/distributed version of this library that alows SMPs to
+ interact with the various IOPs within the site providing a standard mechanism
+ to capture LAN and WAN message traffic.
+ <P>
+ <CENTER>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3 WIDTH=75%>
+ <TR>
+ <TH VALIGN=TOP>SMP</TH>
+ <TD VALIGN=TOP>The Supervisory Management Processor where Wireshark (or equivalent)
+ runs in conjuction with a libpcap front-end.</TD>
+ </TR>
+ <TR>
+ <TH VALIGN=TOP>IOP</TH>
+ <TD VALIGN=TOP>I/O Processors where the monitored ports exist in conjunction
+ with a custom device driver/libpcap back-end.</TD>
+ </TR>
+ </TABLE>
+ </CENTER>
+ <P>
+ Each IOP will be capable of supporting multiple connections from an SMP
+ enabling monitoring of more than one interface at a time, each through
+ its own seperate connection. The IOP is responsible to ensure and report
+ an error if any attempt is made to monitor the same interface more than once.
+ <P>
+ There are three applications that will be supported by the ACN version of libpcap.
+ They each use a slightly different mode for looping/capturing and termination
+ as summarized in the following table:
+ <P>
+ <CENTER>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR><TH>Application</TH> <TH>Capture</TH> <TH>Termination</TH></TR>
+ <TR><TH VALIGN=TOP NOWRAP>wireshark</TH>
+ <TD VALIGN=TOP>pcap_dispatch(all packets in one buffer of capture only)</TD>
+ <TD VALIGN=TOP>pcap_breakloop()</TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>tshark</TH>
+ <TD VALIGN=TOP>pcap_dispatch(one buffer of capture only)</TD>
+ <TD VALIGN=TOP>Since a CTRL-C was used to terminate the application, pcap_breakloop() is never called.</TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>tcpdump</TH>
+ <TD VALIGN=TOP>pcap_loop(all packets in the next buffer, and loop forever)</TD>
+ <TD VALIGN=TOP>pcap_breakloop()</TD>
+ </TR>
+ </TABLE>
+ </CENTER>
+ <P>
+ <B>Note: </B>In all cases, the termination of capturing is always (apparently) followed by
+ pcap_close(). Pcap_breakloop() is only used to stop/suspend looping/processing,
+ and upon close interpretation of the function definitions, it is possible to resume
+ capturing following a pcap_breakloop() without any re-initialization.
+ <P>
+ <H4>ACN Limitations</H4>
+ <OL>
+ <LI>Monitoring of backup IOPs is not currently supported.
+ <LI>Ethernet interfaces cannot be monitored in promiscuous mode.
+ </OL>
+
+</UL>
+
+<H3>ROUTINES</H3>
+<UL>
+ The following list of functions is the sub-set of Pcap functions that have been
+ altered/enhanced to support the ACN remote monitoring facility. The remainder of the Pcap
+ functions continue to perform their duties un-altered. Libpcap only supports this
+ mode of operation if it has been configured/compiled for SITA/ACN support.
+ <P>
+ <UL><FONT FACE=COURIER>
+ pcap_findalldevs<BR>
+ pcap_freealldevs<BR>
+ pcap_open_live<BR>
+ pcap_close<BR>
+ pcap_setfilter<BR>
+ pcap_dispatch<BR>
+ pcap_loop<BR>
+ pcap_next<BR>
+ pcap_next_ex<BR>
+ pcap_stats<BR>
+ </FONT></UL>
+
+ These subroutines have been modified for the ACN specific distributed and remote monitoring
+ ability perform the following basic functions. More detail is provided in the
+ "SMP/IOP Inter-Process Communication Protocol" section.
+ <P>
+<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_open_live()</B></TD>
+ <TD VALIGN=TOP>Used to obtain a packet capture descriptor to look at packets on the network.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP will open a connection to the selected IOP on its 'sniffer' port
+ to ensure it is available. It sends a null terminated string identifying
+ the interface to be monitored.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ After any required processing is complete, the IOP will return a
+ null terminated string containing an error message if one occured.
+ If no error occured, a empty string is still returned.
+ Errors are:
+ <UL>
+ <LI>"Interface (xxx) does not exist."
+ <LI>"Interface (xxx) not configured."
+ <LI>"Interface (xxx) already being monitored."
+ </UL>
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_findalldevs()</B></TD>
+ <TD VALIGN=TOP>It constructs a list of network devices that can be opened with pcap_open_live().</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ It obtains a list of IOPs currently available (via /etc/hosts).
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP will sequentially open a connection to each IOP on its 'sniffer' port to ensure
+ the IOP is available.
+ It sends a null terminated empty interface ID followed by the query request command.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>The IOP returns an error response and its list of devices.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP closes the TCP connection with each IOP.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP adds the received information to its internal structure.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_freealldevs()</B></TD>
+ <TD VALIGN=TOP>Used to free a list allocated by pcap_findalldevs().</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP frees the structure it built as a result of the previous
+ invocation of pcap_findalldevs().
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_dispatch()</B></TD>
+ <TD VALIGN=TOP>Used to collect and process packets.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+ the SMP will pass down the monitor start command and various parameters the IOP should use.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP now sends a stream of captured data.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP will read the reverse channel of the connection between the SMP and the
+ IOP that provides the captured data (via 'p->read_op' which is 'pcap_read_linux()'
+ until the select() call returns a 'no more data' indication.
+ It will the process (at most) the next 'cnt' packets and invoke the specified
+ callback function for each packet processed.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+ <TD>
+ The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_loop()</B></TD>
+ <TD VALIGN=TOP>
+ Is similar to pcap_dispatch() except it keeps reading packets until
+ the requested number of packets are processed or an error occurs.
+ </TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+ the SMP will pass down the monitor start command and various parameters the IOP should use.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP now sends a stream of captured data.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP continuously reads the next packet from the reverse channel of the connection
+ between the SMP and the IOP that provides the captured data (via 'p->read_op'
+ which is 'pcap_read_linux()' until 'cnt' packets have been received.
+ The specified callback function will be invoked for each packet received.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+ <TD>
+ The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_next()</B></TD>
+ <TD VALIGN=TOP>
+ It reads the next packet (by calling pcap_dispatch() with a count of 1)
+ and returns a pointer to the data in that packet.
+ </TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+ the SMP will pass down the monitor start command and various parameters the IOP should use.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP now sends a stream of captured data.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP reads only the next packet from the reverse channel of the connection
+ between the SMP and the IOP that provides the captured data (via calling pcap_dispatch()
+ with a count of 1) and returns a pointer to that data by invoking an internal callback.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+ <TD>
+ The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_next_ex()</B></TD>
+ <TD VALIGN=TOP>Reads the next packet and returns a success/failure indication.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+ the SMP will pass down the monitor start command and various parameters the IOP should use.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP now sends a stream of captured data.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP reads only the next packet from the reverse channel of the connection
+ between the SMP and the IOP that provides the captured data (via calling pcap_dispatch()
+ with a count of 1) and returns seperate pointers to both the
+ packet header and packet data by invoking an internal callback.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+ <TD>
+ The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_setfilter()</B></TD>
+ <TD VALIGN=TOP>Used to specify a filter program.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP sends a 'set filter' command followed by the BPF commands.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP returns a null terminated error string if it failed to accept the filter.
+ If no error occured, then a NULL terminated empty string is returned instead.
+ Errors are:
+ <UL>
+ <LI>"Invalid BPF."
+ <LI>"Insufficient resources for BPF."
+ </UL>
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_stats()</B></TD>
+ <TD VALIGN=TOP>Fills in a pcap_stat struct with packet statistics.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP sends a message to the IOP requesting its statistics.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP returns the statistics.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP fills in the structure provided with the information retrieved from the IOP.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_close()</B></TD>
+ <TD VALIGN=TOP>Closes the file and deallocates resources.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP closes the file descriptor, and if the descriptor is that of
+ the comminucation session with an IOP, it too is terminated.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+ <TD>
+ If the IOP detects that its communication session with an SMP
+ has closed, it will terminate any monitoring in progress,
+ release any resources and close its end of the session.
+ It will not maintain persistance of any information or prior mode of operation.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+</TABLE>
+</UL>
+
+<P>
+<H3>SMP/IOP Inter-Process Communication Protocol</H3>
+
+<UL>
+ <LI><P>Communications between an SMP and an IOP consists of a TCP session
+ between an ephemeral port on the SMP and the well known port of 49152
+ (which is the first available port in the 'dynamic and/or private port'
+ range) on an IOP.
+ <LI><P>Following a TCP open operation the IOP receives a null terminated
+ 'interface ID' string to determine the type of operation that follows:
+ <LI><P>Every command received by an IOP implies a 'stop trace/stop forwarding' operation must
+ occur before executing the received command.
+ <LI><P>A session is closed when the SMP closes the TCP session with the IOP.
+ Obviously monitoring and forwarding is also stopped at that time.
+
+ <B>Note: </B>All multi-octet entities are sent in network neutral order.
+ <P>
+
+ <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=5>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=6>pcap_findalldevs()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>Open socket (to each IOP), and sends:
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>Interface ID</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>A NULL to indicate an an empty 'interface ID'.</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>Send its (possibly empty) NULL terminated error response string.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>Sends the 'interface query request':
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>Interface ID</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>A 'Q' (indicating 'interface query request').</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>The IOP returns a list of sequences of information as
+ defined by the return parameter of this function call (as shown in the following table).
+ Elements are specified by providing an unsigned byte preceeding the actual data that contains length information.
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Notes:</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD ROWSPAN=7>&nbsp;</TD>
+ <TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the name field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Name</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1-255</TD>
+ <TD VALIGN=TOP>The name of the interface. The format of the name is an alphabetic string (indicating
+ the type of interface) followed by an optional numeric string (indicating the interface's
+ sequence number).
+ Sequence numbers (if needed) will begin at zero and progress monotonically upwards.
+ (i.e. 'eth0', 'lo', 'wan0', etc.)
+ <P>
+ For an IOP, the alphabetic string will be one of: 'eth', 'wan', and 'lo'
+ for Ethernet, WAN ports and the IP loopback device respectively.
+ An IOP currently supports: 'eth0', 'eth1', 'lo', 'wan0' ... 'wan7'.
+ <P>
+ <B>Note:</B> IOPs and ACNs will not currently support the concept of 'any' interface.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the interface description field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Interface Description</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+ <TD VALIGN=TOP>A description of the interface or it may be an empty string. (i.e. 'ALC')</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Interface Type</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The type of interface as defined in the description for pcap_datalink() (in network neutral order).</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Loopback Flag</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>1 = if the interface is a loopback interface, zero = otherwise.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=RIGHT>count</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP># of address entries that follow.
+ Each entry is a series of bytes in network neutral order.
+ See the parameter definition above for more details.</TD>
+ </TR>
+ <TR>
+ <TD ALIGN=CENTER ROWSPAN=8 WIDTH=1%>Repeated 'count' number of times.</TD>
+ <TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the address field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Address</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1-255</TD>
+ <TD VALIGN=TOP>The address of this interface (in network neutral order).</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the netmask field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Network Mask</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+ <TD VALIGN=TOP>The network mask used on this interface (if applicable) (in network neutral order).</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the broadcast address field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Broadcast Address</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+ <TD VALIGN=TOP>The broadcast address of this interface (if applicable) (in network neutral order).</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the destination address field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Destination Address</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+ <TD VALIGN=TOP>The destination address of this interface (if applicable) (in network neutral order).</TD>
+ </TR>
+ </TABLE>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>Close the socket.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>Close the socket.</TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2>pcap_open_live()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>Open socket, and sends:
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>Interface ID</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>'n'</TD>
+ <TD VALIGN=TOP>'n' octets containing a NULL terminated interface name string.</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>Send its NULL terminated error response string.</TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP NOWRAP ROWSPAN=2>pcap_dispatch()<BR>pcap_loop()<BR>pcap_next()<BR>pcap_next_ex()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>On the first invocation following a pcap_open_live() or pcap_breakloop() additional information is sent:
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>command</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>'M' (indicating 'monitor start')</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>snaplen</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>snaplen</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>timeout</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>timeout value (in milliseconds)</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>promiscuous</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>A flag indicating that the interface being monitored show operate
+ in promiscuous mode. [off(0) / on(NZ)]</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>direction</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>A flag indicating the direction of traffic that should be captuted [both(0) / in(1) / out(2)]</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>Sends captured packets.</TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2>pcap_setfilter()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>At any time, the SMP can issue a set filter command which contains
+ an indicator, a count of the number of statements in the filter,
+ followed by the sequence of filter commands represented as a sequence
+ of C-style structures.
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>command</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>'F' (indicating 'filter')</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>count</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The number of command in the Berkeley Packet Filter that follow.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>BPF program</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>'n'</TD>
+ <TD VALIGN=TOP>8 bytes of each command (repeated 'n' times).<BR>
+ Each command consists of that C-style structure which contains:
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>opcode</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>2</TD>
+ <TD VALIGN=TOP>The command's opcode.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>'jt'</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The 'jump if true' program counter offset.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>'jf'</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The 'jump if false' program counter offset.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>'k'</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The 'other' data field.</TD>
+ </TR>
+ </TABLE>
+ <P>
+ Refer to the bpf(4) man page for more details.
+ </TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>In return the IOP will send its (possibly empty) NULL terminated error response string.</TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2>pcap_stats()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>At any time, the SMP can issue a 'retrieve statistics' command which contains:<BR>
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>command</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>'S' (indicating 'request statistics')</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>In return the IOP will send:
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>ps_recv</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The number of packets that passed the filter.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>ps_drop</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The number of packets that were dropped because the input queue was full,
+ regardless of whether they passed the filter.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>ps_ifdrop</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The number of packets dropped by the network inteface
+ (regardless of whether they would have passed the input filter).</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=1>pcap_close()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>At any time, the SMP can close the TCP session with the IOP.</TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ </TABLE>
+</UL>
+
+<H3>Interface ID Naming Convention</H3>
+<UL>
+ Each interface within an IOP will be referred to uniquely. Since an currently contains
+ 8 monitorable WAN ports and a monitorable Ethernet port, the naming convention is:
+ <P>
+ <CENTER>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR><TH>Interface #</TH> <TH>Type</TH> <TH>Name</TH></TR>
+ <TR><TD ALIGN=CENTER>1</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan0</TD></TR>
+ <TR><TD ALIGN=CENTER>2</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan1</TD></TR>
+ <TR><TD ALIGN=CENTER>3</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan2</TD></TR>
+ <TR><TD ALIGN=CENTER>4</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan3</TD></TR>
+ <TR><TD ALIGN=CENTER>5</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan4</TD></TR>
+ <TR><TD ALIGN=CENTER>6</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan5</TD></TR>
+ <TR><TD ALIGN=CENTER>7</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan6</TD></TR>
+ <TR><TD ALIGN=CENTER>8</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan7</TD></TR>
+ <TR><TD ALIGN=CENTER>9</TD> <TD ALIGN=CENTER>Ethernet</TD> <TD ALIGN=CENTER>eth0</TD></TR>
+ <TR><TD ALIGN=CENTER>10</TD> <TD ALIGN=CENTER>Ethernet</TD> <TD ALIGN=CENTER>eth1</TD></TR>
+ </TABLE>
+ </CENTER>
+</UL>
+
+<H3>Packet Trace Data Format</H3>
+<UL>
+ The format of the trace data that is sent to the SMP follows a portion of the libpcap file format
+ and is summarized here. This format specifies the generic requirements needed to
+ be able to decode packets, but does not cover ACN specifics such as custom MAC addressing
+ and WAN protocol support.
+ <P>
+
+ Although a libpcap file begins with a global header followed by zero or
+ more records for each captured packet, trace data sent to the SMP does NOT begin with a global header.
+ A trace sequence looks like this:
+ <P>
+ <TABLE>
+ <TR>
+ <TD STYLE="background-color: #c0FFc0">&nbsp;[Packet Header]&nbsp;</TD>
+ <TD STYLE="background-color: #c0FFc0">&nbsp;[Packet Data]&nbsp;</TD>
+ <TD STYLE="background-color: #c0c0FF">&nbsp;[Packet Header]&nbsp;</TD>
+ <TD STYLE="background-color: #c0c0FF">&nbsp;[Packet Data]&nbsp;</TD>
+ <TD STYLE="background-color: #e0c0c0">&nbsp;[Packet Header]&nbsp;</TD>
+ <TD STYLE="background-color: #e0c0c0">&nbsp;[Packet Data]&nbsp;</TD>
+ <TD>...</TD>
+ </TR>
+ </TABLE>
+
+<H4>Packet Header</H4>
+ <UL>
+ Each captured packet starts with a header that contains the following values
+ (in network neutral order):
+
+ <FONT SIZE=-1>
+ <PRE>
+ uint32 tv_sec; /* timestamp seconds */
+ uint32 tv_usec; /* timestamp microseconds */
+ uint32 caplen; /* number of octets in the following packet */
+ uint32 len; /* original length of packet on the wire */
+ </PRE>
+ </FONT>
+
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TD VALIGN=TOP>tv_sec</TD>
+ <TD>The date and time when this packet was captured.
+ This value is in seconds since January 1, 1970 00:00:00 GMT;
+ this is also known as a UN*X time_t. You can use the ANSI C
+ <em>time()</em> function from <em>time.h</em> to get this value,
+ but you might use a more optimized way to get this timestamp value.
+ If this timestamp isn't based on GMT (UTC), use <em>thiszone</em>
+ from the global header for adjustments.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>tv_usec</TD>
+ <TD>The microseconds when this packet was captured, as an offset to <em>ts_sec</em>.
+ <B>Beware: </B>this value must never reach 1 second (1,000,000),
+ in this case <em>ts_sec</em> must be increased instead!</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>caplen</TD>
+ <TD>The number of bytes actually provided in the capture record.
+ This value should never become larger than <em>len</em> or the
+ <em>snaplen</em> value specified during the capture.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>len</TD>
+ <TD>The length of the packet "on the wire" when it was captured.
+ If <em>caplen</em> and <em>len</em> differ, the actually
+ saved packet size was limited by the value of <em>snaplen</em> specified
+ during one of the capture directives such as pcap_dispatch().</TD>
+ </TR>
+ </TABLE>
+ </UL>
+
+<H4>Packet Data</H4>
+ <UL>
+ The actual packet data will immediately follow the packet header as a sequence of <em>caplen</em> octets.
+ Depending on the DLT encoding number assigned to the interface, the packet data will contain an additional
+ custom header used to convey WAN port related information.
+ </UL>
+
+<H4>ACN Custom Packet Header</H4>
+ <UL>
+ PCAP, Wireshark and Tcpdump enhancements have been added to the ACN to support
+ monitoring of its ports, however each of these facilities were focused on capturing
+ and displaying traffic from LAN interfaces. The SITA extentions to these facilities
+ are used to also provide the ability to capture, filter, and display information from
+ an ACN's WAN ports.
+ <P>
+ Although each packet follows the standard libpcap format, since there are
+ two types of interfaces that can be monitored, the format of the data
+ packet varies slightly.
+ <P>
+ <UL TYPE=DISC>
+ <LI>For Ethernet (like) devices, the packet format is unchanged from the standard Pcap format.
+ <LI>For WAN devices, the packet contains a 5 byte header that preceeds the actual captured data
+ described by the following table:
+ </UL>
+ <P>
+ <CENTER>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR> <TH>Octet</TH>
+ <TH>Name</TH>
+ <TH>Mask/Value</TH>
+ <TH COLSPAN=2>Definition</TH> </TR>
+
+ <TR> <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=3>0</TH>
+ <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=3>Control / Status</TH>
+
+ <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx0</FONT></TD>
+ <TD>Transmitted by capture device</TD>
+ <TD ROWSPAN=2 ALIGN=CENTER>(see 'Errors' octets)</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD>
+ <TD>Received by capture device</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD>
+ <TD COLSPAN=2>No buffer was available during capture of previous packet.</TD> </TR>
+
+ <TR> <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=8>1</TH>
+ <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=8>Signals</TH>
+
+ <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD> <TD COLSPAN=2>DSR asserted</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD> <TD COLSPAN=2>DTR asserted</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD> <TD COLSPAN=2>CTS asserted</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD> <TD COLSPAN=2>RTS asserted</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD> <TD COLSPAN=2>DCD asserted</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD> <TD COLSPAN=2>Undefined</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD> <TD COLSPAN=2>Undefined</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD> <TD COLSPAN=2>Undefined</TD> </TR>
+
+ <TR> <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>2</TH>
+ <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>Errors<BR>(octet 1)</TH>
+
+ <TH>&nbsp;</TH> <TH>Tx</TH> <TH>Rx</TH> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD> <TD>Underrun</TD> <TD>Framing</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD> <TD>CTS Lost</TD> <TD>Parity</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD> <TD>UART Error</TD> <TD>Collision</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD> <TD>Re-Tx Limit Reached</TD> <TD>Long Frame</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD> <TD>Undefined</TD> <TD>Short Frame</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD> <TD>Undefined</TD> <TD>Undefined</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD> <TD>Undefined</TD> <TD>Undefined</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD> <TD>Undefined</TD> <TD>Undefined</TD> </TR>
+
+ <TR> <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>3</TH>
+ <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>Errors<BR>(octet 2)</TH>
+
+ <TH>&nbsp;</TH> <TH>Tx</TH> <TH>Rx</TH> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD> <TD>Undefined</TD> <TD>Non-Octet Aligned</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD> <TD>Undefined</TD> <TD>Abort Received</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD> <TD>Undefined</TD> <TD>CD Lost</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD> <TD>Undefined</TD> <TD>Digital PLL Error</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD> <TD>Undefined</TD> <TD>Overrun</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD> <TD>Undefined</TD> <TD>Frame Length Violation</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD> <TD>Undefined</TD> <TD>CRC Error</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD> <TD>Undefined</TD> <TD>Break Received</TD> </TR>
+
+ <TR> <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=12>4</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Protocol</TH>
+
+ <TD COLSPAN=3>
+ <CENTER>
+ <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x01</TD> <TD>-</TD> <TD>LAPB (BOP) <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x02</TD> <TD>-</TD> <TD>Ethernet <SUP>1</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x03</TD> <TD>-</TD> <TD>Async (Interrupt IO) <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x04</TD> <TD>-</TD> <TD>Async (Block IO) <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x05</TD> <TD>-</TD> <TD>IPARS <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x06</TD> <TD>-</TD> <TD>UTS <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x07</TD> <TD>-</TD> <TD>PPP (HDLC) <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x08</TD> <TD>-</TD> <TD>SDLC <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x09</TD> <TD>-</TD> <TD>Token Ring <SUP>1</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x10</TD> <TD>-</TD> <TD>I2C <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x11</TD> <TD>-</TD> <TD>DPM Link <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x12</TD> <TD>-</TD> <TD>Frame Relay (BOP) <SUP>&nbsp;</SUP> </TD> </TR>
+ </TABLE>
+ </CENTER>
+ <P>
+ <STRONG>Note 1:</STRONG>
+ Ethernet and Token Ring frames will never be sent as DLT_SITA (with the 5 octet header),
+ but will be sent as their corresponding DLT types instead.
+ </TD>
+ </TR>
+ </TABLE>
+ </CENTER>
+</UL>
+<P>
+</UL>
+</UL>
diff --git a/contrib/libpcap/pcap-snit.c b/contrib/libpcap/pcap-snit.c
index 60abe64..8f937be 100644
--- a/contrib/libpcap/pcap-snit.c
+++ b/contrib/libpcap/pcap-snit.c
@@ -25,7 +25,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.72.2.1 2005/05/03 18:54:38 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.73.2.4 2008-04-14 20:41:52 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -113,7 +113,6 @@ static int
pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
register int cc, n;
- register struct bpf_insn *fcode = p->fcode.bf_insns;
register u_char *bp, *cp, *ep;
register struct nit_bufhdr *hdrp;
register struct nit_iftime *ntp;
@@ -187,13 +186,13 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
if (caplen > p->snapshot)
caplen = p->snapshot;
- if (bpf_filter(fcode, cp, nlp->nh_pktlen, caplen)) {
+ if (bpf_filter(p->fcode.bf_insns, cp, nlp->nh_pktlen, caplen)) {
struct pcap_pkthdr h;
h.ts = ntp->nh_timestamp;
h.len = nlp->nh_pktlen;
h.caplen = caplen;
(*callback)(user, &h, cp);
- if (++n >= cnt && cnt >= 0) {
+ if (++n >= cnt && cnt > 0) {
p->cc = ep - bp;
p->bp = bp;
return (n);
@@ -261,30 +260,29 @@ nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
return (0);
}
-pcap_t *
-pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
- char *ebuf)
+static int
+pcap_activate_snit(pcap_t *p)
{
struct strioctl si; /* struct for ioctl() */
struct ifreq ifr; /* interface request struct */
int chunksize = CHUNKSIZE;
int fd;
static char dev[] = "/dev/nit";
- register pcap_t *p;
- p = (pcap_t *)malloc(sizeof(*p));
- if (p == NULL) {
- strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
- return (NULL);
+ if (p->opt.rfmon) {
+ /*
+ * No monitor mode on SunOS 4.x (no Wi-Fi devices on
+ * hardware supported by SunOS 4.x).
+ */
+ return (PCAP_ERROR_RFMON_NOTSUP);
}
- if (snaplen < 96)
+ if (p->snapshot < 96)
/*
* NIT requires a snapshot length of at least 96.
*/
- snaplen = 96;
+ p->snapshot = 96;
- memset(p, 0, sizeof(*p));
/*
* Initially try a read/write open (to allow the inject
* method to work). If that fails due to permission
@@ -303,19 +301,19 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
if (fd < 0 && errno == EACCES)
p->fd = fd = open(dev, O_RDONLY);
if (fd < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dev,
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", dev,
pcap_strerror(errno));
goto bad;
}
/* arrange to get discrete messages from the STREAM and use NIT_BUF */
if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s",
pcap_strerror(errno));
goto bad;
}
if (ioctl(fd, I_PUSH, "nbuf") < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "push nbuf: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "push nbuf: %s",
pcap_strerror(errno));
goto bad;
}
@@ -325,34 +323,33 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
si.ic_len = sizeof(chunksize);
si.ic_dp = (char *)&chunksize;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s",
pcap_strerror(errno));
goto bad;
}
/* request the interface */
- strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
si.ic_cmd = NIOCBIND;
si.ic_len = sizeof(ifr);
si.ic_dp = (char *)&ifr;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s",
ifr.ifr_name, pcap_strerror(errno));
goto bad;
}
/* set the snapshot length */
si.ic_cmd = NIOCSSNAP;
- si.ic_len = sizeof(snaplen);
- si.ic_dp = (char *)&snaplen;
+ si.ic_len = sizeof(p->snapshot);
+ si.ic_dp = (char *)&p->snapshot;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s",
pcap_strerror(errno));
goto bad;
}
- p->snapshot = snaplen;
- if (nit_setflags(p->fd, promisc, to_ms, ebuf) < 0)
+ if (nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf) < 0)
goto bad;
(void)ioctl(fd, I_FLUSH, (char *)FLUSHR);
@@ -364,7 +361,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->bufsize = BUFSPACE;
p->buffer = (u_char *)malloc(p->bufsize);
if (p->buffer == NULL) {
- strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
+ strlcpy(p->errbuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE);
goto bad;
}
@@ -402,14 +399,23 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
p->stats_op = pcap_stats_snit;
- p->close_op = pcap_close_common;
- return (p);
+ return (0);
bad:
- if (fd >= 0)
- close(fd);
- free(p);
- return (NULL);
+ return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_snit;
+ return (p);
}
int
diff --git a/contrib/libpcap/pcap-snoop.c b/contrib/libpcap/pcap-snoop.c
index f6425f1..a803434 100644
--- a/contrib/libpcap/pcap-snoop.c
+++ b/contrib/libpcap/pcap-snoop.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.54.2.1 2005/05/03 18:54:38 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.55.2.3 2008-04-14 20:41:52 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -194,9 +194,8 @@ pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
}
/* XXX can't disable promiscuous */
-pcap_t *
-pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
- char *ebuf)
+static int
+pcap_activate_snoop(pcap_t *p)
{
int fd;
struct sockaddr_raw sr;
@@ -204,55 +203,50 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
u_int v;
int ll_hdrlen;
int snooplen;
- pcap_t *p;
struct ifreq ifr;
- p = (pcap_t *)malloc(sizeof(*p));
- if (p == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- return (NULL);
- }
- memset(p, 0, sizeof(*p));
fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
if (fd < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop socket: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop socket: %s",
pcap_strerror(errno));
goto bad;
}
p->fd = fd;
memset(&sr, 0, sizeof(sr));
sr.sr_family = AF_RAW;
- (void)strncpy(sr.sr_ifname, device, sizeof(sr.sr_ifname));
+ (void)strncpy(sr.sr_ifname, p->opt.source, sizeof(sr.sr_ifname));
if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snoop bind: %s",
pcap_strerror(errno));
goto bad;
}
memset(&sf, 0, sizeof(sf));
if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s",
pcap_strerror(errno));
goto bad;
}
- v = 64 * 1024;
+ if (handle->opt.buffer_size != 0)
+ v = handle->opt.buffer_size;
+ else
+ v = 64 * 1024; /* default to 64K buffer size */
(void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v));
/*
* XXX hack - map device name to link layer type
*/
- if (strncmp("et", device, 2) == 0 || /* Challenge 10 Mbit */
- strncmp("ec", device, 2) == 0 || /* Indigo/Indy 10 Mbit,
- O2 10/100 */
- strncmp("ef", device, 2) == 0 || /* O200/2000 10/100 Mbit */
- strncmp("eg", device, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */
- strncmp("gfe", device, 3) == 0 || /* GIO 100 Mbit */
- strncmp("fxp", device, 3) == 0 || /* Challenge VME Enet */
- strncmp("ep", device, 2) == 0 || /* Challenge 8x10 Mbit EPLEX */
- strncmp("vfe", device, 3) == 0 || /* Challenge VME 100Mbit */
- strncmp("fa", device, 2) == 0 ||
- strncmp("qaa", device, 3) == 0 ||
- strncmp("cip", device, 3) == 0 ||
- strncmp("el", device, 2) == 0) {
+ if (strncmp("et", p->opt.source, 2) == 0 || /* Challenge 10 Mbit */
+ strncmp("ec", p->opt.source, 2) == 0 || /* Indigo/Indy 10 Mbit,
+ O2 10/100 */
+ strncmp("ef", p->opt.source, 2) == 0 || /* O200/2000 10/100 Mbit */
+ strncmp("eg", p->opt.source, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */
+ strncmp("gfe", p->opt.source, 3) == 0 || /* GIO 100 Mbit */
+ strncmp("fxp", p->opt.source, 3) == 0 || /* Challenge VME Enet */
+ strncmp("ep", p->opt.source, 2) == 0 || /* Challenge 8x10 Mbit EPLEX */
+ strncmp("vfe", p->opt.source, 3) == 0 || /* Challenge VME 100Mbit */
+ strncmp("fa", p->opt.source, 2) == 0 ||
+ strncmp("qaa", p->opt.source, 3) == 0 ||
+ strncmp("cip", p->opt.source, 3) == 0 ||
+ strncmp("el", p->opt.source, 2) == 0) {
p->linktype = DLT_EN10MB;
p->offset = RAW_HDRPAD(sizeof(struct ether_header));
ll_hdrlen = sizeof(struct ether_header);
@@ -285,29 +279,38 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->dlt_list[1] = DLT_DOCSIS;
p->dlt_count = 2;
}
- } else if (strncmp("ipg", device, 3) == 0 ||
- strncmp("rns", device, 3) == 0 || /* O2/200/2000 FDDI */
- strncmp("xpi", device, 3) == 0) {
+ } else if (strncmp("ipg", p->opt.source, 3) == 0 ||
+ strncmp("rns", p->opt.source, 3) == 0 || /* O2/200/2000 FDDI */
+ strncmp("xpi", p->opt.source, 3) == 0) {
p->linktype = DLT_FDDI;
p->offset = 3; /* XXX yeah? */
ll_hdrlen = 13;
- } else if (strncmp("ppp", device, 3) == 0) {
+ } else if (strncmp("ppp", p->opt.source, 3) == 0) {
p->linktype = DLT_RAW;
ll_hdrlen = 0; /* DLT_RAW meaning "no PPP header, just the IP packet"? */
- } else if (strncmp("qfa", device, 3) == 0) {
+ } else if (strncmp("qfa", p->opt.source, 3) == 0) {
p->linktype = DLT_IP_OVER_FC;
ll_hdrlen = 24;
- } else if (strncmp("pl", device, 2) == 0) {
+ } else if (strncmp("pl", p->opt.source, 2) == 0) {
p->linktype = DLT_RAW;
ll_hdrlen = 0; /* Cray UNICOS/mp pseudo link */
- } else if (strncmp("lo", device, 2) == 0) {
+ } else if (strncmp("lo", p->opt.source, 2) == 0) {
p->linktype = DLT_NULL;
ll_hdrlen = 4;
} else {
- snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"snoop: unknown physical layer type");
goto bad;
}
+
+ if (p->opt.rfmon) {
+ /*
+ * No monitor mode on Irix (no Wi-Fi devices on
+ * hardware supported by Irix).
+ */
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+
#ifdef SIOCGIFMTU
/*
* XXX - IRIX appears to give you an error if you try to set the
@@ -315,9 +318,9 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* the MTU first and, if that succeeds, trim the snap length
* to be no greater than the MTU.
*/
- (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s",
pcap_strerror(errno));
goto bad;
}
@@ -338,8 +341,8 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
#ifndef ifr_mtu
#define ifr_mtu ifr_metric
#endif
- if (snaplen > ifr.ifr_mtu + ll_hdrlen)
- snaplen = ifr.ifr_mtu + ll_hdrlen;
+ if (p->snapshot > ifr.ifr_mtu + ll_hdrlen)
+ p->snapshot = ifr.ifr_mtu + ll_hdrlen;
#endif
/*
@@ -347,18 +350,17 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
* payload bytes to capture - it doesn't count link-layer
* header bytes.
*/
- snooplen = snaplen - ll_hdrlen;
+ snooplen = p->snapshot - ll_hdrlen;
if (snooplen < 0)
snooplen = 0;
if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s",
pcap_strerror(errno));
goto bad;
}
- p->snapshot = snaplen;
v = 1;
if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s",
pcap_strerror(errno));
goto bad;
}
@@ -366,7 +368,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->bufsize = 4096; /* XXX */
p->buffer = (u_char *)malloc(p->bufsize);
if (p->buffer == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
goto bad;
}
@@ -384,18 +386,23 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->getnonblock_op = pcap_getnonblock_fd;
p->setnonblock_op = pcap_setnonblock_fd;
p->stats_op = pcap_stats_snoop;
- p->close_op = pcap_close_common;
- return (p);
+ return (0);
bad:
- (void)close(fd);
- /*
- * Get rid of any link-layer type list we allocated.
- */
- if (p->dlt_list != NULL)
- free(p->dlt_list);
- free(p);
- return (NULL);
+ return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_snoop;
+ return (p);
}
int
diff --git a/contrib/libpcap/pcap-stdinc.h b/contrib/libpcap/pcap-stdinc.h
index 1281024..870e334 100644
--- a/contrib/libpcap/pcap-stdinc.h
+++ b/contrib/libpcap/pcap-stdinc.h
@@ -28,6 +28,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.
*
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-stdinc.h,v 1.10.2.1 2008-10-06 15:38:39 gianluca Exp $ (LBL)
*/
#define SIZEOF_CHAR 1
@@ -61,4 +62,29 @@
#define snprintf _snprintf
#define vsnprintf _vsnprintf
+#define strdup _strdup
#define inline __inline
+
+#ifdef __MINGW32__
+#include <stdint.h>
+#else /*__MINGW32__*/
+/* MSVC compiler */
+#ifndef _UINTPTR_T_DEFINED
+#ifdef _WIN64
+typedef unsigned __int64 uintptr_t;
+#else
+typedef _W64 unsigned int uintptr_t;
+#endif
+#define _UINTPTR_T_DEFINED
+#endif
+
+#ifndef _INTPTR_T_DEFINED
+#ifdef _WIN64
+typedef __int64 intptr_t;
+#else
+typedef _W64 int intptr_t;
+#endif
+#define _INTPTR_T_DEFINED
+#endif
+
+#endif /*__MINGW32__*/
diff --git a/contrib/libpcap/pcap-usb-linux.c b/contrib/libpcap/pcap-usb-linux.c
new file mode 100644
index 0000000..830abc7
--- /dev/null
+++ b/contrib/libpcap/pcap-usb-linux.c
@@ -0,0 +1,730 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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
+ * OWNER 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.
+ *
+ * USB sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ * Modifications: Kris Katterjohn <katterjohn@gmail.com>
+ *
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-usb-linux.c,v 1.16.2.8 2008-04-14 21:06:29 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcap-int.h"
+#include "pcap-usb-linux.h"
+#include "pcap/usb.h"
+
+#ifdef NEED_STRERROR_H
+#include "strerror.h"
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <dirent.h>
+#include <byteswap.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+
+#define USB_IFACE "usb"
+#define USB_TEXT_DIR "/sys/kernel/debug/usbmon"
+#define USB_BUS_DIR "/proc/bus/usb"
+#define USB_LINE_LEN 4096
+
+
+#define PIPE_IN 0x80
+#define PIPE_ISOCHRONOUS 0
+#define PIPE_INTERRUPT 1
+#define PIPE_CONTROL 2
+#define PIPE_BULK 3
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define htols(s) s
+#define htoll(l) l
+#define htol64(ll) ll
+#else
+#define htols(s) bswap_16(s)
+#define htoll(l) bswap_32(l)
+#define htol64(ll) bswap_64(ll)
+#endif
+
+struct mon_bin_stats {
+ u_int32_t queued;
+ u_int32_t dropped;
+};
+
+struct mon_bin_get {
+ pcap_usb_header *hdr;
+ void *data;
+ size_t data_len; /* Length of data (can be zero) */
+};
+
+struct mon_bin_mfetch {
+ int32_t *offvec; /* Vector of events fetched */
+ int32_t nfetch; /* Number of events to fetch (out: fetched) */
+ int32_t nflush; /* Number of events to flush */
+};
+
+#define MON_IOC_MAGIC 0x92
+
+#define MON_IOCQ_URB_LEN _IO(MON_IOC_MAGIC, 1)
+#define MON_IOCX_URB _IOWR(MON_IOC_MAGIC, 2, struct mon_bin_hdr)
+#define MON_IOCG_STATS _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats)
+#define MON_IOCT_RING_SIZE _IO(MON_IOC_MAGIC, 4)
+#define MON_IOCQ_RING_SIZE _IO(MON_IOC_MAGIC, 5)
+#define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
+#define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
+#define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
+
+#define MON_BIN_SETUP 0x1 /* setup hdr is present*/
+#define MON_BIN_SETUP_ZERO 0x2 /* setup buffer is not available */
+#define MON_BIN_DATA_ZERO 0x4 /* data buffer is not available */
+#define MON_BIN_ERROR 0x8
+
+/* forward declaration */
+static int usb_activate(pcap_t *);
+static int usb_stats_linux(pcap_t *, struct pcap_stat *);
+static int usb_stats_linux_bin(pcap_t *, struct pcap_stat *);
+static int usb_read_linux(pcap_t *, int , pcap_handler , u_char *);
+static int usb_read_linux_bin(pcap_t *, int , pcap_handler , u_char *);
+static int usb_read_linux_mmap(pcap_t *, int , pcap_handler , u_char *);
+static int usb_inject_linux(pcap_t *, const void *, size_t);
+static int usb_setfilter_linux(pcap_t *, struct bpf_program *);
+static int usb_setdirection_linux(pcap_t *, pcap_direction_t);
+static void usb_cleanup_linux_mmap(pcap_t *);
+
+/* facility to add an USB device to the device list*/
+static int
+usb_dev_add(pcap_if_t** alldevsp, int n, char *err_str)
+{
+ char dev_name[10];
+ char dev_descr[30];
+ snprintf(dev_name, 10, USB_IFACE"%d", n);
+ snprintf(dev_descr, 30, "USB bus number %d", n);
+
+ if (pcap_add_if(alldevsp, dev_name, 0,
+ dev_descr, err_str) < 0)
+ return -1;
+ return 0;
+}
+
+int
+usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str)
+{
+ struct dirent* data;
+ int ret = 0;
+ DIR* dir;
+
+ /* scan procfs usb bus directory */
+ dir = opendir(USB_BUS_DIR);
+ if (!dir) return 0;
+ while ((ret == 0) && ((data = readdir(dir)) != 0)) {
+ int n;
+ char* name = data->d_name;
+ int len = strlen(name);
+
+ /* if this file name does not end with a number it's not of our interest */
+ if ((len < 1) || !isdigit(name[--len]))
+ continue;
+ while (isdigit(name[--len]));
+ if (sscanf(&name[len+1], "%d", &n) != 1)
+ continue;
+
+ ret = usb_dev_add(alldevsp, n, err_str);
+ }
+
+ closedir(dir);
+ return ret;
+}
+
+static
+int usb_mmap(pcap_t* handle)
+{
+ int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE);
+ if (len < 0)
+ return 0;
+
+ handle->buffer = mmap(0, len, PROT_READ, MAP_SHARED, handle->fd, 0);
+ return handle->buffer != MAP_FAILED;
+}
+
+pcap_t *
+usb_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(device, ebuf);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = usb_activate;
+ return (p);
+}
+
+static int
+usb_activate(pcap_t* handle)
+{
+ char full_path[USB_LINE_LEN];
+
+ /* Initialize some components of the pcap structure. */
+ handle->bufsize = handle->snapshot;
+ handle->offset = 0;
+ handle->linktype = DLT_USB_LINUX;
+
+ handle->inject_op = usb_inject_linux;
+ handle->setfilter_op = usb_setfilter_linux;
+ handle->setdirection_op = usb_setdirection_linux;
+ handle->set_datalink_op = NULL; /* can't change data link type */
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+
+ /*get usb bus index from device name */
+ if (sscanf(handle->opt.source, USB_IFACE"%d", &handle->md.ifindex) != 1)
+ {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't get USB bus index from %s", handle->opt.source);
+ return PCAP_ERROR;
+ }
+
+ /*now select the read method: try to open binary interface */
+ snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handle->md.ifindex);
+ handle->fd = open(full_path, O_RDONLY, 0);
+ if (handle->fd >= 0)
+ {
+ if (handle->opt.rfmon) {
+ /*
+ * Monitor mode doesn't apply to USB devices.
+ */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /* binary api is available, try to use fast mmap access */
+ if (usb_mmap(handle)) {
+ handle->stats_op = usb_stats_linux_bin;
+ handle->read_op = usb_read_linux_mmap;
+ handle->cleanup_op = usb_cleanup_linux_mmap;
+
+ /*
+ * "handle->fd" is a real file, so "select()" and
+ * "poll()" work on it.
+ */
+ handle->selectable_fd = handle->fd;
+ return 0;
+ }
+
+ /* can't mmap, use plain binary interface access */
+ handle->stats_op = usb_stats_linux_bin;
+ handle->read_op = usb_read_linux_bin;
+ }
+ else {
+ /*Binary interface not available, try open text interface */
+ snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handle->md.ifindex);
+ handle->fd = open(full_path, O_RDONLY, 0);
+ if (handle->fd < 0)
+ {
+ /* no more fallback, give it up*/
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't open USB bus file %s: %s", full_path, strerror(errno));
+ return PCAP_ERROR;
+ }
+ handle->stats_op = usb_stats_linux;
+ handle->read_op = usb_read_linux;
+ }
+
+ if (handle->opt.rfmon) {
+ /*
+ * Monitor mode doesn't apply to USB devices.
+ */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /*
+ * "handle->fd" is a real file, so "select()" and "poll()"
+ * work on it.
+ */
+ handle->selectable_fd = handle->fd;
+
+ /* for plain binary access and text access we need to allocate the read
+ * buffer */
+ handle->buffer = malloc(handle->bufsize);
+ if (!handle->buffer) {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ return PCAP_ERROR;
+ }
+ return 0;
+}
+
+static inline int
+ascii_to_int(char c)
+{
+ return c < 'A' ? c- '0': ((c<'a') ? c - 'A' + 10: c-'a'+10);
+}
+
+/*
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
+ * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string
+ * format description
+ */
+static int
+usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+ /* see:
+ * /usr/src/linux/Documentation/usb/usbmon.txt
+ * for message format
+ */
+ unsigned timestamp;
+ int tag, cnt, ep_num, dev_addr, dummy, ret, urb_len, data_len;
+ char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN];
+ char *string = line;
+ u_char * rawdata = handle->buffer;
+ struct pcap_pkthdr pkth;
+ pcap_usb_header* uhdr = (pcap_usb_header*)handle->buffer;
+ u_char urb_transfer=0;
+ int incoming=0;
+
+ /* ignore interrupt system call errors */
+ do {
+ ret = read(handle->fd, line, USB_LINE_LEN - 1);
+ if (handle->break_loop)
+ {
+ handle->break_loop = 0;
+ return -2;
+ }
+ } while ((ret == -1) && (errno == EINTR));
+ if (ret < 0)
+ {
+ if (errno == EAGAIN)
+ return 0; /* no data there */
+
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't read from fd %d: %s", handle->fd, strerror(errno));
+ return -1;
+ }
+
+ /* read urb header; %n argument may increment return value, but it's
+ * not mandatory, so does not count on it*/
+ string[ret] = 0;
+ ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, &timestamp, &etype,
+ &pipeid1, &pipeid2, &dev_addr, &ep_num, status,
+ &cnt);
+ if (ret < 8)
+ {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)",
+ string, ret);
+ return -1;
+ }
+ uhdr->id = tag;
+ uhdr->endpoint_number = ep_num;
+ uhdr->device_address = dev_addr;
+ uhdr->bus_id = handle->md.ifindex;
+ uhdr->status = 0;
+ string += cnt;
+
+ /* don't use usbmon provided timestamp, since it have low precision*/
+ if (gettimeofday(&pkth.ts, NULL) < 0)
+ {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't get timestamp for message '%s' %d:%s",
+ string, errno, strerror(errno));
+ return -1;
+ }
+ uhdr->ts_sec = pkth.ts.tv_sec;
+ uhdr->ts_usec = pkth.ts.tv_usec;
+
+ /* parse endpoint information */
+ if (pipeid1 == 'C')
+ urb_transfer = URB_CONTROL;
+ else if (pipeid1 == 'Z')
+ urb_transfer = URB_ISOCHRONOUS;
+ else if (pipeid1 == 'I')
+ urb_transfer = URB_INTERRUPT;
+ else if (pipeid1 == 'B')
+ urb_transfer = URB_BULK;
+ if (pipeid2 == 'i') {
+ urb_transfer |= URB_TRANSFER_IN;
+ incoming = 1;
+ }
+ if (etype == 'C')
+ incoming = !incoming;
+
+ /* direction check*/
+ if (incoming)
+ {
+ if (handle->direction == PCAP_D_OUT)
+ return 0;
+ }
+ else
+ if (handle->direction == PCAP_D_IN)
+ return 0;
+ uhdr->event_type = etype;
+ uhdr->transfer_type = urb_transfer;
+ pkth.caplen = sizeof(pcap_usb_header);
+ rawdata += sizeof(pcap_usb_header);
+
+ /* check if this is a setup packet */
+ ret = sscanf(status, "%d", &dummy);
+ if (ret != 1)
+ {
+ /* this a setup packet, setup data can be filled with underscore if
+ * usbmon has not been able to read them, so we must parse this fields as
+ * strings */
+ pcap_usb_setup* shdr;
+ char str1[3], str2[3], str3[5], str4[5], str5[5];
+ ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4,
+ str5, &cnt);
+ if (ret < 5)
+ {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't parse USB bus message '%s', too few tokens (expected 5 got %d)",
+ string, ret);
+ return -1;
+ }
+ string += cnt;
+
+ /* try to convert to corresponding integer */
+ shdr = &uhdr->setup;
+ shdr->bmRequestType = strtoul(str1, 0, 16);
+ shdr->bRequest = strtoul(str2, 0, 16);
+ shdr->wValue = htols(strtoul(str3, 0, 16));
+ shdr->wIndex = htols(strtoul(str4, 0, 16));
+ shdr->wLength = htols(strtoul(str5, 0, 16));
+
+ uhdr->setup_flag = 0;
+ }
+ else
+ uhdr->setup_flag = 1;
+
+ /* read urb data */
+ ret = sscanf(string, " %d%n", &urb_len, &cnt);
+ if (ret < 1)
+ {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't parse urb length from '%s'", string);
+ return -1;
+ }
+ string += cnt;
+
+ /* urb tag is not present if urb length is 0, so we can stop here
+ * text parsing */
+ pkth.len = urb_len+pkth.caplen;
+ uhdr->urb_len = urb_len;
+ uhdr->data_flag = 1;
+ data_len = 0;
+ if (uhdr->urb_len == pkth.caplen)
+ goto got;
+
+ /* check for data presence; data is present if and only if urb tag is '=' */
+ if (sscanf(string, " %c", &urb_tag) != 1)
+ {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't parse urb tag from '%s'", string);
+ return -1;
+ }
+
+ if (urb_tag != '=')
+ goto got;
+
+ /* skip urb tag and following space */
+ string += 3;
+
+ /* if we reach this point we got some urb data*/
+ uhdr->data_flag = 0;
+
+ /* read all urb data; if urb length is greater then the usbmon internal
+ * buffer length used by the kernel to spool the URB, we get only
+ * a partial information.
+ * At least until linux 2.6.17 there is no way to set usbmon intenal buffer
+ * length and default value is 130. */
+ while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < handle->snapshot))
+ {
+ rawdata[0] = ascii_to_int(string[0]) * 16 + ascii_to_int(string[1]);
+ rawdata++;
+ string+=2;
+ if (string[0] == ' ')
+ string++;
+ pkth.caplen++;
+ data_len++;
+ }
+
+got:
+ uhdr->data_len = data_len;
+ handle->md.packets_read++;
+ if (pkth.caplen > handle->snapshot)
+ pkth.caplen = handle->snapshot;
+
+ callback(user, &pkth, handle->buffer);
+ return 1;
+}
+
+static int
+usb_inject_linux(pcap_t *handle, const void *buf, size_t size)
+{
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on "
+ "USB devices");
+ return (-1);
+}
+
+static int
+usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+ int dummy, ret, consumed, cnt;
+ char string[USB_LINE_LEN];
+ char token[USB_LINE_LEN];
+ char * ptr = string;
+ snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handle->md.ifindex);
+
+ int fd = open(string, O_RDONLY, 0);
+ if (fd < 0)
+ {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't open USB stats file %s: %s",
+ string, strerror(errno));
+ return -1;
+ }
+
+ /* read stats line */
+ do {
+ ret = read(fd, string, USB_LINE_LEN-1);
+ } while ((ret == -1) && (errno == EINTR));
+ close(fd);
+
+ if (ret < 0)
+ {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't read stats from fd %d ", fd);
+ return -1;
+ }
+ string[ret] = 0;
+
+ /* extract info on dropped urbs */
+ for (consumed=0; consumed < ret; ) {
+ /* from the sscanf man page:
+ * The C standard says: "Execution of a %n directive does
+ * not increment the assignment count returned at the completion
+ * of execution" but the Corrigendum seems to contradict this.
+ * Do not make any assumptions on the effect of %n conversions
+ * on the return value and explicitly check for cnt assignmet*/
+ cnt = -1;
+ int ntok = sscanf(ptr, "%s%n", token, &cnt);
+ if ((ntok < 1) || (cnt < 0))
+ break;
+ consumed += cnt;
+ ptr += cnt;
+ if (strcmp(token, "nreaders") == 0)
+ ret = sscanf(ptr, "%d", &stats->ps_drop);
+ else
+ ret = sscanf(ptr, "%d", &dummy);
+ if (ntok != 1)
+ break;
+ consumed += cnt;
+ ptr += cnt;
+ }
+
+ stats->ps_recv = handle->md.packets_read;
+ stats->ps_ifdrop = 0;
+ return 0;
+}
+
+static int
+usb_setfilter_linux(pcap_t *p, struct bpf_program *fp)
+{
+ return 0;
+}
+
+static int
+usb_setdirection_linux(pcap_t *p, pcap_direction_t d)
+{
+ p->direction = d;
+ return 0;
+}
+
+
+static int
+usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
+{
+ int ret;
+ struct mon_bin_stats st;
+ ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
+ if (ret < 0)
+ {
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't read stats from fd %d:%s ", handle->fd, strerror(errno));
+ return -1;
+ }
+
+ stats->ps_recv = handle->md.packets_read + st.queued;
+ stats->ps_ifdrop = st.dropped;
+ return 0;
+}
+
+/*
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
+ * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
+ */
+static int
+usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+ struct mon_bin_get info;
+ int ret;
+ struct pcap_pkthdr pkth;
+ int clen = handle->snapshot - sizeof(pcap_usb_header);
+
+ /* the usb header is going to be part of 'packet' data*/
+ info.hdr = (pcap_usb_header*) handle->buffer;
+ info.data = handle->buffer + sizeof(pcap_usb_header);
+ info.data_len = clen;
+
+ /* ignore interrupt system call errors */
+ do {
+ ret = ioctl(handle->fd, MON_IOCX_GET, &info);
+ if (handle->break_loop)
+ {
+ handle->break_loop = 0;
+ return -2;
+ }
+ } while ((ret == -1) && (errno == EINTR));
+ if (ret < 0)
+ {
+ if (errno == EAGAIN)
+ return 0; /* no data there */
+
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't read from fd %d: %s", handle->fd, strerror(errno));
+ return -1;
+ }
+
+ /* we can get less that than really captured from kernel, depending on
+ * snaplen, so adjust header accordingly */
+ if (info.hdr->data_len < clen)
+ clen = info.hdr->data_len;
+ info.hdr->data_len = clen;
+ pkth.caplen = clen + sizeof(pcap_usb_header);
+ pkth.len = info.hdr->urb_len + sizeof(pcap_usb_header);
+ pkth.ts.tv_sec = info.hdr->ts_sec;
+ pkth.ts.tv_usec = info.hdr->ts_usec;
+
+ handle->md.packets_read++;
+ callback(user, &pkth, handle->buffer);
+ return 1;
+}
+
+/*
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
+ * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
+ */
+#define VEC_SIZE 32
+static int
+usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+ struct mon_bin_mfetch fetch;
+ int32_t vec[VEC_SIZE];
+ struct pcap_pkthdr pkth;
+ pcap_usb_header* hdr;
+ int nflush = 0;
+ int packets = 0;
+
+ for (;;) {
+ int i, ret;
+ int limit = max_packets - packets;
+ if (limit <= 0)
+ limit = VEC_SIZE;
+ if (limit > VEC_SIZE)
+ limit = VEC_SIZE;
+
+ /* try to fetch as many events as possible*/
+ fetch.offvec = vec;
+ fetch.nfetch = limit;
+ fetch.nflush = nflush;
+ /* ignore interrupt system call errors */
+ do {
+ ret = ioctl(handle->fd, MON_IOCX_MFETCH, &fetch);
+ if (handle->break_loop)
+ {
+ handle->break_loop = 0;
+ return -2;
+ }
+ } while ((ret == -1) && (errno == EINTR));
+ if (ret < 0)
+ {
+ if (errno == EAGAIN)
+ return 0; /* no data there */
+
+ snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't mfetch fd %d: %s", handle->fd, strerror(errno));
+ return -1;
+ }
+
+ /* keep track of processed events, we will flush them later */
+ nflush = fetch.nfetch;
+ for (i=0; i<fetch.nfetch; ++i) {
+ /* discard filler */
+ hdr = (pcap_usb_header*) &handle->buffer[vec[i]];
+ if (hdr->event_type == '@')
+ continue;
+
+ /* get packet info from header*/
+ pkth.caplen = hdr->data_len + sizeof(pcap_usb_header);
+ pkth.len = hdr->urb_len + sizeof(pcap_usb_header);
+ pkth.ts.tv_sec = hdr->ts_sec;
+ pkth.ts.tv_usec = hdr->ts_usec;
+
+ handle->md.packets_read++;
+ callback(user, &pkth, (u_char*) hdr);
+ packets++;
+ }
+
+ /* with max_packets <= 0 we stop afer the first chunk*/
+ if ((max_packets <= 0) || (packets == max_packets))
+ break;
+ }
+
+ /* flush pending events*/
+ ioctl(handle->fd, MON_IOCH_MFLUSH, nflush);
+ return packets;
+}
+
+static void
+usb_cleanup_linux_mmap(pcap_t* handle)
+{
+ /* buffer must not be freed because it's memory mapped */
+ /* XXX - does it need to be unmapped? */
+ handle->buffer = NULL;
+ pcap_cleanup_live_common(handle);
+}
diff --git a/contrib/libpcap/pcap-usb-linux.h b/contrib/libpcap/pcap-usb-linux.h
new file mode 100644
index 0000000..a157907
--- /dev/null
+++ b/contrib/libpcap/pcap-usb-linux.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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
+ * OWNER 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.
+ *
+ * USB sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap-usb-linux.h,v 1.4.2.1 2008-04-04 19:39:06 guy Exp $ (LBL)
+ */
+
+/*
+ * Prototypes for USB-related functions
+ */
+int usb_platform_finddevs(pcap_if_t **alldevsp, char *err_str);
+pcap_t *usb_create(const char *device, char *ebuf);
diff --git a/contrib/libpcap/pcap-win32.c b/contrib/libpcap/pcap-win32.c
index 435da66..4fea621 100644
--- a/contrib/libpcap/pcap-win32.c
+++ b/contrib/libpcap/pcap-win32.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
- * Copyright (c) 2005 - 2007 CACE Technologies, Davis (California)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,12 +33,16 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.25.2.7 2007/06/14 22:07:14 gianluca Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.34.2.8 2008-05-21 22:11:26 gianluca Exp $ (LBL)";
#endif
#include <pcap-int.h>
#include <Packet32.h>
-#include <Ntddndis.h>
+#ifdef __MINGW32__
+#include <ddk/ndis.h>
+#else /*__MINGW32__*/
+#include <ntddndis.h>
+#endif /*__MINGW32__*/
#ifdef HAVE_DAG_API
#include <dagnew.h>
#include <dagapi.h>
@@ -53,8 +57,11 @@ static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
static int pcap_getnonblock_win32(pcap_t *, char *);
static int pcap_setnonblock_win32(pcap_t *, int, char *);
-#define PcapBufSize 256000 /*dimension of the buffer in the pcap_t structure*/
-#define SIZE_BUF 1000000
+/*dimension of the buffer in the pcap_t structure*/
+#define WIN32_DEFAULT_USER_BUFFER_SIZE 256000
+
+/*dimension of the buffer in the kernel driver NPF */
+#define WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000
/* Equivalent to ntohs(), but a lot faster under Windows */
#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
@@ -100,6 +107,43 @@ pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
return 0;
}
+/* Set the dimension of the kernel-level capture buffer */
+static int
+pcap_setbuff_win32(pcap_t *p, int dim)
+{
+ if(PacketSetBuff(p->adapter,dim)==FALSE)
+ {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+ return -1;
+ }
+ return 0;
+}
+
+/* Set the driver working mode */
+static int
+pcap_setmode_win32(pcap_t *p, int mode)
+{
+ if(PacketSetMode(p->adapter,mode)==FALSE)
+ {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*set the minimum amount of data that will release a read call*/
+static int
+pcap_setmintocopy_win32(pcap_t *p, int size)
+{
+ if(PacketSetMinToCopy(p->adapter, size)==FALSE)
+ {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
+ return -1;
+ }
+ return 0;
+}
+
static int
pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
@@ -376,9 +420,8 @@ pcap_inject_win32(pcap_t *p, const void *buf, size_t size){
}
static void
-pcap_close_win32(pcap_t *p)
+pcap_cleanup_win32(pcap_t *p)
{
- pcap_close_common(p);
if (p->adapter != NULL) {
PacketCloseAdapter(p->adapter);
p->adapter = NULL;
@@ -387,41 +430,39 @@ pcap_close_win32(pcap_t *p)
PacketFreePacket(p->Packet);
p->Packet = NULL;
}
+ pcap_cleanup_live_common(p);
}
-pcap_t *
-pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
- char *ebuf)
+static int
+pcap_activate_win32(pcap_t *p)
{
- register pcap_t *p;
NetType type;
+ if (p->opt.rfmon) {
+ /*
+ * No monitor mode on Windows. It could be done on
+ * Vista with drivers that support the native 802.11
+ * mechanism and monitor mode.
+ */
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+
/* Init WinSock */
wsockinit();
- p = (pcap_t *)malloc(sizeof(*p));
- if (p == NULL)
- {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
- return (NULL);
- }
- memset(p, 0, sizeof(*p));
- p->adapter=NULL;
-
- p->adapter = PacketOpenAdapter((char*)device);
+ p->adapter = PacketOpenAdapter(p->opt.source);
if (p->adapter == NULL)
{
- free(p);
/* Adapter detected but we are not able to open it. Return failure. */
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
- return NULL;
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
+ return PCAP_ERROR;
}
/*get network type*/
if(PacketGetNetType (p->adapter,&type) == FALSE)
{
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
goto bad;
}
@@ -505,12 +546,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
}
/* Set promiscuous mode */
- if (promisc)
+ if (p->opt.promisc)
{
if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
{
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
goto bad;
}
}
@@ -518,21 +559,18 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
{
if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE)
{
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
goto bad;
}
}
/* Set the buffer size */
- p->bufsize = PcapBufSize;
-
- /* Store the timeout. Used by pcap_setnonblock() */
- p->timeout= to_ms;
+ p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
/* allocate Packet structure used during the capture */
if((p->Packet = PacketAllocatePacket())==NULL)
{
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
goto bad;
}
@@ -541,29 +579,32 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
/*
* Traditional Adapter
*/
-
- p->buffer = (u_char *)malloc(PcapBufSize);
- if (p->buffer == NULL)
+ /*
+ * If the buffer size wasn't explicitly set, default to
+ * WIN32_DEFAULT_USER_BUFFER_SIZE.
+ */
+ if (p->opt.buffer_size == 0)
+ p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
+
+ if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE)
{
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
goto bad;
}
- PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
-
- p->snapshot = snaplen;
-
- /* allocate the standard buffer in the driver */
- if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
+ p->buffer = (u_char *)malloc(p->bufsize);
+ if (p->buffer == NULL)
{
- snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
goto bad;
}
+ PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
+
/* tell the driver to copy the buffer only if it contains at least 16K */
if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
{
- snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
goto bad;
}
}
@@ -582,7 +623,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
"SYSTEM\\CurrentControlSet\\Services\\DAG",
- strstr(_strlwr((char*)device), "dag"));
+ strstr(_strlwr(p->opt.source), "dag"));
do
{
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
@@ -616,7 +657,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
goto bad;
#endif /* HAVE_DAG_API */
- PacketSetReadTimeout(p->adapter, to_ms);
+ PacketSetReadTimeout(p->adapter, p->md.timeout);
#ifdef HAVE_DAG_API
if(p->adapter->Flags & INFO_FLAG_DAG_CARD)
@@ -641,25 +682,60 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
p->getnonblock_op = pcap_getnonblock_win32;
p->setnonblock_op = pcap_setnonblock_win32;
p->stats_op = pcap_stats_win32;
- p->close_op = pcap_close_win32;
+ p->setbuff_op = pcap_setbuff_win32;
+ p->setmode_op = pcap_setmode_win32;
+ p->setmintocopy_op = pcap_setmintocopy_win32;
+ p->cleanup_op = pcap_cleanup_win32;
- return (p);
+ return (0);
bad:
- if (p->adapter)
- PacketCloseAdapter(p->adapter);
- if (p->buffer != NULL)
- free(p->buffer);
- if(p->Packet)
- PacketFreePacket(p->Packet);
- /*
- * Get rid of any link-layer type list we allocated.
- */
- if (p->dlt_list != NULL)
- free(p->dlt_list);
- free(p);
- return (NULL);
+ pcap_cleanup_win32(p);
+ return (PCAP_ERROR);
}
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ if (strlen(device) == 1)
+ {
+ /*
+ * It's probably a unicode string
+ * Convert to ascii and pass it to pcap_create_common
+ *
+ * This wonderful hack is needed because pcap_lookupdev still returns
+ * unicode strings, and it's used by windump when no device is specified
+ * in the command line
+ */
+ size_t length;
+ char* deviceAscii;
+
+ length = wcslen((wchar_t*)device);
+
+ deviceAscii = (char*)malloc(length + 1);
+
+ if (deviceAscii == NULL)
+ {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "Malloc failed");
+ return NULL;
+ }
+
+ snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device);
+ p = pcap_create_common(deviceAscii, ebuf);
+ free(deviceAscii);
+ }
+ else
+ {
+ p = pcap_create_common(device, ebuf);
+ }
+
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_win32;
+ return (p);
+}
static int
pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp)
@@ -736,7 +812,7 @@ pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
* (Note that this may be -1, in which case we're not
* really leaving non-blocking mode.)
*/
- newtimeout = p->timeout;
+ newtimeout = p->md.timeout;
}
if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
@@ -747,57 +823,9 @@ pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
return (0);
}
-/* Set the driver working mode */
-int
-pcap_setmode(pcap_t *p, int mode){
-
- if (p->adapter==NULL)
- {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file");
- return -1;
- }
-
- if(PacketSetMode(p->adapter,mode)==FALSE)
- {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
- return -1;
- }
-
- return 0;
-}
-
-/* Set the dimension of the kernel-level capture buffer */
-int
-pcap_setbuff(pcap_t *p, int dim)
+/*platform-dependent routine to add devices other than NDIS interfaces*/
+int
+pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
- if (p->adapter==NULL)
- {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file");
- return -1;
- }
-
- if(PacketSetBuff(p->adapter,dim)==FALSE)
- {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
- return -1;
- }
- return 0;
-}
-
-/*set the minimum amount of data that will release a read call*/
-int
-pcap_setmintocopy(pcap_t *p, int size)
-{
- if (p->adapter==NULL)
- {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture");
- return -1;
- }
-
- if(PacketSetMinToCopy(p->adapter, size)==FALSE)
- {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
- return -1;
- }
- return 0;
+ return (0);
}
diff --git a/contrib/libpcap/pcap.3 b/contrib/libpcap/pcap.3
deleted file mode 100644
index 14b9368..0000000
--- a/contrib/libpcap/pcap.3
+++ /dev/null
@@ -1,1332 +0,0 @@
-.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3,v 1.64.2.11 2007/06/11 09:52:05 guy Exp $
-.\"
-.\" Copyright (c) 1994, 1996, 1997
-.\" 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: (1) source code distributions
-.\" retain the above copyright notice and this paragraph in its entirety, (2)
-.\" distributions including binary code include the above copyright notice and
-.\" this paragraph in its entirety in the documentation or other materials
-.\" provided with the distribution, and (3) all advertising materials mentioning
-.\" features or use of this software display the following acknowledgement:
-.\" ``This product includes software developed by the University of California,
-.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
-.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
-.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-.\"
-.\" $FreeBSD$
-.\"
-.TH PCAP 3 "27 February 2004"
-.SH NAME
-pcap \- Packet Capture library
-.SH SYNOPSIS
-.nf
-.ft B
-#include <pcap.h>
-.ft
-.LP
-.nf
-.ft B
-char errbuf[PCAP_ERRBUF_SIZE];
-.ft
-.LP
-.ft B
-pcap_t *pcap_open_live(const char *device, int snaplen,
-.ti +8
-int promisc, int to_ms, char *errbuf)
-pcap_t *pcap_open_dead(int linktype, int snaplen)
-pcap_t *pcap_open_offline(const char *fname, char *errbuf)
-pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf)
-pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname)
-pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp)
-.ft
-.LP
-.ft B
-int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf);
-int pcap_getnonblock(pcap_t *p, char *errbuf);
-.ft
-.LP
-.ft B
-int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
-void pcap_freealldevs(pcap_if_t *alldevs)
-char *pcap_lookupdev(char *errbuf)
-int pcap_lookupnet(const char *device, bpf_u_int32 *netp,
-.ti +8
-bpf_u_int32 *maskp, char *errbuf)
-.ft
-.LP
-.ft B
-typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h,
-.ti +8
- const u_char *bytes);
-.ft B
-int pcap_dispatch(pcap_t *p, int cnt,
-.ti +8
-pcap_handler callback, u_char *user)
-int pcap_loop(pcap_t *p, int cnt,
-.ti +8
-pcap_handler callback, u_char *user)
-void pcap_dump(u_char *user, struct pcap_pkthdr *h,
-.ti +8
-u_char *sp)
-.ft
-.LP
-.ft B
-int pcap_compile(pcap_t *p, struct bpf_program *fp,
-.ti +8
-const char *str, int optimize, bpf_u_int32 netmask)
-int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
-void pcap_freecode(struct bpf_program *)
-int pcap_setdirection(pcap_t *p, pcap_direction_t d)
-.ft
-.LP
-.ft B
-const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
-int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
-.ti +8
-const u_char **pkt_data)
-.ft
-.LP
-.ft B
-void pcap_breakloop(pcap_t *)
-.ft
-.LP
-.ft B
-int pcap_inject(pcap_t *p, const void *buf, size_t size)
-int pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
-.ft
-.LP
-.ft B
-int pcap_datalink(pcap_t *p)
-int pcap_list_datalinks(pcap_t *p, int **dlt_buf);
-int pcap_set_datalink(pcap_t *p, int dlt);
-int pcap_datalink_name_to_val(const char *name);
-const char *pcap_datalink_val_to_name(int dlt);
-const char *pcap_datalink_val_to_description(int dlt);
-int pcap_snapshot(pcap_t *p)
-int pcap_is_swapped(pcap_t *p)
-int pcap_major_version(pcap_t *p)
-int pcap_minor_version(pcap_t *p)
-int pcap_stats(pcap_t *p, struct pcap_stat *ps)
-FILE *pcap_file(pcap_t *p)
-int pcap_fileno(pcap_t *p)
-int pcap_get_selectable_fd(pcap_t *p);
-void pcap_perror(pcap_t *p, char *prefix)
-char *pcap_geterr(pcap_t *p)
-const char *pcap_strerror(int error)
-const char *pcap_lib_version(void)
-.ft
-.LP
-.ft B
-void pcap_close(pcap_t *p)
-int pcap_dump_flush(pcap_dumper_t *p)
-long pcap_dump_ftell(pcap_dumper_t *p)
-FILE *pcap_dump_file(pcap_dumper_t *p)
-void pcap_dump_close(pcap_dumper_t *p)
-.ft
-.fi
-.SH DESCRIPTION
-The Packet Capture library
-provides a high level interface to packet capture systems. All packets
-on the network, even those destined for other hosts, are accessible
-through this mechanism.
-.PP
-.SH ROUTINES
-NOTE:
-.I errbuf
-in
-.BR pcap_open_live() ,
-.BR pcap_open_dead() ,
-.BR pcap_open_offline() ,
-.BR pcap_fopen_offline() ,
-.BR pcap_setnonblock() ,
-.BR pcap_getnonblock() ,
-.BR pcap_findalldevs() ,
-.BR pcap_lookupdev() ,
-and
-.B pcap_lookupnet()
-is assumed to be able to hold at least
-.B PCAP_ERRBUF_SIZE
-chars.
-.PP
-.B pcap_open_live()
-is used to obtain a packet capture descriptor to look
-at packets on the network.
-.I device
-is a string that specifies the network device to open; on Linux systems
-with 2.2 or later kernels, a
-.I device
-argument of "any" or
-.B NULL
-can be used to capture packets from all interfaces.
-.I snaplen
-specifies the maximum number of bytes to capture. If this value is less
-than the size of a packet that is captured, only the first
-.I snaplen
-bytes of that packet will be captured and provided as packet data. A
-value of 65535 should be sufficient, on most if not all networks, to
-capture all the data available from the packet.
-.I promisc
-specifies if the interface is to be put into promiscuous mode.
-(Note that even if this parameter is false, the interface
-could well be in promiscuous mode for some other reason.) For now, this
-doesn't work on the "any" device; if an argument of "any" or NULL is
-supplied, the
-.I promisc
-flag is ignored.
-.I to_ms
-specifies the read timeout in milliseconds. The read timeout is used to
-arrange that the read not necessarily return immediately when a packet
-is seen, but that it wait for some amount of time to allow more packets
-to arrive and to read multiple packets from the OS kernel in one
-operation. Not all platforms support a read timeout; on platforms that
-don't, the read timeout is ignored. A zero value for
-.IR to_ms ,
-on platforms that support a read timeout,
-will cause a read to wait forever to allow enough packets to
-arrive, with no timeout.
-.I errbuf
-is used to return error or warning text. It will be set to error text when
-.B pcap_open_live()
-fails and returns
-.BR NULL .
-.I errbuf
-may also be set to warning text when
-.B pcap_open_live()
-succeds; to detect this case the caller should store a zero-length string in
-.I errbuf
-before calling
-.B pcap_open_live()
-and display the warning to the user if
-.I errbuf
-is no longer a zero-length string.
-.PP
-.B pcap_open_dead()
-is used for creating a
-.B pcap_t
-structure to use when calling the other functions in libpcap. It is
-typically used when just using libpcap for compiling BPF code.
-.PP
-.B pcap_open_offline()
-is called to open a ``savefile'' for reading.
-.I fname
-specifies the name of the file to open. The file has
-the same format as those used by
-.B tcpdump(1)
-and
-.BR tcpslice(1) .
-The name "-" in a synonym for
-.BR stdin .
-Alternatively, you may call
-.B pcap_fopen_offline()
-to read dumped data from an existing open stream
-.IR fp .
-Note that on Windows, that stream should be opened in binary mode.
-.I errbuf
-is used to return error text and is only set when
-.B pcap_open_offline()
-or
-.B pcap_fopen_offline()
-fails and returns
-.BR NULL .
-.PP
-.B pcap_dump_open()
-is called to open a ``savefile'' for writing. The name "-" in a synonym
-for
-.BR stdout .
-.B NULL
-is returned on failure.
-.I p
-is a
-.I pcap
-struct as returned by
-.B pcap_open_offline()
-or
-.BR pcap_open_live() .
-.I fname
-specifies the name of the file to open. Alternatively, you may call
-.B pcap_dump_fopen()
-to write data to an existing open stream
-.IR fp .
-Note that on Windows, that stream should be opened in binary mode.
-If
-.B NULL
-is returned,
-.B pcap_geterr()
-can be used to get the error text.
-.PP
-.PP
-.B pcap_setnonblock()
-puts a capture descriptor, opened with
-.BR pcap_open_live() ,
-into ``non-blocking'' mode, or takes it out of ``non-blocking'' mode,
-depending on whether the
-.I nonblock
-argument is non-zero or zero. It has no effect on ``savefiles''.
-If there is an error, \-1 is returned and
-.I errbuf
-is filled in with an appropriate error message; otherwise, 0 is
-returned.
-In
-``non-blocking'' mode, an attempt to read from the capture descriptor
-with
-.B pcap_dispatch()
-will, if no packets are currently available to be read, return 0
-immediately rather than blocking waiting for packets to arrive.
-.B pcap_loop()
-and
-.B pcap_next()
-will not work in ``non-blocking'' mode.
-.PP
-.B pcap_getnonblock()
-returns the current ``non-blocking'' state of the capture descriptor; it
-always returns 0 on ``savefiles''.
-If there is an error, \-1 is returned and
-.I errbuf
-is filled in with an appropriate error message.
-.PP
-.B pcap_findalldevs()
-constructs a list of network devices that can be opened with
-.BR pcap_open_live() .
-(Note that there may be network devices that cannot be opened with
-.BR pcap_open_live()
-by the
-process calling
-.BR pcap_findalldevs() ,
-because, for example, that process might not have sufficient privileges
-to open them for capturing; if so, those devices will not appear on the
-list.)
-.I alldevsp
-is set to point to the first element of the list; each element of the
-list is of type
-.BR pcap_if_t ,
-and has the following members:
-.RS
-.TP
-.B next
-if not
-.BR NULL ,
-a pointer to the next element in the list;
-.B NULL
-for the last element of the list
-.TP
-.B name
-a pointer to a string giving a name for the device to pass to
-.B pcap_open_live()
-.TP
-.B description
-if not
-.BR NULL ,
-a pointer to a string giving a human-readable description of the device
-.TP
-.B addresses
-a pointer to the first element of a list of addresses for the interface
-.TP
-.B flags
-interface flags:
-.RS
-.TP
-.B PCAP_IF_LOOPBACK
-set if the interface is a loopback interface
-.RE
-.RE
-.PP
-Each element of the list of addresses is of type
-.BR pcap_addr_t ,
-and has the following members:
-.RS
-.TP
-.B next
-if not
-.BR NULL ,
-a pointer to the next element in the list;
-.B NULL
-for the last element of the list
-.TP
-.B addr
-a pointer to a
-.B "struct sockaddr"
-containing an address
-.TP
-.B netmask
-if not
-.BR NULL ,
-a pointer to a
-.B "struct sockaddr"
-that contains the netmask corresponding to the address pointed to by
-.B addr
-.TP
-.B broadaddr
-if not
-.BR NULL ,
-a pointer to a
-.B "struct sockaddr"
-that contains the broadcast address corresponding to the address pointed
-to by
-.BR addr ;
-may be null if the interface doesn't support broadcasts
-.TP
-.B dstaddr
-if not
-.BR NULL ,
-a pointer to a
-.B "struct sockaddr"
-that contains the destination address corresponding to the address pointed
-to by
-.BR addr ;
-may be null if the interface isn't a point-to-point interface
-.RE
-.PP
-Note that not all the addresses in the list of addresses are
-necessarily IPv4 or IPv6 addresses - you must check the
-.B sa_family
-member of the
-.B "struct sockaddr"
-before interpreting the contents of the address.
-.PP
-.B \-1
-is returned on failure, in which case
-.B errbuf
-is filled in with an appropriate error message;
-.B 0
-is returned on success.
-.PP
-.B pcap_freealldevs()
-is used to free a list allocated by
-.BR pcap_findalldevs() .
-.PP
-.B pcap_lookupdev()
-returns a pointer to a network device suitable for use with
-.B pcap_open_live()
-and
-.BR pcap_lookupnet() .
-If there is an error,
-.B NULL
-is returned and
-.I errbuf
-is filled in with an appropriate error message.
-.PP
-.B pcap_lookupnet()
-is used to determine the network number and mask
-associated with the network device
-.BR device .
-Both
-.I netp
-and
-.I maskp
-are
-.I bpf_u_int32
-pointers.
-A return of \-1 indicates an error in which case
-.I errbuf
-is filled in with an appropriate error message.
-.PP
-.B pcap_dispatch()
-is used to collect and process packets.
-.I cnt
-specifies the maximum number of packets to process before returning.
-This is not a minimum number; when reading a live capture, only one
-bufferful of packets is read at a time, so fewer than
-.I cnt
-packets may be processed. A
-.I cnt
-of \-1 processes all the packets received in one buffer when reading a
-live capture, or all the packets in the file when reading a
-``savefile''.
-.I callback
-specifies a routine to be called with three arguments:
-a
-.I u_char
-pointer which is passed in from
-.BR pcap_dispatch() ,
-a
-.I const struct pcap_pkthdr
-pointer to a structure with the following members:
-.RS
-.TP
-.B ts
-a
-.I struct timeval
-containing the time when the packet was captured
-.TP
-.B caplen
-a
-.I bpf_u_int32
-giving the number of bytes of the packet that are available from the
-capture
-.TP
-.B len
-a
-.I bpf_u_int32
-giving the length of the packet, in bytes (which might be more than the
-number of bytes available from the capture, if the length of the packet
-is larger than the maximum number of bytes to capture)
-.RE
-.PP
-and a
-.I const u_char
-pointer to the first
-.B caplen
-(as given in the
-.I struct pcap_pkthdr
-a pointer to which is passed to the callback routine)
-bytes of data from the packet (which won't necessarily be the entire
-packet; to capture the entire packet, you will have to provide a value
-for
-.I snaplen
-in your call to
-.B pcap_open_live()
-that is sufficiently large to get all of the packet's data - a value of
-65535 should be sufficient on most if not all networks).
-.PP
-The number of packets read is returned.
-0 is returned if no packets were read from a live capture (if, for
-example, they were discarded because they didn't pass the packet filter,
-or if, on platforms that support a read timeout that starts before any
-packets arrive, the timeout expires before any packets arrive, or if the
-file descriptor for the capture device is in non-blocking mode and no
-packets were available to be read) or if no more packets are available
-in a ``savefile.'' A return of \-1 indicates
-an error in which case
-.B pcap_perror()
-or
-.B pcap_geterr()
-may be used to display the error text.
-A return of \-2 indicates that the loop terminated due to a call to
-.B pcap_breakloop()
-before any packets were processed.
-.ft B
-If your application uses pcap_breakloop(),
-make sure that you explicitly check for \-1 and \-2, rather than just
-checking for a return value < 0.
-.ft R
-.PP
-.BR NOTE :
-when reading a live capture,
-.B pcap_dispatch()
-will not necessarily return when the read times out; on some platforms,
-the read timeout isn't supported, and, on other platforms, the timer
-doesn't start until at least one packet arrives. This means that the
-read timeout should
-.B NOT
-be used in, for example, an interactive application, to allow the packet
-capture loop to ``poll'' for user input periodically, as there's no
-guarantee that
-.B pcap_dispatch()
-will return after the timeout expires.
-.PP
-.B pcap_loop()
-is similar to
-.B pcap_dispatch()
-except it keeps reading packets until
-.I cnt
-packets are processed or an error occurs.
-It does
-.B not
-return when live read timeouts occur.
-Rather, specifying a non-zero read timeout to
-.B pcap_open_live()
-and then calling
-.B pcap_dispatch()
-allows the reception and processing of any packets that arrive when the
-timeout occurs.
-A negative
-.I cnt
-causes
-.B pcap_loop()
-to loop forever (or at least until an error occurs). \-1 is returned on
-an error; 0 is returned if
-.I cnt
-is exhausted; \-2 is returned if the loop terminated due to a call to
-.B pcap_breakloop()
-before any packets were processed.
-.ft B
-If your application uses pcap_breakloop(),
-make sure that you explicitly check for \-1 and \-2, rather than just
-checking for a return value < 0.
-.ft R
-.PP
-.B pcap_next()
-reads the next packet (by calling
-.B pcap_dispatch()
-with a
-.I cnt
-of 1) and returns a
-.I u_char
-pointer to the data in that packet. (The
-.I pcap_pkthdr
-struct for that packet is not supplied.)
-.B NULL
-is returned if an error occured, or if no packets were read from a live
-capture (if, for example, they were discarded because they didn't pass
-the packet filter, or if, on platforms that support a read timeout that
-starts before any packets arrive, the timeout expires before any packets
-arrive, or if the file descriptor for the capture device is in
-non-blocking mode and no packets were available to be read), or if no
-more packets are available in a ``savefile.'' Unfortunately, there is
-no way to determine whether an error occured or not.
-.PP
-.B pcap_next_ex()
-reads the next packet and returns a success/failure indication:
-.RS
-.TP
-1
-the packet was read without problems
-.TP
-0
-packets are being read from a live capture, and the timeout expired
-.TP
-\-1
-an error occurred while reading the packet
-.TP
-\-2
-packets are being read from a ``savefile'', and there are no more
-packets to read from the savefile.
-.RE
-.PP
-If the packet was read without problems, the pointer pointed to by the
-.I pkt_header
-argument is set to point to the
-.I pcap_pkthdr
-struct for the packet, and the
-pointer pointed to by the
-.I pkt_data
-argument is set to point to the data in the packet.
-.PP
-.B pcap_breakloop()
-sets a flag that will force
-.B pcap_dispatch()
-or
-.B pcap_loop()
-to return rather than looping; they will return the number of packets
-that have been processed so far, or \-2 if no packets have been
-processed so far.
-.PP
-This routine is safe to use inside a signal handler on UNIX or a console
-control handler on Windows, as it merely sets a flag that is checked
-within the loop.
-.PP
-The flag is checked in loops reading packets from the OS - a signal by
-itself will not necessarily terminate those loops - as well as in loops
-processing a set of packets returned by the OS.
-.ft B
-Note that if you are catching signals on UNIX systems that support
-restarting system calls after a signal, and calling pcap_breakloop()
-in the signal handler, you must specify, when catching those signals,
-that system calls should NOT be restarted by that signal. Otherwise,
-if the signal interrupted a call reading packets in a live capture,
-when your signal handler returns after calling pcap_breakloop(), the
-call will be restarted, and the loop will not terminate until more
-packets arrive and the call completes.
-.PP
-Note also that, in a multi-threaded application, if one thread is
-blocked in
-.BR pcap_dispatch() ,
-.BR pcap_loop() ,
-.BR pcap_next() ,
-or
-.BR pcap_next_ex() ,
-a call to
-.B pcap_breakloop()
-in a different thread will not unblock that thread; you will need to use
-whatever mechanism the OS provides for breaking a thread out of blocking
-calls in order to unblock the thread, such as thread cancellation in
-systems that support POSIX threads.
-.ft R
-.PP
-Note that
-.B pcap_next()
-will, on some platforms, loop reading packets from the OS; that loop
-will not necessarily be terminated by a signal, so
-.B pcap_breakloop()
-should be used to terminate packet processing even if
-.B pcap_next()
-is being used.
-.PP
-.B pcap_breakloop()
-does not guarantee that no further packets will be processed by
-.B pcap_dispatch()
-or
-.B pcap_loop()
-after it is called; at most one more packet might be processed.
-.PP
-If \-2 is returned from
-.B pcap_dispatch()
-or
-.BR pcap_loop() ,
-the flag is cleared, so a subsequent call will resume reading packets.
-If a positive number is returned, the flag is not cleared, so a
-subsequent call will return \-2 and clear the flag.
-.PP
-.B pcap_inject()
-sends a raw packet through the network interface;
-.I buf
-points to the data of the packet, including the link-layer header, and
-.I size
-is the number of bytes in the packet.
-It returns the number of bytes written on success. A return of \-1
-indicates an error in which case
-.B pcap_perror()
-or
-.B pcap_geterr()
-may be used to display the error text.
-Note that, even if you successfully open the network interface, you
-might not have permission to send packets on it, or it might not support
-sending packets; as
-.I pcap_open_live()
-doesn't have a flag to indicate whether to open for capturing, sending,
-or capturing and sending, you cannot request an open that supports
-sending and be notified at open time whether sending will be possible.
-Note also that some devices might not support sending packets.
-.PP
-Note that, on some platforms, the link-layer header of the packet that's
-sent might not be the same as the link-layer header of the packet
-supplied to
-.BR pcap_inject() ,
-as the source link-layer address, if the header contains such an
-address, might be changed to be the address assigned to the interface on
-which the packet it sent, if the platform doesn't support sending
-completely raw and unchanged packets. Even worse, some drivers on some
-platforms might change the link-layer type field to whatever value
-libpcap used when attaching to the device, even on platforms that
-.I do
-nominally support sending completely raw and unchanged packets.
-.PP
-.B pcap_sendpacket()
-is like
-.BR pcap_inject() ,
-but it returns 0 on success and \-1 on failure.
-.RB ( pcap_inject()
-comes from OpenBSD;
-.B pcap_sendpacket()
-comes from WinPcap. Both are provided for compatibility.)
-.PP
-.B pcap_dump()
-outputs a packet to the ``savefile'' opened with
-.BR pcap_dump_open() .
-Note that its calling arguments are suitable for use with
-.B pcap_dispatch()
-or
-.BR pcap_loop() .
-If called directly, the
-.I user
-parameter is of type
-.I pcap_dumper_t
-as returned by
-.BR pcap_dump_open() .
-.PP
-.B pcap_compile()
-is used to compile the string
-.I str
-into a filter program.
-.I program
-is a pointer to a
-.I bpf_program
-struct and is filled in by
-.BR pcap_compile() .
-.I optimize
-controls whether optimization on the resulting code is performed.
-.I netmask
-specifies the IPv4 netmask of the network on which packets are being
-captured; it is used only when checking for IPv4 broadcast addresses in
-the filter program. If the netmask of the network on which packets are
-being captured isn't known to the program, or if packets are being
-captured on the Linux "any" pseudo-interface that can capture on more
-than one network, a value of 0 can be supplied; tests for IPv4 broadcast
-addreses won't be done correctly, but all other tests in the filter
-program will be OK. A return of \-1 indicates an error in which case
-.BR pcap_geterr()
-may be used to display the error text.
-.PP
-.B pcap_compile_nopcap()
-is similar to
-.B pcap_compile()
-except that instead of passing a pcap structure, one passes the
-snaplen and linktype explicitly. It is intended to be used for
-compiling filters for direct BPF usage, without necessarily having
-called
-.BR pcap_open() .
-A return of \-1 indicates an error; the error text is unavailable.
-.RB ( pcap_compile_nopcap()
-is a wrapper around
-.BR pcap_open_dead() ,
-.BR pcap_compile() ,
-and
-.BR pcap_close() ;
-the latter three routines can be used directly in order to get the error
-text for a compilation error.)
-.B
-.PP
-.B pcap_setfilter()
-is used to specify a filter program.
-.I fp
-is a pointer to a
-.I bpf_program
-struct, usually the result of a call to
-.BR pcap_compile() .
-.B \-1
-is returned on failure, in which case
-.BR pcap_geterr()
-may be used to display the error text;
-.B 0
-is returned on success.
-.PP
-.B pcap_freecode()
-is used to free up allocated memory pointed to by a
-.I bpf_program
-struct generated by
-.B pcap_compile()
-when that BPF program is no longer needed, for example after it
-has been made the filter program for a pcap structure by a call to
-.BR pcap_setfilter() .
-.PP
-.B pcap_setdirection()
-is used to specify a direction that packets will be captured.
-.I pcap_direction_t
-is one of the constants
-.BR PCAP_D_IN ,
-.B PCAP_D_OUT
-or
-.BR PCAP_D_INOUT .
-.B PCAP_D_IN
-will only capture packets received by the device,
-.B PCAP_D_OUT
-will only capture packets sent by the device and
-.B PCAP_D_INOUT
-will capture packets received by or sent by the device.
-.B PCAP_D_INOUT
-is the default setting if this function is not called. This isn't
-necessarily supported on all platforms; some platforms might return an
-error, and some other platforms might not support
-.BR PCAP_D_OUT .
-This operation is not supported if a ``savefile'' is being read.
-.B \-1
-is returned on failure,
-.B 0
-is returned on success.
-.PP
-.B pcap_datalink()
-returns the link layer type; link layer types it can return include:
-.PP
-.RS 5
-.TP 5
-.B DLT_NULL
-BSD loopback encapsulation; the link layer header is a 4-byte field, in
-.I host
-byte order, containing a PF_ value from
-.B socket.h
-for the network-layer protocol of the packet.
-.IP
-Note that ``host byte order'' is the byte order of the machine on which
-the packets are captured, and the PF_ values are for the OS of the
-machine on which the packets are captured; if a live capture is being
-done, ``host byte order'' is the byte order of the machine capturing the
-packets, and the PF_ values are those of the OS of the machine capturing
-the packets, but if a ``savefile'' is being read, the byte order and PF_
-values are
-.I not
-necessarily those of the machine reading the capture file.
-.TP 5
-.B DLT_EN10MB
-Ethernet (10Mb, 100Mb, 1000Mb, and up)
-.TP 5
-.B DLT_IEEE802
-IEEE 802.5 Token Ring
-.TP 5
-.B DLT_ARCNET
-ARCNET
-.TP 5
-.B DLT_SLIP
-SLIP; the link layer header contains, in order:
-.RS 10
-.LP
-a 1-byte flag, which is 0 for packets received by the machine and 1 for
-packets sent by the machine;
-.LP
-a 1-byte field, the upper 4 bits of which indicate the type of packet,
-as per RFC 1144:
-.RS 5
-.TP 5
-0x40
-an unmodified IP datagram (TYPE_IP);
-.TP 5
-0x70
-an uncompressed-TCP IP datagram (UNCOMPRESSED_TCP), with that byte being
-the first byte of the raw IP header on the wire, containing the
-connection number in the protocol field;
-.TP 5
-0x80
-a compressed-TCP IP datagram (COMPRESSED_TCP), with that byte being the
-first byte of the compressed TCP/IP datagram header;
-.RE
-.LP
-for UNCOMPRESSED_TCP, the rest of the modified IP header, and for
-COMPRESSED_TCP, the compressed TCP/IP datagram header;
-.RE
-.RS 5
-.LP
-for a total of 16 bytes; the uncompressed IP datagram follows the header.
-.RE
-.TP 5
-.B DLT_PPP
-PPP; if the first 2 bytes are 0xff and 0x03, it's PPP in HDLC-like
-framing, with the PPP header following those two bytes, otherwise it's
-PPP without framing, and the packet begins with the PPP header.
-.TP 5
-.B DLT_FDDI
-FDDI
-.TP 5
-.B DLT_ATM_RFC1483
-RFC 1483 LLC/SNAP-encapsulated ATM; the packet begins with an IEEE 802.2
-LLC header.
-.TP 5
-.B DLT_RAW
-raw IP; the packet begins with an IP header.
-.TP 5
-.B DLT_PPP_SERIAL
-PPP in HDLC-like framing, as per RFC 1662, or Cisco PPP with HDLC
-framing, as per section 4.3.1 of RFC 1547; the first byte will be 0xFF
-for PPP in HDLC-like framing, and will be 0x0F or 0x8F for Cisco PPP
-with HDLC framing.
-.TP 5
-.B DLT_PPP_ETHER
-PPPoE; the packet begins with a PPPoE header, as per RFC 2516.
-.TP 5
-.B DLT_C_HDLC
-Cisco PPP with HDLC framing, as per section 4.3.1 of RFC 1547.
-.TP 5
-.B DLT_IEEE802_11
-IEEE 802.11 wireless LAN
-.TP 5
-.B DLT_FRELAY
-Frame Relay
-.TP 5
-.B DLT_LOOP
-OpenBSD loopback encapsulation; the link layer header is a 4-byte field, in
-.I network
-byte order, containing a PF_ value from OpenBSD's
-.B socket.h
-for the network-layer protocol of the packet.
-.IP
-Note that, if a ``savefile'' is being read, those PF_ values are
-.I not
-necessarily those of the machine reading the capture file.
-.TP 5
-.B DLT_LINUX_SLL
-Linux "cooked" capture encapsulation; the link layer header contains, in
-order:
-.RS 10
-.LP
-a 2-byte "packet type", in network byte order, which is one of:
-.RS 5
-.TP 5
-0
-packet was sent to us by somebody else
-.TP 5
-1
-packet was broadcast by somebody else
-.TP 5
-2
-packet was multicast, but not broadcast, by somebody else
-.TP 5
-3
-packet was sent by somebody else to somebody else
-.TP 5
-4
-packet was sent by us
-.RE
-.LP
-a 2-byte field, in network byte order, containing a Linux ARPHRD_ value
-for the link layer device type;
-.LP
-a 2-byte field, in network byte order, containing the length of the
-link layer address of the sender of the packet (which could be 0);
-.LP
-an 8-byte field containing that number of bytes of the link layer header
-(if there are more than 8 bytes, only the first 8 are present);
-.LP
-a 2-byte field containing an Ethernet protocol type, in network byte
-order, or containing 1 for Novell 802.3 frames without an 802.2 LLC
-header or 4 for frames beginning with an 802.2 LLC header.
-.RE
-.TP 5
-.B DLT_LTALK
-Apple LocalTalk; the packet begins with an AppleTalk LLAP header.
-.TP 5
-.B DLT_PFLOG
-OpenBSD pflog; the link layer header contains, in order:
-.RS 10
-.LP
-a 1-byte header length, in host byte order;
-.LP
-a 4-byte PF_ value, in host byte order;
-.LP
-a 2-byte action code, in network byte order, which is one of:
-.RS 5
-.TP 5
-0
-passed
-.TP 5
-1
-dropped
-.TP 5
-2
-scrubbed
-.RE
-.LP
-a 2-byte reason code, in network byte order, which is one of:
-.RS 5
-.TP 5
-0
-match
-.TP 5
-1
-bad offset
-.TP 5
-2
-fragment
-.TP 5
-3
-short
-.TP 5
-4
-normalize
-.TP 5
-5
-memory
-.RE
-.LP
-a 16-character interface name;
-.LP
-a 16-character ruleset name (only meaningful if subrule is set);
-.LP
-a 4-byte rule number, in network byte order;
-.LP
-a 4-byte subrule number, in network byte order;
-.LP
-a 1-byte direction, in network byte order, which is one of:
-.RS 5
-.TP 5
-0
-incoming or outgoing
-.TP 5
-1
-incoming
-.TP 5
-2
-outgoing
-.RE
-.RE
-.TP 5
-.B DLT_PRISM_HEADER
-Prism monitor mode information followed by an 802.11 header.
-.TP 5
-.B DLT_IP_OVER_FC
-RFC 2625 IP-over-Fibre Channel, with the link-layer header being the
-Network_Header as described in that RFC.
-.TP 5
-.B DLT_SUNATM
-SunATM devices; the link layer header contains, in order:
-.RS 10
-.LP
-a 1-byte flag field, containing a direction flag in the uppermost bit,
-which is set for packets transmitted by the machine and clear for
-packets received by the machine, and a 4-byte traffic type in the
-low-order 4 bits, which is one of:
-.RS 5
-.TP 5
-0
-raw traffic
-.TP 5
-1
-LANE traffic
-.TP 5
-2
-LLC-encapsulated traffic
-.TP 5
-3
-MARS traffic
-.TP 5
-4
-IFMP traffic
-.TP 5
-5
-ILMI traffic
-.TP 5
-6
-Q.2931 traffic
-.RE
-.LP
-a 1-byte VPI value;
-.LP
-a 2-byte VCI field, in network byte order.
-.RE
-.TP 5
-.B DLT_IEEE802_11_RADIO
-link-layer information followed by an 802.11 header - see
-http://www.shaftnet.org/~pizza/software/capturefrm.txt for a description
-of the link-layer information.
-.TP 5
-.B DLT_ARCNET_LINUX
-ARCNET, with no exception frames, reassembled packets rather than raw
-frames, and an extra 16-bit offset field between the destination host
-and type bytes.
-.TP 5
-.B DLT_LINUX_IRDA
-Linux-IrDA packets, with a
-.B DLT_LINUX_SLL
-header followed by the IrLAP header.
-.TP 5
-.B DLT_LINUX_LAPD
-LAPD (Q.921) frames, with a
-.B DLT_LINUX_SLL
-header captured via vISDN.
-.RE
-.PP
-.B pcap_list_datalinks()
-is used to get a list of the supported data link types of the interface
-associated with the pcap descriptor.
-.B pcap_list_datalinks()
-allocates an array to hold the list and sets
-.IR *dlt_buf .
-The caller is responsible for freeing the array.
-.B \-1
-is returned on failure;
-otherwise, the number of data link types in the array is returned.
-.PP
-.B pcap_set_datalink()
-is used to set the current data link type of the pcap descriptor
-to the type specified by
-.IR dlt .
-.B \-1
-is returned on failure.
-.PP
-.B pcap_datalink_name_to_val()
-translates a data link type name, which is a
-.B DLT_
-name with the
-.B DLT_
-removed, to the corresponding data link type value. The translation
-is case-insensitive.
-.B \-1
-is returned on failure.
-.PP
-.B pcap_datalink_val_to_name()
-translates a data link type value to the corresponding data link type
-name. NULL is returned on failure.
-.PP
-.B pcap_datalink_val_to_description()
-translates a data link type value to a short description of that data
-link type. NULL is returned on failure.
-.PP
-.B pcap_list_datalinks()
-is used to get a list of the supported data link types of the interface
-associated with the pcap descriptor.
-.B pcap_list_datalinks()
-allocates an array to hold the list and sets
-.IR *dlt_buf .
-The caller is responsible for freeing the array.
-.B \-1
-is returned on failure;
-otherwise, the number of data link types in the array is returned.
-.PP
-.B pcap_set_datalink()
-is used to set the current data link type of the pcap descriptor
-to the type specified by
-.IR dlt .
-.B \-1
-is returned on failure.
-.PP
-.B pcap_snapshot()
-returns the snapshot length specified when
-.B pcap_open_live()
-was called.
-.PP
-.B pcap_is_swapped()
-returns true if the current ``savefile'' uses a different byte order
-than the current system.
-.PP
-.B pcap_major_version()
-returns the major number of the file format of the savefile;
-.B pcap_minor_version()
-returns the minor number of the file format of the savefile. The
-version number is stored in the header of the savefile.
-.PP
-.B pcap_file()
-returns the standard I/O stream of the ``savefile,'' if a ``savefile''
-was opened with
-.BR pcap_open_offline() ,
-or NULL, if a network device was opened with
-.BR pcap_open_live() .
-.PP
-.B pcap_stats()
-returns 0 and fills in the
-.B pcap_stat
-structure pointed to by its second argument. The values represent
-packet statistics from the start of the run to the time of the call. If
-there is an error or the underlying packet capture doesn't support
-packet statistics, \-1 is returned and the error text can be obtained
-with
-.B pcap_perror()
-or
-.BR pcap_geterr() .
-.B pcap_stats()
-is supported only on live captures, not on ``savefiles''; no statistics
-are stored in ``savefiles'', so no statistics are available when reading
-from a ``savefile''.
-.PP
-.B pcap_fileno()
-returns the file descriptor number from which captured packets are read,
-if a network device was opened with
-.BR pcap_open_live() ,
-or \-1, if a ``savefile'' was opened with
-.BR pcap_open_offline() .
-.PP
-.B pcap_get_selectable_fd()
-returns, on UNIX, a file descriptor number for a file descriptor on
-which one can
-do a
-.B select()
-or
-.B poll()
-to wait for it to be possible to read packets without blocking, if such
-a descriptor exists, or \-1, if no such descriptor exists. Some network
-devices opened with
-.B pcap_open_live()
-do not support
-.B select()
-or
-.B poll()
-(for example, regular network devices on FreeBSD 4.3 and 4.4, and Endace
-DAG devices), so \-1 is returned for those devices.
-.PP
-Note that on most versions of most BSDs (including Mac OS X)
-.B select()
-and
-.B poll()
-do not work correctly on BPF devices;
-.B pcap_get_selectable_fd()
-will return a file descriptor on most of those versions (the exceptions
-being FreeBSD 4.3 and 4.4), a simple
-.B select()
-or
-.B poll()
-will not return even after a timeout specified in
-.B pcap_open_live()
-expires. To work around this, an application that uses
-.B select()
-or
-.B poll()
-to wait for packets to arrive must put the
-.B pcap_t
-in non-blocking mode, and must arrange that the
-.B select()
-or
-.B poll()
-have a timeout less than or equal to the timeout specified in
-.BR pcap_open_live() ,
-and must try to read packets after that timeout expires, regardless of
-whether
-.B select()
-or
-.B poll()
-indicated that the file descriptor for the
-.B pcap_t
-is ready to be read or not. (That workaround will not work in FreeBSD
-4.3 and later; however, in FreeBSD 4.6 and later,
-.B select()
-and
-.B poll()
-work correctly on BPF devices, so the workaround isn't necessary,
-although it does no harm.)
-.PP
-.B pcap_get_selectable_fd()
-is not available on Windows.
-.PP
-.B pcap_perror()
-prints the text of the last pcap library error on
-.BR stderr ,
-prefixed by
-.IR prefix .
-.PP
-.B pcap_geterr()
-returns the error text pertaining to the last pcap library error.
-.BR NOTE :
-the pointer it returns will no longer point to a valid error message
-string after the
-.B pcap_t
-passed to it is closed; you must use or copy the string before closing
-the
-.BR pcap_t .
-.PP
-.B pcap_strerror()
-is provided in case
-.BR strerror (1)
-isn't available.
-.PP
-.B pcap_lib_version()
-returns a pointer to a string giving information about the version of
-the libpcap library being used; note that it contains more information
-than just a version number.
-.PP
-.B pcap_close()
-closes the files associated with
-.I p
-and deallocates resources.
-.PP
-.B pcap_dump_file()
-returns the standard I/O stream of the ``savefile'' opened by
-.BR pcap_dump_open().
-.PP
-.B pcap_dump_flush()
-flushes the output buffer to the ``savefile,'' so that any packets
-written with
-.B pcap_dump()
-but not yet written to the ``savefile'' will be written.
-.B \-1
-is returned on error, 0 on success.
-.PP
-.B pcap_dump_ftell()
-returns the current file position for the ``savefile'', representing the
-number of bytes written by
-.B pcap_dump_open()
-and
-.BR pcap_dump() .
-.B \-1
-is returned on error.
-.PP
-.B pcap_dump_close()
-closes the ``savefile.''
-.PP
-.SH SEE ALSO
-tcpdump(1), tcpslice(1)
-.SH AUTHORS
-The original authors are:
-.LP
-Van Jacobson,
-Craig Leres and
-Steven McCanne, all of the
-Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
-.LP
-The current version is available from "The Tcpdump Group"'s Web site at
-.LP
-.RS
-.I http://www.tcpdump.org/
-.RE
-.SH BUGS
-Please send problems, bugs, questions, desirable enhancements, etc. to:
-.LP
-.RS
-tcpdump-workers@tcpdump.org
-.RE
-.LP
-Please send source code contributions, etc. to:
-.LP
-.RS
-patches@tcpdump.org
-.RE
diff --git a/contrib/libpcap/pcap.3pcap b/contrib/libpcap/pcap.3pcap
new file mode 100644
index 0000000..b694714
--- /dev/null
+++ b/contrib/libpcap/pcap.3pcap
@@ -0,0 +1,386 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP 3PCAP "4 April 2008"
+.SH NAME
+pcap \- Packet Capture library
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+.ft
+.fi
+.SH DESCRIPTION
+The Packet Capture library
+provides a high level interface to packet capture systems. All packets
+on the network, even those destined for other hosts, are accessible
+through this mechanism.
+It also supports saving captured packets to a ``savefile'', and reading
+packets from a ``savefile''.
+.PP
+To open a handle for a live capture, call
+.BR pcap_create() ,
+set the appropriate options on the handle, and then activate it with
+.BR pcap_activate() .
+To open a handle for a ``savefile'' with captured packets, call
+.BR pcap_open_offline() .
+Both
+.B pcap_create()
+and
+.B pcap_open_offline()
+return a pointer to a
+.BR pcap_t ,
+which is the handle used for reading packets from the capture stream or
+the ``savefile'', and for finding out information about the capture
+stream or ``savefile''.
+.PP
+The options that can be set on a capture handle include
+.IP "snapshot length"
+If, when capturing, you capture the entire contents of the packet, that
+requires more CPU time to copy the packet to your application, more disk
+and possibly network bandwidth to write the packet data to a file, and
+more disk space to save the packet. If you don't need the entire
+contents of the packet - for example, if you are only interested in the
+TCP headers of packets - you can set the "snapshot length" for the
+capture to an appropriate value. If the snapshot length is set to
+.IR snaplen ,
+and
+.I snaplen
+is less
+than the size of a packet that is captured, only the first
+.I snaplen
+bytes of that packet will be captured and provided as packet data.
+.IP
+A snapshot length of 65535 should be sufficient, on most if not all
+networks, to capture all the data available from the packet.
+.IP
+The snapshot length is set with
+.BR pcap_set_snaplen() .
+.IP "promiscuous mode"
+On broadcast LANs such as Ethernet, if the network isn't switched, or if
+the adapter is connected to a "mirror port" on a switch to which all
+packets passing through the switch are sent, a network adapter receives
+all packets on the LAN, including unicast or multicast packets not sent
+to a network address that the network adapter isn't configured to
+recognize.
+.IP
+Normally, the adapter will discard those packets; however, many network
+adapters support "promiscuous mode", which is a mode in which all
+packets, even if they are not sent to an address that the adapter
+recognizes, are provided to the host. This is useful for passively
+capturing traffic between two or more other hosts for analysis.
+.IP
+Note that even if an application does not set promiscuous mode, the
+adapter could well be in promiscuous mode for some other reason.
+.IP
+For now, this doesn't work on the "any" device; if an argument of "any"
+or NULL is supplied, the setting of promiscuous mode is ignored.
+.IP
+Promiscuous mode is set with
+.BR pcap_set_promisc() .
+.IP "monitor mode"
+On IEEE 802.11 wireless LANs, even if an adapter is in promiscuous mode,
+it will supply to the host only frames for the network with which it's
+associated. It might also supply only data frames, not management or
+control frames, and might not provide the 802.11 header or radio
+information pseudo-header for those frames.
+.IP
+In "monitor mode", sometimes also called "rfmon mode" (for "Radio
+Frequency MONitor"), the adapter will supply all frames that it
+receives, with 802.11 headers, and might supply a pseudo-header with
+radio information about the frame as well.
+.IP
+Note that in monitor mode the adapter might disassociate from the
+network with which it's associated, so that you will not be able to use
+any wireless networks with that adapter. This could prevent accessing
+files on a network server, or resolving host names or network addresses,
+if you are capturing in monitor mode and are not connected to another
+network with another adapter.
+.IP
+Monitor mode is set with
+.BR pcap_set_rfmon() ,
+and
+.B pcap_can_set_rfmon()
+can be used to determine whether an adapter can be put into monitor
+mode.
+.IP "read timeout"
+If, when capturing, packets are delivered as soon as they arrive, the
+application capturing the packets will be woken up for each packet as it
+arrives, and might have to make one or more calls to the operating
+system to fetch each packet.
+.IP
+If, instead, packets are not delivered as soon as they arrive, but are
+delivered after a short delay (called a "read timeout"), more than one
+packet can be accumulated before the packets are delivered, so that a
+single wakeup would be done for multiple packets, and each set of calls
+made to the operating system would supply multiple packets, rather than
+a single packet. This reduces the per-packet CPU overhead if packets
+are arriving at a high rate, increasing the number of packets per second
+that can be captured.
+.IP
+The read timeout is required so that an application won't wait for the
+operating system's capture buffer to fill up before packets are
+delivered; if packets are arriving slowly, that wait could take an
+arbitrarily long period of time.
+.IP
+Not all platforms support a read timeout; on platforms that
+don't, the read timeout is ignored. A zero value for the timeout,
+on platforms that support a read timeout,
+will cause a read to wait forever to allow enough packets to
+arrive, with no timeout.
+.IP
+.BR NOTE :
+the read timeout cannot be used to cause calls that read
+packets to return within a limited period of time, because, on some
+platforms, the read timeout isn't supported, and, on other platforms,
+the timer doesn't start until at least one packet arrives. This means
+that the read timeout should
+.B NOT
+be used, for example, in an interactive application to allow the packet
+capture loop to ``poll'' for user input periodically, as there's no
+guarantee that a call reading packets will return after the timeout
+expires even if no packets have arrived.
+.IP
+The read timeout is set with
+.BR pcap_set_timeout() .
+.IP "buffer size"
+Packets that arrive for a capture are stored in a buffer, so that they
+do not have to be read by the application as soon as they arrive. On
+some platforms, the buffer's size can be set; a size that's too small
+could mean that, if too many packets are being captured and the snapshot
+length doesn't limit the amount of data that's buffered, packets could
+be dropped if the buffer fills up before the application can read
+packets from it, while a size that's too large could use more
+non-pageable operating system memory than is necessary to prevent
+packets from being dropped.
+.IP
+The buffer size is set with
+.BR pcap_set_buffer_size() .
+.PP
+Reading packets from a network interface may require that you have
+special privileges:
+.TP
+.B Under SunOS 3.x or 4.x with NIT or BPF:
+You must have read access to
+.I /dev/nit
+or
+.IR /dev/bpf* .
+.TP
+.B Under Solaris with DLPI:
+You must have read/write access to the network pseudo device, e.g.
+.IR /dev/le .
+On at least some versions of Solaris, however, this is not sufficient to
+allow
+.I tcpdump
+to capture in promiscuous mode; on those versions of Solaris, you must
+be root, or the application capturing packets
+must be installed setuid to root, in order to capture in promiscuous
+mode. Note that, on many (perhaps all) interfaces, if you don't capture
+in promiscuous mode, you will not see any outgoing packets, so a capture
+not done in promiscuous mode may not be very useful.
+.IP
+In newer versions of Solaris, you must have been given the
+.B net_rawaccess
+privilege; this is both necessary and sufficient to give you access to the
+network pseudo-device - there is no need to change the privileges on
+that device. A user can be given that privilege by, for example, adding
+that privilege to the user's
+.B defaultpriv
+key with the
+.B usermod (1M)
+command.
+.TP
+.B Under HP-UX with DLPI:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under IRIX with snoop:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under Linux:
+You must be root or the application capturing packets must be installed
+setuid to root (unless your distribution has a kernel
+that supports capability bits such as CAP_NET_RAW and code to allow
+those capability bits to be given to particular accounts and to cause
+those bits to be set on a user's initial processes when they log in, in
+which case you must have CAP_NET_RAW in order to capture and
+CAP_NET_ADMIN to enumerate network devices with, for example, the
+.B \-D
+flag).
+.TP
+.B Under ULTRIX and Digital UNIX/Tru64 UNIX:
+Any user may capture network traffic.
+However, no user (not even the super-user) can capture in promiscuous
+mode on an interface unless the super-user has enabled promiscuous-mode
+operation on that interface using
+.IR pfconfig (8),
+and no user (not even the super-user) can capture unicast traffic
+received by or sent by the machine on an interface unless the super-user
+has enabled copy-all-mode operation on that interface using
+.IR pfconfig ,
+so
+.I useful
+packet capture on an interface probably requires that either
+promiscuous-mode or copy-all-mode operation, or both modes of
+operation, be enabled on that interface.
+.TP
+.B Under BSD (this includes Mac OS X):
+You must have read access to
+.I /dev/bpf*
+on systems that don't have a cloning BPF device, or to
+.I /dev/bpf
+on systems that do.
+On BSDs with a devfs (this includes Mac OS X), this might involve more
+than just having somebody with super-user access setting the ownership
+or permissions on the BPF devices - it might involve configuring devfs
+to set the ownership or permissions every time the system is booted,
+if the system even supports that; if it doesn't support that, you might
+have to find some other way to make that happen at boot time.
+.PP
+Reading a saved packet file doesn't require special privileges.
+.PP
+To open a ``savefile`` to which to write packets, call
+.BR pcap_dump_open() .
+It returns a pointer to a
+.BR pcap_dumper_t ,
+which is the handle used for writing packets to the ``savefile''.
+.PP
+Packets are read with
+.B pcap_dispatch()
+or
+.BR pcap_loop() ,
+which process one or more packets, calling a callback routine for each
+packet, or with
+.B pcap_next()
+or
+.BR pcap_next_ex() ,
+which return the next packet.
+The callback for
+.B pcap_dispatch()
+and
+.BR pcap_loop()
+is supplied a pointer to a
+.IR "struct pcap_pkthdr" ,
+which includes the following members:
+.RS
+.TP
+.B ts
+a
+.I struct timeval
+containing the time when the packet was captured
+.TP
+.B caplen
+a
+.I bpf_u_int32
+giving the number of bytes of the packet that are available from the
+capture
+.TP
+.B len
+a
+.I bpf_u_int32
+giving the length of the packet, in bytes (which might be more than the
+number of bytes available from the capture, if the length of the packet
+is larger than the maximum number of bytes to capture).
+.RE
+.PP
+.B pcap_next_ex()
+supplies that pointer through a pointer argument.
+.B pcap_next()
+is passed an argument that points to a
+.I struct pcap_pkthdr
+structure, and fills it in.
+.PP
+The callback is also supplied a
+.I const u_char
+pointer to the first
+.B caplen
+(as given in the
+.I struct pcap_pkthdr
+a pointer to which is passed to the callback routine)
+bytes of data from the packet. This won't necessarily be the entire
+packet; to capture the entire packet, you will have to provide a value
+for
+.I snaplen
+in your call to
+.B pcap_open_live()
+that is sufficiently large to get all of the packet's data - a value of
+65535 should be sufficient on most if not all networks). When reading
+from a ``savefile'', the snapshot length specified when the capture was
+performed will limit the amount of packet data available.
+.B pcap_next()
+returns that pointer;
+.B pcap_next_ex()
+supplies that pointer through a pointer argument.
+.SH BACKWARDS COMPATIBILITY
+.PP
+In versions of libpcap prior to 1.0, the
+.B pcap.h
+header file was not in a
+.B pcap
+directory on most platforms; if you are writing an application that must
+work on versions of libpcap prior to 1.0, include
+.BR <pcap.h> ,
+which will include
+.B <pcap/pcap.h>
+for you, rather than including
+.BR <pcap/pcap.h> .
+.PP
+.B pcap_create()
+and
+.B pcap_activate()
+were not available in versions of libpcap prior to 1.0; if you are
+writing an application that must work on versions of libpcap prior to
+1.0, either use
+.B pcap_open_live()
+to get a handle for a live capture or, if you want to be able to use the
+additional capabilities offered by using
+.B pcap_create()
+and
+.BR pcap_activate() ,
+use an
+.BR autoconf (1)
+script or some other configuration script to check whether the libpcap
+1.0 APIs are available and use them only if they are.
+.SH SEE ALSO
+autoconf(1), tcpdump(1), tcpslice(1), pcap-filter(7), pfconfig(8),
+usermod(1M)
+.SH AUTHORS
+The original authors of libpcap are:
+.LP
+Van Jacobson,
+Craig Leres and
+Steven McCanne, all of the
+Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
+.LP
+The current version is available from "The Tcpdump Group"'s Web site at
+.LP
+.RS
+.I http://www.tcpdump.org/
+.RE
+.SH BUGS
+Please send problems, bugs, questions, desirable enhancements, etc. to:
+.LP
+.RS
+tcpdump-workers@lists.tcpdump.org
+.RE
diff --git a/contrib/libpcap/pcap.3pcap.in b/contrib/libpcap/pcap.3pcap.in
new file mode 100644
index 0000000..1c66508
--- /dev/null
+++ b/contrib/libpcap/pcap.3pcap.in
@@ -0,0 +1,386 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP 3PCAP "4 April 2008"
+.SH NAME
+pcap \- Packet Capture library
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+.ft
+.fi
+.SH DESCRIPTION
+The Packet Capture library
+provides a high level interface to packet capture systems. All packets
+on the network, even those destined for other hosts, are accessible
+through this mechanism.
+It also supports saving captured packets to a ``savefile'', and reading
+packets from a ``savefile''.
+.PP
+To open a handle for a live capture, call
+.BR pcap_create() ,
+set the appropriate options on the handle, and then activate it with
+.BR pcap_activate() .
+To open a handle for a ``savefile'' with captured packets, call
+.BR pcap_open_offline() .
+Both
+.B pcap_create()
+and
+.B pcap_open_offline()
+return a pointer to a
+.BR pcap_t ,
+which is the handle used for reading packets from the capture stream or
+the ``savefile'', and for finding out information about the capture
+stream or ``savefile''.
+.PP
+The options that can be set on a capture handle include
+.IP "snapshot length"
+If, when capturing, you capture the entire contents of the packet, that
+requires more CPU time to copy the packet to your application, more disk
+and possibly network bandwidth to write the packet data to a file, and
+more disk space to save the packet. If you don't need the entire
+contents of the packet - for example, if you are only interested in the
+TCP headers of packets - you can set the "snapshot length" for the
+capture to an appropriate value. If the snapshot length is set to
+.IR snaplen ,
+and
+.I snaplen
+is less
+than the size of a packet that is captured, only the first
+.I snaplen
+bytes of that packet will be captured and provided as packet data.
+.IP
+A snapshot length of 65535 should be sufficient, on most if not all
+networks, to capture all the data available from the packet.
+.IP
+The snapshot length is set with
+.BR pcap_set_snaplen() .
+.IP "promiscuous mode"
+On broadcast LANs such as Ethernet, if the network isn't switched, or if
+the adapter is connected to a "mirror port" on a switch to which all
+packets passing through the switch are sent, a network adapter receives
+all packets on the LAN, including unicast or multicast packets not sent
+to a network address that the network adapter isn't configured to
+recognize.
+.IP
+Normally, the adapter will discard those packets; however, many network
+adapters support "promiscuous mode", which is a mode in which all
+packets, even if they are not sent to an address that the adapter
+recognizes, are provided to the host. This is useful for passively
+capturing traffic between two or more other hosts for analysis.
+.IP
+Note that even if an application does not set promiscuous mode, the
+adapter could well be in promiscuous mode for some other reason.
+.IP
+For now, this doesn't work on the "any" device; if an argument of "any"
+or NULL is supplied, the setting of promiscuous mode is ignored.
+.IP
+Promiscuous mode is set with
+.BR pcap_set_promisc() .
+.IP "monitor mode"
+On IEEE 802.11 wireless LANs, even if an adapter is in promiscuous mode,
+it will supply to the host only frames for the network with which it's
+associated. It might also supply only data frames, not management or
+control frames, and might not provide the 802.11 header or radio
+information pseudo-header for those frames.
+.IP
+In "monitor mode", sometimes also called "rfmon mode" (for "Radio
+Frequency MONitor"), the adapter will supply all frames that it
+receives, with 802.11 headers, and might supply a pseudo-header with
+radio information about the frame as well.
+.IP
+Note that in monitor mode the adapter might disassociate from the
+network with which it's associated, so that you will not be able to use
+any wireless networks with that adapter. This could prevent accessing
+files on a network server, or resolving host names or network addresses,
+if you are capturing in monitor mode and are not connected to another
+network with another adapter.
+.IP
+Monitor mode is set with
+.BR pcap_set_rfmon() ,
+and
+.B pcap_can_set_rfmon()
+can be used to determine whether an adapter can be put into monitor
+mode.
+.IP "read timeout"
+If, when capturing, packets are delivered as soon as they arrive, the
+application capturing the packets will be woken up for each packet as it
+arrives, and might have to make one or more calls to the operating
+system to fetch each packet.
+.IP
+If, instead, packets are not delivered as soon as they arrive, but are
+delivered after a short delay (called a "read timeout"), more than one
+packet can be accumulated before the packets are delivered, so that a
+single wakeup would be done for multiple packets, and each set of calls
+made to the operating system would supply multiple packets, rather than
+a single packet. This reduces the per-packet CPU overhead if packets
+are arriving at a high rate, increasing the number of packets per second
+that can be captured.
+.IP
+The read timeout is required so that an application won't wait for the
+operating system's capture buffer to fill up before packets are
+delivered; if packets are arriving slowly, that wait could take an
+arbitrarily long period of time.
+.IP
+Not all platforms support a read timeout; on platforms that
+don't, the read timeout is ignored. A zero value for the timeout,
+on platforms that support a read timeout,
+will cause a read to wait forever to allow enough packets to
+arrive, with no timeout.
+.IP
+.BR NOTE :
+the read timeout cannot be used to cause calls that read
+packets to return within a limited period of time, because, on some
+platforms, the read timeout isn't supported, and, on other platforms,
+the timer doesn't start until at least one packet arrives. This means
+that the read timeout should
+.B NOT
+be used, for example, in an interactive application to allow the packet
+capture loop to ``poll'' for user input periodically, as there's no
+guarantee that a call reading packets will return after the timeout
+expires even if no packets have arrived.
+.IP
+The read timeout is set with
+.BR pcap_set_timeout() .
+.IP "buffer size"
+Packets that arrive for a capture are stored in a buffer, so that they
+do not have to be read by the application as soon as they arrive. On
+some platforms, the buffer's size can be set; a size that's too small
+could mean that, if too many packets are being captured and the snapshot
+length doesn't limit the amount of data that's buffered, packets could
+be dropped if the buffer fills up before the application can read
+packets from it, while a size that's too large could use more
+non-pageable operating system memory than is necessary to prevent
+packets from being dropped.
+.IP
+The buffer size is set with
+.BR pcap_set_buffer_size() .
+.PP
+Reading packets from a network interface may require that you have
+special privileges:
+.TP
+.B Under SunOS 3.x or 4.x with NIT or BPF:
+You must have read access to
+.I /dev/nit
+or
+.IR /dev/bpf* .
+.TP
+.B Under Solaris with DLPI:
+You must have read/write access to the network pseudo device, e.g.
+.IR /dev/le .
+On at least some versions of Solaris, however, this is not sufficient to
+allow
+.I tcpdump
+to capture in promiscuous mode; on those versions of Solaris, you must
+be root, or the application capturing packets
+must be installed setuid to root, in order to capture in promiscuous
+mode. Note that, on many (perhaps all) interfaces, if you don't capture
+in promiscuous mode, you will not see any outgoing packets, so a capture
+not done in promiscuous mode may not be very useful.
+.IP
+In newer versions of Solaris, you must have been given the
+.B net_rawaccess
+privilege; this is both necessary and sufficient to give you access to the
+network pseudo-device - there is no need to change the privileges on
+that device. A user can be given that privilege by, for example, adding
+that privilege to the user's
+.B defaultpriv
+key with the
+.B usermod (1M)
+command.
+.TP
+.B Under HP-UX with DLPI:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under IRIX with snoop:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under Linux:
+You must be root or the application capturing packets must be installed
+setuid to root (unless your distribution has a kernel
+that supports capability bits such as CAP_NET_RAW and code to allow
+those capability bits to be given to particular accounts and to cause
+those bits to be set on a user's initial processes when they log in, in
+which case you must have CAP_NET_RAW in order to capture and
+CAP_NET_ADMIN to enumerate network devices with, for example, the
+.B \-D
+flag).
+.TP
+.B Under ULTRIX and Digital UNIX/Tru64 UNIX:
+Any user may capture network traffic.
+However, no user (not even the super-user) can capture in promiscuous
+mode on an interface unless the super-user has enabled promiscuous-mode
+operation on that interface using
+.IR pfconfig (8),
+and no user (not even the super-user) can capture unicast traffic
+received by or sent by the machine on an interface unless the super-user
+has enabled copy-all-mode operation on that interface using
+.IR pfconfig ,
+so
+.I useful
+packet capture on an interface probably requires that either
+promiscuous-mode or copy-all-mode operation, or both modes of
+operation, be enabled on that interface.
+.TP
+.B Under BSD (this includes Mac OS X):
+You must have read access to
+.I /dev/bpf*
+on systems that don't have a cloning BPF device, or to
+.I /dev/bpf
+on systems that do.
+On BSDs with a devfs (this includes Mac OS X), this might involve more
+than just having somebody with super-user access setting the ownership
+or permissions on the BPF devices - it might involve configuring devfs
+to set the ownership or permissions every time the system is booted,
+if the system even supports that; if it doesn't support that, you might
+have to find some other way to make that happen at boot time.
+.PP
+Reading a saved packet file doesn't require special privileges.
+.PP
+To open a ``savefile`` to which to write packets, call
+.BR pcap_dump_open() .
+It returns a pointer to a
+.BR pcap_dumper_t ,
+which is the handle used for writing packets to the ``savefile''.
+.PP
+Packets are read with
+.B pcap_dispatch()
+or
+.BR pcap_loop() ,
+which process one or more packets, calling a callback routine for each
+packet, or with
+.B pcap_next()
+or
+.BR pcap_next_ex() ,
+which return the next packet.
+The callback for
+.B pcap_dispatch()
+and
+.BR pcap_loop()
+is supplied a pointer to a
+.IR "struct pcap_pkthdr" ,
+which includes the following members:
+.RS
+.TP
+.B ts
+a
+.I struct timeval
+containing the time when the packet was captured
+.TP
+.B caplen
+a
+.I bpf_u_int32
+giving the number of bytes of the packet that are available from the
+capture
+.TP
+.B len
+a
+.I bpf_u_int32
+giving the length of the packet, in bytes (which might be more than the
+number of bytes available from the capture, if the length of the packet
+is larger than the maximum number of bytes to capture).
+.RE
+.PP
+.B pcap_next_ex()
+supplies that pointer through a pointer argument.
+.B pcap_next()
+is passed an argument that points to a
+.I struct pcap_pkthdr
+structure, and fills it in.
+.PP
+The callback is also supplied a
+.I const u_char
+pointer to the first
+.B caplen
+(as given in the
+.I struct pcap_pkthdr
+a pointer to which is passed to the callback routine)
+bytes of data from the packet. This won't necessarily be the entire
+packet; to capture the entire packet, you will have to provide a value
+for
+.I snaplen
+in your call to
+.B pcap_open_live()
+that is sufficiently large to get all of the packet's data - a value of
+65535 should be sufficient on most if not all networks). When reading
+from a ``savefile'', the snapshot length specified when the capture was
+performed will limit the amount of packet data available.
+.B pcap_next()
+returns that pointer;
+.B pcap_next_ex()
+supplies that pointer through a pointer argument.
+.SH BACKWARDS COMPATIBILITY
+.PP
+In versions of libpcap prior to 1.0, the
+.B pcap.h
+header file was not in a
+.B pcap
+directory on most platforms; if you are writing an application that must
+work on versions of libpcap prior to 1.0, include
+.BR <pcap.h> ,
+which will include
+.B <pcap/pcap.h>
+for you, rather than including
+.BR <pcap/pcap.h> .
+.PP
+.B pcap_create()
+and
+.B pcap_activate()
+were not available in versions of libpcap prior to 1.0; if you are
+writing an application that must work on versions of libpcap prior to
+1.0, either use
+.B pcap_open_live()
+to get a handle for a live capture or, if you want to be able to use the
+additional capabilities offered by using
+.B pcap_create()
+and
+.BR pcap_activate() ,
+use an
+.BR autoconf (1)
+script or some other configuration script to check whether the libpcap
+1.0 APIs are available and use them only if they are.
+.SH SEE ALSO
+autoconf(1), tcpdump(1), tcpslice(1), pcap-filter(@MAN_MISC_INFO@), pfconfig(8),
+usermod(1M)
+.SH AUTHORS
+The original authors of libpcap are:
+.LP
+Van Jacobson,
+Craig Leres and
+Steven McCanne, all of the
+Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
+.LP
+The current version is available from "The Tcpdump Group"'s Web site at
+.LP
+.RS
+.I http://www.tcpdump.org/
+.RE
+.SH BUGS
+Please send problems, bugs, questions, desirable enhancements, etc. to:
+.LP
+.RS
+tcpdump-workers@lists.tcpdump.org
+.RE
diff --git a/contrib/libpcap/pcap.c b/contrib/libpcap/pcap.c
index 1a3c6b8..c763093 100644
--- a/contrib/libpcap/pcap.c
+++ b/contrib/libpcap/pcap.c
@@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.88.2.19 2007/09/19 02:50:52 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.112.2.12 2008-09-22 20:16:01 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -71,10 +71,205 @@ static const char rcsid[] _U_ =
#include <dagapi.h>
#endif
+int
+pcap_not_initialized(pcap_t *pcap)
+{
+ /* this means 'not initialized' */
+ return PCAP_ERROR_NOT_ACTIVATED;
+}
+
+/*
+ * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't,
+ * a PCAP_ERROR value on an error.
+ */
int
-pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+pcap_can_set_rfmon(pcap_t *p)
+{
+ return (p->can_set_rfmon_op(p));
+}
+
+/*
+ * For systems where rfmon mode is never supported.
+ */
+static int
+pcap_cant_set_rfmon(pcap_t *p _U_)
+{
+ return (0);
+}
+
+pcap_t *
+pcap_create_common(const char *source, char *ebuf)
+{
+ pcap_t *p;
+
+ p = malloc(sizeof(*p));
+ if (p == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ return (NULL);
+ }
+ memset(p, 0, sizeof(*p));
+#ifndef WIN32
+ p->fd = -1; /* not opened yet */
+#endif
+
+ p->opt.source = strdup(source);
+ if (p->opt.source == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ free(p);
+ return (NULL);
+ }
+
+ /*
+ * Default to "can't set rfmon mode"; if it's supported by
+ * a platform, it can set the op to its routine to check
+ * whether a particular device supports it.
+ */
+ p->can_set_rfmon_op = pcap_cant_set_rfmon;
+
+ /*
+ * Some operations can be performed only on activated pcap_t's;
+ * have those operations handled by a "not supported" handler
+ * until the pcap_t is activated.
+ */
+ p->read_op = (read_op_t)pcap_not_initialized;
+ p->inject_op = (inject_op_t)pcap_not_initialized;
+ p->setfilter_op = (setfilter_op_t)pcap_not_initialized;
+ p->setdirection_op = (setdirection_op_t)pcap_not_initialized;
+ p->set_datalink_op = (set_datalink_op_t)pcap_not_initialized;
+ p->getnonblock_op = (getnonblock_op_t)pcap_not_initialized;
+ p->setnonblock_op = (setnonblock_op_t)pcap_not_initialized;
+ p->stats_op = (stats_op_t)pcap_not_initialized;
+#ifdef WIN32
+ p->setbuff_op = (setbuff_op_t)pcap_not_initialized;
+ p->setmode_op = (setmode_op_t)pcap_not_initialized;
+ p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized;
+#endif
+ p->cleanup_op = pcap_cleanup_live_common;
+
+ /* put in some defaults*/
+ pcap_set_timeout(p, 0);
+ pcap_set_snaplen(p, 65535); /* max packet size */
+ p->opt.promisc = 0;
+ p->opt.buffer_size = 0;
+ return (p);
+}
+
+int
+pcap_check_activated(pcap_t *p)
+{
+ if (p->activated) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
+ " operation on activated capture");
+ return -1;
+ }
+ return 0;
+}
+
+int
+pcap_set_snaplen(pcap_t *p, int snaplen)
+{
+ if (pcap_check_activated(p))
+ return PCAP_ERROR_ACTIVATED;
+ p->snapshot = snaplen;
+ return 0;
+}
+
+int
+pcap_set_promisc(pcap_t *p, int promisc)
+{
+ if (pcap_check_activated(p))
+ return PCAP_ERROR_ACTIVATED;
+ p->opt.promisc = promisc;
+ return 0;
+}
+
+int
+pcap_set_rfmon(pcap_t *p, int rfmon)
+{
+ if (pcap_check_activated(p))
+ return PCAP_ERROR_ACTIVATED;
+ p->opt.rfmon = rfmon;
+ return 0;
+}
+
+int
+pcap_set_timeout(pcap_t *p, int timeout_ms)
+{
+ if (pcap_check_activated(p))
+ return PCAP_ERROR_ACTIVATED;
+ p->md.timeout = timeout_ms;
+ return 0;
+}
+
+int
+pcap_set_buffer_size(pcap_t *p, int buffer_size)
+{
+ if (pcap_check_activated(p))
+ return PCAP_ERROR_ACTIVATED;
+ p->opt.buffer_size = buffer_size;
+ return 0;
+}
+
+int
+pcap_activate(pcap_t *p)
{
+ int status;
+
+ status = p->activate_op(p);
+ if (status >= 0)
+ p->activated = 1;
+ return (status);
+}
+
+pcap_t *
+pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf)
+{
+ pcap_t *p;
+ int status;
+
+ p = pcap_create(source, errbuf);
+ if (p == NULL)
+ return (NULL);
+ status = pcap_set_snaplen(p, snaplen);
+ if (status < 0)
+ goto fail;
+ status = pcap_set_promisc(p, promisc);
+ if (status < 0)
+ goto fail;
+ status = pcap_set_timeout(p, to_ms);
+ if (status < 0)
+ goto fail;
+ /*
+ * Mark this as opened with pcap_open_live(), so that, for
+ * example, we show the full list of DLT_ values, rather
+ * than just the ones that are compatible with capturing
+ * when not in monitor mode. That allows existing applications
+ * to work the way they used to work, but allows new applications
+ * that know about the new open API to, for example, find out the
+ * DLT_ values that they can select without changing whether
+ * the adapter is in monitor mode or not.
+ */
+ p->oldstyle = 1;
+ status = pcap_activate(p);
+ if (status < 0)
+ goto fail;
+ return (p);
+fail:
+ if (status == PCAP_ERROR || status == PCAP_ERROR_NO_SUCH_DEVICE ||
+ status == PCAP_ERROR_PERM_DENIED)
+ strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
+ else
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source,
+ pcap_statustostr(status));
+ pcap_close(p);
+ return (NULL);
+}
+int
+pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
return p->read_op(p, cnt, callback, user);
}
@@ -223,6 +418,12 @@ pcap_datalink(pcap_t *p)
}
int
+pcap_datalink_ext(pcap_t *p)
+{
+ return (p->linktype_ext);
+}
+
+int
pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
{
if (p->dlt_count == 0) {
@@ -253,6 +454,23 @@ pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
}
}
+/*
+ * In Windows, you might have a library built with one version of the
+ * C runtime library and an application built with another version of
+ * the C runtime library, which means that the library might use one
+ * version of malloc() and free() and the application might use another
+ * version of malloc() and free(). If so, that means something
+ * allocated by the library cannot be freed by the application, so we
+ * need to have a pcap_free_datalinks() routine to free up the list
+ * allocated by pcap_list_datalinks(), even though it's just a wrapper
+ * around free().
+ */
+void
+pcap_free_datalinks(int *dlt_list)
+{
+ free(dlt_list);
+}
+
int
pcap_set_datalink(pcap_t *p, int dlt)
{
@@ -328,7 +546,7 @@ static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(DLT_NULL, "BSD loopback"),
DLT_CHOICE(DLT_EN10MB, "Ethernet"),
DLT_CHOICE(DLT_IEEE802, "Token ring"),
- DLT_CHOICE(DLT_ARCNET, "ARCNET"),
+ DLT_CHOICE(DLT_ARCNET, "BSD ARCNET"),
DLT_CHOICE(DLT_SLIP, "SLIP"),
DLT_CHOICE(DLT_PPP, "PPP"),
DLT_CHOICE(DLT_FDDI, "FDDI"),
@@ -339,6 +557,7 @@ static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"),
DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"),
+ DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"),
DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"),
DLT_CHOICE(DLT_IEEE802_11, "802.11"),
DLT_CHOICE(DLT_FRELAY, "Frame Relay"),
@@ -350,17 +569,25 @@ static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
- DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus BSD radio information header"),
- DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
+ DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus radiotap header"),
DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
+ DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
+ DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
+ DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"),
+ DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"),
+ DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
+ DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"),
+ DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
+ DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"),
+ DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
+ DLT_CHOICE(DLT_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
+ DLT_CHOICE(DLT_MTP2, "SS7 MTP2"),
+ DLT_CHOICE(DLT_MTP3, "SS7 MTP3"),
+ DLT_CHOICE(DLT_SCCP, "SS7 SCCP"),
DLT_CHOICE(DLT_DOCSIS, "DOCSIS"),
DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
- DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"),
DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
- DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"),
- DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"),
- DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"),
- DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
+ DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"),
DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"),
DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
@@ -368,27 +595,35 @@ static struct dlt_choice dlt_choices[] = {
DLT_CHOICE(DLT_GPF_T, "GPF-T"),
DLT_CHOICE(DLT_GPF_F, "GPF-F"),
DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"),
- DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
DLT_CHOICE(DLT_ERF_ETH, "Ethernet with Endace ERF header"),
DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"),
- DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"),
- DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"),
- DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
- DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
- DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
+ DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"),
DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"),
DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"),
DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"),
DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"),
DLT_CHOICE(DLT_MFR, "FRF.16 Frame Relay"),
DLT_CHOICE(DLT_JUNIPER_VP, "Juniper Voice PIC"),
- DLT_CHOICE(DLT_MTP2, "SS7 MTP2"),
DLT_CHOICE(DLT_A429, "Arinc 429"),
DLT_CHOICE(DLT_A653_ICM, "Arinc 653 Interpartition Communication"),
DLT_CHOICE(DLT_USB, "USB"),
DLT_CHOICE(DLT_BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
+ DLT_CHOICE(DLT_IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
+ DLT_CHOICE(DLT_USB_LINUX, "USB with Linux header"),
DLT_CHOICE(DLT_CAN20B, "Controller Area Network (CAN) v. 2.0B"),
- DLT_CHOICE(DLT_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
+ DLT_CHOICE(DLT_IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
+ DLT_CHOICE(DLT_PPI, "Per-Packet Information"),
+ DLT_CHOICE(DLT_IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
+ DLT_CHOICE(DLT_JUNIPER_ISM, "Juniper Integrated Service Module"),
+ DLT_CHOICE(DLT_IEEE802_15_4, "IEEE 802.15.4"),
+ DLT_CHOICE(DLT_SITA, "SITA pseudo-header"),
+ DLT_CHOICE(DLT_ERF, "Endace ERF header"),
+ DLT_CHOICE(DLT_RAIF1, "Ethernet with u10 Networks pseudo-header"),
+ DLT_CHOICE(DLT_IPMB, "IPMB"),
+ DLT_CHOICE(DLT_JUNIPER_ST, "Juniper Secure Tunnel"),
+ DLT_CHOICE(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
+ DLT_CHOICE(DLT_AX25_KISS, "AX.25 with KISS header"),
+ DLT_CHOICE(DLT_IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
DLT_CHOICE_SENTINEL
};
@@ -680,6 +915,53 @@ pcap_win32strerror(void)
#endif
/*
+ * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values.
+ */
+const char *
+pcap_statustostr(int errnum)
+{
+ static char ebuf[15+10+1];
+
+ switch (errnum) {
+
+ case PCAP_WARNING:
+ return("Generic warning");
+
+ case PCAP_WARNING_PROMISC_NOTSUP:
+ return ("That device doesn't support promiscuous mode");
+
+ case PCAP_ERROR:
+ return("Generic error");
+
+ case PCAP_ERROR_BREAK:
+ return("Loop terminated by pcap_breakloop");
+
+ case PCAP_ERROR_NOT_ACTIVATED:
+ return("The pcap_t has not been activated");
+
+ case PCAP_ERROR_ACTIVATED:
+ return ("The setting can't be changed after the pcap_t is activated");
+
+ case PCAP_ERROR_NO_SUCH_DEVICE:
+ return ("No such device exists");
+
+ case PCAP_ERROR_RFMON_NOTSUP:
+ return ("That device doesn't support monitor mode");
+
+ case PCAP_ERROR_NOT_RFMON:
+ return ("That operation is supported only in monitor mode");
+
+ case PCAP_ERROR_PERM_DENIED:
+ return ("You don't have permission to capture on that device");
+
+ case PCAP_ERROR_IFACE_NOT_UP:
+ return ("That device is not up");
+ }
+ (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
+ return(ebuf);
+}
+
+/*
* Not all systems have strerror().
*/
const char *
@@ -690,7 +972,7 @@ pcap_strerror(int errnum)
#else
extern int sys_nerr;
extern const char *const sys_errlist[];
- static char ebuf[20];
+ static char ebuf[15+10+1];
if ((unsigned int)errnum < sys_nerr)
return ((char *)sys_errlist[errnum]);
@@ -736,37 +1018,162 @@ pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
return (-1);
}
-void
-pcap_close_common(pcap_t *p)
+#ifdef WIN32
+int
+pcap_setbuff(pcap_t *p, int dim)
+{
+ return p->setbuff_op(p, dim);
+}
+
+static int
+pcap_setbuff_dead(pcap_t *p, int dim)
+{
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+int
+pcap_setmode(pcap_t *p, int mode)
+{
+ return p->setmode_op(p, mode);
+}
+
+static int
+pcap_setmode_dead(pcap_t *p, int mode)
+{
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "impossible to set mode on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+int
+pcap_setmintocopy(pcap_t *p, int size)
+{
+ return p->setmintocopy_op(p, size);
+}
+
+static int
+pcap_setmintocopy_dead(pcap_t *p, int size)
+{
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
+ return (-1);
+}
+#endif
+
+/*
+ * On some platforms, we need to clean up promiscuous or monitor mode
+ * when we close a device - and we want that to happen even if the
+ * application just exits without explicitl closing devices.
+ * On those platforms, we need to register a "close all the pcaps"
+ * routine to be called when we exit, and need to maintain a list of
+ * pcaps that need to be closed to clean up modes.
+ *
+ * XXX - not thread-safe.
+ */
+
+/*
+ * List of pcaps on which we've done something that needs to be
+ * cleaned up.
+ * If there are any such pcaps, we arrange to call "pcap_close_all()"
+ * when we exit, and have it close all of them.
+ */
+static struct pcap *pcaps_to_close;
+
+/*
+ * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to
+ * be called on exit.
+ */
+static int did_atexit;
+
+static void
+pcap_close_all(void)
+{
+ struct pcap *handle;
+
+ while ((handle = pcaps_to_close) != NULL)
+ pcap_close(handle);
+}
+
+int
+pcap_do_addexit(pcap_t *p)
{
-#ifdef BIOCSETBUFMODE
/*
- * Check to see if this pcap instance was using the zerocopy buffer
- * mode. If it was, delete the mappings. Note that p->buffer
- * gets initialized to one of the mmaped regions in this case, so
- * do not try and free it directly.
- *
- * If the regular buffer mode was selected, then it is safe to free
- * this memory.
+ * If we haven't already done so, arrange to have
+ * "pcap_close_all()" called when we exit.
*/
- if (p->zerocopy) {
- if (p->zbuf1 != MAP_FAILED && p->zbuf1 != NULL)
- munmap(p->zbuf1, p->zbufsize);
- if (p->zbuf2 != MAP_FAILED && p->zbuf2 != NULL)
- munmap(p->zbuf2, p->zbufsize);
- p->buffer = NULL;
- } else
-#endif
- if (p->buffer != NULL)
+ if (!did_atexit) {
+ if (atexit(pcap_close_all) == -1) {
+ /*
+ * "atexit()" failed; let our caller know.
+ */
+ strncpy(p->errbuf, "atexit failed",
+ PCAP_ERRBUF_SIZE);
+ return (0);
+ }
+ did_atexit = 1;
+ }
+ return (1);
+}
+
+void
+pcap_add_to_pcaps_to_close(pcap_t *p)
+{
+ p->md.next = pcaps_to_close;
+ pcaps_to_close = p;
+}
+
+void
+pcap_remove_from_pcaps_to_close(pcap_t *p)
+{
+ pcap_t *pc, *prevpc;
+
+ for (pc = pcaps_to_close, prevpc = NULL; pc != NULL;
+ prevpc = pc, pc = pc->md.next) {
+ if (pc == p) {
+ /*
+ * Found it. Remove it from the list.
+ */
+ if (prevpc == NULL) {
+ /*
+ * It was at the head of the list.
+ */
+ pcaps_to_close = pc->md.next;
+ } else {
+ /*
+ * It was in the middle of the list.
+ */
+ prevpc->md.next = pc->md.next;
+ }
+ break;
+ }
+ }
+}
+
+void
+pcap_cleanup_live_common(pcap_t *p)
+{
+ if (p->buffer != NULL) {
free(p->buffer);
+ p->buffer = NULL;
+ }
+ if (p->dlt_list != NULL) {
+ free(p->dlt_list);
+ p->dlt_list = NULL;
+ p->dlt_count = 0;
+ }
+ pcap_freecode(&p->fcode);
#if !defined(WIN32) && !defined(MSDOS)
- if (p->fd >= 0)
+ if (p->fd >= 0) {
close(p->fd);
+ p->fd = -1;
+ }
#endif
}
static void
-pcap_close_dead(pcap_t *p _U_)
+pcap_cleanup_dead(pcap_t *p _U_)
{
/* Nothing to do. */
}
@@ -783,7 +1190,13 @@ pcap_open_dead(int linktype, int snaplen)
p->snapshot = snaplen;
p->linktype = linktype;
p->stats_op = pcap_stats_dead;
- p->close_op = pcap_close_dead;
+#ifdef WIN32
+ p->setbuff_op = pcap_setbuff_dead;
+ p->setmode_op = pcap_setmode_dead;
+ p->setmintocopy_op = pcap_setmintocopy_dead;
+#endif
+ p->cleanup_op = pcap_cleanup_dead;
+ p->activated = 1;
return p;
}
@@ -814,14 +1227,31 @@ pcap_inject(pcap_t *p, const void *buf, size_t size)
void
pcap_close(pcap_t *p)
{
- p->close_op(p);
- if (p->dlt_list != NULL)
- free(p->dlt_list);
- pcap_freecode(&p->fcode);
+ if (p->opt.source != NULL)
+ free(p->opt.source);
+ p->cleanup_op(p);
free(p);
}
/*
+ * Given a BPF program, a pcap_pkthdr structure for a packet, and the raw
+ * data for the packet, check whether the packet passes the filter.
+ * Returns the return value of the filter program, which will be zero if
+ * the packet doesn't pass and non-zero if the packet does pass.
+ */
+int
+pcap_offline_filter(struct bpf_program *fp, const struct pcap_pkthdr *h,
+ const u_char *pkt)
+{
+ struct bpf_insn *fcode = fp->bf_insns;
+
+ if (fcode != NULL)
+ return (bpf_filter(fcode, pkt, h->len, h->caplen));
+ else
+ return (0);
+}
+
+/*
* We make the version string static, and return a pointer to it, rather
* than exporting the version string directly. On at least some UNIXes,
* if you import data from a shared library into an program, the data is
@@ -836,7 +1266,7 @@ pcap_close(pcap_t *p)
#ifdef HAVE_VERSION_H
#include "version.h"
#else
-static const char pcap_version_string[] = "libpcap version 0.9.8";
+static const char pcap_version_string[] = "libpcap version 0.9[.x]";
#endif
#ifdef WIN32
diff --git a/contrib/libpcap/pcap.h b/contrib/libpcap/pcap.h
index c81f81e..270f001e 100644
--- a/contrib/libpcap/pcap.h
+++ b/contrib/libpcap/pcap.h
@@ -1,4 +1,3 @@
-/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
@@ -32,285 +31,39 @@
* SUCH DAMAGE.
*
* $FreeBSD$
- * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.52.2.7 2007/06/11 09:52:05 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.59 2006/10/04 18:09:22 guy Exp $ (LBL)
*/
#ifndef lib_pcap_h
#define lib_pcap_h
-#include <sys/types.h>
-#include <sys/time.h>
+#if defined(WIN32)
+ #include <pcap-stdinc.h>
+#elif defined(MSDOS)
+ #include <sys/types.h>
+ #include <sys/socket.h> /* u_int, u_char etc. */
+#else /* UN*X */
+ #include <sys/types.h>
+ #include <sys/time.h>
+#endif /* WIN32/MSDOS/UN*X */
#include <net/bpf.h>
#include <stdio.h>
-#ifdef __cplusplus
-extern "C" {
-#endif
-
#define PCAP_VERSION_MAJOR 2
#define PCAP_VERSION_MINOR 4
#define PCAP_ERRBUF_SIZE 256
/*
- * Compatibility for systems that have a bpf.h that
- * predates the bpf typedefs for 64-bit support.
- */
-#if BPF_RELEASE - 0 < 199406
-typedef int bpf_int32;
-typedef u_int bpf_u_int32;
-#endif
-
-typedef struct pcap pcap_t;
-typedef struct pcap_dumper pcap_dumper_t;
-typedef struct pcap_if pcap_if_t;
-typedef struct pcap_addr pcap_addr_t;
-
-/*
- * The first record in the file contains saved values for some
- * of the flags used in the printout phases of tcpdump.
- * Many fields here are 32 bit ints so compilers won't insert unwanted
- * padding; these files need to be interchangeable across architectures.
- *
- * Do not change the layout of this structure, in any way (this includes
- * changes that only affect the length of fields in this structure).
- *
- * Also, do not change the interpretation of any of the members of this
- * structure, in any way (this includes using values other than
- * LINKTYPE_ values, as defined in "savefile.c", in the "linktype"
- * field).
- *
- * Instead:
- *
- * introduce a new structure for the new format, if the layout
- * of the structure changed;
- *
- * send mail to "tcpdump-workers@tcpdump.org", requesting a new
- * magic number for your new capture file format, and, when
- * you get the new magic number, put it in "savefile.c";
- *
- * use that magic number for save files with the changed file
- * header;
- *
- * make the code in "savefile.c" capable of reading files with
- * the old file header as well as files with the new file header
- * (using the magic number to determine the header format).
- *
- * Then supply the changes to "patches@tcpdump.org", so that future
- * versions of libpcap and programs that use it (such as tcpdump) will
- * be able to read your new capture file format.
- */
-struct pcap_file_header {
- bpf_u_int32 magic;
- u_short version_major;
- u_short version_minor;
- bpf_int32 thiszone; /* gmt to local correction */
- bpf_u_int32 sigfigs; /* accuracy of timestamps */
- bpf_u_int32 snaplen; /* max length saved portion of each pkt */
- bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
-};
-
-typedef enum {
- PCAP_D_INOUT = 0,
- PCAP_D_IN,
- PCAP_D_OUT
-} pcap_direction_t;
-
-/*
- * Generic per-packet information, as supplied by libpcap.
+ * For backwards compatibility.
*
- * The time stamp can and should be a "struct timeval", regardless of
- * whether your system supports 32-bit tv_sec in "struct timeval",
- * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit
- * and 64-bit applications. The on-disk format of savefiles uses 32-bit
- * tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit
- * and 64-bit versions of libpcap, even if they're on the same platform,
- * should supply the appropriate version of "struct timeval", even if
- * that's not what the underlying packet capture mechanism supplies.
- */
-struct pcap_pkthdr {
- struct timeval ts; /* time stamp */
- bpf_u_int32 caplen; /* length of portion present */
- bpf_u_int32 len; /* length this packet (off wire) */
-};
-
-/*
- * As returned by the pcap_stats()
- */
-struct pcap_stat {
- u_int ps_recv; /* number of packets received */
- u_int ps_drop; /* number of packets dropped */
- u_int ps_ifdrop; /* drops by interface XXX not yet supported */
-#ifdef WIN32
- u_int bs_capt; /* number of packets that reach the application */
-#endif /* WIN32 */
-};
-
-#ifdef MSDOS
-/*
- * As returned by the pcap_stats_ex()
+ * Note to OS vendors: do NOT get rid of this file! Many applications
+ * expect to be able to include <pcap.h>, and at least some of them
+ * go through contortions in their configure scripts to try to detect
+ * OSes that have "helpfully" moved pcap.h to <pcap/pcap.h> without
+ * leaving behind a <pcap.h> file.
*/
-struct pcap_stat_ex {
- u_long rx_packets; /* total packets received */
- u_long tx_packets; /* total packets transmitted */
- u_long rx_bytes; /* total bytes received */
- u_long tx_bytes; /* total bytes transmitted */
- u_long rx_errors; /* bad packets received */
- u_long tx_errors; /* packet transmit problems */
- u_long rx_dropped; /* no space in Rx buffers */
- u_long tx_dropped; /* no space available for Tx */
- u_long multicast; /* multicast packets received */
- u_long collisions;
-
- /* detailed rx_errors: */
- u_long rx_length_errors;
- u_long rx_over_errors; /* receiver ring buff overflow */
- u_long rx_crc_errors; /* recv'd pkt with crc error */
- u_long rx_frame_errors; /* recv'd frame alignment error */
- u_long rx_fifo_errors; /* recv'r fifo overrun */
- u_long rx_missed_errors; /* recv'r missed packet */
-
- /* detailed tx_errors */
- u_long tx_aborted_errors;
- u_long tx_carrier_errors;
- u_long tx_fifo_errors;
- u_long tx_heartbeat_errors;
- u_long tx_window_errors;
- };
-#endif
-
-/*
- * Item in a list of interfaces.
- */
-struct pcap_if {
- struct pcap_if *next;
- char *name; /* name to hand to "pcap_open_live()" */
- char *description; /* textual description of interface, or NULL */
- struct pcap_addr *addresses;
- bpf_u_int32 flags; /* PCAP_IF_ interface flags */
-};
-
-#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */
-
-/*
- * Representation of an interface address.
- */
-struct pcap_addr {
- struct pcap_addr *next;
- struct sockaddr *addr; /* address */
- struct sockaddr *netmask; /* netmask for that address */
- struct sockaddr *broadaddr; /* broadcast address for that address */
- struct sockaddr *dstaddr; /* P2P destination address for that address */
-};
-
-typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
- const u_char *);
-
-char *pcap_lookupdev(char *);
-int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
-pcap_t *pcap_open_live(const char *, int, int, int, char *);
-pcap_t *pcap_open_dead(int, int);
-pcap_t *pcap_open_offline(const char *, char *);
-pcap_t *pcap_fopen_offline(FILE *, char *);
-void pcap_close(pcap_t *);
-int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
-int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
-const u_char*
- pcap_next(pcap_t *, struct pcap_pkthdr *);
-int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
-void pcap_breakloop(pcap_t *);
-int pcap_stats(pcap_t *, struct pcap_stat *);
-int pcap_setfilter(pcap_t *, struct bpf_program *);
-int pcap_setdirection(pcap_t *, pcap_direction_t);
-int pcap_getnonblock(pcap_t *, char *);
-int pcap_setnonblock(pcap_t *, int, char *);
-void pcap_perror(pcap_t *, char *);
-int pcap_inject(pcap_t *, const void *, size_t);
-int pcap_sendpacket(pcap_t *, const u_char *, int);
-const char *pcap_strerror(int);
-char *pcap_geterr(pcap_t *);
-int pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
- bpf_u_int32);
-int pcap_compile_nopcap(int, int, struct bpf_program *,
- const char *, int, bpf_u_int32);
-void pcap_freecode(struct bpf_program *);
-int pcap_datalink(pcap_t *);
-int pcap_list_datalinks(pcap_t *, int **);
-int pcap_set_datalink(pcap_t *, int);
-int pcap_datalink_name_to_val(const char *);
-const char *pcap_datalink_val_to_name(int);
-const char *pcap_datalink_val_to_description(int);
-int pcap_snapshot(pcap_t *);
-int pcap_is_swapped(pcap_t *);
-int pcap_major_version(pcap_t *);
-int pcap_minor_version(pcap_t *);
-
-/* XXX */
-FILE *pcap_file(pcap_t *);
-int pcap_fileno(pcap_t *);
-
-pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
-pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
-FILE *pcap_dump_file(pcap_dumper_t *);
-long pcap_dump_ftell(pcap_dumper_t *);
-int pcap_dump_flush(pcap_dumper_t *);
-void pcap_dump_close(pcap_dumper_t *);
-void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
-
-int pcap_findalldevs(pcap_if_t **, char *);
-void pcap_freealldevs(pcap_if_t *);
-
-const char *pcap_lib_version(void);
-
-/* XXX this guy lives in the bpf tree */
-u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
-int bpf_validate(struct bpf_insn *f, int len);
-char *bpf_image(struct bpf_insn *, int);
-void bpf_dump(struct bpf_program *, int);
-
-#if defined(WIN32)
-
-/*
- * Win32 definitions
- */
-
-int pcap_setbuff(pcap_t *p, int dim);
-int pcap_setmode(pcap_t *p, int mode);
-int pcap_setmintocopy(pcap_t *p, int size);
-
-#ifdef WPCAP
-/* Include file with the wpcap-specific extensions */
-#include <Win32-Extensions.h>
-#endif /* WPCAP */
-
-#define MODE_CAPT 0
-#define MODE_STAT 1
-#define MODE_MON 2
-
-#elif defined(MSDOS)
-
-/*
- * MS-DOS definitions
- */
-
-int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
-void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
-u_long pcap_mac_packets (void);
-
-#else /* UN*X */
-
-/*
- * UN*X definitions
- */
-
-int pcap_get_selectable_fd(pcap_t *);
-
-#endif /* WIN32/MSDOS/UN*X */
-
-#ifdef __cplusplus
-}
-#endif
-
+#include <pcap/pcap.h>
#endif
diff --git a/contrib/libpcap/pcap/bluetooth.h b/contrib/libpcap/pcap/bluetooth.h
new file mode 100644
index 0000000..7bf65df
--- /dev/null
+++ b/contrib/libpcap/pcap/bluetooth.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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
+ * OWNER 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.
+ *
+ * bluetooth data struct
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/bluetooth.h,v 1.1 2007/09/22 02:10:17 guy Exp $
+ */
+
+#ifndef _PCAP_BLUETOOTH_STRUCTS_H__
+#define _PCAP_BLUETOOTH_STRUCTS_H__
+
+/*
+ * Header prepended libpcap to each bluetooth h:4 frame.
+ * fields are in network byte order
+ */
+typedef struct _pcap_bluetooth_h4_header {
+ u_int32_t direction; /* if first bit is set direction is incoming */
+} pcap_bluetooth_h4_header;
+
+
+#endif
diff --git a/contrib/libpcap/pcap/bpf.h b/contrib/libpcap/pcap/bpf.h
new file mode 100644
index 0000000..c9b30ed
--- /dev/null
+++ b/contrib/libpcap/pcap/bpf.h
@@ -0,0 +1,934 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/bpf.h,v 1.19.2.8 2008-09-22 20:16:01 guy Exp $ (LBL)
+ */
+
+/*
+ * This is libpcap's cut-down version of bpf.h; it includes only
+ * the stuff needed for the code generator and the userland BPF
+ * interpreter, and the libpcap APIs for setting filters, etc..
+ *
+ * "pcap-bpf.c" will include the native OS version, as it deals with
+ * the OS's BPF implementation.
+ *
+ * XXX - should this all just be moved to "pcap.h"?
+ */
+
+#ifndef BPF_MAJOR_VERSION
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+#ifdef MSDOS /* must be 32-bit */
+typedef long bpf_int32;
+typedef unsigned long bpf_u_int32;
+#else
+typedef int bpf_int32;
+typedef u_int bpf_u_int32;
+#endif
+
+/*
+ * Alignment macros. BPF_WORDALIGN rounds up to the next
+ * even multiple of BPF_ALIGNMENT.
+ */
+#ifndef __NetBSD__
+#define BPF_ALIGNMENT sizeof(bpf_int32)
+#else
+#define BPF_ALIGNMENT sizeof(long)
+#endif
+#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
+
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+/*
+ * Structure for "pcap_compile()", "pcap_setfilter()", etc..
+ */
+struct bpf_program {
+ u_int bf_len;
+ struct bpf_insn *bf_insns;
+};
+
+/*
+ * Struct return by BIOCVERSION. This represents the version number of
+ * the filter language described by the instruction encodings below.
+ * 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
+ * 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.
+ */
+struct bpf_version {
+ u_short bv_major;
+ u_short bv_minor;
+};
+/* Current version number of filter architecture. */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+/*
+ * Data-link level type codes.
+ *
+ * Do *NOT* add new values to this list without asking
+ * "tcpdump-workers@lists.tcpdump.org" for a value. Otherwise, you run
+ * the risk of using a value that's already being used for some other
+ * purpose, and of having tools that read libpcap-format captures not
+ * being able to handle captures with your new DLT_ value, with no hope
+ * that they will ever be changed to do so (as that would destroy their
+ * ability to read captures using that value for that other purpose).
+ */
+
+/*
+ * These are the types that are the same on all platforms, and that
+ * have been defined by <net/bpf.h> for ages.
+ */
+#define DLT_NULL 0 /* BSD loopback encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* 802.5 Token Ring */
+#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+
+/*
+ * These are types that are different on some platforms, and that
+ * have been defined by <net/bpf.h> for ages. We use #ifdefs to
+ * detect the BSDs that define them differently from the traditional
+ * libpcap <net/bpf.h>
+ *
+ * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
+ * but I don't know what the right #define is for BSD/OS.
+ */
+#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */
+
+#ifdef __OpenBSD__
+#define DLT_RAW 14 /* raw IP */
+#else
+#define DLT_RAW 12 /* raw IP */
+#endif
+
+/*
+ * Given that the only OS that currently generates BSD/OS SLIP or PPP
+ * is, well, BSD/OS, arguably everybody should have chosen its values
+ * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
+ * didn't. So it goes.
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#ifndef DLT_SLIP_BSDOS
+#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
+#endif
+#else
+#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
+#endif
+
+/*
+ * 17 is used for DLT_OLD_PFLOG in OpenBSD;
+ * OBSOLETE: DLT_PFLOG is 117 in OpenBSD now as well. See below.
+ * 18 is used for DLT_PFSYNC in OpenBSD; don't use it for anything else.
+ */
+
+#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
+
+/*
+ * Apparently Redback uses this for its SmartEdge 400/800. I hope
+ * nobody else decided to use it, too.
+ */
+#define DLT_REDBACK_SMARTEDGE 32
+
+/*
+ * These values are defined by NetBSD; other platforms should refrain from
+ * using them for other purposes, so that NetBSD savefiles with link
+ * types of 50 or 51 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
+#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
+
+/*
+ * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
+ * a link-layer type of 99 for the tcpdump it supplies. The link-layer
+ * header has 6 bytes of unknown data, something that appears to be an
+ * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
+ * I've seen.
+ */
+#define DLT_SYMANTEC_FIREWALL 99
+
+/*
+ * Values between 100 and 103 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC 104 /* Cisco HDLC */
+#define DLT_CHDLC DLT_C_HDLC
+
+#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+/*
+ * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
+ * except when it isn't. (I.e., sometimes it's just raw IP, and
+ * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL,
+ * so that we don't have to worry about the link-layer header.)
+ */
+
+/*
+ * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
+ * with other values.
+ * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
+ * (DLCI, etc.).
+ */
+#define DLT_FRELAY 107
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
+ * we don't use 12 for it in OSes other than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_LOOP 12
+#else
+#define DLT_LOOP 108
+#endif
+
+/*
+ * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
+ * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
+ * than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_ENC 13
+#else
+#define DLT_ENC 109
+#endif
+
+/*
+ * Values between 110 and 112 are reserved for use in capture file headers
+ * as link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ types
+ * other than the corresponding DLT_ types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL 113
+
+/*
+ * Apple LocalTalk hardware.
+ */
+#define DLT_LTALK 114
+
+/*
+ * Acorn Econet.
+ */
+#define DLT_ECONET 115
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define DLT_IPFILTER 116
+
+/*
+ * OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, but that's DLT_LANE8023
+ * in SuSE 6.3, so we can't use 17 for it in capture-file headers.
+ *
+ * XXX: is there a conflict with DLT_PFSYNC 18 as well?
+ */
+#ifdef __OpenBSD__
+#define DLT_OLD_PFLOG 17
+#define DLT_PFSYNC 18
+#endif
+#define DLT_PFLOG 117
+
+/*
+ * Registered for Cisco-internal use.
+ */
+#define DLT_CISCO_IOS 118
+
+/*
+ * For 802.11 cards using the Prism II chips, with a link-layer
+ * header including Prism monitor mode information plus an 802.11
+ * header.
+ */
+#define DLT_PRISM_HEADER 119
+
+/*
+ * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
+ * (see Doug Ambrisko's FreeBSD patches).
+ */
+#define DLT_AIRONET_HEADER 120
+
+/*
+ * Reserved for Siemens HiPath HDLC.
+ */
+#define DLT_HHDLC 121
+
+/*
+ * This is for RFC 2625 IP-over-Fibre Channel.
+ *
+ * This is not for use with raw Fibre Channel, where the link-layer
+ * header starts with a Fibre Channel frame header; it's for IP-over-FC,
+ * where the link-layer header starts with an RFC 2625 Network_Header
+ * field.
+ */
+#define DLT_IP_OVER_FC 122
+
+/*
+ * This is for Full Frontal ATM on Solaris with SunATM, with a
+ * pseudo-header followed by an AALn PDU.
+ *
+ * There may be other forms of Full Frontal ATM on other OSes,
+ * with different pseudo-headers.
+ *
+ * If ATM software returns a pseudo-header with VPI/VCI information
+ * (and, ideally, packet type information, e.g. signalling, ILMI,
+ * LANE, LLC-multiplexed traffic, etc.), it should not use
+ * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
+ * and the like don't have to infer the presence or absence of a
+ * pseudo-header and the form of the pseudo-header.
+ */
+#define DLT_SUNATM 123 /* Solaris+SunATM */
+
+/*
+ * Reserved as per request from Kent Dahlgren <kent@praesum.com>
+ * for private use.
+ */
+#define DLT_RIO 124 /* RapidIO */
+#define DLT_PCI_EXP 125 /* PCI Express */
+#define DLT_AURORA 126 /* Xilinx Aurora link layer */
+
+/*
+ * Header for 802.11 plus a number of bits of link-layer information
+ * including radio information, used by some recent BSD drivers as
+ * well as the madwifi Atheros driver for Linux.
+ */
+#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
+
+/*
+ * Reserved for the TZSP encapsulation, as per request from
+ * Chris Waters <chris.waters@networkchemistry.com>
+ * TZSP is a generic encapsulation for any other link type,
+ * which includes a means to include meta-information
+ * with the packet, e.g. signal strength and channel
+ * for 802.11 packets.
+ */
+#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
+
+/*
+ * BSD's ARCNET headers have the source host, destination host,
+ * and type at the beginning of the packet; that's what's handed
+ * up to userland via BPF.
+ *
+ * Linux's ARCNET headers, however, have a 2-byte offset field
+ * between the host IDs and the type; that's what's handed up
+ * to userland via PF_PACKET sockets.
+ *
+ * We therefore have to have separate DLT_ values for them.
+ */
+#define DLT_ARCNET_LINUX 129 /* ARCNET */
+
+/*
+ * Juniper-private data link types, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MLPPP 130
+#define DLT_JUNIPER_MLFR 131
+#define DLT_JUNIPER_ES 132
+#define DLT_JUNIPER_GGSN 133
+#define DLT_JUNIPER_MFR 134
+#define DLT_JUNIPER_ATM2 135
+#define DLT_JUNIPER_SERVICES 136
+#define DLT_JUNIPER_ATM1 137
+
+/*
+ * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
+ * <dieter@apple.com>. The header that's presented is an Ethernet-like
+ * header:
+ *
+ * #define FIREWIRE_EUI64_LEN 8
+ * struct firewire_header {
+ * u_char firewire_dhost[FIREWIRE_EUI64_LEN];
+ * u_char firewire_shost[FIREWIRE_EUI64_LEN];
+ * u_short firewire_type;
+ * };
+ *
+ * with "firewire_type" being an Ethernet type value, rather than,
+ * for example, raw GASP frames being handed up.
+ */
+#define DLT_APPLE_IP_OVER_IEEE1394 138
+
+/*
+ * Various SS7 encapsulations, as per a request from Jeff Morriss
+ * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
+ */
+#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */
+#define DLT_MTP2 140 /* MTP2, without pseudo-header */
+#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */
+#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */
+
+/*
+ * DOCSIS MAC frames.
+ */
+#define DLT_DOCSIS 143
+
+/*
+ * Linux-IrDA packets. Protocol defined at http://www.irda.org.
+ * Those packets include IrLAP headers and above (IrLMP...), but
+ * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
+ * framing can be handled by the hardware and depend on the bitrate.
+ * This is exactly the format you would get capturing on a Linux-IrDA
+ * interface (irdaX), but not on a raw serial port.
+ * Note the capture is done in "Linux-cooked" mode, so each packet include
+ * a fake packet header (struct sll_header). This is because IrDA packet
+ * decoding is dependant on the direction of the packet (incomming or
+ * outgoing).
+ * When/if other platform implement IrDA capture, we may revisit the
+ * issue and define a real DLT_IRDA...
+ * Jean II
+ */
+#define DLT_LINUX_IRDA 144
+
+/*
+ * Reserved for IBM SP switch and IBM Next Federation switch.
+ */
+#define DLT_IBM_SP 145
+#define DLT_IBM_SN 146
+
+/*
+ * Reserved for private use. If you have some link-layer header type
+ * that you want to use within your organization, with the capture files
+ * using that link-layer header type not ever be sent outside your
+ * organization, you can use these values.
+ *
+ * No libpcap release will use these for any purpose, nor will any
+ * tcpdump release use them, either.
+ *
+ * Do *NOT* use these in capture files that you expect anybody not using
+ * your private versions of capture-file-reading tools to read; in
+ * particular, do *NOT* use them in products, otherwise you may find that
+ * people won't be able to use tcpdump, or snort, or Ethereal, or... to
+ * read capture files from your firewall/intrusion detection/traffic
+ * monitoring/etc. appliance, or whatever product uses that DLT_ value,
+ * and you may also find that the developers of those applications will
+ * not accept patches to let them read those files.
+ *
+ * Also, do not use them if somebody might send you a capture using them
+ * for *their* private type and tools using them for *your* private type
+ * would have to read them.
+ *
+ * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value,
+ * as per the comment above, and use the type you're given.
+ */
+#define DLT_USER0 147
+#define DLT_USER1 148
+#define DLT_USER2 149
+#define DLT_USER3 150
+#define DLT_USER4 151
+#define DLT_USER5 152
+#define DLT_USER6 153
+#define DLT_USER7 154
+#define DLT_USER8 155
+#define DLT_USER9 156
+#define DLT_USER10 157
+#define DLT_USER11 158
+#define DLT_USER12 159
+#define DLT_USER13 160
+#define DLT_USER14 161
+#define DLT_USER15 162
+
+/*
+ * For future use with 802.11 captures - defined by AbsoluteValue
+ * Systems to store a number of bits of link-layer information
+ * including radio information:
+ *
+ * http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ *
+ * but it might be used by some non-AVS drivers now or in the
+ * future.
+ */
+#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MONITOR 164
+
+/*
+ * Reserved for BACnet MS/TP.
+ */
+#define DLT_BACNET_MS_TP 165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define DLT_PPP_PPPD 166
+
+/*
+ * Names for backwards compatibility with older versions of some PPP
+ * software; new software should use DLT_PPP_PPPD.
+ */
+#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
+#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define DLT_JUNIPER_PPPOE 167
+#define DLT_JUNIPER_PPPOE_ATM 168
+
+#define DLT_GPRS_LLC 169 /* GPRS LLC */
+#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
+#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define DLT_GCOM_T1E1 172
+#define DLT_GCOM_SERIAL 173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define DLT_JUNIPER_PIC_PEER 174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems. They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define DLT_ERF_ETH 175 /* Ethernet */
+#define DLT_ERF_POS 176 /* Packet-over-SONET */
+
+/*
+ * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
+ * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
+ * includes additional information before the LAPD header, so it's
+ * not necessarily a generic LAPD header.
+ */
+#define DLT_LINUX_LAPD 177
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ are used for prepending meta-information
+ * like interface index, interface name
+ * before standard Ethernet, PPP, Frelay & C-HDLC Frames
+ */
+#define DLT_JUNIPER_ETHER 178
+#define DLT_JUNIPER_PPP 179
+#define DLT_JUNIPER_FRELAY 180
+#define DLT_JUNIPER_CHDLC 181
+
+/*
+ * Multi Link Frame Relay (FRF.16)
+ */
+#define DLT_MFR 182
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * voice Adapter Card (PIC)
+ */
+#define DLT_JUNIPER_VP 183
+
+/*
+ * Arinc 429 frames.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Every frame contains a 32bit A429 label.
+ * More documentation on Arinc 429 can be found at
+ * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ */
+#define DLT_A429 184
+
+/*
+ * Arinc 653 Interpartition Communication messages.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Please refer to the A653-1 standard for more information.
+ */
+#define DLT_A653_ICM 185
+
+/*
+ * USB packets, beginning with a USB setup header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define DLT_USB 186
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4); requested by
+ * Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4 187
+
+/*
+ * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
+ * <cruz_petagay@bah.com>.
+ */
+#define DLT_IEEE802_16_MAC_CPS 188
+
+/*
+ * USB packets, beginning with a Linux USB header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define DLT_USB_LINUX 189
+
+/*
+ * Controller Area Network (CAN) v. 2.0B packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Used to dump CAN packets coming from a CAN Vector board.
+ * More documentation on the CAN v2.0B frames can be found at
+ * http://www.can-cia.org/downloads/?269
+ */
+#define DLT_CAN20B 190
+
+/*
+ * IEEE 802.15.4, with address fields padded, as is done by Linux
+ * drivers; requested by Juergen Schimmer.
+ */
+#define DLT_IEEE802_15_4_LINUX 191
+
+/*
+ * Per Packet Information encapsulated packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ */
+#define DLT_PPI 192
+
+/*
+ * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
+ * requested by Charles Clancy.
+ */
+#define DLT_IEEE802_16_MAC_CPS_RADIO 193
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * integrated service module (ISM).
+ */
+#define DLT_JUNIPER_ISM 194
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
+ */
+#define DLT_IEEE802_15_4 195
+
+/*
+ * Various link-layer types, with a pseudo-header, for SITA
+ * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
+ */
+#define DLT_SITA 196
+
+/*
+ * Various link-layer types, with a pseudo-header, for Endace DAG cards;
+ * encapsulates Endace ERF records. Requested by Stephen Donnelly
+ * <stephen@endace.com>.
+ */
+#define DLT_ERF 197
+
+/*
+ * Special header prepended to Ethernet packets when capturing from a
+ * u10 Networks board. Requested by Phil Mulholland
+ * <phil@u10networks.com>.
+ */
+#define DLT_RAIF1 198
+
+/*
+ * IPMB packet for IPMI, beginning with the I2C slave address, followed
+ * by the netFn and LUN, etc.. Requested by Chanthy Toeung
+ * <chanthy.toeung@ca.kontron.com>.
+ */
+#define DLT_IPMB 199
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for capturing data on a secure tunnel interface.
+ */
+#define DLT_JUNIPER_ST 200
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
+ * that includes direction information; requested by Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
+
+/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ * http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
+ */
+#define DLT_AX25_KISS 202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <varunax@gmail.com>.
+ */
+#define DLT_LAPD 203
+
+/*
+ * Variants of various link-layer headers, with a one-byte direction
+ * pseudo-header prepended - zero means "received by this host",
+ * non-zero (any non-zero value) means "sent by this host" - as per
+ * Will Barker <w.barker@zen.co.uk>.
+ */
+#define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
+#define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */
+#define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */
+#define DLT_LAPB_WITH_DIR 207 /* LAPB */
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ * <avn@pigeonpoint.com>.
+ */
+#define DLT_IPMB_LINUX 209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_FLEXRAY 210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_MOST 211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ * <hannes.kaelber@x2e.de>.
+ */
+#define DLT_LIN 212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_SERIAL 213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_XORAYA 214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <jcmvbkbc@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NONASK_PHY 215
+
+
+/*
+ * DLT and savefile link type values are split into a class and
+ * a member of that class. A class value of 0 indicates a regular
+ * DLT_/LINKTYPE_ value.
+ */
+#define DLT_CLASS(x) ((x) & 0x03ff0000)
+
+/*
+ * NetBSD-specific generic "raw" link type. The class value indicates
+ * that this is the generic raw type, and the lower 16 bits are the
+ * address family we're dealing with. Those values are NetBSD-specific;
+ * do not assume that they correspond to AF_ values for your operating
+ * system.
+ */
+#define DLT_CLASS_NETBSD_RAWAF 0x02240000
+#define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af))
+#define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff)
+#define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
+
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+ u_short code;
+ u_char jt;
+ u_char jf;
+ bpf_u_int32 k;
+};
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+#if __STDC__ || defined(__cplusplus)
+extern int bpf_validate(const struct bpf_insn *, int);
+extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
+#else
+extern int bpf_validate();
+extern u_int bpf_filter();
+#endif
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/libpcap/pcap/namedb.h b/contrib/libpcap/pcap/namedb.h
new file mode 100644
index 0000000..9002c75
--- /dev/null
+++ b/contrib/libpcap/pcap/namedb.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1994, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory 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.
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/namedb.h,v 1.1 2006/10/04 18:09:22 guy Exp $ (LBL)
+ */
+
+#ifndef lib_pcap_namedb_h
+#define lib_pcap_namedb_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * As returned by the pcap_next_etherent()
+ * XXX this stuff doesn't belong in this interface, but this
+ * library already must do name to address translation, so
+ * on systems that don't have support for /etc/ethers, we
+ * export these hooks since they'll
+ */
+struct pcap_etherent {
+ u_char addr[6];
+ char name[122];
+};
+#ifndef PCAP_ETHERS_FILE
+#define PCAP_ETHERS_FILE "/etc/ethers"
+#endif
+struct pcap_etherent *pcap_next_etherent(FILE *);
+u_char *pcap_ether_hostton(const char*);
+u_char *pcap_ether_aton(const char *);
+
+bpf_u_int32 **pcap_nametoaddr(const char *);
+#ifdef INET6
+struct addrinfo *pcap_nametoaddrinfo(const char *);
+#endif
+bpf_u_int32 pcap_nametonetaddr(const char *);
+
+int pcap_nametoport(const char *, int *, int *);
+int pcap_nametoportrange(const char *, int *, int *, int *);
+int pcap_nametoproto(const char *);
+int pcap_nametoeproto(const char *);
+int pcap_nametollc(const char *);
+/*
+ * If a protocol is unknown, PROTO_UNDEF is returned.
+ * Also, pcap_nametoport() returns the protocol along with the port number.
+ * If there are ambiguous entried in /etc/services (i.e. domain
+ * can be either tcp or udp) PROTO_UNDEF is returned.
+ */
+#define PROTO_UNDEF -1
+
+/* XXX move these to pcap-int.h? */
+int __pcap_atodn(const char *, bpf_u_int32 *);
+int __pcap_atoin(const char *, bpf_u_int32 *);
+u_short __pcap_nametodnaddr(const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/libpcap/pcap1.h b/contrib/libpcap/pcap/pcap.h
index 08d0c5a..6997a9f 100644
--- a/contrib/libpcap/pcap1.h
+++ b/contrib/libpcap/pcap/pcap.h
@@ -31,22 +31,23 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Header: /tcpdump/master/libpcap/pcap1.h,v 1.2 2004/03/30 14:42:50 mcr Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/pcap.h,v 1.4.2.11 2008-10-06 15:38:39 gianluca Exp $ (LBL)
*/
-#ifndef lib_pcap_h
-#define lib_pcap_h
+#ifndef lib_pcap_pcap_h
+#define lib_pcap_pcap_h
-#ifdef WIN32
-#include <pcap-stdinc.h>
-#else /* WIN32 */
-#include <sys/types.h>
-#include <sys/time.h>
-#endif /* WIN32 */
+#if defined(WIN32)
+ #include <pcap-stdinc.h>
+#elif defined(MSDOS)
+ #include <sys/types.h>
+ #include <sys/socket.h> /* u_int, u_char etc. */
+#else /* UN*X */
+ #include <sys/types.h>
+ #include <sys/time.h>
+#endif /* WIN32/MSDOS/UN*X */
-#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
-#include <pcap-bpf.h>
-#endif
+#include <net/bpf.h>
#include <stdio.h>
@@ -54,8 +55,8 @@
extern "C" {
#endif
-#define PCAP_VERSION_MAJOR 3
-#define PCAP_VERSION_MINOR 0
+#define PCAP_VERSION_MAJOR 2
+#define PCAP_VERSION_MINOR 4
#define PCAP_ERRBUF_SIZE 256
@@ -92,8 +93,8 @@ typedef struct pcap_addr pcap_addr_t;
* introduce a new structure for the new format, if the layout
* of the structure changed;
*
- * send mail to "tcpdump-workers@tcpdump.org", requesting a new
- * magic number for your new capture file format, and, when
+ * send mail to "tcpdump-workers@lists.tcpdump.org", requesting
+ * a new magic number for your new capture file format, and, when
* you get the new magic number, put it in "savefile.c";
*
* use that magic number for save files with the changed file
@@ -103,75 +104,56 @@ typedef struct pcap_addr pcap_addr_t;
* the old file header as well as files with the new file header
* (using the magic number to determine the header format).
*
- * Then supply the changes to "patches@tcpdump.org", so that future
- * versions of libpcap and programs that use it (such as tcpdump) will
- * be able to read your new capture file format.
+ * Then supply the changes as a patch at
+ *
+ * http://sourceforge.net/projects/libpcap/
+ *
+ * so that future versions of libpcap and programs that use it (such as
+ * tcpdump) will be able to read your new capture file format.
*/
-
-enum pcap1_info_types {
- PCAP_DATACAPTURE,
- PCAP_TIMESTAMP,
- PCAP_WALLTIME,
- PCAP_TIMESKEW,
- PCAP_PROBEPLACE, /* aka direction */
- PCAP_COMMENT, /* comment */
-};
-
-struct pcap1_info_container {
- bpf_u_int32 info_len; /* in bytes */
- bpf_u_int32 info_type; /* enum pcap1_info_types */
- unsigned char info_data[0];
-};
-
-struct pcap1_info_timestamp {
- struct pcap1_info_container pic;
- bpf_u_int32 nanoseconds; /* 10^-9 of seconds */
- bpf_u_int32 seconds; /* seconds since Unix epoch - GMT */
- bpf_u_int16 macroseconds; /* 16 bits more of MSB of time */
- bpf_u_int16 sigfigs; /* accuracy of timestamps - LSB bits */
-};
-
-struct pcap1_info_packet {
- struct pcap1_info_container pic;
- bpf_u_int32 caplen; /* length of portion present */
- bpf_u_int32 len; /* length this packet (off wire) */
+struct pcap_file_header {
+ bpf_u_int32 magic;
+ u_short version_major;
+ u_short version_minor;
+ bpf_int32 thiszone; /* gmt to local correction */
+ bpf_u_int32 sigfigs; /* accuracy of timestamps */
+ bpf_u_int32 snaplen; /* max length saved portion of each pkt */
bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
- bpf_u_int32 ifIndex; /* abstracted interface index */
- unsigned char packet_data[0];
-};
-
-enum pcap1_probe {
- INBOUND =1,
- OUTBOUND =2,
- FORWARD =3,
- PREENCAP =4,
- POSTDECAP=5,
};
-struct pcap1_info_probe {
- struct pcap1_info_container pic;
- bpf_u_int32 probeloc; /* enum pcap1_probe */
- unsigned char probe_desc[0];
-};
-
-struct pcap1_info_comment {
- struct pcap1_info_container pic;
- unsigned char comment[0];
-};
-
-struct pcap1_packet_header {
- bpf_u_int32 magic;
- u_short version_major;
- u_short version_minor;
- bpf_u_int32 block_len;
- struct pcap1_info_container pics[0];
-};
+/*
+ * Macros for the value returned by pcap_datalink_ext().
+ *
+ * If LT_FCS_LENGTH_PRESENT(x) is true, the LT_FCS_LENGTH(x) macro
+ * gives the FCS length of packets in the capture.
+ */
+#define LT_FCS_LENGTH_PRESENT(x) ((x) & 0x04000000)
+#define LT_FCS_LENGTH(x) (((x) & 0xF0000000) >> 28)
+#define LT_FCS_DATALINK_EXT(x) ((((x) & 0xF) << 28) | 0x04000000)
+
+typedef enum {
+ PCAP_D_INOUT = 0,
+ PCAP_D_IN,
+ PCAP_D_OUT
+} pcap_direction_t;
/*
- * Each packet in the dump file is prepended with this generic header.
- * This gets around the problem of different headers for different
- * packet interfaces.
+ * Generic per-packet information, as supplied by libpcap.
+ *
+ * The time stamp can and should be a "struct timeval", regardless of
+ * whether your system supports 32-bit tv_sec in "struct timeval",
+ * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit
+ * and 64-bit applications. The on-disk format of savefiles uses 32-bit
+ * tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit
+ * and 64-bit versions of libpcap, even if they're on the same platform,
+ * should supply the appropriate version of "struct timeval", even if
+ * that's not what the underlying packet capture mechanism supplies.
*/
+struct pcap_pkthdr {
+ struct timeval ts; /* time stamp */
+ bpf_u_int32 caplen; /* length of portion present */
+ bpf_u_int32 len; /* length this packet (off wire) */
+};
/*
* As returned by the pcap_stats()
@@ -185,6 +167,39 @@ struct pcap_stat {
#endif /* WIN32 */
};
+#ifdef MSDOS
+/*
+ * As returned by the pcap_stats_ex()
+ */
+struct pcap_stat_ex {
+ u_long rx_packets; /* total packets received */
+ u_long tx_packets; /* total packets transmitted */
+ u_long rx_bytes; /* total bytes received */
+ u_long tx_bytes; /* total bytes transmitted */
+ u_long rx_errors; /* bad packets received */
+ u_long tx_errors; /* packet transmit problems */
+ u_long rx_dropped; /* no space in Rx buffers */
+ u_long tx_dropped; /* no space available for Tx */
+ u_long multicast; /* multicast packets received */
+ u_long collisions;
+
+ /* detailed rx_errors: */
+ u_long rx_length_errors;
+ u_long rx_over_errors; /* receiver ring buff overflow */
+ u_long rx_crc_errors; /* recv'd pkt with crc error */
+ u_long rx_frame_errors; /* recv'd frame alignment error */
+ u_long rx_fifo_errors; /* recv'r fifo overrun */
+ u_long rx_missed_errors; /* recv'r missed packet */
+
+ /* detailed tx_errors */
+ u_long tx_aborted_errors;
+ u_long tx_carrier_errors;
+ u_long tx_fifo_errors;
+ u_long tx_heartbeat_errors;
+ u_long tx_window_errors;
+ };
+#endif
+
/*
* Item in a list of interfaces.
*/
@@ -212,11 +227,57 @@ struct pcap_addr {
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
const u_char *);
+/*
+ * Error codes for the pcap API.
+ * These will all be negative, so you can check for the success or
+ * failure of a call that returns these codes by checking for a
+ * negative value.
+ */
+#define PCAP_ERROR -1 /* generic error code */
+#define PCAP_ERROR_BREAK -2 /* loop terminated by pcap_breakloop */
+#define PCAP_ERROR_NOT_ACTIVATED -3 /* the capture needs to be activated */
+#define PCAP_ERROR_ACTIVATED -4 /* the operation can't be performed on already activated captures */
+#define PCAP_ERROR_NO_SUCH_DEVICE -5 /* no such device exists */
+#define PCAP_ERROR_RFMON_NOTSUP -6 /* this device doesn't support rfmon (monitor) mode */
+#define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */
+#define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */
+#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */
+
+/*
+ * Warning codes for the pcap API.
+ * These will all be positive and non-zero, so they won't look like
+ * errors.
+ */
+#define PCAP_WARNING 1 /* generic warning code */
+#define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */
+
char *pcap_lookupdev(char *);
int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+
+pcap_t *pcap_create(const char *, char *);
+int pcap_set_snaplen(pcap_t *, int);
+int pcap_set_promisc(pcap_t *, int);
+int pcap_can_set_rfmon(pcap_t *);
+int pcap_set_rfmon(pcap_t *, int);
+int pcap_set_timeout(pcap_t *, int);
+int pcap_set_buffer_size(pcap_t *, int);
+int pcap_activate(pcap_t *);
+
pcap_t *pcap_open_live(const char *, int, int, int, char *);
pcap_t *pcap_open_dead(int, int);
pcap_t *pcap_open_offline(const char *, char *);
+#if defined(WIN32)
+pcap_t *pcap_hopen_offline(intptr_t, char *);
+#if !defined(LIBPCAP_EXPORTS)
+#define pcap_fopen_offline(f,b) \
+ pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
+#else /*LIBPCAP_EXPORTS*/
+static pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif
+#else /*WIN32*/
+pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif /*WIN32*/
+
void pcap_close(pcap_t *);
int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
@@ -226,19 +287,27 @@ int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
void pcap_breakloop(pcap_t *);
int pcap_stats(pcap_t *, struct pcap_stat *);
int pcap_setfilter(pcap_t *, struct bpf_program *);
+int pcap_setdirection(pcap_t *, pcap_direction_t);
int pcap_getnonblock(pcap_t *, char *);
int pcap_setnonblock(pcap_t *, int, char *);
-void pcap_perror(pcap_t *, char *);
-char *pcap_strerror(int);
+int pcap_inject(pcap_t *, const void *, size_t);
+int pcap_sendpacket(pcap_t *, const u_char *, int);
+const char *pcap_statustostr(int);
+const char *pcap_strerror(int);
char *pcap_geterr(pcap_t *);
-int pcap_compile(pcap_t *, struct bpf_program *, char *, int,
+void pcap_perror(pcap_t *, char *);
+int pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
bpf_u_int32);
int pcap_compile_nopcap(int, int, struct bpf_program *,
- char *, int, bpf_u_int32);
+ const char *, int, bpf_u_int32);
void pcap_freecode(struct bpf_program *);
+int pcap_offline_filter(struct bpf_program *, const struct pcap_pkthdr *,
+ const u_char *);
int pcap_datalink(pcap_t *);
+int pcap_datalink_ext(pcap_t *);
int pcap_list_datalinks(pcap_t *, int **);
int pcap_set_datalink(pcap_t *, int);
+void pcap_free_datalinks(int *);
int pcap_datalink_name_to_val(const char *);
const char *pcap_datalink_val_to_name(int);
const char *pcap_datalink_val_to_description(int);
@@ -252,10 +321,12 @@ FILE *pcap_file(pcap_t *);
int pcap_fileno(pcap_t *);
pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
+FILE *pcap_dump_file(pcap_dumper_t *);
+long pcap_dump_ftell(pcap_dumper_t *);
int pcap_dump_flush(pcap_dumper_t *);
void pcap_dump_close(pcap_dumper_t *);
void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
-FILE *pcap_dump_file(pcap_dumper_t *);
int pcap_findalldevs(pcap_if_t **, char *);
void pcap_freealldevs(pcap_if_t *);
@@ -263,37 +334,49 @@ void pcap_freealldevs(pcap_if_t *);
const char *pcap_lib_version(void);
/* XXX this guy lives in the bpf tree */
-u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
+u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
int bpf_validate(struct bpf_insn *f, int len);
char *bpf_image(struct bpf_insn *, int);
void bpf_dump(struct bpf_program *, int);
-#ifdef WIN32
+#if defined(WIN32)
+
/*
* Win32 definitions
*/
int pcap_setbuff(pcap_t *p, int dim);
int pcap_setmode(pcap_t *p, int mode);
-int pcap_sendpacket(pcap_t *p, u_char *buf, int size);
int pcap_setmintocopy(pcap_t *p, int size);
#ifdef WPCAP
/* Include file with the wpcap-specific extensions */
#include <Win32-Extensions.h>
-#endif
+#endif /* WPCAP */
#define MODE_CAPT 0
#define MODE_STAT 1
+#define MODE_MON 2
+
+#elif defined(MSDOS)
+
+/*
+ * MS-DOS definitions
+ */
+
+int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
+void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
+u_long pcap_mac_packets (void);
+
+#else /* UN*X */
-#else
/*
* UN*X definitions
*/
int pcap_get_selectable_fd(pcap_t *);
-#endif /* WIN32 */
+#endif /* WIN32/MSDOS/UN*X */
#ifdef __cplusplus
}
diff --git a/contrib/libpcap/sll.h b/contrib/libpcap/pcap/sll.h
index 85a3a9d..e9d5452 100644
--- a/contrib/libpcap/sll.h
+++ b/contrib/libpcap/pcap/sll.h
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Header: /tcpdump/master/libpcap/sll.h,v 1.7 2002/06/11 17:04:48 itojun Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/sll.h,v 1.2.2.1 2008-05-30 01:36:06 guy Exp $ (LBL)
*/
/*
@@ -64,8 +64,8 @@
* DO NOT change the layout of this structure, or change any of the
* LINUX_SLL_ values below. If you must change the link-layer header
* for a "cooked" Linux capture, introduce a new DLT_ type (ask
- * "tcpdump-workers@tcpdump.org" for one, so that you don't give it a
- * value that collides with a value already being used), and use the
+ * "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it
+ * a value that collides with a value already being used), and use the
* new header in captures of that type, so that programs that can
* handle DLT_LINUX_SLL captures will continue to handle them correctly
* without any change, and so that capture files with different headers
@@ -73,6 +73,9 @@
* packets in them.
*/
+#ifndef lib_pcap_sll_h
+#define lib_pcap_sll_h
+
/*
* A DLT_LINUX_SLL fake link-layer header.
*/
@@ -122,3 +125,5 @@ struct sll_header {
*/
#define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */
#define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */
+
+#endif
diff --git a/contrib/libpcap/pcap/usb.h b/contrib/libpcap/pcap/usb.h
new file mode 100644
index 0000000..adcd19c
--- /dev/null
+++ b/contrib/libpcap/pcap/usb.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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
+ * OWNER 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.
+ *
+ * Basic USB data struct
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/usb.h,v 1.6 2007/09/22 02:06:08 guy Exp $
+ */
+
+#ifndef _PCAP_USB_STRUCTS_H__
+#define _PCAP_USB_STRUCTS_H__
+
+/*
+ * possible transfer mode
+ */
+#define URB_TRANSFER_IN 0x80
+#define URB_ISOCHRONOUS 0x0
+#define URB_INTERRUPT 0x1
+#define URB_CONTROL 0x2
+#define URB_BULK 0x3
+
+/*
+ * possible event type
+ */
+#define URB_SUBMIT 'S'
+#define URB_COMPLETE 'C'
+#define URB_ERROR 'E'
+
+/*
+ * USB setup header as defined in USB specification.
+ * Appears at the front of each packet in DLT_USB captures.
+ */
+typedef struct _usb_setup {
+ u_int8_t bmRequestType;
+ u_int8_t bRequest;
+ u_int16_t wValue;
+ u_int16_t wIndex;
+ u_int16_t wLength;
+} pcap_usb_setup;
+
+
+/*
+ * Header prepended by linux kernel to each event.
+ * Appears at the front of each packet in DLT_USB_LINUX captures.
+ */
+typedef struct _usb_header {
+ u_int64_t id;
+ u_int8_t event_type;
+ u_int8_t transfer_type;
+ u_int8_t endpoint_number;
+ u_int8_t device_address;
+ u_int16_t bus_id;
+ char setup_flag;/*if !=0 the urb setup header is not present*/
+ char data_flag; /*if !=0 no urb data is present*/
+ int64_t ts_sec;
+ int32_t ts_usec;
+ int32_t status;
+ u_int32_t urb_len;
+ u_int32_t data_len; /* amount of urb data really present in this event*/
+ pcap_usb_setup setup;
+} pcap_usb_header;
+
+
+#endif
diff --git a/usr.sbin/sliplogin/pathnames.h b/contrib/libpcap/pcap/vlan.h
index e318f92..b0cb794 100644
--- a/usr.sbin/sliplogin/pathnames.h
+++ b/contrib/libpcap/pcap/vlan.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1990, 1993
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -10,6 +10,10 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@@ -26,19 +30,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * From: @(#)pathnames.h 8.1 (Berkeley) 6/6/93
- * $FreeBSD$
+ * @(#) $Header: /tcpdump/master/libpcap/pcap/vlan.h,v 1.1.2.2 2008-08-06 07:45:59 guy Exp $
*/
-#ifndef COMPAT
-#include <paths.h>
-#else
-#define _PATH_DEVNULL "/dev/null"
-#endif
+#ifndef lib_pcap_vlan_h
+#define lib_pcap_vlan_h
+
+struct vlan_tag {
+ u_int16_t vlan_tpid; /* ETH_P_8021Q */
+ u_int16_t vlan_tci; /* VLAN TCI */
+};
-#define _PATH_ACCESS "/etc/sliphome/slip.hosts"
-#define _PATH_SLPARMS "/etc/sliphome/slip.slparms"
-#define _PATH_SLIP_LOGIN "/etc/sliphome/slip.login"
-#define _PATH_SLIP_LOGOUT "/etc/sliphome/slip.logout"
-#define _PATH_DEBUG "/tmp/sliplogin.XXXXXX"
+#define VLAN_TAG_LEN 4
+#endif
diff --git a/contrib/libpcap/pcap_activate.3pcap b/contrib/libpcap/pcap_activate.3pcap
new file mode 100644
index 0000000..5b19136
--- /dev/null
+++ b/contrib/libpcap/pcap_activate.3pcap
@@ -0,0 +1,89 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_activate.3pcap,v 1.1.2.5 2008-07-01 08:04:03 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_ACTIVATE 3PCAP "5 April 2008"
+.SH NAME
+pcap_activate \- activate a capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_activate(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_activate()
+is used to activate a packet capture handle to look
+at packets on the network, with the options that were set on the handle
+being in effect.
+.SH RETURN VALUE
+.B pcap_activate()
+returns 0 on success without warnings,
+.B PCAP_WARNING_PROMISC_NOTSUP
+on success on a device that doesn't support promiscuous mode if
+promiscuous mode was requested,
+.B PCAP_WARNING
+on success with any other warning,
+.B PCAP_ERROR_ACTIVATED
+if the handle has already been activated,
+.B PCAP_ERROR_NO_SUCH_DEVICE
+if the capture source specified when the handle was created doesn't
+exist,
+.B PCAP_ERROR_PERM_DENIED
+if the process doesn't have permission to open the capture source,
+.B PCAP_ERROR_RFMON_NOTSUP
+if monitor mode was specified but the capture source doesn't support
+monitor mode,
+.B PCAP_ERROR_IFACE_NOT_UP
+if the capture source is not up, and
+.B PCAP_ERROR
+if another error occurred.
+If
+.B PCAP_WARNING
+or
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display a message describing the warning or
+error.
+If
+.BR PCAP_WARNING_PROMISC_NOTSUP ,
+.BR PCAP_ERROR_NO_SUCH_DEVICE ,
+or
+.B PCAP_ERROR_PERM_DENIED
+is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display an message giving additional details
+about the problem that might be useful for debugging the problem if it's
+unexpected.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_breakloop.3pcap b/contrib/libpcap/pcap_breakloop.3pcap
new file mode 100644
index 0000000..cf78860
--- /dev/null
+++ b/contrib/libpcap/pcap_breakloop.3pcap
@@ -0,0 +1,105 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_breakloop.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_BREAKLOOP 3PCAP "5 April 2008"
+.SH NAME
+pcap_breakloop \- force a pcap_dispatch() or pcap_loop() call to return
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_breakloop(pcap_t *);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_breakloop()
+sets a flag that will force
+.B pcap_dispatch()
+or
+.B pcap_loop()
+to return rather than looping; they will return the number of packets
+that have been processed so far, or \-2 if no packets have been
+processed so far.
+.PP
+This routine is safe to use inside a signal handler on UNIX or a console
+control handler on Windows, as it merely sets a flag that is checked
+within the loop.
+.PP
+The flag is checked in loops reading packets from the OS - a signal by
+itself will not necessarily terminate those loops - as well as in loops
+processing a set of packets returned by the OS.
+.ft B
+Note that if you are catching signals on UNIX systems that support
+restarting system calls after a signal, and calling pcap_breakloop()
+in the signal handler, you must specify, when catching those signals,
+that system calls should NOT be restarted by that signal. Otherwise,
+if the signal interrupted a call reading packets in a live capture,
+when your signal handler returns after calling pcap_breakloop(), the
+call will be restarted, and the loop will not terminate until more
+packets arrive and the call completes.
+.PP
+Note also that, in a multi-threaded application, if one thread is
+blocked in
+.BR pcap_dispatch() ,
+.BR pcap_loop() ,
+.BR pcap_next() ,
+or
+.BR pcap_next_ex() ,
+a call to
+.B pcap_breakloop()
+in a different thread will not unblock that thread; you will need to use
+whatever mechanism the OS provides for breaking a thread out of blocking
+calls in order to unblock the thread, such as thread cancellation in
+systems that support POSIX threads.
+.ft R
+.PP
+Note that
+.B pcap_next()
+and
+.B pcap_next_ex()
+will, on some platforms, loop reading packets from the OS; that loop
+will not necessarily be terminated by a signal, so
+.B pcap_breakloop()
+should be used to terminate packet processing even if
+.B pcap_next()
+or
+.B pcap_next_ex()
+is being used.
+.PP
+.B pcap_breakloop()
+does not guarantee that no further packets will be processed by
+.B pcap_dispatch()
+or
+.B pcap_loop()
+after it is called; at most one more packet might be processed.
+.PP
+If \-2 is returned from
+.B pcap_dispatch()
+or
+.BR pcap_loop() ,
+the flag is cleared, so a subsequent call will resume reading packets.
+If a positive number is returned, the flag is not cleared, so a
+subsequent call will return \-2 and clear the flag.
+.SH SEE ALSO
+pcap(3PCAP), pcap_loop(3PCAP), pcap_next_ex(3PCAP)
diff --git a/contrib/libpcap/pcap_can_set_rfmon.3pcap b/contrib/libpcap/pcap_can_set_rfmon.3pcap
new file mode 100644
index 0000000..992d2c8
--- /dev/null
+++ b/contrib/libpcap/pcap_can_set_rfmon.3pcap
@@ -0,0 +1,60 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_can_set_rfmon.3pcap,v 1.1.2.1 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_CAN_SET_RFMON 3PCAP "5 April 2008"
+.SH NAME
+pcap_can_set_rfmon \- check whether monitor mode can be set for a
+not-yet-activated capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_can_set_rfmon(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_can_set_rfmon()
+checks whether monitor mode could be set on a capture handle when
+the handle is activated.
+.SH RETURN VALUE
+.B pcap_set_rfmon()
+returns 0 if monitor mode could not be set,
+1 if monitor mode could be set,
+.B PCAP_ERROR_NO_SUCH_DEVICE
+if the device specified when the handle was created doesn't exist,
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated, or
+.B PCAP_ERROR
+if an error occurred.
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_set_rfmon(3PCAP)
diff --git a/contrib/libpcap/pcap_close.3pcap b/contrib/libpcap/pcap_close.3pcap
new file mode 100644
index 0000000..3d92f03
--- /dev/null
+++ b/contrib/libpcap/pcap_close.3pcap
@@ -0,0 +1,41 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_close.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_CLOSE 3PCAP "5 April 2008"
+.SH NAME
+pcap_close \- close a capture device or savefile
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_close(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_close()
+closes the files associated with
+.I p
+and deallocates resources.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_compile.3pcap b/contrib/libpcap/pcap_compile.3pcap
new file mode 100644
index 0000000..b0bfee3
--- /dev/null
+++ b/contrib/libpcap/pcap_compile.3pcap
@@ -0,0 +1,72 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_compile.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_COMPILE 3PCAP "5 April 2008"
+.SH NAME
+pcap_compile \- compile a filter expression
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_compile(pcap_t *p, struct bpf_program *fp,
+.ti +8
+const char *str, int optimize, bpf_u_int32 netmask);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_compile()
+is used to compile the string
+.I str
+into a filter program. See
+.BR pcap-filter (7)
+for the syntax of that string.
+.I program
+is a pointer to a
+.I bpf_program
+struct and is filled in by
+.BR pcap_compile() .
+.I optimize
+controls whether optimization on the resulting code is performed.
+.I netmask
+specifies the IPv4 netmask of the network on which packets are being
+captured; it is used only when checking for IPv4 broadcast addresses in
+the filter program. If the netmask of the network on which packets are
+being captured isn't known to the program, or if packets are being
+captured on the Linux "any" pseudo-interface that can capture on more
+than one network, a value of 0 can be supplied; tests for IPv4 broadcast
+addreses won't be done correctly, but all other tests in the filter
+program will be OK.
+.SH RETURN VALUE
+.B pcap_compile()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_setfilter(3PCAP), pcap_freecode(3PCAP),
+pcap_geterr(3PCAP), pcap-filter(7)
diff --git a/contrib/libpcap/pcap_compile.3pcap.in b/contrib/libpcap/pcap_compile.3pcap.in
new file mode 100644
index 0000000..87e2778
--- /dev/null
+++ b/contrib/libpcap/pcap_compile.3pcap.in
@@ -0,0 +1,72 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_compile.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_COMPILE 3PCAP "5 April 2008"
+.SH NAME
+pcap_compile \- compile a filter expression
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_compile(pcap_t *p, struct bpf_program *fp,
+.ti +8
+const char *str, int optimize, bpf_u_int32 netmask);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_compile()
+is used to compile the string
+.I str
+into a filter program. See
+.BR pcap-filter (@MAN_MISC_INFO@)
+for the syntax of that string.
+.I program
+is a pointer to a
+.I bpf_program
+struct and is filled in by
+.BR pcap_compile() .
+.I optimize
+controls whether optimization on the resulting code is performed.
+.I netmask
+specifies the IPv4 netmask of the network on which packets are being
+captured; it is used only when checking for IPv4 broadcast addresses in
+the filter program. If the netmask of the network on which packets are
+being captured isn't known to the program, or if packets are being
+captured on the Linux "any" pseudo-interface that can capture on more
+than one network, a value of 0 can be supplied; tests for IPv4 broadcast
+addreses won't be done correctly, but all other tests in the filter
+program will be OK.
+.SH RETURN VALUE
+.B pcap_compile()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_setfilter(3PCAP), pcap_freecode(3PCAP),
+pcap_geterr(3PCAP), pcap-filter(@MAN_MISC_INFO@)
diff --git a/contrib/libpcap/pcap_create.3pcap b/contrib/libpcap/pcap_create.3pcap
new file mode 100644
index 0000000..32071b3
--- /dev/null
+++ b/contrib/libpcap/pcap_create.3pcap
@@ -0,0 +1,74 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_create.3pcap,v 1.1.2.1 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_CREATE 3PCAP "5 April 2008"
+.SH NAME
+pcap_create \- create a live capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_create(const char *source, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_create()
+is used to create a packet capture handle to look
+at packets on the network.
+.I source
+is a string that specifies the network device to open; on Linux systems
+with 2.2 or later kernels, a
+.I source
+argument of "any" or
+.B NULL
+can be used to capture packets from all interfaces.
+.PP
+The returned handle must be activated with
+.B pcap_activate()
+before packets can be captured
+with it; options for the capture, such as promiscuous mode, can be set
+on the handle before activating it.
+.SH RETURN VALUE
+.B pcap_create()
+returns a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap_activate(3PCAP)
diff --git a/contrib/libpcap/pcap_datalink.3pcap b/contrib/libpcap/pcap_datalink.3pcap
new file mode 100644
index 0000000..06dfdee
--- /dev/null
+++ b/contrib/libpcap/pcap_datalink.3pcap
@@ -0,0 +1,41 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_datalink.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK 3PCAP "5 April 2008"
+.SH NAME
+pcap_datalink \- get the link-layer header type
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_datalink(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink()
+returns the link layer type for the live capture or ``savefile''
+specified by
+.IR p .
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(7)
diff --git a/contrib/libpcap/pcap_datalink.3pcap.in b/contrib/libpcap/pcap_datalink.3pcap.in
new file mode 100644
index 0000000..83426f0
--- /dev/null
+++ b/contrib/libpcap/pcap_datalink.3pcap.in
@@ -0,0 +1,41 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_datalink.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK 3PCAP "5 April 2008"
+.SH NAME
+pcap_datalink \- get the link-layer header type
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_datalink(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink()
+returns the link layer type for the live capture or ``savefile''
+specified by
+.IR p .
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
diff --git a/contrib/libpcap/pcap_datalink_name_to_val.3pcap b/contrib/libpcap/pcap_datalink_name_to_val.3pcap
new file mode 100644
index 0000000..f51b933
--- /dev/null
+++ b/contrib/libpcap/pcap_datalink_name_to_val.3pcap
@@ -0,0 +1,48 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_datalink_name_to_val.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK_NAME_TO_VAL 3PCAP "5 April 2008"
+.SH NAME
+pcap_datalink_name_to_val \- get the link-layer header type value
+corresponding to a header type name
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_datalink_name_to_val(const char *name);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink_name_to_val()
+translates a data link type name, which is a
+.B DLT_
+name with the
+.B DLT_
+removed, to the corresponding data link type value. The translation
+is case-insensitive.
+.SH RETURN VALUE
+.B pcap_datalink_name_to_val()
+returns 0 on success and \-1 on failure.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_datalink_val_to_name.3pcap b/contrib/libpcap/pcap_datalink_val_to_name.3pcap
new file mode 100644
index 0000000..476bf10
--- /dev/null
+++ b/contrib/libpcap/pcap_datalink_val_to_name.3pcap
@@ -0,0 +1,44 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_datalink_val_to_name.3pcap,v 1.1.2.2 2008-05-30 01:32:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK_VAL_TO_NAME 3 "4 April 2008"
+.SH NAME
+pcap_datalink_val_to_name, pcap_datalink_val_to_description \- get a
+name or description for a link-layer header type value
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_datalink_val_to_name(int dlt);
+const char *pcap_datalink_val_to_description(int dlt);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink_val_to_name()
+translates a data link type value to the corresponding data link type
+name. NULL is returned on failure.
+.PP
+.B pcap_datalink_val_to_description()
+translates a data link type value to a short description of that data
+link type. NULL is returned on failure.
diff --git a/contrib/libpcap/pcap_dump.3pcap b/contrib/libpcap/pcap_dump.3pcap
new file mode 100644
index 0000000..1808869
--- /dev/null
+++ b/contrib/libpcap/pcap_dump.3pcap
@@ -0,0 +1,53 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump \- write a packet to a capture file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_dump(u_char *user, struct pcap_pkthdr *h,
+.ti +8
+u_char *sp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump()
+outputs a packet to the ``savefile'' opened with
+.BR pcap_dump_open() .
+Note that its calling arguments are suitable for use with
+.B pcap_dispatch()
+or
+.BR pcap_loop() .
+If called directly, the
+.I user
+parameter is of type
+.B pcap_dumper_t
+as returned by
+.BR pcap_dump_open() .
+.SH SEE ALSO
+pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dispatch(3PCAP),
+pcap_loop(3PCAP)
diff --git a/contrib/libpcap/pcap_dump_close.3pcap b/contrib/libpcap/pcap_dump_close.3pcap
new file mode 100644
index 0000000..07b690a
--- /dev/null
+++ b/contrib/libpcap/pcap_dump_close.3pcap
@@ -0,0 +1,39 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_close.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_CLOSE 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump_close \- close a savefile being written to
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_dump_close(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_close()
+closes the ``savefile.''
+.SH SEE ALSO
+pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
diff --git a/contrib/libpcap/pcap_dump_file.3pcap b/contrib/libpcap/pcap_dump_file.3pcap
new file mode 100644
index 0000000..5cf0de6
--- /dev/null
+++ b/contrib/libpcap/pcap_dump_file.3pcap
@@ -0,0 +1,40 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_file.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_FILE 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump_file \- get the standard I/O stream for a savefile being written
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+FILE *pcap_dump_file(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_file()
+returns the standard I/O stream of the ``savefile'' opened by
+.BR pcap_dump_open() .
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_dump_flush.3pcap b/contrib/libpcap/pcap_dump_flush.3pcap
new file mode 100644
index 0000000..e83e2a0
--- /dev/null
+++ b/contrib/libpcap/pcap_dump_flush.3pcap
@@ -0,0 +1,45 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_flush.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_FLUSH 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump_flush \- flush to a savefile packets dumped
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_dump_flush(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_flush()
+flushes the output buffer to the ``savefile,'' so that any packets
+written with
+.B pcap_dump()
+but not yet written to the ``savefile'' will be written.
+.SH RETURN VALUE
+.B pcap_dump_flush()
+returns 0 on success and \-1 on failure.
+.SH SEE ALSO
+pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
diff --git a/contrib/libpcap/pcap_dump_ftell.3pcap b/contrib/libpcap/pcap_dump_ftell.3pcap
new file mode 100644
index 0000000..d9c3600
--- /dev/null
+++ b/contrib/libpcap/pcap_dump_ftell.3pcap
@@ -0,0 +1,44 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_ftell.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_FTELL 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump_ftell \- get the current file offset for a savefile being written
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+long pcap_dump_ftell(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_ftell()
+returns the current file position for the ``savefile'', representing the
+number of bytes written by
+.B pcap_dump_open()
+and
+.BR pcap_dump() .
+\-1 is returned on error.
+.SH SEE ALSO
+pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
diff --git a/contrib/libpcap/pcap_dump_open.3pcap b/contrib/libpcap/pcap_dump_open.3pcap
new file mode 100644
index 0000000..70aa932
--- /dev/null
+++ b/contrib/libpcap/pcap_dump_open.3pcap
@@ -0,0 +1,87 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_open.3pcap.in,v 1.1.2.2 2008-10-23 05:59:43 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_OPEN 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.nf
+.LP
+.ft B
+pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_open()
+is called to open a ``savefile'' for writing.
+.I fname
+specifies the name of the file to open. The file will have
+the same format as those used by
+.BR tcpdump (1)
+and
+.BR tcpslice (1).
+The name "-" in a synonym
+for
+.BR stdout .
+.PP
+.B pcap_dump_fopen()
+is called to write data to an existing open stream
+.IR fp .
+Note that on Windows, that stream should be opened in binary mode.
+.PP
+.I p
+is a capture or ``savefile'' handle returned by an earlier call to
+.B pcap_create()
+and activated by an earlier call to
+.BR pcap_activate() ,
+or returned by an earlier call to
+.BR pcap_open_offline() ,
+.BR pcap_open_live() ,
+or
+.BR pcap_open_dead() .
+The link-layer type and snapshot length from
+.I p
+are used as the link-layer type and snapshot length of the output file.
+.SH RETURN VALUES
+A pointer to a
+.B pcap_dumper_t
+structure to use in subsequent
+.B pcap_dump()
+and
+.B pcap_dump_close()
+calls is returned on success.
+.B NULL
+is returned on failure.
+If
+.B NULL
+is returned,
+.B pcap_geterr(\fIp\fB)
+can be used to get the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_open_offline(3PCAP), pcap_open_live(3PCAP), pcap_open_dead(3PCAP),
+pcap_dump(3PCAP), pcap_dump_close(3PCAP), pcap_geterr(3PCAP),
+pcap-savefile(5)
diff --git a/contrib/libpcap/pcap_dump_open.3pcap.in b/contrib/libpcap/pcap_dump_open.3pcap.in
new file mode 100644
index 0000000..9fe116b
--- /dev/null
+++ b/contrib/libpcap/pcap_dump_open.3pcap.in
@@ -0,0 +1,87 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_dump_open.3pcap.in,v 1.1.2.2 2008-10-23 05:59:43 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_OPEN 3PCAP "5 April 2008"
+.SH NAME
+pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.nf
+.LP
+.ft B
+pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_open()
+is called to open a ``savefile'' for writing.
+.I fname
+specifies the name of the file to open. The file will have
+the same format as those used by
+.BR tcpdump (1)
+and
+.BR tcpslice (1).
+The name "-" in a synonym
+for
+.BR stdout .
+.PP
+.B pcap_dump_fopen()
+is called to write data to an existing open stream
+.IR fp .
+Note that on Windows, that stream should be opened in binary mode.
+.PP
+.I p
+is a capture or ``savefile'' handle returned by an earlier call to
+.B pcap_create()
+and activated by an earlier call to
+.BR pcap_activate() ,
+or returned by an earlier call to
+.BR pcap_open_offline() ,
+.BR pcap_open_live() ,
+or
+.BR pcap_open_dead() .
+The link-layer type and snapshot length from
+.I p
+are used as the link-layer type and snapshot length of the output file.
+.SH RETURN VALUES
+A pointer to a
+.B pcap_dumper_t
+structure to use in subsequent
+.B pcap_dump()
+and
+.B pcap_dump_close()
+calls is returned on success.
+.B NULL
+is returned on failure.
+If
+.B NULL
+is returned,
+.B pcap_geterr(\fIp\fB)
+can be used to get the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_open_offline(3PCAP), pcap_open_live(3PCAP), pcap_open_dead(3PCAP),
+pcap_dump(3PCAP), pcap_dump_close(3PCAP), pcap_geterr(3PCAP),
+pcap-savefile(@MAN_FILE_FORMATS@)
diff --git a/contrib/libpcap/pcap_file.3pcap b/contrib/libpcap/pcap_file.3pcap
new file mode 100644
index 0000000..b74e502
--- /dev/null
+++ b/contrib/libpcap/pcap_file.3pcap
@@ -0,0 +1,59 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_file.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FILE 3PCAP "5 April 2008"
+.SH NAME
+pcap_file \- get the standard I/O stream for a savefile being read
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+FILE *pcap_file(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_file()
+returns the standard I/O stream of the ``savefile,'' if a ``savefile''
+was opened with
+.BR pcap_open_offline() ,
+or NULL, if a network device was opened with
+.B pcap_create()
+and
+.BR pcap_activate() ,
+or with
+.BR pcap_open_live() .
+.PP
+Note that the Packet Capture library is usually built with large file
+support, so the standard I/O stream of the ``savefile'' might refer to
+a file larger than 2 gigabytes; applications that use
+.B pcap_file()
+should, if possible, use calls that support large files on the return
+value of
+.B pcap_file()
+or the value returned by
+.B fileno()
+when passed the return value of
+.BR pcap_file() .
+.SH SEE ALSO
+pcap(3PCAP), pcap_open_offline(3PCAP)
diff --git a/contrib/libpcap/pcap_fileno.3pcap b/contrib/libpcap/pcap_fileno.3pcap
new file mode 100644
index 0000000..9c05be0
--- /dev/null
+++ b/contrib/libpcap/pcap_fileno.3pcap
@@ -0,0 +1,47 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_fileno.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FILENO 3PCAP "5 April 2008"
+.SH NAME
+pcap_fileno \- get the file descriptor for a live capture
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_fileno(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_fileno()
+returns the file descriptor number from which captured packets are read,
+if a network device was opened with
+.B pcap_create()
+and
+.B pcap_activate()
+or with
+.BR pcap_open_live() ,
+or \-1, if a ``savefile'' was opened with
+.BR pcap_open_offline() .
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/contrib/libpcap/pcap_findalldevs.3pcap b/contrib/libpcap/pcap_findalldevs.3pcap
new file mode 100644
index 0000000..93c0455
--- /dev/null
+++ b/contrib/libpcap/pcap_findalldevs.3pcap
@@ -0,0 +1,156 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_findalldevs.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FINDALLDEVS 3PCAP "5 April 2008"
+.SH NAME
+pcap_findalldevs \- get a list of capture devices
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_findalldevs()
+constructs a list of network devices that can be opened with
+.B pcap_create()
+and
+.B pcap_activate()
+or with
+.BR pcap_open_live() .
+(Note that there may be network devices that cannot be opened by the
+process calling
+.BR pcap_findalldevs() ,
+because, for example, that process might not have sufficient privileges
+to open them for capturing; if so, those devices will not appear on the
+list.)
+.I alldevsp
+is set to point to the first element of the list; each element of the
+list is of type
+.BR pcap_if_t ,
+and has the following members:
+.RS
+.TP
+.B next
+if not
+.BR NULL ,
+a pointer to the next element in the list;
+.B NULL
+for the last element of the list
+.TP
+.B name
+a pointer to a string giving a name for the device to pass to
+.B pcap_open_live()
+.TP
+.B description
+if not
+.BR NULL ,
+a pointer to a string giving a human-readable description of the device
+.TP
+.B addresses
+a pointer to the first element of a list of addresses for the interface
+.TP
+.B flags
+interface flags:
+.RS
+.TP
+.B PCAP_IF_LOOPBACK
+set if the interface is a loopback interface
+.RE
+.RE
+.PP
+Each element of the list of addresses is of type
+.BR pcap_addr_t ,
+and has the following members:
+.RS
+.TP
+.B next
+if not
+.BR NULL ,
+a pointer to the next element in the list;
+.B NULL
+for the last element of the list
+.TP
+.B addr
+a pointer to a
+.B "struct sockaddr"
+containing an address
+.TP
+.B netmask
+if not
+.BR NULL ,
+a pointer to a
+.B "struct sockaddr"
+that contains the netmask corresponding to the address pointed to by
+.B addr
+.TP
+.B broadaddr
+if not
+.BR NULL ,
+a pointer to a
+.B "struct sockaddr"
+that contains the broadcast address corresponding to the address pointed
+to by
+.BR addr ;
+may be null if the interface doesn't support broadcasts
+.TP
+.B dstaddr
+if not
+.BR NULL ,
+a pointer to a
+.B "struct sockaddr"
+that contains the destination address corresponding to the address pointed
+to by
+.BR addr ;
+may be null if the interface isn't a point-to-point interface
+.RE
+.PP
+Note that not all the addresses in the list of addresses are
+necessarily IPv4 or IPv6 addresses - you must check the
+.B sa_family
+member of the
+.B "struct sockaddr"
+before interpreting the contents of the address.
+.PP
+The list of devices must be freed with
+.BR pcap_freealldevs() .
+.SH RETURN VALUE
+.B pcap_findalldevs()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_open_live(3PCAP), pcap_freealldevs(3PCAP)
diff --git a/contrib/libpcap/pcap_free_datalinks.3pcap b/contrib/libpcap/pcap_free_datalinks.3pcap
new file mode 100644
index 0000000..8bb7899
--- /dev/null
+++ b/contrib/libpcap/pcap_free_datalinks.3pcap
@@ -0,0 +1,41 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_free_datalinks.3pcap,v 1.1.2.1 2008-05-26 19:58:59 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FREE_DATALINKS 3PCAP "26 May 2008"
+.SH NAME
+pcap_free_datalinks \- free a list of link-layer header types from
+pcap_get_datalinks()
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_free_datalinks(int *dlt_list);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_free_datalinks()
+is used to free a list of supported data link types returned by
+.BR pcap_list_datalinks() .
+.SH SEE ALSO
+pcap(3PCAP), pcap_list_datalinks(3PCAP)
diff --git a/contrib/libpcap/pcap_freealldevs.3pcap b/contrib/libpcap/pcap_freealldevs.3pcap
new file mode 100644
index 0000000..09d4706
--- /dev/null
+++ b/contrib/libpcap/pcap_freealldevs.3pcap
@@ -0,0 +1,40 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_freealldevs.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FREEALLDEVS 3PCAP "5 April 2008"
+.SH NAME
+pcap_freealldevs \- free a list of capture devices
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_freealldevs(pcap_if_t *alldevs);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_freealldevs()
+is used to free a list allocated by
+.BR pcap_findalldevs() .
+.SH SEE ALSO
+pcap(3PCAP), pcap_findalldevs(3PCAP)
diff --git a/contrib/libpcap/pcap_freecode.3pcap b/contrib/libpcap/pcap_freecode.3pcap
new file mode 100644
index 0000000..061b506
--- /dev/null
+++ b/contrib/libpcap/pcap_freecode.3pcap
@@ -0,0 +1,45 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_freecode.3pcap,v 1.1.2.3 2008-04-06 03:21:55 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FREECODE 3PCAP "5 April 2008"
+.SH NAME
+pcap_freecode \- free a BPF program
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_freecode(struct bpf_program *);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_freecode()
+is used to free up allocated memory pointed to by a
+.I bpf_program
+struct generated by
+.B pcap_compile()
+when that BPF program is no longer needed, for example after it
+has been made the filter program for a pcap structure by a call to
+.BR pcap_setfilter() .
+.SH SEE ALSO
+pcap(3PCAP), pcap_compile(3PCAP), pcap_setfilter(3PCAP)
diff --git a/contrib/libpcap/pcap_get_selectable_fd.3pcap b/contrib/libpcap/pcap_get_selectable_fd.3pcap
new file mode 100644
index 0000000..9026f45
--- /dev/null
+++ b/contrib/libpcap/pcap_get_selectable_fd.3pcap
@@ -0,0 +1,114 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_get_selectable_fd.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_GET_SELECTABLE_FD 3PCAP "5 April 2008"
+.SH NAME
+pcap_get_selectable_fd \- get a file descriptor on which a select() can
+be done for a live capture
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_get_selectable_fd(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_get_selectable_fd()
+returns, on UNIX, a file descriptor number for a file descriptor on
+which one can
+do a
+.B select()
+or
+.B poll()
+to wait for it to be possible to read packets without blocking, if such
+a descriptor exists, or \-1, if no such descriptor exists. Some network
+devices opened with
+.B pcap_create()
+and
+.BR pcap_activate() ,
+or with
+.BR pcap_open_live() ,
+do not support
+.B select()
+or
+.B poll()
+(for example, regular network devices on FreeBSD 4.3 and 4.4, and Endace
+DAG devices), so \-1 is returned for those devices.
+.PP
+Note that on most versions of most BSDs (including Mac OS X)
+.B select()
+and
+.B poll()
+do not work correctly on BPF devices;
+.B pcap_get_selectable_fd()
+will return a file descriptor on most of those versions (the exceptions
+being FreeBSD 4.3 and 4.4), a simple
+.B select()
+or
+.B poll()
+will not return even after the read timeout expires. To work around
+this, an application that uses
+.B select()
+or
+.B poll()
+to wait for packets to arrive must put the
+.B pcap_t
+in non-blocking mode, and must arrange that the
+.B select()
+or
+.B poll()
+have a timeout less than or equal to the read timeout,
+and must try to read packets after that timeout expires, regardless of
+whether
+.B select()
+or
+.B poll()
+indicated that the file descriptor for the
+.B pcap_t
+is ready to be read or not. (That workaround will not work in FreeBSD
+4.3 and later; however, in FreeBSD 4.6 and later,
+.B select()
+and
+.B poll()
+work correctly on BPF devices, so the workaround isn't necessary,
+although it does no harm.)
+.PP
+Note also that
+.B poll()
+doesn't work on character special files, including BPF devices, in Mac
+OS X 10.4 and 10.5, so, while
+.B select()
+can be used on the descriptor returned by
+.BR pcap_get_selectable_fd() ,
+.B poll()
+cannot be used on it those versions of Mac OS X. Kqueues also don't
+work on that descriptor.
+.PP
+.B pcap_get_selectable_fd()
+is not available on Windows.
+.SH RETURN VALUE
+A selectable file descriptor is returned if one exists; otherwise, \-1
+is returned.
+.SH SEE ALSO
+pcap(3PCAP), select(2), poll(2)
diff --git a/contrib/libpcap/pcap_geterr.3pcap b/contrib/libpcap/pcap_geterr.3pcap
new file mode 100644
index 0000000..9a46a83
--- /dev/null
+++ b/contrib/libpcap/pcap_geterr.3pcap
@@ -0,0 +1,53 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_geterr.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_GETERR 3PCAP "5 April 2008"
+.SH NAME
+pcap_geterr, pcap_perror \- get or print libpcap error message text
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+char *pcap_geterr(pcap_t *p);
+void pcap_perror(pcap_t *p, char *prefix);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_geterr()
+returns the error text pertaining to the last pcap library error.
+.BR NOTE :
+the pointer it returns will no longer point to a valid error message
+string after the
+.B pcap_t
+passed to it is closed; you must use or copy the string before closing
+the
+.BR pcap_t .
+.PP
+.B pcap_perror()
+prints the text of the last pcap library error on
+.BR stderr ,
+prefixed by
+.IR prefix .
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_inject.3pcap b/contrib/libpcap/pcap_inject.3pcap
new file mode 100644
index 0000000..954984c
--- /dev/null
+++ b/contrib/libpcap/pcap_inject.3pcap
@@ -0,0 +1,90 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_inject.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_INJECT 3PCAP "5 April 2008"
+.SH NAME
+pcap_inject, pcap_sendpacket \- transmit a packet
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_inject(pcap_t *p, const void *buf, size_t size);
+int pcap_sendpacket(pcap_t *p, const u_char *buf, int size);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_inject()
+sends a raw packet through the network interface;
+.I buf
+points to the data of the packet, including the link-layer header, and
+.I size
+is the number of bytes in the packet.
+.PP
+Note that, even if you successfully open the network interface, you
+might not have permission to send packets on it, or it might not support
+sending packets; as
+.I pcap_open_live()
+doesn't have a flag to indicate whether to open for capturing, sending,
+or capturing and sending, you cannot request an open that supports
+sending and be notified at open time whether sending will be possible.
+Note also that some devices might not support sending packets.
+.PP
+Note that, on some platforms, the link-layer header of the packet that's
+sent might not be the same as the link-layer header of the packet
+supplied to
+.BR pcap_inject() ,
+as the source link-layer address, if the header contains such an
+address, might be changed to be the address assigned to the interface on
+which the packet it sent, if the platform doesn't support sending
+completely raw and unchanged packets. Even worse, some drivers on some
+platforms might change the link-layer type field to whatever value
+libpcap used when attaching to the device, even on platforms that
+.I do
+nominally support sending completely raw and unchanged packets.
+.PP
+.B pcap_sendpacket()
+is like
+.BR pcap_inject() ,
+but it returns 0 on success, rather than returning the number of bytes
+written.
+.RB ( pcap_inject()
+comes from OpenBSD;
+.B pcap_sendpacket()
+comes from WinPcap. Both are provided for compatibility.)
+.SH RETURN VALUE
+.B pcap_inject()
+returns the number of bytes written on success and \-1 on failure.
+.PP
+.B pcap_sendpacket()
+returns 0 on success and \-1 on failure.
+.PP
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP)
diff --git a/contrib/libpcap/pcap_is_swapped.3pcap b/contrib/libpcap/pcap_is_swapped.3pcap
new file mode 100644
index 0000000..6cc7089
--- /dev/null
+++ b/contrib/libpcap/pcap_is_swapped.3pcap
@@ -0,0 +1,42 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_is_swapped.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_IS_SWAPPED 3PCAP "5 April 2008"
+.SH NAME
+pcap_is_swapped \- find out whether a savefile has the native byte order
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_is_swapped(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_is_swapped()
+returns true if
+.I p
+refers to a ``savefile'' that uses a different byte order
+than the current system. For a live capture, it always returns false.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_lib_version.3pcap b/contrib/libpcap/pcap_lib_version.3pcap
new file mode 100644
index 0000000..fff9149
--- /dev/null
+++ b/contrib/libpcap/pcap_lib_version.3pcap
@@ -0,0 +1,41 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_lib_version.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LIB_VERSION 3PCAP "5 April 2008"
+.SH NAME
+pcap_lib_version \- get the version information for libpcap
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_lib_version(void);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_lib_version()
+returns a pointer to a string giving information about the version of
+the libpcap library being used; note that it contains more information
+than just a version number.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_list_datalinks.3pcap b/contrib/libpcap/pcap_list_datalinks.3pcap
new file mode 100644
index 0000000..4e73196
--- /dev/null
+++ b/contrib/libpcap/pcap_list_datalinks.3pcap
@@ -0,0 +1,58 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_list_datalinks.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LIST_DATALINKS 3PCAP "5 April 2008"
+.SH NAME
+pcap_list_datalinks \- get a list of link-layer header types supported
+by a capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_list_datalinks(pcap_t *p, int **dlt_buf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_list_datalinks()
+is used to get a list of the supported data link types of the interface
+associated with the pcap descriptor.
+.B pcap_list_datalinks()
+allocates an array to hold the list and sets
+.IR *dlt_buf .
+The caller is responsible for freeing the array with
+.BR pcap_free_datalinks (3PCAP).
+.SH RETURN VALUE
+.B pcap_list_datalinks()
+returns the number of data link types in the array on success and \-1
+on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP), pcap_free_datalinks(3PCAP),
+pcap-linktype(7)
diff --git a/contrib/libpcap/pcap_list_datalinks.3pcap.in b/contrib/libpcap/pcap_list_datalinks.3pcap.in
new file mode 100644
index 0000000..822c70c
--- /dev/null
+++ b/contrib/libpcap/pcap_list_datalinks.3pcap.in
@@ -0,0 +1,58 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_list_datalinks.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LIST_DATALINKS 3PCAP "5 April 2008"
+.SH NAME
+pcap_list_datalinks \- get a list of link-layer header types supported
+by a capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_list_datalinks(pcap_t *p, int **dlt_buf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_list_datalinks()
+is used to get a list of the supported data link types of the interface
+associated with the pcap descriptor.
+.B pcap_list_datalinks()
+allocates an array to hold the list and sets
+.IR *dlt_buf .
+The caller is responsible for freeing the array with
+.BR pcap_free_datalinks (3PCAP).
+.SH RETURN VALUE
+.B pcap_list_datalinks()
+returns the number of data link types in the array on success and \-1
+on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP), pcap_free_datalinks(3PCAP),
+pcap-linktype(@MAN_MISC_INFO@)
diff --git a/contrib/libpcap/pcap_lookupdev.3pcap b/contrib/libpcap/pcap_lookupdev.3pcap
new file mode 100644
index 0000000..2d80bf5
--- /dev/null
+++ b/contrib/libpcap/pcap_lookupdev.3pcap
@@ -0,0 +1,62 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_lookupdev.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LOOKUPDEV 3PCAP "5 April 2008"
+.SH NAME
+pcap_lookupdev \- find the default device on which to capture
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+char *pcap_lookupdev(char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_lookupdev()
+returns a pointer to a string giving the name of a network device
+suitable for use with
+.B pcap_create()
+and
+.BR pcap_activate() ,
+or with
+.BR pcap_open_live() ,
+and with
+.BR pcap_lookupnet() .
+If there is an error,
+.B NULL
+is returned and
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_open_live(3PCAP), pcap_lookupnet(3PCAP)
diff --git a/contrib/libpcap/pcap_lookupnet.3pcap b/contrib/libpcap/pcap_lookupnet.3pcap
new file mode 100644
index 0000000..031acb7
--- /dev/null
+++ b/contrib/libpcap/pcap_lookupnet.3pcap
@@ -0,0 +1,65 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_lookupnet.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LOOKUPNET 3PCAP "5 April 2008"
+.SH NAME
+pcap_lookupnet \- find the IPv4 network number and netmask for a device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+int pcap_lookupnet(const char *device, bpf_u_int32 *netp,
+.ti +8
+bpf_u_int32 *maskp, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_lookupnet()
+is used to determine the IPv4 network number and mask
+associated with the network device
+.IR device .
+Both
+.I netp
+and
+.I maskp
+are
+.I bpf_u_int32
+pointers.
+.SH RETURN VALUE
+.B pcap_lookupnet()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_loop.3pcap b/contrib/libpcap/pcap_loop.3pcap
new file mode 100644
index 0000000..8e491d4
--- /dev/null
+++ b/contrib/libpcap/pcap_loop.3pcap
@@ -0,0 +1,150 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_loop.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LOOP 3PCAP "5 April 2008"
+.SH NAME
+pcap_loop, pcap_dispatch \- process packets from a live capture or savefile
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h,
+.ti +8
+ const u_char *bytes);
+.ft
+.LP
+.ft B
+int pcap_loop(pcap_t *p, int cnt,
+.ti +8
+pcap_handler callback, u_char *user);
+int pcap_dispatch(pcap_t *p, int cnt,
+.ti +8
+pcap_handler callback, u_char *user);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_loop()
+processes packets from a live capture or ``savefile'' until
+.I cnt
+packets are processed, the end of the ``savefile'' is
+reached when reading from a ``savefile'',
+.B pcap_breakloop()
+is called, or an error occurs.
+It does
+.B not
+return when live read timeouts occur.
+A value of \-1 or 0 for
+.I cnt
+is equivalent to infinity, so that packets are processed until another
+ending condition occurs.
+.PP
+.B pcap_dispatch()
+processes packets from a live capture or ``savefile'' until
+.I cnt
+packets are processed, the end of the current bufferful of packets is
+reached when doing a live capture, the end of the ``savefile'' is
+reached when reading from a ``savefile'',
+.B pcap_breakloop()
+is called, or an error occurs.
+Thus, when doing a live capture,
+.I cnt
+is the maximum number of packets to process before returning, but is not
+a minimum number; when reading a live capture, only one
+bufferful of packets is read at a time, so fewer than
+.I cnt
+packets may be processed. A value of \-1 or 0 for
+.I cnt
+causes all the packets received in one buffer to be processed when
+reading a live capture, and causes all the packets in the file to be
+processed when reading a ``savefile''.
+.PP
+.ft B
+(In older versions of libpcap, the behavior when
+\fIcnt\fP
+was 0 was undefined; different platforms and devices behaved
+differently, so code that must work with older versions of libpcap
+should use \-1, nor 0, as the value of
+\fIcnt\fP.)
+.ft R
+.PP
+.I callback
+specifies a routine to be called with three arguments:
+a
+.I u_char
+pointer which is passed in the
+.I user
+argument to
+.B pcap_loop()
+or
+.BR pcap_dispatch() ,
+a
+.I const struct pcap_pkthdr
+pointer pointing to the packet time stamp and lengths, and a
+.I const u_char
+pointer to the first
+.B caplen
+(as given in the
+.I struct pcap_pkthdr
+a pointer to which is passed to the callback routine)
+bytes of data from the packet.
+.SH RETURN VALUE
+.B pcap_loop()
+returns 0 if
+.I cnt
+is exhausted, \-1 if an error occurs, or \-2 if the loop terminated due
+to a call to
+.B pcap_breakloop()
+before any packets were processed.
+It does
+.B not
+return when live read timeouts occur; instead, it attempts to read more
+packets.
+.PP
+.B pcap_dispatch()
+returns the number of packets processed on success; this can be 0 if no
+packets were read from a live capture (if, for example, they were
+discarded because they didn't pass the packet filter, or if, on
+platforms that support a read timeout that starts before any packets
+arrive, the timeout expires before any packets arrive, or if the file
+descriptor for the capture device is in non-blocking mode and no packets
+were available to be read) or if no more packets are available in a
+``savefile.'' It returns \-1 if an error occurs or \-2 if the loop
+terminated due to a call to
+.B pcap_breakloop()
+before any packets were processed.
+.ft B
+If your application uses pcap_breakloop(),
+make sure that you explicitly check for \-1 and \-2, rather than just
+checking for a return value < 0.
+.ft R
+.PP
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP), pcap_breakloop(3PCAP)
diff --git a/contrib/libpcap/pcap_major_version.3pcap b/contrib/libpcap/pcap_major_version.3pcap
new file mode 100644
index 0000000..1eabcf0
--- /dev/null
+++ b/contrib/libpcap/pcap_major_version.3pcap
@@ -0,0 +1,54 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_major_version.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_MAJOR_VERSION 3PCAP "5 April 2008"
+.SH NAME
+pcap_major_version, pcap_minor_version \- get the version number of a savefile
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_major_version(pcap_t *p);
+int pcap_minor_version(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+If
+.I p
+refers to a savefile,
+.B pcap_major_version()
+returns the major number of the file format of the savefile and
+.B pcap_minor_version()
+returns the minor number of the file format of the savefile. The
+version number is stored in the header of the savefile.
+.PP
+If
+.I p
+refers to a live capture, the values returned by
+.B pcap_major_version()
+and
+.B pcap_minor_version()
+are not meaningful.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_next_ex.3pcap b/contrib/libpcap/pcap_next_ex.3pcap
new file mode 100644
index 0000000..d472a2b
--- /dev/null
+++ b/contrib/libpcap/pcap_next_ex.3pcap
@@ -0,0 +1,90 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_next_ex.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_NEXT_EX 3PCAP "5 April 2008"
+.SH NAME
+pcap_next_ex, pcap_next \- read the next packet from a pcap_t
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
+.ti +8
+const u_char **pkt_data);
+const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_next_ex()
+reads the next packet and returns a success/failure indication.
+If the packet was read without problems, the pointer pointed to by the
+.I pkt_header
+argument is set to point to the
+.I pcap_pkthdr
+struct for the packet, and the
+pointer pointed to by the
+.I pkt_data
+argument is set to point to the data in the packet.
+.PP
+.B pcap_next()
+reads the next packet (by calling
+.B pcap_dispatch()
+with a
+.I cnt
+of 1) and returns a
+.I u_char
+pointer to the data in that packet.
+The
+.I pcap_pkthdr
+structure pointed to by
+.I h
+is filled in with the appropriate values for the packet.
+.SH RETURN VALUE
+.B pcap_next_ex()
+returns 1 if the packet was read without problems, 0
+if packets are being read from a live capture, and the timeout expired,
+\-1 if an error occurred while reading the packet, and \-2 if
+packets are being read from a ``savefile'', and there are no more
+packets to read from the savefile.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.PP
+.B pcap_next()
+returns a pointer to the packet data on success, and returns
+.B NULL
+if an error occured, or if no packets were read from a live
+capture (if, for example, they were discarded because they didn't pass
+the packet filter, or if, on platforms that support a read timeout that
+starts before any packets arrive, the timeout expires before any packets
+arrive, or if the file descriptor for the capture device is in
+non-blocking mode and no packets were available to be read), or if no
+more packets are available in a ``savefile.'' Unfortunately, there is
+no way to determine whether an error occured or not.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP), pcap_dispatch(3PCAP)
diff --git a/contrib/libpcap/pcap_offline_filter.3pcap b/contrib/libpcap/pcap_offline_filter.3pcap
new file mode 100644
index 0000000..0ec6977
--- /dev/null
+++ b/contrib/libpcap/pcap_offline_filter.3pcap
@@ -0,0 +1,57 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_offline_filter.3pcap,v 1.1.2.1 2008-05-13 15:20:44 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OFFLINE_FILTER 3PCAP "13 May 2008"
+.SH NAME
+pcap_offline_filter \- check whether a filter matches a packet
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_offline_filter(struct bpf_program *fp,
+.ti +8
+const struct pcap_pkthdr *h, const u_char *pkt)
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_offline_filter()
+checks whether a filter matches a packet.
+.I fp
+is a pointer to a
+.I bpf_program
+struct, usually the result of a call to
+.BR pcap_compile() .
+.I h
+points to the
+.I pcap_pkthdr
+structure for the packet, and
+.I pkt
+points to the data in the packet.
+.SH RETURN VALUE
+.B pcap_offline_filter()
+returns the return value of the filter program. This will be zero if
+the packet doesn't match the filter and non-zero if the packet matches
+the filter.
+.SH SEE ALSO
+pcap(3PCAP), pcap_compile(3PCAP)
diff --git a/contrib/libpcap/pcap_open_dead.3pcap b/contrib/libpcap/pcap_open_dead.3pcap
new file mode 100644
index 0000000..29b8f7a
--- /dev/null
+++ b/contrib/libpcap/pcap_open_dead.3pcap
@@ -0,0 +1,52 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_open_dead.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_DEAD 3PCAP "5 April 2008"
+.SH NAME
+pcap_open_dead \- open a fake pcap_t for compiling filters or opening a
+capture for output
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_dead(int linktype, int snaplen);
+.ft
+.fi
+.SH DESCRIPTION
+.PP
+.B pcap_open_dead()
+is used for creating a
+.B pcap_t
+structure to use when calling the other functions in libpcap. It is
+typically used when just using libpcap for compiling BPF code.
+.PP
+.I linktype
+specifies the link-layer type for the
+.BR pcap_t .
+.PP
+.I snaplen
+specifies the snapshot length for the
+.BR pcap_t .
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(7)
diff --git a/contrib/libpcap/pcap_open_dead.3pcap.in b/contrib/libpcap/pcap_open_dead.3pcap.in
new file mode 100644
index 0000000..18c98ff
--- /dev/null
+++ b/contrib/libpcap/pcap_open_dead.3pcap.in
@@ -0,0 +1,52 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_open_dead.3pcap.in,v 1.1.2.2 2008-10-21 07:44:57 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_DEAD 3PCAP "5 April 2008"
+.SH NAME
+pcap_open_dead \- open a fake pcap_t for compiling filters or opening a
+capture for output
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_dead(int linktype, int snaplen);
+.ft
+.fi
+.SH DESCRIPTION
+.PP
+.B pcap_open_dead()
+is used for creating a
+.B pcap_t
+structure to use when calling the other functions in libpcap. It is
+typically used when just using libpcap for compiling BPF code.
+.PP
+.I linktype
+specifies the link-layer type for the
+.BR pcap_t .
+.PP
+.I snaplen
+specifies the snapshot length for the
+.BR pcap_t .
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
diff --git a/contrib/libpcap/pcap_open_live.3pcap b/contrib/libpcap/pcap_open_live.3pcap
new file mode 100644
index 0000000..6ef1d5f
--- /dev/null
+++ b/contrib/libpcap/pcap_open_live.3pcap
@@ -0,0 +1,89 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_open_live.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_LIVE 3PCAP "5 April 2008"
+.SH NAME
+pcap_open_live \- open a device for capturing
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_live(const char *device, int snaplen,
+.ti +8
+int promisc, int to_ms, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_open_live()
+is used to obtain a packet capture handle to look
+at packets on the network.
+.I device
+is a string that specifies the network device to open; on Linux systems
+with 2.2 or later kernels, a
+.I device
+argument of "any" or
+.B NULL
+can be used to capture packets from all interfaces.
+.PP
+.I snaplen
+specifies the snapshot length to be set on the handle.
+.PP
+.I promisc
+specifies if the interface is to be put into promiscuous mode.
+.PP
+.I to_ms
+specifies the read timeout in milliseconds.
+.SH RETURN VALUE
+.B pcap_open_live()
+returns a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+may also be set to warning text when
+.B pcap_open_live()
+succeds; to detect this case the caller should store a zero-length string in
+.I errbuf
+before calling
+.B pcap_open_live()
+and display the warning to the user if
+.I errbuf
+is no longer a zero-length string.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/contrib/libpcap/pcap_open_offline.3pcap b/contrib/libpcap/pcap_open_offline.3pcap
new file mode 100644
index 0000000..c89b867
--- /dev/null
+++ b/contrib/libpcap/pcap_open_offline.3pcap
@@ -0,0 +1,78 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_open_offline.3pcap.in,v 1.1.2.2 2008-10-23 05:59:43 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_OFFLINE 3PCAP "5 April 2008"
+.SH NAME
+pcap_open_offline, pcap_fopen_offline \- open a saved capture file for reading
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_offline(const char *fname, char *errbuf);
+pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_open_offline()
+is called to open a ``savefile'' for reading.
+.PP
+.I fname
+specifies the name of the file to open. The file has
+the same format as those used by
+.BR tcpdump (1)
+and
+.BR tcpslice (1).
+The name "-" in a synonym for
+.BR stdin .
+.PP
+Alternatively, you may call
+.B pcap_fopen_offline()
+to read dumped data from an existing open stream
+.IR fp .
+Note that on Windows, that stream should be opened in binary mode.
+.SH RETURN VALUE
+.B pcap_open_offline()
+and
+.B pcap_fopen_offline()
+return a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap-savefile(5)
diff --git a/contrib/libpcap/pcap_open_offline.3pcap.in b/contrib/libpcap/pcap_open_offline.3pcap.in
new file mode 100644
index 0000000..ce350dd
--- /dev/null
+++ b/contrib/libpcap/pcap_open_offline.3pcap.in
@@ -0,0 +1,78 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_open_offline.3pcap.in,v 1.1.2.2 2008-10-23 05:59:43 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_OFFLINE 3PCAP "5 April 2008"
+.SH NAME
+pcap_open_offline, pcap_fopen_offline \- open a saved capture file for reading
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_offline(const char *fname, char *errbuf);
+pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_open_offline()
+is called to open a ``savefile'' for reading.
+.PP
+.I fname
+specifies the name of the file to open. The file has
+the same format as those used by
+.BR tcpdump (1)
+and
+.BR tcpslice (1).
+The name "-" in a synonym for
+.BR stdin .
+.PP
+Alternatively, you may call
+.B pcap_fopen_offline()
+to read dumped data from an existing open stream
+.IR fp .
+Note that on Windows, that stream should be opened in binary mode.
+.SH RETURN VALUE
+.B pcap_open_offline()
+and
+.B pcap_fopen_offline()
+return a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap-savefile(@MAN_FILE_FORMATS@)
diff --git a/contrib/libpcap/pcap_set_buffer_size.3pcap b/contrib/libpcap/pcap_set_buffer_size.3pcap
new file mode 100644
index 0000000..d26a7a5
--- /dev/null
+++ b/contrib/libpcap/pcap_set_buffer_size.3pcap
@@ -0,0 +1,47 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_buffer_size.3pcap,v 1.1.2.1 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_BUFFER_SIZE 3PCAP "5 April 2008"
+.SH NAME
+pcap_set_buffer_size \- set the buffer size for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_buffer_size(pcap_t *p, int buffer_size);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_buffer_size()
+sets the buffer size that will be used on a capture handle when
+the handle is activated to
+.IR buffer_size ,
+which is in units of bytes.
+.SH RETURN VALUE
+.B pcap_set_buffer_size()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/contrib/libpcap/pcap_set_datalink.3pcap b/contrib/libpcap/pcap_set_datalink.3pcap
new file mode 100644
index 0000000..5754d76
--- /dev/null
+++ b/contrib/libpcap/pcap_set_datalink.3pcap
@@ -0,0 +1,52 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_datalink.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_DATALINK 3PCAP "5 April 2008"
+.SH NAME
+pcap_set_datalink \- set the link-layer header type to be used by a
+capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_set_datalink(pcap_t *p, int dlt);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_datalink()
+is used to set the current data link type of the pcap descriptor
+to the type specified by
+.IR dlt .
+.SH RETURN VALUE
+.B pcap_set_datalink()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP)
diff --git a/contrib/libpcap/pcap_set_promisc.3pcap b/contrib/libpcap/pcap_set_promisc.3pcap
new file mode 100644
index 0000000..27c0714
--- /dev/null
+++ b/contrib/libpcap/pcap_set_promisc.3pcap
@@ -0,0 +1,48 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_promisc.3pcap,v 1.1.2.1 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_PROMISC 3PCAP "5 April 2008"
+.SH NAME
+pcap_set_promisc \- set promiscuous mode for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_promisc(pcap_t *p, int promisc);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_promisc()
+sets whether promiscuous mode should be set on a capture handle when
+the handle is activated.
+If
+.I promisc
+is non-zero, promiscuous mode will be set, otherwise it will not be set.
+.SH RETURN VALUE
+.B pcap_set_promisc()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/contrib/libpcap/pcap_set_rfmon.3pcap b/contrib/libpcap/pcap_set_rfmon.3pcap
new file mode 100644
index 0000000..ceb62a6
--- /dev/null
+++ b/contrib/libpcap/pcap_set_rfmon.3pcap
@@ -0,0 +1,49 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_rfmon.3pcap,v 1.1.2.1 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_RFMON 3PCAP "5 April 2008"
+.SH NAME
+pcap_set_rfmon \- set monitor mode for a not-yet-activated capture
+handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_rfmon(pcap_t *p, int rfmon);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_rfmon()
+sets whether monitor mode should be set on a capture handle when
+the handle is activated.
+If
+.I rfmon
+is non-zero, monitor mode will be set, otherwise it will not be set.
+.SH RETURN VALUE
+.B pcap_set_rfmon()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_can_set_rfmon(3PCAP)
diff --git a/contrib/libpcap/pcap_set_snaplen.3pcap b/contrib/libpcap/pcap_set_snaplen.3pcap
new file mode 100644
index 0000000..10093e4
--- /dev/null
+++ b/contrib/libpcap/pcap_set_snaplen.3pcap
@@ -0,0 +1,46 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_snaplen.3pcap,v 1.1.2.1 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_SNAPLEN 3PCAP "5 April 2008"
+.SH NAME
+pcap_set_snaplen \- set the snapshot length for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_snaplen(pcap_t *p, int snaplen);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_snaplen()
+sets the snapshot length to be used on a capture handle when the handle
+is activated to
+.IR snaplen .
+.SH RETURN VALUE
+.B pcap_set_snaplen()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/contrib/libpcap/pcap_set_timeout.3pcap b/contrib/libpcap/pcap_set_timeout.3pcap
new file mode 100644
index 0000000..17f2c31
--- /dev/null
+++ b/contrib/libpcap/pcap_set_timeout.3pcap
@@ -0,0 +1,47 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_set_timeout.3pcap,v 1.1.2.1 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_TIMEOUT 3PCAP "5 April 2008"
+.SH NAME
+pcap_set_timeout \- set the read timeout for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_timeout(pcap_t *p, int to_ms);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_timeout()
+sets the read timeout that will be used on a capture handle when
+the handle is activated to
+.IR to_ms ,
+which is in units of milliseconds.
+.SH RETURN VALUE
+.B pcap_set_timeout()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/contrib/libpcap/pcap_setdirection.3pcap b/contrib/libpcap/pcap_setdirection.3pcap
new file mode 100644
index 0000000..70891a2
--- /dev/null
+++ b/contrib/libpcap/pcap_setdirection.3pcap
@@ -0,0 +1,71 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_setdirection.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SETDIRECTION 3PCAP "5 April 2008"
+.SH NAME
+pcap_setdirection \- set the direction for which packets will be captured
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_setdirection(pcap_t *p, pcap_direction_t d);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_setdirection()
+is used to specify a direction that packets will be captured.
+.I d
+is one of the constants
+.BR PCAP_D_IN ,
+.B PCAP_D_OUT
+or
+.BR PCAP_D_INOUT .
+.B PCAP_D_IN
+will only capture packets received by the device,
+.B PCAP_D_OUT
+will only capture packets sent by the device and
+.B PCAP_D_INOUT
+will capture packets received by or sent by the device.
+.B PCAP_D_INOUT
+is the default setting if this function is not called.
+.PP
+.B pcap_setdirection()
+isn't necessarily fully supported on all platforms; some platforms might
+return an error for all values, and some other platforms might not
+support
+.BR PCAP_D_OUT .
+.PP
+This operation is not supported if a ``savefile'' is being read.
+.SH RETURN VALUE
+.B pcap_setdirection()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP)
diff --git a/contrib/libpcap/pcap_setfilter.3pcap b/contrib/libpcap/pcap_setfilter.3pcap
new file mode 100644
index 0000000..67c1214
--- /dev/null
+++ b/contrib/libpcap/pcap_setfilter.3pcap
@@ -0,0 +1,54 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_setfilter.3pcap,v 1.1.2.4 2008-05-13 15:20:44 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SETFILTER 3PCAP "5 April 2008"
+.SH NAME
+pcap_setfilter \- set the filter
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_setfilter(pcap_t *p, struct bpf_program *fp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_setfilter()
+is used to specify a filter program.
+.I fp
+is a pointer to a
+.I bpf_program
+struct, usually the result of a call to
+.BR pcap_compile() .
+.SH RETURN VALUE
+.B pcap_setfilter()
+returns 0 on success and \-1 on failure.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_compile(3PCAP), pcap_geterr(3PCAP)
diff --git a/contrib/libpcap/pcap_setnonblock.3pcap b/contrib/libpcap/pcap_setnonblock.3pcap
new file mode 100644
index 0000000..07d9629
--- /dev/null
+++ b/contrib/libpcap/pcap_setnonblock.3pcap
@@ -0,0 +1,75 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_setnonblock.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SETNONBLOCK 3PCAP "5 April 2008"
+.SH NAME
+pcap_setnonblock, pcap_getnonblock \- set or get the state of
+non-blocking mode on a capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf);
+int pcap_getnonblock(pcap_t *p, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_setnonblock()
+puts a capture handle into ``non-blocking'' mode, or takes it out
+of ``non-blocking'' mode, depending on whether the
+.I nonblock
+argument is non-zero or zero. It has no effect on ``savefiles''.
+If there is an error, \-1 is returned and
+.I errbuf
+is filled in with an appropriate error message; otherwise, 0 is
+returned.
+In
+``non-blocking'' mode, an attempt to read from the capture descriptor
+with
+.B pcap_dispatch()
+will, if no packets are currently available to be read, return 0
+immediately rather than blocking waiting for packets to arrive.
+.B pcap_loop()
+and
+.B pcap_next()
+will not work in ``non-blocking'' mode.
+.SH RETURN VALUE
+.B pcap_getnonblock()
+returns the current ``non-blocking'' state of the capture descriptor; it
+always returns 0 on ``savefiles''.
+If there is an error, \-1 is returned and
+.I errbuf
+is filled in with an appropriate error message.
+.PP
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap_loop(3PCAP), pcap_next_ex(3PCAP), pcap_geterr(3PCAP)
diff --git a/contrib/libpcap/pcap_snapshot.3pcap b/contrib/libpcap/pcap_snapshot.3pcap
new file mode 100644
index 0000000..19bb9de
--- /dev/null
+++ b/contrib/libpcap/pcap_snapshot.3pcap
@@ -0,0 +1,44 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_snapshot.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SNAPSHOT 3PCAP "5 April 2008"
+.SH NAME
+pcap_snapshot \- get the snapshot length
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_snapshot(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_snapshot()
+returns the snapshot length specified when
+.B pcap_set_snapshot()
+or
+.B pcap_open_live()
+was called, for a live capture, or the snapshot length from the capture
+file, for a ``savefile''.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_stats.3pcap b/contrib/libpcap/pcap_stats.3pcap
new file mode 100644
index 0000000..0a68c1e
--- /dev/null
+++ b/contrib/libpcap/pcap_stats.3pcap
@@ -0,0 +1,59 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_stats.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SNAPSHOT 3PCAP "5 April 2008"
+.SH NAME
+pcap_stats \- get capture statistics
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_stats(pcap_t *p, struct pcap_stat *ps);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_stats()
+fills in the
+.I pcap_stat
+structure pointed to by its second argument. The values represent
+packet statistics from the start of the run to the time of the call.
+.PP
+.B pcap_stats()
+is supported only on live captures, not on ``savefiles''; no statistics
+are stored in ``savefiles'', so no statistics are available when reading
+from a ``savefile''.
+.SH RETURN VALUE
+.B pcap_stats()
+returns 0 on success and returns \-1 if there is an error or the
+.I p
+doesn't support packet statistics.
+If \-1 is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_geterr(3PCAP)
diff --git a/contrib/libpcap/pcap_statustostr.3pcap b/contrib/libpcap/pcap_statustostr.3pcap
new file mode 100644
index 0000000..5e8942c
--- /dev/null
+++ b/contrib/libpcap/pcap_statustostr.3pcap
@@ -0,0 +1,43 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_statustostr.3pcap,v 1.1.2.1 2008-04-09 21:41:53 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_STATUSTOSTR 3PCAP "9 April 2008"
+.SH NAME
+pcap_statustostr \- convert a PCAP_ERROR_ or PCAP_WARNING_ value to a string
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_statustostr(int error);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_statustostr()
+converts a
+.B PCAP_ERROR_
+or
+.B PCAP_WARNING_
+value returned by a libpcap routine to an error string.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/contrib/libpcap/pcap_strerror.3pcap b/contrib/libpcap/pcap_strerror.3pcap
new file mode 100644
index 0000000..eacdce4
--- /dev/null
+++ b/contrib/libpcap/pcap_strerror.3pcap
@@ -0,0 +1,42 @@
+.\" @(#) $Header: /tcpdump/master/libpcap/pcap_strerror.3pcap,v 1.1.2.3 2008-04-06 03:21:56 guy Exp $
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" 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: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_STRERROR 3PCAP "4 April 2008"
+.SH NAME
+pcap_strerror \- convert an errno value to a string
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_strerror(int error);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_strerror()
+is provided in case
+.BR strerror (3)
+isn't available. It returns an error message string corresponding to
+.IR error .
+.SH SEE ALSO
+strerror(3)
diff --git a/contrib/libpcap/runlex.sh b/contrib/libpcap/runlex.sh
new file mode 100755
index 0000000..497a618
--- /dev/null
+++ b/contrib/libpcap/runlex.sh
@@ -0,0 +1,235 @@
+#! /bin/sh
+
+#
+# runlex.sh
+# Script to run Lex/Flex.
+# First argument is the (quoted) name of the command; if it's null, that
+# means that neither Flex nor Lex was found, so we report an error and
+# quit.
+#
+# @(#) $Header: /tcpdump/master/libpcap/runlex.sh,v 1.1.2.4 2007/12/31 03:39:06 guy Exp $
+#
+
+#
+# Get the name of the command to run, and then shift to get the arguments.
+#
+if [ $# -eq 0 ]
+then
+ echo "Usage: runlex <lex/flex command to run> [ arguments ]" 1>&2
+ exit 1
+fi
+LEX="$1"
+shift
+
+#
+# Check whether we have Lex or Flex.
+#
+if [ -z "${LEX}" ]
+then
+ echo "Neither lex nor flex was found" 1>&2
+ exit 1
+fi
+
+#
+# Process the flags. We don't use getopt because we don't want to
+# embed complete knowledge of what options are supported by Lex/Flex.
+#
+flags=""
+outfile=lex.yy.c
+while [ $# -ne 0 ]
+do
+ case "$1" in
+
+ -o*)
+ #
+ # Set the output file name.
+ #
+ outfile=`echo "$1" | sed 's/-o\(.*\)/\1/'`
+ ;;
+
+ -*)
+ #
+ # Add this to the list of flags.
+ #
+ flags="$flags $1"
+ ;;
+
+ --|*)
+ #
+ # End of flags.
+ #
+ break
+ ;;
+ esac
+ shift
+done
+
+#
+# Is it Lex, or is it Flex?
+#
+if [ "${LEX}" = flex ]
+then
+ #
+ # It's Flex.
+ #
+ have_flex=yes
+
+ #
+ # Does it support the --noFUNCTION options? If so, we pass
+ # --nounput, as at least some versions that support those
+ # options don't support disabling yyunput by defining
+ # YY_NO_UNPUT.
+ #
+ if flex --help | egrep noFUNCTION >/dev/null
+ then
+ flags="$flags --nounput"
+
+ #
+ # Does it support -R, for generating reentrant scanners?
+ # If so, we're not currently using that feature, but
+ # it'll generate some unused functions anyway - and there
+ # won't be any header file declaring them, so there'll be
+ # defined-but-not-declared warnings. Therefore, we use
+ # --noFUNCTION options to suppress generating those
+ # functions.
+ #
+ if flex --help | egrep reentrant >/dev/null
+ then
+ flags="$flags --noyyget_lineno --noyyget_in --noyyget_out --noyyget_leng --noyyget_text --noyyset_lineno --noyyset_in --noyyset_out"
+ fi
+ fi
+else
+ #
+ # It's Lex.
+ #
+ have_flex=no
+fi
+
+#
+# OK, run it.
+# If it's lex, it doesn't support -o, so we just write to
+# lex.yy.c and, if it succeeds, rename it to the right name,
+# otherwise we remove lex.yy.c.
+# If it's flex, it supports -o, so we use that - flex with -P doesn't
+# write to lex.yy.c, it writes to a lex.{prefix from -P}.c.
+#
+if [ $have_flex = yes ]
+then
+ ${LEX} $flags -o"$outfile" "$@"
+
+ #
+ # Did it succeed?
+ #
+ status=$?
+ if [ $status -ne 0 ]
+ then
+ #
+ # No. Exit with the failing exit status.
+ #
+ exit $status
+ fi
+
+ #
+ # Flex has the annoying habit of stripping all but the last
+ # component of the "-o" flag argument and using that as the
+ # place to put the output. This gets in the way of building
+ # in a directory different from the source directory. Try
+ # to work around this.
+ #
+ # Is the outfile where we think it is?
+ #
+ outfile_base=`basename "$outfile"`
+ if [ "$outfile_base" != "$outfile" -a \( ! -r "$outfile" \) -a -r "$outfile_base" ]
+ then
+ #
+ # No, it's not, but it is in the current directory. Put it
+ # where it's supposed to be.
+ #
+ mv "$outfile_base" "$outfile"
+
+ #
+ # Did that succeed?
+ #
+ status=$?
+ if [ $status -ne 0 ]
+ then
+ #
+ # No. Exit with the failing exit status.
+ #
+ exit $status
+ fi
+ fi
+else
+ ${LEX} $flags "$@"
+
+ #
+ # Did it succeed?
+ #
+ status=$?
+ if [ $status -ne 0 ]
+ then
+ #
+ # No. Get rid of any lex.yy.c file we generated, and
+ # exit with the failing exit status.
+ #
+ rm -f lex.yy.c
+ exit $status
+ fi
+
+ #
+ # OK, rename lex.yy.c to the right output file.
+ #
+ mv lex.yy.c "$outfile"
+
+ #
+ # Did that succeed?
+ #
+ status=$?
+ if [ $status -ne 0 ]
+ then
+ #
+ # No. Get rid of any lex.yy.c file we generated, and
+ # exit with the failing exit status.
+ #
+ rm -f lex.yy.c
+ exit $status
+ fi
+fi
+
+#
+# OK, now let's generate a header file declaring the relevant functions
+# defined by the .c file; if the .c file is .../foo.c, the header file
+# will be .../foo.h.
+#
+# This works around some other Flex suckage, wherein it doesn't declare
+# the lex routine before defining it, causing compiler warnings.
+# XXX - newer versions of Flex support --header-file=, to generate the
+# appropriate header file. With those versions, we should use that option.
+#
+
+#
+# Get the name of the prefix; scan the source files for a %option prefix
+# line. We use the last one.
+#
+prefix=`sed -n 's/%option[ ][ ]*prefix="\(.*\)".*/\1/p' "$@" | tail -1`
+if [ ! -z "$prefix" ]
+then
+ prefixline="#define yylex ${prefix}lex"
+fi
+
+#
+# Construct the name of the header file.
+#
+header_file=`dirname "$outfile"`/`basename "$outfile" .c`.h
+
+#
+# Spew out the declaration.
+#
+cat <<EOF >$header_file
+/* This is generated by runlex.sh. Do not edit it. */
+$prefixline
+#ifndef YY_DECL
+#define YY_DECL int yylex(void)
+#endif
+YY_DECL;
+EOF
diff --git a/contrib/libpcap/savefile.c b/contrib/libpcap/savefile.c
index e5a5403..ddf4a84 100644
--- a/contrib/libpcap/savefile.c
+++ b/contrib/libpcap/savefile.c
@@ -30,7 +30,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.126.2.30 2007/08/14 20:57:49 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.168.2.10 2008-10-06 15:38:39 gianluca Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -44,6 +44,7 @@ static const char rcsid[] _U_ =
#include <string.h>
#include "pcap-int.h"
+#include "pcap/usb.h"
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
@@ -146,11 +147,12 @@ static const char rcsid[] _U_ =
*
* In order to ensure that a given LINKTYPE_* code's value will refer to
* the same encapsulation type on all platforms, you should not allocate
- * a new LINKTYPE_* value without consulting "tcpdump-workers@tcpdump.org".
- * The tcpdump developers will allocate a value for you, and will not
- * subsequently allocate it to anybody else; that value will be added to
- * the "pcap.h" in the tcpdump.org CVS repository, so that a future
- * libpcap release will include it.
+ * a new LINKTYPE_* value without consulting
+ * "tcpdump-workers@lists.tcpdump.org". The tcpdump developers will
+ * allocate a value for you, and will not subsequently allocate it to
+ * anybody else; that value will be added to the "pcap.h" in the
+ * tcpdump.org CVS repository, so that a future libpcap release will
+ * include it.
*
* You should, if possible, also contribute patches to libpcap and tcpdump
* to handle the new encapsulation type, so that they can also be checked
@@ -312,9 +314,9 @@ static const char rcsid[] _U_ =
* for *their* private type and tools using them for *your* private type
* would have to read them.
*
- * Instead, in those cases, ask "tcpdump-workers@tcpdump.org" for a new DLT_
- * and LINKTYPE_ value, as per the comment in pcap-bpf.h, and use the type
- * you're given.
+ * Instead, in those cases, ask "tcpdump-workers@lists.tcpdump.org" for a
+ * new DLT_ and LINKTYPE_ value, as per the comment in pcap/bpf.h, and use
+ * the type you're given.
*/
#define LINKTYPE_USER0 147
#define LINKTYPE_USER1 148
@@ -551,6 +553,100 @@ static const char rcsid[] _U_ =
*/
#define LINKTYPE_IPMB 199
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for capturing data on a secure tunnel interface.
+ */
+#define LINKTYPE_JUNIPER_ST 200
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
+ * that includes direction information; requested by Paolo Abeni.
+ */
+#define LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR 201
+
+/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ * http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
+ */
+#define LINKTYPE_AX25_KISS 202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <varunax@gmail.com>.
+ */
+#define LINKTYPE_LAPD 203
+
+/*
+ * Variants of various link-layer headers, with a one-byte direction
+ * pseudo-header prepended - zero means "received by this host",
+ * non-zero (any non-zero value) means "sent by this host" - as per
+ * Will Barker <w.barker@zen.co.uk>.
+ */
+#define LINKTYPE_PPP_WITH_DIR 204 /* PPP */
+#define LINKTYPE_C_HDLC_WITH_DIR 205 /* Cisco HDLC */
+#define LINKTYPE_FRELAY_WITH_DIR 206 /* Frame Relay */
+#define LINKTYPE_LAPB_WITH_DIR 207 /* LAPB */
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ * <avn@pigeonpoint.com>.
+ */
+#define LINKTYPE_IPMB_LINUX 209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_FLEXRAY 210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_MOST 211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ * <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_LIN 212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_X2E_SERIAL 213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_X2E_XORAYA 214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <jcmvbkbc@gmail.com>.
+ */
+#define LINKTYPE_IEEE802_15_4_NONASK_PHY 215
+
static struct linktype_map {
int dlt;
@@ -811,9 +907,69 @@ static struct linktype_map {
/* IPMB */
{ DLT_IPMB, LINKTYPE_IPMB },
+ /* enc0 device */
+ { DLT_ENC, LINKTYPE_ENC },
+
+ /* Juniper Secure Tunnel */
+ { DLT_JUNIPER_ST, LINKTYPE_JUNIPER_ST },
+
+ /* Bluetooth HCI UART transport layer, with pseudo-header */
+ { DLT_BLUETOOTH_HCI_H4_WITH_PHDR, LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR },
+
+ /* AX.25 with KISS header */
+ { DLT_AX25_KISS, LINKTYPE_AX25_KISS },
+
+ /* Raw LAPD, with no pseudo-header */
+ { DLT_LAPD, LINKTYPE_LAPD },
+
+ /* PPP with one-byte pseudo-header giving direction */
+ { DLT_PPP_WITH_DIR, LINKTYPE_PPP_WITH_DIR },
+
+ /* Cisco HDLC with one-byte pseudo-header giving direction */
+ { DLT_C_HDLC_WITH_DIR, LINKTYPE_C_HDLC_WITH_DIR },
+
+ /* Frame Relay with one-byte pseudo-header giving direction */
+ { DLT_FRELAY_WITH_DIR, LINKTYPE_FRELAY_WITH_DIR },
+
+ /* LAPB with one-byte pseudo-header giving direction */
+ { DLT_LAPB_WITH_DIR, LINKTYPE_LAPB_WITH_DIR },
+
+ /* IPMB with Linux pseudo-header */
+ { DLT_IPMB_LINUX, LINKTYPE_IPMB_LINUX },
+
+ /* FlexRay */
+ { DLT_FLEXRAY, LINKTYPE_FLEXRAY },
+
+ /* MOST */
+ { DLT_MOST, LINKTYPE_MOST },
+
+ /* LIN */
+ { DLT_LIN, LINKTYPE_LIN },
+
+ /* X2E-private serial line capture */
+ { DLT_X2E_SERIAL, LINKTYPE_X2E_SERIAL },
+
+ /* X2E-private for Xoraya data logger family */
+ { DLT_X2E_XORAYA, LINKTYPE_X2E_XORAYA },
+
+ /* IEEE 802.15.4 with PHY data for non-ASK PHYs */
+ { DLT_IEEE802_15_4_NONASK_PHY, LINKTYPE_IEEE802_15_4_NONASK_PHY },
+
{ -1, -1 }
};
+/*
+ * Mechanism for storing information about a capture in the upper
+ * 6 bits of a linktype value in a capture file.
+ *
+ * LT_LINKTYPE_EXT(x) extracts the additional information.
+ *
+ * The rest of the bits are for a value describing the link-layer
+ * value. LT_LINKTYPE(x) extracts that value.
+ */
+#define LT_LINKTYPE(x) ((x) & 0x03FFFFFF)
+#define LT_LINKTYPE_EXT(x) ((x) & 0xFC000000)
+
static int
dlt_to_linktype(int dlt)
{
@@ -909,6 +1065,32 @@ sf_stats(pcap_t *p, struct pcap_stat *ps)
return (-1);
}
+#ifdef WIN32
+static int
+sf_setbuff(pcap_t *p, int dim)
+{
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The kernel buffer size cannot be set while reading from a file");
+ return (-1);
+}
+
+static int
+sf_setmode(pcap_t *p, int mode)
+{
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "impossible to set mode while reading from a file");
+ return (-1);
+}
+
+static int
+sf_setmintocopy(pcap_t *p, int size)
+{
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The mintocopy parameter cannot be set while reading from a file");
+ return (-1);
+}
+#endif
+
static int
sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
{
@@ -930,7 +1112,7 @@ sf_setdirection(pcap_t *p, pcap_direction_t d)
}
static void
-sf_close(pcap_t *p)
+sf_cleanup(pcap_t *p)
{
if (p->sf.rfile != stdin)
(void)fclose(p->sf.rfile);
@@ -975,6 +1157,33 @@ pcap_open_offline(const char *fname, char *errbuf)
return (p);
}
+#ifdef WIN32
+pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
+{
+ int fd;
+ FILE *file;
+
+ fd = _open_osfhandle(osfd, _O_RDONLY);
+ if ( fd < 0 )
+ {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
+ return NULL;
+ }
+
+ file = _fdopen(fd, "rb");
+ if ( file == NULL )
+ {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno));
+ return NULL;
+ }
+
+ return pcap_fopen_offline(file, errbuf);
+}
+#endif
+
+#ifdef WIN32
+static
+#endif
pcap_t *
pcap_fopen_offline(FILE *fp, char *errbuf)
{
@@ -1044,7 +1253,8 @@ pcap_fopen_offline(FILE *fp, char *errbuf)
}
p->tzoff = hdr.thiszone;
p->snapshot = hdr.snaplen;
- p->linktype = linktype_to_dlt(hdr.linktype);
+ p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
+ p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
if (magic == KUZNETZOV_TCPDUMP_MAGIC && p->linktype == DLT_EN10MB) {
/*
* This capture might have been done in raw mode or cooked
@@ -1157,7 +1367,13 @@ pcap_fopen_offline(FILE *fp, char *errbuf)
p->getnonblock_op = sf_getnonblock;
p->setnonblock_op = sf_setnonblock;
p->stats_op = sf_stats;
- p->close_op = sf_close;
+#ifdef WIN32
+ p->setbuff_op = sf_setbuff;
+ p->setmode_op = sf_setmode;
+ p->setmintocopy_op = sf_setmintocopy;
+#endif
+ p->cleanup_op = sf_cleanup;
+ p->activated = 1;
return (p);
bad:
@@ -1195,8 +1411,9 @@ sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, u_int buflen)
} else {
if (amt_read != 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "truncated dump file; tried to read %d header bytes, only got %lu",
- p->sf.hdrsize, (unsigned long)amt_read);
+ "truncated dump file; tried to read %lu header bytes, only got %lu",
+ (unsigned long)p->sf.hdrsize,
+ (unsigned long)amt_read);
return (-1);
}
/* EOF */
@@ -1306,6 +1523,44 @@ sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, u_int buflen)
return (-1);
}
}
+
+ /*
+ * The DLT_USB_LINUX header is in host byte order when capturing
+ * (it's supplied directly from a memory-mapped buffer shared
+ * by the kernel).
+ *
+ * When reading a DLT_USB_LINUX capture file, we need to convert
+ * it from the capturing host's byte order to the reading host's
+ * byte order.
+ */
+ if (p->sf.swapped && p->linktype == DLT_USB_LINUX) {
+ pcap_usb_header* uhdr = (pcap_usb_header*) buf;
+ /*
+ * The URB id is a totally opaque value; do we really need to
+ * converte it to the reading host's byte order???
+ */
+ if (hdr->caplen < 8)
+ return 0;
+ uhdr->id = SWAPLL(uhdr->id);
+ if (hdr->caplen < 14)
+ return 0;
+ uhdr->bus_id = SWAPSHORT(uhdr->bus_id);
+ if (hdr->caplen < 24)
+ return 0;
+ uhdr->ts_sec = SWAPLL(uhdr->ts_sec);
+ if (hdr->caplen < 28)
+ return 0;
+ uhdr->ts_usec = SWAPLONG(uhdr->ts_usec);
+ if (hdr->caplen < 32)
+ return 0;
+ uhdr->status = SWAPLONG(uhdr->status);
+ if (hdr->caplen < 36)
+ return 0;
+ uhdr->urb_len = SWAPLONG(uhdr->urb_len);
+ if (hdr->caplen < 40)
+ return 0;
+ uhdr->data_len = SWAPLONG(uhdr->data_len);
+ }
return (0);
}
@@ -1420,6 +1675,7 @@ pcap_dump_open(pcap_t *p, const char *fname)
fname, linktype);
return (NULL);
}
+ linktype |= p->linktype_ext;
if (fname[0] == '-' && fname[1] == '\0') {
f = stdout;
@@ -1454,6 +1710,7 @@ pcap_dump_fopen(pcap_t *p, FILE *f)
linktype);
return (NULL);
}
+ linktype |= p->linktype_ext;
return (pcap_setup_dump(p, linktype, f, "stream"));
}
diff --git a/contrib/libpcap/scanner.l b/contrib/libpcap/scanner.l
index ff8ae63..551b2cc 100644
--- a/contrib/libpcap/scanner.l
+++ b/contrib/libpcap/scanner.l
@@ -24,7 +24,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.99.2.9 2007/06/11 09:52:05 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.110.2.2 2008/02/06 10:21:47 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -54,7 +54,7 @@ static const char rcsid[] _U_ =
#define AI_NUMERICHOST 0x04
#endif
#endif /*INET6*/
-#include <pcap-namedb.h>
+#include <pcap/namedb.h>
#include "tokdefs.h"
#ifdef HAVE_OS_PROTO_H
@@ -80,6 +80,7 @@ extern YYSTYPE yylval;
N ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
B ([0-9A-Fa-f][0-9A-Fa-f]?)
+B2 ([0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f])
W ([0-9A-Fa-f][0-9A-Fa-f]?[0-9A-Fa-f]?[0-9A-Fa-f]?)
%a 18400
@@ -167,6 +168,10 @@ V6004 ::{N}\.{N}\.{N}\.{N}
V6 ({V680}|{V670}|{V671}|{V672}|{V673}|{V674}|{V675}|{V676}|{V677}|{V660}|{V661}|{V662}|{V663}|{V664}|{V665}|{V666}|{V650}|{V651}|{V652}|{V653}|{V654}|{V655}|{V640}|{V641}|{V642}|{V643}|{V644}|{V630}|{V631}|{V632}|{V633}|{V620}|{V621}|{V622}|{V610}|{V611}|{V600}|{V6604}|{V6504}|{V6514}|{V6524}|{V6534}|{V6544}|{V6554}|{V6404}|{V6414}|{V6424}|{V6434}|{V6444}|{V6304}|{V6314}|{V6324}|{V6334}|{V6204}|{V6214}|{V6224}|{V6104}|{V6114}|{V6004})
+MAC ({B}:{B}:{B}:{B}:{B}:{B}|{B}\-{B}\-{B}\-{B}\-{B}\-{B}|{B}\.{B}\.{B}\.{B}\.{B}\.{B}|{B2}\.{B2}\.{B2}|{B2}{3})
+
+
+
%%
dst return DST;
src return SRC;
@@ -248,6 +253,14 @@ protochain {
gateway return GATEWAY;
+type return TYPE;
+subtype return SUBTYPE;
+direction|dir return DIR;
+address1|addr1 return ADDR1;
+address2|addr2 return ADDR2;
+address3|addr3 return ADDR3;
+address4|addr4 return ADDR4;
+
less return LESS;
greater return GREATER;
byte return CBYTE;
@@ -308,11 +321,11 @@ sls return SLS;
">>" return RSH;
${B} { yylval.e = pcap_ether_aton(((char *)yytext)+1);
return AID; }
+{MAC} { yylval.e = pcap_ether_aton((char *)yytext);
+ return EID; }
{N} { yylval.i = stoi((char *)yytext); return NUM; }
({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) {
yylval.s = sdup((char *)yytext); return HID; }
-{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext);
- return EID; }
{V6} {
#ifdef INET6
struct addrinfo hints, *res;
diff --git a/contrib/tcpdump/CHANGES b/contrib/tcpdump/CHANGES
index aa29e30..3f3b675 100644
--- a/contrib/tcpdump/CHANGES
+++ b/contrib/tcpdump/CHANGES
@@ -1,20 +1,36 @@
-$Header: /tcpdump/master/tcpdump/CHANGES,v 1.87.2.17 2007/09/13 13:39:44 ken Exp $
-
-Mon. September 10, 2007. ken@xelerance.com. Summary for 0.9.8 tcpdump release
- Rework ARP printer
- Rework OSPFv3 printer
- Add support for Frame-Relay ARP
- Decode DHCP Option 121 (RFC 3442 Classless Static Route)
- Decode DHCP Option 249 (MS Classless Static Route) the same as Option 121
- TLV: Add support for Juniper .pcap extensions
- Print EGP header in new-world-order style
- Converted print-isakmp.c to NETDISSECT
- Moved AF specific stuff into af.h
- Test subsystem now table driven, and saves outputs and diffs to one place
+$Header: /tcpdump/master/tcpdump/CHANGES,v 1.98.2.2 2008-10-15 23:26:30 ken Exp $
+
+Mon. October 27, 2008. ken@netfunctional.ca. Summary for 4.0.0 tcpdump release
+ Add support for Bluetooth Sniffing
+ Add support for Realtek Remote Control Protocol (openrrcp.org.ru)
+ Add support for 802.11 AVS
+ Add support for SMB over TCP
+ Add support for 4 byte BGP AS printing
+ Add support for compiling on case-insensitive file systems
+ Add support for ikev2 printing
+ Update support for decoding AFS
+ Update DHCPv6 printer
+ Use newer libpcap API's (allows -B option on all platforms)
+ Add -I to turn on monitor mode
+ Bugfixes in lldp, lspping, dccp, ESP, NFS printers
+ Cleanup unused files and various cruft
+
+Mon. September 10, 2007. ken@xelerance.com. Summary for 3.9.8 tcpdump release
+ Rework ARP printer
+ Rework OSPFv3 printer
+ Add support for Frame-Relay ARP
+ Decode DHCP Option 121 (RFC 3442 Classless Static Route)
+ Decode DHCP Option 249 (MS Classless Static Route) the same as Option 121
+ TLV: Add support for Juniper .pcap extensions
+ Print EGP header in new-world-order style
+ Converted print-isakmp.c to NETDISSECT
+ Moved AF specific stuff into af.h
+ Test subsystem now table driven, and saves outputs and diffs to one place
Require <net/pfvar.h> for pf definitions - allows reading of pflog formatted
libpcap files on an OS other than where the file was generated
-Wed. July 23, 2007. mcr@xelerance.com. Summary for 0.9.7 tcpdump release
+
+Wed. July 23, 2007. mcr@xelerance.com. Summary for 3.9.7 libpcap release
NFS: Print unsigned values as such.
RX: parse safely.
diff --git a/contrib/tcpdump/CREDITS b/contrib/tcpdump/CREDITS
index d327880..b058d67 100644
--- a/contrib/tcpdump/CREDITS
+++ b/contrib/tcpdump/CREDITS
@@ -1,147 +1,165 @@
This file lists people who have contributed to tcpdump:
The current maintainers:
- Bill Fenner <fenner@research.att.com>
- David Young <dyoung@pobox.com>
- Fulvio Risso <risso@polito.it>
- Guy Harris <guy@alum.mit.edu>
- Hannes Gredler <hannes@juniper.net>
- Jun-ichiro itojun Hagino <itojun@iijlab.net>
- Michael Richardson <mcr@sandelman.ottawa.on.ca>
+ Bill Fenner <fenner at research dot att dot com>
+ David Young <dyoung at pobox dot com>
+ Fulvio Risso <risso at polito dot it>
+ Guy Harris <guy at alum dot mit dot edu>
+ Hannes Gredler <hannes at juniper dot net>
+ Michael Richardson <mcr at sandelman dot ottawa dot on dot ca>
Additional people who have contributed patches:
- Aaron Campbell <aaron@arbor.net>
- Alfredo Andres <aandres@s21sec.com>
- Albert Chin <china@thewrittenword.com>
- Andrew Brown <atatat@atatdot.net>
- Andrew Church <andrew@users.sourceforge.net>
- Andrew Hintz <adhintz@users.sourceforge.net>
- Andrew Tridgell <tridge@linuxcare.com>
- Andy Heffernan <ahh@juniper.net>
- Arkadiusz Miskiewicz <misiek@pld.org.pl>
- Armando L. Caro Jr. <acaro@mail.eecis.udel.edu>
- Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
- Atsushi Onoe <onoe@netbsd.org>
- Ben Smithurst <ben@scientia.demon.co.uk>
- Brent L. Bates <blbates@vigyan.com>
- Brian Ginsbach <ginsbach@cray.com>
- Bruce M. Simpson <bms@spc.org>
- Carles Kishimoto Bisbe <ckishimo@ac.upc.es>
- Charlie Lenahan <clenahan@fortresstech.com>
- Charles M. Hannum <mycroft@netbsd.org>
- Chris Cogdon <chris@cogdon.org>
- Chris G. Demetriou <cgd@netbsd.org>
- Christian Sievers <c_s@users.sourceforge.net>
- Chris Jepeway <jepeway@blasted-heath.com>
- Chris Larson <clarson@kergoth.com>
- Craig Rodrigues <rodrigc@mediaone.net>
- Crist J. Clark <cjclark@alum.mit.edu>
- Daniel Hagerty <hag@ai.mit.edu>
- Darren Reed <darrenr@reed.wattle.id.au>
- David Binderman <d.binderman@virgin.net>
- David Smith <dsmith@redhat.com>
- David Young <dyoung@ojctech.com>
- Don Ebright <Don.Ebright@compuware.com>
- Eddie Kohler <xexd@sourceforge.net>
- Francis Dupont <Francis.Dupont@enst-bretagne.fr>
- Francisco Matias Cuenca-Acuna <mcuenca@george.rutgers.edu>
- Frank Volf <volf@oasis.IAEhv.nl>
- Fulvio Risso <risso@polito.it>
- George Bakos <gbakos@ists.dartmouth.edu>
- Gerald Combs <gerald@ethereal.com>
- Gert Doering <gert@greenie.muc.de>
- Greg Stark <gsstark@mit.edu>
- Gilbert Ramirez Jr. <gram@xiexie.org>
- Gisle Vanem <giva@bgnett.no>
- Hannes Viertel <hviertel@juniper.net>
- Hank Leininger <tcpdump-workers@progressive-comp.com>
- Harry Raaymakers <harryr@connect.com.au>
- Heinz-Ado Arnolds <Ado.Arnolds@dhm-systems.de>
- Hendrik Scholz <hendrik@scholz.net>
- Ian McDonald <imcdnzl@gmail.com>
- Jacek Tobiasz <Jacek.Tobiasz@atm.com.pl>
- Jakob Schlyter <jakob@openbsd.org>
- Jan Oravec <wsx@wsx6.net>
- Jason R. Thorpe <thorpej@netbsd.org>
- Jefferson Ogata <jogata@nodc.noaa.gov>
- Jeffrey Hutzelman <jhutz@cmu.edu>
- Jesper Peterson <jesper@endace.com>
- Jim Hutchins <jim@ca.sandia.gov>
- Jonathan Heusser <jonny@drugphish.ch>
- Tatuya Jinmei <jinmei@kame.net>
- Jørgen Thomsen <jth@jth.net>
- Julian Cowley <julian@lava.net>
- Kaarthik Sivakumar <kaarthik@torrentnet.com>
- Kazushi Sugyo <sugyo@pb.jp.nec.com>
- Kelly Carmichael <kcarmich@ipapp.com>
- Ken Hornstein <kenh@cmf.nrl.navy.mil>
- Kevin Steves <stevesk@pobox.com>
- Klaus Klein <kleink@reziprozitaet.de>
- Kris Kennaway <kris@freebsd.org>
- Krzysztof Halasa <khc@pm.waw.pl>
- Larry Lile <lile@stdio.com>
- Lennert Buytenhek <buytenh@gnu.org>
- Loris Degioanni <loris@netgroup-serv.polito.it>
- Love Hörnquist-Åstrand <lha@stacken.kth.se>
- Maciej W. Rozycki <macro@ds2.pg.gda.pl>
- Manu Pathak <mapathak@cisco.com>
- Marc A. Lehmann <pcg@goof.com>
- Mark Ellzey Thomas <mark@ackers.net>
- Marko Kiiskila <carnil@cs.tut.fi>
- Markus Schöpflin <schoepflin@sourceforge.net>
- Marshall Rose <mrose@dbc.mtview.ca.us>
- Martin Husemann <martin@netbsd.org>
- Max Laier <max@love2party.net>
- Michael Madore <mmadore@turbolinux.com>
- Michael Shalayeff <mickey@openbsd.org>
- Michael Shields <shields@msrl.com>
- Michael T. Stolarchuk <mts@off.to>
- Michele "mydecay" Marchetto <smarchetto1@tin.it>
- Monroe Williams <monroe@pobox.com>
- Motonori Shindo <mshindo@mshindo.net>
- Nathan J. Williams <nathanw@MIT.EDU>
- Nathaniel Couper-Noles <Nathaniel@isi1.tccisi.com>
- Neil T. Spring <bluehal@users.sourceforge.net>
- Niels Provos <provos@openbsd.org>
- Nickolai Zeldovich <kolya@MIT.EDU>
- Nicolas Ferrero <toorop@babylo.net>
- Noritoshi Demizu <demizu@users.sourceforge.net>
- Olaf Kirch <okir@caldera.de>
- Onno van der Linden <onno@simplex.nl>
- Pascal Hennequin <pascal.hennequin@int-evry.fr>
- Pasvorn Boonmark <boonmark@juniper.net>
- Paul Mundt <lethal@linux-sh.org>
- Paul S. Traina <pst@freebsd.org>
- Pavlin Radoslavov <pavlin@icir.org>
- Pekka Savola <pekkas@netcore.fi>
- Peter Fales <peter@fales-lorenz.net>
- Peter Jeremy <peter.jeremy@alcatel.com.au>
- <pfhunt@users.sourceforge.net>
- Phil Wood <cpw@lanl.gov>
- Rafal Maszkowski <rzm@icm.edu.pl>
- Raphael Raimbault <raphael.raimbault@netasq.com>
- Rick Cheng <rcheng@juniper.net>
- Rick Jones <rick.jones2@hp.com>
- Rick Watson <watsonrick@users.sourceforge.net>
- Rob Braun <bbraun@synack.net>
- Roderick Schertler <roderick@argon.org>
- Sami Farin <safari@iki.fi>
- Scott Rose <syberpunk@users.sourceforge.net>
- Sebastian Krahmer <krahmer@cs.uni-potsdam.de>
- Sebastien Vincent <svincent@idems.fr>
- Seth Webster <swebster@sst.ll.mit.edu>
- Shinsuke Suzuki <suz@kame.net>
- Steinar Haug <sthaug@nethelp.no>
- Swaminathan Chandrasekaran <chander@juniper.net>
- Takashi Yamamoto <yamt@mwd.biglobe.ne.jp>
- Terry Kennedy <terry@tmk.com>
+ Aaron Campbell <aaron at arbor dot net>
+ Alfredo Andres <aandres at s21sec dot com>
+ Albert Chin <china at thewrittenword dot com>
+ Ananth Suryanarayana <anantha at juniper dot net>
+ Andrea Bittau <a dot bittau at cs dot ucl dot ac dot uk>
+ Andrew Brown <atatat at atatdot dot net>
+ Andrew Church <andrew at users dot sourceforge dot net>
+ Andrew Hintz <adhintz at users dot sourceforge dot net>
+ Andrew Silent <andrew at nording dot ru>
+ Andrew Tridgell <tridge at linuxcare dot com>
+ Andy Heffernan <ahh at juniper dot net>
+ Arkadiusz Miskiewicz <misiek at pld dot org dot pl>
+ Armando L. Caro Jr. <acaro at mail dot eecis dot udel dot edu>
+ Arnaldo Carvalho de Melo <acme at ghostprotocols dot net>
+ Ben Byer <bushing at sourceforge dot net>
+ Atsushi Onoe <onoe at netbsd dot org>
+ Ben Smithurst <ben at scientia dot demon dot co dot uk>
+ Bjoern A. Zeeb <bzeeb at Zabbadoz dot NeT>
+ Brent L. Bates <blbates at vigyan dot com>
+ Brian Ginsbach <ginsbach at cray dot com>
+ Bruce M. Simpson <bms at spc dot org>
+ Carles Kishimoto Bisbe <ckishimo at ac dot upc dot es>
+ Charlie Lenahan <clenahan at fortresstech dot com>
+ Charles M. Hannum <mycroft at netbsd dot org>
+ Chris Cogdon <chris at cogdon dot org>
+ Chris G. Demetriou <cgd at netbsd dot org>
+ Christian Sievers <c_s at users dot sourceforge dot net>
+ Chris Jepeway <jepeway at blasted-heath dot com>
+ Chris Larson <clarson at kergoth dot com>
+ Craig Rodrigues <rodrigc at mediaone dot net>
+ Crist J. Clark <cjclark at alum dot mit dot edu>
+ Daniel Hagerty <hag at ai dot mit dot edu>
+ Darren Reed <darrenr at reed dot wattle dot id dot au>
+ David Binderman <d dot binderman at virgin dot net>
+ David Smith <dsmith at redhat dot com>
+ David Young <dyoung at ojctech dot com>
+ Don Ebright <Don dot Ebright at compuware dot com>
+ Eddie Kohler <xexd at sourceforge dot net>
+ Florent Drouin <Florent dot Drouin at alcatel-lucent dot fr>
+ Francis Dupont <Francis dot Dupont at enst-bretagne dot fr>
+ Francisco Matias Cuenca-Acuna <mcuenca at george dot rutgers dot edu>
+ Francois-Xavier Le Bail <fx dot lebail at yahoo dot com>
+ Frank Volf <volf at oasis dot IAEhv dot nl>
+ Fulvio Risso <risso at polito dot it>
+ George Bakos <gbakos at ists dot dartmouth dot edu>
+ Gerald Combs <gerald at ethereal dot com>
+ Gerrit Renker <gerrit at erg dot abdn dot ac dot uk>
+ Gert Doering <gert at greenie dot muc dot de>
+ Greg Minshall <minshall at acm dot org>
+ Greg Stark <gsstark at mit dot edu>
+ Gilbert Ramirez Jr. <gram at xiexie dot org>
+ Gisle Vanem <giva at bgnett dot no>
+ Hannes Viertel <hviertel at juniper dot net>
+ Hank Leininger <tcpdump-workers at progressive-comp dot com>
+ Harry Raaymakers <harryr at connect dot com dot au>
+ Heinz-Ado Arnolds <Ado dot Arnolds at dhm-systems dot de>
+ Hendrik Scholz <hendrik at scholz dot net>
+ Ian McDonald <imcdnzl at gmail dot com>
+ Jacek Tobiasz <Jacek dot Tobiasz at atm dot com dot pl>
+ Jakob Schlyter <jakob at openbsd dot org>
+ Jan Oravec <wsx at wsx6 dot net>
+ Jason R. Thorpe <thorpej at netbsd dot org>
+ Jefferson Ogata <jogata at nodc dot noaa dot gov>
+ Jeffrey Hutzelman <jhutz at cmu dot edu>
+ Jesper Peterson <jesper at endace dot com>
+ Jim Hutchins <jim at ca dot sandia dot gov>
+ Jonathan Heusser <jonny at drugphish dot ch>
+ Tatuya Jinmei <jinmei at kame dot net>
+ Joerg Mayer <jmayer@loplof.de>
+ Jørgen Thomsen <jth at jth dot net>
+ Julian Cowley <julian at lava dot net>
+ Kaarthik Sivakumar <kaarthik at torrentnet dot com>
+ Kazushi Sugyo <sugyo at pb dot jp dot nec dot com>
+ Kelly Carmichael <kcarmich at ipapp dot com>
+ Ken Hornstein <kenh at cmf dot nrl dot navy dot mil>
+ Kevin Steves <stevesk at pobox dot com>
+ Klaus Klein <kleink at reziprozitaet dot de>
+ Kris Kennaway <kris at freebsd dot org>
+ Krzysztof Halasa <khc at pm dot waw dot pl>
+ Larry Lile <lile at stdio dot com>
+ Lennert Buytenhek <buytenh at gnu dot org>
+ Loris Degioanni <loris at netgroup-serv dot polito dot it>
+ Love Hörnquist-Åstrand <lha at stacken dot kth dot se>
+ Luis Martin Garcia <luis dot mgarc at gmail dot com>
+ Maciej W. Rozycki <macro at ds2 dot pg dot gda dot pl>
+ Manu Pathak <mapathak at cisco dot com>
+ Marc Binderberger <mbind at sourceforge dot net>
+ Marc A. Lehmann <pcg at goof dot com>
+ Mark Ellzey Thomas <mark at ackers dot net>
+ Marko Kiiskila <carnil at cs dot tut dot fi>
+ Markus Schöpflin <schoepflin at sourceforge dot net>
+ Marshall Rose <mrose at dbc dot mtview dot ca dot us>
+ Martin Husemann <martin at netbsd dot org>
+ Max Laier <max at love2party dot net>
+ Michael A. Meffie III <meffie at sourceforge dot net>
+ Michael Madore <mmadore at turbolinux dot com>
+ Michael Shalayeff <mickey at openbsd dot org>
+ Michael Shields <shields at msrl dot com>
+ Michael T. Stolarchuk <mts at off dot to>
+ Michele "mydecay" Marchetto <smarchetto1 at tin dot it>
+ Mike Frysinger <vapier at gmail dot com>
+ Monroe Williams <monroe at pobox dot com>
+ Motonori Shindo <mshindo at mshindo dot net>
+ Nathan J. Williams <nathanw at MIT dot EDU>
+ Nathaniel Couper-Noles <Nathaniel at isi1 dot tccisi dot com>
+ Neil T. Spring <bluehal at users dot sourceforge dot net>
+ Niels Provos <provos at openbsd dot org>
+ Nickolai Zeldovich <kolya at MIT dot EDU>
+ Nicolas Ferrero <toorop at babylo dot net>
+ Noritoshi Demizu <demizu at users dot sourceforge dot net>
+ Olaf Kirch <okir at caldera dot de>
+ Onno van der Linden <onno at simplex dot nl>
+ Paolo Abeni <paolo dot abeni at email dot it>
+ Pascal Hennequin <pascal dot hennequin at int-evry dot fr>
+ Pasvorn Boonmark <boonmark at juniper dot net>
+ Paul Mundt <lethal at linux-sh dot org>
+ Paul S. Traina <pst at freebsd dot org>
+ Pavlin Radoslavov <pavlin at icir dot org>
+ Pekka Savola <pekkas at netcore dot fi>
+ Peter Fales <peter at fales-lorenz dot net>
+ Peter Jeremy <peter dot jeremy at alcatel dot com dot au>
+ <pfhunt at users dot sourceforge dot net>
+ Phil Wood <cpw at lanl dot gov>
+ Rafal Maszkowski <rzm at icm dot edu dot pl>
+ Raphael Raimbault <raphael dot raimbault at netasq dot com>
+ Rick Cheng <rcheng at juniper dot net>
+ Rick Jones <rick dot jones2 at hp dot com>
+ Rick Watson <watsonrick at users dot sourceforge dot net>
+ Rob Braun <bbraun at synack dot net>
+ Roderick Schertler <roderick at argon dot org>
+ Sagun Shakya <sagun dot shakya at sun dot com>
+ Sami Farin <safari at iki dot fi>
+ Scott Rose <syberpunk at users dot sourceforge dot net>
+ Sebastian Krahmer <krahmer at cs dot uni-potsdam dot de>
+ Sebastien Raveau <sebastien dot raveau at epita dot fr>
+ Sebastien Vincent <svincent at idems dot fr>
+ Sepherosa Ziehau <sepherosa at gmail dot com>
+ Seth Webster <swebster at sst dot ll dot mit dot edu>
+ Shinsuke Suzuki <suz at kame dot net>
+ Steinar Haug <sthaug at nethelp dot no>
+ Swaminathan Chandrasekaran <chander at juniper dot net>
+ Takashi Yamamoto <yamt at mwd dot biglobe dot ne dot jp>
+ Terry Kennedy <terry at tmk dot com>
Timo Koskiahde
- Tony Li <tli@procket.com>
- Uns Lider <unslider@miranda.org>
- Victor Oppleman <oppleman@users.sourceforge.net>
- Wesley Griffin <wgriffin@users.sourceforge.net>
- Wilbert de Graaf <wilbertdg@hetnet.nl>
+ Tony Li <tli at procket dot com>
+ Uns Lider <unslider at miranda dot org>
+ Victor Oppleman <oppleman at users dot sourceforge dot net>
+ Wesley Griffin <wgriffin at users dot sourceforge dot net>
+ Wilbert de Graaf <wilbertdg at hetnet dot nl>
+ Will Drewry <will at alum dot bu dot edu>
Yen Yen Lim
Yoshifumi Nishida
@@ -149,3 +167,6 @@ The original LBL crew:
Steve McCanne
Craig Leres
Van Jacobson
+
+Past maintainers:
+ Jun-ichiro itojun Hagino <itojun at iijlab dot net>
diff --git a/contrib/tcpdump/FILES b/contrib/tcpdump/FILES
deleted file mode 100644
index 4e2afa2..0000000
--- a/contrib/tcpdump/FILES
+++ /dev/null
@@ -1,251 +0,0 @@
-CHANGES
-CREDITS
-FILES
-INSTALL
-LICENSE
-Makefile.in
-README
-Readme.Win32
-VERSION
-acconfig.h
-aclocal.m4
-addrtoname.c
-addrtoname.h
-af.c
-af.h
-ah.h
-aodv.h
-appletalk.h
-arcnet.h
-atime.awk
-atm.h
-atmuni31.h
-bootp.h
-bpf_dump.c
-bgp.h
-chdlc.h
-config.guess
-config.h.in
-config.sub
-configure
-configure.in
-cpack.c
-cpack.h
-dccp.h
-decnet.h
-decode_prefix.h
-enc.h
-esp.h
-ether.h
-ethertype.h
-extract.h
-fddi.h
-gmpls.c
-gmpls.h
-gmt2local.c
-gmt2local.h
-icmp6.h
-ieee802_11.h
-ieee802_11_radio.h
-igrp.h
-install-sh
-interface.h
-ip.h
-ip6.h
-ipfc.h
-ipproto.c
-ipproto.h
-ipsec_doi.h
-ipx.h
-isakmp.h
-l2tp.h
-l2vpn.c
-l2vpn.h
-lane.h
-lbl/os-osf4.h
-lbl/os-solaris2.h
-lbl/os-sunos4.h
-lbl/os-ultrix4.h
-llc.h
-machdep.c
-machdep.h
-makemib
-mib.h
-missing/addrinfo.h
-missing/addrsize.h
-missing/bittypes.h
-missing/dlnames.c
-missing/datalinks.c
-missing/getaddrinfo.c
-missing/getnameinfo.c
-missing/inet_aton.c
-missing/inet_ntop.c
-missing/inet_pton.c
-missing/resolv6.h
-missing/resolv_ext.h
-missing/snprintf.c
-missing/sockstorage.h
-missing/strdup.c
-missing/strlcat.c
-missing/strlcpy.c
-missing/strsep.c
-mkdep
-mpls.h
-nameser.h
-netbios.h
-netdissect.h
-nfs.h
-nfsfh.h
-nlpid.c
-nlpid.h
-ntp.h
-oakley.h
-ospf.h
-ospf6.h
-oui.c
-oui.h
-packetdat.awk
-parsenfsfh.c
-pcap_dump_ftell.c
-pcap-missing.h
-pmap_prot.h
-ppp.h
-print-802_11.c
-print-ah.c
-print-aodv.c
-print-ap1394.c
-print-arcnet.c
-print-arp.c
-print-ascii.c
-print-atalk.c
-print-atm.c
-print-beep.c
-print-bfd.c
-print-bgp.c
-print-bootp.c
-print-cdp.c
-print-chdlc.c
-print-cip.c
-print-cnfp.c
-print-dccp.c
-print-decnet.c
-print-dhcp6.c
-print-domain.c
-print-dvmrp.c
-print-eap.c
-print-egp.c
-print-enc.c
-print-esp.c
-print-eigrp.c
-print-ether.c
-print-fddi.c
-print-fr.c
-print-frag6.c
-print-gre.c
-print-hsrp.c
-print-icmp.c
-print-icmp6.c
-print-igmp.c
-print-igrp.c
-print-ip.c
-print-ip6.c
-print-ip6opts.c
-print-ipcomp.c
-print-ipfc.c
-print-ipx.c
-print-isakmp.c
-print-isoclns.c
-print-juniper.c
-print-krb.c
-print-l2tp.c
-print-lane.c
-print-ldp.c
-print-llc.c
-print-lmp.c
-print-lspping.c
-print-lwres.c
-print-mobile.c
-print-mobility.c
-print-mpls.c
-print-msdp.c
-print-netbios.c
-print-nfs.c
-print-ntp.c
-print-null.c
-print-olsr.c
-print-ospf.c
-print-ospf6.c
-print-pflog.c
-print-pgm.c
-print-pim.c
-print-ppp.c
-print-pppoe.c
-print-pptp.c
-print-radius.c
-print-raw.c
-print-rip.c
-print-ripng.c
-print-rsvp.c
-print-rt6.c
-print-rx.c
-print-sctp.c
-print-sip.c
-print-sl.c
-print-sll.c
-print-slow.c
-print-smb.c
-print-snmp.c
-print-stp.c
-print-sunatm.c
-print-sunrpc.c
-print-symantec.c
-print-syslog.c
-print-tcp.c
-print-telnet.c
-print-tftp.c
-print-timed.c
-print-token.c
-print-udp.c
-print-vjc.c
-print-vrrp.c
-print-wb.c
-print-zephyr.c
-route6d.h
-rpc_auth.h
-rpc_msg.h
-rx.h
-sctpConstants.h
-sctpHeader.h
-send-ack.awk
-setsignal.c
-setsignal.h
-slcompress.h
-slip.h
-sll.h
-smb.h
-smbutil.c
-stime.awk
-strcasecmp.c
-tcp.h
-tcpdump.1
-tcpdump.c
-tcpdump-stdinc.h
-telnet.h
-tftp.h
-timed.h
-token.h
-udp.h
-util.c
-vfprintf.c
-win32/Include/Arpa/tftp.h
-win32/Include/errno.h
-win32/Include/getopt.h
-win32/Include/inetprivate.h
-win32/Include/telnet.h
-win32/Include/w32_fzs.h
-win32/Include/Netinet/in_systm.h
-win32/Include/Netinet/ip.h
-win32/Src/getopt.c
-win32/prj/GNUmakefile
-win32/prj/WinDump.dsp
-win32/prj/WinDump.dsw
diff --git a/contrib/tcpdump/FREEBSD-Xlist b/contrib/tcpdump/FREEBSD-Xlist
new file mode 100644
index 0000000..eb234c1
--- /dev/null
+++ b/contrib/tcpdump/FREEBSD-Xlist
@@ -0,0 +1,3 @@
+$FreeBSD$
+Readme.win32
+*/win32
diff --git a/contrib/tcpdump/INSTALL b/contrib/tcpdump/INSTALL.txt
index 745997f..e263f53 100644
--- a/contrib/tcpdump/INSTALL
+++ b/contrib/tcpdump/INSTALL.txt
@@ -1,4 +1,4 @@
-@(#) $Header: /tcpdump/master/tcpdump/INSTALL,v 1.63.2.7 2007/09/14 01:03:12 guy Exp $ (LBL)
+@(#) $Header: /tcpdump/master/tcpdump/INSTALL.txt,v 1.1.2.1 2008-02-06 10:49:22 guy Exp $ (LBL)
If you have not built libpcap, and your system does not have libpcap
installed, install libpcap first. Your system might provide a version
@@ -43,7 +43,7 @@ FILES
CHANGES - description of differences between releases
CREDITS - people that have helped tcpdump along
FILES - list of files exported as part of the distribution
-INSTALL - this file
+INSTALL.txt - this file
LICENSE - the license under which tcpdump is distributed
Makefile.in - compilation rules (input to the configure script)
README - description of distribution
@@ -140,9 +140,10 @@ print-arp.c - Address Resolution Protocol printer routines
print-ascii.c - ASCII packet dump routines
print-atalk.c - AppleTalk printer routines
print-atm.c - ATM printer routines
+print-beep.c - BEEP printer routines
print-bgp.c - Border Gateway Protocol printer routines
print-bootp.c - BOOTP and IPv4 DHCP printer routines
-print-beep.c - BEEP printer routines
+print-bt.c - Bluetooth printer routines
print-cdp.c - Cisco Discovery Protocol printer routines
print-chdlc.c - Cisco HDLC printer routines
print-cip.c - Classical-IP over ATM routines
@@ -199,6 +200,7 @@ print-radius.c - Radius protocol printer routines
print-raw.c - Raw IP printer routines
print-rip.c - Routing Information Protocol printer routines
print-ripng.c - IPv6 Routing Information Protocol printer routines
+print-rrcp.c - Realtek Remote Control Protocol routines
print-rsvp.c - Resource reSerVation Protocol (RSVP) printer routines
print-rt6.c - IPv6 routing header printer routines
print-rx.c - AFS RX printer routines
diff --git a/contrib/tcpdump/Makefile-devel-adds b/contrib/tcpdump/Makefile-devel-adds
deleted file mode 100644
index 512a119..0000000
--- a/contrib/tcpdump/Makefile-devel-adds
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Auto-regenerate configure script or Makefile when things change.
-# From autoconf.info . Works best with GNU Make.
-#
-${srcdir}/configure: configure.in
- cd ${srcdir} && autoconf
-
-# autoheader might not change config.h.in, so touch a stamp file.
-${srcdir}/config.h.in: ${srcdir}/stamp-h.in
-${srcdir}/stamp-h.in: configure.in acconfig.h
- cd ${srcdir} && autoheader
- echo timestamp > ${srcdir}/stamp-h.in
-
-config.h: stamp-h
-stamp-h: ${srcdir}/config.h.in config.status
- ./config.status
-
-Makefile: Makefile.in config.status
- ./config.status
-
-config.status: ${srcdir}/configure
- ./config.status --recheck
diff --git a/contrib/tcpdump/Makefile.in b/contrib/tcpdump/Makefile.in
index dcc8f40..e28e186 100644
--- a/contrib/tcpdump/Makefile.in
+++ b/contrib/tcpdump/Makefile.in
@@ -17,7 +17,7 @@
# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
-# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.293.2.7 2007/09/12 19:48:50 guy Exp $ (LBL)
+# @(#) $Header: /tcpdump/master/tcpdump/Makefile.in,v 1.317.2.4 2008-05-27 07:14:26 guy Exp $ (LBL)
#
# Various configurable paths (remember to edit Makefile.in, not Makefile)
@@ -57,6 +57,7 @@ LIBS = @LIBS@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
+RANLIB = @RANLIB@
# Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
# Also, gcc does not remove the .o before forking 'as', which can be a
@@ -65,45 +66,122 @@ INSTALL_DATA = @INSTALL_DATA@
@rm -f $@
$(CC) $(CFLAGS) -c $(srcdir)/$*.c
-CSRC = addrtoname.c af.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c \
+CSRC = addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c \
nlpid.c l2vpn.c machdep.c parsenfsfh.c \
print-802_11.c print-ap1394.c print-ah.c print-arcnet.c \
print-aodv.c print-arp.c print-ascii.c print-atalk.c print-atm.c \
- print-beep.c print-bfd.c print-bgp.c print-bootp.c print-cdp.c \
- print-chdlc.c print-cip.c print-cnfp.c print-dccp.c print-decnet.c \
- print-domain.c print-dvmrp.c print-enc.c print-egp.c \
+ print-beep.c print-bfd.c print-bgp.c print-bootp.c print-bt.c \
+ print-cdp.c print-cfm.c print-chdlc.c print-cip.c print-cnfp.c \
+ print-dccp.c print-decnet.c \
+ print-domain.c print-dtp.c print-dvmrp.c print-enc.c print-egp.c \
print-eap.c print-eigrp.c\
print-esp.c print-ether.c print-fddi.c print-fr.c \
print-gre.c print-hsrp.c print-icmp.c print-igmp.c \
print-igrp.c print-ip.c print-ipcomp.c print-ipfc.c \
- print-ipx.c print-isakmp.c print-isoclns.c print-juniper.c print-krb.c \
- print-l2tp.c print-lane.c print-ldp.c print-llc.c \
- print-lmp.c print-lspping.c \
- print-lwres.c print-mobile.c print-mpls.c print-msdp.c \
+ print-ipx.c print-isoclns.c print-juniper.c print-krb.c \
+ print-l2tp.c print-lane.c print-ldp.c print-lldp.c print-llc.c \
+ print-lmp.c print-lspping.c print-lwapp.c \
+ print-lwres.c print-mobile.c print-mpcp.c print-mpls.c print-msdp.c \
print-nfs.c print-ntp.c print-null.c print-olsr.c print-ospf.c \
- print-pgm.c print-pim.c print-ppp.c print-pppoe.c \
- print-pptp.c print-radius.c print-raw.c print-rip.c \
- print-rsvp.c print-rx.c print-sctp.c print-sip.c print-sl.c print-sll.c \
+ print-pgm.c print-pim.c print-ppp.c print-pppoe.c print-pptp.c \
+ print-radius.c print-raw.c print-rip.c print-rrcp.c print-rsvp.c \
+ print-rx.c print-sctp.c print-sflow.c print-sip.c print-sl.c print-sll.c \
print-slow.c print-snmp.c print-stp.c print-sunatm.c print-sunrpc.c \
print-symantec.c print-syslog.c print-tcp.c print-telnet.c print-tftp.c \
- print-timed.c print-token.c print-udp.c print-vjc.c print-vrrp.c \
+ print-timed.c print-token.c print-udld.c print-udp.c \
+ print-vjc.c print-vqp.c print-vrrp.c print-vtp.c \
print-wb.c print-zephyr.c setsignal.c tcpdump.c util.c
+LIBNETDISSECT_SRC=print-isakmp.c
+LIBNETDISSECT_OBJ=$(LIBNETDISSECT_SRC:.c=.o)
+LIBNETDISSECT=libnetdissect.a
+
LOCALSRC = @LOCALSRC@
GENSRC = version.c
LIBOBJS = @LIBOBJS@
-SRC = $(CSRC) $(GENSRC) $(LOCALSRC)
+SRC = $(CSRC) $(GENSRC) $(LOCALSRC) $(LIBNETDISSECT_SRC)
# We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
# hack the extra indirection
-OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) $(LOCALSRC:.c=.o) $(LIBOBJS)
-HDR = addrtoname.h appletalk.h bootp.h cpack.h dccp.h decnet.h \
- ethertype.h extract.h fddi.h gmt2local.h igrp.h interface.h \
- ipx.h llc.h machdep.h mib.h nfsfh.h nfsv2.h ntp.h ospf.h \
+OBJ = $(CSRC:.c=.o) $(GENSRC:.c=.o) $(LOCALSRC:.c=.o) $(LIBOBJS) $(LIBNETDISSECT_OBJ)
+HDR = \
+ acconfig.h \
+ addrtoname.h \
+ af.h \
+ ah.h \
+ aodv.h \
+ appletalk.h \
+ arcnet.h \
+ atm.h \
+ atmuni31.h \
+ bootp.h \
+ bgp.h \
+ chdlc.h \
+ cpack.h \
+ dccp.h \
+ decnet.h \
+ decode_prefix.h \
+ enc.h \
+ esp.h \
+ ether.h \
+ ethertype.h \
+ extract.h \
+ fddi.h \
+ gmpls.h \
+ gmt2local.h \
+ icmp6.h \
+ ieee802_11.h \
+ ieee802_11_radio.h \
+ igrp.h \
+ interface.h \
+ interface.h \
+ ip.h \
+ ip6.h \
+ ipfc.h \
+ ipproto.h \
+ ipsec_doi.h \
+ ipx.h \
+ isakmp.h \
+ l2tp.h \
+ l2vpn.h \
+ lane.h \
+ llc.h \
+ machdep.h \
+ mib.h \
+ mpls.h \
+ nameser.h \
+ netbios.h \
+ netdissect.h \
+ nfs.h \
+ nfsfh.h \
+ nlpid.h \
+ ntp.h \
+ oakley.h \
+ ospf.h \
+ ospf6.h \
+ oui.h \
+ pcap-missing.h \
+ pmap_prot.h \
+ ppp.h \
+ route6d.h \
+ rpc_auth.h \
+ rpc_msg.h \
+ rx.h \
+ sctpConstants.h \
+ sctpHeader.h \
setsignal.h \
- gnuc.h ipsec_doi.h isakmp.h l2tp.h nameser.h \
- netbios.h oakley.h ospf6.h pf.h ppp.h route6d.h
+ slcompress.h \
+ slip.h \
+ sll.h \
+ smb.h \
+ tcp.h \
+ tcpdump-stdinc.h \
+ telnet.h \
+ tftp.h \
+ timed.h \
+ token.h \
+ udp.h
TAGHDR = \
/usr/include/arpa/tftp.h \
@@ -120,12 +198,92 @@ TAGFILES = $(SRC) $(HDR) $(TAGHDR)
CLEANFILES = $(PROG) $(OBJ) $(GENSRC)
+EXTRA_DIST = \
+ CHANGES \
+ CREDITS \
+ INSTALL.txt \
+ LICENSE \
+ Makefile.in \
+ README \
+ Readme.Win32 \
+ VERSION \
+ aclocal.m4 \
+ atime.awk \
+ bpf_dump.c \
+ config.guess \
+ config.h.in \
+ config.sub \
+ configure \
+ configure.in \
+ install-sh \
+ lbl/os-osf4.h \
+ lbl/os-solaris2.h \
+ lbl/os-sunos4.h \
+ lbl/os-ultrix4.h \
+ makemib \
+ missing/addrinfo.h \
+ missing/addrsize.h \
+ missing/bittypes.h \
+ missing/dlnames.c \
+ missing/datalinks.c \
+ missing/getaddrinfo.c \
+ missing/getnameinfo.c \
+ missing/inet_aton.c \
+ missing/inet_ntop.c \
+ missing/inet_pton.c \
+ missing/resolv6.h \
+ missing/resolv_ext.h \
+ missing/snprintf.c \
+ missing/sockstorage.h \
+ missing/strdup.c \
+ missing/strlcat.c \
+ missing/strlcpy.c \
+ missing/strsep.c \
+ mkdep \
+ packetdat.awk \
+ pcap_dump_ftell.c \
+ print-dhcp6.c \
+ print-frag6.c \
+ print-icmp6.c \
+ print-ip6.c \
+ print-ip6opts.c \
+ print-mobility.c \
+ print-netbios.c \
+ print-ospf6.c \
+ print-pflog.c \
+ print-ripng.c \
+ print-rt6.c \
+ print-smb.c \
+ send-ack.awk \
+ smbutil.c \
+ stime.awk \
+ strcasecmp.c \
+ tcpdump.1 \
+ vfprintf.c \
+ win32/Include/Arpa/tftp.h \
+ win32/Include/errno.h \
+ win32/Include/getopt.h \
+ win32/Include/inetprivate.h \
+ win32/Include/telnet.h \
+ win32/Include/w32_fzs.h \
+ win32/Include/Netinet/in_systm.h \
+ win32/Include/Netinet/ip.h \
+ win32/Src/getopt.c \
+ win32/prj/GNUmakefile \
+ win32/prj/WinDump.dsp \
+ win32/prj/WinDump.dsw
+
all: $(PROG)
$(PROG): $(OBJ) @V_PCAPDEP@
@rm -f $@
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
+$(LIBNETDISSECT): $(LIBNETDISSECT_OBJ)
+ @rm -f $@
+ $(AR) cr $@ $(LIBNETDISSECT_OBJ)
+ $(RANLIB) $@
+
datalinks.o: $(srcdir)/missing/datalinks.c
$(CC) $(CFLAGS) -o $@ -c $(srcdir)/missing/datalinks.c
dlnames.o: $(srcdir)/missing/dlnames.c
@@ -154,12 +312,20 @@ version.o: version.c
version.c: $(srcdir)/VERSION
@rm -f $@
- sed -e 's/.*/char version[] = "&";/' $(srcdir)/VERSION > $@
+ if grep CVS ${srcdir}/VERSION >/dev/null; then \
+ read ver <${srcdir}/VERSION; \
+ echo $$ver | tr -d '\012'; \
+ date +_%Y_%m_%d; \
+ else \
+ cat ${srcdir}/VERSION; \
+ fi | sed -e 's/.*/char version[] = "&";/' > $@
+
-install:
+install: all
[ -d $(DESTDIR)$(sbindir) ] || \
(mkdir -p $(DESTDIR)$(sbindir); chmod 755 $(DESTDIR)$(sbindir))
$(INSTALL_PROGRAM) $(PROG) $(DESTDIR)$(sbindir)/$(PROG)
+ $(INSTALL_PROGRAM) $(PROG) $(DESTDIR)$(sbindir)/$(PROG).`cat ${srcdir}/VERSION`
[ -d $(DESTDIR)$(mandir)/man1 ] || \
(mkdir -p $(DESTDIR)$(mandir)/man1; chmod 755 $(DESTDIR)$(mandir)/man1)
$(INSTALL_DATA) $(srcdir)/$(PROG).1 $(DESTDIR)$(mandir)/man1/$(PROG).1
@@ -183,10 +349,15 @@ distclean:
tags: $(TAGFILES)
ctags -wtd $(TAGFILES)
+TAGS: $(TAGFILES)
+ etags $(TAGFILES)
+
releasetar:
@cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \
- list="" ; make distclean; cd ..; mkdir -p n; cd n; ln -s ../$$dir $$name; \
- tar -c -z -f $$name.tar.gz $$name/. ;
+ mkdir $$name; \
+ tar cf - $(CSRC) $(HDR) $(LIBNETDISSECT_SRC) $(EXTRA_DIST) | (cd $$name; tar xf -); \
+ tar -c -z -f $$name.tar.gz $$name; \
+ rm -rf $$name
depend: $(GENSRC)
${srcdir}/mkdep -c $(CC) $(DEFS) $(INCLS) $(SRC)
diff --git a/contrib/tcpdump/PLATFORMS b/contrib/tcpdump/PLATFORMS
deleted file mode 100644
index 2e1aedf..0000000
--- a/contrib/tcpdump/PLATFORMS
+++ /dev/null
@@ -1,9 +0,0 @@
-== Tested platforms ==
-NetBSD 1.5/i386 (mcr - 2002/1/1)
-Debian Linux (woody/i386) (mcr - 2002/1/1)
-
----
-RedHat Linux 6.1/i386 (assar)
-FreeBSD 2.2.8/i386 (itojun)
-
-
diff --git a/contrib/tcpdump/README b/contrib/tcpdump/README
index cb51d30..c2b6760 100644
--- a/contrib/tcpdump/README
+++ b/contrib/tcpdump/README
@@ -1,10 +1,11 @@
-@(#) $Header: /tcpdump/master/tcpdump/README,v 1.65.2.1 2007/09/14 01:03:12 guy Exp $ (LBL)
+@(#) $Header: /tcpdump/master/tcpdump/README,v 1.66.2.1 2008-05-30 01:38:20 guy Exp $ (LBL)
TCPDUMP 3.9
Now maintained by "The Tcpdump Group"
See www.tcpdump.org
-Please send inquiries/comments/reports to tcpdump-workers@tcpdump.org
+Please send inquiries/comments/reports to:
+ tcpdump-workers@lists.tcpdump.org
Anonymous CVS is available via:
cvs -d :pserver:cvs.tcpdump.org:/tcpdump/master login
@@ -68,15 +69,14 @@ trace files. See the above distribution for further details and
documentation.
Problems, bugs, questions, desirable enhancements, etc. should be sent
-to the address "tcpdump-workers@tcpdump.org". Bugs, support requests,
-and feature requests may also be submitted on the SourceForge site for
-tcpdump at
+to the address "tcpdump-workers@lists.tcpdump.org". Bugs, support
+requests, and feature requests may also be submitted on the SourceForge
+site for tcpdump at
http://sourceforge.net/projects/tcpdump/
Source code contributions, etc. should be sent to the email address
-"patches@tcpdump.org", or submitted as patches on the SourceForge site
-for tcpdump.
+submitted as patches on the SourceForge site for tcpdump.
Current versions can be found at www.tcpdump.org, or the SourceForge
site for tcpdump.
diff --git a/contrib/tcpdump/Readme.Win32 b/contrib/tcpdump/Readme.Win32
deleted file mode 100644
index fdf8b12..0000000
--- a/contrib/tcpdump/Readme.Win32
+++ /dev/null
@@ -1,24 +0,0 @@
-To build tcpdump under Windows, you need:
-
-- version 6 (or higher) of Microsoft Visual Studio or the Cygnus gnu
-C compiler.
-- The November 2001 (or later) edition of Microsoft Platform
-Software Development Kit (SDK), that contains some necessary includes
-for IPv6 support. You can download it from http://www.microsoft.com/sdk
-- the WinPcap source code, that includes libpcap for win32. Download it
-from http://winpcap.polito.it or download libpcap sources from
-http://www.tcpdump.org and follow the instructions in the README.Win32
-file.
-
-First, extract tcpdump and WinPcap in the same folder, and build WinPcap.
-
-The Visual Studio project and the cygwin makefile are in the Win32\prj
-folder.
-
-From Visual Studio, open windump.dsw and build the program. The release
-version of the WinDump.exe executable file will be created in the
-windump\win32\prj\release directory . The debug version will be generated
-in windump\win32\prj\debug.
-
-From cygnus, go to windump\win32\prj\ and type "make". WinDump.exe will be
-created in the same directory. \ No newline at end of file
diff --git a/contrib/tcpdump/TODO b/contrib/tcpdump/TODO
deleted file mode 100644
index 12c8b3f..0000000
--- a/contrib/tcpdump/TODO
+++ /dev/null
@@ -1,6 +0,0 @@
-1. update credits
-2. review "FILES"
-3. search for version info
-4. get PLATFORMS filled in
-5. update CHANGES file
-6. do same for libpcap
diff --git a/contrib/tcpdump/VERSION b/contrib/tcpdump/VERSION
index 26cb485..fcdb2e1 100644
--- a/contrib/tcpdump/VERSION
+++ b/contrib/tcpdump/VERSION
@@ -1 +1 @@
-3.9.8
+4.0.0
diff --git a/contrib/tcpdump/addrtoname.c b/contrib/tcpdump/addrtoname.c
index db9a93c..0540343 100644
--- a/contrib/tcpdump/addrtoname.c
+++ b/contrib/tcpdump/addrtoname.c
@@ -25,7 +25,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/addrtoname.c,v 1.108.2.9 2007/09/14 00:26:18 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/addrtoname.c,v 1.119 2007-08-08 14:06:34 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -81,7 +81,6 @@ extern int ether_ntohost(char *, const struct ether_addr *);
*/
#define HASHNAMESIZE 4096
-#define BUFSIZE 128
struct hnamemem {
u_int32_t addr;
@@ -511,14 +510,19 @@ etheraddr_string(register const u_char *ep)
}
const char *
-linkaddr_string(const u_char *ep, const unsigned int len)
+linkaddr_string(const u_char *ep, const unsigned int type, const unsigned int len)
{
register u_int i;
register char *cp;
register struct enamemem *tp;
- if (len == ETHER_ADDR_LEN) /* XXX not totally correct... */
- return etheraddr_string(ep);
+ if (type == LINKADDR_ETHER && len == ETHER_ADDR_LEN) {
+ return etheraddr_string(ep);
+ }
+
+ if (type == LINKADDR_FRELAY) {
+ return q922_string(ep);
+ }
tp = lookup_bytestring(ep, len);
if (tp->e_name)
diff --git a/contrib/tcpdump/addrtoname.h b/contrib/tcpdump/addrtoname.h
index 67ded6e..1df204a9 100644
--- a/contrib/tcpdump/addrtoname.h
+++ b/contrib/tcpdump/addrtoname.h
@@ -18,12 +18,21 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/addrtoname.h,v 1.18 2001/09/17 21:57:51 fenner Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/addrtoname.h,v 1.20 2007-08-08 14:06:34 hannes Exp $ (LBL)
*/
/* Name to address translation routines. */
-extern const char *linkaddr_string(const u_char *, const unsigned int);
+enum {
+ LINKADDR_ETHER,
+ LINKADDR_FRELAY,
+ LINKADDR_IEEE1394,
+ LINKADDR_ATM
+};
+
+#define BUFSIZE 128
+
+extern const char *linkaddr_string(const u_char *, const unsigned int, const unsigned int);
extern const char *etheraddr_string(const u_char *);
extern const char *etherproto_string(u_short);
extern const char *tcpport_string(u_short);
diff --git a/contrib/tcpdump/af.c b/contrib/tcpdump/af.c
index 76d6178..e3c77bf 100644
--- a/contrib/tcpdump/af.c
+++ b/contrib/tcpdump/af.c
@@ -17,7 +17,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/af.c,v 1.3.2.1 2007/02/26 13:33:17 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/af.c,v 1.3 2006-03-23 14:58:44 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/af.h b/contrib/tcpdump/af.h
index 1ba7662..c036cef 100644
--- a/contrib/tcpdump/af.h
+++ b/contrib/tcpdump/af.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/af.h,v 1.3.2.1 2007/02/26 13:33:17 hannes Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/af.h,v 1.3 2006-03-23 14:58:44 hannes Exp $ (LBL) */
/*
* Copyright (c) 1998-2006 The TCPDUMP project
diff --git a/contrib/tcpdump/aodv.h b/contrib/tcpdump/aodv.h
index 335c175..456ec8b 100644
--- a/contrib/tcpdump/aodv.h
+++ b/contrib/tcpdump/aodv.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/aodv.h,v 1.3 2003/09/13 01:34:42 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/aodv.h,v 1.3 2003-09-13 01:34:42 guy Exp $ (LBL) */
/*
* Copyright (c) 2003 Bruce M. Simpson <bms@spc.org>
* All rights reserved.
diff --git a/contrib/tcpdump/appletalk.h b/contrib/tcpdump/appletalk.h
index 67e62ef..ff972f6 100644
--- a/contrib/tcpdump/appletalk.h
+++ b/contrib/tcpdump/appletalk.h
@@ -20,7 +20,7 @@
*
* AppleTalk protocol formats (courtesy Bill Croft of Stanford/SUMEX).
*
- * @(#) $Header: /tcpdump/master/tcpdump/appletalk.h,v 1.16 2004/05/01 09:41:50 hannes Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/appletalk.h,v 1.16 2004-05-01 09:41:50 hannes Exp $ (LBL)
*/
struct LAP {
diff --git a/contrib/tcpdump/arcnet.h b/contrib/tcpdump/arcnet.h
index 6e649f6..3b60956 100644
--- a/contrib/tcpdump/arcnet.h
+++ b/contrib/tcpdump/arcnet.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Id: arcnet.h,v 1.3 2003/01/23 09:05:37 guy Exp $ (LBL)
+ * @(#) $Id: arcnet.h,v 1.3 2003-01-23 09:05:37 guy Exp $ (LBL)
*
* from: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp
*/
diff --git a/contrib/tcpdump/atm.h b/contrib/tcpdump/atm.h
index c6ac53e..65ac5c1 100644
--- a/contrib/tcpdump/atm.h
+++ b/contrib/tcpdump/atm.h
@@ -14,7 +14,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/atm.h,v 1.1.4.1 2005/06/20 07:45:05 hannes Exp $
+ * @(#) $Header: /tcpdump/master/tcpdump/atm.h,v 1.3 2006-02-08 01:43:00 hannes Exp $
*/
/*
@@ -30,3 +30,4 @@
*/
#define ATM_OAM_NOHEC 0
#define ATM_OAM_HEC 1
+#define ATM_HDR_LEN_NOHEC 4
diff --git a/contrib/tcpdump/atmuni31.h b/contrib/tcpdump/atmuni31.h
index 304859a..32acfb1 100644
--- a/contrib/tcpdump/atmuni31.h
+++ b/contrib/tcpdump/atmuni31.h
@@ -29,18 +29,18 @@
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/atmuni31.h,v 1.2 2002/08/05 07:47:23 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/atmuni31.h,v 1.2.6.1 2007-10-22 19:39:12 guy Exp $ (LBL)
*/
/* Based on UNI3.1 standard by ATM Forum */
/* ATM traffic types based on VPI=0 and (the following VCI */
-#define PPC 0x05 /* Point-to-point signal msg */
-#define BCC 0x02 /* Broadcast signal msg */
-#define OAMF4SC 0x03 /* Segment OAM F4 flow cell */
-#define OAMF4EC 0x04 /* End-to-end OAM F4 flow cell */
-#define METAC 0x01 /* Meta signal msg */
-#define ILMIC 0x10 /* ILMI msg */
+#define VCI_PPC 0x05 /* Point-to-point signal msg */
+#define VCI_BCC 0x02 /* Broadcast signal msg */
+#define VCI_OAMF4SC 0x03 /* Segment OAM F4 flow cell */
+#define VCI_OAMF4EC 0x04 /* End-to-end OAM F4 flow cell */
+#define VCI_METAC 0x01 /* Meta signal msg */
+#define VCI_ILMIC 0x10 /* ILMI msg */
/* Q.2931 signalling messages */
#define CALL_PROCEED 0x02 /* call proceeding */
diff --git a/contrib/tcpdump/bgp.h b/contrib/tcpdump/bgp.h
index 06be3ea..5081596 100755
--- a/contrib/tcpdump/bgp.h
+++ b/contrib/tcpdump/bgp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/bgp.h,v 1.3 2004/06/16 08:45:15 hannes Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/bgp.h,v 1.3 2004-06-16 08:45:15 hannes Exp $ (LBL) */
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code
diff --git a/contrib/tcpdump/bootp.h b/contrib/tcpdump/bootp.h
index 7c63d0c..8f61b13 100644
--- a/contrib/tcpdump/bootp.h
+++ b/contrib/tcpdump/bootp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/bootp.h,v 1.15.4.3 2007/08/21 22:02:08 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/bootp.h,v 1.18 2007-08-21 21:59:11 guy Exp $ (LBL) */
/*
* Bootstrap Protocol (BOOTP). RFC951 and RFC1048.
*
diff --git a/contrib/tcpdump/bpf_dump.c b/contrib/tcpdump/bpf_dump.c
index 0cad4d9..f509b7e 100644
--- a/contrib/tcpdump/bpf_dump.c
+++ b/contrib/tcpdump/bpf_dump.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/bpf_dump.c,v 1.16 2003/11/16 09:36:08 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/bpf_dump.c,v 1.16.4.1 2008-02-14 20:54:53 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -35,7 +35,7 @@ static const char rcsid[] _U_ =
#include "interface.h"
void
-bpf_dump(struct bpf_program *p, int option)
+bpf_dump(const struct bpf_program *p, int option)
{
struct bpf_insn *insn;
int i;
diff --git a/contrib/tcpdump/chdlc.h b/contrib/tcpdump/chdlc.h
index 4fb6e1d..d117263 100644
--- a/contrib/tcpdump/chdlc.h
+++ b/contrib/tcpdump/chdlc.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/chdlc.h,v 1.1 2000/09/18 05:11:43 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/chdlc.h,v 1.1 2000-09-18 05:11:43 guy Exp $ (LBL) */
/*
* Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
diff --git a/contrib/tcpdump/checksum.c b/contrib/tcpdump/checksum.c
new file mode 100644
index 0000000..f441be3
--- /dev/null
+++ b/contrib/tcpdump/checksum.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 1998-2006 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * miscellaneous checksumming routines
+ *
+ * Original code by Hannes Gredler (hannes@juniper.net)
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/checksum.c,v 1.4 2006-09-25 09:23:32 hannes Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interface.h"
+
+#define CRC10_POLYNOMIAL 0x633
+static u_int16_t crc10_table[256];
+
+static void
+init_crc10_table(void)
+{
+ register int i, j;
+ register u_int16_t accum;
+
+ for ( i = 0; i < 256; i++ )
+ {
+ accum = ((unsigned short) i << 2);
+ for ( j = 0; j < 8; j++ )
+ {
+ if ((accum <<= 1) & 0x400) accum ^= CRC10_POLYNOMIAL;
+ }
+ crc10_table[i] = accum;
+ }
+ return;
+}
+
+u_int16_t
+verify_crc10_cksum(u_int16_t accum, const u_char *p, int length)
+{
+ register int i;
+
+ for ( i = 0; i < length; i++ )
+ {
+ accum = ((accum << 8) & 0x3ff)
+ ^ crc10_table[( accum >> 2) & 0xff]
+ ^ *p++;
+ }
+ return accum;
+}
+
+/* precompute checksum tables */
+void
+init_checksum(void) {
+
+ init_crc10_table();
+
+}
+
+/*
+ * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
+ * The checksum field of the passed PDU does not need to be reset to zero.
+ */
+u_int16_t
+create_osi_cksum (const u_int8_t *pptr, int checksum_offset, int length)
+{
+
+ int x;
+ int y;
+ u_int32_t mul;
+ u_int32_t c0;
+ u_int32_t c1;
+ u_int16_t checksum;
+ int index;
+
+ checksum = 0;
+
+ c0 = 0;
+ c1 = 0;
+
+ for (index = 0; index < length; index++) {
+ /*
+ * Ignore the contents of the checksum field.
+ */
+ if (index == checksum_offset ||
+ index == checksum_offset+1) {
+ c1 += c0;
+ pptr++;
+ } else {
+ c0 = c0 + *(pptr++);
+ c1 += c0;
+ }
+ }
+
+ c0 = c0 % 255;
+ c1 = c1 % 255;
+
+ mul = (length - checksum_offset)*(c0);
+
+ x = mul - c0 - c1;
+ y = c1 - mul - 1;
+
+ if ( y >= 0 ) y++;
+ if ( x < 0 ) x--;
+
+ x %= 255;
+ y %= 255;
+
+
+ if (x == 0) x = 255;
+ if (y == 0) y = 255;
+
+ y &= 0x00FF;
+ checksum = ((x << 8) | y);
+
+ return checksum;
+}
diff --git a/contrib/tcpdump/config.h.in b/contrib/tcpdump/config.h.in
index 86ffe06..085cc93 100644
--- a/contrib/tcpdump/config.h.in
+++ b/contrib/tcpdump/config.h.in
@@ -187,9 +187,15 @@
/* Define to 1 if you have the <openssl/evp.h> header file. */
#undef HAVE_OPENSSL_EVP_H
+/* Define to 1 if you have the <pcap/bluetooth.h> header file. */
+#undef HAVE_PCAP_BLUETOOTH_H
+
/* Define to 1 if you have the `pcap_breakloop' function. */
#undef HAVE_PCAP_BREAKLOOP
+/* Define to 1 if you have the `pcap_create' function. */
+#undef HAVE_PCAP_CREATE
+
/* Define to 1 if you have the `pcap_dump_flush' function. */
#undef HAVE_PCAP_DUMP_FLUSH
diff --git a/contrib/tcpdump/configure b/contrib/tcpdump/configure
index 2494df5..f4b7754 100755
--- a/contrib/tcpdump/configure
+++ b/contrib/tcpdump/configure
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.in Revision: 1.188.2.8 .
+# From configure.in Revision: 1.196.2.6 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.61.
#
@@ -671,6 +671,7 @@ CPP
GREP
EGREP
LIBOBJS
+RANLIB
V_CCOPT
V_DEFS
V_GROUP
@@ -1274,7 +1275,8 @@ Optional Packages:
--without-gcc don't use gcc
--with-user=USERNAME drop privileges by default to USERNAME
--with-chroot=DIRECTORY when dropping privileges, chroot to DIRECTORY
- --without-crypto disable crypto support
+ --with-crypto[=PATH] use SSLeay libcrypto (located in directory PATH, if
+ supplied). [default=yes, if available]
Some influential environment variables:
CC C compiler command
@@ -4035,7 +4037,7 @@ fi
done
-if test "$ac_cv_header_net_pfvar_h" == yes; then
+if test "$ac_cv_header_net_pfvar_h" = yes; then
LOCALSRC="print-pflog.c $LOCALSRC"
fi
@@ -9362,7 +9364,7 @@ fi
echo "$as_me: error: see the INSTALL doc for more info" >&2;}
{ (exit 1); exit 1; }; }
fi
- { echo "$as_me:$LINENO: checking for extraneous pcap header directories" >&5
+ { echo "$as_me:$LINENO: checking for extraneous pcap header directories" >&5
echo $ECHO_N "checking for extraneous pcap header directories... $ECHO_C" >&6; }
if test \( ! -r /usr/local/include/pcap.h \) -a \
\( ! -r /usr/include/pcap.h \); then
@@ -10758,6 +10760,73 @@ _ACEOF
fi
fi
+# libdlpi is needed for Solaris 11 and later.
+{ echo "$as_me:$LINENO: checking for dlpi_walk in -ldlpi" >&5
+echo $ECHO_N "checking for dlpi_walk in -ldlpi... $ECHO_C" >&6; }
+if test "${ac_cv_lib_dlpi_dlpi_walk+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldlpi -L/lib $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlpi_walk ();
+int
+main ()
+{
+return dlpi_walk ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ ac_cv_lib_dlpi_dlpi_walk=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_cv_lib_dlpi_dlpi_walk=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_dlpi_dlpi_walk" >&5
+echo "${ECHO_T}$ac_cv_lib_dlpi_dlpi_walk" >&6; }
+if test $ac_cv_lib_dlpi_dlpi_walk = yes; then
+ LIBS="$LIBS -ldlpi" LDFLAGS="-L/lib $LDFLAGS"
+fi
+
+
{ echo "$as_me:$LINENO: checking if sockaddr struct has sa_len member" >&5
echo $ECHO_N "checking if sockaddr struct has sa_len member... $ECHO_C" >&6; }
@@ -10822,6 +10891,104 @@ if test "$ac_cv_sockaddr_has_sa_len" = no; then
missing_includes=yes
fi
+#
+# Do we have the new open API? Check for pcap_create, and assume that,
+# if we do, we also have pcap_activate() and the other new routines.
+
+for ac_func in pcap_create
+do
+as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_link") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext &&
+ $as_test_x conftest$ac_exeext; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ eval "$as_ac_var=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval echo '${'$as_ac_var'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
@@ -10919,8 +11086,8 @@ fi
done
if test $ac_cv_func_pcap_findalldevs = "yes" ; then
- savedcflags="$CFLAGS"
- CFLAGS="$CFLAGS $V_INCLS"
+ savedppflags="$CPPLAGS"
+ CPPFLAGS="$CPPFLAGS $V_INCLS"
{ echo "$as_me:$LINENO: checking for pcap_if_t" >&5
echo $ECHO_N "checking for pcap_if_t... $ECHO_C" >&6; }
if test "${ac_cv_type_pcap_if_t+set}" = set; then
@@ -10984,7 +11151,7 @@ _ACEOF
fi
- CFLAGS="$savedcflags"
+ CPPFLAGS="$savedcppflags"
fi
if test $ac_cv_func_pcap_lib_version = "no" ; then
@@ -11304,6 +11471,154 @@ if test -f /dev/bpf0 ; then
V_GROUP=bpf
fi
+#
+# Check for some headers introduced in later versions of libpcap
+# and used by some printers.
+#
+savedcppflags="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $V_INCLS"
+
+for ac_header in pcap/bluetooth.h
+do
+as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ { echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
+echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_compile") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then
+ ac_header_compiler=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
+echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then
+ ac_header_preproc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+ yes:no: )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+ ac_header_preproc=yes
+ ;;
+ no:yes:* )
+ { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+ { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+
+ ;;
+esac
+{ echo "$as_me:$LINENO: checking for $ac_header" >&5
+echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+ { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+CPPFLAGS="$savedcppflags"
+
for ac_header in sys/bitypes.h
do
@@ -12581,6 +12896,103 @@ fi
fi
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { echo "$as_me:$LINENO: result: $RANLIB" >&5
+echo "${ECHO_T}$RANLIB" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; }
+if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5
+echo "${ECHO_T}$ac_ct_RANLIB" >&6; }
+else
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ echo "$as_me:$LINENO: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&5
+echo "$as_me: WARNING: In the future, Autoconf will not detect cross-tools
+whose name does not start with the host triplet. If you think this
+configuration is useful to you, please write to autoconf@gnu.org." >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+
rm -f os-proto.h
if test "${LBL_CFLAGS+set}" = set; then
V_CCOPT="$V_CCOPT ${LBL_CFLAGS}"
@@ -12719,7 +13131,7 @@ else
# know it does work, and have the script just fail on other
# cpu types and update it when such a failure occurs.
#
- alpha*|arm*|hp*|mips*|sh*|sparc*|ia64|nv1)
+ alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1)
ac_cv_lbl_unaligned_fail=yes
;;
@@ -12837,65 +13249,136 @@ _ACEOF
fi
+# Check for SSLeay
+{ echo "$as_me:$LINENO: checking whether to use SSLeay libcrypto" >&5
+echo $ECHO_N "checking whether to use SSLeay libcrypto... $ECHO_C" >&6; }
+# Specify location for both includes and libraries.
+want_libcrypto=youmama
# Check whether --with-crypto was given.
if test "${with_crypto+set}" = set; then
withval=$with_crypto;
+ if test $withval = no
+ then
+ want_libcrypto=no
+ { echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6; }
+ elif test $withval = yes
+ then
+ want_libcrypto=yes
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ else
+ want_libcrypto=yes
+ { echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6; }
+ crypto_dir=$withval
+ fi
+
else
-{ echo "$as_me:$LINENO: checking for SSLeay" >&5
-echo $ECHO_N "checking for SSLeay... $ECHO_C" >&6; }
-ac_cv_ssleay_path=no
-incdir=no
+ #
+ # Use libcrypto if it's present, otherwise don't.
+ #
+ want_libcrypto=ifavailable
+ { echo "$as_me:$LINENO: result: yes, if available" >&5
+echo "${ECHO_T}yes, if available" >&6; }
-#
-# If Xprefix is set in the environment, use that value.
-# XXX - this should arguably be done by having --with-crypto take an
-# optional argument, and have that argument be used to set Xprefix
-# if present.
-#
-if test -z "$Xprefix"; then
- Xprefix=`eval echo $prefix`
fi
-for dir in $Xprefix /usr/${host_alias} /usr /usr/local /usr/local/ssl /usr/pkg; do
+if test "$want_libcrypto" != "no"; then
+ ac_cv_ssleay_path=no
+ incdir=no
+ if test "x$crypto_dir" = x; then
+ #
+ # Location not specified; check the default locations.
+ #
+ { echo "$as_me:$LINENO: checking where SSLeay is located" >&5
+echo $ECHO_N "checking where SSLeay is located... $ECHO_C" >&6; }
+ dirs="/usr /usr/local /usr/local/ssl /usr/pkg"
+ if test "x${host_alias}" != x; then
+ dirs="/usr/${host_alias} $dirs"
+ fi
+ for dir in $dirs; do
+
#
# XXX - is there a better way to check if a given library is
# in a given directory than checking each of the possible
# shared library suffixes?
#
- # Are there any other suffixes we need to look for? Do we have to
- # worry about ".so.{version}"?
+ # Are there any other suffixes we need to look for? Do we
+ # have to worry about ".so.{version}"?
#
# Or should we just look for "libcrypto.*"?
#
- if test -d $dir/lib -a \( -f $dir/lib/libcrypto.a -o \
- -f $dir/lib/libcrypto.so -o \
- -f $dir/lib/libcrypto.sl -o \
- -f $dir/lib/libcrypto.dylib \); then
- ac_cv_ssleay_path=$dir
+ if test -d "$dir/lib" -a \( -f "$dir/lib/libcrypto.a" -o \
+ -f "$dir/lib/libcrypto.so" -o \
+ -f "$dir/lib/libcrypto.sl" -o \
+ -f "$dir/lib/libcrypto.dylib" \); then
+ ac_cv_ssleay_path="$dir"
fi
- if test -d $dir/include/openssl -a -f $dir/include/openssl/des.h; then
+
+ #
+ # Make sure we have the headers as well.
+ #
+ if test -d "$dir/include/openssl" -a -f "$dir/include/openssl/des.h"; then
incdir="-I$dir/include"
fi
- if test "$ac_cv_ssleay_path" != "no" -a "$incdir" != "no"; then
- break;
+
+
+ if test "$ac_cv_ssleay_path" != "no" -a "$incdir" != "no"; then
+ break;
+ else
+ ac_cv_ssleay_path=no
+ incdir=no
+ fi
+ done
+ if test "$ac_cv_ssleay_path" != no; then
+ { echo "$as_me:$LINENO: result: $ac_cv_ssleay_path" >&5
+echo "${ECHO_T}$ac_cv_ssleay_path" >&6; }
+ fi
else
- ac_cv_ssleay_path=no
- incdir=no
+ { echo "$as_me:$LINENO: checking for SSLeay in $crypto_dir" >&5
+echo $ECHO_N "checking for SSLeay in $crypto_dir... $ECHO_C" >&6; }
+
+ #
+ # XXX - is there a better way to check if a given library is
+ # in a given directory than checking each of the possible
+ # shared library suffixes?
+ #
+ # Are there any other suffixes we need to look for? Do we
+ # have to worry about ".so.{version}"?
+ #
+ # Or should we just look for "libcrypto.*"?
+ #
+ if test -d "$crypto_dir/lib" -a \( -f "$crypto_dir/lib/libcrypto.a" -o \
+ -f "$crypto_dir/lib/libcrypto.so" -o \
+ -f "$crypto_dir/lib/libcrypto.sl" -o \
+ -f "$crypto_dir/lib/libcrypto.dylib" \); then
+ ac_cv_ssleay_path="$crypto_dir"
fi
-done
-{ echo "$as_me:$LINENO: result: $ac_cv_ssleay_path" >&5
-echo "${ECHO_T}$ac_cv_ssleay_path" >&6; }
-if test "$ac_cv_ssleay_path" != no; then
- V_INCLS="$V_INCLS $incdir"
- LDFLAGS="-L$dir/lib $LDFLAGS"
- if test -f $ac_cv_ssleay_path/lib/libRSAglue.a; then
- LIBS="$LIBS -lRSAglue"
+
+ #
+ # Make sure we have the headers as well.
+ #
+ if test -d "$crypto_dir/include/openssl" -a -f "$crypto_dir/include/openssl/des.h"; then
+ incdir="-I$crypto_dir/include"
fi
- if test -f $ac_cv_ssleay_path/lib/librsaref.a; then
- LIBS="$LIBS -lrsaref"
+
+ if test "$ac_cv_ssleay_path" != no; then
+ { echo "$as_me:$LINENO: result: found" >&5
+echo "${ECHO_T}found" >&6; }
+ fi
fi
+ if test "$ac_cv_ssleay_path" != no; then
+ V_INCLS="$V_INCLS $incdir"
+ LDFLAGS="-L$dir/lib $LDFLAGS"
+ if test -f $ac_cv_ssleay_path/lib/libRSAglue.a; then
+ LIBS="$LIBS -lRSAglue"
+ fi
+ if test -f $ac_cv_ssleay_path/lib/librsaref.a; then
+ LIBS="$LIBS -lrsaref"
+ fi
{ echo "$as_me:$LINENO: checking for DES_cbc_encrypt in -lcrypto" >&5
echo $ECHO_N "checking for DES_cbc_encrypt in -lcrypto... $ECHO_C" >&6; }
@@ -12968,7 +13451,7 @@ _ACEOF
fi
- CPPFLAGS="$CPPFLAGS $V_INCLS"
+ CPPFLAGS="$CPPFLAGS $V_INCLS"
for ac_header in openssl/evp.h
do
@@ -13109,11 +13592,20 @@ fi
done
+ else
+ #
+ # Not found. Did the user explicitly ask for it?
+ #
+ { echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; }
+ if test "$want_libcrypto" = yes; then
+ { { echo "$as_me:$LINENO: error: SSLeay not found" >&5
+echo "$as_me: error: SSLeay not found" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
fi
-fi
-
-
if test "$missing_includes" = "yes"; then
CPPFLAGS="$CPPFLAGS -I\$(srcdir)/missing"
V_INCLS="$V_INCLS -I\$(srcdir)/missing"
@@ -13898,6 +14390,7 @@ CPP!$CPP$ac_delim
GREP!$GREP$ac_delim
EGREP!$EGREP$ac_delim
LIBOBJS!$LIBOBJS$ac_delim
+RANLIB!$RANLIB$ac_delim
V_CCOPT!$V_CCOPT$ac_delim
V_DEFS!$V_DEFS$ac_delim
V_GROUP!$V_GROUP$ac_delim
@@ -13910,7 +14403,7 @@ INSTALL_DATA!$INSTALL_DATA$ac_delim
LTLIBOBJS!$LTLIBOBJS$ac_delim
_ACEOF
- if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 67; then
+ if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 68; then
break
elif $ac_last_try; then
{ { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
diff --git a/contrib/tcpdump/configure.in b/contrib/tcpdump/configure.in
index 5a010e7..f3528c4 100755
--- a/contrib/tcpdump/configure.in
+++ b/contrib/tcpdump/configure.in
@@ -1,4 +1,4 @@
-dnl @(#) $Header: /tcpdump/master/tcpdump/configure.in,v 1.188.2.8 2007/09/12 19:48:50 guy Exp $ (LBL)
+dnl @(#) $Header: /tcpdump/master/tcpdump/configure.in,v 1.196.2.6 2008-09-25 21:50:04 guy Exp $ (LBL)
dnl
dnl Copyright (c) 1994, 1995, 1996, 1997
dnl The Regents of the University of California. All rights reserved.
@@ -6,7 +6,7 @@ dnl
dnl Process this file with autoconf to produce a configure script.
dnl
-AC_REVISION($Revision: 1.188.2.8 $)
+AC_REVISION($Revision: 1.196.2.6 $)
AC_PREREQ(2.50)
AC_INIT(tcpdump.c)
@@ -19,7 +19,7 @@ AC_CHECK_HEADERS(fcntl.h rpc/rpcent.h netdnet/dnetdb.h)
AC_CHECK_HEADERS(net/pfvar.h, , , [#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>])
-if test "$ac_cv_header_net_pfvar_h" == yes; then
+if test "$ac_cv_header_net_pfvar_h" = yes; then
LOCALSRC="print-pflog.c $LOCALSRC"
fi
AC_CHECK_HEADERS(netinet/if_ether.h, , , [#include <sys/types.h>
@@ -696,6 +696,9 @@ don't.])
fi
fi
+# libdlpi is needed for Solaris 11 and later.
+AC_CHECK_LIB(dlpi, dlpi_walk, LIBS="$LIBS -ldlpi" LDFLAGS="-L/lib $LDFLAGS", ,-L/lib)
+
dnl portability macros for getaddrinfo/getnameinfo
dnl
dnl Check for sa_len
@@ -704,15 +707,20 @@ if test "$ac_cv_sockaddr_has_sa_len" = no; then
missing_includes=yes
fi
+#
+# Do we have the new open API? Check for pcap_create, and assume that,
+# if we do, we also have pcap_activate() and the other new routines.
+AC_CHECK_FUNCS(pcap_create)
+
AC_CHECK_FUNCS(pcap_findalldevs pcap_dump_flush pcap_lib_version)
if test $ac_cv_func_pcap_findalldevs = "yes" ; then
dnl Check for Mac OS X, which may ship pcap.h from 0.6 but libpcap may
dnl be 0.8; this means that lib has pcap_findalldevs but header doesn't
dnl have pcap_if_t.
- savedcflags="$CFLAGS"
- CFLAGS="$CFLAGS $V_INCLS"
+ savedppflags="$CPPLAGS"
+ CPPFLAGS="$CPPFLAGS $V_INCLS"
AC_CHECK_TYPES(pcap_if_t, , , [#include <pcap.h>])
- CFLAGS="$savedcflags"
+ CPPFLAGS="$savedcppflags"
fi
if test $ac_cv_func_pcap_lib_version = "no" ; then
@@ -795,6 +803,15 @@ if test -f /dev/bpf0 ; then
V_GROUP=bpf
fi
+#
+# Check for some headers introduced in later versions of libpcap
+# and used by some printers.
+#
+savedcppflags="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $V_INCLS"
+AC_CHECK_HEADERS(pcap/bluetooth.h)
+CPPFLAGS="$savedcppflags"
+
AC_CHECK_HEADERS(sys/bitypes.h)
AC_CHECK_TYPE([int8_t], ,
@@ -900,6 +917,8 @@ if test "$ac_lbl_inttypes_h_defines_formats" = no; then
])
fi
+AC_PROG_RANLIB
+
AC_LBL_DEVEL(V_CCOPT)
AC_LBL_SOCKADDR_SA_LEN
@@ -908,65 +927,89 @@ AC_LBL_UNALIGNED_ACCESS
AC_VAR_H_ERRNO
-AC_ARG_WITH(crypto, [ --without-crypto disable crypto support],
- [], [
-AC_MSG_CHECKING(for SSLeay)
-ac_cv_ssleay_path=no
-incdir=no
-
-#
-# If Xprefix is set in the environment, use that value.
-# XXX - this should arguably be done by having --with-crypto take an
-# optional argument, and have that argument be used to set Xprefix
-# if present.
-#
-if test -z "$Xprefix"; then
- Xprefix=`eval echo $prefix`
-fi
-
-for dir in $Xprefix /usr/${host_alias} /usr /usr/local /usr/local/ssl /usr/pkg; do
- #
- # XXX - is there a better way to check if a given library is
- # in a given directory than checking each of the possible
- # shared library suffixes?
- #
- # Are there any other suffixes we need to look for? Do we have to
- # worry about ".so.{version}"?
+# Check for SSLeay
+AC_MSG_CHECKING(whether to use SSLeay libcrypto)
+# Specify location for both includes and libraries.
+want_libcrypto=youmama
+AC_ARG_WITH(crypto,
+ AS_HELP_STRING([--with-crypto@<:@=PATH@:>@],
+ [use SSLeay libcrypto (located in directory PATH, if supplied). @<:@default=yes, if available@:>@]),
+[
+ if test $withval = no
+ then
+ want_libcrypto=no
+ AC_MSG_RESULT(no)
+ elif test $withval = yes
+ then
+ want_libcrypto=yes
+ AC_MSG_RESULT(yes)
+ else
+ want_libcrypto=yes
+ AC_MSG_RESULT(yes)
+ crypto_dir=$withval
+ fi
+],[
#
- # Or should we just look for "libcrypto.*"?
+ # Use libcrypto if it's present, otherwise don't.
#
- if test -d $dir/lib -a \( -f $dir/lib/libcrypto.a -o \
- -f $dir/lib/libcrypto.so -o \
- -f $dir/lib/libcrypto.sl -o \
- -f $dir/lib/libcrypto.dylib \); then
- ac_cv_ssleay_path=$dir
- fi
- if test -d $dir/include/openssl -a -f $dir/include/openssl/des.h; then
- incdir="-I$dir/include"
- fi
- if test "$ac_cv_ssleay_path" != "no" -a "$incdir" != "no"; then
- break;
+ want_libcrypto=ifavailable
+ AC_MSG_RESULT([yes, if available])
+])
+if test "$want_libcrypto" != "no"; then
+ ac_cv_ssleay_path=no
+ incdir=no
+ if test "x$crypto_dir" = x; then
+ #
+ # Location not specified; check the default locations.
+ #
+ AC_MSG_CHECKING(where SSLeay is located)
+ dirs="/usr /usr/local /usr/local/ssl /usr/pkg"
+ if test "x${host_alias}" != x; then
+ dirs="/usr/${host_alias} $dirs"
+ fi
+ for dir in $dirs; do
+ AC_LBL_SSLEAY($dir)
+
+ if test "$ac_cv_ssleay_path" != "no" -a "$incdir" != "no"; then
+ break;
+ else
+ ac_cv_ssleay_path=no
+ incdir=no
+ fi
+ done
+ if test "$ac_cv_ssleay_path" != no; then
+ AC_MSG_RESULT($ac_cv_ssleay_path)
+ fi
else
- ac_cv_ssleay_path=no
- incdir=no
- fi
-done
-AC_MSG_RESULT($ac_cv_ssleay_path)
-if test "$ac_cv_ssleay_path" != no; then
- V_INCLS="$V_INCLS $incdir"
- LDFLAGS="-L$dir/lib $LDFLAGS"
- if test -f $ac_cv_ssleay_path/lib/libRSAglue.a; then
- LIBS="$LIBS -lRSAglue"
- fi
- if test -f $ac_cv_ssleay_path/lib/librsaref.a; then
- LIBS="$LIBS -lrsaref"
+ AC_MSG_CHECKING(for SSLeay in $crypto_dir)
+ AC_LBL_SSLEAY($crypto_dir)
+ if test "$ac_cv_ssleay_path" != no; then
+ AC_MSG_RESULT(found)
+ fi
fi
- AC_CHECK_LIB(crypto, DES_cbc_encrypt)
+ if test "$ac_cv_ssleay_path" != no; then
+ V_INCLS="$V_INCLS $incdir"
+ LDFLAGS="-L$dir/lib $LDFLAGS"
+ if test -f $ac_cv_ssleay_path/lib/libRSAglue.a; then
+ LIBS="$LIBS -lRSAglue"
+ fi
+ if test -f $ac_cv_ssleay_path/lib/librsaref.a; then
+ LIBS="$LIBS -lrsaref"
+ fi
+ AC_CHECK_LIB(crypto, DES_cbc_encrypt)
- CPPFLAGS="$CPPFLAGS $V_INCLS"
- AC_CHECK_HEADERS(openssl/evp.h)
+ CPPFLAGS="$CPPFLAGS $V_INCLS"
+ AC_CHECK_HEADERS(openssl/evp.h)
+ else
+ #
+ # Not found. Did the user explicitly ask for it?
+ #
+ AC_MSG_RESULT(not found)
+ if test "$want_libcrypto" = yes; then
+ AC_MSG_ERROR(SSLeay not found)
+ fi
+ fi
fi
-])
dnl
dnl set additional include path if necessary
diff --git a/contrib/tcpdump/dccp.h b/contrib/tcpdump/dccp.h
index 1afa8c0..5c66e23 100644
--- a/contrib/tcpdump/dccp.h
+++ b/contrib/tcpdump/dccp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/dccp.h,v 1.1.2.4 2006/05/12 01:46:17 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/dccp.h,v 1.5 2006-11-02 09:05:23 hannes Exp $ (LBL) */
/*
* Copyright (C) Arnaldo Carvalho de Melo 2004
* Copyright (C) Ian McDonald 2005 <iam4@cs.waikato.ac.nz>
@@ -36,8 +36,8 @@ struct dccp_hdr {
} dccph_xtrs;
};
-#define DCCPH_CCVAL(dh) (((dh)->dccph_ccval_cscov) & 0x0F)
-#define DCCPH_CSCOV(dh) (((dh)->dccph_ccval_cscov >> 4) & 0x0F)
+#define DCCPH_CCVAL(dh) (((dh)->dccph_ccval_cscov >> 4) & 0xF)
+#define DCCPH_CSCOV(dh) (((dh)->dccph_ccval_cscov) & 0xF)
#define DCCPH_X(dh) ((dh)->dccph_xtrs.dccph_xtr & 1)
#define DCCPH_TYPE(dh) (((dh)->dccph_xtrs.dccph_xtr >> 1) & 0xF)
diff --git a/contrib/tcpdump/decnet.h b/contrib/tcpdump/decnet.h
index 9a5c147..d25d157 100644
--- a/contrib/tcpdump/decnet.h
+++ b/contrib/tcpdump/decnet.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/decnet.h,v 1.11 2002/12/11 07:13:50 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/decnet.h,v 1.11 2002-12-11 07:13:50 guy Exp $ (LBL)
*/
#ifndef WIN32
diff --git a/contrib/tcpdump/enc.h b/contrib/tcpdump/enc.h
index f54b4eb..2d57e2b 100644
--- a/contrib/tcpdump/enc.h
+++ b/contrib/tcpdump/enc.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/enc.h,v 1.1 2003/03/08 08:55:33 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/enc.h,v 1.1 2003-03-08 08:55:33 guy Exp $ (LBL) */
/* From $OpenBSD: if_enc.h,v 1.8 2001/06/25 05:14:00 angelos Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
diff --git a/contrib/tcpdump/ether.h b/contrib/tcpdump/ether.h
index 3d3f3be..e8b3a71 100644
--- a/contrib/tcpdump/ether.h
+++ b/contrib/tcpdump/ether.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/ether.h,v 1.8 2002/12/11 07:13:51 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/ether.h,v 1.8 2002-12-11 07:13:51 guy Exp $ (LBL) */
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
diff --git a/contrib/tcpdump/ethertype.h b/contrib/tcpdump/ethertype.h
index 1555b4d..456a7d6 100644
--- a/contrib/tcpdump/ethertype.h
+++ b/contrib/tcpdump/ethertype.h
@@ -18,8 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- *
- * @(#) $Header: /tcpdump/master/tcpdump/ethertype.h,v 1.24.2.1 2005/07/10 14:51:10 hannes Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/ethertype.h,v 1.29.2.1 2008-02-06 10:49:22 guy Exp $ (LBL)
* $FreeBSD$
*/
@@ -111,6 +110,9 @@
#ifndef ETHERTYPE_PPP
#define ETHERTYPE_PPP 0x880b
#endif
+#ifndef ETHERTYPE_MPCP
+#define ETHERTYPE_MPCP 0x8808
+#endif
#ifndef ETHERTYPE_SLOW
#define ETHERTYPE_SLOW 0x8809
#endif
@@ -135,15 +137,27 @@
#ifndef ETHERTYPE_JUMBO
#define ETHERTYPE_JUMBO 0x8870
#endif
+#ifndef ETHERTYPE_LLDP
+#define ETHERTYPE_LLDP 0x88cc
+#endif
#ifndef ETHERTYPE_EAPOL
#define ETHERTYPE_EAPOL 0x888e
#endif
+#ifndef ETHERTYPE_RRCP
+#define ETHERTYPE_RRCP 0x8899
+#endif
#ifndef ETHERTYPE_LOOPBACK
#define ETHERTYPE_LOOPBACK 0x9000
#endif
#ifndef ETHERTYPE_VMAN
#define ETHERTYPE_VMAN 0x9100 /* Extreme VMAN Protocol */
#endif
+#ifndef ETHERTYPE_CFM_OLD
+#define ETHERTYPE_CFM_OLD 0xabcd /* 802.1ag depreciated */
+#endif
+#ifndef ETHERTYPE_CFM
+#define ETHERTYPE_CFM 0x8902 /* 802.1ag */
+#endif
#ifndef ETHERTYPE_ISO
#define ETHERTYPE_ISO 0xfefe /* nonstandard - used in Cisco HDLC encapsulation */
#endif
diff --git a/contrib/tcpdump/extract.h b/contrib/tcpdump/extract.h
index f3db250..bab63f2 100644
--- a/contrib/tcpdump/extract.h
+++ b/contrib/tcpdump/extract.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/extract.h,v 1.24 2005/01/15 02:06:50 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/extract.h,v 1.25 2006-01-30 16:20:07 hannes Exp $ (LBL)
*/
/*
@@ -115,6 +115,10 @@ typedef struct {
(u_int32_t)*((const u_int8_t *)(p) + 2) << 16 | \
(u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \
(u_int32_t)*((const u_int8_t *)(p) + 0)))
+#define EXTRACT_LE_24BITS(p) \
+ ((u_int32_t)((u_int32_t)*((const u_int8_t *)(p) + 2) << 16 | \
+ (u_int32_t)*((const u_int8_t *)(p) + 1) << 8 | \
+ (u_int32_t)*((const u_int8_t *)(p) + 0)))
#define EXTRACT_LE_64BITS(p) \
((u_int64_t)((u_int64_t)*((const u_int8_t *)(p) + 7) << 56 | \
(u_int64_t)*((const u_int8_t *)(p) + 6) << 48 | \
diff --git a/contrib/tcpdump/fddi.h b/contrib/tcpdump/fddi.h
index 690af48..df38c8e 100644
--- a/contrib/tcpdump/fddi.h
+++ b/contrib/tcpdump/fddi.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/fddi.h,v 1.11 2002/12/11 07:13:51 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/fddi.h,v 1.11 2002-12-11 07:13:51 guy Exp $ (LBL)
*/
/*
diff --git a/contrib/tcpdump/gmpls.c b/contrib/tcpdump/gmpls.c
index 4d4b9ae..ff9adb5 100644
--- a/contrib/tcpdump/gmpls.c
+++ b/contrib/tcpdump/gmpls.c
@@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/gmpls.c,v 1.5.2.1 2005/05/19 06:44:02 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/gmpls.c,v 1.7 2006-04-14 07:11:59 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -25,6 +25,7 @@ static const char rcsid[] _U_ =
#include <tcpdump-stdinc.h>
#include "interface.h"
+#include "gmpls.h"
/* rfc3471 */
struct tok gmpls_link_prot_values[] = {
@@ -41,14 +42,21 @@ struct tok gmpls_link_prot_values[] = {
/* rfc3471 */
struct tok gmpls_switch_cap_values[] = {
- { 1, "Packet-Switch Capable-1"},
- { 2, "Packet-Switch Capable-2"},
- { 3, "Packet-Switch Capable-3"},
- { 4, "Packet-Switch Capable-4"},
- { 51, "Layer-2 Switch Capable"},
- { 100, "Time-Division-Multiplex"},
- { 150, "Lambda-Switch Capable"},
- { 200, "Fiber-Switch Capable"},
+ { GMPLS_PSC1, "Packet-Switch Capable-1"},
+ { GMPLS_PSC2, "Packet-Switch Capable-2"},
+ { GMPLS_PSC3, "Packet-Switch Capable-3"},
+ { GMPLS_PSC4, "Packet-Switch Capable-4"},
+ { GMPLS_L2SC, "Layer-2 Switch Capable"},
+ { GMPLS_TSC, "Time-Division-Multiplex"},
+ { GMPLS_LSC, "Lambda-Switch Capable"},
+ { GMPLS_FSC, "Fiber-Switch Capable"},
+ { 0, NULL }
+};
+
+/* rfc4205 */
+struct tok gmpls_switch_cap_tsc_indication_values[] = {
+ { 0, "Standard SONET/SDH" },
+ { 1, "Arbitrary SONET/SDH" },
{ 0, NULL }
};
diff --git a/contrib/tcpdump/gmpls.h b/contrib/tcpdump/gmpls.h
index 8c3f051..6b2db23 100644
--- a/contrib/tcpdump/gmpls.h
+++ b/contrib/tcpdump/gmpls.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/gmpls.h,v 1.3.2.1 2005/05/19 06:44:03 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/gmpls.h,v 1.5 2006-04-14 07:11:59 hannes Exp $ (LBL) */
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code
@@ -14,8 +14,18 @@
* Original code by Hannes Gredler (hannes@juniper.net)
*/
+#define GMPLS_PSC1 1
+#define GMPLS_PSC2 2
+#define GMPLS_PSC3 3
+#define GMPLS_PSC4 4
+#define GMPLS_L2SC 51
+#define GMPLS_TSC 100
+#define GMPLS_LSC 150
+#define GMPLS_FSC 200
+
extern struct tok gmpls_link_prot_values[];
extern struct tok gmpls_switch_cap_values[];
+extern struct tok gmpls_switch_cap_tsc_indication_values[];
extern struct tok gmpls_encoding_values[];
extern struct tok gmpls_payload_values[];
extern struct tok diffserv_te_bc_values[];
diff --git a/contrib/tcpdump/gmt2local.c b/contrib/tcpdump/gmt2local.c
index 926e86c..1fe0e8a 100644
--- a/contrib/tcpdump/gmt2local.c
+++ b/contrib/tcpdump/gmt2local.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/gmt2local.c,v 1.9 2003/11/16 09:36:09 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/gmt2local.c,v 1.9 2003-11-16 09:36:09 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/gmt2local.h b/contrib/tcpdump/gmt2local.h
index 81b0e96..17120c5 100644
--- a/contrib/tcpdump/gmt2local.h
+++ b/contrib/tcpdump/gmt2local.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/gmt2local.h,v 1.2.1.1 1999/10/07 23:47:10 mcr Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/gmt2local.h,v 1.2.1.1 1999-10-07 23:47:10 mcr Exp $ (LBL)
*/
#ifndef gmt2local_h
#define gmt2local_h
diff --git a/contrib/tcpdump/icmp6.h b/contrib/tcpdump/icmp6.h
index 20a51e3..5d27270 100644
--- a/contrib/tcpdump/icmp6.h
+++ b/contrib/tcpdump/icmp6.h
@@ -1,5 +1,5 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/icmp6.h,v 1.16.2.1 2005/09/05 09:29:28 guy Exp $ (LBL) */
-/* $NetBSD: icmp6.h,v 1.13 2000/08/03 16:30:37 itojun Exp $ */
+/* @(#) $Header: /tcpdump/master/tcpdump/icmp6.h,v 1.18 2007-08-29 02:31:44 mcr Exp $ (LBL) */
+/* NetBSD: icmp6.h,v 1.13 2000/08/03 16:30:37 itojun Exp */
/* $KAME: icmp6.h,v 1.22 2000/08/03 15:25:16 jinmei Exp $ */
/*
diff --git a/contrib/tcpdump/ieee802_11.h b/contrib/tcpdump/ieee802_11.h
index d98f979..c1159c6 100644
--- a/contrib/tcpdump/ieee802_11.h
+++ b/contrib/tcpdump/ieee802_11.h
@@ -1,5 +1,5 @@
/* $FreeBSD$ */
-/* @(#) $Header: /tcpdump/master/tcpdump/ieee802_11.h,v 1.9.4.3 2007/07/22 20:01:16 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/ieee802_11.h,v 1.12 2007-07-22 19:59:06 guy Exp $ (LBL) */
/*
* Copyright (c) 2001
* Fortress Technologies
diff --git a/contrib/tcpdump/ieee802_11_radio.h b/contrib/tcpdump/ieee802_11_radio.h
index 82eb97b..bbbd199 100644
--- a/contrib/tcpdump/ieee802_11_radio.h
+++ b/contrib/tcpdump/ieee802_11_radio.h
@@ -1,6 +1,6 @@
/* $FreeBSD$ */
/* $NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp $ */
-/* $Header: /tcpdump/master/tcpdump/ieee802_11_radio.h,v 1.1.2.1 2006/06/13 22:24:45 guy Exp $ */
+/* $Header: /tcpdump/master/tcpdump/ieee802_11_radio.h,v 1.3 2007-08-29 02:31:44 mcr Exp $ */
/*-
* Copyright (c) 2003, 2004 David Young. All rights reserved.
diff --git a/contrib/tcpdump/igrp.h b/contrib/tcpdump/igrp.h
index 78876d3..b5f133b 100644
--- a/contrib/tcpdump/igrp.h
+++ b/contrib/tcpdump/igrp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/igrp.h,v 1.6 2002/12/11 07:13:52 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/igrp.h,v 1.6 2002-12-11 07:13:52 guy Exp $ (LBL) */
/* Cisco IGRP definitions */
/* IGRP Header */
diff --git a/contrib/tcpdump/interface.h b/contrib/tcpdump/interface.h
index 302d2ea..5e4a5eb 100644
--- a/contrib/tcpdump/interface.h
+++ b/contrib/tcpdump/interface.h
@@ -19,7 +19,7 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* $FreeBSD$
- * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.244.2.21 2007/03/28 07:45:46 hannes Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/interface.h,v 1.280.2.4 2008-04-04 19:42:52 guy Exp $ (LBL)
*/
#ifndef tcpdump_interface_h
@@ -165,6 +165,11 @@ extern const char *ipxsap_string(u_short);
extern const char *dnname_string(u_short);
extern const char *dnnum_string(u_short);
+/* checksum routines */
+extern void init_checksum(void);
+extern u_int16_t verify_crc10_cksum(u_int16_t, const u_char *, int);
+extern u_int16_t create_osi_cksum(const u_int8_t *, int, int);
+
/* The printer routines. */
#include <pcap.h>
@@ -210,10 +215,13 @@ extern u_int fr_if_print(const struct pcap_pkthdr *, const u_char *);
extern u_int mfr_if_print(const struct pcap_pkthdr *, const u_char *);
extern u_int fr_print(register const u_char *, u_int);
extern u_int mfr_print(register const u_char *, u_int);
+extern char *q922_string(const u_char *);
extern u_int ieee802_11_if_print(const struct pcap_pkthdr *, const u_char *);
extern u_int ieee802_11_radio_if_print(const struct pcap_pkthdr *,
const u_char *);
extern u_int ap1394_if_print(const struct pcap_pkthdr *, const u_char *);
+extern u_int ieee802_11_radio_avs_if_print(const struct pcap_pkthdr *,
+ const u_char *);
extern void gre_print(const u_char *, u_int);
extern void icmp_print(const u_char *, u_int, const u_char *, int);
extern void igmp_print(const u_char *, u_int);
@@ -237,8 +245,11 @@ extern void pimv1_print(const u_char *, u_int);
extern void cisco_autorp_print(const u_char *, u_int);
extern void rsvp_print(const u_char *, u_int);
extern void ldp_print(const u_char *, u_int);
+extern void lldp_print(const u_char *, u_int);
extern void lmp_print(const u_char *, u_int);
extern void lspping_print(const u_char *, u_int);
+extern void lwapp_control_print(const u_char *, u_int, int);
+extern void lwapp_data_print(const u_char *, u_int);
extern void eigrp_print(const u_char *, u_int);
extern void mobile_print(const u_char *, u_int);
extern void pim_print(const u_char *, u_int);
@@ -251,6 +262,7 @@ extern u_int pppoe_if_print(const struct pcap_pkthdr *, const u_char *);
extern u_int prism_if_print(const struct pcap_pkthdr *, const u_char *);
extern void q933_print(const u_char *, u_int);
extern int vjc_print(register const char *, u_short);
+extern void vqp_print(register const u_char *, register u_int);
extern u_int raw_if_print(const struct pcap_pkthdr *, const u_char *);
extern void rip_print(const u_char *, u_int);
extern u_int sl_if_print(const struct pcap_pkthdr *, const u_char *);
@@ -282,7 +294,9 @@ extern u_int symantec_if_print(const struct pcap_pkthdr *, const u_char *);
extern void tcp_print(const u_char *, u_int, const u_char *, int);
extern void tftp_print(const u_char *, u_int);
extern void timed_print(const u_char *);
+extern void udld_print(const u_char *, u_int);
extern void udp_print(const u_char *, u_int, const u_char *, int);
+extern void vtp_print(const u_char *, u_int);
extern void wb_print(const void *, u_int);
extern int ah_print(register const u_char *);
extern int ipcomp_print(register const u_char *, int *);
@@ -292,14 +306,19 @@ extern void ipx_netbios_print(const u_char *, u_int);
extern void nbt_tcp_print(const u_char *, int);
extern void nbt_udp137_print(const u_char *, int);
extern void nbt_udp138_print(const u_char *, int);
+extern void smb_tcp_print(const u_char *, int);
extern char *smb_errstr(int, int);
extern const char *nt_errstr(u_int32_t);
extern void print_data(const unsigned char *, int);
extern void l2tp_print(const u_char *, u_int);
extern void vrrp_print(const u_char *, u_int, int);
extern void slow_print(const u_char *, u_int);
+extern void sflow_print(const u_char *, u_int);
+extern void mpcp_print(const u_char *, u_int);
+extern void cfm_print(const u_char *, u_int);
extern void pgm_print(const u_char *, u_int, const u_char *);
extern void cdp_print(const u_char *, u_int, u_int);
+extern void dtp_print(const u_char *, u_int);
extern void stp_print(const u_char *, u_int);
extern void radius_print(const u_char *, u_int);
extern void lwres_print(const u_char *, u_int);
@@ -313,6 +332,7 @@ extern void hsrp_print(const u_char *, u_int);
extern void bfd_print(const u_char *, u_int, u_int);
extern void sip_print(const u_char *, u_int);
extern void syslog_print(const u_char *, u_int);
+extern u_int bt_if_print(const struct pcap_pkthdr *, const u_char *);
#ifdef INET6
extern void ip6_print(const u_char *, u_int);
@@ -333,7 +353,7 @@ extern u_int16_t in_cksum_shouldbe(u_int16_t, u_int16_t);
#ifndef HAVE_BPF_DUMP
struct bpf_program;
-extern void bpf_dump(struct bpf_program *, int);
+extern void bpf_dump(const struct bpf_program *, int);
#endif
@@ -341,10 +361,12 @@ extern void bpf_dump(struct bpf_program *, int);
/* forward compatibility */
+#ifndef NETDISSECT_REWORKED
extern netdissect_options *gndo;
#define eflag gndo->ndo_eflag
#define fflag gndo->ndo_fflag
+#define Kflag gndo->ndo_Kflag
#define nflag gndo->ndo_nflag
#define Nflag gndo->ndo_Nflag
#define Oflag gndo->ndo_Oflag
@@ -360,13 +382,19 @@ extern netdissect_options *gndo;
#define xflag gndo->ndo_xflag
#define Xflag gndo->ndo_Xflag
#define Cflag gndo->ndo_Cflag
+#define Gflag gndo->ndo_Gflag
#define Aflag gndo->ndo_Aflag
+#define Bflag gndo->ndo_Bflag
+#define Iflag gndo->ndo_Iflag
#define suppress_default_print gndo->ndo_suppress_default_print
#define packettype gndo->ndo_packettype
#define tcpmd5secret gndo->ndo_tcpmd5secret
#define Wflag gndo->ndo_Wflag
#define WflagChars gndo->ndo_WflagChars
#define Cflag_count gndo->ndo_Cflag_count
+#define Gflag_count gndo->ndo_Gflag_count
+#define Gflag_time gndo->ndo_Gflag_time
#define snaplen gndo->ndo_snaplen
#define snapend gndo->ndo_snapend
+#endif
diff --git a/contrib/tcpdump/ip.h b/contrib/tcpdump/ip.h
index e232ae0..a01d0f0 100644
--- a/contrib/tcpdump/ip.h
+++ b/contrib/tcpdump/ip.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/ip.h,v 1.11.2.1 2007/09/14 01:30:02 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/ip.h,v 1.12 2007-09-14 01:29:28 guy Exp $ (LBL) */
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
diff --git a/contrib/tcpdump/ip6.h b/contrib/tcpdump/ip6.h
index acf465c..e4f9fe1 100644
--- a/contrib/tcpdump/ip6.h
+++ b/contrib/tcpdump/ip6.h
@@ -1,5 +1,5 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/ip6.h,v 1.6.4.1 2005/04/20 10:04:37 guy Exp $ (LBL) */
-/* $NetBSD: ip6.h,v 1.9 2000/07/13 05:34:21 itojun Exp $ */
+/* @(#) $Header: /tcpdump/master/tcpdump/ip6.h,v 1.8 2007-08-29 02:31:44 mcr Exp $ (LBL) */
+/* NetBSD: ip6.h,v 1.9 2000/07/13 05:34:21 itojun Exp */
/* $KAME: ip6.h,v 1.9 2000/07/02 21:01:32 itojun Exp $ */
/*
diff --git a/contrib/tcpdump/ipfc.h b/contrib/tcpdump/ipfc.h
index f822d4a..438d115 100644
--- a/contrib/tcpdump/ipfc.h
+++ b/contrib/tcpdump/ipfc.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/ipfc.h,v 1.4 2002/12/11 07:13:53 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/ipfc.h,v 1.4 2002-12-11 07:13:53 guy Exp $ (LBL)
*/
struct ipfc_header {
diff --git a/contrib/tcpdump/ipproto.c b/contrib/tcpdump/ipproto.c
index 66ea356..7b89afb 100755
--- a/contrib/tcpdump/ipproto.c
+++ b/contrib/tcpdump/ipproto.c
@@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/ipproto.c,v 1.3.2.3 2005/09/20 06:05:37 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/ipproto.c,v 1.6 2005-09-20 06:01:22 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/ipproto.h b/contrib/tcpdump/ipproto.h
index 1800db4..ea339b1 100644
--- a/contrib/tcpdump/ipproto.h
+++ b/contrib/tcpdump/ipproto.h
@@ -30,11 +30,12 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/ipproto.h,v 1.4.2.2 2005/09/20 06:05:37 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/ipproto.h,v 1.6 2005-09-20 06:01:22 guy Exp $ (LBL)
*
* From:
* @(#)in.h 8.3 (Berkeley) 1/3/94
* $FreeBSD$
+ * FreeBSD: src/sys/netinet/in.h,v 1.38.2.3 1999/08/29 16:29:34 peter Exp
*/
extern struct tok ipproto_values[];
diff --git a/contrib/tcpdump/ipsec_doi.h b/contrib/tcpdump/ipsec_doi.h
index 83d05ea..554a258 100644
--- a/contrib/tcpdump/ipsec_doi.h
+++ b/contrib/tcpdump/ipsec_doi.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-/* YIPS @(#)$Id: ipsec_doi.h,v 1.7 2002/12/11 07:13:53 guy Exp $ */
+/* YIPS @(#)$Id: ipsec_doi.h,v 1.7 2002-12-11 07:13:53 guy Exp $ */
/* refer to RFC 2407 */
diff --git a/contrib/tcpdump/ipx.h b/contrib/tcpdump/ipx.h
index a8c1cd5..bfc3019 100644
--- a/contrib/tcpdump/ipx.h
+++ b/contrib/tcpdump/ipx.h
@@ -1,7 +1,7 @@
/*
* IPX protocol formats
*
- * @(#) $Header: /tcpdump/master/tcpdump/ipx.h,v 1.8 2002/12/11 07:13:54 guy Exp $
+ * @(#) $Header: /tcpdump/master/tcpdump/ipx.h,v 1.8 2002-12-11 07:13:54 guy Exp $
*/
/* well-known sockets */
diff --git a/contrib/tcpdump/isakmp.h b/contrib/tcpdump/isakmp.h
index 94fac40..85d383d 100644
--- a/contrib/tcpdump/isakmp.h
+++ b/contrib/tcpdump/isakmp.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-/* YIPS @(#)$Id: isakmp.h,v 1.10 2002/12/11 07:13:54 guy Exp $ */
+/* YIPS @(#)$Id: isakmp.h,v 1.11 2007-08-29 02:38:14 mcr Exp $ */
/* refer to RFC 2408 */
@@ -81,7 +81,7 @@ typedef struct { /* i_cookie + r_cookie */
#define ISAKMP_TIMER_DEFAULT 10 /* seconds */
#define ISAKMP_TRY_DEFAULT 3 /* times */
-/* 3.1 ISAKMP Header Format
+/* 3.1 ISAKMP Header Format (IKEv1 and IKEv2)
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
! Initiator !
@@ -128,8 +128,11 @@ struct isakmp {
#define ISAKMP_NPTYPE_D 12 /* Delete */
#define ISAKMP_NPTYPE_VID 13 /* Vendor ID */
-#define ISAKMP_MAJOR_VERSION 1
-#define ISAKMP_MINOR_VERSION 0
+#define IKEv1_MAJOR_VERSION 1
+#define IKEv1_MINOR_VERSION 0
+
+#define IKEv2_MAJOR_VERSION 2
+#define IKEv2_MINOR_VERSION 0
/* Exchange Type */
#define ISAKMP_ETYPE_NONE 0 /* NONE */
@@ -142,6 +145,13 @@ struct isakmp {
/* Flags */
#define ISAKMP_FLAG_E 0x01 /* Encryption Bit */
#define ISAKMP_FLAG_C 0x02 /* Commit Bit */
+#define ISAKMP_FLAG_extra 0x04
+
+/* IKEv2 */
+#define ISAKMP_FLAG_I (1 << 3) /* (I)nitiator */
+#define ISAKMP_FLAG_V (1 << 4) /* (V)ersion */
+#define ISAKMP_FLAG_R (1 << 5) /* (R)esponse */
+
/* 3.2 Payload Generic Header
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -151,7 +161,7 @@ struct isakmp {
*/
struct isakmp_gen {
u_int8_t np; /* Next Payload */
- u_int8_t reserved; /* RESERVED, unused, must set to 0 */
+ u_int8_t critical; /* bit 7 - critical, rest is RESERVED */
u_int16_t len; /* Payload Length */
};
@@ -188,7 +198,7 @@ struct isakmp_data {
message of a Base Exchange (see Section 4.4) and the value "0" in the
first message of an Identity Protect Exchange (see Section 4.5).
*/
-struct isakmp_pl_sa {
+struct ikev1_pl_sa {
struct isakmp_gen h;
u_int32_t doi; /* Domain of Interpretation */
u_int32_t sit; /* Situation */
@@ -202,7 +212,7 @@ struct isakmp_pl_sa {
last within the security association proposal, then this field will
be 0.
*/
-struct isakmp_pl_p {
+struct ikev1_pl_p {
struct isakmp_gen h;
u_int8_t p_no; /* Proposal # */
u_int8_t prot_id; /* Protocol */
@@ -218,7 +228,7 @@ struct isakmp_pl_p {
then this field will be 3. If the current Transform payload is the
last within the proposal, then this field will be 0.
*/
-struct isakmp_pl_t {
+struct ikev1_pl_t {
struct isakmp_gen h;
u_int8_t t_no; /* Transform # */
u_int8_t t_id; /* Transform-Id */
@@ -227,14 +237,14 @@ struct isakmp_pl_t {
};
/* 3.7 Key Exchange Payload */
-struct isakmp_pl_ke {
+struct ikev1_pl_ke {
struct isakmp_gen h;
/* Key Exchange Data */
};
/* 3.8 Identification Payload */
/* MUST NOT to be used, because of being defined in ipsec-doi. */
-struct isakmp_pl_id {
+struct ikev1_pl_id {
struct isakmp_gen h;
union {
u_int8_t id_type; /* ID Type */
@@ -244,7 +254,7 @@ struct isakmp_pl_id {
};
/* 3.9 Certificate Payload */
-struct isakmp_pl_cert {
+struct ikev1_pl_cert {
struct isakmp_gen h;
u_int8_t encode; /* Cert Encoding */
char cert; /* Certificate Data */
@@ -268,7 +278,7 @@ struct isakmp_pl_cert {
#define ISAKMP_CERT_SPKI 9
/* 3.10 Certificate Request Payload */
-struct isakmp_pl_cr {
+struct ikev1_pl_cr {
struct isakmp_gen h;
u_int8_t num_cert; /* # Cert. Types */
/*
@@ -283,27 +293,27 @@ struct isakmp_pl_cr {
/* 3.11 Hash Payload */
/* may not be used, because of having only data. */
-struct isakmp_pl_hash {
+struct ikev1_pl_hash {
struct isakmp_gen h;
/* Hash Data */
};
/* 3.12 Signature Payload */
/* may not be used, because of having only data. */
-struct isakmp_pl_sig {
+struct ikev1_pl_sig {
struct isakmp_gen h;
/* Signature Data */
};
/* 3.13 Nonce Payload */
/* may not be used, because of having only data. */
-struct isakmp_pl_nonce {
+struct ikev1_pl_nonce {
struct isakmp_gen h;
/* Nonce Data */
};
/* 3.14 Notification Payload */
-struct isakmp_pl_n {
+struct ikev1_pl_n {
struct isakmp_gen h;
u_int32_t doi; /* Domain of Interpretation */
u_int8_t prot_id; /* Protocol-ID */
@@ -347,7 +357,7 @@ struct isakmp_pl_n {
#define ISAKMP_LOG_RETRY_LIMIT_REACHED 65530
/* 3.15 Delete Payload */
-struct isakmp_pl_d {
+struct ikev1_pl_d {
struct isakmp_gen h;
u_int32_t doi; /* Domain of Interpretation */
u_int8_t prot_id; /* Protocol-Id */
@@ -357,15 +367,15 @@ struct isakmp_pl_d {
};
-struct isakmp_ph1tab {
- struct isakmp_ph1 *head;
- struct isakmp_ph1 *tail;
+struct ikev1_ph1tab {
+ struct ikev1_ph1 *head;
+ struct ikev1_ph1 *tail;
int len;
};
struct isakmp_ph2tab {
- struct isakmp_ph2 *head;
- struct isakmp_ph2 *tail;
+ struct ikev1_ph2 *head;
+ struct ikev1_ph2 *tail;
int len;
};
@@ -375,4 +385,99 @@ struct isakmp_ph2tab {
#define PFS_NEED 1
#define PFS_NONEED 0
+/* IKEv2 (RFC4306) */
+
+/* 3.3 Security Association Payload -- generic header */
+/* 3.3.1. Proposal Substructure */
+struct ikev2_p {
+ struct isakmp_gen h;
+ u_int8_t p_no; /* Proposal # */
+ u_int8_t prot_id; /* Protocol */
+ u_int8_t spi_size; /* SPI Size */
+ u_int8_t num_t; /* Number of Transforms */
+};
+
+/* 3.3.2. Transform Substructure */
+struct ikev2_t {
+ struct isakmp_gen h;
+ u_int8_t t_type; /* Transform Type (ENCR,PRF,INTEG,etc.*/
+ u_int8_t res2; /* reserved byte */
+ u_int16_t t_id; /* Transform ID */
+};
+
+enum ikev2_t_type {
+ IV2_T_ENCR = 1,
+ IV2_T_PRF = 2,
+ IV2_T_INTEG= 3,
+ IV2_T_DH = 4,
+ IV2_T_ESN = 5,
+};
+
+/* 3.4. Key Exchange Payload */
+struct ikev2_ke {
+ struct isakmp_gen h;
+ u_int16_t ke_group;
+ u_int16_t ke_res1;
+ /* KE data */
+};
+
+
+/* 3.10 Notification Payload */
+struct ikev2_n {
+ struct isakmp_gen h;
+ u_int8_t prot_id; /* Protocol-ID */
+ u_int8_t spi_size; /* SPI Size */
+ u_int16_t type; /* Notify Message Type */
+ /* SPI */
+ /* Notification Data */
+};
+
+enum ikev2_n_type {
+ IV2_NOTIFY_UNSUPPORTED_CRITICAL_PAYLOAD = 1,
+ IV2_NOTIFY_INVALID_IKE_SPI = 4,
+ IV2_NOTIFY_INVALID_MAJOR_VERSION = 5,
+ IV2_NOTIFY_INVALID_SYNTAX = 7,
+ IV2_NOTIFY_INVALID_MESSAGE_ID = 9,
+ IV2_NOTIFY_INVALID_SPI =11,
+ IV2_NOTIFY_NO_PROPOSAL_CHOSEN =14,
+ IV2_NOTIFY_INVALID_KE_PAYLOAD =17,
+ IV2_NOTIFY_AUTHENTICATION_FAILED =24,
+ IV2_NOTIFY_SINGLE_PAIR_REQUIRED =34,
+ IV2_NOTIFY_NO_ADDITIONAL_SAS =35,
+ IV2_NOTIFY_INTERNAL_ADDRESS_FAILURE =36,
+ IV2_NOTIFY_FAILED_CP_REQUIRED =37,
+ IV2_NOTIFY_INVALID_SELECTORS =39,
+ IV2_NOTIFY_INITIAL_CONTACT =16384,
+ IV2_NOTIFY_SET_WINDOW_SIZE =16385,
+ IV2_NOTIFY_ADDITIONAL_TS_POSSIBLE =16386,
+ IV2_NOTIFY_IPCOMP_SUPPORTED =16387,
+ IV2_NOTIFY_NAT_DETECTION_SOURCE_IP =16388,
+ IV2_NOTIFY_NAT_DETECTION_DESTINATION_IP =16389,
+ IV2_NOTIFY_COOKIE =16390,
+ IV2_NOTIFY_USE_TRANSPORT_MODE =16391,
+ IV2_NOTIFY_HTTP_CERT_LOOKUP_SUPPORTED =16392,
+ IV2_NOTIFY_REKEY_SA =16393,
+ IV2_NOTIFY_ESP_TFC_PADDING_NOT_SUPPORTED =16394,
+ IV2_NOTIFY_NON_FIRST_FRAGMENTS_ALSO =16395
+};
+
+struct notify_messages {
+ u_int16_t type;
+ char *msg;
+};
+
+/* 3.8 Notification Payload */
+struct ikev2_auth {
+ struct isakmp_gen h;
+ u_int8_t auth_method; /* Protocol-ID */
+ u_int8_t reserved[3];
+ /* authentication data */
+};
+
+enum ikev2_auth_type {
+ IV2_RSA_SIG = 1,
+ IV2_SHARED = 2,
+ IV2_DSS_SIG = 3,
+};
+
#endif /* !defined(_ISAKMP_H_) */
diff --git a/contrib/tcpdump/l2tp.h b/contrib/tcpdump/l2tp.h
index 1568883..5be24b9 100644
--- a/contrib/tcpdump/l2tp.h
+++ b/contrib/tcpdump/l2tp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/l2tp.h,v 1.5 2001/11/05 10:03:27 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/l2tp.h,v 1.5 2001-11-05 10:03:27 guy Exp $ (LBL) */
/*
* Copyright (c) 1991, 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
diff --git a/contrib/tcpdump/l2vpn.c b/contrib/tcpdump/l2vpn.c
index d98e69a..a822191 100755
--- a/contrib/tcpdump/l2vpn.c
+++ b/contrib/tcpdump/l2vpn.c
@@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/l2vpn.c,v 1.1 2004/06/15 09:42:40 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/l2vpn.c,v 1.1 2004-06-15 09:42:40 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/l2vpn.h b/contrib/tcpdump/l2vpn.h
index 64eb024..766cda5 100755
--- a/contrib/tcpdump/l2vpn.h
+++ b/contrib/tcpdump/l2vpn.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/l2vpn.h,v 1.1 2004/06/15 09:42:41 hannes Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/l2vpn.h,v 1.1 2004-06-15 09:42:41 hannes Exp $ (LBL) */
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code
diff --git a/contrib/tcpdump/lane.h b/contrib/tcpdump/lane.h
index 51b6e19..76cc020 100644
--- a/contrib/tcpdump/lane.h
+++ b/contrib/tcpdump/lane.h
@@ -20,7 +20,7 @@
*
*/
-/* $Id: lane.h,v 1.7 2002/12/11 07:13:54 guy Exp $ */
+/* $Id: lane.h,v 1.7 2002-12-11 07:13:54 guy Exp $ */
#ifndef ETHER_ADDR_LEN
#define ETHER_ADDR_LEN 6
diff --git a/contrib/tcpdump/lbl/os-osf4.h b/contrib/tcpdump/lbl/os-osf4.h
index 62866ed..5682b7e 100644
--- a/contrib/tcpdump/lbl/os-osf4.h
+++ b/contrib/tcpdump/lbl/os-osf4.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/lbl/os-osf4.h,v 1.1 2002/12/11 05:03:13 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/lbl/os-osf4.h,v 1.1 2002-12-11 05:03:13 guy Exp $ (LBL)
*/
/* Prototypes missing in Digital UNIX 4.x */
diff --git a/contrib/tcpdump/lbl/os-solaris2.h b/contrib/tcpdump/lbl/os-solaris2.h
index de481c2..5c01b87 100644
--- a/contrib/tcpdump/lbl/os-solaris2.h
+++ b/contrib/tcpdump/lbl/os-solaris2.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/lbl/os-solaris2.h,v 1.19 2000/10/11 04:02:15 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/lbl/os-solaris2.h,v 1.19 2000-10-11 04:02:15 guy Exp $ (LBL)
*/
/* Prototypes missing in SunOS 5 */
diff --git a/contrib/tcpdump/lbl/os-sunos4.h b/contrib/tcpdump/lbl/os-sunos4.h
index 2e0f25f..51a70dd 100644
--- a/contrib/tcpdump/lbl/os-sunos4.h
+++ b/contrib/tcpdump/lbl/os-sunos4.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/lbl/os-sunos4.h,v 1.32.1.1 1999/10/07 23:47:13 mcr Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/lbl/os-sunos4.h,v 1.32.1.1 1999-10-07 23:47:13 mcr Exp $ (LBL)
*/
/* Prototypes missing in SunOS 4 */
diff --git a/contrib/tcpdump/lbl/os-ultrix4.h b/contrib/tcpdump/lbl/os-ultrix4.h
index 676b3bd..1b154ee 100644
--- a/contrib/tcpdump/lbl/os-ultrix4.h
+++ b/contrib/tcpdump/lbl/os-ultrix4.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/lbl/os-ultrix4.h,v 1.19.1.1 1999/10/07 23:47:13 mcr Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/lbl/os-ultrix4.h,v 1.19.1.1 1999-10-07 23:47:13 mcr Exp $ (LBL)
*/
/* Prototypes missing in Ultrix 4 */
diff --git a/contrib/tcpdump/llc.h b/contrib/tcpdump/llc.h
index fc04c67..faa7256 100644
--- a/contrib/tcpdump/llc.h
+++ b/contrib/tcpdump/llc.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/llc.h,v 1.17.2.4 2007/02/08 07:07:51 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/llc.h,v 1.23 2007-04-13 09:43:11 hannes Exp $ (LBL)
*/
/*
@@ -104,6 +104,8 @@
#define PID_CISCO_CDP 0x2000 /* Cisco Discovery Protocol */
#define PID_CISCO_VTP 0x2003 /* Cisco VLAN Trunk Protocol */
#define PID_CISCO_DTP 0x2004 /* Cisco Dynamic Trunk Protocol */
+#define PID_CISCO_UDLD 0x0111 /* Unidirectional Link Detection */
+#define PID_CISCO_PVST 0x010b /* Per VLAN Spanning Tree+ and RPVST+ */
/*
* PIDs for use with OUI_RFC2684.
diff --git a/contrib/tcpdump/machdep.c b/contrib/tcpdump/machdep.c
index 5b04503..2bcf317 100644
--- a/contrib/tcpdump/machdep.c
+++ b/contrib/tcpdump/machdep.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/machdep.c,v 1.13 2003/12/15 03:53:21 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/machdep.c,v 1.13 2003-12-15 03:53:21 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/machdep.h b/contrib/tcpdump/machdep.h
index 8d49a7a..6328c82 100644
--- a/contrib/tcpdump/machdep.h
+++ b/contrib/tcpdump/machdep.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/machdep.h,v 1.2 2000/01/17 06:24:24 itojun Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/machdep.h,v 1.2 2000-01-17 06:24:24 itojun Exp $ (LBL)
*/
#ifndef tcpdump_machdep_h
#define tcpdump_machdep_h
diff --git a/contrib/tcpdump/makemib b/contrib/tcpdump/makemib
index 2c80bef..b59e2f1 100755
--- a/contrib/tcpdump/makemib
+++ b/contrib/tcpdump/makemib
@@ -27,7 +27,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.
#
-# @(#) $Id: makemib,v 1.3 2001/09/17 22:16:52 fenner Exp $ (jlv)
+# @(#) $Id: makemib,v 1.3 2001-09-17 22:16:52 fenner Exp $ (jlv)
#
# This script will read either ASN.1-style MIB files or the ".defs" files
diff --git a/contrib/tcpdump/missing/addrinfo.h b/contrib/tcpdump/missing/addrinfo.h
index 09f6a42..1b5f92e 100644
--- a/contrib/tcpdump/missing/addrinfo.h
+++ b/contrib/tcpdump/missing/addrinfo.h
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*/
-/* $Id: addrinfo.h,v 1.4 2002/06/11 17:13:36 itojun Exp $ */
+/* $Id: addrinfo.h,v 1.4 2002-06-11 17:13:36 itojun Exp $ */
#ifndef HAVE_ADDRINFO
diff --git a/contrib/tcpdump/missing/datalinks.c b/contrib/tcpdump/missing/datalinks.c
index 2cc1267..1bd8644 100644
--- a/contrib/tcpdump/missing/datalinks.c
+++ b/contrib/tcpdump/missing/datalinks.c
@@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/datalinks.c,v 1.3 2003/11/16 09:36:47 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/datalinks.c,v 1.3 2003-11-16 09:36:47 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/missing/dlnames.c b/contrib/tcpdump/missing/dlnames.c
index f4f583e..32072b7 100644
--- a/contrib/tcpdump/missing/dlnames.c
+++ b/contrib/tcpdump/missing/dlnames.c
@@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/dlnames.c,v 1.5 2003/11/18 23:09:43 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/dlnames.c,v 1.5 2003-11-18 23:09:43 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/missing/getaddrinfo.c b/contrib/tcpdump/missing/getaddrinfo.c
index 8830322..f59b2c4 100644
--- a/contrib/tcpdump/missing/getaddrinfo.c
+++ b/contrib/tcpdump/missing/getaddrinfo.c
@@ -51,7 +51,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/getaddrinfo.c,v 1.13 2003/11/16 09:36:48 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/getaddrinfo.c,v 1.13 2003-11-16 09:36:48 guy Exp $";
#endif
#include <sys/types.h>
diff --git a/contrib/tcpdump/missing/getnameinfo.c b/contrib/tcpdump/missing/getnameinfo.c
index 6bd5b47..c287221 100644
--- a/contrib/tcpdump/missing/getnameinfo.c
+++ b/contrib/tcpdump/missing/getnameinfo.c
@@ -43,7 +43,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/getnameinfo.c,v 1.11 2003/11/16 09:36:49 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/getnameinfo.c,v 1.11 2003-11-16 09:36:49 guy Exp $";
#endif
#include <sys/types.h>
diff --git a/contrib/tcpdump/missing/inet_aton.c b/contrib/tcpdump/missing/inet_aton.c
index a4b2eeb..bc1461a 100644
--- a/contrib/tcpdump/missing/inet_aton.c
+++ b/contrib/tcpdump/missing/inet_aton.c
@@ -36,11 +36,11 @@
* SUCH DAMAGE.
*/
-/* $Id: inet_aton.c,v 1.6 2003/11/16 09:36:49 guy Exp $ */
+/* $Id: inet_aton.c,v 1.6 2003-11-16 09:36:49 guy Exp $ */
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/inet_aton.c,v 1.6 2003/11/16 09:36:49 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/inet_aton.c,v 1.6 2003-11-16 09:36:49 guy Exp $";
#endif
#include <tcpdump-stdinc.h>
diff --git a/contrib/tcpdump/missing/inet_ntop.c b/contrib/tcpdump/missing/inet_ntop.c
index 8bbbad6..d17d592 100644
--- a/contrib/tcpdump/missing/inet_ntop.c
+++ b/contrib/tcpdump/missing/inet_ntop.c
@@ -36,11 +36,11 @@
* SUCH DAMAGE.
*/
-/* $Id: inet_ntop.c,v 1.8 2005/02/09 02:25:46 guy Exp $ */
+/* $Id: inet_ntop.c,v 1.8 2005-02-09 02:25:46 guy Exp $ */
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/inet_ntop.c,v 1.8 2005/02/09 02:25:46 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/inet_ntop.c,v 1.8 2005-02-09 02:25:46 guy Exp $";
#endif
#include <tcpdump-stdinc.h>
diff --git a/contrib/tcpdump/missing/inet_pton.c b/contrib/tcpdump/missing/inet_pton.c
index 1b8abd2..83f67e1 100644
--- a/contrib/tcpdump/missing/inet_pton.c
+++ b/contrib/tcpdump/missing/inet_pton.c
@@ -36,11 +36,11 @@
* SUCH DAMAGE.
*/
-/* $Id: inet_pton.c,v 1.6 2003/11/16 09:36:51 guy Exp $ */
+/* $Id: inet_pton.c,v 1.6 2003-11-16 09:36:51 guy Exp $ */
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/inet_pton.c,v 1.6 2003/11/16 09:36:51 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/inet_pton.c,v 1.6 2003-11-16 09:36:51 guy Exp $";
#endif
#include <tcpdump-stdinc.h>
diff --git a/contrib/tcpdump/missing/snprintf.c b/contrib/tcpdump/missing/snprintf.c
index 4f2bb32..7932997 100644
--- a/contrib/tcpdump/missing/snprintf.c
+++ b/contrib/tcpdump/missing/snprintf.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-/* $Id: snprintf.c,v 1.8 2003/11/16 09:36:51 guy Exp $ */
+/* $Id: snprintf.c,v 1.8 2003-11-16 09:36:51 guy Exp $ */
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -39,7 +39,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/snprintf.c,v 1.8 2003/11/16 09:36:51 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/snprintf.c,v 1.8 2003-11-16 09:36:51 guy Exp $";
#endif
#include <stdio.h>
diff --git a/contrib/tcpdump/missing/strdup.c b/contrib/tcpdump/missing/strdup.c
index 103c3b2..079a8ff 100644
--- a/contrib/tcpdump/missing/strdup.c
+++ b/contrib/tcpdump/missing/strdup.c
@@ -33,7 +33,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/strdup.c,v 1.1 2001/01/20 07:26:08 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/strdup.c,v 1.1 2001-01-20 07:26:08 guy Exp $ (LBL)";
#endif /* LIBC_SCCS and not lint */
#include <stddef.h>
diff --git a/contrib/tcpdump/missing/strlcat.c b/contrib/tcpdump/missing/strlcat.c
index fca2e8a..a3d3fac 100644
--- a/contrib/tcpdump/missing/strlcat.c
+++ b/contrib/tcpdump/missing/strlcat.c
@@ -30,7 +30,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/strlcat.c,v 1.5 2003/11/16 09:36:51 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/strlcat.c,v 1.5 2003-11-16 09:36:51 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/missing/strlcpy.c b/contrib/tcpdump/missing/strlcpy.c
index 3f1809a..a92e4d1 100644
--- a/contrib/tcpdump/missing/strlcpy.c
+++ b/contrib/tcpdump/missing/strlcpy.c
@@ -30,7 +30,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/strlcpy.c,v 1.5 2003/11/16 09:36:52 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/strlcpy.c,v 1.5 2003-11-16 09:36:52 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/missing/strsep.c b/contrib/tcpdump/missing/strsep.c
index 19fb6b2..0362d1f 100644
--- a/contrib/tcpdump/missing/strsep.c
+++ b/contrib/tcpdump/missing/strsep.c
@@ -33,7 +33,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
static const char rcsid[] =
- "@(#) $Header: /tcpdump/master/tcpdump/missing/strsep.c,v 1.3 2003/03/25 08:33:48 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/missing/strsep.c,v 1.3 2003-03-25 08:33:48 guy Exp $ (LBL)";
#endif /* LIBC_SCCS and not lint */
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/mpls.h b/contrib/tcpdump/mpls.h
index 69fc9c9..ae1c97e 100644
--- a/contrib/tcpdump/mpls.h
+++ b/contrib/tcpdump/mpls.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/mpls.h,v 1.1 2004/06/14 14:47:58 hannes Exp $ (LBL)
+/* @(#) $Header: /tcpdump/master/tcpdump/mpls.h,v 1.1 2004-06-14 14:47:58 hannes Exp $ (LBL)
* Copyright (C) 2001 WIDE Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
diff --git a/contrib/tcpdump/nameser.h b/contrib/tcpdump/nameser.h
index e6391f4..f441f3e 100644
--- a/contrib/tcpdump/nameser.h
+++ b/contrib/tcpdump/nameser.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/nameser.h,v 1.14.4.2 2006/11/10 03:15:35 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/nameser.h,v 1.16 2006-11-10 03:18:21 guy Exp $ (LBL) */
/*
* Copyright (c) 1983, 1989, 1993
* The Regents of the University of California. All rights reserved.
diff --git a/contrib/tcpdump/netbios.h b/contrib/tcpdump/netbios.h
index 34abeba..d3e2725 100644
--- a/contrib/tcpdump/netbios.h
+++ b/contrib/tcpdump/netbios.h
@@ -1,7 +1,7 @@
/*
* NETBIOS protocol formats
*
- * @(#) $Header: /tcpdump/master/tcpdump/netbios.h,v 1.3 2002/12/11 07:13:55 guy Exp $
+ * @(#) $Header: /tcpdump/master/tcpdump/netbios.h,v 1.3 2002-12-11 07:13:55 guy Exp $
*/
struct p8022Hdr {
diff --git a/contrib/tcpdump/netdissect.h b/contrib/tcpdump/netdissect.h
index 3609455..cd6f2f1 100644
--- a/contrib/tcpdump/netdissect.h
+++ b/contrib/tcpdump/netdissect.h
@@ -21,7 +21,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/netdissect.h,v 1.16.2.4 2006/02/08 01:40:09 hannes Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/netdissect.h,v 1.23.2.2 2008-04-04 19:42:52 guy Exp $ (LBL)
*/
#ifndef netdissect_h
@@ -77,6 +77,7 @@ extern const char *tok2strbuf(const struct tok *, const char *, int,
/* tok2str is deprecated */
extern const char *tok2str(const struct tok *, const char *, int);
extern char *bittok2str(const struct tok *, const char *, int);
+extern char *bittok2str_nosep(const struct tok *, const char *, int);
typedef struct netdissect_options netdissect_options;
@@ -85,6 +86,7 @@ struct netdissect_options {
int ndo_aflag; /* translate network and broadcast addresses */
int ndo_eflag; /* print ethernet header */
int ndo_fflag; /* don't translate "foreign" IP address */
+ int ndo_Kflag; /* don't check TCP checksums */
int ndo_nflag; /* leave addresses as numbers */
int ndo_Nflag; /* remove domains from printed host names */
int ndo_qflag; /* quick (shorter) output */
@@ -100,12 +102,17 @@ struct netdissect_options {
int ndo_Aflag; /* print packet only in ascii observing TAB,
* LF, CR and SPACE as graphical chars
*/
+ int ndo_Bflag; /* buffer size */
+ int ndo_Iflag; /* rfmon (monitor) mode */
int ndo_Oflag; /* run filter code optimizer */
int ndo_dlt; /* if != -1, ask libpcap for the DLT it names*/
int ndo_pflag; /* don't go promiscuous */
int ndo_Cflag; /* rotate dump files after this many bytes */
int ndo_Cflag_count; /* Keep track of which file number we're writing */
+ int ndo_Gflag; /* rotate dump files after this many seconds */
+ int ndo_Gflag_count; /* number of files created with Gflag rotation */
+ time_t ndo_Gflag_time; /* The last time_t the dump file was rotated. */
int ndo_Wflag; /* recycle output files after this number of files */
int ndo_WflagChars;
int ndo_suppress_default_print; /* don't use default_print() for unknown packet types */
@@ -245,7 +252,7 @@ extern const char *dnnum_string(netdissect_options *, u_short);
#include <pcap.h>
-extern void eap_print(netdissect_options *,const u_char *, u_int);
+extern void eap_print(netdissect_options *,const u_char *, u_int);
extern int esp_print(netdissect_options *,
register const u_char *bp, int len, register const u_char *bp2,
int *nhdr, int *padlen);
@@ -258,6 +265,7 @@ extern void ip_print(netdissect_options *,const u_char *, u_int);
extern void ip_print_inner(netdissect_options *ndo,
const u_char *bp, u_int length, u_int nh,
const u_char *bp2);
+extern void rrcp_print(netdissect_options *,const u_char *, u_int);
/* stuff that has not yet been rototiled */
#if 0
diff --git a/contrib/tcpdump/nfs.h b/contrib/tcpdump/nfs.h
index 82c8dd3..36b788c 100644
--- a/contrib/tcpdump/nfs.h
+++ b/contrib/tcpdump/nfs.h
@@ -1,5 +1,5 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/nfs.h,v 1.7 2002/12/11 07:13:55 guy Exp $ (LBL) */
-/* $NetBSD: nfs.h,v 1.1 1996/05/23 22:49:53 fvdl Exp $ */
+/* @(#) $Header: /tcpdump/master/tcpdump/nfs.h,v 1.8.2.1 2007-11-18 03:24:55 guy Exp $ (LBL) */
+/* NetBSD: nfs.h,v 1.1 1996/05/23 22:49:53 fvdl Exp */
/*
* Copyright (c) 1989, 1993
@@ -287,21 +287,6 @@ struct nfs_uquad {
};
typedef struct nfs_uquad nfsuint64;
-#if 0 /* XXX - this doesn't seemed to be used and it doesn't work
- * with non-gcc, so comment it out for now.
- */
-
-/*
- * Used to convert between two u_longs and a u_quad_t.
- */
-union nfs_quadconvert {
- u_int32_t lval[2];
- u_int64_t qval;
-};
-typedef union nfs_quadconvert nfsquad_t;
-
-#endif
-
/*
* NFS Version 3 special file number.
*/
diff --git a/contrib/tcpdump/nfsfh.h b/contrib/tcpdump/nfsfh.h
index 8a337ba..8236713 100644
--- a/contrib/tcpdump/nfsfh.h
+++ b/contrib/tcpdump/nfsfh.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/nfsfh.h,v 1.13 2002/04/24 06:27:05 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/nfsfh.h,v 1.13 2002-04-24 06:27:05 guy Exp $ (LBL) */
/*
* Copyright (c) 1993, 1994 Jeffrey C. Mogul, Digital Equipment Corporation,
diff --git a/contrib/tcpdump/nlpid.c b/contrib/tcpdump/nlpid.c
index 7dfd6a6..47ebb53 100755
--- a/contrib/tcpdump/nlpid.c
+++ b/contrib/tcpdump/nlpid.c
@@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/nlpid.c,v 1.4 2004/10/19 15:27:55 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/nlpid.c,v 1.4 2004-10-19 15:27:55 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/nlpid.h b/contrib/tcpdump/nlpid.h
index fdca446..31f6b66 100644
--- a/contrib/tcpdump/nlpid.h
+++ b/contrib/tcpdump/nlpid.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/nlpid.h,v 1.4 2004/10/19 15:27:55 hannes Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/nlpid.h,v 1.4 2004-10-19 15:27:55 hannes Exp $ (LBL) */
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code
diff --git a/contrib/tcpdump/ntp.h b/contrib/tcpdump/ntp.h
index df85669..0614f73 100644
--- a/contrib/tcpdump/ntp.h
+++ b/contrib/tcpdump/ntp.h
@@ -1,4 +1,4 @@
-/* $Header: /tcpdump/master/tcpdump/ntp.h,v 1.8 2004/01/28 14:34:50 hannes Exp $ */
+/* $Header: /tcpdump/master/tcpdump/ntp.h,v 1.8 2004-01-28 14:34:50 hannes Exp $ */
/*
* Based on ntp.h from the U of MD implementation
diff --git a/contrib/tcpdump/oakley.h b/contrib/tcpdump/oakley.h
index f40d607..ad32817 100644
--- a/contrib/tcpdump/oakley.h
+++ b/contrib/tcpdump/oakley.h
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-/* YIPS @(#)$Id: oakley.h,v 1.4 2002/12/11 07:13:56 guy Exp $ */
+/* YIPS @(#)$Id: oakley.h,v 1.4 2002-12-11 07:13:56 guy Exp $ */
/* refer to RFC 2409 */
diff --git a/contrib/tcpdump/ospf.h b/contrib/tcpdump/ospf.h
index 91a904f..2b1c6ee 100644
--- a/contrib/tcpdump/ospf.h
+++ b/contrib/tcpdump/ospf.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/ospf.h,v 1.16.2.2 2006/12/13 08:24:27 hannes Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/ospf.h,v 1.23 2007-10-08 07:53:21 hannes Exp $ (LBL) */
/*
* Copyright (c) 1991, 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
@@ -31,7 +31,7 @@
/* Options field
*
* +------------------------------------+
- * | * | O | DC | EA | N/P | MC | E | T |
+ * | DN | O | DC | L | N/P | MC | E | T |
* +------------------------------------+
*
*/
@@ -41,6 +41,7 @@
#define OSPF_OPTION_MC 0x04 /* MC bit: Multicast capable */
#define OSPF_OPTION_NP 0x08 /* N/P bit: NSSA capable */
#define OSPF_OPTION_EA 0x10 /* EA bit: External Attribute capable */
+#define OSPF_OPTION_L 0x10 /* L bit: Packet contains LLS data block */
#define OSPF_OPTION_DC 0x20 /* DC bit: Demand circuit capable */
#define OSPF_OPTION_O 0x40 /* O bit: Opaque LSA capable */
#define OSPF_OPTION_DN 0x80 /* DN bit: Up/Down Bit capable - draft-ietf-ospf-2547-dnbit-04 */
@@ -53,9 +54,10 @@
#define OSPF_AUTH_MD5_LEN 16 /* length of MD5 authentication */
/* db_flags */
-#define OSPF_DB_INIT 0x04 /* */
+#define OSPF_DB_INIT 0x04
#define OSPF_DB_MORE 0x02
-#define OSPF_DB_MASTER 0x01
+#define OSPF_DB_MASTER 0x01
+#define OSPF_DB_RESYNC 0x08 /* RFC4811 */
/* ls_type */
#define LS_TYPE_ROUTER 1 /* router link */
@@ -86,10 +88,10 @@
#define LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW 7 /* rfc3630 */
#define LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW 8 /* rfc3630 */
#define LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP 9 /* rfc3630 */
-#define LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID 11 /* draft-ietf-ccamp-ospf-gmpls-extensions */
-#define LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE 14 /* draft-ietf-ccamp-ospf-gmpls-extensions */
-#define LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR 15 /* draft-ietf-ccamp-ospf-gmpls-extensions */
-#define LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP 16 /* draft-ietf-ccamp-ospf-gmpls-extensions */
+#define LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID 11 /* rfc4203 */
+#define LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE 14 /* rfc4203 */
+#define LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR 15 /* rfc4203 */
+#define LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP 16 /* rfc4203 */
#define LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS 17 /* rfc4124 */
#define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP 1 /* rfc3630 */
@@ -106,12 +108,6 @@
#define LS_OPAQUE_RI_TLV_CAP 1 /* draft-ietf-ospf-cap-03 */
-/*************************************************
- *
- * is the above a bug in the documentation?
- *
- *************************************************/
-
/* rla_link.link_type */
#define RLA_TYPE_ROUTER 1 /* point-to-point to another router */
@@ -140,6 +136,31 @@
#define MCLA_VERTEX_ROUTER 1
#define MCLA_VERTEX_NETWORK 2
+/* Link-Local-Signaling */
+#define OSPF_LLS_EO 1 /* RFC4811, RFC4812 */
+#define OSPF_LLS_MD5 2 /* RFC4813 */
+
+#define OSPF_LLS_EO_LR 0x00000001 /* RFC4811 */
+#define OSPF_LLS_EO_RS 0x00000002 /* RFC4812 */
+
+/*
+ * TOS metric struct (will be 0 or more in router links update)
+ */
+struct tos_metric {
+ u_int8_t tos_type;
+ u_int8_t reserved;
+ u_int8_t tos_metric[2];
+};
+struct tos_link {
+ u_int8_t link_type;
+ u_int8_t link_tos_count;
+ u_int8_t tos_metric[2];
+};
+union un_tos {
+ struct tos_link link;
+ struct tos_metric metrics;
+};
+
/* link state advertisement header */
struct lsa_hdr {
u_int16_t ls_age;
@@ -172,9 +193,7 @@ struct lsa {
struct rlalink {
struct in_addr link_id;
struct in_addr link_data;
- u_int8_t link_type;
- u_int8_t link_toscount;
- u_int16_t link_tos0metric;
+ union un_tos un_tos;
} rla_link[1]; /* may repeat */
} un_rla;
@@ -235,16 +254,6 @@ struct lsa {
} lsa_un;
};
-
-/*
- * TOS metric struct (will be 0 or more in router links update)
- */
-struct tos_metric {
- u_int8_t tos_type;
- u_int8_t tos_zero;
- u_int16_t tos_metric;
-};
-
#define OSPF_AUTH_SIZE 8
/*
@@ -275,7 +284,7 @@ struct ospfhdr {
/* Database Description packet */
struct {
- u_int8_t db_zero[2];
+ u_int16_t db_ifmtu;
u_int8_t db_options;
u_int8_t db_flags;
u_int32_t db_seq;
@@ -314,3 +323,6 @@ struct ospfhdr {
#define ospf_lsu ospf_un.un_lsu
#define ospf_lsa ospf_un.un_lsa
+/* Functions shared by ospf and ospf6 */
+extern int ospf_print_te_lsa(u_int8_t *, u_int);
+extern int ospf_print_grace_lsa(u_int8_t *, u_int);
diff --git a/contrib/tcpdump/ospf6.h b/contrib/tcpdump/ospf6.h
index b8298ea..e2eabee 100644
--- a/contrib/tcpdump/ospf6.h
+++ b/contrib/tcpdump/ospf6.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/ospf6.h,v 1.6 2002/12/11 07:13:56 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/ospf6.h,v 1.7 2006-09-05 15:50:26 hannes Exp $ (LBL) */
/*
* Copyright (c) 1991, 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
@@ -21,13 +21,11 @@
*
* OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu)
*/
-#define OSPF_TYPE_UMD 0 /* UMd's special monitoring packets */
-#define OSPF_TYPE_HELLO 1 /* Hello */
-#define OSPF_TYPE_DB 2 /* Database Description */
-#define OSPF_TYPE_LSR 3 /* Link State Request */
-#define OSPF_TYPE_LSU 4 /* Link State Update */
-#define OSPF_TYPE_LSA 5 /* Link State Ack */
-#define OSPF_TYPE_MAX 6
+#define OSPF_TYPE_HELLO 1 /* Hello */
+#define OSPF_TYPE_DD 2 /* Database Description */
+#define OSPF_TYPE_LS_REQ 3 /* Link State Request */
+#define OSPF_TYPE_LS_UPDATE 4 /* Link State Update */
+#define OSPF_TYPE_LS_ACK 5 /* Link State Ack */
/* Options *_options */
#define OSPF6_OPTION_V6 0x01 /* V6 bit: A bit for peeping tom */
@@ -50,23 +48,18 @@
#define LS_TYPE_INTER_AR 4 /* Inter-Area-Router */
#define LS_TYPE_ASE 5 /* ASE */
#define LS_TYPE_GROUP 6 /* Group membership */
-#define LS_TYPE_TYPE7 7 /* Type 7 LSA */
+#define LS_TYPE_NSSA 7 /* NSSA */
#define LS_TYPE_LINK 8 /* Link LSA */
#define LS_TYPE_INTRA_AP 9 /* Intra-Area-Prefix */
-#define LS_TYPE_MAX 10
+#define LS_TYPE_INTRA_ATE 10 /* Intra-Area-TE */
+#define LS_TYPE_GRACE 11 /* Grace LSA */
#define LS_TYPE_MASK 0x1fff
#define LS_SCOPE_LINKLOCAL 0x0000
#define LS_SCOPE_AREA 0x2000
#define LS_SCOPE_AS 0x4000
#define LS_SCOPE_MASK 0x6000
-
-/*************************************************
- *
- * is the above a bug in the documentation?
- *
- *************************************************/
-
+#define LS_SCOPE_U 0x8000
/* rla_link.link_type */
#define RLA_TYPE_ROUTER 1 /* point-to-point to another router */
@@ -78,6 +71,14 @@
#define RLA_FLAG_E 0x02
#define RLA_FLAG_V 0x04
#define RLA_FLAG_W 0x08
+#define RLA_FLAG_N 0x10
+
+/* lsa_prefix options */
+#define LSA_PREFIX_OPT_NU 0x01
+#define LSA_PREFIX_OPT_LA 0x02
+#define LSA_PREFIX_OPT_MC 0x04
+#define LSA_PREFIX_OPT_P 0x08
+#define LSA_PREFIX_OPT_DN 0x10
/* sla_tosmetric breakdown */
#define SLA_MASK_TOS 0x7f000000
@@ -85,19 +86,14 @@
#define SLA_SHIFT_TOS 24
/* asla_metric */
-#define ASLA_FLAG_EXTERNAL 0x04000000
#define ASLA_FLAG_FWDADDR 0x02000000
#define ASLA_FLAG_ROUTETAG 0x01000000
#define ASLA_MASK_METRIC 0x00ffffff
-/* multicast vertex type */
-#define MCLA_VERTEX_ROUTER 1
-#define MCLA_VERTEX_NETWORK 2
-
typedef u_int32_t rtrid_t;
/* link state advertisement header */
-struct lsa_hdr {
+struct lsa6_hdr {
u_int16_t ls_age;
u_int16_t ls_type;
rtrid_t ls_stateid;
@@ -107,16 +103,16 @@ struct lsa_hdr {
u_int16_t ls_length;
};
-struct lsa_prefix {
+struct lsa6_prefix {
u_int8_t lsa_p_len;
u_int8_t lsa_p_opt;
- u_int16_t lsa_p_mbz;
+ u_int16_t lsa_p_metric;
u_int8_t lsa_p_prefix[4];
};
/* link state advertisement */
-struct lsa {
- struct lsa_hdr ls_hdr;
+struct lsa6 {
+ struct lsa6_hdr ls_hdr;
/* Link state types */
union {
@@ -128,7 +124,7 @@ struct lsa {
} rla_flgandopt;
#define rla_flags rla_flgandopt.flg
#define rla_options rla_flgandopt.opt
- struct rlalink {
+ struct rlalink6 {
u_int8_t link_type;
u_int8_t link_zero[1];
u_int16_t link_metric;
@@ -147,13 +143,13 @@ struct lsa {
/* Inter Area Prefix LSA */
struct {
u_int32_t inter_ap_metric;
- struct lsa_prefix inter_ap_prefix[1];
+ struct lsa6_prefix inter_ap_prefix[1];
} un_inter_ap;
/* AS external links advertisements */
struct {
u_int32_t asla_metric;
- struct lsa_prefix asla_prefix[1];
+ struct lsa6_prefix asla_prefix[1];
/* some optional fields follow */
} un_asla;
@@ -183,7 +179,7 @@ struct lsa {
#define llsa_options llsa_priandopt.opt
struct in6_addr llsa_lladdr;
u_int32_t llsa_nprefix;
- struct lsa_prefix llsa_prefix[1];
+ struct lsa6_prefix llsa_prefix[1];
} un_llsa;
/* Intra-Area-Prefix */
@@ -192,21 +188,12 @@ struct lsa {
u_int16_t intra_ap_lstype;
rtrid_t intra_ap_lsid;
rtrid_t intra_ap_rtid;
- struct lsa_prefix intra_ap_prefix[1];
+ struct lsa6_prefix intra_ap_prefix[1];
} un_intra_ap;
} lsa_un;
};
-/*
- * TOS metric struct (will be 0 or more in router links update)
- */
-struct tos_metric {
- u_int8_t tos_type;
- u_int8_t tos_zero;
- u_int16_t tos_metric;
-};
-
#define OSPF_AUTH_SIZE 8
/*
@@ -246,11 +233,11 @@ struct ospf6hdr {
u_int8_t db_mbz;
u_int8_t db_flags;
u_int32_t db_seq;
- struct lsa_hdr db_lshdr[1]; /* may repeat */
+ struct lsa6_hdr db_lshdr[1]; /* may repeat */
} un_db;
/* Link State Request */
- struct lsr {
+ struct lsr6 {
u_int16_t ls_mbz;
u_int16_t ls_type;
rtrid_t ls_stateid;
@@ -260,12 +247,12 @@ struct ospf6hdr {
/* Link State Update */
struct {
u_int32_t lsu_count;
- struct lsa lsu_lsa[1]; /* may repeat */
+ struct lsa6 lsu_lsa[1]; /* may repeat */
} un_lsu;
/* Link State Acknowledgement */
struct {
- struct lsa_hdr lsa_lshdr[1]; /* may repeat */
+ struct lsa6_hdr lsa_lshdr[1]; /* may repeat */
} un_lsa ;
} ospf6_un ;
};
diff --git a/contrib/tcpdump/oui.c b/contrib/tcpdump/oui.c
index 7cdcd40..e6569d4 100644
--- a/contrib/tcpdump/oui.c
+++ b/contrib/tcpdump/oui.c
@@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/oui.c,v 1.4.2.1 2005/04/17 01:20:56 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/oui.c,v 1.8.2.1 2008-01-09 09:44:39 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -39,6 +39,9 @@ struct tok oui_values[] = {
{ OUI_APPLETALK, "Appletalk" },
{ OUI_JUNIPER, "Juniper" },
{ OUI_HP, "Hewlett-Packard" },
+ { OUI_IEEE_8021_PRIVATE, "IEEE 802.1 Private"},
+ { OUI_IEEE_8023_PRIVATE, "IEEE 802.3 Private"},
+ { OUI_TIA, "ANSI/TIA"},
{ 0, NULL }
};
diff --git a/contrib/tcpdump/oui.h b/contrib/tcpdump/oui.h
index 4d79e19..e70f82a 100644
--- a/contrib/tcpdump/oui.h
+++ b/contrib/tcpdump/oui.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/oui.h,v 1.3.2.1 2005/04/17 01:20:56 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/oui.h,v 1.7.2.1 2008-01-09 09:44:39 hannes Exp $ (LBL) */
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code
@@ -27,6 +27,9 @@ extern struct tok smi_values[];
#define OUI_APPLETALK 0x080007 /* Appletalk */
#define OUI_JUNIPER 0x009069 /* Juniper */
#define OUI_HP 0x080009 /* Hewlett-Packard */
+#define OUI_IEEE_8021_PRIVATE 0x0080c2 /* IEEE 802.1 Organisation Specific - Annex F */
+#define OUI_IEEE_8023_PRIVATE 0x00120f /* IEEE 802.3 Organisation Specific - Annex G */
+#define OUI_TIA 0x0012bb /* TIA - Telecommunications Industry Association - ANSI/TIA-1057- 2006 */
/*
* These are SMI Network Management Private Enterprise Codes for
diff --git a/contrib/tcpdump/parsenfsfh.c b/contrib/tcpdump/parsenfsfh.c
index 4aa8191..bf575e0 100644
--- a/contrib/tcpdump/parsenfsfh.c
+++ b/contrib/tcpdump/parsenfsfh.c
@@ -44,7 +44,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/parsenfsfh.c,v 1.28.2.1 2007/06/15 19:15:04 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/parsenfsfh.c,v 1.29 2006-06-13 22:21:38 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/pcap-missing.h b/contrib/tcpdump/pcap-missing.h
index 1f2fcb4..5c0ece2 100644
--- a/contrib/tcpdump/pcap-missing.h
+++ b/contrib/tcpdump/pcap-missing.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/pcap-missing.h,v 1.2.2.1 2005/06/03 22:10:16 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/pcap-missing.h,v 1.3 2005-06-03 22:08:52 guy Exp $ (LBL)
*/
#ifndef tcpdump_pcap_missing_h
diff --git a/contrib/tcpdump/pcap_dump_ftell.c b/contrib/tcpdump/pcap_dump_ftell.c
index 438cd29..6eb3a4a 100644
--- a/contrib/tcpdump/pcap_dump_ftell.c
+++ b/contrib/tcpdump/pcap_dump_ftell.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/pcap_dump_ftell.c,v 1.1.2.1 2005/06/03 22:10:17 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/pcap_dump_ftell.c,v 1.1 2005-06-03 22:08:52 guy Exp $ (LBL)";
#endif
#include <stdio.h>
diff --git a/contrib/tcpdump/pmap_prot.h b/contrib/tcpdump/pmap_prot.h
index 17cb92f..949c399 100644
--- a/contrib/tcpdump/pmap_prot.h
+++ b/contrib/tcpdump/pmap_prot.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/pmap_prot.h,v 1.1.2.2 2005/04/27 21:44:06 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/pmap_prot.h,v 1.3 2005-04-27 21:43:48 guy Exp $ (LBL) */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -30,6 +30,7 @@
* from: @(#)pmap_prot.h 1.14 88/02/08 SMI
* from: @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC
* $FreeBSD$
+ * FreeBSD: src/include/rpc/pmap_prot.h,v 1.9.2.1 1999/08/29 14:39:05 peter Exp
*/
/*
diff --git a/contrib/tcpdump/ppp.h b/contrib/tcpdump/ppp.h
index 9c4b473..3ae519b 100644
--- a/contrib/tcpdump/ppp.h
+++ b/contrib/tcpdump/ppp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/ppp.h,v 1.16 2004/10/20 16:14:16 hannes Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/ppp.h,v 1.16 2004-10-20 16:14:16 hannes Exp $ (LBL) */
/*
* Point to Point Protocol (PPP) RFC1331
*
diff --git a/contrib/tcpdump/print-802_11.c b/contrib/tcpdump/print-802_11.c
index 100730a..d7eb371 100644
--- a/contrib/tcpdump/print-802_11.c
+++ b/contrib/tcpdump/print-802_11.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.31.2.15 2007/07/22 23:14:14 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-802_11.c,v 1.47.2.2 2007-12-29 23:25:28 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -286,7 +286,7 @@ parse_elements(struct mgmt_body_t *pbody, const u_char *p, int offset)
if (pbody->tim.length <= 3)
break;
- if (pbody->tim.length - 3 > sizeof pbody->tim.bitmap)
+ if (pbody->tim.length - 3 > (int)sizeof pbody->tim.bitmap)
return;
if (!TTEST2(*(p + offset), pbody->tim.length - 3))
return;
@@ -1325,6 +1325,11 @@ ieee802_11_avs_radio_print(const u_char *p, u_int length, u_int caplen)
{
u_int32_t caphdr_len;
+ if (caplen < 8) {
+ printf("[|802.11]");
+ return caplen;
+ }
+
caphdr_len = EXTRACT_32BITS(p + 4);
if (caphdr_len < 8) {
/*
@@ -1347,32 +1352,38 @@ ieee802_11_avs_radio_print(const u_char *p, u_int length, u_int caplen)
#define PRISM_HDR_LEN 144
+#define WLANCAP_MAGIC_COOKIE_BASE 0x80211000
#define WLANCAP_MAGIC_COOKIE_V1 0x80211001
+#define WLANCAP_MAGIC_COOKIE_V2 0x80211002
/*
* For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header,
* containing information such as radio information, which we
* currently ignore.
*
- * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1, it's
- * really DLT_IEEE802_11_RADIO (currently, on Linux, there's no
- * ARPHRD_ type for DLT_IEEE802_11_RADIO, as there is a
- * ARPHRD_IEEE80211_PRISM for DLT_PRISM_HEADER, so
- * ARPHRD_IEEE80211_PRISM is used for DLT_IEEE802_11_RADIO, and
- * the first 4 bytes of the header are used to indicate which it is).
+ * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or
+ * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS
+ * (currently, on Linux, there's no ARPHRD_ type for
+ * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM
+ * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for
+ * the AVS header, and the first 4 bytes of the header are used to
+ * indicate whether it's a Prism header or an AVS header).
*/
u_int
prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
{
u_int caplen = h->caplen;
u_int length = h->len;
+ u_int32_t msgcode;
if (caplen < 4) {
printf("[|802.11]");
return caplen;
}
- if (EXTRACT_32BITS(p) == WLANCAP_MAGIC_COOKIE_V1)
+ msgcode = EXTRACT_32BITS(p);
+ if (msgcode == WLANCAP_MAGIC_COOKIE_V1 ||
+ msgcode == WLANCAP_MAGIC_COOKIE_V2)
return ieee802_11_avs_radio_print(p, length, caplen);
if (caplen < PRISM_HDR_LEN) {
@@ -1386,19 +1397,21 @@ prism_if_print(const struct pcap_pkthdr *h, const u_char *p)
/*
* For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra
- * header, containing information such as radio information, which we
- * currently ignore.
+ * header, containing information such as radio information.
*/
u_int
ieee802_11_radio_if_print(const struct pcap_pkthdr *h, const u_char *p)
{
- u_int caplen = h->caplen;
- u_int length = h->len;
-
- if (caplen < 8) {
- printf("[|802.11]");
- return caplen;
- }
+ return ieee802_11_radio_print(p, h->len, h->caplen);
+}
- return ieee802_11_radio_print(p, length, caplen);
+/*
+ * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an
+ * extra header, containing information such as radio information,
+ * which we currently ignore.
+ */
+u_int
+ieee802_11_radio_avs_if_print(const struct pcap_pkthdr *h, const u_char *p)
+{
+ return ieee802_11_avs_radio_print(p, h->len, h->caplen);
}
diff --git a/contrib/tcpdump/print-ah.c b/contrib/tcpdump/print-ah.c
index 92ed909..ecd106b 100644
--- a/contrib/tcpdump/print-ah.c
+++ b/contrib/tcpdump/print-ah.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ah.c,v 1.22 2003/11/19 00:36:06 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ah.c,v 1.22 2003-11-19 00:36:06 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-aodv.c b/contrib/tcpdump/print-aodv.c
index 80a547d..c5f6622 100644
--- a/contrib/tcpdump/print-aodv.c
+++ b/contrib/tcpdump/print-aodv.c
@@ -32,7 +32,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-aodv.c,v 1.11 2004/03/24 00:30:19 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-aodv.c,v 1.11 2004-03-24 00:30:19 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-ap1394.c b/contrib/tcpdump/print-ap1394.c
index a01ce34..dd9bc5a 100644
--- a/contrib/tcpdump/print-ap1394.c
+++ b/contrib/tcpdump/print-ap1394.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ap1394.c,v 1.3.2.1 2005/07/07 01:24:33 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ap1394.c,v 1.5 2006-02-11 22:12:06 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -60,8 +60,8 @@ ap1394_hdr_print(register const u_char *bp, u_int length)
fp = (const struct firewire_header *)bp;
(void)printf("%s > %s",
- linkaddr_string(fp->firewire_dhost, FIREWIRE_EUI64_LEN),
- linkaddr_string(fp->firewire_shost, FIREWIRE_EUI64_LEN));
+ linkaddr_string(fp->firewire_dhost, LINKADDR_IEEE1394, FIREWIRE_EUI64_LEN),
+ linkaddr_string(fp->firewire_shost, LINKADDR_IEEE1394, FIREWIRE_EUI64_LEN));
if (!qflag) {
(void)printf(", ethertype %s (0x%04x)",
diff --git a/contrib/tcpdump/print-arcnet.c b/contrib/tcpdump/print-arcnet.c
index 63f9c21..48a4303 100644
--- a/contrib/tcpdump/print-arcnet.c
+++ b/contrib/tcpdump/print-arcnet.c
@@ -22,7 +22,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-arcnet.c,v 1.20 2005/04/06 21:32:38 mcr Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-arcnet.c,v 1.20 2005-04-06 21:32:38 mcr Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-arp.c b/contrib/tcpdump/print-arp.c
index 3dc2894..b15ae50 100644
--- a/contrib/tcpdump/print-arp.c
+++ b/contrib/tcpdump/print-arp.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-arp.c,v 1.64 2004/04/30 16:42:14 mcr Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-arp.c,v 1.66 2006-03-03 22:53:21 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -51,24 +51,27 @@ static const char rcsid[] _U_ =
* arp_tha and arp_tpa in that order, according to the lengths
* specified. Field names used correspond to RFC 826.
*/
-struct arp_pkthdr {
- u_short ar_hrd; /* format of hardware address */
-#define ARPHRD_ETHER 1 /* ethernet hardware format */
-#define ARPHRD_IEEE802 6 /* token-ring hardware format */
-#define ARPHRD_ARCNET 7 /* arcnet hardware format */
-#define ARPHRD_FRELAY 15 /* frame relay hardware format */
-#define ARPHRD_STRIP 23 /* Ricochet Starmode Radio hardware format */
-#define ARPHRD_IEEE1394 24 /* IEEE 1394 (FireWire) hardware format */
- u_short ar_pro; /* format of protocol address */
- u_char ar_hln; /* length of hardware address */
- u_char ar_pln; /* length of protocol address */
- u_short ar_op; /* one of: */
-#define ARPOP_REQUEST 1 /* request to resolve address */
-#define ARPOP_REPLY 2 /* response to previous request */
-#define ARPOP_REVREQUEST 3 /* request protocol address given hardware */
-#define ARPOP_REVREPLY 4 /* response giving protocol address */
-#define ARPOP_INVREQUEST 8 /* request to identify peer */
-#define ARPOP_INVREPLY 9 /* response identifying peer */
+struct arp_pkthdr {
+ u_short ar_hrd; /* format of hardware address */
+#define ARPHRD_ETHER 1 /* ethernet hardware format */
+#define ARPHRD_IEEE802 6 /* token-ring hardware format */
+#define ARPHRD_ARCNET 7 /* arcnet hardware format */
+#define ARPHRD_FRELAY 15 /* frame relay hardware format */
+#define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */
+#define ARPHRD_STRIP 23 /* Ricochet Starmode Radio hardware format */
+#define ARPHRD_IEEE1394 24 /* IEEE 1394 (FireWire) hardware format */
+ u_short ar_pro; /* format of protocol address */
+ u_char ar_hln; /* length of hardware address */
+ u_char ar_pln; /* length of protocol address */
+ u_short ar_op; /* one of: */
+#define ARPOP_REQUEST 1 /* request to resolve address */
+#define ARPOP_REPLY 2 /* response to previous request */
+#define ARPOP_REVREQUEST 3 /* request protocol address given hardware */
+#define ARPOP_REVREPLY 4 /* response giving protocol address */
+#define ARPOP_INVREQUEST 8 /* request to identify peer */
+#define ARPOP_INVREPLY 9 /* response identifying peer */
+#define ARPOP_NAK 10 /* NAK - only valif for ATM ARP */
+
/*
* The remaining fields are variable in size,
* according to the sizes above.
@@ -88,8 +91,8 @@ struct arp_pkthdr {
#define ARP_HDRLEN 8
#define HRD(ap) EXTRACT_16BITS(&(ap)->ar_hrd)
-#define HLN(ap) ((ap)->ar_hln)
-#define PLN(ap) ((ap)->ar_pln)
+#define HRD_LEN(ap) ((ap)->ar_hln)
+#define PROTO_LEN(ap) ((ap)->ar_pln)
#define OP(ap) EXTRACT_16BITS(&(ap)->ar_op)
#define PRO(ap) EXTRACT_16BITS(&(ap)->ar_pro)
#define SHA(ap) (ar_sha(ap))
@@ -97,6 +100,29 @@ struct arp_pkthdr {
#define THA(ap) (ar_tha(ap))
#define TPA(ap) (ar_tpa(ap))
+
+struct tok arpop_values[] = {
+ { ARPOP_REQUEST, "Request" },
+ { ARPOP_REPLY, "Reply" },
+ { ARPOP_REVREQUEST, "Reverse Request" },
+ { ARPOP_REVREPLY, "Reverse Reply" },
+ { ARPOP_INVREQUEST, "Inverse Request" },
+ { ARPOP_INVREPLY, "Inverse Reply" },
+ { ARPOP_NAK, "NACK Reply" },
+ { 0, NULL }
+};
+
+struct tok arphrd_values[] = {
+ { ARPHRD_ETHER, "Ethernet" },
+ { ARPHRD_IEEE802, "TokenRing" },
+ { ARPHRD_ARCNET, "ArcNet" },
+ { ARPHRD_FRELAY, "FrameRelay" },
+ { ARPHRD_STRIP, "Strip" },
+ { ARPHRD_IEEE1394, "IEEE 1394" },
+ { ARPHRD_ATM2225, "ATM" },
+ { 0, NULL }
+};
+
/*
* ATM Address Resolution Protocol.
*
@@ -106,20 +132,18 @@ struct arp_pkthdr {
* the ATM number and subaddress - and the hardware addresses consist
* of an ATM number and an ATM subaddress.
*/
-struct atmarp_pkthdr {
- u_short aar_hrd; /* format of hardware address */
-#define ARPHRD_ATM2225 19 /* ATM (RFC 2225) */
- u_short aar_pro; /* format of protocol address */
- u_char aar_shtl; /* length of source ATM number */
- u_char aar_sstl; /* length of source ATM subaddress */
-#define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */
-#define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */
- u_short aar_op; /* same as regular ARP */
-#define ATMARPOP_NAK 10 /* NAK */
- u_char aar_spln; /* length of source protocol address */
- u_char aar_thtl; /* length of target ATM number */
- u_char aar_tstl; /* length of target ATM subaddress */
- u_char aar_tpln; /* length of target protocol address */
+struct atmarp_pkthdr {
+ u_short aar_hrd; /* format of hardware address */
+ u_short aar_pro; /* format of protocol address */
+ u_char aar_shtl; /* length of source ATM number */
+ u_char aar_sstl; /* length of source ATM subaddress */
+#define ATMARP_IS_E164 0x40 /* bit in type/length for E.164 format */
+#define ATMARP_LEN_MASK 0x3F /* length of {sub}address in type/length */
+ u_short aar_op; /* same as regular ARP */
+ u_char aar_spln; /* length of source protocol address */
+ u_char aar_thtl; /* length of target ATM number */
+ u_char aar_tstl; /* length of target ATM subaddress */
+ u_char aar_tpln; /* length of target protocol address */
/*
* The remaining fields are variable in size,
* according to the sizes above.
@@ -134,19 +158,19 @@ struct atmarp_pkthdr {
#endif
#define ATMHRD(ap) EXTRACT_16BITS(&(ap)->aar_hrd)
-#define ATMSHLN(ap) ((ap)->aar_shtl & ATMARP_LEN_MASK)
+#define ATMSHRD_LEN(ap) ((ap)->aar_shtl & ATMARP_LEN_MASK)
#define ATMSSLN(ap) ((ap)->aar_sstl & ATMARP_LEN_MASK)
-#define ATMSPLN(ap) ((ap)->aar_spln)
+#define ATMSPROTO_LEN(ap) ((ap)->aar_spln)
#define ATMOP(ap) EXTRACT_16BITS(&(ap)->aar_op)
#define ATMPRO(ap) EXTRACT_16BITS(&(ap)->aar_pro)
-#define ATMTHLN(ap) ((ap)->aar_thtl & ATMARP_LEN_MASK)
+#define ATMTHRD_LEN(ap) ((ap)->aar_thtl & ATMARP_LEN_MASK)
#define ATMTSLN(ap) ((ap)->aar_tstl & ATMARP_LEN_MASK)
-#define ATMTPLN(ap) ((ap)->aar_tpln)
+#define ATMTPROTO_LEN(ap) ((ap)->aar_tpln)
#define aar_sha(ap) ((const u_char *)((ap)+1))
-#define aar_ssa(ap) (aar_sha(ap) + ATMSHLN(ap))
+#define aar_ssa(ap) (aar_sha(ap) + ATMSHRD_LEN(ap))
#define aar_spa(ap) (aar_ssa(ap) + ATMSSLN(ap))
-#define aar_tha(ap) (aar_spa(ap) + ATMSPLN(ap))
-#define aar_tsa(ap) (aar_tha(ap) + ATMTHLN(ap))
+#define aar_tha(ap) (aar_spa(ap) + ATMSPROTO_LEN(ap))
+#define aar_tsa(ap) (aar_tha(ap) + ATMTHRD_LEN(ap))
#define aar_tpa(ap) (aar_tsa(ap) + ATMTSLN(ap))
};
@@ -167,10 +191,10 @@ atmarp_addr_print(netdissect_options *ndo,
if (ha_len == 0)
ND_PRINT((ndo, "<No address>"));
else {
- ND_PRINT((ndo, "%s", linkaddr_string(ha, ha_len)));
+ ND_PRINT((ndo, "%s", linkaddr_string(ha, LINKADDR_ATM, ha_len)));
if (srca_len != 0)
ND_PRINT((ndo, ",%s",
- linkaddr_string(srca, srca_len)));
+ linkaddr_string(srca, LINKADDR_ATM, srca_len)));
}
}
@@ -188,69 +212,86 @@ atmarp_print(netdissect_options *ndo,
pro = ATMPRO(ap);
op = ATMOP(ap);
- if (!ND_TTEST2(*aar_tpa(ap), ATMTPLN(ap))) {
- ND_PRINT((ndo, "truncated-atmarp"));
+ if (!ND_TTEST2(*aar_tpa(ap), ATMTPROTO_LEN(ap))) {
+ ND_PRINT((ndo, "[|ARP]"));
ND_DEFAULTPRINT((const u_char *)ap, length);
return;
}
+ if (!ndo->ndo_eflag) {
+ ND_PRINT((ndo, "ARP, "));
+ }
+
if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
- ATMSPLN(ap) != 4 || ATMTPLN(ap) != 4) {
- ND_PRINT((ndo, "atmarp-#%d for proto #%d (%d/%d) hardware #%d",
- op, pro, ATMSPLN(ap), ATMTPLN(ap), hrd));
- return;
+ ATMSPROTO_LEN(ap) != 4 ||
+ ATMTPROTO_LEN(ap) != 4 ||
+ ndo->ndo_vflag) {
+ ND_PRINT((ndo, "%s, %s (len %u/%u)",
+ tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
+ tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
+ ATMSPROTO_LEN(ap),
+ ATMTPROTO_LEN(ap)));
+
+ /* don't know know about the address formats */
+ if (!ndo->ndo_vflag) {
+ goto out;
+ }
}
- if (pro == ETHERTYPE_TRAIL)
- ND_PRINT((ndo, "trailer-"));
+
+ /* print operation */
+ printf("%s%s ",
+ ndo->ndo_vflag ? ", " : "",
+ tok2str(arpop_values, "Unknown (%u)", op));
+
switch (op) {
case ARPOP_REQUEST:
- ND_PRINT((ndo, "arp who-has %s", ipaddr_string(ATMTPA(ap))));
- if (ATMTHLN(ap) != 0) {
+ ND_PRINT((ndo, "who-has %s", ipaddr_string(ATMTPA(ap))));
+ if (ATMTHRD_LEN(ap) != 0) {
ND_PRINT((ndo, " ("));
- atmarp_addr_print(ndo, ATMTHA(ap), ATMTHLN(ap),
+ atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap),
ATMTSA(ap), ATMTSLN(ap));
ND_PRINT((ndo, ")"));
}
- ND_PRINT((ndo, " tell %s", ipaddr_string(ATMSPA(ap))));
+ ND_PRINT((ndo, "tell %s", ipaddr_string(ATMSPA(ap))));
break;
case ARPOP_REPLY:
- ND_PRINT((ndo, "arp reply %s", ipaddr_string(ATMSPA(ap))));
- ND_PRINT((ndo, " is-at "));
- atmarp_addr_print(ndo, ATMSHA(ap), ATMSHLN(ap), ATMSSA(ap),
- ATMSSLN(ap));
+ ND_PRINT((ndo, "%s is-at ", ipaddr_string(ATMSPA(ap))));
+ atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
+ ATMSSLN(ap));
break;
case ARPOP_INVREQUEST:
- ND_PRINT((ndo, "invarp who-is "));
- atmarp_addr_print(ndo, ATMTHA(ap), ATMTHLN(ap), ATMTSA(ap),
+ ND_PRINT((ndo, "who-is "));
+ atmarp_addr_print(ndo, ATMTHA(ap), ATMTHRD_LEN(ap), ATMTSA(ap),
ATMTSLN(ap));
ND_PRINT((ndo, " tell "));
- atmarp_addr_print(ndo, ATMSHA(ap), ATMSHLN(ap), ATMSSA(ap),
+ atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
ATMSSLN(ap));
break;
case ARPOP_INVREPLY:
- ND_PRINT((ndo, "invarp reply "));
- atmarp_addr_print(ndo, ATMSHA(ap), ATMSHLN(ap), ATMSSA(ap),
+ atmarp_addr_print(ndo, ATMSHA(ap), ATMSHRD_LEN(ap), ATMSSA(ap),
ATMSSLN(ap));
- ND_PRINT((ndo, " at %s", ipaddr_string(ATMSPA(ap))));
+ ND_PRINT((ndo, "at %s", ipaddr_string(ATMSPA(ap))));
break;
- case ATMARPOP_NAK:
- ND_PRINT((ndo, "nak reply for %s",
- ipaddr_string(ATMSPA(ap))));
+ case ARPOP_NAK:
+ ND_PRINT((ndo, "for %s", ipaddr_string(ATMSPA(ap))));
break;
default:
- ND_PRINT((ndo, "atmarp-#%d", op));
ND_DEFAULTPRINT((const u_char *)ap, caplen);
return;
}
- return;
+
+ out:
+ ND_PRINT((ndo, ", length %u", length));
+ return;
+
trunc:
- ND_PRINT((ndo, "[|atmarp]"));
+ ND_PRINT((ndo, "[|ARP]"));
}
void
@@ -258,81 +299,115 @@ arp_print(netdissect_options *ndo,
const u_char *bp, u_int length, u_int caplen)
{
const struct arp_pkthdr *ap;
- u_short pro, hrd, op;
+ u_short pro, hrd, op, linkaddr;
ap = (const struct arp_pkthdr *)bp;
ND_TCHECK(*ap);
+
hrd = HRD(ap);
- if (hrd == ARPHRD_ATM2225) {
- atmarp_print(ndo, bp, length, caplen);
- return;
- }
pro = PRO(ap);
op = OP(ap);
- if (!ND_TTEST2(*ar_tpa(ap), PLN(ap))) {
- ND_PRINT((ndo, "truncated-arp"));
+
+ /* if its ATM then call the ATM ARP printer
+ for Frame-relay ARP most of the fields
+ are similar to Ethernet so overload the Ethernet Printer
+ and set the linkaddr type for linkaddr_string() accordingly */
+
+ switch(hrd) {
+ case ARPHRD_ATM2225:
+ atmarp_print(ndo, bp, length, caplen);
+ return;
+ case ARPHRD_FRELAY:
+ linkaddr = LINKADDR_FRELAY;
+ default:
+ linkaddr = LINKADDR_ETHER;
+ break;
+ }
+
+ if (!ND_TTEST2(*ar_tpa(ap), PROTO_LEN(ap))) {
+ ND_PRINT((ndo, "[|ARP]"));
ND_DEFAULTPRINT((const u_char *)ap, length);
return;
}
- if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
- PLN(ap) != 4 || HLN(ap) == 0) {
- ND_PRINT((ndo, "arp-#%d for proto #%d (%d) hardware #%d (%d)",
- op, pro, PLN(ap), hrd, HLN(ap)));
- return;
+ if (!ndo->ndo_eflag) {
+ ND_PRINT((ndo, "ARP, "));
+ }
+
+ /* print hardware type/len and proto type/len */
+ if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) ||
+ PROTO_LEN(ap) != 4 ||
+ HRD_LEN(ap) == 0 ||
+ ndo->ndo_vflag) {
+ ND_PRINT((ndo, "%s (len %u), %s (len %u)",
+ tok2str(arphrd_values, "Unknown Hardware (%u)", hrd),
+ HRD_LEN(ap),
+ tok2str(ethertype_values, "Unknown Protocol (0x%04x)", pro),
+ PROTO_LEN(ap)));
+
+ /* don't know know about the address formats */
+ if (!ndo->ndo_vflag) {
+ goto out;
+ }
}
- if (pro == ETHERTYPE_TRAIL)
- ND_PRINT((ndo, "trailer-"));
+
+ /* print operation */
+ printf("%s%s ",
+ ndo->ndo_vflag ? ", " : "",
+ tok2str(arpop_values, "Unknown (%u)", op));
+
switch (op) {
case ARPOP_REQUEST:
- ND_PRINT((ndo, "arp who-has %s", ipaddr_string(TPA(ap))));
- if (memcmp((const char *)ezero, (const char *)THA(ap), HLN(ap)) != 0)
+ ND_PRINT((ndo, "who-has %s", ipaddr_string(TPA(ap))));
+ if (memcmp((const char *)ezero, (const char *)THA(ap), HRD_LEN(ap)) != 0)
ND_PRINT((ndo, " (%s)",
- linkaddr_string(THA(ap), HLN(ap))));
+ linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap))));
ND_PRINT((ndo, " tell %s", ipaddr_string(SPA(ap))));
break;
case ARPOP_REPLY:
- ND_PRINT((ndo, "arp reply %s", ipaddr_string(SPA(ap))));
- ND_PRINT((ndo, " is-at %s", linkaddr_string(SHA(ap), HLN(ap))));
+ ND_PRINT((ndo, "%s is-at %s",
+ ipaddr_string(SPA(ap)),
+ linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap))));
break;
case ARPOP_REVREQUEST:
- ND_PRINT((ndo, "rarp who-is %s tell %s",
- linkaddr_string(THA(ap), HLN(ap)),
- linkaddr_string(SHA(ap), HLN(ap))));
+ ND_PRINT((ndo, "who-is %s tell %s",
+ linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
+ linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap))));
break;
case ARPOP_REVREPLY:
- ND_PRINT((ndo, "rarp reply %s at %s",
- linkaddr_string(THA(ap), HLN(ap)),
+ ND_PRINT((ndo, "%s at %s",
+ linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
ipaddr_string(TPA(ap))));
break;
case ARPOP_INVREQUEST:
- ND_PRINT((ndo, "invarp who-is %s tell %s",
- linkaddr_string(THA(ap), HLN(ap)),
- linkaddr_string(SHA(ap), HLN(ap))));
+ ND_PRINT((ndo, "who-is %s tell %s",
+ linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
+ linkaddr_string(SHA(ap), linkaddr, HRD_LEN(ap))));
break;
case ARPOP_INVREPLY:
- ND_PRINT((ndo,"invarp reply %s at %s",
- linkaddr_string(THA(ap), HLN(ap)),
+ ND_PRINT((ndo,"%s at %s",
+ linkaddr_string(THA(ap), linkaddr, HRD_LEN(ap)),
ipaddr_string(TPA(ap))));
break;
default:
- ND_PRINT((ndo, "arp-#%d", op));
ND_DEFAULTPRINT((const u_char *)ap, caplen);
return;
}
- if (hrd != ARPHRD_ETHER)
- ND_PRINT((ndo, " hardware #%d", hrd));
+
+ out:
+ ND_PRINT((ndo, ", length %u", length));
+
return;
trunc:
- ND_PRINT((ndo, "[|arp]"));
+ ND_PRINT((ndo, "[|ARP]"));
}
/*
diff --git a/contrib/tcpdump/print-ascii.c b/contrib/tcpdump/print-ascii.c
index cd48edd..fa8793cb 100644
--- a/contrib/tcpdump/print-ascii.c
+++ b/contrib/tcpdump/print-ascii.c
@@ -42,7 +42,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ascii.c,v 1.16.2.1 2005/07/06 20:54:49 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ascii.c,v 1.17 2005-07-06 20:53:32 guy Exp $";
#endif
#include <tcpdump-stdinc.h>
#include <stdio.h>
diff --git a/contrib/tcpdump/print-atalk.c b/contrib/tcpdump/print-atalk.c
index 1d575a6..6a8056b 100644
--- a/contrib/tcpdump/print-atalk.c
+++ b/contrib/tcpdump/print-atalk.c
@@ -25,7 +25,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-atalk.c,v 1.81 2004/05/01 09:41:50 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-atalk.c,v 1.81 2004-05-01 09:41:50 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-atm.c b/contrib/tcpdump/print-atm.c
index 03ca34b..3f000e3 100644
--- a/contrib/tcpdump/print-atm.c
+++ b/contrib/tcpdump/print-atm.c
@@ -22,7 +22,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-atm.c,v 1.38.2.6 2006/01/25 13:27:24 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-atm.c,v 1.48.2.1 2007-10-22 19:39:12 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -45,25 +45,51 @@ static const char rcsid[] _U_ =
#include "ether.h"
+#define OAM_CRC10_MASK 0x3ff
+#define OAM_PAYLOAD_LEN 48
+#define OAM_FUNCTION_SPECIFIC_LEN 45 /* this excludes crc10 and cell-type/function-type */
+#define OAM_CELLTYPE_FUNCTYPE_LEN 1
+
struct tok oam_f_values[] = {
- { OAMF4SC, "OAM F4 (segment)" },
- { OAMF4EC, "OAM F4 (end)" },
+ { VCI_OAMF4SC, "OAM F4 (segment)" },
+ { VCI_OAMF4EC, "OAM F4 (end)" },
+ { 0, NULL }
+};
+
+struct tok atm_pty_values[] = {
+ { 0x0, "user data, uncongested, SDU 0" },
+ { 0x1, "user data, uncongested, SDU 1" },
+ { 0x2, "user data, congested, SDU 0" },
+ { 0x3, "user data, congested, SDU 1" },
+ { 0x4, "VCC OAM F5 flow segment" },
+ { 0x5, "VCC OAM F5 flow end-to-end" },
+ { 0x6, "Traffic Control and resource Mgmt" },
{ 0, NULL }
};
+#define OAM_CELLTYPE_FM 0x1
+#define OAM_CELLTYPE_PM 0x2
+#define OAM_CELLTYPE_AD 0x8
+#define OAM_CELLTYPE_SM 0xf
+
struct tok oam_celltype_values[] = {
- { 0x1, "Fault Management" },
- { 0x2, "Performance Management" },
- { 0x8, "activate/deactivate" },
- { 0xf, "System Management" },
+ { OAM_CELLTYPE_FM, "Fault Management" },
+ { OAM_CELLTYPE_PM, "Performance Management" },
+ { OAM_CELLTYPE_AD, "activate/deactivate" },
+ { OAM_CELLTYPE_SM, "System Management" },
{ 0, NULL }
};
+#define OAM_FM_FUNCTYPE_AIS 0x0
+#define OAM_FM_FUNCTYPE_RDI 0x1
+#define OAM_FM_FUNCTYPE_CONTCHECK 0x4
+#define OAM_FM_FUNCTYPE_LOOPBACK 0x8
+
struct tok oam_fm_functype_values[] = {
- { 0x0, "AIS" },
- { 0x1, "RDI" },
- { 0x4, "Continuity Check" },
- { 0x8, "Loopback" },
+ { OAM_FM_FUNCTYPE_AIS, "AIS" },
+ { OAM_FM_FUNCTYPE_RDI, "RDI" },
+ { OAM_FM_FUNCTYPE_CONTCHECK, "Continuity Check" },
+ { OAM_FM_FUNCTYPE_LOOPBACK, "Loopback" },
{ 0, NULL }
};
@@ -80,6 +106,14 @@ struct tok oam_ad_functype_values[] = {
{ 0, NULL }
};
+#define OAM_FM_LOOPBACK_INDICATOR_MASK 0x1
+
+struct tok oam_fm_loopback_indicator_values[] = {
+ { 0x0, "Reply" },
+ { 0x1, "Request" },
+ { 0, NULL }
+};
+
static const struct tok *oam_functype_values[16] = {
NULL,
oam_fm_functype_values, /* 1 */
@@ -263,24 +297,24 @@ atm_print(u_int vpi, u_int vci, u_int traftype, const u_char *p, u_int length,
if (vpi == 0) {
switch (vci) {
- case PPC:
+ case VCI_PPC:
sig_print(p, caplen);
return;
- case BCC:
+ case VCI_BCC:
printf("broadcast sig: ");
return;
- case OAMF4SC: /* fall through */
- case OAMF4EC:
+ case VCI_OAMF4SC: /* fall through */
+ case VCI_OAMF4EC:
oam_print(p, length, ATM_OAM_HEC);
return;
- case METAC:
+ case VCI_METAC:
printf("meta: ");
return;
- case ILMIC:
+ case VCI_ILMIC:
printf("ilmi: ");
snmp_print(p, length);
return;
@@ -303,26 +337,53 @@ atm_print(u_int vpi, u_int vci, u_int traftype, const u_char *p, u_int length,
}
}
+struct oam_fm_loopback_t {
+ u_int8_t loopback_indicator;
+ u_int8_t correlation_tag[4];
+ u_int8_t loopback_id[12];
+ u_int8_t source_id[12];
+ u_int8_t unused[16];
+};
+
+struct oam_fm_ais_rdi_t {
+ u_int8_t failure_type;
+ u_int8_t failure_location[16];
+ u_int8_t unused[28];
+};
+
int
oam_print (const u_char *p, u_int length, u_int hec) {
u_int32_t cell_header;
- u_int16_t cell_type, func_type,vpi,vci,payload,clp;
+ u_int16_t vpi, vci, cksum, cksum_shouldbe, idx;
+ u_int8_t cell_type, func_type, payload, clp;
+
+ union {
+ const struct oam_fm_loopback_t *oam_fm_loopback;
+ const struct oam_fm_ais_rdi_t *oam_fm_ais_rdi;
+ } oam_ptr;
+
cell_header = EXTRACT_32BITS(p+hec);
- cell_type = ((*(p+4+hec))>>4) & 0x0f;
- func_type = *(p+4+hec) & 0x0f;
+ cell_type = ((*(p+ATM_HDR_LEN_NOHEC+hec))>>4) & 0x0f;
+ func_type = (*(p+ATM_HDR_LEN_NOHEC+hec)) & 0x0f;
vpi = (cell_header>>20)&0xff;
vci = (cell_header>>4)&0xffff;
payload = (cell_header>>1)&0x7;
clp = cell_header&0x1;
- printf("%s, vpi %u, vci %u, payload %u, clp %u, ",
+ printf("%s, vpi %u, vci %u, payload [ %s ], clp %u, length %u",
tok2str(oam_f_values, "OAM F5", vci),
- vpi, vci, payload, clp);
+ vpi, vci,
+ tok2str(atm_pty_values, "Unknown", payload),
+ clp, length);
+
+ if (!vflag) {
+ return 1;
+ }
- printf("cell-type %s (%u)",
+ printf("\n\tcell-type %s (%u)",
tok2str(oam_celltype_values, "unknown", cell_type),
cell_type);
@@ -330,9 +391,61 @@ oam_print (const u_char *p, u_int length, u_int hec) {
printf(", func-type unknown (%u)", func_type);
else
printf(", func-type %s (%u)",
- bittok2str(oam_functype_values[cell_type],"none",func_type),
+ tok2str(oam_functype_values[cell_type],"none",func_type),
func_type);
- printf(", length %u",length);
+ p += ATM_HDR_LEN_NOHEC + hec;
+
+ switch (cell_type << 4 | func_type) {
+ case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_LOOPBACK):
+ oam_ptr.oam_fm_loopback = (const struct oam_fm_loopback_t *)(p + OAM_CELLTYPE_FUNCTYPE_LEN);
+ printf("\n\tLoopback-Indicator %s, Correlation-Tag 0x%08x",
+ tok2str(oam_fm_loopback_indicator_values,
+ "Unknown",
+ oam_ptr.oam_fm_loopback->loopback_indicator & OAM_FM_LOOPBACK_INDICATOR_MASK),
+ EXTRACT_32BITS(&oam_ptr.oam_fm_loopback->correlation_tag));
+ printf("\n\tLocation-ID ");
+ for (idx = 0; idx < sizeof(oam_ptr.oam_fm_loopback->loopback_id); idx++) {
+ if (idx % 2) {
+ printf("%04x ", EXTRACT_16BITS(&oam_ptr.oam_fm_loopback->loopback_id[idx]));
+ }
+ }
+ printf("\n\tSource-ID ");
+ for (idx = 0; idx < sizeof(oam_ptr.oam_fm_loopback->source_id); idx++) {
+ if (idx % 2) {
+ printf("%04x ", EXTRACT_16BITS(&oam_ptr.oam_fm_loopback->source_id[idx]));
+ }
+ }
+ break;
+
+ case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_AIS):
+ case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_RDI):
+ oam_ptr.oam_fm_ais_rdi = (const struct oam_fm_ais_rdi_t *)(p + OAM_CELLTYPE_FUNCTYPE_LEN);
+ printf("\n\tFailure-type 0x%02x", oam_ptr.oam_fm_ais_rdi->failure_type);
+ printf("\n\tLocation-ID ");
+ for (idx = 0; idx < sizeof(oam_ptr.oam_fm_ais_rdi->failure_location); idx++) {
+ if (idx % 2) {
+ printf("%04x ", EXTRACT_16BITS(&oam_ptr.oam_fm_ais_rdi->failure_location[idx]));
+ }
+ }
+ break;
+
+ case (OAM_CELLTYPE_FM << 4 | OAM_FM_FUNCTYPE_CONTCHECK):
+ /* FIXME */
+ break;
+
+ default:
+ break;
+ }
+
+ /* crc10 checksum verification */
+ cksum = EXTRACT_16BITS(p + OAM_CELLTYPE_FUNCTYPE_LEN + OAM_FUNCTION_SPECIFIC_LEN)
+ & OAM_CRC10_MASK;
+ cksum_shouldbe = verify_crc10_cksum(0, p, OAM_PAYLOAD_LEN);
+
+ printf("\n\tcksum 0x%03x (%scorrect)",
+ cksum,
+ cksum_shouldbe == 0 ? "" : "in");
+
return 1;
}
diff --git a/contrib/tcpdump/print-beep.c b/contrib/tcpdump/print-beep.c
index db40d611..b476dbf 100644
--- a/contrib/tcpdump/print-beep.c
+++ b/contrib/tcpdump/print-beep.c
@@ -11,7 +11,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-beep.c,v 1.6 2003/11/16 09:36:13 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-beep.c,v 1.6 2003-11-16 09:36:13 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-bfd.c b/contrib/tcpdump/print-bfd.c
index 03e59dc..6406168 100644
--- a/contrib/tcpdump/print-bfd.c
+++ b/contrib/tcpdump/print-bfd.c
@@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-bfd.c,v 1.5.2.5 2006/02/02 06:36:37 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-bfd.c,v 1.10 2006-02-02 06:35:52 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-bgp.c b/contrib/tcpdump/print-bgp.c
index 34aa798..2dfdf52 100644
--- a/contrib/tcpdump/print-bgp.c
+++ b/contrib/tcpdump/print-bgp.c
@@ -36,7 +36,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.91.2.12 2007/07/14 22:26:35 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.117.2.1 2007-12-08 10:08:07 hannes Exp $";
#endif
#include <tcpdump-stdinc.h>
@@ -49,8 +49,8 @@ static const char rcsid[] _U_ =
#include "addrtoname.h"
#include "extract.h"
#include "bgp.h"
-#include "l2vpn.h"
#include "af.h"
+#include "l2vpn.h"
struct bgp {
u_int8_t bgp_marker[16];
@@ -145,6 +145,9 @@ struct bgp_attr {
#define BGPTYPE_MP_REACH_NLRI 14 /* RFC2283 */
#define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC2283 */
#define BGPTYPE_EXTD_COMMUNITIES 16 /* draft-ietf-idr-bgp-ext-communities */
+#define BGPTYPE_AS4_PATH 17 /* RFC4893 */
+#define BGPTYPE_AGGREGATOR4 18 /* RFC4893 */
+#define BGPTYPE_PMSI_TUNNEL 22 /* draft-ietf-l3vpn-2547bis-mcast-bgp-02.txt */
#define BGPTYPE_ATTR_SET 128 /* draft-marques-ppvpn-ibgp */
#define BGP_MP_NLRI_MINSIZE 3 /* End of RIB Marker detection */
@@ -152,11 +155,13 @@ struct bgp_attr {
static struct tok bgp_attr_values[] = {
{ BGPTYPE_ORIGIN, "Origin"},
{ BGPTYPE_AS_PATH, "AS Path"},
+ { BGPTYPE_AS4_PATH, "AS4 Path"},
{ BGPTYPE_NEXT_HOP, "Next Hop"},
{ BGPTYPE_MULTI_EXIT_DISC, "Multi Exit Discriminator"},
{ BGPTYPE_LOCAL_PREF, "Local Preference"},
{ BGPTYPE_ATOMIC_AGGREGATE, "Atomic Aggregate"},
{ BGPTYPE_AGGREGATOR, "Aggregator"},
+ { BGPTYPE_AGGREGATOR4, "Aggregator4"},
{ BGPTYPE_COMMUNITIES, "Community"},
{ BGPTYPE_ORIGINATOR_ID, "Originator ID"},
{ BGPTYPE_CLUSTER_LIST, "Cluster List"},
@@ -166,6 +171,7 @@ static struct tok bgp_attr_values[] = {
{ BGPTYPE_MP_REACH_NLRI, "Multi-Protocol Reach NLRI"},
{ BGPTYPE_MP_UNREACH_NLRI, "Multi-Protocol Unreach NLRI"},
{ BGPTYPE_EXTD_COMMUNITIES, "Extended Community"},
+ { BGPTYPE_PMSI_TUNNEL, "PMSI Tunnel"},
{ BGPTYPE_ATTR_SET, "Attribute Set"},
{ 255, "Reserved for development"},
{ 0, NULL}
@@ -176,6 +182,9 @@ static struct tok bgp_attr_values[] = {
#define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */
#define BGP_CONFED_AS_SET 4 /* draft-ietf-idr-rfc3065bis-01 */
+#define BGP_AS_SEG_TYPE_MIN BGP_AS_SET
+#define BGP_AS_SEG_TYPE_MAX BGP_CONFED_AS_SET
+
static struct tok bgp_as_path_segment_open_values[] = {
{ BGP_AS_SEQUENCE, ""},
{ BGP_AS_SET, "{ "},
@@ -267,6 +276,7 @@ static struct tok bgp_notify_minor_open_values[] = {
{ 4, "Unsupported Optional Parameter"},
{ 5, "Authentication Failure"},
{ 6, "Unacceptable Hold Time"},
+ { 7, "Capability Message Error"},
{ 0, NULL}
};
@@ -300,6 +310,31 @@ static struct tok bgp_origin_values[] = {
{ 0, NULL}
};
+#define BGP_PMSI_TUNNEL_RSVP_P2MP 1
+#define BGP_PMSI_TUNNEL_LDP_P2MP 2
+#define BGP_PMSI_TUNNEL_PIM_SSM 3
+#define BGP_PMSI_TUNNEL_PIM_SM 4
+#define BGP_PMSI_TUNNEL_PIM_BIDIR 5
+#define BGP_PMSI_TUNNEL_INGRESS 6
+#define BGP_PMSI_TUNNEL_LDP_MP2MP 7
+
+static struct tok bgp_pmsi_tunnel_values[] = {
+ { BGP_PMSI_TUNNEL_RSVP_P2MP, "RSVP-TE P2MP LSP"},
+ { BGP_PMSI_TUNNEL_LDP_P2MP, "LDP P2MP LSP"},
+ { BGP_PMSI_TUNNEL_PIM_SSM, "PIM-SSM Tree"},
+ { BGP_PMSI_TUNNEL_PIM_SM, "PIM-SM Tree"},
+ { BGP_PMSI_TUNNEL_PIM_BIDIR, "PIM-Bidir Tree"},
+ { BGP_PMSI_TUNNEL_INGRESS, "Ingress Replication"},
+ { BGP_PMSI_TUNNEL_LDP_MP2MP, "LDP MP2MP LSP"},
+ { 0, NULL}
+};
+
+static struct tok bgp_pmsi_flag_values[] = {
+ { 0x01, "Leaf Information required"},
+ { 0, NULL}
+};
+
+
/* Subsequent address family identifier, RFC2283 section 7 */
#define SAFNUM_RES 0
#define SAFNUM_UNICAST 1
@@ -307,6 +342,8 @@ static struct tok bgp_origin_values[] = {
#define SAFNUM_UNIMULTICAST 3
/* labeled BGP RFC3107 */
#define SAFNUM_LABUNICAST 4
+/* draft-ietf-l3vpn-2547bis-mcast-bgp-02.txt */
+#define SAFNUM_MULTICAST_VPN 5
#define SAFNUM_TUNNEL 64 /* XXX */
#define SAFNUM_VPLS 65 /* XXX */
#define SAFNUM_MDT 66 /* XXX */
@@ -331,7 +368,8 @@ static struct tok bgp_safi_values[] = {
{ SAFNUM_VPNUNICAST, "labeled VPN Unicast"},
{ SAFNUM_VPNMULTICAST, "labeled VPN Multicast"},
{ SAFNUM_VPNUNIMULTICAST, "labeled VPN Unicast+Multicast"},
- { SAFNUM_RT_ROUTING_INFO, "Route Target Routing Information"}, /* draft-marques-ppvpn-rt-constrain-01.txt */
+ { SAFNUM_RT_ROUTING_INFO, "Route Target Routing Information"},
+ { SAFNUM_MULTICAST_VPN, "Multicast VPN"},
{ 0, NULL }
};
@@ -349,8 +387,6 @@ static struct tok bgp_safi_values[] = {
#define BGP_EXT_COM_RO_2 0x0203 /* Route Origin,Format AN(4bytes):local(2bytes) */
#define BGP_EXT_COM_LINKBAND 0x4004 /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */
/* rfc2547 bgp-mpls-vpns */
-#define BGP_EXT_COM_CISCO_MCAST 0x0009 /* cisco proprietary */
-
#define BGP_EXT_COM_VPN_ORIGIN 0x0005 /* OSPF Domain ID / VPN of Origin - draft-rosen-vpns-ospf-bgp-mpls */
#define BGP_EXT_COM_VPN_ORIGIN2 0x0105 /* duplicate - keep for backwards compatability */
#define BGP_EXT_COM_VPN_ORIGIN3 0x0205 /* duplicate - keep for backwards compatability */
@@ -364,6 +400,9 @@ static struct tok bgp_safi_values[] = {
#define BGP_EXT_COM_L2INFO 0x800a /* draft-kompella-ppvpn-l2vpn */
+#define BGP_EXT_COM_SOURCE_AS 0x0009 /* draft-ietf-l3vpn-2547bis-mcast-bgp-02.txt */
+#define BGP_EXT_COM_VRF_RT_IMP 0x010a /* draft-ietf-l3vpn-2547bis-mcast-bgp-02.txt */
+
/* http://www.cisco.com/en/US/tech/tk436/tk428/technologies_tech_note09186a00801eb09a.shtml */
#define BGP_EXT_COM_EIGRP_GEN 0x8800
#define BGP_EXT_COM_EIGRP_METRIC_AS_DELAY 0x8801
@@ -386,7 +425,6 @@ static struct tok bgp_extd_comm_subtype_values[] = {
{ BGP_EXT_COM_RO_1, "origin"},
{ BGP_EXT_COM_RO_2, "origin"},
{ BGP_EXT_COM_LINKBAND, "link-BW"},
- { BGP_EXT_COM_CISCO_MCAST, "mdt-group"},
{ BGP_EXT_COM_VPN_ORIGIN, "ospf-domain"},
{ BGP_EXT_COM_VPN_ORIGIN2, "ospf-domain"},
{ BGP_EXT_COM_VPN_ORIGIN3, "ospf-domain"},
@@ -402,6 +440,8 @@ static struct tok bgp_extd_comm_subtype_values[] = {
{ BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU , "eigrp-route-metric (load, MTU)" },
{ BGP_EXT_COM_EIGRP_EXT_REMAS_REMID , "eigrp-external-route (remote-AS, remote-ID)" },
{ BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC , "eigrp-external-route (remote-proto, remote-metric)" },
+ { BGP_EXT_COM_SOURCE_AS, "source-AS" },
+ { BGP_EXT_COM_VRF_RT_IMP, "vrf-route-import"},
{ 0, NULL},
};
@@ -494,6 +534,99 @@ trunc:
return -2;
}
+/*
+ * bgp_vpn_ip_print
+ *
+ * print an ipv4 or ipv6 address into a buffer dependend on address length.
+ */
+static char *
+bgp_vpn_ip_print (const u_char *pptr, u_int addr_length) {
+
+ /* worst case string is s fully formatted v6 address */
+ static char addr[sizeof("1234:5678:89ab:cdef:1234:5678:89ab:cdef")];
+ char *pos = addr;
+
+ switch(addr_length) {
+ case (sizeof(struct in_addr) << 3): /* 32 */
+ TCHECK2(pptr[0], sizeof(struct in_addr));
+ snprintf(pos, sizeof(addr), "%s", ipaddr_string(pptr));
+ break;
+#ifdef INET6
+ case (sizeof(struct in6_addr) << 3): /* 128 */
+ TCHECK2(pptr[0], sizeof(struct in6_addr));
+ snprintf(pos, sizeof(addr), "%s", ip6addr_string(pptr));
+ break;
+#endif
+ default:
+ snprintf(pos, sizeof(addr), "bogus address length %u", addr_length);
+ break;
+ }
+ pos += strlen(pos);
+
+trunc:
+ *(pos) = '\0';
+ return (addr);
+}
+
+/*
+ * bgp_vpn_sg_print
+ *
+ * print an multicast s,g entry into a buffer.
+ * the s,g entry is encoded like this.
+ *
+ * +-----------------------------------+
+ * | Multicast Source Length (1 octet) |
+ * +-----------------------------------+
+ * | Multicast Source (Variable) |
+ * +-----------------------------------+
+ * | Multicast Group Length (1 octet) |
+ * +-----------------------------------+
+ * | Multicast Group (Variable) |
+ * +-----------------------------------+
+ *
+ * return the number of bytes read from the wire.
+ */
+static int
+bgp_vpn_sg_print (const u_char *pptr, char *buf, u_int buflen) {
+
+ u_int8_t addr_length;
+ u_int total_length, offset;
+
+ total_length = 0;
+
+ /* Source address length, encoded in bits */
+ TCHECK2(pptr[0], 1);
+ addr_length = *pptr++;
+
+ /* Source address */
+ TCHECK2(pptr[0], (addr_length >> 3));
+ total_length += (addr_length >> 3) + 1;
+ offset = strlen(buf);
+ if (addr_length) {
+ snprintf(buf + offset, buflen - offset, ", Source %s",
+ bgp_vpn_ip_print(pptr, addr_length));
+ pptr += (addr_length >> 3);
+ }
+
+ /* Group address length, encoded in bits */
+ TCHECK2(pptr[0], 1);
+ addr_length = *pptr++;
+
+ /* Group address */
+ TCHECK2(pptr[0], (addr_length >> 3));
+ total_length += (addr_length >> 3) + 1;
+ offset = strlen(buf);
+ if (addr_length) {
+ snprintf(buf + offset, buflen - offset, ", Group %s",
+ bgp_vpn_ip_print(pptr, addr_length));
+ pptr += (addr_length >> 3);
+ }
+
+trunc:
+ return (total_length);
+}
+
+
/* RDs and RTs share the same semantics
* we use bgp_vpn_rd_print for
* printing route targets inside a NLRI */
@@ -507,10 +640,12 @@ bgp_vpn_rd_print (const u_char *pptr) {
/* ok lets load the RD format */
switch (EXTRACT_16BITS(pptr)) {
- /* AS:IP-address fmt*/
+ /* 2-byte-AS:number fmt*/
case 0:
- snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u.%u.%u.%u",
- EXTRACT_16BITS(pptr+2), *(pptr+4), *(pptr+5), *(pptr+6), *(pptr+7));
+ snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u (= %u.%u.%u.%u)",
+ EXTRACT_16BITS(pptr+2),
+ EXTRACT_32BITS(pptr+4),
+ *(pptr+4), *(pptr+5), *(pptr+6), *(pptr+7));
break;
/* IP-address:AS fmt*/
@@ -609,6 +744,108 @@ trunc:
return -2;
}
+#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI 1
+#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI 2
+#define BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI 3
+#define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF 4
+#define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE 5
+#define BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN 6
+#define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN 7
+
+static struct tok bgp_multicast_vpn_route_type_values[] = {
+ { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI, "Intra-AS I-PMSI"},
+ { BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI, "Inter-AS I-PMSI"},
+ { BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI, "S-PMSI"},
+ { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF, "Intra-AS Segment-Leaf"},
+ { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE, "Source-Active"},
+ { BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN, "Shared Tree Join"},
+ { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN, "Source Tree Join"},
+};
+
+static int
+decode_multicast_vpn(const u_char *pptr, char *buf, u_int buflen)
+{
+ u_int8_t route_type, route_length, addr_length, sg_length;
+ u_int offset;
+
+ TCHECK2(pptr[0], 2);
+ route_type = *pptr++;
+ route_length = *pptr++;
+
+ snprintf(buf, buflen, "Route-Type: %s (%u), length: %u",
+ tok2str(bgp_multicast_vpn_route_type_values,
+ "Unknown", route_type),
+ route_type, route_length);
+
+ switch(route_type) {
+ case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI:
+ TCHECK2(pptr[0], BGP_VPN_RD_LEN);
+ offset = strlen(buf);
+ snprintf(buf + offset, buflen - offset, ", RD: %s, Originator %s",
+ bgp_vpn_rd_print(pptr),
+ bgp_vpn_ip_print(pptr + BGP_VPN_RD_LEN,
+ (route_length - BGP_VPN_RD_LEN) << 3));
+ break;
+ case BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI:
+ TCHECK2(pptr[0], BGP_VPN_RD_LEN + 4);
+ offset = strlen(buf);
+ snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %u",
+ bgp_vpn_rd_print(pptr),
+ EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN));
+ break;
+
+ case BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI:
+ TCHECK2(pptr[0], BGP_VPN_RD_LEN);
+ offset = strlen(buf);
+ snprintf(buf + offset, buflen - offset, ", RD: %s",
+ bgp_vpn_rd_print(pptr));
+ pptr += BGP_VPN_RD_LEN;
+
+ sg_length = bgp_vpn_sg_print(pptr, buf, buflen);
+ addr_length = route_length - sg_length;
+
+ TCHECK2(pptr[0], addr_length);
+ offset = strlen(buf);
+ snprintf(buf + offset, buflen - offset, ", Originator %s",
+ bgp_vpn_ip_print(pptr, addr_length << 3));
+ break;
+
+ case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE:
+ TCHECK2(pptr[0], BGP_VPN_RD_LEN);
+ offset = strlen(buf);
+ snprintf(buf + offset, buflen - offset, ", RD: %s",
+ bgp_vpn_rd_print(pptr));
+ pptr += BGP_VPN_RD_LEN;
+
+ bgp_vpn_sg_print(pptr, buf, buflen);
+ break;
+
+ case BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN: /* fall through */
+ case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN:
+ TCHECK2(pptr[0], BGP_VPN_RD_LEN);
+ offset = strlen(buf);
+ snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %u",
+ bgp_vpn_rd_print(pptr),
+ EXTRACT_32BITS(pptr + BGP_VPN_RD_LEN));
+ pptr += BGP_VPN_RD_LEN;
+
+ bgp_vpn_sg_print(pptr, buf, buflen);
+ break;
+
+ /*
+ * no per route-type printing yet.
+ */
+ case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF:
+ default:
+ break;
+ }
+
+ return route_length + 2;
+
+trunc:
+ return -2;
+}
+
/*
* As I remember, some versions of systems have an snprintf() that
* returns -1 if the buffer would have overflowed. If the return
@@ -863,6 +1100,63 @@ trunc:
return -2;
}
+/*
+ * bgp_attr_get_as_size
+ *
+ * Try to find the size of the ASs encoded in an as-path. It is not obvious, as
+ * both Old speakers that do not support 4 byte AS, and the new speakers that do
+ * support, exchange AS-Path with the same path-attribute type value 0x02.
+ */
+static int
+bgp_attr_get_as_size (u_int8_t bgpa_type, const u_char *pptr, int len)
+{
+ const u_char *tptr = pptr;
+
+ /*
+ * If the path attribute is the optional AS4 path type, then we already
+ * know, that ASs must be encoded in 4 byte format.
+ */
+ if (bgpa_type == BGPTYPE_AS4_PATH) {
+ return 4;
+ }
+
+ /*
+ * Let us assume that ASs are of 2 bytes in size, and check if the AS-Path
+ * TLV is good. If not, ask the caller to try with AS encoded as 4 bytes
+ * each.
+ */
+ while (tptr < pptr + len) {
+ TCHECK(tptr[0]);
+
+ /*
+ * If we do not find a valid segment type, our guess might be wrong.
+ */
+ if (tptr[0] < BGP_AS_SEG_TYPE_MIN || tptr[0] > BGP_AS_SEG_TYPE_MAX) {
+ goto trunc;
+ }
+ TCHECK(tptr[1]);
+ tptr += 2 + tptr[1] * 2;
+ }
+
+ /*
+ * If we correctly reached end of the AS path attribute data content,
+ * then most likely ASs were indeed encoded as 2 bytes.
+ */
+ if (tptr == pptr + len) {
+ return 2;
+ }
+
+trunc:
+
+ /*
+ * We can come here, either we did not have enough data, or if we
+ * try to decode 4 byte ASs in 2 byte format. Either way, return 4,
+ * so that calller can try to decode each AS as of 4 bytes. If indeed
+ * there was not enough data, it will crib and end the parse anyways.
+ */
+ return 4;
+}
+
static int
bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
{
@@ -878,6 +1172,7 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
const u_char *tptr;
char buf[MAXHOSTNAMELEN + 100];
char tokbuf[TOKBUFSIZE];
+ int as_size;
tptr = pptr;
tlen=len;
@@ -895,6 +1190,11 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
}
break;
+
+ /*
+ * Process AS4 byte path and AS2 byte path attributes here.
+ */
+ case BGPTYPE_AS4_PATH:
case BGPTYPE_AS_PATH:
if (len % 2) {
printf("invalid len");
@@ -905,21 +1205,33 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
break;
}
+ /*
+ * BGP updates exchanged between New speakers that support 4
+ * byte AS, ASs are always encoded in 4 bytes. There is no
+ * definitive way to find this, just by the packet's
+ * contents. So, check for packet's TLV's sanity assuming
+ * 2 bytes first, and it does not pass, assume that ASs are
+ * encoded in 4 bytes format and move on.
+ */
+ as_size = bgp_attr_get_as_size(attr->bgpa_type, pptr, len);
+
while (tptr < pptr + len) {
TCHECK(tptr[0]);
printf("%s", tok2strbuf(bgp_as_path_segment_open_values,
"?", tptr[0],
tokbuf, sizeof(tokbuf)));
- for (i = 0; i < tptr[1] * 2; i += 2) {
- TCHECK2(tptr[2 + i], 2);
- printf("%u ", EXTRACT_16BITS(&tptr[2 + i]));
+ for (i = 0; i < tptr[1] * as_size; i += as_size) {
+ TCHECK2(tptr[2 + i], as_size);
+ printf("%u ",
+ as_size == 2 ? EXTRACT_16BITS(&tptr[2 + i]) :
+ EXTRACT_32BITS(&tptr[2 + i]));
}
TCHECK(tptr[0]);
printf("%s", tok2strbuf(bgp_as_path_segment_close_values,
"?", tptr[0],
tokbuf, sizeof(tokbuf)));
TCHECK(tptr[1]);
- tptr += 2 + tptr[1] * 2;
+ tptr += 2 + tptr[1] * as_size;
}
break;
case BGPTYPE_NEXT_HOP:
@@ -952,6 +1264,15 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
printf(" AS #%u, origin %s", EXTRACT_16BITS(tptr),
getname(tptr + 2));
break;
+ case BGPTYPE_AGGREGATOR4:
+ if (len != 8) {
+ printf("invalid len");
+ break;
+ }
+ TCHECK2(tptr[0], 8);
+ printf(" AS #%u, origin %s", EXTRACT_32BITS(tptr),
+ getname(tptr + 4));
+ break;
case BGPTYPE_COMMUNITIES:
if (len % 4) {
printf("invalid len");
@@ -1027,12 +1348,12 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST):
+ case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
#ifdef INET6
case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
- case (AFNUM_INET6<<8 | SAFNUM_RT_ROUTING_INFO):
case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST):
case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST):
@@ -1073,6 +1394,7 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST):
case (AFNUM_INET<<8 | SAFNUM_LABUNICAST):
case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO):
+ case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN):
if (tlen < (int)sizeof(struct in_addr)) {
printf("invalid len");
tlen = 0;
@@ -1103,7 +1425,6 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST):
case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST):
- case (AFNUM_INET6<<8 | SAFNUM_RT_ROUTING_INFO):
if (tlen < (int)sizeof(struct in6_addr)) {
printf("invalid len");
tlen = 0;
@@ -1248,6 +1569,16 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
else
printf("\n\t %s", buf);
break;
+ case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
+ case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
+ advance = decode_multicast_vpn(tptr, buf, sizeof(buf));
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
+ break;
#ifdef INET6
case (AFNUM_INET6<<8 | SAFNUM_UNICAST):
case (AFNUM_INET6<<8 | SAFNUM_MULTICAST):
@@ -1280,15 +1611,6 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
else
printf("\n\t %s", buf);
break;
- case (AFNUM_INET6<<8 | SAFNUM_RT_ROUTING_INFO):
- advance = decode_rt_routing_info(tptr, buf, sizeof(buf));
- if (advance == -1)
- printf("\n\t (illegal prefix length)");
- else if (advance == -2)
- goto trunc;
- else
- printf("\n\t %s", buf);
- break;
#endif
case (AFNUM_VPLS<<8 | SAFNUM_VPLS):
case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST):
@@ -1459,6 +1781,16 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
else
printf("\n\t %s", buf);
break;
+ case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */
+ case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN):
+ advance = decode_multicast_vpn(tptr, buf, sizeof(buf));
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
+ break;
default:
TCHECK2(*(tptr-3),tlen);
printf("no AFI %u / SAFI %u decoder",af,safi);
@@ -1495,12 +1827,14 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
switch(extd_comm) {
case BGP_EXT_COM_RT_0:
case BGP_EXT_COM_RO_0:
- printf(": %u:%s",
+ printf(": %u:%u (= %s)",
EXTRACT_16BITS(tptr+2),
+ EXTRACT_32BITS(tptr+4),
getname(tptr+4));
break;
case BGP_EXT_COM_RT_1:
case BGP_EXT_COM_RO_1:
+ case BGP_EXT_COM_VRF_RT_IMP:
printf(": %s:%u",
getname(tptr+2),
EXTRACT_16BITS(tptr+6));
@@ -1516,11 +1850,6 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
printf(": bandwidth: %.3f Mbps",
bw.f*8/1000000);
break;
- case BGP_EXT_COM_CISCO_MCAST:
- printf(": AS %u, group %s",
- EXTRACT_16BITS(tptr+2),
- getname(tptr+4));
- break;
case BGP_EXT_COM_VPN_ORIGIN:
case BGP_EXT_COM_VPN_ORIGIN2:
case BGP_EXT_COM_VPN_ORIGIN3:
@@ -1549,6 +1878,9 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
*(tptr+3),
EXTRACT_16BITS(tptr+4));
break;
+ case BGP_EXT_COM_SOURCE_AS:
+ printf(": AS %u", EXTRACT_16BITS(tptr+2));
+ break;
default:
TCHECK2(*tptr,8);
print_unknown_data(tptr,"\n\t ",8);
@@ -1559,6 +1891,64 @@ bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
}
break;
+ case BGPTYPE_PMSI_TUNNEL:
+ {
+ u_int8_t tunnel_type, flags;
+
+ tunnel_type = *(tptr+1);
+ flags = *tptr;
+ tlen = len;
+
+ TCHECK2(tptr[0], 5);
+ printf("\n\t Tunnel-type %s (%u), Flags [%s], MPLS Label %u",
+ tok2str(bgp_pmsi_tunnel_values, "Unknown", tunnel_type),
+ tunnel_type,
+ bittok2str(bgp_pmsi_flag_values, "none", flags),
+ EXTRACT_24BITS(tptr+2)>>4);
+
+ tptr +=5;
+ tlen -= 5;
+
+ switch (tunnel_type) {
+ case BGP_PMSI_TUNNEL_PIM_SM: /* fall through */
+ case BGP_PMSI_TUNNEL_PIM_BIDIR:
+ TCHECK2(tptr[0], 8);
+ printf("\n\t Sender %s, P-Group %s",
+ ipaddr_string(tptr),
+ ipaddr_string(tptr+4));
+ break;
+
+ case BGP_PMSI_TUNNEL_PIM_SSM:
+ TCHECK2(tptr[0], 8);
+ printf("\n\t Root-Node %s, P-Group %s",
+ ipaddr_string(tptr),
+ ipaddr_string(tptr+4));
+ break;
+ case BGP_PMSI_TUNNEL_INGRESS:
+ TCHECK2(tptr[0], 4);
+ printf("\n\t Tunnel-Endpoint %s",
+ ipaddr_string(tptr));
+ break;
+ case BGP_PMSI_TUNNEL_LDP_P2MP: /* fall through */
+ case BGP_PMSI_TUNNEL_LDP_MP2MP:
+ TCHECK2(tptr[0], 8);
+ printf("\n\t Root-Node %s, LSP-ID 0x%08x",
+ ipaddr_string(tptr),
+ EXTRACT_32BITS(tptr+4));
+ break;
+ case BGP_PMSI_TUNNEL_RSVP_P2MP:
+ TCHECK2(tptr[0], 8);
+ printf("\n\t Extended-Tunnel-ID %s, P2MP-ID 0x%08x",
+ ipaddr_string(tptr),
+ EXTRACT_32BITS(tptr+4));
+ break;
+ default:
+ if (vflag <= 1) {
+ print_unknown_data(tptr,"\n\t ",tlen);
+ }
+ }
+ break;
+ }
case BGPTYPE_ATTR_SET:
TCHECK2(tptr[0], 4);
printf("\n\t Origin AS: %u", EXTRACT_32BITS(tptr));
@@ -2077,3 +2467,10 @@ bgp_print(const u_char *dat, int length)
trunc:
printf(" [|BGP]");
}
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/contrib/tcpdump/print-bootp.c b/contrib/tcpdump/print-bootp.c
index b7e2cda..0715eb1 100644
--- a/contrib/tcpdump/print-bootp.c
+++ b/contrib/tcpdump/print-bootp.c
@@ -24,7 +24,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-bootp.c,v 1.78.2.9 2007/08/21 22:02:08 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-bootp.c,v 1.88 2007-09-20 15:04:45 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -354,9 +354,13 @@ static struct tok dhcp_msg_values[] = {
{ 0, NULL }
};
-#define AGENT_SUBOPTION_CIRCUIT_ID 1
+#define AGENT_SUBOPTION_CIRCUIT_ID 1 /* RFC 3046 */
+#define AGENT_SUBOPTION_REMOTE_ID 2 /* RFC 3046 */
+#define AGENT_SUBOPTION_SUBSCRIBER_ID 6 /* RFC 3993 */
static struct tok agent_suboption_values[] = {
{ AGENT_SUBOPTION_CIRCUIT_ID, "Circuit-ID" },
+ { AGENT_SUBOPTION_REMOTE_ID, "Remote-ID" },
+ { AGENT_SUBOPTION_SUBSCRIBER_ID, "Subscriber-ID" },
{ 0, NULL }
};
@@ -688,9 +692,11 @@ rfc1048_print(register const u_char *bp)
suboptlen);
switch (subopt) {
- case AGENT_SUBOPTION_CIRCUIT_ID:
- fn_printn(bp, suboptlen, NULL);
- break;
+ case AGENT_SUBOPTION_CIRCUIT_ID: /* fall through */
+ case AGENT_SUBOPTION_REMOTE_ID:
+ case AGENT_SUBOPTION_SUBSCRIBER_ID:
+ fn_printn(bp, suboptlen, NULL);
+ break;
default:
print_unknown_data(bp, "\n\t\t", suboptlen);
diff --git a/contrib/tcpdump/print-bt.c b/contrib/tcpdump/print-bt.c
new file mode 100644
index 0000000..498440c
--- /dev/null
+++ b/contrib/tcpdump/print-bt.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2007
+ * paolo.abeni@email.it All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by Paolo Abeni.''
+ * The name of author may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/print-bt.c,v 1.1.2.1 2008-09-25 21:50:04 guy Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <pcap.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+
+#if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H)
+#include <pcap/bluetooth.h>
+
+#define BT_HDRLEN sizeof(pcap_bluetooth_h4_header)
+/*
+ * This is the top level routine of the printer. 'p' points
+ * to the bluetooth header of the packet, 'h->ts' is the timestamp,
+ * 'h->len' is the length of the packet off the wire, and 'h->caplen'
+ * is the number of bytes actually captured.
+ */
+u_int
+bt_if_print(const struct pcap_pkthdr *h, const u_char *p)
+{
+ u_int length = h->len;
+ u_int caplen = h->caplen;
+ const pcap_bluetooth_h4_header* hdr = (const pcap_bluetooth_h4_header*)p;
+
+ if (caplen < BT_HDRLEN) {
+ printf("[|bt]");
+ return (BT_HDRLEN);
+ }
+ caplen -= BT_HDRLEN;
+ length -= BT_HDRLEN;
+ p += BT_HDRLEN;
+ if (eflag)
+ (void)printf("hci length %d, direction %s, ", length, (ntohl(hdr->direction)&0x1)?"in":"out");
+
+ if (!suppress_default_print)
+ default_print(p, caplen);
+
+ return (BT_HDRLEN);
+}
+#endif
+
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/contrib/tcpdump/print-cdp.c b/contrib/tcpdump/print-cdp.c
index 4398fbe..f8f4427 100644
--- a/contrib/tcpdump/print-cdp.c
+++ b/contrib/tcpdump/print-cdp.c
@@ -26,7 +26,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-cdp.c,v 1.25 2004/10/07 14:53:11 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-cdp.c,v 1.25 2004-10-07 14:53:11 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-cfm.c b/contrib/tcpdump/print-cfm.c
new file mode 100644
index 0000000..bd98dd2
--- /dev/null
+++ b/contrib/tcpdump/print-cfm.c
@@ -0,0 +1,641 @@
+/*
+ * Copyright (c) 1998-2006 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * Support for the IEEE Connectivity Fault Management Protocols as per 802.1ag.
+ *
+ * Original code by Hannes Gredler (hannes@juniper.net)
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/print-cfm.c,v 1.5 2007-07-24 16:01:42 hannes Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interface.h"
+#include "extract.h"
+#include "ether.h"
+#include "addrtoname.h"
+#include "oui.h"
+#include "af.h"
+
+/*
+ * Prototypes
+ */
+const char * cfm_egress_id_string(register const u_char *);
+int cfm_mgmt_addr_print(register const u_char *);
+
+struct cfm_common_header_t {
+ u_int8_t mdlevel_version;
+ u_int8_t opcode;
+ u_int8_t flags;
+ u_int8_t first_tlv_offset;
+};
+
+#define CFM_VERSION 0
+#define CFM_EXTRACT_VERSION(x) (((x)&0x1f))
+#define CFM_EXTRACT_MD_LEVEL(x) (((x)&0xe0)>>5)
+
+#define CFM_OPCODE_CCM 1
+#define CFM_OPCODE_LBR 2
+#define CFM_OPCODE_LBM 3
+#define CFM_OPCODE_LTR 4
+#define CFM_OPCODE_LTM 5
+
+static const struct tok cfm_opcode_values[] = {
+ { CFM_OPCODE_CCM, "Continouity Check Message"},
+ { CFM_OPCODE_LBR, "Loopback Reply"},
+ { CFM_OPCODE_LBM, "Loopback Message"},
+ { CFM_OPCODE_LTR, "Linktrace Reply"},
+ { CFM_OPCODE_LTM, "Linktrace Message"},
+ { 0, NULL}
+};
+
+/*
+ * Message Formats.
+ */
+struct cfm_ccm_t {
+ u_int8_t sequence[4];
+ u_int8_t ma_epi[2];
+ u_int8_t md_nameformat;
+ u_int8_t md_namelength;
+ u_int8_t md_name[46]; /* md name and short ma name */
+ u_int8_t reserved_itu[16];
+ u_int8_t reserved[6];
+};
+
+/*
+ * Timer Bases for the CCM Interval field.
+ * Expressed in units of seconds.
+ */
+const float ccm_interval_base[8] = {0, 0.003333, 0.01, 0.1, 1, 10, 60, 600};
+#define CCM_INTERVAL_MIN_MULTIPLIER 3.25
+#define CCM_INTERVAL_MAX_MULTIPLIER 3.5
+
+#define CFM_CCM_RDI_FLAG 0x80
+#define CFM_EXTRACT_CCM_INTERVAL(x) (((x)&0x07))
+
+#define CFM_CCM_MD_FORMAT_8021 0
+#define CFM_CCM_MD_FORMAT_NONE 1
+#define CFM_CCM_MD_FORMAT_DNS 2
+#define CFM_CCM_MD_FORMAT_MAC 3
+#define CFM_CCM_MD_FORMAT_CHAR 4
+
+static const struct tok cfm_md_nameformat_values[] = {
+ { CFM_CCM_MD_FORMAT_8021, "IEEE 802.1"},
+ { CFM_CCM_MD_FORMAT_NONE, "No MD Name present"},
+ { CFM_CCM_MD_FORMAT_DNS, "DNS string"},
+ { CFM_CCM_MD_FORMAT_MAC, "MAC + 16Bit Integer"},
+ { CFM_CCM_MD_FORMAT_CHAR, "Character string"},
+ { 0, NULL}
+};
+
+#define CFM_CCM_MA_FORMAT_8021 0
+#define CFM_CCM_MA_FORMAT_VID 1
+#define CFM_CCM_MA_FORMAT_CHAR 2
+#define CFM_CCM_MA_FORMAT_INT 3
+#define CFM_CCM_MA_FORMAT_VPN 4
+
+static const struct tok cfm_ma_nameformat_values[] = {
+ { CFM_CCM_MA_FORMAT_8021, "IEEE 802.1"},
+ { CFM_CCM_MA_FORMAT_VID, "Primary VID"},
+ { CFM_CCM_MA_FORMAT_CHAR, "Character string"},
+ { CFM_CCM_MA_FORMAT_INT, "16Bit Integer"},
+ { CFM_CCM_MA_FORMAT_VPN, "RFC2685 VPN-ID"},
+ { 0, NULL}
+};
+
+struct cfm_lbm_t {
+ u_int8_t transaction_id[4];
+ u_int8_t reserved[4];
+};
+
+struct cfm_ltm_t {
+ u_int8_t transaction_id[4];
+ u_int8_t egress_id[8];
+ u_int8_t ttl;
+ u_int8_t original_mac[ETHER_ADDR_LEN];
+ u_int8_t target_mac[ETHER_ADDR_LEN];
+ u_int8_t reserved[3];
+};
+
+static const struct tok cfm_ltm_flag_values[] = {
+ { 0x80, "Use Forwarding-DB only"},
+ { 0, NULL}
+};
+
+struct cfm_ltr_t {
+ u_int8_t transaction_id[4];
+ u_int8_t last_egress_id[8];
+ u_int8_t next_egress_id[8];
+ u_int8_t ttl;
+ u_int8_t replay_action;
+ u_int8_t reserved[6];
+};
+
+static const struct tok cfm_ltr_flag_values[] = {
+ { 0x80, "Forwarded"},
+ { 0x40, "Terminal MEP"},
+ { 0, NULL}
+};
+
+static const struct tok cfm_ltr_replay_action_values[] = {
+ { 1, "Exact Match"},
+ { 2, "Filtering DB"},
+ { 3, "MIP CCM DB"},
+ { 0, NULL}
+};
+
+
+#define CFM_TLV_END 0
+#define CFM_TLV_SENDER_ID 1
+#define CFM_TLV_PORT_STATUS 2
+#define CFM_TLV_INTERFACE_STATUS 3
+#define CFM_TLV_DATA 4
+#define CFM_TLV_REPLY_INGRESS 5
+#define CFM_TLV_REPLY_EGRESS 6
+#define CFM_TLV_PRIVATE 31
+
+static const struct tok cfm_tlv_values[] = {
+ { CFM_TLV_END, "End"},
+ { CFM_TLV_SENDER_ID, "Sender ID"},
+ { CFM_TLV_PORT_STATUS, "Port status"},
+ { CFM_TLV_INTERFACE_STATUS, "Interface status"},
+ { CFM_TLV_DATA, "Data"},
+ { CFM_TLV_REPLY_INGRESS, "Reply Ingress"},
+ { CFM_TLV_REPLY_EGRESS, "Reply Egress"},
+ { CFM_TLV_PRIVATE, "Organization Specific"},
+ { 0, NULL}
+};
+
+/*
+ * TLVs
+ */
+
+struct cfm_tlv_header_t {
+ u_int8_t type;
+ u_int8_t length[2];
+};
+
+/* FIXME define TLV formats */
+
+static const struct tok cfm_tlv_port_status_values[] = {
+ { 1, "Blocked"},
+ { 2, "Up"},
+ { 0, NULL}
+};
+
+static const struct tok cfm_tlv_interface_status_values[] = {
+ { 1, "Up"},
+ { 2, "Down"},
+ { 3, "Testing"},
+ { 5, "Dormant"},
+ { 6, "not present"},
+ { 7, "lower Layer down"},
+ { 0, NULL}
+};
+
+#define CFM_CHASSIS_ID_CHASSIS_COMPONENT 1
+#define CFM_CHASSIS_ID_INTERFACE_ALIAS 2
+#define CFM_CHASSIS_ID_PORT_COMPONENT 3
+#define CFM_CHASSIS_ID_MAC_ADDRESS 4
+#define CFM_CHASSIS_ID_NETWORK_ADDRESS 5
+#define CFM_CHASSIS_ID_INTERFACE_NAME 6
+#define CFM_CHASSIS_ID_LOCAL 7
+
+static const struct tok cfm_tlv_senderid_chassisid_values[] = {
+ { 0, "Reserved"},
+ { CFM_CHASSIS_ID_CHASSIS_COMPONENT, "Chassis component"},
+ { CFM_CHASSIS_ID_INTERFACE_ALIAS, "Interface alias"},
+ { CFM_CHASSIS_ID_PORT_COMPONENT, "Port component"},
+ { CFM_CHASSIS_ID_MAC_ADDRESS, "MAC address"},
+ { CFM_CHASSIS_ID_NETWORK_ADDRESS, "Network address"},
+ { CFM_CHASSIS_ID_INTERFACE_NAME, "Interface name"},
+ { CFM_CHASSIS_ID_LOCAL, "Locally assigned"},
+ { 0, NULL}
+};
+
+
+int
+cfm_mgmt_addr_print(register const u_char *tptr) {
+
+ u_int mgmt_addr_type;
+ u_int hexdump = FALSE;
+
+ /*
+ * Altough AFIs are tpically 2 octects wide,
+ * 802.1ab specifies that this field width
+ * is only once octet
+ */
+ mgmt_addr_type = *tptr;
+ printf("\n\t Management Address Type %s (%u)",
+ tok2str(af_values, "Unknown", mgmt_addr_type),
+ mgmt_addr_type);
+
+ /*
+ * Resolve the passed in Address.
+ */
+ switch(mgmt_addr_type) {
+ case AFNUM_INET:
+ printf(", %s", ipaddr_string(tptr + 1));
+ break;
+
+#ifdef INET6
+ case AFNUM_INET6:
+ printf(", %s", ip6addr_string(tptr + 1));
+ break;
+#endif
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+
+ return hexdump;
+}
+
+/*
+ * The egress-ID string is a 16-Bit string plus a MAC address.
+ */
+const char *
+cfm_egress_id_string(register const u_char *tptr) {
+ static char egress_id_buffer[80];
+
+ snprintf(egress_id_buffer, sizeof(egress_id_buffer),
+ "MAC %0x4x-%s",
+ EXTRACT_16BITS(tptr),
+ etheraddr_string(tptr+2));
+
+ return egress_id_buffer;
+}
+
+void
+cfm_print(register const u_char *pptr, register u_int length) {
+
+ const struct cfm_common_header_t *cfm_common_header;
+ const struct cfm_tlv_header_t *cfm_tlv_header;
+ const u_int8_t *tptr, *tlv_ptr, *ma_name, *ma_nameformat, *ma_namelength;
+ u_int hexdump, tlen, cfm_tlv_len, cfm_tlv_type, ccm_interval;
+
+
+ union {
+ const struct cfm_ccm_t *cfm_ccm;
+ const struct cfm_lbm_t *cfm_lbm;
+ const struct cfm_ltm_t *cfm_ltm;
+ const struct cfm_ltr_t *cfm_ltr;
+ } msg_ptr;
+
+ tptr=pptr;
+ cfm_common_header = (const struct cfm_common_header_t *)pptr;
+ TCHECK(*cfm_common_header);
+
+ /*
+ * Sanity checking of the header.
+ */
+ if (CFM_EXTRACT_VERSION(cfm_common_header->mdlevel_version) != CFM_VERSION) {
+ printf("CFMv%u not supported, length %u",
+ CFM_EXTRACT_VERSION(cfm_common_header->mdlevel_version), length);
+ return;
+ }
+
+ printf("CFMv%u %s, MD Level %u, length %u",
+ CFM_EXTRACT_VERSION(cfm_common_header->mdlevel_version),
+ tok2str(cfm_opcode_values, "unknown (%u)", cfm_common_header->opcode),
+ CFM_EXTRACT_MD_LEVEL(cfm_common_header->mdlevel_version),
+ length);
+
+ /*
+ * In non-verbose mode just print the opcode and md-level.
+ */
+ if (vflag < 1) {
+ return;
+ }
+
+ printf("\n\tFirst TLV offset %u", cfm_common_header->first_tlv_offset);
+
+ tptr += sizeof(const struct cfm_common_header_t);
+ tlen = length - sizeof(struct cfm_common_header_t);
+
+ switch (cfm_common_header->opcode) {
+ case CFM_OPCODE_CCM:
+ msg_ptr.cfm_ccm = (const struct cfm_ccm_t *)tptr;
+
+ ccm_interval = CFM_EXTRACT_CCM_INTERVAL(cfm_common_header->flags);
+ printf(", Flags [CCM Interval %u%s]",
+ ccm_interval,
+ cfm_common_header->flags & CFM_CCM_RDI_FLAG ?
+ ", RDI" : "");
+
+ /*
+ * Resolve the CCM interval field.
+ */
+ if (ccm_interval) {
+ printf("\n\t CCM Interval %.3fs"
+ ", min CCM Lifetime %.3fs, max CCM Lifetime %.3fs",
+ ccm_interval_base[ccm_interval],
+ ccm_interval_base[ccm_interval] * CCM_INTERVAL_MIN_MULTIPLIER,
+ ccm_interval_base[ccm_interval] * CCM_INTERVAL_MAX_MULTIPLIER);
+ }
+
+ printf("\n\t Sequence Number 0x%08x, MA-End-Point-ID 0x%04x",
+ EXTRACT_32BITS(msg_ptr.cfm_ccm->sequence),
+ EXTRACT_16BITS(msg_ptr.cfm_ccm->ma_epi));
+
+
+ /*
+ * Resolve the MD fields.
+ */
+ printf("\n\t MD Name Format %s (%u), MD Name length %u",
+ tok2str(cfm_md_nameformat_values, "Unknown",
+ msg_ptr.cfm_ccm->md_nameformat),
+ msg_ptr.cfm_ccm->md_nameformat,
+ msg_ptr.cfm_ccm->md_namelength);
+
+ if (msg_ptr.cfm_ccm->md_nameformat != CFM_CCM_MD_FORMAT_NONE) {
+ printf("\n\t MD Name: ");
+ switch (msg_ptr.cfm_ccm->md_nameformat) {
+ case CFM_CCM_MD_FORMAT_DNS:
+ case CFM_CCM_MD_FORMAT_CHAR:
+ safeputs((const char *)msg_ptr.cfm_ccm->md_name, msg_ptr.cfm_ccm->md_namelength);
+ break;
+
+ case CFM_CCM_MD_FORMAT_MAC:
+ printf("\n\t MAC %s", etheraddr_string(
+ msg_ptr.cfm_ccm->md_name));
+ break;
+
+ /* FIXME add printers for those MD formats - hexdump for now */
+ case CFM_CCM_MA_FORMAT_8021:
+ default:
+ print_unknown_data(msg_ptr.cfm_ccm->md_name, "\n\t ",
+ msg_ptr.cfm_ccm->md_namelength);
+ }
+ }
+
+
+ /*
+ * Resolve the MA fields.
+ */
+ ma_nameformat = msg_ptr.cfm_ccm->md_name + msg_ptr.cfm_ccm->md_namelength;
+ ma_namelength = msg_ptr.cfm_ccm->md_name + msg_ptr.cfm_ccm->md_namelength + 1;
+ ma_name = msg_ptr.cfm_ccm->md_name + msg_ptr.cfm_ccm->md_namelength + 2;
+
+ printf("\n\t MA Name-Format %s (%u), MA name length %u",
+ tok2str(cfm_ma_nameformat_values, "Unknown",
+ *ma_nameformat),
+ *ma_nameformat,
+ *ma_namelength);
+
+ printf("\n\t MA Name: ");
+ switch (*ma_nameformat) {
+ case CFM_CCM_MA_FORMAT_CHAR:
+ safeputs((const char *)ma_name, *ma_namelength);
+ break;
+
+ /* FIXME add printers for those MA formats - hexdump for now */
+ case CFM_CCM_MA_FORMAT_8021:
+ case CFM_CCM_MA_FORMAT_VID:
+ case CFM_CCM_MA_FORMAT_INT:
+ case CFM_CCM_MA_FORMAT_VPN:
+ default:
+ print_unknown_data(ma_name, "\n\t ", *ma_namelength);
+ }
+ break;
+
+ case CFM_OPCODE_LTM:
+ printf(", Flags [%s]",
+ bittok2str(cfm_ltm_flag_values, "none", cfm_common_header->flags));
+
+ printf("\n\t Transaction-ID 0x%08x, Egress-ID %s, ttl %u",
+ EXTRACT_32BITS(msg_ptr.cfm_ltm->transaction_id),
+ cfm_egress_id_string(msg_ptr.cfm_ltm->egress_id),
+ msg_ptr.cfm_ltm->ttl);
+
+ printf("\n\t Original-MAC %s, Target-MAC %s",
+ etheraddr_string(msg_ptr.cfm_ltm->original_mac),
+ etheraddr_string(msg_ptr.cfm_ltm->target_mac));
+ break;
+
+ case CFM_OPCODE_LTR:
+ printf(", Flags [%s]",
+ bittok2str(cfm_ltr_flag_values, "none", cfm_common_header->flags));
+
+ printf("\n\t Transaction-ID 0x%08x, Last-Egress-ID %s",
+ EXTRACT_32BITS(msg_ptr.cfm_ltr->transaction_id),
+ cfm_egress_id_string(msg_ptr.cfm_ltr->last_egress_id));
+
+ printf("\n\t Next-Egress-ID %s, ttl %u",
+ cfm_egress_id_string(msg_ptr.cfm_ltr->next_egress_id),
+ msg_ptr.cfm_ltr->ttl);
+
+ printf("\n\t Replay-Action %s (%u)",
+ tok2str(cfm_ltr_replay_action_values,
+ "Unknown",
+ msg_ptr.cfm_ltr->replay_action),
+ msg_ptr.cfm_ltr->replay_action);
+ break;
+
+ /*
+ * No message decoder yet.
+ * Hexdump everything up until the start of the TLVs
+ */
+ case CFM_OPCODE_LBR:
+ case CFM_OPCODE_LBM:
+ default:
+ if (tlen > cfm_common_header->first_tlv_offset) {
+ print_unknown_data(tptr, "\n\t ",
+ tlen - cfm_common_header->first_tlv_offset);
+ }
+ break;
+ }
+
+ /*
+ * Sanity check for not walking off.
+ */
+ if (tlen <= cfm_common_header->first_tlv_offset) {
+ return;
+ }
+
+ tptr += cfm_common_header->first_tlv_offset;
+ tlen -= cfm_common_header->first_tlv_offset;
+
+ while (tlen > 0) {
+ cfm_tlv_header = (const struct cfm_tlv_header_t *)tptr;
+
+ /* Enough to read the tlv type ? */
+ TCHECK2(*tptr, 1);
+ cfm_tlv_type=cfm_tlv_header->type;
+
+ if (cfm_tlv_type != CFM_TLV_END) {
+ /* did we capture enough for fully decoding the object header ? */
+ TCHECK2(*tptr, sizeof(struct cfm_tlv_header_t));
+ cfm_tlv_len=EXTRACT_16BITS(&cfm_tlv_header->length);
+ } else {
+ cfm_tlv_len = 0;
+ }
+
+ printf("\n\t%s TLV (0x%02x), length %u",
+ tok2str(cfm_tlv_values, "Unknown", cfm_tlv_type),
+ cfm_tlv_type,
+ cfm_tlv_len);
+
+ /* sanity check for not walking off and infinite loop check. */
+ if ((cfm_tlv_type != CFM_TLV_END) &&
+ ((cfm_tlv_len + sizeof(struct cfm_tlv_header_t) > tlen) ||
+ (!cfm_tlv_len))) {
+ print_unknown_data(tptr,"\n\t ",tlen);
+ return;
+ }
+
+ tptr += sizeof(struct cfm_tlv_header_t);
+ tlen -= sizeof(struct cfm_tlv_header_t);
+ tlv_ptr = tptr;
+
+ /* did we capture enough for fully decoding the object ? */
+ if (cfm_tlv_type != CFM_TLV_END) {
+ TCHECK2(*tptr, cfm_tlv_len);
+ }
+ hexdump = FALSE;
+
+ switch(cfm_tlv_type) {
+ case CFM_TLV_END:
+ /* we are done - bail out */
+ return;
+
+ case CFM_TLV_PORT_STATUS:
+ printf(", Status: %s (%u)",
+ tok2str(cfm_tlv_port_status_values, "Unknown", *tptr),
+ *tptr);
+ break;
+
+ case CFM_TLV_INTERFACE_STATUS:
+ printf(", Status: %s (%u)",
+ tok2str(cfm_tlv_interface_status_values, "Unknown", *tptr),
+ *tptr);
+ break;
+
+ case CFM_TLV_PRIVATE:
+ printf(", Vendor: %s (%u), Sub-Type %u",
+ tok2str(oui_values,"Unknown", EXTRACT_24BITS(tptr)),
+ EXTRACT_24BITS(tptr),
+ *(tptr+3));
+ hexdump = TRUE;
+ break;
+
+ case CFM_TLV_SENDER_ID:
+ {
+ u_int chassis_id_type, chassis_id_length;
+ u_int mgmt_addr_length;
+
+ /*
+ * Check if there is a Chassis-ID.
+ */
+ chassis_id_length = *tptr;
+ if (chassis_id_length > tlen) {
+ hexdump = TRUE;
+ break;
+ }
+
+ tptr++;
+ tlen--;
+
+ if (chassis_id_length) {
+ chassis_id_type = *tptr;
+ printf("\n\t Chassis-ID Type %s (%u), Chassis-ID length %u",
+ tok2str(cfm_tlv_senderid_chassisid_values,
+ "Unknown",
+ chassis_id_type),
+ chassis_id_type,
+ chassis_id_length);
+
+ switch (chassis_id_type) {
+ case CFM_CHASSIS_ID_MAC_ADDRESS:
+ printf("\n\t MAC %s", etheraddr_string(tptr+1));
+ break;
+
+ case CFM_CHASSIS_ID_NETWORK_ADDRESS:
+ hexdump |= cfm_mgmt_addr_print(tptr);
+ break;
+
+ case CFM_CHASSIS_ID_INTERFACE_NAME: /* fall through */
+ case CFM_CHASSIS_ID_INTERFACE_ALIAS:
+ case CFM_CHASSIS_ID_LOCAL:
+ case CFM_CHASSIS_ID_CHASSIS_COMPONENT:
+ case CFM_CHASSIS_ID_PORT_COMPONENT:
+ safeputs((const char *)tptr+1, chassis_id_length);
+ break;
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+ }
+
+ tptr += chassis_id_length;
+ tlen -= chassis_id_length;
+
+ /*
+ * Check if there is a Management Address.
+ */
+ mgmt_addr_length = *tptr;
+ if (mgmt_addr_length > tlen) {
+ hexdump = TRUE;
+ break;
+ }
+
+ tptr++;
+ tlen--;
+
+ if (mgmt_addr_length) {
+ hexdump |= cfm_mgmt_addr_print(tptr);
+ }
+
+ tptr += mgmt_addr_length;
+ tlen -= mgmt_addr_length;
+
+ }
+ break;
+
+ /*
+ * FIXME those are the defined TLVs that lack a decoder
+ * you are welcome to contribute code ;-)
+ */
+
+ case CFM_TLV_DATA:
+ case CFM_TLV_REPLY_INGRESS:
+ case CFM_TLV_REPLY_EGRESS:
+ default:
+ hexdump = TRUE;
+ break;
+ }
+ /* do we want to see an additional hexdump ? */
+ if (hexdump || vflag > 1)
+ print_unknown_data(tlv_ptr, "\n\t ", cfm_tlv_len);
+
+ tptr+=cfm_tlv_len;
+ tlen-=cfm_tlv_len;
+ }
+ return;
+trunc:
+ printf("\n\t\t packet exceeded snapshot");
+}
diff --git a/contrib/tcpdump/print-chdlc.c b/contrib/tcpdump/print-chdlc.c
index b7654f5..238e91a 100644
--- a/contrib/tcpdump/print-chdlc.c
+++ b/contrib/tcpdump/print-chdlc.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-chdlc.c,v 1.32.2.11 2005/11/29 08:57:10 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-chdlc.c,v 1.43 2005-11-29 08:56:19 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-cip.c b/contrib/tcpdump/print-cip.c
index 774b700..e9d672f 100644
--- a/contrib/tcpdump/print-cip.c
+++ b/contrib/tcpdump/print-cip.c
@@ -22,7 +22,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-cip.c,v 1.25.2.1 2005/07/07 01:24:34 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-cip.c,v 1.26 2005-07-07 01:22:17 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-cnfp.c b/contrib/tcpdump/print-cnfp.c
index 9fdfbd4..86d7128 100644
--- a/contrib/tcpdump/print-cnfp.c
+++ b/contrib/tcpdump/print-cnfp.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-cnfp.c,v 1.16.2.1 2005/04/20 20:53:39 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-cnfp.c,v 1.17 2005-04-20 20:53:18 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-dccp.c b/contrib/tcpdump/print-dccp.c
index e6bfca6..b7377cf 100644
--- a/contrib/tcpdump/print-dccp.c
+++ b/contrib/tcpdump/print-dccp.c
@@ -9,7 +9,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-dccp.c,v 1.1.2.6 2006/02/19 05:08:44 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-dccp.c,v 1.7.2.1 2007-11-09 00:45:16 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -60,9 +60,20 @@ static const char *dccp_feature_nums[] = {
"check data checksum",
};
+static inline int dccp_csum_coverage(const struct dccp_hdr* dh, u_int len)
+{
+ u_int cov;
+
+ if (DCCPH_CSCOV(dh) == 0)
+ return len;
+ cov = (dh->dccph_doff + DCCPH_CSCOV(dh) - 1) * sizeof(u_int32_t);
+ return (cov > len)? len : cov;
+}
+
static int dccp_cksum(const struct ip *ip,
const struct dccp_hdr *dh, u_int len)
{
+ int cov = dccp_csum_coverage(dh, len);
union phu {
struct phdr {
u_int32_t src;
@@ -86,15 +97,15 @@ static int dccp_cksum(const struct ip *ip,
phu.ph.dst = ip_finddst(ip);
sp = &phu.pa[0];
- return in_cksum((u_short *)dh, len, sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]);
+ return in_cksum((u_short *)dh, cov, sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]);
}
#ifdef INET6
static int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_int len)
{
size_t i;
- const u_int16_t *sp;
- u_int32_t sum;
+ u_int32_t sum = 0;
+ int cov = dccp_csum_coverage(dh, len);
union {
struct {
struct in6_addr ph_src;
@@ -113,23 +124,10 @@ static int dccp6_cksum(const struct ip6_hdr *ip6, const struct dccp_hdr *dh, u_i
phu.ph.ph_len = htonl(len);
phu.ph.ph_nxt = IPPROTO_DCCP;
- sum = 0;
for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)
sum += phu.pa[i];
- sp = (const u_int16_t *)dh;
-
- for (i = 0; i < (len & ~1); i += 2)
- sum += *sp++;
-
- if (len & 1)
- sum += htons((*(const u_int8_t *)sp) << 8);
-
- while (sum > 0xffff)
- sum = (sum & 0xffff) + (sum >> 16);
- sum = ~sum & 0xffff;
-
- return (sum);
+ return in_cksum((u_short *)dh, cov, sum);
}
#endif
@@ -279,32 +277,21 @@ void dccp_print(const u_char *bp, const u_char *data2, u_int len)
}
/* checksum calculation */
-#ifdef INET6
- if (ip6) {
- if (ip6->ip6_plen && vflag) {
- u_int16_t sum, dccp_sum;
+ if (vflag && TTEST2(bp[0], len)) {
+ u_int16_t sum = 0, dccp_sum;
+ dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);
+ (void)printf("cksum 0x%04x ", dccp_sum);
+ if (IP_V(ip) == 4)
+ sum = dccp_cksum(ip, dh, len);
+#ifdef INET6
+ else if (IP_V(ip) == 6)
sum = dccp6_cksum(ip6, dh, len);
- dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);
- printf("cksum 0x%04x", dccp_sum);
- if (sum != 0) {
- (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum));
- } else
- (void)printf(" (correct), ");
- }
- } else
-#endif /* INET6 */
- if (vflag)
- {
- u_int16_t sum, dccp_sum;
-
- sum = dccp_cksum(ip, dh, len);
- dccp_sum = EXTRACT_16BITS(&dh->dccph_checksum);
- printf("cksum 0x%04x", dccp_sum);
- if (sum != 0) {
- (void)printf(" (incorrect (-> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum));
- } else
- (void)printf(" (correct), ");
+#endif
+ if (sum != 0)
+ (void)printf("(incorrect -> 0x%04x), ",in_cksum_shouldbe(dccp_sum, sum));
+ else
+ (void)printf("(correct), ");
}
switch (DCCPH_TYPE(dh)) {
diff --git a/contrib/tcpdump/print-decnet.c b/contrib/tcpdump/print-decnet.c
index ae7ba5c4..7fea582 100644
--- a/contrib/tcpdump/print-decnet.c
+++ b/contrib/tcpdump/print-decnet.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.38.2.1 2005/05/06 02:16:53 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-decnet.c,v 1.39 2005-05-06 02:16:26 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-dhcp6.c b/contrib/tcpdump/print-dhcp6.c
index 9f4999d..ec0df76 100644
--- a/contrib/tcpdump/print-dhcp6.c
+++ b/contrib/tcpdump/print-dhcp6.c
@@ -40,7 +40,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.35.2.1 2006/10/25 22:04:36 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-dhcp6.c,v 1.36.2.1 2008-02-06 10:26:27 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -80,6 +80,8 @@ static const char rcsid[] _U_ =
#define DH6_INFORM_REQ 11
#define DH6_RELAY_FORW 12
#define DH6_RELAY_REPLY 13
+#define DH6_LEASEQUERY 14
+#define DH6_LQ_REPLY 15
/* DHCP6 base packet format */
struct dhcp6 {
@@ -130,6 +132,10 @@ struct dhcp6_relay {
# define DH6OPT_STCODE_NOTONLINK 4
# define DH6OPT_STCODE_USEMULTICAST 5
# define DH6OPT_STCODE_NOPREFIXAVAIL 6
+# define DH6OPT_STCODE_UNKNOWNQUERYTYPE 7
+# define DH6OPT_STCODE_MALFORMEDQUERY 8
+# define DH6OPT_STCODE_NOTCONFIGURED 9
+# define DH6OPT_STCODE_NOTALLOWED 10
#define DH6OPT_RAPID_COMMIT 14
#define DH6OPT_USER_CLASS 15
#define DH6OPT_VENDOR_CLASS 16
@@ -155,6 +161,15 @@ struct dhcp6_relay {
#define DH6OPT_REMOTE_ID 37
#define DH6OPT_SUBSCRIBER_ID 38
#define DH6OPT_CLIENT_FQDN 39
+#define DH6OPT_PANA_AGENT 40
+#define DH6OPT_NEW_POSIX_TIMEZONE 41
+#define DH6OPT_NEW_TZDB_TIMEZONE 42
+#define DH6OPT_ERO 43
+#define DH6OPT_LQ_QUERY 44
+#define DH6OPT_CLIENT_DATA 45
+#define DH6OPT_CLT_TIME 46
+#define DH6OPT_LQ_RELAY_DATA 47
+#define DH6OPT_LQ_CLIENT_LINK 48
struct dhcp6opt {
u_int16_t dh6opt_type;
@@ -280,6 +295,24 @@ dhcp6opt_name(int type)
return "Subscriber ID";
case DH6OPT_CLIENT_FQDN:
return "Client FQDN";
+ case DH6OPT_PANA_AGENT:
+ return "PANA agent";
+ case DH6OPT_NEW_POSIX_TIMEZONE:
+ return "POSIX timezone";
+ case DH6OPT_NEW_TZDB_TIMEZONE:
+ return "POSIX tz database";
+ case DH6OPT_ERO:
+ return "Echo request option";
+ case DH6OPT_LQ_QUERY:
+ return "Lease query";
+ case DH6OPT_CLIENT_DATA:
+ return "LQ client data";
+ case DH6OPT_CLT_TIME:
+ return "Clt time";
+ case DH6OPT_LQ_RELAY_DATA:
+ return "LQ relay data";
+ case DH6OPT_LQ_CLIENT_LINK:
+ return "LQ client link";
default:
snprintf(genstr, sizeof(genstr), "opt_%d", type);
return(genstr);
@@ -309,6 +342,14 @@ dhcp6stcode(int code)
return "use multicast";
case DH6OPT_STCODE_NOPREFIXAVAIL:
return "no prefixes";
+ case DH6OPT_STCODE_UNKNOWNQUERYTYPE:
+ return "unknown query type";
+ case DH6OPT_STCODE_MALFORMEDQUERY:
+ return "malformed query";
+ case DH6OPT_STCODE_NOTCONFIGURED:
+ return "not configured";
+ case DH6OPT_STCODE_NOTALLOWED:
+ return "not allowed";
default:
snprintf(genstr, sizeof(genstr), "code%d", code);
return(genstr);
@@ -420,6 +461,7 @@ dhcp6opt_print(const u_char *cp, const u_char *ep)
printf(")");
break;
case DH6OPT_ORO:
+ case DH6OPT_ERO:
if (optlen % 2) {
printf(" ?)");
break;
@@ -549,12 +591,15 @@ dhcp6opt_print(const u_char *cp, const u_char *ep)
printf(")");
break;
case DH6OPT_INTERFACE_ID:
+ case DH6OPT_SUBSCRIBER_ID:
/*
* Since we cannot predict the encoding, print hex dump
* at most 10 characters.
*/
+ printf(" ");
for (i = 0; i < optlen && i < 10; i++)
printf("%02x", ((u_char *)(dh6o + 1))[i]);
+ printf("...)");
break;
case DH6OPT_RECONF_MSG:
tp = (u_char *)(dh6o + 1);
@@ -579,6 +624,8 @@ dhcp6opt_print(const u_char *cp, const u_char *ep)
case DH6OPT_NIS_SERVERS:
case DH6OPT_NISP_SERVERS:
case DH6OPT_BCMCS_SERVER_A:
+ case DH6OPT_PANA_AGENT:
+ case DH6OPT_LQ_CLIENT_LINK:
if (optlen % 16) {
printf(" ?)");
break;
@@ -618,6 +665,21 @@ dhcp6opt_print(const u_char *cp, const u_char *ep)
}
printf(")");
break;
+ case DH6OPT_IA_TA:
+ if (optlen < 4) {
+ printf(" ?)");
+ break;
+ }
+ memcpy(&val32, dh6o + 1, sizeof(val32));
+ val32 = ntohl(val32);
+ printf(" IAID:%lu", (unsigned long)val32);
+ if (optlen > 4) {
+ /* there are sub-options */
+ dhcp6opt_print((u_char *)(dh6o + 1) + 4,
+ (u_char *)(dh6o + 1) + optlen);
+ }
+ printf(")");
+ break;
case DH6OPT_IA_PD_PREFIX:
if (optlen < sizeof(ia_prefix) - 4) {
printf(" ?)");
@@ -643,6 +705,7 @@ dhcp6opt_print(const u_char *cp, const u_char *ep)
printf(")");
break;
case DH6OPT_LIFETIME:
+ case DH6OPT_CLT_TIME:
if (optlen != 4) {
printf(" ?)");
break;
@@ -651,6 +714,68 @@ dhcp6opt_print(const u_char *cp, const u_char *ep)
val32 = ntohl(val32);
printf(" %d)", (int)val32);
break;
+ case DH6OPT_REMOTE_ID:
+ if (optlen < 4) {
+ printf(" ?)");
+ break;
+ }
+ tp = (u_char *)(dh6o + 1);
+ memcpy(&val32, &tp[0], sizeof(val32));
+ val32 = ntohl(val32);
+ printf(" %d ", (int)val32);
+ /*
+ * Print hex dump first 10 characters.
+ */
+ for (i = 4; i < optlen && i < 14; i++)
+ printf("%02x", tp[i]);
+ printf("...)");
+ break;
+ case DH6OPT_LQ_QUERY:
+ if (optlen < 17) {
+ printf(" ?)");
+ break;
+ }
+ tp = (u_char *)(dh6o + 1);
+ switch (*tp) {
+ case 1:
+ printf(" by-address");
+ break;
+ case 2:
+ printf(" by-clientID");
+ break;
+ default:
+ printf(" type_%d", (int)*tp);
+ break;
+ }
+ printf(" %s", ip6addr_string(&tp[1]));
+ if (optlen > 17) {
+ /* there are query-options */
+ dhcp6opt_print(tp + 17, tp + optlen);
+ }
+ printf(")");
+ break;
+ case DH6OPT_CLIENT_DATA:
+ if (optlen > 0) {
+ /* there are encapsulated options */
+ dhcp6opt_print((u_char *)(dh6o + 1),
+ (u_char *)(dh6o + 1) + optlen);
+ }
+ printf(")");
+ break;
+ case DH6OPT_LQ_RELAY_DATA:
+ if (optlen < 16) {
+ printf(" ?)");
+ break;
+ }
+ tp = (u_char *)(dh6o + 1);
+ printf(" %s ", ip6addr_string(&tp[0]));
+ /*
+ * Print hex dump first 10 characters.
+ */
+ for (i = 16; i < optlen && i < 26; i++)
+ printf("%02x", tp[i]);
+ printf("...)");
+ break;
default:
printf(")");
break;
@@ -725,6 +850,12 @@ dhcp6_print(const u_char *cp, u_int length)
case DH6_RELAY_REPLY:
name= "relay-reply";
break;
+ case DH6_LEASEQUERY:
+ name= "leasequery";
+ break;
+ case DH6_LQ_REPLY:
+ name= "leasequery-reply";
+ break;
default:
name = NULL;
break;
diff --git a/contrib/tcpdump/print-domain.c b/contrib/tcpdump/print-domain.c
index 827d1be..39abda5 100644
--- a/contrib/tcpdump/print-domain.c
+++ b/contrib/tcpdump/print-domain.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-domain.c,v 1.89.2.8 2007/02/13 19:19:27 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-domain.c,v 1.97.2.1 2007-12-09 01:51:12 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -389,13 +389,22 @@ ns_rprint(register const u_char *cp, register const u_char *bp, int is_mdns)
printf(" (Cache flush)");
}
- /* ignore ttl */
- cp += 2;
- /* if T_OPT, save opt_flags */
- if (typ == T_OPT)
+ if (typ == T_OPT) {
+ /* get opt flags */
+ cp += 2;
opt_flags = EXTRACT_16BITS(cp);
- /* ignore rest of ttl */
- cp += 2;
+ /* ignore rest of ttl field */
+ cp += 2;
+ } else if (vflag > 2) {
+ /* print ttl */
+ printf(" [");
+ relts_print(EXTRACT_32BITS(cp));
+ printf("]");
+ cp += 4;
+ } else {
+ /* ignore ttl */
+ cp += 4;
+ }
len = EXTRACT_16BITS(cp);
cp += 2;
@@ -410,7 +419,7 @@ ns_rprint(register const u_char *cp, register const u_char *bp, int is_mdns)
case T_A:
if (!TTEST2(*cp, sizeof(struct in_addr)))
return(NULL);
- printf(" %s", ipaddr_string(cp));
+ printf(" %s", intoa(htonl(EXTRACT_32BITS(cp))));
break;
case T_NS:
@@ -477,15 +486,24 @@ ns_rprint(register const u_char *cp, register const u_char *bp, int is_mdns)
#ifdef INET6
case T_AAAA:
+ {
+ struct in6_addr addr;
+ char ntop_buf[INET6_ADDRSTRLEN];
+
if (!TTEST2(*cp, sizeof(struct in6_addr)))
return(NULL);
- printf(" %s", ip6addr_string(cp));
+ memcpy(&addr, cp, sizeof(struct in6_addr));
+ printf(" %s",
+ inet_ntop(AF_INET6, &addr, ntop_buf, sizeof(ntop_buf)));
+
break;
+ }
case T_A6:
{
struct in6_addr a;
int pbit, pbyte;
+ char ntop_buf[INET6_ADDRSTRLEN];
if (!TTEST2(*cp, 1))
return(NULL);
@@ -499,7 +517,8 @@ ns_rprint(register const u_char *cp, register const u_char *bp, int is_mdns)
return(NULL);
memset(&a, 0, sizeof(a));
memcpy(&a.s6_addr[pbyte], cp + 1, sizeof(a) - pbyte);
- printf(" %u %s", pbit, ip6addr_string(&a));
+ printf(" %u %s", pbit,
+ inet_ntop(AF_INET6, &a, ntop_buf, sizeof(ntop_buf)));
}
if (pbit > 0) {
putchar(' ');
diff --git a/contrib/tcpdump/print-dtp.c b/contrib/tcpdump/print-dtp.c
new file mode 100644
index 0000000..c358a89
--- /dev/null
+++ b/contrib/tcpdump/print-dtp.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1998-2007 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * Dynamic Trunk Protocol (DTP)
+ *
+ * Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"
+#include "nlpid.h"
+
+#define DTP_HEADER_LEN 1
+#define DTP_DOMAIN_TLV 0x0001
+#define DTP_STATUS_TLV 0x0002
+#define DTP_DTP_TYPE_TLV 0x0003
+#define DTP_NEIGHBOR_TLV 0x0004
+
+static struct tok dtp_tlv_values[] = {
+ { DTP_DOMAIN_TLV, "Domain TLV"},
+ { DTP_STATUS_TLV, "Status TLV"},
+ { DTP_DTP_TYPE_TLV, "DTP type TLV"},
+ { DTP_NEIGHBOR_TLV, "Neighbor TLV"},
+ { 0, NULL}
+};
+
+void
+dtp_print (const u_char *pptr, u_int length)
+{
+ int type, len;
+ const u_char *tptr;
+
+ if (length < DTP_HEADER_LEN)
+ goto trunc;
+
+ tptr = pptr;
+
+ if (!TTEST2(*tptr, DTP_HEADER_LEN))
+ goto trunc;
+
+ printf("DTPv%u, length %u",
+ (*tptr),
+ length);
+
+ /*
+ * In non-verbose mode, just print version.
+ */
+ if (vflag < 1) {
+ return;
+ }
+
+ tptr += DTP_HEADER_LEN;
+
+ while (tptr < (pptr+length)) {
+
+ if (!TTEST2(*tptr, 4))
+ goto trunc;
+
+ type = EXTRACT_16BITS(tptr);
+ len = EXTRACT_16BITS(tptr+2);
+
+ /* infinite loop check */
+ if (type == 0 || len == 0) {
+ return;
+ }
+
+ printf("\n\t%s (0x%04x) TLV, length %u",
+ tok2str(dtp_tlv_values, "Unknown", type),
+ type, len);
+
+ switch (type) {
+ case DTP_DOMAIN_TLV:
+ printf(", %s", tptr+4);
+ break;
+
+ case DTP_STATUS_TLV:
+ case DTP_DTP_TYPE_TLV:
+ printf(", 0x%x", *(tptr+4));
+ break;
+
+ case DTP_NEIGHBOR_TLV:
+ printf(", %s", etheraddr_string(tptr+4));
+ break;
+
+ default:
+ break;
+ }
+ tptr += len;
+ }
+
+ return;
+
+ trunc:
+ printf("[|dtp]");
+}
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/contrib/tcpdump/print-dvmrp.c b/contrib/tcpdump/print-dvmrp.c
index 2c159bf..437e716 100644
--- a/contrib/tcpdump/print-dvmrp.c
+++ b/contrib/tcpdump/print-dvmrp.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-dvmrp.c,v 1.27 2003/11/19 09:42:04 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-dvmrp.c,v 1.27 2003-11-19 09:42:04 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-eap.c b/contrib/tcpdump/print-eap.c
index fb39e76..9fb333a 100644
--- a/contrib/tcpdump/print-eap.c
+++ b/contrib/tcpdump/print-eap.c
@@ -17,12 +17,13 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * Format and print bootp packets.
+ * Format and print EAP packets.
+ *
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-eap.c,v 1.3 2004/04/23 19:03:39 mcr Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-eap.c,v 1.5 2007-10-04 16:41:33 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -35,37 +36,272 @@ static const char rcsid[] _U_ =
#include <string.h>
#include "netdissect.h"
+#include "interface.h"
#include "addrtoname.h"
#include "extract.h"
#include "ether.h"
+#define EAP_FRAME_TYPE_PACKET 0
+#define EAP_FRAME_TYPE_START 1
+#define EAP_FRAME_TYPE_LOGOFF 2
+#define EAP_FRAME_TYPE_KEY 3
+#define EAP_FRAME_TYPE_ENCAP_ASF_ALERT 4
+
+struct eap_frame_t {
+ unsigned char version;
+ unsigned char type;
+ unsigned char length[2];
+};
+
+static const struct tok eap_frame_type_values[] = {
+ { EAP_FRAME_TYPE_PACKET, "EAP packet" },
+ { EAP_FRAME_TYPE_START, "EAPOL start" },
+ { EAP_FRAME_TYPE_LOGOFF, "EAPOL logoff" },
+ { EAP_FRAME_TYPE_KEY, "EAPOL key" },
+ { EAP_FRAME_TYPE_ENCAP_ASF_ALERT, "Encapsulated ASF alert" },
+ { 0, NULL}
+};
+
+/* RFC 3748 */
struct eap_packet_t {
- unsigned char code;
- unsigned char id;
- unsigned char length[2];
- unsigned char data[1];
+ unsigned char code;
+ unsigned char id;
+ unsigned char length[2];
+};
+
+#define EAP_REQUEST 1
+#define EAP_RESPONSE 2
+#define EAP_SUCCESS 3
+#define EAP_FAILURE 4
+
+static const struct tok eap_code_values[] = {
+ { EAP_REQUEST, "Request" },
+ { EAP_RESPONSE, "Response" },
+ { EAP_SUCCESS, "Success" },
+ { EAP_FAILURE, "Failure" },
+ { 0, NULL}
+};
+
+#define EAP_TYPE_NO_PROPOSED 0
+#define EAP_TYPE_IDENTITY 1
+#define EAP_TYPE_NOTIFICATION 2
+#define EAP_TYPE_NAK 3
+#define EAP_TYPE_MD5_CHALLENGE 4
+#define EAP_TYPE_OTP 5
+#define EAP_TYPE_GTC 6
+#define EAP_TYPE_TLS 13 /* RFC 2716 */
+#define EAP_TYPE_SIM 18 /* RFC 4186 */
+#define EAP_TYPE_TTLS 21 /* draft-funk-eap-ttls-v0-01.txt */
+#define EAP_TYPE_AKA 23 /* RFC 4187 */
+#define EAP_TYPE_FAST 43 /* RFC 4851 */
+#define EAP_TYPE_EXPANDED_TYPES 254
+#define EAP_TYPE_EXPERIMENTAL 255
+
+static const struct tok eap_type_values[] = {
+ { EAP_TYPE_NO_PROPOSED, "No proposed" },
+ { EAP_TYPE_IDENTITY, "Identity" },
+ { EAP_TYPE_NOTIFICATION, "Notification" },
+ { EAP_TYPE_NAK, "Nak" },
+ { EAP_TYPE_MD5_CHALLENGE, "MD5-challenge" },
+ { EAP_TYPE_OTP, "OTP" },
+ { EAP_TYPE_GTC, "GTC" },
+ { EAP_TYPE_TLS, "TLS" },
+ { EAP_TYPE_SIM, "SIM" },
+ { EAP_TYPE_TTLS, "TTLS" },
+ { EAP_TYPE_AKA, "AKA" },
+ { EAP_TYPE_FAST, "FAST" },
+ { EAP_TYPE_EXPANDED_TYPES, "Expanded types" },
+ { EAP_TYPE_EXPERIMENTAL, "Experimental" },
+ { 0, NULL}
+};
+
+#define EAP_TLS_EXTRACT_BIT_L(x) (((x)&0x80)>>7)
+
+/* RFC 2716 - EAP TLS bits */
+#define EAP_TLS_FLAGS_LEN_INCLUDED (1 << 7)
+#define EAP_TLS_FLAGS_MORE_FRAGMENTS (1 << 6)
+#define EAP_TLS_FLAGS_START (1 << 5)
+
+static const struct tok eap_tls_flags_values[] = {
+ { EAP_TLS_FLAGS_LEN_INCLUDED, "L bit" },
+ { EAP_TLS_FLAGS_MORE_FRAGMENTS, "More fragments bit"},
+ { EAP_TLS_FLAGS_START, "Start bit"},
+ { 0, NULL}
+};
+
+#define EAP_TTLS_VERSION(x) ((x)&0x07)
+
+/* EAP-AKA and EAP-SIM - RFC 4187 */
+#define EAP_AKA_CHALLENGE 1
+#define EAP_AKA_AUTH_REJECT 2
+#define EAP_AKA_SYNC_FAILURE 4
+#define EAP_AKA_IDENTITY 5
+#define EAP_SIM_START 10
+#define EAP_SIM_CHALLENGE 11
+#define EAP_AKA_NOTIFICATION 12
+#define EAP_AKA_REAUTH 13
+#define EAP_AKA_CLIENT_ERROR 14
+
+static const struct tok eap_aka_subtype_values[] = {
+ { EAP_AKA_CHALLENGE, "Challenge" },
+ { EAP_AKA_AUTH_REJECT, "Auth reject" },
+ { EAP_AKA_SYNC_FAILURE, "Sync failure" },
+ { EAP_AKA_IDENTITY, "Identity" },
+ { EAP_SIM_START, "Start" },
+ { EAP_SIM_CHALLENGE, "Challenge" },
+ { EAP_AKA_NOTIFICATION, "Notification" },
+ { EAP_AKA_REAUTH, "Reauth" },
+ { EAP_AKA_CLIENT_ERROR, "Client error" },
+ { 0, NULL}
};
/*
- * Print bootp requests
+ * Print EAP requests / responses
*/
void
-eap_print(netdissect_options *ndo,
- register const u_char *cp,
- u_int length _U_)
+eap_print(netdissect_options *ndo _U_,
+ register const u_char *cp,
+ u_int length _U_)
{
- const struct eap_packet_t *eap;
+ const struct eap_frame_t *eap;
+ const u_char *tptr;
+ u_int tlen, type, subtype;
+ int count=0, len;
+
+ tptr = cp;
+ tlen = length;
+ eap = (const struct eap_frame_t *)cp;
+ TCHECK(*eap);
+
+ /* in non-verbose mode just lets print the basic info */
+ if (vflag < 1) {
+ printf("%s (%u) v%u, len %u",
+ tok2str(eap_frame_type_values, "unknown", eap->type),
+ eap->type,
+ eap->version,
+ EXTRACT_16BITS(eap->length));
+ return;
+ }
+
+ printf("%s (%u) v%u, len %u",
+ tok2str(eap_frame_type_values, "unknown", eap->type),
+ eap->type,
+ eap->version,
+ EXTRACT_16BITS(eap->length));
+
+ tptr += sizeof(const struct eap_frame_t);
+ tlen -= sizeof(const struct eap_frame_t);
+
+ switch (eap->type) {
+ case EAP_FRAME_TYPE_PACKET:
+ type = *(tptr);
+ len = EXTRACT_16BITS(tptr+2);
+ printf(", %s (%u), id %u, len %u",
+ tok2str(eap_code_values, "unknown", type),
+ type,
+ *(tptr+1),
+ len);
+
+ if (!TTEST2(*tptr, len))
+ goto trunc;
+
+ if (type <= 2) { /* For EAP_REQUEST and EAP_RESPONSE only */
+ subtype = *(tptr+4);
+ printf("\n\t\t Type %s (%u)",
+ tok2str(eap_type_values, "unknown", *(tptr+4)),
+ *(tptr+4));
+
+ switch (subtype) {
+ case EAP_TYPE_IDENTITY:
+ if (len - 5 > 0) {
+ printf(", Identity: ");
+ safeputs((const char *)tptr+5, len-5);
+ }
+ break;
+
+ case EAP_TYPE_NOTIFICATION:
+ if (len - 5 > 0) {
+ printf(", Notification: ");
+ safeputs((const char *)tptr+5, len-5);
+ }
+ break;
+
+ case EAP_TYPE_NAK:
+ count = 5;
- eap = (const struct eap_packet_t *)cp;
- ND_TCHECK(eap->data);
+ /*
+ * one or more octets indicating
+ * the desired authentication
+ * type one octet per type
+ */
+ while (count < len) {
+ printf(" %s (%u),",
+ tok2str(eap_type_values, "unknown", *(tptr+count)),
+ *(tptr+count));
+ count++;
+ }
+ break;
- ND_PRINT((ndo, "EAP code=%u id=%u length=%u ",
- eap->code, eap->id, (eap->length[0]<<8) + eap->length[1]));
+ case EAP_TYPE_TTLS:
+ printf(" TTLSv%u",
+ EAP_TTLS_VERSION(*(tptr+5))); /* fall through */
+ case EAP_TYPE_TLS:
+ printf(" flags [%s] 0x%02x,",
+ bittok2str(eap_tls_flags_values, "none", *(tptr+5)),
+ *(tptr+5));
- if (!ndo->ndo_vflag)
- return;
+ if (EAP_TLS_EXTRACT_BIT_L(*(tptr+5))) {
+ printf(" len %u", EXTRACT_32BITS(tptr+6));
+ }
+ break;
-trunc:
- ;
+ case EAP_TYPE_FAST:
+ printf(" FASTv%u",
+ EAP_TTLS_VERSION(*(tptr+5)));
+ printf(" flags [%s] 0x%02x,",
+ bittok2str(eap_tls_flags_values, "none", *(tptr+5)),
+ *(tptr+5));
+
+ if (EAP_TLS_EXTRACT_BIT_L(*(tptr+5))) {
+ printf(" len %u", EXTRACT_32BITS(tptr+6));
+ }
+
+ /* FIXME - TLV attributes follow */
+ break;
+
+ case EAP_TYPE_AKA:
+ case EAP_TYPE_SIM:
+ printf(" subtype [%s] 0x%02x,",
+ tok2str(eap_aka_subtype_values, "unknown", *(tptr+5)),
+ *(tptr+5));
+
+ /* FIXME - TLV attributes follow */
+ break;
+
+ case EAP_TYPE_MD5_CHALLENGE:
+ case EAP_TYPE_OTP:
+ case EAP_TYPE_GTC:
+ case EAP_TYPE_EXPANDED_TYPES:
+ case EAP_TYPE_EXPERIMENTAL:
+ default:
+ break;
+ }
+ }
+ break;
+
+ case EAP_FRAME_TYPE_LOGOFF:
+ case EAP_FRAME_TYPE_ENCAP_ASF_ALERT:
+ default:
+ break;
+ }
+ return;
+
+ trunc:
+ printf("\n\t[|EAP]");
}
+/*
+ * Local Variables:
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/contrib/tcpdump/print-egp.c b/contrib/tcpdump/print-egp.c
index e5a811d..4a1d046 100644
--- a/contrib/tcpdump/print-egp.c
+++ b/contrib/tcpdump/print-egp.c
@@ -20,7 +20,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-egp.c,v 1.37 2005/01/12 11:19:09 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-egp.c,v 1.38 2006-02-11 22:13:24 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -226,13 +226,23 @@ egp_print(register const u_int8_t *bp, register u_int length)
printf("[|egp]");
return;
}
- (void)printf("egp: ");
+
+ if (!vflag) {
+ printf("EGPv%u, AS %u, seq %u, length %u",
+ egp->egp_version,
+ EXTRACT_16BITS(&egp->egp_as),
+ EXTRACT_16BITS(&egp->egp_sequence),
+ length);
+ return;
+ } else
+ printf("EGPv%u, length %u",
+ egp->egp_version,
+ length);
if (egp->egp_version != EGP_VERSION) {
printf("[version %d]", egp->egp_version);
return;
}
- printf("as:%d seq:%d", EXTRACT_16BITS(&egp->egp_as), EXTRACT_16BITS(&egp->egp_sequence));
type = egp->egp_type;
code = egp->egp_code;
diff --git a/contrib/tcpdump/print-eigrp.c b/contrib/tcpdump/print-eigrp.c
index 3168b3c..2787baf 100644
--- a/contrib/tcpdump/print-eigrp.c
+++ b/contrib/tcpdump/print-eigrp.c
@@ -16,7 +16,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-eigrp.c,v 1.5.2.2 2005/05/06 02:53:41 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-eigrp.c,v 1.7 2005-05-06 02:53:26 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-enc.c b/contrib/tcpdump/print-enc.c
index f9b871b..9876d6d 100644
--- a/contrib/tcpdump/print-enc.c
+++ b/contrib/tcpdump/print-enc.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-enc.c,v 1.4 2005/04/06 21:32:39 mcr Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-enc.c,v 1.4.4.1 2008-02-06 10:34:15 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -70,8 +70,19 @@ enc_if_print(const struct pcap_pkthdr *h, register const u_char *p)
printf("SPI 0x%08x: ", (u_int32_t)ntohl(hdr->spi));
length -= ENC_HDRLEN;
- /* XXX - use the address family */
- ip_print(gndo, p + ENC_HDRLEN, length);
+ caplen -= ENC_HDRLEN;
+ p += ENC_HDRLEN;
+
+ switch (hdr->af) {
+ case AF_INET:
+ ip_print(gndo, p, length);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ip6_print(p, length);
+ break;
+#endif
+ }
out:
return (ENC_HDRLEN);
diff --git a/contrib/tcpdump/print-esp.c b/contrib/tcpdump/print-esp.c
index 3ccc899..260fe87 100644
--- a/contrib/tcpdump/print-esp.c
+++ b/contrib/tcpdump/print-esp.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.55.2.1 2005/04/21 06:44:57 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.56 2005-04-21 06:44:40 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-ether.c b/contrib/tcpdump/print-ether.c
index d8911d3..0fbdf3b 100644
--- a/contrib/tcpdump/print-ether.c
+++ b/contrib/tcpdump/print-ether.c
@@ -22,7 +22,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ether.c,v 1.95.2.6 2006/02/20 18:15:03 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ether.c,v 1.105.2.1 2008-02-06 10:49:22 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -67,14 +67,19 @@ const struct tok ethertype_values[] = {
{ ETHERTYPE_AARP, "Appletalk ARP" },
{ ETHERTYPE_IPX, "IPX" },
{ ETHERTYPE_PPP, "PPP" },
+ { ETHERTYPE_MPCP, "MPCP" },
{ ETHERTYPE_SLOW, "Slow Protocols" },
{ ETHERTYPE_PPPOED, "PPPoE D" },
{ ETHERTYPE_PPPOES, "PPPoE S" },
{ ETHERTYPE_EAPOL, "EAPOL" },
+ { ETHERTYPE_RRCP, "RRCP" },
{ ETHERTYPE_JUMBO, "Jumbo" },
{ ETHERTYPE_LOOPBACK, "Loopback" },
{ ETHERTYPE_ISO, "OSI" },
{ ETHERTYPE_GRE_ISO, "GRE-OSI" },
+ { ETHERTYPE_CFM_OLD, "CFM (old)" },
+ { ETHERTYPE_CFM, "CFM" },
+ { ETHERTYPE_LLDP, "LLDP" },
{ 0, NULL}
};
@@ -295,6 +300,10 @@ ether_encap_print(u_short ether_type, const u_char *p,
eap_print(gndo, p, length);
return (1);
+ case ETHERTYPE_RRCP:
+ rrcp_print(gndo, p - 14 , length + 14);
+ return (1);
+
case ETHERTYPE_PPP:
if (length) {
printf(": ");
@@ -302,10 +311,23 @@ ether_encap_print(u_short ether_type, const u_char *p,
}
return (1);
+ case ETHERTYPE_MPCP:
+ mpcp_print(p, length);
+ return (1);
+
case ETHERTYPE_SLOW:
slow_print(p, length);
return (1);
+ case ETHERTYPE_CFM:
+ case ETHERTYPE_CFM_OLD:
+ cfm_print(p, length);
+ return (1);
+
+ case ETHERTYPE_LLDP:
+ lldp_print(p, length);
+ return (1);
+
case ETHERTYPE_LOOPBACK:
return (1);
diff --git a/contrib/tcpdump/print-fddi.c b/contrib/tcpdump/print-fddi.c
index 49e2b00..94e9be7 100644
--- a/contrib/tcpdump/print-fddi.c
+++ b/contrib/tcpdump/print-fddi.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-fddi.c,v 1.64.2.2 2005/11/13 12:12:59 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-fddi.c,v 1.66 2005-11-13 12:12:41 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-fr.c b/contrib/tcpdump/print-fr.c
index abc3cd7..d0956f6 100644
--- a/contrib/tcpdump/print-fr.c
+++ b/contrib/tcpdump/print-fr.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#)$Header: /tcpdump/master/tcpdump/print-fr.c,v 1.32.2.15 2006/02/01 14:39:56 hannes Exp $ (LBL)";
+ "@(#)$Header: /tcpdump/master/tcpdump/print-fr.c,v 1.51 2006-06-23 22:20:32 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -102,7 +102,7 @@ struct tok frf_flag_values[] = {
/* Finds out Q.922 address length, DLCI and flags. Returns 0 on success
* save the flags dep. on address length
*/
-static int parse_q922_addr(const u_char *p, u_int *dlci, u_int *sdlcore,
+static int parse_q922_addr(const u_char *p, u_int *dlci,
u_int *addr_len, u_int8_t *flags)
{
if ((p[0] & FR_EA_BIT))
@@ -132,14 +132,26 @@ static int parse_q922_addr(const u_char *p, u_int *dlci, u_int *sdlcore,
flags[3] = p[0] & 0x02;
- if (p[0] & 0x02)
- *sdlcore = p[0] >> 2;
- else
- *dlci = (*dlci << 6) | (p[0] >> 2);
+ *dlci = (*dlci << 6) | (p[0] >> 2);
return 0;
}
+char *q922_string(const u_char *p) {
+
+ static u_int dlci, addr_len;
+ static u_int8_t flags[4];
+ static char buffer[sizeof("DLCI xxxxxxxxxx")];
+ memset(buffer, 0, sizeof(buffer));
+
+ if (parse_q922_addr(p, &dlci, &addr_len, flags) == 0){
+ snprintf(buffer, sizeof(buffer), "DLCI %u", dlci);
+ }
+
+ return buffer;
+}
+
+
/* Frame Relay packet structure, with flags and CRC removed
+---------------------------+
@@ -224,13 +236,12 @@ fr_print(register const u_char *p, u_int length)
{
u_int16_t extracted_ethertype;
u_int dlci;
- u_int sdlcore;
u_int addr_len;
u_int16_t nlpid;
u_int hdr_len;
u_int8_t flags[4];
- if (parse_q922_addr(p, &dlci, &sdlcore, &addr_len, flags)) {
+ if (parse_q922_addr(p, &dlci, &addr_len, flags)) {
printf("Q.922, invalid address");
return 0;
}
@@ -732,25 +743,29 @@ q933_print(const u_char *p, u_int length)
codeset = p[2]&0x0f; /* extract the codeset */
- if (p[2] == MSG_ANSI_LOCKING_SHIFT)
- is_ansi = 1;
+ if (p[2] == MSG_ANSI_LOCKING_SHIFT) {
+ is_ansi = 1;
+ }
printf("%s", eflag ? "" : "Q.933, ");
/* printing out header part */
printf("%s, codeset %u", is_ansi ? "ANSI" : "CCITT", codeset);
- if (p[0])
- printf(", Call Ref: 0x%02x", p[0]);
-
- if (vflag)
- printf(", %s (0x%02x), length %u",
- tok2str(fr_q933_msg_values,"unknown message",p[1]),
- p[1],
- length);
- else
- printf(", %s",
- tok2str(fr_q933_msg_values,"unknown message 0x%02x",p[1]));
+ if (p[0]) {
+ printf(", Call Ref: 0x%02x", p[0]);
+ }
+ if (vflag) {
+ printf(", %s (0x%02x), length %u",
+ tok2str(fr_q933_msg_values,
+ "unknown message", p[1]),
+ p[1],
+ length);
+ } else {
+ printf(", %s",
+ tok2str(fr_q933_msg_values,
+ "unknown message 0x%02x", p[1]));
+ }
olen = length; /* preserve the original length for non verbose mode */
@@ -758,49 +773,57 @@ q933_print(const u_char *p, u_int length)
printf("[|q.933]");
return;
}
- length -= 2 - is_ansi;
+ length -= 2 + is_ansi;
ptemp += 2 + is_ansi;
/* Loop through the rest of IE */
- while (length > sizeof(struct ie_tlv_header_t )) {
+ while (length > sizeof(struct ie_tlv_header_t)) {
ie_p = (struct ie_tlv_header_t *)ptemp;
- if (length < sizeof(struct ie_tlv_header_t ) ||
- length < sizeof(struct ie_tlv_header_t ) + ie_p->ie_len) {
- if (vflag) /* not bark if there is just a trailer */
+ if (length < sizeof(struct ie_tlv_header_t) ||
+ length < sizeof(struct ie_tlv_header_t) + ie_p->ie_len) {
+ if (vflag) { /* not bark if there is just a trailer */
printf("\n[|q.933]");
- else
+ } else {
printf(", length %u",olen);
+ }
return;
}
/* lets do the full IE parsing only in verbose mode
* however some IEs (DLCI Status, Link Verify)
- * are also intereststing in non-verbose mode */
- if (vflag)
+ * are also interestting in non-verbose mode */
+ if (vflag) {
printf("\n\t%s IE (0x%02x), length %u: ",
- tok2str(fr_q933_ie_codesets[codeset],"unknown",ie_p->ie_type),
+ tok2str(fr_q933_ie_codesets[codeset],
+ "unknown", ie_p->ie_type),
ie_p->ie_type,
ie_p->ie_len);
-
+ }
+
/* sanity check */
- if (ie_p->ie_type == 0 || ie_p->ie_len == 0)
+ if (ie_p->ie_type == 0 || ie_p->ie_len == 0) {
return;
+ }
- if (fr_q933_print_ie_codeset[codeset] != NULL)
+ if (fr_q933_print_ie_codeset[codeset] != NULL) {
ie_is_known = fr_q933_print_ie_codeset[codeset](ie_p, ptemp);
-
- if (vflag >= 1 && !ie_is_known)
+ }
+
+ if (vflag >= 1 && !ie_is_known) {
print_unknown_data(ptemp+2,"\n\t",ie_p->ie_len);
+ }
/* do we want to see a hexdump of the IE ? */
- if (vflag> 1 && ie_is_known)
+ if (vflag> 1 && ie_is_known) {
print_unknown_data(ptemp+2,"\n\t ",ie_p->ie_len);
+ }
length = length - ie_p->ie_len - 2;
ptemp = ptemp + ie_p->ie_len + 2;
}
- if (!vflag)
+ if (!vflag) {
printf(", length %u",olen);
+ }
}
static int
@@ -812,24 +835,27 @@ fr_q933_print_ie_codeset5(const struct ie_tlv_header_t *ie_p, const u_char *p)
case FR_LMI_ANSI_REPORT_TYPE_IE: /* fall through */
case FR_LMI_CCITT_REPORT_TYPE_IE:
- if (vflag)
+ if (vflag) {
printf("%s (%u)",
tok2str(fr_lmi_report_type_ie_values,"unknown",p[2]),
p[2]);
+ }
return 1;
case FR_LMI_ANSI_LINK_VERIFY_IE: /* fall through */
case FR_LMI_CCITT_LINK_VERIFY_IE:
case FR_LMI_ANSI_LINK_VERIFY_IE_91:
- if (!vflag)
+ if (!vflag) {
printf(", ");
+ }
printf("TX Seq: %3d, RX Seq: %3d", p[2], p[3]);
return 1;
case FR_LMI_ANSI_PVC_STATUS_IE: /* fall through */
case FR_LMI_CCITT_PVC_STATUS_IE:
- if (!vflag)
+ if (!vflag) {
printf(", ");
+ }
/* now parse the DLCI information element. */
if ((ie_p->ie_len < 3) ||
(p[2] & 0x80) ||
@@ -838,14 +864,17 @@ fr_q933_print_ie_codeset5(const struct ie_tlv_header_t *ie_p, const u_char *p)
((ie_p->ie_len == 5) && ((p[3] & 0x80) || (p[4] & 0x80) ||
!(p[5] & 0x80))) ||
(ie_p->ie_len > 5) ||
- !(p[ie_p->ie_len + 1] & 0x80))
+ !(p[ie_p->ie_len + 1] & 0x80)) {
printf("Invalid DLCI IE");
+ }
dlci = ((p[2] & 0x3F) << 4) | ((p[3] & 0x78) >> 3);
- if (ie_p->ie_len == 4)
+ if (ie_p->ie_len == 4) {
dlci = (dlci << 6) | ((p[4] & 0x7E) >> 1);
- else if (ie_p->ie_len == 5)
+ }
+ else if (ie_p->ie_len == 5) {
dlci = (dlci << 13) | (p[4] & 0x7F) | ((p[5] & 0x7E) >> 1);
+ }
printf("DLCI %u: status %s%s", dlci,
p[ie_p->ie_len + 1] & 0x8 ? "New, " : "",
diff --git a/contrib/tcpdump/print-frag6.c b/contrib/tcpdump/print-frag6.c
index 2c7788b..e125bd3 100644
--- a/contrib/tcpdump/print-frag6.c
+++ b/contrib/tcpdump/print-frag6.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-frag6.c,v 1.19.2.1 2005/04/20 22:33:21 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-frag6.c,v 1.20 2005-04-20 22:33:06 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-gre.c b/contrib/tcpdump/print-gre.c
index d739356..55f0e9d 100644
--- a/contrib/tcpdump/print-gre.c
+++ b/contrib/tcpdump/print-gre.c
@@ -38,7 +38,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.28 2005/04/06 21:32:39 mcr Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-gre.c,v 1.28 2005-04-06 21:32:39 mcr Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-hsrp.c b/contrib/tcpdump/print-hsrp.c
index 1d22247..06304fd 100644
--- a/contrib/tcpdump/print-hsrp.c
+++ b/contrib/tcpdump/print-hsrp.c
@@ -31,7 +31,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-hsrp.c,v 1.9.2.1 2005/05/06 07:57:17 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-hsrp.c,v 1.10 2005-05-06 07:56:52 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-icmp.c b/contrib/tcpdump/print-icmp.c
index 09a7a89..811d599 100644
--- a/contrib/tcpdump/print-icmp.c
+++ b/contrib/tcpdump/print-icmp.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-icmp.c,v 1.81.2.6 2007/09/13 17:40:18 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-icmp.c,v 1.87 2007-09-13 17:42:31 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -414,7 +414,7 @@ icmp_print(const u_char *bp, u_int plen, const u_char *bp2, int fragmented)
case ICMP_UNREACH_NEEDFRAG:
{
register const struct mtu_discovery *mp;
- mp = (struct mtu_discovery *)&dp->icmp_void;
+ mp = (struct mtu_discovery *)(u_char *)&dp->icmp_void;
mtu = EXTRACT_16BITS(&mp->nexthopmtu);
if (mtu) {
(void)snprintf(buf, sizeof(buf),
diff --git a/contrib/tcpdump/print-icmp6.c b/contrib/tcpdump/print-icmp6.c
index c503924..41d56b6 100644
--- a/contrib/tcpdump/print-icmp6.c
+++ b/contrib/tcpdump/print-icmp6.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.79.2.6 2005/09/05 09:29:28 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-icmp6.c,v 1.85.2.1 2008-02-05 19:36:58 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -1192,9 +1192,9 @@ icmp6_rrenum_print(const u_char *bp, const u_char *ep)
F(ICMP6_RR_FLAGS_PREVDONE, "P"));
}
printf("seg=%u,", rr6->rr_segnum);
- printf("maxdelay=%u", rr6->rr_maxdelay);
+ printf("maxdelay=%u", EXTRACT_16BITS(&rr6->rr_maxdelay));
if (rr6->rr_reserved)
- printf("rsvd=0x%x", EXTRACT_16BITS(&rr6->rr_reserved));
+ printf("rsvd=0x%x", EXTRACT_32BITS(&rr6->rr_reserved));
/*[*/
printf("]");
#undef F
diff --git a/contrib/tcpdump/print-igmp.c b/contrib/tcpdump/print-igmp.c
index c310d55..a848562 100644
--- a/contrib/tcpdump/print-igmp.c
+++ b/contrib/tcpdump/print-igmp.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-igmp.c,v 1.15 2004/03/24 00:59:16 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-igmp.c,v 1.15 2004-03-24 00:59:16 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-igrp.c b/contrib/tcpdump/print-igrp.c
index 898471d..3cede7e 100644
--- a/contrib/tcpdump/print-igrp.c
+++ b/contrib/tcpdump/print-igrp.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-igrp.c,v 1.20.2.1 2005/04/20 21:02:15 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-igrp.c,v 1.21 2005-04-20 21:01:56 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-ip.c b/contrib/tcpdump/print-ip.c
index 48d54dd..6563d53 100644
--- a/contrib/tcpdump/print-ip.c
+++ b/contrib/tcpdump/print-ip.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.149.2.9 2007/09/14 01:30:02 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ip.c,v 1.159 2007-09-14 01:29:28 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -668,7 +668,7 @@ ip_print(netdissect_options *ndo,
}
}
- printf(") ");
+ printf(")\n ");
}
/*
diff --git a/contrib/tcpdump/print-ip6.c b/contrib/tcpdump/print-ip6.c
index 4928734..1793974 100644
--- a/contrib/tcpdump/print-ip6.c
+++ b/contrib/tcpdump/print-ip6.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ip6.c,v 1.47.2.5 2007/09/21 07:07:52 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ip6.c,v 1.52 2007-09-21 07:05:33 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-ip6opts.c b/contrib/tcpdump/print-ip6opts.c
index 82163a2..7a4bf55 100644
--- a/contrib/tcpdump/print-ip6opts.c
+++ b/contrib/tcpdump/print-ip6opts.c
@@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ip6opts.c,v 1.17.2.1 2005/04/20 22:19:06 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ip6opts.c,v 1.18 2005-04-20 22:18:50 guy Exp $";
#endif
#ifdef INET6
diff --git a/contrib/tcpdump/print-ipcomp.c b/contrib/tcpdump/print-ipcomp.c
index 099e5ad..89130a3 100644
--- a/contrib/tcpdump/print-ipcomp.c
+++ b/contrib/tcpdump/print-ipcomp.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ipcomp.c,v 1.20 2003/11/19 00:36:08 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ipcomp.c,v 1.20 2003-11-19 00:36:08 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-ipfc.c b/contrib/tcpdump/print-ipfc.c
index 6712e5f..c980765 100644
--- a/contrib/tcpdump/print-ipfc.c
+++ b/contrib/tcpdump/print-ipfc.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ipfc.c,v 1.7.2.2 2005/11/13 12:12:59 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ipfc.c,v 1.9 2005-11-13 12:12:42 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-ipx.c b/contrib/tcpdump/print-ipx.c
index 6459b31..8184425 100644
--- a/contrib/tcpdump/print-ipx.c
+++ b/contrib/tcpdump/print-ipx.c
@@ -26,7 +26,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ipx.c,v 1.40.2.2 2005/05/06 08:27:00 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ipx.c,v 1.42 2005-05-06 08:26:44 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-isakmp.c b/contrib/tcpdump/print-isakmp.c
index 09972f0..763f58a 100644
--- a/contrib/tcpdump/print-isakmp.c
+++ b/contrib/tcpdump/print-isakmp.c
@@ -30,9 +30,10 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.51 2005/04/07 00:28:17 mcr Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-isakmp.c,v 1.56 2007-08-29 12:31:00 mcr Exp $ (LBL)";
#endif
+#define NETDISSECT_REWORKED
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -59,39 +60,64 @@ static const char rcsid[] _U_ =
#define sockaddr_storage sockaddr
#endif
-static const u_char *isakmp_sa_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_p_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_t_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_ke_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_id_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_cert_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_cr_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_sig_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_hash_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_nonce_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_n_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_d_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_vid_print(const struct isakmp_gen *,
- u_int, const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_sub0_print(u_char, const struct isakmp_gen *,
+#define DECLARE_PRINTER(func) static const u_char *ike##func##_print( \
+ netdissect_options *ndo, u_char tpay, \
+ const struct isakmp_gen *ext, \
+ u_int item_len, \
+ const u_char *end_pointer, \
+ u_int32_t phase,\
+ u_int32_t doi0, \
+ u_int32_t proto0, int depth)
+
+DECLARE_PRINTER(v1_sa);
+DECLARE_PRINTER(v1_p);
+DECLARE_PRINTER(v1_t);
+DECLARE_PRINTER(v1_ke);
+DECLARE_PRINTER(v1_id);
+DECLARE_PRINTER(v1_cert);
+DECLARE_PRINTER(v1_cr);
+DECLARE_PRINTER(v1_sig);
+DECLARE_PRINTER(v1_hash);
+DECLARE_PRINTER(v1_nonce);
+DECLARE_PRINTER(v1_n);
+DECLARE_PRINTER(v1_d);
+DECLARE_PRINTER(v1_vid);
+
+DECLARE_PRINTER(v2_sa);
+DECLARE_PRINTER(v2_ke);
+DECLARE_PRINTER(v2_ID);
+DECLARE_PRINTER(v2_cert);
+DECLARE_PRINTER(v2_cr);
+DECLARE_PRINTER(v2_auth);
+DECLARE_PRINTER(v2_nonce);
+DECLARE_PRINTER(v2_n);
+DECLARE_PRINTER(v2_d);
+DECLARE_PRINTER(v2_vid);
+DECLARE_PRINTER(v2_TS);
+DECLARE_PRINTER(v2_e);
+DECLARE_PRINTER(v2_cp);
+DECLARE_PRINTER(v2_eap);
+
+static const u_char *ike_sub0_print(netdissect_options *ndo,u_char, const struct isakmp_gen *,
const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
-static const u_char *isakmp_sub_print(u_char, const struct isakmp_gen *,
+static const u_char *ikev1_sub_print(netdissect_options *ndo,u_char, const struct isakmp_gen *,
const u_char *, u_int32_t, u_int32_t, u_int32_t, int);
+
+static const u_char *ikev2_sub_print(netdissect_options *ndo,
+ u_char np, const struct isakmp_gen *ext,
+ const u_char *ep, u_int32_t phase,
+ u_int32_t doi, u_int32_t proto,
+ int depth);
+
+
static char *numstr(int);
static void safememcpy(void *, const void *, size_t);
+static void
+ikev1_print(netdissect_options *ndo,
+ const u_char *bp, u_int length,
+ const u_char *bp2, struct isakmp *base);
+
#define MAXINITIATORS 20
int ninitiator = 0;
struct {
@@ -107,36 +133,73 @@ static const char *protoidstr[] = {
/* isakmp->np */
static const char *npstr[] = {
- "none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash",
- "sig", "nonce", "n", "d", "vid"
+ "none", "sa", "p", "t", "ke", "id", "cert", "cr", "hash", /* 0 - 8 */
+ "sig", "nonce", "n", "d", "vid", /* 9 - 13 */
+ "pay14", "pay15", "pay16", "pay17", "pay18", /* 14- 18 */
+ "pay19", "pay20", "pay21", "pay22", "pay23", /* 19- 23 */
+ "pay24", "pay25", "pay26", "pay27", "pay28", /* 24- 28 */
+ "pay29", "pay30", "pay31", "pay32", /* 29- 32 */
+ "v2sa", "v2ke", "v2IDi", "v2IDr", "v2cert",/* 33- 37 */
+ "v2cr", "v2auth","v2nonce", "v2n", "v2d", /* 38- 42 */
+ "v2vid", "v2TSi", "v2TSr", "v2e", "v2cp", /* 43- 47 */
+ "v2eap", /* 48 */
+
};
/* isakmp->np */
-static const u_char *(*npfunc[])(const struct isakmp_gen *, u_int,
- const u_char *, u_int32_t, u_int32_t, u_int32_t, int) = {
+static const u_char *(*npfunc[])(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len,
+ const u_char *end_pointer,
+ u_int32_t phase,
+ u_int32_t doi0,
+ u_int32_t proto0, int depth) = {
NULL,
- isakmp_sa_print,
- isakmp_p_print,
- isakmp_t_print,
- isakmp_ke_print,
- isakmp_id_print,
- isakmp_cert_print,
- isakmp_cr_print,
- isakmp_hash_print,
- isakmp_sig_print,
- isakmp_nonce_print,
- isakmp_n_print,
- isakmp_d_print,
- isakmp_vid_print,
+ ikev1_sa_print,
+ ikev1_p_print,
+ ikev1_t_print,
+ ikev1_ke_print,
+ ikev1_id_print,
+ ikev1_cert_print,
+ ikev1_cr_print,
+ ikev1_hash_print,
+ ikev1_sig_print,
+ ikev1_nonce_print,
+ ikev1_n_print,
+ ikev1_d_print,
+ ikev1_vid_print, /* 13 */
+ NULL, NULL, NULL, NULL, NULL, /* 14- 18 */
+ NULL, NULL, NULL, NULL, NULL, /* 19- 23 */
+ NULL, NULL, NULL, NULL, NULL, /* 24- 28 */
+ NULL, NULL, NULL, NULL, /* 29- 32 */
+ ikev2_sa_print, /* 33 */
+ ikev2_ke_print, /* 34 */
+ ikev2_ID_print, /* 35 */
+ ikev2_ID_print, /* 36 */
+ ikev2_cert_print, /* 37 */
+ ikev2_cr_print, /* 38 */
+ ikev2_auth_print, /* 39 */
+ ikev2_nonce_print, /* 40 */
+ ikev2_n_print, /* 41 */
+ ikev2_d_print, /* 42 */
+ ikev2_vid_print, /* 43 */
+ ikev2_TS_print, /* 44 */
+ ikev2_TS_print, /* 45 */
+ ikev2_e_print, /* 46 */
+ ikev2_cp_print, /* 47 */
+ ikev2_eap_print, /* 48 */
};
/* isakmp->etype */
static const char *etypestr[] = {
- "none", "base", "ident", "auth", "agg", "inf", NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- "oakley-quick", "oakley-newgroup",
+/* IKEv1 exchange types */
+ "none", "base", "ident", "auth", "agg", "inf", NULL, NULL, /* 0-7 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 8-15 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 16-23 */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 24-31 */
+ "oakley-quick", "oakley-newgroup", /* 32-33 */
+/* IKEv2 exchange types */
+ "ikev2_init", "ikev2_auth", "child_sa", "inf2" /* 34-37 */
};
#define STR_OR_ID(x, tab) \
@@ -145,6 +208,13 @@ static const char *etypestr[] = {
#define NPSTR(x) STR_OR_ID(x, npstr)
#define ETYPESTR(x) STR_OR_ID(x, etypestr)
+#define CHECKLEN(p, np) \
+ if (ep < (u_char *)(p)) { \
+ ND_PRINT((ndo," [|%s]", NPSTR(np))); \
+ goto done; \
+ }
+
+
#define NPFUNC(x) \
(((x) < sizeof(npfunc)/sizeof(npfunc[0]) && npfunc[(x)]) \
? npfunc[(x)] : NULL)
@@ -322,21 +392,54 @@ cookie_sidecheck(int i, const u_char *bp2, int initiator)
}
static int
-rawprint(caddr_t loc, size_t len)
+rawprint(netdissect_options *ndo, caddr_t loc, size_t len)
{
static u_char *p;
size_t i;
- TCHECK2(*loc, len);
+ ND_TCHECK2(*loc, len);
p = (u_char *)loc;
for (i = 0; i < len; i++)
- printf("%02x", p[i] & 0xff);
+ ND_PRINT((ndo,"%02x", p[i] & 0xff));
return 1;
trunc:
return 0;
}
+/*
+ * returns false if we run out of data buffer
+ */
+static int ike_show_somedata(struct netdissect_options *ndo,
+ const u_char *cp, const u_char *ep)
+{
+ /* there is too much data, just show some of it */
+ const u_char *end = ep - 20;
+ int elen = 20;
+ int len = ep - cp;
+ if(len > 10) {
+ len = 10;
+ }
+
+ /* really shouldn't happen because of above */
+ if(end < cp + len) {
+ end = cp+len;
+ elen = ep - end;
+ }
+
+ ND_PRINT((ndo," data=("));
+ if(!rawprint(ndo, (caddr_t)(cp), len)) goto trunc;
+ ND_PRINT((ndo, "..."));
+ if(elen) {
+ if(!rawprint(ndo, (caddr_t)(end), elen)) goto trunc;
+ }
+ ND_PRINT((ndo,")"));
+ return 1;
+
+trunc:
+ return 0;
+}
+
struct attrmap {
const char *type;
u_int nvalue;
@@ -344,8 +447,9 @@ struct attrmap {
};
static const u_char *
-isakmp_attrmap_print(const u_char *p, const u_char *ep,
- const struct attrmap *map, size_t nmap)
+ikev1_attrmap_print(netdissect_options *ndo,
+ const u_char *p, const u_char *ep,
+ const struct attrmap *map, size_t nmap)
{
u_int16_t *q;
int totlen;
@@ -357,33 +461,33 @@ isakmp_attrmap_print(const u_char *p, const u_char *ep,
else
totlen = 4 + EXTRACT_16BITS(&q[1]);
if (ep < p + totlen) {
- printf("[|attr]");
+ ND_PRINT((ndo,"[|attr]"));
return ep + 1;
}
- printf("(");
+ ND_PRINT((ndo,"("));
t = EXTRACT_16BITS(&q[0]) & 0x7fff;
if (map && t < nmap && map[t].type)
- printf("type=%s ", map[t].type);
+ ND_PRINT((ndo,"type=%s ", map[t].type));
else
- printf("type=#%d ", t);
+ ND_PRINT((ndo,"type=#%d ", t));
if (p[0] & 0x80) {
- printf("value=");
+ ND_PRINT((ndo,"value="));
v = EXTRACT_16BITS(&q[1]);
if (map && t < nmap && v < map[t].nvalue && map[t].value[v])
- printf("%s", map[t].value[v]);
+ ND_PRINT((ndo,"%s", map[t].value[v]));
else
- rawprint((caddr_t)&q[1], 2);
+ rawprint(ndo, (caddr_t)&q[1], 2);
} else {
- printf("len=%d value=", EXTRACT_16BITS(&q[1]));
- rawprint((caddr_t)&p[4], EXTRACT_16BITS(&q[1]));
+ ND_PRINT((ndo,"len=%d value=", EXTRACT_16BITS(&q[1])));
+ rawprint(ndo, (caddr_t)&p[4], EXTRACT_16BITS(&q[1]));
}
- printf(")");
+ ND_PRINT((ndo,")"));
return p + totlen;
}
static const u_char *
-isakmp_attr_print(const u_char *p, const u_char *ep)
+ikev1_attr_print(netdissect_options *ndo, const u_char *p, const u_char *ep)
{
u_int16_t *q;
int totlen;
@@ -395,129 +499,166 @@ isakmp_attr_print(const u_char *p, const u_char *ep)
else
totlen = 4 + EXTRACT_16BITS(&q[1]);
if (ep < p + totlen) {
- printf("[|attr]");
+ ND_PRINT((ndo,"[|attr]"));
return ep + 1;
}
- printf("(");
+ ND_PRINT((ndo,"("));
t = EXTRACT_16BITS(&q[0]) & 0x7fff;
- printf("type=#%d ", t);
+ ND_PRINT((ndo,"type=#%d ", t));
if (p[0] & 0x80) {
- printf("value=");
+ ND_PRINT((ndo,"value="));
t = q[1];
- rawprint((caddr_t)&q[1], 2);
+ rawprint(ndo, (caddr_t)&q[1], 2);
} else {
- printf("len=%d value=", EXTRACT_16BITS(&q[1]));
- rawprint((caddr_t)&p[2], EXTRACT_16BITS(&q[1]));
+ ND_PRINT((ndo,"len=%d value=", EXTRACT_16BITS(&q[1])));
+ rawprint(ndo, (caddr_t)&p[2], EXTRACT_16BITS(&q[1]));
}
- printf(")");
+ ND_PRINT((ndo,")"));
return p + totlen;
}
static const u_char *
-isakmp_sa_print(const struct isakmp_gen *ext,
+ikev1_sa_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext,
u_int item_len _U_,
const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
u_int32_t proto0, int depth)
{
- const struct isakmp_pl_sa *p;
- struct isakmp_pl_sa sa;
+ const struct ikev1_pl_sa *p;
+ struct ikev1_pl_sa sa;
const u_int32_t *q;
u_int32_t doi, sit, ident;
const u_char *cp, *np;
int t;
- printf("%s:", NPSTR(ISAKMP_NPTYPE_SA));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_SA)));
- p = (struct isakmp_pl_sa *)ext;
- TCHECK(*p);
+ p = (struct ikev1_pl_sa *)ext;
+ ND_TCHECK(*p);
safememcpy(&sa, ext, sizeof(sa));
doi = ntohl(sa.doi);
sit = ntohl(sa.sit);
if (doi != 1) {
- printf(" doi=%d", doi);
- printf(" situation=%u", (u_int32_t)ntohl(sa.sit));
+ ND_PRINT((ndo," doi=%d", doi));
+ ND_PRINT((ndo," situation=%u", (u_int32_t)ntohl(sa.sit)));
return (u_char *)(p + 1);
}
- printf(" doi=ipsec");
+ ND_PRINT((ndo," doi=ipsec"));
q = (u_int32_t *)&sa.sit;
- printf(" situation=");
+ ND_PRINT((ndo," situation="));
t = 0;
if (sit & 0x01) {
- printf("identity");
+ ND_PRINT((ndo,"identity"));
t++;
}
if (sit & 0x02) {
- printf("%ssecrecy", t ? "+" : "");
+ ND_PRINT((ndo,"%ssecrecy", t ? "+" : ""));
t++;
}
if (sit & 0x04)
- printf("%sintegrity", t ? "+" : "");
+ ND_PRINT((ndo,"%sintegrity", t ? "+" : ""));
np = (u_char *)ext + sizeof(sa);
if (sit != 0x01) {
- TCHECK2(*(ext + 1), sizeof(ident));
+ ND_TCHECK2(*(ext + 1), sizeof(ident));
safememcpy(&ident, ext + 1, sizeof(ident));
- printf(" ident=%u", (u_int32_t)ntohl(ident));
+ ND_PRINT((ndo," ident=%u", (u_int32_t)ntohl(ident)));
np += sizeof(ident);
}
ext = (struct isakmp_gen *)np;
- TCHECK(*ext);
+ ND_TCHECK(*ext);
- cp = isakmp_sub_print(ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
+ cp = ikev1_sub_print(ndo, ISAKMP_NPTYPE_P, ext, ep, phase, doi, proto0,
depth);
return cp;
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SA));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_SA)));
return NULL;
}
static const u_char *
-isakmp_p_print(const struct isakmp_gen *ext, u_int item_len _U_,
+ikev1_p_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext, u_int item_len _U_,
const u_char *ep, u_int32_t phase, u_int32_t doi0,
u_int32_t proto0 _U_, int depth)
{
- const struct isakmp_pl_p *p;
- struct isakmp_pl_p prop;
+ const struct ikev1_pl_p *p;
+ struct ikev1_pl_p prop;
const u_char *cp;
- printf("%s:", NPSTR(ISAKMP_NPTYPE_P));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_P)));
- p = (struct isakmp_pl_p *)ext;
- TCHECK(*p);
+ p = (struct ikev1_pl_p *)ext;
+ ND_TCHECK(*p);
safememcpy(&prop, ext, sizeof(prop));
- printf(" #%d protoid=%s transform=%d",
- prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t);
+ ND_PRINT((ndo," #%d protoid=%s transform=%d",
+ prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t));
if (prop.spi_size) {
- printf(" spi=");
- if (!rawprint((caddr_t)(p + 1), prop.spi_size))
+ ND_PRINT((ndo," spi="));
+ if (!rawprint(ndo, (caddr_t)(p + 1), prop.spi_size))
goto trunc;
}
ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
- TCHECK(*ext);
-
- cp = isakmp_sub_print(ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
- prop.prot_id, depth);
-
+ ND_TCHECK(*ext);
+
+ cp = ikev1_sub_print(ndo, ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
+ prop.prot_id, depth);
+
return cp;
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_P));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_P)));
return NULL;
}
-static const char *isakmp_p_map[] = {
+static const char *ikev1_p_map[] = {
NULL, "ike",
};
+static const char *ikev2_t_type_map[]={
+ NULL, "encr", "prf", "integ", "dh", "esn"
+};
+
static const char *ah_p_map[] = {
NULL, "(reserved)", "md5", "sha", "1des",
"sha2-256", "sha2-384", "sha2-512",
};
+static const char *prf_p_map[] = {
+ NULL, "hmac-md5", "hmac-sha", "hmac-tiger",
+ "aes128_xcbc"
+};
+
+static const char *integ_p_map[] = {
+ NULL, "hmac-md5", "hmac-sha", "dec-mac",
+ "kpdk-md5", "aes-xcbc"
+};
+
+static const char *esn_p_map[] = {
+ "no-esn", "esn"
+};
+
+static const char *dh_p_map[] = {
+ NULL, "modp768",
+ "modp1024", /* group 2 */
+ "EC2N 2^155", /* group 3 */
+ "EC2N 2^185", /* group 4 */
+ "modp1536", /* group 5 */
+ "iana-grp06", "iana-grp07", /* reserved */
+ "iana-grp08", "iana-grp09",
+ "iana-grp10", "iana-grp11",
+ "iana-grp12", "iana-grp13",
+ "modp2048", /* group 14 */
+ "modp3072", /* group 15 */
+ "modp4096", /* group 16 */
+ "modp6144", /* group 17 */
+ "modp8192", /* group 18 */
+};
+
static const char *esp_p_map[] = {
NULL, "1des-iv64", "1des", "3des", "rc5", "idea", "cast",
"blowfish", "3idea", "1des-iv32", "rc4", "null", "aes"
@@ -531,8 +672,21 @@ const struct attrmap ipsec_t_map[] = {
{ NULL, 0, { NULL } },
{ "lifetype", 3, { NULL, "sec", "kb", }, },
{ "life", 0, { NULL } },
- { "group desc", 5, { NULL, "modp768", "modp1024", "EC2N 2^155",
- "EC2N 2^185", }, },
+ { "group desc", 18, { NULL, "modp768",
+ "modp1024", /* group 2 */
+ "EC2N 2^155", /* group 3 */
+ "EC2N 2^185", /* group 4 */
+ "modp1536", /* group 5 */
+ "iana-grp06", "iana-grp07", /* reserved */
+ "iana-grp08", "iana-grp09",
+ "iana-grp10", "iana-grp11",
+ "iana-grp12", "iana-grp13",
+ "modp2048", /* group 14 */
+ "modp3072", /* group 15 */
+ "modp4096", /* group 16 */
+ "modp6144", /* group 17 */
+ "modp8192", /* group 18 */
+ }, },
{ "enc mode", 3, { NULL, "tunnel", "transport", }, },
{ "auth", 5, { NULL, "hmac-md5", "hmac-sha1", "1des-mac", "keyed", }, },
{ "keylen", 0, { NULL } },
@@ -541,6 +695,17 @@ const struct attrmap ipsec_t_map[] = {
{ "privalg", 0, { NULL } },
};
+const struct attrmap encr_t_map[] = {
+ { NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 0, 1 */
+ { NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 2, 3 */
+ { NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 4, 5 */
+ { NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 6, 7 */
+ { NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 8, 9 */
+ { NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 10,11*/
+ { NULL, 0, { NULL } }, { NULL, 0, { NULL } }, /* 12,13*/
+ { "keylen", 14, { NULL }},
+};
+
const struct attrmap oakley_t_map[] = {
{ NULL, 0, { NULL } },
{ "enc", 8, { NULL, "1des", "idea", "blowfish", "rc5",
@@ -549,8 +714,21 @@ const struct attrmap oakley_t_map[] = {
"sha2-256", "sha2-384", "sha2-512", }, },
{ "auth", 6, { NULL, "preshared", "dss", "rsa sig", "rsa enc",
"rsa enc revised", }, },
- { "group desc", 5, { NULL, "modp768", "modp1024", "EC2N 2^155",
- "EC2N 2^185", }, },
+ { "group desc", 18, { NULL, "modp768",
+ "modp1024", /* group 2 */
+ "EC2N 2^155", /* group 3 */
+ "EC2N 2^185", /* group 4 */
+ "modp1536", /* group 5 */
+ "iana-grp06", "iana-grp07", /* reserved */
+ "iana-grp08", "iana-grp09",
+ "iana-grp10", "iana-grp11",
+ "iana-grp12", "iana-grp13",
+ "modp2048", /* group 14 */
+ "modp3072", /* group 15 */
+ "modp4096", /* group 16 */
+ "modp6144", /* group 17 */
+ "modp8192", /* group 18 */
+ }, },
{ "group type", 4, { NULL, "MODP", "ECP", "EC2N", }, },
{ "group prime", 0, { NULL } },
{ "group gen1", 0, { NULL } },
@@ -566,27 +744,28 @@ const struct attrmap oakley_t_map[] = {
};
static const u_char *
-isakmp_t_print(const struct isakmp_gen *ext, u_int item_len,
- const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
- u_int32_t proto, int depth _U_)
+ikev1_t_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext, u_int item_len,
+ const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto, int depth _U_)
{
- const struct isakmp_pl_t *p;
- struct isakmp_pl_t t;
+ const struct ikev1_pl_t *p;
+ struct ikev1_pl_t t;
const u_char *cp;
const char *idstr;
const struct attrmap *map;
size_t nmap;
const u_char *ep2;
- printf("%s:", NPSTR(ISAKMP_NPTYPE_T));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_T)));
- p = (struct isakmp_pl_t *)ext;
- TCHECK(*p);
+ p = (struct ikev1_pl_t *)ext;
+ ND_TCHECK(*p);
safememcpy(&t, ext, sizeof(t));
switch (proto) {
case 1:
- idstr = STR_OR_ID(t.t_id, isakmp_p_map);
+ idstr = STR_OR_ID(t.t_id, ikev1_p_map);
map = oakley_t_map;
nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
break;
@@ -613,57 +792,59 @@ isakmp_t_print(const struct isakmp_gen *ext, u_int item_len,
}
if (idstr)
- printf(" #%d id=%s ", t.t_no, idstr);
+ ND_PRINT((ndo," #%d id=%s ", t.t_no, idstr));
else
- printf(" #%d id=%d ", t.t_no, t.t_id);
+ ND_PRINT((ndo," #%d id=%d ", t.t_no, t.t_id));
cp = (u_char *)(p + 1);
ep2 = (u_char *)p + item_len;
while (cp < ep && cp < ep2) {
if (map && nmap) {
- cp = isakmp_attrmap_print(cp, (ep < ep2) ? ep : ep2,
+ cp = ikev1_attrmap_print(ndo, cp, (ep < ep2) ? ep : ep2,
map, nmap);
} else
- cp = isakmp_attr_print(cp, (ep < ep2) ? ep : ep2);
+ cp = ikev1_attr_print(ndo, cp, (ep < ep2) ? ep : ep2);
}
if (ep < ep2)
- printf("...");
+ ND_PRINT((ndo,"..."));
return cp;
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_T));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_T)));
return NULL;
}
static const u_char *
-isakmp_ke_print(const struct isakmp_gen *ext, u_int item_len _U_,
- const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
- u_int32_t proto _U_, int depth _U_)
+ikev1_ke_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
struct isakmp_gen e;
- printf("%s:", NPSTR(ISAKMP_NPTYPE_KE));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_KE)));
- TCHECK(*ext);
+ ND_TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
- printf(" key len=%d", ntohs(e.len) - 4);
- if (2 < vflag && 4 < ntohs(e.len)) {
- printf(" ");
- if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
+ ND_PRINT((ndo," key len=%d", ntohs(e.len) - 4));
+ if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
+ ND_PRINT((ndo," "));
+ if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
goto trunc;
}
return (u_char *)ext + ntohs(e.len);
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_KE));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_KE)));
return NULL;
}
static const u_char *
-isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
- const u_char *ep _U_, u_int32_t phase, u_int32_t doi _U_,
- u_int32_t proto _U_, int depth _U_)
+ikev1_id_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
#define USE_IPSECDOI_IN_PHASE1 1
- const struct isakmp_pl_id *p;
- struct isakmp_pl_id id;
+ const struct ikev1_pl_id *p;
+ struct ikev1_pl_id id;
static const char *idtypestr[] = {
"IPv4", "IPv4net", "IPv6", "IPv6net",
};
@@ -675,10 +856,10 @@ isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
int len;
const u_char *data;
- printf("%s:", NPSTR(ISAKMP_NPTYPE_ID));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_ID)));
- p = (struct isakmp_pl_id *)ext;
- TCHECK(*p);
+ p = (struct ikev1_pl_id *)ext;
+ ND_TCHECK(*p);
safememcpy(&id, ext, sizeof(id));
if (sizeof(*p) < item_len) {
data = (u_char *)(p + 1);
@@ -689,16 +870,16 @@ isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
}
#if 0 /*debug*/
- printf(" [phase=%d doi=%d proto=%d]", phase, doi, proto);
+ ND_PRINT((ndo," [phase=%d doi=%d proto=%d]", phase, doi, proto));
#endif
switch (phase) {
#ifndef USE_IPSECDOI_IN_PHASE1
case 1:
#endif
default:
- printf(" idtype=%s", STR_OR_ID(id.d.id_type, idtypestr));
- printf(" doi_data=%u",
- (u_int32_t)(ntohl(id.d.doi_data) & 0xffffff));
+ ND_PRINT((ndo," idtype=%s", STR_OR_ID(id.d.id_type, idtypestr)));
+ ND_PRINT((ndo," doi_data=%u",
+ (u_int32_t)(ntohl(id.d.doi_data) & 0xffffff)));
break;
#ifdef USE_IPSECDOI_IN_PHASE1
@@ -711,42 +892,42 @@ isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
struct protoent *pe;
p = (struct ipsecdoi_id *)ext;
- TCHECK(*p);
+ ND_TCHECK(*p);
safememcpy(&id, ext, sizeof(id));
- printf(" idtype=%s", STR_OR_ID(id.type, ipsecidtypestr));
+ ND_PRINT((ndo," idtype=%s", STR_OR_ID(id.type, ipsecidtypestr)));
if (id.proto_id) {
#ifndef WIN32
setprotoent(1);
#endif /* WIN32 */
pe = getprotobynumber(id.proto_id);
if (pe)
- printf(" protoid=%s", pe->p_name);
+ ND_PRINT((ndo," protoid=%s", pe->p_name));
#ifndef WIN32
endprotoent();
#endif /* WIN32 */
} else {
/* it DOES NOT mean IPPROTO_IP! */
- printf(" protoid=%s", "0");
+ ND_PRINT((ndo," protoid=%s", "0"));
}
- printf(" port=%d", ntohs(id.port));
+ ND_PRINT((ndo," port=%d", ntohs(id.port)));
if (!len)
break;
if (data == NULL)
goto trunc;
- TCHECK2(*data, len);
+ ND_TCHECK2(*data, len);
switch (id.type) {
case IPSECDOI_ID_IPV4_ADDR:
if (len < 4)
- printf(" len=%d [bad: < 4]", len);
+ ND_PRINT((ndo," len=%d [bad: < 4]", len));
else
- printf(" len=%d %s", len, ipaddr_string(data));
+ ND_PRINT((ndo," len=%d %s", len, ipaddr_string(data)));
len = 0;
break;
case IPSECDOI_ID_FQDN:
case IPSECDOI_ID_USER_FQDN:
{
int i;
- printf(" len=%d ", len);
+ ND_PRINT((ndo," len=%d ", len));
for (i = 0; i < len; i++)
safeputchar(data[i]);
len = 0;
@@ -756,12 +937,12 @@ isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
{
const u_char *mask;
if (len < 8)
- printf(" len=%d [bad: < 8]", len);
+ ND_PRINT((ndo," len=%d [bad: < 8]", len));
else {
mask = data + sizeof(struct in_addr);
- printf(" len=%d %s/%u.%u.%u.%u", len,
- ipaddr_string(data),
- mask[0], mask[1], mask[2], mask[3]);
+ ND_PRINT((ndo," len=%d %s/%u.%u.%u.%u", len,
+ ipaddr_string(data),
+ mask[0], mask[1], mask[2], mask[3]));
}
len = 0;
break;
@@ -769,22 +950,22 @@ isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
#ifdef INET6
case IPSECDOI_ID_IPV6_ADDR:
if (len < 16)
- printf(" len=%d [bad: < 16]", len);
+ ND_PRINT((ndo," len=%d [bad: < 16]", len));
else
- printf(" len=%d %s", len, ip6addr_string(data));
+ ND_PRINT((ndo," len=%d %s", len, ip6addr_string(data)));
len = 0;
break;
case IPSECDOI_ID_IPV6_ADDR_SUBNET:
{
const u_int32_t *mask;
if (len < 20)
- printf(" len=%d [bad: < 20]", len);
+ ND_PRINT((ndo," len=%d [bad: < 20]", len));
else {
mask = (u_int32_t *)(data + sizeof(struct in6_addr));
/*XXX*/
- printf(" len=%d %s/0x%08x%08x%08x%08x", len,
- ip6addr_string(data),
- mask[0], mask[1], mask[2], mask[3]);
+ ND_PRINT((ndo," len=%d %s/0x%08x%08x%08x%08x", len,
+ ip6addr_string(data),
+ mask[0], mask[1], mask[2], mask[3]));
}
len = 0;
break;
@@ -792,22 +973,22 @@ isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
#endif /*INET6*/
case IPSECDOI_ID_IPV4_ADDR_RANGE:
if (len < 8)
- printf(" len=%d [bad: < 8]", len);
+ ND_PRINT((ndo," len=%d [bad: < 8]", len));
else {
- printf(" len=%d %s-%s", len,
- ipaddr_string(data),
- ipaddr_string(data + sizeof(struct in_addr)));
+ ND_PRINT((ndo," len=%d %s-%s", len,
+ ipaddr_string(data),
+ ipaddr_string(data + sizeof(struct in_addr))));
}
len = 0;
break;
#ifdef INET6
case IPSECDOI_ID_IPV6_ADDR_RANGE:
if (len < 32)
- printf(" len=%d [bad: < 32]", len);
+ ND_PRINT((ndo," len=%d [bad: < 32]", len));
else {
- printf(" len=%d %s-%s", len,
- ip6addr_string(data),
- ip6addr_string(data + sizeof(struct in6_addr)));
+ ND_PRINT((ndo," len=%d %s-%s", len,
+ ip6addr_string(data),
+ ip6addr_string(data + sizeof(struct in6_addr))));
}
len = 0;
break;
@@ -821,159 +1002,169 @@ isakmp_id_print(const struct isakmp_gen *ext, u_int item_len _U_,
}
}
if (data && len) {
- printf(" len=%d", len);
- if (2 < vflag) {
- printf(" ");
- if (!rawprint((caddr_t)data, len))
+ ND_PRINT((ndo," len=%d", len));
+ if (2 < ndo->ndo_vflag) {
+ ND_PRINT((ndo," "));
+ if (!rawprint(ndo, (caddr_t)data, len))
goto trunc;
}
}
return (u_char *)ext + item_len;
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_ID));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_ID)));
return NULL;
}
static const u_char *
-isakmp_cert_print(const struct isakmp_gen *ext, u_int item_len _U_,
- const u_char *ep _U_, u_int32_t phase _U_,
- u_int32_t doi0 _U_,
- u_int32_t proto0 _U_, int depth _U_)
+ikev1_cert_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_,
+ u_int32_t doi0 _U_,
+ u_int32_t proto0 _U_, int depth _U_)
{
- const struct isakmp_pl_cert *p;
- struct isakmp_pl_cert cert;
+ const struct ikev1_pl_cert *p;
+ struct ikev1_pl_cert cert;
static const char *certstr[] = {
"none", "pkcs7", "pgp", "dns",
"x509sign", "x509ke", "kerberos", "crl",
"arl", "spki", "x509attr",
};
- printf("%s:", NPSTR(ISAKMP_NPTYPE_CERT));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_CERT)));
- p = (struct isakmp_pl_cert *)ext;
- TCHECK(*p);
+ p = (struct ikev1_pl_cert *)ext;
+ ND_TCHECK(*p);
safememcpy(&cert, ext, sizeof(cert));
- printf(" len=%d", item_len - 4);
- printf(" type=%s", STR_OR_ID((cert.encode), certstr));
- if (2 < vflag && 4 < item_len) {
- printf(" ");
- if (!rawprint((caddr_t)(ext + 1), item_len - 4))
+ ND_PRINT((ndo," len=%d", item_len - 4));
+ ND_PRINT((ndo," type=%s", STR_OR_ID((cert.encode), certstr)));
+ if (2 < ndo->ndo_vflag && 4 < item_len) {
+ ND_PRINT((ndo," "));
+ if (!rawprint(ndo, (caddr_t)(ext + 1), item_len - 4))
goto trunc;
}
return (u_char *)ext + item_len;
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CERT));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_CERT)));
return NULL;
}
static const u_char *
-isakmp_cr_print(const struct isakmp_gen *ext, u_int item_len _U_,
- const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
- u_int32_t proto0 _U_, int depth _U_)
+ikev1_cr_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
+ u_int32_t proto0 _U_, int depth _U_)
{
- const struct isakmp_pl_cert *p;
- struct isakmp_pl_cert cert;
+ const struct ikev1_pl_cert *p;
+ struct ikev1_pl_cert cert;
static const char *certstr[] = {
"none", "pkcs7", "pgp", "dns",
"x509sign", "x509ke", "kerberos", "crl",
"arl", "spki", "x509attr",
};
- printf("%s:", NPSTR(ISAKMP_NPTYPE_CR));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_CR)));
- p = (struct isakmp_pl_cert *)ext;
- TCHECK(*p);
+ p = (struct ikev1_pl_cert *)ext;
+ ND_TCHECK(*p);
safememcpy(&cert, ext, sizeof(cert));
- printf(" len=%d", item_len - 4);
- printf(" type=%s", STR_OR_ID((cert.encode), certstr));
- if (2 < vflag && 4 < item_len) {
- printf(" ");
- if (!rawprint((caddr_t)(ext + 1), item_len - 4))
+ ND_PRINT((ndo," len=%d", item_len - 4));
+ ND_PRINT((ndo," type=%s", STR_OR_ID((cert.encode), certstr)));
+ if (2 < ndo->ndo_vflag && 4 < item_len) {
+ ND_PRINT((ndo," "));
+ if (!rawprint(ndo, (caddr_t)(ext + 1), item_len - 4))
goto trunc;
}
return (u_char *)ext + item_len;
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_CR));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_CR)));
return NULL;
}
static const u_char *
-isakmp_hash_print(const struct isakmp_gen *ext, u_int item_len _U_,
- const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
- u_int32_t proto _U_, int depth _U_)
+ikev1_hash_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
struct isakmp_gen e;
- printf("%s:", NPSTR(ISAKMP_NPTYPE_HASH));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_HASH)));
- TCHECK(*ext);
+ ND_TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
- printf(" len=%d", ntohs(e.len) - 4);
- if (2 < vflag && 4 < ntohs(e.len)) {
- printf(" ");
- if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
+ ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
+ if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
+ ND_PRINT((ndo," "));
+ if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
goto trunc;
}
return (u_char *)ext + ntohs(e.len);
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_HASH));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_HASH)));
return NULL;
}
static const u_char *
-isakmp_sig_print(const struct isakmp_gen *ext, u_int item_len _U_,
- const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
- u_int32_t proto _U_, int depth _U_)
+ikev1_sig_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
struct isakmp_gen e;
- printf("%s:", NPSTR(ISAKMP_NPTYPE_SIG));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_SIG)));
- TCHECK(*ext);
+ ND_TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
- printf(" len=%d", ntohs(e.len) - 4);
- if (2 < vflag && 4 < ntohs(e.len)) {
- printf(" ");
- if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
+ ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
+ if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
+ ND_PRINT((ndo," "));
+ if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
goto trunc;
}
return (u_char *)ext + ntohs(e.len);
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_SIG));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_SIG)));
return NULL;
}
static const u_char *
-isakmp_nonce_print(const struct isakmp_gen *ext,
- u_int item_len _U_,
- const u_char *ep _U_,
- u_int32_t phase _U_, u_int32_t doi _U_,
- u_int32_t proto _U_, int depth _U_)
+ikev1_nonce_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_,
+ const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
struct isakmp_gen e;
- printf("%s:", NPSTR(ISAKMP_NPTYPE_NONCE));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_NONCE)));
- TCHECK(*ext);
+ ND_TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
- printf(" n len=%d", ntohs(e.len) - 4);
- if (2 < vflag && 4 < ntohs(e.len)) {
- printf(" ");
- if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
+ ND_PRINT((ndo," n len=%d", ntohs(e.len) - 4));
+ if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
+ ND_PRINT((ndo," "));
+ if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
+ goto trunc;
+ } else if (1 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
+ ND_PRINT((ndo," "));
+ if (!ike_show_somedata(ndo, (u_char *)(caddr_t)(ext + 1), ep))
goto trunc;
}
return (u_char *)ext + ntohs(e.len);
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_NONCE)));
return NULL;
}
static const u_char *
-isakmp_n_print(const struct isakmp_gen *ext, u_int item_len,
- const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
- u_int32_t proto0 _U_, int depth)
+ikev1_n_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext, u_int item_len,
+ const u_char *ep, u_int32_t phase, u_int32_t doi0 _U_,
+ u_int32_t proto0 _U_, int depth)
{
- struct isakmp_pl_n *p, n;
+ struct ikev1_pl_n *p, n;
const u_char *cp;
u_char *ep2;
u_int32_t doi;
@@ -1024,47 +1215,47 @@ isakmp_n_print(const struct isakmp_gen *ext, u_int item_len,
#define IPSEC_NOTIFY_STATUS_STR(x) \
STR_OR_ID((u_int)((x) - 24576), ipsec_notify_status_str)
- printf("%s:", NPSTR(ISAKMP_NPTYPE_N));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_N)));
- p = (struct isakmp_pl_n *)ext;
- TCHECK(*p);
+ p = (struct ikev1_pl_n *)ext;
+ ND_TCHECK(*p);
safememcpy(&n, ext, sizeof(n));
doi = ntohl(n.doi);
proto = n.prot_id;
if (doi != 1) {
- printf(" doi=%d", doi);
- printf(" proto=%d", proto);
+ ND_PRINT((ndo," doi=%d", doi));
+ ND_PRINT((ndo," proto=%d", proto));
if (ntohs(n.type) < 8192)
- printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
+ ND_PRINT((ndo," type=%s", NOTIFY_ERROR_STR(ntohs(n.type))));
else if (ntohs(n.type) < 16384)
- printf(" type=%s", numstr(ntohs(n.type)));
+ ND_PRINT((ndo," type=%s", numstr(ntohs(n.type))));
else if (ntohs(n.type) < 24576)
- printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
+ ND_PRINT((ndo," type=%s", NOTIFY_STATUS_STR(ntohs(n.type))));
else
- printf(" type=%s", numstr(ntohs(n.type)));
+ ND_PRINT((ndo," type=%s", numstr(ntohs(n.type))));
if (n.spi_size) {
- printf(" spi=");
- if (!rawprint((caddr_t)(p + 1), n.spi_size))
+ ND_PRINT((ndo," spi="));
+ if (!rawprint(ndo, (caddr_t)(p + 1), n.spi_size))
goto trunc;
}
return (u_char *)(p + 1) + n.spi_size;
}
- printf(" doi=ipsec");
- printf(" proto=%s", PROTOIDSTR(proto));
+ ND_PRINT((ndo," doi=ipsec"));
+ ND_PRINT((ndo," proto=%s", PROTOIDSTR(proto)));
if (ntohs(n.type) < 8192)
- printf(" type=%s", NOTIFY_ERROR_STR(ntohs(n.type)));
+ ND_PRINT((ndo," type=%s", NOTIFY_ERROR_STR(ntohs(n.type))));
else if (ntohs(n.type) < 16384)
- printf(" type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type)));
+ ND_PRINT((ndo," type=%s", IPSEC_NOTIFY_ERROR_STR(ntohs(n.type))));
else if (ntohs(n.type) < 24576)
- printf(" type=%s", NOTIFY_STATUS_STR(ntohs(n.type)));
+ ND_PRINT((ndo," type=%s", NOTIFY_STATUS_STR(ntohs(n.type))));
else if (ntohs(n.type) < 32768)
- printf(" type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type)));
+ ND_PRINT((ndo," type=%s", IPSEC_NOTIFY_STATUS_STR(ntohs(n.type))));
else
- printf(" type=%s", numstr(ntohs(n.type)));
+ ND_PRINT((ndo," type=%s", numstr(ntohs(n.type))));
if (n.spi_size) {
- printf(" spi=");
- if (!rawprint((caddr_t)(p + 1), n.spi_size))
+ ND_PRINT((ndo," spi="));
+ if (!rawprint(ndo, (caddr_t)(p + 1), n.spi_size))
goto trunc;
}
@@ -1072,119 +1263,712 @@ isakmp_n_print(const struct isakmp_gen *ext, u_int item_len,
ep2 = (u_char *)p + item_len;
if (cp < ep) {
- printf(" orig=(");
+ ND_PRINT((ndo," orig=("));
switch (ntohs(n.type)) {
case IPSECDOI_NTYPE_RESPONDER_LIFETIME:
{
const struct attrmap *map = oakley_t_map;
size_t nmap = sizeof(oakley_t_map)/sizeof(oakley_t_map[0]);
while (cp < ep && cp < ep2) {
- cp = isakmp_attrmap_print(cp,
+ cp = ikev1_attrmap_print(ndo, cp,
(ep < ep2) ? ep : ep2, map, nmap);
}
break;
}
case IPSECDOI_NTYPE_REPLAY_STATUS:
- printf("replay detection %sabled",
- (*(u_int32_t *)cp) ? "en" : "dis");
+ ND_PRINT((ndo,"replay detection %sabled",
+ (*(u_int32_t *)cp) ? "en" : "dis"));
break;
case ISAKMP_NTYPE_NO_PROPOSAL_CHOSEN:
- if (isakmp_sub_print(ISAKMP_NPTYPE_SA,
- (struct isakmp_gen *)cp, ep, phase, doi, proto,
- depth) == NULL)
+ if (ikev1_sub_print(ndo, ISAKMP_NPTYPE_SA,
+ (struct isakmp_gen *)cp, ep, phase, doi, proto,
+ depth) == NULL)
return NULL;
break;
default:
/* NULL is dummy */
- isakmp_print(gndo, cp,
+ isakmp_print(ndo, cp,
item_len - sizeof(*p) - n.spi_size,
NULL);
}
- printf(")");
+ ND_PRINT((ndo,")"));
}
return (u_char *)ext + item_len;
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_N));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_N)));
return NULL;
}
static const u_char *
-isakmp_d_print(const struct isakmp_gen *ext, u_int item_len _U_,
- const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
- u_int32_t proto0 _U_, int depth _U_)
+ikev1_d_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep _U_, u_int32_t phase _U_, u_int32_t doi0 _U_,
+ u_int32_t proto0 _U_, int depth _U_)
{
- const struct isakmp_pl_d *p;
- struct isakmp_pl_d d;
+ const struct ikev1_pl_d *p;
+ struct ikev1_pl_d d;
const u_int8_t *q;
u_int32_t doi;
u_int32_t proto;
int i;
- printf("%s:", NPSTR(ISAKMP_NPTYPE_D));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_D)));
- p = (struct isakmp_pl_d *)ext;
- TCHECK(*p);
+ p = (struct ikev1_pl_d *)ext;
+ ND_TCHECK(*p);
safememcpy(&d, ext, sizeof(d));
doi = ntohl(d.doi);
proto = d.prot_id;
if (doi != 1) {
- printf(" doi=%u", doi);
- printf(" proto=%u", proto);
+ ND_PRINT((ndo," doi=%u", doi));
+ ND_PRINT((ndo," proto=%u", proto));
} else {
- printf(" doi=ipsec");
- printf(" proto=%s", PROTOIDSTR(proto));
+ ND_PRINT((ndo," doi=ipsec"));
+ ND_PRINT((ndo," proto=%s", PROTOIDSTR(proto)));
}
- printf(" spilen=%u", d.spi_size);
- printf(" nspi=%u", ntohs(d.num_spi));
- printf(" spi=");
+ ND_PRINT((ndo," spilen=%u", d.spi_size));
+ ND_PRINT((ndo," nspi=%u", ntohs(d.num_spi)));
+ ND_PRINT((ndo," spi="));
q = (u_int8_t *)(p + 1);
for (i = 0; i < ntohs(d.num_spi); i++) {
if (i != 0)
- printf(",");
- if (!rawprint((caddr_t)q, d.spi_size))
+ ND_PRINT((ndo,","));
+ if (!rawprint(ndo, (caddr_t)q, d.spi_size))
goto trunc;
q += d.spi_size;
}
return q;
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_D));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_D)));
return NULL;
}
static const u_char *
-isakmp_vid_print(const struct isakmp_gen *ext,
- u_int item_len _U_, const u_char *ep _U_,
- u_int32_t phase _U_, u_int32_t doi _U_,
- u_int32_t proto _U_, int depth _U_)
+ikev1_vid_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
{
struct isakmp_gen e;
- printf("%s:", NPSTR(ISAKMP_NPTYPE_VID));
+ ND_PRINT((ndo,"%s:", NPSTR(ISAKMP_NPTYPE_VID)));
- TCHECK(*ext);
+ ND_TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
- printf(" len=%d", ntohs(e.len) - 4);
- if (2 < vflag && 4 < ntohs(e.len)) {
- printf(" ");
- if (!rawprint((caddr_t)(ext + 1), ntohs(e.len) - 4))
+ ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
+ if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
+ ND_PRINT((ndo," "));
+ if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
goto trunc;
}
return (u_char *)ext + ntohs(e.len);
trunc:
- printf(" [|%s]", NPSTR(ISAKMP_NPTYPE_VID));
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_VID)));
return NULL;
}
+/************************************************************/
+/* */
+/* IKE v2 - rfc4306 - dissector */
+/* */
+/************************************************************/
+
+static void
+ikev2_pay_print(netdissect_options *ndo, const char *payname, int critical)
+{
+ ND_PRINT((ndo,"%s%s:", payname, critical&0x80 ? "[C]" : ""));
+}
+
static const u_char *
-isakmp_sub0_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
- u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
+ikev2_gen_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext)
+{
+ struct isakmp_gen e;
+
+ ND_TCHECK(*ext);
+ safememcpy(&e, ext, sizeof(e));
+ ikev2_pay_print(ndo, NPSTR(tpay), e.critical);
+
+ ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
+ if (2 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
+ ND_PRINT((ndo," "));
+ if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
+ goto trunc;
+ }
+ return (u_char *)ext + ntohs(e.len);
+trunc:
+ ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
+ return NULL;
+}
+
+static const u_char *
+ikev2_t_print(netdissect_options *ndo, u_char tpay _U_, int pcount,
+ const struct isakmp_gen *ext, u_int item_len,
+ const u_char *ep, u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ const struct ikev2_t *p;
+ struct ikev2_t t;
+ u_int16_t t_id;
+ const u_char *cp;
+ const char *idstr;
+ const struct attrmap *map;
+ size_t nmap;
+ const u_char *ep2;
+
+ p = (struct ikev2_t *)ext;
+ ND_TCHECK(*p);
+ safememcpy(&t, ext, sizeof(t));
+ ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_T), t.h.critical);
+
+ t_id = ntohs(t.t_id);
+
+ map = NULL;
+ nmap = 0;
+
+ switch (t.t_type) {
+ case IV2_T_ENCR:
+ idstr = STR_OR_ID(t_id, esp_p_map);
+ map = encr_t_map;
+ nmap = sizeof(encr_t_map)/sizeof(encr_t_map[0]);
+ break;
+
+ case IV2_T_PRF:
+ idstr = STR_OR_ID(t_id, prf_p_map);
+ break;
+
+ case IV2_T_INTEG:
+ idstr = STR_OR_ID(t_id, integ_p_map);
+ break;
+
+ case IV2_T_DH:
+ idstr = STR_OR_ID(t_id, dh_p_map);
+ break;
+
+ case IV2_T_ESN:
+ idstr = STR_OR_ID(t_id, esn_p_map);
+ break;
+
+ default:
+ idstr = NULL;
+ break;
+ }
+
+ if (idstr)
+ ND_PRINT((ndo," #%u type=%s id=%s ", pcount,
+ STR_OR_ID(t.t_type, ikev2_t_type_map),
+ idstr));
+ else
+ ND_PRINT((ndo," #%u type=%s id=%u ", pcount,
+ STR_OR_ID(t.t_type, ikev2_t_type_map),
+ t.t_id));
+ cp = (u_char *)(p + 1);
+ ep2 = (u_char *)p + item_len;
+ while (cp < ep && cp < ep2) {
+ if (map && nmap) {
+ cp = ikev1_attrmap_print(ndo, cp, (ep < ep2) ? ep : ep2,
+ map, nmap);
+ } else
+ cp = ikev1_attr_print(ndo, cp, (ep < ep2) ? ep : ep2);
+ }
+ if (ep < ep2)
+ ND_PRINT((ndo,"..."));
+ return cp;
+trunc:
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_T)));
+ return NULL;
+}
+
+static const u_char *
+ikev2_p_print(netdissect_options *ndo, u_char tpay _U_, int pcount _U_,
+ const struct isakmp_gen *ext, u_int item_len _U_,
+ const u_char *ep, u_int32_t phase, u_int32_t doi0,
+ u_int32_t proto0 _U_, int depth)
+{
+ const struct ikev2_p *p;
+ struct ikev2_p prop;
+ const u_char *cp;
+
+ p = (struct ikev2_p *)ext;
+ ND_TCHECK(*p);
+ safememcpy(&prop, ext, sizeof(prop));
+ ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_P), prop.h.critical);
+
+ ND_PRINT((ndo," #%u protoid=%s transform=%d",
+ prop.p_no, PROTOIDSTR(prop.prot_id), prop.num_t));
+ if (prop.spi_size) {
+ ND_PRINT((ndo," spi="));
+ if (!rawprint(ndo, (caddr_t)(p + 1), prop.spi_size))
+ goto trunc;
+ }
+
+ ext = (struct isakmp_gen *)((u_char *)(p + 1) + prop.spi_size);
+ ND_TCHECK(*ext);
+
+ cp = ikev2_sub_print(ndo, ISAKMP_NPTYPE_T, ext, ep, phase, doi0,
+ prop.prot_id, depth);
+
+ return cp;
+trunc:
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_P)));
+ return NULL;
+}
+
+static const u_char *
+ikev2_sa_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext1,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ struct isakmp_gen e;
+ int osa_len, sa_len;
+
+ ND_TCHECK(*ext1);
+ safememcpy(&e, ext1, sizeof(e));
+ ikev2_pay_print(ndo, "sa", e.critical);
+
+ osa_len= ntohs(e.len);
+ sa_len = osa_len - 4;
+ ND_PRINT((ndo," len=%d", sa_len));
+
+ ikev2_sub_print(ndo, ISAKMP_NPTYPE_P,
+ ext1+1, ep,
+ 0, 0, 0, depth);
+
+ return (u_char *)ext1 + osa_len;
+trunc:
+ ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
+ return NULL;
+}
+
+static const u_char *
+ikev2_ke_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ struct ikev2_ke ke;
+ struct ikev2_ke *k;
+
+ k = (struct ikev2_ke *)ext;
+ ND_TCHECK(*ext);
+ safememcpy(&ke, ext, sizeof(ke));
+ ikev2_pay_print(ndo, NPSTR(tpay), ke.h.critical);
+
+ ND_PRINT((ndo," len=%u group=%s", ntohs(ke.h.len) - 8,
+ STR_OR_ID(ntohs(ke.ke_group), dh_p_map)));
+
+ if (2 < ndo->ndo_vflag && 8 < ntohs(ke.h.len)) {
+ ND_PRINT((ndo," "));
+ if (!rawprint(ndo, (caddr_t)(k + 1), ntohs(ke.h.len) - 8))
+ goto trunc;
+ }
+ return (u_char *)ext + ntohs(ke.h.len);
+trunc:
+ ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
+ return NULL;
+}
+
+static const u_char *
+ikev2_ID_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ return ikev2_gen_print(ndo, tpay, ext);
+}
+
+static const u_char *
+ikev2_cert_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ return ikev2_gen_print(ndo, tpay, ext);
+}
+
+static const u_char *
+ikev2_cr_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ return ikev2_gen_print(ndo, tpay, ext);
+}
+
+static const u_char *
+ikev2_auth_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ struct ikev2_auth e;
+ const char *v2_auth[]={ "invalid", "rsasig",
+ "shared-secret", "dsssig" };
+
+ ND_TCHECK(*ext);
+ safememcpy(&e, ext, sizeof(e));
+ ikev2_pay_print(ndo, NPSTR(tpay), e.h.critical);
+
+ ND_PRINT((ndo," len=%d method=%s", ntohs(e.h.len) - 4,
+ STR_OR_ID(e.auth_method, v2_auth)));
+
+ if (1 < ndo->ndo_vflag && 4 < ntohs(e.h.len)) {
+ ND_PRINT((ndo," authdata=("));
+ if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.h.len) - 4))
+ goto trunc;
+ ND_PRINT((ndo,") "));
+ } else if(ndo->ndo_vflag && 4 < ntohs(e.h.len)) {
+ if(!ike_show_somedata(ndo, (const u_char *)(ext+1), ep)) goto trunc;
+ }
+
+ return (u_char *)ext + ntohs(e.h.len);
+trunc:
+ ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
+ return NULL;
+}
+
+static const u_char *
+ikev2_nonce_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ struct isakmp_gen e;
+
+ ND_TCHECK(*ext);
+ safememcpy(&e, ext, sizeof(e));
+ ikev2_pay_print(ndo, "nonce", e.critical);
+
+ ND_PRINT((ndo," len=%d", ntohs(e.len) - 4));
+ if (1 < ndo->ndo_vflag && 4 < ntohs(e.len)) {
+ ND_PRINT((ndo," nonce=("));
+ if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
+ goto trunc;
+ ND_PRINT((ndo,") "));
+ } else if(ndo->ndo_vflag && 4 < ntohs(e.len)) {
+ if(!ike_show_somedata(ndo, (const u_char *)(ext+1), ep)) goto trunc;
+ }
+
+ return (u_char *)ext + ntohs(e.len);
+trunc:
+ ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
+ return NULL;
+}
+
+/* notify payloads */
+static const u_char *
+ikev2_n_print(netdissect_options *ndo, u_char tpay _U_,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ struct ikev2_n *p, n;
+ const u_char *cp;
+ u_char *ep2;
+ u_char showspi, showdata, showsomedata;
+ const char *notify_name;
+ u_int32_t type;
+
+ p = (struct ikev2_n *)ext;
+ ND_TCHECK(*p);
+ safememcpy(&n, ext, sizeof(n));
+ ikev2_pay_print(ndo, NPSTR(ISAKMP_NPTYPE_N), n.h.critical);
+
+ showspi = 1;
+ showdata = 0;
+ showsomedata=0;
+ notify_name=NULL;
+
+ ND_PRINT((ndo," prot_id=%s", PROTOIDSTR(n.prot_id)));
+
+ type = ntohs(n.type);
+
+ /* notify space is annoying sparse */
+ switch(type) {
+ case IV2_NOTIFY_UNSUPPORTED_CRITICAL_PAYLOAD:
+ notify_name = "unsupported_critical_payload";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_INVALID_IKE_SPI:
+ notify_name = "invalid_ike_spi";
+ showspi = 1;
+ break;
+
+ case IV2_NOTIFY_INVALID_MAJOR_VERSION:
+ notify_name = "invalid_major_version";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_INVALID_SYNTAX:
+ notify_name = "invalid_syntax";
+ showspi = 1;
+ break;
+
+ case IV2_NOTIFY_INVALID_MESSAGE_ID:
+ notify_name = "invalid_message_id";
+ showspi = 1;
+ break;
+
+ case IV2_NOTIFY_INVALID_SPI:
+ notify_name = "invalid_spi";
+ showspi = 1;
+ break;
+
+ case IV2_NOTIFY_NO_PROPOSAL_CHOSEN:
+ notify_name = "no_protocol_chosen";
+ showspi = 1;
+ break;
+
+ case IV2_NOTIFY_INVALID_KE_PAYLOAD:
+ notify_name = "invalid_ke_payload";
+ showspi = 1;
+ break;
+
+ case IV2_NOTIFY_AUTHENTICATION_FAILED:
+ notify_name = "authentication_failed";
+ showspi = 1;
+ break;
+
+ case IV2_NOTIFY_SINGLE_PAIR_REQUIRED:
+ notify_name = "single_pair_required";
+ showspi = 1;
+ break;
+
+ case IV2_NOTIFY_NO_ADDITIONAL_SAS:
+ notify_name = "no_additional_sas";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_INTERNAL_ADDRESS_FAILURE:
+ notify_name = "internal_address_failure";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_FAILED_CP_REQUIRED:
+ notify_name = "failed:cp_required";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_INVALID_SELECTORS:
+ notify_name = "invalid_selectors";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_INITIAL_CONTACT:
+ notify_name = "initial_contact";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_SET_WINDOW_SIZE:
+ notify_name = "set_window_size";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_ADDITIONAL_TS_POSSIBLE:
+ notify_name = "additional_ts_possible";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_IPCOMP_SUPPORTED:
+ notify_name = "ipcomp_supported";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_NAT_DETECTION_SOURCE_IP:
+ notify_name = "nat_detection_source_ip";
+ showspi = 1;
+ break;
+
+ case IV2_NOTIFY_NAT_DETECTION_DESTINATION_IP:
+ notify_name = "nat_detection_destination_ip";
+ showspi = 1;
+ break;
+
+ case IV2_NOTIFY_COOKIE:
+ notify_name = "cookie";
+ showspi = 1;
+ showsomedata= 1;
+ showdata= 0;
+ break;
+
+ case IV2_NOTIFY_USE_TRANSPORT_MODE:
+ notify_name = "use_transport_mode";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_HTTP_CERT_LOOKUP_SUPPORTED:
+ notify_name = "http_cert_lookup_supported";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_REKEY_SA:
+ notify_name = "rekey_sa";
+ showspi = 1;
+ break;
+
+ case IV2_NOTIFY_ESP_TFC_PADDING_NOT_SUPPORTED:
+ notify_name = "tfc_padding_not_supported";
+ showspi = 0;
+ break;
+
+ case IV2_NOTIFY_NON_FIRST_FRAGMENTS_ALSO:
+ notify_name = "non_first_fragment_also";
+ showspi = 0;
+ break;
+
+ default:
+ if (type < 8192) {
+ notify_name="error";
+ } else if(type < 16384) {
+ notify_name="private-error";
+ } else if(type < 40960) {
+ notify_name="status";
+ } else {
+ notify_name="private-status";
+ }
+ }
+
+ if(notify_name) {
+ ND_PRINT((ndo," type=%u(%s)", type, notify_name));
+ }
+
+
+ if (showspi && n.spi_size) {
+ ND_PRINT((ndo," spi="));
+ if (!rawprint(ndo, (caddr_t)(p + 1), n.spi_size))
+ goto trunc;
+ }
+
+ cp = (u_char *)(p + 1) + n.spi_size;
+ ep2 = (u_char *)p + item_len;
+
+ if(3 < ndo->ndo_vflag) {
+ showdata = 1;
+ }
+
+ if ((showdata || (showsomedata && ep-cp < 30)) && cp < ep) {
+ ND_PRINT((ndo," data=("));
+ if (!rawprint(ndo, (caddr_t)(cp), ep - cp))
+ goto trunc;
+
+ ND_PRINT((ndo,")"));
+
+ } else if(showsomedata && cp < ep) {
+ if(!ike_show_somedata(ndo, cp, ep)) goto trunc;
+ }
+
+ return (u_char *)ext + item_len;
+trunc:
+ ND_PRINT((ndo," [|%s]", NPSTR(ISAKMP_NPTYPE_N)));
+ return NULL;
+}
+
+static const u_char *
+ikev2_d_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ return ikev2_gen_print(ndo, tpay, ext);
+}
+
+static const u_char *
+ikev2_vid_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ struct isakmp_gen e;
+ const u_char *vid;
+ int i, len;
+
+ ND_TCHECK(*ext);
+ safememcpy(&e, ext, sizeof(e));
+ ikev2_pay_print(ndo, NPSTR(tpay), e.critical);
+ ND_PRINT((ndo," len=%d vid=", ntohs(e.len) - 4));
+
+ vid = (const u_char *)(ext+1);
+ len = ntohs(e.len) - 4;
+ ND_TCHECK2(*vid, len);
+ for(i=0; i<len; i++) {
+ if(isprint(vid[i])) ND_PRINT((ndo, "%c", vid[i]));
+ else ND_PRINT((ndo, ".", vid[i]));
+ }
+ if (2 < ndo->ndo_vflag && 4 < len) {
+ ND_PRINT((ndo," "));
+ if (!rawprint(ndo, (caddr_t)(ext + 1), ntohs(e.len) - 4))
+ goto trunc;
+ }
+ return (u_char *)ext + ntohs(e.len);
+trunc:
+ ND_PRINT((ndo," [|%s]", NPSTR(tpay)));
+ return NULL;
+}
+
+static const u_char *
+ikev2_TS_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ return ikev2_gen_print(ndo, tpay, ext);
+}
+
+static const u_char *
+ikev2_e_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ return ikev2_gen_print(ndo, tpay, ext);
+}
+
+static const u_char *
+ikev2_cp_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ return ikev2_gen_print(ndo, tpay, ext);
+}
+
+static const u_char *
+ikev2_eap_print(netdissect_options *ndo, u_char tpay,
+ const struct isakmp_gen *ext,
+ u_int item_len _U_, const u_char *ep _U_,
+ u_int32_t phase _U_, u_int32_t doi _U_,
+ u_int32_t proto _U_, int depth _U_)
+{
+ return ikev2_gen_print(ndo, tpay, ext);
+}
+
+static const u_char *
+ike_sub0_print(netdissect_options *ndo,
+ u_char np, const struct isakmp_gen *ext, const u_char *ep,
+ u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
{
const u_char *cp;
struct isakmp_gen e;
u_int item_len;
cp = (u_char *)ext;
- TCHECK(*ext);
+ ND_TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
/*
@@ -1202,21 +1986,22 @@ isakmp_sub0_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
* XXX - what if item_len is too short, or too long,
* for this payload type?
*/
- cp = (*npfunc[np])(ext, item_len, ep, phase, doi, proto, depth);
+ cp = (*npfunc[np])(ndo, np, ext, item_len, ep, phase, doi, proto, depth);
} else {
- printf("%s", NPSTR(np));
+ ND_PRINT((ndo,"%s", NPSTR(np)));
cp += item_len;
}
return cp;
trunc:
- printf(" [|isakmp]");
+ ND_PRINT((ndo," [|isakmp]"));
return NULL;
}
static const u_char *
-isakmp_sub_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
- u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
+ikev1_sub_print(netdissect_options *ndo,
+ u_char np, const struct isakmp_gen *ext, const u_char *ep,
+ u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
{
const u_char *cp;
int i;
@@ -1225,19 +2010,19 @@ isakmp_sub_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
cp = (const u_char *)ext;
while (np) {
- TCHECK(*ext);
+ ND_TCHECK(*ext);
safememcpy(&e, ext, sizeof(e));
- TCHECK2(*ext, ntohs(e.len));
+ ND_TCHECK2(*ext, ntohs(e.len));
depth++;
- printf("\n");
+ ND_PRINT((ndo,"\n"));
for (i = 0; i < depth; i++)
- printf(" ");
- printf("(");
- cp = isakmp_sub0_print(np, ext, ep, phase, doi, proto, depth);
- printf(")");
+ ND_PRINT((ndo," "));
+ ND_PRINT((ndo,"("));
+ cp = ike_sub0_print(ndo, np, ext, ep, phase, doi, proto, depth);
+ ND_PRINT((ndo,")"));
depth--;
if (cp == NULL) {
@@ -1250,7 +2035,7 @@ isakmp_sub_print(u_char np, const struct isakmp_gen *ext, const u_char *ep,
}
return cp;
trunc:
- printf(" [|%s]", NPSTR(np));
+ ND_PRINT((ndo," [|%s]", NPSTR(np)));
return NULL;
}
@@ -1274,120 +2059,287 @@ safememcpy(void *p, const void *q, size_t l)
}
void
-isakmp_print(netdissect_options *ndo,
- const u_char *bp, u_int length,
- const u_char *bp2)
+ikev1_print(netdissect_options *ndo,
+ const u_char *bp, u_int length,
+ const u_char *bp2, struct isakmp *base)
{
const struct isakmp *p;
- struct isakmp base;
const u_char *ep;
u_char np;
int i;
int phase;
- int major, minor;
-
+
p = (const struct isakmp *)bp;
ep = ndo->ndo_snapend;
-
- if ((struct isakmp *)ep < p + 1) {
- printf("[|isakmp]");
- return;
- }
-
- safememcpy(&base, p, sizeof(base));
-
- printf("isakmp");
- if (vflag) {
- major = (base.vers & ISAKMP_VERS_MAJOR)
- >> ISAKMP_VERS_MAJOR_SHIFT;
- minor = (base.vers & ISAKMP_VERS_MINOR)
- >> ISAKMP_VERS_MINOR_SHIFT;
- printf(" %d.%d", major, minor);
- }
-
- if (vflag) {
- printf(" msgid ");
- rawprint((caddr_t)&base.msgid, sizeof(base.msgid));
- }
-
- if (1 < vflag) {
- printf(" cookie ");
- rawprint((caddr_t)&base.i_ck, sizeof(base.i_ck));
- printf("->");
- rawprint((caddr_t)&base.r_ck, sizeof(base.r_ck));
- }
- printf(":");
-
- phase = (*(u_int32_t *)base.msgid == 0) ? 1 : 2;
+
+ phase = (*(u_int32_t *)base->msgid == 0) ? 1 : 2;
if (phase == 1)
- printf(" phase %d", phase);
+ ND_PRINT((ndo," phase %d", phase));
else
- printf(" phase %d/others", phase);
-
- i = cookie_find(&base.i_ck);
+ ND_PRINT((ndo," phase %d/others", phase));
+
+ i = cookie_find(&base->i_ck);
if (i < 0) {
- if (iszero((u_char *)&base.r_ck, sizeof(base.r_ck))) {
+ if (iszero((u_char *)&base->r_ck, sizeof(base->r_ck))) {
/* the first packet */
- printf(" I");
+ ND_PRINT((ndo," I"));
if (bp2)
- cookie_record(&base.i_ck, bp2);
+ cookie_record(&base->i_ck, bp2);
} else
- printf(" ?");
+ ND_PRINT((ndo," ?"));
} else {
if (bp2 && cookie_isinitiator(i, bp2))
- printf(" I");
+ ND_PRINT((ndo," I"));
else if (bp2 && cookie_isresponder(i, bp2))
- printf(" R");
+ ND_PRINT((ndo," R"));
else
- printf(" ?");
+ ND_PRINT((ndo," ?"));
}
-
- printf(" %s", ETYPESTR(base.etype));
- if (base.flags) {
- printf("[%s%s]", base.flags & ISAKMP_FLAG_E ? "E" : "",
- base.flags & ISAKMP_FLAG_C ? "C" : "");
+
+ ND_PRINT((ndo," %s", ETYPESTR(base->etype)));
+ if (base->flags) {
+ ND_PRINT((ndo,"[%s%s]", base->flags & ISAKMP_FLAG_E ? "E" : "",
+ base->flags & ISAKMP_FLAG_C ? "C" : ""));
}
-
- if (vflag) {
+
+ if (ndo->ndo_vflag) {
const struct isakmp_gen *ext;
int nparen;
+
+ ND_PRINT((ndo,":"));
+
+ /* regardless of phase... */
+ if (base->flags & ISAKMP_FLAG_E) {
+ /*
+ * encrypted, nothing we can do right now.
+ * we hope to decrypt the packet in the future...
+ */
+ ND_PRINT((ndo," [encrypted %s]", NPSTR(base->np)));
+ goto done;
+ }
+
+ nparen = 0;
+ CHECKLEN(p + 1, base->np);
+ np = base->np;
+ ext = (struct isakmp_gen *)(p + 1);
+ ikev1_sub_print(ndo, np, ext, ep, phase, 0, 0, 0);
+ }
+
+done:
+ if (ndo->ndo_vflag) {
+ if (ntohl(base->len) != length) {
+ ND_PRINT((ndo," (len mismatch: isakmp %u/ip %u)",
+ (u_int32_t)ntohl(base->len), length));
+ }
+ }
+}
-#define CHECKLEN(p, np) \
- if (ep < (u_char *)(p)) { \
- printf(" [|%s]", NPSTR(np)); \
- goto done; \
+static const u_char *
+ikev2_sub0_print(netdissect_options *ndo, u_char np, int pcount,
+ const struct isakmp_gen *ext, const u_char *ep,
+ u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
+{
+ const u_char *cp;
+ struct isakmp_gen e;
+ u_int item_len;
+
+ cp = (u_char *)ext;
+ ND_TCHECK(*ext);
+ safememcpy(&e, ext, sizeof(e));
+
+ /*
+ * Since we can't have a payload length of less than 4 bytes,
+ * we need to bail out here if the generic header is nonsensical
+ * or truncated, otherwise we could loop forever processing
+ * zero-length items or otherwise misdissect the packet.
+ */
+ item_len = ntohs(e.len);
+ if (item_len <= 4)
+ return NULL;
+
+ if(np == ISAKMP_NPTYPE_P) {
+ cp = ikev2_p_print(ndo, np, pcount, ext, item_len,
+ ep, phase, doi, proto, depth);
+ } else if(np == ISAKMP_NPTYPE_T) {
+ cp = ikev2_t_print(ndo, np, pcount, ext, item_len,
+ ep, phase, doi, proto, depth);
+ } else if (NPFUNC(np)) {
+ /*
+ * XXX - what if item_len is too short, or too long,
+ * for this payload type?
+ */
+ cp = (*npfunc[np])(ndo, np, /*pcount,*/ ext, item_len,
+ ep, phase, doi, proto, depth);
+ } else {
+ ND_PRINT((ndo,"%s", NPSTR(np)));
+ cp += item_len;
+ }
+
+ return cp;
+trunc:
+ ND_PRINT((ndo," [|isakmp]"));
+ return NULL;
+}
+
+static const u_char *
+ikev2_sub_print(netdissect_options *ndo,
+ u_char np, const struct isakmp_gen *ext, const u_char *ep,
+ u_int32_t phase, u_int32_t doi, u_int32_t proto, int depth)
+{
+ const u_char *cp;
+ int i;
+ int pcount;
+ struct isakmp_gen e;
+
+ cp = (const u_char *)ext;
+ pcount = 0;
+ while (np) {
+ pcount++;
+ ND_TCHECK(*ext);
+
+ safememcpy(&e, ext, sizeof(e));
+
+ ND_TCHECK2(*ext, ntohs(e.len));
+
+ depth++;
+ ND_PRINT((ndo,"\n"));
+ for (i = 0; i < depth; i++)
+ ND_PRINT((ndo," "));
+ ND_PRINT((ndo,"("));
+ cp = ikev2_sub0_print(ndo, np, pcount,
+ ext, ep, phase, doi, proto, depth);
+ ND_PRINT((ndo,")"));
+ depth--;
+
+ if (cp == NULL) {
+ /* Zero-length subitem */
+ return NULL;
}
- printf(":");
+ np = e.np;
+ ext = (struct isakmp_gen *)cp;
+ }
+ return cp;
+trunc:
+ ND_PRINT((ndo," [|%s]", NPSTR(np)));
+ return NULL;
+}
+
+static void
+ikev2_print(netdissect_options *ndo,
+ const u_char *bp, u_int length,
+ const u_char *bp2 _U_, struct isakmp *base)
+{
+ const struct isakmp *p;
+ const u_char *ep;
+ u_char np;
+ int phase;
+
+ p = (const struct isakmp *)bp;
+ ep = ndo->ndo_snapend;
+
+ phase = (*(u_int32_t *)base->msgid == 0) ? 1 : 2;
+ if (phase == 1)
+ ND_PRINT((ndo, " parent_sa"));
+ else
+ ND_PRINT((ndo, " child_sa "));
+
+ ND_PRINT((ndo, " %s", ETYPESTR(base->etype)));
+ if (base->flags) {
+ ND_PRINT((ndo, "[%s%s]",
+ base->flags & ISAKMP_FLAG_I ? "I" : "",
+ base->flags & ISAKMP_FLAG_V ? "V" : "",
+ base->flags & ISAKMP_FLAG_R ? "R" : ""));
+ }
+
+ if (ndo->ndo_vflag) {
+ const struct isakmp_gen *ext;
+ int nparen;
+
+ ND_PRINT((ndo, ":"));
/* regardless of phase... */
- if (base.flags & ISAKMP_FLAG_E) {
+ if (base->flags & ISAKMP_FLAG_E) {
/*
* encrypted, nothing we can do right now.
* we hope to decrypt the packet in the future...
*/
- printf(" [encrypted %s]", NPSTR(base.np));
+ ND_PRINT((ndo, " [encrypted %s]", NPSTR(base->np)));
goto done;
}
nparen = 0;
- CHECKLEN(p + 1, base.np)
+ CHECKLEN(p + 1, base->np)
- np = base.np;
+ np = base->np;
ext = (struct isakmp_gen *)(p + 1);
- isakmp_sub_print(np, ext, ep, phase, 0, 0, 0);
+ ikev2_sub_print(ndo, np, ext, ep, phase, 0, 0, 0);
}
done:
- if (vflag) {
- if (ntohl(base.len) != length) {
- printf(" (len mismatch: isakmp %u/ip %u)",
- (u_int32_t)ntohl(base.len), length);
+ if (ndo->ndo_vflag) {
+ if (ntohl(base->len) != length) {
+ ND_PRINT((ndo, " (len mismatch: isakmp %u/ip %u)",
+ (u_int32_t)ntohl(base->len), length));
}
}
}
void
+isakmp_print(netdissect_options *ndo,
+ const u_char *bp, u_int length,
+ const u_char *bp2)
+{
+ const struct isakmp *p;
+ struct isakmp base;
+ const u_char *ep;
+ int major, minor;
+
+ p = (const struct isakmp *)bp;
+ ep = ndo->ndo_snapend;
+
+ if ((struct isakmp *)ep < p + 1) {
+ ND_PRINT((ndo,"[|isakmp]"));
+ return;
+ }
+
+ safememcpy(&base, p, sizeof(base));
+
+ ND_PRINT((ndo,"isakmp"));
+ major = (base.vers & ISAKMP_VERS_MAJOR)
+ >> ISAKMP_VERS_MAJOR_SHIFT;
+ minor = (base.vers & ISAKMP_VERS_MINOR)
+ >> ISAKMP_VERS_MINOR_SHIFT;
+
+ if (ndo->ndo_vflag) {
+ ND_PRINT((ndo," %d.%d", major, minor));
+ }
+
+ if (ndo->ndo_vflag) {
+ ND_PRINT((ndo," msgid "));
+ rawprint(ndo, (caddr_t)&base.msgid, sizeof(base.msgid));
+ }
+
+ if (1 < ndo->ndo_vflag) {
+ ND_PRINT((ndo," cookie "));
+ rawprint(ndo, (caddr_t)&base.i_ck, sizeof(base.i_ck));
+ ND_PRINT((ndo,"->"));
+ rawprint(ndo, (caddr_t)&base.r_ck, sizeof(base.r_ck));
+ }
+ ND_PRINT((ndo,":"));
+
+ switch(major) {
+ case IKEv1_MAJOR_VERSION:
+ ikev1_print(ndo, bp, length, bp2, &base);
+ break;
+
+ case IKEv2_MAJOR_VERSION:
+ ikev2_print(ndo, bp, length, bp2, &base);
+ break;
+ }
+}
+
+void
isakmp_rfc3948_print(netdissect_options *ndo,
const u_char *bp, u_int length,
const u_char *bp2)
@@ -1403,7 +2355,7 @@ isakmp_rfc3948_print(netdissect_options *ndo,
if(length < 4) {
goto trunc;
}
-
+
/*
* see if this is an IKE packet
*/
@@ -1433,7 +2385,7 @@ isakmp_rfc3948_print(netdissect_options *ndo,
}
trunc:
- printf("[|isakmp]");
+ ND_PRINT((ndo,"[|isakmp]"));
return;
}
diff --git a/contrib/tcpdump/print-isoclns.c b/contrib/tcpdump/print-isoclns.c
index 2ea3a3d..fe06a9c 100644
--- a/contrib/tcpdump/print-isoclns.c
+++ b/contrib/tcpdump/print-isoclns.c
@@ -28,7 +28,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.133.2.25 2007/03/02 09:20:27 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-isoclns.c,v 1.163 2007-03-02 09:16:19 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -49,9 +49,6 @@ static const char rcsid[] _U_ =
#include "gmpls.h"
#include "oui.h"
-#define IPV4 1 /* AFI value */
-#define IPV6 2 /* AFI value */
-
/*
* IS-IS is defined in ISO 10589. Look there for protocol definitions.
*/
@@ -340,7 +337,7 @@ static struct tok clnp_option_qos_global_values[] = {
};
#define ISIS_SUBTLV_EXT_IS_REACH_ADMIN_GROUP 3 /* draft-ietf-isis-traffic-05 */
-#define ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID 4 /* draft-ietf-isis-gmpls-extensions */
+#define ISIS_SUBTLV_EXT_IS_REACH_LINK_LOCAL_REMOTE_ID 4 /* rfc4205 */
#define ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID 5 /* draft-ietf-isis-traffic-05 */
#define ISIS_SUBTLV_EXT_IS_REACH_IPV4_INTF_ADDR 6 /* draft-ietf-isis-traffic-05 */
#define ISIS_SUBTLV_EXT_IS_REACH_IPV4_NEIGHBOR_ADDR 8 /* draft-ietf-isis-traffic-05 */
@@ -349,8 +346,9 @@ static struct tok clnp_option_qos_global_values[] = {
#define ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW 11 /* rfc4124 */
#define ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS_OLD 12 /* draft-ietf-tewg-diff-te-proto-06 */
#define ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC 18 /* draft-ietf-isis-traffic-05 */
-#define ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE 20 /* draft-ietf-isis-gmpls-extensions */
-#define ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR 21 /* draft-ietf-isis-gmpls-extensions */
+#define ISIS_SUBTLV_EXT_IS_REACH_LINK_ATTRIBUTE 19 /* draft-ietf-isis-link-attr-01 */
+#define ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE 20 /* rfc4205 */
+#define ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR 21 /* rfc4205 */
#define ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS 22 /* rfc4124 */
static struct tok isis_ext_is_reach_subtlv_values[] = {
@@ -363,6 +361,7 @@ static struct tok isis_ext_is_reach_subtlv_values[] = {
{ ISIS_SUBTLV_EXT_IS_REACH_RESERVABLE_BW, "Reservable link bandwidth" },
{ ISIS_SUBTLV_EXT_IS_REACH_UNRESERVED_BW, "Unreserved bandwidth" },
{ ISIS_SUBTLV_EXT_IS_REACH_TE_METRIC, "Traffic Engineering Metric" },
+ { ISIS_SUBTLV_EXT_IS_REACH_LINK_ATTRIBUTE, "Link Attribute" },
{ ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE, "Link Protection Type" },
{ ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR, "Interface Switching Capability" },
{ ISIS_SUBTLV_EXT_IS_REACH_BW_CONSTRAINTS_OLD, "Bandwidth Constraints (old)" },
@@ -387,6 +386,13 @@ static struct tok isis_ext_ip_reach_subtlv_values[] = {
{ 0, NULL }
};
+static struct tok isis_subtlv_link_attribute_values[] = {
+ { 0x01, "Local Protection Available" },
+ { 0x02, "Link excluded from local protection path" },
+ { 0x04, "Local maintenance required"},
+ { 0, NULL }
+};
+
#define ISIS_SUBTLV_AUTH_SIMPLE 1
#define ISIS_SUBTLV_AUTH_MD5 54
#define ISIS_SUBTLV_AUTH_MD5_LEN 16
@@ -504,7 +510,8 @@ struct isis_tlv_ptp_adj {
u_int8_t neighbor_extd_local_circuit_id[4];
};
-static int osi_cksum(const u_int8_t *, u_int);
+static void osi_print_cksum(const u_int8_t *pptr, u_int16_t checksum,
+ u_int checksum_offset, u_int length);
static int clnp_print(const u_int8_t *, u_int);
static void esis_print(const u_int8_t *, u_int);
static int isis_print(const u_int8_t *, u_int);
@@ -767,7 +774,7 @@ static int clnp_print (const u_int8_t *pptr, u_int length)
}
printf("%slength %u",eflag ? "" : ", ",length);
- printf("\n\t%s PDU, hlen: %u, v: %u, lifetime: %u.%us, Segment PDU length: %u, checksum: 0x%04x ",
+ printf("\n\t%s PDU, hlen: %u, v: %u, lifetime: %u.%us, Segment PDU length: %u, checksum: 0x%04x",
tok2str(clnp_pdu_values, "unknown (%u)",clnp_pdu_type),
clnp_header->length_indicator,
clnp_header->version,
@@ -776,10 +783,8 @@ static int clnp_print (const u_int8_t *pptr, u_int length)
EXTRACT_16BITS(clnp_header->segment_length),
EXTRACT_16BITS(clnp_header->cksum));
- /* do not attempt to verify the checksum if it is zero */
- if (EXTRACT_16BITS(clnp_header->cksum) == 0)
- printf("(unverified)");
- else printf("(%s)", osi_cksum(optr, clnp_header->length_indicator) ? "incorrect" : "correct");
+ osi_print_cksum(optr, EXTRACT_16BITS(clnp_header->cksum), 7,
+ clnp_header->length_indicator);
printf("\n\tFlags [%s]",
bittok2str(clnp_flag_values,"none",clnp_flags));
@@ -1033,12 +1038,9 @@ esis_print(const u_int8_t *pptr, u_int length)
esis_pdu_type);
printf(", v: %u%s", esis_header->version, esis_header->version == ESIS_VERSION ? "" : "unsupported" );
- printf(", checksum: 0x%04x ", EXTRACT_16BITS(esis_header->cksum));
- /* do not attempt to verify the checksum if it is zero */
- if (EXTRACT_16BITS(esis_header->cksum) == 0)
- printf("(unverified)");
- else
- printf("(%s)", osi_cksum(pptr, li) ? "incorrect" : "correct");
+ printf(", checksum: 0x%04x", EXTRACT_16BITS(esis_header->cksum));
+
+ osi_print_cksum(pptr, EXTRACT_16BITS(esis_header->cksum), 7, li);
printf(", holding time: %us, length indicator: %u",EXTRACT_16BITS(esis_header->holdtime),li);
@@ -1413,7 +1415,7 @@ trunctlv:
static int
isis_print_is_reach_subtlv (const u_int8_t *tptr,u_int subt,u_int subl,const char *ident) {
- u_int te_class,priority_level;
+ u_int te_class,priority_level,gmpls_switch_cap;
union { /* int to float conversion buffer for several subTLVs */
float f;
u_int32_t i;
@@ -1437,7 +1439,7 @@ isis_print_is_reach_subtlv (const u_int8_t *tptr,u_int subt,u_int subl,const cha
case ISIS_SUBTLV_EXT_IS_REACH_LINK_REMOTE_ID:
if (subl >= 4) {
printf(", 0x%08x", EXTRACT_32BITS(tptr));
- if (subl == 8) /* draft-ietf-isis-gmpls-extensions */
+ if (subl == 8) /* rfc4205 */
printf(", 0x%08x", EXTRACT_32BITS(tptr+4));
}
break;
@@ -1486,6 +1488,15 @@ isis_print_is_reach_subtlv (const u_int8_t *tptr,u_int subt,u_int subl,const cha
if (subl >= 3)
printf(", %u", EXTRACT_24BITS(tptr));
break;
+ case ISIS_SUBTLV_EXT_IS_REACH_LINK_ATTRIBUTE:
+ if (subl == 2) {
+ printf(", [ %s ] (0x%04x)",
+ bittok2str(isis_subtlv_link_attribute_values,
+ "Unknown",
+ EXTRACT_16BITS(tptr)),
+ EXTRACT_16BITS(tptr));
+ }
+ break;
case ISIS_SUBTLV_EXT_IS_REACH_LINK_PROTECTION_TYPE:
if (subl >= 2) {
printf(", %s, Priority %u",
@@ -1495,9 +1506,10 @@ isis_print_is_reach_subtlv (const u_int8_t *tptr,u_int subt,u_int subl,const cha
break;
case ISIS_SUBTLV_EXT_IS_REACH_INTF_SW_CAP_DESCR:
if (subl >= 36) {
+ gmpls_switch_cap = *tptr;
printf("%s Interface Switching Capability:%s",
ident,
- tok2str(gmpls_switch_cap_values, "Unknown", *(tptr)));
+ tok2str(gmpls_switch_cap_values, "Unknown", gmpls_switch_cap));
printf(", LSP Encoding: %s",
tok2str(gmpls_encoding_values, "Unknown", *(tptr+1)));
tptr+=4;
@@ -1511,12 +1523,29 @@ isis_print_is_reach_subtlv (const u_int8_t *tptr,u_int subt,u_int subl,const cha
tptr+=4;
}
subl-=36;
- /* there is some optional stuff left to decode but this is as of yet
- not specified so just lets hexdump what is left */
- if(subl>0){
- if(!print_unknown_data(tptr,"\n\t\t ",
- subl))
+ switch (gmpls_switch_cap) {
+ case GMPLS_PSC1:
+ case GMPLS_PSC2:
+ case GMPLS_PSC3:
+ case GMPLS_PSC4:
+ bw.i = EXTRACT_32BITS(tptr);
+ printf("%s Min LSP Bandwidth: %.3f Mbps", ident, bw.f*8/1000000);
+ printf("%s Interface MTU: %u", ident, EXTRACT_16BITS(tptr+4));
+ break;
+ case GMPLS_TSC:
+ bw.i = EXTRACT_32BITS(tptr);
+ printf("%s Min LSP Bandwidth: %.3f Mbps", ident, bw.f*8/1000000);
+ printf("%s Indication %s", ident,
+ tok2str(gmpls_switch_cap_tsc_indication_values, "Unknown (%u)", *(tptr+4)));
+ break;
+ default:
+ /* there is some optional stuff left to decode but this is as of yet
+ not specified so just lets hexdump what is left */
+ if(subl>0){
+ if(!print_unknown_data(tptr,"\n\t\t ",
+ subl))
return(0);
+ }
}
}
break;
@@ -1631,7 +1660,7 @@ isis_print_extd_ip_reach (const u_int8_t *tptr, const char *ident, u_int16_t afi
processed=4;
tptr+=4;
- if (afi == IPV4) {
+ if (afi == AF_INET) {
if (!TTEST2(*tptr, 1)) /* fetch status byte */
return (0);
status_byte=*(tptr++);
@@ -1644,7 +1673,7 @@ isis_print_extd_ip_reach (const u_int8_t *tptr, const char *ident, u_int16_t afi
}
processed++;
#ifdef INET6
- } else if (afi == IPV6) {
+ } else if (afi == AF_INET6) {
if (!TTEST2(*tptr, 1)) /* fetch status & prefix_len byte */
return (0);
status_byte=*(tptr++);
@@ -1669,13 +1698,13 @@ isis_print_extd_ip_reach (const u_int8_t *tptr, const char *ident, u_int16_t afi
tptr+=byte_length;
processed+=byte_length;
- if (afi == IPV4)
+ if (afi == AF_INET)
printf("%sIPv4 prefix: %15s/%u",
ident,
ipaddr_string(prefix),
bit_length);
#ifdef INET6
- if (afi == IPV6)
+ if (afi == AF_INET6)
printf("%sIPv6 prefix: %s/%u",
ident,
ip6addr_string(prefix),
@@ -1686,17 +1715,20 @@ isis_print_extd_ip_reach (const u_int8_t *tptr, const char *ident, u_int16_t afi
ISIS_MASK_TLV_EXTD_IP_UPDOWN(status_byte) ? "down" : "up",
metric);
- if (afi == IPV4 && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte))
+ if (afi == AF_INET && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte))
printf(", sub-TLVs present");
#ifdef INET6
- if (afi == IPV6)
+ if (afi == AF_INET6)
printf(", %s%s",
ISIS_MASK_TLV_EXTD_IP6_IE(status_byte) ? "External" : "Internal",
ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) ? ", sub-TLVs present" : "");
#endif
- if ((ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte) && afi == IPV4) ||
- (ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte) && afi == IPV6)) {
+ if ((afi == AF_INET && ISIS_MASK_TLV_EXTD_IP_SUBTLV(status_byte))
+#ifdef INET6
+ || (afi == AF_INET6 && ISIS_MASK_TLV_EXTD_IP6_SUBTLV(status_byte))
+#endif
+ ) {
/* assume that one prefix can hold more
than one subTLV - therefore the first byte must reflect
the aggregate bytecount of the subTLVs for this prefix
@@ -1979,15 +2011,9 @@ static int isis_print (const u_int8_t *p, u_int length)
EXTRACT_16BITS(header_lsp->remaining_lifetime),
EXTRACT_16BITS(header_lsp->checksum));
- /* if this is a purge do not attempt to verify the checksum */
- if ( EXTRACT_16BITS(header_lsp->remaining_lifetime) == 0 &&
- EXTRACT_16BITS(header_lsp->checksum) == 0)
- printf(" (purged)");
- else
- /* verify the checksum -
- * checking starts at the lsp-id field at byte position [12]
- * hence the length needs to be reduced by 12 bytes */
- printf(" (%s)", (osi_cksum((u_int8_t *)header_lsp->lsp_id, length-12)) ? "incorrect" : "correct");
+
+ osi_print_cksum((u_int8_t *)header_lsp->lsp_id,
+ EXTRACT_16BITS(header_lsp->checksum), 12, length-12);
printf(", PDU length: %u, Flags: [ %s",
pdu_len,
@@ -2240,7 +2266,7 @@ static int isis_print (const u_int8_t *p, u_int length)
case ISIS_TLV_EXTD_IP_REACH:
while (tmp>0) {
- ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV4);
+ ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", AF_INET);
if (ext_ip_len == 0) /* did something go wrong ? */
goto trunctlv;
tptr+=ext_ip_len;
@@ -2257,7 +2283,7 @@ static int isis_print (const u_int8_t *p, u_int length)
tmp-=mt_len;
while (tmp>0) {
- ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV4);
+ ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", AF_INET);
if (ext_ip_len == 0) /* did something go wrong ? */
goto trunctlv;
tptr+=ext_ip_len;
@@ -2268,7 +2294,7 @@ static int isis_print (const u_int8_t *p, u_int length)
#ifdef INET6
case ISIS_TLV_IP6_REACH:
while (tmp>0) {
- ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV6);
+ ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", AF_INET6);
if (ext_ip_len == 0) /* did something go wrong ? */
goto trunctlv;
tptr+=ext_ip_len;
@@ -2285,7 +2311,7 @@ static int isis_print (const u_int8_t *p, u_int length)
tmp-=mt_len;
while (tmp>0) {
- ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", IPV6);
+ ext_ip_len = isis_print_extd_ip_reach(tptr, "\n\t ", AF_INET6);
if (ext_ip_len == 0) /* did something go wrong ? */
goto trunctlv;
tptr+=ext_ip_len;
@@ -2490,9 +2516,7 @@ static int isis_print (const u_int8_t *p, u_int length)
* to avoid conflicts the checksum TLV is zeroed.
* see rfc3358 for details
*/
- if (EXTRACT_16BITS(tptr) == 0)
- printf("(unverified)");
- else printf("(%s)", osi_cksum(optr, length) ? "incorrect" : "correct");
+ osi_print_cksum(optr, EXTRACT_16BITS(tptr), tptr-optr, length);
break;
case ISIS_TLV_MT_SUPPORTED:
@@ -2684,25 +2708,25 @@ static int isis_print (const u_int8_t *p, u_int length)
return(1);
}
-/*
- * Verify the checksum. See 8473-1, Appendix C, section C.4.
- */
-
-static int
-osi_cksum(const u_int8_t *tptr, u_int len)
+static void
+osi_print_cksum (const u_int8_t *pptr, u_int16_t checksum,
+ u_int checksum_offset, u_int length)
{
- int32_t c0 = 0, c1 = 0;
+ u_int16_t calculated_checksum;
- while ((int)--len >= 0) {
- c0 += *tptr++;
- c0 %= 255;
- c1 += c0;
- c1 %= 255;
- }
- return (c0 | c1);
+ /* do not attempt to verify the checksum if it is zero */
+ if (!checksum) {
+ printf("(unverified)");
+ } else {
+ calculated_checksum = create_osi_cksum(pptr, checksum_offset, length);
+ if (checksum == calculated_checksum) {
+ printf(" (correct)");
+ } else {
+ printf(" (incorrect should be 0x%04x)", calculated_checksum);
+ }
+ }
}
-
/*
* Local Variables:
* c-style: whitesmith
diff --git a/contrib/tcpdump/print-juniper.c b/contrib/tcpdump/print-juniper.c
index b5837e3..08a929f 100644
--- a/contrib/tcpdump/print-juniper.c
+++ b/contrib/tcpdump/print-juniper.c
@@ -1,3 +1,5 @@
+/* NetBSD: print-juniper.c,v 1.2 2007/07/24 11:53:45 drochner Exp */
+
/*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code
@@ -15,7 +17,9 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.8.2.22 2006/05/10 22:42:46 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.34 2007-08-29 02:31:44 mcr Exp $ (LBL)";
+#else
+__RCSID("NetBSD: print-juniper.c,v 1.3 2007/07/25 06:31:32 dogcow Exp ");
#endif
#ifdef HAVE_CONFIG_H
@@ -40,6 +44,8 @@ static const char rcsid[] _U_ =
#define JUNIPER_BPF_IN 1 /* Incoming packet */
#define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
#define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
+#define JUNIPER_BPF_IIF 0x4 /* IIF is valid */
+#define JUNIPER_BPF_FILTER 0x40 /* BPF filtering is supported */
#define JUNIPER_BPF_EXT 0x80 /* extensions present */
#define JUNIPER_MGC_NUMBER 0x4d4743 /* = "MGC" */
@@ -74,6 +80,291 @@ static struct tok juniper_direction_values[] = {
{ 0, NULL}
};
+/* codepoints for encoding extensions to a .pcap file */
+enum {
+ JUNIPER_EXT_TLV_IFD_IDX = 1,
+ JUNIPER_EXT_TLV_IFD_NAME = 2,
+ JUNIPER_EXT_TLV_IFD_MEDIATYPE = 3,
+ JUNIPER_EXT_TLV_IFL_IDX = 4,
+ JUNIPER_EXT_TLV_IFL_UNIT = 5,
+ JUNIPER_EXT_TLV_IFL_ENCAPS = 6,
+ JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE = 7,
+ JUNIPER_EXT_TLV_TTP_IFL_ENCAPS = 8
+};
+
+/* 1 byte type and 1-byte length */
+#define JUNIPER_EXT_TLV_OVERHEAD 2
+
+struct tok jnx_ext_tlv_values[] = {
+ { JUNIPER_EXT_TLV_IFD_IDX, "Device Interface Index" },
+ { JUNIPER_EXT_TLV_IFD_NAME,"Device Interface Name" },
+ { JUNIPER_EXT_TLV_IFD_MEDIATYPE, "Device Media Type" },
+ { JUNIPER_EXT_TLV_IFL_IDX, "Logical Interface Index" },
+ { JUNIPER_EXT_TLV_IFL_UNIT,"Logical Unit Number" },
+ { JUNIPER_EXT_TLV_IFL_ENCAPS, "Logical Interface Encapsulation" },
+ { JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE, "TTP derived Device Media Type" },
+ { JUNIPER_EXT_TLV_TTP_IFL_ENCAPS, "TTP derived Logical Interface Encapsulation" },
+ { 0, NULL }
+};
+
+struct tok jnx_flag_values[] = {
+ { JUNIPER_BPF_EXT, "Ext" },
+ { JUNIPER_BPF_FILTER, "Filter" },
+ { JUNIPER_BPF_IIF, "IIF" },
+ { JUNIPER_BPF_NO_L2, "no-L2" },
+ { JUNIPER_BPF_PKT_IN, "In" },
+ { 0, NULL }
+};
+
+#define JUNIPER_IFML_ETHER 1
+#define JUNIPER_IFML_FDDI 2
+#define JUNIPER_IFML_TOKENRING 3
+#define JUNIPER_IFML_PPP 4
+#define JUNIPER_IFML_FRAMERELAY 5
+#define JUNIPER_IFML_CISCOHDLC 6
+#define JUNIPER_IFML_SMDSDXI 7
+#define JUNIPER_IFML_ATMPVC 8
+#define JUNIPER_IFML_PPP_CCC 9
+#define JUNIPER_IFML_FRAMERELAY_CCC 10
+#define JUNIPER_IFML_IPIP 11
+#define JUNIPER_IFML_GRE 12
+#define JUNIPER_IFML_PIM 13
+#define JUNIPER_IFML_PIMD 14
+#define JUNIPER_IFML_CISCOHDLC_CCC 15
+#define JUNIPER_IFML_VLAN_CCC 16
+#define JUNIPER_IFML_MLPPP 17
+#define JUNIPER_IFML_MLFR 18
+#define JUNIPER_IFML_ML 19
+#define JUNIPER_IFML_LSI 20
+#define JUNIPER_IFML_DFE 21
+#define JUNIPER_IFML_ATM_CELLRELAY_CCC 22
+#define JUNIPER_IFML_CRYPTO 23
+#define JUNIPER_IFML_GGSN 24
+#define JUNIPER_IFML_LSI_PPP 25
+#define JUNIPER_IFML_LSI_CISCOHDLC 26
+#define JUNIPER_IFML_PPP_TCC 27
+#define JUNIPER_IFML_FRAMERELAY_TCC 28
+#define JUNIPER_IFML_CISCOHDLC_TCC 29
+#define JUNIPER_IFML_ETHERNET_CCC 30
+#define JUNIPER_IFML_VT 31
+#define JUNIPER_IFML_EXTENDED_VLAN_CCC 32
+#define JUNIPER_IFML_ETHER_OVER_ATM 33
+#define JUNIPER_IFML_MONITOR 34
+#define JUNIPER_IFML_ETHERNET_TCC 35
+#define JUNIPER_IFML_VLAN_TCC 36
+#define JUNIPER_IFML_EXTENDED_VLAN_TCC 37
+#define JUNIPER_IFML_CONTROLLER 38
+#define JUNIPER_IFML_MFR 39
+#define JUNIPER_IFML_LS 40
+#define JUNIPER_IFML_ETHERNET_VPLS 41
+#define JUNIPER_IFML_ETHERNET_VLAN_VPLS 42
+#define JUNIPER_IFML_ETHERNET_EXTENDED_VLAN_VPLS 43
+#define JUNIPER_IFML_LT 44
+#define JUNIPER_IFML_SERVICES 45
+#define JUNIPER_IFML_ETHER_VPLS_OVER_ATM 46
+#define JUNIPER_IFML_FR_PORT_CCC 47
+#define JUNIPER_IFML_FRAMERELAY_EXT_CCC 48
+#define JUNIPER_IFML_FRAMERELAY_EXT_TCC 49
+#define JUNIPER_IFML_FRAMERELAY_FLEX 50
+#define JUNIPER_IFML_GGSNI 51
+#define JUNIPER_IFML_ETHERNET_FLEX 52
+#define JUNIPER_IFML_COLLECTOR 53
+#define JUNIPER_IFML_AGGREGATOR 54
+#define JUNIPER_IFML_LAPD 55
+#define JUNIPER_IFML_PPPOE 56
+#define JUNIPER_IFML_PPP_SUBORDINATE 57
+#define JUNIPER_IFML_CISCOHDLC_SUBORDINATE 58
+#define JUNIPER_IFML_DFC 59
+#define JUNIPER_IFML_PICPEER 60
+
+struct tok juniper_ifmt_values[] = {
+ { JUNIPER_IFML_ETHER, "Ethernet" },
+ { JUNIPER_IFML_FDDI, "FDDI" },
+ { JUNIPER_IFML_TOKENRING, "Token-Ring" },
+ { JUNIPER_IFML_PPP, "PPP" },
+ { JUNIPER_IFML_PPP_SUBORDINATE, "PPP-Subordinate" },
+ { JUNIPER_IFML_FRAMERELAY, "Frame-Relay" },
+ { JUNIPER_IFML_CISCOHDLC, "Cisco-HDLC" },
+ { JUNIPER_IFML_SMDSDXI, "SMDS-DXI" },
+ { JUNIPER_IFML_ATMPVC, "ATM-PVC" },
+ { JUNIPER_IFML_PPP_CCC, "PPP-CCC" },
+ { JUNIPER_IFML_FRAMERELAY_CCC, "Frame-Relay-CCC" },
+ { JUNIPER_IFML_FRAMERELAY_EXT_CCC, "Extended FR-CCC" },
+ { JUNIPER_IFML_IPIP, "IP-over-IP" },
+ { JUNIPER_IFML_GRE, "GRE" },
+ { JUNIPER_IFML_PIM, "PIM-Encapsulator" },
+ { JUNIPER_IFML_PIMD, "PIM-Decapsulator" },
+ { JUNIPER_IFML_CISCOHDLC_CCC, "Cisco-HDLC-CCC" },
+ { JUNIPER_IFML_VLAN_CCC, "VLAN-CCC" },
+ { JUNIPER_IFML_EXTENDED_VLAN_CCC, "Extended-VLAN-CCC" },
+ { JUNIPER_IFML_MLPPP, "Multilink-PPP" },
+ { JUNIPER_IFML_MLFR, "Multilink-FR" },
+ { JUNIPER_IFML_MFR, "Multilink-FR-UNI-NNI" },
+ { JUNIPER_IFML_ML, "Multilink" },
+ { JUNIPER_IFML_LS, "LinkService" },
+ { JUNIPER_IFML_LSI, "LSI" },
+ { JUNIPER_IFML_ATM_CELLRELAY_CCC, "ATM-CCC-Cell-Relay" },
+ { JUNIPER_IFML_CRYPTO, "IPSEC-over-IP" },
+ { JUNIPER_IFML_GGSN, "GGSN" },
+ { JUNIPER_IFML_PPP_TCC, "PPP-TCC" },
+ { JUNIPER_IFML_FRAMERELAY_TCC, "Frame-Relay-TCC" },
+ { JUNIPER_IFML_FRAMERELAY_EXT_TCC, "Extended FR-TCC" },
+ { JUNIPER_IFML_CISCOHDLC_TCC, "Cisco-HDLC-TCC" },
+ { JUNIPER_IFML_ETHERNET_CCC, "Ethernet-CCC" },
+ { JUNIPER_IFML_VT, "VPN-Loopback-tunnel" },
+ { JUNIPER_IFML_ETHER_OVER_ATM, "Ethernet-over-ATM" },
+ { JUNIPER_IFML_ETHER_VPLS_OVER_ATM, "Ethernet-VPLS-over-ATM" },
+ { JUNIPER_IFML_MONITOR, "Monitor" },
+ { JUNIPER_IFML_ETHERNET_TCC, "Ethernet-TCC" },
+ { JUNIPER_IFML_VLAN_TCC, "VLAN-TCC" },
+ { JUNIPER_IFML_EXTENDED_VLAN_TCC, "Extended-VLAN-TCC" },
+ { JUNIPER_IFML_CONTROLLER, "Controller" },
+ { JUNIPER_IFML_ETHERNET_VPLS, "VPLS" },
+ { JUNIPER_IFML_ETHERNET_VLAN_VPLS, "VLAN-VPLS" },
+ { JUNIPER_IFML_ETHERNET_EXTENDED_VLAN_VPLS, "Extended-VLAN-VPLS" },
+ { JUNIPER_IFML_LT, "Logical-tunnel" },
+ { JUNIPER_IFML_SERVICES, "General-Services" },
+ { JUNIPER_IFML_PPPOE, "PPPoE" },
+ { JUNIPER_IFML_ETHERNET_FLEX, "Flexible-Ethernet-Services" },
+ { JUNIPER_IFML_FRAMERELAY_FLEX, "Flexible-FrameRelay" },
+ { JUNIPER_IFML_COLLECTOR, "Flow-collection" },
+ { JUNIPER_IFML_PICPEER, "PIC Peer" },
+ { JUNIPER_IFML_DFC, "Dynamic-Flow-Capture" },
+ {0, NULL}
+};
+
+#define JUNIPER_IFLE_ATM_SNAP 2
+#define JUNIPER_IFLE_ATM_NLPID 3
+#define JUNIPER_IFLE_ATM_VCMUX 4
+#define JUNIPER_IFLE_ATM_LLC 5
+#define JUNIPER_IFLE_ATM_PPP_VCMUX 6
+#define JUNIPER_IFLE_ATM_PPP_LLC 7
+#define JUNIPER_IFLE_ATM_PPP_FUNI 8
+#define JUNIPER_IFLE_ATM_CCC 9
+#define JUNIPER_IFLE_FR_NLPID 10
+#define JUNIPER_IFLE_FR_SNAP 11
+#define JUNIPER_IFLE_FR_PPP 12
+#define JUNIPER_IFLE_FR_CCC 13
+#define JUNIPER_IFLE_ENET2 14
+#define JUNIPER_IFLE_IEEE8023_SNAP 15
+#define JUNIPER_IFLE_IEEE8023_LLC 16
+#define JUNIPER_IFLE_PPP 17
+#define JUNIPER_IFLE_CISCOHDLC 18
+#define JUNIPER_IFLE_PPP_CCC 19
+#define JUNIPER_IFLE_IPIP_NULL 20
+#define JUNIPER_IFLE_PIM_NULL 21
+#define JUNIPER_IFLE_GRE_NULL 22
+#define JUNIPER_IFLE_GRE_PPP 23
+#define JUNIPER_IFLE_PIMD_DECAPS 24
+#define JUNIPER_IFLE_CISCOHDLC_CCC 25
+#define JUNIPER_IFLE_ATM_CISCO_NLPID 26
+#define JUNIPER_IFLE_VLAN_CCC 27
+#define JUNIPER_IFLE_MLPPP 28
+#define JUNIPER_IFLE_MLFR 29
+#define JUNIPER_IFLE_LSI_NULL 30
+#define JUNIPER_IFLE_AGGREGATE_UNUSED 31
+#define JUNIPER_IFLE_ATM_CELLRELAY_CCC 32
+#define JUNIPER_IFLE_CRYPTO 33
+#define JUNIPER_IFLE_GGSN 34
+#define JUNIPER_IFLE_ATM_TCC 35
+#define JUNIPER_IFLE_FR_TCC 36
+#define JUNIPER_IFLE_PPP_TCC 37
+#define JUNIPER_IFLE_CISCOHDLC_TCC 38
+#define JUNIPER_IFLE_ETHERNET_CCC 39
+#define JUNIPER_IFLE_VT 40
+#define JUNIPER_IFLE_ATM_EOA_LLC 41
+#define JUNIPER_IFLE_EXTENDED_VLAN_CCC 42
+#define JUNIPER_IFLE_ATM_SNAP_TCC 43
+#define JUNIPER_IFLE_MONITOR 44
+#define JUNIPER_IFLE_ETHERNET_TCC 45
+#define JUNIPER_IFLE_VLAN_TCC 46
+#define JUNIPER_IFLE_EXTENDED_VLAN_TCC 47
+#define JUNIPER_IFLE_MFR 48
+#define JUNIPER_IFLE_ETHERNET_VPLS 49
+#define JUNIPER_IFLE_ETHERNET_VLAN_VPLS 50
+#define JUNIPER_IFLE_ETHERNET_EXTENDED_VLAN_VPLS 51
+#define JUNIPER_IFLE_SERVICES 52
+#define JUNIPER_IFLE_ATM_ETHER_VPLS_ATM_LLC 53
+#define JUNIPER_IFLE_FR_PORT_CCC 54
+#define JUNIPER_IFLE_ATM_MLPPP_LLC 55
+#define JUNIPER_IFLE_ATM_EOA_CCC 56
+#define JUNIPER_IFLE_LT_VLAN 57
+#define JUNIPER_IFLE_COLLECTOR 58
+#define JUNIPER_IFLE_AGGREGATOR 59
+#define JUNIPER_IFLE_LAPD 60
+#define JUNIPER_IFLE_ATM_PPPOE_LLC 61
+#define JUNIPER_IFLE_ETHERNET_PPPOE 62
+#define JUNIPER_IFLE_PPPOE 63
+#define JUNIPER_IFLE_PPP_SUBORDINATE 64
+#define JUNIPER_IFLE_CISCOHDLC_SUBORDINATE 65
+#define JUNIPER_IFLE_DFC 66
+#define JUNIPER_IFLE_PICPEER 67
+
+struct tok juniper_ifle_values[] = {
+ { JUNIPER_IFLE_AGGREGATOR, "Aggregator" },
+ { JUNIPER_IFLE_ATM_CCC, "CCC over ATM" },
+ { JUNIPER_IFLE_ATM_CELLRELAY_CCC, "ATM CCC Cell Relay" },
+ { JUNIPER_IFLE_ATM_CISCO_NLPID, "CISCO compatible NLPID" },
+ { JUNIPER_IFLE_ATM_EOA_CCC, "Ethernet over ATM CCC" },
+ { JUNIPER_IFLE_ATM_EOA_LLC, "Ethernet over ATM LLC" },
+ { JUNIPER_IFLE_ATM_ETHER_VPLS_ATM_LLC, "Ethernet VPLS over ATM LLC" },
+ { JUNIPER_IFLE_ATM_LLC, "ATM LLC" },
+ { JUNIPER_IFLE_ATM_MLPPP_LLC, "MLPPP over ATM LLC" },
+ { JUNIPER_IFLE_ATM_NLPID, "ATM NLPID" },
+ { JUNIPER_IFLE_ATM_PPPOE_LLC, "PPPoE over ATM LLC" },
+ { JUNIPER_IFLE_ATM_PPP_FUNI, "PPP over FUNI" },
+ { JUNIPER_IFLE_ATM_PPP_LLC, "PPP over ATM LLC" },
+ { JUNIPER_IFLE_ATM_PPP_VCMUX, "PPP over ATM VCMUX" },
+ { JUNIPER_IFLE_ATM_SNAP, "ATM SNAP" },
+ { JUNIPER_IFLE_ATM_SNAP_TCC, "ATM SNAP TCC" },
+ { JUNIPER_IFLE_ATM_TCC, "ATM VCMUX TCC" },
+ { JUNIPER_IFLE_ATM_VCMUX, "ATM VCMUX" },
+ { JUNIPER_IFLE_CISCOHDLC, "C-HDLC" },
+ { JUNIPER_IFLE_CISCOHDLC_CCC, "C-HDLC CCC" },
+ { JUNIPER_IFLE_CISCOHDLC_SUBORDINATE, "C-HDLC via dialer" },
+ { JUNIPER_IFLE_CISCOHDLC_TCC, "C-HDLC TCC" },
+ { JUNIPER_IFLE_COLLECTOR, "Collector" },
+ { JUNIPER_IFLE_CRYPTO, "Crypto" },
+ { JUNIPER_IFLE_ENET2, "Ethernet" },
+ { JUNIPER_IFLE_ETHERNET_CCC, "Ethernet CCC" },
+ { JUNIPER_IFLE_ETHERNET_EXTENDED_VLAN_VPLS, "Extended VLAN VPLS" },
+ { JUNIPER_IFLE_ETHERNET_PPPOE, "PPPoE over Ethernet" },
+ { JUNIPER_IFLE_ETHERNET_TCC, "Ethernet TCC" },
+ { JUNIPER_IFLE_ETHERNET_VLAN_VPLS, "VLAN VPLS" },
+ { JUNIPER_IFLE_ETHERNET_VPLS, "VPLS" },
+ { JUNIPER_IFLE_EXTENDED_VLAN_CCC, "Extended VLAN CCC" },
+ { JUNIPER_IFLE_EXTENDED_VLAN_TCC, "Extended VLAN TCC" },
+ { JUNIPER_IFLE_FR_CCC, "FR CCC" },
+ { JUNIPER_IFLE_FR_NLPID, "FR NLPID" },
+ { JUNIPER_IFLE_FR_PORT_CCC, "FR CCC" },
+ { JUNIPER_IFLE_FR_PPP, "FR PPP" },
+ { JUNIPER_IFLE_FR_SNAP, "FR SNAP" },
+ { JUNIPER_IFLE_FR_TCC, "FR TCC" },
+ { JUNIPER_IFLE_GGSN, "GGSN" },
+ { JUNIPER_IFLE_GRE_NULL, "GRE NULL" },
+ { JUNIPER_IFLE_GRE_PPP, "PPP over GRE" },
+ { JUNIPER_IFLE_IPIP_NULL, "IPIP" },
+ { JUNIPER_IFLE_LAPD, "LAPD" },
+ { JUNIPER_IFLE_LSI_NULL, "LSI Null" },
+ { JUNIPER_IFLE_LT_VLAN, "LT VLAN" },
+ { JUNIPER_IFLE_MFR, "MFR" },
+ { JUNIPER_IFLE_MLFR, "MLFR" },
+ { JUNIPER_IFLE_MLPPP, "MLPPP" },
+ { JUNIPER_IFLE_MONITOR, "Monitor" },
+ { JUNIPER_IFLE_PIMD_DECAPS, "PIMd" },
+ { JUNIPER_IFLE_PIM_NULL, "PIM Null" },
+ { JUNIPER_IFLE_PPP, "PPP" },
+ { JUNIPER_IFLE_PPPOE, "PPPoE" },
+ { JUNIPER_IFLE_PPP_CCC, "PPP CCC" },
+ { JUNIPER_IFLE_PPP_SUBORDINATE, "" },
+ { JUNIPER_IFLE_PPP_TCC, "PPP TCC" },
+ { JUNIPER_IFLE_SERVICES, "General Services" },
+ { JUNIPER_IFLE_VLAN_CCC, "VLAN CCC" },
+ { JUNIPER_IFLE_VLAN_TCC, "VLAN TCC" },
+ { JUNIPER_IFLE_VT, "VT" },
+ {0, NULL}
+};
+
struct juniper_cookie_table_t {
u_int32_t pictype; /* pic type */
u_int8_t cookie_len; /* cookie len */
@@ -128,6 +419,7 @@ struct juniper_l2info_t {
u_int8_t cookie[8];
u_int8_t bundle;
u_int16_t proto;
+ u_int8_t flags;
};
#define LS_COOKIE_ID 0x54
@@ -156,6 +448,7 @@ static struct tok juniper_protocol_values[] = {
int ip_heuristic_guess(register const u_char *, u_int);
int juniper_ppp_heuristic_guess(register const u_char *, u_int);
+int juniper_read_tlv_value(const u_char *, u_int, u_int);
static int juniper_parse_header (const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
#ifdef DLT_JUNIPER_GGSN
@@ -178,13 +471,14 @@ juniper_ggsn_print(const struct pcap_pkthdr *h, register const u_char *p)
return l2info.header_len;
p+=l2info.header_len;
- gh = (struct juniper_ggsn_header *)p;
+ gh = (struct juniper_ggsn_header *)&l2info.cookie;
- if (eflag)
+ if (eflag) {
printf("proto %s (%u), vlan %u: ",
tok2str(juniper_protocol_values,"Unknown",gh->proto),
gh->proto,
EXTRACT_16BITS(&gh->vlan_id[0]));
+ }
switch (gh->proto) {
case JUNIPER_PROTO_IPV4:
@@ -256,8 +550,8 @@ juniper_es_print(const struct pcap_pkthdr *h, register const u_char *p)
tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
ih->type,
EXTRACT_32BITS(&ih->spi),
- ipaddr_string(EXTRACT_32BITS(&ih->src_ip)),
- ipaddr_string(EXTRACT_32BITS(&ih->dst_ip)),
+ ipaddr_string(&ih->src_ip),
+ ipaddr_string(&ih->dst_ip),
l2info.length);
} else {
printf("ES SA, index %u, ttl %u type %s (%u), length %u\n",
@@ -790,14 +1084,63 @@ ip_heuristic_guess(register const u_char *p, u_int length) {
return 1; /* we printed an v4/v6 packet */
}
+int
+juniper_read_tlv_value(const u_char *p, u_int tlv_type, u_int tlv_len) {
+
+ int tlv_value;
+
+ /* TLVs < 128 are little endian encoded */
+ if (tlv_type < 128) {
+ switch (tlv_len) {
+ case 1:
+ tlv_value = *p;
+ break;
+ case 2:
+ tlv_value = EXTRACT_LE_16BITS(p);
+ break;
+ case 3:
+ tlv_value = EXTRACT_LE_24BITS(p);
+ break;
+ case 4:
+ tlv_value = EXTRACT_LE_32BITS(p);
+ break;
+ default:
+ tlv_value = -1;
+ break;
+ }
+ } else {
+ /* TLVs >= 128 are big endian encoded */
+ switch (tlv_len) {
+ case 1:
+ tlv_value = *p;
+ break;
+ case 2:
+ tlv_value = EXTRACT_16BITS(p);
+ break;
+ case 3:
+ tlv_value = EXTRACT_24BITS(p);
+ break;
+ case 4:
+ tlv_value = EXTRACT_32BITS(p);
+ break;
+ default:
+ tlv_value = -1;
+ break;
+ }
+ }
+ return tlv_value;
+}
+
static int
juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) {
struct juniper_cookie_table_t *lp = juniper_cookie_table;
- u_int idx, offset;
-#ifdef DLT_JUNIPER_ATM2
+ u_int idx, jnx_ext_len, jnx_header_len = 0;
+ u_int8_t tlv_type,tlv_len;
u_int32_t control_word;
-#endif
+ int tlv_value;
+ const u_char *tptr;
+
l2info->header_len = 0;
l2info->cookie_len = 0;
@@ -806,9 +1149,10 @@ juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct junip
l2info->length = h->len;
l2info->caplen = h->caplen;
+ TCHECK2(p[0],4);
+ l2info->flags = p[3];
l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
- TCHECK2(p[0],4);
if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */
printf("no magic-number found!");
return 0;
@@ -817,15 +1161,92 @@ juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct junip
if (eflag) /* print direction */
printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction));
+ /* magic number + flags */
+ jnx_header_len = 4;
+
+ if (vflag>1)
+ printf("\n\tJuniper PCAP Flags [%s]",
+ bittok2str(jnx_flag_values, "none", l2info->flags));
+
/* extensions present ? - calculate how much bytes to skip */
- if ((p[3] & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) {
- offset = 6 + EXTRACT_16BITS(p+4);
- if (eflag>1)
- printf("ext-len %u, ",EXTRACT_16BITS(p+4));
- } else
- offset = 4;
-
- if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
+ if ((l2info->flags & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) {
+
+ tptr = p+jnx_header_len;
+
+ /* ok to read extension length ? */
+ TCHECK2(tptr[0], 2);
+ jnx_ext_len = EXTRACT_16BITS(tptr);
+ jnx_header_len += 2;
+ tptr +=2;
+
+ /* nail up the total length -
+ * just in case something goes wrong
+ * with TLV parsing */
+ jnx_header_len += jnx_ext_len;
+
+ if (vflag>1)
+ printf(", PCAP Extension(s) total length %u",
+ jnx_ext_len);
+
+ TCHECK2(tptr[0], jnx_ext_len);
+ while (jnx_ext_len > JUNIPER_EXT_TLV_OVERHEAD) {
+ tlv_type = *(tptr++);
+ tlv_len = *(tptr++);
+ tlv_value = 0;
+
+ /* sanity check */
+ if (tlv_type == 0 || tlv_len == 0)
+ break;
+
+ if (vflag>1)
+ printf("\n\t %s Extension TLV #%u, length %u, value ",
+ tok2str(jnx_ext_tlv_values,"Unknown",tlv_type),
+ tlv_type,
+ tlv_len);
+
+ tlv_value = juniper_read_tlv_value(tptr, tlv_type, tlv_len);
+ switch (tlv_type) {
+ case JUNIPER_EXT_TLV_IFD_NAME:
+ /* FIXME */
+ break;
+ case JUNIPER_EXT_TLV_IFD_MEDIATYPE:
+ case JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE:
+ if (tlv_value != -1) {
+ if (vflag>1)
+ printf("%s (%u)",
+ tok2str(juniper_ifmt_values, "Unknown", tlv_value),
+ tlv_value);
+ }
+ break;
+ case JUNIPER_EXT_TLV_IFL_ENCAPS:
+ case JUNIPER_EXT_TLV_TTP_IFL_ENCAPS:
+ if (tlv_value != -1) {
+ if (vflag>1)
+ printf("%s (%u)",
+ tok2str(juniper_ifle_values, "Unknown", tlv_value),
+ tlv_value);
+ }
+ break;
+ case JUNIPER_EXT_TLV_IFL_IDX: /* fall through */
+ case JUNIPER_EXT_TLV_IFL_UNIT:
+ case JUNIPER_EXT_TLV_IFD_IDX:
+ default:
+ if (tlv_value != -1) {
+ if (vflag>1)
+ printf("%u",tlv_value);
+ }
+ break;
+ }
+
+ tptr+=tlv_len;
+ jnx_ext_len -= tlv_len+JUNIPER_EXT_TLV_OVERHEAD;
+ }
+
+ if (vflag>1)
+ printf("\n\t-----original packet-----\n\t");
+ }
+
+ if ((l2info->flags & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
if (eflag)
printf("no-L2-hdr, ");
@@ -833,15 +1254,15 @@ juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct junip
* perform the v4/v6 heuristics
* to figure out what it is
*/
- TCHECK2(p[offset+4],1);
- if(ip_heuristic_guess(p+offset+4,l2info->length-(offset+4)) == 0)
+ TCHECK2(p[jnx_header_len+4],1);
+ if(ip_heuristic_guess(p+jnx_header_len+4,l2info->length-(jnx_header_len+4)) == 0)
printf("no IP-hdr found!");
- l2info->header_len=offset+4;
+ l2info->header_len=jnx_header_len+4;
return 0; /* stop parsing the output further */
}
- l2info->header_len = offset;
+ l2info->header_len = jnx_header_len;
p+=l2info->header_len;
l2info->length -= l2info->header_len;
l2info->caplen -= l2info->header_len;
@@ -988,6 +1409,10 @@ juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct junip
}
break;
#endif
+#ifdef DLT_JUNIPER_GGSN
+ case DLT_JUNIPER_GGSN:
+ break;
+#endif
#ifdef DLT_JUNIPER_ATM1
case DLT_JUNIPER_ATM1:
break;
diff --git a/contrib/tcpdump/print-krb.c b/contrib/tcpdump/print-krb.c
index d6c8e14..213db64 100644
--- a/contrib/tcpdump/print-krb.c
+++ b/contrib/tcpdump/print-krb.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-krb.c,v 1.23 2003/11/16 09:36:26 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-krb.c,v 1.23 2003-11-16 09:36:26 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-l2tp.c b/contrib/tcpdump/print-l2tp.c
index 6ceab43..55c21251 100644
--- a/contrib/tcpdump/print-l2tp.c
+++ b/contrib/tcpdump/print-l2tp.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-l2tp.c,v 1.17.2.3 2006/06/23 02:07:27 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-l2tp.c,v 1.20 2006-06-23 02:03:09 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-lane.c b/contrib/tcpdump/print-lane.c
index 1c3c2c2..33723aa 100644
--- a/contrib/tcpdump/print-lane.c
+++ b/contrib/tcpdump/print-lane.c
@@ -22,7 +22,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-lane.c,v 1.23.2.2 2005/11/13 12:12:59 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-lane.c,v 1.25 2005-11-13 12:12:42 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-ldp.c b/contrib/tcpdump/print-ldp.c
index 3280d8c..de3b34e 100644
--- a/contrib/tcpdump/print-ldp.c
+++ b/contrib/tcpdump/print-ldp.c
@@ -16,7 +16,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ldp.c,v 1.8.2.10 2007/02/26 13:31:33 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ldp.c,v 1.20 2006-06-23 02:03:09 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -33,9 +33,9 @@ static const char rcsid[] _U_ =
#include "decode_prefix.h"
#include "extract.h"
#include "addrtoname.h"
-#include "af.h"
#include "l2vpn.h"
+#include "af.h"
/*
* ldp common header
@@ -131,6 +131,7 @@ static const struct tok ldp_msg_values[] = {
#define LDP_TLV_FEC 0x0100
#define LDP_TLV_ADDRESS_LIST 0x0101
+#define LDP_TLV_ADDRESS_LIST_AFNUM_LEN 2
#define LDP_TLV_HOP_COUNT 0x0103
#define LDP_TLV_PATH_VECTOR 0x0104
#define LDP_TLV_GENERIC_LABEL 0x0200
@@ -149,6 +150,7 @@ static const struct tok ldp_msg_values[] = {
#define LDP_TLV_FR_SESSION_PARM 0x0502
#define LDP_TLV_FT_SESSION 0x0503
#define LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600
+#define LDP_TLV_MTU 0x0601 /* rfc 3988 */
static const struct tok ldp_tlv_values[] = {
{ LDP_TLV_FEC, "FEC" },
@@ -171,6 +173,7 @@ static const struct tok ldp_tlv_values[] = {
{ LDP_TLV_FR_SESSION_PARM, "Frame-Relay Session Parameters" },
{ LDP_TLV_FT_SESSION, "Fault-Tolerant Session Parameters" },
{ LDP_TLV_LABEL_REQUEST_MSG_ID, "Label Request Message ID" },
+ { LDP_TLV_MTU, "MTU" },
{ 0, NULL}
};
@@ -215,8 +218,6 @@ static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = {
{ 0, NULL}
};
-#define AFNUM_LEN 2
-
int ldp_msg_print(register const u_char *);
int ldp_tlv_print(register const u_char *);
@@ -292,27 +293,31 @@ ldp_tlv_print(register const u_char *tptr) {
case LDP_TLV_ADDRESS_LIST:
af = EXTRACT_16BITS(tptr);
- tptr+=AFNUM_LEN;
- tlv_tlen -= AFNUM_LEN;
- printf("\n\t Address Family: ");
- if (af == AFNUM_INET) {
- printf("IPv4, addresses:");
+ tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
+ tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN;
+ printf("\n\t Address Family: %s, addresses",
+ tok2str(af_values, "Unknown (%u)", af));
+ switch (af) {
+ case AFNUM_INET:
while(tlv_tlen >= sizeof(struct in_addr)) {
printf(" %s",ipaddr_string(tptr));
tlv_tlen-=sizeof(struct in_addr);
tptr+=sizeof(struct in_addr);
}
- }
+ break;
#ifdef INET6
- else if (af == AFNUM_INET6) {
- printf("IPv6, addresses:");
+ case AFNUM_INET6:
while(tlv_tlen >= sizeof(struct in6_addr)) {
printf(" %s",ip6addr_string(tptr));
tlv_tlen-=sizeof(struct in6_addr);
tptr+=sizeof(struct in6_addr);
}
- }
+ break;
#endif
+ default:
+ /* unknown AF */
+ break;
+ }
break;
case LDP_TLV_COMMON_SESSION:
@@ -450,6 +455,10 @@ ldp_tlv_print(register const u_char *tptr) {
printf(", Recovery Time: %ums", ui);
break;
+ case LDP_TLV_MTU:
+ printf("\n\t MTU: %u", EXTRACT_16BITS(tptr));
+ break;
+
/*
* FIXME those are the defined TLVs that lack a decoder
diff --git a/contrib/tcpdump/print-llc.c b/contrib/tcpdump/print-llc.c
index 8ffd289..315704c 100644
--- a/contrib/tcpdump/print-llc.c
+++ b/contrib/tcpdump/print-llc.c
@@ -26,7 +26,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-llc.c,v 1.61.2.10 2007/02/08 07:07:51 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-llc.c,v 1.75 2007-04-13 09:43:11 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -107,6 +107,8 @@ static const struct tok cisco_values[] = {
{ PID_CISCO_CDP, "CDP" },
{ PID_CISCO_VTP, "VTP" },
{ PID_CISCO_DTP, "DTP" },
+ { PID_CISCO_UDLD, "UDLD" },
+ { PID_CISCO_PVST, "PVST" },
{ 0, NULL }
};
@@ -443,11 +445,25 @@ snap_print(const u_char *p, u_int length, u_int caplen,
break;
case OUI_CISCO:
- if (et == PID_CISCO_CDP) {
- cdp_print(p, length, caplen);
- return (1);
- }
- break;
+ switch (et) {
+ case PID_CISCO_CDP:
+ cdp_print(p, length, caplen);
+ return (1);
+ case PID_CISCO_DTP:
+ dtp_print(p, length);
+ return (1);
+ case PID_CISCO_UDLD:
+ udld_print(p, length);
+ return (1);
+ case PID_CISCO_VTP:
+ vtp_print(p, length);
+ return (1);
+ case PID_CISCO_PVST:
+ stp_print(p, length);
+ return (1);
+ default:
+ break;
+ }
case OUI_RFC2684:
switch (et) {
diff --git a/contrib/tcpdump/print-lldp.c b/contrib/tcpdump/print-lldp.c
new file mode 100644
index 0000000..36b9934
--- /dev/null
+++ b/contrib/tcpdump/print-lldp.c
@@ -0,0 +1,1107 @@
+/*
+ * Copyright (c) 1998-2007 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * support for the IEEE Link Discovery Protocol as per 802.1ab
+ *
+ * Original code by Hannes Gredler (hannes@juniper.net)
+ * IEEE and TIA extensions by Carles Kishimoto <carles.kishimoto@gmail.com>
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+"@(#) $Header: /tcpdump/master/tcpdump/print-lldp.c,v 1.7.2.3 2008-03-20 09:33:52 hannes Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interface.h"
+#include "extract.h"
+#include "addrtoname.h"
+#include "af.h"
+#include "oui.h"
+
+#define LLDP_EXTRACT_TYPE(x) (((x)&0xfe00)>>9)
+#define LLDP_EXTRACT_LEN(x) ((x)&0x01ff)
+
+/*
+ * TLV type codes
+ */
+#define LLDP_END_TLV 0
+#define LLDP_CHASSIS_ID_TLV 1
+#define LLDP_PORT_ID_TLV 2
+#define LLDP_TTL_TLV 3
+#define LLDP_PORT_DESCR_TLV 4
+#define LLDP_SYSTEM_NAME_TLV 5
+#define LLDP_SYSTEM_DESCR_TLV 6
+#define LLDP_SYSTEM_CAP_TLV 7
+#define LLDP_MGMT_ADDR_TLV 8
+#define LLDP_PRIVATE_TLV 127
+
+static const struct tok lldp_tlv_values[] = {
+ { LLDP_END_TLV, "End" },
+ { LLDP_CHASSIS_ID_TLV, "Chassis ID" },
+ { LLDP_PORT_ID_TLV, "Port ID" },
+ { LLDP_TTL_TLV, "Time to Live" },
+ { LLDP_PORT_DESCR_TLV, "Port Description" },
+ { LLDP_SYSTEM_NAME_TLV, "System Name" },
+ { LLDP_SYSTEM_DESCR_TLV, "System Description" },
+ { LLDP_SYSTEM_CAP_TLV, "System Capabilities" },
+ { LLDP_MGMT_ADDR_TLV, "Management Address" },
+ { LLDP_PRIVATE_TLV, "Organization specific" },
+ { 0, NULL}
+};
+
+/*
+ * Chassis ID subtypes
+ */
+#define LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE 1
+#define LLDP_CHASSIS_INTF_ALIAS_SUBTYPE 2
+#define LLDP_CHASSIS_PORT_COMP_SUBTYPE 3
+#define LLDP_CHASSIS_MAC_ADDR_SUBTYPE 4
+#define LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE 5
+#define LLDP_CHASSIS_INTF_NAME_SUBTYPE 6
+#define LLDP_CHASSIS_LOCAL_SUBTYPE 7
+
+static const struct tok lldp_chassis_subtype_values[] = {
+ { LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE, "Chassis component"},
+ { LLDP_CHASSIS_INTF_ALIAS_SUBTYPE, "Interface alias"},
+ { LLDP_CHASSIS_PORT_COMP_SUBTYPE, "Port component"},
+ { LLDP_CHASSIS_MAC_ADDR_SUBTYPE, "MAC address"},
+ { LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE, "Network address"},
+ { LLDP_CHASSIS_INTF_NAME_SUBTYPE, "Interface name"},
+ { LLDP_CHASSIS_LOCAL_SUBTYPE, "Local"},
+ { 0, NULL}
+};
+
+/*
+ * Port ID subtypes
+ */
+#define LLDP_PORT_INTF_ALIAS_SUBTYPE 1
+#define LLDP_PORT_PORT_COMP_SUBTYPE 2
+#define LLDP_PORT_MAC_ADDR_SUBTYPE 3
+#define LLDP_PORT_NETWORK_ADDR_SUBTYPE 4
+#define LLDP_PORT_INTF_NAME_SUBTYPE 5
+#define LLDP_PORT_AGENT_CIRC_ID_SUBTYPE 6
+#define LLDP_PORT_LOCAL_SUBTYPE 7
+
+static const struct tok lldp_port_subtype_values[] = {
+ { LLDP_PORT_INTF_ALIAS_SUBTYPE, "Interface alias"},
+ { LLDP_PORT_PORT_COMP_SUBTYPE, "Port component"},
+ { LLDP_PORT_MAC_ADDR_SUBTYPE, "MAC address"},
+ { LLDP_PORT_NETWORK_ADDR_SUBTYPE, "Network Address"},
+ { LLDP_PORT_INTF_NAME_SUBTYPE, "Interface Name"},
+ { LLDP_PORT_AGENT_CIRC_ID_SUBTYPE, "Agent circuit ID"},
+ { LLDP_PORT_LOCAL_SUBTYPE, "Local"},
+ { 0, NULL}
+};
+
+/*
+ * System Capabilities
+ */
+#define LLDP_CAP_OTHER (1 << 0)
+#define LLDP_CAP_REPEATER (1 << 1)
+#define LLDP_CAP_BRIDGE (1 << 2)
+#define LLDP_CAP_WLAN_AP (1 << 3)
+#define LLDP_CAP_ROUTER (1 << 4)
+#define LLDP_CAP_PHONE (1 << 5)
+#define LLDP_CAP_DOCSIS (1 << 6)
+#define LLDP_CAP_STATION_ONLY (1 << 7)
+
+static const struct tok lldp_cap_values[] = {
+ { LLDP_CAP_OTHER, "Other"},
+ { LLDP_CAP_REPEATER, "Repeater"},
+ { LLDP_CAP_BRIDGE, "Bridge"},
+ { LLDP_CAP_WLAN_AP, "WLAN AP"},
+ { LLDP_CAP_ROUTER, "Router"},
+ { LLDP_CAP_PHONE, "Telephone"},
+ { LLDP_CAP_DOCSIS, "Docsis"},
+ { LLDP_CAP_STATION_ONLY, "Station Only"},
+ { 0, NULL}
+};
+
+#define LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID 1
+#define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID 2
+#define LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME 3
+#define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY 4
+
+static const struct tok lldp_8021_subtype_values[] = {
+ { LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID, "Port VLAN Id"},
+ { LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID, "Port and Protocol VLAN ID"},
+ { LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME, "VLAN name"},
+ { LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY, "Protocol Identity"},
+ { 0, NULL}
+};
+
+#define LLDP_8021_PORT_PROTOCOL_VLAN_SUPPORT (1 << 1)
+#define LLDP_8021_PORT_PROTOCOL_VLAN_STATUS (1 << 2)
+
+static const struct tok lldp_8021_port_protocol_id_values[] = {
+ { LLDP_8021_PORT_PROTOCOL_VLAN_SUPPORT, "supported"},
+ { LLDP_8021_PORT_PROTOCOL_VLAN_STATUS, "enabled"},
+ { 0, NULL}
+};
+
+#define LLDP_PRIVATE_8023_SUBTYPE_MACPHY 1
+#define LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER 2
+#define LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR 3
+#define LLDP_PRIVATE_8023_SUBTYPE_MTU 4
+
+static const struct tok lldp_8023_subtype_values[] = {
+ { LLDP_PRIVATE_8023_SUBTYPE_MACPHY, "MAC/PHY configuration/status"},
+ { LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER, "Power via MDI"},
+ { LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR, "Link aggregation"},
+ { LLDP_PRIVATE_8023_SUBTYPE_MTU, "Max frame size"},
+ { 0, NULL}
+};
+
+#define LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES 1
+#define LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY 2
+#define LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID 3
+#define LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI 4
+#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV 5
+#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV 6
+#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV 7
+#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER 8
+#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME 9
+#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME 10
+#define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID 11
+
+static const struct tok lldp_tia_subtype_values[] = {
+ { LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES, "LLDP-MED Capabilities" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY, "Network policy" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID, "Location identification" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI, "Extended power-via-MDI" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV, "Inventory - hardware revision" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV, "Inventory - firmware revision" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV, "Inventory - software revision" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER, "Inventory - serial number" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME, "Inventory - manufacturer name" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME, "Inventory - model name" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID, "Inventory - asset ID" },
+ { 0, NULL}
+};
+
+#define LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_METERS 1
+#define LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_FLOORS 2
+
+static const struct tok lldp_tia_location_altitude_type_values[] = {
+ { LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_METERS, "meters"},
+ { LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_FLOORS, "floors"},
+ { 0, NULL}
+};
+
+/* ANSI/TIA-1057 - Annex B */
+#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A1 1
+#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A2 2
+#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A3 3
+#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A4 4
+#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A5 5
+#define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A6 6
+
+static const struct tok lldp_tia_location_lci_catype_values[] = {
+ { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A1, "national subdivisions (state,canton,region,province,prefecture)"},
+ { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A2, "county, parish, gun, district"},
+ { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A3, "city, township, shi"},
+ { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A4, "city division, borough, city district, ward chou"},
+ { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A5, "neighborhood, block"},
+ { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A6, "street"},
+ { 0, NULL}
+};
+
+static const struct tok lldp_tia_location_lci_what_values[] = {
+ { 0, "location of DHCP server"},
+ { 1, "location of the network element believed to be closest to the client"},
+ { 2, "location of the client"},
+ { 0, NULL}
+};
+
+/*
+ * From RFC 3636 - dot3MauType
+ */
+#define LLDP_MAU_TYPE_UNKNOWN 0
+#define LLDP_MAU_TYPE_AUI 1
+#define LLDP_MAU_TYPE_10BASE_5 2
+#define LLDP_MAU_TYPE_FOIRL 3
+#define LLDP_MAU_TYPE_10BASE_2 4
+#define LLDP_MAU_TYPE_10BASE_T 5
+#define LLDP_MAU_TYPE_10BASE_FP 6
+#define LLDP_MAU_TYPE_10BASE_FB 7
+#define LLDP_MAU_TYPE_10BASE_FL 8
+#define LLDP_MAU_TYPE_10BROAD36 9
+#define LLDP_MAU_TYPE_10BASE_T_HD 10
+#define LLDP_MAU_TYPE_10BASE_T_FD 11
+#define LLDP_MAU_TYPE_10BASE_FL_HD 12
+#define LLDP_MAU_TYPE_10BASE_FL_FD 13
+#define LLDP_MAU_TYPE_100BASE_T4 14
+#define LLDP_MAU_TYPE_100BASE_TX_HD 15
+#define LLDP_MAU_TYPE_100BASE_TX_FD 16
+#define LLDP_MAU_TYPE_100BASE_FX_HD 17
+#define LLDP_MAU_TYPE_100BASE_FX_FD 18
+#define LLDP_MAU_TYPE_100BASE_T2_HD 19
+#define LLDP_MAU_TYPE_100BASE_T2_FD 20
+#define LLDP_MAU_TYPE_1000BASE_X_HD 21
+#define LLDP_MAU_TYPE_1000BASE_X_FD 22
+#define LLDP_MAU_TYPE_1000BASE_LX_HD 23
+#define LLDP_MAU_TYPE_1000BASE_LX_FD 24
+#define LLDP_MAU_TYPE_1000BASE_SX_HD 25
+#define LLDP_MAU_TYPE_1000BASE_SX_FD 26
+#define LLDP_MAU_TYPE_1000BASE_CX_HD 27
+#define LLDP_MAU_TYPE_1000BASE_CX_FD 28
+#define LLDP_MAU_TYPE_1000BASE_T_HD 29
+#define LLDP_MAU_TYPE_1000BASE_T_FD 30
+#define LLDP_MAU_TYPE_10GBASE_X 31
+#define LLDP_MAU_TYPE_10GBASE_LX4 32
+#define LLDP_MAU_TYPE_10GBASE_R 33
+#define LLDP_MAU_TYPE_10GBASE_ER 34
+#define LLDP_MAU_TYPE_10GBASE_LR 35
+#define LLDP_MAU_TYPE_10GBASE_SR 36
+#define LLDP_MAU_TYPE_10GBASE_W 37
+#define LLDP_MAU_TYPE_10GBASE_EW 38
+#define LLDP_MAU_TYPE_10GBASE_LW 39
+#define LLDP_MAU_TYPE_10GBASE_SW 40
+
+static const struct tok lldp_mau_types_values[] = {
+ { LLDP_MAU_TYPE_UNKNOWN, "Unknown"},
+ { LLDP_MAU_TYPE_AUI, "AUI"},
+ { LLDP_MAU_TYPE_10BASE_5, "10BASE_5"},
+ { LLDP_MAU_TYPE_FOIRL, "FOIRL"},
+ { LLDP_MAU_TYPE_10BASE_2, "10BASE2"},
+ { LLDP_MAU_TYPE_10BASE_T, "10BASET duplex mode unknown"},
+ { LLDP_MAU_TYPE_10BASE_FP, "10BASEFP"},
+ { LLDP_MAU_TYPE_10BASE_FB, "10BASEFB"},
+ { LLDP_MAU_TYPE_10BASE_FL, "10BASEFL duplex mode unknown"},
+ { LLDP_MAU_TYPE_10BROAD36, "10BROAD36"},
+ { LLDP_MAU_TYPE_10BASE_T_HD, "10BASET hdx"},
+ { LLDP_MAU_TYPE_10BASE_T_FD, "10BASET fdx"},
+ { LLDP_MAU_TYPE_10BASE_FL_HD, "10BASEFL hdx"},
+ { LLDP_MAU_TYPE_10BASE_FL_FD, "10BASEFL fdx"},
+ { LLDP_MAU_TYPE_100BASE_T4, "100BASET4"},
+ { LLDP_MAU_TYPE_100BASE_TX_HD, "100BASETX hdx"},
+ { LLDP_MAU_TYPE_100BASE_TX_FD, "100BASETX fdx"},
+ { LLDP_MAU_TYPE_100BASE_FX_HD, "100BASEFX hdx"},
+ { LLDP_MAU_TYPE_100BASE_FX_FD, "100BASEFX fdx"},
+ { LLDP_MAU_TYPE_100BASE_T2_HD, "100BASET2 hdx"},
+ { LLDP_MAU_TYPE_100BASE_T2_FD, "100BASET2 fdx"},
+ { LLDP_MAU_TYPE_1000BASE_X_HD, "1000BASEX hdx"},
+ { LLDP_MAU_TYPE_1000BASE_X_FD, "1000BASEX fdx"},
+ { LLDP_MAU_TYPE_1000BASE_LX_HD, "1000BASELX hdx"},
+ { LLDP_MAU_TYPE_1000BASE_LX_FD, "1000BASELX fdx"},
+ { LLDP_MAU_TYPE_1000BASE_SX_HD, "1000BASESX hdx"},
+ { LLDP_MAU_TYPE_1000BASE_SX_FD, "1000BASESX fdx"},
+ { LLDP_MAU_TYPE_1000BASE_CX_HD, "1000BASECX hdx"},
+ { LLDP_MAU_TYPE_1000BASE_CX_FD, "1000BASECX fdx"},
+ { LLDP_MAU_TYPE_1000BASE_T_HD, "1000BASET hdx"},
+ { LLDP_MAU_TYPE_1000BASE_T_FD, "1000BASET fdx"},
+ { LLDP_MAU_TYPE_10GBASE_X, "10GBASEX"},
+ { LLDP_MAU_TYPE_10GBASE_LX4, "10GBASELX4"},
+ { LLDP_MAU_TYPE_10GBASE_R, "10GBASER"},
+ { LLDP_MAU_TYPE_10GBASE_ER, "10GBASEER"},
+ { LLDP_MAU_TYPE_10GBASE_LR, "10GBASELR"},
+ { LLDP_MAU_TYPE_10GBASE_SR, "10GBASESR"},
+ { LLDP_MAU_TYPE_10GBASE_W, "10GBASEW"},
+ { LLDP_MAU_TYPE_10GBASE_EW, "10GBASEEW"},
+ { LLDP_MAU_TYPE_10GBASE_LW, "10GBASELW"},
+ { LLDP_MAU_TYPE_10GBASE_SW, "10GBASESW"},
+ { 0, NULL}
+};
+
+#define LLDP_8023_AUTONEGOTIATION_SUPPORT (1 << 0)
+#define LLDP_8023_AUTONEGOTIATION_STATUS (1 << 1)
+
+static const struct tok lldp_8023_autonegotiation_values[] = {
+ { LLDP_8023_AUTONEGOTIATION_SUPPORT, "supported"},
+ { LLDP_8023_AUTONEGOTIATION_STATUS, "enabled"},
+ { 0, NULL}
+};
+
+#define LLDP_TIA_CAPABILITY_MED (1 << 0)
+#define LLDP_TIA_CAPABILITY_NETWORK_POLICY (1 << 1)
+#define LLDP_TIA_CAPABILITY_LOCATION_IDENTIFICATION (1 << 2)
+#define LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PSE (1 << 3)
+#define LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PD (1 << 4)
+#define LLDP_TIA_CAPABILITY_INVENTORY (1 << 5)
+
+static const struct tok lldp_tia_capabilities_values[] = {
+ { LLDP_TIA_CAPABILITY_MED, "LLDP-MED capabilities"},
+ { LLDP_TIA_CAPABILITY_NETWORK_POLICY, "network policy"},
+ { LLDP_TIA_CAPABILITY_LOCATION_IDENTIFICATION, "location identification"},
+ { LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PSE, "extended power via MDI-PSE"},
+ { LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PD, "extended power via MDI-PD"},
+ { LLDP_TIA_CAPABILITY_INVENTORY, "Inventory"},
+ { 0, NULL}
+};
+
+#define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_1 1
+#define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_2 2
+#define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_3 3
+#define LLDP_TIA_DEVICE_TYPE_NETWORK_CONNECTIVITY 4
+
+static const struct tok lldp_tia_device_type_values[] = {
+ { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_1, "endpoint class 1"},
+ { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_2, "endpoint class 2"},
+ { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_3, "endpoint class 3"},
+ { LLDP_TIA_DEVICE_TYPE_NETWORK_CONNECTIVITY, "network connectivity"},
+ { 0, NULL}
+};
+
+#define LLDP_TIA_APPLICATION_TYPE_VOICE 1
+#define LLDP_TIA_APPLICATION_TYPE_VOICE_SIGNALING 2
+#define LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE 3
+#define LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE_SIGNALING 4
+#define LLDP_TIA_APPLICATION_TYPE_SOFTPHONE_VOICE 5
+#define LLDP_TIA_APPLICATION_TYPE_VIDEO_CONFERENCING 6
+#define LLDP_TIA_APPLICATION_TYPE_STREAMING_VIDEO 7
+#define LLDP_TIA_APPLICATION_TYPE_VIDEO_SIGNALING 8
+
+static const struct tok lldp_tia_application_type_values[] = {
+ { LLDP_TIA_APPLICATION_TYPE_VOICE, "voice"},
+ { LLDP_TIA_APPLICATION_TYPE_VOICE_SIGNALING, "voice signaling"},
+ { LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE, "guest voice"},
+ { LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE_SIGNALING, "guest voice signaling"},
+ { LLDP_TIA_APPLICATION_TYPE_SOFTPHONE_VOICE, "softphone voice"},
+ { LLDP_TIA_APPLICATION_TYPE_VIDEO_CONFERENCING, "video conferencing"},
+ { LLDP_TIA_APPLICATION_TYPE_STREAMING_VIDEO, "streaming video"},
+ { LLDP_TIA_APPLICATION_TYPE_VIDEO_SIGNALING, "video signaling"},
+ { 0, NULL}
+};
+
+#define LLDP_TIA_NETWORK_POLICY_U_BIT (1 << 5)
+#define LLDP_TIA_NETWORK_POLICY_T_BIT (1 << 6)
+#define LLDP_TIA_NETWORK_POLICY_X_BIT (1 << 7)
+
+static const struct tok lldp_tia_network_policy_bits_values[] = {
+ { LLDP_TIA_NETWORK_POLICY_U_BIT, "Unknown"},
+ { LLDP_TIA_NETWORK_POLICY_T_BIT, "Tagged"},
+ { LLDP_TIA_NETWORK_POLICY_X_BIT, "reserved"},
+ { 0, NULL}
+};
+
+#define LLDP_EXTRACT_NETWORK_POLICY_VLAN(x) (((x)&0x1ffe)>>1)
+#define LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(x) (((x)&0x01ff)>>6)
+#define LLDP_EXTRACT_NETWORK_POLICY_DSCP(x) ((x)&0x003f)
+
+#define LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED 1
+#define LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS 2
+#define LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN 3
+
+static const struct tok lldp_tia_location_data_format_values[] = {
+ { LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED, "coordinate-based LCI"},
+ { LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS, "civic address LCI"},
+ { LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN, "ECS ELIN"},
+ { 0, NULL}
+};
+
+#define LLDP_TIA_LOCATION_DATUM_WGS_84 1
+#define LLDP_TIA_LOCATION_DATUM_NAD_83_NAVD_88 2
+#define LLDP_TIA_LOCATION_DATUM_NAD_83_MLLW 3
+
+static const struct tok lldp_tia_location_datum_type_values[] = {
+ { LLDP_TIA_LOCATION_DATUM_WGS_84, "World Geodesic System 1984"},
+ { LLDP_TIA_LOCATION_DATUM_NAD_83_NAVD_88, "North American Datum 1983 (NAVD88)"},
+ { LLDP_TIA_LOCATION_DATUM_NAD_83_MLLW, "North American Datum 1983 (MLLW)"},
+ { 0, NULL}
+};
+
+#define LLDP_TIA_POWER_SOURCE_PSE 1
+#define LLDP_TIA_POWER_SOURCE_LOCAL 2
+#define LLDP_TIA_POWER_SOURCE_PSE_AND_LOCAL 3
+
+static const struct tok lldp_tia_power_source_values[] = {
+ { LLDP_TIA_POWER_SOURCE_PSE, "PSE - primary power source"},
+ { LLDP_TIA_POWER_SOURCE_LOCAL, "local - backup power source"},
+ { LLDP_TIA_POWER_SOURCE_PSE_AND_LOCAL, "PSE+local - reserved"},
+ { 0, NULL}
+};
+
+#define LLDP_TIA_POWER_PRIORITY_CRITICAL 1
+#define LLDP_TIA_POWER_PRIORITY_HIGH 2
+#define LLDP_TIA_POWER_PRIORITY_LOW 3
+
+static const struct tok lldp_tia_power_priority_values[] = {
+ { LLDP_TIA_POWER_PRIORITY_CRITICAL, "critical"},
+ { LLDP_TIA_POWER_PRIORITY_HIGH, "high"},
+ { LLDP_TIA_POWER_PRIORITY_LOW, "low"},
+ { 0, NULL}
+};
+
+#define LLDP_TIA_POWER_VAL_MAX 1024
+
+static const struct tok lldp_tia_inventory_values[] = {
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV, "Hardware revision" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV, "Firmware revision" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV, "Software revision" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER, "Serial number" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME, "Manufacturer name" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME, "Model name" },
+ { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID, "Asset ID" },
+ { 0, NULL}
+};
+
+/*
+ * From RFC 3636 - ifMauAutoNegCapAdvertisedBits
+ */
+#define LLDP_MAU_PMD_OTHER (1 << 15)
+#define LLDP_MAU_PMD_10BASE_T (1 << 14)
+#define LLDP_MAU_PMD_10BASE_T_FD (1 << 13)
+#define LLDP_MAU_PMD_100BASE_T4 (1 << 12)
+#define LLDP_MAU_PMD_100BASE_TX (1 << 11)
+#define LLDP_MAU_PMD_100BASE_TX_FD (1 << 10)
+#define LLDP_MAU_PMD_100BASE_T2 (1 << 9)
+#define LLDP_MAU_PMD_100BASE_T2_FD (1 << 8)
+#define LLDP_MAU_PMD_FDXPAUSE (1 << 7)
+#define LLDP_MAU_PMD_FDXAPAUSE (1 << 6)
+#define LLDP_MAU_PMD_FDXSPAUSE (1 << 5)
+#define LLDP_MAU_PMD_FDXBPAUSE (1 << 4)
+#define LLDP_MAU_PMD_1000BASE_X (1 << 3)
+#define LLDP_MAU_PMD_1000BASE_X_FD (1 << 2)
+#define LLDP_MAU_PMD_1000BASE_T (1 << 1)
+#define LLDP_MAU_PMD_1000BASE_T_FD (1 << 0)
+
+static const struct tok lldp_pmd_capability_values[] = {
+ { LLDP_MAU_PMD_10BASE_T, "10BASE-T hdx"},
+ { LLDP_MAU_PMD_10BASE_T_FD, "10BASE-T fdx"},
+ { LLDP_MAU_PMD_100BASE_T4, "100BASE-T4"},
+ { LLDP_MAU_PMD_100BASE_TX, "100BASE-TX hdx"},
+ { LLDP_MAU_PMD_100BASE_TX_FD, "100BASE-TX fdx"},
+ { LLDP_MAU_PMD_100BASE_T2, "100BASE-T2 hdx"},
+ { LLDP_MAU_PMD_100BASE_T2_FD, "100BASE-T2 fdx"},
+ { LLDP_MAU_PMD_FDXPAUSE, "Pause for fdx links"},
+ { LLDP_MAU_PMD_FDXAPAUSE, "Asym PAUSE for fdx"},
+ { LLDP_MAU_PMD_FDXSPAUSE, "Sym PAUSE for fdx"},
+ { LLDP_MAU_PMD_FDXBPAUSE, "Asym and Sym PAUSE for fdx"},
+ { LLDP_MAU_PMD_1000BASE_X, "1000BASE-{X LX SX CX} hdx"},
+ { LLDP_MAU_PMD_1000BASE_X_FD, "1000BASE-{X LX SX CX} fdx"},
+ { LLDP_MAU_PMD_1000BASE_T, "1000BASE-T hdx"},
+ { LLDP_MAU_PMD_1000BASE_T_FD, "1000BASE-T fdx"},
+ { 0, NULL}
+};
+
+#define LLDP_MDI_PORT_CLASS (1 << 0)
+#define LLDP_MDI_POWER_SUPPORT (1 << 1)
+#define LLDP_MDI_POWER_STATE (1 << 2)
+#define LLDP_MDI_PAIR_CONTROL_ABILITY (1 << 3)
+
+static const struct tok lldp_mdi_values[] = {
+ { LLDP_MDI_PORT_CLASS, "PSE"},
+ { LLDP_MDI_POWER_SUPPORT, "supported"},
+ { LLDP_MDI_POWER_STATE, "enabled"},
+ { LLDP_MDI_PAIR_CONTROL_ABILITY, "can be controlled"},
+ { 0, NULL}
+};
+
+#define LLDP_MDI_PSE_PORT_POWER_PAIRS_SIGNAL 1
+#define LLDP_MDI_PSE_PORT_POWER_PAIRS_SPARE 2
+
+static const struct tok lldp_mdi_power_pairs_values[] = {
+ { LLDP_MDI_PSE_PORT_POWER_PAIRS_SIGNAL, "signal"},
+ { LLDP_MDI_PSE_PORT_POWER_PAIRS_SPARE, "spare"},
+ { 0, NULL}
+};
+
+#define LLDP_MDI_POWER_CLASS0 1
+#define LLDP_MDI_POWER_CLASS1 2
+#define LLDP_MDI_POWER_CLASS2 3
+#define LLDP_MDI_POWER_CLASS3 4
+#define LLDP_MDI_POWER_CLASS4 5
+
+static const struct tok lldp_mdi_power_class_values[] = {
+ { LLDP_MDI_POWER_CLASS0, "class0"},
+ { LLDP_MDI_POWER_CLASS1, "class1"},
+ { LLDP_MDI_POWER_CLASS2, "class2"},
+ { LLDP_MDI_POWER_CLASS3, "class3"},
+ { LLDP_MDI_POWER_CLASS4, "class4"},
+ { 0, NULL}
+};
+
+#define LLDP_AGGREGATION_CAPABILTIY (1 << 0)
+#define LLDP_AGGREGATION_STATUS (1 << 1)
+
+static const struct tok lldp_aggregation_values[] = {
+ { LLDP_AGGREGATION_CAPABILTIY, "supported"},
+ { LLDP_AGGREGATION_STATUS, "enabled"},
+ { 0, NULL}
+};
+
+/*
+ * Interface numbering subtypes.
+ */
+#define LLDP_INTF_NUMB_IFX_SUBTYPE 2
+#define LLDP_INTF_NUMB_SYSPORT_SUBTYPE 3
+
+static const struct tok lldp_intf_numb_subtype_values[] = {
+ { LLDP_INTF_NUMB_IFX_SUBTYPE, "Interface Index" },
+ { LLDP_INTF_NUMB_SYSPORT_SUBTYPE, "System Port Number" },
+ { 0, NULL}
+};
+
+#define LLDP_INTF_NUM_LEN 5
+
+/*
+ * Print IEEE private extensions. (802.1 annex F)
+ */
+static int
+lldp_private_8021_print(const u_char *tptr)
+{
+ int subtype, hexdump = FALSE;
+
+ subtype = *(tptr+3);
+
+ printf("\n\t %s Subtype (%u)",
+ tok2str(lldp_8021_subtype_values, "unknown", subtype),
+ subtype);
+
+ switch (subtype) {
+ case LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID:
+ printf("\n\t port vlan id (PVID): %u",
+ EXTRACT_16BITS(tptr+4));
+ break;
+ case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID:
+ printf("\n\t port and protocol vlan id (PPVID): %u, flags [%s] (0x%02x)",
+ EXTRACT_16BITS(tptr+5),
+ bittok2str(lldp_8021_port_protocol_id_values, "none", *(tptr+4)),
+ *(tptr+4));
+ break;
+ case LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME:
+ printf("\n\t vlan id (VID): %u",
+ EXTRACT_16BITS(tptr+4));
+ printf("\n\t vlan name: ");
+ safeputs((const char *)tptr+7, *(tptr+6));
+ break;
+ case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY:
+ printf("\n\t protocol identity: ");
+ safeputs((const char *)tptr+5, *(tptr+4));
+ break;
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+
+ return hexdump;
+}
+
+/*
+ * Print IEEE private extensions. (802.3)
+ */
+static int
+lldp_private_8023_print(const u_char *tptr)
+{
+ int subtype, hexdump = FALSE;
+
+ subtype = *(tptr+3);
+
+ printf("\n\t %s Subtype (%u)",
+ tok2str(lldp_8023_subtype_values, "unknown", subtype),
+ subtype);
+
+ switch (subtype) {
+ case LLDP_PRIVATE_8023_SUBTYPE_MACPHY:
+ printf("\n\t autonegotiation [%s] (0x%02x)",
+ bittok2str(lldp_8023_autonegotiation_values, "none", *(tptr+4)),
+ *(tptr+4));
+ printf("\n\t PMD autoneg capability [%s] (0x%04x)",
+ bittok2str(lldp_pmd_capability_values,"unknown", EXTRACT_16BITS(tptr+5)),
+ EXTRACT_16BITS(tptr+5));
+ printf("\n\t MAU type %s (0x%04x)",
+ tok2str(lldp_mau_types_values, "unknown", EXTRACT_16BITS(tptr+7)),
+ EXTRACT_16BITS(tptr+7));
+ break;
+
+ case LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER:
+ printf("\n\t MDI power support [%s], power pair %s, power class %s",
+ bittok2str(lldp_mdi_values, "none", *(tptr+4)),
+ tok2str(lldp_mdi_power_pairs_values, "unknown", *(tptr+5)),
+ tok2str(lldp_mdi_power_class_values, "unknown", *(tptr+6)));
+ break;
+
+ case LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR:
+ printf("\n\t aggregation status [%s], aggregation port ID %u",
+ bittok2str(lldp_aggregation_values, "none", *(tptr+4)),
+ EXTRACT_32BITS(tptr+5));
+ break;
+
+ case LLDP_PRIVATE_8023_SUBTYPE_MTU:
+ printf("\n\t MTU size %u", EXTRACT_16BITS(tptr+4));
+ break;
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+
+ return hexdump;
+}
+
+/*
+ * Extract 34bits of latitude/longitude coordinates.
+ */
+static u_int64_t
+lldp_extract_latlon(const u_char *tptr)
+{
+ u_int64_t latlon;
+
+ latlon = *tptr & 0x3;
+ latlon = (latlon << 32) | EXTRACT_32BITS(tptr+1);
+
+ return latlon;
+}
+
+/*
+ * Print private TIA extensions.
+ */
+static int
+lldp_private_tia_print(const u_char *tptr, u_int tlv_len)
+{
+ int subtype, hexdump = FALSE;
+ u_int8_t location_format;
+ u_int16_t power_val;
+ u_int8_t lci_len, ca_type, ca_len;
+
+ subtype = *(tptr+3);
+
+ printf("\n\t %s Subtype (%u)",
+ tok2str(lldp_tia_subtype_values, "unknown", subtype),
+ subtype);
+
+ switch (subtype) {
+ case LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES:
+ printf("\n\t Media capabilities [%s] (0x%04x)",
+ bittok2str(lldp_tia_capabilities_values, "none",
+ EXTRACT_16BITS(tptr+4)), EXTRACT_16BITS(tptr+4));
+ printf("\n\t Device type [%s] (0x%02x)",
+ tok2str(lldp_tia_device_type_values, "unknown", *(tptr+6)),
+ *(tptr+6));
+ break;
+
+ case LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY:
+ printf("\n\t Application type [%s] (0x%02x)",
+ tok2str(lldp_tia_application_type_values, "none", *(tptr+4)),
+ *(tptr+4));
+ printf(", Flags [%s]", bittok2str(
+ lldp_tia_network_policy_bits_values, "none", *(tptr+5)));
+ printf("\n\t Vlan id %u",
+ LLDP_EXTRACT_NETWORK_POLICY_VLAN(EXTRACT_16BITS(tptr+5)));
+ printf(", L2 priority %u",
+ LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(EXTRACT_16BITS(tptr+6)));
+ printf(", DSCP value %u",
+ LLDP_EXTRACT_NETWORK_POLICY_DSCP(EXTRACT_16BITS(tptr+6)));
+ break;
+
+ case LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID:
+ location_format = *(tptr+4);
+ printf("\n\t Location data format %s (0x%02x)",
+ tok2str(lldp_tia_location_data_format_values, "unknown", location_format),
+ location_format);
+
+ switch (location_format) {
+ case LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED:
+ printf("\n\t Latitude resolution %u, latitude value %" PRIu64,
+ (*(tptr+5)>>2), lldp_extract_latlon(tptr+5));
+ printf("\n\t Longitude resolution %u, longitude value %" PRIu64,
+ (*(tptr+10)>>2), lldp_extract_latlon(tptr+10));
+ printf("\n\t Altitude type %s (%u)",
+ tok2str(lldp_tia_location_altitude_type_values, "unknown",(*(tptr+15)>>4)),
+ (*(tptr+15)>>4));
+ printf("\n\t Altitude resolution %u, altitude value 0x%x",
+ (EXTRACT_16BITS(tptr+15)>>6)&0x3f,
+ ((EXTRACT_32BITS(tptr+16)&0x3fffffff)));
+ printf("\n\t Datum %s (0x%02x)",
+ tok2str(lldp_tia_location_datum_type_values, "unknown", *(tptr+20)),
+ *(tptr+20));
+ break;
+
+ case LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS:
+ lci_len = *(tptr+5);
+ printf("\n\t LCI length %u, LCI what %s (0x%02x), Country-code ",
+ lci_len,
+ tok2str(lldp_tia_location_lci_what_values, "unknown", *(tptr+6)),
+ *(tptr+6));
+
+ /* Country code */
+ safeputs((const char *)(tptr+7), 2);
+
+ lci_len = lci_len-3;
+ tptr = tptr + 9;
+
+ /* Decode each civic address element */
+ while (lci_len > 0) {
+ ca_type = *(tptr);
+ ca_len = *(tptr+1);
+
+ tptr += 2;
+ lci_len -= 2;
+
+ printf("\n\t CA type \'%s\' (%u), length %u: ",
+ tok2str(lldp_tia_location_lci_catype_values, "unknown", ca_type),
+ ca_type, ca_len);
+
+ /* basic sanity check */
+ if ( ca_type == 0 || ca_len == 0) {
+ return hexdump;
+ }
+
+ safeputs((const char *)tptr, ca_len);
+ tptr += ca_len;
+ lci_len -= ca_len;
+ }
+ break;
+
+ case LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN:
+ printf("\n\t ECS ELIN id ");
+ safeputs((const char *)tptr+5, tlv_len-5);
+ break;
+
+ default:
+ printf("\n\t Location ID ");
+ print_unknown_data(tptr+5, "\n\t ", tlv_len-5);
+ }
+ break;
+
+ case LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI:
+ printf("\n\t Power type [%s]",
+ (*(tptr+4)&0xC0>>6) ? "PD device" : "PSE device");
+ printf(", Power source [%s]",
+ tok2str(lldp_tia_power_source_values, "none", (*(tptr+4)&0x30)>>4));
+ printf("\n\t Power priority [%s] (0x%02x)",
+ tok2str(lldp_tia_power_priority_values, "none", *(tptr+4)&0x0f),
+ *(tptr+4)&0x0f);
+ power_val = EXTRACT_16BITS(tptr+5);
+ if (power_val < LLDP_TIA_POWER_VAL_MAX) {
+ printf(", Power %.1f Watts", ((float)power_val)/10);
+ } else {
+ printf(", Power %u (Reserved)", power_val);
+ }
+ break;
+
+ case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV:
+ case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV:
+ case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV:
+ case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER:
+ case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME:
+ case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME:
+ case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID:
+ printf("\n\t %s ",
+ tok2str(lldp_tia_inventory_values, "unknown", subtype));
+ safeputs((const char *)tptr+4, tlv_len-4);
+ break;
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+
+ return hexdump;
+}
+
+static char *
+lldp_network_addr_print(const u_char *tptr) {
+
+ u_int8_t af;
+ static char buf[BUFSIZE];
+ const char * (*pfunc)(const u_char *);
+
+ af = *tptr;
+ switch (af) {
+ case AFNUM_INET:
+ pfunc = getname;
+ break;
+#ifdef INET6
+ case AFNUM_INET6:
+ pfunc = getname6;
+ break;
+#endif
+ case AFNUM_802:
+ pfunc = etheraddr_string;
+ break;
+ default:
+ pfunc = NULL;
+ break;
+ }
+
+ if (!pfunc) {
+ snprintf(buf, sizeof(buf), "AFI %s (%u), no AF printer !",
+ tok2str(af_values, "Unknown", af), af);
+ } else {
+ snprintf(buf, sizeof(buf), "AFI %s (%u): %s",
+ tok2str(af_values, "Unknown", af), af, (*pfunc)(tptr+1));
+ }
+
+ return buf;
+}
+
+static int
+lldp_mgmt_addr_tlv_print(const u_char *pptr, u_int len) {
+
+ u_int8_t mgmt_addr_len, intf_num_subtype, oid_len;
+ const u_char *tptr;
+ u_int tlen;
+
+ tlen = len;
+ tptr = pptr;
+
+ mgmt_addr_len = *tptr++;
+ tlen--;
+
+ if (tlen < mgmt_addr_len) {
+ return 0;
+ }
+
+ printf("\n\t Management Address length %u, %s",
+ mgmt_addr_len,
+ lldp_network_addr_print(tptr));
+ tptr += mgmt_addr_len;
+ tlen -= mgmt_addr_len;
+
+ if (tlen < LLDP_INTF_NUM_LEN) {
+ return 0;
+ }
+
+ intf_num_subtype = *tptr;
+ printf("\n\t %s Interface Numbering (%u): %u",
+ tok2str(lldp_intf_numb_subtype_values, "Unknown", intf_num_subtype),
+ intf_num_subtype,
+ EXTRACT_32BITS(tptr+1));
+
+ tptr += LLDP_INTF_NUM_LEN;
+ tlen -= LLDP_INTF_NUM_LEN;
+
+ /*
+ * The OID is optional.
+ */
+ if (tlen) {
+ oid_len = *tptr;
+
+ if (oid_len) {
+ printf("\n\t OID length %u", oid_len);
+ safeputs((const char *)tptr+1, oid_len);
+ }
+ }
+
+ return 1;
+}
+
+void
+lldp_print(register const u_char *pptr, register u_int len) {
+
+ u_int8_t subtype;
+ u_int16_t tlv, cap, ena_cap;
+ u_int oui, tlen, hexdump, tlv_type, tlv_len;
+ const u_char *tptr;
+
+ tptr = pptr;
+ tlen = len;
+
+ if (vflag) {
+ printf("LLDP, length %u", len);
+ }
+
+ while (tlen >= sizeof(tlv)) {
+
+ TCHECK2(*tptr, sizeof(tlv));
+
+ tlv = EXTRACT_16BITS(tptr);
+
+ tlv_type = LLDP_EXTRACT_TYPE(tlv);
+ tlv_len = LLDP_EXTRACT_LEN(tlv);
+ hexdump = FALSE;
+
+ tlen -= sizeof(tlv);
+ tptr += sizeof(tlv);
+
+ if (vflag) {
+ printf("\n\t%s TLV (%u), length %u",
+ tok2str(lldp_tlv_values, "Unknown", tlv_type),
+ tlv_type, tlv_len);
+ }
+
+ /* infinite loop check */
+ if (!tlv_type || !tlv_len) {
+ break;
+ }
+
+ TCHECK2(*tptr, tlv_len);
+
+ switch (tlv_type) {
+ case LLDP_TTL_TLV:
+ if (vflag) {
+ printf(": TTL %us", EXTRACT_16BITS(tptr));
+ }
+ break;
+
+ case LLDP_SYSTEM_NAME_TLV:
+
+ /*
+ * The system name is also print in non-verbose mode
+ * similar to the CDP printer.
+ */
+ if (vflag) {
+ printf(": ");
+ safeputs((const char *)tptr, tlv_len);
+ } else {
+ printf("LLDP, name ");
+ safeputs((const char *)tptr, tlv_len);
+ printf(", length %u", len);
+ }
+ break;
+
+ case LLDP_PORT_DESCR_TLV:
+ if (vflag) {
+ printf(": ");
+ safeputs((const char *)tptr, tlv_len);
+ }
+ break;
+
+ case LLDP_SYSTEM_DESCR_TLV:
+ if (vflag) {
+ printf("\n\t ");
+ safeputs((const char *)tptr, tlv_len);
+ }
+ break;
+
+
+ case LLDP_CHASSIS_ID_TLV:
+ if (vflag) {
+ subtype = *tptr;
+ printf("\n\t Subtype %s (%u): ",
+ tok2str(lldp_chassis_subtype_values, "Unknown", subtype),
+ subtype);
+
+ switch (subtype) {
+ case LLDP_CHASSIS_MAC_ADDR_SUBTYPE:
+ printf("%s", etheraddr_string(tptr+1));
+ break;
+
+ case LLDP_CHASSIS_INTF_NAME_SUBTYPE: /* fall through */
+ case LLDP_CHASSIS_LOCAL_SUBTYPE:
+ case LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE:
+ case LLDP_CHASSIS_INTF_ALIAS_SUBTYPE:
+ case LLDP_CHASSIS_PORT_COMP_SUBTYPE:
+ safeputs((const char *)tptr+1, tlv_len-1);
+ break;
+
+ case LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE:
+ printf("%s", lldp_network_addr_print(tptr+1));
+ break;
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+ }
+ break;
+
+ case LLDP_PORT_ID_TLV:
+ if (vflag) {
+ subtype = *tptr;
+ printf("\n\t Subtype %s (%u): ",
+ tok2str(lldp_port_subtype_values, "Unknown", subtype),
+ subtype);
+
+ switch (subtype) {
+ case LLDP_PORT_MAC_ADDR_SUBTYPE:
+ printf("%s", etheraddr_string(tptr+1));
+ break;
+
+ case LLDP_PORT_INTF_NAME_SUBTYPE: /* fall through */
+ case LLDP_PORT_LOCAL_SUBTYPE:
+ case LLDP_PORT_AGENT_CIRC_ID_SUBTYPE:
+ case LLDP_PORT_INTF_ALIAS_SUBTYPE:
+ case LLDP_PORT_PORT_COMP_SUBTYPE:
+ safeputs((const char *)tptr+1, tlv_len-1);
+ break;
+
+ case LLDP_PORT_NETWORK_ADDR_SUBTYPE:
+ printf("%s", lldp_network_addr_print(tptr+1));
+ break;
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+ }
+ break;
+
+ case LLDP_PRIVATE_TLV:
+ if (vflag) {
+ oui = EXTRACT_24BITS(tptr);
+ printf(": OUI %s (0x%06x)", tok2str(oui_values, "Unknown", oui), oui);
+
+ switch (oui) {
+ case OUI_IEEE_8021_PRIVATE:
+ hexdump = lldp_private_8021_print(tptr);
+ break;
+ case OUI_IEEE_8023_PRIVATE:
+ hexdump = lldp_private_8023_print(tptr);
+ break;
+ case OUI_TIA:
+ hexdump = lldp_private_tia_print(tptr, tlv_len);
+ break;
+ default:
+ hexdump = TRUE;
+ break;
+ }
+ }
+ break;
+
+ case LLDP_SYSTEM_CAP_TLV:
+ if (vflag) {
+ cap = EXTRACT_16BITS(tptr);
+ ena_cap = EXTRACT_16BITS(tptr+2);
+ printf("\n\t System Capabilities [%s] (0x%04x)",
+ bittok2str(lldp_cap_values, "none", cap), cap);
+ printf("\n\t Enabled Capabilities [%s] (0x%04x)",
+ bittok2str(lldp_cap_values, "none", ena_cap), ena_cap);
+ }
+ break;
+
+ case LLDP_MGMT_ADDR_TLV:
+ if (vflag) {
+ if (!lldp_mgmt_addr_tlv_print(tptr, tlen)) {
+ goto trunc;
+ }
+ }
+ break;
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+
+ /* do we also want to see a hex dump ? */
+ if (vflag > 1 || (vflag && hexdump)) {
+ print_unknown_data(tptr,"\n\t ", tlv_len);
+ }
+
+ tlen -= tlv_len;
+ tptr += tlv_len;
+ }
+ return;
+ trunc:
+ printf("\n\t[|LLDP]");
+}
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/contrib/tcpdump/print-lmp.c b/contrib/tcpdump/print-lmp.c
index 84d166f..556db17 100644
--- a/contrib/tcpdump/print-lmp.c
+++ b/contrib/tcpdump/print-lmp.c
@@ -10,6 +10,8 @@
* LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
+ * Support for the Link Management Protocol as per rfc 4204.
+ *
* Original code by Hannes Gredler (hannes@juniper.net)
* Support for LMP service discovery extensions (defined by UNI 1.0) added
* by Manu Pathak (mapathak@cisco.com), May 2005
@@ -17,7 +19,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-lmp.c,v 1.5.2.4 2006/06/23 02:07:27 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-lmp.c,v 1.11 2007-08-02 17:32:49 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -91,21 +93,21 @@ static const struct tok lmp_obj_begin_verify_flag_values[] = {
};
static const struct tok lmp_obj_begin_verify_error_values[] = {
- { 0x01, "\n\t\tLink Verification Procedure Not supported"},
- { 0x02, "\n\t\tUnwilling to verify"},
- { 0x04, "\n\t\tUnsupported verification transport mechanism"},
- { 0x08, "\n\t\tLink_Id configuration error"},
- { 0x10, "\n\t\tUnknown object c-type"},
+ { 0x01, "Link Verification Procedure Not supported"},
+ { 0x02, "Unwilling to verify"},
+ { 0x04, "Unsupported verification transport mechanism"},
+ { 0x08, "Link-Id configuration error"},
+ { 0x10, "Unknown object c-type"},
{ 0, NULL}
};
static const struct tok lmp_obj_link_summary_error_values[] = {
- { 0x01, "\n\t\tUnacceptable non-negotiable LINK_SUMMARY parameters"},
- { 0x02, "\n\t\tRenegotiate LINK_SUMMARY parameters"},
- { 0x04, "\n\t\tInvalid TE-LINK Object"},
- { 0x08, "\n\t\tInvalid DATA-LINK Object"},
- { 0x10, "\n\t\tUnknown TE-LINK Object c-type"},
- { 0x20, "\n\t\tUnknown DATA-LINK Object c-type"},
+ { 0x01, "Unacceptable non-negotiable LINK-SUMMARY parameters"},
+ { 0x02, "Renegotiate LINK-SUMMARY parameters"},
+ { 0x04, "Invalid TE-LINK Object"},
+ { 0x08, "Invalid DATA-LINK Object"},
+ { 0x10, "Unknown TE-LINK Object c-type"},
+ { 0x20, "Unknown DATA-LINK Object c-type"},
{ 0, NULL}
};
@@ -532,7 +534,7 @@ lmp_print(register const u_char *pptr, register u_int len) {
case LMP_OBJ_HELLO:
switch(lmp_obj_ctype) {
case LMP_CTYPE_HELLO:
- printf("\n\t TxSeqNum: %u\n\t RcvSeqNum: %u",
+ printf("\n\t Tx Seq: %u, Rx Seq: %u",
EXTRACT_32BITS(obj_tptr),
EXTRACT_32BITS(obj_tptr+4));
break;
diff --git a/contrib/tcpdump/print-lspping.c b/contrib/tcpdump/print-lspping.c
index a80cdc6..f47a900 100644
--- a/contrib/tcpdump/print-lspping.c
+++ b/contrib/tcpdump/print-lspping.c
@@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-lspping.c,v 1.12.2.6 2006/06/23 02:07:27 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-lspping.c,v 1.18.2.1 2008-01-28 13:48:16 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -574,10 +574,11 @@ lspping_print(register const u_char *pptr, register u_int len) {
lspping_tlv_type=EXTRACT_16BITS(lspping_tlv_header->type);
lspping_tlv_len=EXTRACT_16BITS(lspping_tlv_header->length);
- if (lspping_tlv_len == 0)
+ /* some little sanity checking */
+ if (lspping_tlv_type == 0 || lspping_tlv_len == 0)
return;
- if(lspping_tlv_len % 4 || lspping_tlv_len < 4) { /* aligned to four octet boundary */
+ if(lspping_tlv_len < 4) {
printf("\n\t ERROR: TLV %u bogus size %u",lspping_tlv_type,lspping_tlv_len);
return;
}
@@ -858,6 +859,12 @@ lspping_print(register const u_char *pptr, register u_int len) {
print_unknown_data(tptr+sizeof(sizeof(struct lspping_tlv_header)),"\n\t ",
lspping_tlv_len);
+
+ /* All TLVs are aligned to four octet boundary */
+ if (lspping_tlv_len % 4) {
+ lspping_tlv_len += (4 - lspping_tlv_len % 4);
+ }
+
tptr+=lspping_tlv_len+sizeof(struct lspping_tlv_header);
tlen-=lspping_tlv_len+sizeof(struct lspping_tlv_header);
}
diff --git a/contrib/tcpdump/print-lwapp.c b/contrib/tcpdump/print-lwapp.c
new file mode 100644
index 0000000..984ebaa
--- /dev/null
+++ b/contrib/tcpdump/print-lwapp.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (c) 1998-2007 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * Support for the Light Weight Access Point Protocol as per draft-ohara-capwap-lwapp-04
+ *
+ * Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+"@(#) $Header: /tcpdump/master/tcpdump/print-lwapp.c,v 1.1 2007-07-24 16:07:30 hannes Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interface.h"
+#include "extract.h"
+#include "addrtoname.h"
+
+/*
+ * LWAPP transport (common) header
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |VER| RID |C|F|L| Frag ID | Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Status/WLANs | Payload... |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+struct lwapp_transport_header {
+ u_int8_t version;
+ u_int8_t frag_id;
+ u_int8_t length[2];
+ u_int16_t status;
+};
+
+/*
+ * LWAPP control header
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Message Type | Seq Num | Msg Element Length |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Session ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Msg Element [0..N] |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+struct lwapp_control_header {
+ u_int8_t msg_type;
+ u_int8_t seq_num;
+ u_int8_t len[2];
+ u_int8_t session_id[4];
+};
+
+#define LWAPP_VERSION 0
+#define LWAPP_EXTRACT_VERSION(x) (((x)&0xC0)>>6)
+#define LWAPP_EXTRACT_RID(x) (((x)&0x38)>>3)
+#define LWAPP_EXTRACT_CONTROL_BIT(x) (((x)&0x04)>>2)
+
+static const struct tok lwapp_header_bits_values[] = {
+ { 0x01, "Last Fragment Bit"},
+ { 0x02, "Fragment Bit"},
+ { 0x04, "Control Bit"},
+ { 0, NULL}
+};
+
+#define LWAPP_MSGTYPE_DISCOVERY_REQUEST 1
+#define LWAPP_MSGTYPE_DISCOVERY_RESPONSE 2
+#define LWAPP_MSGTYPE_JOIN_REQUEST 3
+#define LWAPP_MSGTYPE_JOIN_RESPONSE 4
+#define LWAPP_MSGTYPE_JOIN_ACK 5
+#define LWAPP_MSGTYPE_JOIN_CONFIRM 6
+#define LWAPP_MSGTYPE_CONFIGURE_REQUEST 10
+#define LWAPP_MSGTYPE_CONFIGURE_RESPONSE 11
+#define LWAPP_MSGTYPE_CONF_UPDATE_REQUEST 12
+#define LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE 13
+#define LWAPP_MSGTYPE_WTP_EVENT_REQUEST 14
+#define LWAPP_MSGTYPE_WTP_EVENT_RESPONSE 15
+#define LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST 16
+#define LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE 17
+#define LWAPP_MSGTYPE_ECHO_REQUEST 22
+#define LWAPP_MSGTYPE_ECHO_RESPONSE 23
+#define LWAPP_MSGTYPE_IMAGE_DATA_REQUEST 24
+#define LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE 25
+#define LWAPP_MSGTYPE_RESET_REQUEST 26
+#define LWAPP_MSGTYPE_RESET_RESPONSE 27
+#define LWAPP_MSGTYPE_KEY_UPDATE_REQUEST 30
+#define LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE 31
+#define LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST 32
+#define LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE 33
+#define LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST 34
+#define LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE 35
+#define LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION 36
+#define LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST 37
+#define LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE 38
+#define LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST 39
+#define LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE 40
+
+static const struct tok lwapp_msg_type_values[] = {
+ { LWAPP_MSGTYPE_DISCOVERY_REQUEST, "Discovery req"},
+ { LWAPP_MSGTYPE_DISCOVERY_RESPONSE, "Discovery resp"},
+ { LWAPP_MSGTYPE_JOIN_REQUEST, "Join req"},
+ { LWAPP_MSGTYPE_JOIN_RESPONSE, "Join resp"},
+ { LWAPP_MSGTYPE_JOIN_ACK, "Join ack"},
+ { LWAPP_MSGTYPE_JOIN_CONFIRM, "Join confirm"},
+ { LWAPP_MSGTYPE_CONFIGURE_REQUEST, "Configure req"},
+ { LWAPP_MSGTYPE_CONFIGURE_RESPONSE, "Configure resp"},
+ { LWAPP_MSGTYPE_CONF_UPDATE_REQUEST, "Update req"},
+ { LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE, "Update resp"},
+ { LWAPP_MSGTYPE_WTP_EVENT_REQUEST, "WTP event req"},
+ { LWAPP_MSGTYPE_WTP_EVENT_RESPONSE, "WTP event resp"},
+ { LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST, "Change state event req"},
+ { LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE, "Change state event resp"},
+ { LWAPP_MSGTYPE_ECHO_REQUEST, "Echo req"},
+ { LWAPP_MSGTYPE_ECHO_RESPONSE, "Echo resp"},
+ { LWAPP_MSGTYPE_IMAGE_DATA_REQUEST, "Image data req"},
+ { LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE, "Image data resp"},
+ { LWAPP_MSGTYPE_RESET_REQUEST, "Channel status req"},
+ { LWAPP_MSGTYPE_RESET_RESPONSE, "Channel status resp"},
+ { LWAPP_MSGTYPE_KEY_UPDATE_REQUEST, "Key update req"},
+ { LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE, "Key update resp"},
+ { LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST, "Primary discovery req"},
+ { LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE, "Primary discovery resp"},
+ { LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST, "Data transfer req"},
+ { LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE, "Data transfer resp"},
+ { LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION, "Clear config ind"},
+ { LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST, "Wlan config req"},
+ { LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE, "Wlan config resp"},
+ { LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST, "Mobile config req"},
+ { LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE, "Mobile config resp"},
+ { 0, NULL}
+};
+
+/*
+ * LWAPP message elements
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Type | Length | Value ... |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct lwapp_message_header {
+ u_int8_t type;
+ u_int8_t length[2];
+};
+
+void
+lwapp_control_print(const u_char *pptr, u_int len, int has_ap_ident) {
+
+ const struct lwapp_transport_header *lwapp_trans_header;
+ const struct lwapp_control_header *lwapp_control_header;
+ const u_char *tptr;
+ int hexdump,tlen;
+ int msg_tlen;
+
+ tptr=pptr;
+
+ if (has_ap_ident) {
+ /* check if enough bytes for AP identity */
+ if (!TTEST2(*tptr, 6))
+ goto trunc;
+ lwapp_trans_header = (const struct lwapp_transport_header *)(pptr+6);
+ } else {
+ lwapp_trans_header = (const struct lwapp_transport_header *)pptr;
+ }
+ TCHECK(*lwapp_trans_header);
+
+ /*
+ * Sanity checking of the header.
+ */
+ if (LWAPP_EXTRACT_VERSION(lwapp_trans_header->version) != LWAPP_VERSION) {
+ printf("LWAPP version %u packet not supported",
+ LWAPP_EXTRACT_VERSION(lwapp_trans_header->version));
+ return;
+ }
+
+ /* non-verbose */
+ if (vflag < 1) {
+ printf("LWAPPv%u, %s frame, Flags [%s], length %u",
+ LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
+ LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
+ bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
+ len);
+ return;
+ }
+
+ /* ok they seem to want to know everything - lets fully decode it */
+ tlen=EXTRACT_16BITS(lwapp_trans_header->length);
+
+ printf("LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u",
+ LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
+ LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
+ LWAPP_EXTRACT_RID(lwapp_trans_header->version),
+ bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
+ lwapp_trans_header->frag_id,
+ tlen);
+
+ if (has_ap_ident) {
+ printf("\n\tAP identity: %s",
+ etheraddr_string(tptr));
+ tptr+=sizeof(const struct lwapp_transport_header)+6;
+ } else {
+ tptr+=sizeof(const struct lwapp_transport_header);
+ }
+
+ while(tlen>0) {
+
+ /* did we capture enough for fully decoding the object header ? */
+ if (!TTEST2(*tptr, sizeof(struct lwapp_control_header)))
+ goto trunc;
+
+ lwapp_control_header = (const struct lwapp_control_header *)tptr;
+ msg_tlen = EXTRACT_16BITS(lwapp_control_header->len);
+
+ /* print message header */
+ printf("\n\t Msg type: %s (%u), Seqnum: %u, Msg len: %d, Session: 0x%08x",
+ tok2str(lwapp_msg_type_values,"Unknown",lwapp_control_header->msg_type),
+ lwapp_control_header->msg_type,
+ lwapp_control_header->seq_num,
+ msg_tlen,
+ EXTRACT_32BITS(lwapp_control_header->session_id));
+
+ /* did we capture enough for fully decoding the message */
+ if (!TTEST2(*tptr, msg_tlen))
+ goto trunc;
+ hexdump=FALSE;
+
+ /* XXX - Decode sub messages for each message */
+ switch(lwapp_control_header->msg_type) {
+ case LWAPP_MSGTYPE_DISCOVERY_REQUEST:
+ case LWAPP_MSGTYPE_DISCOVERY_RESPONSE:
+ case LWAPP_MSGTYPE_JOIN_REQUEST:
+ case LWAPP_MSGTYPE_JOIN_RESPONSE:
+ case LWAPP_MSGTYPE_JOIN_ACK:
+ case LWAPP_MSGTYPE_JOIN_CONFIRM:
+ case LWAPP_MSGTYPE_CONFIGURE_REQUEST:
+ case LWAPP_MSGTYPE_CONFIGURE_RESPONSE:
+ case LWAPP_MSGTYPE_CONF_UPDATE_REQUEST:
+ case LWAPP_MSGTYPE_CONF_UPDATE_RESPONSE:
+ case LWAPP_MSGTYPE_WTP_EVENT_REQUEST:
+ case LWAPP_MSGTYPE_WTP_EVENT_RESPONSE:
+ case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_REQUEST:
+ case LWAPP_MSGTYPE_CHANGE_STATE_EVENT_RESPONSE:
+ case LWAPP_MSGTYPE_ECHO_REQUEST:
+ case LWAPP_MSGTYPE_ECHO_RESPONSE:
+ case LWAPP_MSGTYPE_IMAGE_DATA_REQUEST:
+ case LWAPP_MSGTYPE_IMAGE_DATA_RESPONSE:
+ case LWAPP_MSGTYPE_RESET_REQUEST:
+ case LWAPP_MSGTYPE_RESET_RESPONSE:
+ case LWAPP_MSGTYPE_KEY_UPDATE_REQUEST:
+ case LWAPP_MSGTYPE_KEY_UPDATE_RESPONSE:
+ case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_REQUEST:
+ case LWAPP_MSGTYPE_PRIMARY_DISCOVERY_RESPONSE:
+ case LWAPP_MSGTYPE_DATA_TRANSFER_REQUEST:
+ case LWAPP_MSGTYPE_DATA_TRANSFER_RESPONSE:
+ case LWAPP_MSGTYPE_CLEAR_CONFIG_INDICATION:
+ case LWAPP_MSGTYPE_WLAN_CONFIG_REQUEST:
+ case LWAPP_MSGTYPE_WLAN_CONFIG_RESPONSE:
+ case LWAPP_MSGTYPE_MOBILE_CONFIG_REQUEST:
+ case LWAPP_MSGTYPE_MOBILE_CONFIG_RESPONSE:
+ default:
+ break;
+ }
+
+ tptr += sizeof(struct lwapp_control_header) + msg_tlen;
+ tlen -= sizeof(struct lwapp_control_header) + msg_tlen;
+ }
+ return;
+
+ trunc:
+ printf("\n\t\t packet exceeded snapshot");
+}
+
+void
+lwapp_data_print(const u_char *pptr, u_int len) {
+
+ const struct lwapp_transport_header *lwapp_trans_header;
+ const u_char *tptr;
+ int tlen;
+
+ tptr=pptr;
+
+ /* check if enough bytes for AP identity */
+ if (!TTEST2(*tptr, 6))
+ goto trunc;
+ lwapp_trans_header = (const struct lwapp_transport_header *)pptr;
+ TCHECK(*lwapp_trans_header);
+
+ /*
+ * Sanity checking of the header.
+ */
+ if (LWAPP_EXTRACT_VERSION(lwapp_trans_header->version) != LWAPP_VERSION) {
+ printf("LWAPP version %u packet not supported",
+ LWAPP_EXTRACT_VERSION(lwapp_trans_header->version));
+ return;
+ }
+
+ /* non-verbose */
+ if (vflag < 1) {
+ printf("LWAPPv%u, %s frame, Flags [%s], length %u",
+ LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
+ LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
+ bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
+ len);
+ return;
+ }
+
+ /* ok they seem to want to know everything - lets fully decode it */
+ tlen=EXTRACT_16BITS(lwapp_trans_header->length);
+
+ printf("LWAPPv%u, %s frame, Radio-id %u, Flags [%s], Frag-id %u, length %u",
+ LWAPP_EXTRACT_VERSION(lwapp_trans_header->version),
+ LWAPP_EXTRACT_CONTROL_BIT(lwapp_trans_header->version) ? "Control" : "Data",
+ LWAPP_EXTRACT_RID(lwapp_trans_header->version),
+ bittok2str(lwapp_header_bits_values,"none",(lwapp_trans_header->version)&0x07),
+ lwapp_trans_header->frag_id,
+ tlen);
+
+ tptr+=sizeof(const struct lwapp_transport_header);
+ tlen-=sizeof(const struct lwapp_transport_header);
+
+ /* FIX - An IEEE 802.11 frame follows - hexdump for now */
+ print_unknown_data(tptr, "\n\t", tlen);
+
+ return;
+
+ trunc:
+ printf("\n\t\t packet exceeded snapshot");
+}
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/contrib/tcpdump/print-lwres.c b/contrib/tcpdump/print-lwres.c
index d0d6fe1..aad4eee 100644
--- a/contrib/tcpdump/print-lwres.c
+++ b/contrib/tcpdump/print-lwres.c
@@ -29,7 +29,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-lwres.c,v 1.13 2004/03/24 01:54:29 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-lwres.c,v 1.13 2004-03-24 01:54:29 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-mobile.c b/contrib/tcpdump/print-mobile.c
index fe6f013..816ffd6 100644
--- a/contrib/tcpdump/print-mobile.c
+++ b/contrib/tcpdump/print-mobile.c
@@ -42,7 +42,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-mobile.c,v 1.15 2004/03/24 01:58:14 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-mobile.c,v 1.15 2004-03-24 01:58:14 guy Exp $";
#endif
#include <tcpdump-stdinc.h>
diff --git a/contrib/tcpdump/print-mobility.c b/contrib/tcpdump/print-mobility.c
index 8f9cbee..1490b72 100644
--- a/contrib/tcpdump/print-mobility.c
+++ b/contrib/tcpdump/print-mobility.c
@@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-mobility.c,v 1.11.2.1 2005/04/20 22:21:16 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-mobility.c,v 1.12 2005-04-20 22:21:00 guy Exp $";
#endif
#ifdef INET6
diff --git a/contrib/tcpdump/print-mpcp.c b/contrib/tcpdump/print-mpcp.c
new file mode 100644
index 0000000..244f280
--- /dev/null
+++ b/contrib/tcpdump/print-mpcp.c
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 1998-2006 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * support for the IEEE MPCP protocol as per 802.3ah
+ *
+ * Original code by Hannes Gredler (hannes@juniper.net)
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/print-mpcp.c,v 1.2 2006-02-10 17:24:55 hannes Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interface.h"
+#include "extract.h"
+#include "addrtoname.h"
+#include "ether.h"
+
+#define MPCP_TIMESTAMP_LEN 4
+#define MPCP_TIMESTAMP_DURATION_LEN 2
+
+struct mpcp_common_header_t {
+ u_int8_t opcode[2];
+ u_int8_t timestamp[MPCP_TIMESTAMP_LEN];
+};
+
+#define MPCP_OPCODE_PAUSE 0x0001
+#define MPCP_OPCODE_GATE 0x0002
+#define MPCP_OPCODE_REPORT 0x0003
+#define MPCP_OPCODE_REG_REQ 0x0004
+#define MPCP_OPCODE_REG 0x0005
+#define MPCP_OPCODE_REG_ACK 0x0006
+
+static const struct tok mpcp_opcode_values[] = {
+ { MPCP_OPCODE_PAUSE, "Pause" },
+ { MPCP_OPCODE_GATE, "Gate" },
+ { MPCP_OPCODE_REPORT, "Report" },
+ { MPCP_OPCODE_REG_REQ, "Register Request" },
+ { MPCP_OPCODE_REG, "Register" },
+ { MPCP_OPCODE_REG_ACK, "Register ACK" },
+ { 0, NULL}
+};
+
+#define MPCP_GRANT_NUMBER_LEN 1
+#define MPCP_GRANT_NUMBER_MASK 0x7
+static const struct tok mpcp_grant_flag_values[] = {
+ { 0x08, "Discovery" },
+ { 0x10, "Force Grant #1" },
+ { 0x20, "Force Grant #2" },
+ { 0x40, "Force Grant #3" },
+ { 0x80, "Force Grant #4" },
+ { 0, NULL}
+};
+
+struct mpcp_grant_t {
+ u_int8_t starttime[MPCP_TIMESTAMP_LEN];
+ u_int8_t duration[MPCP_TIMESTAMP_DURATION_LEN];
+};
+
+struct mpcp_reg_req_t {
+ u_int8_t flags;
+ u_int8_t pending_grants;
+};
+
+
+static const struct tok mpcp_reg_req_flag_values[] = {
+ { 1, "Register" },
+ { 3, "De-Register" },
+ { 0, NULL}
+};
+
+struct mpcp_reg_t {
+ u_int8_t assigned_port[2];
+ u_int8_t flags;
+ u_int8_t sync_time[MPCP_TIMESTAMP_DURATION_LEN];
+ u_int8_t echoed_pending_grants;
+};
+
+static const struct tok mpcp_reg_flag_values[] = {
+ { 1, "Re-Register" },
+ { 2, "De-Register" },
+ { 3, "ACK" },
+ { 4, "NACK" },
+ { 0, NULL}
+};
+
+#define MPCP_REPORT_QUEUESETS_LEN 1
+#define MPCP_REPORT_REPORTBITMAP_LEN 1
+static const struct tok mpcp_report_bitmap_values[] = {
+ { 0x01, "Q0" },
+ { 0x02, "Q1" },
+ { 0x04, "Q2" },
+ { 0x08, "Q3" },
+ { 0x10, "Q4" },
+ { 0x20, "Q5" },
+ { 0x40, "Q6" },
+ { 0x80, "Q7" },
+ { 0, NULL}
+};
+
+struct mpcp_reg_ack_t {
+ u_int8_t flags;
+ u_int8_t echoed_assigned_port[2];
+ u_int8_t echoed_sync_time[MPCP_TIMESTAMP_DURATION_LEN];
+};
+
+static const struct tok mpcp_reg_ack_flag_values[] = {
+ { 0, "NACK" },
+ { 1, "ACK" },
+ { 0, NULL}
+};
+
+void
+mpcp_print(register const u_char *pptr, register u_int length) {
+
+ union {
+ const struct mpcp_common_header_t *common_header;
+ const struct mpcp_grant_t *grant;
+ const struct mpcp_reg_req_t *reg_req;
+ const struct mpcp_reg_t *reg;
+ const struct mpcp_reg_ack_t *reg_ack;
+ } mpcp;
+
+
+ const u_char *tptr;
+ u_int16_t opcode;
+ u_int8_t grant_numbers, grant;
+ u_int8_t queue_sets, queue_set, report_bitmap, report;
+
+ tptr=pptr;
+ mpcp.common_header = (const struct mpcp_common_header_t *)pptr;
+
+ if (!TTEST2(*tptr, sizeof(const struct mpcp_common_header_t)))
+ goto trunc;
+ opcode = EXTRACT_16BITS(mpcp.common_header->opcode);
+ printf("MPCP, Opcode %s", tok2str(mpcp_opcode_values, "Unknown (%u)", opcode));
+ if (opcode != MPCP_OPCODE_PAUSE) {
+ printf(", Timestamp %u ticks", EXTRACT_32BITS(mpcp.common_header->timestamp));
+ }
+ printf(", length %u", length);
+
+ if (!vflag)
+ return;
+
+ tptr += sizeof(const struct mpcp_common_header_t);
+
+ switch (opcode) {
+ case MPCP_OPCODE_PAUSE:
+ break;
+
+ case MPCP_OPCODE_GATE:
+ if (!TTEST2(*tptr, MPCP_GRANT_NUMBER_LEN))
+ goto trunc;
+ grant_numbers = *tptr & MPCP_GRANT_NUMBER_MASK;
+ printf("\n\tGrant Numbers %u, Flags [ %s ]",
+ grant_numbers,
+ bittok2str(mpcp_grant_flag_values,
+ "?",
+ *tptr &~ MPCP_GRANT_NUMBER_MASK));
+ tptr++;
+
+ for (grant = 1; grant <= grant_numbers; grant++) {
+ if (!TTEST2(*tptr, sizeof(const struct mpcp_grant_t)))
+ goto trunc;
+ mpcp.grant = (const struct mpcp_grant_t *)tptr;
+ printf("\n\tGrant #%u, Start-Time %u ticks, duration %u ticks",
+ grant,
+ EXTRACT_32BITS(mpcp.grant->starttime),
+ EXTRACT_16BITS(mpcp.grant->duration));
+ tptr += sizeof(const struct mpcp_grant_t);
+ }
+
+ if (!TTEST2(*tptr, MPCP_TIMESTAMP_DURATION_LEN))
+ goto trunc;
+ printf("\n\tSync-Time %u ticks", EXTRACT_16BITS(tptr));
+ break;
+
+
+ case MPCP_OPCODE_REPORT:
+ if (!TTEST2(*tptr, MPCP_REPORT_QUEUESETS_LEN))
+ goto trunc;
+ queue_sets = *tptr;
+ tptr+=MPCP_REPORT_QUEUESETS_LEN;
+ printf("\n\tTotal Queue-Sets %u", queue_sets);
+
+ for (queue_set = 1; queue_set < queue_sets; queue_set++) {
+ if (!TTEST2(*tptr, MPCP_REPORT_REPORTBITMAP_LEN))
+ goto trunc;
+ report_bitmap = *(tptr);
+ printf("\n\t Queue-Set #%u, Report-Bitmap [ %s ]",
+ queue_sets,
+ bittok2str(mpcp_report_bitmap_values, "Unknown", report_bitmap));
+ tptr++;
+
+ report=1;
+ while (report_bitmap != 0) {
+ if (report_bitmap & 1) {
+ if (!TTEST2(*tptr, MPCP_TIMESTAMP_DURATION_LEN))
+ goto trunc;
+ printf("\n\t Q%u Report, Duration %u ticks",
+ report,
+ EXTRACT_16BITS(tptr));
+ tptr+=MPCP_TIMESTAMP_DURATION_LEN;
+ }
+ report++;
+ report_bitmap = report_bitmap >> 1;
+ }
+ }
+ break;
+
+ case MPCP_OPCODE_REG_REQ:
+ if (!TTEST2(*tptr, sizeof(const struct mpcp_reg_req_t)))
+ goto trunc;
+ mpcp.reg_req = (const struct mpcp_reg_req_t *)tptr;
+ printf("\n\tFlags [ %s ], Pending-Grants %u",
+ bittok2str(mpcp_reg_req_flag_values, "Reserved", mpcp.reg_req->flags),
+ mpcp.reg_req->pending_grants);
+ break;
+
+ case MPCP_OPCODE_REG:
+ if (!TTEST2(*tptr, sizeof(const struct mpcp_reg_t)))
+ goto trunc;
+ mpcp.reg = (const struct mpcp_reg_t *)tptr;
+ printf("\n\tAssigned-Port %u, Flags [ %s ]" \
+ "\n\tSync-Time %u ticks, Echoed-Pending-Grants %u",
+ EXTRACT_16BITS(mpcp.reg->assigned_port),
+ bittok2str(mpcp_reg_flag_values, "Reserved", mpcp.reg->flags),
+ EXTRACT_16BITS(mpcp.reg->sync_time),
+ mpcp.reg->echoed_pending_grants);
+ break;
+
+ case MPCP_OPCODE_REG_ACK:
+ if (!TTEST2(*tptr, sizeof(const struct mpcp_reg_ack_t)))
+ goto trunc;
+ mpcp.reg_ack = (const struct mpcp_reg_ack_t *)tptr;
+ printf("\n\tEchoed-Assigned-Port %u, Flags [ %s ]" \
+ "\n\tEchoed-Sync-Time %u ticks",
+ EXTRACT_16BITS(mpcp.reg_ack->echoed_assigned_port),
+ bittok2str(mpcp_reg_ack_flag_values, "Reserved", mpcp.reg_ack->flags),
+ EXTRACT_16BITS(mpcp.reg_ack->echoed_sync_time));
+ break;
+
+ default:
+ /* unknown opcode - hexdump for now */
+ print_unknown_data(pptr, "\n\t", length);
+ break;
+ }
+
+ return;
+
+trunc:
+ printf("\n\t[|MPCP]");
+}
diff --git a/contrib/tcpdump/print-mpls.c b/contrib/tcpdump/print-mpls.c
index 9d54567..c6b0814 100644
--- a/contrib/tcpdump/print-mpls.c
+++ b/contrib/tcpdump/print-mpls.c
@@ -28,7 +28,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-mpls.c,v 1.13.2.1 2005/07/05 09:39:29 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-mpls.c,v 1.14 2005-07-05 09:38:19 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-msdp.c b/contrib/tcpdump/print-msdp.c
index 3f79b68..a228ab7 100644
--- a/contrib/tcpdump/print-msdp.c
+++ b/contrib/tcpdump/print-msdp.c
@@ -17,7 +17,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-msdp.c,v 1.7 2005/04/06 21:32:41 mcr Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-msdp.c,v 1.7 2005-04-06 21:32:41 mcr Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-netbios.c b/contrib/tcpdump/print-netbios.c
index 419953c..c92eb9e 100644
--- a/contrib/tcpdump/print-netbios.c
+++ b/contrib/tcpdump/print-netbios.c
@@ -24,7 +24,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-netbios.c,v 1.20 2003/11/16 09:36:29 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-netbios.c,v 1.20 2003-11-16 09:36:29 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-nfs.c b/contrib/tcpdump/print-nfs.c
index e47f0f6..c648357 100644
--- a/contrib/tcpdump/print-nfs.c
+++ b/contrib/tcpdump/print-nfs.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-nfs.c,v 1.106.2.4 2007/06/15 23:17:40 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-nfs.c,v 1.110.2.1 2007-12-22 03:08:45 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -51,7 +51,7 @@ static const char rcsid[] _U_ =
#include "rpc_msg.h"
static void nfs_printfh(const u_int32_t *, const u_int);
-static void xid_map_enter(const struct sunrpc_msg *, const u_char *);
+static int xid_map_enter(const struct sunrpc_msg *, const u_char *);
static int32_t xid_map_find(const struct sunrpc_msg *, const u_char *,
u_int32_t *, u_int32_t *);
static void interp_reply(const struct sunrpc_msg *, u_int32_t, u_int32_t, int);
@@ -299,6 +299,7 @@ nfsreply_print(register const u_char *bp, u_int length,
nfserr = 0; /* assume no error */
rp = (const struct sunrpc_msg *)bp;
+ TCHECK(rp->rm_xid);
if (!nflag) {
strlcpy(srcid, "nfs", sizeof(srcid));
snprintf(dstid, sizeof(dstid), "%u",
@@ -309,6 +310,7 @@ nfsreply_print(register const u_char *bp, u_int length,
EXTRACT_32BITS(&rp->rm_xid));
}
print_nfsaddr(bp2, srcid, dstid);
+ TCHECK(rp->rm_reply.rp_stat);
reply_stat = EXTRACT_32BITS(&rp->rm_reply.rp_stat);
switch (reply_stat) {
@@ -320,10 +322,12 @@ nfsreply_print(register const u_char *bp, u_int length,
case SUNRPC_MSG_DENIED:
(void)printf("reply ERR %u: ", length);
+ TCHECK(rp->rm_reply.rp_reject.rj_stat);
rstat = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_stat);
switch (rstat) {
case SUNRPC_RPC_MISMATCH:
+ TCHECK(rp->rm_reply.rp_reject.rj_vers.high);
rlow = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.low);
rhigh = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_vers.high);
(void)printf("RPC Version mismatch (%u-%u)",
@@ -331,6 +335,7 @@ nfsreply_print(register const u_char *bp, u_int length,
break;
case SUNRPC_AUTH_ERROR:
+ TCHECK(rp->rm_reply.rp_reject.rj_why);
rwhy = EXTRACT_32BITS(&rp->rm_reply.rp_reject.rj_why);
(void)printf("Auth ");
switch (rwhy) {
@@ -386,6 +391,11 @@ nfsreply_print(register const u_char *bp, u_int length,
reply_stat, length);
break;
}
+ return;
+
+trunc:
+ if (!nfserr)
+ fputs(" [|nfs]", stdout);
}
/*
@@ -505,6 +515,8 @@ nfsreq_print(register const u_char *bp, u_int length,
nfserr = 0; /* assume no error */
rp = (const struct sunrpc_msg *)bp;
+
+ TCHECK(rp->rm_xid);
if (!nflag) {
snprintf(srcid, sizeof(srcid), "%u",
EXTRACT_32BITS(&rp->rm_xid));
@@ -517,7 +529,8 @@ nfsreq_print(register const u_char *bp, u_int length,
print_nfsaddr(bp2, srcid, dstid);
(void)printf("%d", length);
- xid_map_enter(rp, bp2); /* record proc number for later on */
+ if (!xid_map_enter(rp, bp2)) /* record proc number for later on */
+ goto trunc;
v3 = (EXTRACT_32BITS(&rp->rm_call.cb_vers) == NFS_VER3);
proc = EXTRACT_32BITS(&rp->rm_call.cb_proc);
@@ -888,7 +901,7 @@ struct xid_map_entry xid_map[XIDMAPSIZE];
int xid_map_next = 0;
int xid_map_hint = 0;
-static void
+static int
xid_map_enter(const struct sunrpc_msg *rp, const u_char *bp)
{
struct ip *ip = NULL;
@@ -897,6 +910,8 @@ xid_map_enter(const struct sunrpc_msg *rp, const u_char *bp)
#endif
struct xid_map_entry *xmep;
+ if (!TTEST(rp->rm_call.cb_vers))
+ return (0);
switch (IP_V((struct ip *)bp)) {
case 4:
ip = (struct ip *)bp;
@@ -907,7 +922,7 @@ xid_map_enter(const struct sunrpc_msg *rp, const u_char *bp)
break;
#endif
default:
- return;
+ return (1);
}
xmep = &xid_map[xid_map_next];
@@ -930,6 +945,7 @@ xid_map_enter(const struct sunrpc_msg *rp, const u_char *bp)
#endif
xmep->proc = EXTRACT_32BITS(&rp->rm_call.cb_proc);
xmep->vers = EXTRACT_32BITS(&rp->rm_call.cb_vers);
+ return (1);
}
/*
diff --git a/contrib/tcpdump/print-ntp.c b/contrib/tcpdump/print-ntp.c
index 9e8ccfa..8676cbe 100644
--- a/contrib/tcpdump/print-ntp.c
+++ b/contrib/tcpdump/print-ntp.c
@@ -27,7 +27,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ntp.c,v 1.41.2.1 2005/05/06 07:57:18 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ntp.c,v 1.42 2005-05-06 07:56:53 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-null.c b/contrib/tcpdump/print-null.c
index b525600..ba26733 100644
--- a/contrib/tcpdump/print-null.c
+++ b/contrib/tcpdump/print-null.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-null.c,v 1.53.2.4 2007/02/26 13:31:33 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-null.c,v 1.57 2006-03-23 14:58:44 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -38,12 +38,12 @@ static const char rcsid[] _U_ =
#include "interface.h"
#include "addrtoname.h"
-#include "af.h"
#include "ip.h"
#ifdef INET6
#include "ip6.h"
#endif
+#include "af.h"
/*
* The DLT_NULL packet header is 4 bytes long. It contains a host-byte-order
@@ -57,7 +57,6 @@ static const char rcsid[] _U_ =
*/
#define NULL_HDRLEN 4
-
/*
* Byte-swap a 32-bit number.
* ("htonl()" or "ntohl()" won't work - we want to byte-swap even on
diff --git a/contrib/tcpdump/print-ospf.c b/contrib/tcpdump/print-ospf.c
index fd8f111..4490496 100644
--- a/contrib/tcpdump/print-ospf.c
+++ b/contrib/tcpdump/print-ospf.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.56.2.4 2006/12/13 08:24:27 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ospf.c,v 1.66 2007-10-08 07:53:21 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -44,11 +44,11 @@ static const char rcsid[] _U_ =
#include "ip.h"
static struct tok ospf_option_values[] = {
- { OSPF_OPTION_T, "TOS" },
+ { OSPF_OPTION_T, "MultiTopology" }, /* draft-ietf-ospf-mt-09 */
{ OSPF_OPTION_E, "External" },
{ OSPF_OPTION_MC, "Multicast" },
{ OSPF_OPTION_NP, "NSSA" },
- { OSPF_OPTION_EA, "Advertise External" },
+ { OSPF_OPTION_L, "LLS" },
{ OSPF_OPTION_DC, "Demand Circuit" },
{ OSPF_OPTION_O, "Opaque" },
{ OSPF_OPTION_DN, "Up/Down" },
@@ -98,6 +98,7 @@ static struct tok ospf_dd_flag_values[] = {
{ OSPF_DB_INIT, "Init" },
{ OSPF_DB_MORE, "More" },
{ OSPF_DB_MASTER, "Master" },
+ { OSPF_DB_RESYNC, "OOBResync" },
{ 0, NULL }
};
@@ -172,7 +173,19 @@ static struct tok lsa_opaque_ri_tlv_cap_values[] = {
{ 0, NULL }
};
-static char tstr[] = " [|ospf]";
+static struct tok ospf_lls_tlv_values[] = {
+ { OSPF_LLS_EO, "Extended Options" },
+ { OSPF_LLS_MD5, "MD5 Authentication" },
+ { 0, NULL }
+};
+
+static struct tok ospf_lls_eo_options[] = {
+ { OSPF_LLS_EO_LR, "LSDB resync" },
+ { OSPF_LLS_EO_RS, "Restart" },
+ { 0, NULL }
+};
+
+static char tstr[] = " [|ospf2]";
#ifdef WIN32
#define inline __inline
@@ -181,6 +194,274 @@ static char tstr[] = " [|ospf]";
static int ospf_print_lshdr(const struct lsa_hdr *);
static const u_char *ospf_print_lsa(const struct lsa *);
static int ospf_decode_v2(const struct ospfhdr *, const u_char *);
+static int ospf_decode_lls(const struct ospfhdr *, register u_int);
+
+int
+ospf_print_grace_lsa (u_int8_t *tptr, u_int ls_length) {
+
+ u_int tlv_type, tlv_length;
+
+
+ while (ls_length > 0) {
+ TCHECK2(*tptr, 4);
+ if (ls_length < 4) {
+ printf("\n\t Remaining LS length %u < 4", ls_length);
+ return -1;
+ }
+ tlv_type = EXTRACT_16BITS(tptr);
+ tlv_length = EXTRACT_16BITS(tptr+2);
+ tptr+=4;
+ ls_length-=4;
+
+ printf("\n\t %s TLV (%u), length %u, value: ",
+ tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type),
+ tlv_type,
+ tlv_length);
+
+ if (tlv_length > ls_length) {
+ printf("\n\t Bogus length %u > %u", tlv_length,
+ ls_length);
+ return -1;
+ }
+
+ /* Infinite loop protection. */
+ if (tlv_type == 0 || tlv_length ==0) {
+ return -1;
+ }
+
+ TCHECK2(*tptr, tlv_length);
+ switch(tlv_type) {
+
+ case LS_OPAQUE_GRACE_TLV_PERIOD:
+ if (tlv_length != 4) {
+ printf("\n\t Bogus length %u != 4", tlv_length);
+ return -1;
+ }
+ printf("%us",EXTRACT_32BITS(tptr));
+ break;
+
+ case LS_OPAQUE_GRACE_TLV_REASON:
+ if (tlv_length != 1) {
+ printf("\n\t Bogus length %u != 1", tlv_length);
+ return -1;
+ }
+ printf("%s (%u)",
+ tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", *tptr),
+ *tptr);
+ break;
+
+ case LS_OPAQUE_GRACE_TLV_INT_ADDRESS:
+ if (tlv_length != 4) {
+ printf("\n\t Bogus length %u != 4", tlv_length);
+ return -1;
+ }
+ printf("%s", ipaddr_string(tptr));
+ break;
+
+ default:
+ if (vflag <= 1) {
+ if(!print_unknown_data(tptr,"\n\t ",tlv_length))
+ return -1;
+ }
+ break;
+
+ }
+ /* in OSPF everything has to be 32-bit aligned, including TLVs */
+ if (tlv_length%4 != 0)
+ tlv_length+=4-(tlv_length%4);
+ ls_length-=tlv_length;
+ tptr+=tlv_length;
+ }
+
+ return 0;
+trunc:
+ return -1;
+}
+
+int
+ospf_print_te_lsa (u_int8_t *tptr, u_int ls_length) {
+
+ u_int tlv_type, tlv_length, subtlv_type, subtlv_length;
+ u_int priority_level, te_class, count_srlg;
+ union { /* int to float conversion buffer for several subTLVs */
+ float f;
+ u_int32_t i;
+ } bw;
+
+ while (ls_length != 0) {
+ TCHECK2(*tptr, 4);
+ if (ls_length < 4) {
+ printf("\n\t Remaining LS length %u < 4", ls_length);
+ return -1;
+ }
+ tlv_type = EXTRACT_16BITS(tptr);
+ tlv_length = EXTRACT_16BITS(tptr+2);
+ tptr+=4;
+ ls_length-=4;
+
+ printf("\n\t %s TLV (%u), length: %u",
+ tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type),
+ tlv_type,
+ tlv_length);
+
+ if (tlv_length > ls_length) {
+ printf("\n\t Bogus length %u > %u", tlv_length,
+ ls_length);
+ return -1;
+ }
+
+ /* Infinite loop protection. */
+ if (tlv_type == 0 || tlv_length ==0) {
+ return -1;
+ }
+
+ switch(tlv_type) {
+ case LS_OPAQUE_TE_TLV_LINK:
+ while (tlv_length >= sizeof(subtlv_type) + sizeof(subtlv_length)) {
+ if (tlv_length < 4) {
+ printf("\n\t Remaining TLV length %u < 4",
+ tlv_length);
+ return -1;
+ }
+ TCHECK2(*tptr, 4);
+ subtlv_type = EXTRACT_16BITS(tptr);
+ subtlv_length = EXTRACT_16BITS(tptr+2);
+ tptr+=4;
+ tlv_length-=4;
+
+ printf("\n\t %s subTLV (%u), length: %u",
+ tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type),
+ subtlv_type,
+ subtlv_length);
+
+ TCHECK2(*tptr, subtlv_length);
+ switch(subtlv_type) {
+ case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP:
+ printf(", 0x%08x", EXTRACT_32BITS(tptr));
+ break;
+ case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID:
+ case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID:
+ printf(", %s (0x%08x)",
+ ipaddr_string(tptr),
+ EXTRACT_32BITS(tptr));
+ if (subtlv_length == 8) /* rfc4203 */
+ printf(", %s (0x%08x)",
+ ipaddr_string(tptr+4),
+ EXTRACT_32BITS(tptr+4));
+ break;
+ case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP:
+ case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP:
+ printf(", %s", ipaddr_string(tptr));
+ break;
+ case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW:
+ case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW:
+ bw.i = EXTRACT_32BITS(tptr);
+ printf(", %.3f Mbps", bw.f*8/1000000 );
+ break;
+ case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW:
+ for (te_class = 0; te_class < 8; te_class++) {
+ bw.i = EXTRACT_32BITS(tptr+te_class*4);
+ printf("\n\t\tTE-Class %u: %.3f Mbps",
+ te_class,
+ bw.f*8/1000000 );
+ }
+ break;
+ case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS:
+ printf("\n\t\tBandwidth Constraints Model ID: %s (%u)",
+ tok2str(diffserv_te_bc_values, "unknown", *tptr),
+ *tptr);
+ /* decode BCs until the subTLV ends */
+ for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) {
+ bw.i = EXTRACT_32BITS(tptr+4+te_class*4);
+ printf("\n\t\t Bandwidth constraint CT%u: %.3f Mbps",
+ te_class,
+ bw.f*8/1000000 );
+ }
+ break;
+ case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC:
+ printf(", Metric %u", EXTRACT_32BITS(tptr));
+ break;
+ case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE:
+ printf(", %s, Priority %u",
+ bittok2str(gmpls_link_prot_values, "none", *tptr),
+ *(tptr+1));
+ break;
+ case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR:
+ printf("\n\t\tInterface Switching Capability: %s",
+ tok2str(gmpls_switch_cap_values, "Unknown", *(tptr)));
+ printf("\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:",
+ tok2str(gmpls_encoding_values, "Unknown", *(tptr+1)));
+ for (priority_level = 0; priority_level < 8; priority_level++) {
+ bw.i = EXTRACT_32BITS(tptr+4+(priority_level*4));
+ printf("\n\t\t priority level %d: %.3f Mbps",
+ priority_level,
+ bw.f*8/1000000 );
+ }
+ break;
+ case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE:
+ printf(", %s (%u)",
+ tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",*tptr),
+ *tptr);
+ break;
+
+ case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP:
+ count_srlg = subtlv_length / 4;
+ if (count_srlg != 0)
+ printf("\n\t\t Shared risk group: ");
+ while (count_srlg > 0) {
+ bw.i = EXTRACT_32BITS(tptr);
+ printf("%d",bw.i);
+ tptr+=4;
+ count_srlg--;
+ if (count_srlg > 0)
+ printf(", ");
+ }
+ break;
+
+ default:
+ if (vflag <= 1) {
+ if(!print_unknown_data(tptr,"\n\t\t",subtlv_length))
+ return -1;
+ }
+ break;
+ }
+ /* in OSPF everything has to be 32-bit aligned, including subTLVs */
+ if (subtlv_length%4 != 0)
+ subtlv_length+=4-(subtlv_length%4);
+
+ tlv_length-=subtlv_length;
+ tptr+=subtlv_length;
+
+ }
+ break;
+
+ case LS_OPAQUE_TE_TLV_ROUTER:
+ if (tlv_length < 4) {
+ printf("\n\t TLV length %u < 4", tlv_length);
+ return -1;
+ }
+ TCHECK2(*tptr, 4);
+ printf(", %s", ipaddr_string(tptr));
+ break;
+
+ default:
+ if (vflag <= 1) {
+ if(!print_unknown_data(tptr,"\n\t ",tlv_length))
+ return -1;
+ }
+ break;
+ }
+ /* in OSPF everything has to be 32-bit aligned, including TLVs */
+ if (tlv_length%4 != 0)
+ tlv_length+=4-(tlv_length%4);
+ ls_length-=tlv_length;
+ tptr+=tlv_length;
+ }
+ return 0;
+trunc:
+ return -1;
+}
+
static int
ospf_print_lshdr(register const struct lsa_hdr *lshp)
@@ -190,13 +471,13 @@ ospf_print_lshdr(register const struct lsa_hdr *lshp)
TCHECK(lshp->ls_length);
ls_length = EXTRACT_16BITS(&lshp->ls_length);
if (ls_length < sizeof(struct lsa_hdr)) {
- printf("\n\t Bogus length %u < %lu", ls_length,
+ printf("\n\t Bogus length %u < header (%lu)", ls_length,
(unsigned long)sizeof(struct lsa_hdr));
return(-1);
}
TCHECK(lshp->ls_seq); /* XXX - ls_length check checked this */
- printf("\n\t Advertising Router: %s, seq 0x%08x, age %us, length: %u",
+ printf("\n\t Advertising Router %s, seq 0x%08x, age %us, length %u",
ipaddr_string(&lshp->ls_router),
EXTRACT_32BITS(&lshp->ls_seq),
EXTRACT_16BITS(&lshp->ls_age),
@@ -208,7 +489,7 @@ ospf_print_lshdr(register const struct lsa_hdr *lshp)
case LS_TYPE_OPAQUE_LL:
case LS_TYPE_OPAQUE_AL:
case LS_TYPE_OPAQUE_DW:
- printf("\n\t %s LSA (%d), Opaque-Type: %s LSA (%u), Opaque-ID: %u",
+ printf("\n\t %s LSA (%d), Opaque-Type %s LSA (%u), Opaque-ID %u",
tok2str(lsa_values,"unknown",lshp->ls_type),
lshp->ls_type,
@@ -238,6 +519,41 @@ trunc:
return (-1);
}
+/* draft-ietf-ospf-mt-09 */
+static struct tok ospf_topology_values[] = {
+ { 0, "default " },
+ { 1, "multicast " },
+ { 2, "management " },
+ { 0, NULL }
+};
+
+/*
+ * Print all the per-topology metrics.
+ */
+static void
+ospf_print_tos_metrics(const union un_tos *tos)
+{
+ int metric_count;
+ int toscount;
+
+ toscount = tos->link.link_tos_count+1;
+ metric_count = 0;
+
+ /*
+ * All but the first metric contain a valid topology id.
+ */
+ while (toscount) {
+ printf("\n\t\ttopology %s(%u), metric %u",
+ tok2str(ospf_topology_values, "",
+ metric_count ? tos->metrics.tos_type : 0),
+ metric_count ? tos->metrics.tos_type : 0,
+ EXTRACT_16BITS(&tos->metrics.tos_metric));
+ metric_count++;
+ tos++;
+ toscount--;
+ }
+}
+
/*
* Print a single link state advertisement. If truncated or if LSA length
* field is less than the length of the LSA header, return NULl, else
@@ -248,19 +564,13 @@ ospf_print_lsa(register const struct lsa *lsap)
{
register const u_int8_t *ls_end;
register const struct rlalink *rlp;
- register const struct tos_metric *tosp;
register const struct in_addr *ap;
register const struct aslametric *almp;
register const struct mcla *mcp;
register const u_int32_t *lp;
- register int j, k, tlv_type, tlv_length, subtlv_type, subtlv_length, priority_level, te_class;
+ register int j, tlv_type, tlv_length, topology;
register int ls_length;
const u_int8_t *tptr;
- int count_srlg;
- union { /* int to float conversion buffer for several subTLVs */
- float f;
- u_int32_t i;
- } bw;
tptr = (u_int8_t *)lsap->lsa_un.un_unknown; /* squelch compiler warnings */
ls_length = ospf_print_lshdr(&lsap->ls_hdr);
@@ -281,7 +591,7 @@ ospf_print_lsa(register const struct lsa *lsap)
rlp = lsap->lsa_un.un_rla.rla_link;
while (j--) {
TCHECK(*rlp);
- switch (rlp->link_type) {
+ switch (rlp->un_tos.link.link_type) {
case RLA_TYPE_VIRTUAL:
printf("\n\t Virtual Link: Neighbor Router-ID: %s, Interface Address: %s",
@@ -309,20 +619,14 @@ ospf_print_lsa(register const struct lsa *lsap)
default:
printf("\n\t Unknown Router Link Type (%u)",
- rlp->link_type);
+ rlp->un_tos.link.link_type);
return (ls_end);
}
- printf(", tos 0, metric: %d", EXTRACT_16BITS(&rlp->link_tos0metric));
- tosp = (struct tos_metric *)
- ((sizeof rlp->link_tos0metric) + (u_char *) rlp);
- for (k = 0; k < (int) rlp->link_toscount; ++k, ++tosp) {
- TCHECK(*tosp);
- printf(", tos %d, metric: %d",
- tosp->tos_type,
- EXTRACT_16BITS(&tosp->tos_metric));
- }
+
+ ospf_print_tos_metrics(&rlp->un_tos);
+
rlp = (struct rlalink *)((u_char *)(rlp + 1) +
- ((rlp->link_toscount) * sizeof(*tosp)));
+ ((rlp->un_tos.link.link_tos_count) * sizeof(union un_tos)));
}
break;
@@ -344,19 +648,16 @@ ospf_print_lsa(register const struct lsa *lsap)
ipaddr_string(&lsap->lsa_un.un_sla.sla_mask));
TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
lp = lsap->lsa_un.un_sla.sla_tosmetric;
- /* suppress tos if its not supported */
- if(!((lsap->ls_hdr.ls_options)&OSPF_OPTION_T)) {
- printf(", metric: %u", EXTRACT_32BITS(lp)&SLA_MASK_METRIC);
- break;
- }
while ((u_char *)lp < ls_end) {
register u_int32_t ul;
TCHECK(*lp);
ul = EXTRACT_32BITS(lp);
- printf(", tos %d metric %d",
- (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
- ul & SLA_MASK_METRIC);
+ topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
+ printf("\n\t\ttopology %s(%u) metric %d",
+ tok2str(ospf_topology_values, "", topology),
+ topology,
+ ul & SLA_MASK_METRIC);
++lp;
}
break;
@@ -364,19 +665,16 @@ ospf_print_lsa(register const struct lsa *lsap)
case LS_TYPE_SUM_ABR:
TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
lp = lsap->lsa_un.un_sla.sla_tosmetric;
- /* suppress tos if its not supported */
- if(!((lsap->ls_hdr.ls_options)&OSPF_OPTION_T)) {
- printf(", metric: %u", EXTRACT_32BITS(lp)&SLA_MASK_METRIC);
- break;
- }
while ((u_char *)lp < ls_end) {
register u_int32_t ul;
TCHECK(*lp);
ul = EXTRACT_32BITS(lp);
- printf(", tos %d metric %d",
- (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
- ul & SLA_MASK_METRIC);
+ topology = (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
+ printf("\n\t\ttopology %s(%u) metric %d",
+ tok2str(ospf_topology_values, "", topology),
+ topology,
+ ul & SLA_MASK_METRIC);
++lp;
}
break;
@@ -394,9 +692,11 @@ ospf_print_lsa(register const struct lsa *lsap)
TCHECK(almp->asla_tosmetric);
ul = EXTRACT_32BITS(&almp->asla_tosmetric);
- printf(", type %d, tos %d metric:",
- (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1,
- (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS);
+ topology = ((ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS);
+ printf("\n\t\ttopology %s(%u), type %d, metric",
+ tok2str(ospf_topology_values, "", topology),
+ topology,
+ (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1);
if ((ul & ASLA_MASK_METRIC)==0xffffff)
printf(" infinite");
else
@@ -471,7 +771,6 @@ ospf_print_lsa(register const struct lsa *lsap)
ls_length);
return(ls_end);
}
- ls_length-=tlv_length;
TCHECK2(*tptr, tlv_length);
switch(tlv_type) {
@@ -492,245 +791,32 @@ ospf_print_lsa(register const struct lsa *lsap)
}
tptr+=tlv_length;
+ ls_length-=tlv_length;
}
-
break;
- case LS_OPAQUE_TYPE_GRACE:
- tptr = (u_int8_t *)(&lsap->lsa_un.un_grace_tlv.type);
-
- while (ls_length != 0) {
- TCHECK2(*tptr, 4);
- if (ls_length < 4) {
- printf("\n\t Remaining LS length %u < 4", ls_length);
- return(ls_end);
- }
- tlv_type = EXTRACT_16BITS(tptr);
- tlv_length = EXTRACT_16BITS(tptr+2);
- tptr+=4;
- ls_length-=4;
-
- printf("\n\t %s TLV (%u), length: %u, value: ",
- tok2str(lsa_opaque_grace_tlv_values,"unknown",tlv_type),
- tlv_type,
- tlv_length);
-
- if (tlv_length > ls_length) {
- printf("\n\t Bogus length %u > %u", tlv_length,
- ls_length);
- return(ls_end);
- }
- ls_length-=tlv_length;
- TCHECK2(*tptr, tlv_length);
- switch(tlv_type) {
-
- case LS_OPAQUE_GRACE_TLV_PERIOD:
- if (tlv_length != 4) {
- printf("\n\t Bogus length %u != 4", tlv_length);
- return(ls_end);
- }
- printf("%us",EXTRACT_32BITS(tptr));
- break;
- case LS_OPAQUE_GRACE_TLV_REASON:
- if (tlv_length != 1) {
- printf("\n\t Bogus length %u != 1", tlv_length);
- return(ls_end);
- }
- printf("%s (%u)",
- tok2str(lsa_opaque_grace_tlv_reason_values, "Unknown", *tptr),
- *tptr);
- break;
- case LS_OPAQUE_GRACE_TLV_INT_ADDRESS:
- if (tlv_length != 4) {
- printf("\n\t Bogus length %u != 4", tlv_length);
- return(ls_end);
- }
- printf("%s", ipaddr_string(tptr));
- break;
- default:
- if (vflag <= 1) {
- if(!print_unknown_data(tptr,"\n\t ",tlv_length))
- return(ls_end);
- }
- break;
- }
- tptr+=tlv_length;
+ case LS_OPAQUE_TYPE_GRACE:
+ if (ospf_print_grace_lsa((u_int8_t *)(&lsap->lsa_un.un_grace_tlv.type),
+ ls_length) == -1) {
+ return(ls_end);
}
-
break;
- case LS_OPAQUE_TYPE_TE:
- tptr = (u_int8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type);
- while (ls_length != 0) {
- TCHECK2(*tptr, 4);
- if (ls_length < 4) {
- printf("\n\t Remaining LS length %u < 4", ls_length);
- return(ls_end);
- }
- tlv_type = EXTRACT_16BITS(tptr);
- tlv_length = EXTRACT_16BITS(tptr+2);
- tptr+=4;
- ls_length-=4;
-
- printf("\n\t %s TLV (%u), length: %u",
- tok2str(lsa_opaque_te_tlv_values,"unknown",tlv_type),
- tlv_type,
- tlv_length);
+ case LS_OPAQUE_TYPE_TE:
+ if (ospf_print_te_lsa((u_int8_t *)(&lsap->lsa_un.un_te_lsa_tlv.type),
+ ls_length) == -1) {
+ return(ls_end);
+ }
+ break;
- if (tlv_length > ls_length) {
- printf("\n\t Bogus length %u > %u", tlv_length,
- ls_length);
+ default:
+ if (vflag <= 1) {
+ if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown,
+ "\n\t ", ls_length))
return(ls_end);
- }
- ls_length-=tlv_length;
- switch(tlv_type) {
- case LS_OPAQUE_TE_TLV_LINK:
- while (tlv_length != 0) {
- if (tlv_length < 4) {
- printf("\n\t Remaining TLV length %u < 4",
- tlv_length);
- return(ls_end);
- }
- TCHECK2(*tptr, 4);
- subtlv_type = EXTRACT_16BITS(tptr);
- subtlv_length = EXTRACT_16BITS(tptr+2);
- tptr+=4;
- tlv_length-=4;
-
- printf("\n\t %s subTLV (%u), length: %u",
- tok2str(lsa_opaque_te_link_tlv_subtlv_values,"unknown",subtlv_type),
- subtlv_type,
- subtlv_length);
-
- TCHECK2(*tptr, subtlv_length);
- switch(subtlv_type) {
- case LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP:
- printf(", 0x%08x", EXTRACT_32BITS(tptr));
- break;
- case LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID:
- case LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID:
- printf(", %s (0x%08x)",
- ipaddr_string(tptr),
- EXTRACT_32BITS(tptr));
- if (subtlv_length == 8) /* draft-ietf-ccamp-ospf-gmpls-extensions */
- printf(", %s (0x%08x)",
- ipaddr_string(tptr+4),
- EXTRACT_32BITS(tptr+4));
- break;
- case LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP:
- case LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP:
- printf(", %s", ipaddr_string(tptr));
- break;
- case LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW:
- case LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW:
- bw.i = EXTRACT_32BITS(tptr);
- printf(", %.3f Mbps", bw.f*8/1000000 );
- break;
- case LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW:
- for (te_class = 0; te_class < 8; te_class++) {
- bw.i = EXTRACT_32BITS(tptr+te_class*4);
- printf("\n\t\tTE-Class %u: %.3f Mbps",
- te_class,
- bw.f*8/1000000 );
- }
- break;
- case LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS:
- printf("\n\t\tBandwidth Constraints Model ID: %s (%u)",
- tok2str(diffserv_te_bc_values, "unknown", *tptr),
- *tptr);
- /* decode BCs until the subTLV ends */
- for (te_class = 0; te_class < (subtlv_length-4)/4; te_class++) {
- bw.i = EXTRACT_32BITS(tptr+4+te_class*4);
- printf("\n\t\t Bandwidth constraint CT%u: %.3f Mbps",
- te_class,
- bw.f*8/1000000 );
- }
- break;
- case LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC:
- printf(", Metric %u", EXTRACT_32BITS(tptr));
- break;
- case LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE:
- printf(", %s, Priority %u",
- bittok2str(gmpls_link_prot_values, "none", *tptr),
- *(tptr+1));
- break;
- case LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR:
- printf("\n\t\tInterface Switching Capability: %s",
- tok2str(gmpls_switch_cap_values, "Unknown", *(tptr)));
- printf("\n\t\tLSP Encoding: %s\n\t\tMax LSP Bandwidth:",
- tok2str(gmpls_encoding_values, "Unknown", *(tptr+1)));
- for (priority_level = 0; priority_level < 8; priority_level++) {
- bw.i = EXTRACT_32BITS(tptr+4+(priority_level*4));
- printf("\n\t\t priority level %d: %.3f Mbps",
- priority_level,
- bw.f*8/1000000 );
- }
- break;
- case LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE:
- printf(", %s (%u)",
- tok2str(lsa_opaque_te_tlv_link_type_sub_tlv_values,"unknown",*tptr),
- *tptr);
- break;
-
- case LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP:
- count_srlg = subtlv_length / 4;
- if (count_srlg != 0)
- printf("\n\t\t Shared risk group: ");
- while (count_srlg > 0) {
- bw.i = EXTRACT_32BITS(tptr);
- printf("%d",bw.i);
- tptr+=4;
- count_srlg--;
- if (count_srlg > 0)
- printf(", ");
- }
- break;
-
- default:
- if (vflag <= 1) {
- if(!print_unknown_data(tptr,"\n\t\t",subtlv_length))
- return(ls_end);
- }
- break;
- }
- /* in OSPF everything has to be 32-bit aligned, including TLVs */
- if (subtlv_length%4 != 0)
- subtlv_length+=4-(subtlv_length%4);
-
- tlv_length-=subtlv_length;
- tptr+=subtlv_length;
-
- }
- break;
-
- case LS_OPAQUE_TE_TLV_ROUTER:
- if (tlv_length < 4) {
- printf("\n\t TLV length %u < 4", tlv_length);
- return(ls_end);
- }
- TCHECK2(*tptr, 4);
- printf(", %s", ipaddr_string(tptr));
- break;
-
- default:
- if (vflag <= 1) {
- if(!print_unknown_data(tptr,"\n\t ",tlv_length))
- return(ls_end);
- }
- break;
- }
- tptr+=tlv_length;
- }
+ }
break;
- }
- break;
- default:
- if (vflag <= 1) {
- if(!print_unknown_data((u_int8_t *)lsap->lsa_un.un_unknown,
- "\n\t ", ls_length))
- return(ls_end);
- }
- break;
+ }
}
/* do we want to see an additionally hexdump ? */
@@ -746,6 +832,98 @@ trunc:
}
static int
+ospf_decode_lls(register const struct ospfhdr *op,
+ register u_int length)
+{
+ register const u_char *dptr;
+ register const u_char *dataend;
+ register u_int length2;
+ register u_int16_t lls_type, lls_len;
+ register u_int32_t lls_flags;
+
+ switch (op->ospf_type) {
+
+ case OSPF_TYPE_HELLO:
+ if (!(op->ospf_hello.hello_options & OSPF_OPTION_L))
+ return (0);
+ break;
+
+ case OSPF_TYPE_DD:
+ if (!(op->ospf_db.db_options & OSPF_OPTION_L))
+ return (0);
+ break;
+
+ default:
+ return (0);
+ }
+
+ /* dig deeper if LLS data is available; see RFC4813 */
+ length2 = EXTRACT_16BITS(&op->ospf_len);
+ dptr = (u_char *)op + length2;
+ dataend = (u_char *)op + length;
+
+ if (EXTRACT_16BITS(&op->ospf_authtype) == OSPF_AUTH_MD5) {
+ dptr = dptr + op->ospf_authdata[3];
+ length2 += op->ospf_authdata[3];
+ }
+ if (length2 >= length) {
+ printf("\n\t[LLS truncated]");
+ return (1);
+ }
+ TCHECK2(*dptr, 2);
+ printf("\n\t LLS: checksum: 0x%04x", (u_int)EXTRACT_16BITS(dptr));
+
+ dptr += 2;
+ TCHECK2(*dptr, 2);
+ length2 = EXTRACT_16BITS(dptr);
+ printf(", length: %u", length2);
+
+ dptr += 2;
+ TCHECK(*dptr);
+ while (dptr < dataend) {
+ TCHECK2(*dptr, 2);
+ lls_type = EXTRACT_16BITS(dptr);
+ printf("\n\t %s (%u)",
+ tok2str(ospf_lls_tlv_values,"Unknown TLV",lls_type),
+ lls_type);
+ dptr += 2;
+ TCHECK2(*dptr, 2);
+ lls_len = EXTRACT_16BITS(dptr);
+ printf(", length: %u", lls_len);
+ dptr += 2;
+ switch (lls_type) {
+
+ case OSPF_LLS_EO:
+ if (lls_len != 4) {
+ printf(" [should be 4]");
+ lls_len = 4;
+ }
+ TCHECK2(*dptr, 4);
+ lls_flags = EXTRACT_32BITS(dptr);
+ printf("\n\t Options: 0x%08x [%s]", lls_flags,
+ bittok2str(ospf_lls_eo_options,"?",lls_flags));
+
+ break;
+
+ case OSPF_LLS_MD5:
+ if (lls_len != 20) {
+ printf(" [should be 20]");
+ lls_len = 20;
+ }
+ TCHECK2(*dptr, 4);
+ printf("\n\t Sequence number: 0x%08x", EXTRACT_32BITS(dptr));
+ break;
+ }
+
+ dptr += lls_len;
+ }
+
+ return (0);
+trunc:
+ return (1);
+}
+
+static int
ospf_decode_v2(register const struct ospfhdr *op,
register const u_char *dataend)
{
@@ -765,11 +943,11 @@ ospf_decode_v2(register const struct ospfhdr *op,
break;
case OSPF_TYPE_HELLO:
- printf("\n\tOptions: [%s]",
+ printf("\n\tOptions [%s]",
bittok2str(ospf_option_values,"none",op->ospf_hello.hello_options));
TCHECK(op->ospf_hello.hello_deadint);
- printf("\n\t Hello Timer: %us, Dead Timer %us, Mask: %s, Priority: %u",
+ printf("\n\t Hello Timer %us, Dead Timer %us, Mask %s, Priority %u",
EXTRACT_16BITS(&op->ospf_hello.hello_helloint),
EXTRACT_32BITS(&op->ospf_hello.hello_deadint),
ipaddr_string(&op->ospf_hello.hello_mask),
@@ -797,19 +975,23 @@ ospf_decode_v2(register const struct ospfhdr *op,
case OSPF_TYPE_DD:
TCHECK(op->ospf_db.db_options);
- printf("\n\tOptions: [%s]",
+ printf("\n\tOptions [%s]",
bittok2str(ospf_option_values,"none",op->ospf_db.db_options));
TCHECK(op->ospf_db.db_flags);
- printf(", DD Flags: [%s]",
+ printf(", DD Flags [%s]",
bittok2str(ospf_dd_flag_values,"none",op->ospf_db.db_flags));
+ TCHECK(op->ospf_db.db_ifmtu);
+ if (op->ospf_db.db_ifmtu) {
+ printf(", MTU: %u", ntohs(op->ospf_db.db_ifmtu));
+ }
+ TCHECK(op->ospf_db.db_seq);
+ printf(", Sequence: 0x%08x", EXTRACT_32BITS(&op->ospf_db.db_seq));
- if (vflag) {
- /* Print all the LS adv's */
- lshp = op->ospf_db.db_lshdr;
- while (ospf_print_lshdr(lshp) != -1) {
- ++lshp;
- }
- }
+ /* Print all the LS adv's */
+ lshp = op->ospf_db.db_lshdr;
+ while (((u_char *)lshp < dataend) && ospf_print_lshdr(lshp) != -1) {
+ ++lshp;
+ }
break;
case OSPF_TYPE_LS_REQ:
@@ -863,7 +1045,6 @@ ospf_decode_v2(register const struct ospfhdr *op,
break;
default:
- printf("v2 type (%d)", op->ospf_type);
break;
}
return (0);
@@ -892,25 +1073,30 @@ ospf_print(register const u_char *bp, register u_int length,
/* value. If it's not valid, say so and return */
TCHECK(op->ospf_type);
cp = tok2str(type2str, "unknown LS-type", op->ospf_type);
- printf("OSPFv%u, %s, length: %u",
+ printf("OSPFv%u, %s, length %u",
op->ospf_version,
cp,
length);
if (*cp == 'u')
return;
- if(!vflag) /* non verbose - so lets bail out here */
+ if(!vflag) { /* non verbose - so lets bail out here */
return;
+ }
TCHECK(op->ospf_len);
if (length != EXTRACT_16BITS(&op->ospf_len)) {
printf(" [len %d]", EXTRACT_16BITS(&op->ospf_len));
- return;
}
- dataend = bp + length;
+
+ if (length > EXTRACT_16BITS(&op->ospf_len)) {
+ dataend = bp + EXTRACT_16BITS(&op->ospf_len);
+ } else {
+ dataend = bp + length;
+ }
TCHECK(op->ospf_routerid);
- printf("\n\tRouter-ID: %s", ipaddr_string(&op->ospf_routerid));
+ printf("\n\tRouter-ID %s", ipaddr_string(&op->ospf_routerid));
TCHECK(op->ospf_areaid);
if (op->ospf_areaid.s_addr != 0)
@@ -933,7 +1119,7 @@ ospf_print(register const u_char *bp, register u_int length,
case OSPF_AUTH_SIMPLE:
printf("\n\tSimple text password: ");
- safeputs(op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN);
+ safeputs((const char *)op->ospf_authdata, OSPF_AUTH_SIMPLE_LEN);
break;
case OSPF_AUTH_MD5:
@@ -954,6 +1140,10 @@ ospf_print(register const u_char *bp, register u_int length,
/* ospf version 2 */
if (ospf_decode_v2(op, dataend))
goto trunc;
+ if (length > EXTRACT_16BITS(&op->ospf_len)) {
+ if (ospf_decode_lls(op, length))
+ goto trunc;
+ }
break;
default:
diff --git a/contrib/tcpdump/print-ospf6.c b/contrib/tcpdump/print-ospf6.c
index 6325a21..1100485 100644
--- a/contrib/tcpdump/print-ospf6.c
+++ b/contrib/tcpdump/print-ospf6.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ospf6.c,v 1.13 2003/11/16 09:36:31 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ospf6.c,v 1.15 2006-09-13 06:31:11 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -39,188 +39,120 @@ static const char rcsid[] _U_ =
#include "addrtoname.h"
#include "extract.h"
+#include "ospf.h"
#include "ospf6.h"
-struct bits {
- u_int32_t bit;
- const char *str;
+static const struct tok ospf6_option_values[] = {
+ { OSPF6_OPTION_V6, "V6" },
+ { OSPF6_OPTION_E, "External" },
+ { OSPF6_OPTION_MC, "Multicast" },
+ { OSPF6_OPTION_N, "NSSA" },
+ { OSPF6_OPTION_R, "Router" },
+ { OSPF6_OPTION_DC, "Demand Circuit" },
+ { 0, NULL }
};
-static const struct bits ospf6_option_bits[] = {
- { OSPF6_OPTION_V6, "V6" },
- { OSPF6_OPTION_E, "E" },
- { OSPF6_OPTION_MC, "MC" },
- { OSPF6_OPTION_N, "N" },
- { OSPF6_OPTION_R, "R" },
- { OSPF6_OPTION_DC, "DC" },
+static const struct tok ospf6_rla_flag_values[] = {
+ { RLA_FLAG_B, "ABR" },
+ { RLA_FLAG_E, "External" },
+ { RLA_FLAG_V, "Virtual-Link Endpoint" },
+ { RLA_FLAG_W, "Wildcard Receiver" },
+ { RLA_FLAG_N, "NSSA Translator" },
{ 0, NULL }
};
-static const struct bits ospf6_rla_flag_bits[] = {
- { RLA_FLAG_B, "B" },
- { RLA_FLAG_E, "E" },
- { RLA_FLAG_V, "V" },
- { RLA_FLAG_W, "W" },
+static const struct tok ospf6_asla_flag_values[] = {
+ { ASLA_FLAG_EXTERNAL, "External Type 2" },
+ { ASLA_FLAG_FWDADDR, "Fforwarding" },
+ { ASLA_FLAG_ROUTETAG, "Tag" },
{ 0, NULL }
};
-static const struct bits ospf6_asla_flag_bits[] = {
- { ASLA_FLAG_EXTERNAL, "E" },
- { ASLA_FLAG_FWDADDR, "F" },
- { ASLA_FLAG_ROUTETAG, "T" },
+static struct tok ospf6_type_values[] = {
+ { OSPF_TYPE_HELLO, "Hello" },
+ { OSPF_TYPE_DD, "Database Description" },
+ { OSPF_TYPE_LS_REQ, "LS-Request" },
+ { OSPF_TYPE_LS_UPDATE, "LS-Update" },
+ { OSPF_TYPE_LS_ACK, "LS-Ack" },
{ 0, NULL }
};
-static struct tok type2str[] = {
- { OSPF_TYPE_UMD, "umd" },
- { OSPF_TYPE_HELLO, "hello" },
- { OSPF_TYPE_DB, "dd" },
- { OSPF_TYPE_LSR, "ls_req" },
- { OSPF_TYPE_LSU, "ls_upd" },
- { OSPF_TYPE_LSA, "ls_ack" },
+static struct tok ospf6_lsa_values[] = {
+ { LS_TYPE_ROUTER, "Router" },
+ { LS_TYPE_NETWORK, "Network" },
+ { LS_TYPE_INTER_AP, "Inter-Area Prefix" },
+ { LS_TYPE_INTER_AR, "Inter-Area Router" },
+ { LS_TYPE_ASE, "External" },
+ { LS_TYPE_GROUP, "Multicast Group" },
+ { LS_TYPE_NSSA, "NSSA" },
+ { LS_TYPE_LINK, "Link" },
+ { LS_TYPE_INTRA_AP, "Intra-Area Prefix" },
+ { LS_TYPE_INTRA_ATE, "Intra-Area TE" },
+ { LS_TYPE_GRACE, "Grace" },
{ 0, NULL }
};
-static char tstr[] = " [|ospf]";
+static struct tok ospf6_ls_scope_values[] = {
+ { LS_SCOPE_LINKLOCAL, "Link Local" },
+ { LS_SCOPE_AREA, "Area Local" },
+ { LS_SCOPE_AS, "Domain Wide" },
+ { 0, NULL }
+};
+
+static struct tok ospf6_dd_flag_values[] = {
+ { OSPF6_DB_INIT, "Init" },
+ { OSPF6_DB_MORE, "More" },
+ { OSPF6_DB_MASTER, "Master" },
+ { 0, NULL }
+};
+
+static struct tok ospf6_lsa_prefix_option_values[] = {
+ { LSA_PREFIX_OPT_NU, "No Unicast" },
+ { LSA_PREFIX_OPT_LA, "Local address" },
+ { LSA_PREFIX_OPT_MC, "Multicast" },
+ { LSA_PREFIX_OPT_P, "Propagate" },
+ { LSA_PREFIX_OPT_DN, "Down" },
+ { 0, NULL }
+};
+
+static char tstr[] = " [|ospf3]";
#ifdef WIN32
#define inline __inline
#endif /* WIN32 */
/* Forwards */
-static inline void ospf6_print_seqage(u_int32_t, time_t);
-static inline void ospf6_print_bits(const struct bits *, u_char);
-static void ospf6_print_ls_type(u_int, const rtrid_t *,
- const rtrid_t *, const char *);
-static int ospf6_print_lshdr(const struct lsa_hdr *);
-static int ospf6_print_lsa(const struct lsa *);
+static void ospf6_print_ls_type(u_int, const rtrid_t *);
+static int ospf6_print_lshdr(const struct lsa6_hdr *);
+static int ospf6_print_lsa(const struct lsa6 *);
static int ospf6_decode_v3(const struct ospf6hdr *, const u_char *);
-static inline void
-ospf6_print_seqage(register u_int32_t seq, register time_t us)
-{
- register time_t sec = us % 60;
- register time_t mins = (us / 60) % 60;
- register time_t hour = us / 3600;
-
- printf(" S %X age ", seq);
- if (hour)
- printf("%u:%02u:%02u",
- (u_int32_t) hour, (u_int32_t) mins, (u_int32_t) sec);
- else if (mins)
- printf("%u:%02u", (u_int32_t) mins, (u_int32_t) sec);
- else
- printf("%u", (u_int32_t) sec);
-}
-
-
-static inline void
-ospf6_print_bits(register const struct bits *bp, register u_char options)
-{
- register char sep = ' ';
-
- do {
- if (options & bp->bit) {
- printf("%c%s", sep, bp->str);
- sep = '/';
- }
- } while ((++bp)->bit);
-}
static void
-ospf6_print_ls_type(register u_int ls_type,
- register const rtrid_t *ls_stateid,
- register const rtrid_t *ls_router, register const char *fmt)
+ospf6_print_ls_type(register u_int ls_type, register const rtrid_t *ls_stateid)
{
- const char *scope;
-
- switch (ls_type & LS_SCOPE_MASK) {
- case LS_SCOPE_LINKLOCAL:
- scope = "linklocal-";
- break;
- case LS_SCOPE_AREA:
- scope = "area-";
- break;
- case LS_SCOPE_AS:
- scope = "AS-";
- break;
- default:
- scope = "";
- break;
- }
-
- switch (ls_type & LS_TYPE_MASK) {
- case LS_TYPE_ROUTER:
- printf(" %srtr %s", scope, ipaddr_string(ls_router));
- break;
-
- case LS_TYPE_NETWORK:
- printf(" %snet dr %s if %s", scope,
- ipaddr_string(ls_router),
- ipaddr_string(ls_stateid));
- break;
-
- case LS_TYPE_INTER_AP:
- printf(" %sinter-area-prefix %s abr %s", scope,
- ipaddr_string(ls_stateid),
- ipaddr_string(ls_router));
- break;
-
- case LS_TYPE_INTER_AR:
- printf(" %sinter-area-router %s rtr %s", scope,
- ipaddr_string(ls_router),
- ipaddr_string(ls_stateid));
- break;
-
- case LS_TYPE_ASE:
- printf(" %sase %s asbr %s", scope,
- ipaddr_string(ls_stateid),
- ipaddr_string(ls_router));
- break;
-
- case LS_TYPE_GROUP:
- printf(" %sgroup %s rtr %s", scope,
- ipaddr_string(ls_stateid),
- ipaddr_string(ls_router));
- break;
-
- case LS_TYPE_TYPE7:
- printf(" %stype7 %s rtr %s", scope,
- ipaddr_string(ls_stateid),
- ipaddr_string(ls_router));
- break;
-
- case LS_TYPE_LINK:
- printf(" %slink %s rtr %s", scope,
- ipaddr_string(ls_stateid),
- ipaddr_string(ls_router));
- break;
-
- case LS_TYPE_INTRA_AP:
- printf(" %sintra-area-prefix %s rtr %s", scope,
- ipaddr_string(ls_stateid),
- ipaddr_string(ls_router));
- break;
-
- default:
- printf(" %s", scope);
- printf(fmt, ls_type);
- break;
- }
-
+ printf("\n\t %s LSA (%d), %s Scope%s, LSA-ID %s",
+ tok2str(ospf6_lsa_values, "Unknown", ls_type & LS_TYPE_MASK),
+ ls_type & LS_TYPE_MASK,
+ tok2str(ospf6_ls_scope_values, "Unknown", ls_type & LS_SCOPE_MASK),
+ ls_type &0x8000 ? ", transitive" : "", /* U-bit */
+ ipaddr_string(ls_stateid));
}
static int
-ospf6_print_lshdr(register const struct lsa_hdr *lshp)
+ospf6_print_lshdr(register const struct lsa6_hdr *lshp)
{
TCHECK(lshp->ls_type);
- printf(" {"); /* } (ctags) */
-
TCHECK(lshp->ls_seq);
- ospf6_print_seqage(EXTRACT_32BITS(&lshp->ls_seq), EXTRACT_16BITS(&lshp->ls_age));
- ospf6_print_ls_type(EXTRACT_16BITS(&lshp->ls_type), &lshp->ls_stateid,
- &lshp->ls_router, "ls_type %d");
+
+ printf("\n\t Advertising Router %s, seq 0x%08x, age %us, length %u",
+ ipaddr_string(&lshp->ls_router),
+ EXTRACT_32BITS(&lshp->ls_seq),
+ EXTRACT_16BITS(&lshp->ls_age),
+ EXTRACT_16BITS(&lshp->ls_length)-(u_int)sizeof(struct lsa6_hdr));
+
+ ospf6_print_ls_type(EXTRACT_16BITS(&lshp->ls_type), &lshp->ls_stateid);
return (0);
trunc:
@@ -228,26 +160,28 @@ trunc:
}
static int
-ospf6_print_lsaprefix(register const struct lsa_prefix *lsapp)
+ospf6_print_lsaprefix(register const struct lsa6_prefix *lsapp)
{
- u_int k;
+ u_int wordlen;
struct in6_addr prefix;
TCHECK(*lsapp);
- k = (lsapp->lsa_p_len + 31) / 32;
- if (k * 4 > sizeof(struct in6_addr)) {
- printf("??prefixlen %d??", lsapp->lsa_p_len);
+ wordlen = (lsapp->lsa_p_len + 31) / 32;
+ if (wordlen * 4 > sizeof(struct in6_addr)) {
+ printf(" bogus prefixlen /%d", lsapp->lsa_p_len);
goto trunc;
}
memset(&prefix, 0, sizeof(prefix));
- memcpy(&prefix, lsapp->lsa_p_prefix, k * 4);
- printf(" %s/%d", ip6addr_string(&prefix),
+ memcpy(&prefix, lsapp->lsa_p_prefix, wordlen * 4);
+ printf("\n\t\t%s/%d", ip6addr_string(&prefix),
lsapp->lsa_p_len);
- if (lsapp->lsa_p_opt)
- printf("(opt=%x)", lsapp->lsa_p_opt);
- if (lsapp->lsa_p_mbz)
- printf("(mbz=%x)", EXTRACT_16BITS(&lsapp->lsa_p_mbz)); /* XXX */
- return sizeof(*lsapp) - 4 + k * 4;
+ if (lsapp->lsa_p_opt) {
+ printf(", Options [%s]",
+ bittok2str(ospf6_lsa_prefix_option_values,
+ "none", lsapp->lsa_p_opt));
+ }
+ printf(", metric %u", EXTRACT_16BITS(&lsapp->lsa_p_metric));
+ return sizeof(*lsapp) - 4 + wordlen * 4;
trunc:
return -1;
@@ -258,10 +192,10 @@ trunc:
* Print a single link state advertisement. If truncated return 1, else 0.
*/
static int
-ospf6_print_lsa(register const struct lsa *lsap)
+ospf6_print_lsa(register const struct lsa6 *lsap)
{
register const u_char *ls_end, *ls_opt;
- register const struct rlalink *rlp;
+ register const struct rlalink6 *rlp;
#if 0
register const struct tos_metric *tosp;
#endif
@@ -271,102 +205,115 @@ ospf6_print_lsa(register const struct lsa *lsap)
register const struct mcla *mcp;
#endif
register const struct llsa *llsap;
- register const struct lsa_prefix *lsapp;
+ register const struct lsa6_prefix *lsapp;
#if 0
register const u_int32_t *lp;
#endif
- register u_int j;
- register int k;
+ register u_int prefixes;
+ register int bytelen, length, lsa_length;
u_int32_t flags32;
+ u_int8_t *tptr;
if (ospf6_print_lshdr(&lsap->ls_hdr))
return (1);
TCHECK(lsap->ls_hdr.ls_length);
- ls_end = (u_char *)lsap + EXTRACT_16BITS(&lsap->ls_hdr.ls_length);
+ length = EXTRACT_16BITS(&lsap->ls_hdr.ls_length);
+ lsa_length = length - sizeof(struct lsa6_hdr);
+ ls_end = (u_char *)lsap + length;
+ tptr = (u_int8_t *)lsap+sizeof(struct lsa6_hdr);
+
switch (EXTRACT_16BITS(&lsap->ls_hdr.ls_type)) {
case LS_TYPE_ROUTER | LS_SCOPE_AREA:
- TCHECK(lsap->lsa_un.un_rla.rla_flags);
- ospf6_print_bits(ospf6_rla_flag_bits,
- lsap->lsa_un.un_rla.rla_flags);
TCHECK(lsap->lsa_un.un_rla.rla_options);
- ospf6_print_bits(ospf6_option_bits,
- EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options));
+ printf("\n\t Options [%s]",
+ bittok2str(ospf6_option_values, "none",
+ EXTRACT_32BITS(&lsap->lsa_un.un_rla.rla_options)));
+
+ TCHECK(lsap->lsa_un.un_rla.rla_flags);
+ printf(", RLA-Flags [%s]",
+ bittok2str(ospf6_rla_flag_values, "none",
+ lsap->lsa_un.un_rla.rla_flags));
+
TCHECK(lsap->lsa_un.un_rla.rla_link);
rlp = lsap->lsa_un.un_rla.rla_link;
- while (rlp + sizeof(*rlp) <= (struct rlalink *)ls_end) {
+ while (rlp + 1 <= (struct rlalink6 *)ls_end) {
TCHECK(*rlp);
- printf(" {"); /* } (ctags) */
switch (rlp->link_type) {
case RLA_TYPE_VIRTUAL:
- printf(" virt");
- /* Fall through */
+ printf("\n\t Virtual Link: Neighbor Router-ID %s"
+ "\n\t Neighbor Interface-ID %s, Interface %s",
+ ipaddr_string(&rlp->link_nrtid),
+ ipaddr_string(&rlp->link_nifid),
+ ipaddr_string(&rlp->link_ifid));
+ break;
case RLA_TYPE_ROUTER:
- printf(" nbrid %s nbrif %s if %s",
- ipaddr_string(&rlp->link_nrtid),
- ipaddr_string(&rlp->link_nifid),
- ipaddr_string(&rlp->link_ifid));
+ printf("\n\t Neighbor Router-ID %s"
+ "\n\t Neighbor Interface-ID %s, Interface %s",
+ ipaddr_string(&rlp->link_nrtid),
+ ipaddr_string(&rlp->link_nifid),
+ ipaddr_string(&rlp->link_ifid));
break;
case RLA_TYPE_TRANSIT:
- printf(" dr %s drif %s if %s",
+ printf("\n\t Neighbor Network-ID %s"
+ "\n\t Neighbor Interface-ID %s, Interface %s",
ipaddr_string(&rlp->link_nrtid),
ipaddr_string(&rlp->link_nifid),
ipaddr_string(&rlp->link_ifid));
break;
default:
- /* { (ctags) */
- printf(" ??RouterLinksType 0x%02x?? }",
+ printf("\n\t Unknown Router Links Type 0x%02x",
rlp->link_type);
return (0);
}
- printf(" metric %d", EXTRACT_16BITS(&rlp->link_metric));
- /* { (ctags) */
- printf(" }");
+ printf(", metric %d", EXTRACT_16BITS(&rlp->link_metric));
rlp++;
}
break;
case LS_TYPE_NETWORK | LS_SCOPE_AREA:
TCHECK(lsap->lsa_un.un_nla.nla_options);
- ospf6_print_bits(ospf6_option_bits,
- EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options));
- printf(" rtrs");
+ printf("\n\t Options [%s]",
+ bittok2str(ospf6_option_values, "none",
+ EXTRACT_32BITS(&lsap->lsa_un.un_nla.nla_options)));
+ printf("\n\t Connected Routers:");
ap = lsap->lsa_un.un_nla.nla_router;
while ((u_char *)ap < ls_end) {
TCHECK(*ap);
- printf(" %s", ipaddr_string(ap));
+ printf("\n\t\t%s", ipaddr_string(ap));
++ap;
}
break;
case LS_TYPE_INTER_AP | LS_SCOPE_AREA:
TCHECK(lsap->lsa_un.un_inter_ap.inter_ap_metric);
- printf(" metric %u",
+ printf(", metric %u",
EXTRACT_32BITS(&lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC);
lsapp = lsap->lsa_un.un_inter_ap.inter_ap_prefix;
- while (lsapp + sizeof(lsapp) <= (struct lsa_prefix *)ls_end) {
- k = ospf6_print_lsaprefix(lsapp);
- if (k)
+ while (lsapp + sizeof(lsapp) <= (struct lsa6_prefix *)ls_end) {
+ bytelen = ospf6_print_lsaprefix(lsapp);
+ if (bytelen)
goto trunc;
- lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k);
+ lsapp = (struct lsa6_prefix *)(((u_char *)lsapp) + bytelen);
}
break;
case LS_SCOPE_AS | LS_TYPE_ASE:
TCHECK(lsap->lsa_un.un_asla.asla_metric);
flags32 = EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric);
- ospf6_print_bits(ospf6_asla_flag_bits, flags32);
+ printf("\n\t Flags [%s]",
+ bittok2str(ospf6_asla_flag_values, "none", flags32));
printf(" metric %u",
EXTRACT_32BITS(&lsap->lsa_un.un_asla.asla_metric) &
ASLA_MASK_METRIC);
lsapp = lsap->lsa_un.un_asla.asla_prefix;
- k = ospf6_print_lsaprefix(lsapp);
- if (k < 0)
+ bytelen = ospf6_print_lsaprefix(lsapp);
+ if (bytelen < 0)
goto trunc;
- if ((ls_opt = (u_char *)(((u_char *)lsapp) + k)) < ls_end) {
+ if ((ls_opt = (u_char *)(((u_char *)lsapp) + bytelen)) < ls_end) {
struct in6_addr *fwdaddr6;
if ((flags32 & ASLA_FLAG_FWDADDR) != 0) {
@@ -386,7 +333,7 @@ ospf6_print_lsa(register const struct lsa *lsap)
ls_opt += sizeof(u_int32_t);
}
- if (lsapp->lsa_p_mbz) {
+ if (lsapp->lsa_p_metric) {
TCHECK(*(u_int32_t *)ls_opt);
printf(" RefLSID: %s",
ipaddr_string((u_int32_t *)ls_opt));
@@ -395,64 +342,30 @@ ospf6_print_lsa(register const struct lsa *lsap)
}
}
break;
-#if 0
- case LS_TYPE_SUM_ABR:
- TCHECK(lsap->lsa_un.un_sla.sla_tosmetric);
- lp = lsap->lsa_un.un_sla.sla_tosmetric;
- while ((u_char *)lp < ls_end) {
- register u_int32_t ul;
-
- TCHECK(*lp);
- ul = EXTRACT_32BITS(lp);
- printf(" tos %d metric %d",
- (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS,
- ul & SLA_MASK_METRIC);
- ++lp;
- }
- break;
-
- case LS_TYPE_GROUP:
- /* Multicast extensions as of 23 July 1991 */
- mcp = lsap->lsa_un.un_mcla;
- while ((u_char *)mcp < ls_end) {
- TCHECK(mcp->mcla_vid);
- switch (EXTRACT_32BITS(&mcp->mcla_vtype)) {
-
- case MCLA_VERTEX_ROUTER:
- printf(" rtr rtrid %s",
- ipaddr_string(&mcp->mcla_vid));
- break;
-
- case MCLA_VERTEX_NETWORK:
- printf(" net dr %s",
- ipaddr_string(&mcp->mcla_vid));
- break;
-
- default:
- printf(" ??VertexType %u??",
- EXTRACT_32BITS(&mcp->mcla_vtype));
- break;
- }
- ++mcp;
- }
-#endif
case LS_TYPE_LINK:
/* Link LSA */
llsap = &lsap->lsa_un.un_llsa;
TCHECK(llsap->llsa_options);
- ospf6_print_bits(ospf6_option_bits, EXTRACT_32BITS(&llsap->llsa_options));
+ printf("\n\t Options [%s]",
+ bittok2str(ospf6_option_values, "none",
+ EXTRACT_32BITS(&llsap->llsa_options)));
TCHECK(llsap->llsa_nprefix);
- printf(" pri %d lladdr %s npref %d", llsap->llsa_priority,
- ip6addr_string(&llsap->llsa_lladdr),
- EXTRACT_32BITS(&llsap->llsa_nprefix));
- lsapp = llsap->llsa_prefix;
- for (j = 0; j < EXTRACT_32BITS(&llsap->llsa_nprefix); j++) {
- k = ospf6_print_lsaprefix(lsapp);
- if (k)
- goto trunc;
- lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k);
- }
+ prefixes = EXTRACT_32BITS(&llsap->llsa_nprefix);
+ printf("\n\t Priority %d, Link-local address %s, Prefixes %d:",
+ llsap->llsa_priority,
+ ip6addr_string(&llsap->llsa_lladdr),
+ prefixes);
+
+ tptr = (u_int8_t *)llsap->llsa_prefix;
+ while (prefixes > 0) {
+ lsapp = (struct lsa6_prefix *)tptr;
+ if ((bytelen = ospf6_print_lsaprefix(lsapp)) == -1) {
+ goto trunc;
+ }
+ prefixes--;
+ tptr += bytelen;
+ }
break;
case LS_TYPE_INTRA_AP | LS_SCOPE_AREA:
@@ -460,34 +373,46 @@ ospf6_print_lsa(register const struct lsa *lsap)
TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_rtid);
ospf6_print_ls_type(
EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_lstype),
- &lsap->lsa_un.un_intra_ap.intra_ap_lsid,
- &lsap->lsa_un.un_intra_ap.intra_ap_rtid,
- "LinkStateType %d");
+ &lsap->lsa_un.un_intra_ap.intra_ap_lsid);
TCHECK(lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
- printf(" npref %d",
- EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix));
-
- lsapp = lsap->lsa_un.un_intra_ap.intra_ap_prefix;
- for (j = 0;
- j < EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
- j++) {
- k = ospf6_print_lsaprefix(lsapp);
- if (k)
- goto trunc;
- lsapp = (struct lsa_prefix *)(((u_char *)lsapp) + k);
- }
+ prefixes = EXTRACT_16BITS(&lsap->lsa_un.un_intra_ap.intra_ap_nprefix);
+ printf("\n\t Prefixes %d:", prefixes);
+
+ tptr = (u_int8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix;
+
+ while (prefixes > 0) {
+ lsapp = (struct lsa6_prefix *)tptr;
+ if ((bytelen = ospf6_print_lsaprefix(lsapp)) == -1) {
+ goto trunc;
+ }
+ prefixes--;
+ tptr += bytelen;
+ }
break;
+ case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL:
+ if (ospf_print_grace_lsa(tptr, lsa_length) == -1) {
+ return 1;
+ }
+
+ break;
+
+ case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL:
+ if (ospf_print_te_lsa(tptr, lsa_length) == -1) {
+ return 1;
+ }
+ break;
+
default:
- printf(" ??LinkStateType 0x%04x??",
- EXTRACT_16BITS(&lsap->ls_hdr.ls_type));
+ if(!print_unknown_data(tptr,
+ "\n\t ",
+ lsa_length)) {
+ return (1);
+ }
}
- /* { (ctags) */
- fputs(" }", stdout);
return (0);
trunc:
- fputs(" }", stdout);
return (1);
}
@@ -496,103 +421,80 @@ ospf6_decode_v3(register const struct ospf6hdr *op,
register const u_char *dataend)
{
register const rtrid_t *ap;
- register const struct lsr *lsrp;
- register const struct lsa_hdr *lshp;
- register const struct lsa *lsap;
- register char sep;
+ register const struct lsr6 *lsrp;
+ register const struct lsa6_hdr *lshp;
+ register const struct lsa6 *lsap;
register int i;
switch (op->ospf6_type) {
- case OSPF_TYPE_UMD:
- /*
- * Rob Coltun's special monitoring packets;
- * do nothing
- */
- break;
-
case OSPF_TYPE_HELLO:
- if (vflag) {
- TCHECK(op->ospf6_hello.hello_deadint);
- ospf6_print_bits(ospf6_option_bits,
- EXTRACT_32BITS(&op->ospf6_hello.hello_options));
- printf(" ifid %s pri %d int %d dead %u",
- ipaddr_string(&op->ospf6_hello.hello_ifid),
- op->ospf6_hello.hello_priority,
- EXTRACT_16BITS(&op->ospf6_hello.hello_helloint),
- EXTRACT_16BITS(&op->ospf6_hello.hello_deadint));
- }
+ printf("\n\tOptions [%s]",
+ bittok2str(ospf6_option_values, "none",
+ EXTRACT_32BITS(&op->ospf6_hello.hello_options)));
+
+ TCHECK(op->ospf6_hello.hello_deadint);
+ printf("\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u",
+ EXTRACT_16BITS(&op->ospf6_hello.hello_helloint),
+ EXTRACT_16BITS(&op->ospf6_hello.hello_deadint),
+ ipaddr_string(&op->ospf6_hello.hello_ifid),
+ op->ospf6_hello.hello_priority);
+
TCHECK(op->ospf6_hello.hello_dr);
if (op->ospf6_hello.hello_dr != 0)
- printf(" dr %s",
+ printf("\n\t Designated Router %s",
ipaddr_string(&op->ospf6_hello.hello_dr));
TCHECK(op->ospf6_hello.hello_bdr);
if (op->ospf6_hello.hello_bdr != 0)
- printf(" bdr %s",
+ printf(", Backup Designated Router %s",
ipaddr_string(&op->ospf6_hello.hello_bdr));
if (vflag) {
- printf(" nbrs");
+ printf("\n\t Neighbor List:");
ap = op->ospf6_hello.hello_neighbor;
while ((u_char *)ap < dataend) {
TCHECK(*ap);
- printf(" %s", ipaddr_string(ap));
+ printf("\n\t %s", ipaddr_string(ap));
++ap;
}
}
break; /* HELLO */
- case OSPF_TYPE_DB:
+ case OSPF_TYPE_DD:
TCHECK(op->ospf6_db.db_options);
- ospf6_print_bits(ospf6_option_bits,
- EXTRACT_32BITS(&op->ospf6_db.db_options));
- sep = ' ';
+ printf("\n\tOptions [%s]",
+ bittok2str(ospf6_option_values, "none",
+ EXTRACT_32BITS(&op->ospf6_db.db_options)));
TCHECK(op->ospf6_db.db_flags);
- if (op->ospf6_db.db_flags & OSPF6_DB_INIT) {
- printf("%cI", sep);
- sep = '/';
- }
- if (op->ospf6_db.db_flags & OSPF6_DB_MORE) {
- printf("%cM", sep);
- sep = '/';
- }
- if (op->ospf6_db.db_flags & OSPF6_DB_MASTER) {
- printf("%cMS", sep);
- sep = '/';
- }
- TCHECK(op->ospf6_db.db_seq);
- printf(" mtu %u S %X", EXTRACT_16BITS(&op->ospf6_db.db_mtu),
- EXTRACT_32BITS(&op->ospf6_db.db_seq));
-
- if (vflag) {
- /* Print all the LS adv's */
- lshp = op->ospf6_db.db_lshdr;
+ printf(", DD Flags [%s]",
+ bittok2str(ospf6_dd_flag_values,"none",op->ospf6_db.db_flags));
- while (!ospf6_print_lshdr(lshp)) {
- /* { (ctags) */
- printf(" }");
- ++lshp;
- }
- }
+ TCHECK(op->ospf6_db.db_seq);
+ printf(", MTU %u, DD-Sequence 0x%08x",
+ EXTRACT_16BITS(&op->ospf6_db.db_mtu),
+ EXTRACT_32BITS(&op->ospf6_db.db_seq));
+
+ /* Print all the LS adv's */
+ lshp = op->ospf6_db.db_lshdr;
+ while (!ospf6_print_lshdr(lshp)) {
+ ++lshp;
+ }
break;
- case OSPF_TYPE_LSR:
+ case OSPF_TYPE_LS_REQ:
if (vflag) {
lsrp = op->ospf6_lsr;
while ((u_char *)lsrp < dataend) {
TCHECK(*lsrp);
- printf(" {"); /* } (ctags) */
+ printf("\n\t Advertising Router %s",
+ ipaddr_string(&lsrp->ls_router));
ospf6_print_ls_type(EXTRACT_16BITS(&lsrp->ls_type),
- &lsrp->ls_stateid,
- &lsrp->ls_router,
- "LinkStateType %d");
- /* { (ctags) */
- printf(" }");
+ &lsrp->ls_stateid);
++lsrp;
}
}
break;
- case OSPF_TYPE_LSU:
+ case OSPF_TYPE_LS_UPDATE:
if (vflag) {
lsap = op->ospf6_lsu.lsu_lsa;
TCHECK(op->ospf6_lsu.lsu_count);
@@ -600,27 +502,24 @@ ospf6_decode_v3(register const struct ospf6hdr *op,
while (i--) {
if (ospf6_print_lsa(lsap))
goto trunc;
- lsap = (struct lsa *)((u_char *)lsap +
+ lsap = (struct lsa6 *)((u_char *)lsap +
EXTRACT_16BITS(&lsap->ls_hdr.ls_length));
}
}
break;
- case OSPF_TYPE_LSA:
+ case OSPF_TYPE_LS_ACK:
if (vflag) {
lshp = op->ospf6_lsa.lsa_lshdr;
while (!ospf6_print_lshdr(lshp)) {
- /* { (ctags) */
- printf(" }");
++lshp;
}
}
break;
default:
- printf("v3 type %d", op->ospf6_type);
break;
}
return (0);
@@ -640,10 +539,15 @@ ospf6_print(register const u_char *bp, register u_int length)
/* If the type is valid translate it, or just print the type */
/* value. If it's not valid, say so and return */
TCHECK(op->ospf6_type);
- cp = tok2str(type2str, "type%d", op->ospf6_type);
- printf("OSPFv%d-%s %d:", op->ospf6_version, cp, length);
- if (*cp == 't')
+ cp = tok2str(ospf6_type_values, "unknown LS-type", op->ospf6_type);
+ printf("OSPFv%u, %s, length %d", op->ospf6_version, cp, length);
+ if (*cp == 'u') {
return;
+ }
+
+ if(!vflag) { /* non verbose - so lets bail out here */
+ return;
+ }
TCHECK(op->ospf6_len);
if (length != EXTRACT_16BITS(&op->ospf6_len)) {
@@ -654,16 +558,16 @@ ospf6_print(register const u_char *bp, register u_int length)
/* Print the routerid if it is not the same as the source */
TCHECK(op->ospf6_routerid);
- printf(" rtrid %s", ipaddr_string(&op->ospf6_routerid));
+ printf("\n\tRouter-ID %s", ipaddr_string(&op->ospf6_routerid));
TCHECK(op->ospf6_areaid);
if (op->ospf6_areaid != 0)
- printf(" area %s", ipaddr_string(&op->ospf6_areaid));
+ printf(", Area %s", ipaddr_string(&op->ospf6_areaid));
else
- printf(" backbone");
+ printf(", Backbone Area");
TCHECK(op->ospf6_instanceid);
if (op->ospf6_instanceid)
- printf(" instance %u", op->ospf6_instanceid);
+ printf(", Instance %u", op->ospf6_instanceid);
/* Do rest according to version. */
switch (op->ospf6_version) {
diff --git a/contrib/tcpdump/print-pflog.c b/contrib/tcpdump/print-pflog.c
index dd9ba49..972cb4b 100644
--- a/contrib/tcpdump/print-pflog.c
+++ b/contrib/tcpdump/print-pflog.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-pflog.c,v 1.13.2.4 2007/09/13 17:18:10 gianluca Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-pflog.c,v 1.16 2007-09-12 19:36:18 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -31,17 +31,12 @@ static const char rcsid[] _U_ =
#ifndef HAVE_NET_PFVAR_H
#error "No pf headers available"
#endif
-
#include <sys/types.h>
-#ifndef WIN32
#include <sys/socket.h>
-#endif
#include <net/if.h>
#include <net/pfvar.h>
#include <net/if_pflog.h>
-
-
#include <tcpdump-stdinc.h>
#include <stdio.h>
diff --git a/contrib/tcpdump/print-pgm.c b/contrib/tcpdump/print-pgm.c
index edaf933..73a4291 100644
--- a/contrib/tcpdump/print-pgm.c
+++ b/contrib/tcpdump/print-pgm.c
@@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-pgm.c,v 1.1.2.5 2005/06/07 22:06:16 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-pgm.c,v 1.5 2005-06-07 22:05:58 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-pim.c b/contrib/tcpdump/print-pim.c
index d539809..01080f3 100644
--- a/contrib/tcpdump/print-pim.c
+++ b/contrib/tcpdump/print-pim.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.45.2.4 2006/02/13 01:32:34 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.49 2006-02-13 01:31:35 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-ppp.c b/contrib/tcpdump/print-ppp.c
index e25930b..ba5d836 100644
--- a/contrib/tcpdump/print-ppp.c
+++ b/contrib/tcpdump/print-ppp.c
@@ -33,7 +33,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ppp.c,v 1.108.2.6 2005/12/05 11:40:36 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ppp.c,v 1.114 2005-12-05 11:35:58 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-pppoe.c b/contrib/tcpdump/print-pppoe.c
index 229b5ee..7abc787 100644
--- a/contrib/tcpdump/print-pppoe.c
+++ b/contrib/tcpdump/print-pppoe.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
-"@(#) $Header: /tcpdump/master/tcpdump/print-pppoe.c,v 1.30.2.1 2005/04/26 19:48:56 guy Exp $ (LBL)";
+"@(#) $Header: /tcpdump/master/tcpdump/print-pppoe.c,v 1.31 2005-04-26 19:48:38 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-pptp.c b/contrib/tcpdump/print-pptp.c
index d400589..2fbba62 100644
--- a/contrib/tcpdump/print-pptp.c
+++ b/contrib/tcpdump/print-pptp.c
@@ -24,7 +24,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-pptp.c,v 1.11.2.1 2006/06/23 02:07:27 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-pptp.c,v 1.12 2006-06-23 02:03:09 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-radius.c b/contrib/tcpdump/print-radius.c
index 203c50b..44f0c7f 100644
--- a/contrib/tcpdump/print-radius.c
+++ b/contrib/tcpdump/print-radius.c
@@ -44,7 +44,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "$Id: print-radius.c,v 1.27.2.1 2005/09/26 01:02:40 guy Exp $";
+ "$Id: print-radius.c,v 1.28 2005-09-26 01:01:55 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-raw.c b/contrib/tcpdump/print-raw.c
index 0fe6dd1..8e376ce5 100644
--- a/contrib/tcpdump/print-raw.c
+++ b/contrib/tcpdump/print-raw.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-raw.c,v 1.41 2003/11/16 09:36:34 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-raw.c,v 1.41 2003-11-16 09:36:34 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-rip.c b/contrib/tcpdump/print-rip.c
index 772a2e0..27446a6 100644
--- a/contrib/tcpdump/print-rip.c
+++ b/contrib/tcpdump/print-rip.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-rip.c,v 1.57 2003/11/16 09:36:34 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-rip.c,v 1.59 2006-03-23 14:58:44 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -37,6 +37,8 @@ static const char rcsid[] _U_ =
#include "addrtoname.h"
#include "extract.h" /* must come after interface.h */
+#include "af.h"
+
struct rip {
u_int8_t rip_cmd; /* request/response */
u_int8_t rip_vers; /* protocol version # */
@@ -100,8 +102,8 @@ rip_entry_print_v1(register const struct rip_netinfo *ni)
/* RFC 1058 */
family = EXTRACT_16BITS(&ni->rip_family);
- if (family != AF_INET) {
- printf("\n\t AFI: %u:", family);
+ if (family != BSD_AFNUM_INET) {
+ printf("\n\t AFI %s, ", tok2str(bsd_af_values, "Unknown (%u)", family));
print_unknown_data((u_int8_t *)&ni->rip_family,"\n\t ",RIP_ROUTELEN);
return;
}
@@ -111,7 +113,7 @@ rip_entry_print_v1(register const struct rip_netinfo *ni)
/* MBZ fields not zero */
print_unknown_data((u_int8_t *)&ni->rip_family,"\n\t ",RIP_ROUTELEN);
return;
- } /* AF_INET */
+ } /* BSD_AFNUM_INET */
printf("\n\t %s, metric: %u",
ipaddr_string(&ni->rip_dest),
EXTRACT_32BITS(&ni->rip_metric));
@@ -139,12 +141,13 @@ rip_entry_print_v2(register const struct rip_netinfo *ni)
EXTRACT_16BITS(&ni->rip_tag));
print_unknown_data((u_int8_t *)&ni->rip_dest,"\n\t ",RIP_AUTHLEN);
}
- } else if (family != AF_INET) {
- printf("\n\t AFI: %u", family);
+ } else if (family != BSD_AFNUM_INET) {
+ printf("\n\t AFI %s", tok2str(bsd_af_values, "Unknown (%u)", family));
print_unknown_data((u_int8_t *)&ni->rip_tag,"\n\t ",RIP_ROUTELEN-2);
return;
- } else { /* AF_INET */
- printf("\n\t AFI: IPv4: %15s/%-2d, tag 0x%04x, metric: %u, next-hop: ",
+ } else { /* BSD_AFNUM_INET */
+ printf("\n\t AFI %s, %15s/%-2d, tag 0x%04x, metric: %u, next-hop: ",
+ tok2str(bsd_af_values, "Unknown (%u)", family),
ipaddr_string(&ni->rip_dest),
mask2plen(EXTRACT_32BITS(&ni->rip_dest_mask)),
EXTRACT_16BITS(&ni->rip_tag),
diff --git a/contrib/tcpdump/print-ripng.c b/contrib/tcpdump/print-ripng.c
index 5e7a02e..cef39da 100644
--- a/contrib/tcpdump/print-ripng.c
+++ b/contrib/tcpdump/print-ripng.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-ripng.c,v 1.18 2005/01/04 00:15:54 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-ripng.c,v 1.18 2005-01-04 00:15:54 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-rrcp.c b/contrib/tcpdump/print-rrcp.c
new file mode 100644
index 0000000..dc30457
--- /dev/null
+++ b/contrib/tcpdump/print-rrcp.c
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2007 - Andrey "nording" Chernyak <andrew@nording.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Format and print Realtek Remote Control Protocol (RRCP)
+ * and Realtek Echo Protocol (RRCP-REP) packets.
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/print-rrcp.c,v 1.1.2.2 2008-04-11 17:00:00 gianluca Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "netdissect.h"
+#include "addrtoname.h"
+#include "extract.h"
+#include "ether.h"
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+struct rrcp_packet_t
+{
+ u_int16_t rrcp_ethertype; /* 0x8899 */
+ u_int8_t rrcp_proto; /* must be 0x01 */
+ u_int8_t rrcp_opcode:7; /* 0x00 = hello, 0x01 = get, 0x02 = set */
+ u_int8_t rrcp_isreply:1; /* 0 = request to switch, 1 = reply from switch */
+ u_int16_t rrcp_authkey; /* 0x2379 by default */
+ u_int16_t rrcp_reg_addr; /* register address */
+ u_int32_t rrcp_reg_data; /* register data */
+ u_int32_t cookie1;
+ u_int32_t cookie2;
+};
+
+struct rrcp_helloreply_packet_t
+{
+ u_int16_t rrcp_ethertype; /* 0x8899 */
+ u_int8_t rrcp_proto; /* must be 0x01 */
+ u_int8_t rrcp_opcode:7; /* 0x00 = hello, 0x01 = get, 0x02 = set */
+ u_int8_t rrcp_isreply:1; /* 0 = request to switch, 1 = reply from switch */
+ u_int16_t rrcp_authkey; /* 0x2379 by default */
+ u_int8_t rrcp_downlink_port; /* */
+ u_int8_t rrcp_uplink_port; /* */
+ u_int8_t rrcp_uplink_mac[ETH_ALEN]; /* */
+ u_int16_t rrcp_chip_id; /* */
+ u_int32_t rrcp_vendor_id; /* */
+};
+
+
+/*
+ * Print RRCP requests
+ */
+void
+rrcp_print(netdissect_options *ndo,
+ register const u_char *cp,
+ u_int length _U_)
+{
+ const struct rrcp_packet_t *rrcp;
+ const struct rrcp_helloreply_packet_t *rrcp_hello;
+ register const struct ether_header *ep;
+ char proto_str[16];
+ char opcode_str[32];
+
+ ep = (const struct ether_header *)cp;
+ rrcp = (const struct rrcp_packet_t *)(cp+12);
+ rrcp_hello = (const struct rrcp_helloreply_packet_t *)(cp+12);
+
+ if (rrcp->rrcp_proto==1){
+ strcpy(proto_str,"RRCP");
+ }else if ( rrcp->rrcp_proto==2 ){
+ strcpy(proto_str,"RRCP-REP");
+ }else{
+ sprintf(proto_str,"RRCP-0x%02d",rrcp->rrcp_proto);
+ }
+ if (rrcp->rrcp_opcode==0){
+ strcpy(opcode_str,"hello");
+ }else if ( rrcp->rrcp_opcode==1 ){
+ strcpy(opcode_str,"get");
+ }else if ( rrcp->rrcp_opcode==2 ){
+ strcpy(opcode_str,"set");
+ }else{
+ sprintf(opcode_str,"unknown opcode (0x%02d)",rrcp->rrcp_opcode);
+ }
+ ND_PRINT((ndo, "%s > %s, %s %s",
+ etheraddr_string(ESRC(ep)),
+ etheraddr_string(EDST(ep)),
+ proto_str, rrcp->rrcp_isreply ? "reply" : "query"));
+ if (rrcp->rrcp_proto==1){
+ ND_PRINT((ndo, ": %s", opcode_str));
+ }
+ if (rrcp->rrcp_opcode==1 || rrcp->rrcp_opcode==2){
+ ND_PRINT((ndo, " addr=0x%04x, data=0x%04x",
+ rrcp->rrcp_reg_addr, rrcp->rrcp_reg_data, rrcp->rrcp_authkey));
+ }
+ if (rrcp->rrcp_proto==1){
+ ND_PRINT((ndo, ", auth=0x%04x",
+ ntohs(rrcp->rrcp_authkey)));
+ }
+ if (rrcp->rrcp_proto==1 && rrcp->rrcp_opcode==0 && rrcp->rrcp_isreply){
+ ND_PRINT((ndo, " downlink_port=%d, uplink_port=%d, uplink_mac=%s, vendor_id=%08x ,chip_id=%04x ",
+ rrcp_hello->rrcp_downlink_port,
+ rrcp_hello->rrcp_uplink_port,
+ etheraddr_string(rrcp_hello->rrcp_uplink_mac),
+ rrcp_hello->rrcp_vendor_id,
+ rrcp_hello->rrcp_chip_id));
+ }else if (rrcp->rrcp_opcode==1 || rrcp->rrcp_opcode==2 || rrcp->rrcp_proto==2){
+ ND_PRINT((ndo, ", cookie=0x%08x%08x ",
+ rrcp->cookie2, rrcp->cookie1));
+ }
+ if (!ndo->ndo_vflag)
+ return;
+}
diff --git a/contrib/tcpdump/print-rsvp.c b/contrib/tcpdump/print-rsvp.c
index ad51930..5ed731c 100644
--- a/contrib/tcpdump/print-rsvp.c
+++ b/contrib/tcpdump/print-rsvp.c
@@ -17,7 +17,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-rsvp.c,v 1.33.2.15 2007/09/13 17:33:54 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-rsvp.c,v 1.48 2007-09-13 17:29:50 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-rt6.c b/contrib/tcpdump/print-rt6.c
index 39e22ae..dc196b4 100644
--- a/contrib/tcpdump/print-rt6.c
+++ b/contrib/tcpdump/print-rt6.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-rt6.c,v 1.26.2.1 2005/04/20 22:35:11 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-rt6.c,v 1.27 2005-04-20 22:34:57 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-rx.c b/contrib/tcpdump/print-rx.c
index d991066..3812a12 100644
--- a/contrib/tcpdump/print-rx.c
+++ b/contrib/tcpdump/print-rx.c
@@ -34,7 +34,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.37.2.2 2007/06/15 19:43:15 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-rx.c,v 1.39.2.3 2008-07-01 07:45:09 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -118,6 +118,12 @@ static struct tok fs_req[] = {
{ 162, "dfs-flushcps" },
{ 163, "dfs-symlink" },
{ 220, "residency" },
+ { 65536, "inline-bulk-status" },
+ { 65537, "fetch-data-64" },
+ { 65538, "store-data-64" },
+ { 65539, "give-up-all-cbs" },
+ { 65540, "get-caps" },
+ { 65541, "cb-rx-conn-addr" },
{ 0, NULL },
};
@@ -137,6 +143,9 @@ static struct tok cb_req[] = {
{ 216, "getcellservdb" },
{ 217, "getlocalcell" },
{ 218, "getcacheconf" },
+ { 65536, "getce64" },
+ { 65537, "getcellbynum" },
+ { 65538, "tellmeaboutyourself" },
{ 0, NULL },
};
@@ -163,6 +172,7 @@ static struct tok pt_req[] = {
{ 519, "get-host-cps" },
{ 520, "update-entry" },
{ 521, "list-entries" },
+ { 530, "list-super-groups" },
{ 0, NULL },
};
@@ -256,6 +266,9 @@ static struct tok vol_req[] = {
{ 126, "set-info" },
{ 127, "x-list-partitions" },
{ 128, "forward-multiple" },
+ { 65536, "convert-ro" },
+ { 65537, "get-size" },
+ { 65538, "dump-v2" },
{ 0, NULL },
};
@@ -307,6 +320,8 @@ static struct tok ubik_req[] = {
{ 10003, "vote-getsyncsite" },
{ 10004, "vote-debug" },
{ 10005, "vote-sdebug" },
+ { 10006, "vote-xdebug" },
+ { 10007, "vote-xsdebug" },
{ 20000, "disk-begin" },
{ 20001, "disk-commit" },
{ 20002, "disk-lock" },
@@ -325,7 +340,7 @@ static struct tok ubik_req[] = {
};
#define VOTE_LOW 10000
-#define VOTE_HIGH 10005
+#define VOTE_HIGH 10007
#define DISK_LOW 20000
#define DISK_HIGH 20013
@@ -688,6 +703,13 @@ rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport,
printf(" %lu", i); \
}
+#define UINT64OUT() { u_int64_t i; \
+ TCHECK2(bp[0], sizeof(u_int64_t)); \
+ i = EXTRACT_64BITS(bp); \
+ bp += sizeof(u_int64_t); \
+ printf(" %" PRIu64, i); \
+ }
+
#define DATEOUT() { time_t t; struct tm *tm; char str[256]; \
TCHECK2(bp[0], sizeof(int32_t)); \
t = (time_t) EXTRACT_32BITS(bp); \
@@ -763,6 +785,17 @@ rx_cache_find(const struct rx_header *rxh, const struct ip *ip, int sport,
printf("\""); \
}
+#define DESTSERVEROUT() { unsigned long n1, n2, n3; \
+ TCHECK2(bp[0], sizeof(int32_t) * 3); \
+ n1 = EXTRACT_32BITS(bp); \
+ bp += sizeof(int32_t); \
+ n2 = EXTRACT_32BITS(bp); \
+ bp += sizeof(int32_t); \
+ n3 = EXTRACT_32BITS(bp); \
+ bp += sizeof(int32_t); \
+ printf(" server %d:%d:%d", (int) n1, (int) n2, (int) n3); \
+ }
+
/*
* Handle calls to the AFS file service (fs)
*/
@@ -890,6 +923,7 @@ fs_print(register const u_char *bp, int length)
STROUT(AFSNAMEMAX);
break;
case 155: /* Bulk stat */
+ case 65536: /* Inline bulk stat */
{
unsigned long j;
TCHECK2(bp[0], 4);
@@ -904,6 +938,26 @@ fs_print(register const u_char *bp, int length)
if (j == 0)
printf(" <none!>");
}
+ case 65537: /* Fetch data 64 */
+ FIDOUT();
+ printf(" offset");
+ UINT64OUT();
+ printf(" length");
+ UINT64OUT();
+ break;
+ case 65538: /* Store data 64 */
+ FIDOUT();
+ STOREATTROUT();
+ printf(" offset");
+ UINT64OUT();
+ printf(" length");
+ UINT64OUT();
+ printf(" flen");
+ UINT64OUT();
+ break;
+ case 65541: /* CallBack rx conn address */
+ printf(" addr");
+ UINTOUT();
default:
;
}
@@ -1267,6 +1321,7 @@ prot_print(register const u_char *bp, int length)
case 517: /* List owned */
case 518: /* Get CPS2 */
case 519: /* Get host CPS */
+ case 530: /* List super groups */
printf(" id");
INTOUT();
break;
@@ -1915,13 +1970,176 @@ vol_print(register const u_char *bp, int length)
printf(" vol call %s", tok2str(vol_req, "op#%d", vol_op));
- /*
- * Normally there would be a switch statement here to decode the
- * arguments to the AFS call, but since I don't have access to
- * an AFS server (yet) and I'm not an AFS admin, I can't
- * test any of these calls. Leave this blank for now.
- */
+ bp += sizeof(struct rx_header) + 4;
+ switch (vol_op) {
+ case 100: /* Create volume */
+ printf(" partition");
+ UINTOUT();
+ printf(" name");
+ STROUT(AFSNAMEMAX);
+ printf(" type");
+ UINTOUT();
+ printf(" parent");
+ UINTOUT();
+ break;
+ case 101: /* Delete volume */
+ case 107: /* Get flags */
+ printf(" trans");
+ UINTOUT();
+ break;
+ case 102: /* Restore */
+ printf(" totrans");
+ UINTOUT();
+ printf(" flags");
+ UINTOUT();
+ break;
+ case 103: /* Forward */
+ printf(" fromtrans");
+ UINTOUT();
+ printf(" fromdate");
+ DATEOUT();
+ DESTSERVEROUT();
+ printf(" desttrans");
+ INTOUT();
+ break;
+ case 104: /* End trans */
+ printf(" trans");
+ UINTOUT();
+ break;
+ case 105: /* Clone */
+ printf(" trans");
+ UINTOUT();
+ printf(" purgevol");
+ UINTOUT();
+ printf(" newtype");
+ UINTOUT();
+ printf(" newname");
+ STROUT(AFSNAMEMAX);
+ break;
+ case 106: /* Set flags */
+ printf(" trans");
+ UINTOUT();
+ printf(" flags");
+ UINTOUT();
+ break;
+ case 108: /* Trans create */
+ printf(" vol");
+ UINTOUT();
+ printf(" partition");
+ UINTOUT();
+ printf(" flags");
+ UINTOUT();
+ break;
+ case 109: /* Dump */
+ case 655537: /* Get size */
+ printf(" fromtrans");
+ UINTOUT();
+ printf(" fromdate");
+ DATEOUT();
+ break;
+ case 110: /* Get n-th volume */
+ printf(" index");
+ UINTOUT();
+ break;
+ case 111: /* Set forwarding */
+ printf(" tid");
+ UINTOUT();
+ printf(" newsite");
+ UINTOUT();
+ break;
+ case 112: /* Get name */
+ case 113: /* Get status */
+ printf(" tid");
+ break;
+ case 114: /* Signal restore */
+ printf(" name");
+ STROUT(AFSNAMEMAX);
+ printf(" type");
+ UINTOUT();
+ printf(" pid");
+ UINTOUT();
+ printf(" cloneid");
+ UINTOUT();
+ break;
+ case 116: /* List volumes */
+ printf(" partition");
+ UINTOUT();
+ printf(" flags");
+ UINTOUT();
+ break;
+ case 117: /* Set id types */
+ printf(" tid");
+ UINTOUT();
+ printf(" name");
+ STROUT(AFSNAMEMAX);
+ printf(" type");
+ UINTOUT();
+ printf(" pid");
+ UINTOUT();
+ printf(" clone");
+ UINTOUT();
+ printf(" backup");
+ UINTOUT();
+ break;
+ case 119: /* Partition info */
+ printf(" name");
+ STROUT(AFSNAMEMAX);
+ break;
+ case 120: /* Reclone */
+ printf(" tid");
+ UINTOUT();
+ break;
+ case 121: /* List one volume */
+ case 122: /* Nuke volume */
+ case 124: /* Extended List volumes */
+ case 125: /* Extended List one volume */
+ case 65536: /* Convert RO to RW volume */
+ printf(" partid");
+ UINTOUT();
+ printf(" volid");
+ UINTOUT();
+ break;
+ case 123: /* Set date */
+ printf(" tid");
+ UINTOUT();
+ printf(" date");
+ DATEOUT();
+ break;
+ case 126: /* Set info */
+ printf(" tid");
+ UINTOUT();
+ break;
+ case 128: /* Forward multiple */
+ printf(" fromtrans");
+ UINTOUT();
+ printf(" fromdate");
+ DATEOUT();
+ {
+ unsigned long i, j;
+ TCHECK2(bp[0], 4);
+ j = EXTRACT_32BITS(bp);
+ bp += sizeof(int32_t);
+ for (i = 0; i < j; i++) {
+ DESTSERVEROUT();
+ if (i != j - 1)
+ printf(",");
+ }
+ if (j == 0)
+ printf(" <none!>");
+ }
+ break;
+ case 65538: /* Dump version 2 */
+ printf(" fromtrans");
+ UINTOUT();
+ printf(" fromdate");
+ DATEOUT();
+ printf(" flags");
+ UINTOUT();
+ break;
+ default:
+ ;
+ }
return;
trunc:
@@ -1955,10 +2173,100 @@ vol_reply_print(register const u_char *bp, int length, int32_t opcode)
* If it was a data packet, interpret the response.
*/
- if (rxh->type == RX_PACKET_TYPE_DATA)
- /* Well, no, not really. Leave this for later */
- ;
- else {
+ if (rxh->type == RX_PACKET_TYPE_DATA) {
+ switch (opcode) {
+ case 100: /* Create volume */
+ printf(" volid");
+ UINTOUT();
+ printf(" trans");
+ UINTOUT();
+ break;
+ case 104: /* End transaction */
+ UINTOUT();
+ break;
+ case 105: /* Clone */
+ printf(" newvol");
+ UINTOUT();
+ break;
+ case 107: /* Get flags */
+ UINTOUT();
+ break;
+ case 108: /* Transaction create */
+ printf(" trans");
+ UINTOUT();
+ break;
+ case 110: /* Get n-th volume */
+ printf(" volume");
+ UINTOUT();
+ printf(" partition");
+ UINTOUT();
+ break;
+ case 112: /* Get name */
+ STROUT(AFSNAMEMAX);
+ break;
+ case 113: /* Get status */
+ printf(" volid");
+ UINTOUT();
+ printf(" nextuniq");
+ UINTOUT();
+ printf(" type");
+ UINTOUT();
+ printf(" parentid");
+ UINTOUT();
+ printf(" clone");
+ UINTOUT();
+ printf(" backup");
+ UINTOUT();
+ printf(" restore");
+ UINTOUT();
+ printf(" maxquota");
+ UINTOUT();
+ printf(" minquota");
+ UINTOUT();
+ printf(" owner");
+ UINTOUT();
+ printf(" create");
+ DATEOUT();
+ printf(" access");
+ DATEOUT();
+ printf(" update");
+ DATEOUT();
+ printf(" expire");
+ DATEOUT();
+ printf(" backup");
+ DATEOUT();
+ printf(" copy");
+ DATEOUT();
+ break;
+ case 115: /* Old list partitions */
+ break;
+ case 116: /* List volumes */
+ case 121: /* List one volume */
+ {
+ unsigned long i, j;
+ TCHECK2(bp[0], 4);
+ j = EXTRACT_32BITS(bp);
+ bp += sizeof(int32_t);
+ for (i = 0; i < j; i++) {
+ printf(" name");
+ VECOUT(32);
+ printf(" volid");
+ UINTOUT();
+ printf(" type");
+ bp += sizeof(int32_t) * 21;
+ if (i != j - 1)
+ printf(",");
+ }
+ if (j == 0)
+ printf(" <none!>");
+ }
+ break;
+
+
+ default:
+ ;
+ }
+ } else {
/*
* Otherwise, just print out the return code
*/
diff --git a/contrib/tcpdump/print-sctp.c b/contrib/tcpdump/print-sctp.c
index 7a18978..05c753a 100644
--- a/contrib/tcpdump/print-sctp.c
+++ b/contrib/tcpdump/print-sctp.c
@@ -35,7 +35,7 @@
#ifndef lint
static const char rcsid[] _U_ =
-"@(#) $Header: /tcpdump/master/tcpdump/print-sctp.c,v 1.16.2.5 2007/09/13 18:04:58 guy Exp $ (NETLAB/PEL)";
+"@(#) $Header: /tcpdump/master/tcpdump/print-sctp.c,v 1.21 2007-09-13 18:03:49 guy Exp $ (NETLAB/PEL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-sflow.c b/contrib/tcpdump/print-sflow.c
new file mode 100644
index 0000000..baa5530
--- /dev/null
+++ b/contrib/tcpdump/print-sflow.c
@@ -0,0 +1,577 @@
+/*
+ * Copyright (c) 1998-2007 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * The SFLOW protocol as per http://www.sflow.org/developers/specifications.php
+ *
+ * Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+"@(#) $Header: /tcpdump/master/tcpdump/print-sflow.c,v 1.1 2007-08-08 17:20:58 hannes Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interface.h"
+#include "extract.h"
+#include "addrtoname.h"
+
+/*
+ * sFlow datagram
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Sflow version (2,4,5) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | IP version (1 for IPv4 | 2 for IPv6) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | IP Address AGENT (4 or 16 bytes) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Sub agent ID |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Datagram sequence number |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Switch uptime in ms |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | num samples in datagram |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+struct sflow_datagram_t {
+ u_int8_t version[4];
+ u_int8_t ip_version[4];
+ u_int8_t agent[4];
+ u_int8_t agent_id[4];
+ u_int8_t seqnum[4];
+ u_int8_t uptime[4];
+ u_int8_t samples[4];
+};
+
+struct sflow_sample_header {
+ u_int8_t format[4];
+ u_int8_t len[4];
+};
+
+#define SFLOW_FLOW_SAMPLE 1
+#define SFLOW_COUNTER_SAMPLE 2
+#define SFLOW_EXPANDED_FLOW_SAMPLE 3
+#define SFLOW_EXPANDED_COUNTER_SAMPLE 4
+
+static const struct tok sflow_format_values[] = {
+ { SFLOW_FLOW_SAMPLE, "flow sample" },
+ { SFLOW_COUNTER_SAMPLE, "counter sample" },
+ { SFLOW_EXPANDED_FLOW_SAMPLE, "expanded flow sample" },
+ { SFLOW_EXPANDED_COUNTER_SAMPLE, "expanded counter sample" },
+ { 0, NULL}
+};
+
+struct sflow_expanded_flow_sample_t {
+ u_int8_t seqnum[4];
+ u_int8_t type[4];
+ u_int8_t index[4];
+ u_int8_t rate[4];
+ u_int8_t pool[4];
+ u_int8_t drops[4];
+ u_int8_t in_interface_format[4];
+ u_int8_t in_interface_value[4];
+ u_int8_t out_interface_format[4];
+ u_int8_t out_interface_value[4];
+ u_int8_t records[4];
+};
+
+#define SFLOW_FLOW_RAW_PACKET 1
+#define SFLOW_FLOW_ETHERNET_FRAME 2
+#define SFLOW_FLOW_IPV4_DATA 3
+#define SFLOW_FLOW_IPV6_DATA 4
+#define SFLOW_FLOW_EXTENDED_SWITCH_DATA 1001
+#define SFLOW_FLOW_EXTENDED_ROUTER_DATA 1002
+#define SFLOW_FLOW_EXTENDED_GATEWAY_DATA 1003
+#define SFLOW_FLOW_EXTENDED_USER_DATA 1004
+#define SFLOW_FLOW_EXTENDED_URL_DATA 1005
+#define SFLOW_FLOW_EXTENDED_MPLS_DATA 1006
+#define SFLOW_FLOW_EXTENDED_NAT_DATA 1007
+#define SFLOW_FLOW_EXTENDED_MPLS_TUNNEL 1008
+#define SFLOW_FLOW_EXTENDED_MPLS_VC 1009
+#define SFLOW_FLOW_EXTENDED_MPLS_FEC 1010
+#define SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC 1011
+#define SFLOW_FLOW_EXTENDED_VLAN_TUNNEL 1012
+
+static const struct tok sflow_flow_type_values[] = {
+ { SFLOW_FLOW_RAW_PACKET, "Raw packet"},
+ { SFLOW_FLOW_ETHERNET_FRAME, "Ethernet frame"},
+ { SFLOW_FLOW_IPV4_DATA, "IPv4 Data"},
+ { SFLOW_FLOW_IPV6_DATA, "IPv6 Data"},
+ { SFLOW_FLOW_EXTENDED_SWITCH_DATA, "Extended Switch data"},
+ { SFLOW_FLOW_EXTENDED_ROUTER_DATA, "Extended Router data"},
+ { SFLOW_FLOW_EXTENDED_GATEWAY_DATA, "Extended Gateway data"},
+ { SFLOW_FLOW_EXTENDED_USER_DATA, "Extended User data"},
+ { SFLOW_FLOW_EXTENDED_URL_DATA, "Extended URL data"},
+ { SFLOW_FLOW_EXTENDED_MPLS_DATA, "Extended MPLS data"},
+ { SFLOW_FLOW_EXTENDED_NAT_DATA, "Extended NAT data"},
+ { SFLOW_FLOW_EXTENDED_MPLS_TUNNEL, "Extended MPLS tunnel"},
+ { SFLOW_FLOW_EXTENDED_MPLS_VC, "Extended MPLS VC"},
+ { SFLOW_FLOW_EXTENDED_MPLS_FEC, "Extended MPLS FEC"},
+ { SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC, "Extended MPLS LVP FEC"},
+ { SFLOW_FLOW_EXTENDED_VLAN_TUNNEL, "Extended VLAN Tunnel"},
+ { 0, NULL}
+};
+
+#define SFLOW_HEADER_PROTOCOL_ETHERNET 1
+#define SFLOW_HEADER_PROTOCOL_IPV4 11
+#define SFLOW_HEADER_PROTOCOL_IPV6 12
+
+static const struct tok sflow_flow_raw_protocol_values[] = {
+ { SFLOW_HEADER_PROTOCOL_ETHERNET, "Ethernet"},
+ { SFLOW_HEADER_PROTOCOL_IPV4, "IPv4"},
+ { SFLOW_HEADER_PROTOCOL_IPV6, "IPv6"},
+ { 0, NULL}
+};
+
+struct sflow_expanded_flow_raw_t {
+ u_int8_t protocol[4];
+ u_int8_t length[4];
+ u_int8_t stripped_bytes[4];
+ u_int8_t header_size[4];
+};
+
+struct sflow_expanded_counter_sample_t {
+ u_int8_t seqnum[4];
+ u_int8_t type[4];
+ u_int8_t index[4];
+ u_int8_t records[4];
+};
+
+#define SFLOW_COUNTER_GENERIC 1
+#define SFLOW_COUNTER_ETHERNET 2
+#define SFLOW_COUNTER_TOKEN_RING 3
+#define SFLOW_COUNTER_BASEVG 4
+#define SFLOW_COUNTER_VLAN 5
+#define SFLOW_COUNTER_PROCESSOR 1001
+
+static const struct tok sflow_counter_type_values[] = {
+ { SFLOW_COUNTER_GENERIC, "Generic counter"},
+ { SFLOW_COUNTER_ETHERNET, "Ethernet counter"},
+ { SFLOW_COUNTER_TOKEN_RING, "Token ring counter"},
+ { SFLOW_COUNTER_BASEVG, "100 BaseVG counter"},
+ { SFLOW_COUNTER_VLAN, "Vlan counter"},
+ { SFLOW_COUNTER_PROCESSOR, "Processor counter"},
+ { 0, NULL}
+};
+
+#define SFLOW_IFACE_DIRECTION_UNKNOWN 0
+#define SFLOW_IFACE_DIRECTION_FULLDUPLEX 1
+#define SFLOW_IFACE_DIRECTION_HALFDUPLEX 2
+#define SFLOW_IFACE_DIRECTION_IN 3
+#define SFLOW_IFACE_DIRECTION_OUT 4
+
+static const struct tok sflow_iface_direction_values[] = {
+ { SFLOW_IFACE_DIRECTION_UNKNOWN, "unknown"},
+ { SFLOW_IFACE_DIRECTION_FULLDUPLEX, "full-duplex"},
+ { SFLOW_IFACE_DIRECTION_HALFDUPLEX, "half-duplex"},
+ { SFLOW_IFACE_DIRECTION_IN, "in"},
+ { SFLOW_IFACE_DIRECTION_OUT, "out"},
+ { 0, NULL}
+};
+
+struct sflow_generic_counter_t {
+ u_int8_t ifindex[4];
+ u_int8_t iftype[4];
+ u_int8_t ifspeed[8];
+ u_int8_t ifdirection[4];
+ u_int8_t ifstatus[4];
+ u_int8_t ifinoctets[8];
+ u_int8_t ifinunicastpkts[4];
+ u_int8_t ifinmulticastpkts[4];
+ u_int8_t ifinbroadcastpkts[4];
+ u_int8_t ifindiscards[4];
+ u_int8_t ifinerrors[4];
+ u_int8_t ifinunkownprotos[4];
+ u_int8_t ifoutoctets[8];
+ u_int8_t ifoutunicastpkts[4];
+ u_int8_t ifoutmulticastpkts[4];
+ u_int8_t ifoutbroadcastpkts[4];
+ u_int8_t ifoutdiscards[4];
+ u_int8_t ifouterrors[4];
+ u_int8_t ifpromiscmode[4];
+};
+
+struct sflow_ethernet_counter_t {
+ u_int8_t alignerrors[4];
+ u_int8_t fcserrors[4];
+ u_int8_t single_collision_frames[4];
+ u_int8_t multiple_collision_frames[4];
+ u_int8_t test_errors[4];
+ u_int8_t deferred_transmissions[4];
+ u_int8_t late_collisions[4];
+ u_int8_t excessive_collisions[4];
+ u_int8_t mac_transmit_errors[4];
+ u_int8_t carrier_sense_errors[4];
+ u_int8_t frame_too_longs[4];
+ u_int8_t mac_receive_errors[4];
+ u_int8_t symbol_errors[4];
+};
+
+struct sflow_100basevg_counter_t {
+ u_int8_t in_highpriority_frames[4];
+ u_int8_t in_highpriority_octets[8];
+ u_int8_t in_normpriority_frames[4];
+ u_int8_t in_normpriority_octets[8];
+ u_int8_t in_ipmerrors[4];
+ u_int8_t in_oversized[4];
+ u_int8_t in_data_errors[4];
+ u_int8_t in_null_addressed_frames[4];
+ u_int8_t out_highpriority_frames[4];
+ u_int8_t out_highpriority_octets[8];
+ u_int8_t transitioninto_frames[4];
+ u_int8_t hc_in_highpriority_octets[8];
+ u_int8_t hc_in_normpriority_octets[8];
+ u_int8_t hc_out_highpriority_octets[8];
+};
+
+struct sflow_vlan_counter_t {
+ u_int8_t vlan_id[4];
+ u_int8_t octets[8];
+ u_int8_t unicast_pkt[4];
+ u_int8_t multicast_pkt[4];
+ u_int8_t broadcast_pkt[4];
+ u_int8_t discards[4];
+};
+
+void
+sflow_print(const u_char *pptr, u_int len) {
+
+ const struct sflow_datagram_t *sflow_datagram;
+ const struct sflow_sample_header *sflow_sample;
+ const struct sflow_expanded_flow_sample_t *sflow_expanded_flow_sample;
+ const struct sflow_expanded_flow_raw_t *sflow_flow_raw;
+ const struct sflow_expanded_counter_sample_t *sflow_expanded_counter_sample;
+ const struct sflow_generic_counter_t *sflow_gen_counter;
+ const struct sflow_ethernet_counter_t *sflow_eth_counter;
+ const struct sflow_100basevg_counter_t *sflow_100basevg_counter;
+ const struct sflow_vlan_counter_t *sflow_vlan_counter;
+ const u_char *tptr;
+ int tlen;
+ u_int32_t sflow_sample_type, sflow_sample_len;
+ int nsamples, nrecords, counter_len, counter_type, flow_len, flow_type;
+
+ tptr=pptr;
+ tlen = len;
+ sflow_datagram = (const struct sflow_datagram_t *)pptr;
+ TCHECK(*sflow_datagram);
+
+ /*
+ * Sanity checking of the header.
+ */
+ if (EXTRACT_32BITS(sflow_datagram->version) != 5) {
+ printf("sFlow version %u packet not supported",
+ EXTRACT_32BITS(sflow_datagram->version));
+ return;
+ }
+
+ if (vflag < 1) {
+ printf("sFlowv%u, %s agent %s, agent-id %u, length %u",
+ EXTRACT_32BITS(sflow_datagram->version),
+ EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6",
+ ipaddr_string(sflow_datagram->agent),
+ EXTRACT_32BITS(sflow_datagram->samples),
+ len);
+ return;
+ }
+
+ /* ok they seem to want to know everything - lets fully decode it */
+ nsamples=EXTRACT_32BITS(sflow_datagram->samples);
+ printf("sFlowv%u, %s agent %s, agent-id %u, seqnum %u, uptime %u, samples %u, length %u",
+ EXTRACT_32BITS(sflow_datagram->version),
+ EXTRACT_32BITS(sflow_datagram->ip_version) == 1 ? "IPv4" : "IPv6",
+ ipaddr_string(sflow_datagram->agent),
+ EXTRACT_32BITS(sflow_datagram->agent_id),
+ EXTRACT_32BITS(sflow_datagram->seqnum),
+ EXTRACT_32BITS(sflow_datagram->uptime),
+ nsamples,
+ len);
+
+ /* skip Common header */
+ tptr+=sizeof(const struct sflow_datagram_t);
+ tlen-=sizeof(const struct sflow_datagram_t);
+
+ while (nsamples > 0 && tlen > 0) {
+ sflow_sample = (const struct sflow_sample_header *)tptr;
+ sflow_sample_type = (EXTRACT_32BITS(sflow_sample->format)&0x0FFF);
+ sflow_sample_len = EXTRACT_32BITS(sflow_sample->len);
+
+ tptr+=sizeof(struct sflow_sample_header);
+ tlen-=sizeof(struct sflow_sample_header);
+
+ printf("\n\t%s (%u), length %u,",
+ tok2str(sflow_format_values, "Unknown", sflow_sample_type),
+ sflow_sample_type,
+ sflow_sample_len);
+
+ /* basic sanity check */
+ if (sflow_sample_type == 0 || sflow_sample_len ==0) {
+ return;
+ }
+
+ /* did we capture enough for fully decoding the sample ? */
+ if (!TTEST2(*tptr, sflow_sample_len))
+ goto trunc;
+
+ switch(sflow_sample_type) {
+ case SFLOW_FLOW_SAMPLE: /* XXX */
+ break;
+
+ case SFLOW_COUNTER_SAMPLE: /* XXX */
+ break;
+
+ case SFLOW_EXPANDED_FLOW_SAMPLE:
+ sflow_expanded_flow_sample = (const struct sflow_expanded_flow_sample_t *)tptr;
+ nrecords = EXTRACT_32BITS(sflow_expanded_flow_sample->records);
+
+ printf(" seqnum %u, type %u, idx %u, rate %u, pool %u, drops %u, records %u",
+ EXTRACT_32BITS(sflow_expanded_flow_sample->seqnum),
+ EXTRACT_32BITS(sflow_expanded_flow_sample->type),
+ EXTRACT_32BITS(sflow_expanded_flow_sample->index),
+ EXTRACT_32BITS(sflow_expanded_flow_sample->rate),
+ EXTRACT_32BITS(sflow_expanded_flow_sample->pool),
+ EXTRACT_32BITS(sflow_expanded_flow_sample->drops),
+ EXTRACT_32BITS(sflow_expanded_flow_sample->records));
+
+ tptr+= sizeof(struct sflow_expanded_flow_sample_t);
+ tlen-= sizeof(struct sflow_expanded_flow_sample_t);
+
+ while ( nrecords > 0 && tlen > 0) {
+
+ /* decode Flow record - 2 bytes */
+ flow_type = EXTRACT_32BITS(tptr)&0x0FFF;
+ flow_len = EXTRACT_32BITS(tptr+4);
+ printf("\n\t %s (%u) length %u",
+ tok2str(sflow_flow_type_values,"Unknown",flow_type),
+ flow_type,
+ flow_len);
+
+ tptr += 8;
+ tlen -= 8;
+
+ /* did we capture enough for fully decoding the flow ? */
+ if (!TTEST2(*tptr, flow_len))
+ goto trunc;
+
+ switch(flow_type) {
+ case SFLOW_FLOW_RAW_PACKET:
+ sflow_flow_raw = (const struct sflow_expanded_flow_raw_t *)tptr;
+ printf("\n\t protocol %s (%u), length %u, stripped bytes %u, header_size %u",
+ tok2str(sflow_flow_raw_protocol_values,"Unknown",EXTRACT_32BITS(sflow_flow_raw->protocol)),
+ EXTRACT_32BITS(sflow_flow_raw->protocol),
+ EXTRACT_32BITS(sflow_flow_raw->length),
+ EXTRACT_32BITS(sflow_flow_raw->stripped_bytes),
+ EXTRACT_32BITS(sflow_flow_raw->header_size));
+ break;
+
+ /*
+ * FIXME those are the defined flow types that lack a decoder
+ */
+ case SFLOW_FLOW_ETHERNET_FRAME:
+ case SFLOW_FLOW_IPV4_DATA:
+ case SFLOW_FLOW_IPV6_DATA:
+ case SFLOW_FLOW_EXTENDED_SWITCH_DATA:
+ case SFLOW_FLOW_EXTENDED_ROUTER_DATA:
+ case SFLOW_FLOW_EXTENDED_GATEWAY_DATA:
+ case SFLOW_FLOW_EXTENDED_USER_DATA:
+ case SFLOW_FLOW_EXTENDED_URL_DATA:
+ case SFLOW_FLOW_EXTENDED_MPLS_DATA:
+ case SFLOW_FLOW_EXTENDED_NAT_DATA:
+ case SFLOW_FLOW_EXTENDED_MPLS_TUNNEL:
+ case SFLOW_FLOW_EXTENDED_MPLS_VC:
+ case SFLOW_FLOW_EXTENDED_MPLS_FEC:
+ case SFLOW_FLOW_EXTENDED_MPLS_LVP_FEC:
+ case SFLOW_FLOW_EXTENDED_VLAN_TUNNEL:
+ break;
+ default:
+ if (vflag <= 1)
+ print_unknown_data(tptr, "\n\t ", flow_len);
+ break;
+
+ }
+ tptr += flow_len;
+ tlen -= flow_len;
+ nrecords--;
+ }
+ break;
+
+ case SFLOW_EXPANDED_COUNTER_SAMPLE:
+ sflow_expanded_counter_sample = (const struct sflow_expanded_counter_sample_t *)tptr;
+ nrecords = EXTRACT_32BITS(sflow_expanded_counter_sample->records);
+
+ printf(" seqnum %u, type %u, idx %u, records %u",
+ EXTRACT_32BITS(sflow_expanded_counter_sample->seqnum),
+ EXTRACT_32BITS(sflow_expanded_counter_sample->type),
+ EXTRACT_32BITS(sflow_expanded_counter_sample->index),
+ nrecords);
+
+ tptr+= sizeof(struct sflow_expanded_counter_sample_t);
+ tlen-= sizeof(struct sflow_expanded_counter_sample_t);
+
+ while ( nrecords > 0 && tlen > 0) {
+
+ /* decode counter record - 2 bytes */
+ counter_type = EXTRACT_32BITS(tptr)&0x0FFF;
+ counter_len = EXTRACT_32BITS(tptr+4);
+ printf("\n\t %s (%u) length %u",
+ tok2str(sflow_counter_type_values,"Unknown",counter_type),
+ counter_type,
+ counter_len);
+
+ tptr += 8;
+ tlen -= 8;
+
+ /* did we capture enough for fully decoding the counter ? */
+ if (!TTEST2(*tptr, counter_len))
+ goto trunc;
+
+ switch(counter_type) {
+ case SFLOW_COUNTER_GENERIC:
+ sflow_gen_counter = (const struct sflow_generic_counter_t *)tptr;
+ printf("\n\t ifindex %u, iftype %u, ifspeed %u, ifdirection %u (%s)",
+ EXTRACT_32BITS(sflow_gen_counter->ifindex),
+ EXTRACT_32BITS(sflow_gen_counter->iftype),
+ EXTRACT_32BITS(sflow_gen_counter->ifspeed),
+ EXTRACT_32BITS(sflow_gen_counter->ifdirection),
+ tok2str(sflow_iface_direction_values, "Unknown",
+ EXTRACT_32BITS(sflow_gen_counter->ifdirection)));
+ printf("\n\t ifstatus %u, adminstatus: %s, operstatus: %s",
+ EXTRACT_32BITS(sflow_gen_counter->ifstatus),
+ EXTRACT_32BITS(sflow_gen_counter->ifstatus)&1 ? "up" : "down",
+ (EXTRACT_32BITS(sflow_gen_counter->ifstatus)>>1)&1 ? "up" : "down");
+ printf("\n\t In octets %" PRIu64
+ ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u",
+ EXTRACT_64BITS(sflow_gen_counter->ifinoctets),
+ EXTRACT_32BITS(sflow_gen_counter->ifinunicastpkts),
+ EXTRACT_32BITS(sflow_gen_counter->ifinmulticastpkts),
+ EXTRACT_32BITS(sflow_gen_counter->ifinbroadcastpkts),
+ EXTRACT_32BITS(sflow_gen_counter->ifindiscards));
+ printf("\n\t In errors %u, unknown protos %u",
+ EXTRACT_32BITS(sflow_gen_counter->ifinerrors),
+ EXTRACT_32BITS(sflow_gen_counter->ifinunkownprotos));
+ printf("\n\t Out octets %" PRIu64
+ ", unicast pkts %u, multicast pkts %u, broadcast pkts %u, discards %u",
+ EXTRACT_64BITS(sflow_gen_counter->ifoutoctets),
+ EXTRACT_32BITS(sflow_gen_counter->ifoutunicastpkts),
+ EXTRACT_32BITS(sflow_gen_counter->ifoutmulticastpkts),
+ EXTRACT_32BITS(sflow_gen_counter->ifoutbroadcastpkts),
+ EXTRACT_32BITS(sflow_gen_counter->ifoutdiscards));
+ printf("\n\t Out errors %u, promisc mode %u",
+ EXTRACT_32BITS(sflow_gen_counter->ifouterrors),
+ EXTRACT_32BITS(sflow_gen_counter->ifpromiscmode));
+ break;
+ case SFLOW_COUNTER_ETHERNET:
+ sflow_eth_counter = (const struct sflow_ethernet_counter_t *)tptr;
+ printf("\n\t align errors %u, fcs errors %u, single collision %u, multiple collision %u, test error %u",
+ EXTRACT_32BITS(sflow_eth_counter->alignerrors),
+ EXTRACT_32BITS(sflow_eth_counter->fcserrors),
+ EXTRACT_32BITS(sflow_eth_counter->single_collision_frames),
+ EXTRACT_32BITS(sflow_eth_counter->multiple_collision_frames),
+ EXTRACT_32BITS(sflow_eth_counter->test_errors));
+ printf("\n\t deferred %u, late collision %u, excessive collision %u, mac trans error %u",
+ EXTRACT_32BITS(sflow_eth_counter->deferred_transmissions),
+ EXTRACT_32BITS(sflow_eth_counter->late_collisions),
+ EXTRACT_32BITS(sflow_eth_counter->excessive_collisions),
+ EXTRACT_32BITS(sflow_eth_counter->mac_transmit_errors));
+ printf("\n\t carrier error %u, frames too long %u, mac receive errors %u, symbol errors %u",
+ EXTRACT_32BITS(sflow_eth_counter->carrier_sense_errors),
+ EXTRACT_32BITS(sflow_eth_counter->frame_too_longs),
+ EXTRACT_32BITS(sflow_eth_counter->mac_receive_errors),
+ EXTRACT_32BITS(sflow_eth_counter->symbol_errors));
+ break;
+ case SFLOW_COUNTER_TOKEN_RING: /* XXX */
+ break;
+ case SFLOW_COUNTER_BASEVG:
+ sflow_100basevg_counter = (const struct sflow_100basevg_counter_t *)tptr;
+ printf("\n\t in high prio frames %u, in high prio octets %" PRIu64,
+ EXTRACT_32BITS(sflow_100basevg_counter->in_highpriority_frames),
+ EXTRACT_64BITS(sflow_100basevg_counter->in_highpriority_octets));
+ printf("\n\t in norm prio frames %u, in norm prio octets %" PRIu64,
+ EXTRACT_32BITS(sflow_100basevg_counter->in_normpriority_frames),
+ EXTRACT_64BITS(sflow_100basevg_counter->in_normpriority_octets));
+ printf("\n\t in ipm errors %u, oversized %u, in data errors %u, null addressed frames %u",
+ EXTRACT_32BITS(sflow_100basevg_counter->in_ipmerrors),
+ EXTRACT_32BITS(sflow_100basevg_counter->in_oversized),
+ EXTRACT_32BITS(sflow_100basevg_counter->in_data_errors),
+ EXTRACT_32BITS(sflow_100basevg_counter->in_null_addressed_frames));
+ printf("\n\t out high prio frames %u, out high prio octets %" PRIu64
+ ", trans into frames %u",
+ EXTRACT_32BITS(sflow_100basevg_counter->out_highpriority_frames),
+ EXTRACT_64BITS(sflow_100basevg_counter->out_highpriority_octets),
+ EXTRACT_32BITS(sflow_100basevg_counter->transitioninto_frames));
+ printf("\n\t in hc high prio octets %" PRIu64
+ ", in hc norm prio octets %" PRIu64
+ ", out hc high prio octets %" PRIu64,
+ EXTRACT_64BITS(sflow_100basevg_counter->hc_in_highpriority_octets),
+ EXTRACT_64BITS(sflow_100basevg_counter->hc_in_normpriority_octets),
+ EXTRACT_64BITS(sflow_100basevg_counter->hc_out_highpriority_octets));
+ break;
+ case SFLOW_COUNTER_VLAN:
+ sflow_vlan_counter = (const struct sflow_vlan_counter_t *)tptr;
+ printf("\n\t vlan_id %u, octets %" PRIu64
+ ", unicast_pkt %u, multicast_pkt %u, broadcast_pkt %u, discards %u",
+ EXTRACT_32BITS(sflow_vlan_counter->vlan_id),
+ EXTRACT_64BITS(sflow_vlan_counter->octets),
+ EXTRACT_32BITS(sflow_vlan_counter->unicast_pkt),
+ EXTRACT_32BITS(sflow_vlan_counter->multicast_pkt),
+ EXTRACT_32BITS(sflow_vlan_counter->broadcast_pkt),
+ EXTRACT_32BITS(sflow_vlan_counter->discards));
+ break;
+ case SFLOW_COUNTER_PROCESSOR: /* XXX */
+ break;
+ default:
+ if (vflag <= 1)
+ print_unknown_data(tptr, "\n\t\t", counter_len);
+ break;
+ }
+ tptr += counter_len;
+ tlen -= counter_len;
+ nrecords--;
+ }
+ break;
+ default:
+ if (vflag <= 1)
+ print_unknown_data(tptr, "\n\t ", sflow_sample_len);
+ break;
+ }
+ tptr += sflow_sample_len;
+ tlen -= sflow_sample_len;
+ nsamples--;
+ }
+ return;
+
+ trunc:
+ printf("[|SFLOW]");
+}
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/contrib/tcpdump/print-sip.c b/contrib/tcpdump/print-sip.c
index b4d13b1..48562f8 100644
--- a/contrib/tcpdump/print-sip.c
+++ b/contrib/tcpdump/print-sip.c
@@ -15,7 +15,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-sip.c,v 1.1 2004/07/27 17:04:20 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-sip.c,v 1.1 2004-07-27 17:04:20 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-sl.c b/contrib/tcpdump/print-sl.c
index 97389d8..dd02767 100644
--- a/contrib/tcpdump/print-sl.c
+++ b/contrib/tcpdump/print-sl.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-sl.c,v 1.65 2005/04/06 21:32:42 mcr Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-sl.c,v 1.65 2005-04-06 21:32:42 mcr Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-sll.c b/contrib/tcpdump/print-sll.c
index 1735f65..d96b3de 100644
--- a/contrib/tcpdump/print-sll.c
+++ b/contrib/tcpdump/print-sll.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-sll.c,v 1.16.2.3 2005/11/13 12:13:00 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-sll.c,v 1.19 2005-11-13 12:12:43 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-slow.c b/contrib/tcpdump/print-slow.c
index 9609922..eaf94ed 100644
--- a/contrib/tcpdump/print-slow.c
+++ b/contrib/tcpdump/print-slow.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998-2005 The TCPDUMP project
+ * Copyright (c) 1998-2006 The TCPDUMP project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code
@@ -13,13 +13,14 @@
* FOR A PARTICULAR PURPOSE.
*
* support for the IEEE "slow protocols" LACP, MARKER as per 802.3ad
+ * OAM as per 802.3ah
*
* Original code by Hannes Gredler (hannes@juniper.net)
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-slow.c,v 1.1.2.1 2005/07/10 14:47:56 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-slow.c,v 1.8 2006-10-12 05:44:33 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -36,14 +37,16 @@ static const char rcsid[] _U_ =
#include "extract.h"
#include "addrtoname.h"
#include "ether.h"
+#include "oui.h"
-struct slow_common_header {
+struct slow_common_header_t {
u_int8_t proto_subtype;
u_int8_t version;
};
#define SLOW_PROTO_LACP 1
#define SLOW_PROTO_MARKER 2
+#define SLOW_PROTO_OAM 3
#define LACP_VERSION 1
#define MARKER_VERSION 1
@@ -51,6 +54,137 @@ struct slow_common_header {
static const struct tok slow_proto_values[] = {
{ SLOW_PROTO_LACP, "LACP" },
{ SLOW_PROTO_MARKER, "MARKER" },
+ { SLOW_PROTO_OAM, "OAM" },
+ { 0, NULL}
+};
+
+static const struct tok slow_oam_flag_values[] = {
+ { 0x0001, "Link Fault" },
+ { 0x0002, "Dying Gasp" },
+ { 0x0004, "Critical Event" },
+ { 0x0008, "Local Evaluating" },
+ { 0x0010, "Local Stable" },
+ { 0x0020, "Remote Evaluating" },
+ { 0x0040, "Remote Stable" },
+ { 0, NULL}
+};
+
+#define SLOW_OAM_CODE_INFO 0x00
+#define SLOW_OAM_CODE_EVENT_NOTIF 0x01
+#define SLOW_OAM_CODE_VAR_REQUEST 0x02
+#define SLOW_OAM_CODE_VAR_RESPONSE 0x03
+#define SLOW_OAM_CODE_LOOPBACK_CTRL 0x04
+#define SLOW_OAM_CODE_PRIVATE 0xfe
+
+static const struct tok slow_oam_code_values[] = {
+ { SLOW_OAM_CODE_INFO, "Information" },
+ { SLOW_OAM_CODE_EVENT_NOTIF, "Event Notification" },
+ { SLOW_OAM_CODE_VAR_REQUEST, "Variable Request" },
+ { SLOW_OAM_CODE_VAR_RESPONSE, "Variable Response" },
+ { SLOW_OAM_CODE_LOOPBACK_CTRL, "Loopback Control" },
+ { SLOW_OAM_CODE_PRIVATE, "Vendor Private" },
+ { 0, NULL}
+};
+
+struct slow_oam_info_t {
+ u_int8_t info_type;
+ u_int8_t info_length;
+ u_int8_t oam_version;
+ u_int8_t revision[2];
+ u_int8_t state;
+ u_int8_t oam_config;
+ u_int8_t oam_pdu_config[2];
+ u_int8_t oui[3];
+ u_int8_t vendor_private[4];
+};
+
+#define SLOW_OAM_INFO_TYPE_END_OF_TLV 0x00
+#define SLOW_OAM_INFO_TYPE_LOCAL 0x01
+#define SLOW_OAM_INFO_TYPE_REMOTE 0x02
+#define SLOW_OAM_INFO_TYPE_ORG_SPECIFIC 0xfe
+
+static const struct tok slow_oam_info_type_values[] = {
+ { SLOW_OAM_INFO_TYPE_END_OF_TLV, "End of TLV marker" },
+ { SLOW_OAM_INFO_TYPE_LOCAL, "Local" },
+ { SLOW_OAM_INFO_TYPE_REMOTE, "Remote" },
+ { SLOW_OAM_INFO_TYPE_ORG_SPECIFIC, "Organization specific" },
+ { 0, NULL}
+};
+
+#define OAM_INFO_TYPE_PARSER_MASK 0x3
+static const struct tok slow_oam_info_type_state_parser_values[] = {
+ { 0x00, "forwarding" },
+ { 0x01, "looping back" },
+ { 0x02, "discarding" },
+ { 0x03, "reserved" },
+ { 0, NULL}
+};
+
+#define OAM_INFO_TYPE_MUX_MASK 0x4
+static const struct tok slow_oam_info_type_state_mux_values[] = {
+ { 0x00, "forwarding" },
+ { 0x04, "discarding" },
+ { 0, NULL}
+};
+
+static const struct tok slow_oam_info_type_oam_config_values[] = {
+ { 0x01, "Active" },
+ { 0x02, "Unidirectional" },
+ { 0x04, "Remote-Loopback" },
+ { 0x08, "Link-Events" },
+ { 0x10, "Variable-Retrieval" },
+ { 0, NULL}
+};
+
+/* 11 Bits */
+#define OAM_INFO_TYPE_PDU_SIZE_MASK 0x7ff
+
+#define SLOW_OAM_LINK_EVENT_END_OF_TLV 0x00
+#define SLOW_OAM_LINK_EVENT_ERR_SYM_PER 0x01
+#define SLOW_OAM_LINK_EVENT_ERR_FRM 0x02
+#define SLOW_OAM_LINK_EVENT_ERR_FRM_PER 0x03
+#define SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM 0x04
+#define SLOW_OAM_LINK_EVENT_ORG_SPECIFIC 0xfe
+
+static const struct tok slow_oam_link_event_values[] = {
+ { SLOW_OAM_LINK_EVENT_END_OF_TLV, "End of TLV marker" },
+ { SLOW_OAM_LINK_EVENT_ERR_SYM_PER, "Errored Symbol Period Event" },
+ { SLOW_OAM_LINK_EVENT_ERR_FRM, "Errored Frame Event" },
+ { SLOW_OAM_LINK_EVENT_ERR_FRM_PER, "Errored Frame Period Event" },
+ { SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM, "Errored Frame Seconds Summary Event" },
+ { SLOW_OAM_LINK_EVENT_ORG_SPECIFIC, "Organization specific" },
+ { 0, NULL}
+};
+
+struct slow_oam_link_event_t {
+ u_int8_t event_type;
+ u_int8_t event_length;
+ u_int8_t time_stamp[2];
+ u_int8_t window[8];
+ u_int8_t threshold[8];
+ u_int8_t errors[8];
+ u_int8_t errors_running_total[8];
+ u_int8_t event_running_total[4];
+};
+
+struct slow_oam_variablerequest_t {
+ u_int8_t branch;
+ u_int8_t leaf[2];
+};
+
+struct slow_oam_variableresponse_t {
+ u_int8_t branch;
+ u_int8_t leaf[2];
+ u_int8_t length;
+};
+
+struct slow_oam_loopbackctrl_t {
+ u_int8_t command;
+};
+
+static const struct tok slow_oam_loopbackctrl_cmd_values[] = {
+ { 0x01, "Enable OAM Remote Loopback" },
+ { 0x02, "Disable OAM Remote Loopback" },
{ 0, NULL}
};
@@ -116,58 +250,113 @@ struct lacp_marker_tlv_terminator_t {
u_int8_t pad[50];
};
+void slow_marker_lacp_print(register const u_char *, register u_int);
+void slow_oam_print(register const u_char *, register u_int);
+
+const struct slow_common_header_t *slow_com_header;
+
void
slow_print(register const u_char *pptr, register u_int len) {
- const struct slow_common_header *slow_com_header;
- const struct tlv_header_t *tlv_header;
- const u_char *tptr,*tlv_tptr;
- u_int tlv_len,tlen,tlv_tlen;
-
- union {
- const struct lacp_marker_tlv_terminator_t *lacp_marker_tlv_terminator;
- const struct lacp_tlv_actor_partner_info_t *lacp_tlv_actor_partner_info;
- const struct lacp_tlv_collector_info_t *lacp_tlv_collector_info;
- const struct marker_tlv_marker_info_t *marker_tlv_marker_info;
- } tlv_ptr;
+ int print_version;
- tptr=pptr;
- slow_com_header = (const struct slow_common_header *)pptr;
+ slow_com_header = (const struct slow_common_header_t *)pptr;
TCHECK(*slow_com_header);
/*
* Sanity checking of the header.
*/
- if (slow_com_header->proto_subtype == SLOW_PROTO_LACP &&
- slow_com_header->version != LACP_VERSION) {
- printf("LACP version %u packet not supported",slow_com_header->version);
- return;
+ switch (slow_com_header->proto_subtype) {
+ case SLOW_PROTO_LACP:
+ if (slow_com_header->version != LACP_VERSION) {
+ printf("LACP version %u packet not supported",slow_com_header->version);
+ return;
+ }
+ print_version = 1;
+ break;
+
+ case SLOW_PROTO_MARKER:
+ if (slow_com_header->version != MARKER_VERSION) {
+ printf("MARKER version %u packet not supported",slow_com_header->version);
+ return;
+ }
+ print_version = 1;
+ break;
+
+ case SLOW_PROTO_OAM: /* fall through */
+ print_version = 0;
+ break;
+
+ default:
+ /* print basic information and exit */
+ print_version = -1;
+ break;
}
- if (slow_com_header->proto_subtype == SLOW_PROTO_MARKER &&
- slow_com_header->version != MARKER_VERSION) {
- printf("MARKER version %u packet not supported",slow_com_header->version);
- return;
+
+ if (print_version) {
+ printf("%sv%u, length %u",
+ tok2str(slow_proto_values, "unknown (%u)",slow_com_header->proto_subtype),
+ slow_com_header->version,
+ len);
+ } else {
+ /* some slow protos don't have a version number in the header */
+ printf("%s, length %u",
+ tok2str(slow_proto_values, "unknown (%u)",slow_com_header->proto_subtype),
+ len);
}
- printf("%sv%u, length: %u",
- tok2str(slow_proto_values, "unknown (%u)",slow_com_header->proto_subtype),
- slow_com_header->version,
- len);
+ /* unrecognized subtype */
+ if (print_version == -1) {
+ print_unknown_data(pptr, "\n\t", len);
+ return;
+ }
if (!vflag)
return;
- /* ok they seem to want to know everything - lets fully decode it */
- tlen=len-sizeof(struct slow_common_header);
- tptr+=sizeof(const struct slow_common_header);
+ switch (slow_com_header->proto_subtype) {
+ default: /* should not happen */
+ break;
+
+ case SLOW_PROTO_OAM:
+ /* skip proto_subtype */
+ slow_oam_print(pptr+1, len-1);
+ break;
+
+ case SLOW_PROTO_LACP: /* LACP and MARKER share the same semantics */
+ case SLOW_PROTO_MARKER:
+ /* skip slow_common_header */
+ len -= sizeof(const struct slow_common_header_t);
+ pptr += sizeof(const struct slow_common_header_t);
+ slow_marker_lacp_print(pptr, len);
+ break;
+ }
+ return;
+
+trunc:
+ printf("\n\t\t packet exceeded snapshot");
+}
+void slow_marker_lacp_print(register const u_char *tptr, register u_int tlen) {
+
+ const struct tlv_header_t *tlv_header;
+ const u_char *tlv_tptr;
+ u_int tlv_len, tlv_tlen;
+
+ union {
+ const struct lacp_marker_tlv_terminator_t *lacp_marker_tlv_terminator;
+ const struct lacp_tlv_actor_partner_info_t *lacp_tlv_actor_partner_info;
+ const struct lacp_tlv_collector_info_t *lacp_tlv_collector_info;
+ const struct marker_tlv_marker_info_t *marker_tlv_marker_info;
+ } tlv_ptr;
+
while(tlen>0) {
/* did we capture enough for fully decoding the tlv header ? */
TCHECK2(*tptr, sizeof(struct tlv_header_t));
tlv_header = (const struct tlv_header_t *)tptr;
tlv_len = tlv_header->length;
- printf("\n\t%s TLV (0x%02x), length: %u",
+ printf("\n\t%s TLV (0x%02x), length %u",
tok2str(slow_tlv_values,
"Unknown",
(slow_com_header->proto_subtype << 8) + tlv_header->type),
@@ -250,10 +439,11 @@ slow_print(register const u_char *pptr, register u_int len) {
print_unknown_data(tlv_tptr,"\n\t ",tlv_tlen);
break;
}
- /* do we want to see an additionally hexdump ? */
- if (vflag > 1)
+ /* do we want to see an additional hexdump ? */
+ if (vflag > 1) {
print_unknown_data(tptr+sizeof(sizeof(struct tlv_header_t)),"\n\t ",
tlv_len-sizeof(struct tlv_header_t));
+ }
tptr+=tlv_len;
tlen-=tlv_len;
@@ -262,3 +452,210 @@ slow_print(register const u_char *pptr, register u_int len) {
trunc:
printf("\n\t\t packet exceeded snapshot");
}
+
+void slow_oam_print(register const u_char *tptr, register u_int tlen) {
+
+ u_int hexdump;
+
+ struct slow_oam_common_header_t {
+ u_int8_t flags[2];
+ u_int8_t code;
+ };
+
+ struct slow_oam_tlv_header_t {
+ u_int8_t type;
+ u_int8_t length;
+ };
+
+ union {
+ const struct slow_oam_common_header_t *slow_oam_common_header;
+ const struct slow_oam_tlv_header_t *slow_oam_tlv_header;
+ } ptr;
+
+ union {
+ const struct slow_oam_info_t *slow_oam_info;
+ const struct slow_oam_link_event_t *slow_oam_link_event;
+ const struct slow_oam_variablerequest_t *slow_oam_variablerequest;
+ const struct slow_oam_variableresponse_t *slow_oam_variableresponse;
+ const struct slow_oam_loopbackctrl_t *slow_oam_loopbackctrl;
+ } tlv;
+
+ ptr.slow_oam_common_header = (struct slow_oam_common_header_t *)tptr;
+ tptr += sizeof(struct slow_oam_common_header_t);
+ tlen -= sizeof(struct slow_oam_common_header_t);
+
+ printf("\n\tCode %s OAM PDU, Flags [%s]",
+ tok2str(slow_oam_code_values, "Unknown (%u)", ptr.slow_oam_common_header->code),
+ bittok2str(slow_oam_flag_values,
+ "none",
+ EXTRACT_16BITS(&ptr.slow_oam_common_header->flags)));
+
+ switch (ptr.slow_oam_common_header->code) {
+ case SLOW_OAM_CODE_INFO:
+ while (tlen > 0) {
+ ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr;
+ printf("\n\t %s Information Type (%u), length %u",
+ tok2str(slow_oam_info_type_values, "Reserved",
+ ptr.slow_oam_tlv_header->type),
+ ptr.slow_oam_tlv_header->type,
+ ptr.slow_oam_tlv_header->length);
+
+ hexdump = FALSE;
+ switch (ptr.slow_oam_tlv_header->type) {
+ case SLOW_OAM_INFO_TYPE_END_OF_TLV:
+ if (ptr.slow_oam_tlv_header->length != 0) {
+ printf("\n\t ERROR: illegal length - should be 0");
+ }
+ return;
+
+ case SLOW_OAM_INFO_TYPE_LOCAL: /* identical format - fall through */
+ case SLOW_OAM_INFO_TYPE_REMOTE:
+ tlv.slow_oam_info = (const struct slow_oam_info_t *)tptr;
+
+ if (tlv.slow_oam_info->info_length !=
+ sizeof(struct slow_oam_info_t)) {
+ printf("\n\t ERROR: illegal length - should be %lu",
+ (unsigned long) sizeof(struct slow_oam_info_t));
+ return;
+ }
+
+ printf("\n\t OAM-Version %u, Revision %u",
+ tlv.slow_oam_info->oam_version,
+ EXTRACT_16BITS(&tlv.slow_oam_info->revision));
+
+ printf("\n\t State-Parser-Action %s, State-MUX-Action %s",
+ tok2str(slow_oam_info_type_state_parser_values, "Reserved",
+ tlv.slow_oam_info->state & OAM_INFO_TYPE_PARSER_MASK),
+ tok2str(slow_oam_info_type_state_mux_values, "Reserved",
+ tlv.slow_oam_info->state & OAM_INFO_TYPE_MUX_MASK));
+ printf("\n\t OAM-Config Flags [%s], OAM-PDU-Config max-PDU size %u",
+ bittok2str(slow_oam_info_type_oam_config_values, "none",
+ tlv.slow_oam_info->oam_config),
+ EXTRACT_16BITS(&tlv.slow_oam_info->oam_pdu_config) &
+ OAM_INFO_TYPE_PDU_SIZE_MASK);
+ printf("\n\t OUI %s (0x%06x), Vendor-Private 0x%08x",
+ tok2str(oui_values, "Unknown",
+ EXTRACT_24BITS(&tlv.slow_oam_info->oui)),
+ EXTRACT_24BITS(&tlv.slow_oam_info->oui),
+ EXTRACT_32BITS(&tlv.slow_oam_info->vendor_private));
+ break;
+
+ case SLOW_OAM_INFO_TYPE_ORG_SPECIFIC:
+ hexdump = TRUE;
+ break;
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+
+ /* infinite loop check */
+ if (!ptr.slow_oam_tlv_header->length) {
+ return;
+ }
+
+ /* do we also want to see a hex dump ? */
+ if (vflag > 1 || hexdump==TRUE) {
+ print_unknown_data(tptr,"\n\t ",
+ ptr.slow_oam_tlv_header->length);
+ }
+
+ tlen -= ptr.slow_oam_tlv_header->length;
+ tptr += ptr.slow_oam_tlv_header->length;
+ }
+ break;
+
+ case SLOW_OAM_CODE_EVENT_NOTIF:
+ while (tlen > 0) {
+ ptr.slow_oam_tlv_header = (const struct slow_oam_tlv_header_t *)tptr;
+ printf("\n\t %s Link Event Type (%u), length %u",
+ tok2str(slow_oam_link_event_values, "Reserved",
+ ptr.slow_oam_tlv_header->type),
+ ptr.slow_oam_tlv_header->type,
+ ptr.slow_oam_tlv_header->length);
+
+ hexdump = FALSE;
+ switch (ptr.slow_oam_tlv_header->type) {
+ case SLOW_OAM_LINK_EVENT_END_OF_TLV:
+ if (ptr.slow_oam_tlv_header->length != 0) {
+ printf("\n\t ERROR: illegal length - should be 0");
+ }
+ return;
+
+ case SLOW_OAM_LINK_EVENT_ERR_SYM_PER: /* identical format - fall through */
+ case SLOW_OAM_LINK_EVENT_ERR_FRM:
+ case SLOW_OAM_LINK_EVENT_ERR_FRM_PER:
+ case SLOW_OAM_LINK_EVENT_ERR_FRM_SUMM:
+ tlv.slow_oam_link_event = (const struct slow_oam_link_event_t *)tptr;
+
+ if (tlv.slow_oam_link_event->event_length !=
+ sizeof(struct slow_oam_link_event_t)) {
+ printf("\n\t ERROR: illegal length - should be %lu",
+ (unsigned long) sizeof(struct slow_oam_link_event_t));
+ return;
+ }
+
+ printf("\n\t Timestamp %u ms, Errored Window %" PRIu64
+ "\n\t Errored Threshold %" PRIu64
+ "\n\t Errors %" PRIu64
+ "\n\t Error Running Total %" PRIu64
+ "\n\t Event Running Total %u",
+ EXTRACT_16BITS(&tlv.slow_oam_link_event->time_stamp)*100,
+ EXTRACT_64BITS(&tlv.slow_oam_link_event->window),
+ EXTRACT_64BITS(&tlv.slow_oam_link_event->threshold),
+ EXTRACT_64BITS(&tlv.slow_oam_link_event->errors),
+ EXTRACT_64BITS(&tlv.slow_oam_link_event->errors_running_total),
+ EXTRACT_32BITS(&tlv.slow_oam_link_event->event_running_total));
+ break;
+
+ case SLOW_OAM_LINK_EVENT_ORG_SPECIFIC:
+ hexdump = TRUE;
+ break;
+
+ default:
+ hexdump = TRUE;
+ break;
+ }
+
+ /* infinite loop check */
+ if (!ptr.slow_oam_tlv_header->length) {
+ return;
+ }
+
+ /* do we also want to see a hex dump ? */
+ if (vflag > 1 || hexdump==TRUE) {
+ print_unknown_data(tptr,"\n\t ",
+ ptr.slow_oam_tlv_header->length);
+ }
+
+ tlen -= ptr.slow_oam_tlv_header->length;
+ tptr += ptr.slow_oam_tlv_header->length;
+ }
+ break;
+
+ case SLOW_OAM_CODE_LOOPBACK_CTRL:
+ tlv.slow_oam_loopbackctrl = (const struct slow_oam_loopbackctrl_t *)tptr;
+ printf("\n\t Command %s (%u)",
+ tok2str(slow_oam_loopbackctrl_cmd_values,
+ "Unknown",
+ tlv.slow_oam_loopbackctrl->command),
+ tlv.slow_oam_loopbackctrl->command);
+ tptr ++;
+ tlen --;
+ break;
+
+ /*
+ * FIXME those are the defined codes that lack a decoder
+ * you are welcome to contribute code ;-)
+ */
+ case SLOW_OAM_CODE_VAR_REQUEST:
+ case SLOW_OAM_CODE_VAR_RESPONSE:
+ case SLOW_OAM_CODE_PRIVATE:
+ default:
+ if (vflag <= 1) {
+ print_unknown_data(tptr,"\n\t ", tlen);
+ }
+ break;
+ }
+ return;
+}
diff --git a/contrib/tcpdump/print-smb.c b/contrib/tcpdump/print-smb.c
index 5b963de..391f186 100644
--- a/contrib/tcpdump/print-smb.c
+++ b/contrib/tcpdump/print-smb.c
@@ -12,7 +12,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-smb.c,v 1.41.2.4 2007/07/14 22:29:05 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-smb.c,v 1.46.2.1 2007-12-09 00:31:35 guy Exp $";
#endif
#include <tcpdump-stdinc.h>
@@ -1244,7 +1244,47 @@ trunc:
return;
}
+/*
+ * Print an SMB-over-TCP packet received across tcp on port 445
+ */
+void
+smb_tcp_print (const u_char * data, int length)
+{
+ int caplen;
+ u_int smb_len;
+ const u_char *maxbuf;
+
+ if (length < 4)
+ goto trunc;
+ if (snapend < data)
+ goto trunc;
+ caplen = snapend - data;
+ if (caplen < 4)
+ goto trunc;
+ maxbuf = data + caplen;
+ smb_len = EXTRACT_24BITS(data + 1);
+ length -= 4;
+ caplen -= 4;
+ startbuf = data;
+ data += 4;
+
+ if (smb_len >= 4 && caplen >= 4 && memcmp(data,"\377SMB",4) == 0) {
+ if ((int)smb_len > caplen) {
+ if ((int)smb_len > length)
+ printf("WARNING: Packet is continued in later TCP segments\n");
+ else
+ printf("WARNING: Short packet. Try increasing the snap length by %d\n",
+ smb_len - caplen);
+ }
+ print_smb(data, maxbuf > data + smb_len ? data + smb_len : maxbuf);
+ } else
+ printf("SMB-over-TCP packet:(raw data or continuation?)\n");
+ return;
+trunc:
+ printf("[|SMB]");
+ return;
+}
/*
* print a NBT packet received across udp on port 138
@@ -1459,8 +1499,7 @@ ipx_netbios_print(const u_char *data, u_int length)
break;
if (memcmp(&data[i], "\377SMB", 4) == 0) {
smb_fdata(data, "\n>>> IPX transport ", &data[i], 0);
- if (data != NULL)
- print_smb(&data[i], maxbuf);
+ print_smb(&data[i], maxbuf);
printf("\n");
fflush(stdout);
break;
diff --git a/contrib/tcpdump/print-snmp.c b/contrib/tcpdump/print-snmp.c
index 0686b62..728da6b 100644
--- a/contrib/tcpdump/print-snmp.c
+++ b/contrib/tcpdump/print-snmp.c
@@ -58,7 +58,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-snmp.c,v 1.62.2.2 2005/05/06 07:57:19 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-snmp.c,v 1.64 2005-05-06 07:56:53 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-stp.c b/contrib/tcpdump/print-stp.c
index 4308ae0..8822c30 100644
--- a/contrib/tcpdump/print-stp.c
+++ b/contrib/tcpdump/print-stp.c
@@ -11,7 +11,7 @@
#ifndef lint
static const char rcsid[] _U_ =
-"@(#) $Header: /tcpdump/master/tcpdump/print-stp.c,v 1.13.2.7 2007/03/18 17:12:36 hannes Exp $";
+"@(#) $Header: /tcpdump/master/tcpdump/print-stp.c,v 1.20 2007-03-18 17:11:46 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-sunatm.c b/contrib/tcpdump/print-sunatm.c
index acd38bf..e6f19e8 100644
--- a/contrib/tcpdump/print-sunatm.c
+++ b/contrib/tcpdump/print-sunatm.c
@@ -31,7 +31,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-sunatm.c,v 1.8 2004/03/17 23:24:38 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-sunatm.c,v 1.8 2004-03-17 23:24:38 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-sunrpc.c b/contrib/tcpdump/print-sunrpc.c
index 420ec36..565cbfd 100644
--- a/contrib/tcpdump/print-sunrpc.c
+++ b/contrib/tcpdump/print-sunrpc.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-sunrpc.c,v 1.46.2.1 2005/04/27 21:44:06 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-sunrpc.c,v 1.47 2005-04-27 21:43:48 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-symantec.c b/contrib/tcpdump/print-symantec.c
index eb72180..ebb62cd 100644
--- a/contrib/tcpdump/print-symantec.c
+++ b/contrib/tcpdump/print-symantec.c
@@ -20,7 +20,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-symantec.c,v 1.4.2.1 2005/07/07 01:24:39 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-symantec.c,v 1.5 2005-07-07 01:22:21 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-syslog.c b/contrib/tcpdump/print-syslog.c
index 099d027..3685d62 100755
--- a/contrib/tcpdump/print-syslog.c
+++ b/contrib/tcpdump/print-syslog.c
@@ -16,7 +16,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-syslog.c,v 1.1 2004/10/29 11:42:53 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-syslog.c,v 1.1 2004-10-29 11:42:53 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-tcp.c b/contrib/tcpdump/print-tcp.c
index 11bd6b7..5b0a796 100644
--- a/contrib/tcpdump/print-tcp.c
+++ b/contrib/tcpdump/print-tcp.c
@@ -1,3 +1,5 @@
+/* $NetBSD: print-tcp.c,v 1.9 2007/07/26 18:15:12 plunky Exp $ */
+
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
* The Regents of the University of California. All rights reserved.
@@ -23,7 +25,9 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.120.2.3 2005/10/16 06:05:46 guy Exp $ (LBL)";
+"@(#) $Header: /tcpdump/master/tcpdump/print-tcp.c,v 1.130.2.3 2007-12-22 03:08:45 guy Exp $ (LBL)";
+ #else
+__RCSID("$NetBSD: print-tcp.c,v 1.8 2007/07/24 11:53:48 drochner Exp $");
#endif
#ifdef HAVE_CONFIG_H
@@ -60,7 +64,7 @@ static const char rcsid[] _U_ =
#define CANT_CHECK_SIGNATURE 2
static int tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp,
- const u_char *data, int length, const u_char *rcvsig);
+ const u_char *data, int length, const u_char *rcvsig);
#endif
static void print_tcp_rst_data(register const u_char *sp, u_int length);
@@ -70,20 +74,20 @@ static void print_tcp_rst_data(register const u_char *sp, u_int length);
struct tha {
#ifndef INET6
- struct in_addr src;
- struct in_addr dst;
+ struct in_addr src;
+ struct in_addr dst;
#else
- struct in6_addr src;
- struct in6_addr dst;
+ struct in6_addr src;
+ struct in6_addr dst;
#endif /*INET6*/
- u_int port;
+ u_int port;
};
struct tcp_seq_hash {
- struct tcp_seq_hash *nxt;
- struct tha addr;
- tcp_seq seq;
- tcp_seq ack;
+ struct tcp_seq_hash *nxt;
+ struct tha addr;
+ tcp_seq seq;
+ tcp_seq ack;
};
#define TSEQ_HASHSIZE 919
@@ -93,97 +97,95 @@ struct tcp_seq_hash {
static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE];
+struct tok tcp_flag_values[] = {
+ { TH_FIN, "F" },
+ { TH_SYN, "S" },
+ { TH_RST, "R" },
+ { TH_PUSH, "P" },
+ { TH_ACK, "." },
+ { TH_URG, "U" },
+ { TH_ECNECHO, "E" },
+ { TH_CWR, "W" },
+ { 0, NULL }
+};
-#ifndef TELNET_PORT
-#define TELNET_PORT 23
-#endif
-#ifndef BGP_PORT
-#define BGP_PORT 179
-#endif
-#define NETBIOS_SSN_PORT 139
-#ifndef PPTP_PORT
-#define PPTP_PORT 1723
-#endif
-#define BEEP_PORT 10288
-#ifndef NFS_PORT
-#define NFS_PORT 2049
-#endif
-#define MSDP_PORT 639
-#define LDP_PORT 646
+struct tok tcp_option_values[] = {
+ { TCPOPT_EOL, "eol" },
+ { TCPOPT_NOP, "nop" },
+ { TCPOPT_MAXSEG, "mss" },
+ { TCPOPT_WSCALE, "wscale" },
+ { TCPOPT_SACKOK, "sackOK" },
+ { TCPOPT_SACK, "sack" },
+ { TCPOPT_ECHO, "echo" },
+ { TCPOPT_ECHOREPLY, "echoreply" },
+ { TCPOPT_TIMESTAMP, "TS" },
+ { TCPOPT_CC, "cc" },
+ { TCPOPT_CCNEW, "ccnew" },
+ { TCPOPT_CCECHO, "" },
+ { TCPOPT_SIGNATURE, "md5" },
+ { TCPOPT_AUTH, "enhanced auth" },
+ { 0, NULL }
+};
static int tcp_cksum(register const struct ip *ip,
register const struct tcphdr *tp,
register u_int len)
{
- union phu {
- struct phdr {
- u_int32_t src;
- u_int32_t dst;
- u_char mbz;
- u_char proto;
- u_int16_t len;
- } ph;
- u_int16_t pa[6];
- } phu;
- const u_int16_t *sp;
-
- /* pseudo-header.. */
- phu.ph.len = htons((u_int16_t)len);
- phu.ph.mbz = 0;
- phu.ph.proto = IPPROTO_TCP;
- memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
- if (IP_HL(ip) == 5)
- memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
- else
- phu.ph.dst = ip_finddst(ip);
-
- sp = &phu.pa[0];
- return in_cksum((u_short *)tp, len,
- sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]);
+ union phu {
+ struct phdr {
+ u_int32_t src;
+ u_int32_t dst;
+ u_char mbz;
+ u_char proto;
+ u_int16_t len;
+ } ph;
+ u_int16_t pa[6];
+ } phu;
+ const u_int16_t *sp;
+
+ /* pseudo-header.. */
+ phu.ph.len = htons((u_int16_t)len);
+ phu.ph.mbz = 0;
+ phu.ph.proto = IPPROTO_TCP;
+ memcpy(&phu.ph.src, &ip->ip_src.s_addr, sizeof(u_int32_t));
+ if (IP_HL(ip) == 5)
+ memcpy(&phu.ph.dst, &ip->ip_dst.s_addr, sizeof(u_int32_t));
+ else
+ phu.ph.dst = ip_finddst(ip);
+
+ sp = &phu.pa[0];
+ return in_cksum((u_short *)tp, len,
+ sp[0]+sp[1]+sp[2]+sp[3]+sp[4]+sp[5]);
}
#ifdef INET6
static int tcp6_cksum(const struct ip6_hdr *ip6, const struct tcphdr *tp,
- u_int len)
+ u_int len)
{
- size_t i;
- register const u_int16_t *sp;
- u_int32_t sum;
- union {
- struct {
- struct in6_addr ph_src;
- struct in6_addr ph_dst;
- u_int32_t ph_len;
- u_int8_t ph_zero[3];
- u_int8_t ph_nxt;
- } ph;
- u_int16_t pa[20];
- } phu;
-
- /* pseudo-header */
- memset(&phu, 0, sizeof(phu));
- phu.ph.ph_src = ip6->ip6_src;
- phu.ph.ph_dst = ip6->ip6_dst;
- phu.ph.ph_len = htonl(len);
- phu.ph.ph_nxt = IPPROTO_TCP;
-
- sum = 0;
- for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)
- sum += phu.pa[i];
-
- sp = (const u_int16_t *)tp;
-
- for (i = 0; i < (len & ~1); i += 2)
- sum += *sp++;
-
- if (len & 1)
- sum += htons((*(const u_int8_t *)sp) << 8);
-
- while (sum > 0xffff)
- sum = (sum & 0xffff) + (sum >> 16);
- sum = ~sum & 0xffff;
-
- return (sum);
+ size_t i;
+ u_int32_t sum = 0;
+ union {
+ struct {
+ struct in6_addr ph_src;
+ struct in6_addr ph_dst;
+ u_int32_t ph_len;
+ u_int8_t ph_zero[3];
+ u_int8_t ph_nxt;
+ } ph;
+ u_int16_t pa[20];
+ } phu;
+
+ /* pseudo-header */
+ memset(&phu, 0, sizeof(phu));
+ phu.ph.ph_src = ip6->ip6_src;
+ phu.ph.ph_dst = ip6->ip6_dst;
+ phu.ph.ph_len = htonl(len);
+ phu.ph.ph_nxt = IPPROTO_TCP;
+
+ for (i = 0; i < sizeof(phu.pa) / sizeof(phu.pa[0]); i++)
+ sum += phu.pa[i];
+
+ return in_cksum((u_short *)tp, len, sum);
}
#endif
@@ -191,507 +193,509 @@ void
tcp_print(register const u_char *bp, register u_int length,
register const u_char *bp2, int fragmented)
{
- register const struct tcphdr *tp;
- register const struct ip *ip;
- register u_char flags;
- register u_int hlen;
- register char ch;
- u_int16_t sport, dport, win, urp;
- u_int32_t seq, ack, thseq, thack;
- int threv;
+ register const struct tcphdr *tp;
+ register const struct ip *ip;
+ register u_char flags;
+ register u_int hlen;
+ register char ch;
+ u_int16_t sport, dport, win, urp;
+ u_int32_t seq, ack, thseq, thack;
+ int threv;
#ifdef INET6
- register const struct ip6_hdr *ip6;
+ register const struct ip6_hdr *ip6;
#endif
- tp = (struct tcphdr *)bp;
- ip = (struct ip *)bp2;
+ tp = (struct tcphdr *)bp;
+ ip = (struct ip *)bp2;
#ifdef INET6
- if (IP_V(ip) == 6)
- ip6 = (struct ip6_hdr *)bp2;
- else
- ip6 = NULL;
+ if (IP_V(ip) == 6)
+ ip6 = (struct ip6_hdr *)bp2;
+ else
+ ip6 = NULL;
#endif /*INET6*/
- ch = '\0';
- if (!TTEST(tp->th_dport)) {
- (void)printf("%s > %s: [|tcp]",
- ipaddr_string(&ip->ip_src),
- ipaddr_string(&ip->ip_dst));
- return;
- }
+ ch = '\0';
+ if (!TTEST(tp->th_dport)) {
+ (void)printf("%s > %s: [|tcp]",
+ ipaddr_string(&ip->ip_src),
+ ipaddr_string(&ip->ip_dst));
+ return;
+ }
- sport = EXTRACT_16BITS(&tp->th_sport);
- dport = EXTRACT_16BITS(&tp->th_dport);
+ sport = EXTRACT_16BITS(&tp->th_sport);
+ dport = EXTRACT_16BITS(&tp->th_dport);
- hlen = TH_OFF(tp) * 4;
+ hlen = TH_OFF(tp) * 4;
- /*
+ /*
* If data present, header length valid, and NFS port used,
* assume NFS.
* Pass offset of data plus 4 bytes for RPC TCP msg length
* to NFS print routines.
*/
- if (!qflag && hlen >= sizeof(*tp) && hlen <= length) {
- if ((u_char *)tp + 4 + sizeof(struct sunrpc_msg) <= snapend &&
- dport == NFS_PORT) {
- nfsreq_print((u_char *)tp + hlen + 4, length - hlen,
- (u_char *)ip);
- return;
- } else if ((u_char *)tp + 4 + sizeof(struct sunrpc_msg)
- <= snapend &&
- sport == NFS_PORT) {
- nfsreply_print((u_char *)tp + hlen + 4, length - hlen,
- (u_char *)ip);
- return;
- }
- }
+ if (!qflag && hlen >= sizeof(*tp) && hlen <= length &&
+ (length - hlen) >= 4) {
+ u_char *fraglenp;
+ u_int32_t fraglen;
+ register struct sunrpc_msg *rp;
+ enum sunrpc_msg_type direction;
+
+ fraglenp = (u_char *)tp + hlen;
+ if (TTEST2(*fraglenp, 4)) {
+ fraglen = EXTRACT_32BITS(fraglenp) & 0x7FFFFFFF;
+ if (fraglen > (length - hlen) - 4)
+ fraglen = (length - hlen) - 4;
+ rp = (struct sunrpc_msg *)(fraglenp + 4);
+ if (TTEST(rp->rm_direction)) {
+ direction = (enum sunrpc_msg_type)EXTRACT_32BITS(&rp->rm_direction);
+ if (dport == NFS_PORT &&
+ direction == SUNRPC_CALL) {
+ nfsreq_print((u_char *)rp, fraglen,
+ (u_char *)ip);
+ return;
+ }
+ if (sport == NFS_PORT &&
+ direction == SUNRPC_REPLY) {
+ nfsreply_print((u_char *)rp, fraglen,
+ (u_char *)ip);
+ return;
+ }
+ }
+ }
+ }
#ifdef INET6
- if (ip6) {
- if (ip6->ip6_nxt == IPPROTO_TCP) {
- (void)printf("%s.%s > %s.%s: ",
- ip6addr_string(&ip6->ip6_src),
- tcpport_string(sport),
- ip6addr_string(&ip6->ip6_dst),
- tcpport_string(dport));
- } else {
- (void)printf("%s > %s: ",
- tcpport_string(sport), tcpport_string(dport));
- }
- } else
+ if (ip6) {
+ if (ip6->ip6_nxt == IPPROTO_TCP) {
+ (void)printf("%s.%s > %s.%s: ",
+ ip6addr_string(&ip6->ip6_src),
+ tcpport_string(sport),
+ ip6addr_string(&ip6->ip6_dst),
+ tcpport_string(dport));
+ } else {
+ (void)printf("%s > %s: ",
+ tcpport_string(sport), tcpport_string(dport));
+ }
+ } else
#endif /*INET6*/
- {
- if (ip->ip_p == IPPROTO_TCP) {
- (void)printf("%s.%s > %s.%s: ",
- ipaddr_string(&ip->ip_src),
- tcpport_string(sport),
- ipaddr_string(&ip->ip_dst),
- tcpport_string(dport));
- } else {
- (void)printf("%s > %s: ",
- tcpport_string(sport), tcpport_string(dport));
- }
- }
-
- if (hlen < sizeof(*tp)) {
- (void)printf(" tcp %d [bad hdr length %u - too short, < %lu]",
- length - hlen, hlen, (unsigned long)sizeof(*tp));
- return;
- }
-
- TCHECK(*tp);
-
- seq = EXTRACT_32BITS(&tp->th_seq);
- ack = EXTRACT_32BITS(&tp->th_ack);
- win = EXTRACT_16BITS(&tp->th_win);
- urp = EXTRACT_16BITS(&tp->th_urp);
-
- if (qflag) {
- (void)printf("tcp %d", length - hlen);
- if (hlen > length) {
- (void)printf(" [bad hdr length %u - too long, > %u]",
- hlen, length);
- }
- return;
- }
- if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH|
- TH_ECNECHO|TH_CWR)) {
- if (flags & TH_SYN)
- putchar('S');
- if (flags & TH_FIN)
- putchar('F');
- if (flags & TH_RST)
- putchar('R');
- if (flags & TH_PUSH)
- putchar('P');
- if (flags & TH_CWR)
- putchar('W'); /* congestion _W_indow reduced (ECN) */
- if (flags & TH_ECNECHO)
- putchar('E'); /* ecn _E_cho sent (ECN) */
- } else
- putchar('.');
-
- if (!Sflag && (flags & TH_ACK)) {
- register struct tcp_seq_hash *th;
- const void *src, *dst;
- register int rev;
- struct tha tha;
- /*
- * Find (or record) the initial sequence numbers for
- * this conversation. (we pick an arbitrary
- * collating order so there's only one entry for
- * both directions).
- */
+ {
+ if (ip->ip_p == IPPROTO_TCP) {
+ (void)printf("%s.%s > %s.%s: ",
+ ipaddr_string(&ip->ip_src),
+ tcpport_string(sport),
+ ipaddr_string(&ip->ip_dst),
+ tcpport_string(dport));
+ } else {
+ (void)printf("%s > %s: ",
+ tcpport_string(sport), tcpport_string(dport));
+ }
+ }
+
+ if (hlen < sizeof(*tp)) {
+ (void)printf(" tcp %d [bad hdr length %u - too short, < %lu]",
+ length - hlen, hlen, (unsigned long)sizeof(*tp));
+ return;
+ }
+
+ TCHECK(*tp);
+
+ seq = EXTRACT_32BITS(&tp->th_seq);
+ ack = EXTRACT_32BITS(&tp->th_ack);
+ win = EXTRACT_16BITS(&tp->th_win);
+ urp = EXTRACT_16BITS(&tp->th_urp);
+
+ if (qflag) {
+ (void)printf("tcp %d", length - hlen);
+ if (hlen > length) {
+ (void)printf(" [bad hdr length %u - too long, > %u]",
+ hlen, length);
+ }
+ return;
+ }
+
+ flags = tp->th_flags;
+ printf("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags));
+
+ if (!Sflag && (flags & TH_ACK)) {
+ register struct tcp_seq_hash *th;
+ const void *src, *dst;
+ register int rev;
+ struct tha tha;
+ /*
+ * Find (or record) the initial sequence numbers for
+ * this conversation. (we pick an arbitrary
+ * collating order so there's only one entry for
+ * both directions).
+ */
#ifdef INET6
- memset(&tha, 0, sizeof(tha));
- rev = 0;
- if (ip6) {
- src = &ip6->ip6_src;
- dst = &ip6->ip6_dst;
- if (sport > dport)
- rev = 1;
- else if (sport == dport) {
- if (memcmp(src, dst, sizeof ip6->ip6_dst) > 0)
- rev = 1;
- }
- if (rev) {
- memcpy(&tha.src, dst, sizeof ip6->ip6_dst);
- memcpy(&tha.dst, src, sizeof ip6->ip6_src);
- tha.port = dport << 16 | sport;
- } else {
- memcpy(&tha.dst, dst, sizeof ip6->ip6_dst);
- memcpy(&tha.src, src, sizeof ip6->ip6_src);
- tha.port = sport << 16 | dport;
- }
- } else {
- src = &ip->ip_src;
- dst = &ip->ip_dst;
- if (sport > dport)
- rev = 1;
- else if (sport == dport) {
- if (memcmp(src, dst, sizeof ip->ip_dst) > 0)
- rev = 1;
- }
- if (rev) {
- memcpy(&tha.src, dst, sizeof ip->ip_dst);
- memcpy(&tha.dst, src, sizeof ip->ip_src);
- tha.port = dport << 16 | sport;
- } else {
- memcpy(&tha.dst, dst, sizeof ip->ip_dst);
- memcpy(&tha.src, src, sizeof ip->ip_src);
- tha.port = sport << 16 | dport;
- }
- }
+ memset(&tha, 0, sizeof(tha));
+ rev = 0;
+ if (ip6) {
+ src = &ip6->ip6_src;
+ dst = &ip6->ip6_dst;
+ if (sport > dport)
+ rev = 1;
+ else if (sport == dport) {
+ if (memcmp(src, dst, sizeof ip6->ip6_dst) > 0)
+ rev = 1;
+ }
+ if (rev) {
+ memcpy(&tha.src, dst, sizeof ip6->ip6_dst);
+ memcpy(&tha.dst, src, sizeof ip6->ip6_src);
+ tha.port = dport << 16 | sport;
+ } else {
+ memcpy(&tha.dst, dst, sizeof ip6->ip6_dst);
+ memcpy(&tha.src, src, sizeof ip6->ip6_src);
+ tha.port = sport << 16 | dport;
+ }
+ } else {
+ src = &ip->ip_src;
+ dst = &ip->ip_dst;
+ if (sport > dport)
+ rev = 1;
+ else if (sport == dport) {
+ if (memcmp(src, dst, sizeof ip->ip_dst) > 0)
+ rev = 1;
+ }
+ if (rev) {
+ memcpy(&tha.src, dst, sizeof ip->ip_dst);
+ memcpy(&tha.dst, src, sizeof ip->ip_src);
+ tha.port = dport << 16 | sport;
+ } else {
+ memcpy(&tha.dst, dst, sizeof ip->ip_dst);
+ memcpy(&tha.src, src, sizeof ip->ip_src);
+ tha.port = sport << 16 | dport;
+ }
+ }
#else
- rev = 0;
- src = &ip->ip_src;
- dst = &ip->ip_dst;
- if (sport > dport)
- rev = 1;
- else if (sport == dport) {
- if (memcmp(src, dst, sizeof ip->ip_dst) > 0)
- rev = 1;
- }
- if (rev) {
- memcpy(&tha.src, dst, sizeof ip->ip_dst);
- memcpy(&tha.dst, src, sizeof ip->ip_src);
- tha.port = dport << 16 | sport;
- } else {
- memcpy(&tha.dst, dst, sizeof ip->ip_dst);
- memcpy(&tha.src, src, sizeof ip->ip_src);
- tha.port = sport << 16 | dport;
- }
+ rev = 0;
+ src = &ip->ip_src;
+ dst = &ip->ip_dst;
+ if (sport > dport)
+ rev = 1;
+ else if (sport == dport) {
+ if (memcmp(src, dst, sizeof ip->ip_dst) > 0)
+ rev = 1;
+ }
+ if (rev) {
+ memcpy(&tha.src, dst, sizeof ip->ip_dst);
+ memcpy(&tha.dst, src, sizeof ip->ip_src);
+ tha.port = dport << 16 | sport;
+ } else {
+ memcpy(&tha.dst, dst, sizeof ip->ip_dst);
+ memcpy(&tha.src, src, sizeof ip->ip_src);
+ tha.port = sport << 16 | dport;
+ }
#endif
- threv = rev;
- for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
- th->nxt; th = th->nxt)
- if (memcmp((char *)&tha, (char *)&th->addr,
- sizeof(th->addr)) == 0)
- break;
-
- if (!th->nxt || (flags & TH_SYN)) {
- /* didn't find it or new conversation */
- if (th->nxt == NULL) {
- th->nxt = (struct tcp_seq_hash *)
- calloc(1, sizeof(*th));
- if (th->nxt == NULL)
- error("tcp_print: calloc");
- }
- th->addr = tha;
- if (rev)
- th->ack = seq, th->seq = ack - 1;
- else
- th->seq = seq, th->ack = ack - 1;
- } else {
- if (rev)
- seq -= th->ack, ack -= th->seq;
- else
- seq -= th->seq, ack -= th->ack;
- }
-
- thseq = th->seq;
- thack = th->ack;
- } else {
- /*fool gcc*/
- thseq = thack = threv = 0;
- }
- if (hlen > length) {
- (void)printf(" [bad hdr length %u - too long, > %u]",
- hlen, length);
- return;
- }
-
- if (IP_V(ip) == 4 && vflag && !fragmented) {
- u_int16_t sum, tcp_sum;
- if (TTEST2(tp->th_sport, length)) {
- sum = tcp_cksum(ip, tp, length);
+ threv = rev;
+ for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE];
+ th->nxt; th = th->nxt)
+ if (memcmp((char *)&tha, (char *)&th->addr,
+ sizeof(th->addr)) == 0)
+ break;
+
+ if (!th->nxt || (flags & TH_SYN)) {
+ /* didn't find it or new conversation */
+ if (th->nxt == NULL) {
+ th->nxt = (struct tcp_seq_hash *)
+ calloc(1, sizeof(*th));
+ if (th->nxt == NULL)
+ error("tcp_print: calloc");
+ }
+ th->addr = tha;
+ if (rev)
+ th->ack = seq, th->seq = ack - 1;
+ else
+ th->seq = seq, th->ack = ack - 1;
+ } else {
+ if (rev)
+ seq -= th->ack, ack -= th->seq;
+ else
+ seq -= th->seq, ack -= th->ack;
+ }
+
+ thseq = th->seq;
+ thack = th->ack;
+ } else {
+ /*fool gcc*/
+ thseq = thack = threv = 0;
+ }
+ if (hlen > length) {
+ (void)printf(" [bad hdr length %u - too long, > %u]",
+ hlen, length);
+ return;
+ }
+
+ if (IP_V(ip) == 4 && vflag && !Kflag && !fragmented) {
+ u_int16_t sum, tcp_sum;
+ if (TTEST2(tp->th_sport, length)) {
+ sum = tcp_cksum(ip, tp, length);
(void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum));
- if (sum != 0) {
- tcp_sum = EXTRACT_16BITS(&tp->th_sum);
- (void)printf(" (incorrect (-> 0x%04x),",in_cksum_shouldbe(tcp_sum, sum));
- } else
- (void)printf(" (correct),");
- }
- }
+ if (sum != 0) {
+ tcp_sum = EXTRACT_16BITS(&tp->th_sum);
+ (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum));
+ } else
+ (void)printf(" (correct)");
+ }
+ }
#ifdef INET6
- if (IP_V(ip) == 6 && ip6->ip6_plen && vflag && !fragmented) {
- u_int16_t sum,tcp_sum;
- if (TTEST2(tp->th_sport, length)) {
- sum = tcp6_cksum(ip6, tp, length);
+ if (IP_V(ip) == 6 && ip6->ip6_plen && vflag && !Kflag && !fragmented) {
+ u_int16_t sum,tcp_sum;
+ if (TTEST2(tp->th_sport, length)) {
+ sum = tcp6_cksum(ip6, tp, length);
(void)printf(", cksum 0x%04x",EXTRACT_16BITS(&tp->th_sum));
- if (sum != 0) {
- tcp_sum = EXTRACT_16BITS(&tp->th_sum);
- (void)printf(" (incorrect (-> 0x%04x),",in_cksum_shouldbe(tcp_sum, sum));
- } else
- (void)printf(" (correct),");
-
- }
- }
+ if (sum != 0) {
+ tcp_sum = EXTRACT_16BITS(&tp->th_sum);
+ (void)printf(" (incorrect -> 0x%04x)",in_cksum_shouldbe(tcp_sum, sum));
+ } else
+ (void)printf(" (correct)");
+
+ }
+ }
#endif
- length -= hlen;
- if (vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST))
- (void)printf(" %u:%u(%u)", seq, seq + length, length);
- if (flags & TH_ACK)
- (void)printf(" ack %u", ack);
-
- (void)printf(" win %d", win);
-
- if (flags & TH_URG)
- (void)printf(" urg %d", urp);
- /*
- * Handle any options.
- */
- if (hlen > sizeof(*tp)) {
- register const u_char *cp;
- register u_int i, opt, datalen;
- register u_int len;
-
- hlen -= sizeof(*tp);
- cp = (const u_char *)tp + sizeof(*tp);
- putchar(' ');
- ch = '<';
- while (hlen > 0) {
- putchar(ch);
- TCHECK(*cp);
- opt = *cp++;
- if (ZEROLENOPT(opt))
- len = 1;
- else {
- TCHECK(*cp);
- len = *cp++; /* total including type, len */
- if (len < 2 || len > hlen)
- goto bad;
- --hlen; /* account for length byte */
- }
- --hlen; /* account for type byte */
- datalen = 0;
+ length -= hlen;
+ if (vflag > 1 || flags & (TH_SYN | TH_FIN | TH_RST)) {
+ (void)printf(", seq %u", seq);
+
+ if (length > 0) {
+ (void)printf(":%u", seq + length);
+ }
+ }
+
+ if (flags & TH_ACK) {
+ (void)printf(", ack %u", ack);
+ }
+
+ (void)printf(", win %d", win);
+
+ if (flags & TH_URG)
+ (void)printf(", urg %d", urp);
+ /*
+ * Handle any options.
+ */
+ if (hlen > sizeof(*tp)) {
+ register const u_char *cp;
+ register u_int i, opt, datalen;
+ register u_int len;
+
+ hlen -= sizeof(*tp);
+ cp = (const u_char *)tp + sizeof(*tp);
+ printf(", options [");
+ while (hlen > 0) {
+ if (ch != '\0')
+ putchar(ch);
+ TCHECK(*cp);
+ opt = *cp++;
+ if (ZEROLENOPT(opt))
+ len = 1;
+ else {
+ TCHECK(*cp);
+ len = *cp++; /* total including type, len */
+ if (len < 2 || len > hlen)
+ goto bad;
+ --hlen; /* account for length byte */
+ }
+ --hlen; /* account for type byte */
+ datalen = 0;
/* Bail if "l" bytes of data are not left or were not captured */
#define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); }
- switch (opt) {
-
- case TCPOPT_MAXSEG:
- (void)printf("mss");
- datalen = 2;
- LENCHECK(datalen);
- (void)printf(" %u", EXTRACT_16BITS(cp));
-
- break;
-
- case TCPOPT_EOL:
- (void)printf("eol");
- break;
-
- case TCPOPT_NOP:
- (void)printf("nop");
- break;
-
- case TCPOPT_WSCALE:
- (void)printf("wscale");
- datalen = 1;
- LENCHECK(datalen);
- (void)printf(" %u", *cp);
- break;
-
- case TCPOPT_SACKOK:
- (void)printf("sackOK");
- break;
-
- case TCPOPT_SACK:
- datalen = len - 2;
- if (datalen % 8 != 0) {
- (void)printf("malformed sack");
- } else {
- u_int32_t s, e;
-
- (void)printf("sack %d ", datalen / 8);
- for (i = 0; i < datalen; i += 8) {
- LENCHECK(i + 4);
- s = EXTRACT_32BITS(cp + i);
- LENCHECK(i + 8);
- e = EXTRACT_32BITS(cp + i + 4);
- if (threv) {
- s -= thseq;
- e -= thseq;
- } else {
- s -= thack;
- e -= thack;
- }
- (void)printf("{%u:%u}", s, e);
- }
- }
- break;
-
- case TCPOPT_ECHO:
- (void)printf("echo");
- datalen = 4;
- LENCHECK(datalen);
- (void)printf(" %u", EXTRACT_32BITS(cp));
- break;
-
- case TCPOPT_ECHOREPLY:
- (void)printf("echoreply");
- datalen = 4;
- LENCHECK(datalen);
- (void)printf(" %u", EXTRACT_32BITS(cp));
- break;
-
- case TCPOPT_TIMESTAMP:
- (void)printf("timestamp");
- datalen = 8;
- LENCHECK(4);
- (void)printf(" %u", EXTRACT_32BITS(cp));
- LENCHECK(datalen);
- (void)printf(" %u", EXTRACT_32BITS(cp + 4));
- break;
-
- case TCPOPT_CC:
- (void)printf("cc");
- datalen = 4;
- LENCHECK(datalen);
- (void)printf(" %u", EXTRACT_32BITS(cp));
- break;
-
- case TCPOPT_CCNEW:
- (void)printf("ccnew");
- datalen = 4;
- LENCHECK(datalen);
- (void)printf(" %u", EXTRACT_32BITS(cp));
- break;
-
- case TCPOPT_CCECHO:
- (void)printf("ccecho");
- datalen = 4;
- LENCHECK(datalen);
- (void)printf(" %u", EXTRACT_32BITS(cp));
- break;
-
- case TCPOPT_SIGNATURE:
- (void)printf("md5:");
- datalen = TCP_SIGLEN;
- LENCHECK(datalen);
+
+ printf("%s", tok2str(tcp_option_values, "Unknown Option %u", opt));
+
+ switch (opt) {
+
+ case TCPOPT_MAXSEG:
+ datalen = 2;
+ LENCHECK(datalen);
+ (void)printf(" %u", EXTRACT_16BITS(cp));
+ break;
+
+ case TCPOPT_WSCALE:
+ datalen = 1;
+ LENCHECK(datalen);
+ (void)printf(" %u", *cp);
+ break;
+
+ case TCPOPT_SACK:
+ datalen = len - 2;
+ if (datalen % 8 != 0) {
+ (void)printf("malformed sack");
+ } else {
+ u_int32_t s, e;
+
+ (void)printf(" %d ", datalen / 8);
+ for (i = 0; i < datalen; i += 8) {
+ LENCHECK(i + 4);
+ s = EXTRACT_32BITS(cp + i);
+ LENCHECK(i + 8);
+ e = EXTRACT_32BITS(cp + i + 4);
+ if (threv) {
+ s -= thseq;
+ e -= thseq;
+ } else {
+ s -= thack;
+ e -= thack;
+ }
+ (void)printf("{%u:%u}", s, e);
+ }
+ }
+ break;
+
+ case TCPOPT_CC:
+ case TCPOPT_CCNEW:
+ case TCPOPT_CCECHO:
+ case TCPOPT_ECHO:
+ case TCPOPT_ECHOREPLY:
+
+ /*
+ * those options share their semantics.
+ * fall through
+ */
+ datalen = 4;
+ LENCHECK(datalen);
+ (void)printf(" %u", EXTRACT_32BITS(cp));
+ break;
+
+ case TCPOPT_TIMESTAMP:
+ datalen = 8;
+ LENCHECK(datalen);
+ (void)printf(" val %u ecr %u",
+ EXTRACT_32BITS(cp),
+ EXTRACT_32BITS(cp + 4));
+ break;
+
+ case TCPOPT_SIGNATURE:
+ datalen = TCP_SIGLEN;
+ LENCHECK(datalen);
#ifdef HAVE_LIBCRYPTO
- switch (tcp_verify_signature(ip, tp,
- bp + TH_OFF(tp) * 4, length, cp)) {
-
- case SIGNATURE_VALID:
- (void)printf("valid");
- break;
-
- case SIGNATURE_INVALID:
- (void)printf("invalid");
- break;
-
- case CANT_CHECK_SIGNATURE:
- (void)printf("can't check - ");
- for (i = 0; i < TCP_SIGLEN; ++i)
- (void)printf("%02x", cp[i]);
- break;
- }
+ switch (tcp_verify_signature(ip, tp,
+ bp + TH_OFF(tp) * 4, length, cp)) {
+
+ case SIGNATURE_VALID:
+ (void)printf("valid");
+ break;
+
+ case SIGNATURE_INVALID:
+ (void)printf("invalid");
+ break;
+
+ case CANT_CHECK_SIGNATURE:
+ (void)printf("can't check - ");
+ for (i = 0; i < TCP_SIGLEN; ++i)
+ (void)printf("%02x", cp[i]);
+ break;
+ }
#else
- for (i = 0; i < TCP_SIGLEN; ++i)
- (void)printf("%02x", cp[i]);
+ for (i = 0; i < TCP_SIGLEN; ++i)
+ (void)printf("%02x", cp[i]);
#endif
- break;
-
- default:
- (void)printf("opt-%u:", opt);
- datalen = len - 2;
- for (i = 0; i < datalen; ++i) {
- LENCHECK(i);
- (void)printf("%02x", cp[i]);
- }
- break;
- }
-
- /* Account for data printed */
- cp += datalen;
- hlen -= datalen;
-
- /* Check specification against observed length */
- ++datalen; /* option octet */
- if (!ZEROLENOPT(opt))
- ++datalen; /* size octet */
- if (datalen != len)
- (void)printf("[len %d]", len);
- ch = ',';
- if (opt == TCPOPT_EOL)
- break;
- }
- putchar('>');
- }
-
- if (length <= 0)
- return;
-
- /*
- * Decode payload if necessary.
- */
- bp += TH_OFF(tp) * 4;
- if (flags & TH_RST) {
- if (vflag)
- print_tcp_rst_data(bp, length);
- } else {
- if (sport == TELNET_PORT || dport == TELNET_PORT) {
- if (!qflag && vflag)
- telnet_print(bp, length);
- } else if (sport == BGP_PORT || dport == BGP_PORT)
- bgp_print(bp, length);
- else if (sport == PPTP_PORT || dport == PPTP_PORT)
- pptp_print(bp);
+ break;
+
+ case TCPOPT_AUTH:
+ (void)printf("keyid %d", *cp++);
+ datalen = len - 3;
+ for (i = 0; i < datalen; ++i) {
+ LENCHECK(i);
+ (void)printf("%02x", cp[i]);
+ }
+ break;
+
+
+ case TCPOPT_EOL:
+ case TCPOPT_NOP:
+ case TCPOPT_SACKOK:
+ /*
+ * Nothing interesting.
+ * fall through
+ */
+ break;
+
+ default:
+ datalen = len - 2;
+ for (i = 0; i < datalen; ++i) {
+ LENCHECK(i);
+ (void)printf("%02x", cp[i]);
+ }
+ break;
+ }
+
+ /* Account for data printed */
+ cp += datalen;
+ hlen -= datalen;
+
+ /* Check specification against observed length */
+ ++datalen; /* option octet */
+ if (!ZEROLENOPT(opt))
+ ++datalen; /* size octet */
+ if (datalen != len)
+ (void)printf("[len %d]", len);
+ ch = ',';
+ if (opt == TCPOPT_EOL)
+ break;
+ }
+ putchar(']');
+ }
+
+ /*
+ * Print length field before crawling down the stack.
+ */
+ printf(", length %u", length);
+
+ if (length <= 0)
+ return;
+
+ /*
+ * Decode payload if necessary.
+ */
+ bp += TH_OFF(tp) * 4;
+ if ((flags & TH_RST) && vflag) {
+ print_tcp_rst_data(bp, length);
+ return;
+ }
+
+ if (sport == TELNET_PORT || dport == TELNET_PORT) {
+ if (!qflag && vflag)
+ telnet_print(bp, length);
+ } else if (sport == BGP_PORT || dport == BGP_PORT)
+ bgp_print(bp, length);
+ else if (sport == PPTP_PORT || dport == PPTP_PORT)
+ pptp_print(bp);
#ifdef TCPDUMP_DO_SMB
- else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT)
- nbt_tcp_print(bp, length);
+ else if (sport == NETBIOS_SSN_PORT || dport == NETBIOS_SSN_PORT)
+ nbt_tcp_print(bp, length);
+ else if (sport == SMB_PORT || dport == SMB_PORT)
+ smb_tcp_print(bp, length);
#endif
- else if (sport == BEEP_PORT || dport == BEEP_PORT)
- beep_print(bp, length);
- else if (length > 2 &&
- (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT ||
- sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) {
- /*
- * TCP DNS query has 2byte length at the head.
- * XXX packet could be unaligned, it can go strange
- */
- ns_print(bp + 2, length - 2, 0);
- } else if (sport == MSDP_PORT || dport == MSDP_PORT) {
- msdp_print(bp, length);
- }
- else if (length > 0 && (sport == LDP_PORT || dport == LDP_PORT)) {
- ldp_print(bp, length);
- }
- }
- return;
-bad:
- fputs("[bad opt]", stdout);
- if (ch != '\0')
- putchar('>');
- return;
-trunc:
- fputs("[|tcp]", stdout);
- if (ch != '\0')
- putchar('>');
+ else if (sport == BEEP_PORT || dport == BEEP_PORT)
+ beep_print(bp, length);
+ else if (length > 2 &&
+ (sport == NAMESERVER_PORT || dport == NAMESERVER_PORT ||
+ sport == MULTICASTDNS_PORT || dport == MULTICASTDNS_PORT)) {
+ /*
+ * TCP DNS query has 2byte length at the head.
+ * XXX packet could be unaligned, it can go strange
+ */
+ ns_print(bp + 2, length - 2, 0);
+ } else if (sport == MSDP_PORT || dport == MSDP_PORT) {
+ msdp_print(bp, length);
+ }
+ else if (length > 0 && (sport == LDP_PORT || dport == LDP_PORT)) {
+ ldp_print(bp, length);
+ }
+
+ return;
+ bad:
+ fputs("[bad opt]", stdout);
+ if (ch != '\0')
+ putchar('>');
+ return;
+ trunc:
+ fputs("[|tcp]", stdout);
+ if (ch != '\0')
+ putchar('>');
}
/*
@@ -712,96 +716,103 @@ trunc:
static void
print_tcp_rst_data(register const u_char *sp, u_int length)
{
- int c;
-
- if (TTEST2(*sp, length))
- printf(" [RST");
- else
- printf(" [!RST");
- if (length > MAX_RST_DATA_LEN) {
- length = MAX_RST_DATA_LEN; /* can use -X for longer */
- putchar('+'); /* indicate we truncate */
- }
- putchar(' ');
- while (length-- && sp <= snapend) {
- c = *sp++;
- safeputchar(c);
- }
- putchar(']');
+ int c;
+
+ if (TTEST2(*sp, length))
+ printf(" [RST");
+ else
+ printf(" [!RST");
+ if (length > MAX_RST_DATA_LEN) {
+ length = MAX_RST_DATA_LEN; /* can use -X for longer */
+ putchar('+'); /* indicate we truncate */
+ }
+ putchar(' ');
+ while (length-- && sp <= snapend) {
+ c = *sp++;
+ safeputchar(c);
+ }
+ putchar(']');
}
#ifdef HAVE_LIBCRYPTO
static int
tcp_verify_signature(const struct ip *ip, const struct tcphdr *tp,
- const u_char *data, int length, const u_char *rcvsig)
+ const u_char *data, int length, const u_char *rcvsig)
{
struct tcphdr tp1;
- u_char sig[TCP_SIGLEN];
- char zero_proto = 0;
- MD5_CTX ctx;
- u_int16_t savecsum, tlen;
+ u_char sig[TCP_SIGLEN];
+ char zero_proto = 0;
+ MD5_CTX ctx;
+ u_int16_t savecsum, tlen;
#ifdef INET6
- struct ip6_hdr *ip6;
+ struct ip6_hdr *ip6;
+ u_int32_t len32;
+ u_int8_t nxt;
#endif
- u_int32_t len32;
- u_int8_t nxt;
-
- tp1 = *tp;
-
- if (tcpmd5secret == NULL)
- return (CANT_CHECK_SIGNATURE);
- MD5_Init(&ctx);
- /*
- * Step 1: Update MD5 hash with IP pseudo-header.
- */
- if (IP_V(ip) == 4) {
- MD5_Update(&ctx, (char *)&ip->ip_src, sizeof(ip->ip_src));
- MD5_Update(&ctx, (char *)&ip->ip_dst, sizeof(ip->ip_dst));
- MD5_Update(&ctx, (char *)&zero_proto, sizeof(zero_proto));
- MD5_Update(&ctx, (char *)&ip->ip_p, sizeof(ip->ip_p));
- tlen = EXTRACT_16BITS(&ip->ip_len) - IP_HL(ip) * 4;
- tlen = htons(tlen);
- MD5_Update(&ctx, (char *)&tlen, sizeof(tlen));
+ tp1 = *tp;
+
+ if (tcpmd5secret == NULL)
+ return (CANT_CHECK_SIGNATURE);
+
+ MD5_Init(&ctx);
+ /*
+ * Step 1: Update MD5 hash with IP pseudo-header.
+ */
+ if (IP_V(ip) == 4) {
+ MD5_Update(&ctx, (char *)&ip->ip_src, sizeof(ip->ip_src));
+ MD5_Update(&ctx, (char *)&ip->ip_dst, sizeof(ip->ip_dst));
+ MD5_Update(&ctx, (char *)&zero_proto, sizeof(zero_proto));
+ MD5_Update(&ctx, (char *)&ip->ip_p, sizeof(ip->ip_p));
+ tlen = EXTRACT_16BITS(&ip->ip_len) - IP_HL(ip) * 4;
+ tlen = htons(tlen);
+ MD5_Update(&ctx, (char *)&tlen, sizeof(tlen));
#ifdef INET6
- } else if (IP_V(ip) == 6) {
- ip6 = (struct ip6_hdr *)ip;
- MD5_Update(&ctx, (char *)&ip6->ip6_src, sizeof(ip6->ip6_src));
- MD5_Update(&ctx, (char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst));
- len32 = htonl(ntohs(ip6->ip6_plen));
- MD5_Update(&ctx, (char *)&len32, sizeof(len32));
- nxt = 0;
- MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
- MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
- MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
- nxt = IPPROTO_TCP;
- MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
+ } else if (IP_V(ip) == 6) {
+ ip6 = (struct ip6_hdr *)ip;
+ MD5_Update(&ctx, (char *)&ip6->ip6_src, sizeof(ip6->ip6_src));
+ MD5_Update(&ctx, (char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst));
+ len32 = htonl(ntohs(ip6->ip6_plen));
+ MD5_Update(&ctx, (char *)&len32, sizeof(len32));
+ nxt = 0;
+ MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
+ MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
+ MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
+ nxt = IPPROTO_TCP;
+ MD5_Update(&ctx, (char *)&nxt, sizeof(nxt));
#endif
- } else
- return (CANT_CHECK_SIGNATURE);
-
- /*
- * Step 2: Update MD5 hash with TCP header, excluding options.
- * The TCP checksum must be set to zero.
- */
- savecsum = tp1.th_sum;
- tp1.th_sum = 0;
- MD5_Update(&ctx, (char *)&tp1, sizeof(struct tcphdr));
- tp1.th_sum = savecsum;
- /*
- * Step 3: Update MD5 hash with TCP segment data, if present.
- */
- if (length > 0)
- MD5_Update(&ctx, data, length);
- /*
- * Step 4: Update MD5 hash with shared secret.
- */
- MD5_Update(&ctx, tcpmd5secret, strlen(tcpmd5secret));
- MD5_Final(sig, &ctx);
-
- if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0)
- return (SIGNATURE_VALID);
- else
- return (SIGNATURE_INVALID);
+ } else
+ return (CANT_CHECK_SIGNATURE);
+
+ /*
+ * Step 2: Update MD5 hash with TCP header, excluding options.
+ * The TCP checksum must be set to zero.
+ */
+ savecsum = tp1.th_sum;
+ tp1.th_sum = 0;
+ MD5_Update(&ctx, (char *)&tp1, sizeof(struct tcphdr));
+ tp1.th_sum = savecsum;
+ /*
+ * Step 3: Update MD5 hash with TCP segment data, if present.
+ */
+ if (length > 0)
+ MD5_Update(&ctx, data, length);
+ /*
+ * Step 4: Update MD5 hash with shared secret.
+ */
+ MD5_Update(&ctx, tcpmd5secret, strlen(tcpmd5secret));
+ MD5_Final(sig, &ctx);
+
+ if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0)
+ return (SIGNATURE_VALID);
+ else
+ return (SIGNATURE_INVALID);
}
#endif /* HAVE_LIBCRYPTO */
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/contrib/tcpdump/print-telnet.c b/contrib/tcpdump/print-telnet.c
index 7888727..4911e5c 100644
--- a/contrib/tcpdump/print-telnet.c
+++ b/contrib/tcpdump/print-telnet.c
@@ -51,7 +51,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-telnet.c,v 1.24 2003/12/29 11:05:10 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-telnet.c,v 1.24 2003-12-29 11:05:10 hannes Exp $";
#endif
#include <tcpdump-stdinc.h>
diff --git a/contrib/tcpdump/print-tftp.c b/contrib/tcpdump/print-tftp.c
index b517898..c4fc7ea 100644
--- a/contrib/tcpdump/print-tftp.c
+++ b/contrib/tcpdump/print-tftp.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-tftp.c,v 1.37.2.1 2007/09/14 01:03:12 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-tftp.c,v 1.38.2.1 2008-04-11 16:44:17 gianluca Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -50,7 +50,7 @@ static struct tok op2str[] = {
{ WRQ, "WRQ" }, /* write request */
{ DATA, "DATA" }, /* data packet */
{ ACK, "ACK" }, /* acknowledgement */
- { ERROR, "ERROR" }, /* error code */
+ { TFTP_ERROR, "ERROR" }, /* error code */
{ OACK, "OACK" }, /* option acknowledgement */
{ 0, NULL }
};
@@ -137,7 +137,7 @@ tftp_print(register const u_char *bp, u_int length)
printf(" block %d", EXTRACT_16BITS(&tp->th_block));
break;
- case ERROR:
+ case TFTP_ERROR:
/* Print error code string */
TCHECK(tp->th_code);
printf(" %s \"", tok2str(err2str, "tftp-err-#%d \"",
diff --git a/contrib/tcpdump/print-timed.c b/contrib/tcpdump/print-timed.c
index 3df2241..55fbb39 100644
--- a/contrib/tcpdump/print-timed.c
+++ b/contrib/tcpdump/print-timed.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-timed.c,v 1.9 2003/11/16 09:36:40 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-timed.c,v 1.9 2003-11-16 09:36:40 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-token.c b/contrib/tcpdump/print-token.c
index 8a5f4f5..8fe96c6 100644
--- a/contrib/tcpdump/print-token.c
+++ b/contrib/tcpdump/print-token.c
@@ -27,7 +27,7 @@
*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-token.c,v 1.25.2.2 2005/11/13 12:13:01 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-token.c,v 1.27 2005-11-13 12:12:43 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-udld.c b/contrib/tcpdump/print-udld.c
new file mode 100644
index 0000000..a5488dd
--- /dev/null
+++ b/contrib/tcpdump/print-udld.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 1998-2007 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * UNIDIRECTIONAL LINK DETECTION (UDLD) as per
+ * http://www.ietf.org/internet-drafts/draft-foschiano-udld-02.txt
+ *
+ * Original code by Carles Kishimoto <carles.kishimoto@gmail.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"
+#include "nlpid.h"
+
+#define UDLD_HEADER_LEN 4
+#define UDLD_DEVICE_ID_TLV 0x0001
+#define UDLD_PORT_ID_TLV 0x0002
+#define UDLD_ECHO_TLV 0x0003
+#define UDLD_MESSAGE_INTERVAL_TLV 0x0004
+#define UDLD_TIMEOUT_INTERVAL_TLV 0x0005
+#define UDLD_DEVICE_NAME_TLV 0x0006
+#define UDLD_SEQ_NUMBER_TLV 0x0007
+
+static struct tok udld_tlv_values[] = {
+ { UDLD_DEVICE_ID_TLV, "Device-ID TLV"},
+ { UDLD_PORT_ID_TLV, "Port-ID TLV"},
+ { UDLD_ECHO_TLV, "Echo TLV"},
+ { UDLD_MESSAGE_INTERVAL_TLV, "Message Interval TLV"},
+ { UDLD_TIMEOUT_INTERVAL_TLV, "Timeout Interval TLV"},
+ { UDLD_DEVICE_NAME_TLV, "Device Name TLV"},
+ { UDLD_SEQ_NUMBER_TLV,"Sequence Number TLV"},
+ { 0, NULL}
+};
+
+static struct tok udld_code_values[] = {
+ { 0x00, "Reserved"},
+ { 0x01, "Probe message"},
+ { 0x02, "Echo message"},
+ { 0x03, "Flush message"},
+ { 0, NULL}
+};
+
+static struct tok udld_flags_values[] = {
+ { 0x00, "RT"},
+ { 0x01, "RSY"},
+ { 0, NULL}
+};
+
+/*
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Ver | Opcode | Flags | Checksum |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | List of TLVs (variable length list) |
+ * | ... |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+#define UDLD_EXTRACT_VERSION(x) (((x)&0xe0)>>5)
+#define UDLD_EXTRACT_OPCODE(x) ((x)&0x1f)
+
+void
+udld_print (const u_char *pptr, u_int length)
+{
+ int code, type, len;
+ const u_char *tptr;
+
+ if (length < UDLD_HEADER_LEN)
+ goto trunc;
+
+ tptr = pptr;
+
+ if (!TTEST2(*tptr, UDLD_HEADER_LEN))
+ goto trunc;
+
+ code = UDLD_EXTRACT_OPCODE(*tptr);
+
+ printf("UDLDv%u, Code %s (%x), Flags [%s] (0x%02x), length %u",
+ UDLD_EXTRACT_VERSION(*tptr),
+ tok2str(udld_code_values, "Reserved", code),
+ code,
+ bittok2str(udld_flags_values, "none", *(tptr+1)),
+ *(tptr+1),
+ length);
+
+ /*
+ * In non-verbose mode, just print version and opcode type
+ */
+ if (vflag < 1) {
+ return;
+ }
+
+ printf("\n\tChecksum 0x%04x (unverified)", EXTRACT_16BITS(tptr+2));
+
+ tptr += UDLD_HEADER_LEN;
+
+ while (tptr < (pptr+length)) {
+
+ if (!TTEST2(*tptr, 4))
+ goto trunc;
+
+ type = EXTRACT_16BITS(tptr);
+ len = EXTRACT_16BITS(tptr+2);
+ len -= 4;
+ tptr += 4;
+
+ /* infinite loop check */
+ if (type == 0 || len == 0) {
+ return;
+ }
+
+ printf("\n\t%s (0x%04x) TLV, length %u",
+ tok2str(udld_tlv_values, "Unknown", type),
+ type, len);
+
+ switch (type) {
+ case UDLD_DEVICE_ID_TLV:
+ case UDLD_PORT_ID_TLV:
+ case UDLD_ECHO_TLV:
+ case UDLD_DEVICE_NAME_TLV:
+ printf(", %s", tptr);
+ break;
+
+ case UDLD_MESSAGE_INTERVAL_TLV:
+ case UDLD_TIMEOUT_INTERVAL_TLV:
+ printf(", %us", (*tptr));
+ break;
+
+ case UDLD_SEQ_NUMBER_TLV:
+ printf(", %u", EXTRACT_32BITS(tptr));
+ break;
+
+ default:
+ break;
+ }
+ tptr += len;
+ }
+
+ return;
+
+ trunc:
+ printf("[|udld]");
+}
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/contrib/tcpdump/print-udp.c b/contrib/tcpdump/print-udp.c
index d530d6a..0c70544 100644
--- a/contrib/tcpdump/print-udp.c
+++ b/contrib/tcpdump/print-udp.c
@@ -23,7 +23,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-udp.c,v 1.138.2.1 2007/03/28 07:45:46 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-udp.c,v 1.142 2007-08-08 17:20:58 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -685,6 +685,16 @@ udp_print(register const u_char *bp, u_int length,
bfd_print((const u_char *)(up+1), length, dport);
else if (ISPORT(LMP_PORT))
lmp_print((const u_char *)(up + 1), length);
+ else if (ISPORT(VQP_PORT))
+ vqp_print((const u_char *)(up + 1), length);
+ else if (ISPORT(SFLOW_PORT))
+ sflow_print((const u_char *)(up + 1), length);
+ else if (dport == LWAPP_CONTROL_PORT)
+ lwapp_control_print((const u_char *)(up + 1), length, 1);
+ else if (sport == LWAPP_CONTROL_PORT)
+ lwapp_control_print((const u_char *)(up + 1), length, 0);
+ else if (ISPORT(LWAPP_DATA_PORT))
+ lwapp_data_print((const u_char *)(up + 1), length);
else if (ISPORT(SIP_PORT))
sip_print((const u_char *)(up + 1), length);
else if (ISPORT(SYSLOG_PORT))
diff --git a/contrib/tcpdump/print-vjc.c b/contrib/tcpdump/print-vjc.c
index 55b7d08..2dc89aa 100644
--- a/contrib/tcpdump/print-vjc.c
+++ b/contrib/tcpdump/print-vjc.c
@@ -25,7 +25,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-vjc.c,v 1.15 2004/03/25 03:31:17 mcr Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-vjc.c,v 1.15 2004-03-25 03:31:17 mcr Exp $ (LBL)";
#endif
#include <tcpdump-stdinc.h>
diff --git a/contrib/tcpdump/print-vqp.c b/contrib/tcpdump/print-vqp.c
new file mode 100644
index 0000000..2d9e8e1
--- /dev/null
+++ b/contrib/tcpdump/print-vqp.c
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 1998-2006 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * support for the Cisco prop. VQP Protocol
+ *
+ * Original code by Carles Kishimoto <Carles.Kishimoto@bsc.es>
+ */
+
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/tcpdump/print-vqp.c,v 1.3 2006-08-19 06:51:13 guy Exp $";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "interface.h"
+#include "extract.h"
+#include "addrtoname.h"
+
+#define VQP_VERSION 1
+#define VQP_EXTRACT_VERSION(x) ((x)&0xFF)
+
+/*
+ * VQP common header
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Constant | Packet type | Error Code | nitems |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Packet Sequence Number (4 bytes) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+struct vqp_common_header_t {
+ u_int8_t version;
+ u_int8_t msg_type;
+ u_int8_t error_code;
+ u_int8_t nitems;
+ u_int8_t sequence[4];
+};
+
+struct vqp_obj_tlv_t {
+ u_int8_t obj_type[4];
+ u_int8_t obj_length[2];
+};
+
+#define VQP_OBJ_REQ_JOIN_PORT 0x01
+#define VQP_OBJ_RESP_VLAN 0x02
+#define VQP_OBJ_REQ_RECONFIRM 0x03
+#define VQP_OBJ_RESP_RECONFIRM 0x04
+
+static const struct tok vqp_msg_type_values[] = {
+ { VQP_OBJ_REQ_JOIN_PORT, "Request, Join Port"},
+ { VQP_OBJ_RESP_VLAN, "Response, VLAN"},
+ { VQP_OBJ_REQ_RECONFIRM, "Request, Reconfirm"},
+ { VQP_OBJ_RESP_RECONFIRM, "Response, Reconfirm"},
+ { 0, NULL}
+};
+
+static const struct tok vqp_error_code_values[] = {
+ { 0x00, "No error"},
+ { 0x03, "Access denied"},
+ { 0x04, "Shutdown port"},
+ { 0x05, "Wrong VTP domain"},
+ { 0, NULL}
+};
+
+/* FIXME the heading 0x0c looks ugly - those must be flags etc. */
+#define VQP_OBJ_IP_ADDRESS 0x0c01
+#define VQP_OBJ_PORT_NAME 0x0c02
+#define VQP_OBJ_VLAN_NAME 0x0c03
+#define VQP_OBJ_VTP_DOMAIN 0x0c04
+#define VQP_OBJ_ETHERNET_PKT 0x0c05
+#define VQP_OBJ_MAC_NULL 0x0c06
+#define VQP_OBJ_MAC_ADDRESS 0x0c08
+
+static const struct tok vqp_obj_values[] = {
+ { VQP_OBJ_IP_ADDRESS, "Client IP Address" },
+ { VQP_OBJ_PORT_NAME, "Port Name" },
+ { VQP_OBJ_VLAN_NAME, "VLAN Name" },
+ { VQP_OBJ_VTP_DOMAIN, "VTP Domain" },
+ { VQP_OBJ_ETHERNET_PKT, "Ethernet Packet" },
+ { VQP_OBJ_MAC_NULL, "MAC Null" },
+ { VQP_OBJ_MAC_ADDRESS, "MAC Address" },
+ { 0, NULL}
+};
+
+void
+vqp_print(register const u_char *pptr, register u_int len)
+{
+ const struct vqp_common_header_t *vqp_common_header;
+ const struct vqp_obj_tlv_t *vqp_obj_tlv;
+
+ const u_char *tptr;
+ u_int16_t vqp_obj_len;
+ u_int32_t vqp_obj_type;
+ int tlen;
+ u_int8_t nitems;
+
+ tptr=pptr;
+ tlen = len;
+ vqp_common_header = (const struct vqp_common_header_t *)pptr;
+ TCHECK(*vqp_common_header);
+
+ /*
+ * Sanity checking of the header.
+ */
+ if (VQP_EXTRACT_VERSION(vqp_common_header->version) != VQP_VERSION) {
+ printf("VQP version %u packet not supported",
+ VQP_EXTRACT_VERSION(vqp_common_header->version));
+ return;
+ }
+
+ /* in non-verbose mode just lets print the basic Message Type */
+ if (vflag < 1) {
+ printf("VQPv%u %s Message, error-code %s (%u), length %u",
+ VQP_EXTRACT_VERSION(vqp_common_header->version),
+ tok2str(vqp_msg_type_values, "unknown (%u)",vqp_common_header->msg_type),
+ tok2str(vqp_error_code_values, "unknown (%u)",vqp_common_header->error_code),
+ vqp_common_header->error_code,
+ len);
+ return;
+ }
+
+ /* ok they seem to want to know everything - lets fully decode it */
+ nitems = vqp_common_header->nitems;
+ printf("\n\tVQPv%u, %s Message, error-code %s (%u), seq 0x%08x, items %u, length %u",
+ VQP_EXTRACT_VERSION(vqp_common_header->version),
+ tok2str(vqp_msg_type_values, "unknown (%u)",vqp_common_header->msg_type),
+ tok2str(vqp_error_code_values, "unknown (%u)",vqp_common_header->error_code),
+ vqp_common_header->error_code,
+ EXTRACT_32BITS(&vqp_common_header->sequence),
+ nitems,
+ len);
+
+ /* skip VQP Common header */
+ tptr+=sizeof(const struct vqp_common_header_t);
+ tlen-=sizeof(const struct vqp_common_header_t);
+
+ while (nitems > 0 && tlen > 0) {
+
+ vqp_obj_tlv = (const struct vqp_obj_tlv_t *)tptr;
+ vqp_obj_type = EXTRACT_32BITS(vqp_obj_tlv->obj_type);
+ vqp_obj_len = EXTRACT_16BITS(vqp_obj_tlv->obj_length);
+ tptr+=sizeof(struct vqp_obj_tlv_t);
+ tlen-=sizeof(struct vqp_obj_tlv_t);
+
+ printf("\n\t %s Object (0x%08x), length %u, value: ",
+ tok2str(vqp_obj_values, "Unknown", vqp_obj_type),
+ vqp_obj_type, vqp_obj_len);
+
+ /* basic sanity check */
+ if (vqp_obj_type == 0 || vqp_obj_len ==0) {
+ return;
+ }
+
+ /* did we capture enough for fully decoding the object ? */
+ if (!TTEST2(*tptr, vqp_obj_len))
+ goto trunc;
+
+ switch(vqp_obj_type) {
+ case VQP_OBJ_IP_ADDRESS:
+ printf("%s (0x%08x)", ipaddr_string(tptr), EXTRACT_32BITS(tptr));
+ break;
+ /* those objects have similar semantics - fall through */
+ case VQP_OBJ_PORT_NAME:
+ case VQP_OBJ_VLAN_NAME:
+ case VQP_OBJ_VTP_DOMAIN:
+ case VQP_OBJ_ETHERNET_PKT:
+ safeputs((const char *)tptr, vqp_obj_len);
+ break;
+ /* those objects have similar semantics - fall through */
+ case VQP_OBJ_MAC_ADDRESS:
+ case VQP_OBJ_MAC_NULL:
+ printf("%s", etheraddr_string(tptr));
+ break;
+ default:
+ if (vflag <= 1)
+ print_unknown_data(tptr, "\n\t ", vqp_obj_len);
+ break;
+ }
+ tptr += vqp_obj_len;
+ tlen -= vqp_obj_len;
+ nitems--;
+ }
+ return;
+trunc:
+ printf("\n\t[|VQP]");
+}
diff --git a/contrib/tcpdump/print-vrrp.c b/contrib/tcpdump/print-vrrp.c
index 1e87a50..899542d 100644
--- a/contrib/tcpdump/print-vrrp.c
+++ b/contrib/tcpdump/print-vrrp.c
@@ -25,7 +25,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-vrrp.c,v 1.9.2.1 2005/05/06 07:57:20 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-vrrp.c,v 1.10 2005-05-06 07:56:54 guy Exp $";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-vtp.c b/contrib/tcpdump/print-vtp.c
new file mode 100644
index 0000000..7631c6f
--- /dev/null
+++ b/contrib/tcpdump/print-vtp.c
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 1998-2007 The TCPDUMP project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ * VLAN TRUNKING PROTOCOL (VTP)
+ *
+ * Reference documentation:
+ * http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml
+ * http://www.cisco.com/warp/public/473/21.html
+ * http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
+ *
+ * Original code ode by Carles Kishimoto <carles.kishimoto@gmail.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tcpdump-stdinc.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "interface.h"
+#include "addrtoname.h"
+#include "extract.h"
+#include "nlpid.h"
+
+#define VTP_HEADER_LEN 36
+#define VTP_DOMAIN_NAME_LEN 32
+#define VTP_MD5_DIGEST_LEN 16
+#define VTP_UPDATE_TIMESTAMP_LEN 12
+#define VTP_VLAN_INFO_OFFSET 12
+
+#define VTP_SUMMARY_ADV 0x01
+#define VTP_SUBSET_ADV 0x02
+#define VTP_ADV_REQUEST 0x03
+#define VTP_JOIN_MESSAGE 0x04
+
+struct vtp_vlan_ {
+ u_int8_t len;
+ u_int8_t status;
+ u_int8_t type;
+ u_int8_t name_len;
+ u_int16_t vlanid;
+ u_int16_t mtu;
+ u_int32_t index;
+};
+
+static struct tok vtp_message_type_values[] = {
+ { VTP_SUMMARY_ADV, "Summary advertisement"},
+ { VTP_SUBSET_ADV, "Subset advertisement"},
+ { VTP_ADV_REQUEST, "Advertisement request"},
+ { VTP_JOIN_MESSAGE, "Join message"},
+ { 0, NULL }
+};
+
+static struct tok vtp_header_values[] = {
+ { 0x01, "Followers"}, /* On Summary advertisement, 3rd byte is Followers */
+ { 0x02, "Seq number"}, /* On Subset advertisement, 3rd byte is Sequence number */
+ { 0x03, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */
+ { 0x04, "Rsvd"}, /* On Adver. requests 3rd byte is Rsvd */
+ { 0, NULL }
+};
+
+static struct tok vtp_vlan_type_values[] = {
+ { 0x01, "Ethernet"},
+ { 0x02, "FDDI"},
+ { 0x03, "TrCRF"},
+ { 0x04, "FDDI-net"},
+ { 0x05, "TrBRF"},
+ { 0, NULL }
+};
+
+static struct tok vtp_vlan_status[] = {
+ { 0x00, "Operational"},
+ { 0x01, "Suspended"},
+ { 0, NULL }
+};
+
+#define VTP_VLAN_SOURCE_ROUTING_RING_NUMBER 0x01
+#define VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER 0x02
+#define VTP_VLAN_STP_TYPE 0x03
+#define VTP_VLAN_PARENT_VLAN 0x04
+#define VTP_VLAN_TRANS_BRIDGED_VLAN 0x05
+#define VTP_VLAN_PRUNING 0x06
+#define VTP_VLAN_BRIDGE_TYPE 0x07
+#define VTP_VLAN_ARP_HOP_COUNT 0x08
+#define VTP_VLAN_STE_HOP_COUNT 0x09
+#define VTP_VLAN_BACKUP_CRF_MODE 0x0A
+
+static struct tok vtp_vlan_tlv_values[] = {
+ { VTP_VLAN_SOURCE_ROUTING_RING_NUMBER, "Source-Routing Ring Number TLV"},
+ { VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER, "Source-Routing Bridge Number TLV"},
+ { VTP_VLAN_STP_TYPE, "STP type TLV"},
+ { VTP_VLAN_PARENT_VLAN, "Parent VLAN TLV"},
+ { VTP_VLAN_TRANS_BRIDGED_VLAN, "Translationally bridged VLANs TLV"},
+ { VTP_VLAN_PRUNING, "Pruning TLV"},
+ { VTP_VLAN_BRIDGE_TYPE, "Bridge Type TLV"},
+ { VTP_VLAN_ARP_HOP_COUNT, "Max ARP Hop Count TLV"},
+ { VTP_VLAN_STE_HOP_COUNT, "Max STE Hop Count TLV"},
+ { VTP_VLAN_BACKUP_CRF_MODE, "Backup CRF Mode TLV"},
+ { 0, NULL }
+};
+
+static struct tok vtp_stp_type_values[] = {
+ { 1, "SRT"},
+ { 2, "SRB"},
+ { 3, "Auto"},
+ { 0, NULL }
+};
+
+void
+vtp_print (const u_char *pptr, u_int length)
+{
+ int type, len, tlv_len, tlv_value;
+ const u_char *tptr;
+ const struct vtp_vlan_ *vtp_vlan;
+
+ if (length < VTP_HEADER_LEN)
+ goto trunc;
+
+ tptr = pptr;
+
+ if (!TTEST2(*tptr, VTP_HEADER_LEN))
+ goto trunc;
+
+ type = *(tptr+1);
+ printf("VTPv%u, Message %s (0x%02x), length %u",
+ *tptr,
+ tok2str(vtp_message_type_values,"Unknown message type", type),
+ *(tptr+1),
+ length);
+
+ /* In non-verbose mode, just print version and message type */
+ if (vflag < 1) {
+ return;
+ }
+
+ /* verbose mode print all fields */
+ printf("\n\tDomain name: %s, %s: %u",
+ (tptr+4),
+ tok2str(vtp_header_values,"Unknown",*(tptr+1)),
+ *(tptr+2));
+
+ tptr += VTP_HEADER_LEN;
+
+ switch (type) {
+
+ case VTP_SUMMARY_ADV:
+
+ /*
+ * SUMMARY ADVERTISEMENT
+ *
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Version | Code | Followers | MmgtD Len |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Management Domain Name |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Configuration revision number |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Updater Identity IP address |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Update Timestamp (12 bytes) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | MD5 digest (16 bytes) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+ printf("\n\t Config Rev %x, Updater %s",
+ EXTRACT_32BITS(tptr),
+ ipaddr_string(tptr+4));
+ tptr += 8;
+ printf(", Timestamp 0x%08x 0x%08x 0x%08x",
+ EXTRACT_32BITS(tptr),
+ EXTRACT_32BITS(tptr + 4),
+ EXTRACT_32BITS(tptr + 8));
+ tptr += VTP_UPDATE_TIMESTAMP_LEN;
+ printf(", MD5 digest: %08x%08x%08x%08x",
+ EXTRACT_32BITS(tptr),
+ EXTRACT_32BITS(tptr + 4),
+ EXTRACT_32BITS(tptr + 8),
+ EXTRACT_32BITS(tptr + 12));
+ tptr += VTP_MD5_DIGEST_LEN;
+ break;
+
+ case VTP_SUBSET_ADV:
+
+ /*
+ * SUBSET ADVERTISEMENT
+ *
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Version | Code | Seq number | MmgtD Len |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Management Domain Name |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Configuration revision number |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | VLAN info field 1 |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | ................ |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | VLAN info field N |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+ printf(", Config Rev %x", EXTRACT_32BITS(tptr));
+
+ /*
+ * VLAN INFORMATION
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | V info len | Status | VLAN type | VLAN name len |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | ISL vlan id | MTU size |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | 802.10 index (SAID) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | VLAN name |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+ tptr += 4;
+ while (tptr < (pptr+length)) {
+
+ len = *tptr;
+ if (len == 0)
+ break;
+
+ if (!TTEST2(*tptr, len))
+ goto trunc;
+
+ vtp_vlan = (struct vtp_vlan_*)tptr;
+ printf("\n\tVLAN info status %s, type %s, VLAN-id %u, MTU %u, SAID 0x%08x, Name %s",
+ tok2str(vtp_vlan_status,"Unknown",vtp_vlan->status),
+ tok2str(vtp_vlan_type_values,"Unknown",vtp_vlan->type),
+ EXTRACT_16BITS(&vtp_vlan->vlanid),
+ EXTRACT_16BITS(&vtp_vlan->mtu),
+ EXTRACT_32BITS(&vtp_vlan->index),
+ (tptr + VTP_VLAN_INFO_OFFSET));
+
+ /*
+ * Vlan names are aligned to 32-bit boundaries.
+ */
+ len -= VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4);
+ tptr += VTP_VLAN_INFO_OFFSET + 4*((vtp_vlan->name_len + 3)/4);
+
+ /* TLV information follows */
+
+ while (len > 0) {
+
+ /*
+ * Cisco specs says 2 bytes for type + 2 bytes for length, take only 1
+ * See: http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.htm
+ */
+ type = *tptr;
+ tlv_len = *(tptr+1);
+
+ printf("\n\t\t%s (0x%04x) TLV",
+ tok2str(vtp_vlan_tlv_values, "Unknown", type),
+ type);
+
+ /*
+ * infinite loop check
+ */
+ if (type == 0 || tlv_len == 0) {
+ return;
+ }
+
+ if (!TTEST2(*tptr, tlv_len*2 +2))
+ goto trunc;
+
+ tlv_value = EXTRACT_16BITS(tptr+2);
+
+ switch (type) {
+ case VTP_VLAN_STE_HOP_COUNT:
+ printf(", %u", tlv_value);
+ break;
+
+ case VTP_VLAN_PRUNING:
+ printf(", %s (%u)",
+ tlv_value == 1 ? "Enabled" : "Disabled",
+ tlv_value);
+ break;
+
+ case VTP_VLAN_STP_TYPE:
+ printf(", %s (%u)",
+ tok2str(vtp_stp_type_values, "Unknown", tlv_value),
+ tlv_value);
+ break;
+
+ case VTP_VLAN_BRIDGE_TYPE:
+ printf(", %s (%u)",
+ tlv_value == 1 ? "SRB" : "SRT",
+ tlv_value);
+ break;
+
+ case VTP_VLAN_BACKUP_CRF_MODE:
+ printf(", %s (%u)",
+ tlv_value == 1 ? "Backup" : "Not backup",
+ tlv_value);
+ break;
+
+ /*
+ * FIXME those are the defined TLVs that lack a decoder
+ * you are welcome to contribute code ;-)
+ */
+
+ case VTP_VLAN_SOURCE_ROUTING_RING_NUMBER:
+ case VTP_VLAN_SOURCE_ROUTING_BRIDGE_NUMBER:
+ case VTP_VLAN_PARENT_VLAN:
+ case VTP_VLAN_TRANS_BRIDGED_VLAN:
+ case VTP_VLAN_ARP_HOP_COUNT:
+ default:
+ print_unknown_data(tptr, "\n\t\t ", 2 + tlv_len*2);
+ break;
+ }
+ len -= 2 + tlv_len*2;
+ tptr += 2 + tlv_len*2;
+ }
+ }
+ break;
+
+ case VTP_ADV_REQUEST:
+
+ /*
+ * ADVERTISEMENT REQUEST
+ *
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Version | Code | Reserved | MmgtD Len |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Management Domain Name |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Start value |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ */
+
+ printf("\n\tStart value: %u", EXTRACT_32BITS(tptr));
+ break;
+
+ case VTP_JOIN_MESSAGE:
+
+ /* FIXME - Could not find message format */
+ break;
+
+ default:
+ break;
+ }
+
+ return;
+
+ trunc:
+ printf("[|vtp]");
+}
+
+/*
+ * Local Variables:
+ * c-style: whitesmith
+ * c-basic-offset: 4
+ * End:
+ */
diff --git a/contrib/tcpdump/print-wb.c b/contrib/tcpdump/print-wb.c
index e28697a..3ae604f 100644
--- a/contrib/tcpdump/print-wb.c
+++ b/contrib/tcpdump/print-wb.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-wb.c,v 1.33 2004/03/24 04:06:28 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-wb.c,v 1.33 2004-03-24 04:06:28 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/print-zephyr.c b/contrib/tcpdump/print-zephyr.c
index 698faa2..7c52e65 100644
--- a/contrib/tcpdump/print-zephyr.c
+++ b/contrib/tcpdump/print-zephyr.c
@@ -22,7 +22,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-zephyr.c,v 1.8.2.1 2005/04/21 06:51:24 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-zephyr.c,v 1.10 2007-08-09 18:47:27 hannes Exp $";
#endif
#ifdef HAVE_CONFIG_H
@@ -140,6 +140,15 @@ zephyr_print(const u_char *cp, int length)
char *s;
int lose = 0;
+ /* squelch compiler warnings */
+
+ z.kind = 0;
+ z.class = 0;
+ z.inst = 0;
+ z.opcode = 0;
+ z.sender = 0;
+ z.recipient = 0;
+
#define PARSE_STRING \
s = parse_field(&parse, &parselen); \
if (!s) lose = 1;
diff --git a/contrib/tcpdump/route6d.h b/contrib/tcpdump/route6d.h
index ee00331..53953fd 100644
--- a/contrib/tcpdump/route6d.h
+++ b/contrib/tcpdump/route6d.h
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*/
/*
- * $Header: /tcpdump/master/tcpdump/route6d.h,v 1.5 2002/12/11 07:14:10 guy Exp $
+ * $Header: /tcpdump/master/tcpdump/route6d.h,v 1.5 2002-12-11 07:14:10 guy Exp $
*/
#define RIP6_VERSION 1
diff --git a/contrib/tcpdump/rpc_auth.h b/contrib/tcpdump/rpc_auth.h
index 2b8ddc1..0e5a1c1 100644
--- a/contrib/tcpdump/rpc_auth.h
+++ b/contrib/tcpdump/rpc_auth.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/rpc_auth.h,v 1.1.2.1 2005/04/27 21:44:07 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/rpc_auth.h,v 1.2 2005-04-27 21:43:48 guy Exp $ (LBL) */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -30,6 +30,7 @@
* from: @(#)auth.h 1.17 88/02/08 SMI
* from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC
* $FreeBSD$
+ * FreeBSD: src/include/rpc/auth.h,v 1.14.2.1 1999/08/29 14:39:02 peter Exp
*/
/*
diff --git a/contrib/tcpdump/rpc_msg.h b/contrib/tcpdump/rpc_msg.h
index 01185de..9c2770c 100644
--- a/contrib/tcpdump/rpc_msg.h
+++ b/contrib/tcpdump/rpc_msg.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/rpc_msg.h,v 1.1.2.1 2005/04/27 21:44:07 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/rpc_msg.h,v 1.2 2005-04-27 21:43:48 guy Exp $ (LBL) */
/*
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
* unrestricted use provided that this legend is included on all tape
@@ -30,6 +30,7 @@
* from: @(#)rpc_msg.h 1.7 86/07/16 SMI
* from: @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC
* $FreeBSD$
+ * FreeBSD: src/include/rpc/rpc_msg.h,v 1.11.2.1 1999/08/29 14:39:07 peter Exp
*/
/*
diff --git a/contrib/tcpdump/rx.h b/contrib/tcpdump/rx.h
index 1912e51..b79dd30 100644
--- a/contrib/tcpdump/rx.h
+++ b/contrib/tcpdump/rx.h
@@ -23,7 +23,7 @@
/*
* Rx protocol format
*
- * $Id: rx.h,v 1.8 2002/12/11 07:14:11 guy Exp $
+ * $Id: rx.h,v 1.8 2002-12-11 07:14:11 guy Exp $
*/
#define FS_RX_PORT 7000
diff --git a/contrib/tcpdump/sctpConstants.h b/contrib/tcpdump/sctpConstants.h
index f70226b..ac28a15 100644
--- a/contrib/tcpdump/sctpConstants.h
+++ b/contrib/tcpdump/sctpConstants.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/sctpConstants.h,v 1.4 2003/06/03 23:49:23 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/sctpConstants.h,v 1.4 2003-06-03 23:49:23 guy Exp $ (LBL) */
/* SCTP reference Implementation Copyright (C) 1999 Cisco And Motorola
*
diff --git a/contrib/tcpdump/sctpHeader.h b/contrib/tcpdump/sctpHeader.h
index 3b26094..63f30b5 100644
--- a/contrib/tcpdump/sctpHeader.h
+++ b/contrib/tcpdump/sctpHeader.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/sctpHeader.h,v 1.6 2002/12/11 07:14:11 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/sctpHeader.h,v 1.6 2002-12-11 07:14:11 guy Exp $ (LBL) */
/* SCTP reference Implementation Copyright (C) 1999 Cisco And Motorola
*
diff --git a/contrib/tcpdump/setsignal.c b/contrib/tcpdump/setsignal.c
index dbb8678..a4b59ce 100644
--- a/contrib/tcpdump/setsignal.c
+++ b/contrib/tcpdump/setsignal.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/setsignal.c,v 1.11 2003/11/16 09:36:42 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/setsignal.c,v 1.11 2003-11-16 09:36:42 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/tcpdump/setsignal.h b/contrib/tcpdump/setsignal.h
index a7fb2a7..cc8e86c 100644
--- a/contrib/tcpdump/setsignal.h
+++ b/contrib/tcpdump/setsignal.h
@@ -18,7 +18,7 @@
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/setsignal.h,v 1.2.1.1 1999/10/07 23:47:13 mcr Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/setsignal.h,v 1.2.1.1 1999-10-07 23:47:13 mcr Exp $ (LBL)
*/
#ifndef setsignal_h
#define setsignal_h
diff --git a/contrib/tcpdump/slcompress.h b/contrib/tcpdump/slcompress.h
index d8a596c..d10243a 100644
--- a/contrib/tcpdump/slcompress.h
+++ b/contrib/tcpdump/slcompress.h
@@ -1,7 +1,7 @@
/*
* Definitions for tcp compression routines.
*
- * @(#) $Header: /tcpdump/master/tcpdump/slcompress.h,v 1.2 2000/10/09 02:03:44 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/slcompress.h,v 1.2 2000-10-09 02:03:44 guy Exp $ (LBL)
*
* Copyright (c) 1989, 1990, 1992, 1993 Regents of the University of
* California. All rights reserved.
diff --git a/contrib/tcpdump/slip.h b/contrib/tcpdump/slip.h
index e64f301..aa6402c 100644
--- a/contrib/tcpdump/slip.h
+++ b/contrib/tcpdump/slip.h
@@ -2,7 +2,7 @@
* Definitions that user level programs might need to know to interact
* with serial line IP (slip) lines.
*
- * @(#) $Header: /tcpdump/master/tcpdump/slip.h,v 1.1 2000/10/09 01:53:21 guy Exp $
+ * @(#) $Header: /tcpdump/master/tcpdump/slip.h,v 1.1 2000-10-09 01:53:21 guy Exp $
*
* Copyright (c) 1990 Regents of the University of California.
* All rights reserved.
diff --git a/contrib/tcpdump/sll.h b/contrib/tcpdump/sll.h
index 693f05e..bad31e2 100644
--- a/contrib/tcpdump/sll.h
+++ b/contrib/tcpdump/sll.h
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Header: /tcpdump/master/tcpdump/sll.h,v 1.7 2002/12/11 07:14:11 guy Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/sll.h,v 1.7.6.1 2008-05-30 01:38:21 guy Exp $ (LBL)
*/
/*
@@ -64,8 +64,8 @@
* DO NOT change the layout of this structure, or change any of the
* LINUX_SLL_ values below. If you must change the link-layer header
* for a "cooked" Linux capture, introduce a new DLT_ type (ask
- * "tcpdump-workers@tcpdump.org" for one, so that you don't give it a
- * value that collides with a value already being used), and use the
+ * "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it
+ * a value that collides with a value already being used), and use the
* new header in captures of that type, so that programs that can
* handle DLT_LINUX_SLL captures will continue to handle them correctly
* without any change, and so that capture files with different headers
diff --git a/contrib/tcpdump/smb.h b/contrib/tcpdump/smb.h
index bb05227..8eeb303 100644
--- a/contrib/tcpdump/smb.h
+++ b/contrib/tcpdump/smb.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/smb.h,v 1.9 2004/12/28 22:29:44 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/smb.h,v 1.9 2004-12-28 22:29:44 guy Exp $ (LBL) */
/*
* Copyright (C) Andrew Tridgell 1995-1999
*
diff --git a/contrib/tcpdump/smbutil.c b/contrib/tcpdump/smbutil.c
index 86bcb4c..ba7ec31 100644
--- a/contrib/tcpdump/smbutil.c
+++ b/contrib/tcpdump/smbutil.c
@@ -12,7 +12,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/smbutil.c,v 1.36.2.3 2007/07/15 19:08:25 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/smbutil.c,v 1.39 2007-07-15 19:07:39 guy Exp $";
#endif
#include <tcpdump-stdinc.h>
diff --git a/contrib/tcpdump/strcasecmp.c b/contrib/tcpdump/strcasecmp.c
index aa6d007..f19ccf5 100644
--- a/contrib/tcpdump/strcasecmp.c
+++ b/contrib/tcpdump/strcasecmp.c
@@ -16,7 +16,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/strcasecmp.c,v 1.6 2003/11/16 09:36:43 guy Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/strcasecmp.c,v 1.6 2003-11-16 09:36:43 guy Exp $";
#endif
#include <tcpdump-stdinc.h>
diff --git a/contrib/tcpdump/tcp.h b/contrib/tcpdump/tcp.h
index 5934cd6..db7dd44 100644
--- a/contrib/tcpdump/tcp.h
+++ b/contrib/tcpdump/tcp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/tcp.h,v 1.11.2.1 2005/11/29 09:09:26 hannes Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/tcp.h,v 1.13.2.1 2007-12-09 00:31:35 guy Exp $ (LBL) */
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
@@ -45,21 +45,25 @@ struct tcphdr {
tcp_seq th_seq; /* sequence number */
tcp_seq th_ack; /* acknowledgement number */
u_int8_t th_offx2; /* data offset, rsvd */
-#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
u_int8_t th_flags;
-#define TH_FIN 0x01
-#define TH_SYN 0x02
-#define TH_RST 0x04
-#define TH_PUSH 0x08
-#define TH_ACK 0x10
-#define TH_URG 0x20
-#define TH_ECNECHO 0x40 /* ECN Echo */
-#define TH_CWR 0x80 /* ECN Cwnd Reduced */
u_int16_t th_win; /* window */
u_int16_t th_sum; /* checksum */
u_int16_t th_urp; /* urgent pointer */
};
+#define TH_OFF(th) (((th)->th_offx2 & 0xf0) >> 4)
+
+/* TCP flags */
+#define TH_FIN 0x01
+#define TH_SYN 0x02
+#define TH_RST 0x04
+#define TH_PUSH 0x08
+#define TH_ACK 0x10
+#define TH_URG 0x20
+#define TH_ECNECHO 0x40 /* ECN Echo */
+#define TH_CWR 0x80 /* ECN Cwnd Reduced */
+
+
#define TCPOPT_EOL 0
#define TCPOPT_NOP 1
#define TCPOPT_MAXSEG 2
@@ -82,3 +86,23 @@ struct tcphdr {
#define TCPOPT_TSTAMP_HDR \
(TCPOPT_NOP<<24|TCPOPT_NOP<<16|TCPOPT_TIMESTAMP<<8|TCPOLEN_TIMESTAMP)
+
+#ifndef TELNET_PORT
+#define TELNET_PORT 23
+#endif
+#ifndef BGP_PORT
+#define BGP_PORT 179
+#endif
+#define NETBIOS_SSN_PORT 139
+#ifndef PPTP_PORT
+#define PPTP_PORT 1723
+#endif
+#define BEEP_PORT 10288
+#ifndef NFS_PORT
+#define NFS_PORT 2049
+#endif
+#define MSDP_PORT 639
+#define LDP_PORT 646
+#ifndef SMB_PORT
+#define SMB_PORT 445
+#endif
diff --git a/contrib/tcpdump/tcpdump-stdinc.h b/contrib/tcpdump/tcpdump-stdinc.h
index 4e599c3..5b10ef8 100644
--- a/contrib/tcpdump/tcpdump-stdinc.h
+++ b/contrib/tcpdump/tcpdump-stdinc.h
@@ -30,7 +30,7 @@
*
*
* $FreeBSD$
- * @(#) $Header: /tcpdump/master/tcpdump/tcpdump-stdinc.h,v 1.12.2.5 2006/06/23 02:07:27 hannes Exp $ (LBL)
+ * @(#) $Header: /tcpdump/master/tcpdump/tcpdump-stdinc.h,v 1.17 2006-05-19 17:55:34 hannes Exp $ (LBL)
*/
/*
diff --git a/contrib/tcpdump/tcpdump.1 b/contrib/tcpdump/tcpdump.1
index 8b70af2..1635ff6 100644
--- a/contrib/tcpdump/tcpdump.1
+++ b/contrib/tcpdump/tcpdump.1
@@ -1,4 +1,4 @@
-.\" @(#) $Header: /tcpdump/master/tcpdump/tcpdump.1,v 1.167.2.11 2007/06/15 20:13:49 guy Exp $ (LBL)
+.\" @(#) $Header: /tcpdump/master/tcpdump/tcpdump.1,v 1.185.2.6 2008-05-30 01:38:21 guy Exp $ (LBL)
.\"
.\" $NetBSD: tcpdump.8,v 1.9 2003/03/31 00:18:17 perry Exp $
.\"
@@ -24,14 +24,17 @@
.\"
.\" $FreeBSD$
.\"
-.TH TCPDUMP 1 "18 April 2005"
+.TH TCPDUMP 1 "07 January 2008"
.SH NAME
tcpdump \- dump traffic on a network
.SH SYNOPSIS
.na
.B tcpdump
[
-.B \-AdDeflLnNOpqRStuUvxX
+.B \-AdDefIKlLnNOpqRStuUvxX
+] [
+.B \-B
+.I buffer_size
] [
.B \-c
.I count
@@ -42,6 +45,9 @@ tcpdump \- dump traffic on a network
.B \-C
.I file_size
] [
+.B \-G
+.I rotate_seconds
+] [
.B \-F
.I file
]
@@ -96,6 +102,10 @@ tcpdump \- dump traffic on a network
.I datalinktype
]
[
+.B \-z
+.I postrotate-command
+]
+[
.B \-Z
.I user
]
@@ -178,87 +188,19 @@ default, so you must set it with
in order to use it) and will continue capturing packets.
.LP
Reading packets from a network interface may require that you have
-special privileges:
-.TP
-.B Under SunOS 3.x or 4.x with NIT or BPF:
-You must have read access to
-.I /dev/nit
-or
-.IR /dev/bpf* .
-.TP
-.B Under Solaris with DLPI:
-You must have read/write access to the network pseudo device, e.g.
-.IR /dev/le .
-On at least some versions of Solaris, however, this is not sufficient to
-allow
-.I tcpdump
-to capture in promiscuous mode; on those versions of Solaris, you must
-be root, or
-.I tcpdump
-must be installed setuid to root, in order to capture in promiscuous
-mode. Note that, on many (perhaps all) interfaces, if you don't capture
-in promiscuous mode, you will not see any outgoing packets, so a capture
-not done in promiscuous mode may not be very useful.
-.TP
-.B Under HP-UX with DLPI:
-You must be root or
-.I tcpdump
-must be installed setuid to root.
-.TP
-.B Under IRIX with snoop:
-You must be root or
-.I tcpdump
-must be installed setuid to root.
-.TP
-.B Under Linux:
-You must be root or
-.I tcpdump
-must be installed setuid to root (unless your distribution has a kernel
-that supports capability bits such as CAP_NET_RAW and code to allow
-those capability bits to be given to particular accounts and to cause
-those bits to be set on a user's initial processes when they log in, in
-which case you must have CAP_NET_RAW in order to capture and
-CAP_NET_ADMIN to enumerate network devices with, for example, the
-.B \-D
-flag).
-.TP
-.B Under ULTRIX and Digital UNIX/Tru64 UNIX:
-Any user may capture network traffic with
-.IR tcpdump .
-However, no user (not even the super-user) can capture in promiscuous
-mode on an interface unless the super-user has enabled promiscuous-mode
-operation on that interface using
-.IR pfconfig (8),
-and no user (not even the super-user) can capture unicast traffic
-received by or sent by the machine on an interface unless the super-user
-has enabled copy-all-mode operation on that interface using
-.IR pfconfig ,
-so
-.I useful
-packet capture on an interface probably requires that either
-promiscuous-mode or copy-all-mode operation, or both modes of
-operation, be enabled on that interface.
-.TP
-.B Under BSD (this includes Mac OS X):
-You must have read access to
-.I /dev/bpf*
-on systems that don't have a cloning BPF device, or to
-.I /dev/bpf
-on systems that do.
-On BSDs with a devfs (this includes Mac OS X), this might involve more
-than just having somebody with super-user access setting the ownership
-or permissions on the BPF devices - it might involve configuring devfs
-to set the ownership or permissions every time the system is booted,
-if the system even supports that; if it doesn't support that, you might
-have to find some other way to make that happen at boot time.
-.LP
-Reading a saved packet file doesn't require special privileges.
+special privileges; see the
+.B pcap (3PCAP)
+man page for details. Reading a saved packet file doesn't require
+special privileges.
.SH OPTIONS
.TP
.B \-A
Print each packet (minus its link level header) in ASCII. Handy for
capturing web pages.
.TP
+.B \-B
+Set the operating system capture buffer size to \fIbuffer_size\fP.
+.TP
.B \-c
Exit after receiving \fIcount\fP packets.
.TP
@@ -366,6 +308,20 @@ correctly.
Use \fIfile\fP as input for the filter expression.
An additional expression given on the command line is ignored.
.TP
+.B \-G
+If specified, rotates the dump file specified with the
+.B \-w
+option every \fIrotate_seconds\fP seconds.
+Savefiles will have the name specified by
+.B \-w
+which should include a time format as defined by
+.BR strftime (3).
+If no time format is specified, each new file will overwrite the previous.
+.IP
+If used in conjunction with the
+.B \-C
+option, filenames will take the form of `\fIfile\fP<count>'.
+.TP
.B \-i
Listen on \fIinterface\fP.
If unspecified, \fItcpdump\fP searches the system interface list for the
@@ -385,6 +341,22 @@ used as the
.I interface
argument.
.TP
+.B \-I
+Put the interface in "monitor mode"; this is supported only on IEEE
+802.11 Wi-Fi interfaces, and supported only on some operating systems.
+.IP
+Note that in monitor mode the adapter might disassociate from the
+network with which it's associated, so that you will not be able to use
+any wireless networks with that adapter. This could prevent accessing
+files on a network server, or resolving host names or network addresses,
+if you are capturing in monitor mode and are not connected to another
+network with another adapter.
+.TP
+.B \-K
+Don't attempt to verify TCP checksums. This is useful for interfaces
+that perform the TCP checksum calculation in hardware; otherwise,
+all outgoing TCP checksums will be flagged as bad.
+.TP
.B \-l
Make stdout line buffered.
Useful if you want to see the data
@@ -488,12 +460,16 @@ and
Print an unformatted timestamp on each dump line.
.TP
.B \-ttt
-Print a delta (in micro-seconds) between current and previous line
+Print a delta (micro-second resolution) between current and previous line
on each dump line.
.TP
.B \-tttt
Print a timestamp in default format proceeded by date on each dump line.
.TP
+.B \-ttttt
+Print a delta (micro-second resolution) between current and first line
+on each dump line.
+.TP
.B \-u
Print undecoded NFS handles.
.TP
@@ -554,6 +530,13 @@ from the beginning, thus creating a 'rotating' buffer.
In addition, it will name
the files with enough leading 0s to support the maximum number of
files, allowing them to sort correctly.
+.IP
+Used in conjunction with the
+.B \-G
+option, this will limit the number of rotated dump files that get
+created, exiting with status 0 when reaching the limit. If used with
+.B \-C
+as well, the behavior will result in cyclical files per timeslice.
.TP
.B \-x
When parsing and printing,
@@ -589,6 +572,31 @@ its link level header, in hex and ASCII.
.B \-y
Set the data link type to use while capturing packets to \fIdatalinktype\fP.
.TP
+.B \-z
+Used in conjunction with the
+.B -C
+or
+.B -G
+options, this will make
+.I tcpdump
+run "
+.I command file
+" where
+.I file
+is the savefile being closed after each rotation. For example, specifying
+.B \-z gzip
+or
+.B \-z bzip2
+will compress each savefile using gzip or bzip2.
+.IP
+Note that tcpdump will run the command in parallel to the capture, using
+the lowest priority so that this doesn't disturb the capture process.
+.IP
+And in case you would like to use a command that itself takes flags or
+different arguments, you can always write a shell script that will take the
+savefile name as the only argument, make the flags & arguments arrangements
+and execute the command that you want.
+.TP
.B \-Z
Drops privileges (if root) and changes user ID to
.I user
@@ -604,687 +612,8 @@ is given, all packets on the net will be dumped.
Otherwise,
only packets for which \fIexpression\fP is `true' will be dumped.
.LP
-The \fIexpression\fP consists of one or more
-.I primitives.
-Primitives usually consist of an
-.I id
-(name or number) preceded by one or more qualifiers.
-There are three
-different kinds of qualifier:
-.IP \fItype\fP
-qualifiers say what kind of thing the id name or number refers to.
-Possible types are
-.BR host ,
-.B net ,
-.B port
-and
-.BR portrange .
-E.g., `host foo', `net 128.3', `port 20', `portrange 6000-6008'.
-If there is no type
-qualifier,
-.B host
-is assumed.
-.IP \fIdir\fP
-qualifiers specify a particular transfer direction to and/or from
-.IR id .
-Possible directions are
-.BR src ,
-.BR dst ,
-.B "src or dst"
-and
-.B "src and"
-.BR dst .
-E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'.
-If
-there is no dir qualifier,
-.B "src or dst"
-is assumed.
-For some link layers, such as SLIP and the ``cooked'' Linux capture mode
-used for the ``any'' device and for some other device types, the
-.B inbound
-and
-.B outbound
-qualifiers can be used to specify a desired direction.
-.IP \fIproto\fP
-qualifiers restrict the match to a particular protocol.
-Possible
-protos are:
-.BR ether ,
-.BR fddi ,
-.BR tr ,
-.BR wlan ,
-.BR ip ,
-.BR ip6 ,
-.BR arp ,
-.BR rarp ,
-.BR decnet ,
-.BR lat ,
-.BR sca ,
-.BR moprc ,
-.BR mopdl ,
-.BR iso ,
-.BR esis ,
-.BR isis ,
-.BR icmp ,
-.BR icmp6 ,
-.B tcp
-and
-.BR udp .
-E.g., `ether src foo', `arp net 128.3', `tcp port 21', `udp portrange
-7000-7009'.
-If there is
-no proto qualifier, all protocols consistent with the type are
-assumed.
-E.g., `src foo' means `(ip or arp or rarp) src foo'
-(except the latter is not legal syntax), `net bar' means `(ip or
-arp or rarp) net bar' and `port 53' means `(tcp or udp) port 53'.
-.LP
-[`fddi' is actually an alias for `ether'; the parser treats them
-identically as meaning ``the data link level used on the specified
-network interface.'' FDDI headers contain Ethernet-like source
-and destination addresses, and often contain Ethernet-like packet
-types, so you can filter on these FDDI fields just as with the
-analogous Ethernet fields.
-FDDI headers also contain other fields,
-but you cannot name them explicitly in a filter expression.
-.LP
-Similarly, `tr' and `wlan' are aliases for `ether'; the previous
-paragraph's statements about FDDI headers also apply to Token Ring
-and 802.11 wireless LAN headers. For 802.11 headers, the destination
-address is the DA field and the source address is the SA field; the
-BSSID, RA, and TA fields aren't tested.]
-.LP
-In addition to the above, there are some special `primitive' keywords
-that don't follow the pattern:
-.BR gateway ,
-.BR broadcast ,
-.BR less ,
-.B greater
-and arithmetic expressions.
-All of these are described below.
-.LP
-More complex filter expressions are built up by using the words
-.BR and ,
-.B or
-and
-.B not
-to combine primitives.
-E.g., `host foo and not port ftp and not port ftp-data'.
-To save typing, identical qualifier lists can be omitted.
-E.g.,
-`tcp dst port ftp or ftp-data or domain' is exactly the same as
-`tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'.
-.LP
-Allowable primitives are:
-.IP "\fBdst host \fIhost\fR"
-True if the IPv4/v6 destination field of the packet is \fIhost\fP,
-which may be either an address or a name.
-.IP "\fBsrc host \fIhost\fR"
-True if the IPv4/v6 source field of the packet is \fIhost\fP.
-.IP "\fBhost \fIhost\fP
-True if either the IPv4/v6 source or destination of the packet is \fIhost\fP.
-.IP
-Any of the above host expressions can be prepended with the keywords,
-\fBip\fP, \fBarp\fP, \fBrarp\fP, or \fBip6\fP as in:
-.in +.5i
-.nf
-\fBip host \fIhost\fR
-.fi
-.in -.5i
-which is equivalent to:
-.in +.5i
-.nf
-\fBether proto \fI\\ip\fB and host \fIhost\fR
-.fi
-.in -.5i
-If \fIhost\fR is a name with multiple IP addresses, each address will
-be checked for a match.
-.IP "\fBether dst \fIehost\fP
-True if the Ethernet destination address is \fIehost\fP.
-\fIEhost\fP
-may be either a name from /etc/ethers or a number (see
-.IR ethers (3N)
-for numeric format).
-.IP "\fBether src \fIehost\fP
-True if the Ethernet source address is \fIehost\fP.
-.IP "\fBether host \fIehost\fP
-True if either the Ethernet source or destination address is \fIehost\fP.
-.IP "\fBgateway\fP \fIhost\fP
-True if the packet used \fIhost\fP as a gateway.
-I.e., the Ethernet
-source or destination address was \fIhost\fP but neither the IP source
-nor the IP destination was \fIhost\fP.
-\fIHost\fP must be a name and
-must be found both by the machine's host-name-to-IP-address resolution
-mechanisms (host name file, DNS, NIS, etc.) and by the machine's
-host-name-to-Ethernet-address resolution mechanism (/etc/ethers, etc.).
-(An equivalent expression is
-.in +.5i
-.nf
-\fBether host \fIehost \fBand not host \fIhost\fR
-.fi
-.in -.5i
-which can be used with either names or numbers for \fIhost / ehost\fP.)
-This syntax does not work in IPv6-enabled configuration at this moment.
-.IP "\fBdst net \fInet\fR"
-True if the IPv4/v6 destination address of the packet has a network
-number of \fInet\fP.
-\fINet\fP may be either a name from the networks database
-(/etc/networks, etc.) or a network number.
-An IPv4 network number can be written as a dotted quad (e.g., 192.168.1.0),
-dotted triple (e.g., 192.168.1), dotted pair (e.g, 172.16), or single
-number (e.g., 10); the netmask is 255.255.255.255 for a dotted quad
-(which means that it's really a host match), 255.255.255.0 for a dotted
-triple, 255.255.0.0 for a dotted pair, or 255.0.0.0 for a single number.
-An IPv6 network number must be written out fully; the netmask is
-ff:ff:ff:ff:ff:ff:ff:ff, so IPv6 "network" matches are really always
-host matches, and a network match requires a netmask length.
-.IP "\fBsrc net \fInet\fR"
-True if the IPv4/v6 source address of the packet has a network
-number of \fInet\fP.
-.IP "\fBnet \fInet\fR"
-True if either the IPv4/v6 source or destination address of the packet has a network
-number of \fInet\fP.
-.IP "\fBnet \fInet\fR \fBmask \fInetmask\fR"
-True if the IPv4 address matches \fInet\fR with the specific \fInetmask\fR.
-May be qualified with \fBsrc\fR or \fBdst\fR.
-Note that this syntax is not valid for IPv6 \fInet\fR.
-.IP "\fBnet \fInet\fR/\fIlen\fR"
-True if the IPv4/v6 address matches \fInet\fR with a netmask \fIlen\fR
-bits wide.
-May be qualified with \fBsrc\fR or \fBdst\fR.
-.IP "\fBdst port \fIport\fR"
-True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
-destination port value of \fIport\fP.
-The \fIport\fP can be a number or a name used in /etc/services (see
-.IR tcp (4P)
-and
-.IR udp (4P)).
-If a name is used, both the port
-number and protocol are checked.
-If a number or ambiguous name is used,
-only the port number is checked (e.g., \fBdst port 513\fR will print both
-tcp/login traffic and udp/who traffic, and \fBport domain\fR will print
-both tcp/domain and udp/domain traffic).
-.IP "\fBsrc port \fIport\fR"
-True if the packet has a source port value of \fIport\fP.
-.IP "\fBport \fIport\fR"
-True if either the source or destination port of the packet is \fIport\fP.
-.IP "\fBdst portrange \fIport1\fB-\fIport2\fR"
-True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
-destination port value between \fIport1\fP and \fIport2\fP.
-.I port1
-and
-.I port2
-are interpreted in the same fashion as the
-.I port
-parameter for
-.BR port .
-.IP "\fBsrc portrange \fIport1\fB-\fIport2\fR"
-True if the packet has a source port value between \fIport1\fP and
-\fIport2\fP.
-.IP "\fBportrange \fIport1\fB-\fIport2\fR"
-True if either the source or destination port of the packet is between
-\fIport1\fP and \fIport2\fP.
-.IP
-Any of the above port or port range expressions can be prepended with
-the keywords, \fBtcp\fP or \fBudp\fP, as in:
-.in +.5i
-.nf
-\fBtcp src port \fIport\fR
-.fi
-.in -.5i
-which matches only tcp packets whose source port is \fIport\fP.
-.IP "\fBless \fIlength\fR"
-True if the packet has a length less than or equal to \fIlength\fP.
-This is equivalent to:
-.in +.5i
-.nf
-\fBlen <= \fIlength\fP.
-.fi
-.in -.5i
-.IP "\fBgreater \fIlength\fR"
-True if the packet has a length greater than or equal to \fIlength\fP.
-This is equivalent to:
-.in +.5i
-.nf
-\fBlen >= \fIlength\fP.
-.fi
-.in -.5i
-.IP "\fBip proto \fIprotocol\fR"
-True if the packet is an IPv4 packet (see
-.IR ip (4P))
-of protocol type \fIprotocol\fP.
-\fIProtocol\fP can be a number or one of the names
-\fBicmp\fP, \fBicmp6\fP, \fBigmp\fP, \fBigrp\fP, \fBpim\fP, \fBah\fP,
-\fBesp\fP, \fBvrrp\fP, \fBudp\fP, or \fBtcp\fP.
-Note that the identifiers \fBtcp\fP, \fBudp\fP, and \fBicmp\fP are also
-keywords and must be escaped via backslash (\\), which is \\\\ in the C-shell.
-Note that this primitive does not chase the protocol header chain.
-.IP "\fBip6 proto \fIprotocol\fR"
-True if the packet is an IPv6 packet of protocol type \fIprotocol\fP.
-Note that this primitive does not chase the protocol header chain.
-.IP "\fBip6 protochain \fIprotocol\fR"
-True if the packet is IPv6 packet,
-and contains protocol header with type \fIprotocol\fR
-in its protocol header chain.
-For example,
-.in +.5i
-.nf
-\fBip6 protochain 6\fR
-.fi
-.in -.5i
-matches any IPv6 packet with TCP protocol header in the protocol header chain.
-The packet may contain, for example,
-authentication header, routing header, or hop-by-hop option header,
-between IPv6 header and TCP header.
-The BPF code emitted by this primitive is complex and
-cannot be optimized by BPF optimizer code in \fItcpdump\fP,
-so this can be somewhat slow.
-.IP "\fBip protochain \fIprotocol\fR"
-Equivalent to \fBip6 protochain \fIprotocol\fR, but this is for IPv4.
-.IP "\fBether broadcast\fR"
-True if the packet is an Ethernet broadcast packet.
-The \fIether\fP
-keyword is optional.
-.IP "\fBip broadcast\fR"
-True if the packet is an IPv4 broadcast packet.
-It checks for both the all-zeroes and all-ones broadcast conventions,
-and looks up the subnet mask on the interface on which the capture is
-being done.
-.IP
-If the subnet mask of the interface on which the capture is being done
-is not available, either because the interface on which capture is being
-done has no netmask or because the capture is being done on the Linux
-"any" interface, which can capture on more than one interface, this
-check will not work correctly.
-.IP "\fBether multicast\fR"
-True if the packet is an Ethernet multicast packet.
-The \fBether\fP
-keyword is optional.
-This is shorthand for `\fBether[0] & 1 != 0\fP'.
-.IP "\fBip multicast\fR"
-True if the packet is an IPv4 multicast packet.
-.IP "\fBip6 multicast\fR"
-True if the packet is an IPv6 multicast packet.
-.IP "\fBether proto \fIprotocol\fR"
-True if the packet is of ether type \fIprotocol\fR.
-\fIProtocol\fP can be a number or one of the names
-\fBip\fP, \fBip6\fP, \fBarp\fP, \fBrarp\fP, \fBatalk\fP, \fBaarp\fP,
-\fBdecnet\fP, \fBsca\fP, \fBlat\fP, \fBmopdl\fP, \fBmoprc\fP,
-\fBiso\fP, \fBstp\fP, \fBipx\fP, or \fBnetbeui\fP.
-Note these identifiers are also keywords
-and must be escaped via backslash (\\).
-.IP
-[In the case of FDDI (e.g., `\fBfddi protocol arp\fR'), Token Ring
-(e.g., `\fBtr protocol arp\fR'), and IEEE 802.11 wireless LANS (e.g.,
-`\fBwlan protocol arp\fR'), for most of those protocols, the
-protocol identification comes from the 802.2 Logical Link Control (LLC)
-header, which is usually layered on top of the FDDI, Token Ring, or
-802.11 header.
-.IP
-When filtering for most protocol identifiers on FDDI, Token Ring, or
-802.11, \fItcpdump\fR checks only the protocol ID field of an LLC header
-in so-called SNAP format with an Organizational Unit Identifier (OUI) of
-0x000000, for encapsulated Ethernet; it doesn't check whether the packet
-is in SNAP format with an OUI of 0x000000.
-The exceptions are:
-.RS
-.TP
-\fBiso\fP
-\fItcpdump\fR checks the DSAP (Destination Service Access Point) and
-SSAP (Source Service Access Point) fields of the LLC header;
-.TP
-\fBstp\fP and \fBnetbeui\fP
-\fItcpdump\fR checks the DSAP of the LLC header;
-.TP
-\fBatalk\fP
-\fItcpdump\fR checks for a SNAP-format packet with an OUI of 0x080007
-and the AppleTalk etype.
-.RE
-.IP
-In the case of Ethernet, \fItcpdump\fR checks the Ethernet type field
-for most of those protocols. The exceptions are:
-.RS
-.TP
-\fBiso\fP, \fBstp\fP, and \fBnetbeui\fP
-\fItcpdump\fR checks for an 802.3 frame and then checks the LLC header as
-it does for FDDI, Token Ring, and 802.11;
-.TP
-\fBatalk\fP
-\fItcpdump\fR checks both for the AppleTalk etype in an Ethernet frame and
-for a SNAP-format packet as it does for FDDI, Token Ring, and 802.11;
-.TP
-\fBaarp\fP
-\fItcpdump\fR checks for the AppleTalk ARP etype in either an Ethernet
-frame or an 802.2 SNAP frame with an OUI of 0x000000;
-.TP
-\fBipx\fP
-\fItcpdump\fR checks for the IPX etype in an Ethernet frame, the IPX
-DSAP in the LLC header, the 802.3-with-no-LLC-header encapsulation of
-IPX, and the IPX etype in a SNAP frame.
-.RE
-.IP "\fBdecnet src \fIhost\fR"
-True if the DECNET source address is
-.IR host ,
-which may be an address of the form ``10.123'', or a DECNET host
-name.
-[DECNET host name support is only available on ULTRIX systems
-that are configured to run DECNET.]
-.IP "\fBdecnet dst \fIhost\fR"
-True if the DECNET destination address is
-.IR host .
-.IP "\fBdecnet host \fIhost\fR"
-True if either the DECNET source or destination address is
-.IR host .
-.IP "\fBifname \fIinterface\fR"
-True if the packet was logged as coming from the specified interface (applies
-only to packets logged by OpenBSD's
-.BR pf (4)).
-.IP "\fBon \fIinterface\fR"
-Synonymous with the
-.B ifname
-modifier.
-.IP "\fBrnr \fInum\fR"
-True if the packet was logged as matching the specified PF rule number
-(applies only to packets logged by OpenBSD's
-.BR pf (4)).
-.IP "\fBrulenum \fInum\fR"
-Synonomous with the
-.B rnr
-modifier.
-.IP "\fBreason \fIcode\fR"
-True if the packet was logged with the specified PF reason code. The known
-codes are:
-.BR match ,
-.BR bad-offset ,
-.BR fragment ,
-.BR short ,
-.BR normalize ,
-and
-.B memory
-(applies only to packets logged by OpenBSD's
-.BR pf (4)).
-.IP "\fBrset \fIname\fR"
-True if the packet was logged as matching the specified PF ruleset
-name of an anchored ruleset (applies only to packets logged by
-.BR pf (4)).
-.IP "\fBruleset \fIname\fR"
-Synonomous with the
-.B rset
-modifier.
-.IP "\fBsrnr \fInum\fR"
-True if the packet was logged as matching the specified PF rule number
-of an anchored ruleset (applies only to packets logged by
-.BR pf (4)).
-.IP "\fBsubrulenum \fInum\fR"
-Synonomous with the
-.B srnr
-modifier.
-.IP "\fBaction \fIact\fR"
-True if PF took the specified action when the packet was logged. Known actions
-are:
-.B pass
-and
-.B block
-(applies only to packets logged by OpenBSD's
-.BR pf (4)).
-.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fInetbeui\fP"
-Abbreviations for:
-.in +.5i
-.nf
-\fBether proto \fIp\fR
-.fi
-.in -.5i
-where \fIp\fR is one of the above protocols.
-.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR"
-Abbreviations for:
-.in +.5i
-.nf
-\fBether proto \fIp\fR
-.fi
-.in -.5i
-where \fIp\fR is one of the above protocols.
-Note that
-\fItcpdump\fP does not currently know how to parse these protocols.
-.IP "\fBvlan \fI[vlan_id]\fR"
-True if the packet is an IEEE 802.1Q VLAN packet.
-If \fI[vlan_id]\fR is specified, only true if the packet has the specified
-\fIvlan_id\fR.
-Note that the first \fBvlan\fR keyword encountered in \fIexpression\fR
-changes the decoding offsets for the remainder of \fIexpression\fR on
-the assumption that the packet is a VLAN packet. The \fBvlan
-\fI[vlan_id]\fR expression may be used more than once, to filter on VLAN
-hierarchies. Each use of that expression increments the filter offsets
-by 4.
-.IP
-For example:
-.in +.5i
-.nf
-\fBvlan 100 && vlan 200\fR
-.fi
-.in -.5i
-filters on VLAN 200 encapsulated within VLAN 100, and
-.in +.5i
-.nf
-\fBvlan && vlan 300 && ip\fR
-.fi
-.in -.5i
-filters IPv4 protocols encapsulated in VLAN 300 encapsulated within any
-higher order VLAN.
-.IP "\fBmpls \fI[label_num]\fR"
-True if the packet is an MPLS packet.
-If \fI[label_num]\fR is specified, only true is the packet has the specified
-\fIlabel_num\fR.
-Note that the first \fBmpls\fR keyword encountered in \fIexpression\fR
-changes the decoding offsets for the remainder of \fIexpression\fR on
-the assumption that the packet is a MPLS-encapsulated IP packet. The
-\fBmpls \fI[label_num]\fR expression may be used more than once, to
-filter on MPLS hierarchies. Each use of that expression increments the
-filter offsets by 4.
-.IP
-For example:
-.in +.5i
-.nf
-\fBmpls 100000 && mpls 1024\fR
-.fi
-.in -.5i
-filters packets with an outer label of 100000 and an inner label of
-1024, and
-.in +.5i
-.nf
-\fBmpls && mpls 1024 && host 192.9.200.1\fR
-.fi
-.in -.5i
-filters packets to or from 192.9.200.1 with an inner label of 1024 and
-any outer label.
-.IP \fBpppoed\fP
-True if the packet is a PPP-over-Ethernet Discovery packet (Ethernet
-type 0x8863).
-.IP \fBpppoes\fP
-True if the packet is a PPP-over-Ethernet Session packet (Ethernet
-type 0x8864).
-Note that the first \fBpppoes\fR keyword encountered in \fIexpression\fR
-changes the decoding offsets for the remainder of \fIexpression\fR on
-the assumption that the packet is a PPPoE session packet.
-.IP
-For example:
-.in +.5i
-.nf
-\fBpppoes && ip\fR
-.fi
-.in -.5i
-filters IPv4 protocols encapsulated in PPPoE.
-.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR"
-Abbreviations for:
-.in +.5i
-.nf
-\fBip proto \fIp\fR\fB or ip6 proto \fIp\fR
-.fi
-.in -.5i
-where \fIp\fR is one of the above protocols.
-.IP "\fBiso proto \fIprotocol\fR"
-True if the packet is an OSI packet of protocol type \fIprotocol\fP.
-\fIProtocol\fP can be a number or one of the names
-\fBclnp\fP, \fBesis\fP, or \fBisis\fP.
-.IP "\fBclnp\fR, \fBesis\fR, \fBisis\fR"
-Abbreviations for:
-.in +.5i
-.nf
-\fBiso proto \fIp\fR
-.fi
-.in -.5i
-where \fIp\fR is one of the above protocols.
-.IP "\fBl1\fR, \fBl2\fR, \fBiih\fR, \fBlsp\fR, \fBsnp\fR, \fBcsnp\fR, \fBpsnp\fR"
-Abbreviations for IS-IS PDU types.
-.IP "\fBvpi\fP \fIn\fR
-True if the packet is an ATM packet, for SunATM on Solaris, with a
-virtual path identifier of
-.IR n .
-.IP "\fBvci\fP \fIn\fR
-True if the packet is an ATM packet, for SunATM on Solaris, with a
-virtual channel identifier of
-.IR n .
-.IP \fBlane\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-an ATM LANE packet.
-Note that the first \fBlane\fR keyword encountered in \fIexpression\fR
-changes the tests done in the remainder of \fIexpression\fR
-on the assumption that the packet is either a LANE emulated Ethernet
-packet or a LANE LE Control packet. If \fBlane\fR isn't specified, the
-tests are done under the assumption that the packet is an
-LLC-encapsulated packet.
-.IP \fBllc\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-an LLC-encapsulated packet.
-.IP \fBoamf4s\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-a segment OAM F4 flow cell (VPI=0 & VCI=3).
-.IP \fBoamf4e\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-an end-to-end OAM F4 flow cell (VPI=0 & VCI=4).
-.IP \fBoamf4\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
-.IP \fBoam\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
-.IP \fBmetac\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-on a meta signaling circuit (VPI=0 & VCI=1).
-.IP \fBbcc\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-on a broadcast signaling circuit (VPI=0 & VCI=2).
-.IP \fBsc\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-on a signaling circuit (VPI=0 & VCI=5).
-.IP \fBilmic\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-on an ILMI circuit (VPI=0 & VCI=16).
-.IP \fBconnectmsg\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-on a signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
-Connect Ack, Release, or Release Done message.
-.IP \fBmetaconnect\fP
-True if the packet is an ATM packet, for SunATM on Solaris, and is
-on a meta signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
-Release, or Release Done message.
-.IP "\fIexpr relop expr\fR"
-True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =,
-!=, and \fIexpr\fR is an arithmetic expression composed of integer
-constants (expressed in standard C syntax), the normal binary operators
-[+, -, *, /, &, |, <<, >>], a length operator, and special packet data
-accessors. Note that all comparisons are unsigned, so that, for example,
-0x80000000 and 0xffffffff are > 0.
-To access
-data inside the packet, use the following syntax:
-.in +.5i
-.nf
-\fIproto\fB [ \fIexpr\fB : \fIsize\fB ]\fR
-.fi
-.in -.5i
-\fIProto\fR is one of \fBether, fddi, tr, wlan, ppp, slip, link,
-ip, arp, rarp, tcp, udp, icmp, ip6\fR or \fBradio\fR, and
-indicates the protocol layer for the index operation.
-(\fBether, fddi, wlan, tr, ppp, slip\fR and \fBlink\fR all refer to the
-link layer. \fBradio\fR refers to the "radio header" added to some
-802.11 captures.)
-Note that \fItcp, udp\fR and other upper-layer protocol types only
-apply to IPv4, not IPv6 (this will be fixed in the future).
-The byte offset, relative to the indicated protocol layer, is
-given by \fIexpr\fR.
-\fISize\fR is optional and indicates the number of bytes in the
-field of interest; it can be either one, two, or four, and defaults to one.
-The length operator, indicated by the keyword \fBlen\fP, gives the
-length of the packet.
-
-For example, `\fBether[0] & 1 != 0\fP' catches all multicast traffic.
-The expression `\fBip[0] & 0xf != 5\fP'
-catches all IPv4 packets with options.
-The expression
-`\fBip[6:2] & 0x1fff = 0\fP'
-catches only unfragmented IPv4 datagrams and frag zero of fragmented
-IPv4 datagrams.
-This check is implicitly applied to the \fBtcp\fP and \fBudp\fP
-index operations.
-For instance, \fBtcp[0]\fP always means the first
-byte of the TCP \fIheader\fP, and never means the first byte of an
-intervening fragment.
-
-Some offsets and field values may be expressed as names rather than
-as numeric values.
-The following protocol header field offsets are
-available: \fBicmptype\fP (ICMP type field), \fBicmpcode\fP (ICMP
-code field), and \fBtcpflags\fP (TCP flags field).
-
-The following ICMP type field values are available: \fBicmp-echoreply\fP,
-\fBicmp-unreach\fP, \fBicmp-sourcequench\fP, \fBicmp-redirect\fP,
-\fBicmp-echo\fP, \fBicmp-routeradvert\fP, \fBicmp-routersolicit\fP,
-\fBicmp-timxceed\fP, \fBicmp-paramprob\fP, \fBicmp-tstamp\fP,
-\fBicmp-tstampreply\fP, \fBicmp-ireq\fP, \fBicmp-ireqreply\fP,
-\fBicmp-maskreq\fP, \fBicmp-maskreply\fP.
-
-The following TCP flags field values are available: \fBtcp-fin\fP,
-\fBtcp-syn\fP, \fBtcp-rst\fP, \fBtcp-push\fP,
-\fBtcp-ack\fP, \fBtcp-urg\fP.
-.LP
-Primitives may be combined using:
-.IP
-A parenthesized group of primitives and operators
-(parentheses are special to the Shell and must be escaped).
-.IP
-Negation (`\fB!\fP' or `\fBnot\fP').
-.IP
-Concatenation (`\fB&&\fP' or `\fBand\fP').
-.IP
-Alternation (`\fB||\fP' or `\fBor\fP').
-.LP
-Negation has highest precedence.
-Alternation and concatenation have equal precedence and associate
-left to right.
-Note that explicit \fBand\fR tokens, not juxtaposition,
-are now required for concatenation.
-.LP
-If an identifier is given without a keyword, the most recent keyword
-is assumed.
-For example,
-.in +.5i
-.nf
-\fBnot host vs and ace\fR
-.fi
-.in -.5i
-is short for
-.in +.5i
-.nf
-\fBnot host vs and host ace\fR
-.fi
-.in -.5i
-which should not be confused with
-.in +.5i
-.nf
-\fBnot ( host vs or ace )\fR
-.fi
-.in -.5i
+For the \fIexpression\fP syntax, see
+.BR pcap-filter (4).
.LP
Expression arguments can be passed to \fItcpdump\fP as either a single
argument or as multiple arguments, whichever is more convenient.
@@ -2288,7 +1617,7 @@ is made to account for the time lag between when the
Ethernet interface removed the packet from the wire and when the kernel
serviced the `new packet' interrupt.
.SH "SEE ALSO"
-bpf(4), pcap(3)
+stty(1), pcap(3PCAP), pcap-filter(4), bpf(4), nit(4P)
.SH AUTHORS
The original authors are:
.LP
@@ -2312,18 +1641,13 @@ The original distribution is available via anonymous ftp:
.RE
.LP
IPv6/IPsec support is added by WIDE/KAME project.
-This program uses Eric Young's SSLeay library, under specific configuration.
+This program uses Eric Young's SSLeay library, under specific configurations.
.SH BUGS
-Please send problems, bugs, questions, desirable enhancements, etc. to:
-.LP
-.RS
-tcpdump-workers@tcpdump.org
-.RE
-.LP
-Please send source code contributions, etc. to:
+Please send problems, bugs, questions, desirable enhancements, patches
+etc. to:
.LP
.RS
-patches@tcpdump.org
+tcpdump-workers@lists.tcpdump.org
.RE
.LP
NIT doesn't let you watch your own outbound traffic, BPF will.
diff --git a/contrib/tcpdump/tcpdump.c b/contrib/tcpdump/tcpdump.c
index e45ab23..f19878b 100644
--- a/contrib/tcpdump/tcpdump.c
+++ b/contrib/tcpdump/tcpdump.c
@@ -30,7 +30,7 @@ static const char copyright[] _U_ =
"@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
The Regents of the University of California. All rights reserved.\n";
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.253.2.13 2007/09/12 19:48:51 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/tcpdump.c,v 1.271.2.11 2008-09-25 21:50:04 guy Exp $ (LBL)";
#endif
/* $FreeBSD$ */
@@ -67,12 +67,16 @@ extern int SIZE_BUF;
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#ifndef WIN32
+#include <sys/wait.h>
+#include <sys/resource.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#endif /* WIN32 */
+
#include "netdissect.h"
#include "interface.h"
#include "addrtoname.h"
@@ -81,19 +85,16 @@ extern int SIZE_BUF;
#include "gmt2local.h"
#include "pcap-missing.h"
+#ifndef NAME_MAX
+#define NAME_MAX 255
+#endif
+
netdissect_options Gndo;
netdissect_options *gndo = &Gndo;
-/*
- * Define the maximum number of files for the -C flag, and how many
- * characters can be added to a filename for the -C flag (which
- * should be enough to handle MAX_CFLAG - 1).
- */
-#define MAX_CFLAG 1000000
-#define MAX_CFLAG_CHARS 6
-
int dflag; /* print filter code */
int Lflag; /* list available data link types and exit */
+char *zflag = NULL; /* compress each savefile using a specified command (like gzip or bzip2) */
static int infodelay;
static int infoprint;
@@ -104,6 +105,7 @@ int32_t thiszone; /* seconds offset from gmt to local time */
/* Forwards */
static RETSIGTYPE cleanup(int);
+static RETSIGTYPE child_cleanup(int);
static void usage(void) __attribute__((noreturn));
static void show_dlts_and_exit(pcap_t *pd) __attribute__((noreturn));
@@ -222,6 +224,9 @@ static struct printer printers[] = {
#ifdef DLT_APPLE_IP_OVER_IEEE1394
{ ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 },
#endif
+#ifdef DLT_IEEE802_11_RADIO_AVS
+ { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS },
+#endif
#ifdef DLT_JUNIPER_ATM1
{ juniper_atm1_print, DLT_JUNIPER_ATM1 },
#endif
@@ -270,6 +275,9 @@ static struct printer printers[] = {
#ifdef DLT_MFR
{ mfr_if_print, DLT_MFR },
#endif
+#if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H)
+ { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR},
+#endif
{ NULL, 0 },
};
@@ -298,6 +306,7 @@ struct print_info {
struct dump_info {
char *WFileName;
+ char *CurrentFileName;
pcap_t *pd;
pcap_dumper_t *p;
};
@@ -327,10 +336,10 @@ show_dlts_and_exit(pcap_t *pd)
* OK, does tcpdump handle that type?
*/
if (lookup_printer(dlts[n_dlts]) == NULL)
- (void) fprintf(stderr, " (not supported)");
+ (void) fprintf(stderr, " (printing not supported)");
putchar('\n');
} else {
- (void) fprintf(stderr, " DLT %d (not supported)\n",
+ (void) fprintf(stderr, " DLT %d (printing not supported)\n",
dlts[n_dlts]);
}
}
@@ -342,13 +351,19 @@ show_dlts_and_exit(pcap_t *pd)
* Set up flags that might or might not be supported depending on the
* version of libpcap we're using.
*/
-#ifdef WIN32
+#if defined(HAVE_PCAP_CREATE) || defined(WIN32)
#define B_FLAG "B:"
#define B_FLAG_USAGE " [ -B size ]"
-#else /* WIN32 */
+#else /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */
#define B_FLAG
#define B_FLAG_USAGE
-#endif /* WIN32 */
+#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */
+
+#ifdef HAVE_PCAP_CREATE
+#define I_FLAG "I"
+#else /* HAVE_PCAP_CREATE */
+#define I_FLAG
+#endif /* HAVE_PCAP_CREATE */
#ifdef HAVE_PCAP_FINDALLDEVS
#ifndef HAVE_PCAP_IF_T
@@ -425,10 +440,32 @@ getWflagChars(int x)
static void
MakeFilename(char *buffer, char *orig_name, int cnt, int max_chars)
{
+ char *filename = malloc(NAME_MAX + 1);
+
+ /* Process with strftime if Gflag is set. */
+ if (Gflag != 0) {
+ struct tm *local_tm;
+
+ /* Convert Gflag_time to a usable format */
+ if ((local_tm = localtime(&Gflag_time)) == NULL) {
+ error("MakeTimedFilename: localtime");
+ }
+
+ /* There's no good way to detect an error in strftime since a return
+ * value of 0 isn't necessarily failure.
+ */
+ strftime(filename, NAME_MAX, orig_name, local_tm);
+ } else {
+ strncpy(filename, orig_name, NAME_MAX);
+ }
+
if (cnt == 0 && max_chars == 0)
- strcpy(buffer, orig_name);
+ strncpy(buffer, filename, NAME_MAX + 1);
else
- sprintf(buffer, "%s%0*d", orig_name, max_chars, cnt);
+ if (snprintf(buffer, NAME_MAX + 1, "%s%0*d", filename, max_chars, cnt) > NAME_MAX)
+ /* Report an error if the filename is too large */
+ error("too many output files or filename is too long (> %d)", NAME_MAX);
+ free(filename);
}
static int tcpdump_printf(netdissect_options *ndo _U_,
@@ -450,7 +487,7 @@ main(int argc, char **argv)
{
register int cnt, op, i;
bpf_u_int32 localnet, netmask;
- register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName, *WFileNameAlt;
+ register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName;
pcap_handler callback;
int type;
struct bpf_program fcode;
@@ -469,7 +506,6 @@ main(int argc, char **argv)
#endif
int status;
#ifdef WIN32
- u_int UserBufferSize = 1000000;
if(wsockinit() != 0) return 1;
#endif /* WIN32 */
@@ -501,7 +537,7 @@ main(int argc, char **argv)
opterr = 0;
while (
- (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:i:lLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:YZ:")) != -1)
+ (op = getopt(argc, argv, "aA" B_FLAG "c:C:d" D_FLAG "eE:fF:G:i:" I_FLAG "KlLm:M:nNOpqr:Rs:StT:u" U_FLAG "vw:W:xXy:Yz:Z:")) != -1)
switch (op) {
case 'a':
@@ -512,13 +548,13 @@ main(int argc, char **argv)
++Aflag;
break;
-#ifdef WIN32
+#if defined(HAVE_PCAP_CREATE) || defined(WIN32)
case 'B':
- UserBufferSize = atoi(optarg)*1024;
- if (UserBufferSize < 0)
+ Bflag = atoi(optarg)*1024;
+ if (Bflag <= 0)
error("invalid packet buffer size %s", optarg);
break;
-#endif /* WIN32 */
+#endif /* defined(HAVE_PCAP_CREATE) || defined(WIN32) */
case 'c':
cnt = atoi(optarg);
@@ -575,6 +611,21 @@ main(int argc, char **argv)
infile = optarg;
break;
+ case 'G':
+ Gflag = atoi(optarg);
+ if (Gflag < 0)
+ error("invalid number of seconds %s", optarg);
+
+ /* We will create one file initially. */
+ Gflag_count = 0;
+
+ /* Grab the current time for rotation use. */
+ if ((Gflag_time = time(NULL)) == (time_t)-1) {
+ error("main: can't get current time: %s",
+ pcap_strerror(errno));
+ }
+ break;
+
case 'i':
if (optarg[0] == '0' && optarg[1] == 0)
error("Invalid adapter index");
@@ -610,6 +661,12 @@ main(int argc, char **argv)
device = optarg;
break;
+#ifdef HAVE_PCAP_CREATE
+ case 'I':
+ ++Iflag;
+ break;
+#endif /* HAVE_PCAP_CREATE */
+
case 'l':
#ifdef WIN32
/*
@@ -631,19 +688,15 @@ main(int argc, char **argv)
#endif /* WIN32 */
break;
- case 'n':
- ++nflag;
- break;
-
- case 'N':
- ++Nflag;
+ case 'K':
+ ++Kflag;
break;
case 'm':
#ifdef LIBSMI
- if (smiLoadModule(optarg) == 0) {
+ if (smiLoadModule(optarg) == 0) {
error("could not load MIB module %s", optarg);
- }
+ }
sflag = 1;
#else
(void)fprintf(stderr, "%s: ignoring option `-m %s' ",
@@ -660,6 +713,14 @@ main(int argc, char **argv)
tcpmd5secret = optarg;
break;
+ case 'n':
+ ++nflag;
+ break;
+
+ case 'N':
+ ++Nflag;
+ break;
+
case 'O':
Oflag = 0;
break;
@@ -781,6 +842,15 @@ main(int argc, char **argv)
}
break;
#endif
+ case 'z':
+ if (optarg) {
+ zflag = strdup(optarg);
+ } else {
+ usage();
+ /* NOTREACHED */
+ }
+ break;
+
case 'Z':
if (optarg) {
username = strdup(optarg);
@@ -806,10 +876,11 @@ main(int argc, char **argv)
case 1: /* No time stamp */
case 2: /* Unix timeval style */
case 3: /* Microseconds since previous packet */
+ case 5: /* Microseconds since first packet */
break;
default: /* Not supported */
- error("only -t, -tt, -ttt, and -tttt are supported");
+ error("only -t, -tt, -ttt, -tttt and -ttttt are supported");
break;
}
@@ -884,12 +955,74 @@ main(int argc, char **argv)
fflush(stderr);
#endif /* WIN32 */
+#ifdef HAVE_PCAP_CREATE
+ pd = pcap_create(device, ebuf);
+ if (pd == NULL)
+ error("%s", ebuf);
+ status = pcap_set_snaplen(pd, snaplen);
+ if (status != 0)
+ error("%s: pcap_set_snaplen failed: %s",
+ device, pcap_statustostr(status));
+ status = pcap_set_promisc(pd, !pflag);
+ if (status != 0)
+ error("%s: pcap_set_promisc failed: %s",
+ device, pcap_statustostr(status));
+ if (Iflag) {
+ status = pcap_set_rfmon(pd, 1);
+ if (status != 0)
+ error("%s: pcap_set_rfmon failed: %s",
+ device, pcap_statustostr(status));
+ }
+ status = pcap_set_timeout(pd, 1000);
+ if (status != 0)
+ error("%s: pcap_set_timeout failed: %s",
+ device, pcap_statustostr(status));
+ if (Bflag != 0) {
+ status = pcap_set_buffer_size(pd, Bflag);
+ if (status != 0)
+ error("%s: pcap_set_buffer_size failed: %s",
+ device, pcap_statustostr(status));
+ }
+ status = pcap_activate(pd);
+ if (status < 0) {
+ /*
+ * pcap_activate() failed.
+ */
+ cp = pcap_geterr(pd);
+ if (status == PCAP_ERROR)
+ error("%s", cp);
+ else if ((status == PCAP_ERROR_NO_SUCH_DEVICE ||
+ status == PCAP_ERROR_PERM_DENIED) &&
+ *cp != '\0')
+ error("%s: %s\n(%s)", device,
+ pcap_statustostr(status), cp);
+ else
+ error("%s: %s", device,
+ pcap_statustostr(status));
+ } else if (status > 0) {
+ /*
+ * pcap_activate() succeeded, but it's warning us
+ * of a problem it had.
+ */
+ cp = pcap_geterr(pd);
+ if (status == PCAP_WARNING)
+ warning("%s", cp);
+ else if (status == PCAP_WARNING_PROMISC_NOTSUP &&
+ *cp != '\0')
+ warning("%s: %s\n(%s)", device,
+ pcap_statustostr(status), cp);
+ else
+ warning("%s: %s", device,
+ pcap_statustostr(status));
+ }
+#else
*ebuf = '\0';
pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf);
if (pd == NULL)
error("%s", ebuf);
else if (*ebuf)
warning("%s", ebuf);
+#endif /* HAVE_PCAP_CREATE */
/*
* Let user own process after socket has been opened.
*/
@@ -897,12 +1030,12 @@ main(int argc, char **argv)
if (setgid(getgid()) != 0 || setuid(getuid()) != 0)
fprintf(stderr, "Warning: setgid/setuid failed !\n");
#endif /* WIN32 */
-#ifdef WIN32
- if(UserBufferSize != 1000000)
- if(pcap_setbuff(pd, UserBufferSize)==-1){
+#if !defined(HAVE_PCAP_CREATE) && defined(WIN32)
+ if(Bflag != 0)
+ if(pcap_setbuff(pd, Bflag)==-1){
error("%s", pcap_geterr(pd));
}
-#endif /* WIN32 */
+#endif /* !defined(HAVE_PCAP_CREATE) && defined(WIN32) */
if (Lflag)
show_dlts_and_exit(pd);
if (gndo->ndo_dlt >= 0) {
@@ -921,7 +1054,7 @@ main(int argc, char **argv)
}
#endif
(void)fprintf(stderr, "%s: data link type %s\n",
- program_name, gndo->ndo_dltname);
+ program_name, gndo->ndo_dltname);
(void)fflush(stderr);
}
i = pcap_snapshot(pd);
@@ -948,12 +1081,14 @@ main(int argc, char **argv)
exit(0);
}
init_addrtoname(localnet, netmask);
+ init_checksum();
#ifndef WIN32
(void)setsignal(SIGPIPE, cleanup);
-#endif /* WIN32 */
(void)setsignal(SIGTERM, cleanup);
(void)setsignal(SIGINT, cleanup);
+ (void)setsignal(SIGCHLD, child_cleanup);
+#endif /* WIN32 */
/* Cooperate with nohup(1) */
#ifndef WIN32
if ((oldhandler = setsignal(SIGHUP, cleanup)) != SIG_DFL)
@@ -964,15 +1099,22 @@ main(int argc, char **argv)
error("%s", pcap_geterr(pd));
if (WFileName) {
pcap_dumper_t *p;
+ /* Do not exceed the default NAME_MAX for files. */
+ dumpinfo.CurrentFileName = (char *)malloc(NAME_MAX + 1);
+
+ if (dumpinfo.CurrentFileName == NULL)
+ error("malloc of dumpinfo.CurrentFileName");
+
+ /* We do not need numbering for dumpfiles if Cflag isn't set. */
+ if (Cflag != 0)
+ MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, WflagChars);
+ else
+ MakeFilename(dumpinfo.CurrentFileName, WFileName, 0, 0);
- WFileNameAlt = (char *)malloc(strlen(WFileName) + MAX_CFLAG_CHARS + 1);
- if (WFileNameAlt == NULL)
- error("malloc of WFileNameAlt");
- MakeFilename(WFileNameAlt, WFileName, 0, WflagChars);
- p = pcap_dump_open(pd, WFileNameAlt);
+ p = pcap_dump_open(pd, dumpinfo.CurrentFileName);
if (p == NULL)
error("%s", pcap_geterr(pd));
- if (Cflag != 0) {
+ if (Cflag != 0 || Gflag != 0) {
callback = dump_packet_and_trunc;
dumpinfo.WFileName = WFileName;
dumpinfo.pd = pd;
@@ -1007,7 +1149,12 @@ main(int argc, char **argv)
}
#endif /* WIN32 */
#ifdef SIGINFO
- (void)setsignal(SIGINFO, requestinfo);
+ /*
+ * We can't get statistics when reading from a file rather
+ * than capturing from a device.
+ */
+ if (RFileName == NULL)
+ (void)setsignal(SIGINFO, requestinfo);
#endif
if (vflag > 0 && WFileName) {
@@ -1125,6 +1272,18 @@ cleanup(int signo _U_)
#endif
}
+/*
+ On windows, we do not use a fork, so we do not care less about
+ waiting a child processes to die
+ */
+#ifndef WIN32
+static RETSIGTYPE
+child_cleanup(int signo _U_)
+{
+ wait(NULL);
+}
+#endif /* WIN32 */
+
static void
info(register int verbose)
{
@@ -1153,11 +1312,40 @@ info(register int verbose)
infoprint = 0;
}
+#ifndef WIN32
+static void
+compress_savefile(const char *filename)
+{
+ if (fork())
+ return;
+ /*
+ * Set to lowest priority so that this doesn't disturb the capture
+ */
+#ifdef NZERO
+ setpriority(PRIO_PROCESS, 0, NZERO - 1);
+#else
+ setpriority(PRIO_PROCESS, 0, 19);
+#endif
+ if (execlp(zflag, zflag, filename, NULL) == -1)
+ fprintf(stderr,
+ "compress_savefile:execlp(%s, %s): %s\n",
+ zflag,
+ filename,
+ strerror(errno));
+}
+#else /* WIN32 */
+static void
+compress_savefile(const char *filename)
+{
+ fprintf(stderr,
+ "compress_savefile failed. Functionality not implemented under windows\n");
+}
+#endif /* WIN32 */
+
static void
dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
{
struct dump_info *dump_info;
- char *name;
++packets_captured;
@@ -1166,29 +1354,103 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
dump_info = (struct dump_info *)user;
/*
+ * XXX - this won't force the file to rotate on the specified time
+ * boundary, but it will rotate on the first packet received after the
+ * specified Gflag number of seconds. Note: if a Gflag time boundary
+ * and a Cflag size boundary coincide, the time rotation will occur
+ * first thereby cancelling the Cflag boundary (since the file should
+ * be 0).
+ */
+ if (Gflag != 0) {
+ /* Check if it is time to rotate */
+ time_t t;
+
+ /* Get the current time */
+ if ((t = time(NULL)) == (time_t)-1) {
+ error("dump_and_trunc_packet: can't get current_time: %s",
+ pcap_strerror(errno));
+ }
+
+
+ /* If the time is greater than the specified window, rotate */
+ if (t - Gflag_time >= Gflag) {
+ /* Update the Gflag_time */
+ Gflag_time = t;
+ /* Update Gflag_count */
+ Gflag_count++;
+ /*
+ * Close the current file and open a new one.
+ */
+ pcap_dump_close(dump_info->p);
+
+ /*
+ * Compress the file we just closed, if the user asked for it
+ */
+ if (zflag != NULL)
+ compress_savefile(dump_info->CurrentFileName);
+
+ /*
+ * Check to see if we've exceeded the Wflag (when
+ * not using Cflag).
+ */
+ if (Cflag == 0 && Wflag > 0 && Gflag_count >= Wflag) {
+ (void)fprintf(stderr, "Maximum file limit reached: %d\n",
+ Wflag);
+ exit(0);
+ /* NOTREACHED */
+ }
+ if (dump_info->CurrentFileName != NULL)
+ free(dump_info->CurrentFileName);
+ /* Allocate space for max filename + \0. */
+ dump_info->CurrentFileName = (char *)malloc(NAME_MAX + 1);
+ if (dump_info->CurrentFileName == NULL)
+ error("dump_packet_and_trunc: malloc");
+ /*
+ * This is always the first file in the Cflag
+ * rotation: e.g. 0
+ * We also don't need numbering if Cflag is not set.
+ */
+ if (Cflag != 0)
+ MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0,
+ WflagChars);
+ else
+ MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, 0, 0);
+
+ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
+ if (dump_info->p == NULL)
+ error("%s", pcap_geterr(pd));
+ }
+ }
+
+ /*
* XXX - this won't prevent capture files from getting
* larger than Cflag - the last packet written to the
* file could put it over Cflag.
*/
- if (pcap_dump_ftell(dump_info->p) > Cflag) {
+ if (Cflag != 0 && pcap_dump_ftell(dump_info->p) > Cflag) {
/*
* Close the current file and open a new one.
*/
pcap_dump_close(dump_info->p);
+
+ /*
+ * Compress the file we just closed, if the user asked for it
+ */
+ if (zflag != NULL)
+ compress_savefile(dump_info->CurrentFileName);
+
Cflag_count++;
if (Wflag > 0) {
if (Cflag_count >= Wflag)
Cflag_count = 0;
- } else {
- if (Cflag_count >= MAX_CFLAG)
- error("too many output files");
}
- name = (char *)malloc(strlen(dump_info->WFileName) + MAX_CFLAG_CHARS + 1);
- if (name == NULL)
+ if (dump_info->CurrentFileName != NULL)
+ free(dump_info->CurrentFileName);
+ dump_info->CurrentFileName = (char *)malloc(NAME_MAX + 1);
+ if (dump_info->CurrentFileName == NULL)
error("dump_packet_and_trunc: malloc");
- MakeFilename(name, dump_info->WFileName, Cflag_count, WflagChars);
- dump_info->p = pcap_dump_open(dump_info->pd, name);
- free(name);
+ MakeFilename(dump_info->CurrentFileName, dump_info->WFileName, Cflag_count, WflagChars);
+ dump_info->p = pcap_dump_open(dump_info->pd, dump_info->CurrentFileName);
if (dump_info->p == NULL)
error("%s", pcap_geterr(pd));
}
@@ -1365,7 +1627,7 @@ RETSIGTYPE requestinfo(int signo _U_)
*/
#ifdef USE_WIN32_MM_TIMER
void CALLBACK verbose_stats_dump (UINT timer_id _U_, UINT msg _U_, DWORD_PTR arg _U_,
- DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_)
+ DWORD_PTR dw1 _U_, DWORD_PTR dw2 _U_)
{
struct pcap_stat stat;
@@ -1412,13 +1674,15 @@ usage(void)
#endif /* WIN32 */
#endif /* HAVE_PCAP_LIB_VERSION */
(void)fprintf(stderr,
-"Usage: %s [-aAd" D_FLAG "eflLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [-c count] [ -C file_size ]\n", program_name);
+"Usage: %s [-aAd" D_FLAG "ef" I_FLAG "KlLnNOpqRStu" U_FLAG "vxX]" B_FLAG_USAGE " [ -c count ]\n", program_name);
+ (void)fprintf(stderr,
+"\t\t[ -C file_size ] [ -E algo:secret ] [ -F file ] [ -G seconds ]\n");
(void)fprintf(stderr,
-"\t\t[ -E algo:secret ] [ -F file ] [ -i interface ] [ -M secret ]\n");
+"\t\t[ -i interface ] [ -M secret ] [ -r file ]\n");
(void)fprintf(stderr,
-"\t\t[ -r file ] [ -s snaplen ] [ -T type ] [ -w file ]\n");
+"\t\t[ -s snaplen ] [ -T type ] [ -w file ] [ -W filecount ]\n");
(void)fprintf(stderr,
-"\t\t[ -W filecount ] [ -y datalinktype ] [ -Z user ]\n");
+"\t\t[ -y datalinktype ] [ -z command ] [ -Z user ]\n");
(void)fprintf(stderr,
"\t\t[ expression ]\n");
exit(1);
@@ -1461,4 +1725,3 @@ ndo_warning(netdissect_options *ndo _U_, const char *fmt, ...)
(void)fputc('\n', stderr);
}
}
-
diff --git a/contrib/tcpdump/telnet.h b/contrib/tcpdump/telnet.h
index da11043..33a07be 100644
--- a/contrib/tcpdump/telnet.h
+++ b/contrib/tcpdump/telnet.h
@@ -1,6 +1,6 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/telnet.h,v 1.4 2002/06/11 17:09:01 itojun Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/telnet.h,v 1.5 2007-08-29 02:31:44 mcr Exp $ (LBL) */
-/* $NetBSD: telnet.h,v 1.9 2001/06/11 01:50:50 wiz Exp $ */
+/* NetBSD: telnet.h,v 1.9 2001/06/11 01:50:50 wiz Exp */
/*
* Copyright (c) 1983, 1993
diff --git a/contrib/tcpdump/tests/.cvsignore b/contrib/tcpdump/tests/.cvsignore
deleted file mode 100644
index f097c8a..0000000
--- a/contrib/tcpdump/tests/.cvsignore
+++ /dev/null
@@ -1,11 +0,0 @@
-*.new
-*.pcap
-02-sunrise-sunset-esp.pcap
-08-sunrise-sunset-aes.pcap
-08-sunrise-sunset-esp.pcap
-08-sunrise-sunset-esp2.pcap
-isakmp-delete-segfault.pcap
-isakmp-identification-segfault.pcap
-isakmp-pointer-loop.pcap
-run1.pcap
-run2.pcap
diff --git a/contrib/tcpdump/tests/02-sunrise-sunset-esp.puu b/contrib/tcpdump/tests/02-sunrise-sunset-esp.puu
deleted file mode 100644
index 0ceffc1..0000000
--- a/contrib/tcpdump/tests/02-sunrise-sunset-esp.puu
+++ /dev/null
@@ -1,34 +0,0 @@
-begin 644 02-sunrise-sunset-esp.pcap
-MU,.RH0(`!``````````````&```!``````````````"6````E@```!```&1D
-M11```&1D(P@`10``B/]G``!`,O:5P`$"%\`!`BT2-%9X`````4P@12\\L)(1
-MTZ=(S>7($>.<3N@\_I:AY"K/TKAZJP719"NCKYP;PT(0+$"M%=]-X"`*8V.'
-M-'$1A]02"3N#OZI#&1R]A*1;`G8S@YFQ]<H7S))417Y9!E4:<$'CW)%VZ&_3
-M_]T`L+P1^!`PEP``````````E@```)8````0``!D9$40``!D9",(`$4``(C_
-M:```0#+VE,`!`A?``0(M$C16>`````(:<$'CW)%VZ',2KQMB@CN?'"^GJ<=:
-MD-0`+.V^J'2AK).'XQ_B"B8:[%A_+K[6KS2'XR[UN`,R"BJP?^].ZM#/[$)#
-M17^!D"8_[BZ>GU4Z*$7I"N$U*>J47?C-4;I>#`%6+#0%]D75YC']*Z\`````
-M`````)8```"6````$```9&1%$```9&0C"`!%``"(_VD``$`R]I/``0(7P`$"
-M+1(T5G@````#7?C-4;I>#`%@W%89?QJ#$TJ,4G\FO&HO=F+,,%1E(]);XI]T
-MV7W.RY$2=JZ1%!QCNX[;^.JD4W91;7)NJWV2MF4?7`=&_3OWW%V&6RIXKB75
-M#;2TWNL"A:MF!I@_5R^]L6;Z`L?E@1:T&71G``````````"6````E@```!``
-M`&1D11```&1D(P@`10``B/]J``!`,O:2P`$"%\`!`BT2-%9X````!*MF!I@_
-M5R^]%';9*Q:S_B]]O_8FV:2K1A!]/SQHI7>OS815*I?4%/:.=BBJUEGJ(X8\
-M<SZ>P1E/@&P\9MR)DP3[UCWI@,MR%A$\CR]=G(("[CFB7AUN$AENZOO&\:7%
-M2KLW<'NP,L(I=!;8=0``````````E@```)8````0``!D9$40``!D9",(`$4`
-M`(C_:P``0#+VD<`!`A?``0(M$C16>`````5NZOO&\:7%2J12,9;LOK"-S,=$
-MO0]X+J(OJQED#PLBRY[\^352UZK&57<R0L9JQ:KH6`)BUN$`5]1WU@"A!8TM
-MO^)<;`-SW;1HQO$CE\#`O[W[17GW[0G&M,^T?7>6,Z<:%73AWV3:;Y/:=@(`
-M`````````)8```"6````$```9&1%$```9&0C"`!%``"(_VP``$`R]I#``0(7
-MP`$"+1(T5G@````&M,^T?7>6,Z=>N_YZQFV[H1^6\!/I*IMAOHZE\E0M.Z!X
-M#[0EG3#>%]7`]*2F?@S4X2''TK09J@NG/.HEXCE./..K^'-@":X[\?0L+B`S
-MQA\HTK\'J]:S]N6O`]\)NQD)9;H2P\K`^NX37`R5``````````"6````E@``
-M`!```&1D11```&1D(P@`10``B/]M``!`,O:/P`$"%\`!`BT2-%9X````!^6O
-M`]\)NQD)>BYZ>`/DA=N;A2...3-7FZOK?:5KGXBN`/E?$\[-11-$G#E;(>N"
-M+<$/YP'SM$>16LU18&Q]9)$]0)/M]:2Z#A6]-,SM*>FI/`X*K-*-:KS3IW<"
-MO(>(P(K=:X::SJ;O[J>0K```````````E@```)8````0``!D9$40``!D9",(
-M`$4``(C_;@``0#+VCL`!`A?``0(M$C16>`````C3IW<"O(>(P'-43;C[`MCD
-M`BMZAX]F!?'Z$8Q"5HYMVDC9"8I^O(Z4!/)`/IVD-(ZK)_52-H2XK+,(-LR)
-MM)K#XLF">KY0>C?\[MA%3F%$?ORJ@:>O]5H>?-$OQH)J<ZFOW_+K%G=UG0"[
-"G'T`
-`
-end
diff --git a/contrib/tcpdump/tests/08-sunrise-sunset-aes.puu b/contrib/tcpdump/tests/08-sunrise-sunset-aes.puu
deleted file mode 100644
index ec8793d..0000000
--- a/contrib/tcpdump/tests/08-sunrise-sunset-aes.puu
+++ /dev/null
@@ -1,36 +0,0 @@
-begin 644 08-sunrise-sunset-aes.pcap
-MU,.RH0(`!``````````````&```!``````````````"F````I@```!```&1D
-M11```&1D(P@`10``F/SJ``!`,OD"P`$"%\`!`BW1(T5G`````>:['.C0J(%P
-MVF'>(TU6&*"9A,`,/KS\:>DH>O_L(51)_[YY"L<H#LJ/;(BQ)=[*$<APY/A1
-M-"T@(`_Q&)S!C)$*7S?G3Q4H\F=)OYF+P@S&11%^*]S)N@L*TZ@!:&&:QFZT
-ML'#7<>9?8'?J4V:_.]B+6UR\T>39D+=NA;$``````````*8```"F````$```
-M9&1%$```9&0C"`!%``"8_.L``$`R^0'``0(7P`$"+=$C16<````";K2P<-=Q
-MYE]@=^I39K\[V$1HDU9'L,6BVK.^B4]E6QY&:?3?T)G?"RSU;X!J]]7S)<`,
-M*L!SYO^RUWR?!EIJMWU=5B406YL-I`]LK`^;-3%(NEY#R`ST=W40=:*[M$*8
-M#<KX)19@.`.4_5YD^:V;G@3>`GLTK(5ZCS"BC@``````````I@```*8````0
-M``!D9$40``!D9",(`$4``)C\[```0#+Y`,`!`A?``0(MT2-%9P````,-RO@E
-M%F`X`Y3]7F3YK9N>=6-;U&'6">_4H80DMY^Z9E3ZL3[ONN*L<"Z@7(VO]XT^
-M/2JP<(/^8NTO-4\/B5AJEC4N;,\"7-&(;9AM_2G5A1C.[LBK3')P?AE;$I[)
-M!8N&RC?OTD7<V)AIU4,*E>7ELURFXRD/JD(:@RER``````````"F````I@``
-M`!```&1D11```&1D(P@`10``F/SM``!`,OC_P`$"%\`!`BW1(T5G````!(;*
-M-^_21=S8F&G50PJ5Y>5K%@R;)A(E<5YD'@86@GT"-&&MHP*.A=?%=:FDZH=4
-M*9":>]'G'CB4%2?PJ"2^H*51\8P!9T`X3#;F+H$[<GW7=?K.R30-'6'L3AO8
-MR=:M3S$GIZ>4Z$7ZL0<\S=S\%`:BW9U2'@U^@D,,:.P``````````*8```"F
-M````$```9&1%$```9&0C"`!%``"8_.X``$`R^/[``0(7P`$"+=$C16<````%
-M,2>GIY3H1?JQ!SS-W/P4!BW&*&A[$!XGK<^M^>_X193"G"1QTWG>Q"CO25$"
-MPM+1+8[6&(17\EE\P:6-WVPT=911?@'-Z,,/UVZ2!QV(X4513U9]P62CJMS>
-M^ODBGHU=%T.H2&Z<4,8(!4,2[&A4^H="L:+`=4G?*(7,2@``````````I@``
-M`*8````0``!D9$40``!D9",(`$4``)C\[P``0#+X_<`!`A?``0(MT2-%9P``
-M``870ZA(;IQ0Q@@%0Q+L:%3Z@*HQPZA]3STWDY#CYJGOJH)K<KVT9G61>>I'
-MEHMF"X!^G,H@,YWT7^=60.3/$7?AYH)G9GBD%%#,D]!EDA]B*?UE>U96+"5\
-MK=""/.LO'__^;$N<E@!.2&3^@U:P__8_'D^YC!41E,!@!6<K``````````"F
-M````I@```!```&1D11```&1D(P@`10``F/SP``!`,OC\P`$"%\`!`BW1(T5G
-M````!_YL2YR6`$Y(9/Z#5K#_]C_ZJU%7M?L23>I`L#D]@&G?Z7B2O#GI?NDK
-MF[7JPN,8V\H>%G+)'+%+FL*&\8+H2^KFWF5YQ:$4V!,1?G;=OYD;!,3YD'V(
-MW[Y!I(U=X9[\:L)(5GBJ,B!-5N$.CGV$VLD^R?Z,KL[AMI(ZC-P`````````
-M`*8```"F````$```9&1%$```9&0C"`!%``"8_/$``$`R^/O``0(7P`$"+=$C
-M16<````(PDA6>*HR($U6X0Z.?83:R;Y0<E/4SN)UX;Q:D$D%K(DZZ:^_\K$'
-MZQ81NT4KBGD#Z=_^`E^!HS*KHEJ!)!KE>&'2065/"*M'ELXD?1%3\L3TC.UK
-HKWB(C5O@78>9LQ^<0Z6]F=:<;@[>L^;/\-6WB81[GX)<MS0B=>LGD@``
-`
-end
diff --git a/contrib/tcpdump/tests/08-sunrise-sunset-esp2.puu b/contrib/tcpdump/tests/08-sunrise-sunset-esp2.puu
deleted file mode 100644
index 4785f2b..0000000
--- a/contrib/tcpdump/tests/08-sunrise-sunset-esp2.puu
+++ /dev/null
@@ -1,43 +0,0 @@
-begin 644 08-sunrise-sunset-esp2.pcap
-MU,.RH0(`!``````````````&```!``````````````#.````S@```!```&1D
-M11```&1D(P@`10``P"E-``!`,LQXP`$"%\`!`BT2-%9X`````4=!+\5+F8`+
-M[[NOU-#98*AO5\780X[VDXF@2W8<10:J!'!Z!-[7N4CFNRKIH;PUA1SL"Y9\
-M-?_3N_,W/@*T+C/"]=S[`;D!/;`SR5,3+><9K.^\9N><18TY9Z\!I\S./L8R
-MFE53,S6Y5X_Z\(T)ZIUS?X$8>&(_MT1"!SV:VPP!\XU$[3S-5L)4-O"&>]`Z
-M1:./61=%C6`6U1/65"A&KUE902]*``````````#.````S@```!```&1D11``
-M`&1D(P@`10``P"E/``!`,LQVP`$"%\`!`BT2-%9X`````CIU^SX%;G^!GUSP
-MSA<?/8FY?L/'^2]6'&3[\-NES3E]33Z$Q]#7D9$8TFS5);?S?)ZJOP4;ZD-M
-M+0_/@#*U=7A9;FYR*5&/^V%MSFEM`DAZY,8'<0.9M^'::<M+M2G0LG6*S/[3
-M?T`IIJUJ[GW,L+&PH<AR&K(]^=[K7IMGD[`8[ONL8LD3AM`N@$S!*?=;*8=>
-ML7P6FM81),N>T/1Z'"P7H5;```````````#.````S@```!```&1D11```&1D
-M(P@`10``P"E1``!`,LQTP`$"%\`!`BT2-%9X`````R4)-P&F>HPK/?_$MTFC
-M^TOO=/L#W_APTK6MIH_BC*I7\L<,9(?/0M"HK3[T3F;(Y2V70$P5?D'7GFIB
-MJZ/C",S/BD!9N8GV"\.;GVME[P!@!B1"DT=1W0_75FMI23H!T2^C);4GY>`I
-M-2T^O_0_WU&$)&+/P)%[TQUQ-T7G%\RXYJT0HO</^*)F`^2<W8KTY.W<FK4K
-M8UC+J'.*X)NH%<UTK+K+``````````#.````S@```!```&1D11```&1D(P@`
-M10``P"E3``!`,LQRP`$"%\`!`BT2-%9X````!)`9]]SHKI[EGW4M?W8>[$=<
-M`@@TL1#(Y980]E*/!^2@G`*&S9O^QMS1S?/`TL=5F9B(12?(145>Y2I+;+T?
-MKWUD@&.7U36]K-$[.%9CB*FK^E8>N:K/)4#$]ZO/:=#;MRH-)_139\,W6M4T
-M7SQ?BBX&GT,+A3#BB5^O=>+GKIC-4]5VBP)D-S<X2O)H[_/#M*T+&$\7PL.M
-M>7-)\W&;<@_J@,*!``````````#.````S@```!```&1D11```&1D(P@`10``
-MP"E5``!`,LQPP`$"%\`!`BT2-%9X````!0OIFA;,@2C4HF3>5!-C(0>5LR0"
-M='1\OQ.!-?@D(U0!453"<Q/!\*CDK.&OU'+WE:^7J8"AMS<@UYX*,<(&YA2Q
-MGQ(.3+0\#`!+`.TE,;\3:.<+F:?=T@.KOBL%VAAX9_RY$/^%$C+I*4&S<AM]
-MP*]SZ"RD'G.AJH76?SV&2HQLF+!J/QZ;.:<LB::-]+AE1+&);M^]`XZ-W2CX
-M+&CPZINP*9?>``````````#.````S@```!```&1D11```&1D(P@`10``P"E7
-M``!`,LQNP`$"%\`!`BT2-%9X````!I0M"-THEF=+!L=>A3N,\1+"'Z7(J?O0
-M.B?)(#X=/5F-.">%3.X'(=JKK:W<MZF2^8#73C[US$-O&ZZ+L:94R9E2#=J=
-M18HP?AN`5^)A+HW6EB*5P=AZ(S"\TIBZ'\.=]4A,#18'0/R_#C:4XX_?>ZMN
-M=B+^Q3"(KE\1299]=5E,'.&U(`H9N)+>9FS/`CA*>D^>AV.-C(S\)BM&)*XM
-M^BF__^<_``````````#.````S@```!```&1D11```&1D(P@`10``P"E9``!`
-M,LQLP`$"%\`!`BT2-%9X````!R"SQ'[6%(;Q>>O+]CS6D*+AD3IMC\^MMK8[
-M:T3)KM06!G^.H\>%UAT@)X6JL9\3V.HR"+_Q^_T-O$Y_S":_TP;V,LIV1O]H
-M-G@DOL'V-5)O@%<%!#O$2V,AS@W7(&$IX.YKK]\K#>FITU)<>O42T2GKFW+^
-M\/[,>E4P[Q"+7O,Y1(R22LND[H+469(%3,SN&3:U:/I`'&R@<`<TR"-4:&8+
-MQ5SX``````````#.````S@```!```&1D11```&1D(P@`10``P"E;``!`,LQJ
-MP`$"%\`!`BT2-%9X````"*',]A6A,Q(*B+]=&6X&T*L^\)Z6N%,G)(.;6X-K
-MM@&4<FRJ]#IJ%Y'-^T+4[&;0;_%7HM85LR8W(>HKGOV,^#L9,QF%)W^9!VFM
-MXG'XY]CWI5VF33?7,*P?6:.PS'&[\N$7W<*==+;P*$./4*OH&=O,6G!JIN>I
-M'ZDP*D&4K>SK-\/!7\Z&<&5J4%NU?NRM&25'*_"'UE3VH&?U]/V@932UYZT\
-`
-end
diff --git a/contrib/tcpdump/tests/alltests.sh b/contrib/tcpdump/tests/alltests.sh
deleted file mode 100644
index 7df2599..0000000
--- a/contrib/tcpdump/tests/alltests.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-for i in *.sh
-do
- if [ "X$i" = "Xalltests.sh" ]
- then
- continue;
- fi
- sh ./$i
-done
-
-
diff --git a/contrib/tcpdump/tests/bgp_vpn_attrset.out b/contrib/tcpdump/tests/bgp_vpn_attrset.out
deleted file mode 100644
index 7fb12ae..0000000
--- a/contrib/tcpdump/tests/bgp_vpn_attrset.out
+++ /dev/null
@@ -1,18 +0,0 @@
-IP (tos 0xc0, ttl 62, id 58628, offset 0, flags [none], proto: TCP (6), length: 173) 12.4.4.4.2051 > 12.1.1.1.179: P, cksum 0xcf18 (correct), 3293077573:3293077694(121) ack 3348108582 win 16384 <nop,nop,timestamp 383131 890299>: BGP, length: 121
- Update Message (2), length: 121
- Origin (1), length: 1, Flags [T]: IGP
- AS Path (2), length: 0, Flags [T]: empty
- Local Preference (5), length: 4, Flags [T]: 100
- Extended Community (16), length: 8, Flags [OT]:
- target (0x0002), Flags [none]: 300:0.0.1.44
- Attribute Set (128), length: 36, Flags [OT]:
- Origin AS: 65001
- Origin (1), length: 1, Flags [T]: IGP
- AS Path (2), length: 4, Flags [T]: 5555
- Local Preference (5), length: 4, Flags [T]: 44
- Originator ID (9), length: 4, Flags [O]: 22.5.5.5
- Cluster List (10), length: 4, Flags [O]: 22.5.5.5
- Multi-Protocol Reach NLRI (14), length: 30, Flags [OE]:
- AFI: IPv4 (1), SAFI: labeled VPN Unicast (128)
- nexthop: RD: 0:0.0.0.0, 12.4.4.4, nh-length: 12, no SNPA
- RD: 500:0.0.1.244, 133.0.0.0/8, label:100208 (bottom)
diff --git a/contrib/tcpdump/tests/bgp_vpn_attrset.sh b/contrib/tcpdump/tests/bgp_vpn_attrset.sh
deleted file mode 100755
index c32872c..0000000
--- a/contrib/tcpdump/tests/bgp_vpn_attrset.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-
-echo -n test bgp_vpn_attrset...
-if (../tcpdump -t -n -v -r bgp_vpn_attrset.pcap | diff -w - bgp_vpn_attrset.out)
-then
- echo passed.
-else
- echo failed.
-fi
-
-
diff --git a/contrib/tcpdump/tests/eapon1.gdbinit b/contrib/tcpdump/tests/eapon1.gdbinit
deleted file mode 100644
index 37ad0bc..0000000
--- a/contrib/tcpdump/tests/eapon1.gdbinit
+++ /dev/null
@@ -1 +0,0 @@
-set args -r eapon1.pcap
diff --git a/contrib/tcpdump/tests/eapon1.out b/contrib/tcpdump/tests/eapon1.out
deleted file mode 100644
index c5042e3..0000000
--- a/contrib/tcpdump/tests/eapon1.out
+++ /dev/null
@@ -1,114 +0,0 @@
-IP 192.168.1.249.netbios-dgm > 192.168.1.255.netbios-dgm: NBT UDP PACKET(138)
-IP 192.168.1.249.netbios-dgm > 192.168.1.255.netbios-dgm: NBT UDP PACKET(138)
-IP 192.168.1.249.netbios-dgm > 192.168.1.255.netbios-dgm: NBT UDP PACKET(138)
-IP 192.168.1.249.netbios-ns > 192.168.1.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-IP 192.168.1.249.netbios-ns > 192.168.1.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-IP 192.168.1.249.netbios-ns > 192.168.1.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-IP 192.168.1.249.netbios-dgm > 192.168.1.255.netbios-dgm: NBT UDP PACKET(138)
-IP 192.168.1.249.netbios-ns > 192.168.1.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-IP 192.168.1.249.netbios-ns > 192.168.1.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-IP 192.168.1.249.netbios-ns > 192.168.1.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-arp who-has 192.168.1.1 tell 192.168.1.249
-arp reply 192.168.1.1 is-at 00:0d:88:4f:25:91 (oui Unknown)
-IP 192.168.1.249.bootpc > 192.168.1.1.bootps: BOOTP/DHCP, Request from 00:04:23:57:a5:7a (oui Unknown), length: 300
-EAP code=1 id=0 length=5
-IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:04:23:57:a5:7a (oui Unknown), length: 300
-IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:04:23:57:a5:7a (oui Unknown), length: 300
-EAP code=1 id=1 length=0
-EAP code=1 id=0 length=5
-EAP code=1 id=0 length=45
-EAP code=1 id=0 length=20
-EAP code=1 id=0 length=76
-EAP code=1 id=0 length=80
-EAP code=1 id=0 length=28
-EAP code=1 id=0 length=4
-EAP code=1 id=3 length=57
-EAP code=1 id=3 length=44
-IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:04:23:57:a5:7a (oui Unknown), length: 300
-IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:04:23:57:a5:7a (oui Unknown), length: 300
-IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:04:23:57:a5:7a (oui Unknown), length: 300
-EAP code=1 id=1 length=0
-EAP code=1 id=0 length=5
-EAP code=1 id=0 length=45
-EAP code=1 id=0 length=20
-EAP code=1 id=0 length=76
-EAP code=1 id=0 length=80
-EAP code=1 id=0 length=28
-EAP code=1 id=0 length=4
-EAP code=1 id=3 length=57
-EAP code=1 id=3 length=44
-arp who-has 169.254.67.194 tell 169.254.67.194
-arp who-has 169.254.67.194 tell 169.254.67.194
-arp who-has 169.254.67.194 tell 169.254.67.194
-IP 169.254.67.194.4299 > 239.255.255.250.1900: UDP, length 133
-IP 169.254.67.194 > IGMP: igmp v3 report, 1 group record(s)
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194 > IGMP: igmp v3 report, 1 group record(s)
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:04:23:57:a5:7a (oui Unknown), length: 300
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.4299 > 239.255.255.250.1900: UDP, length 133
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-EAP code=1 id=1 length=0
-EAP code=1 id=0 length=5
-EAP code=1 id=0 length=45
-EAP code=1 id=0 length=20
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-EAP code=1 id=0 length=76
-EAP code=1 id=0 length=80
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-EAP code=1 id=0 length=28
-EAP code=1 id=0 length=4
-EAP code=1 id=3 length=57
-EAP code=1 id=3 length=44
-IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:04:23:57:a5:7a (oui Unknown), length: 300
-IP 169.254.67.194.4299 > 239.255.255.250.1900: UDP, length 133
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:04:23:57:a5:7a (oui Unknown), length: 300
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): REGISTRATION; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-IP 169.254.67.194.netbios-ns > 169.254.255.255.netbios-ns: NBT UDP PACKET(137): QUERY; REQUEST; BROADCAST
-IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:04:23:57:a5:7a (oui Unknown), length: 300
-EAP code=1 id=1 length=0
-EAP code=1 id=0 length=5
-EAP code=1 id=0 length=45
-EAP code=1 id=0 length=20
-IP 169.254.67.194.netbios-dgm > 169.254.255.255.netbios-dgm: NBT UDP PACKET(138)
-EAP code=1 id=0 length=76
-EAP code=1 id=0 length=80
-EAP code=1 id=0 length=28
-EAP code=1 id=0 length=4
-EAP code=1 id=3 length=57
-EAP code=1 id=3 length=44
diff --git a/contrib/tcpdump/tests/eapon1.puu b/contrib/tcpdump/tests/eapon1.puu
deleted file mode 100644
index 25c1436..0000000
--- a/contrib/tcpdump/tests/eapon1.puu
+++ /dev/null
@@ -1,368 +0,0 @@
-begin 644 eapon1.pcap
-MU,.RH0(`!````````````/__```!````"%5@0)*@#@#=````W0```/______
-M_P`$(U>E>@@`10``SSB'``"`$7Q.P*@!^<"H`?\`B@"*`+M3[!$.B1W`J`'Y
-M`(H`I0``($5%14M&041*1$9&1$1!14M#04-!0T%#04-!0T%#04%!`"!%0D9#
-M14-%1D5*1D5&1$5(1D-&1D9!1D%%1D-!0T%!00#_4TU")0``````````````
-M`````````````````````!$```L```````````#H`P``````````"P!6``,`
-M`0`!``(`'`!<34%)3%-,3U1<0E)/5U-%``(`1$I0.353,$H`"%5@0/2@#@#=
-M````W0```/_______P`$(U>E>@@`10``SSB(``"`$7Q-P*@!^<"H`?\`B@"*
-M`+L,\A$.B1[`J`'Y`(H`I0``($5%14M&041*1$9&1$1!14M#04-!0T%#04-!
-M0T%#04%!`"!!0D%#1E!&4$5.1D1%0T9#15!&2$9$149&4$9004-!0@#_4TU"
-M)0```````````````````````````````````!$```L```````````#H`P``
-M````````"P!6``,``0`!``(`'`!<34%)3%-,3U1<0E)/5U-%``(`1$I0.353
-M,$H`"%5@0("C#@#[````^P```/_______P`$(U>E>@@`10``[3B)``"`$7PN
-MP*@!^<"H`?\`B@"*`-E#WA$.B1_`J`'Y`(H`PP``($5%14M&041*1$9&1$1!
-M14M#04-!0T%#04-!0T%#04%!`"!!0D%#1E!&4$5.1D1%0T9#15!&2$9$149&
-M4$9004-!0@#_4TU")0```````````````````````````````````!$``"D`
-M``````````#H`P``````````*0!6``,``0`!``(`.@!<34%)3%-,3U1<0E)/
-M5U-%``P`8.H``$%20D5)5%-'4E504$4``0`#"@`0`(!,_@0#1$I0.353,$H`
-M"%5@0/JI#@!<````7````/_______P`$(U>E>@@`10``3CB*``"`$7S,P*@!
-M^<"H`?\`B0")`#J"=XDA`1```0```````"!%0D9#14-%1D5*1D5&1$5(1D-&
-M1D9!1D%%1D-!0T%"3```(``!"55@0//8"@!<````7````/_______P`$(U>E
-M>@@`10``3CB-``"`$7S)P*@!^<"H`?\`B0")`#J"=XDA`1```0```````"!%
-M0D9#14-%1D5*1D5&1$5(1D-&1D9!1D%%1D-!0T%"3```(``!"E5@0+,)!P!<
-M````7````/_______P`$(U>E>@@`10``3CB.``"`$7S(P*@!^<"H`?\`B0")
-M`#J"=XDA`1```0```````"!%0D9#14-%1D5*1D5&1$5(1D-&1D9!1D%%1D-!
-M0T%"3```(``!"E5@0,@N#`#S````\P```/_______P`$(U>E>@@`10``Y3B/
-M``"`$7PPP*@!^<"H`?\`B@"*`-'GIA$.B2+`J`'Y`(H`NP``($5%14M&041*
-M1$9&1$1!14M#04-!0T%#04-!0T%#04-!`"!%0D9#14-%1D5*1D5&1$5(1D-&
-M1D9!1D%%1D-!0T%"3P#_4TU")0``````````````````````````````````
-M`!$``"$```````````#H`P``````````(0!6``,``0````(`,@!<34%)3%-,
-M3U1<0E)/5U-%``\`@/P*`$1*4#DU4S!*``!R`&\`<P`%`0,0!0`/`56J``U5
-M8$!5%0<`7````%P```#_______\`!"-7I7H(`$4``$XXE```@!%\PL"H`?G`
-MJ`'_`(D`B0`Z@G")*`$0``$````````@14)&0T5#149%2D9%1D1%2$9#1D9&
-M049!149#04-!0DP``"```0Y58$`>10,`7````%P```#_______\`!"-7I7H(
-M`$4``$XXE0``@!%\P<"H`?G`J`'_`(D`B0`Z@G")*`$0``$````````@14)&
-M0T5#149%2D9%1D1%2$9#1D9&049!149#04-!0DP``"```0Y58$!0N`X`7```
-M`%P```#_______\`!"-7I7H(`$4``$XXE@``@!%\P,"H`?G`J`'_`(D`B0`Z
-M@G")*`$0``$````````@14)&0T5#149%2D9%1D1%2$9#1D9&049!149#04-!
-M0DP``"```0]58$#*.`<`*@```"H```#_______\`!"-7I7H(!@`!"``&!``!
-M``0C5Z5ZP*@!^0```````,"H`0$/56!`%UD'`#P````\``````0C5Z5Z``V(
-M3R61"`8``0@`!@0``@`-B$\ED<"H`0$`!"-7I7K`J`'Y````````````````
-M````````#U5@0"E9!P!6`0``5@$````-B$\ED0`$(U>E>@@`10`!2#B7``"`
-M$7S#P*@!^<"H`0$`1`!#`31YVP$!!@#(+24]CP&``,"H`?D`````````````
-M````!"-7I7H`````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````8X)38S4!!S8$P*@!`3T'
-M`0`$(U>E>O\`````````````````````````````````````````````````
-M``````]58$`6@0D`/````#P`````!"-7I7H`#,Z(,9J(C@$```4!`0`%`0``
-M```````````````````````````````````````````````/56!`"BL*`%8!
-M``!6`0``________``0C5Z5Z"`!%``%(.)\``(`1`0<`````_____P!$`$,!
-M-,&K`0$&`)@7ASP````````````````````````````$(U>E>@``````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````!C@E-C-0$!=`$!/0<!``0C5Z5Z,@3`J`'Y#`A$2E`Y
-M-5,P2CP(35-&5"`U+C`W"P$/`P8L+B\?(?DK_P``````#U5@0![^#`!6`0``
-M5@$``/_______P`$(U>E>@@`10`!2#BA``"`$0$%`````/____\`1`!#`32.
-MS0$!!@#5`WTN````````````````````````````!"-7I7H`````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````8X)38S4!`70!`3T'`0`$(U>E>C($P*@!^0P(1$I0.353
-M,$H\"$U31E0@-2XP-PL!#P,&+"XO'R'Y*_\``````!!58$"$8P(`$P```!,`
-M````#,Z(,9H`!"-7I7J(C@$!````$%5@0.IK`@`\````/``````$(U>E>@`,
-MSH@QFHB.`0``!0$"``4!````````````````````````````````````````
-M`````````!%58$!>L`L`/P```#\`````#,Z(,9H`!"-7I7J(C@$``"T"`@`M
-M`3$R.34P,C,X,C`P,#4S.3%`;6YC,#(S+FUC8S(Y-2YO=VQA;BYO<F<156!`
-M81`,`#P````\``````0C5Z5Z``S.B#&:B(X!```4`1``%!(*```/`@`"``$`
-M`!$!`0``````````````````````````````$55@0,VL#`!>````7@`````,
-MSH@QF@`$(U>E>HB.`0``3`(0`$P2"@``#@L`*#$R.34P,C,X,C`P,#4S.3%`
-M;6YC,#(S+FUC8S(Y-2YO=VQA;BYO<F<'!0``XM+Y<LO)&X'VQ\&EG)_*XA`!
-M``$156!`P?(,`&(```!B``````0C5Z5Z``S.B#&:B(X!``!0`1$`4!(+```!
-M#0``,````````````````````#$````````````````````R````````````
-M````````"P4``.OTCH!BE[/.*TUX]HB,9O8256!`LQD*`"X````N``````S.
-MB#&:``0C5Z5ZB(X!```<`A$`'!(+```+!0``#*NYLZ2O7U"%636?B,5I[A)5
-M8$`H=0H`/````#P`````!"-7I7H`#,Z(,9J(C@$```0#```$````````````
-M```````````````````````````````````````256!`%GD*`$L```!+````
-M``0C5Z5Z``S.B#&:B(X!`P`Y`0`-``!`8%41`)MJNAB%#R>L.*X:RH)3A8\F
-M`ET1,5U'QWV%1Z`@V,N=24.:\=%3TKI<SV/#HB:X$E5@0$Y\"@`^````/@``
-M```$(U>E>@`,SH@QFHB.`0,`+`$`#0``0&!5$0"<E?@]+KE3IY6RR"$-=DAO
-M3H-QX7H>=&X[D=]]>4;W^,JD$U5@0*@!#0!6`0``5@$``/_______P`$(U>E
-M>@@`10`!2#BG``"`$0#_`````/____\`1`!#`30ES`$!!@#5`WTN:0$`````
-M````````````````````!"-7I7H`````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````8X)3
-M8S4!`70!`3T'`0`$(U>E>C($P*@!^0P(1$I0.353,$H\"$U31E0@-2XP-PL!
-M#P,&+"XO'R'Y*_\``````!I58$#O`@T`5@$``%8!``#_______\`!"-7I7H(
-M`$4``4@XKP``@!$`]P````#_____`$0`0P$T)<P!`08`U0-]+FD!````````
-M``````````````````0C5Z5Z````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````````````````````````````````````&."4V,U
-M`0%T`0$]!P$`!"-7I7HR!,"H`?D,"$1*4#DU4S!*/`A-4T94(#4N,#<+`0\#
-M!BPN+Q\A^2O_```````J56!`^P(-`%8!``!6`0``________``0C5Z5Z"`!%
-M``%(.+(``(`1`/0`````_____P!$`$,!-"7,`0$&`-4#?2YI`0``````````
-M```````````````$(U>E>@``````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M``````````````````````````````````````````````````!C@E-C-0$!
-M=`$!/0<!``0C5Z5Z,@3`J`'Y#`A$2E`Y-5,P2CP(35-&5"`U+C`W"P$/`P8L
-M+B\?(?DK_P``````,%5@0.B$"@`3````$P`````,SH@QF@`$(U>E>HB.`0$`
-M```P56!`^J$*`#P````\``````0C5Z5Z``S.B#&:B(X!```%`0,`!0$`````
-M````````````````````````````````````````````,%5@0)SA"@`_````
-M/P`````,SH@QF@`$(U>E>HB.`0``+0(#`"T!,3(Y-3`R,S@R,#`P-3,Y,4!M
-M;F,P,C,N;6-C,CDU+F]W;&%N+F]R9S!58$#0!`P`/````#P`````!"-7I7H`
-M#,Z(,9J(C@$``!0!+P`4$@H```\"``(``0``$0$!````````````````````
-M```````````R56!`-$(%`%X```!>``````S.B#&:``0C5Z5ZB(X!``!,`B\`
-M3!(*```."P`H,3(Y-3`R,S@R,#`P-3,Y,4!M;F,P,C,N;6-C,CDU+F]W;&%N
-M+F]R9P<%``#7H!![\\SE,P[&']$W6C<%$`$``3)58$#,.`<`8@```&(`````
-M!"-7I7H`#,Z(,9J(C@$``%`!,`!0$@L```$-```P````````````````````
-M,0```````````````````#(````````````````````+!0``0WL?0G!%;49D
-M0(DL@MD'#C-58$!S4P(`+@```"X`````#,Z(,9H`!"-7I7J(C@$``!P",``<
-M$@L```L%``!%[_\P8H+&6U!$B#@$)T-",U5@0"'6`P`\````/``````$(U>E
-M>@`,SH@QFHB.`0``!`,```0`````````````````````````````````````
-M`````````````#-58$!=V@,`2P```$L`````!"-7I7H`#,Z(,9J(C@$#`#D!
-M``T``$!@53$`G7]!<++?0.3Y>#A83O[YHHT"0T@&N\)FL/6P9NHATX%<E?[@
-M45S@"_@>BIRI%B`S56!`F-T#`#X````^``````0C5Z5Z``S.B#&:B(X!`P`L
-M`0`-``!`8%4Q`)[N$`!R;$K*.XLG`JO9N"A#@XK>5*[_:U"C]E[O?""IR!5+
-M56!`]Q(-`"H````J````________``0C5Z5Z"`8``0@`!@0``0`$(U>E>JG^
-M0\(```````"I_D/"2U5@0'&!#0`J````*@```/_______P`$(U>E>@@&``$(
-M``8$``$`!"-7I7JI_D/"````````J?Y#PDQ58$`X@@T`*@```"H```#_____
-M__\`!"-7I7H(!@`!"``&!``!``0C5Z5ZJ?Y#P@```````*G^0\)-56!`*=H-
-M`*\```"O`````0!>?__Z``0C5Z5Z"`!%``"A.+X```$1HM.I_D/"[___^A#+
-M!VP`C6+X32U314%20T@@*B!(5%10+S$N,0T*2&]S=#HR,SDN,C4U+C(U-2XR
-M-3`Z,3DP,`T*4U0Z=7)N.G-C:&5M87,M=7!N<"UO<F<Z9&5V:6-E.DEN=&5R
-M;F5T1V%T97=A>41E=FEC93HQ#0I-86XZ(G-S9'`Z9&ES8V]V97(B#0I-6#HS
-M#0H-"DU58$"\Y`T`-@```#8````!`%X``!8`!"-7I7H(`$8``"@XP````0(>
-M.:G^0\+@```6E`0``"(`Z@,````!!````.____I-56!`OK4.`&X```!N````
-M________``0C5Z5Z"`!%``!@.,(``(`1:@RI_D/"J?[__P")`(D`3+4(B2XI
-M$``!```````!($5%14M&041*1$9&1$1!14M#04-!0T%#04-!0T%#04%!```@
-M``'`#``@``$`!)/@``9@`*G^0\).56!`!H\*`#8````V`````0!>```6``0C
-M5Z5Z"`!&```H.,0```$"'C6I_D/"X```%I0$```B`.H#`````00```#O___Z
-M3E5@0!3E"@!N````;@```/_______P`$(U>E>@@`10``8#C%``"`$6H)J?Y#
-MPJG^__\`B0")`$RU"(DN*1```0```````2!%145+1D%$2D1&1D1$045+0T%#
-M04-!0T%#04-!0T%!00``(``!P`P`(``!``23X``&8`"I_D/"3U5@0#,6!P!N
-M````;@```/_______P`$(U>E>@@`10``8#C&``"`$6H(J?Y#PJG^__\`B0")
-M`$RU"(DN*1```0```````2!%145+1D%$2D1&1D1$045+0T%#04-!0T%#04-!
-M0T%!00``(``!P`P`(``!``23X``&8`"I_D/"3U5@0*^U#0!6`0``5@$``/__
-M_____P`$(U>E>@@`10`!2#C'``"`$0#?`````/____\`1`!#`325:P$!!@"2
-M13E.``"`````````````````````````!"-7I7H`````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````8X)38S4!`70!`3T'`0`$(U>E>C($P*@!^0P(1$I0.353,$H\"$U3
-M1E0@-2XP-PL!#P,&+"XO'R'Y*_\``````%!58$`T1P,`;@```&X```#_____
-M__\`!"-7I7H(`$4``&`XR```@!%J!JG^0\*I_O__`(D`B0!,M@B)+B@0``$`
-M``````$@145%2T9!1$I$1D9$1$%%2T-!0T%#04-!0T%#04-!04$``"```<`,
-M`"```0`$D^``!F``J?Y#PE!58$",WPT`KP```*\````!`%Y___H`!"-7I7H(
-M`$4``*$XR@```1&BQZG^0\+O___Z$,L';`"-8OA-+5-%05)#2"`J($A45%`O
-M,2XQ#0I(;W-T.C(S.2XR-34N,C4U+C(U,#HQ.3`P#0I35#IU<FXZ<V-H96UA
-M<RUU<&YP+6]R9SID979I8V4Z26YT97)N971'871E=V%Y1&5V:6-E.C$-"DUA
-M;CHB<W-D<#ID:7-C;W9E<B(-"DU8.C,-"@T*4%5@0`"\#@!N````;@```/__
-M_____P`$(U>E>@@`10``8#C,``"`$6H"J?Y#PJG^__\`B0")`$PP]8DO*1``
-M`0```````2!%0D9#14-%1D5*1D5&1$5(1D-&1D9!1D%%1D-!0T%!00``(``!
-MP`P`(``!``23X``&X`"I_D/"455@0#/A`P`3````$P`````,SH@QF@`$(U>E
-M>HB.`0$```!156!`8>D#`#P````\``````0C5Z5Z``S.B#&:B(X!```%`00`
-M!0$`````````````````````````````````````````````````455@0+TU
-M!``_````/P`````,SH@QF@`$(U>E>HB.`0``+0($`"T!,3(Y-3`R,S@R,#`P
-M-3,Y,4!M;F,P,C,N;6-C,CDU+F]W;&%N+F]R9U%58$#Y[@4`/````#P`````
-M!"-7I7H`#,Z(,9J(C@$``!0!4``4$@H```\"``(``0``$0$!````````````
-M``````````````````!156!`9.L*`&X```!N````________``0C5Z5Z"`!%
-M``!@.,T``(`1:@&I_D/"J?[__P")`(D`3##UB2\I$``!```````!($5"1D-%
-M0T5&14I&149$14A&0T9&1D%&045&0T%#04%!```@``'`#``@``$`!)/@``;@
-M`*G^0\)256!`71P'`&X```!N````________``0C5Z5Z"`!%``!@.,X``(`1
-M:@"I_D/"J?[__P")`(D`3##UB2\I$``!```````!($5"1D-%0T5&14I&149$
-M14A&0T9&1D%&045&0T%#04%!```@``'`#``@``$`!)/@``;@`*G^0\)256!`
-M9[(.`%X```!>``````S.B#&:``0C5Z5ZB(X!``!,`E``3!(*```."P`H,3(Y
-M-3`R,S@R,#`P-3,Y,4!M;F,P,C,N;6-C,CDU+F]W;&%N+F]R9P<%```Z)]TL
-M?V'JYOR&8?J))U]%$`$``5)58$`"$P\`8@```&(`````!"-7I7H`#,Z(,9J(
-MC@$``%`!40!0$@L```$-```P````````````````````,0``````````````
-M`````#(````````````````````+!0``*IFHOZ$\8[TX!>!F]%P6:%-58$!8
-M30,`;@```&X```#_______\`!"-7I7H(`$4``&`XSP``@!%I_ZG^0\*I_O__
-M`(D`B0!,,?6)+R@0``$```````$@14)&0T5#149%2D9%1D1%2$9#1D9&049!
-M149#04-!04$``"```<`,`"```0`$D^``!N``J?Y#PE-58$#M3`H`+@```"X`
-M````#,Z(,9H`!"-7I7J(C@$``!P"40`<$@L```L%``#BE(K>$<9]M,I(_@G,
-MC).Y4U5@0`*="@`\````/``````$(U>E>@`,SH@QFHB.`0``!`,```0`````
-M`````````````````````````````````````````````%-58$#CH`H`2P``
-M`$L`````!"-7I7H`#,Z(,9J(C@$#`#D!``T``$!@55(`GZN0MGOEA8[@4WO*
-M&_11@$@"&2ZIH`.YHY==8)$_%6#R:U/Z"F'14BLDK,Z)I:%356!`&*0*`#X`
-M```^``````0C5Z5Z``S.B#&:B(X!`P`L`0`-``!`8%52`*!&UK1?K<RECIT@
-MY'<O#NGZ@YJ^O,Y@JP;?M,0[/;M1?PY356!`9+H-`%8!``!6`0``________
-M``0C5Z5Z"`!%``%(.-```(`1`-8`````_____P!$`$,!-&QJ`0$&`))%.4XI
-M`8`````````````````````````$(U>E>@``````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M``!C@E-C-0$!=`$!/0<!``0C5Z5Z,@3`J`'Y#`A$2E`Y-5,P2CP(35-&5"`U
-M+C`W"P$/`P8L+B\?(?DK_P``````4U5@0)?A#0"O````KP````$`7G__^@`$
-M(U>E>@@`10``H3C2```!$:*_J?Y#PN____H0RP=L`(UB^$TM4T5!4D-(("H@
-M2%144"\Q+C$-"DAO<W0Z,C,Y+C(U-2XR-34N,C4P.C$Y,#`-"E-4.G5R;CIS
-M8VAE;6%S+75P;G`M;W)G.F1E=FEC93I);G1E<FYE=$=A=&5W87E$979I8V4Z
-M,0T*36%N.B)S<V1P.F1I<V-O=F5R(@T*35@Z,PT*#0I356!`N<(.`&X```!N
-M````________``0C5Z5Z"`!%``!@.-0``(`1:?JI_D/"J?[__P")`(D`3+4$
-MB3`I$``!```````!($5%14M&041*1$9&1$1!14M#04-!0T%#04-!0T%#04-!
-M```@``'`#``@``$`!)/@``9@`*G^0\)356!`V,0.`&X```!N````________
-M``0C5Z5Z"`!%``!@.-4``(`1:?FI_D/"J?[__P")`(D`3"+RB3$I$``!````
-M```!($5"1D-%0T5&14I&149$14A&0T9&1D%&045&0T%#04)/```@``'`#``@
-M``$`!)/@``;@`*G^0\)456!`C/$*`&X```!N````________``0C5Z5Z"`!%
-M``!@.-@``(`1:?:I_D/"J?[__P")`(D`3+4$B3`I$``!```````!($5%14M&
-M041*1$9&1$1!14M#04-!0T%#04-!0T%#04-!```@``'`#``@``$`!)/@``9@
-M`*G^0\)456!`4?4*`&X```!N````________``0C5Z5Z"`!%``!@.-D``(`1
-M:?6I_D/"J?[__P")`(D`3"+RB3$I$``!```````!($5"1D-%0T5&14I&149$
-M14A&0T9&1D%&045&0T%#04)/```@``'`#``@``$`!)/@``;@`*G^0\)556!`
-MB2('`&X```!N````________``0C5Z5Z"`!%``!@.-H``(`1:?2I_D/"J?[_
-M_P")`(D`3+4$B3`I$``!```````!($5%14M&041*1$9&1$1!14M#04-!0T%#
-M04-!0T%#04-!```@``'`#``@``$`!)/@``9@`*G^0\)556!`328'`&X```!N
-M````________``0C5Z5Z"`!%``!@.-L``(`1:?.I_D/"J?[__P")`(D`3"+R
-MB3$I$``!```````!($5"1D-%0T5&14I&149$14A&0T9&1D%&045&0T%#04)/
-M```@``'`#``@``$`!)/@``;@`*G^0\)656!`?%,#`&X```!N````________
-M``0C5Z5Z"`!%``!@.-P``(`1:?*I_D/"J?[__P")`(D`3+8$B3`H$``!````
-M```!($5%14M&041*1$9&1$1!14M#04-!0T%#04-!0T%#04-!```@``'`#``@
-M``$`!)/@``9@`*G^0\)656!`1E<#`&X```!N````________``0C5Z5Z"`!%
-M``!@.-T``(`1:?&I_D/"J?[__P")`(D`3"/RB3$H$``!```````!($5"1D-%
-M0T5&14I&149$14A&0T9&1D%&045&0T%#04)/```@``'`#``@``$`!)/@``;@
-M`*G^0\)656!`R<P.`-T```#=````________``0C5Z5Z"`!%``#/..,``(`1
-M:7RI_D/"J?[__P"*`(H`NPE!$0Z),JG^0\(`B@"E```@145%2T9!1$I$1D9$
-M1$%%2T-!0T%#04-!0T%#04-!04$`($5"1D-%0T5&14I&149$14A&0T9&1D%&
-M045&0T%#04).`/]334(E````````````````````````````````````$0``
-M"P```````````.@#```````````+`%8``P`!``$``@`<`%Q-04E,4TQ/5%Q"
-M4D]74T4``@!$2E`Y-5,P2@!656!`W<T.`/,```#S````________``0C5Z5Z
-M"`!%``#E..0``(`1:66I_D/"J?[__P"*`(H`T1`"$0Z),ZG^0\(`B@"[```@
-M145%2T9!1$I$1D9$1$%%2T-!0T%#04-!0T%#04-!0T$`($5"1D-%0T5&14I&
-M149$14A&0T9&1D%&045&0T%#04).`/]334(E````````````````````````
-M````````````$0``(0```````````.@#```````````A`%8``P`!`````@`R
-M`%Q-04E,4TQ/5%Q"4D]74T4``0"`_`H`1$I0.353,$H````````!``4!`Q`!
-M``\!5:H`6%5@0+\L!P#=````W0```/_______P`$(U>E>@@`10``SSCF``"`
-M$6EYJ?Y#PJG^__\`B@"*`+L)/1$.B3:I_D/"`(H`I0``($5%14M&041*1$9&
-M1$1!14M#04-!0T%#04-!0T%#04%!`"!%0D9#14-%1D5*1D5&1$5(1D-&1D9!
-M1D%%1D-!0T%"3@#_4TU")0```````````````````````````````````!$`
-M``L```````````#H`P``````````"P!6``,``0`!``(`'`!<34%)3%-,3U1<
-M0E)/5U-%``(`1$I0.353,$H`655@0.K0#@#=````W0```/_______P`$(U>E
-M>@@`10``SSCG``"`$6EXJ?Y#PJG^__\`B@"*`+L)/!$.B3>I_D/"`(H`I0``
-M($5%14M&041*1$9&1$1!14M#04-!0T%#04-!0T%#04%!`"!%0D9#14-%1D5*
-M1D5&1$5(1D-&1D9!1D%%1D-!0T%"3@#_4TU")0``````````````````````
-M`````````````!$```L```````````#H`P``````````"P!6``,``0`!``(`
-M'`!<34%)3%-,3U1<0E)/5U-%``(`1$I0.353,$H`6U5@0-@R!P#=````W0``
-M`/_______P`$(U>E>@@`10``SSCH``"`$6EWJ?Y#PJG^__\`B@"*`+L).Q$.
-MB3BI_D/"`(H`I0``($5%14M&041*1$9&1$1!14M#04-!0T%#04-!0T%#04%!
-M`"!%0D9#14-%1D5*1D5&1$5(1D-&1D9!1D%%1D-!0T%"3@#_4TU")0``````
-M`````````````````````````````!$```L```````````#H`P``````````
-M"P!6``,``0`!``(`'`!<34%)3%-,3U1<0E)/5U-%``(`1$I0.353,$H`7%5@
-M0"2]#0!6`0``5@$``/_______P`$(U>E>@@`10`!2#CI``"`$0"]`````/__
-M__\`1`!#`31L:@$!!@"213E.*0&`````````````````````````!"-7I7H`
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````8X)38S4!`70!`3T'`0`$(U>E>C($P*@!
-M^0P(1$I0.353,$H\"$U31E0@-2XP-PL!#P,&+"XO'R'Y*_\``````%Q58$`#
-MUPX`Z0```.D```#_______\`!"-7I7H(`$4``-LXZ@``@!%I::G^0\*I_O__
-M`(H`B@#';@L1#HDYJ?Y#P@"*`+$``"!%145+1D%$2D1&1D1$045+0T%#04-!
-M0T%#04-!0T%!00`@14)&0T5#149%2D9%1D1%2$9#1D9&049!149#04-!0D\`
-M_U--0B4````````````````````````````````````1```7````````````
-MZ`,``````````!<`5@`#``$``0`"`"@`7$U!24Q33$]47$)23U=310`(`2`/
-M`1!9L1D5`````$1*4#DU4S!*`%U58$#/UPX`Z0```.D```#_______\`!"-7
-MI7H(`$4``-LXZP``@!%I:*G^0\*I_O__`(H`B@#';@H1#HDZJ?Y#P@"*`+$`
-M`"!%145+1D%$2D1&1D1$045+0T%#04-!0T%#04-!0T%!00`@14)&0T5#149%
-M2D9%1D1%2$9#1D9&049!149#04-!0D\`_U--0B4`````````````````````
-M```````````````1```7````````````Z`,``````````!<`5@`#``$``0`"
-M`"@`7$U!24Q33$]47$)23U=310`(`2`/`1!9L1D5`````$1*4#DU4S!*`%Y5
-M8$"+V`X`Z0```.D```#_______\`!"-7I7H(`$4``-LX[```@!%I9ZG^0\*I
-M_O__`(H`B@#';@D1#HD[J?Y#P@"*`+$``"!%145+1D%$2D1&1D1$045+0T%#
-M04-!0T%#04-!0T%!00`@14)&0T5#149%2D9%1D1%2$9#1D9&049!149#04-!
-M0D\`_U--0B4````````````````````````````````````1```7````````
-M````Z`,``````````!<`5@`#``$``0`"`"@`7$U!24Q33$]47$)23U=310`(
-M`2`/`1!9L1D5`````$1*4#DU4S!*`%]58$!)V0X`Z0```.D```#_______\`
-M!"-7I7H(`$4``-LX[0``@!%I9JG^0\*I_O__`(H`B@#';@@1#HD\J?Y#P@"*
-M`+$``"!%145+1D%$2D1&1D1$045+0T%#04-!0T%#04-!0T%!00`@14)&0T5#
-M149%2D9%1D1%2$9#1D9&049!149#04-!0D\`_U--0B4`````````````````
-M```````````````````1```7````````````Z`,``````````!<`5@`#``$`
-M`0`"`"@`7$U!24Q33$]47$)23U=310`(`2`/`1!9L1D5`````$1*4#DU4S!*
-M`&!58$"CV@X`;@```&X```#_______\`!"-7I7H(`$4``&`X[@``@!%IX*G^
-M0\*I_O__`(D`B0!,H^:)/2D0``$```````$@14)&0T5#149%2D9%1D1%2$9#
-M1D9&049!149#04-!0DX``"```<`,`"```0`$D^``!F``J?Y#PF%58$#F"@L`
-M;@```&X```#_______\`!"-7I7H(`$4``&`X[P``@!%IWZG^0\*I_O__`(D`
-MB0!,H^:)/2D0``$```````$@14)&0T5#149%2D9%1D1%2$9#1D9&049!149#
-M04-!0DX``"```<`,`"```0`$D^``!F``J?Y#PF)58$#?.P<`;@```&X```#_
-M______\`!"-7I7H(`$4``&`X\```@!%IWJG^0\*I_O__`(D`B0!,H^:)/2D0
-M``$```````$@14)&0T5#149%2D9%1D1%2$9#1D9&049!149#04-!0DX``"``
-M`<`,`"```0`$D^``!F``J?Y#PF-58$#9;`,`;@```&X```#_______\`!"-7
-MI7H(`$4``&`X\P``@!%IVZG^0\*I_O__`(D`B0!,I.:)/2@0``$```````$@
-M14)&0T5#149%2D9%1D1%2$9#1D9&049!149#04-!0DX``"```<`,`"```0`$
-MD^``!F``J?Y#PF-58$"'X`X`;@```&X```#_______\`!"-7I7H(`$4``&`X
-M]```@!%IVJG^0\*I_O__`(D`B0!,Z>R)/BD0``$```````$@04)!0T901E!%
-M3D9$14-&0T501DA&1$5&1E!&4$%#04(``"```<`,`"```0`$D^``!N``J?Y#
-MPF158$`/$0L`;@```&X```#_______\`!"-7I7H(`$4``&`X]0``@!%IV:G^
-M0\*I_O__`(D`B0!,Z>R)/BD0``$```````$@04)!0T901E!%3D9$14-&0T50
-M1DA&1$5&1E!&4$%#04(``"```<`,`"```0`$D^``!N``J?Y#PF558$`&0@<`
-M;@```&X```#_______\`!"-7I7H(`$4``&`X]@``@!%IV*G^0\*I_O__`(D`
-MB0!,Z>R)/BD0``$```````$@04)!0T901E!%3D9$14-&0T501DA&1$5&1E!&
-M4$%#04(``"```<`,`"```0`$D^``!N``J?Y#PF958$#^<@,`;@```&X```#_
-M______\`!"-7I7H(`$4``&`X]P``@!%IUZG^0\*I_O__`(D`B0!,ZNR)/B@0
-M``$```````$@04)!0T901E!%3D9$14-&0T501DA&1$5&1E!&4$%#04(``"``
-M`<`,`"```0`$D^``!N``J?Y#PF958$!_Y@X`W0```-T```#_______\`!"-7
-MI7H(`$4``,\X^```@!%I9ZG^0\*I_O__`(H`B@"[%C41#HD_J?Y#P@"*`*4`
-M`"!%145+1D%$2D1&1D1$045+0T%#04-!0T%#04-!0T%!00`@14)&0T5#149%
-M2D9%1D1%2$9#1D9&049!149#04-!04$`_U--0B4`````````````````````
-M```````````````1```+````````````Z`,```````````L`5@`#``$``0`"
-M`!P`7$U!24Q33$]47$)23U=310`"`$1*4#DU4S!*`&958$!AYPX`W0```-T`
-M``#_______\`!"-7I7H(`$4``,\X^0``@!%I9JG^0\*I_O__`(H`B@"[SSH1
-M#HE`J?Y#P@"*`*4``"!%145+1D%$2D1&1D1$045+0T%#04-!0T%#04-!0T%!
-M00`@04)!0T901E!%3D9$14-&0T501DA&1$5&1E!&4$%#04(`_U--0B4`````
-M```````````````````````````````1```+````````````Z`,`````````
-M``L`5@`#``$``0`"`!P`7$U!24Q33$]47$)23U=310`"`$1*4#DU4S!*`&95
-M8$!PZ@X`^P```/L```#_______\`!"-7I7H(`$4``.TX^@``@!%I1ZG^0\*I
-M_O__`(H`B@#9)2,1#HE!J?Y#P@"*`,,``"!%145+1D%$2D1&1D1$045+0T%#
-M04-!0T%#04-!0T%!00`@04)!0T901E!%3D9$14-&0T501DA&1$5&1E!&4$%#
-M04(`_U--0B4````````````````````````````````````1```I````````
-M````Z`,``````````"D`5@`#``$``0`"`#H`7$U!24Q33$]47$)23U=310`,
-M`&#J``!!4D)%25131U)54%!%``$``PH`$`"`;/[%!D1*4#DU4S!*`&958$"4
-M\`X`7````%P```#_______\`!"-7I7H(`$4``$XX^P``@!%IY:G^0\*I_O__
-M`(D`B0`Z;]^)0P$0``$````````@14)&0T5#149%2D9%1D1%2$9#1D9&049!
-M149#04-!0DP``"```6=58$`('PL`7````%P```#_______\`!"-7I7H(`$4`
-M`$XX_```@!%IY*G^0\*I_O__`(D`B0`Z;]^)0P$0``$````````@14)&0T5#
-M149%2D9%1D1%2$9#1D9&049!149#04-!0DP``"```6A58$`&4`<`7````%P`
-M``#_______\`!"-7I7H(`$4``$XX_0``@!%IXZG^0\*I_O__`(D`B0`Z;]^)
-M0P$0``$````````@14)&0T5#149%2D9%1D1%2$9#1D9&049!149#04-!0DP`
-M`"```6M58$"J6P<`7````%P```#_______\`!"-7I7H(`$4``$XY`0``@!%I
-MWZG^0\*I_O__`(D`B0`Z;]N)1P$0``$````````@14)&0T5#149%2D9%1D1%
-M2$9#1D9&049!149#04-!0DP``"```6Q58$`-BP,`7````%P```#_______\`
-M!"-7I7H(`$4``$XY`@``@!%IWJG^0\*I_O__`(D`B0`Z;]N)1P$0``$`````
-M```@14)&0T5#149%2D9%1D1%2$9#1D9&049!149#04-!0DP``"```6Q58$!%
-M_@X`7````%P```#_______\`!"-7I7H(`$4``$XY!```@!%IW*G^0\*I_O__
-M`(D`B0`Z;]N)1P$0``$````````@14)&0T5#149%2D9%1D1%2$9#1D9&049!
-M149#04-!0DP``"```6U58$`7O@T`5@$``%8!``#_______\`!"-7I7H(`$4`
-M`4@Y!@``@!$`H`````#_____`$0`0P$T;&H!`08`DD4Y3BD!@```````````
-M``````````````0C5Z5Z````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M`````````````````````````````````````````````````&."4V,U`0%T
-M`0$]!P$`!"-7I7HR!,"H`?D,"$1*4#DU4S!*/`A-4T94(#4N,#<+`0\#!BPN
-M+Q\A^2O_``````!Q56!`]:$*`!,````3``````S.B#&:``0C5Z5ZB(X!`0``
-M`'%58$!%P`H`/````#P`````!"-7I7H`#,Z(,9J(C@$```4!!0`%`0``````
-M``````````````````````````````````````````!Q56!`C?4*`#\````_
-M``````S.B#&:``0C5Z5ZB(X!```M`@4`+0$Q,CDU,#(S.#(P,#`U,SDQ0&UN
-M8S`R,RYM8V,R.34N;W=L86XN;W)G<55@0/XV"P`\````/``````$(U>E>@`,
-MSH@QFHB.`0``%`%P`!02"@``#P(``@`!```1`0$`````````````````````
-M`````````')58$#=.0P`\P```/,```#_______\`!"-7I7H(`$4``.4Y#```
-M@!%I/:G^0\*I_O__`(H`B@#1\^D1#HE*J?Y#P@"*`+L``"!%145+1D%$2D1&
-M1D1$045+0T%#04-!0T%#04-!0T%#00`@14)&0T5#149%2D9%1D1%2$9#1D9&
-M049!149#04-!0D\`_U--0B4````````````````````````````````````1
-M```A````````````Z`,``````````"$`5@`#``$````"`#(`7$U!24Q33$]4
-M7$)23U=310`/`(#\"@!$2E`Y-5,P2@``60!<`%4`!0$#$`4`#P%5J@!S56!`
-MJ'L$`%X```!>``````S.B#&:``0C5Z5ZB(X!``!,`G``3!(*```."P`H,3(Y
-M-3`R,S@R,#`P-3,Y,4!M;F,P,C,N;6-C,CDU+F]W;&%N+F]R9P<%```)[DNV
-M]<TYOH8?&=*L`<`&$`$``7-58$#3Q`0`8@```&(`````!"-7I7H`#,Z(,9J(
-MC@$``%`!<0!0$@L```$-```P````````````````````,0``````````````
-M`````#(````````````````````+!0``4,1=:28,Y[A5';!-.W&=A7-58$"#
-M.0\`+@```"X`````#,Z(,9H`!"-7I7J(C@$``!P"<0`<$@L```L%``#,G3O*
-M(MF[ZP#.U#83NT:1=%5@0#-7```\````/``````$(U>E>@`,SH@QFHB.`0``
-M!`,```0``````````````````````````````````````````````````'15
-M8$`G6P``2P```$L`````!"-7I7H`#,Z(,9J(C@$#`#D!``T``$!@57(`H7=G
-MF]`<U=:Q_.ODF.0!O^<"RF-&L(?"6]$(GK,%9)J4;"'MPR]@Y#?:1B?;0,UT
-M56!`55X``#X````^``````0C5Z5Z``S.B#&:B(X!`P`L`0`-``!`8%5R`*(I
-@:.4"VF#:A*@Q;&CP#+\$@]3C#=%3<0P&M\#VWIK`IL$`
-`
-end
diff --git a/contrib/tcpdump/tests/eapon1.sh b/contrib/tcpdump/tests/eapon1.sh
deleted file mode 100755
index 1c8aa63..0000000
--- a/contrib/tcpdump/tests/eapon1.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-uudecode eapon1.puu
-
-echo -n test eapon1...
-../tcpdump -t -N -r eapon1.pcap > eapon1.new
-if diff eapon1.new eapon1.out
-then
- echo passed.
-else
- echo failed.
-fi
-
diff --git a/contrib/tcpdump/tests/eapon2.puu b/contrib/tcpdump/tests/eapon2.puu
deleted file mode 100644
index 70abb23..0000000
--- a/contrib/tcpdump/tests/eapon2.puu
+++ /dev/null
@@ -1,66 +0,0 @@
-begin 644 eapon2.pcap
-MU,.RH0(`!````````````&`````!````_E1@0(0`#`!"````0@`````+VY#]
-M`@#@3UR$8`@`11``-"500``W!O$4U8'_>L&:EKBMN@`6*6Y2?^.:F>V`$/C@
-M9C@```$!"`H974FMBM15+Q!58$!QG`8`8````.L`````"]N0_0(`X$]<A&`(
-M`$4``-TH'P``]A%NH=6!_WK!FI:X5(X'%`#)!M0!%`#!,KA08YA%<^E.@.W\
-MVGEAG@$J,3(Y-3`R,S@R,#`P-3,Y,4!M;F,P,C,N;6-C,CDU+F\056!``J0&
-M`&````"*```````,!ZR%``O;D/T""`!%``!\``!``$`1#2+!FI:XU8'_>@<4
-M5(X`:)P-"Q0`8$$!<I3L?-I\^CLZZ8W&J$<(!O____X,!@```D`&!@````)/
-M%@$0`!02"@``#P(``@`!$%5@0/N`!P!@````'`$````+VY#]`@#@3UR$8`@`
-M10`!#B@@``#V$6YOU8'_>L&:EKA4C@<4`/I,<`$5`/+M5G/\`0<0G:=Q]S4<
-MM<W1`2HQ,CDU,#(S.#(P,#`U,SDQ0&UN8S`R,RYM8V,R.34N;Q!58$"?AP<`
-M8````,8```````P'K(4`"]N0_0((`$4``+@``4``0!$,Y<&:EKC5@?]Z!Q14
-MC@"D*@T+%0"<GZ@ST?&@X&3DA[P+.!KY+@@&_____@P&```"0`8&`````D]2
-M`1$`4!(+```!#0``,``156!`QP`%`&````#L``````O;D/T"`.!/7(1@"`!%
-M``#>*"$``/81;I[5@?]ZP9J6N%2.!Q0`RHLB`18`PB*WG4W^01LM]B4XN&`'
-M6E(!*C$R.34P,C,X,C`P,#4S.3%`;6YC,#(S+FUC8S(Y-2YO$55@0!P&!0!@
-M````!@$`````#`>LA0`+VY#]`@@`10``^``"0`!`$0RDP9J6N-6!_WH'%%2.
-M`.2>DP(6`-P04TN>&O"\WL%@,.`1V142"`;____^#`8```)`!@8````"&CH`
-M``$W$32`+U<1;LS62B]58$!:H@8`8````.L`````"]N0_0(`X$]<A&`(`$4`
-M`-TH)```]A%NG-6!_WK!FI:X5(X'%`#)G_(!&`#!8I@\,J5DDRGEM>@M>A=G
-MB0$J,3(Y-3`R,S@R,#`P-3,Y,4!M;F,P,C,N;6-C,CDU+F\O56!`G*<&`&``
-M``"*```````,!ZR%``O;D/T""`!%``!\``-``$`1#1_!FI:XU8'_>@<45(X`
-M:#<F"Q@`8$VXJ\Z['F%^RCK?B4C^(6T(!O____X,!@```D`&!@````)/%@$O
-M`!02"@``#P(``@`!,55@0-S/`0!@````'`$````+VY#]`@#@3UR$8`@`10`!
-M#B@E``#V$6YJU8'_>L&:EKA4C@<4`/H2$P$9`/)6HP7H8R0(O<O]:/"4@0=%
-M`2HQ,CDU,#(S.#(P,#`U,SDQ0&UN8S`R,RYM8V,R.34N;S%58$!7U@$`8```
-M`,8```````P'K(4`"]N0_0((`$4``+@`!$``0!$,XL&:EKC5@?]Z!Q14C@"D
-MZ2,+&0"<(Y3XP!`C^NV)J[-Q+PU3"@@&_____@P&```"0`8&`````D]2`3``
-M4!(+```!#0``,``Q56!`$JX-`&````#L``````O;D/T"`.!/7(1@"`!%``#>
-M*"8``/81;IG5@?]ZP9J6N%2.!Q0`R@WC`1H`PCS/?&QHIT8SX.[2#=[S68H!
-M*C$R.34P,C,X,C`P,#4S.3%`;6YC,#(S+FUC8S(Y-2YO,55@0#VS#0!@````
-M!@$`````#`>LA0`+VY#]`@@`10``^``%0`!`$0RAP9J6N-6!_WH'%%2.`.3B
-MMP(:`-S*Z(?9H34)&AB0":D9<!O)"`;____^#`8```)`!@8````"&CH```$W
-M$321P=T3ADE-XU!58$"$D@``8````.L`````"]N0_0(`X$]<A&`(`$4``-TH
-M*```]A%NF-6!_WK!FI:X5(X'%`#)[%H!&P#!PB<W7,;1#%UAF"-V*ORC90$J
-M,3(Y-3`R,S@R,#`P-3,Y,4!M;F,P,C,N;6-C,CDU+F]056!`8I<``&````"*
-M```````,!ZR%``O;D/T""`!%``!\``9``$`1#1S!FI:XU8'_>@<45(X`:#0%
-M"QL`8(N:^N5L(EK&#H6-':U$XV((!O____X,!@```D`&!@````)/%@%0`!02
-M"@``#P(``@`!455@0*VL"0!@````'`$````+VY#]`@#@3UR$8`@`10`!#B@I
-M``#V$6YFU8'_>L&:EKA4C@<4`/KDFP$<`/+H$R8P9(B"W[^G<4!"HKQ+`2HQ
-M,CDU,#(S.#(P,#`U,SDQ0&UN8S`R,RYM8V,R.34N;U%58$"ZL@D`8````,8`
-M``````P'K(4`"]N0_0((`$4``+@`!T``0!$,W\&:EKC5@?]Z!Q14C@"DI=@+
-M'`"<G^$P>;*!>&FY;C?2/)T74`@&_____@P&```"0`8&`````D]2`5$`4!(+
-M```!#0``,`!256!`@SL%`&````#L``````O;D/T"`.!/7(1@"`!%``#>*"H`
-M`/81;I75@?]ZP9J6N%2.!Q0`RI"T`1T`PE:^P6JH@]U$D*!C#8CO0UP!*C$R
-M.34P,C,X,C`P,#4S.3%`;6YC,#(S+FUC8S(Y-2YO4E5@0'M`!0!@````!@$`
-M````#`>LA0`+VY#]`@@`10``^``(0`!`$0R>P9J6N-6!_WH'%%2.`.2<&@(=
-M`-P&]WGHNB++Z0K&A"^B<2S/"`;____^#`8```)`!@8````"&CH```$W$32F
-M=DT@&\D[/G!58$!OW04`8````.L`````"]N0_0(`X$]<A&`(`$4``-TH*P``
-M]A%NE=6!_WK!FI:X5(X'%`#)*:D!'@#!I[D+3?C+./K-`/>AS"W^P0$J,3(Y
-M-3`R,S@R,#`P-3,Y,4!M;F,P,C,N;6-C,CDU+F]P56!`L>(%`&````"*````
-M```,!ZR%``O;D/T""`!%``!\``E``$`1#1G!FI:XU8'_>@<45(X`:`.V"QX`
-M8+P/!*Y!RZ>(/:C.%/A62\((!O____X,!@```D`&!@````)/%@%P`!02"@``
-M#P(``@`!<55@0)*H#@!@````'`$````+VY#]`@#@3UR$8`@`10`!#B@L``#V
-M$6YCU8'_>L&:EKA4C@<4`/JLH@$?`/*.M".D<>M4,KL=.(:"[-F;`2HQ,CDU
-M,#(S.#(P,#`U,SDQ0&UN8S`R,RYM8V,R.34N;W%58$#$K@X`8````,8`````
-M``P'K(4`"]N0_0((`$4``+@`"D``0!$,W,&:EKC5@?]Z!Q14C@"DK7D+'P"<
-MMWVPJO:XC`JEY#15<5U0Z@@&_____@P&```"0`8&`````D]2`7$`4!(+```!
-M#0``,`!R56!`S#4*`&````#L``````O;D/T"`.!/7(1@"`!%``#>*"T``/81
-M;I+5@?]ZP9J6N%2.!Q0`RE>1`2``PK+"]?UCV]G1I<-+X16?0+L!*C$R.34P
-M,C,X,C`P,#4S.3%`;6YC,#(S+FUC8S(Y-2YO<E5@0,,Z"@!@````!@$`````
-M#`>LA0`+VY#]`@@`10``^``+0`!`$0R;P9J6N-6!_WH'%%2.`.1M%P(@`-PJ
-M=?H'6<1=UD&:FRVA,V+S"`;____^#`8```)`!@8````"&CH```$W$32RVRE=
-$I%P\00``
-`
-end
diff --git a/contrib/tcpdump/tests/esp-secrets.txt b/contrib/tcpdump/tests/esp-secrets.txt
deleted file mode 100644
index 81847a0..0000000
--- a/contrib/tcpdump/tests/esp-secrets.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-# a comment
-
-0x12345678@192.1.2.45 3des-cbc-hmac96:0x43434545464649494a4a4c4c4f4f51515252545457575840
-0xabcdabcd@192.0.1.1 3des-cbc-hmac96:0x434545464649494a4a4c4c4f4f5151525254545757584043
-0xd1234567@192.1.2.45 aes256-cbc-hmac96:0xaaaabbbbccccdddd4043434545464649494a4a4c4c4f4f515152525454575758
diff --git a/contrib/tcpdump/tests/esp0.out b/contrib/tcpdump/tests/esp0.out
deleted file mode 100644
index a0ddf1b..0000000
--- a/contrib/tcpdump/tests/esp0.out
+++ /dev/null
@@ -1,8 +0,0 @@
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x1), length 116
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x2), length 116
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x3), length 116
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x4), length 116
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x5), length 116
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x6), length 116
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x7), length 116
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x8), length 116
diff --git a/contrib/tcpdump/tests/esp0.sh b/contrib/tcpdump/tests/esp0.sh
deleted file mode 100644
index daf407c..0000000
--- a/contrib/tcpdump/tests/esp0.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-echo -n test esp0...
-uudecode 02-sunrise-sunset-esp.puu
-if (../tcpdump -t -n -r 02-sunrise-sunset-esp.pcap | diff - esp0.out)
-then
- echo passed.
-else
- echo failed.
-fi
-
-
diff --git a/contrib/tcpdump/tests/esp1.gdbinit b/contrib/tcpdump/tests/esp1.gdbinit
deleted file mode 100644
index 6c8ae89..0000000
--- a/contrib/tcpdump/tests/esp1.gdbinit
+++ /dev/null
@@ -1 +0,0 @@
-set args -t -n -E "0x12345678@192.1.2.45 3des-cbc-hmac96:0x4043434545464649494a4a4c4c4f4f515152525454575758" -r 02-sunrise-sunset-esp.pcap
diff --git a/contrib/tcpdump/tests/esp1.out b/contrib/tcpdump/tests/esp1.out
deleted file mode 100644
index 61b2967..0000000
--- a/contrib/tcpdump/tests/esp1.out
+++ /dev/null
@@ -1,8 +0,0 @@
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x1), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 1280, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x2), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 1536, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x3), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 1792, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x4), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2048, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x5), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2304, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x6), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2560, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x7), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2816, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x8), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 3072, length 64 (ipip-proto-4)
diff --git a/contrib/tcpdump/tests/esp1.sh b/contrib/tcpdump/tests/esp1.sh
deleted file mode 100644
index 87ee3b9..0000000
--- a/contrib/tcpdump/tests/esp1.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-uudecode 02-sunrise-sunset-esp.puu
-
-echo -n test esp1...
-../tcpdump -t -n -E "0x12345678@192.1.2.45 3des-cbc-hmac96:0x4043434545464649494a4a4c4c4f4f515152525454575758" -r 02-sunrise-sunset-esp.pcap >esp1.new
-if diff esp1.new esp1.out
-then
- echo passed.
-else
- echo failed.
-fi
-
diff --git a/contrib/tcpdump/tests/esp2.gdbinit b/contrib/tcpdump/tests/esp2.gdbinit
deleted file mode 100644
index 7c18407..0000000
--- a/contrib/tcpdump/tests/esp2.gdbinit
+++ /dev/null
@@ -1 +0,0 @@
-set args -t -n -E "0x12345678@192.1.2.45 3des-cbc-hmac96:0x43434545464649494a4a4c4c4f4f51515252545457575840,0xabcdabcd@192.0.1.1 3des-cbc-hmac96:0x434545464649494a4a4c4c4f4f5151525254545757584043" -r 08-sunrise-sunset-esp2.pcap
diff --git a/contrib/tcpdump/tests/esp2.out b/contrib/tcpdump/tests/esp2.out
deleted file mode 100644
index a829c8e..0000000
--- a/contrib/tcpdump/tests/esp2.out
+++ /dev/null
@@ -1,8 +0,0 @@
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x1), length 172: IP 192.1.2.23 > 192.0.1.1: ESP(spi=0xabcdabcd,seq=0x1), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 1280, length 64 (ipip-proto-4) (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x2), length 172: IP 192.1.2.23 > 192.0.1.1: ESP(spi=0xabcdabcd,seq=0x2), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 1536, length 64 (ipip-proto-4) (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x3), length 172: IP 192.1.2.23 > 192.0.1.1: ESP(spi=0xabcdabcd,seq=0x3), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 1792, length 64 (ipip-proto-4) (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x4), length 172: IP 192.1.2.23 > 192.0.1.1: ESP(spi=0xabcdabcd,seq=0x4), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2048, length 64 (ipip-proto-4) (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x5), length 172: IP 192.1.2.23 > 192.0.1.1: ESP(spi=0xabcdabcd,seq=0x5), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2304, length 64 (ipip-proto-4) (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x6), length 172: IP 192.1.2.23 > 192.0.1.1: ESP(spi=0xabcdabcd,seq=0x6), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2560, length 64 (ipip-proto-4) (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x7), length 172: IP 192.1.2.23 > 192.0.1.1: ESP(spi=0xabcdabcd,seq=0x7), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2816, length 64 (ipip-proto-4) (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0x12345678,seq=0x8), length 172: IP 192.1.2.23 > 192.0.1.1: ESP(spi=0xabcdabcd,seq=0x8), length 116: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 3072, length 64 (ipip-proto-4) (ipip-proto-4)
diff --git a/contrib/tcpdump/tests/esp2.sh b/contrib/tcpdump/tests/esp2.sh
deleted file mode 100644
index 18a7083..0000000
--- a/contrib/tcpdump/tests/esp2.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-uudecode 08-sunrise-sunset-esp2.puu
-
-echo -n test esp2...
-../tcpdump -t -n -E "0x12345678@192.1.2.45 3des-cbc-hmac96:0x43434545464649494a4a4c4c4f4f51515252545457575840,0xabcdabcd@192.0.1.1 3des-cbc-hmac96:0x434545464649494a4a4c4c4f4f5151525254545757584043" -r 08-sunrise-sunset-esp2.pcap >esp2.new
-if diff esp2.new esp2.out
-then
- echo passed.
-else
- echo failed.
-fi
-
diff --git a/contrib/tcpdump/tests/esp3.gdbinit b/contrib/tcpdump/tests/esp3.gdbinit
deleted file mode 100644
index 7150118..0000000
--- a/contrib/tcpdump/tests/esp3.gdbinit
+++ /dev/null
@@ -1 +0,0 @@
-set args -t -n -E "3des-cbc-hmac96:0x43434545464649494a4a4c4c4f4f51515252545457575840" -r 08-sunrise-sunset-esp2.pcap
diff --git a/contrib/tcpdump/tests/esp3.sh b/contrib/tcpdump/tests/esp3.sh
deleted file mode 100644
index 122beab..0000000
--- a/contrib/tcpdump/tests/esp3.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-uudecode 02-sunrise-sunset-esp.puu
-echo -n test esp3...
- ../tcpdump -t -n -E "3des-cbc-hmac96:0x4043434545464649494a4a4c4c4f4f515152525454575758" -r 02-sunrise-sunset-esp.pcap >esp3.new
-if diff esp3.new esp1.out
-then
- echo passed.
-else
- echo failed.
-fi
-
diff --git a/contrib/tcpdump/tests/esp4.gdbinit b/contrib/tcpdump/tests/esp4.gdbinit
deleted file mode 100644
index 8007444..0000000
--- a/contrib/tcpdump/tests/esp4.gdbinit
+++ /dev/null
@@ -1,2 +0,0 @@
-set args -t -n -E "file esp-secrets.txt" -r 08-sunrise-sunset-esp2.pcap
-
diff --git a/contrib/tcpdump/tests/esp4.sh b/contrib/tcpdump/tests/esp4.sh
deleted file mode 100644
index bba26e7..0000000
--- a/contrib/tcpdump/tests/esp4.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-uudecode 08-sunrise-sunset-esp2.puu
-
-echo -n test esp4...
-../tcpdump -t -n -E "file esp-secrets.txt" -r 08-sunrise-sunset-esp2.pcap >esp4.new
-if diff esp4.new esp2.out
-then
- echo passed.
-else
- echo failed.
-fi
-
diff --git a/contrib/tcpdump/tests/esp5.gdbinit b/contrib/tcpdump/tests/esp5.gdbinit
deleted file mode 100644
index 2f578e3..0000000
--- a/contrib/tcpdump/tests/esp5.gdbinit
+++ /dev/null
@@ -1,3 +0,0 @@
-set args -t -n -E "file esp-secrets.txt" -r 08-sunrise-sunset-aes.pcap
-
-
diff --git a/contrib/tcpdump/tests/esp5.out b/contrib/tcpdump/tests/esp5.out
deleted file mode 100644
index 73f35e0..0000000
--- a/contrib/tcpdump/tests/esp5.out
+++ /dev/null
@@ -1,8 +0,0 @@
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0xd1234567,seq=0x1), length 132: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 1280, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0xd1234567,seq=0x2), length 132: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 1536, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0xd1234567,seq=0x3), length 132: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 1792, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0xd1234567,seq=0x4), length 132: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2048, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0xd1234567,seq=0x5), length 132: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2304, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0xd1234567,seq=0x6), length 132: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2560, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0xd1234567,seq=0x7), length 132: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 2816, length 64 (ipip-proto-4)
-IP 192.1.2.23 > 192.1.2.45: ESP(spi=0xd1234567,seq=0x8), length 132: IP 192.0.2.1 > 192.0.1.1: ICMP echo request, id 28416, seq 3072, length 64 (ipip-proto-4)
diff --git a/contrib/tcpdump/tests/esp5.sh b/contrib/tcpdump/tests/esp5.sh
deleted file mode 100644
index 405b677..0000000
--- a/contrib/tcpdump/tests/esp5.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-uudecode 08-sunrise-sunset-aes.puu
-
-echo -n test esp5...
-../tcpdump -t -n -E "file esp-secrets.txt" -r 08-sunrise-sunset-aes.pcap > esp5.new
-if diff esp5.new esp5.out
-then
- echo passed.
-else
- echo failed.
-fi
-
diff --git a/contrib/tcpdump/tests/espudp1.out b/contrib/tcpdump/tests/espudp1.out
deleted file mode 100644
index 8999ff4..0000000
--- a/contrib/tcpdump/tests/espudp1.out
+++ /dev/null
@@ -1,8 +0,0 @@
-IP 192.1.2.23.4500 > 192.1.2.45.4500: UDP-encap: ESP(spi=0x12345678,seq=0x1), length 116
-IP 192.1.2.23.4500 > 192.1.2.45.4500: UDP-encap: ESP(spi=0x12345678,seq=0x2), length 116: ip-proto-227 49
-IP 192.1.2.23.4500 > 192.1.2.45.4500: UDP-encap: ESP(spi=0x12345678,seq=0x3), length 116: PIMv13, length: 10
-IP 192.1.2.23.4500 > 192.1.2.45.4500: UDP-encap: ESP(spi=0x12345678,seq=0x4), length 116
-IP 192.1.2.23.4500 > 192.1.2.45.4500: UDP-encap: ESP(spi=0x12345678,seq=0x5), length 116
-IP 192.1.2.23.4500 > 192.1.2.45.4500: UDP-encap: ESP(spi=0x12345678,seq=0x6), length 116: ip-proto-183 28
-IP 192.1.2.23.4500 > 192.1.2.45.4500: UDP-encap: ESP(spi=0x12345678,seq=0x7), length 116: ip-proto-72 34
-IP 192.1.2.23.4500 > 192.1.2.45.4500: UDP-encap: ESP(spi=0x12345678,seq=0x8), length 116: ip-proto-224 59
diff --git a/contrib/tcpdump/tests/espudp1.puu b/contrib/tcpdump/tests/espudp1.puu
deleted file mode 100644
index 353c1c9..0000000
--- a/contrib/tcpdump/tests/espudp1.puu
+++ /dev/null
@@ -1,35 +0,0 @@
-begin 644 espudp1.pcap
-MU,.RH0(`!``````````````&```!``````````````">````G@```!```&1D
-M11```&1D(P@`10``D*8.``!`$5`(P`$"%\`!`BT1E!&4`'P``!(T5G@````!
-MIQI1WARY*2.,3*N>\E4-MV0"Q0&B9RG\CH]Z?F.J2U2J6?9"%WHI),PCC4.T
-MPHU1D2,KT6".3TG`1R:V$E7'FE[]PG%1#\!'O=1;9"P[#Q*U;DU12<9BO$:/
-M(AI2S*,BK5H_YVKC,]K'@[Y^``````````">````G@```!```&1D11```&1D
-M(P@`10``D*8/``!`$5`'P`$"%\`!`BT1E!&4`'P``!(T5G@````"*3$H)*^K
-MG65!9?U^[O>)/*D1"&WNUN@=BGJZV$;E12<$J$SGOAFJ!<5)O%=NY:HY\B$3
-M!*Q.N--U/:_F^;L-H0>[$9AU0\QP"`F5JD8GY307\SDD5=Y\G@%('76R5O`G
-MA/2`=,$VWF]0[L\*``````````">````G@```!```&1D11```&1D(P@`10``
-MD*80``!`$5`&P`$"%\`!`BT1E!&4`'P``!(T5G@````#C]!\R;K$H/YX7>T6
-MZT6>/2I[+Q4&*]7A`VLB)[%A_/MKQMX-:R"-)DA.[G>)\5]KF#Z5:3L+JCMC
-MXDHKBE%/Q%D1VV#=?\3JEZ?8)&[3[(4F"4*0W"B)."[.?0U(7!!Z2_69:0DV
-M98H$8R%=``````````">````G@```!```&1D11```&1D(P@`10``D*81``!`
-M$5`%P`$"%\`!`BT1E!&4`'P``!(T5G@````$FV8=\*GR(@_[&TF2&3'AZ9)Q
-M*?@[(M!I:IE"@-?4W5TEZ-5@(F\613%V19L#%[XCJFJY^G4BVW"O\/*X\!A6
-M@1<[4J(5+60M8]9R>$=\TU>XX7AB7\T'1W1HAPX[(KPTVN"*NEC)E/7@5D_1
-M``````````">````G@```!```&1D11```&1D(P@`10``D*82``!`$5`$P`$"
-M%\`!`BT1E!&4`'P``!(T5G@````%=@CRA49O0D;A1@T5[WR$Q5?Y(\M[>D@C
-MRFK+$5I%Y8:85K`)&LZ.Q@G&N)8-RG@2;GNYJ\2OC9ZV?,IT7HJU7K&DM/1_
-M:K+-8KXY4?22*8=.1@O<,#R&;^R2P`>PAR9E7*>!>3*D24OK4*C1````````
-M``">````G@```!```&1D11```&1D(P@`10``D*83``!`$5`#P`$"%\`!`BT1
-ME!&4`'P``!(T5G@````&OTF+$=SM[Y.=U8E>9V&69R:M\.1&LA]$#9Q^:+E7
-MQE#E^)1R]--?O]SW!%7]KB<7\MLR56^<HT.D."4A5M1LBB7FNX7DP-C$&AH]
-M+':VL$0V)[[KSCAW[YA,>WX)#?)/IJR<_@C91NG`(S^S``````````">````
-MG@```!```&1D11```&1D(P@`10``D*84``!`$5`"P`$"%\`!`BT1E!&4`'P`
-M`!(T5G@````'!12933DTC1RSTN*./4ZCE%A8GGVL:;@`.%'8MEA.C7/6]D[S
-MO1C([D/N6]%[?NISR>1W1EE,)=\I9&.PF-'Q*LXZQU71100.[\,-HK41G3/R
-MG9DY$,].(M58U1\0XT\4R[<=RCCXM;_%AVM)``````````">````G@```!``
-M`&1D11```&1D(P@`10``D*85``!`$5`!P`$"%\`!`BT1E!&4`'P``!(T5G@`
-M```(*_3L6&DE`65QQPA"@BAQ5FY@=%,+]@C9K+O)@],/GCI4%,MKI282(0M9
-M*<@/=L.DB"**EM":*2KJK`^H=0YM,$^[`=L%(RO,O_<4`MNKJ*:^9W8@1BP$
-59LK`-:)VQ/=2B;1'4FV3B?L]2;O!
-`
-end
diff --git a/contrib/tcpdump/tests/espudp1.sh b/contrib/tcpdump/tests/espudp1.sh
deleted file mode 100644
index 35dc0a8..0000000
--- a/contrib/tcpdump/tests/espudp1.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-uudecode espudp1.puu
-
-echo -n test espudp1...
-../tcpdump -t -n -E "file esp-secrets.txt" -r espudp1.pcap >espudp1.new
-if diff espudp1.new espudp1.out
-then
- echo passed.
-else
- echo failed.
-fi
-
diff --git a/contrib/tcpdump/tests/isakmp-delete-segfault.puu b/contrib/tcpdump/tests/isakmp-delete-segfault.puu
deleted file mode 100644
index 11512b1..0000000
--- a/contrib/tcpdump/tests/isakmp-delete-segfault.puu
+++ /dev/null
@@ -1,20 +0,0 @@
-begin 644 isakmp-delete-segfault.pcap
-MU,.RH0(`!``````````````$```!````@"X```````"I`@``J0(``/______
-M_P$!`0$!`0@`10``I@`O0`!`$3PA?P```7\```$!]`'T`<@``!N3$,+\/7K^
-M3SF!FR'H6?T,OKXN&YH=5T,AEYH%R@(@71+C65#___\`````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-!````
-`
-end
diff --git a/contrib/tcpdump/tests/isakmp-identification-segfault.puu b/contrib/tcpdump/tests/isakmp-identification-segfault.puu
deleted file mode 100644
index 6f0ae0e..0000000
--- a/contrib/tcpdump/tests/isakmp-identification-segfault.puu
+++ /dev/null
@@ -1,11 +0,0 @@
-begin 644 isakmp-identification-segfault.pcap
-MU,.RH0(`!````````````/__````````HV%@0"_*#@`\`0``/`$```(```!%
-M``$XH&P``/\1'$9_```!?P```0'U`?0!)$KL)9EPC(1ZBP(```````````40
-M`@`````````!'````0`"````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-M````````````````````````````````````````````````````````````
-I````````````````````````````````````````````````````````
-`
-end
diff --git a/contrib/tcpdump/tests/isakmp-pointer-loop.puu b/contrib/tcpdump/tests/isakmp-pointer-loop.puu
deleted file mode 100644
index fc58248..0000000
--- a/contrib/tcpdump/tests/isakmp-pointer-loop.puu
+++ /dev/null
@@ -1,6 +0,0 @@
-begin 644 isakmp-pointer-loop.pcap
-MU,.RH0(`!````````````/__```!````DR;5/[_@!0!(````2``````$6D[H
-ME``"+6_:]@@`10``.H=E0`#S$0HB@:KY?H&J^5<!]`'T`";R?@``````````
-6```````````($`$````````````*````
-`
-end
diff --git a/contrib/tcpdump/tests/isakmp1.out b/contrib/tcpdump/tests/isakmp1.out
deleted file mode 100644
index 67a6ed1..0000000
--- a/contrib/tcpdump/tests/isakmp1.out
+++ /dev/null
@@ -1 +0,0 @@
-IP 127.0.0.1.500 > 127.0.0.1.500: isakmp: phase 2/others ? #190[C]
diff --git a/contrib/tcpdump/tests/isakmp1.sh b/contrib/tcpdump/tests/isakmp1.sh
deleted file mode 100644
index ce2de7d..0000000
--- a/contrib/tcpdump/tests/isakmp1.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-uudecode isakmp-delete-segfault.puu
-
-echo -n test isakmp1...
-if (../tcpdump -t -n -r isakmp-delete-segfault.pcap | diff - isakmp1.out)
-then
- echo passed.
-else
- echo failed.
-fi
-
diff --git a/contrib/tcpdump/tests/isakmp2.out b/contrib/tcpdump/tests/isakmp2.out
deleted file mode 100644
index 44c28db..0000000
--- a/contrib/tcpdump/tests/isakmp2.out
+++ /dev/null
@@ -1 +0,0 @@
-IP 129.170.249.126.500 > 129.170.249.87.500: isakmp: phase 1 ? base
diff --git a/contrib/tcpdump/tests/isakmp2.sh b/contrib/tcpdump/tests/isakmp2.sh
deleted file mode 100644
index d0006a8..0000000
--- a/contrib/tcpdump/tests/isakmp2.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-uudecode isakmp-pointer-loop.puu
-
-echo -n test isakmp2...
-if (../tcpdump -t -n -r isakmp-pointer-loop.pcap | diff - isakmp2.out)
-then
- echo passed.
-else
- echo failed.
-fi
-
diff --git a/contrib/tcpdump/tests/isakmp3.out b/contrib/tcpdump/tests/isakmp3.out
deleted file mode 100644
index 6b37b77..0000000
--- a/contrib/tcpdump/tests/isakmp3.out
+++ /dev/null
@@ -1,2 +0,0 @@
-IP (tos 0x0, ttl 255, id 41068, offset 0, flags [none], proto: UDP (17), length: 312) 127.0.0.1.501 > 127.0.0.1.500: isakmp 1.0 msgid : phase 1 I ident:
- (id: idtype=FQDN protoid=0 port=0 len=248 \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000)
diff --git a/contrib/tcpdump/tests/isakmp3.sh b/contrib/tcpdump/tests/isakmp3.sh
deleted file mode 100644
index e6003cc..0000000
--- a/contrib/tcpdump/tests/isakmp3.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-uudecode isakmp-identification-segfault.puu
-
-echo -n test isakmp3...
-../tcpdump -t -v -n -r isakmp-identification-segfault.pcap > isakmp3.new
-if diff isakmp3.new isakmp3.out
-then
- echo passed.
-else
- echo failed.
-fi
-
diff --git a/contrib/tcpdump/tests/isakmp4.out b/contrib/tcpdump/tests/isakmp4.out
deleted file mode 100644
index 8c5b7da..0000000
--- a/contrib/tcpdump/tests/isakmp4.out
+++ /dev/null
@@ -1,35 +0,0 @@
-arp who-has 192.1.2.23 tell 192.1.2.254
-arp reply 192.1.2.23 is-at 10:00:00:64:64:23
-IP 192.1.2.254.500 > 192.1.2.23.500: isakmp: phase 1 I ident
-IP 192.1.2.23.500 > 192.1.2.254.500: isakmp: phase 1 R ident
-IP 192.1.2.254.500 > 192.1.2.23.500: isakmp: phase 1 I ident
-IP 192.1.2.23.500 > 192.1.2.254.500: isakmp: phase 1 R ident
-IP 192.1.2.254.4500 > 192.1.2.23.4500: NONESP-encap: isakmp: phase 1 I ident[E]
-IP 192.1.2.23.4500 > 192.1.2.254.4500: NONESP-encap: isakmp: phase 1 R ident[E]
-IP 192.1.2.254.4500 > 192.1.2.23.4500: NONESP-encap: isakmp: phase 2/others I oakley-quick[E]
-IP 192.1.2.23.4500 > 192.1.2.254.4500: NONESP-encap: isakmp: phase 2/others R oakley-quick[E]
-IP 192.1.2.254.4500 > 192.1.2.23.4500: NONESP-encap: isakmp: phase 2/others I oakley-quick[E]
-IP 192.1.2.254.4500 > 192.1.2.23.4500: UDP-encap: ESP(spi=0xf4dc0ae5,seq=0x1), length 132
-arp who-has 192.1.2.254 tell 192.1.2.23
-arp reply 192.1.2.254 is-at 10:00:00:de:ad:ba
-IP 192.1.2.23.4500 > 192.1.2.254.4500: NONESP-encap: isakmp: phase 2/others R oakley-quick[E]
-IP 192.1.2.254.4500 > 192.1.2.23.4500: NONESP-encap: isakmp: phase 2/others I oakley-quick[E]
-IP 192.1.2.254.4500 > 192.1.2.23.4500: UDP-encap: ESP(spi=0xf4dc0ae5,seq=0x2), length 132
-IP 192.1.2.254.4500 > 192.1.2.23.4500: isakmp-nat-keep-alive
-IP 192.1.2.254.4500 > 192.1.2.23.4500: UDP-encap: ESP(spi=0xf4dc0ae5,seq=0x3), length 132
-IP 192.1.2.23.4500 > 192.1.2.254.4500: NONESP-encap: isakmp: phase 2/others R oakley-quick[E]
-IP 192.1.2.254.4500 > 192.1.2.23.4500: NONESP-encap: isakmp: phase 2/others I oakley-quick[E]
-IP 192.1.2.254.4500 > 192.1.2.23.4500: UDP-encap: ESP(spi=0xf4dc0ae5,seq=0x4), length 132
-IP 192.1.2.254.4500 > 192.1.2.23.4500: isakmp-nat-keep-alive
-IP 192.1.2.254.4500 > 192.1.2.23.4500: UDP-encap: ESP(spi=0xf4dc0ae5,seq=0x5), length 132
-IP 192.1.2.254.4500 > 192.1.2.23.4500: UDP-encap: ESP(spi=0xf4dc0ae5,seq=0x6), length 132
-arp who-has 192.1.2.23 tell 192.1.2.254
-arp reply 192.1.2.23 is-at 10:00:00:64:64:23
-IP 192.1.2.254.4500 > 192.1.2.23.4500: isakmp-nat-keep-alive
-IP 192.1.2.254.4500 > 192.1.2.23.4500: UDP-encap: ESP(spi=0xf4dc0ae5,seq=0x7), length 132
-IP 192.1.2.23.4500 > 192.1.2.254.4500: NONESP-encap: isakmp: phase 2/others R oakley-quick[E]
-IP 192.1.2.254.4500 > 192.1.2.23.4500: UDP-encap: ESP(spi=0xf4dc0ae5,seq=0x8), length 132
-arp who-has 192.1.2.254 tell 192.1.2.23
-arp reply 192.1.2.254 is-at 10:00:00:de:ad:ba
-IP 192.1.2.254.4500 > 192.1.2.23.4500: isakmp-nat-keep-alive
-IP 192.1.2.23.4500 > 192.1.2.254.4500: NONESP-encap: isakmp: phase 2/others R inf[E]
diff --git a/contrib/tcpdump/tests/isakmp4.sh b/contrib/tcpdump/tests/isakmp4.sh
deleted file mode 100644
index dd7bf07..0000000
--- a/contrib/tcpdump/tests/isakmp4.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-uudecode isakmp4500.puu
-
-echo -n test isakmp4...
-../tcpdump -t -n -E "file esp-secrets.txt" -r isakmp4500.pcap >isakmp4.new
-if diff isakmp4.new isakmp4.out
-then
- echo passed.
-else
- echo failed.
-fi
-
diff --git a/contrib/tcpdump/tests/isakmp4500.puu b/contrib/tcpdump/tests/isakmp4500.puu
deleted file mode 100644
index 0b55dcc..0000000
--- a/contrib/tcpdump/tests/isakmp4500.puu
+++ /dev/null
@@ -1,155 +0,0 @@
-begin 644 isakmp4500.pcap
-MU,.RH0(`!``````````````&```!```````````````J````*@```/______
-M_Q```-ZMN@@&``$(``8$``$0``#>K;K``0+^````````P`$"%P``````````
-M*@```"H````0``#>K;H0``!D9",(!@`!"``&!``"$```9&0CP`$"%Q```-ZM
-MNL`!`OX``````````$X!``!.`0``$```9&0C$```WJVZ"`!%``%```!``#\1
-MM97``0+^P`$"%P'T`?0!+)6LGHGR.(^0O!X```````````$0`@`````````!
-M)`T``)0````!`````0```(@``0`$`P``(``!``"`"P`!@`P.$(`!``6``@`!
-M@`,``X`$``4#```@`0$``(`+``&`#`X0@`$`!8`"``*``P`#@`0`!0,``"`"
-M`0``@`L``8`,#A"``0`%@`(``H`#``.`!``"````(`,!``"`"P`!@`P.$(`!
-M``6``@`!@`,``X`$``(-```03T5K4F)'6%)V;5!%#0``%*_*UQ-HH?'):X:6
-M_'=7`0`-```42A,<@0<#6$5<5RCR#I5%+PT``!1]E!FF4Q#*;RP7G9(54IU6
-M#0``%,U@1D,UWR'X?/VR_&BVI$@````41(45+1BVN\T+Z*A&E7G=S```````
-M````L@```+(````0``#>K;H0``!D9",(`$4``*0``$``0!&U,<`!`A?``0+^
-M`?0!]`"08%.>B?(XCY"\'@IT-7SCT:2_`1`"``````````"(#0``-`````$`
-M```!````*``!``$````@``$``(`+``&`#`X0@`$`!8`"``&``P`#@`0`!0T`
-M`!!/16M28D=84G9M4$4-```4K\K7$VBA\<EKAI;\=U<!`````!1*$QR!!P-8
-M15Q7*/(.E44O``````````!&`0``1@$``!```&1D(Q```-ZMN@@`10`!.```
-M0``_$;6=P`$"_L`!`A<!]`'T`206L9Z)\CB/D+P>"G0U?./1I+\$$`(`````
-M`````1P*``#$M]N'X4E&AEMT*7(UA)]?Z:M`RW>TPRPR/2V-U^-O'ST7,9K7
-MCQQFQ`#^2/PP0G^@]QHR=9!Y7?/EL'O(\L(I'#51V6N1?)1J+6P-A6&T0Y@"
-M-KJ[,_WPC+W%H'KSV>J_(W#3`3A4&A^4Q*T^3Q*2'^M#9[XHW-IVWO.#J=M?
-MDHTX?/DS#]CDJG;?BC_E:$W:3AD]N9+!U'[+6UU.`,)4^&ASH2SO\CU.=2!#
-MH'<T@54L9-$X/5ZQ*&_;9BF5E3Q7%```%&;6]C)I>UY(FI*395>I?Z@4```4
-M;OX2\$KY#?O/L5UQN$&[G@```!1$]1?@/[.!^`^$+14XS/^L``````````!&
-M`0``1@$``!```-ZMNA```&1D(P@`10`!.```0`!`$;2=P`$"%\`!`OX!]`'T
-M`20!UYZ)\CB/D+P>"G0U?./1I+\$$`(``````````1P*``#$YYI?^#V[%WO*
-M+,?[XKU\"YVFZ0UCMOA'6Y:C93#4^M&/)'3",1Q/"&7*"D0_<1SX#@"KRZDV
-M\_XCB4O9XNS0"_O8-'[C&AG5O;G^G_N*#?4,"OA'?R><"WN68Q(H<1EONM3!
-MS3=]U]MRZ(4UBM]&:I\KW&3X;LQ%M[B0:,/"]DTM1^J8+8CESE'6JEFCE,,$
-M?$W5P,^5=1K1AT@YX0J-9%/E]`MY&<%C?*Y*K\'5X#2B5OD6+FTGJ)^V299#
-M*>H6%```%&Q^7ZRJ16$T%<6UJE<?IS$4```4.9,$U0^]3*/;'AEZ]\$>;P``
-M`!1N_A+P2OD-^\^Q77&X0;N>``````````!R`0``<@$``!```&1D(Q```-ZM
-MN@@`10`!9```0``_$;5QP`$"_L`!`A<1E!&4`5!RH0````">B?(XCY"\'@IT
-M-7SCT:2_!1`"`0````````%$H"1@W`ZTW:4&'Z=!K*`IRTNLK:3J/^$DD/B4
-M>Q,F?M5`3=(?!HGW$/M)`\W8Z/'FXK6$!(9!7BL9!@QV=(^E7><\)R8EVE3F
-M6`.O^:2F!(>LD7%71N]`LA?B!/!0\*H2"YOJ0]_W9#9DJYZ).M/.;+8A?L[O
-M`J-'HV_0*'&&^P\8:$'I^"13SN]VT%5\8O8;P2VV=`+&9+4]'MH+/&:'PR!H
-M4O#,GI+1=+*MRN"5.-8D&$16)<O!`SBZM\AKC&P_X<;S]@/)1)Y\.&WOY7\H
-M1V\P7.NL<92?18X,F+:L`^^F#O1Y505Q0H85DLC9DG)B/V<^\\%WS5TO;E$:
-M"1$F`DG*=R<?ZQYTN1P^4Q#1].60GK<.AK=_XOM^<JSB!P9\:C2X3QI`L]D`
-M`````````%H!``!:`0``$```WJVZ$```9&0C"`!%``%,``!``$`1M(G``0(7
-MP`$"_A&4$90!.,?$`````)Z)\CB/D+P>"G0U?./1I+\%$`(!`````````2S"
-M8Z5]+<^-M8Q9P&X;^%JN2^*NYC1"AZ%4J-PIMZM611W<D%]6ET9DUBF=TH.0
-MQQSMHS[FF;=E?$HJP1Z27H0;DRN`@QD+=-Y#&>A:Z$*6IBWC.3.9037)<B;;
-M0U&M+H9[&=K##GX++CXGX(L;7E^)B\Q+'_'N5/5,"[?P96K'-(4;25\#D%M/
-MVIN6C#7'Q:0PBF3\=1($ODAZ(&:$((=V1,STM/MIB(]C;^7T=R$*%X?+MTX^
-MB*X%6DJ09BC(XU@(,4IU1Q]MV_;%S@8Y96MB,W3/!#M5BS)JGA5$(J4H5W@8
-M<*B:G<;Q^>L`[ADSH`K&0*^[6)>")$E3;"4;U="I",2*`1TP_=5+%B"II3>(
-M'@``````````V@$``-H!```0``!D9",0``#>K;H(`$4``<P``$``/Q&U"<`!
-M`O[``0(7$901E`&XW3@`````GHGR.(^0O!X*=#5\X]&DOP@0(`&+?HE'```!
-MK''I#[H$<_"<YEGG2)8)!97PF%0-_\8^X(V1[(=%+UAMJ9A(1/!,[6+WM32C
-M)*0IG:EM/C)SF$P$=$P"Y_R.@/MCQOS;\U>4YQ5SAO`10)\84&I?],R2.?5M
-MZ/Y^Y"#*%+0.<9KX(/Z$'&M,-)/2I7U^,!G,*G!E_O.D;7F_;D^V#&&*(R.+
-MH;YSI'1@I8GV%+\'*6,1(8`8D(VUP[,(R?PQ7#,5WQY3[HT+IFF"3?.+;(*M
-M_?C;JQ#]O'9522*ZO7>'TEDYLLA`*L$8(XJ$!T>_HYS?G=WR11E($-021FMS
-MB[NXAJ^CQVGO87[B@^I6THHW-%Z8%PTH&BCO^.[@K_NS8RVTE7CE&MA]6C@>
-MEDIDM&T^.41?F(\X$Z-5[547$HC='*\>8``"[9.IHT)+[,^LZ?_6(6I\L32#
-MF-JM7U".L4?X/8=G*KFA<>THJ-622W,;J`IW2^MLBI?_O<<EC)!V1^7\U,YK
-M7'E&R_].`C#$#;X]E]1SX@092]ZE(@C-2M!ZAW.#%L^J[^'13BY&SG@`````
-M`````(H!``"*`0``$```WJVZ$```9&0C"`!%``%\``!``$`1M%G``0(7P`$"
-M_A&4$90!:,KN`````)Z)\CB/D+P>"G0U?./1I+\($"`!BWZ)1P```5RM:&N4
-MQ1;W19+;77%JE,,H'8&F6ITJM=R5O>KL1%[]#E/LJ#&./WFJ`#,3C!H=I_'*
-M34/)_E+)(`!A&W00*T\"9O9JX0N">$#'(ZL<$'\P=GHB.0:\AXT/!^^*<P2!
-M<!A\>%U.'5#'2IX<Q;9+I6GRVRW_+T,S>:7/2KZ$%^3W;%R4[&2T>'?2(@FF
-M#T/=+2O[?Q4.(\@Q;]3V=L5Q2XFG)^E)0J:1AX`J4%E3_Y]^6='!R-ENY%9#
-M3!XD:5K?/V&.!&X#>I_$96Y;P_!5']<G(@<:I94]["%1#F3MY*U1V%WQVL1_
-MRT*Z$\KEVW>070(D3N#$47!AZ^VCW-?I?JT2AL5YOWBO5[D!"OV)46(FK)9"
-M$C40GNJ7*A,SE6%6A(4>KPE(-$)=L6=2VQLO>Y12N8QBH3V%(90.\5YL`R,O
-M1@``````````8@```&(````0``!D9",0``#>K;H(`$4``%0``$``/Q&V@<`!
-M`O[``0(7$901E`!`KQ<`````GHGR.(^0O!X*=#5\X]&DOP@0(`&+?HE'````
-M-"4[,88.:.R$%:1S6K/X<EH]YZH).22D`@``````````K@```*X````0``!D
-M9",0``#>K;H(`$4``*"JM```/Q%+@<`!`O[``0(7$901E`",``#TW`KE````
-M`?SD"<11-X_=FBX7J&]'/C[B>;BA23X"^A;(BA/H;8_\0'U,E@M&;+=R&*LY
-MAF.NT6<PXR31!Z\MX@W4>/*J.SL[UR2)+H^A6#5<38R;!FY\:AV_6ZV)FQ2!
-M1T\L:`GPK6U?_?TVHSK[6(WSF?Q"XF5K/0U,A.Y+D\RP]G(``````````"H`
-M```J````$```WJVZ$```9&0C"`8``0@`!@0``1```&1D(\`!`A<```````#`
-M`0+^```````````J````*@```!```&1D(Q```-ZMN@@&``$(``8$``(0``#>
-MK;K``0+^$```9&0CP`$"%P``````````B@$``(H!```0``#>K;H0``!D9",(
-M`$4``7P``$``0!&T6<`!`A?``0+^$901E`%HRNX`````GHGR.(^0O!X*=#5\
-MX]&DOP@0(`&+?HE'```!7*UH:Y3%%O=%DMM=<6J4PR@=@:9:G2JUW)6]ZNQ$
-M7OT.4^RH,8X_>:H`,Q.,&AVG\<I-0\G^4LD@`&$;=!`K3P)F]FKA"X)X0,<C
-MJQP0?S!V>B(Y!KR'C0\'[XIS!(%P&'QX74X=4,=*GAS%MDNE:?+;+?\O0S-Y
-MI<]*OH07Y/=L7)3L9+1X=](B":8/0]TM*_M_%0XCR#%OU/9VQ7%+B:<GZ4E"
-MII&'@"I065/_GWY9T<'(V6[D5D-,'B1I6M\_88X$;@-ZG\1E;EO#\%4?UR<B
-M!QJEE3WL(5$.9.WDK5'87?':Q'_+0KH3RN7;=Y!=`B1.X,11<&'K[:/<U^E^
-MK1*&Q7F_>*]7N0$*_8E18B:LED(2-1">ZI<J$S.585:$A1ZO"4@T0EVQ9U+;
-M&R][E%*YC&*A/84AE`[Q7FP#(R]&``````````!B````8@```!```&1D(Q``
-M`-ZMN@@`10``5```0``_$;:!P`$"_L`!`A<1E!&4`$"O%P````">B?(XCY"\
-M'@IT-7SCT:2_"!`@`8M^B4<````T)3LQA@YH[(05I'-:L_AR6CWGJ@DY)*0"
-M``````````"N````K@```!```&1D(Q```-ZMN@@`10``H*JU```_$4N`P`$"
-M_L`!`A<1E!&4`(P``/3<"N4````";5_]_3:C.OM8C?.9_$+B9;KU/R+D"U^-
-MLGB)>"40ZCMW:+^A4%UI1Y)\.O4B]`44T(2XS\S=2[[[X.6A-PCDZP*3XFAD
-M294>+W:M%%+\`)?XP#[:6]NHG>#;FFF-RMAA7D"KQ-&OX<E(GNRS/6*%P8?B
-M>3Z5S'CBYC"740``````````*P```"L````0``!D9",0``#>K;H(`$4``!T`
-M`$``/Q&VN,`!`O[``0(7$901E``)6)O_``````````"N````K@```!```&1D
-M(Q```-ZMN@@`10``H*JV```_$4M_P`$"_L`!`A<1E!&4`(P``/3<"N4````#
-M7D"KQ-&OX<E(GNRS/6*%P6M-D[MJGU)RI[EA3)LD/W^:S2V!1P<2Y/0I:_`%
-MF3-`LSA3&QM8DD^\>1F0#F$^I@1V5E>.`*!H=Z?(&*,.MS]E4H#P+<JB/C=Q
-MS26IBN>2"^MMG?%@Y3*L%D'7$>LLOA,HUEB3IB;87,\:-0``````````B@$`
-M`(H!```0``#>K;H0``!D9",(`$4``7P``$``0!&T6<`!`A?``0+^$901E`%H
-MRNX`````GHGR.(^0O!X*=#5\X]&DOP@0(`&+?HE'```!7*UH:Y3%%O=%DMM=
-M<6J4PR@=@:9:G2JUW)6]ZNQ$7OT.4^RH,8X_>:H`,Q.,&AVG\<I-0\G^4LD@
-M`&$;=!`K3P)F]FKA"X)X0,<CJQP0?S!V>B(Y!KR'C0\'[XIS!(%P&'QX74X=
-M4,=*GAS%MDNE:?+;+?\O0S-YI<]*OH07Y/=L7)3L9+1X=](B":8/0]TM*_M_
-M%0XCR#%OU/9VQ7%+B:<GZ4E"II&'@"I065/_GWY9T<'(V6[D5D-,'B1I6M\_
-M88X$;@-ZG\1E;EO#\%4?UR<B!QJEE3WL(5$.9.WDK5'87?':Q'_+0KH3RN7;
-M=Y!=`B1.X,11<&'K[:/<U^E^K1*&Q7F_>*]7N0$*_8E18B:LED(2-1">ZI<J
-M$S.585:$A1ZO"4@T0EVQ9U+;&R][E%*YC&*A/84AE`[Q7FP#(R]&````````
-M``!B````8@```!```&1D(Q```-ZMN@@`10``5```0``_$;:!P`$"_L`!`A<1
-ME!&4`$"O%P````">B?(XCY"\'@IT-7SCT:2_"!`@`8M^B4<````T)3LQA@YH
-M[(05I'-:L_AR6CWGJ@DY)*0"``````````"N````K@```!```&1D(Q```-ZM
-MN@@`10``H*JW```_$4M^P`$"_L`!`A<1E!&4`(P``/3<"N4````$"^MMG?%@
-MY3*L%D'7$>LLOHFXH,6B3<'M/]A_UT%X.MP;F`ZT@=\62*]W'/Y5@1,(8+`W
-MTIZ(C;<M^%)G.9R$N1)6J_7Z_!GT%\UMQ:XQPM8]>8G'VC<"+'VM:$K/=:VI
-MD#:KB^/G$BB@:+=TSV\S)T5-E#UOBKZ"E5_,%P``````````*P```"L````0
-M``!D9",0``#>K;H(`$4``!T``$``/Q&VN,`!`O[``0(7$901E``)6)O_````
-M``````"N````K@```!```&1D(Q```-ZMN@@`10``H*JX```_$4M]P`$"_L`!
-M`A<1E!&4`(P``/3<"N4````%D#:KB^/G$BB@:+=TSV\S)XZ>X,YAOI/W1_BS
-M7:N%MO?3J+1\I=>O-<R^HIZU--!X&6`$]U#*J@;R@64%SKQ.B/^^IGB<&88W
-M[8)FS;H6%4)M9NV]\#Q+3^^'.,PQY7<SC6OG8>36N1GBDD+HMR]D8U)G(OJ]
-MMX!><$3'U0``````````K@```*X````0``!D9",0``#>K;H(`$4``*"JN0``
-M/Q%+?,`!`O[``0(7$901E`",``#TW`KE````!HUKYV'DUKD9XI)"Z+<O9&,5
-M_X1R'`1@>@>3:9638^IH_2\8CVE-BL2&43,3ZAY3'1@3Z:+\)XSXDSO]L,@?
-MCOL6<I7.*]L#N>@]+&+X^#H(D.X>B;)<%[E4:S:#.D70:!#<8Q\QZFH`<C&^
-MG'`JQ0_F"K\L?F]\HUG$8G,``````````"H````J````$```9&0C$```WJVZ
-M"`8``0@`!@0``1```-ZMNL`!`OX```````#``0(7```````````J````*@``
-M`!```-ZMNA```&1D(P@&``$(``8$``(0``!D9"/``0(7$```WJVZP`$"_@``
-M````````*P```"L````0``!D9",0``#>K;H(`$4``!T``$``/Q&VN,`!`O[`
-M`0(7$901E``)6)O_``````````"N````K@```!```&1D(Q```-ZMN@@`10``
-MH*JZ```_$4M[P`$"_L`!`A<1E!&4`(P``/3<"N4````'$-QC'S'J:@!R,;Z<
-M<"K%#ST!-8\O2;F**R/9Z%HAZ`2#KQIW*9'HI9C067ZK-G^XAL^O0I7Z/'H(
-M<.`7P<QG3<<?7R7Z!!3MQ1MY5B=F9N",J@L.`]?M!U5)TB`<"]W5C[,`[Y'2
-MT6\N$CD@6'"CP$3F`AEER>@/P'/E0@``````````B@$``(H!```0``#>K;H0
-M``!D9",(`$4``7P``$``0!&T6<`!`A?``0+^$901E`%HRNX`````GHGR.(^0
-MO!X*=#5\X]&DOP@0(`&+?HE'```!7*UH:Y3%%O=%DMM=<6J4PR@=@:9:G2JU
-MW)6]ZNQ$7OT.4^RH,8X_>:H`,Q.,&AVG\<I-0\G^4LD@`&$;=!`K3P)F]FKA
-M"X)X0,<CJQP0?S!V>B(Y!KR'C0\'[XIS!(%P&'QX74X=4,=*GAS%MDNE:?+;
-M+?\O0S-YI<]*OH07Y/=L7)3L9+1X=](B":8/0]TM*_M_%0XCR#%OU/9VQ7%+
-MB:<GZ4E"II&'@"I065/_GWY9T<'(V6[D5D-,'B1I6M\_88X$;@-ZG\1E;EO#
-M\%4?UR<B!QJEE3WL(5$.9.WDK5'87?':Q'_+0KH3RN7;=Y!=`B1.X,11<&'K
-M[:/<U^E^K1*&Q7F_>*]7N0$*_8E18B:LED(2-1">ZI<J$S.585:$A1ZO"4@T
-M0EVQ9U+;&R][E%*YC&*A/84AE`[Q7FP#(R]&``````````"N````K@```!``
-M`&1D(Q```-ZMN@@`10``H*J[```_$4MZP`$"_L`!`A<1E!&4`(P``/3<"N4`
-M```(C[,`[Y'2T6\N$CD@6'"CP*@CBNC9!,,HJ*K#(R8N5?*%N(<XX+>GVJ+F
-M#M/G_FP&NANM[W@`)Y9\\Z?F4SX%'E.^2BCP\9+!/`25PK%+G'U@$&1+=@%(
-M#9RV^U"B8-5,EXJ0-QZTLOJ/L^F\).BC@++XQGOL8JC_`L;'=```````````
-M*@```"H````0``#>K;H0``!D9",(!@`!"``&!``!$```9&0CP`$"%P``````
-M`,`!`OX``````````"H````J````$```9&0C$```WJVZ"`8``0@`!@0``A``
-M`-ZMNL`!`OX0``!D9"/``0(7```````````K````*P```!```&1D(Q```-ZM
-MN@@`10``'0``0``_$;:XP`$"_L`!`A<1E!&4``E8F_\``````````'H```!Z
-M````$```WJVZ$```9&0C"`!%``!L``!``$`1M6G``0(7P`$"_A&4$90`6,G#
-M`````)Z)\CB/D+P>"G0U?./1I+\($`4!`KW&3P```$S_T\^1(\?(IVCQDA]J
-C20SF@.^<&]2'1D(_3FHHKW7PKQJ'!!.01QV>?]$9K_EN`N<`
-`
-end
diff --git a/contrib/tcpdump/tests/lmp.out b/contrib/tcpdump/tests/lmp.out
deleted file mode 100644
index ee37bca..0000000
--- a/contrib/tcpdump/tests/lmp.out
+++ /dev/null
@@ -1,191 +0,0 @@
-IP (tos 0x0, ttl 1, id 44530, offset 0, flags [none], proto: UDP (17), length: 84) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Begin Verify, Flags: [Control Channel Down], length: 56
- Link ID Object (3), Class-Type: IPv4 Local (1) Flags: [non-negotiable], length: 8
- IPv4 Link ID: 1.0.0.0 (0x01000000)
- Message ID Object (5), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Message ID: 3 (0x00000003)
- Link ID Object (3), Class-Type: IPv4 Remote (2) Flags: [non-negotiable], length: 8
- IPv4 Link ID: 1.0.0.0 (0x01000000)
- Verify Begin Object (8), Class-Type: 1 (1) Flags: [negotiable], length: 24
- Flags: none
- Verify Interval: 20
- Data links: 30
- Encoding type: Lambda (photonic)
- Verify Tranport Mechanism: 32768 (0x8000)
- Transmission Rate: 100.000 Mbps
- Wavelength: 8
-IP (tos 0x0, ttl 1, id 44531, offset 0, flags [none], proto: UDP (17), length: 56) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Hello, Flags: [Control Channel Down], length: 28
- Control Channel ID Object (1), Class-Type: Local (1) Flags: [non-negotiable], length: 8
- Control Channel ID: 1 (0x00000001)
- Hello Object (7), Class-Type: 1 (1) Flags: [non-negotiable], length: 12
- TxSeqNum: 50
- RcvSeqNum: 60
-IP (tos 0x0, ttl 1, id 44532, offset 0, flags [none], proto: UDP (17), length: 84) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Config NACK, Flags: [Control Channel Down], length: 56
- Control Channel ID Object (1), Class-Type: Local (1) Flags: [non-negotiable], length: 8
- Control Channel ID: 1 (0x00000001)
- Node ID Object (2), Class-Type: Local (1) Flags: [non-negotiable], length: 8
- Node ID: 10.0.50.1 (0x0a003201)
- Control Channel ID Object (1), Class-Type: Remote (2) Flags: [non-negotiable], length: 8
- Control Channel ID: 2 (0x00000002)
- Message ID Object (5), Class-Type: 2 (2) Flags: [non-negotiable], length: 8
- Message ID Ack: 3 (0x00000003)
- Node ID Object (2), Class-Type: Remote (2) Flags: [non-negotiable], length: 8
- Node ID: 10.0.50.2 (0x0a003202)
- Configuration Object (6), Class-Type: 1 (1) Flags: [negotiable], length: 8
- Hello Interval: 5
- Hello Dead Interval: 15
-IP (tos 0x0, ttl 1, id 44533, offset 0, flags [none], proto: UDP (17), length: 76) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Config ACK, Flags: [Control Channel Down], length: 48
- Control Channel ID Object (1), Class-Type: Local (1) Flags: [non-negotiable], length: 8
- Control Channel ID: 1 (0x00000001)
- Node ID Object (2), Class-Type: Local (1) Flags: [non-negotiable], length: 8
- Node ID: 10.0.50.1 (0x0a003201)
- Control Channel ID Object (1), Class-Type: Remote (2) Flags: [non-negotiable], length: 8
- Control Channel ID: 2 (0x00000002)
- Message ID Object (5), Class-Type: 2 (2) Flags: [non-negotiable], length: 8
- Message ID Ack: 3 (0x00000003)
- Node ID Object (2), Class-Type: Remote (2) Flags: [non-negotiable], length: 8
- Node ID: 10.0.50.2 (0x0a003202)
-IP (tos 0x0, ttl 1, id 44534, offset 0, flags [none], proto: UDP (17), length: 68) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Config, Flags: [Control Channel Down], length: 40
- Control Channel ID Object (1), Class-Type: Local (1) Flags: [non-negotiable], length: 8
- Control Channel ID: 1 (0x00000001)
- Message ID Object (5), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Message ID: 3 (0x00000003)
- Node ID Object (2), Class-Type: Local (1) Flags: [non-negotiable], length: 8
- Node ID: 10.0.50.1 (0x0a003201)
- Configuration Object (6), Class-Type: 1 (1) Flags: [negotiable], length: 8
- Hello Interval: 5
- Hello Dead Interval: 15
-IP (tos 0x0, ttl 1, id 44535, offset 0, flags [none], proto: UDP (17), length: 44) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Link Summary ACK, Flags: [Control Channel Down], length: 16
- Message ID Object (5), Class-Type: 2 (2) Flags: [non-negotiable], length: 8
- Message ID Ack: 1 (0x00000001)
-IP (tos 0x0, ttl 1, id 44536, offset 0, flags [none], proto: UDP (17), length: 124) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Link Summary NACK, Flags: [Control Channel Down], length: 96
- Message ID Object (5), Class-Type: 2 (2) Flags: [non-negotiable], length: 8
- Message ID Ack: 1 (0x00000001)
- Error Code Object (20), Class-Type: 2 (2) Flags: [non-negotiable], length: 8
- Error Code:
- Unacceptable non-negotiable LINK_SUMMARY parameters,
- Renegotiate LINK_SUMMARY parameters,
- Invalid DATA-LINK Object,
- Unknown TE-LINK Object c-type,
- Unknown DATA-LINK Object c-type
- Data Link Object (12), Class-Type: IPv4 (1) Flags: [non-negotiable], length: 36
- Flags: [none]
- Local Interface ID: 192.168.1.1 (0xc0a80101)
- Remote Interface ID: 192.168.1.2 (0xc0a80102)
- Subobject, Type: Interface Switching Type (1), Length: 12
- Switching Type: Lambda-Switch Capable (150)
- Encoding Type: Lambda (photonic) (8)
- Min Reservable Bandwidth: 100.000 Mbps
- Max Reservable Bandwidth: 100.000 Mbps
- Subobject, Type: Wavelength (2), Length: 8
- Wavelength: 6
- Data Link Object (12), Class-Type: IPv4 (1) Flags: [non-negotiable], length: 36
- Flags: [none]
- Local Interface ID: 10.1.1.1 (0x0a010101)
- Remote Interface ID: 10.1.1.2 (0x0a010102)
- Subobject, Type: Interface Switching Type (1), Length: 12
- Switching Type: Lambda-Switch Capable (150)
- Encoding Type: ANSI/ETSI PDH (3)
- Min Reservable Bandwidth: 1234736768.000 Mbps
- Max Reservable Bandwidth: 1290693376.000 Mbps
- Subobject, Type: Wavelength (2), Length: 8
- Wavelength: 353
-IP (tos 0x0, ttl 1, id 44537, offset 0, flags [none], proto: UDP (17), length: 68) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Begin Verify ACK, Flags: [Control Channel Down], length: 40
- Link ID Object (3), Class-Type: IPv4 Local (1) Flags: [non-negotiable], length: 8
- IPv4 Link ID: 1.0.0.0 (0x01000000)
- Message ID Object (5), Class-Type: 2 (2) Flags: [non-negotiable], length: 8
- Message ID Ack: 1 (0x00000001)
- Verify Begin ACK Object (9), Class-Type: 1 (1) Flags: [negotiable], length: 8
- Verify Dead Interval: 50
- Verify Transport Response: 100
- Verify ID Object (10), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Verify ID: 5
-IP (tos 0x0, ttl 1, id 44538, offset 0, flags [none], proto: UDP (17), length: 60) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Begin Verify NACK, Flags: [Control Channel Down], length: 32
- Link ID Object (3), Class-Type: IPv4 Local (1) Flags: [non-negotiable], length: 8
- IPv4 Link ID: 10.0.0.0 (0x0a000000)
- Message ID Object (5), Class-Type: 2 (2) Flags: [non-negotiable], length: 8
- Message ID Ack: 3 (0x00000003)
- Error Code Object (20), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Error Code:
- Link Verification Procedure Not supported,
- Unwilling to verify,
- Unsupported verification transport mechanism
-IP (tos 0x0, ttl 1, id 44539, offset 0, flags [none], proto: UDP (17), length: 52) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: End Verify, Flags: [Control Channel Down], length: 24
- Message ID Object (5), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Message ID: 3 (0x00000003)
- Verify ID Object (10), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Verify ID: 5
-IP (tos 0x0, ttl 1, id 44540, offset 0, flags [none], proto: UDP (17), length: 52) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: End Verify ACK, Flags: [Control Channel Down], length: 24
- Message ID Object (5), Class-Type: 2 (2) Flags: [non-negotiable], length: 8
- Message ID Ack: 3 (0x00000003)
- Verify ID Object (10), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Verify ID: 5
-IP (tos 0x0, ttl 1, id 44541, offset 0, flags [none], proto: UDP (17), length: 52) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Test, Flags: [Control Channel Down], length: 24
- Interface ID Object (4), Class-Type: IPv4 Local (1) Flags: [non-negotiable], length: 8
- IPv4 Link ID: 1.0.0.0 (0x01000000)
- Verify ID Object (10), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Verify ID: 5
-IP (tos 0x0, ttl 1, id 44542, offset 0, flags [none], proto: UDP (17), length: 52) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Test Status Failure, Flags: [Control Channel Down], length: 24
- Message ID Object (5), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Message ID: 1 (0x00000001)
- Verify ID Object (10), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Verify ID: 5
-IP (tos 0x0, ttl 1, id 44543, offset 0, flags [none], proto: UDP (17), length: 52) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Test Status ACK, Flags: [Control Channel Down], length: 24
- Message ID Object (5), Class-Type: 2 (2) Flags: [non-negotiable], length: 8
- Message ID Ack: 1 (0x00000001)
- Verify ID Object (10), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Verify ID: 5
-IP (tos 0x0, ttl 1, id 44544, offset 0, flags [none], proto: UDP (17), length: 44) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Channel Status ACK, Flags: [Control Channel Down], length: 16
- Message ID Object (5), Class-Type: 2 (2) Flags: [non-negotiable], length: 8
- Message ID Ack: 3 (0x00000003)
-IP (tos 0x0, ttl 1, id 44545, offset 0, flags [none], proto: UDP (17), length: 64) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Channel Status Request, Flags: [Control Channel Down], length: 36
- Link ID Object (3), Class-Type: IPv4 Local (1) Flags: [non-negotiable], length: 8
- IPv4 Link ID: 1.0.0.0 (0x01000000)
- Message ID Object (5), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Message ID: 3 (0x00000003)
- Channel Status Request Object (14), Class-Type: IPv4 (1) Flags: [non-negotiable], length: 12
- Interface ID: 2.0.0.0 (0x02000000)
- Interface ID: 2.0.0.0 (0x02000000)
-IP (tos 0x0, ttl 1, id 44546, offset 0, flags [none], proto: UDP (17), length: 72) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Channel Status, Flags: [Control Channel Down], length: 44
- Link ID Object (3), Class-Type: IPv4 Local (1) Flags: [non-negotiable], length: 8
- IPv4 Link ID: 1.0.0.0 (0x01000000)
- Message ID Object (5), Class-Type: 1 (1) Flags: [non-negotiable], length: 8
- Message ID: 3 (0x00000003)
- Channel Status Object (13), Class-Type: IPv4 (1) Flags: [non-negotiable], length: 20
- Interface ID: 1.0.0.0 (0x01000000)
- Active: Allocated (1)
- Direction: Transmit (1)
- Channel Status: Signal Fail (3)
- Interface ID: 1.0.0.0 (0x01000000)
- Active: Allocated (1)
- Direction: Receive (0)
- Channel Status: Signal Degraded (2)
-IP (tos 0x0, ttl 1, id 44547, offset 0, flags [none], proto: UDP (17), length: 64) 10.0.12.1.49998 > 10.0.12.2.49998:
- LMPv1, msg-type: Channel Status Response, Flags: [Control Channel Down], length: 36
- Message ID Object (5), Class-Type: 2 (2) Flags: [non-negotiable], length: 8
- Message ID Ack: 3 (0x00000003)
- Channel Status Object (13), Class-Type: IPv4 (1) Flags: [non-negotiable], length: 20
- Interface ID: 1.0.0.0 (0x01000000)
- Active: Allocated (1)
- Direction: Transmit (1)
- Channel Status: Signal Degraded (2)
- Interface ID: 1.0.0.0 (0x01000000)
- Active: Allocated (1)
- Direction: Transmit (1)
- Channel Status: Signal Okay (1)
diff --git a/contrib/tcpdump/tests/lmp.puu b/contrib/tcpdump/tests/lmp.puu
deleted file mode 100644
index c14cd56..0000000
--- a/contrib/tcpdump/tests/lmp.puu
+++ /dev/null
@@ -1,42 +0,0 @@
-begin 644 lmp.pcap
-MU,.RH0(`!````````````/__```!````I!J-0&;J``!B````8@`````%75SJ
-MQ@`$=="&2@@`10``5*WR```!$=^D"@`,`0H`#`+#3L-.`$```!````4`.```
-M`0,`"`$````!!0`(`````P(#``@!````@0@`&````!0````>")*``$+(````
-M```(I!J-0#SQ``!&````1@`````%75SJQ@`$=="&2@@`10``.*WS```!$=^_
-M"@`,`0H`#`+#3L-.`"0``!````0`'````0$`"`````$!!P`,````,@```#RD
-M&HU`@/(``&(```!B``````5=7.K&``1UT(9*"`!%``!4K?0```$1WZ(*``P!
-M"@`,`L-.PTX`0```$````P`X```!`0`(`````0$"``@*`#(!`@$`"`````("
-M!0`(`````P("``@*`#("@08`"``%``^D&HU`?_,``%H```!:``````5=7.K&
-M``1UT(9*"`!%``!,K?4```$1WZD*``P!"@`,`L-.PTX`.```$````@`P```!
-M`0`(`````0$"``@*`#(!`@$`"`````("!0`(`````P("``@*`#("I!J-0'+T
-M``!2````4@`````%75SJQ@`$=="&2@@`10``1*WV```!$=^P"@`,`0H`#`+#
-M3L-.`#```!````$`*````0$`"`````$!!0`(`````P$"``@*`#(!@08`"``%
-M``^D&HU`0_4``#H````Z``````5=7.K&``1UT(9*"`!%```LK?<```$1W\<*
-M``P!"@`,`L-.PTX`&```$```#P`0```"!0`(`````:0:C4"E]P``B@```(H`
-M````!5U<ZL8`!'70ADH(`$4``'RM^````1'?=@H`#`$*``P"PT[#3@!H```0
-M```0`&````(%``@````!`A0`"````#L!#``D`````,"H`0'`J`$"`0R6"$+(
-M``!"R````@@```````8!#``D``````H!`0$*`0$"`0R6`TZ3,2U.F=S6`@@`
-M`````6&D&HU`C/@``%(```!2``````5=7.K&``1UT(9*"`!%``!$K?D```$1
-MWZT*``P!"@`,`L-.PTX`,```$```!@`H```!`P`(`0````(%``@````!@0D`
-M"``R`&0!"@`(````!:0:C4!E^0``2@```$H`````!5U<ZL8`!'70ADH(`$4`
-M`#RM^@```1'?M`H`#`$*``P"PT[#3@`H```0```'`"````$#``@*`````@4`
-M"`````,!%``(````!Z0:C4`Q^@``0@```$(`````!5U<ZL8`!'70ADH(`$4`
-M`#2M^P```1'?NPH`#`$*``P"PT[#3@`@```0```(`!@```$%``@````#`0H`
-M"`````6D&HU``_L``$(```!"``````5=7.K&``1UT(9*"`!%```TK?P```$1
-MW[H*``P!"@`,`L-.PTX`(```$```"0`8```"!0`(`````P$*``@````%I!J-
-M0-#[``!"````0@`````%75SJQ@`$=="&2@@`10``-*W]```!$=^Y"@`,`0H`
-M#`+#3L-.`"```!````H`&````00`"`$````!"@`(````!:0:C4"=_```0@``
-M`$(`````!5U<ZL8`!'70ADH(`$4``#2M_@```1'?N`H`#`$*``P"PT[#3@`@
-M```0```,`!@```$%``@````!`0H`"`````6D&HU`:?T``$(```!"``````5=
-M7.K&``1UT(9*"`!%```TK?\```$1W[<*``P!"@`,`L-.PTX`(```$```#0`8
-M```"!0`(`````0$*``@````%I!J-0#C^```Z````.@`````%75SJQ@`$=="&
-M2@@`10``+*X````!$=^^"@`,`0H`#`+#3L-.`!@``!```!(`$````@4`"```
-M``.D&HU`)?\``$X```!.``````5=7.K&``1UT(9*"`!%``!`K@$```$1WZD*
-M``P!"@`,`L-.PTX`+```$```$P`D```!`P`(`0````$%``@````#`0X`#`(`
-M```"````I!J-0`8``0!6````5@`````%75SJQ@`$=="&2@@`10``2*X"```!
-M$=^@"@`,`0H`#`+#3L-.`#0``!```!$`+````0,`"`$````!!0`(`````P$-
-M`!0!````P````P$```"````"I!J-0-4``0!.````3@`````%75SJQ@`$=="&
-M2@@`10``0*X#```!$=^G"@`,`0H`#`+#3L-.`"P``!```!0`)````@4`"```
-6``,!#0`4`0```,````(!````P````0``
-`
-end
diff --git a/contrib/tcpdump/tests/lmp.sh b/contrib/tcpdump/tests/lmp.sh
deleted file mode 100755
index 9919044..0000000
--- a/contrib/tcpdump/tests/lmp.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-uudecode lmp.puu
-
-echo -n test lmp ...
-../tcpdump -t -n -v -r lmp.pcap >lmp.new
-if diff lmp.new lmp.out
-then
- echo passed.
-else
- echo failed.
-fi
-
-
diff --git a/contrib/tcpdump/tests/mpls-ldp-hello.out b/contrib/tcpdump/tests/mpls-ldp-hello.out
deleted file mode 100644
index fa621ca..0000000
--- a/contrib/tcpdump/tests/mpls-ldp-hello.out
+++ /dev/null
@@ -1,9 +0,0 @@
-IP (tos 0xc0, ttl 1, id 15579, offset 0, flags [none], proto: UDP (17), length: 70) 10.1.1.3.646 > 224.0.0.2.646:
- LDP, Label-Space-ID: 10.1.0.2:0, pdu-length: 38
- Hello Message (0x0100), length: 28, Message ID: 0x00011970, Flags: [ignore if unknown]
- Common Hello Parameters TLV (0x0400), length: 4, Flags: [ignore and don't forward if unknown]
- Hold Time: 15s, Flags: [Link Hello]
- IPv4 Transport Address TLV (0x0401), length: 4, Flags: [ignore and don't forward if unknown]
- IPv4 Transport Address: 10.1.0.2
- Configuration Sequence Number TLV (0x0402), length: 4, Flags: [ignore and don't forward if unknown]
- Sequence Number: 1
diff --git a/contrib/tcpdump/tests/mpls-ldp-hello.puu b/contrib/tcpdump/tests/mpls-ldp-hello.puu
deleted file mode 100644
index b7f3b62..0000000
--- a/contrib/tcpdump/tests/mpls-ldp-hello.puu
+++ /dev/null
@@ -1,6 +0,0 @@
-begin 644 mpls-ldp-hello.pcap
-MU,.RH0(`!````````````.H%```)````1UFZ/E2'#`!*````2@```/\#`"%%
-MP`!&/-L```$1D08*`0$#X````@*&`H8`,M2>``$`)@H!``(```$``!P``1EP
-8!```!``/```$`0`$"@$``@0"``0````!
-`
-end
diff --git a/contrib/tcpdump/tests/mpls-ldp-hello.sh b/contrib/tcpdump/tests/mpls-ldp-hello.sh
deleted file mode 100755
index b1a5b19..0000000
--- a/contrib/tcpdump/tests/mpls-ldp-hello.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-uudecode mpls-ldp-hello.puu
-
-echo -n test mpls-ldp-hello ...
-../tcpdump -t -n -v -r mpls-ldp-hello.pcap >mpls-ldp-hello.new
-if diff mpls-ldp-hello.new mpls-ldp-hello.out
-then
- echo passed.
-else
- echo failed.
-fi
-
-
diff --git a/contrib/tcpdump/tests/ospf-gmpls.out b/contrib/tcpdump/tests/ospf-gmpls.out
deleted file mode 100644
index 965affc..0000000
--- a/contrib/tcpdump/tests/ospf-gmpls.out
+++ /dev/null
@@ -1,83 +0,0 @@
-IP (tos 0xc0, ttl 1, id 4052, offset 0, flags [none], proto: OSPF (89), length: 172) 40.35.1.2 > 224.0.0.5: OSPFv2, LS-Update, length: 152
- Router-ID: 10.255.245.35, Backbone Area, Authentication Type: none (0), 1 LSA
- LSA #1
- Advertising Router: 10.255.245.37, seq 0x80000002, age 9s, length: 104
- Area Local Opaque LSA (10), Opaque-Type: Traffic Engineering LSA (1), Opaque-ID: 8
- Options: [External]
- Link TLV (2), length: 100
- Link Type subTLV (1), length: 1, Point-to-point (1)
- Link ID subTLV (2), length: 4, 10.255.245.69 (0x0afff545)
- Local Interface IP address subTLV (3), length: 4, 10.9.142.1
- Remote Interface IP address subTLV (4), length: 4, 10.9.142.2
- Traffic Engineering Metric subTLV (5), length: 4, Metric 63
- Maximum Bandwidth subTLV (6), length: 4, 622.080 Mbps
- Maximum Reservable Bandwidth subTLV (7), length: 4, 622.080 Mbps
- Unreserved Bandwidth subTLV (8), length: 32
- TE-Class 0: 622.080 Mbps
- TE-Class 1: 622.080 Mbps
- TE-Class 2: 622.080 Mbps
- TE-Class 3: 622.080 Mbps
- TE-Class 4: 622.080 Mbps
- TE-Class 5: 622.080 Mbps
- TE-Class 6: 622.080 Mbps
- TE-Class 7: 622.080 Mbps
- Administrative Group subTLV (9), length: 4, 0x00000000
-IP (tos 0xc0, ttl 1, id 4106, offset 0, flags [none], proto: OSPF (89), length: 172) 40.35.1.2 > 224.0.0.5: OSPFv2, LS-Update, length: 152
- Router-ID: 10.255.245.35, Backbone Area, Authentication Type: none (0), 1 LSA
- LSA #1
- Advertising Router: 10.255.245.37, seq 0x80000002, age 9s, length: 104
- Area Local Opaque LSA (10), Opaque-Type: Traffic Engineering LSA (1), Opaque-ID: 9
- Options: [External]
- Link TLV (2), length: 100
- Link Type subTLV (1), length: 1, Point-to-point (1)
- Link ID subTLV (2), length: 4, 10.255.245.69 (0x0afff545)
- Local Interface IP address subTLV (3), length: 4, 10.9.143.1
- Remote Interface IP address subTLV (4), length: 4, 10.9.143.2
- Traffic Engineering Metric subTLV (5), length: 4, Metric 63
- Maximum Bandwidth subTLV (6), length: 4, 622.080 Mbps
- Maximum Reservable Bandwidth subTLV (7), length: 4, 622.080 Mbps
- Unreserved Bandwidth subTLV (8), length: 32
- TE-Class 0: 622.080 Mbps
- TE-Class 1: 622.080 Mbps
- TE-Class 2: 622.080 Mbps
- TE-Class 3: 622.080 Mbps
- TE-Class 4: 622.080 Mbps
- TE-Class 5: 622.080 Mbps
- TE-Class 6: 622.080 Mbps
- TE-Class 7: 622.080 Mbps
- Administrative Group subTLV (9), length: 4, 0x00000000
-IP (tos 0xc0, ttl 1, id 4160, offset 0, flags [none], proto: OSPF (89), length: 212) 40.35.1.2 > 224.0.0.5: OSPFv2, LS-Update, length: 192
- Router-ID: 10.255.245.35, Backbone Area, Authentication Type: none (0), 1 LSA
- LSA #1
- Advertising Router: 10.255.245.35, seq 0x80000003, age 3s, length: 144
- Area Local Opaque LSA (10), Opaque-Type: Traffic Engineering LSA (1), Opaque-ID: 3
- Options: [External]
- Link TLV (2), length: 140
- Link Type subTLV (1), length: 1, Point-to-point (1)
- Link ID subTLV (2), length: 4, 10.255.245.40 (0x0afff528)
- Local Interface IP address subTLV (3), length: 4, 10.40.35.14
- Remote Interface IP address subTLV (4), length: 4, 10.40.35.13
- Traffic Engineering Metric subTLV (5), length: 4, Metric 1
- Maximum Bandwidth subTLV (6), length: 4, 100.000 Mbps
- Maximum Reservable Bandwidth subTLV (7), length: 4, 100.000 Mbps
- Unreserved Bandwidth subTLV (8), length: 32
- TE-Class 0: 0.000 Mbps
- TE-Class 1: 0.000 Mbps
- TE-Class 2: 0.000 Mbps
- TE-Class 3: 0.000 Mbps
- TE-Class 4: 0.000 Mbps
- TE-Class 5: 0.000 Mbps
- TE-Class 6: 0.000 Mbps
- TE-Class 7: 0.000 Mbps
- Interface Switching Capability subTLV (15), length: 44
- Interface Switching Capability: Packet-Switch Capable-1
- LSP Encoding: Ethernet V2/DIX
- Max LSP Bandwidth:
- priority level 0: 0.000 Mbps
- priority level 1: 0.000 Mbps
- priority level 2: 0.000 Mbps
- priority level 3: 0.000 Mbps
- priority level 4: 0.000 Mbps
- priority level 5: 0.000 Mbps
- priority level 6: 0.000 Mbps
- priority level 7: 0.000 Mbps
diff --git a/contrib/tcpdump/tests/ospf-gmpls.puu b/contrib/tcpdump/tests/ospf-gmpls.puu
deleted file mode 100644
index 691e38e..0000000
--- a/contrib/tcpdump/tests/ospf-gmpls.puu
+++ /dev/null
@@ -1,18 +0,0 @@
-begin 644 ospf-gmpls.pcap
-MU,.RH0(`!````````````'81````````KME</_6D!0"P````L`````(```!%
-MP`"L#]0```%9GSLH(P$"X```!0($`)@*__4C`````*F*````````````````
-M``$`"0(*`0``"`K_]26````">#X`?``"`&0``0`!`0`````"``0*__5%``,`
-M!`H)C@$`!``$"@F.`@`%``0````_``8`!$R44,``!P`$3)10P``(`"!,E%#`
-M3)10P$R44,!,E%#`3)10P$R44,!,E%#`3)10P``)``0`````Y-E</P;,#0"P
-M````L`````(```!%P`"L$`H```%9GP4H(P$"X```!0($`)@*__4C`````&_$
-M``````````````````$`"0(*`0``"0K_]26````"L`,`?``"`&0``0`!`0``
-M```"``0*__5%``,`!`H)CP$`!``$"@F/`@`%``0````_``8`!$R44,``!P`$
-M3)10P``(`"!,E%#`3)10P$R44,!,E%#`3)10P$R44,!,E%#`3)10P``)``0`
-M````&=I</S4\!@#8````V`````(```!%P`#4$$````%9GJ<H(P$"X```!0($
-M`,`*__4C`````-HW``````````````````$``P(*`0```PK_]2.````#(00`
-MI``"`(P``0`!`0`````"``0*__4H``,`!`HH(PX`!``$"B@C#0`%``0````!
-M``8`!$L^O"``!P`$2SZ\(``(`"``````````````````````````````````
-M```````````/`"P!`@``````````````````````````````````````````
-*``!+/KP@"B@`````
-`
-end
diff --git a/contrib/tcpdump/tests/ospf-gmpls.sh b/contrib/tcpdump/tests/ospf-gmpls.sh
deleted file mode 100755
index da2dd3b..0000000
--- a/contrib/tcpdump/tests/ospf-gmpls.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-uudecode ospf-gmpls.puu
-
-echo -n test ospf-gmpls...
-../tcpdump -t -n -v -r ospf-gmpls.pcap > ospf-gmpls.new
-if diff ospf-gmpls.new ospf-gmpls.out
-then
- echo passed.
-else
- echo failed.
-fi
-
-
diff --git a/contrib/tcpdump/tests/print-A.out b/contrib/tcpdump/tests/print-A.out
deleted file mode 100644
index 107ffcb..0000000
--- a/contrib/tcpdump/tests/print-A.out
+++ /dev/null
@@ -1,193 +0,0 @@
-23:57:35.938066 IP 127.0.0.1.55920 > 127.0.0.1.80: S 928549246:928549246(0) win 32767 <mss 16396,sackOK,timestamp 1306300950 0,nop,wscale 2>
-E..<.h@.@.!R.........p.P7X.~.........!....@....
-M...........
-23:57:35.938122 IP 127.0.0.1.80 > 127.0.0.1.55920: S 930778609:930778609(0) ack 928549247 win 32767 <mss 16396,sackOK,timestamp 1306300950 1306300950,nop,wscale 2>
-E..<..@.@.<..........P.p7z..7X......n.....@....
-M...M.......
-23:57:35.938167 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 1 win 8192 <nop,nop,timestamp 1306300950 1306300950>
-E..4.j@.@.!X.........p.P7X..7z.... .7......
-M...M...
-23:57:35.939423 IP 127.0.0.1.55920 > 127.0.0.1.80: P 1:203(202) ack 1 win 8192 <nop,nop,timestamp 1306300951 1306300950>
-E....l@.@. ..........p.P7X..7z.... ........
-M...M...GET / HTTP/1.1
-Host: localhost
-User-Agent: ELinks/0.10.4-7-debian (textmode; Linux 2.6.11-1-686-smp i686; 132x56-2)
-Accept: */*
-Accept-Encoding: gzip
-Accept-Language: en
-Connection: Keep-Alive
-
-
-23:57:35.940474 IP 127.0.0.1.80 > 127.0.0.1.55920: . ack 203 win 8192 <nop,nop,timestamp 1306300952 1306300951>
-E..4..@.@............P.p7z..7X.I.. .7......
-M...M...
-23:57:35.941232 IP 127.0.0.1.80 > 127.0.0.1.55920: P 1:5560(5559) ack 203 win 8192 <nop,nop,timestamp 1306300953 1306300951>
-E.....@.@..%.........P.p7z..7X.I.. ........
-M...M...HTTP/1.1 200 OK
-Date: Wed, 06 Jul 2005 03:57:35 GMT
-Server: Apache/1.3.33
-Last-Modified: Sun, 15 Aug 2004 00:43:41 GMT
-ETag: "6e80f0-148a-411eb1bd"
-Accept-Ranges: bytes
-Content-Length: 5258
-Keep-Alive: timeout=15, max=100
-Connection: Keep-Alive
-Content-Type: text/html; charset=iso-8859-1
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<HTML>
-<HEAD>
- <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
- <META NAME="Description" CONTENT="The initial installation of Debian apache.">
- <TITLE>Placeholder page</TITLE>
-</HEAD>
-<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EF" VLINK="#55188A" ALINK="#FF0000">
-
-<H1>Placeholder page</H1>
-<H2>If you are just browsing the web</h2>
-
-<P>The owner of this web site has not put up any web pages yet.
-Please come back later.</P>
-
-<P><SMALL><CITE>Move along, nothing to see here...</CITE> :-)</SMALL></P>
-
-<H2>If you are trying to locate the administrator of this machine</H2>
-
-<P>If you want to report something about this host's behavior, please
-contact the Internet Service Provider (ISP) involved directly.</P>
-
-<P>See the <A href="http://www.abuse.net/">Network Abuse
-Clearinghouse</A> for how to do this.</P>
-
-<H2>If you are the administrator of this machine</H2>
-
-<P>The initial installation of <A href="http://www.debian.org/">Debian's
-apache</A> web server package was successful.</P>
-
-<P><STRONG>You should replace this page with your own web pages as
-soon as possible.</STRONG></P>
-
-<P>Unless you changed its configuration, your new server is configured as follows:
-<UL>
-<LI>
-Configuration files can be found in <TT>/etc/apache</TT>.</LI>
-
-<LI>
-The <TT>DocumentRoot</TT>, which is the directory under which all your
-HTML files should exist, is set to <TT>/var/www</TT>.</LI>
-
-<LI>
-CGI scripts are looked for in <TT>/usr/lib/cgi-bin</TT>, which is where
-Debian packages will place their scripts.</LI>
-
-<LI>
-Log files are placed in <TT>/var/log/apache</TT>, and will be rotated
-weekly. The frequency of rotation can be easily changed by editing
-<TT>/etc/logrotate.d/apache</TT>.</LI>
-
-<LI>
-The default directory index is <TT>index.html</TT>, meaning that requests
-for a directory <TT>/foo/bar/</TT> will give the contents of the file <TT>/var/www/foo/bar/index.html</TT>
-if it exists (assuming that <TT>/var/www</TT> is your <TT>DocumentRoot</TT>).</LI>
-
-<LI>
-User directories are enabled, and user documents will be looked for
-in the <TT>public_html</TT> directory of the users' homes. These dirs
-should be under <TT>/home</TT>, and users will not be able to symlink
-to files they don't own.</LI>
-
-</UL>
-All the standard apache modules are available with this release and are
-now managed with debconf. Type <TT>dpkg-reconfigure apache</TT> to
-select which modules you want enabled. Many other modules are available
-through the Debian package system with the names <TT>libapache-mod-*</TT>.
-If you need to compile a module yourself, you will need to install the
-<TT>apache-dev</TT> package.
-
-<P>More documentation on Apache can be found on:
-<UL>
-<LI>
-The <A HREF="/doc/apache-doc/manual/">Apache documentation</A> stored on your server.</LI>
-
-<LI>
-The <A HREF="http://www.apache.org/">Apache Project</A> home site.</LI>
-
-<LI>
-The <A HREF="http://www.apache-ssl.org/">Apache-SSL</A> home site.</LI>
-
-<LI>
-The <A HREF="http://perl.apache.org/">mod perl</A> home site.</LI>
-
-<LI>
-The <A HREF="http://www.apacheweek.com/">ApacheWeek</A> newsletter.</LI>
-
-<LI>
-The <A HREF="http://www.debian.org/doc/">Debian Project
-Documentation</A> which contains HOWTOs, FAQs, and software updates.</LI>
-</UL>
-
-<P>You can also consult the list of <A HREF="http://www.boutell.com/faq/">World
-Wide Web Frequently Asked Questions</A> for information.
-
-<H2>Let other people know about this server</H2>
-
-<A HREF="http://netcraft.com/">Netcraft</A> provides an interesting free
-service for web site monitoring and statistic collection.
-You can let them know about your server using their
-<A HREF="http://uptime.netcraft.com/">interface</A>.
-Enabling the monitoring of your server will provide a better global overview
-of who is using what and where, and it would give Debian a better
-overview of the apache package usage.
-
-<H2>About this page</H2>
-
-<IMG ALIGN="right" ALT="" HEIGHT="247" WIDTH="278" SRC="icons/jhe061.png">
-
-<P>This is a placeholder page installed by the <A
-HREF="http://www.debian.org/">Debian</A>
-release of the apache Web server package.
-
-<P>This computer has installed the Debian GNU/Linux operating system,
-but it has <strong>nothing to do with the Debian
-Project</strong>. Please do <strong>not</strong> contact the Debian
-Project about it.</P>
-
-<P>If you find a bug in this apache package, or in Apache itself,
-please file a bug report on it. Instructions on doing this, and the
-list of <A HREF="http://bugs.debian.org/src:apache">known bugs</A> of this
-package, can be found in the
-<A HREF="http://www.debian.org/Bugs/Reporting">Debian Bug Tracking System</A>.
-
-<P>Thanks for using this package, and congratulations for your choice of
-a Debian system!</P>
-
-<DIV align="center">
-<a href="http://www.debian.org/">
-<IMG align="middle" height="30" width="25" src="icons/debian/openlogo-25.jpg" alt="Debian">
-</a>
-<a href="http://www.apache.org/">
-<IMG align="middle" height="32" width="259" src="icons/apache_pb.png" alt="Apache">
-</a>
-</DIV>
-
-<!--
- This page was initially created by Johnie Ingram (http://netgod.net/)
- It was later edited by Matthew Wilcox and Josip Rodin.
- Last modified: $Date: 2004/06/20 15:33:57 $.
- -->
-
-</BODY>
-</HTML>
-
-23:57:35.941260 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5560 win 12383 <nop,nop,timestamp 1306300953 1306300953>
-E..4.n@.@.!T.........p.P7X.I7z....0_.......
-M...M...
-23:57:37.229575 IP 127.0.0.1.55920 > 127.0.0.1.80: F 203:203(0) ack 5560 win 12383 <nop,nop,timestamp 1306302241 1306300953>
-E..4.p@.@.!R.........p.P7X.I7z....0_.......
-M..!M...
-23:57:37.230839 IP 127.0.0.1.80 > 127.0.0.1.55920: F 5560:5560(0) ack 204 win 8192 <nop,nop,timestamp 1306302243 1306302241>
-E..4..@.@............P.p7z..7X.J.. ..5.....
-M..#M..!
-23:57:37.230900 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5561 win 12383 <nop,nop,timestamp 1306302243 1306302243>
-E..4.r@.@.!P.........p.P7X.J7z....0_.......
-M..#M..#
diff --git a/contrib/tcpdump/tests/print-AA.out b/contrib/tcpdump/tests/print-AA.out
deleted file mode 100644
index 52c0a77..0000000
--- a/contrib/tcpdump/tests/print-AA.out
+++ /dev/null
@@ -1,193 +0,0 @@
-23:57:35.938066 IP 127.0.0.1.55920 > 127.0.0.1.80: S 928549246:928549246(0) win 32767 <mss 16396,sackOK,timestamp 1306300950 0,nop,wscale 2>
-..............E..<.h@.@.!R.........p.P7X.~.........!....@....
-M...........
-23:57:35.938122 IP 127.0.0.1.80 > 127.0.0.1.55920: S 930778609:930778609(0) ack 928549247 win 32767 <mss 16396,sackOK,timestamp 1306300950 1306300950,nop,wscale 2>
-..............E..<..@.@.<..........P.p7z..7X......n.....@....
-M...M.......
-23:57:35.938167 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 1 win 8192 <nop,nop,timestamp 1306300950 1306300950>
-..............E..4.j@.@.!X.........p.P7X..7z.... .7......
-M...M...
-23:57:35.939423 IP 127.0.0.1.55920 > 127.0.0.1.80: P 1:203(202) ack 1 win 8192 <nop,nop,timestamp 1306300951 1306300950>
-..............E....l@.@. ..........p.P7X..7z.... ........
-M...M...GET / HTTP/1.1
-Host: localhost
-User-Agent: ELinks/0.10.4-7-debian (textmode; Linux 2.6.11-1-686-smp i686; 132x56-2)
-Accept: */*
-Accept-Encoding: gzip
-Accept-Language: en
-Connection: Keep-Alive
-
-
-23:57:35.940474 IP 127.0.0.1.80 > 127.0.0.1.55920: . ack 203 win 8192 <nop,nop,timestamp 1306300952 1306300951>
-..............E..4..@.@............P.p7z..7X.I.. .7......
-M...M...
-23:57:35.941232 IP 127.0.0.1.80 > 127.0.0.1.55920: P 1:5560(5559) ack 203 win 8192 <nop,nop,timestamp 1306300953 1306300951>
-..............E.....@.@..%.........P.p7z..7X.I.. ........
-M...M...HTTP/1.1 200 OK
-Date: Wed, 06 Jul 2005 03:57:35 GMT
-Server: Apache/1.3.33
-Last-Modified: Sun, 15 Aug 2004 00:43:41 GMT
-ETag: "6e80f0-148a-411eb1bd"
-Accept-Ranges: bytes
-Content-Length: 5258
-Keep-Alive: timeout=15, max=100
-Connection: Keep-Alive
-Content-Type: text/html; charset=iso-8859-1
-
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<HTML>
-<HEAD>
- <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
- <META NAME="Description" CONTENT="The initial installation of Debian apache.">
- <TITLE>Placeholder page</TITLE>
-</HEAD>
-<BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EF" VLINK="#55188A" ALINK="#FF0000">
-
-<H1>Placeholder page</H1>
-<H2>If you are just browsing the web</h2>
-
-<P>The owner of this web site has not put up any web pages yet.
-Please come back later.</P>
-
-<P><SMALL><CITE>Move along, nothing to see here...</CITE> :-)</SMALL></P>
-
-<H2>If you are trying to locate the administrator of this machine</H2>
-
-<P>If you want to report something about this host's behavior, please
-contact the Internet Service Provider (ISP) involved directly.</P>
-
-<P>See the <A href="http://www.abuse.net/">Network Abuse
-Clearinghouse</A> for how to do this.</P>
-
-<H2>If you are the administrator of this machine</H2>
-
-<P>The initial installation of <A href="http://www.debian.org/">Debian's
-apache</A> web server package was successful.</P>
-
-<P><STRONG>You should replace this page with your own web pages as
-soon as possible.</STRONG></P>
-
-<P>Unless you changed its configuration, your new server is configured as follows:
-<UL>
-<LI>
-Configuration files can be found in <TT>/etc/apache</TT>.</LI>
-
-<LI>
-The <TT>DocumentRoot</TT>, which is the directory under which all your
-HTML files should exist, is set to <TT>/var/www</TT>.</LI>
-
-<LI>
-CGI scripts are looked for in <TT>/usr/lib/cgi-bin</TT>, which is where
-Debian packages will place their scripts.</LI>
-
-<LI>
-Log files are placed in <TT>/var/log/apache</TT>, and will be rotated
-weekly. The frequency of rotation can be easily changed by editing
-<TT>/etc/logrotate.d/apache</TT>.</LI>
-
-<LI>
-The default directory index is <TT>index.html</TT>, meaning that requests
-for a directory <TT>/foo/bar/</TT> will give the contents of the file <TT>/var/www/foo/bar/index.html</TT>
-if it exists (assuming that <TT>/var/www</TT> is your <TT>DocumentRoot</TT>).</LI>
-
-<LI>
-User directories are enabled, and user documents will be looked for
-in the <TT>public_html</TT> directory of the users' homes. These dirs
-should be under <TT>/home</TT>, and users will not be able to symlink
-to files they don't own.</LI>
-
-</UL>
-All the standard apache modules are available with this release and are
-now managed with debconf. Type <TT>dpkg-reconfigure apache</TT> to
-select which modules you want enabled. Many other modules are available
-through the Debian package system with the names <TT>libapache-mod-*</TT>.
-If you need to compile a module yourself, you will need to install the
-<TT>apache-dev</TT> package.
-
-<P>More documentation on Apache can be found on:
-<UL>
-<LI>
-The <A HREF="/doc/apache-doc/manual/">Apache documentation</A> stored on your server.</LI>
-
-<LI>
-The <A HREF="http://www.apache.org/">Apache Project</A> home site.</LI>
-
-<LI>
-The <A HREF="http://www.apache-ssl.org/">Apache-SSL</A> home site.</LI>
-
-<LI>
-The <A HREF="http://perl.apache.org/">mod perl</A> home site.</LI>
-
-<LI>
-The <A HREF="http://www.apacheweek.com/">ApacheWeek</A> newsletter.</LI>
-
-<LI>
-The <A HREF="http://www.debian.org/doc/">Debian Project
-Documentation</A> which contains HOWTOs, FAQs, and software updates.</LI>
-</UL>
-
-<P>You can also consult the list of <A HREF="http://www.boutell.com/faq/">World
-Wide Web Frequently Asked Questions</A> for information.
-
-<H2>Let other people know about this server</H2>
-
-<A HREF="http://netcraft.com/">Netcraft</A> provides an interesting free
-service for web site monitoring and statistic collection.
-You can let them know about your server using their
-<A HREF="http://uptime.netcraft.com/">interface</A>.
-Enabling the monitoring of your server will provide a better global overview
-of who is using what and where, and it would give Debian a better
-overview of the apache package usage.
-
-<H2>About this page</H2>
-
-<IMG ALIGN="right" ALT="" HEIGHT="247" WIDTH="278" SRC="icons/jhe061.png">
-
-<P>This is a placeholder page installed by the <A
-HREF="http://www.debian.org/">Debian</A>
-release of the apache Web server package.
-
-<P>This computer has installed the Debian GNU/Linux operating system,
-but it has <strong>nothing to do with the Debian
-Project</strong>. Please do <strong>not</strong> contact the Debian
-Project about it.</P>
-
-<P>If you find a bug in this apache package, or in Apache itself,
-please file a bug report on it. Instructions on doing this, and the
-list of <A HREF="http://bugs.debian.org/src:apache">known bugs</A> of this
-package, can be found in the
-<A HREF="http://www.debian.org/Bugs/Reporting">Debian Bug Tracking System</A>.
-
-<P>Thanks for using this package, and congratulations for your choice of
-a Debian system!</P>
-
-<DIV align="center">
-<a href="http://www.debian.org/">
-<IMG align="middle" height="30" width="25" src="icons/debian/openlogo-25.jpg" alt="Debian">
-</a>
-<a href="http://www.apache.org/">
-<IMG align="middle" height="32" width="259" src="icons/apache_pb.png" alt="Apache">
-</a>
-</DIV>
-
-<!--
- This page was initially created by Johnie Ingram (http://netgod.net/)
- It was later edited by Matthew Wilcox and Josip Rodin.
- Last modified: $Date: 2004/06/20 15:33:57 $.
- -->
-
-</BODY>
-</HTML>
-
-23:57:35.941260 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5560 win 12383 <nop,nop,timestamp 1306300953 1306300953>
-..............E..4.n@.@.!T.........p.P7X.I7z....0_.......
-M...M...
-23:57:37.229575 IP 127.0.0.1.55920 > 127.0.0.1.80: F 203:203(0) ack 5560 win 12383 <nop,nop,timestamp 1306302241 1306300953>
-..............E..4.p@.@.!R.........p.P7X.I7z....0_.......
-M..!M...
-23:57:37.230839 IP 127.0.0.1.80 > 127.0.0.1.55920: F 5560:5560(0) ack 204 win 8192 <nop,nop,timestamp 1306302243 1306302241>
-..............E..4..@.@............P.p7z..7X.J.. ..5.....
-M..#M..!
-23:57:37.230900 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5561 win 12383 <nop,nop,timestamp 1306302243 1306302243>
-..............E..4.r@.@.!P.........p.P7X.J7z....0_.......
-M..#M..#
diff --git a/contrib/tcpdump/tests/print-X.out b/contrib/tcpdump/tests/print-X.out
deleted file mode 100644
index 53e44ed..0000000
--- a/contrib/tcpdump/tests/print-X.out
+++ /dev/null
@@ -1,409 +0,0 @@
-23:57:35.938066 IP 127.0.0.1.55920 > 127.0.0.1.80: S 928549246:928549246(0) win 32767 <mss 16396,sackOK,timestamp 1306300950 0,nop,wscale 2>
- 0x0000: 4500 003c 1b68 4000 4006 2152 7f00 0001 E..<.h@.@.!R....
- 0x0010: 7f00 0001 da70 0050 3758 897e 0000 0000 .....p.P7X.~....
- 0x0020: a002 7fff 1421 0000 0204 400c 0402 080a .....!....@.....
- 0x0030: 4ddc 9216 0000 0000 0103 0302 M...........
-23:57:35.938122 IP 127.0.0.1.80 > 127.0.0.1.55920: S 930778609:930778609(0) ack 928549247 win 32767 <mss 16396,sackOK,timestamp 1306300950 1306300950,nop,wscale 2>
- 0x0000: 4500 003c 0000 4000 4006 3cba 7f00 0001 E..<..@.@.<.....
- 0x0010: 7f00 0001 0050 da70 377a 8df1 3758 897f .....P.p7z..7X..
- 0x0020: a012 7fff 6eb1 0000 0204 400c 0402 080a ....n.....@.....
- 0x0030: 4ddc 9216 4ddc 9216 0103 0302 M...M.......
-23:57:35.938167 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 1 win 8192 <nop,nop,timestamp 1306300950 1306300950>
- 0x0000: 4500 0034 1b6a 4000 4006 2158 7f00 0001 E..4.j@.@.!X....
- 0x0010: 7f00 0001 da70 0050 3758 897f 377a 8df2 .....p.P7X..7z..
- 0x0020: 8010 2000 37d0 0000 0101 080a 4ddc 9216 ....7.......M...
- 0x0030: 4ddc 9216 M...
-23:57:35.939423 IP 127.0.0.1.55920 > 127.0.0.1.80: P 1:203(202) ack 1 win 8192 <nop,nop,timestamp 1306300951 1306300950>
- 0x0000: 4500 00fe 1b6c 4000 4006 208c 7f00 0001 E....l@.@.......
- 0x0010: 7f00 0001 da70 0050 3758 897f 377a 8df2 .....p.P7X..7z..
- 0x0020: 8018 2000 fef2 0000 0101 080a 4ddc 9217 ............M...
- 0x0030: 4ddc 9216 4745 5420 2f20 4854 5450 2f31 M...GET./.HTTP/1
- 0x0040: 2e31 0d0a 486f 7374 3a20 6c6f 6361 6c68 .1..Host:.localh
- 0x0050: 6f73 740d 0a55 7365 722d 4167 656e 743a ost..User-Agent:
- 0x0060: 2045 4c69 6e6b 732f 302e 3130 2e34 2d37 .ELinks/0.10.4-7
- 0x0070: 2d64 6562 6961 6e20 2874 6578 746d 6f64 -debian.(textmod
- 0x0080: 653b 204c 696e 7578 2032 2e36 2e31 312d e;.Linux.2.6.11-
- 0x0090: 312d 3638 362d 736d 7020 6936 3836 3b20 1-686-smp.i686;.
- 0x00a0: 3133 3278 3536 2d32 290d 0a41 6363 6570 132x56-2)..Accep
- 0x00b0: 743a 202a 2f2a 0d0a 4163 6365 7074 2d45 t:.*/*..Accept-E
- 0x00c0: 6e63 6f64 696e 673a 2067 7a69 700d 0a41 ncoding:.gzip..A
- 0x00d0: 6363 6570 742d 4c61 6e67 7561 6765 3a20 ccept-Language:.
- 0x00e0: 656e 0d0a 436f 6e6e 6563 7469 6f6e 3a20 en..Connection:.
- 0x00f0: 4b65 6570 2d41 6c69 7665 0d0a 0d0a Keep-Alive....
-23:57:35.940474 IP 127.0.0.1.80 > 127.0.0.1.55920: . ack 203 win 8192 <nop,nop,timestamp 1306300952 1306300951>
- 0x0000: 4500 0034 1fe4 4000 4006 1cde 7f00 0001 E..4..@.@.......
- 0x0010: 7f00 0001 0050 da70 377a 8df2 3758 8a49 .....P.p7z..7X.I
- 0x0020: 8010 2000 3703 0000 0101 080a 4ddc 9218 ....7.......M...
- 0x0030: 4ddc 9217 M...
-23:57:35.941232 IP 127.0.0.1.80 > 127.0.0.1.55920: P 1:5560(5559) ack 203 win 8192 <nop,nop,timestamp 1306300953 1306300951>
- 0x0000: 4500 15eb 1fe6 4000 4006 0725 7f00 0001 E.....@.@..%....
- 0x0010: 7f00 0001 0050 da70 377a 8df2 3758 8a49 .....P.p7z..7X.I
- 0x0020: 8018 2000 13e0 0000 0101 080a 4ddc 9219 ............M...
- 0x0030: 4ddc 9217 4854 5450 2f31 2e31 2032 3030 M...HTTP/1.1.200
- 0x0040: 204f 4b0d 0a44 6174 653a 2057 6564 2c20 .OK..Date:.Wed,.
- 0x0050: 3036 204a 756c 2032 3030 3520 3033 3a35 06.Jul.2005.03:5
- 0x0060: 373a 3335 2047 4d54 0d0a 5365 7276 6572 7:35.GMT..Server
- 0x0070: 3a20 4170 6163 6865 2f31 2e33 2e33 330d :.Apache/1.3.33.
- 0x0080: 0a4c 6173 742d 4d6f 6469 6669 6564 3a20 .Last-Modified:.
- 0x0090: 5375 6e2c 2031 3520 4175 6720 3230 3034 Sun,.15.Aug.2004
- 0x00a0: 2030 303a 3433 3a34 3120 474d 540d 0a45 .00:43:41.GMT..E
- 0x00b0: 5461 673a 2022 3665 3830 6630 2d31 3438 Tag:."6e80f0-148
- 0x00c0: 612d 3431 3165 6231 6264 220d 0a41 6363 a-411eb1bd"..Acc
- 0x00d0: 6570 742d 5261 6e67 6573 3a20 6279 7465 ept-Ranges:.byte
- 0x00e0: 730d 0a43 6f6e 7465 6e74 2d4c 656e 6774 s..Content-Lengt
- 0x00f0: 683a 2035 3235 380d 0a4b 6565 702d 416c h:.5258..Keep-Al
- 0x0100: 6976 653a 2074 696d 656f 7574 3d31 352c ive:.timeout=15,
- 0x0110: 206d 6178 3d31 3030 0d0a 436f 6e6e 6563 .max=100..Connec
- 0x0120: 7469 6f6e 3a20 4b65 6570 2d41 6c69 7665 tion:.Keep-Alive
- 0x0130: 0d0a 436f 6e74 656e 742d 5479 7065 3a20 ..Content-Type:.
- 0x0140: 7465 7874 2f68 746d 6c3b 2063 6861 7273 text/html;.chars
- 0x0150: 6574 3d69 736f 2d38 3835 392d 310d 0a0d et=iso-8859-1...
- 0x0160: 0a3c 2144 4f43 5459 5045 2048 544d 4c20 .<!DOCTYPE.HTML.
- 0x0170: 5055 424c 4943 2022 2d2f 2f57 3343 2f2f PUBLIC."-//W3C//
- 0x0180: 4454 4420 4854 4d4c 2034 2e30 3120 5472 DTD.HTML.4.01.Tr
- 0x0190: 616e 7369 7469 6f6e 616c 2f2f 454e 223e ansitional//EN">
- 0x01a0: 0a3c 4854 4d4c 3e0a 3c48 4541 443e 0a20 .<HTML>.<HEAD>..
- 0x01b0: 2020 3c4d 4554 4120 4854 5450 2d45 5155 ..<META.HTTP-EQU
- 0x01c0: 4956 3d22 436f 6e74 656e 742d 5479 7065 IV="Content-Type
- 0x01d0: 2220 434f 4e54 454e 543d 2274 6578 742f ".CONTENT="text/
- 0x01e0: 6874 6d6c 3b20 6368 6172 7365 743d 6973 html;.charset=is
- 0x01f0: 6f2d 3838 3539 2d31 223e 0a20 2020 3c4d o-8859-1">....<M
- 0x0200: 4554 4120 4e41 4d45 3d22 4465 7363 7269 ETA.NAME="Descri
- 0x0210: 7074 696f 6e22 2043 4f4e 5445 4e54 3d22 ption".CONTENT="
- 0x0220: 5468 6520 696e 6974 6961 6c20 696e 7374 The.initial.inst
- 0x0230: 616c 6c61 7469 6f6e 206f 6620 4465 6269 allation.of.Debi
- 0x0240: 616e 2061 7061 6368 652e 223e 0a20 2020 an.apache.">....
- 0x0250: 3c54 4954 4c45 3e50 6c61 6365 686f 6c64 <TITLE>Placehold
- 0x0260: 6572 2070 6167 653c 2f54 4954 4c45 3e0a er.page</TITLE>.
- 0x0270: 3c2f 4845 4144 3e0a 3c42 4f44 5920 5445 </HEAD>.<BODY.TE
- 0x0280: 5854 3d22 2330 3030 3030 3022 2042 4743 XT="#000000".BGC
- 0x0290: 4f4c 4f52 3d22 2346 4646 4646 4622 204c OLOR="#FFFFFF".L
- 0x02a0: 494e 4b3d 2223 3030 3030 4546 2220 564c INK="#0000EF".VL
- 0x02b0: 494e 4b3d 2223 3535 3138 3841 2220 414c INK="#55188A".AL
- 0x02c0: 494e 4b3d 2223 4646 3030 3030 223e 0a0a INK="#FF0000">..
- 0x02d0: 3c48 313e 506c 6163 6568 6f6c 6465 7220 <H1>Placeholder.
- 0x02e0: 7061 6765 3c2f 4831 3e0a 3c48 323e 4966 page</H1>.<H2>If
- 0x02f0: 2079 6f75 2061 7265 206a 7573 7420 6272 .you.are.just.br
- 0x0300: 6f77 7369 6e67 2074 6865 2077 6562 3c2f owsing.the.web</
- 0x0310: 6832 3e0a 0a3c 503e 5468 6520 6f77 6e65 h2>..<P>The.owne
- 0x0320: 7220 6f66 2074 6869 7320 7765 6220 7369 r.of.this.web.si
- 0x0330: 7465 2068 6173 206e 6f74 2070 7574 2075 te.has.not.put.u
- 0x0340: 7020 616e 7920 7765 6220 7061 6765 7320 p.any.web.pages.
- 0x0350: 7965 742e 0a50 6c65 6173 6520 636f 6d65 yet..Please.come
- 0x0360: 2062 6163 6b20 6c61 7465 722e 3c2f 503e .back.later.</P>
- 0x0370: 0a0a 3c50 3e3c 534d 414c 4c3e 3c43 4954 ..<P><SMALL><CIT
- 0x0380: 453e 4d6f 7665 2061 6c6f 6e67 2c20 6e6f E>Move.along,.no
- 0x0390: 7468 696e 6720 746f 2073 6565 2068 6572 thing.to.see.her
- 0x03a0: 652e 2e2e 3c2f 4349 5445 3e20 3a2d 293c e...</CITE>.:-)<
- 0x03b0: 2f53 4d41 4c4c 3e3c 2f50 3e0a 0a3c 4832 /SMALL></P>..<H2
- 0x03c0: 3e49 6620 796f 7520 6172 6520 7472 7969 >If.you.are.tryi
- 0x03d0: 6e67 2074 6f20 6c6f 6361 7465 2074 6865 ng.to.locate.the
- 0x03e0: 2061 646d 696e 6973 7472 6174 6f72 206f .administrator.o
- 0x03f0: 6620 7468 6973 206d 6163 6869 6e65 3c2f f.this.machine</
- 0x0400: 4832 3e0a 0a3c 503e 4966 2079 6f75 2077 H2>..<P>If.you.w
- 0x0410: 616e 7420 746f 2072 6570 6f72 7420 736f ant.to.report.so
- 0x0420: 6d65 7468 696e 6720 6162 6f75 7420 7468 mething.about.th
- 0x0430: 6973 2068 6f73 7427 7320 6265 6861 7669 is.host's.behavi
- 0x0440: 6f72 2c20 706c 6561 7365 0a63 6f6e 7461 or,.please.conta
- 0x0450: 6374 2074 6865 2049 6e74 6572 6e65 7420 ct.the.Internet.
- 0x0460: 5365 7276 6963 6520 5072 6f76 6964 6572 Service.Provider
- 0x0470: 2028 4953 5029 2069 6e76 6f6c 7665 6420 .(ISP).involved.
- 0x0480: 6469 7265 6374 6c79 2e3c 2f50 3e0a 0a3c directly.</P>..<
- 0x0490: 503e 5365 6520 7468 6520 3c41 2068 7265 P>See.the.<A.hre
- 0x04a0: 663d 2268 7474 703a 2f2f 7777 772e 6162 f="http://www.ab
- 0x04b0: 7573 652e 6e65 742f 223e 4e65 7477 6f72 use.net/">Networ
- 0x04c0: 6b20 4162 7573 650a 436c 6561 7269 6e67 k.Abuse.Clearing
- 0x04d0: 686f 7573 653c 2f41 3e20 666f 7220 686f house</A>.for.ho
- 0x04e0: 7720 746f 2064 6f20 7468 6973 2e3c 2f50 w.to.do.this.</P
- 0x04f0: 3e0a 0a3c 4832 3e49 6620 796f 7520 6172 >..<H2>If.you.ar
- 0x0500: 6520 7468 6520 6164 6d69 6e69 7374 7261 e.the.administra
- 0x0510: 746f 7220 6f66 2074 6869 7320 6d61 6368 tor.of.this.mach
- 0x0520: 696e 653c 2f48 323e 0a0a 3c50 3e54 6865 ine</H2>..<P>The
- 0x0530: 2069 6e69 7469 616c 2069 6e73 7461 6c6c .initial.install
- 0x0540: 6174 696f 6e20 6f66 203c 4120 6872 6566 ation.of.<A.href
- 0x0550: 3d22 6874 7470 3a2f 2f77 7777 2e64 6562 ="http://www.deb
- 0x0560: 6961 6e2e 6f72 672f 223e 4465 6269 616e ian.org/">Debian
- 0x0570: 2773 0a61 7061 6368 653c 2f41 3e20 7765 's.apache</A>.we
- 0x0580: 6220 7365 7276 6572 2070 6163 6b61 6765 b.server.package
- 0x0590: 2077 6173 2073 7563 6365 7373 6675 6c2e .was.successful.
- 0x05a0: 3c2f 503e 0a0a 3c50 3e3c 5354 524f 4e47 </P>..<P><STRONG
- 0x05b0: 3e59 6f75 2073 686f 756c 6420 7265 706c >You.should.repl
- 0x05c0: 6163 6520 7468 6973 2070 6167 6520 7769 ace.this.page.wi
- 0x05d0: 7468 2079 6f75 7220 6f77 6e20 7765 6220 th.your.own.web.
- 0x05e0: 7061 6765 7320 6173 0a73 6f6f 6e20 6173 pages.as.soon.as
- 0x05f0: 2070 6f73 7369 626c 652e 3c2f 5354 524f .possible.</STRO
- 0x0600: 4e47 3e3c 2f50 3e0a 0a3c 503e 556e 6c65 NG></P>..<P>Unle
- 0x0610: 7373 2079 6f75 2063 6861 6e67 6564 2069 ss.you.changed.i
- 0x0620: 7473 2063 6f6e 6669 6775 7261 7469 6f6e ts.configuration
- 0x0630: 2c20 796f 7572 206e 6577 2073 6572 7665 ,.your.new.serve
- 0x0640: 7220 6973 2063 6f6e 6669 6775 7265 6420 r.is.configured.
- 0x0650: 6173 2066 6f6c 6c6f 7773 3a0a 3c55 4c3e as.follows:.<UL>
- 0x0660: 0a3c 4c49 3e0a 436f 6e66 6967 7572 6174 .<LI>.Configurat
- 0x0670: 696f 6e20 6669 6c65 7320 6361 6e20 6265 ion.files.can.be
- 0x0680: 2066 6f75 6e64 2069 6e20 3c54 543e 2f65 .found.in.<TT>/e
- 0x0690: 7463 2f61 7061 6368 653c 2f54 543e 2e3c tc/apache</TT>.<
- 0x06a0: 2f4c 493e 0a0a 3c4c 493e 0a54 6865 203c /LI>..<LI>.The.<
- 0x06b0: 5454 3e44 6f63 756d 656e 7452 6f6f 743c TT>DocumentRoot<
- 0x06c0: 2f54 543e 2c20 7768 6963 6820 6973 2074 /TT>,.which.is.t
- 0x06d0: 6865 2064 6972 6563 746f 7279 2075 6e64 he.directory.und
- 0x06e0: 6572 2077 6869 6368 2061 6c6c 2079 6f75 er.which.all.you
- 0x06f0: 720a 4854 4d4c 2066 696c 6573 2073 686f r.HTML.files.sho
- 0x0700: 756c 6420 6578 6973 742c 2069 7320 7365 uld.exist,.is.se
- 0x0710: 7420 746f 203c 5454 3e2f 7661 722f 7777 t.to.<TT>/var/ww
- 0x0720: 773c 2f54 543e 2e3c 2f4c 493e 0a0a 3c4c w</TT>.</LI>..<L
- 0x0730: 493e 0a43 4749 2073 6372 6970 7473 2061 I>.CGI.scripts.a
- 0x0740: 7265 206c 6f6f 6b65 6420 666f 7220 696e re.looked.for.in
- 0x0750: 203c 5454 3e2f 7573 722f 6c69 622f 6367 .<TT>/usr/lib/cg
- 0x0760: 692d 6269 6e3c 2f54 543e 2c20 7768 6963 i-bin</TT>,.whic
- 0x0770: 6820 6973 2077 6865 7265 0a44 6562 6961 h.is.where.Debia
- 0x0780: 6e20 7061 636b 6167 6573 2077 696c 6c20 n.packages.will.
- 0x0790: 706c 6163 6520 7468 6569 7220 7363 7269 place.their.scri
- 0x07a0: 7074 732e 3c2f 4c49 3e0a 0a3c 4c49 3e0a pts.</LI>..<LI>.
- 0x07b0: 4c6f 6720 6669 6c65 7320 6172 6520 706c Log.files.are.pl
- 0x07c0: 6163 6564 2069 6e20 3c54 543e 2f76 6172 aced.in.<TT>/var
- 0x07d0: 2f6c 6f67 2f61 7061 6368 653c 2f54 543e /log/apache</TT>
- 0x07e0: 2c20 616e 6420 7769 6c6c 2062 6520 726f ,.and.will.be.ro
- 0x07f0: 7461 7465 640a 7765 656b 6c79 2e20 2054 tated.weekly...T
- 0x0800: 6865 2066 7265 7175 656e 6379 206f 6620 he.frequency.of.
- 0x0810: 726f 7461 7469 6f6e 2063 616e 2062 6520 rotation.can.be.
- 0x0820: 6561 7369 6c79 2063 6861 6e67 6564 2062 easily.changed.b
- 0x0830: 7920 6564 6974 696e 670a 3c54 543e 2f65 y.editing.<TT>/e
- 0x0840: 7463 2f6c 6f67 726f 7461 7465 2e64 2f61 tc/logrotate.d/a
- 0x0850: 7061 6368 653c 2f54 543e 2e3c 2f4c 493e pache</TT>.</LI>
- 0x0860: 0a0a 3c4c 493e 0a54 6865 2064 6566 6175 ..<LI>.The.defau
- 0x0870: 6c74 2064 6972 6563 746f 7279 2069 6e64 lt.directory.ind
- 0x0880: 6578 2069 7320 3c54 543e 696e 6465 782e ex.is.<TT>index.
- 0x0890: 6874 6d6c 3c2f 5454 3e2c 206d 6561 6e69 html</TT>,.meani
- 0x08a0: 6e67 2074 6861 7420 7265 7175 6573 7473 ng.that.requests
- 0x08b0: 0a66 6f72 2061 2064 6972 6563 746f 7279 .for.a.directory
- 0x08c0: 203c 5454 3e2f 666f 6f2f 6261 722f 3c2f .<TT>/foo/bar/</
- 0x08d0: 5454 3e20 7769 6c6c 2067 6976 6520 7468 TT>.will.give.th
- 0x08e0: 6520 636f 6e74 656e 7473 206f 6620 7468 e.contents.of.th
- 0x08f0: 6520 6669 6c65 203c 5454 3e2f 7661 722f e.file.<TT>/var/
- 0x0900: 7777 772f 666f 6f2f 6261 722f 696e 6465 www/foo/bar/inde
- 0x0910: 782e 6874 6d6c 3c2f 5454 3e0a 6966 2069 x.html</TT>.if.i
- 0x0920: 7420 6578 6973 7473 2028 6173 7375 6d69 t.exists.(assumi
- 0x0930: 6e67 2074 6861 7420 3c54 543e 2f76 6172 ng.that.<TT>/var
- 0x0940: 2f77 7777 3c2f 5454 3e20 6973 2079 6f75 /www</TT>.is.you
- 0x0950: 7220 3c54 543e 446f 6375 6d65 6e74 526f r.<TT>DocumentRo
- 0x0960: 6f74 3c2f 5454 3e29 2e3c 2f4c 493e 0a0a ot</TT>).</LI>..
- 0x0970: 3c4c 493e 0a55 7365 7220 6469 7265 6374 <LI>.User.direct
- 0x0980: 6f72 6965 7320 6172 6520 656e 6162 6c65 ories.are.enable
- 0x0990: 642c 2061 6e64 2075 7365 7220 646f 6375 d,.and.user.docu
- 0x09a0: 6d65 6e74 7320 7769 6c6c 2062 6520 6c6f ments.will.be.lo
- 0x09b0: 6f6b 6564 2066 6f72 0a69 6e20 7468 6520 oked.for.in.the.
- 0x09c0: 3c54 543e 7075 626c 6963 5f68 746d 6c3c <TT>public_html<
- 0x09d0: 2f54 543e 2064 6972 6563 746f 7279 206f /TT>.directory.o
- 0x09e0: 6620 7468 6520 7573 6572 7327 2068 6f6d f.the.users'.hom
- 0x09f0: 6573 2e20 2054 6865 7365 2064 6972 730a es...These.dirs.
- 0x0a00: 7368 6f75 6c64 2062 6520 756e 6465 7220 should.be.under.
- 0x0a10: 3c54 543e 2f68 6f6d 653c 2f54 543e 2c20 <TT>/home</TT>,.
- 0x0a20: 616e 6420 7573 6572 7320 7769 6c6c 206e and.users.will.n
- 0x0a30: 6f74 2062 6520 6162 6c65 2074 6f20 7379 ot.be.able.to.sy
- 0x0a40: 6d6c 696e 6b0a 746f 2066 696c 6573 2074 mlink.to.files.t
- 0x0a50: 6865 7920 646f 6e27 7420 6f77 6e2e 3c2f hey.don't.own.</
- 0x0a60: 4c49 3e0a 0a3c 2f55 4c3e 0a41 6c6c 2074 LI>..</UL>.All.t
- 0x0a70: 6865 2073 7461 6e64 6172 6420 6170 6163 he.standard.apac
- 0x0a80: 6865 206d 6f64 756c 6573 2061 7265 2061 he.modules.are.a
- 0x0a90: 7661 696c 6162 6c65 2077 6974 6820 7468 vailable.with.th
- 0x0aa0: 6973 2072 656c 6561 7365 2061 6e64 2061 is.release.and.a
- 0x0ab0: 7265 0a6e 6f77 206d 616e 6167 6564 2077 re.now.managed.w
- 0x0ac0: 6974 6820 6465 6263 6f6e 662e 2020 5479 ith.debconf...Ty
- 0x0ad0: 7065 203c 5454 3e64 706b 672d 7265 636f pe.<TT>dpkg-reco
- 0x0ae0: 6e66 6967 7572 6520 6170 6163 6865 3c2f nfigure.apache</
- 0x0af0: 5454 3e20 746f 0a73 656c 6563 7420 7768 TT>.to.select.wh
- 0x0b00: 6963 6820 6d6f 6475 6c65 7320 796f 7520 ich.modules.you.
- 0x0b10: 7761 6e74 2065 6e61 626c 6564 2e20 204d want.enabled...M
- 0x0b20: 616e 7920 6f74 6865 7220 6d6f 6475 6c65 any.other.module
- 0x0b30: 7320 6172 6520 6176 6169 6c61 626c 650a s.are.available.
- 0x0b40: 7468 726f 7567 6820 7468 6520 4465 6269 through.the.Debi
- 0x0b50: 616e 2070 6163 6b61 6765 2073 7973 7465 an.package.syste
- 0x0b60: 6d20 7769 7468 2074 6865 206e 616d 6573 m.with.the.names
- 0x0b70: 203c 5454 3e6c 6962 6170 6163 6865 2d6d .<TT>libapache-m
- 0x0b80: 6f64 2d2a 3c2f 5454 3e2e 0a49 6620 796f od-*</TT>..If.yo
- 0x0b90: 7520 6e65 6564 2074 6f20 636f 6d70 696c u.need.to.compil
- 0x0ba0: 6520 6120 6d6f 6475 6c65 2079 6f75 7273 e.a.module.yours
- 0x0bb0: 656c 662c 2079 6f75 2077 696c 6c20 6e65 elf,.you.will.ne
- 0x0bc0: 6564 2074 6f20 696e 7374 616c 6c20 7468 ed.to.install.th
- 0x0bd0: 650a 3c54 543e 6170 6163 6865 2d64 6576 e.<TT>apache-dev
- 0x0be0: 3c2f 5454 3e20 7061 636b 6167 652e 0a0a </TT>.package...
- 0x0bf0: 3c50 3e4d 6f72 6520 646f 6375 6d65 6e74 <P>More.document
- 0x0c00: 6174 696f 6e20 6f6e 2041 7061 6368 6520 ation.on.Apache.
- 0x0c10: 6361 6e20 6265 2066 6f75 6e64 206f 6e3a can.be.found.on:
- 0x0c20: 0a3c 554c 3e0a 3c4c 493e 0a54 6865 203c .<UL>.<LI>.The.<
- 0x0c30: 4120 4852 4546 3d22 2f64 6f63 2f61 7061 A.HREF="/doc/apa
- 0x0c40: 6368 652d 646f 632f 6d61 6e75 616c 2f22 che-doc/manual/"
- 0x0c50: 3e41 7061 6368 6520 646f 6375 6d65 6e74 >Apache.document
- 0x0c60: 6174 696f 6e3c 2f41 3e20 7374 6f72 6564 ation</A>.stored
- 0x0c70: 206f 6e20 796f 7572 2073 6572 7665 722e .on.your.server.
- 0x0c80: 3c2f 4c49 3e0a 0a3c 4c49 3e0a 5468 6520 </LI>..<LI>.The.
- 0x0c90: 3c41 2048 5245 463d 2268 7474 703a 2f2f <A.HREF="http://
- 0x0ca0: 7777 772e 6170 6163 6865 2e6f 7267 2f22 www.apache.org/"
- 0x0cb0: 3e41 7061 6368 6520 5072 6f6a 6563 743c >Apache.Project<
- 0x0cc0: 2f41 3e20 686f 6d65 2073 6974 652e 3c2f /A>.home.site.</
- 0x0cd0: 4c49 3e0a 0a3c 4c49 3e0a 5468 6520 3c41 LI>..<LI>.The.<A
- 0x0ce0: 2048 5245 463d 2268 7474 703a 2f2f 7777 .HREF="http://ww
- 0x0cf0: 772e 6170 6163 6865 2d73 736c 2e6f 7267 w.apache-ssl.org
- 0x0d00: 2f22 3e41 7061 6368 652d 5353 4c3c 2f41 /">Apache-SSL</A
- 0x0d10: 3e20 686f 6d65 2073 6974 652e 3c2f 4c49 >.home.site.</LI
- 0x0d20: 3e0a 0a3c 4c49 3e0a 5468 6520 3c41 2048 >..<LI>.The.<A.H
- 0x0d30: 5245 463d 2268 7474 703a 2f2f 7065 726c REF="http://perl
- 0x0d40: 2e61 7061 6368 652e 6f72 672f 223e 6d6f .apache.org/">mo
- 0x0d50: 6420 7065 726c 3c2f 413e 2068 6f6d 6520 d.perl</A>.home.
- 0x0d60: 7369 7465 2e3c 2f4c 493e 0a0a 3c4c 493e site.</LI>..<LI>
- 0x0d70: 0a54 6865 203c 4120 4852 4546 3d22 6874 .The.<A.HREF="ht
- 0x0d80: 7470 3a2f 2f77 7777 2e61 7061 6368 6577 tp://www.apachew
- 0x0d90: 6565 6b2e 636f 6d2f 223e 4170 6163 6865 eek.com/">Apache
- 0x0da0: 5765 656b 3c2f 413e 206e 6577 736c 6574 Week</A>.newslet
- 0x0db0: 7465 722e 3c2f 4c49 3e0a 0a3c 4c49 3e0a ter.</LI>..<LI>.
- 0x0dc0: 5468 6520 3c41 2048 5245 463d 2268 7474 The.<A.HREF="htt
- 0x0dd0: 703a 2f2f 7777 772e 6465 6269 616e 2e6f p://www.debian.o
- 0x0de0: 7267 2f64 6f63 2f22 3e44 6562 6961 6e20 rg/doc/">Debian.
- 0x0df0: 5072 6f6a 6563 740a 446f 6375 6d65 6e74 Project.Document
- 0x0e00: 6174 696f 6e3c 2f41 3e20 7768 6963 6820 ation</A>.which.
- 0x0e10: 636f 6e74 6169 6e73 2048 4f57 544f 732c contains.HOWTOs,
- 0x0e20: 2046 4151 732c 2061 6e64 2073 6f66 7477 .FAQs,.and.softw
- 0x0e30: 6172 6520 7570 6461 7465 732e 3c2f 4c49 are.updates.</LI
- 0x0e40: 3e0a 3c2f 554c 3e0a 0a3c 503e 596f 7520 >.</UL>..<P>You.
- 0x0e50: 6361 6e20 616c 736f 2063 6f6e 7375 6c74 can.also.consult
- 0x0e60: 2074 6865 206c 6973 7420 6f66 203c 4120 .the.list.of.<A.
- 0x0e70: 4852 4546 3d22 6874 7470 3a2f 2f77 7777 HREF="http://www
- 0x0e80: 2e62 6f75 7465 6c6c 2e63 6f6d 2f66 6171 .boutell.com/faq
- 0x0e90: 2f22 3e57 6f72 6c64 0a57 6964 6520 5765 /">World.Wide.We
- 0x0ea0: 6220 4672 6571 7565 6e74 6c79 2041 736b b.Frequently.Ask
- 0x0eb0: 6564 2051 7565 7374 696f 6e73 3c2f 413e ed.Questions</A>
- 0x0ec0: 2066 6f72 2069 6e66 6f72 6d61 7469 6f6e .for.information
- 0x0ed0: 2e0a 0a3c 4832 3e4c 6574 206f 7468 6572 ...<H2>Let.other
- 0x0ee0: 2070 656f 706c 6520 6b6e 6f77 2061 626f .people.know.abo
- 0x0ef0: 7574 2074 6869 7320 7365 7276 6572 3c2f ut.this.server</
- 0x0f00: 4832 3e0a 0a3c 4120 4852 4546 3d22 6874 H2>..<A.HREF="ht
- 0x0f10: 7470 3a2f 2f6e 6574 6372 6166 742e 636f tp://netcraft.co
- 0x0f20: 6d2f 223e 4e65 7463 7261 6674 3c2f 413e m/">Netcraft</A>
- 0x0f30: 2070 726f 7669 6465 7320 616e 2069 6e74 .provides.an.int
- 0x0f40: 6572 6573 7469 6e67 2066 7265 650a 7365 eresting.free.se
- 0x0f50: 7276 6963 6520 666f 7220 7765 6220 7369 rvice.for.web.si
- 0x0f60: 7465 206d 6f6e 6974 6f72 696e 6720 616e te.monitoring.an
- 0x0f70: 6420 7374 6174 6973 7469 6320 636f 6c6c d.statistic.coll
- 0x0f80: 6563 7469 6f6e 2e0a 596f 7520 6361 6e20 ection..You.can.
- 0x0f90: 6c65 7420 7468 656d 206b 6e6f 7720 6162 let.them.know.ab
- 0x0fa0: 6f75 7420 796f 7572 2073 6572 7665 7220 out.your.server.
- 0x0fb0: 7573 696e 6720 7468 6569 720a 3c41 2048 using.their.<A.H
- 0x0fc0: 5245 463d 2268 7474 703a 2f2f 7570 7469 REF="http://upti
- 0x0fd0: 6d65 2e6e 6574 6372 6166 742e 636f 6d2f me.netcraft.com/
- 0x0fe0: 223e 696e 7465 7266 6163 653c 2f41 3e2e ">interface</A>.
- 0x0ff0: 0a45 6e61 626c 696e 6720 7468 6520 6d6f .Enabling.the.mo
- 0x1000: 6e69 746f 7269 6e67 206f 6620 796f 7572 nitoring.of.your
- 0x1010: 2073 6572 7665 7220 7769 6c6c 2070 726f .server.will.pro
- 0x1020: 7669 6465 2061 2062 6574 7465 7220 676c vide.a.better.gl
- 0x1030: 6f62 616c 206f 7665 7276 6965 770a 6f66 obal.overview.of
- 0x1040: 2077 686f 2069 7320 7573 696e 6720 7768 .who.is.using.wh
- 0x1050: 6174 2061 6e64 2077 6865 7265 2c20 616e at.and.where,.an
- 0x1060: 6420 6974 2077 6f75 6c64 2067 6976 6520 d.it.would.give.
- 0x1070: 4465 6269 616e 2061 2062 6574 7465 720a Debian.a.better.
- 0x1080: 6f76 6572 7669 6577 206f 6620 7468 6520 overview.of.the.
- 0x1090: 6170 6163 6865 2070 6163 6b61 6765 2075 apache.package.u
- 0x10a0: 7361 6765 2e0a 0a3c 4832 3e41 626f 7574 sage...<H2>About
- 0x10b0: 2074 6869 7320 7061 6765 3c2f 4832 3e0a .this.page</H2>.
- 0x10c0: 0a3c 494d 4720 414c 4947 4e3d 2272 6967 .<IMG.ALIGN="rig
- 0x10d0: 6874 2220 414c 543d 2222 2048 4549 4748 ht".ALT="".HEIGH
- 0x10e0: 543d 2232 3437 2220 5749 4454 483d 2232 T="247".WIDTH="2
- 0x10f0: 3738 2220 5352 433d 2269 636f 6e73 2f6a 78".SRC="icons/j
- 0x1100: 6865 3036 312e 706e 6722 3e0a 0a3c 503e he061.png">..<P>
- 0x1110: 5468 6973 2069 7320 6120 706c 6163 6568 This.is.a.placeh
- 0x1120: 6f6c 6465 7220 7061 6765 2069 6e73 7461 older.page.insta
- 0x1130: 6c6c 6564 2062 7920 7468 6520 3c41 0a48 lled.by.the.<A.H
- 0x1140: 5245 463d 2268 7474 703a 2f2f 7777 772e REF="http://www.
- 0x1150: 6465 6269 616e 2e6f 7267 2f22 3e44 6562 debian.org/">Deb
- 0x1160: 6961 6e3c 2f41 3e0a 7265 6c65 6173 6520 ian</A>.release.
- 0x1170: 6f66 2074 6865 2061 7061 6368 6520 5765 of.the.apache.We
- 0x1180: 6220 7365 7276 6572 2070 6163 6b61 6765 b.server.package
- 0x1190: 2e0a 0a3c 503e 5468 6973 2063 6f6d 7075 ...<P>This.compu
- 0x11a0: 7465 7220 6861 7320 696e 7374 616c 6c65 ter.has.installe
- 0x11b0: 6420 7468 6520 4465 6269 616e 2047 4e55 d.the.Debian.GNU
- 0x11c0: 2f4c 696e 7578 206f 7065 7261 7469 6e67 /Linux.operating
- 0x11d0: 2073 7973 7465 6d2c 0a62 7574 2069 7420 .system,.but.it.
- 0x11e0: 6861 7320 3c73 7472 6f6e 673e 6e6f 7468 has.<strong>noth
- 0x11f0: 696e 6720 746f 2064 6f20 7769 7468 2074 ing.to.do.with.t
- 0x1200: 6865 2044 6562 6961 6e0a 5072 6f6a 6563 he.Debian.Projec
- 0x1210: 743c 2f73 7472 6f6e 673e 2e20 506c 6561 t</strong>..Plea
- 0x1220: 7365 2064 6f20 3c73 7472 6f6e 673e 6e6f se.do.<strong>no
- 0x1230: 743c 2f73 7472 6f6e 673e 2063 6f6e 7461 t</strong>.conta
- 0x1240: 6374 2074 6865 2044 6562 6961 6e0a 5072 ct.the.Debian.Pr
- 0x1250: 6f6a 6563 7420 6162 6f75 7420 6974 2e3c oject.about.it.<
- 0x1260: 2f50 3e0a 0a3c 503e 4966 2079 6f75 2066 /P>..<P>If.you.f
- 0x1270: 696e 6420 6120 6275 6720 696e 2074 6869 ind.a.bug.in.thi
- 0x1280: 7320 6170 6163 6865 2070 6163 6b61 6765 s.apache.package
- 0x1290: 2c20 6f72 2069 6e20 4170 6163 6865 2069 ,.or.in.Apache.i
- 0x12a0: 7473 656c 662c 0a70 6c65 6173 6520 6669 tself,.please.fi
- 0x12b0: 6c65 2061 2062 7567 2072 6570 6f72 7420 le.a.bug.report.
- 0x12c0: 6f6e 2069 742e 2020 496e 7374 7275 6374 on.it...Instruct
- 0x12d0: 696f 6e73 206f 6e20 646f 696e 6720 7468 ions.on.doing.th
- 0x12e0: 6973 2c20 616e 6420 7468 650a 6c69 7374 is,.and.the.list
- 0x12f0: 206f 6620 3c41 2048 5245 463d 2268 7474 .of.<A.HREF="htt
- 0x1300: 703a 2f2f 6275 6773 2e64 6562 6961 6e2e p://bugs.debian.
- 0x1310: 6f72 672f 7372 633a 6170 6163 6865 223e org/src:apache">
- 0x1320: 6b6e 6f77 6e20 6275 6773 3c2f 413e 206f known.bugs</A>.o
- 0x1330: 6620 7468 6973 0a70 6163 6b61 6765 2c20 f.this.package,.
- 0x1340: 6361 6e20 6265 2066 6f75 6e64 2069 6e20 can.be.found.in.
- 0x1350: 7468 6520 0a3c 4120 4852 4546 3d22 6874 the..<A.HREF="ht
- 0x1360: 7470 3a2f 2f77 7777 2e64 6562 6961 6e2e tp://www.debian.
- 0x1370: 6f72 672f 4275 6773 2f52 6570 6f72 7469 org/Bugs/Reporti
- 0x1380: 6e67 223e 4465 6269 616e 2042 7567 2054 ng">Debian.Bug.T
- 0x1390: 7261 636b 696e 6720 5379 7374 656d 3c2f racking.System</
- 0x13a0: 413e 2e0a 0a3c 503e 5468 616e 6b73 2066 A>...<P>Thanks.f
- 0x13b0: 6f72 2075 7369 6e67 2074 6869 7320 7061 or.using.this.pa
- 0x13c0: 636b 6167 652c 2061 6e64 2063 6f6e 6772 ckage,.and.congr
- 0x13d0: 6174 756c 6174 696f 6e73 2066 6f72 2079 atulations.for.y
- 0x13e0: 6f75 7220 6368 6f69 6365 206f 660a 6120 our.choice.of.a.
- 0x13f0: 4465 6269 616e 2073 7973 7465 6d21 3c2f Debian.system!</
- 0x1400: 503e 0a0a 3c44 4956 2061 6c69 676e 3d22 P>..<DIV.align="
- 0x1410: 6365 6e74 6572 223e 0a3c 6120 6872 6566 center">.<a.href
- 0x1420: 3d22 6874 7470 3a2f 2f77 7777 2e64 6562 ="http://www.deb
- 0x1430: 6961 6e2e 6f72 672f 223e 0a3c 494d 4720 ian.org/">.<IMG.
- 0x1440: 616c 6967 6e3d 226d 6964 646c 6522 2068 align="middle".h
- 0x1450: 6569 6768 743d 2233 3022 2077 6964 7468 eight="30".width
- 0x1460: 3d22 3235 2220 7372 633d 2269 636f 6e73 ="25".src="icons
- 0x1470: 2f64 6562 6961 6e2f 6f70 656e 6c6f 676f /debian/openlogo
- 0x1480: 2d32 352e 6a70 6722 2061 6c74 3d22 4465 -25.jpg".alt="De
- 0x1490: 6269 616e 223e 0a3c 2f61 3e0a 3c61 2068 bian">.</a>.<a.h
- 0x14a0: 7265 663d 2268 7474 703a 2f2f 7777 772e ref="http://www.
- 0x14b0: 6170 6163 6865 2e6f 7267 2f22 3e0a 3c49 apache.org/">.<I
- 0x14c0: 4d47 2061 6c69 676e 3d22 6d69 6464 6c65 MG.align="middle
- 0x14d0: 2220 6865 6967 6874 3d22 3332 2220 7769 ".height="32".wi
- 0x14e0: 6474 683d 2232 3539 2220 7372 633d 2269 dth="259".src="i
- 0x14f0: 636f 6e73 2f61 7061 6368 655f 7062 2e70 cons/apache_pb.p
- 0x1500: 6e67 2220 616c 743d 2241 7061 6368 6522 ng".alt="Apache"
- 0x1510: 3e0a 3c2f 613e 0a3c 2f44 4956 3e0a 0a3c >.</a>.</DIV>..<
- 0x1520: 212d 2d0a 2020 5468 6973 2070 6167 6520 !--...This.page.
- 0x1530: 7761 7320 696e 6974 6961 6c6c 7920 6372 was.initially.cr
- 0x1540: 6561 7465 6420 6279 204a 6f68 6e69 6520 eated.by.Johnie.
- 0x1550: 496e 6772 616d 2028 6874 7470 3a2f 2f6e Ingram.(http://n
- 0x1560: 6574 676f 642e 6e65 742f 290a 2020 4974 etgod.net/)...It
- 0x1570: 2077 6173 206c 6174 6572 2065 6469 7465 .was.later.edite
- 0x1580: 6420 6279 204d 6174 7468 6577 2057 696c d.by.Matthew.Wil
- 0x1590: 636f 7820 616e 6420 4a6f 7369 7020 526f cox.and.Josip.Ro
- 0x15a0: 6469 6e2e 0a20 204c 6173 7420 6d6f 6469 din....Last.modi
- 0x15b0: 6669 6564 3a20 2444 6174 653a 2032 3030 fied:.$Date:.200
- 0x15c0: 342f 3036 2f32 3020 3135 3a33 333a 3537 4/06/20.15:33:57
- 0x15d0: 2024 2e0a 2020 2d2d 3e0a 0a3c 2f42 4f44 .$....-->..</BOD
- 0x15e0: 593e 0a3c 2f48 544d 4c3e 0a Y>.</HTML>.
-23:57:35.941260 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5560 win 12383 <nop,nop,timestamp 1306300953 1306300953>
- 0x0000: 4500 0034 1b6e 4000 4006 2154 7f00 0001 E..4.n@.@.!T....
- 0x0010: 7f00 0001 da70 0050 3758 8a49 377a a3a9 .....p.P7X.I7z..
- 0x0020: 8010 305f 10ea 0000 0101 080a 4ddc 9219 ..0_........M...
- 0x0030: 4ddc 9219 M...
-23:57:37.229575 IP 127.0.0.1.55920 > 127.0.0.1.80: F 203:203(0) ack 5560 win 12383 <nop,nop,timestamp 1306302241 1306300953>
- 0x0000: 4500 0034 1b70 4000 4006 2152 7f00 0001 E..4.p@.@.!R....
- 0x0010: 7f00 0001 da70 0050 3758 8a49 377a a3a9 .....p.P7X.I7z..
- 0x0020: 8011 305f 0be1 0000 0101 080a 4ddc 9721 ..0_........M..!
- 0x0030: 4ddc 9219 M...
-23:57:37.230839 IP 127.0.0.1.80 > 127.0.0.1.55920: F 5560:5560(0) ack 204 win 8192 <nop,nop,timestamp 1306302243 1306302241>
- 0x0000: 4500 0034 1fe8 4000 4006 1cda 7f00 0001 E..4..@.@.......
- 0x0010: 7f00 0001 0050 da70 377a a3a9 3758 8a4a .....P.p7z..7X.J
- 0x0020: 8011 2000 1735 0000 0101 080a 4ddc 9723 .....5......M..#
- 0x0030: 4ddc 9721 M..!
-23:57:37.230900 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5561 win 12383 <nop,nop,timestamp 1306302243 1306302243>
- 0x0000: 4500 0034 1b72 4000 4006 2150 7f00 0001 E..4.r@.@.!P....
- 0x0010: 7f00 0001 da70 0050 3758 8a4a 377a a3aa .....p.P7X.J7z..
- 0x0020: 8010 305f 06d4 0000 0101 080a 4ddc 9723 ..0_........M..#
- 0x0030: 4ddc 9723 M..#
diff --git a/contrib/tcpdump/tests/print-XX.out b/contrib/tcpdump/tests/print-XX.out
deleted file mode 100644
index 6921a01..0000000
--- a/contrib/tcpdump/tests/print-XX.out
+++ /dev/null
@@ -1,419 +0,0 @@
-23:57:35.938066 IP 127.0.0.1.55920 > 127.0.0.1.80: S 928549246:928549246(0) win 32767 <mss 16396,sackOK,timestamp 1306300950 0,nop,wscale 2>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 003c 1b68 4000 4006 2152 7f00 0001 7f00 .<.h@.@.!R......
- 0x0020: 0001 da70 0050 3758 897e 0000 0000 a002 ...p.P7X.~......
- 0x0030: 7fff 1421 0000 0204 400c 0402 080a 4ddc ...!....@.....M.
- 0x0040: 9216 0000 0000 0103 0302 ..........
-23:57:35.938122 IP 127.0.0.1.80 > 127.0.0.1.55920: S 930778609:930778609(0) ack 928549247 win 32767 <mss 16396,sackOK,timestamp 1306300950 1306300950,nop,wscale 2>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 003c 0000 4000 4006 3cba 7f00 0001 7f00 .<..@.@.<.......
- 0x0020: 0001 0050 da70 377a 8df1 3758 897f a012 ...P.p7z..7X....
- 0x0030: 7fff 6eb1 0000 0204 400c 0402 080a 4ddc ..n.....@.....M.
- 0x0040: 9216 4ddc 9216 0103 0302 ..M.......
-23:57:35.938167 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 1 win 8192 <nop,nop,timestamp 1306300950 1306300950>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1b6a 4000 4006 2158 7f00 0001 7f00 .4.j@.@.!X......
- 0x0020: 0001 da70 0050 3758 897f 377a 8df2 8010 ...p.P7X..7z....
- 0x0030: 2000 37d0 0000 0101 080a 4ddc 9216 4ddc ..7.......M...M.
- 0x0040: 9216 ..
-23:57:35.939423 IP 127.0.0.1.55920 > 127.0.0.1.80: P 1:203(202) ack 1 win 8192 <nop,nop,timestamp 1306300951 1306300950>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 00fe 1b6c 4000 4006 208c 7f00 0001 7f00 ...l@.@.........
- 0x0020: 0001 da70 0050 3758 897f 377a 8df2 8018 ...p.P7X..7z....
- 0x0030: 2000 fef2 0000 0101 080a 4ddc 9217 4ddc ..........M...M.
- 0x0040: 9216 4745 5420 2f20 4854 5450 2f31 2e31 ..GET./.HTTP/1.1
- 0x0050: 0d0a 486f 7374 3a20 6c6f 6361 6c68 6f73 ..Host:.localhos
- 0x0060: 740d 0a55 7365 722d 4167 656e 743a 2045 t..User-Agent:.E
- 0x0070: 4c69 6e6b 732f 302e 3130 2e34 2d37 2d64 Links/0.10.4-7-d
- 0x0080: 6562 6961 6e20 2874 6578 746d 6f64 653b ebian.(textmode;
- 0x0090: 204c 696e 7578 2032 2e36 2e31 312d 312d .Linux.2.6.11-1-
- 0x00a0: 3638 362d 736d 7020 6936 3836 3b20 3133 686-smp.i686;.13
- 0x00b0: 3278 3536 2d32 290d 0a41 6363 6570 743a 2x56-2)..Accept:
- 0x00c0: 202a 2f2a 0d0a 4163 6365 7074 2d45 6e63 .*/*..Accept-Enc
- 0x00d0: 6f64 696e 673a 2067 7a69 700d 0a41 6363 oding:.gzip..Acc
- 0x00e0: 6570 742d 4c61 6e67 7561 6765 3a20 656e ept-Language:.en
- 0x00f0: 0d0a 436f 6e6e 6563 7469 6f6e 3a20 4b65 ..Connection:.Ke
- 0x0100: 6570 2d41 6c69 7665 0d0a 0d0a ep-Alive....
-23:57:35.940474 IP 127.0.0.1.80 > 127.0.0.1.55920: . ack 203 win 8192 <nop,nop,timestamp 1306300952 1306300951>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1fe4 4000 4006 1cde 7f00 0001 7f00 .4..@.@.........
- 0x0020: 0001 0050 da70 377a 8df2 3758 8a49 8010 ...P.p7z..7X.I..
- 0x0030: 2000 3703 0000 0101 080a 4ddc 9218 4ddc ..7.......M...M.
- 0x0040: 9217 ..
-23:57:35.941232 IP 127.0.0.1.80 > 127.0.0.1.55920: P 1:5560(5559) ack 203 win 8192 <nop,nop,timestamp 1306300953 1306300951>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 15eb 1fe6 4000 4006 0725 7f00 0001 7f00 ....@.@..%......
- 0x0020: 0001 0050 da70 377a 8df2 3758 8a49 8018 ...P.p7z..7X.I..
- 0x0030: 2000 13e0 0000 0101 080a 4ddc 9219 4ddc ..........M...M.
- 0x0040: 9217 4854 5450 2f31 2e31 2032 3030 204f ..HTTP/1.1.200.O
- 0x0050: 4b0d 0a44 6174 653a 2057 6564 2c20 3036 K..Date:.Wed,.06
- 0x0060: 204a 756c 2032 3030 3520 3033 3a35 373a .Jul.2005.03:57:
- 0x0070: 3335 2047 4d54 0d0a 5365 7276 6572 3a20 35.GMT..Server:.
- 0x0080: 4170 6163 6865 2f31 2e33 2e33 330d 0a4c Apache/1.3.33..L
- 0x0090: 6173 742d 4d6f 6469 6669 6564 3a20 5375 ast-Modified:.Su
- 0x00a0: 6e2c 2031 3520 4175 6720 3230 3034 2030 n,.15.Aug.2004.0
- 0x00b0: 303a 3433 3a34 3120 474d 540d 0a45 5461 0:43:41.GMT..ETa
- 0x00c0: 673a 2022 3665 3830 6630 2d31 3438 612d g:."6e80f0-148a-
- 0x00d0: 3431 3165 6231 6264 220d 0a41 6363 6570 411eb1bd"..Accep
- 0x00e0: 742d 5261 6e67 6573 3a20 6279 7465 730d t-Ranges:.bytes.
- 0x00f0: 0a43 6f6e 7465 6e74 2d4c 656e 6774 683a .Content-Length:
- 0x0100: 2035 3235 380d 0a4b 6565 702d 416c 6976 .5258..Keep-Aliv
- 0x0110: 653a 2074 696d 656f 7574 3d31 352c 206d e:.timeout=15,.m
- 0x0120: 6178 3d31 3030 0d0a 436f 6e6e 6563 7469 ax=100..Connecti
- 0x0130: 6f6e 3a20 4b65 6570 2d41 6c69 7665 0d0a on:.Keep-Alive..
- 0x0140: 436f 6e74 656e 742d 5479 7065 3a20 7465 Content-Type:.te
- 0x0150: 7874 2f68 746d 6c3b 2063 6861 7273 6574 xt/html;.charset
- 0x0160: 3d69 736f 2d38 3835 392d 310d 0a0d 0a3c =iso-8859-1....<
- 0x0170: 2144 4f43 5459 5045 2048 544d 4c20 5055 !DOCTYPE.HTML.PU
- 0x0180: 424c 4943 2022 2d2f 2f57 3343 2f2f 4454 BLIC."-//W3C//DT
- 0x0190: 4420 4854 4d4c 2034 2e30 3120 5472 616e D.HTML.4.01.Tran
- 0x01a0: 7369 7469 6f6e 616c 2f2f 454e 223e 0a3c sitional//EN">.<
- 0x01b0: 4854 4d4c 3e0a 3c48 4541 443e 0a20 2020 HTML>.<HEAD>....
- 0x01c0: 3c4d 4554 4120 4854 5450 2d45 5155 4956 <META.HTTP-EQUIV
- 0x01d0: 3d22 436f 6e74 656e 742d 5479 7065 2220 ="Content-Type".
- 0x01e0: 434f 4e54 454e 543d 2274 6578 742f 6874 CONTENT="text/ht
- 0x01f0: 6d6c 3b20 6368 6172 7365 743d 6973 6f2d ml;.charset=iso-
- 0x0200: 3838 3539 2d31 223e 0a20 2020 3c4d 4554 8859-1">....<MET
- 0x0210: 4120 4e41 4d45 3d22 4465 7363 7269 7074 A.NAME="Descript
- 0x0220: 696f 6e22 2043 4f4e 5445 4e54 3d22 5468 ion".CONTENT="Th
- 0x0230: 6520 696e 6974 6961 6c20 696e 7374 616c e.initial.instal
- 0x0240: 6c61 7469 6f6e 206f 6620 4465 6269 616e lation.of.Debian
- 0x0250: 2061 7061 6368 652e 223e 0a20 2020 3c54 .apache.">....<T
- 0x0260: 4954 4c45 3e50 6c61 6365 686f 6c64 6572 ITLE>Placeholder
- 0x0270: 2070 6167 653c 2f54 4954 4c45 3e0a 3c2f .page</TITLE>.</
- 0x0280: 4845 4144 3e0a 3c42 4f44 5920 5445 5854 HEAD>.<BODY.TEXT
- 0x0290: 3d22 2330 3030 3030 3022 2042 4743 4f4c ="#000000".BGCOL
- 0x02a0: 4f52 3d22 2346 4646 4646 4622 204c 494e OR="#FFFFFF".LIN
- 0x02b0: 4b3d 2223 3030 3030 4546 2220 564c 494e K="#0000EF".VLIN
- 0x02c0: 4b3d 2223 3535 3138 3841 2220 414c 494e K="#55188A".ALIN
- 0x02d0: 4b3d 2223 4646 3030 3030 223e 0a0a 3c48 K="#FF0000">..<H
- 0x02e0: 313e 506c 6163 6568 6f6c 6465 7220 7061 1>Placeholder.pa
- 0x02f0: 6765 3c2f 4831 3e0a 3c48 323e 4966 2079 ge</H1>.<H2>If.y
- 0x0300: 6f75 2061 7265 206a 7573 7420 6272 6f77 ou.are.just.brow
- 0x0310: 7369 6e67 2074 6865 2077 6562 3c2f 6832 sing.the.web</h2
- 0x0320: 3e0a 0a3c 503e 5468 6520 6f77 6e65 7220 >..<P>The.owner.
- 0x0330: 6f66 2074 6869 7320 7765 6220 7369 7465 of.this.web.site
- 0x0340: 2068 6173 206e 6f74 2070 7574 2075 7020 .has.not.put.up.
- 0x0350: 616e 7920 7765 6220 7061 6765 7320 7965 any.web.pages.ye
- 0x0360: 742e 0a50 6c65 6173 6520 636f 6d65 2062 t..Please.come.b
- 0x0370: 6163 6b20 6c61 7465 722e 3c2f 503e 0a0a ack.later.</P>..
- 0x0380: 3c50 3e3c 534d 414c 4c3e 3c43 4954 453e <P><SMALL><CITE>
- 0x0390: 4d6f 7665 2061 6c6f 6e67 2c20 6e6f 7468 Move.along,.noth
- 0x03a0: 696e 6720 746f 2073 6565 2068 6572 652e ing.to.see.here.
- 0x03b0: 2e2e 3c2f 4349 5445 3e20 3a2d 293c 2f53 ..</CITE>.:-)</S
- 0x03c0: 4d41 4c4c 3e3c 2f50 3e0a 0a3c 4832 3e49 MALL></P>..<H2>I
- 0x03d0: 6620 796f 7520 6172 6520 7472 7969 6e67 f.you.are.trying
- 0x03e0: 2074 6f20 6c6f 6361 7465 2074 6865 2061 .to.locate.the.a
- 0x03f0: 646d 696e 6973 7472 6174 6f72 206f 6620 dministrator.of.
- 0x0400: 7468 6973 206d 6163 6869 6e65 3c2f 4832 this.machine</H2
- 0x0410: 3e0a 0a3c 503e 4966 2079 6f75 2077 616e >..<P>If.you.wan
- 0x0420: 7420 746f 2072 6570 6f72 7420 736f 6d65 t.to.report.some
- 0x0430: 7468 696e 6720 6162 6f75 7420 7468 6973 thing.about.this
- 0x0440: 2068 6f73 7427 7320 6265 6861 7669 6f72 .host's.behavior
- 0x0450: 2c20 706c 6561 7365 0a63 6f6e 7461 6374 ,.please.contact
- 0x0460: 2074 6865 2049 6e74 6572 6e65 7420 5365 .the.Internet.Se
- 0x0470: 7276 6963 6520 5072 6f76 6964 6572 2028 rvice.Provider.(
- 0x0480: 4953 5029 2069 6e76 6f6c 7665 6420 6469 ISP).involved.di
- 0x0490: 7265 6374 6c79 2e3c 2f50 3e0a 0a3c 503e rectly.</P>..<P>
- 0x04a0: 5365 6520 7468 6520 3c41 2068 7265 663d See.the.<A.href=
- 0x04b0: 2268 7474 703a 2f2f 7777 772e 6162 7573 "http://www.abus
- 0x04c0: 652e 6e65 742f 223e 4e65 7477 6f72 6b20 e.net/">Network.
- 0x04d0: 4162 7573 650a 436c 6561 7269 6e67 686f Abuse.Clearingho
- 0x04e0: 7573 653c 2f41 3e20 666f 7220 686f 7720 use</A>.for.how.
- 0x04f0: 746f 2064 6f20 7468 6973 2e3c 2f50 3e0a to.do.this.</P>.
- 0x0500: 0a3c 4832 3e49 6620 796f 7520 6172 6520 .<H2>If.you.are.
- 0x0510: 7468 6520 6164 6d69 6e69 7374 7261 746f the.administrato
- 0x0520: 7220 6f66 2074 6869 7320 6d61 6368 696e r.of.this.machin
- 0x0530: 653c 2f48 323e 0a0a 3c50 3e54 6865 2069 e</H2>..<P>The.i
- 0x0540: 6e69 7469 616c 2069 6e73 7461 6c6c 6174 nitial.installat
- 0x0550: 696f 6e20 6f66 203c 4120 6872 6566 3d22 ion.of.<A.href="
- 0x0560: 6874 7470 3a2f 2f77 7777 2e64 6562 6961 http://www.debia
- 0x0570: 6e2e 6f72 672f 223e 4465 6269 616e 2773 n.org/">Debian's
- 0x0580: 0a61 7061 6368 653c 2f41 3e20 7765 6220 .apache</A>.web.
- 0x0590: 7365 7276 6572 2070 6163 6b61 6765 2077 server.package.w
- 0x05a0: 6173 2073 7563 6365 7373 6675 6c2e 3c2f as.successful.</
- 0x05b0: 503e 0a0a 3c50 3e3c 5354 524f 4e47 3e59 P>..<P><STRONG>Y
- 0x05c0: 6f75 2073 686f 756c 6420 7265 706c 6163 ou.should.replac
- 0x05d0: 6520 7468 6973 2070 6167 6520 7769 7468 e.this.page.with
- 0x05e0: 2079 6f75 7220 6f77 6e20 7765 6220 7061 .your.own.web.pa
- 0x05f0: 6765 7320 6173 0a73 6f6f 6e20 6173 2070 ges.as.soon.as.p
- 0x0600: 6f73 7369 626c 652e 3c2f 5354 524f 4e47 ossible.</STRONG
- 0x0610: 3e3c 2f50 3e0a 0a3c 503e 556e 6c65 7373 ></P>..<P>Unless
- 0x0620: 2079 6f75 2063 6861 6e67 6564 2069 7473 .you.changed.its
- 0x0630: 2063 6f6e 6669 6775 7261 7469 6f6e 2c20 .configuration,.
- 0x0640: 796f 7572 206e 6577 2073 6572 7665 7220 your.new.server.
- 0x0650: 6973 2063 6f6e 6669 6775 7265 6420 6173 is.configured.as
- 0x0660: 2066 6f6c 6c6f 7773 3a0a 3c55 4c3e 0a3c .follows:.<UL>.<
- 0x0670: 4c49 3e0a 436f 6e66 6967 7572 6174 696f LI>.Configuratio
- 0x0680: 6e20 6669 6c65 7320 6361 6e20 6265 2066 n.files.can.be.f
- 0x0690: 6f75 6e64 2069 6e20 3c54 543e 2f65 7463 ound.in.<TT>/etc
- 0x06a0: 2f61 7061 6368 653c 2f54 543e 2e3c 2f4c /apache</TT>.</L
- 0x06b0: 493e 0a0a 3c4c 493e 0a54 6865 203c 5454 I>..<LI>.The.<TT
- 0x06c0: 3e44 6f63 756d 656e 7452 6f6f 743c 2f54 >DocumentRoot</T
- 0x06d0: 543e 2c20 7768 6963 6820 6973 2074 6865 T>,.which.is.the
- 0x06e0: 2064 6972 6563 746f 7279 2075 6e64 6572 .directory.under
- 0x06f0: 2077 6869 6368 2061 6c6c 2079 6f75 720a .which.all.your.
- 0x0700: 4854 4d4c 2066 696c 6573 2073 686f 756c HTML.files.shoul
- 0x0710: 6420 6578 6973 742c 2069 7320 7365 7420 d.exist,.is.set.
- 0x0720: 746f 203c 5454 3e2f 7661 722f 7777 773c to.<TT>/var/www<
- 0x0730: 2f54 543e 2e3c 2f4c 493e 0a0a 3c4c 493e /TT>.</LI>..<LI>
- 0x0740: 0a43 4749 2073 6372 6970 7473 2061 7265 .CGI.scripts.are
- 0x0750: 206c 6f6f 6b65 6420 666f 7220 696e 203c .looked.for.in.<
- 0x0760: 5454 3e2f 7573 722f 6c69 622f 6367 692d TT>/usr/lib/cgi-
- 0x0770: 6269 6e3c 2f54 543e 2c20 7768 6963 6820 bin</TT>,.which.
- 0x0780: 6973 2077 6865 7265 0a44 6562 6961 6e20 is.where.Debian.
- 0x0790: 7061 636b 6167 6573 2077 696c 6c20 706c packages.will.pl
- 0x07a0: 6163 6520 7468 6569 7220 7363 7269 7074 ace.their.script
- 0x07b0: 732e 3c2f 4c49 3e0a 0a3c 4c49 3e0a 4c6f s.</LI>..<LI>.Lo
- 0x07c0: 6720 6669 6c65 7320 6172 6520 706c 6163 g.files.are.plac
- 0x07d0: 6564 2069 6e20 3c54 543e 2f76 6172 2f6c ed.in.<TT>/var/l
- 0x07e0: 6f67 2f61 7061 6368 653c 2f54 543e 2c20 og/apache</TT>,.
- 0x07f0: 616e 6420 7769 6c6c 2062 6520 726f 7461 and.will.be.rota
- 0x0800: 7465 640a 7765 656b 6c79 2e20 2054 6865 ted.weekly...The
- 0x0810: 2066 7265 7175 656e 6379 206f 6620 726f .frequency.of.ro
- 0x0820: 7461 7469 6f6e 2063 616e 2062 6520 6561 tation.can.be.ea
- 0x0830: 7369 6c79 2063 6861 6e67 6564 2062 7920 sily.changed.by.
- 0x0840: 6564 6974 696e 670a 3c54 543e 2f65 7463 editing.<TT>/etc
- 0x0850: 2f6c 6f67 726f 7461 7465 2e64 2f61 7061 /logrotate.d/apa
- 0x0860: 6368 653c 2f54 543e 2e3c 2f4c 493e 0a0a che</TT>.</LI>..
- 0x0870: 3c4c 493e 0a54 6865 2064 6566 6175 6c74 <LI>.The.default
- 0x0880: 2064 6972 6563 746f 7279 2069 6e64 6578 .directory.index
- 0x0890: 2069 7320 3c54 543e 696e 6465 782e 6874 .is.<TT>index.ht
- 0x08a0: 6d6c 3c2f 5454 3e2c 206d 6561 6e69 6e67 ml</TT>,.meaning
- 0x08b0: 2074 6861 7420 7265 7175 6573 7473 0a66 .that.requests.f
- 0x08c0: 6f72 2061 2064 6972 6563 746f 7279 203c or.a.directory.<
- 0x08d0: 5454 3e2f 666f 6f2f 6261 722f 3c2f 5454 TT>/foo/bar/</TT
- 0x08e0: 3e20 7769 6c6c 2067 6976 6520 7468 6520 >.will.give.the.
- 0x08f0: 636f 6e74 656e 7473 206f 6620 7468 6520 contents.of.the.
- 0x0900: 6669 6c65 203c 5454 3e2f 7661 722f 7777 file.<TT>/var/ww
- 0x0910: 772f 666f 6f2f 6261 722f 696e 6465 782e w/foo/bar/index.
- 0x0920: 6874 6d6c 3c2f 5454 3e0a 6966 2069 7420 html</TT>.if.it.
- 0x0930: 6578 6973 7473 2028 6173 7375 6d69 6e67 exists.(assuming
- 0x0940: 2074 6861 7420 3c54 543e 2f76 6172 2f77 .that.<TT>/var/w
- 0x0950: 7777 3c2f 5454 3e20 6973 2079 6f75 7220 ww</TT>.is.your.
- 0x0960: 3c54 543e 446f 6375 6d65 6e74 526f 6f74 <TT>DocumentRoot
- 0x0970: 3c2f 5454 3e29 2e3c 2f4c 493e 0a0a 3c4c </TT>).</LI>..<L
- 0x0980: 493e 0a55 7365 7220 6469 7265 6374 6f72 I>.User.director
- 0x0990: 6965 7320 6172 6520 656e 6162 6c65 642c ies.are.enabled,
- 0x09a0: 2061 6e64 2075 7365 7220 646f 6375 6d65 .and.user.docume
- 0x09b0: 6e74 7320 7769 6c6c 2062 6520 6c6f 6f6b nts.will.be.look
- 0x09c0: 6564 2066 6f72 0a69 6e20 7468 6520 3c54 ed.for.in.the.<T
- 0x09d0: 543e 7075 626c 6963 5f68 746d 6c3c 2f54 T>public_html</T
- 0x09e0: 543e 2064 6972 6563 746f 7279 206f 6620 T>.directory.of.
- 0x09f0: 7468 6520 7573 6572 7327 2068 6f6d 6573 the.users'.homes
- 0x0a00: 2e20 2054 6865 7365 2064 6972 730a 7368 ...These.dirs.sh
- 0x0a10: 6f75 6c64 2062 6520 756e 6465 7220 3c54 ould.be.under.<T
- 0x0a20: 543e 2f68 6f6d 653c 2f54 543e 2c20 616e T>/home</TT>,.an
- 0x0a30: 6420 7573 6572 7320 7769 6c6c 206e 6f74 d.users.will.not
- 0x0a40: 2062 6520 6162 6c65 2074 6f20 7379 6d6c .be.able.to.syml
- 0x0a50: 696e 6b0a 746f 2066 696c 6573 2074 6865 ink.to.files.the
- 0x0a60: 7920 646f 6e27 7420 6f77 6e2e 3c2f 4c49 y.don't.own.</LI
- 0x0a70: 3e0a 0a3c 2f55 4c3e 0a41 6c6c 2074 6865 >..</UL>.All.the
- 0x0a80: 2073 7461 6e64 6172 6420 6170 6163 6865 .standard.apache
- 0x0a90: 206d 6f64 756c 6573 2061 7265 2061 7661 .modules.are.ava
- 0x0aa0: 696c 6162 6c65 2077 6974 6820 7468 6973 ilable.with.this
- 0x0ab0: 2072 656c 6561 7365 2061 6e64 2061 7265 .release.and.are
- 0x0ac0: 0a6e 6f77 206d 616e 6167 6564 2077 6974 .now.managed.wit
- 0x0ad0: 6820 6465 6263 6f6e 662e 2020 5479 7065 h.debconf...Type
- 0x0ae0: 203c 5454 3e64 706b 672d 7265 636f 6e66 .<TT>dpkg-reconf
- 0x0af0: 6967 7572 6520 6170 6163 6865 3c2f 5454 igure.apache</TT
- 0x0b00: 3e20 746f 0a73 656c 6563 7420 7768 6963 >.to.select.whic
- 0x0b10: 6820 6d6f 6475 6c65 7320 796f 7520 7761 h.modules.you.wa
- 0x0b20: 6e74 2065 6e61 626c 6564 2e20 204d 616e nt.enabled...Man
- 0x0b30: 7920 6f74 6865 7220 6d6f 6475 6c65 7320 y.other.modules.
- 0x0b40: 6172 6520 6176 6169 6c61 626c 650a 7468 are.available.th
- 0x0b50: 726f 7567 6820 7468 6520 4465 6269 616e rough.the.Debian
- 0x0b60: 2070 6163 6b61 6765 2073 7973 7465 6d20 .package.system.
- 0x0b70: 7769 7468 2074 6865 206e 616d 6573 203c with.the.names.<
- 0x0b80: 5454 3e6c 6962 6170 6163 6865 2d6d 6f64 TT>libapache-mod
- 0x0b90: 2d2a 3c2f 5454 3e2e 0a49 6620 796f 7520 -*</TT>..If.you.
- 0x0ba0: 6e65 6564 2074 6f20 636f 6d70 696c 6520 need.to.compile.
- 0x0bb0: 6120 6d6f 6475 6c65 2079 6f75 7273 656c a.module.yoursel
- 0x0bc0: 662c 2079 6f75 2077 696c 6c20 6e65 6564 f,.you.will.need
- 0x0bd0: 2074 6f20 696e 7374 616c 6c20 7468 650a .to.install.the.
- 0x0be0: 3c54 543e 6170 6163 6865 2d64 6576 3c2f <TT>apache-dev</
- 0x0bf0: 5454 3e20 7061 636b 6167 652e 0a0a 3c50 TT>.package...<P
- 0x0c00: 3e4d 6f72 6520 646f 6375 6d65 6e74 6174 >More.documentat
- 0x0c10: 696f 6e20 6f6e 2041 7061 6368 6520 6361 ion.on.Apache.ca
- 0x0c20: 6e20 6265 2066 6f75 6e64 206f 6e3a 0a3c n.be.found.on:.<
- 0x0c30: 554c 3e0a 3c4c 493e 0a54 6865 203c 4120 UL>.<LI>.The.<A.
- 0x0c40: 4852 4546 3d22 2f64 6f63 2f61 7061 6368 HREF="/doc/apach
- 0x0c50: 652d 646f 632f 6d61 6e75 616c 2f22 3e41 e-doc/manual/">A
- 0x0c60: 7061 6368 6520 646f 6375 6d65 6e74 6174 pache.documentat
- 0x0c70: 696f 6e3c 2f41 3e20 7374 6f72 6564 206f ion</A>.stored.o
- 0x0c80: 6e20 796f 7572 2073 6572 7665 722e 3c2f n.your.server.</
- 0x0c90: 4c49 3e0a 0a3c 4c49 3e0a 5468 6520 3c41 LI>..<LI>.The.<A
- 0x0ca0: 2048 5245 463d 2268 7474 703a 2f2f 7777 .HREF="http://ww
- 0x0cb0: 772e 6170 6163 6865 2e6f 7267 2f22 3e41 w.apache.org/">A
- 0x0cc0: 7061 6368 6520 5072 6f6a 6563 743c 2f41 pache.Project</A
- 0x0cd0: 3e20 686f 6d65 2073 6974 652e 3c2f 4c49 >.home.site.</LI
- 0x0ce0: 3e0a 0a3c 4c49 3e0a 5468 6520 3c41 2048 >..<LI>.The.<A.H
- 0x0cf0: 5245 463d 2268 7474 703a 2f2f 7777 772e REF="http://www.
- 0x0d00: 6170 6163 6865 2d73 736c 2e6f 7267 2f22 apache-ssl.org/"
- 0x0d10: 3e41 7061 6368 652d 5353 4c3c 2f41 3e20 >Apache-SSL</A>.
- 0x0d20: 686f 6d65 2073 6974 652e 3c2f 4c49 3e0a home.site.</LI>.
- 0x0d30: 0a3c 4c49 3e0a 5468 6520 3c41 2048 5245 .<LI>.The.<A.HRE
- 0x0d40: 463d 2268 7474 703a 2f2f 7065 726c 2e61 F="http://perl.a
- 0x0d50: 7061 6368 652e 6f72 672f 223e 6d6f 6420 pache.org/">mod.
- 0x0d60: 7065 726c 3c2f 413e 2068 6f6d 6520 7369 perl</A>.home.si
- 0x0d70: 7465 2e3c 2f4c 493e 0a0a 3c4c 493e 0a54 te.</LI>..<LI>.T
- 0x0d80: 6865 203c 4120 4852 4546 3d22 6874 7470 he.<A.HREF="http
- 0x0d90: 3a2f 2f77 7777 2e61 7061 6368 6577 6565 ://www.apachewee
- 0x0da0: 6b2e 636f 6d2f 223e 4170 6163 6865 5765 k.com/">ApacheWe
- 0x0db0: 656b 3c2f 413e 206e 6577 736c 6574 7465 ek</A>.newslette
- 0x0dc0: 722e 3c2f 4c49 3e0a 0a3c 4c49 3e0a 5468 r.</LI>..<LI>.Th
- 0x0dd0: 6520 3c41 2048 5245 463d 2268 7474 703a e.<A.HREF="http:
- 0x0de0: 2f2f 7777 772e 6465 6269 616e 2e6f 7267 //www.debian.org
- 0x0df0: 2f64 6f63 2f22 3e44 6562 6961 6e20 5072 /doc/">Debian.Pr
- 0x0e00: 6f6a 6563 740a 446f 6375 6d65 6e74 6174 oject.Documentat
- 0x0e10: 696f 6e3c 2f41 3e20 7768 6963 6820 636f ion</A>.which.co
- 0x0e20: 6e74 6169 6e73 2048 4f57 544f 732c 2046 ntains.HOWTOs,.F
- 0x0e30: 4151 732c 2061 6e64 2073 6f66 7477 6172 AQs,.and.softwar
- 0x0e40: 6520 7570 6461 7465 732e 3c2f 4c49 3e0a e.updates.</LI>.
- 0x0e50: 3c2f 554c 3e0a 0a3c 503e 596f 7520 6361 </UL>..<P>You.ca
- 0x0e60: 6e20 616c 736f 2063 6f6e 7375 6c74 2074 n.also.consult.t
- 0x0e70: 6865 206c 6973 7420 6f66 203c 4120 4852 he.list.of.<A.HR
- 0x0e80: 4546 3d22 6874 7470 3a2f 2f77 7777 2e62 EF="http://www.b
- 0x0e90: 6f75 7465 6c6c 2e63 6f6d 2f66 6171 2f22 outell.com/faq/"
- 0x0ea0: 3e57 6f72 6c64 0a57 6964 6520 5765 6220 >World.Wide.Web.
- 0x0eb0: 4672 6571 7565 6e74 6c79 2041 736b 6564 Frequently.Asked
- 0x0ec0: 2051 7565 7374 696f 6e73 3c2f 413e 2066 .Questions</A>.f
- 0x0ed0: 6f72 2069 6e66 6f72 6d61 7469 6f6e 2e0a or.information..
- 0x0ee0: 0a3c 4832 3e4c 6574 206f 7468 6572 2070 .<H2>Let.other.p
- 0x0ef0: 656f 706c 6520 6b6e 6f77 2061 626f 7574 eople.know.about
- 0x0f00: 2074 6869 7320 7365 7276 6572 3c2f 4832 .this.server</H2
- 0x0f10: 3e0a 0a3c 4120 4852 4546 3d22 6874 7470 >..<A.HREF="http
- 0x0f20: 3a2f 2f6e 6574 6372 6166 742e 636f 6d2f ://netcraft.com/
- 0x0f30: 223e 4e65 7463 7261 6674 3c2f 413e 2070 ">Netcraft</A>.p
- 0x0f40: 726f 7669 6465 7320 616e 2069 6e74 6572 rovides.an.inter
- 0x0f50: 6573 7469 6e67 2066 7265 650a 7365 7276 esting.free.serv
- 0x0f60: 6963 6520 666f 7220 7765 6220 7369 7465 ice.for.web.site
- 0x0f70: 206d 6f6e 6974 6f72 696e 6720 616e 6420 .monitoring.and.
- 0x0f80: 7374 6174 6973 7469 6320 636f 6c6c 6563 statistic.collec
- 0x0f90: 7469 6f6e 2e0a 596f 7520 6361 6e20 6c65 tion..You.can.le
- 0x0fa0: 7420 7468 656d 206b 6e6f 7720 6162 6f75 t.them.know.abou
- 0x0fb0: 7420 796f 7572 2073 6572 7665 7220 7573 t.your.server.us
- 0x0fc0: 696e 6720 7468 6569 720a 3c41 2048 5245 ing.their.<A.HRE
- 0x0fd0: 463d 2268 7474 703a 2f2f 7570 7469 6d65 F="http://uptime
- 0x0fe0: 2e6e 6574 6372 6166 742e 636f 6d2f 223e .netcraft.com/">
- 0x0ff0: 696e 7465 7266 6163 653c 2f41 3e2e 0a45 interface</A>..E
- 0x1000: 6e61 626c 696e 6720 7468 6520 6d6f 6e69 nabling.the.moni
- 0x1010: 746f 7269 6e67 206f 6620 796f 7572 2073 toring.of.your.s
- 0x1020: 6572 7665 7220 7769 6c6c 2070 726f 7669 erver.will.provi
- 0x1030: 6465 2061 2062 6574 7465 7220 676c 6f62 de.a.better.glob
- 0x1040: 616c 206f 7665 7276 6965 770a 6f66 2077 al.overview.of.w
- 0x1050: 686f 2069 7320 7573 696e 6720 7768 6174 ho.is.using.what
- 0x1060: 2061 6e64 2077 6865 7265 2c20 616e 6420 .and.where,.and.
- 0x1070: 6974 2077 6f75 6c64 2067 6976 6520 4465 it.would.give.De
- 0x1080: 6269 616e 2061 2062 6574 7465 720a 6f76 bian.a.better.ov
- 0x1090: 6572 7669 6577 206f 6620 7468 6520 6170 erview.of.the.ap
- 0x10a0: 6163 6865 2070 6163 6b61 6765 2075 7361 ache.package.usa
- 0x10b0: 6765 2e0a 0a3c 4832 3e41 626f 7574 2074 ge...<H2>About.t
- 0x10c0: 6869 7320 7061 6765 3c2f 4832 3e0a 0a3c his.page</H2>..<
- 0x10d0: 494d 4720 414c 4947 4e3d 2272 6967 6874 IMG.ALIGN="right
- 0x10e0: 2220 414c 543d 2222 2048 4549 4748 543d ".ALT="".HEIGHT=
- 0x10f0: 2232 3437 2220 5749 4454 483d 2232 3738 "247".WIDTH="278
- 0x1100: 2220 5352 433d 2269 636f 6e73 2f6a 6865 ".SRC="icons/jhe
- 0x1110: 3036 312e 706e 6722 3e0a 0a3c 503e 5468 061.png">..<P>Th
- 0x1120: 6973 2069 7320 6120 706c 6163 6568 6f6c is.is.a.placehol
- 0x1130: 6465 7220 7061 6765 2069 6e73 7461 6c6c der.page.install
- 0x1140: 6564 2062 7920 7468 6520 3c41 0a48 5245 ed.by.the.<A.HRE
- 0x1150: 463d 2268 7474 703a 2f2f 7777 772e 6465 F="http://www.de
- 0x1160: 6269 616e 2e6f 7267 2f22 3e44 6562 6961 bian.org/">Debia
- 0x1170: 6e3c 2f41 3e0a 7265 6c65 6173 6520 6f66 n</A>.release.of
- 0x1180: 2074 6865 2061 7061 6368 6520 5765 6220 .the.apache.Web.
- 0x1190: 7365 7276 6572 2070 6163 6b61 6765 2e0a server.package..
- 0x11a0: 0a3c 503e 5468 6973 2063 6f6d 7075 7465 .<P>This.compute
- 0x11b0: 7220 6861 7320 696e 7374 616c 6c65 6420 r.has.installed.
- 0x11c0: 7468 6520 4465 6269 616e 2047 4e55 2f4c the.Debian.GNU/L
- 0x11d0: 696e 7578 206f 7065 7261 7469 6e67 2073 inux.operating.s
- 0x11e0: 7973 7465 6d2c 0a62 7574 2069 7420 6861 ystem,.but.it.ha
- 0x11f0: 7320 3c73 7472 6f6e 673e 6e6f 7468 696e s.<strong>nothin
- 0x1200: 6720 746f 2064 6f20 7769 7468 2074 6865 g.to.do.with.the
- 0x1210: 2044 6562 6961 6e0a 5072 6f6a 6563 743c .Debian.Project<
- 0x1220: 2f73 7472 6f6e 673e 2e20 506c 6561 7365 /strong>..Please
- 0x1230: 2064 6f20 3c73 7472 6f6e 673e 6e6f 743c .do.<strong>not<
- 0x1240: 2f73 7472 6f6e 673e 2063 6f6e 7461 6374 /strong>.contact
- 0x1250: 2074 6865 2044 6562 6961 6e0a 5072 6f6a .the.Debian.Proj
- 0x1260: 6563 7420 6162 6f75 7420 6974 2e3c 2f50 ect.about.it.</P
- 0x1270: 3e0a 0a3c 503e 4966 2079 6f75 2066 696e >..<P>If.you.fin
- 0x1280: 6420 6120 6275 6720 696e 2074 6869 7320 d.a.bug.in.this.
- 0x1290: 6170 6163 6865 2070 6163 6b61 6765 2c20 apache.package,.
- 0x12a0: 6f72 2069 6e20 4170 6163 6865 2069 7473 or.in.Apache.its
- 0x12b0: 656c 662c 0a70 6c65 6173 6520 6669 6c65 elf,.please.file
- 0x12c0: 2061 2062 7567 2072 6570 6f72 7420 6f6e .a.bug.report.on
- 0x12d0: 2069 742e 2020 496e 7374 7275 6374 696f .it...Instructio
- 0x12e0: 6e73 206f 6e20 646f 696e 6720 7468 6973 ns.on.doing.this
- 0x12f0: 2c20 616e 6420 7468 650a 6c69 7374 206f ,.and.the.list.o
- 0x1300: 6620 3c41 2048 5245 463d 2268 7474 703a f.<A.HREF="http:
- 0x1310: 2f2f 6275 6773 2e64 6562 6961 6e2e 6f72 //bugs.debian.or
- 0x1320: 672f 7372 633a 6170 6163 6865 223e 6b6e g/src:apache">kn
- 0x1330: 6f77 6e20 6275 6773 3c2f 413e 206f 6620 own.bugs</A>.of.
- 0x1340: 7468 6973 0a70 6163 6b61 6765 2c20 6361 this.package,.ca
- 0x1350: 6e20 6265 2066 6f75 6e64 2069 6e20 7468 n.be.found.in.th
- 0x1360: 6520 0a3c 4120 4852 4546 3d22 6874 7470 e..<A.HREF="http
- 0x1370: 3a2f 2f77 7777 2e64 6562 6961 6e2e 6f72 ://www.debian.or
- 0x1380: 672f 4275 6773 2f52 6570 6f72 7469 6e67 g/Bugs/Reporting
- 0x1390: 223e 4465 6269 616e 2042 7567 2054 7261 ">Debian.Bug.Tra
- 0x13a0: 636b 696e 6720 5379 7374 656d 3c2f 413e cking.System</A>
- 0x13b0: 2e0a 0a3c 503e 5468 616e 6b73 2066 6f72 ...<P>Thanks.for
- 0x13c0: 2075 7369 6e67 2074 6869 7320 7061 636b .using.this.pack
- 0x13d0: 6167 652c 2061 6e64 2063 6f6e 6772 6174 age,.and.congrat
- 0x13e0: 756c 6174 696f 6e73 2066 6f72 2079 6f75 ulations.for.you
- 0x13f0: 7220 6368 6f69 6365 206f 660a 6120 4465 r.choice.of.a.De
- 0x1400: 6269 616e 2073 7973 7465 6d21 3c2f 503e bian.system!</P>
- 0x1410: 0a0a 3c44 4956 2061 6c69 676e 3d22 6365 ..<DIV.align="ce
- 0x1420: 6e74 6572 223e 0a3c 6120 6872 6566 3d22 nter">.<a.href="
- 0x1430: 6874 7470 3a2f 2f77 7777 2e64 6562 6961 http://www.debia
- 0x1440: 6e2e 6f72 672f 223e 0a3c 494d 4720 616c n.org/">.<IMG.al
- 0x1450: 6967 6e3d 226d 6964 646c 6522 2068 6569 ign="middle".hei
- 0x1460: 6768 743d 2233 3022 2077 6964 7468 3d22 ght="30".width="
- 0x1470: 3235 2220 7372 633d 2269 636f 6e73 2f64 25".src="icons/d
- 0x1480: 6562 6961 6e2f 6f70 656e 6c6f 676f 2d32 ebian/openlogo-2
- 0x1490: 352e 6a70 6722 2061 6c74 3d22 4465 6269 5.jpg".alt="Debi
- 0x14a0: 616e 223e 0a3c 2f61 3e0a 3c61 2068 7265 an">.</a>.<a.hre
- 0x14b0: 663d 2268 7474 703a 2f2f 7777 772e 6170 f="http://www.ap
- 0x14c0: 6163 6865 2e6f 7267 2f22 3e0a 3c49 4d47 ache.org/">.<IMG
- 0x14d0: 2061 6c69 676e 3d22 6d69 6464 6c65 2220 .align="middle".
- 0x14e0: 6865 6967 6874 3d22 3332 2220 7769 6474 height="32".widt
- 0x14f0: 683d 2232 3539 2220 7372 633d 2269 636f h="259".src="ico
- 0x1500: 6e73 2f61 7061 6368 655f 7062 2e70 6e67 ns/apache_pb.png
- 0x1510: 2220 616c 743d 2241 7061 6368 6522 3e0a ".alt="Apache">.
- 0x1520: 3c2f 613e 0a3c 2f44 4956 3e0a 0a3c 212d </a>.</DIV>..<!-
- 0x1530: 2d0a 2020 5468 6973 2070 6167 6520 7761 -...This.page.wa
- 0x1540: 7320 696e 6974 6961 6c6c 7920 6372 6561 s.initially.crea
- 0x1550: 7465 6420 6279 204a 6f68 6e69 6520 496e ted.by.Johnie.In
- 0x1560: 6772 616d 2028 6874 7470 3a2f 2f6e 6574 gram.(http://net
- 0x1570: 676f 642e 6e65 742f 290a 2020 4974 2077 god.net/)...It.w
- 0x1580: 6173 206c 6174 6572 2065 6469 7465 6420 as.later.edited.
- 0x1590: 6279 204d 6174 7468 6577 2057 696c 636f by.Matthew.Wilco
- 0x15a0: 7820 616e 6420 4a6f 7369 7020 526f 6469 x.and.Josip.Rodi
- 0x15b0: 6e2e 0a20 204c 6173 7420 6d6f 6469 6669 n....Last.modifi
- 0x15c0: 6564 3a20 2444 6174 653a 2032 3030 342f ed:.$Date:.2004/
- 0x15d0: 3036 2f32 3020 3135 3a33 333a 3537 2024 06/20.15:33:57.$
- 0x15e0: 2e0a 2020 2d2d 3e0a 0a3c 2f42 4f44 593e ....-->..</BODY>
- 0x15f0: 0a3c 2f48 544d 4c3e 0a .</HTML>.
-23:57:35.941260 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5560 win 12383 <nop,nop,timestamp 1306300953 1306300953>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1b6e 4000 4006 2154 7f00 0001 7f00 .4.n@.@.!T......
- 0x0020: 0001 da70 0050 3758 8a49 377a a3a9 8010 ...p.P7X.I7z....
- 0x0030: 305f 10ea 0000 0101 080a 4ddc 9219 4ddc 0_........M...M.
- 0x0040: 9219 ..
-23:57:37.229575 IP 127.0.0.1.55920 > 127.0.0.1.80: F 203:203(0) ack 5560 win 12383 <nop,nop,timestamp 1306302241 1306300953>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1b70 4000 4006 2152 7f00 0001 7f00 .4.p@.@.!R......
- 0x0020: 0001 da70 0050 3758 8a49 377a a3a9 8011 ...p.P7X.I7z....
- 0x0030: 305f 0be1 0000 0101 080a 4ddc 9721 4ddc 0_........M..!M.
- 0x0040: 9219 ..
-23:57:37.230839 IP 127.0.0.1.80 > 127.0.0.1.55920: F 5560:5560(0) ack 204 win 8192 <nop,nop,timestamp 1306302243 1306302241>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1fe8 4000 4006 1cda 7f00 0001 7f00 .4..@.@.........
- 0x0020: 0001 0050 da70 377a a3a9 3758 8a4a 8011 ...P.p7z..7X.J..
- 0x0030: 2000 1735 0000 0101 080a 4ddc 9723 4ddc ...5......M..#M.
- 0x0040: 9721 .!
-23:57:37.230900 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5561 win 12383 <nop,nop,timestamp 1306302243 1306302243>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1b72 4000 4006 2150 7f00 0001 7f00 .4.r@.@.!P......
- 0x0020: 0001 da70 0050 3758 8a4a 377a a3aa 8010 ...p.P7X.J7z....
- 0x0030: 305f 06d4 0000 0101 080a 4ddc 9723 4ddc 0_........M..#M.
- 0x0040: 9723 .#
diff --git a/contrib/tcpdump/tests/print-capX.out b/contrib/tcpdump/tests/print-capX.out
deleted file mode 100644
index 53e44ed..0000000
--- a/contrib/tcpdump/tests/print-capX.out
+++ /dev/null
@@ -1,409 +0,0 @@
-23:57:35.938066 IP 127.0.0.1.55920 > 127.0.0.1.80: S 928549246:928549246(0) win 32767 <mss 16396,sackOK,timestamp 1306300950 0,nop,wscale 2>
- 0x0000: 4500 003c 1b68 4000 4006 2152 7f00 0001 E..<.h@.@.!R....
- 0x0010: 7f00 0001 da70 0050 3758 897e 0000 0000 .....p.P7X.~....
- 0x0020: a002 7fff 1421 0000 0204 400c 0402 080a .....!....@.....
- 0x0030: 4ddc 9216 0000 0000 0103 0302 M...........
-23:57:35.938122 IP 127.0.0.1.80 > 127.0.0.1.55920: S 930778609:930778609(0) ack 928549247 win 32767 <mss 16396,sackOK,timestamp 1306300950 1306300950,nop,wscale 2>
- 0x0000: 4500 003c 0000 4000 4006 3cba 7f00 0001 E..<..@.@.<.....
- 0x0010: 7f00 0001 0050 da70 377a 8df1 3758 897f .....P.p7z..7X..
- 0x0020: a012 7fff 6eb1 0000 0204 400c 0402 080a ....n.....@.....
- 0x0030: 4ddc 9216 4ddc 9216 0103 0302 M...M.......
-23:57:35.938167 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 1 win 8192 <nop,nop,timestamp 1306300950 1306300950>
- 0x0000: 4500 0034 1b6a 4000 4006 2158 7f00 0001 E..4.j@.@.!X....
- 0x0010: 7f00 0001 da70 0050 3758 897f 377a 8df2 .....p.P7X..7z..
- 0x0020: 8010 2000 37d0 0000 0101 080a 4ddc 9216 ....7.......M...
- 0x0030: 4ddc 9216 M...
-23:57:35.939423 IP 127.0.0.1.55920 > 127.0.0.1.80: P 1:203(202) ack 1 win 8192 <nop,nop,timestamp 1306300951 1306300950>
- 0x0000: 4500 00fe 1b6c 4000 4006 208c 7f00 0001 E....l@.@.......
- 0x0010: 7f00 0001 da70 0050 3758 897f 377a 8df2 .....p.P7X..7z..
- 0x0020: 8018 2000 fef2 0000 0101 080a 4ddc 9217 ............M...
- 0x0030: 4ddc 9216 4745 5420 2f20 4854 5450 2f31 M...GET./.HTTP/1
- 0x0040: 2e31 0d0a 486f 7374 3a20 6c6f 6361 6c68 .1..Host:.localh
- 0x0050: 6f73 740d 0a55 7365 722d 4167 656e 743a ost..User-Agent:
- 0x0060: 2045 4c69 6e6b 732f 302e 3130 2e34 2d37 .ELinks/0.10.4-7
- 0x0070: 2d64 6562 6961 6e20 2874 6578 746d 6f64 -debian.(textmod
- 0x0080: 653b 204c 696e 7578 2032 2e36 2e31 312d e;.Linux.2.6.11-
- 0x0090: 312d 3638 362d 736d 7020 6936 3836 3b20 1-686-smp.i686;.
- 0x00a0: 3133 3278 3536 2d32 290d 0a41 6363 6570 132x56-2)..Accep
- 0x00b0: 743a 202a 2f2a 0d0a 4163 6365 7074 2d45 t:.*/*..Accept-E
- 0x00c0: 6e63 6f64 696e 673a 2067 7a69 700d 0a41 ncoding:.gzip..A
- 0x00d0: 6363 6570 742d 4c61 6e67 7561 6765 3a20 ccept-Language:.
- 0x00e0: 656e 0d0a 436f 6e6e 6563 7469 6f6e 3a20 en..Connection:.
- 0x00f0: 4b65 6570 2d41 6c69 7665 0d0a 0d0a Keep-Alive....
-23:57:35.940474 IP 127.0.0.1.80 > 127.0.0.1.55920: . ack 203 win 8192 <nop,nop,timestamp 1306300952 1306300951>
- 0x0000: 4500 0034 1fe4 4000 4006 1cde 7f00 0001 E..4..@.@.......
- 0x0010: 7f00 0001 0050 da70 377a 8df2 3758 8a49 .....P.p7z..7X.I
- 0x0020: 8010 2000 3703 0000 0101 080a 4ddc 9218 ....7.......M...
- 0x0030: 4ddc 9217 M...
-23:57:35.941232 IP 127.0.0.1.80 > 127.0.0.1.55920: P 1:5560(5559) ack 203 win 8192 <nop,nop,timestamp 1306300953 1306300951>
- 0x0000: 4500 15eb 1fe6 4000 4006 0725 7f00 0001 E.....@.@..%....
- 0x0010: 7f00 0001 0050 da70 377a 8df2 3758 8a49 .....P.p7z..7X.I
- 0x0020: 8018 2000 13e0 0000 0101 080a 4ddc 9219 ............M...
- 0x0030: 4ddc 9217 4854 5450 2f31 2e31 2032 3030 M...HTTP/1.1.200
- 0x0040: 204f 4b0d 0a44 6174 653a 2057 6564 2c20 .OK..Date:.Wed,.
- 0x0050: 3036 204a 756c 2032 3030 3520 3033 3a35 06.Jul.2005.03:5
- 0x0060: 373a 3335 2047 4d54 0d0a 5365 7276 6572 7:35.GMT..Server
- 0x0070: 3a20 4170 6163 6865 2f31 2e33 2e33 330d :.Apache/1.3.33.
- 0x0080: 0a4c 6173 742d 4d6f 6469 6669 6564 3a20 .Last-Modified:.
- 0x0090: 5375 6e2c 2031 3520 4175 6720 3230 3034 Sun,.15.Aug.2004
- 0x00a0: 2030 303a 3433 3a34 3120 474d 540d 0a45 .00:43:41.GMT..E
- 0x00b0: 5461 673a 2022 3665 3830 6630 2d31 3438 Tag:."6e80f0-148
- 0x00c0: 612d 3431 3165 6231 6264 220d 0a41 6363 a-411eb1bd"..Acc
- 0x00d0: 6570 742d 5261 6e67 6573 3a20 6279 7465 ept-Ranges:.byte
- 0x00e0: 730d 0a43 6f6e 7465 6e74 2d4c 656e 6774 s..Content-Lengt
- 0x00f0: 683a 2035 3235 380d 0a4b 6565 702d 416c h:.5258..Keep-Al
- 0x0100: 6976 653a 2074 696d 656f 7574 3d31 352c ive:.timeout=15,
- 0x0110: 206d 6178 3d31 3030 0d0a 436f 6e6e 6563 .max=100..Connec
- 0x0120: 7469 6f6e 3a20 4b65 6570 2d41 6c69 7665 tion:.Keep-Alive
- 0x0130: 0d0a 436f 6e74 656e 742d 5479 7065 3a20 ..Content-Type:.
- 0x0140: 7465 7874 2f68 746d 6c3b 2063 6861 7273 text/html;.chars
- 0x0150: 6574 3d69 736f 2d38 3835 392d 310d 0a0d et=iso-8859-1...
- 0x0160: 0a3c 2144 4f43 5459 5045 2048 544d 4c20 .<!DOCTYPE.HTML.
- 0x0170: 5055 424c 4943 2022 2d2f 2f57 3343 2f2f PUBLIC."-//W3C//
- 0x0180: 4454 4420 4854 4d4c 2034 2e30 3120 5472 DTD.HTML.4.01.Tr
- 0x0190: 616e 7369 7469 6f6e 616c 2f2f 454e 223e ansitional//EN">
- 0x01a0: 0a3c 4854 4d4c 3e0a 3c48 4541 443e 0a20 .<HTML>.<HEAD>..
- 0x01b0: 2020 3c4d 4554 4120 4854 5450 2d45 5155 ..<META.HTTP-EQU
- 0x01c0: 4956 3d22 436f 6e74 656e 742d 5479 7065 IV="Content-Type
- 0x01d0: 2220 434f 4e54 454e 543d 2274 6578 742f ".CONTENT="text/
- 0x01e0: 6874 6d6c 3b20 6368 6172 7365 743d 6973 html;.charset=is
- 0x01f0: 6f2d 3838 3539 2d31 223e 0a20 2020 3c4d o-8859-1">....<M
- 0x0200: 4554 4120 4e41 4d45 3d22 4465 7363 7269 ETA.NAME="Descri
- 0x0210: 7074 696f 6e22 2043 4f4e 5445 4e54 3d22 ption".CONTENT="
- 0x0220: 5468 6520 696e 6974 6961 6c20 696e 7374 The.initial.inst
- 0x0230: 616c 6c61 7469 6f6e 206f 6620 4465 6269 allation.of.Debi
- 0x0240: 616e 2061 7061 6368 652e 223e 0a20 2020 an.apache.">....
- 0x0250: 3c54 4954 4c45 3e50 6c61 6365 686f 6c64 <TITLE>Placehold
- 0x0260: 6572 2070 6167 653c 2f54 4954 4c45 3e0a er.page</TITLE>.
- 0x0270: 3c2f 4845 4144 3e0a 3c42 4f44 5920 5445 </HEAD>.<BODY.TE
- 0x0280: 5854 3d22 2330 3030 3030 3022 2042 4743 XT="#000000".BGC
- 0x0290: 4f4c 4f52 3d22 2346 4646 4646 4622 204c OLOR="#FFFFFF".L
- 0x02a0: 494e 4b3d 2223 3030 3030 4546 2220 564c INK="#0000EF".VL
- 0x02b0: 494e 4b3d 2223 3535 3138 3841 2220 414c INK="#55188A".AL
- 0x02c0: 494e 4b3d 2223 4646 3030 3030 223e 0a0a INK="#FF0000">..
- 0x02d0: 3c48 313e 506c 6163 6568 6f6c 6465 7220 <H1>Placeholder.
- 0x02e0: 7061 6765 3c2f 4831 3e0a 3c48 323e 4966 page</H1>.<H2>If
- 0x02f0: 2079 6f75 2061 7265 206a 7573 7420 6272 .you.are.just.br
- 0x0300: 6f77 7369 6e67 2074 6865 2077 6562 3c2f owsing.the.web</
- 0x0310: 6832 3e0a 0a3c 503e 5468 6520 6f77 6e65 h2>..<P>The.owne
- 0x0320: 7220 6f66 2074 6869 7320 7765 6220 7369 r.of.this.web.si
- 0x0330: 7465 2068 6173 206e 6f74 2070 7574 2075 te.has.not.put.u
- 0x0340: 7020 616e 7920 7765 6220 7061 6765 7320 p.any.web.pages.
- 0x0350: 7965 742e 0a50 6c65 6173 6520 636f 6d65 yet..Please.come
- 0x0360: 2062 6163 6b20 6c61 7465 722e 3c2f 503e .back.later.</P>
- 0x0370: 0a0a 3c50 3e3c 534d 414c 4c3e 3c43 4954 ..<P><SMALL><CIT
- 0x0380: 453e 4d6f 7665 2061 6c6f 6e67 2c20 6e6f E>Move.along,.no
- 0x0390: 7468 696e 6720 746f 2073 6565 2068 6572 thing.to.see.her
- 0x03a0: 652e 2e2e 3c2f 4349 5445 3e20 3a2d 293c e...</CITE>.:-)<
- 0x03b0: 2f53 4d41 4c4c 3e3c 2f50 3e0a 0a3c 4832 /SMALL></P>..<H2
- 0x03c0: 3e49 6620 796f 7520 6172 6520 7472 7969 >If.you.are.tryi
- 0x03d0: 6e67 2074 6f20 6c6f 6361 7465 2074 6865 ng.to.locate.the
- 0x03e0: 2061 646d 696e 6973 7472 6174 6f72 206f .administrator.o
- 0x03f0: 6620 7468 6973 206d 6163 6869 6e65 3c2f f.this.machine</
- 0x0400: 4832 3e0a 0a3c 503e 4966 2079 6f75 2077 H2>..<P>If.you.w
- 0x0410: 616e 7420 746f 2072 6570 6f72 7420 736f ant.to.report.so
- 0x0420: 6d65 7468 696e 6720 6162 6f75 7420 7468 mething.about.th
- 0x0430: 6973 2068 6f73 7427 7320 6265 6861 7669 is.host's.behavi
- 0x0440: 6f72 2c20 706c 6561 7365 0a63 6f6e 7461 or,.please.conta
- 0x0450: 6374 2074 6865 2049 6e74 6572 6e65 7420 ct.the.Internet.
- 0x0460: 5365 7276 6963 6520 5072 6f76 6964 6572 Service.Provider
- 0x0470: 2028 4953 5029 2069 6e76 6f6c 7665 6420 .(ISP).involved.
- 0x0480: 6469 7265 6374 6c79 2e3c 2f50 3e0a 0a3c directly.</P>..<
- 0x0490: 503e 5365 6520 7468 6520 3c41 2068 7265 P>See.the.<A.hre
- 0x04a0: 663d 2268 7474 703a 2f2f 7777 772e 6162 f="http://www.ab
- 0x04b0: 7573 652e 6e65 742f 223e 4e65 7477 6f72 use.net/">Networ
- 0x04c0: 6b20 4162 7573 650a 436c 6561 7269 6e67 k.Abuse.Clearing
- 0x04d0: 686f 7573 653c 2f41 3e20 666f 7220 686f house</A>.for.ho
- 0x04e0: 7720 746f 2064 6f20 7468 6973 2e3c 2f50 w.to.do.this.</P
- 0x04f0: 3e0a 0a3c 4832 3e49 6620 796f 7520 6172 >..<H2>If.you.ar
- 0x0500: 6520 7468 6520 6164 6d69 6e69 7374 7261 e.the.administra
- 0x0510: 746f 7220 6f66 2074 6869 7320 6d61 6368 tor.of.this.mach
- 0x0520: 696e 653c 2f48 323e 0a0a 3c50 3e54 6865 ine</H2>..<P>The
- 0x0530: 2069 6e69 7469 616c 2069 6e73 7461 6c6c .initial.install
- 0x0540: 6174 696f 6e20 6f66 203c 4120 6872 6566 ation.of.<A.href
- 0x0550: 3d22 6874 7470 3a2f 2f77 7777 2e64 6562 ="http://www.deb
- 0x0560: 6961 6e2e 6f72 672f 223e 4465 6269 616e ian.org/">Debian
- 0x0570: 2773 0a61 7061 6368 653c 2f41 3e20 7765 's.apache</A>.we
- 0x0580: 6220 7365 7276 6572 2070 6163 6b61 6765 b.server.package
- 0x0590: 2077 6173 2073 7563 6365 7373 6675 6c2e .was.successful.
- 0x05a0: 3c2f 503e 0a0a 3c50 3e3c 5354 524f 4e47 </P>..<P><STRONG
- 0x05b0: 3e59 6f75 2073 686f 756c 6420 7265 706c >You.should.repl
- 0x05c0: 6163 6520 7468 6973 2070 6167 6520 7769 ace.this.page.wi
- 0x05d0: 7468 2079 6f75 7220 6f77 6e20 7765 6220 th.your.own.web.
- 0x05e0: 7061 6765 7320 6173 0a73 6f6f 6e20 6173 pages.as.soon.as
- 0x05f0: 2070 6f73 7369 626c 652e 3c2f 5354 524f .possible.</STRO
- 0x0600: 4e47 3e3c 2f50 3e0a 0a3c 503e 556e 6c65 NG></P>..<P>Unle
- 0x0610: 7373 2079 6f75 2063 6861 6e67 6564 2069 ss.you.changed.i
- 0x0620: 7473 2063 6f6e 6669 6775 7261 7469 6f6e ts.configuration
- 0x0630: 2c20 796f 7572 206e 6577 2073 6572 7665 ,.your.new.serve
- 0x0640: 7220 6973 2063 6f6e 6669 6775 7265 6420 r.is.configured.
- 0x0650: 6173 2066 6f6c 6c6f 7773 3a0a 3c55 4c3e as.follows:.<UL>
- 0x0660: 0a3c 4c49 3e0a 436f 6e66 6967 7572 6174 .<LI>.Configurat
- 0x0670: 696f 6e20 6669 6c65 7320 6361 6e20 6265 ion.files.can.be
- 0x0680: 2066 6f75 6e64 2069 6e20 3c54 543e 2f65 .found.in.<TT>/e
- 0x0690: 7463 2f61 7061 6368 653c 2f54 543e 2e3c tc/apache</TT>.<
- 0x06a0: 2f4c 493e 0a0a 3c4c 493e 0a54 6865 203c /LI>..<LI>.The.<
- 0x06b0: 5454 3e44 6f63 756d 656e 7452 6f6f 743c TT>DocumentRoot<
- 0x06c0: 2f54 543e 2c20 7768 6963 6820 6973 2074 /TT>,.which.is.t
- 0x06d0: 6865 2064 6972 6563 746f 7279 2075 6e64 he.directory.und
- 0x06e0: 6572 2077 6869 6368 2061 6c6c 2079 6f75 er.which.all.you
- 0x06f0: 720a 4854 4d4c 2066 696c 6573 2073 686f r.HTML.files.sho
- 0x0700: 756c 6420 6578 6973 742c 2069 7320 7365 uld.exist,.is.se
- 0x0710: 7420 746f 203c 5454 3e2f 7661 722f 7777 t.to.<TT>/var/ww
- 0x0720: 773c 2f54 543e 2e3c 2f4c 493e 0a0a 3c4c w</TT>.</LI>..<L
- 0x0730: 493e 0a43 4749 2073 6372 6970 7473 2061 I>.CGI.scripts.a
- 0x0740: 7265 206c 6f6f 6b65 6420 666f 7220 696e re.looked.for.in
- 0x0750: 203c 5454 3e2f 7573 722f 6c69 622f 6367 .<TT>/usr/lib/cg
- 0x0760: 692d 6269 6e3c 2f54 543e 2c20 7768 6963 i-bin</TT>,.whic
- 0x0770: 6820 6973 2077 6865 7265 0a44 6562 6961 h.is.where.Debia
- 0x0780: 6e20 7061 636b 6167 6573 2077 696c 6c20 n.packages.will.
- 0x0790: 706c 6163 6520 7468 6569 7220 7363 7269 place.their.scri
- 0x07a0: 7074 732e 3c2f 4c49 3e0a 0a3c 4c49 3e0a pts.</LI>..<LI>.
- 0x07b0: 4c6f 6720 6669 6c65 7320 6172 6520 706c Log.files.are.pl
- 0x07c0: 6163 6564 2069 6e20 3c54 543e 2f76 6172 aced.in.<TT>/var
- 0x07d0: 2f6c 6f67 2f61 7061 6368 653c 2f54 543e /log/apache</TT>
- 0x07e0: 2c20 616e 6420 7769 6c6c 2062 6520 726f ,.and.will.be.ro
- 0x07f0: 7461 7465 640a 7765 656b 6c79 2e20 2054 tated.weekly...T
- 0x0800: 6865 2066 7265 7175 656e 6379 206f 6620 he.frequency.of.
- 0x0810: 726f 7461 7469 6f6e 2063 616e 2062 6520 rotation.can.be.
- 0x0820: 6561 7369 6c79 2063 6861 6e67 6564 2062 easily.changed.b
- 0x0830: 7920 6564 6974 696e 670a 3c54 543e 2f65 y.editing.<TT>/e
- 0x0840: 7463 2f6c 6f67 726f 7461 7465 2e64 2f61 tc/logrotate.d/a
- 0x0850: 7061 6368 653c 2f54 543e 2e3c 2f4c 493e pache</TT>.</LI>
- 0x0860: 0a0a 3c4c 493e 0a54 6865 2064 6566 6175 ..<LI>.The.defau
- 0x0870: 6c74 2064 6972 6563 746f 7279 2069 6e64 lt.directory.ind
- 0x0880: 6578 2069 7320 3c54 543e 696e 6465 782e ex.is.<TT>index.
- 0x0890: 6874 6d6c 3c2f 5454 3e2c 206d 6561 6e69 html</TT>,.meani
- 0x08a0: 6e67 2074 6861 7420 7265 7175 6573 7473 ng.that.requests
- 0x08b0: 0a66 6f72 2061 2064 6972 6563 746f 7279 .for.a.directory
- 0x08c0: 203c 5454 3e2f 666f 6f2f 6261 722f 3c2f .<TT>/foo/bar/</
- 0x08d0: 5454 3e20 7769 6c6c 2067 6976 6520 7468 TT>.will.give.th
- 0x08e0: 6520 636f 6e74 656e 7473 206f 6620 7468 e.contents.of.th
- 0x08f0: 6520 6669 6c65 203c 5454 3e2f 7661 722f e.file.<TT>/var/
- 0x0900: 7777 772f 666f 6f2f 6261 722f 696e 6465 www/foo/bar/inde
- 0x0910: 782e 6874 6d6c 3c2f 5454 3e0a 6966 2069 x.html</TT>.if.i
- 0x0920: 7420 6578 6973 7473 2028 6173 7375 6d69 t.exists.(assumi
- 0x0930: 6e67 2074 6861 7420 3c54 543e 2f76 6172 ng.that.<TT>/var
- 0x0940: 2f77 7777 3c2f 5454 3e20 6973 2079 6f75 /www</TT>.is.you
- 0x0950: 7220 3c54 543e 446f 6375 6d65 6e74 526f r.<TT>DocumentRo
- 0x0960: 6f74 3c2f 5454 3e29 2e3c 2f4c 493e 0a0a ot</TT>).</LI>..
- 0x0970: 3c4c 493e 0a55 7365 7220 6469 7265 6374 <LI>.User.direct
- 0x0980: 6f72 6965 7320 6172 6520 656e 6162 6c65 ories.are.enable
- 0x0990: 642c 2061 6e64 2075 7365 7220 646f 6375 d,.and.user.docu
- 0x09a0: 6d65 6e74 7320 7769 6c6c 2062 6520 6c6f ments.will.be.lo
- 0x09b0: 6f6b 6564 2066 6f72 0a69 6e20 7468 6520 oked.for.in.the.
- 0x09c0: 3c54 543e 7075 626c 6963 5f68 746d 6c3c <TT>public_html<
- 0x09d0: 2f54 543e 2064 6972 6563 746f 7279 206f /TT>.directory.o
- 0x09e0: 6620 7468 6520 7573 6572 7327 2068 6f6d f.the.users'.hom
- 0x09f0: 6573 2e20 2054 6865 7365 2064 6972 730a es...These.dirs.
- 0x0a00: 7368 6f75 6c64 2062 6520 756e 6465 7220 should.be.under.
- 0x0a10: 3c54 543e 2f68 6f6d 653c 2f54 543e 2c20 <TT>/home</TT>,.
- 0x0a20: 616e 6420 7573 6572 7320 7769 6c6c 206e and.users.will.n
- 0x0a30: 6f74 2062 6520 6162 6c65 2074 6f20 7379 ot.be.able.to.sy
- 0x0a40: 6d6c 696e 6b0a 746f 2066 696c 6573 2074 mlink.to.files.t
- 0x0a50: 6865 7920 646f 6e27 7420 6f77 6e2e 3c2f hey.don't.own.</
- 0x0a60: 4c49 3e0a 0a3c 2f55 4c3e 0a41 6c6c 2074 LI>..</UL>.All.t
- 0x0a70: 6865 2073 7461 6e64 6172 6420 6170 6163 he.standard.apac
- 0x0a80: 6865 206d 6f64 756c 6573 2061 7265 2061 he.modules.are.a
- 0x0a90: 7661 696c 6162 6c65 2077 6974 6820 7468 vailable.with.th
- 0x0aa0: 6973 2072 656c 6561 7365 2061 6e64 2061 is.release.and.a
- 0x0ab0: 7265 0a6e 6f77 206d 616e 6167 6564 2077 re.now.managed.w
- 0x0ac0: 6974 6820 6465 6263 6f6e 662e 2020 5479 ith.debconf...Ty
- 0x0ad0: 7065 203c 5454 3e64 706b 672d 7265 636f pe.<TT>dpkg-reco
- 0x0ae0: 6e66 6967 7572 6520 6170 6163 6865 3c2f nfigure.apache</
- 0x0af0: 5454 3e20 746f 0a73 656c 6563 7420 7768 TT>.to.select.wh
- 0x0b00: 6963 6820 6d6f 6475 6c65 7320 796f 7520 ich.modules.you.
- 0x0b10: 7761 6e74 2065 6e61 626c 6564 2e20 204d want.enabled...M
- 0x0b20: 616e 7920 6f74 6865 7220 6d6f 6475 6c65 any.other.module
- 0x0b30: 7320 6172 6520 6176 6169 6c61 626c 650a s.are.available.
- 0x0b40: 7468 726f 7567 6820 7468 6520 4465 6269 through.the.Debi
- 0x0b50: 616e 2070 6163 6b61 6765 2073 7973 7465 an.package.syste
- 0x0b60: 6d20 7769 7468 2074 6865 206e 616d 6573 m.with.the.names
- 0x0b70: 203c 5454 3e6c 6962 6170 6163 6865 2d6d .<TT>libapache-m
- 0x0b80: 6f64 2d2a 3c2f 5454 3e2e 0a49 6620 796f od-*</TT>..If.yo
- 0x0b90: 7520 6e65 6564 2074 6f20 636f 6d70 696c u.need.to.compil
- 0x0ba0: 6520 6120 6d6f 6475 6c65 2079 6f75 7273 e.a.module.yours
- 0x0bb0: 656c 662c 2079 6f75 2077 696c 6c20 6e65 elf,.you.will.ne
- 0x0bc0: 6564 2074 6f20 696e 7374 616c 6c20 7468 ed.to.install.th
- 0x0bd0: 650a 3c54 543e 6170 6163 6865 2d64 6576 e.<TT>apache-dev
- 0x0be0: 3c2f 5454 3e20 7061 636b 6167 652e 0a0a </TT>.package...
- 0x0bf0: 3c50 3e4d 6f72 6520 646f 6375 6d65 6e74 <P>More.document
- 0x0c00: 6174 696f 6e20 6f6e 2041 7061 6368 6520 ation.on.Apache.
- 0x0c10: 6361 6e20 6265 2066 6f75 6e64 206f 6e3a can.be.found.on:
- 0x0c20: 0a3c 554c 3e0a 3c4c 493e 0a54 6865 203c .<UL>.<LI>.The.<
- 0x0c30: 4120 4852 4546 3d22 2f64 6f63 2f61 7061 A.HREF="/doc/apa
- 0x0c40: 6368 652d 646f 632f 6d61 6e75 616c 2f22 che-doc/manual/"
- 0x0c50: 3e41 7061 6368 6520 646f 6375 6d65 6e74 >Apache.document
- 0x0c60: 6174 696f 6e3c 2f41 3e20 7374 6f72 6564 ation</A>.stored
- 0x0c70: 206f 6e20 796f 7572 2073 6572 7665 722e .on.your.server.
- 0x0c80: 3c2f 4c49 3e0a 0a3c 4c49 3e0a 5468 6520 </LI>..<LI>.The.
- 0x0c90: 3c41 2048 5245 463d 2268 7474 703a 2f2f <A.HREF="http://
- 0x0ca0: 7777 772e 6170 6163 6865 2e6f 7267 2f22 www.apache.org/"
- 0x0cb0: 3e41 7061 6368 6520 5072 6f6a 6563 743c >Apache.Project<
- 0x0cc0: 2f41 3e20 686f 6d65 2073 6974 652e 3c2f /A>.home.site.</
- 0x0cd0: 4c49 3e0a 0a3c 4c49 3e0a 5468 6520 3c41 LI>..<LI>.The.<A
- 0x0ce0: 2048 5245 463d 2268 7474 703a 2f2f 7777 .HREF="http://ww
- 0x0cf0: 772e 6170 6163 6865 2d73 736c 2e6f 7267 w.apache-ssl.org
- 0x0d00: 2f22 3e41 7061 6368 652d 5353 4c3c 2f41 /">Apache-SSL</A
- 0x0d10: 3e20 686f 6d65 2073 6974 652e 3c2f 4c49 >.home.site.</LI
- 0x0d20: 3e0a 0a3c 4c49 3e0a 5468 6520 3c41 2048 >..<LI>.The.<A.H
- 0x0d30: 5245 463d 2268 7474 703a 2f2f 7065 726c REF="http://perl
- 0x0d40: 2e61 7061 6368 652e 6f72 672f 223e 6d6f .apache.org/">mo
- 0x0d50: 6420 7065 726c 3c2f 413e 2068 6f6d 6520 d.perl</A>.home.
- 0x0d60: 7369 7465 2e3c 2f4c 493e 0a0a 3c4c 493e site.</LI>..<LI>
- 0x0d70: 0a54 6865 203c 4120 4852 4546 3d22 6874 .The.<A.HREF="ht
- 0x0d80: 7470 3a2f 2f77 7777 2e61 7061 6368 6577 tp://www.apachew
- 0x0d90: 6565 6b2e 636f 6d2f 223e 4170 6163 6865 eek.com/">Apache
- 0x0da0: 5765 656b 3c2f 413e 206e 6577 736c 6574 Week</A>.newslet
- 0x0db0: 7465 722e 3c2f 4c49 3e0a 0a3c 4c49 3e0a ter.</LI>..<LI>.
- 0x0dc0: 5468 6520 3c41 2048 5245 463d 2268 7474 The.<A.HREF="htt
- 0x0dd0: 703a 2f2f 7777 772e 6465 6269 616e 2e6f p://www.debian.o
- 0x0de0: 7267 2f64 6f63 2f22 3e44 6562 6961 6e20 rg/doc/">Debian.
- 0x0df0: 5072 6f6a 6563 740a 446f 6375 6d65 6e74 Project.Document
- 0x0e00: 6174 696f 6e3c 2f41 3e20 7768 6963 6820 ation</A>.which.
- 0x0e10: 636f 6e74 6169 6e73 2048 4f57 544f 732c contains.HOWTOs,
- 0x0e20: 2046 4151 732c 2061 6e64 2073 6f66 7477 .FAQs,.and.softw
- 0x0e30: 6172 6520 7570 6461 7465 732e 3c2f 4c49 are.updates.</LI
- 0x0e40: 3e0a 3c2f 554c 3e0a 0a3c 503e 596f 7520 >.</UL>..<P>You.
- 0x0e50: 6361 6e20 616c 736f 2063 6f6e 7375 6c74 can.also.consult
- 0x0e60: 2074 6865 206c 6973 7420 6f66 203c 4120 .the.list.of.<A.
- 0x0e70: 4852 4546 3d22 6874 7470 3a2f 2f77 7777 HREF="http://www
- 0x0e80: 2e62 6f75 7465 6c6c 2e63 6f6d 2f66 6171 .boutell.com/faq
- 0x0e90: 2f22 3e57 6f72 6c64 0a57 6964 6520 5765 /">World.Wide.We
- 0x0ea0: 6220 4672 6571 7565 6e74 6c79 2041 736b b.Frequently.Ask
- 0x0eb0: 6564 2051 7565 7374 696f 6e73 3c2f 413e ed.Questions</A>
- 0x0ec0: 2066 6f72 2069 6e66 6f72 6d61 7469 6f6e .for.information
- 0x0ed0: 2e0a 0a3c 4832 3e4c 6574 206f 7468 6572 ...<H2>Let.other
- 0x0ee0: 2070 656f 706c 6520 6b6e 6f77 2061 626f .people.know.abo
- 0x0ef0: 7574 2074 6869 7320 7365 7276 6572 3c2f ut.this.server</
- 0x0f00: 4832 3e0a 0a3c 4120 4852 4546 3d22 6874 H2>..<A.HREF="ht
- 0x0f10: 7470 3a2f 2f6e 6574 6372 6166 742e 636f tp://netcraft.co
- 0x0f20: 6d2f 223e 4e65 7463 7261 6674 3c2f 413e m/">Netcraft</A>
- 0x0f30: 2070 726f 7669 6465 7320 616e 2069 6e74 .provides.an.int
- 0x0f40: 6572 6573 7469 6e67 2066 7265 650a 7365 eresting.free.se
- 0x0f50: 7276 6963 6520 666f 7220 7765 6220 7369 rvice.for.web.si
- 0x0f60: 7465 206d 6f6e 6974 6f72 696e 6720 616e te.monitoring.an
- 0x0f70: 6420 7374 6174 6973 7469 6320 636f 6c6c d.statistic.coll
- 0x0f80: 6563 7469 6f6e 2e0a 596f 7520 6361 6e20 ection..You.can.
- 0x0f90: 6c65 7420 7468 656d 206b 6e6f 7720 6162 let.them.know.ab
- 0x0fa0: 6f75 7420 796f 7572 2073 6572 7665 7220 out.your.server.
- 0x0fb0: 7573 696e 6720 7468 6569 720a 3c41 2048 using.their.<A.H
- 0x0fc0: 5245 463d 2268 7474 703a 2f2f 7570 7469 REF="http://upti
- 0x0fd0: 6d65 2e6e 6574 6372 6166 742e 636f 6d2f me.netcraft.com/
- 0x0fe0: 223e 696e 7465 7266 6163 653c 2f41 3e2e ">interface</A>.
- 0x0ff0: 0a45 6e61 626c 696e 6720 7468 6520 6d6f .Enabling.the.mo
- 0x1000: 6e69 746f 7269 6e67 206f 6620 796f 7572 nitoring.of.your
- 0x1010: 2073 6572 7665 7220 7769 6c6c 2070 726f .server.will.pro
- 0x1020: 7669 6465 2061 2062 6574 7465 7220 676c vide.a.better.gl
- 0x1030: 6f62 616c 206f 7665 7276 6965 770a 6f66 obal.overview.of
- 0x1040: 2077 686f 2069 7320 7573 696e 6720 7768 .who.is.using.wh
- 0x1050: 6174 2061 6e64 2077 6865 7265 2c20 616e at.and.where,.an
- 0x1060: 6420 6974 2077 6f75 6c64 2067 6976 6520 d.it.would.give.
- 0x1070: 4465 6269 616e 2061 2062 6574 7465 720a Debian.a.better.
- 0x1080: 6f76 6572 7669 6577 206f 6620 7468 6520 overview.of.the.
- 0x1090: 6170 6163 6865 2070 6163 6b61 6765 2075 apache.package.u
- 0x10a0: 7361 6765 2e0a 0a3c 4832 3e41 626f 7574 sage...<H2>About
- 0x10b0: 2074 6869 7320 7061 6765 3c2f 4832 3e0a .this.page</H2>.
- 0x10c0: 0a3c 494d 4720 414c 4947 4e3d 2272 6967 .<IMG.ALIGN="rig
- 0x10d0: 6874 2220 414c 543d 2222 2048 4549 4748 ht".ALT="".HEIGH
- 0x10e0: 543d 2232 3437 2220 5749 4454 483d 2232 T="247".WIDTH="2
- 0x10f0: 3738 2220 5352 433d 2269 636f 6e73 2f6a 78".SRC="icons/j
- 0x1100: 6865 3036 312e 706e 6722 3e0a 0a3c 503e he061.png">..<P>
- 0x1110: 5468 6973 2069 7320 6120 706c 6163 6568 This.is.a.placeh
- 0x1120: 6f6c 6465 7220 7061 6765 2069 6e73 7461 older.page.insta
- 0x1130: 6c6c 6564 2062 7920 7468 6520 3c41 0a48 lled.by.the.<A.H
- 0x1140: 5245 463d 2268 7474 703a 2f2f 7777 772e REF="http://www.
- 0x1150: 6465 6269 616e 2e6f 7267 2f22 3e44 6562 debian.org/">Deb
- 0x1160: 6961 6e3c 2f41 3e0a 7265 6c65 6173 6520 ian</A>.release.
- 0x1170: 6f66 2074 6865 2061 7061 6368 6520 5765 of.the.apache.We
- 0x1180: 6220 7365 7276 6572 2070 6163 6b61 6765 b.server.package
- 0x1190: 2e0a 0a3c 503e 5468 6973 2063 6f6d 7075 ...<P>This.compu
- 0x11a0: 7465 7220 6861 7320 696e 7374 616c 6c65 ter.has.installe
- 0x11b0: 6420 7468 6520 4465 6269 616e 2047 4e55 d.the.Debian.GNU
- 0x11c0: 2f4c 696e 7578 206f 7065 7261 7469 6e67 /Linux.operating
- 0x11d0: 2073 7973 7465 6d2c 0a62 7574 2069 7420 .system,.but.it.
- 0x11e0: 6861 7320 3c73 7472 6f6e 673e 6e6f 7468 has.<strong>noth
- 0x11f0: 696e 6720 746f 2064 6f20 7769 7468 2074 ing.to.do.with.t
- 0x1200: 6865 2044 6562 6961 6e0a 5072 6f6a 6563 he.Debian.Projec
- 0x1210: 743c 2f73 7472 6f6e 673e 2e20 506c 6561 t</strong>..Plea
- 0x1220: 7365 2064 6f20 3c73 7472 6f6e 673e 6e6f se.do.<strong>no
- 0x1230: 743c 2f73 7472 6f6e 673e 2063 6f6e 7461 t</strong>.conta
- 0x1240: 6374 2074 6865 2044 6562 6961 6e0a 5072 ct.the.Debian.Pr
- 0x1250: 6f6a 6563 7420 6162 6f75 7420 6974 2e3c oject.about.it.<
- 0x1260: 2f50 3e0a 0a3c 503e 4966 2079 6f75 2066 /P>..<P>If.you.f
- 0x1270: 696e 6420 6120 6275 6720 696e 2074 6869 ind.a.bug.in.thi
- 0x1280: 7320 6170 6163 6865 2070 6163 6b61 6765 s.apache.package
- 0x1290: 2c20 6f72 2069 6e20 4170 6163 6865 2069 ,.or.in.Apache.i
- 0x12a0: 7473 656c 662c 0a70 6c65 6173 6520 6669 tself,.please.fi
- 0x12b0: 6c65 2061 2062 7567 2072 6570 6f72 7420 le.a.bug.report.
- 0x12c0: 6f6e 2069 742e 2020 496e 7374 7275 6374 on.it...Instruct
- 0x12d0: 696f 6e73 206f 6e20 646f 696e 6720 7468 ions.on.doing.th
- 0x12e0: 6973 2c20 616e 6420 7468 650a 6c69 7374 is,.and.the.list
- 0x12f0: 206f 6620 3c41 2048 5245 463d 2268 7474 .of.<A.HREF="htt
- 0x1300: 703a 2f2f 6275 6773 2e64 6562 6961 6e2e p://bugs.debian.
- 0x1310: 6f72 672f 7372 633a 6170 6163 6865 223e org/src:apache">
- 0x1320: 6b6e 6f77 6e20 6275 6773 3c2f 413e 206f known.bugs</A>.o
- 0x1330: 6620 7468 6973 0a70 6163 6b61 6765 2c20 f.this.package,.
- 0x1340: 6361 6e20 6265 2066 6f75 6e64 2069 6e20 can.be.found.in.
- 0x1350: 7468 6520 0a3c 4120 4852 4546 3d22 6874 the..<A.HREF="ht
- 0x1360: 7470 3a2f 2f77 7777 2e64 6562 6961 6e2e tp://www.debian.
- 0x1370: 6f72 672f 4275 6773 2f52 6570 6f72 7469 org/Bugs/Reporti
- 0x1380: 6e67 223e 4465 6269 616e 2042 7567 2054 ng">Debian.Bug.T
- 0x1390: 7261 636b 696e 6720 5379 7374 656d 3c2f racking.System</
- 0x13a0: 413e 2e0a 0a3c 503e 5468 616e 6b73 2066 A>...<P>Thanks.f
- 0x13b0: 6f72 2075 7369 6e67 2074 6869 7320 7061 or.using.this.pa
- 0x13c0: 636b 6167 652c 2061 6e64 2063 6f6e 6772 ckage,.and.congr
- 0x13d0: 6174 756c 6174 696f 6e73 2066 6f72 2079 atulations.for.y
- 0x13e0: 6f75 7220 6368 6f69 6365 206f 660a 6120 our.choice.of.a.
- 0x13f0: 4465 6269 616e 2073 7973 7465 6d21 3c2f Debian.system!</
- 0x1400: 503e 0a0a 3c44 4956 2061 6c69 676e 3d22 P>..<DIV.align="
- 0x1410: 6365 6e74 6572 223e 0a3c 6120 6872 6566 center">.<a.href
- 0x1420: 3d22 6874 7470 3a2f 2f77 7777 2e64 6562 ="http://www.deb
- 0x1430: 6961 6e2e 6f72 672f 223e 0a3c 494d 4720 ian.org/">.<IMG.
- 0x1440: 616c 6967 6e3d 226d 6964 646c 6522 2068 align="middle".h
- 0x1450: 6569 6768 743d 2233 3022 2077 6964 7468 eight="30".width
- 0x1460: 3d22 3235 2220 7372 633d 2269 636f 6e73 ="25".src="icons
- 0x1470: 2f64 6562 6961 6e2f 6f70 656e 6c6f 676f /debian/openlogo
- 0x1480: 2d32 352e 6a70 6722 2061 6c74 3d22 4465 -25.jpg".alt="De
- 0x1490: 6269 616e 223e 0a3c 2f61 3e0a 3c61 2068 bian">.</a>.<a.h
- 0x14a0: 7265 663d 2268 7474 703a 2f2f 7777 772e ref="http://www.
- 0x14b0: 6170 6163 6865 2e6f 7267 2f22 3e0a 3c49 apache.org/">.<I
- 0x14c0: 4d47 2061 6c69 676e 3d22 6d69 6464 6c65 MG.align="middle
- 0x14d0: 2220 6865 6967 6874 3d22 3332 2220 7769 ".height="32".wi
- 0x14e0: 6474 683d 2232 3539 2220 7372 633d 2269 dth="259".src="i
- 0x14f0: 636f 6e73 2f61 7061 6368 655f 7062 2e70 cons/apache_pb.p
- 0x1500: 6e67 2220 616c 743d 2241 7061 6368 6522 ng".alt="Apache"
- 0x1510: 3e0a 3c2f 613e 0a3c 2f44 4956 3e0a 0a3c >.</a>.</DIV>..<
- 0x1520: 212d 2d0a 2020 5468 6973 2070 6167 6520 !--...This.page.
- 0x1530: 7761 7320 696e 6974 6961 6c6c 7920 6372 was.initially.cr
- 0x1540: 6561 7465 6420 6279 204a 6f68 6e69 6520 eated.by.Johnie.
- 0x1550: 496e 6772 616d 2028 6874 7470 3a2f 2f6e Ingram.(http://n
- 0x1560: 6574 676f 642e 6e65 742f 290a 2020 4974 etgod.net/)...It
- 0x1570: 2077 6173 206c 6174 6572 2065 6469 7465 .was.later.edite
- 0x1580: 6420 6279 204d 6174 7468 6577 2057 696c d.by.Matthew.Wil
- 0x1590: 636f 7820 616e 6420 4a6f 7369 7020 526f cox.and.Josip.Ro
- 0x15a0: 6469 6e2e 0a20 204c 6173 7420 6d6f 6469 din....Last.modi
- 0x15b0: 6669 6564 3a20 2444 6174 653a 2032 3030 fied:.$Date:.200
- 0x15c0: 342f 3036 2f32 3020 3135 3a33 333a 3537 4/06/20.15:33:57
- 0x15d0: 2024 2e0a 2020 2d2d 3e0a 0a3c 2f42 4f44 .$....-->..</BOD
- 0x15e0: 593e 0a3c 2f48 544d 4c3e 0a Y>.</HTML>.
-23:57:35.941260 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5560 win 12383 <nop,nop,timestamp 1306300953 1306300953>
- 0x0000: 4500 0034 1b6e 4000 4006 2154 7f00 0001 E..4.n@.@.!T....
- 0x0010: 7f00 0001 da70 0050 3758 8a49 377a a3a9 .....p.P7X.I7z..
- 0x0020: 8010 305f 10ea 0000 0101 080a 4ddc 9219 ..0_........M...
- 0x0030: 4ddc 9219 M...
-23:57:37.229575 IP 127.0.0.1.55920 > 127.0.0.1.80: F 203:203(0) ack 5560 win 12383 <nop,nop,timestamp 1306302241 1306300953>
- 0x0000: 4500 0034 1b70 4000 4006 2152 7f00 0001 E..4.p@.@.!R....
- 0x0010: 7f00 0001 da70 0050 3758 8a49 377a a3a9 .....p.P7X.I7z..
- 0x0020: 8011 305f 0be1 0000 0101 080a 4ddc 9721 ..0_........M..!
- 0x0030: 4ddc 9219 M...
-23:57:37.230839 IP 127.0.0.1.80 > 127.0.0.1.55920: F 5560:5560(0) ack 204 win 8192 <nop,nop,timestamp 1306302243 1306302241>
- 0x0000: 4500 0034 1fe8 4000 4006 1cda 7f00 0001 E..4..@.@.......
- 0x0010: 7f00 0001 0050 da70 377a a3a9 3758 8a4a .....P.p7z..7X.J
- 0x0020: 8011 2000 1735 0000 0101 080a 4ddc 9723 .....5......M..#
- 0x0030: 4ddc 9721 M..!
-23:57:37.230900 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5561 win 12383 <nop,nop,timestamp 1306302243 1306302243>
- 0x0000: 4500 0034 1b72 4000 4006 2150 7f00 0001 E..4.r@.@.!P....
- 0x0010: 7f00 0001 da70 0050 3758 8a4a 377a a3aa .....p.P7X.J7z..
- 0x0020: 8010 305f 06d4 0000 0101 080a 4ddc 9723 ..0_........M..#
- 0x0030: 4ddc 9723 M..#
diff --git a/contrib/tcpdump/tests/print-capXX.out b/contrib/tcpdump/tests/print-capXX.out
deleted file mode 100644
index 6921a01..0000000
--- a/contrib/tcpdump/tests/print-capXX.out
+++ /dev/null
@@ -1,419 +0,0 @@
-23:57:35.938066 IP 127.0.0.1.55920 > 127.0.0.1.80: S 928549246:928549246(0) win 32767 <mss 16396,sackOK,timestamp 1306300950 0,nop,wscale 2>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 003c 1b68 4000 4006 2152 7f00 0001 7f00 .<.h@.@.!R......
- 0x0020: 0001 da70 0050 3758 897e 0000 0000 a002 ...p.P7X.~......
- 0x0030: 7fff 1421 0000 0204 400c 0402 080a 4ddc ...!....@.....M.
- 0x0040: 9216 0000 0000 0103 0302 ..........
-23:57:35.938122 IP 127.0.0.1.80 > 127.0.0.1.55920: S 930778609:930778609(0) ack 928549247 win 32767 <mss 16396,sackOK,timestamp 1306300950 1306300950,nop,wscale 2>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 003c 0000 4000 4006 3cba 7f00 0001 7f00 .<..@.@.<.......
- 0x0020: 0001 0050 da70 377a 8df1 3758 897f a012 ...P.p7z..7X....
- 0x0030: 7fff 6eb1 0000 0204 400c 0402 080a 4ddc ..n.....@.....M.
- 0x0040: 9216 4ddc 9216 0103 0302 ..M.......
-23:57:35.938167 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 1 win 8192 <nop,nop,timestamp 1306300950 1306300950>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1b6a 4000 4006 2158 7f00 0001 7f00 .4.j@.@.!X......
- 0x0020: 0001 da70 0050 3758 897f 377a 8df2 8010 ...p.P7X..7z....
- 0x0030: 2000 37d0 0000 0101 080a 4ddc 9216 4ddc ..7.......M...M.
- 0x0040: 9216 ..
-23:57:35.939423 IP 127.0.0.1.55920 > 127.0.0.1.80: P 1:203(202) ack 1 win 8192 <nop,nop,timestamp 1306300951 1306300950>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 00fe 1b6c 4000 4006 208c 7f00 0001 7f00 ...l@.@.........
- 0x0020: 0001 da70 0050 3758 897f 377a 8df2 8018 ...p.P7X..7z....
- 0x0030: 2000 fef2 0000 0101 080a 4ddc 9217 4ddc ..........M...M.
- 0x0040: 9216 4745 5420 2f20 4854 5450 2f31 2e31 ..GET./.HTTP/1.1
- 0x0050: 0d0a 486f 7374 3a20 6c6f 6361 6c68 6f73 ..Host:.localhos
- 0x0060: 740d 0a55 7365 722d 4167 656e 743a 2045 t..User-Agent:.E
- 0x0070: 4c69 6e6b 732f 302e 3130 2e34 2d37 2d64 Links/0.10.4-7-d
- 0x0080: 6562 6961 6e20 2874 6578 746d 6f64 653b ebian.(textmode;
- 0x0090: 204c 696e 7578 2032 2e36 2e31 312d 312d .Linux.2.6.11-1-
- 0x00a0: 3638 362d 736d 7020 6936 3836 3b20 3133 686-smp.i686;.13
- 0x00b0: 3278 3536 2d32 290d 0a41 6363 6570 743a 2x56-2)..Accept:
- 0x00c0: 202a 2f2a 0d0a 4163 6365 7074 2d45 6e63 .*/*..Accept-Enc
- 0x00d0: 6f64 696e 673a 2067 7a69 700d 0a41 6363 oding:.gzip..Acc
- 0x00e0: 6570 742d 4c61 6e67 7561 6765 3a20 656e ept-Language:.en
- 0x00f0: 0d0a 436f 6e6e 6563 7469 6f6e 3a20 4b65 ..Connection:.Ke
- 0x0100: 6570 2d41 6c69 7665 0d0a 0d0a ep-Alive....
-23:57:35.940474 IP 127.0.0.1.80 > 127.0.0.1.55920: . ack 203 win 8192 <nop,nop,timestamp 1306300952 1306300951>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1fe4 4000 4006 1cde 7f00 0001 7f00 .4..@.@.........
- 0x0020: 0001 0050 da70 377a 8df2 3758 8a49 8010 ...P.p7z..7X.I..
- 0x0030: 2000 3703 0000 0101 080a 4ddc 9218 4ddc ..7.......M...M.
- 0x0040: 9217 ..
-23:57:35.941232 IP 127.0.0.1.80 > 127.0.0.1.55920: P 1:5560(5559) ack 203 win 8192 <nop,nop,timestamp 1306300953 1306300951>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 15eb 1fe6 4000 4006 0725 7f00 0001 7f00 ....@.@..%......
- 0x0020: 0001 0050 da70 377a 8df2 3758 8a49 8018 ...P.p7z..7X.I..
- 0x0030: 2000 13e0 0000 0101 080a 4ddc 9219 4ddc ..........M...M.
- 0x0040: 9217 4854 5450 2f31 2e31 2032 3030 204f ..HTTP/1.1.200.O
- 0x0050: 4b0d 0a44 6174 653a 2057 6564 2c20 3036 K..Date:.Wed,.06
- 0x0060: 204a 756c 2032 3030 3520 3033 3a35 373a .Jul.2005.03:57:
- 0x0070: 3335 2047 4d54 0d0a 5365 7276 6572 3a20 35.GMT..Server:.
- 0x0080: 4170 6163 6865 2f31 2e33 2e33 330d 0a4c Apache/1.3.33..L
- 0x0090: 6173 742d 4d6f 6469 6669 6564 3a20 5375 ast-Modified:.Su
- 0x00a0: 6e2c 2031 3520 4175 6720 3230 3034 2030 n,.15.Aug.2004.0
- 0x00b0: 303a 3433 3a34 3120 474d 540d 0a45 5461 0:43:41.GMT..ETa
- 0x00c0: 673a 2022 3665 3830 6630 2d31 3438 612d g:."6e80f0-148a-
- 0x00d0: 3431 3165 6231 6264 220d 0a41 6363 6570 411eb1bd"..Accep
- 0x00e0: 742d 5261 6e67 6573 3a20 6279 7465 730d t-Ranges:.bytes.
- 0x00f0: 0a43 6f6e 7465 6e74 2d4c 656e 6774 683a .Content-Length:
- 0x0100: 2035 3235 380d 0a4b 6565 702d 416c 6976 .5258..Keep-Aliv
- 0x0110: 653a 2074 696d 656f 7574 3d31 352c 206d e:.timeout=15,.m
- 0x0120: 6178 3d31 3030 0d0a 436f 6e6e 6563 7469 ax=100..Connecti
- 0x0130: 6f6e 3a20 4b65 6570 2d41 6c69 7665 0d0a on:.Keep-Alive..
- 0x0140: 436f 6e74 656e 742d 5479 7065 3a20 7465 Content-Type:.te
- 0x0150: 7874 2f68 746d 6c3b 2063 6861 7273 6574 xt/html;.charset
- 0x0160: 3d69 736f 2d38 3835 392d 310d 0a0d 0a3c =iso-8859-1....<
- 0x0170: 2144 4f43 5459 5045 2048 544d 4c20 5055 !DOCTYPE.HTML.PU
- 0x0180: 424c 4943 2022 2d2f 2f57 3343 2f2f 4454 BLIC."-//W3C//DT
- 0x0190: 4420 4854 4d4c 2034 2e30 3120 5472 616e D.HTML.4.01.Tran
- 0x01a0: 7369 7469 6f6e 616c 2f2f 454e 223e 0a3c sitional//EN">.<
- 0x01b0: 4854 4d4c 3e0a 3c48 4541 443e 0a20 2020 HTML>.<HEAD>....
- 0x01c0: 3c4d 4554 4120 4854 5450 2d45 5155 4956 <META.HTTP-EQUIV
- 0x01d0: 3d22 436f 6e74 656e 742d 5479 7065 2220 ="Content-Type".
- 0x01e0: 434f 4e54 454e 543d 2274 6578 742f 6874 CONTENT="text/ht
- 0x01f0: 6d6c 3b20 6368 6172 7365 743d 6973 6f2d ml;.charset=iso-
- 0x0200: 3838 3539 2d31 223e 0a20 2020 3c4d 4554 8859-1">....<MET
- 0x0210: 4120 4e41 4d45 3d22 4465 7363 7269 7074 A.NAME="Descript
- 0x0220: 696f 6e22 2043 4f4e 5445 4e54 3d22 5468 ion".CONTENT="Th
- 0x0230: 6520 696e 6974 6961 6c20 696e 7374 616c e.initial.instal
- 0x0240: 6c61 7469 6f6e 206f 6620 4465 6269 616e lation.of.Debian
- 0x0250: 2061 7061 6368 652e 223e 0a20 2020 3c54 .apache.">....<T
- 0x0260: 4954 4c45 3e50 6c61 6365 686f 6c64 6572 ITLE>Placeholder
- 0x0270: 2070 6167 653c 2f54 4954 4c45 3e0a 3c2f .page</TITLE>.</
- 0x0280: 4845 4144 3e0a 3c42 4f44 5920 5445 5854 HEAD>.<BODY.TEXT
- 0x0290: 3d22 2330 3030 3030 3022 2042 4743 4f4c ="#000000".BGCOL
- 0x02a0: 4f52 3d22 2346 4646 4646 4622 204c 494e OR="#FFFFFF".LIN
- 0x02b0: 4b3d 2223 3030 3030 4546 2220 564c 494e K="#0000EF".VLIN
- 0x02c0: 4b3d 2223 3535 3138 3841 2220 414c 494e K="#55188A".ALIN
- 0x02d0: 4b3d 2223 4646 3030 3030 223e 0a0a 3c48 K="#FF0000">..<H
- 0x02e0: 313e 506c 6163 6568 6f6c 6465 7220 7061 1>Placeholder.pa
- 0x02f0: 6765 3c2f 4831 3e0a 3c48 323e 4966 2079 ge</H1>.<H2>If.y
- 0x0300: 6f75 2061 7265 206a 7573 7420 6272 6f77 ou.are.just.brow
- 0x0310: 7369 6e67 2074 6865 2077 6562 3c2f 6832 sing.the.web</h2
- 0x0320: 3e0a 0a3c 503e 5468 6520 6f77 6e65 7220 >..<P>The.owner.
- 0x0330: 6f66 2074 6869 7320 7765 6220 7369 7465 of.this.web.site
- 0x0340: 2068 6173 206e 6f74 2070 7574 2075 7020 .has.not.put.up.
- 0x0350: 616e 7920 7765 6220 7061 6765 7320 7965 any.web.pages.ye
- 0x0360: 742e 0a50 6c65 6173 6520 636f 6d65 2062 t..Please.come.b
- 0x0370: 6163 6b20 6c61 7465 722e 3c2f 503e 0a0a ack.later.</P>..
- 0x0380: 3c50 3e3c 534d 414c 4c3e 3c43 4954 453e <P><SMALL><CITE>
- 0x0390: 4d6f 7665 2061 6c6f 6e67 2c20 6e6f 7468 Move.along,.noth
- 0x03a0: 696e 6720 746f 2073 6565 2068 6572 652e ing.to.see.here.
- 0x03b0: 2e2e 3c2f 4349 5445 3e20 3a2d 293c 2f53 ..</CITE>.:-)</S
- 0x03c0: 4d41 4c4c 3e3c 2f50 3e0a 0a3c 4832 3e49 MALL></P>..<H2>I
- 0x03d0: 6620 796f 7520 6172 6520 7472 7969 6e67 f.you.are.trying
- 0x03e0: 2074 6f20 6c6f 6361 7465 2074 6865 2061 .to.locate.the.a
- 0x03f0: 646d 696e 6973 7472 6174 6f72 206f 6620 dministrator.of.
- 0x0400: 7468 6973 206d 6163 6869 6e65 3c2f 4832 this.machine</H2
- 0x0410: 3e0a 0a3c 503e 4966 2079 6f75 2077 616e >..<P>If.you.wan
- 0x0420: 7420 746f 2072 6570 6f72 7420 736f 6d65 t.to.report.some
- 0x0430: 7468 696e 6720 6162 6f75 7420 7468 6973 thing.about.this
- 0x0440: 2068 6f73 7427 7320 6265 6861 7669 6f72 .host's.behavior
- 0x0450: 2c20 706c 6561 7365 0a63 6f6e 7461 6374 ,.please.contact
- 0x0460: 2074 6865 2049 6e74 6572 6e65 7420 5365 .the.Internet.Se
- 0x0470: 7276 6963 6520 5072 6f76 6964 6572 2028 rvice.Provider.(
- 0x0480: 4953 5029 2069 6e76 6f6c 7665 6420 6469 ISP).involved.di
- 0x0490: 7265 6374 6c79 2e3c 2f50 3e0a 0a3c 503e rectly.</P>..<P>
- 0x04a0: 5365 6520 7468 6520 3c41 2068 7265 663d See.the.<A.href=
- 0x04b0: 2268 7474 703a 2f2f 7777 772e 6162 7573 "http://www.abus
- 0x04c0: 652e 6e65 742f 223e 4e65 7477 6f72 6b20 e.net/">Network.
- 0x04d0: 4162 7573 650a 436c 6561 7269 6e67 686f Abuse.Clearingho
- 0x04e0: 7573 653c 2f41 3e20 666f 7220 686f 7720 use</A>.for.how.
- 0x04f0: 746f 2064 6f20 7468 6973 2e3c 2f50 3e0a to.do.this.</P>.
- 0x0500: 0a3c 4832 3e49 6620 796f 7520 6172 6520 .<H2>If.you.are.
- 0x0510: 7468 6520 6164 6d69 6e69 7374 7261 746f the.administrato
- 0x0520: 7220 6f66 2074 6869 7320 6d61 6368 696e r.of.this.machin
- 0x0530: 653c 2f48 323e 0a0a 3c50 3e54 6865 2069 e</H2>..<P>The.i
- 0x0540: 6e69 7469 616c 2069 6e73 7461 6c6c 6174 nitial.installat
- 0x0550: 696f 6e20 6f66 203c 4120 6872 6566 3d22 ion.of.<A.href="
- 0x0560: 6874 7470 3a2f 2f77 7777 2e64 6562 6961 http://www.debia
- 0x0570: 6e2e 6f72 672f 223e 4465 6269 616e 2773 n.org/">Debian's
- 0x0580: 0a61 7061 6368 653c 2f41 3e20 7765 6220 .apache</A>.web.
- 0x0590: 7365 7276 6572 2070 6163 6b61 6765 2077 server.package.w
- 0x05a0: 6173 2073 7563 6365 7373 6675 6c2e 3c2f as.successful.</
- 0x05b0: 503e 0a0a 3c50 3e3c 5354 524f 4e47 3e59 P>..<P><STRONG>Y
- 0x05c0: 6f75 2073 686f 756c 6420 7265 706c 6163 ou.should.replac
- 0x05d0: 6520 7468 6973 2070 6167 6520 7769 7468 e.this.page.with
- 0x05e0: 2079 6f75 7220 6f77 6e20 7765 6220 7061 .your.own.web.pa
- 0x05f0: 6765 7320 6173 0a73 6f6f 6e20 6173 2070 ges.as.soon.as.p
- 0x0600: 6f73 7369 626c 652e 3c2f 5354 524f 4e47 ossible.</STRONG
- 0x0610: 3e3c 2f50 3e0a 0a3c 503e 556e 6c65 7373 ></P>..<P>Unless
- 0x0620: 2079 6f75 2063 6861 6e67 6564 2069 7473 .you.changed.its
- 0x0630: 2063 6f6e 6669 6775 7261 7469 6f6e 2c20 .configuration,.
- 0x0640: 796f 7572 206e 6577 2073 6572 7665 7220 your.new.server.
- 0x0650: 6973 2063 6f6e 6669 6775 7265 6420 6173 is.configured.as
- 0x0660: 2066 6f6c 6c6f 7773 3a0a 3c55 4c3e 0a3c .follows:.<UL>.<
- 0x0670: 4c49 3e0a 436f 6e66 6967 7572 6174 696f LI>.Configuratio
- 0x0680: 6e20 6669 6c65 7320 6361 6e20 6265 2066 n.files.can.be.f
- 0x0690: 6f75 6e64 2069 6e20 3c54 543e 2f65 7463 ound.in.<TT>/etc
- 0x06a0: 2f61 7061 6368 653c 2f54 543e 2e3c 2f4c /apache</TT>.</L
- 0x06b0: 493e 0a0a 3c4c 493e 0a54 6865 203c 5454 I>..<LI>.The.<TT
- 0x06c0: 3e44 6f63 756d 656e 7452 6f6f 743c 2f54 >DocumentRoot</T
- 0x06d0: 543e 2c20 7768 6963 6820 6973 2074 6865 T>,.which.is.the
- 0x06e0: 2064 6972 6563 746f 7279 2075 6e64 6572 .directory.under
- 0x06f0: 2077 6869 6368 2061 6c6c 2079 6f75 720a .which.all.your.
- 0x0700: 4854 4d4c 2066 696c 6573 2073 686f 756c HTML.files.shoul
- 0x0710: 6420 6578 6973 742c 2069 7320 7365 7420 d.exist,.is.set.
- 0x0720: 746f 203c 5454 3e2f 7661 722f 7777 773c to.<TT>/var/www<
- 0x0730: 2f54 543e 2e3c 2f4c 493e 0a0a 3c4c 493e /TT>.</LI>..<LI>
- 0x0740: 0a43 4749 2073 6372 6970 7473 2061 7265 .CGI.scripts.are
- 0x0750: 206c 6f6f 6b65 6420 666f 7220 696e 203c .looked.for.in.<
- 0x0760: 5454 3e2f 7573 722f 6c69 622f 6367 692d TT>/usr/lib/cgi-
- 0x0770: 6269 6e3c 2f54 543e 2c20 7768 6963 6820 bin</TT>,.which.
- 0x0780: 6973 2077 6865 7265 0a44 6562 6961 6e20 is.where.Debian.
- 0x0790: 7061 636b 6167 6573 2077 696c 6c20 706c packages.will.pl
- 0x07a0: 6163 6520 7468 6569 7220 7363 7269 7074 ace.their.script
- 0x07b0: 732e 3c2f 4c49 3e0a 0a3c 4c49 3e0a 4c6f s.</LI>..<LI>.Lo
- 0x07c0: 6720 6669 6c65 7320 6172 6520 706c 6163 g.files.are.plac
- 0x07d0: 6564 2069 6e20 3c54 543e 2f76 6172 2f6c ed.in.<TT>/var/l
- 0x07e0: 6f67 2f61 7061 6368 653c 2f54 543e 2c20 og/apache</TT>,.
- 0x07f0: 616e 6420 7769 6c6c 2062 6520 726f 7461 and.will.be.rota
- 0x0800: 7465 640a 7765 656b 6c79 2e20 2054 6865 ted.weekly...The
- 0x0810: 2066 7265 7175 656e 6379 206f 6620 726f .frequency.of.ro
- 0x0820: 7461 7469 6f6e 2063 616e 2062 6520 6561 tation.can.be.ea
- 0x0830: 7369 6c79 2063 6861 6e67 6564 2062 7920 sily.changed.by.
- 0x0840: 6564 6974 696e 670a 3c54 543e 2f65 7463 editing.<TT>/etc
- 0x0850: 2f6c 6f67 726f 7461 7465 2e64 2f61 7061 /logrotate.d/apa
- 0x0860: 6368 653c 2f54 543e 2e3c 2f4c 493e 0a0a che</TT>.</LI>..
- 0x0870: 3c4c 493e 0a54 6865 2064 6566 6175 6c74 <LI>.The.default
- 0x0880: 2064 6972 6563 746f 7279 2069 6e64 6578 .directory.index
- 0x0890: 2069 7320 3c54 543e 696e 6465 782e 6874 .is.<TT>index.ht
- 0x08a0: 6d6c 3c2f 5454 3e2c 206d 6561 6e69 6e67 ml</TT>,.meaning
- 0x08b0: 2074 6861 7420 7265 7175 6573 7473 0a66 .that.requests.f
- 0x08c0: 6f72 2061 2064 6972 6563 746f 7279 203c or.a.directory.<
- 0x08d0: 5454 3e2f 666f 6f2f 6261 722f 3c2f 5454 TT>/foo/bar/</TT
- 0x08e0: 3e20 7769 6c6c 2067 6976 6520 7468 6520 >.will.give.the.
- 0x08f0: 636f 6e74 656e 7473 206f 6620 7468 6520 contents.of.the.
- 0x0900: 6669 6c65 203c 5454 3e2f 7661 722f 7777 file.<TT>/var/ww
- 0x0910: 772f 666f 6f2f 6261 722f 696e 6465 782e w/foo/bar/index.
- 0x0920: 6874 6d6c 3c2f 5454 3e0a 6966 2069 7420 html</TT>.if.it.
- 0x0930: 6578 6973 7473 2028 6173 7375 6d69 6e67 exists.(assuming
- 0x0940: 2074 6861 7420 3c54 543e 2f76 6172 2f77 .that.<TT>/var/w
- 0x0950: 7777 3c2f 5454 3e20 6973 2079 6f75 7220 ww</TT>.is.your.
- 0x0960: 3c54 543e 446f 6375 6d65 6e74 526f 6f74 <TT>DocumentRoot
- 0x0970: 3c2f 5454 3e29 2e3c 2f4c 493e 0a0a 3c4c </TT>).</LI>..<L
- 0x0980: 493e 0a55 7365 7220 6469 7265 6374 6f72 I>.User.director
- 0x0990: 6965 7320 6172 6520 656e 6162 6c65 642c ies.are.enabled,
- 0x09a0: 2061 6e64 2075 7365 7220 646f 6375 6d65 .and.user.docume
- 0x09b0: 6e74 7320 7769 6c6c 2062 6520 6c6f 6f6b nts.will.be.look
- 0x09c0: 6564 2066 6f72 0a69 6e20 7468 6520 3c54 ed.for.in.the.<T
- 0x09d0: 543e 7075 626c 6963 5f68 746d 6c3c 2f54 T>public_html</T
- 0x09e0: 543e 2064 6972 6563 746f 7279 206f 6620 T>.directory.of.
- 0x09f0: 7468 6520 7573 6572 7327 2068 6f6d 6573 the.users'.homes
- 0x0a00: 2e20 2054 6865 7365 2064 6972 730a 7368 ...These.dirs.sh
- 0x0a10: 6f75 6c64 2062 6520 756e 6465 7220 3c54 ould.be.under.<T
- 0x0a20: 543e 2f68 6f6d 653c 2f54 543e 2c20 616e T>/home</TT>,.an
- 0x0a30: 6420 7573 6572 7320 7769 6c6c 206e 6f74 d.users.will.not
- 0x0a40: 2062 6520 6162 6c65 2074 6f20 7379 6d6c .be.able.to.syml
- 0x0a50: 696e 6b0a 746f 2066 696c 6573 2074 6865 ink.to.files.the
- 0x0a60: 7920 646f 6e27 7420 6f77 6e2e 3c2f 4c49 y.don't.own.</LI
- 0x0a70: 3e0a 0a3c 2f55 4c3e 0a41 6c6c 2074 6865 >..</UL>.All.the
- 0x0a80: 2073 7461 6e64 6172 6420 6170 6163 6865 .standard.apache
- 0x0a90: 206d 6f64 756c 6573 2061 7265 2061 7661 .modules.are.ava
- 0x0aa0: 696c 6162 6c65 2077 6974 6820 7468 6973 ilable.with.this
- 0x0ab0: 2072 656c 6561 7365 2061 6e64 2061 7265 .release.and.are
- 0x0ac0: 0a6e 6f77 206d 616e 6167 6564 2077 6974 .now.managed.wit
- 0x0ad0: 6820 6465 6263 6f6e 662e 2020 5479 7065 h.debconf...Type
- 0x0ae0: 203c 5454 3e64 706b 672d 7265 636f 6e66 .<TT>dpkg-reconf
- 0x0af0: 6967 7572 6520 6170 6163 6865 3c2f 5454 igure.apache</TT
- 0x0b00: 3e20 746f 0a73 656c 6563 7420 7768 6963 >.to.select.whic
- 0x0b10: 6820 6d6f 6475 6c65 7320 796f 7520 7761 h.modules.you.wa
- 0x0b20: 6e74 2065 6e61 626c 6564 2e20 204d 616e nt.enabled...Man
- 0x0b30: 7920 6f74 6865 7220 6d6f 6475 6c65 7320 y.other.modules.
- 0x0b40: 6172 6520 6176 6169 6c61 626c 650a 7468 are.available.th
- 0x0b50: 726f 7567 6820 7468 6520 4465 6269 616e rough.the.Debian
- 0x0b60: 2070 6163 6b61 6765 2073 7973 7465 6d20 .package.system.
- 0x0b70: 7769 7468 2074 6865 206e 616d 6573 203c with.the.names.<
- 0x0b80: 5454 3e6c 6962 6170 6163 6865 2d6d 6f64 TT>libapache-mod
- 0x0b90: 2d2a 3c2f 5454 3e2e 0a49 6620 796f 7520 -*</TT>..If.you.
- 0x0ba0: 6e65 6564 2074 6f20 636f 6d70 696c 6520 need.to.compile.
- 0x0bb0: 6120 6d6f 6475 6c65 2079 6f75 7273 656c a.module.yoursel
- 0x0bc0: 662c 2079 6f75 2077 696c 6c20 6e65 6564 f,.you.will.need
- 0x0bd0: 2074 6f20 696e 7374 616c 6c20 7468 650a .to.install.the.
- 0x0be0: 3c54 543e 6170 6163 6865 2d64 6576 3c2f <TT>apache-dev</
- 0x0bf0: 5454 3e20 7061 636b 6167 652e 0a0a 3c50 TT>.package...<P
- 0x0c00: 3e4d 6f72 6520 646f 6375 6d65 6e74 6174 >More.documentat
- 0x0c10: 696f 6e20 6f6e 2041 7061 6368 6520 6361 ion.on.Apache.ca
- 0x0c20: 6e20 6265 2066 6f75 6e64 206f 6e3a 0a3c n.be.found.on:.<
- 0x0c30: 554c 3e0a 3c4c 493e 0a54 6865 203c 4120 UL>.<LI>.The.<A.
- 0x0c40: 4852 4546 3d22 2f64 6f63 2f61 7061 6368 HREF="/doc/apach
- 0x0c50: 652d 646f 632f 6d61 6e75 616c 2f22 3e41 e-doc/manual/">A
- 0x0c60: 7061 6368 6520 646f 6375 6d65 6e74 6174 pache.documentat
- 0x0c70: 696f 6e3c 2f41 3e20 7374 6f72 6564 206f ion</A>.stored.o
- 0x0c80: 6e20 796f 7572 2073 6572 7665 722e 3c2f n.your.server.</
- 0x0c90: 4c49 3e0a 0a3c 4c49 3e0a 5468 6520 3c41 LI>..<LI>.The.<A
- 0x0ca0: 2048 5245 463d 2268 7474 703a 2f2f 7777 .HREF="http://ww
- 0x0cb0: 772e 6170 6163 6865 2e6f 7267 2f22 3e41 w.apache.org/">A
- 0x0cc0: 7061 6368 6520 5072 6f6a 6563 743c 2f41 pache.Project</A
- 0x0cd0: 3e20 686f 6d65 2073 6974 652e 3c2f 4c49 >.home.site.</LI
- 0x0ce0: 3e0a 0a3c 4c49 3e0a 5468 6520 3c41 2048 >..<LI>.The.<A.H
- 0x0cf0: 5245 463d 2268 7474 703a 2f2f 7777 772e REF="http://www.
- 0x0d00: 6170 6163 6865 2d73 736c 2e6f 7267 2f22 apache-ssl.org/"
- 0x0d10: 3e41 7061 6368 652d 5353 4c3c 2f41 3e20 >Apache-SSL</A>.
- 0x0d20: 686f 6d65 2073 6974 652e 3c2f 4c49 3e0a home.site.</LI>.
- 0x0d30: 0a3c 4c49 3e0a 5468 6520 3c41 2048 5245 .<LI>.The.<A.HRE
- 0x0d40: 463d 2268 7474 703a 2f2f 7065 726c 2e61 F="http://perl.a
- 0x0d50: 7061 6368 652e 6f72 672f 223e 6d6f 6420 pache.org/">mod.
- 0x0d60: 7065 726c 3c2f 413e 2068 6f6d 6520 7369 perl</A>.home.si
- 0x0d70: 7465 2e3c 2f4c 493e 0a0a 3c4c 493e 0a54 te.</LI>..<LI>.T
- 0x0d80: 6865 203c 4120 4852 4546 3d22 6874 7470 he.<A.HREF="http
- 0x0d90: 3a2f 2f77 7777 2e61 7061 6368 6577 6565 ://www.apachewee
- 0x0da0: 6b2e 636f 6d2f 223e 4170 6163 6865 5765 k.com/">ApacheWe
- 0x0db0: 656b 3c2f 413e 206e 6577 736c 6574 7465 ek</A>.newslette
- 0x0dc0: 722e 3c2f 4c49 3e0a 0a3c 4c49 3e0a 5468 r.</LI>..<LI>.Th
- 0x0dd0: 6520 3c41 2048 5245 463d 2268 7474 703a e.<A.HREF="http:
- 0x0de0: 2f2f 7777 772e 6465 6269 616e 2e6f 7267 //www.debian.org
- 0x0df0: 2f64 6f63 2f22 3e44 6562 6961 6e20 5072 /doc/">Debian.Pr
- 0x0e00: 6f6a 6563 740a 446f 6375 6d65 6e74 6174 oject.Documentat
- 0x0e10: 696f 6e3c 2f41 3e20 7768 6963 6820 636f ion</A>.which.co
- 0x0e20: 6e74 6169 6e73 2048 4f57 544f 732c 2046 ntains.HOWTOs,.F
- 0x0e30: 4151 732c 2061 6e64 2073 6f66 7477 6172 AQs,.and.softwar
- 0x0e40: 6520 7570 6461 7465 732e 3c2f 4c49 3e0a e.updates.</LI>.
- 0x0e50: 3c2f 554c 3e0a 0a3c 503e 596f 7520 6361 </UL>..<P>You.ca
- 0x0e60: 6e20 616c 736f 2063 6f6e 7375 6c74 2074 n.also.consult.t
- 0x0e70: 6865 206c 6973 7420 6f66 203c 4120 4852 he.list.of.<A.HR
- 0x0e80: 4546 3d22 6874 7470 3a2f 2f77 7777 2e62 EF="http://www.b
- 0x0e90: 6f75 7465 6c6c 2e63 6f6d 2f66 6171 2f22 outell.com/faq/"
- 0x0ea0: 3e57 6f72 6c64 0a57 6964 6520 5765 6220 >World.Wide.Web.
- 0x0eb0: 4672 6571 7565 6e74 6c79 2041 736b 6564 Frequently.Asked
- 0x0ec0: 2051 7565 7374 696f 6e73 3c2f 413e 2066 .Questions</A>.f
- 0x0ed0: 6f72 2069 6e66 6f72 6d61 7469 6f6e 2e0a or.information..
- 0x0ee0: 0a3c 4832 3e4c 6574 206f 7468 6572 2070 .<H2>Let.other.p
- 0x0ef0: 656f 706c 6520 6b6e 6f77 2061 626f 7574 eople.know.about
- 0x0f00: 2074 6869 7320 7365 7276 6572 3c2f 4832 .this.server</H2
- 0x0f10: 3e0a 0a3c 4120 4852 4546 3d22 6874 7470 >..<A.HREF="http
- 0x0f20: 3a2f 2f6e 6574 6372 6166 742e 636f 6d2f ://netcraft.com/
- 0x0f30: 223e 4e65 7463 7261 6674 3c2f 413e 2070 ">Netcraft</A>.p
- 0x0f40: 726f 7669 6465 7320 616e 2069 6e74 6572 rovides.an.inter
- 0x0f50: 6573 7469 6e67 2066 7265 650a 7365 7276 esting.free.serv
- 0x0f60: 6963 6520 666f 7220 7765 6220 7369 7465 ice.for.web.site
- 0x0f70: 206d 6f6e 6974 6f72 696e 6720 616e 6420 .monitoring.and.
- 0x0f80: 7374 6174 6973 7469 6320 636f 6c6c 6563 statistic.collec
- 0x0f90: 7469 6f6e 2e0a 596f 7520 6361 6e20 6c65 tion..You.can.le
- 0x0fa0: 7420 7468 656d 206b 6e6f 7720 6162 6f75 t.them.know.abou
- 0x0fb0: 7420 796f 7572 2073 6572 7665 7220 7573 t.your.server.us
- 0x0fc0: 696e 6720 7468 6569 720a 3c41 2048 5245 ing.their.<A.HRE
- 0x0fd0: 463d 2268 7474 703a 2f2f 7570 7469 6d65 F="http://uptime
- 0x0fe0: 2e6e 6574 6372 6166 742e 636f 6d2f 223e .netcraft.com/">
- 0x0ff0: 696e 7465 7266 6163 653c 2f41 3e2e 0a45 interface</A>..E
- 0x1000: 6e61 626c 696e 6720 7468 6520 6d6f 6e69 nabling.the.moni
- 0x1010: 746f 7269 6e67 206f 6620 796f 7572 2073 toring.of.your.s
- 0x1020: 6572 7665 7220 7769 6c6c 2070 726f 7669 erver.will.provi
- 0x1030: 6465 2061 2062 6574 7465 7220 676c 6f62 de.a.better.glob
- 0x1040: 616c 206f 7665 7276 6965 770a 6f66 2077 al.overview.of.w
- 0x1050: 686f 2069 7320 7573 696e 6720 7768 6174 ho.is.using.what
- 0x1060: 2061 6e64 2077 6865 7265 2c20 616e 6420 .and.where,.and.
- 0x1070: 6974 2077 6f75 6c64 2067 6976 6520 4465 it.would.give.De
- 0x1080: 6269 616e 2061 2062 6574 7465 720a 6f76 bian.a.better.ov
- 0x1090: 6572 7669 6577 206f 6620 7468 6520 6170 erview.of.the.ap
- 0x10a0: 6163 6865 2070 6163 6b61 6765 2075 7361 ache.package.usa
- 0x10b0: 6765 2e0a 0a3c 4832 3e41 626f 7574 2074 ge...<H2>About.t
- 0x10c0: 6869 7320 7061 6765 3c2f 4832 3e0a 0a3c his.page</H2>..<
- 0x10d0: 494d 4720 414c 4947 4e3d 2272 6967 6874 IMG.ALIGN="right
- 0x10e0: 2220 414c 543d 2222 2048 4549 4748 543d ".ALT="".HEIGHT=
- 0x10f0: 2232 3437 2220 5749 4454 483d 2232 3738 "247".WIDTH="278
- 0x1100: 2220 5352 433d 2269 636f 6e73 2f6a 6865 ".SRC="icons/jhe
- 0x1110: 3036 312e 706e 6722 3e0a 0a3c 503e 5468 061.png">..<P>Th
- 0x1120: 6973 2069 7320 6120 706c 6163 6568 6f6c is.is.a.placehol
- 0x1130: 6465 7220 7061 6765 2069 6e73 7461 6c6c der.page.install
- 0x1140: 6564 2062 7920 7468 6520 3c41 0a48 5245 ed.by.the.<A.HRE
- 0x1150: 463d 2268 7474 703a 2f2f 7777 772e 6465 F="http://www.de
- 0x1160: 6269 616e 2e6f 7267 2f22 3e44 6562 6961 bian.org/">Debia
- 0x1170: 6e3c 2f41 3e0a 7265 6c65 6173 6520 6f66 n</A>.release.of
- 0x1180: 2074 6865 2061 7061 6368 6520 5765 6220 .the.apache.Web.
- 0x1190: 7365 7276 6572 2070 6163 6b61 6765 2e0a server.package..
- 0x11a0: 0a3c 503e 5468 6973 2063 6f6d 7075 7465 .<P>This.compute
- 0x11b0: 7220 6861 7320 696e 7374 616c 6c65 6420 r.has.installed.
- 0x11c0: 7468 6520 4465 6269 616e 2047 4e55 2f4c the.Debian.GNU/L
- 0x11d0: 696e 7578 206f 7065 7261 7469 6e67 2073 inux.operating.s
- 0x11e0: 7973 7465 6d2c 0a62 7574 2069 7420 6861 ystem,.but.it.ha
- 0x11f0: 7320 3c73 7472 6f6e 673e 6e6f 7468 696e s.<strong>nothin
- 0x1200: 6720 746f 2064 6f20 7769 7468 2074 6865 g.to.do.with.the
- 0x1210: 2044 6562 6961 6e0a 5072 6f6a 6563 743c .Debian.Project<
- 0x1220: 2f73 7472 6f6e 673e 2e20 506c 6561 7365 /strong>..Please
- 0x1230: 2064 6f20 3c73 7472 6f6e 673e 6e6f 743c .do.<strong>not<
- 0x1240: 2f73 7472 6f6e 673e 2063 6f6e 7461 6374 /strong>.contact
- 0x1250: 2074 6865 2044 6562 6961 6e0a 5072 6f6a .the.Debian.Proj
- 0x1260: 6563 7420 6162 6f75 7420 6974 2e3c 2f50 ect.about.it.</P
- 0x1270: 3e0a 0a3c 503e 4966 2079 6f75 2066 696e >..<P>If.you.fin
- 0x1280: 6420 6120 6275 6720 696e 2074 6869 7320 d.a.bug.in.this.
- 0x1290: 6170 6163 6865 2070 6163 6b61 6765 2c20 apache.package,.
- 0x12a0: 6f72 2069 6e20 4170 6163 6865 2069 7473 or.in.Apache.its
- 0x12b0: 656c 662c 0a70 6c65 6173 6520 6669 6c65 elf,.please.file
- 0x12c0: 2061 2062 7567 2072 6570 6f72 7420 6f6e .a.bug.report.on
- 0x12d0: 2069 742e 2020 496e 7374 7275 6374 696f .it...Instructio
- 0x12e0: 6e73 206f 6e20 646f 696e 6720 7468 6973 ns.on.doing.this
- 0x12f0: 2c20 616e 6420 7468 650a 6c69 7374 206f ,.and.the.list.o
- 0x1300: 6620 3c41 2048 5245 463d 2268 7474 703a f.<A.HREF="http:
- 0x1310: 2f2f 6275 6773 2e64 6562 6961 6e2e 6f72 //bugs.debian.or
- 0x1320: 672f 7372 633a 6170 6163 6865 223e 6b6e g/src:apache">kn
- 0x1330: 6f77 6e20 6275 6773 3c2f 413e 206f 6620 own.bugs</A>.of.
- 0x1340: 7468 6973 0a70 6163 6b61 6765 2c20 6361 this.package,.ca
- 0x1350: 6e20 6265 2066 6f75 6e64 2069 6e20 7468 n.be.found.in.th
- 0x1360: 6520 0a3c 4120 4852 4546 3d22 6874 7470 e..<A.HREF="http
- 0x1370: 3a2f 2f77 7777 2e64 6562 6961 6e2e 6f72 ://www.debian.or
- 0x1380: 672f 4275 6773 2f52 6570 6f72 7469 6e67 g/Bugs/Reporting
- 0x1390: 223e 4465 6269 616e 2042 7567 2054 7261 ">Debian.Bug.Tra
- 0x13a0: 636b 696e 6720 5379 7374 656d 3c2f 413e cking.System</A>
- 0x13b0: 2e0a 0a3c 503e 5468 616e 6b73 2066 6f72 ...<P>Thanks.for
- 0x13c0: 2075 7369 6e67 2074 6869 7320 7061 636b .using.this.pack
- 0x13d0: 6167 652c 2061 6e64 2063 6f6e 6772 6174 age,.and.congrat
- 0x13e0: 756c 6174 696f 6e73 2066 6f72 2079 6f75 ulations.for.you
- 0x13f0: 7220 6368 6f69 6365 206f 660a 6120 4465 r.choice.of.a.De
- 0x1400: 6269 616e 2073 7973 7465 6d21 3c2f 503e bian.system!</P>
- 0x1410: 0a0a 3c44 4956 2061 6c69 676e 3d22 6365 ..<DIV.align="ce
- 0x1420: 6e74 6572 223e 0a3c 6120 6872 6566 3d22 nter">.<a.href="
- 0x1430: 6874 7470 3a2f 2f77 7777 2e64 6562 6961 http://www.debia
- 0x1440: 6e2e 6f72 672f 223e 0a3c 494d 4720 616c n.org/">.<IMG.al
- 0x1450: 6967 6e3d 226d 6964 646c 6522 2068 6569 ign="middle".hei
- 0x1460: 6768 743d 2233 3022 2077 6964 7468 3d22 ght="30".width="
- 0x1470: 3235 2220 7372 633d 2269 636f 6e73 2f64 25".src="icons/d
- 0x1480: 6562 6961 6e2f 6f70 656e 6c6f 676f 2d32 ebian/openlogo-2
- 0x1490: 352e 6a70 6722 2061 6c74 3d22 4465 6269 5.jpg".alt="Debi
- 0x14a0: 616e 223e 0a3c 2f61 3e0a 3c61 2068 7265 an">.</a>.<a.hre
- 0x14b0: 663d 2268 7474 703a 2f2f 7777 772e 6170 f="http://www.ap
- 0x14c0: 6163 6865 2e6f 7267 2f22 3e0a 3c49 4d47 ache.org/">.<IMG
- 0x14d0: 2061 6c69 676e 3d22 6d69 6464 6c65 2220 .align="middle".
- 0x14e0: 6865 6967 6874 3d22 3332 2220 7769 6474 height="32".widt
- 0x14f0: 683d 2232 3539 2220 7372 633d 2269 636f h="259".src="ico
- 0x1500: 6e73 2f61 7061 6368 655f 7062 2e70 6e67 ns/apache_pb.png
- 0x1510: 2220 616c 743d 2241 7061 6368 6522 3e0a ".alt="Apache">.
- 0x1520: 3c2f 613e 0a3c 2f44 4956 3e0a 0a3c 212d </a>.</DIV>..<!-
- 0x1530: 2d0a 2020 5468 6973 2070 6167 6520 7761 -...This.page.wa
- 0x1540: 7320 696e 6974 6961 6c6c 7920 6372 6561 s.initially.crea
- 0x1550: 7465 6420 6279 204a 6f68 6e69 6520 496e ted.by.Johnie.In
- 0x1560: 6772 616d 2028 6874 7470 3a2f 2f6e 6574 gram.(http://net
- 0x1570: 676f 642e 6e65 742f 290a 2020 4974 2077 god.net/)...It.w
- 0x1580: 6173 206c 6174 6572 2065 6469 7465 6420 as.later.edited.
- 0x1590: 6279 204d 6174 7468 6577 2057 696c 636f by.Matthew.Wilco
- 0x15a0: 7820 616e 6420 4a6f 7369 7020 526f 6469 x.and.Josip.Rodi
- 0x15b0: 6e2e 0a20 204c 6173 7420 6d6f 6469 6669 n....Last.modifi
- 0x15c0: 6564 3a20 2444 6174 653a 2032 3030 342f ed:.$Date:.2004/
- 0x15d0: 3036 2f32 3020 3135 3a33 333a 3537 2024 06/20.15:33:57.$
- 0x15e0: 2e0a 2020 2d2d 3e0a 0a3c 2f42 4f44 593e ....-->..</BODY>
- 0x15f0: 0a3c 2f48 544d 4c3e 0a .</HTML>.
-23:57:35.941260 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5560 win 12383 <nop,nop,timestamp 1306300953 1306300953>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1b6e 4000 4006 2154 7f00 0001 7f00 .4.n@.@.!T......
- 0x0020: 0001 da70 0050 3758 8a49 377a a3a9 8010 ...p.P7X.I7z....
- 0x0030: 305f 10ea 0000 0101 080a 4ddc 9219 4ddc 0_........M...M.
- 0x0040: 9219 ..
-23:57:37.229575 IP 127.0.0.1.55920 > 127.0.0.1.80: F 203:203(0) ack 5560 win 12383 <nop,nop,timestamp 1306302241 1306300953>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1b70 4000 4006 2152 7f00 0001 7f00 .4.p@.@.!R......
- 0x0020: 0001 da70 0050 3758 8a49 377a a3a9 8011 ...p.P7X.I7z....
- 0x0030: 305f 0be1 0000 0101 080a 4ddc 9721 4ddc 0_........M..!M.
- 0x0040: 9219 ..
-23:57:37.230839 IP 127.0.0.1.80 > 127.0.0.1.55920: F 5560:5560(0) ack 204 win 8192 <nop,nop,timestamp 1306302243 1306302241>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1fe8 4000 4006 1cda 7f00 0001 7f00 .4..@.@.........
- 0x0020: 0001 0050 da70 377a a3a9 3758 8a4a 8011 ...P.p7z..7X.J..
- 0x0030: 2000 1735 0000 0101 080a 4ddc 9723 4ddc ...5......M..#M.
- 0x0040: 9721 .!
-23:57:37.230900 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5561 win 12383 <nop,nop,timestamp 1306302243 1306302243>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500 ..............E.
- 0x0010: 0034 1b72 4000 4006 2150 7f00 0001 7f00 .4.r@.@.!P......
- 0x0020: 0001 da70 0050 3758 8a4a 377a a3aa 8010 ...p.P7X.J7z....
- 0x0030: 305f 06d4 0000 0101 080a 4ddc 9723 4ddc 0_........M..#M.
- 0x0040: 9723 .#
diff --git a/contrib/tcpdump/tests/print-flags.puu b/contrib/tcpdump/tests/print-flags.puu
deleted file mode 100644
index bcd8b99..0000000
--- a/contrib/tcpdump/tests/print-flags.puu
+++ /dev/null
@@ -1,151 +0,0 @@
-begin 644 print-flags.pcap
-MU,.RH0(`!````````````/__```!````KU;+0E)0#@!*````2@``````````
-M``````````@`10``/!MH0`!`!B%2?P```7\```':<`!0-UB)?@````"@`G__
-M%"$```($0`P$`@@*3=R2%@`````!`P,"KU;+0HI0#@!*````2@``````````
-M``````````@`10``/```0`!`!CRZ?P```7\```$`4-IP-WJ-\3=8B7^@$G__
-M;K$```($0`P$`@@*3=R2%DW<DA8!`P,"KU;+0K=0#@!"````0@``````````
-M``````````@`10``-!MJ0`!`!B%8?P```7\```':<`!0-UB)?S=ZC?*`$"``
-M-]````$!"`I-W)(63=R2%J]6RT*?50X`#`$```P!```````````````````(
-M`$4``/X;;$``0`8@C'\```%_```!VG``4#=8B7\W>HWR@!@@`/[R```!`0@*
-M3=R2%TW<DA9'150@+R!(5%10+S$N,0T*2&]S=#H@;&]C86QH;W-T#0I5<V5R
-M+4%G96YT.B!%3&EN:W,O,"XQ,"XT+3<M9&5B:6%N("AT97AT;6]D93L@3&EN
-M=7@@,BXV+C$Q+3$M-C@V+7-M<"!I-C@V.R`Q,S)X-38M,BD-"D%C8V5P=#H@
-M*B\J#0I!8V-E<'0M16YC;V1I;F<Z(&=Z:7`-"D%C8V5P="U,86YG=6%G93H@
-M96X-"D-O;FYE8W1I;VXZ($ME97`M06QI=F4-"@T*KU;+0KI9#@!"````0@``
-M``````````````````@`10``-!_D0`!`!AS>?P```7\```$`4-IP-WJ-\C=8
-MBDF`$"``-P,```$!"`I-W)(83=R2%Z]6RT*P7`X`^14``/D5````````````
-M```````(`$4`%>L?YD``0`8')7\```%_```!`%#:<#=ZC?(W6(I)@!@@`!/@
-M```!`0@*3=R2&4W<DA=(5%10+S$N,2`R,#`@3TL-"D1A=&4Z(%=E9"P@,#8@
-M2G5L(#(P,#4@,#,Z-3<Z,S4@1TU4#0I397)V97(Z($%P86-H92\Q+C,N,S,-
-M"DQA<W0M36]D:69I960Z(%-U;BP@,34@075G(#(P,#0@,#`Z-#,Z-#$@1TU4
-M#0I%5&%G.B`B-F4X,&8P+3$T.&$M-#$Q96(Q8F0B#0I!8V-E<'0M4F%N9V5S
-M.B!B>71E<PT*0V]N=&5N="U,96YG=&@Z(#4R-3@-"DME97`M06QI=F4Z('1I
-M;65O=70],34L(&UA>#TQ,#`-"D-O;FYE8W1I;VXZ($ME97`M06QI=F4-"D-O
-M;G1E;G0M5'EP93H@=&5X="]H=&UL.R!C:&%R<V5T/6ES;RTX.#4Y+3$-"@T*
-M/"%$3T-465!%($A434P@4%5"3$E#("(M+R]7,T,O+T141"!(5$U,(#0N,#$@
-M5')A;G-I=&EO;F%L+R]%3B(^"CQ(5$U,/@H\2$5!1#X*("`@/$U%5$$@2%14
-M4"U%455)5CTB0V]N=&5N="U4>7!E(B!#3TY414Y4/2)T97AT+VAT;6P[(&-H
-M87)S970]:7-O+3@X-3DM,2(^"B`@(#Q-151!($Y!344](D1E<V-R:7!T:6]N
-M(B!#3TY414Y4/2)4:&4@:6YI=&EA;"!I;G-T86QL871I;VX@;V8@1&5B:6%N
-M(&%P86-H92XB/@H@("`\5$E43$4^4&QA8V5H;VQD97(@<&%G93PO5$E43$4^
-M"CPO2$5!1#X*/$)/1%D@5$585#TB(S`P,#`P,"(@0D=#3TQ/4CTB(T9&1D9&
-M1B(@3$E.2STB(S`P,#!%1B(@5DQ)3DL](B,U-3$X.$$B($%,24Y+/2(C1D8P
-M,#`P(CX*"CQ(,3Y0;&%C96AO;&1E<B!P86=E/"](,3X*/$@R/DEF('EO=2!A
-M<F4@:G5S="!B<F]W<VEN9R!T:&4@=V5B/"]H,CX*"CQ0/E1H92!O=VYE<B!O
-M9B!T:&ES('=E8B!S:71E(&AA<R!N;W0@<'5T('5P(&%N>2!W96(@<&%G97,@
-M>65T+@I0;&5A<V4@8V]M92!B86-K(&QA=&5R+CPO4#X*"CQ0/CQ334%,3#X\
-M0TE413Y-;W9E(&%L;VYG+"!N;W1H:6YG('1O('-E92!H97)E+BXN/"]#251%
-M/B`Z+2D\+U--04Q,/CPO4#X*"CQ(,CY)9B!Y;W4@87)E('1R>6EN9R!T;R!L
-M;V-A=&4@=&AE(&%D;6EN:7-T<F%T;W(@;V8@=&AI<R!M86-H:6YE/"](,CX*
-M"CQ0/DEF('EO=2!W86YT('1O(')E<&]R="!S;VUE=&AI;F<@86)O=70@=&AI
-M<R!H;W-T)W,@8F5H879I;W(L('!L96%S90IC;VYT86-T('1H92!);G1E<FYE
-M="!397)V:6-E(%!R;W9I9&5R("A)4U`I(&EN=F]L=F5D(&1I<F5C=&QY+CPO
-M4#X*"CQ0/E-E92!T:&4@/$$@:')E9CTB:'1T<#HO+W=W=RYA8G5S92YN970O
-M(CY.971W;W)K($%B=7-E"D-L96%R:6YG:&]U<V4\+T$^(&9O<B!H;W<@=&\@
-M9&\@=&AI<RX\+U`^"@H\2#(^268@>6]U(&%R92!T:&4@861M:6YI<W1R871O
-M<B!O9B!T:&ES(&UA8VAI;F4\+T@R/@H*/%`^5&AE(&EN:71I86P@:6YS=&%L
-M;&%T:6]N(&]F(#Q!(&AR968](FAT='`Z+R]W=W<N9&5B:6%N+F]R9R\B/D1E
-M8FEA;B=S"F%P86-H93PO03X@=V5B('-E<G9E<B!P86-K86=E('=A<R!S=6-C
-M97-S9G5L+CPO4#X*"CQ0/CQ35%)/3D<^66]U('-H;W5L9"!R97!L86-E('1H
-M:7,@<&%G92!W:71H('EO=7(@;W=N('=E8B!P86=E<R!A<PIS;V]N(&%S('!O
-M<W-I8FQE+CPO4U123TY'/CPO4#X*"CQ0/E5N;&5S<R!Y;W4@8VAA;F=E9"!I
-M=',@8V]N9FEG=7)A=&EO;BP@>6]U<B!N97<@<V5R=F5R(&ES(&-O;F9I9W5R
-M960@87,@9F]L;&]W<SH*/%5,/@H\3$D^"D-O;F9I9W5R871I;VX@9FEL97,@
-M8V%N(&)E(&9O=6YD(&EN(#Q45#XO971C+V%P86-H93PO5%0^+CPO3$D^"@H\
-M3$D^"E1H92`\5%0^1&]C=6UE;G12;V]T/"]45#XL('=H:6-H(&ES('1H92!D
-M:7)E8W1O<GD@=6YD97(@=VAI8V@@86QL('EO=7(*2%1-3"!F:6QE<R!S:&]U
-M;&0@97AI<W0L(&ES('-E="!T;R`\5%0^+W9A<B]W=W<\+U14/BX\+TQ)/@H*
-M/$Q)/@I#1TD@<V-R:7!T<R!A<F4@;&]O:V5D(&9O<B!I;B`\5%0^+W5S<B]L
-M:6(O8V=I+6)I;CPO5%0^+"!W:&EC:"!I<R!W:&5R90I$96)I86X@<&%C:V%G
-M97,@=VEL;"!P;&%C92!T:&5I<B!S8W)I<'1S+CPO3$D^"@H\3$D^"DQO9R!F
-M:6QE<R!A<F4@<&QA8V5D(&EN(#Q45#XO=F%R+VQO9R]A<&%C:&4\+U14/BP@
-M86YD('=I;&P@8F4@<F]T871E9`IW965K;'DN("!4:&4@9G)E<75E;F-Y(&]F
-M(')O=&%T:6]N(&-A;B!B92!E87-I;'D@8VAA;F=E9"!B>2!E9&ET:6YG"CQ4
-M5#XO971C+VQO9W)O=&%T92YD+V%P86-H93PO5%0^+CPO3$D^"@H\3$D^"E1H
-M92!D969A=6QT(&1I<F5C=&]R>2!I;F1E>"!I<R`\5%0^:6YD97@N:'1M;#PO
-M5%0^+"!M96%N:6YG('1H870@<F5Q=65S=',*9F]R(&$@9&ER96-T;W)Y(#Q4
-M5#XO9F]O+V)A<B\\+U14/B!W:6QL(&=I=F4@=&AE(&-O;G1E;G1S(&]F('1H
-M92!F:6QE(#Q45#XO=F%R+W=W=R]F;V\O8F%R+VEN9&5X+FAT;6P\+U14/@II
-M9B!I="!E>&ES=',@*&%S<W5M:6YG('1H870@/%14/B]V87(O=W=W/"]45#X@
-M:7,@>6]U<B`\5%0^1&]C=6UE;G12;V]T/"]45#XI+CPO3$D^"@H\3$D^"E5S
-M97(@9&ER96-T;W)I97,@87)E(&5N86)L960L(&%N9"!U<V5R(&1O8W5M96YT
-M<R!W:6QL(&)E(&QO;VME9"!F;W(*:6X@=&AE(#Q45#YP=6)L:6-?:'1M;#PO
-M5%0^(&1I<F5C=&]R>2!O9B!T:&4@=7-E<G,G(&AO;65S+B`@5&AE<V4@9&ER
-M<PIS:&]U;&0@8F4@=6YD97(@/%14/B]H;VUE/"]45#XL(&%N9"!U<V5R<R!W
-M:6QL(&YO="!B92!A8FQE('1O('-Y;6QI;FL*=&\@9FEL97,@=&AE>2!D;VXG
-M="!O=VXN/"],23X*"CPO54P^"D%L;"!T:&4@<W1A;F1A<F0@87!A8VAE(&UO
-M9'5L97,@87)E(&%V86EL86)L92!W:71H('1H:7,@<F5L96%S92!A;F0@87)E
-M"FYO=R!M86YA9V5D('=I=&@@9&5B8V]N9BX@(%1Y<&4@/%14/F1P:V<M<F5C
-M;VYF:6=U<F4@87!A8VAE/"]45#X@=&\*<V5L96-T('=H:6-H(&UO9'5L97,@
-M>6]U('=A;G0@96YA8FQE9"X@($UA;GD@;W1H97(@;6]D=6QE<R!A<F4@879A
-M:6QA8FQE"G1H<F]U9V@@=&AE($1E8FEA;B!P86-K86=E('-Y<W1E;2!W:71H
-M('1H92!N86UE<R`\5%0^;&EB87!A8VAE+6UO9"TJ/"]45#XN"DEF('EO=2!N
-M965D('1O(&-O;7!I;&4@82!M;V1U;&4@>6]U<G-E;&8L('EO=2!W:6QL(&YE
-M960@=&\@:6YS=&%L;"!T:&4*/%14/F%P86-H92UD978\+U14/B!P86-K86=E
-M+@H*/%`^36]R92!D;V-U;65N=&%T:6]N(&]N($%P86-H92!C86X@8F4@9F]U
-M;F0@;VXZ"CQ53#X*/$Q)/@I4:&4@/$$@2%)%1CTB+V1O8R]A<&%C:&4M9&]C
-M+VUA;G5A;"\B/D%P86-H92!D;V-U;65N=&%T:6]N/"]!/B!S=&]R960@;VX@
-M>6]U<B!S97)V97(N/"],23X*"CQ,23X*5&AE(#Q!($A2148](FAT='`Z+R]W
-M=W<N87!A8VAE+F]R9R\B/D%P86-H92!0<F]J96-T/"]!/B!H;VUE('-I=&4N
-M/"],23X*"CQ,23X*5&AE(#Q!($A2148](FAT='`Z+R]W=W<N87!A8VAE+7-S
-M;"YO<F<O(CY!<&%C:&4M4U-,/"]!/B!H;VUE('-I=&4N/"],23X*"CQ,23X*
-M5&AE(#Q!($A2148](FAT='`Z+R]P97)L+F%P86-H92YO<F<O(CYM;V0@<&5R
-M;#PO03X@:&]M92!S:71E+CPO3$D^"@H\3$D^"E1H92`\02!(4D5&/2)H='1P
-M.B\O=W=W+F%P86-H97=E96LN8V]M+R(^07!A8VAE5V5E:SPO03X@;F5W<VQE
-M='1E<BX\+TQ)/@H*/$Q)/@I4:&4@/$$@2%)%1CTB:'1T<#HO+W=W=RYD96)I
-M86XN;W)G+V1O8R\B/D1E8FEA;B!0<F]J96-T"D1O8W5M96YT871I;VX\+T$^
-M('=H:6-H(&-O;G1A:6YS($A/5U1/<RP@1D%1<RP@86YD('-O9G1W87)E('5P
-M9&%T97,N/"],23X*/"]53#X*"CQ0/EEO=2!C86X@86QS;R!C;VYS=6QT('1H
-M92!L:7-T(&]F(#Q!($A2148](FAT='`Z+R]W=W<N8F]U=&5L;"YC;VTO9F%Q
-M+R(^5V]R;&0*5VED92!796(@1G)E<75E;G1L>2!!<VME9"!1=65S=&EO;G,\
-M+T$^(&9O<B!I;F9O<FUA=&EO;BX*"CQ(,CY,970@;W1H97(@<&5O<&QE(&MN
-M;W<@86)O=70@=&AI<R!S97)V97(\+T@R/@H*/$$@2%)%1CTB:'1T<#HO+VYE
-M=&-R869T+F-O;2\B/DYE=&-R869T/"]!/B!P<F]V:61E<R!A;B!I;G1E<F5S
-M=&EN9R!F<F5E"G-E<G9I8V4@9F]R('=E8B!S:71E(&UO;FET;W)I;F<@86YD
-M('-T871I<W1I8R!C;VQL96-T:6]N+@I9;W4@8V%N(&QE="!T:&5M(&MN;W<@
-M86)O=70@>6]U<B!S97)V97(@=7-I;F<@=&AE:7(*/$$@2%)%1CTB:'1T<#HO
-M+W5P=&EM92YN971C<F%F="YC;VTO(CYI;G1E<F9A8V4\+T$^+@I%;F%B;&EN
-M9R!T:&4@;6]N:71O<FEN9R!O9B!Y;W5R('-E<G9E<B!W:6QL('!R;W9I9&4@
-M82!B971T97(@9VQO8F%L(&]V97)V:65W"F]F('=H;R!I<R!U<VEN9R!W:&%T
-M(&%N9"!W:&5R92P@86YD(&ET('=O=6QD(&=I=F4@1&5B:6%N(&$@8F5T=&5R
-M"F]V97)V:65W(&]F('1H92!A<&%C:&4@<&%C:V%G92!U<V%G92X*"CQ(,CY!
-M8F]U="!T:&ES('!A9V4\+T@R/@H*/$E-1R!!3$E'3CTB<FEG:'0B($%,5#TB
-M(B!(14E'2%0](C(T-R(@5TE$5$@](C(W."(@4U)#/2)I8V]N<R]J:&4P-C$N
-M<&YG(CX*"CQ0/E1H:7,@:7,@82!P;&%C96AO;&1E<B!P86=E(&EN<W1A;&QE
-M9"!B>2!T:&4@/$$*2%)%1CTB:'1T<#HO+W=W=RYD96)I86XN;W)G+R(^1&5B
-M:6%N/"]!/@IR96QE87-E(&]F('1H92!A<&%C:&4@5V5B('-E<G9E<B!P86-K
-M86=E+@H*/%`^5&AI<R!C;VUP=71E<B!H87,@:6YS=&%L;&5D('1H92!$96)I
-M86X@1TY5+TQI;G5X(&]P97)A=&EN9R!S>7-T96TL"F)U="!I="!H87,@/'-T
-M<F]N9SYN;W1H:6YG('1O(&1O('=I=&@@=&AE($1E8FEA;@I0<F]J96-T/"]S
-M=')O;F<^+B!0;&5A<V4@9&\@/'-T<F]N9SYN;W0\+W-T<F]N9SX@8V]N=&%C
-M="!T:&4@1&5B:6%N"E!R;VIE8W0@86)O=70@:70N/"]0/@H*/%`^268@>6]U
-M(&9I;F0@82!B=6<@:6X@=&AI<R!A<&%C:&4@<&%C:V%G92P@;W(@:6X@07!A
-M8VAE(&ET<V5L9BP*<&QE87-E(&9I;&4@82!B=6<@<F5P;W)T(&]N(&ET+B`@
-M26YS=')U8W1I;VYS(&]N(&1O:6YG('1H:7,L(&%N9"!T:&4*;&ES="!O9B`\
-M02!(4D5&/2)H='1P.B\O8G5G<RYD96)I86XN;W)G+W-R8SIA<&%C:&4B/FMN
-M;W=N(&)U9W,\+T$^(&]F('1H:7,*<&%C:V%G92P@8V%N(&)E(&9O=6YD(&EN
-M('1H92`*/$$@2%)%1CTB:'1T<#HO+W=W=RYD96)I86XN;W)G+T)U9W,O4F5P
-M;W)T:6YG(CY$96)I86X@0G5G(%1R86-K:6YG(%-Y<W1E;3PO03XN"@H\4#Y4
-M:&%N:W,@9F]R('5S:6YG('1H:7,@<&%C:V%G92P@86YD(&-O;F=R871U;&%T
-M:6]N<R!F;W(@>6]U<B!C:&]I8V4@;V8*82!$96)I86X@<WES=&5M(3PO4#X*
-M"CQ$258@86QI9VX](F-E;G1E<B(^"CQA(&AR968](FAT='`Z+R]W=W<N9&5B
-M:6%N+F]R9R\B/@H\24U'(&%L:6=N/2)M:61D;&4B(&AE:6=H=#TB,S`B('=I
-M9'1H/2(R-2(@<W)C/2)I8V]N<R]D96)I86XO;W!E;FQO9V\M,C4N:G!G(B!A
-M;'0](D1E8FEA;B(^"CPO83X*/&$@:')E9CTB:'1T<#HO+W=W=RYA<&%C:&4N
-M;W)G+R(^"CQ)34<@86QI9VX](FUI9&1L92(@:&5I9VAT/2(S,B(@=VED=&@]
-M(C(U.2(@<W)C/2)I8V]N<R]A<&%C:&5?<&(N<&YG(B!A;'0](D%P86-H92(^
-M"CPO83X*/"]$258^"@H\(2TM"B`@5&AI<R!P86=E('=A<R!I;FET:6%L;'D@
-M8W)E871E9"!B>2!*;VAN:64@26YG<F%M("AH='1P.B\O;F5T9V]D+FYE="\I
-M"B`@270@=V%S(&QA=&5R(&5D:71E9"!B>2!-871T:&5W(%=I;&-O>"!A;F0@
-M2F]S:7`@4F]D:6XN"B`@3&%S="!M;V1I9FEE9#H@)$1A=&4Z(#(P,#0O,#8O
-M,C`@,34Z,S,Z-3<@)"X*("`M+3X*"CPO0D]$63X*/"](5$U,/@JO5LM"S%P.
-M`$(```!"````````````````````"`!%```T&VY``$`&(51_```!?P```=IP
-M`%`W6(I)-WJCJ8`0,%\0Z@```0$("DW<DAE-W)(9L5;+0L>``P!"````0@``
-M``````````````````@`10``-!MP0`!`!B%2?P```7\```':<`!0-UB*23=Z
-MHZF`$3!?"^$```$!"`I-W)<A3=R2&;%6RT*WA0,`0@```$(`````````````
-M```````(`$4``#0?Z$``0`8<VG\```%_```!`%#:<#=ZHZDW6(I*@!$@`!<U
-M```!`0@*3=R7(TW<ER&Q5LM"](4#`$(```!"````````````````````"`!%
-M```T&W)``$`&(5!_```!?P```=IP`%`W6(I*-WJCJH`0,%\&U````0$("DW<
-&ER--W)<C
-`
-end
diff --git a/contrib/tcpdump/tests/print-flags.sh b/contrib/tcpdump/tests/print-flags.sh
deleted file mode 100755
index c99f782..0000000
--- a/contrib/tcpdump/tests/print-flags.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-uudecode print-flags.puu
-
-for i in x xx X XX A AA; do
- if (../tcpdump -$i -s0 -nr print-flags.pcap | tee print-$i.new | diff - print-$i.out)
- then
- echo print-$i passed.
- else
- echo print-$i failed.
- fi
-done
diff --git a/contrib/tcpdump/tests/print-x.out b/contrib/tcpdump/tests/print-x.out
deleted file mode 100644
index 0b25bf6..0000000
--- a/contrib/tcpdump/tests/print-x.out
+++ /dev/null
@@ -1,409 +0,0 @@
-23:57:35.938066 IP 127.0.0.1.55920 > 127.0.0.1.80: S 928549246:928549246(0) win 32767 <mss 16396,sackOK,timestamp 1306300950 0,nop,wscale 2>
- 0x0000: 4500 003c 1b68 4000 4006 2152 7f00 0001
- 0x0010: 7f00 0001 da70 0050 3758 897e 0000 0000
- 0x0020: a002 7fff 1421 0000 0204 400c 0402 080a
- 0x0030: 4ddc 9216 0000 0000 0103 0302
-23:57:35.938122 IP 127.0.0.1.80 > 127.0.0.1.55920: S 930778609:930778609(0) ack 928549247 win 32767 <mss 16396,sackOK,timestamp 1306300950 1306300950,nop,wscale 2>
- 0x0000: 4500 003c 0000 4000 4006 3cba 7f00 0001
- 0x0010: 7f00 0001 0050 da70 377a 8df1 3758 897f
- 0x0020: a012 7fff 6eb1 0000 0204 400c 0402 080a
- 0x0030: 4ddc 9216 4ddc 9216 0103 0302
-23:57:35.938167 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 1 win 8192 <nop,nop,timestamp 1306300950 1306300950>
- 0x0000: 4500 0034 1b6a 4000 4006 2158 7f00 0001
- 0x0010: 7f00 0001 da70 0050 3758 897f 377a 8df2
- 0x0020: 8010 2000 37d0 0000 0101 080a 4ddc 9216
- 0x0030: 4ddc 9216
-23:57:35.939423 IP 127.0.0.1.55920 > 127.0.0.1.80: P 1:203(202) ack 1 win 8192 <nop,nop,timestamp 1306300951 1306300950>
- 0x0000: 4500 00fe 1b6c 4000 4006 208c 7f00 0001
- 0x0010: 7f00 0001 da70 0050 3758 897f 377a 8df2
- 0x0020: 8018 2000 fef2 0000 0101 080a 4ddc 9217
- 0x0030: 4ddc 9216 4745 5420 2f20 4854 5450 2f31
- 0x0040: 2e31 0d0a 486f 7374 3a20 6c6f 6361 6c68
- 0x0050: 6f73 740d 0a55 7365 722d 4167 656e 743a
- 0x0060: 2045 4c69 6e6b 732f 302e 3130 2e34 2d37
- 0x0070: 2d64 6562 6961 6e20 2874 6578 746d 6f64
- 0x0080: 653b 204c 696e 7578 2032 2e36 2e31 312d
- 0x0090: 312d 3638 362d 736d 7020 6936 3836 3b20
- 0x00a0: 3133 3278 3536 2d32 290d 0a41 6363 6570
- 0x00b0: 743a 202a 2f2a 0d0a 4163 6365 7074 2d45
- 0x00c0: 6e63 6f64 696e 673a 2067 7a69 700d 0a41
- 0x00d0: 6363 6570 742d 4c61 6e67 7561 6765 3a20
- 0x00e0: 656e 0d0a 436f 6e6e 6563 7469 6f6e 3a20
- 0x00f0: 4b65 6570 2d41 6c69 7665 0d0a 0d0a
-23:57:35.940474 IP 127.0.0.1.80 > 127.0.0.1.55920: . ack 203 win 8192 <nop,nop,timestamp 1306300952 1306300951>
- 0x0000: 4500 0034 1fe4 4000 4006 1cde 7f00 0001
- 0x0010: 7f00 0001 0050 da70 377a 8df2 3758 8a49
- 0x0020: 8010 2000 3703 0000 0101 080a 4ddc 9218
- 0x0030: 4ddc 9217
-23:57:35.941232 IP 127.0.0.1.80 > 127.0.0.1.55920: P 1:5560(5559) ack 203 win 8192 <nop,nop,timestamp 1306300953 1306300951>
- 0x0000: 4500 15eb 1fe6 4000 4006 0725 7f00 0001
- 0x0010: 7f00 0001 0050 da70 377a 8df2 3758 8a49
- 0x0020: 8018 2000 13e0 0000 0101 080a 4ddc 9219
- 0x0030: 4ddc 9217 4854 5450 2f31 2e31 2032 3030
- 0x0040: 204f 4b0d 0a44 6174 653a 2057 6564 2c20
- 0x0050: 3036 204a 756c 2032 3030 3520 3033 3a35
- 0x0060: 373a 3335 2047 4d54 0d0a 5365 7276 6572
- 0x0070: 3a20 4170 6163 6865 2f31 2e33 2e33 330d
- 0x0080: 0a4c 6173 742d 4d6f 6469 6669 6564 3a20
- 0x0090: 5375 6e2c 2031 3520 4175 6720 3230 3034
- 0x00a0: 2030 303a 3433 3a34 3120 474d 540d 0a45
- 0x00b0: 5461 673a 2022 3665 3830 6630 2d31 3438
- 0x00c0: 612d 3431 3165 6231 6264 220d 0a41 6363
- 0x00d0: 6570 742d 5261 6e67 6573 3a20 6279 7465
- 0x00e0: 730d 0a43 6f6e 7465 6e74 2d4c 656e 6774
- 0x00f0: 683a 2035 3235 380d 0a4b 6565 702d 416c
- 0x0100: 6976 653a 2074 696d 656f 7574 3d31 352c
- 0x0110: 206d 6178 3d31 3030 0d0a 436f 6e6e 6563
- 0x0120: 7469 6f6e 3a20 4b65 6570 2d41 6c69 7665
- 0x0130: 0d0a 436f 6e74 656e 742d 5479 7065 3a20
- 0x0140: 7465 7874 2f68 746d 6c3b 2063 6861 7273
- 0x0150: 6574 3d69 736f 2d38 3835 392d 310d 0a0d
- 0x0160: 0a3c 2144 4f43 5459 5045 2048 544d 4c20
- 0x0170: 5055 424c 4943 2022 2d2f 2f57 3343 2f2f
- 0x0180: 4454 4420 4854 4d4c 2034 2e30 3120 5472
- 0x0190: 616e 7369 7469 6f6e 616c 2f2f 454e 223e
- 0x01a0: 0a3c 4854 4d4c 3e0a 3c48 4541 443e 0a20
- 0x01b0: 2020 3c4d 4554 4120 4854 5450 2d45 5155
- 0x01c0: 4956 3d22 436f 6e74 656e 742d 5479 7065
- 0x01d0: 2220 434f 4e54 454e 543d 2274 6578 742f
- 0x01e0: 6874 6d6c 3b20 6368 6172 7365 743d 6973
- 0x01f0: 6f2d 3838 3539 2d31 223e 0a20 2020 3c4d
- 0x0200: 4554 4120 4e41 4d45 3d22 4465 7363 7269
- 0x0210: 7074 696f 6e22 2043 4f4e 5445 4e54 3d22
- 0x0220: 5468 6520 696e 6974 6961 6c20 696e 7374
- 0x0230: 616c 6c61 7469 6f6e 206f 6620 4465 6269
- 0x0240: 616e 2061 7061 6368 652e 223e 0a20 2020
- 0x0250: 3c54 4954 4c45 3e50 6c61 6365 686f 6c64
- 0x0260: 6572 2070 6167 653c 2f54 4954 4c45 3e0a
- 0x0270: 3c2f 4845 4144 3e0a 3c42 4f44 5920 5445
- 0x0280: 5854 3d22 2330 3030 3030 3022 2042 4743
- 0x0290: 4f4c 4f52 3d22 2346 4646 4646 4622 204c
- 0x02a0: 494e 4b3d 2223 3030 3030 4546 2220 564c
- 0x02b0: 494e 4b3d 2223 3535 3138 3841 2220 414c
- 0x02c0: 494e 4b3d 2223 4646 3030 3030 223e 0a0a
- 0x02d0: 3c48 313e 506c 6163 6568 6f6c 6465 7220
- 0x02e0: 7061 6765 3c2f 4831 3e0a 3c48 323e 4966
- 0x02f0: 2079 6f75 2061 7265 206a 7573 7420 6272
- 0x0300: 6f77 7369 6e67 2074 6865 2077 6562 3c2f
- 0x0310: 6832 3e0a 0a3c 503e 5468 6520 6f77 6e65
- 0x0320: 7220 6f66 2074 6869 7320 7765 6220 7369
- 0x0330: 7465 2068 6173 206e 6f74 2070 7574 2075
- 0x0340: 7020 616e 7920 7765 6220 7061 6765 7320
- 0x0350: 7965 742e 0a50 6c65 6173 6520 636f 6d65
- 0x0360: 2062 6163 6b20 6c61 7465 722e 3c2f 503e
- 0x0370: 0a0a 3c50 3e3c 534d 414c 4c3e 3c43 4954
- 0x0380: 453e 4d6f 7665 2061 6c6f 6e67 2c20 6e6f
- 0x0390: 7468 696e 6720 746f 2073 6565 2068 6572
- 0x03a0: 652e 2e2e 3c2f 4349 5445 3e20 3a2d 293c
- 0x03b0: 2f53 4d41 4c4c 3e3c 2f50 3e0a 0a3c 4832
- 0x03c0: 3e49 6620 796f 7520 6172 6520 7472 7969
- 0x03d0: 6e67 2074 6f20 6c6f 6361 7465 2074 6865
- 0x03e0: 2061 646d 696e 6973 7472 6174 6f72 206f
- 0x03f0: 6620 7468 6973 206d 6163 6869 6e65 3c2f
- 0x0400: 4832 3e0a 0a3c 503e 4966 2079 6f75 2077
- 0x0410: 616e 7420 746f 2072 6570 6f72 7420 736f
- 0x0420: 6d65 7468 696e 6720 6162 6f75 7420 7468
- 0x0430: 6973 2068 6f73 7427 7320 6265 6861 7669
- 0x0440: 6f72 2c20 706c 6561 7365 0a63 6f6e 7461
- 0x0450: 6374 2074 6865 2049 6e74 6572 6e65 7420
- 0x0460: 5365 7276 6963 6520 5072 6f76 6964 6572
- 0x0470: 2028 4953 5029 2069 6e76 6f6c 7665 6420
- 0x0480: 6469 7265 6374 6c79 2e3c 2f50 3e0a 0a3c
- 0x0490: 503e 5365 6520 7468 6520 3c41 2068 7265
- 0x04a0: 663d 2268 7474 703a 2f2f 7777 772e 6162
- 0x04b0: 7573 652e 6e65 742f 223e 4e65 7477 6f72
- 0x04c0: 6b20 4162 7573 650a 436c 6561 7269 6e67
- 0x04d0: 686f 7573 653c 2f41 3e20 666f 7220 686f
- 0x04e0: 7720 746f 2064 6f20 7468 6973 2e3c 2f50
- 0x04f0: 3e0a 0a3c 4832 3e49 6620 796f 7520 6172
- 0x0500: 6520 7468 6520 6164 6d69 6e69 7374 7261
- 0x0510: 746f 7220 6f66 2074 6869 7320 6d61 6368
- 0x0520: 696e 653c 2f48 323e 0a0a 3c50 3e54 6865
- 0x0530: 2069 6e69 7469 616c 2069 6e73 7461 6c6c
- 0x0540: 6174 696f 6e20 6f66 203c 4120 6872 6566
- 0x0550: 3d22 6874 7470 3a2f 2f77 7777 2e64 6562
- 0x0560: 6961 6e2e 6f72 672f 223e 4465 6269 616e
- 0x0570: 2773 0a61 7061 6368 653c 2f41 3e20 7765
- 0x0580: 6220 7365 7276 6572 2070 6163 6b61 6765
- 0x0590: 2077 6173 2073 7563 6365 7373 6675 6c2e
- 0x05a0: 3c2f 503e 0a0a 3c50 3e3c 5354 524f 4e47
- 0x05b0: 3e59 6f75 2073 686f 756c 6420 7265 706c
- 0x05c0: 6163 6520 7468 6973 2070 6167 6520 7769
- 0x05d0: 7468 2079 6f75 7220 6f77 6e20 7765 6220
- 0x05e0: 7061 6765 7320 6173 0a73 6f6f 6e20 6173
- 0x05f0: 2070 6f73 7369 626c 652e 3c2f 5354 524f
- 0x0600: 4e47 3e3c 2f50 3e0a 0a3c 503e 556e 6c65
- 0x0610: 7373 2079 6f75 2063 6861 6e67 6564 2069
- 0x0620: 7473 2063 6f6e 6669 6775 7261 7469 6f6e
- 0x0630: 2c20 796f 7572 206e 6577 2073 6572 7665
- 0x0640: 7220 6973 2063 6f6e 6669 6775 7265 6420
- 0x0650: 6173 2066 6f6c 6c6f 7773 3a0a 3c55 4c3e
- 0x0660: 0a3c 4c49 3e0a 436f 6e66 6967 7572 6174
- 0x0670: 696f 6e20 6669 6c65 7320 6361 6e20 6265
- 0x0680: 2066 6f75 6e64 2069 6e20 3c54 543e 2f65
- 0x0690: 7463 2f61 7061 6368 653c 2f54 543e 2e3c
- 0x06a0: 2f4c 493e 0a0a 3c4c 493e 0a54 6865 203c
- 0x06b0: 5454 3e44 6f63 756d 656e 7452 6f6f 743c
- 0x06c0: 2f54 543e 2c20 7768 6963 6820 6973 2074
- 0x06d0: 6865 2064 6972 6563 746f 7279 2075 6e64
- 0x06e0: 6572 2077 6869 6368 2061 6c6c 2079 6f75
- 0x06f0: 720a 4854 4d4c 2066 696c 6573 2073 686f
- 0x0700: 756c 6420 6578 6973 742c 2069 7320 7365
- 0x0710: 7420 746f 203c 5454 3e2f 7661 722f 7777
- 0x0720: 773c 2f54 543e 2e3c 2f4c 493e 0a0a 3c4c
- 0x0730: 493e 0a43 4749 2073 6372 6970 7473 2061
- 0x0740: 7265 206c 6f6f 6b65 6420 666f 7220 696e
- 0x0750: 203c 5454 3e2f 7573 722f 6c69 622f 6367
- 0x0760: 692d 6269 6e3c 2f54 543e 2c20 7768 6963
- 0x0770: 6820 6973 2077 6865 7265 0a44 6562 6961
- 0x0780: 6e20 7061 636b 6167 6573 2077 696c 6c20
- 0x0790: 706c 6163 6520 7468 6569 7220 7363 7269
- 0x07a0: 7074 732e 3c2f 4c49 3e0a 0a3c 4c49 3e0a
- 0x07b0: 4c6f 6720 6669 6c65 7320 6172 6520 706c
- 0x07c0: 6163 6564 2069 6e20 3c54 543e 2f76 6172
- 0x07d0: 2f6c 6f67 2f61 7061 6368 653c 2f54 543e
- 0x07e0: 2c20 616e 6420 7769 6c6c 2062 6520 726f
- 0x07f0: 7461 7465 640a 7765 656b 6c79 2e20 2054
- 0x0800: 6865 2066 7265 7175 656e 6379 206f 6620
- 0x0810: 726f 7461 7469 6f6e 2063 616e 2062 6520
- 0x0820: 6561 7369 6c79 2063 6861 6e67 6564 2062
- 0x0830: 7920 6564 6974 696e 670a 3c54 543e 2f65
- 0x0840: 7463 2f6c 6f67 726f 7461 7465 2e64 2f61
- 0x0850: 7061 6368 653c 2f54 543e 2e3c 2f4c 493e
- 0x0860: 0a0a 3c4c 493e 0a54 6865 2064 6566 6175
- 0x0870: 6c74 2064 6972 6563 746f 7279 2069 6e64
- 0x0880: 6578 2069 7320 3c54 543e 696e 6465 782e
- 0x0890: 6874 6d6c 3c2f 5454 3e2c 206d 6561 6e69
- 0x08a0: 6e67 2074 6861 7420 7265 7175 6573 7473
- 0x08b0: 0a66 6f72 2061 2064 6972 6563 746f 7279
- 0x08c0: 203c 5454 3e2f 666f 6f2f 6261 722f 3c2f
- 0x08d0: 5454 3e20 7769 6c6c 2067 6976 6520 7468
- 0x08e0: 6520 636f 6e74 656e 7473 206f 6620 7468
- 0x08f0: 6520 6669 6c65 203c 5454 3e2f 7661 722f
- 0x0900: 7777 772f 666f 6f2f 6261 722f 696e 6465
- 0x0910: 782e 6874 6d6c 3c2f 5454 3e0a 6966 2069
- 0x0920: 7420 6578 6973 7473 2028 6173 7375 6d69
- 0x0930: 6e67 2074 6861 7420 3c54 543e 2f76 6172
- 0x0940: 2f77 7777 3c2f 5454 3e20 6973 2079 6f75
- 0x0950: 7220 3c54 543e 446f 6375 6d65 6e74 526f
- 0x0960: 6f74 3c2f 5454 3e29 2e3c 2f4c 493e 0a0a
- 0x0970: 3c4c 493e 0a55 7365 7220 6469 7265 6374
- 0x0980: 6f72 6965 7320 6172 6520 656e 6162 6c65
- 0x0990: 642c 2061 6e64 2075 7365 7220 646f 6375
- 0x09a0: 6d65 6e74 7320 7769 6c6c 2062 6520 6c6f
- 0x09b0: 6f6b 6564 2066 6f72 0a69 6e20 7468 6520
- 0x09c0: 3c54 543e 7075 626c 6963 5f68 746d 6c3c
- 0x09d0: 2f54 543e 2064 6972 6563 746f 7279 206f
- 0x09e0: 6620 7468 6520 7573 6572 7327 2068 6f6d
- 0x09f0: 6573 2e20 2054 6865 7365 2064 6972 730a
- 0x0a00: 7368 6f75 6c64 2062 6520 756e 6465 7220
- 0x0a10: 3c54 543e 2f68 6f6d 653c 2f54 543e 2c20
- 0x0a20: 616e 6420 7573 6572 7320 7769 6c6c 206e
- 0x0a30: 6f74 2062 6520 6162 6c65 2074 6f20 7379
- 0x0a40: 6d6c 696e 6b0a 746f 2066 696c 6573 2074
- 0x0a50: 6865 7920 646f 6e27 7420 6f77 6e2e 3c2f
- 0x0a60: 4c49 3e0a 0a3c 2f55 4c3e 0a41 6c6c 2074
- 0x0a70: 6865 2073 7461 6e64 6172 6420 6170 6163
- 0x0a80: 6865 206d 6f64 756c 6573 2061 7265 2061
- 0x0a90: 7661 696c 6162 6c65 2077 6974 6820 7468
- 0x0aa0: 6973 2072 656c 6561 7365 2061 6e64 2061
- 0x0ab0: 7265 0a6e 6f77 206d 616e 6167 6564 2077
- 0x0ac0: 6974 6820 6465 6263 6f6e 662e 2020 5479
- 0x0ad0: 7065 203c 5454 3e64 706b 672d 7265 636f
- 0x0ae0: 6e66 6967 7572 6520 6170 6163 6865 3c2f
- 0x0af0: 5454 3e20 746f 0a73 656c 6563 7420 7768
- 0x0b00: 6963 6820 6d6f 6475 6c65 7320 796f 7520
- 0x0b10: 7761 6e74 2065 6e61 626c 6564 2e20 204d
- 0x0b20: 616e 7920 6f74 6865 7220 6d6f 6475 6c65
- 0x0b30: 7320 6172 6520 6176 6169 6c61 626c 650a
- 0x0b40: 7468 726f 7567 6820 7468 6520 4465 6269
- 0x0b50: 616e 2070 6163 6b61 6765 2073 7973 7465
- 0x0b60: 6d20 7769 7468 2074 6865 206e 616d 6573
- 0x0b70: 203c 5454 3e6c 6962 6170 6163 6865 2d6d
- 0x0b80: 6f64 2d2a 3c2f 5454 3e2e 0a49 6620 796f
- 0x0b90: 7520 6e65 6564 2074 6f20 636f 6d70 696c
- 0x0ba0: 6520 6120 6d6f 6475 6c65 2079 6f75 7273
- 0x0bb0: 656c 662c 2079 6f75 2077 696c 6c20 6e65
- 0x0bc0: 6564 2074 6f20 696e 7374 616c 6c20 7468
- 0x0bd0: 650a 3c54 543e 6170 6163 6865 2d64 6576
- 0x0be0: 3c2f 5454 3e20 7061 636b 6167 652e 0a0a
- 0x0bf0: 3c50 3e4d 6f72 6520 646f 6375 6d65 6e74
- 0x0c00: 6174 696f 6e20 6f6e 2041 7061 6368 6520
- 0x0c10: 6361 6e20 6265 2066 6f75 6e64 206f 6e3a
- 0x0c20: 0a3c 554c 3e0a 3c4c 493e 0a54 6865 203c
- 0x0c30: 4120 4852 4546 3d22 2f64 6f63 2f61 7061
- 0x0c40: 6368 652d 646f 632f 6d61 6e75 616c 2f22
- 0x0c50: 3e41 7061 6368 6520 646f 6375 6d65 6e74
- 0x0c60: 6174 696f 6e3c 2f41 3e20 7374 6f72 6564
- 0x0c70: 206f 6e20 796f 7572 2073 6572 7665 722e
- 0x0c80: 3c2f 4c49 3e0a 0a3c 4c49 3e0a 5468 6520
- 0x0c90: 3c41 2048 5245 463d 2268 7474 703a 2f2f
- 0x0ca0: 7777 772e 6170 6163 6865 2e6f 7267 2f22
- 0x0cb0: 3e41 7061 6368 6520 5072 6f6a 6563 743c
- 0x0cc0: 2f41 3e20 686f 6d65 2073 6974 652e 3c2f
- 0x0cd0: 4c49 3e0a 0a3c 4c49 3e0a 5468 6520 3c41
- 0x0ce0: 2048 5245 463d 2268 7474 703a 2f2f 7777
- 0x0cf0: 772e 6170 6163 6865 2d73 736c 2e6f 7267
- 0x0d00: 2f22 3e41 7061 6368 652d 5353 4c3c 2f41
- 0x0d10: 3e20 686f 6d65 2073 6974 652e 3c2f 4c49
- 0x0d20: 3e0a 0a3c 4c49 3e0a 5468 6520 3c41 2048
- 0x0d30: 5245 463d 2268 7474 703a 2f2f 7065 726c
- 0x0d40: 2e61 7061 6368 652e 6f72 672f 223e 6d6f
- 0x0d50: 6420 7065 726c 3c2f 413e 2068 6f6d 6520
- 0x0d60: 7369 7465 2e3c 2f4c 493e 0a0a 3c4c 493e
- 0x0d70: 0a54 6865 203c 4120 4852 4546 3d22 6874
- 0x0d80: 7470 3a2f 2f77 7777 2e61 7061 6368 6577
- 0x0d90: 6565 6b2e 636f 6d2f 223e 4170 6163 6865
- 0x0da0: 5765 656b 3c2f 413e 206e 6577 736c 6574
- 0x0db0: 7465 722e 3c2f 4c49 3e0a 0a3c 4c49 3e0a
- 0x0dc0: 5468 6520 3c41 2048 5245 463d 2268 7474
- 0x0dd0: 703a 2f2f 7777 772e 6465 6269 616e 2e6f
- 0x0de0: 7267 2f64 6f63 2f22 3e44 6562 6961 6e20
- 0x0df0: 5072 6f6a 6563 740a 446f 6375 6d65 6e74
- 0x0e00: 6174 696f 6e3c 2f41 3e20 7768 6963 6820
- 0x0e10: 636f 6e74 6169 6e73 2048 4f57 544f 732c
- 0x0e20: 2046 4151 732c 2061 6e64 2073 6f66 7477
- 0x0e30: 6172 6520 7570 6461 7465 732e 3c2f 4c49
- 0x0e40: 3e0a 3c2f 554c 3e0a 0a3c 503e 596f 7520
- 0x0e50: 6361 6e20 616c 736f 2063 6f6e 7375 6c74
- 0x0e60: 2074 6865 206c 6973 7420 6f66 203c 4120
- 0x0e70: 4852 4546 3d22 6874 7470 3a2f 2f77 7777
- 0x0e80: 2e62 6f75 7465 6c6c 2e63 6f6d 2f66 6171
- 0x0e90: 2f22 3e57 6f72 6c64 0a57 6964 6520 5765
- 0x0ea0: 6220 4672 6571 7565 6e74 6c79 2041 736b
- 0x0eb0: 6564 2051 7565 7374 696f 6e73 3c2f 413e
- 0x0ec0: 2066 6f72 2069 6e66 6f72 6d61 7469 6f6e
- 0x0ed0: 2e0a 0a3c 4832 3e4c 6574 206f 7468 6572
- 0x0ee0: 2070 656f 706c 6520 6b6e 6f77 2061 626f
- 0x0ef0: 7574 2074 6869 7320 7365 7276 6572 3c2f
- 0x0f00: 4832 3e0a 0a3c 4120 4852 4546 3d22 6874
- 0x0f10: 7470 3a2f 2f6e 6574 6372 6166 742e 636f
- 0x0f20: 6d2f 223e 4e65 7463 7261 6674 3c2f 413e
- 0x0f30: 2070 726f 7669 6465 7320 616e 2069 6e74
- 0x0f40: 6572 6573 7469 6e67 2066 7265 650a 7365
- 0x0f50: 7276 6963 6520 666f 7220 7765 6220 7369
- 0x0f60: 7465 206d 6f6e 6974 6f72 696e 6720 616e
- 0x0f70: 6420 7374 6174 6973 7469 6320 636f 6c6c
- 0x0f80: 6563 7469 6f6e 2e0a 596f 7520 6361 6e20
- 0x0f90: 6c65 7420 7468 656d 206b 6e6f 7720 6162
- 0x0fa0: 6f75 7420 796f 7572 2073 6572 7665 7220
- 0x0fb0: 7573 696e 6720 7468 6569 720a 3c41 2048
- 0x0fc0: 5245 463d 2268 7474 703a 2f2f 7570 7469
- 0x0fd0: 6d65 2e6e 6574 6372 6166 742e 636f 6d2f
- 0x0fe0: 223e 696e 7465 7266 6163 653c 2f41 3e2e
- 0x0ff0: 0a45 6e61 626c 696e 6720 7468 6520 6d6f
- 0x1000: 6e69 746f 7269 6e67 206f 6620 796f 7572
- 0x1010: 2073 6572 7665 7220 7769 6c6c 2070 726f
- 0x1020: 7669 6465 2061 2062 6574 7465 7220 676c
- 0x1030: 6f62 616c 206f 7665 7276 6965 770a 6f66
- 0x1040: 2077 686f 2069 7320 7573 696e 6720 7768
- 0x1050: 6174 2061 6e64 2077 6865 7265 2c20 616e
- 0x1060: 6420 6974 2077 6f75 6c64 2067 6976 6520
- 0x1070: 4465 6269 616e 2061 2062 6574 7465 720a
- 0x1080: 6f76 6572 7669 6577 206f 6620 7468 6520
- 0x1090: 6170 6163 6865 2070 6163 6b61 6765 2075
- 0x10a0: 7361 6765 2e0a 0a3c 4832 3e41 626f 7574
- 0x10b0: 2074 6869 7320 7061 6765 3c2f 4832 3e0a
- 0x10c0: 0a3c 494d 4720 414c 4947 4e3d 2272 6967
- 0x10d0: 6874 2220 414c 543d 2222 2048 4549 4748
- 0x10e0: 543d 2232 3437 2220 5749 4454 483d 2232
- 0x10f0: 3738 2220 5352 433d 2269 636f 6e73 2f6a
- 0x1100: 6865 3036 312e 706e 6722 3e0a 0a3c 503e
- 0x1110: 5468 6973 2069 7320 6120 706c 6163 6568
- 0x1120: 6f6c 6465 7220 7061 6765 2069 6e73 7461
- 0x1130: 6c6c 6564 2062 7920 7468 6520 3c41 0a48
- 0x1140: 5245 463d 2268 7474 703a 2f2f 7777 772e
- 0x1150: 6465 6269 616e 2e6f 7267 2f22 3e44 6562
- 0x1160: 6961 6e3c 2f41 3e0a 7265 6c65 6173 6520
- 0x1170: 6f66 2074 6865 2061 7061 6368 6520 5765
- 0x1180: 6220 7365 7276 6572 2070 6163 6b61 6765
- 0x1190: 2e0a 0a3c 503e 5468 6973 2063 6f6d 7075
- 0x11a0: 7465 7220 6861 7320 696e 7374 616c 6c65
- 0x11b0: 6420 7468 6520 4465 6269 616e 2047 4e55
- 0x11c0: 2f4c 696e 7578 206f 7065 7261 7469 6e67
- 0x11d0: 2073 7973 7465 6d2c 0a62 7574 2069 7420
- 0x11e0: 6861 7320 3c73 7472 6f6e 673e 6e6f 7468
- 0x11f0: 696e 6720 746f 2064 6f20 7769 7468 2074
- 0x1200: 6865 2044 6562 6961 6e0a 5072 6f6a 6563
- 0x1210: 743c 2f73 7472 6f6e 673e 2e20 506c 6561
- 0x1220: 7365 2064 6f20 3c73 7472 6f6e 673e 6e6f
- 0x1230: 743c 2f73 7472 6f6e 673e 2063 6f6e 7461
- 0x1240: 6374 2074 6865 2044 6562 6961 6e0a 5072
- 0x1250: 6f6a 6563 7420 6162 6f75 7420 6974 2e3c
- 0x1260: 2f50 3e0a 0a3c 503e 4966 2079 6f75 2066
- 0x1270: 696e 6420 6120 6275 6720 696e 2074 6869
- 0x1280: 7320 6170 6163 6865 2070 6163 6b61 6765
- 0x1290: 2c20 6f72 2069 6e20 4170 6163 6865 2069
- 0x12a0: 7473 656c 662c 0a70 6c65 6173 6520 6669
- 0x12b0: 6c65 2061 2062 7567 2072 6570 6f72 7420
- 0x12c0: 6f6e 2069 742e 2020 496e 7374 7275 6374
- 0x12d0: 696f 6e73 206f 6e20 646f 696e 6720 7468
- 0x12e0: 6973 2c20 616e 6420 7468 650a 6c69 7374
- 0x12f0: 206f 6620 3c41 2048 5245 463d 2268 7474
- 0x1300: 703a 2f2f 6275 6773 2e64 6562 6961 6e2e
- 0x1310: 6f72 672f 7372 633a 6170 6163 6865 223e
- 0x1320: 6b6e 6f77 6e20 6275 6773 3c2f 413e 206f
- 0x1330: 6620 7468 6973 0a70 6163 6b61 6765 2c20
- 0x1340: 6361 6e20 6265 2066 6f75 6e64 2069 6e20
- 0x1350: 7468 6520 0a3c 4120 4852 4546 3d22 6874
- 0x1360: 7470 3a2f 2f77 7777 2e64 6562 6961 6e2e
- 0x1370: 6f72 672f 4275 6773 2f52 6570 6f72 7469
- 0x1380: 6e67 223e 4465 6269 616e 2042 7567 2054
- 0x1390: 7261 636b 696e 6720 5379 7374 656d 3c2f
- 0x13a0: 413e 2e0a 0a3c 503e 5468 616e 6b73 2066
- 0x13b0: 6f72 2075 7369 6e67 2074 6869 7320 7061
- 0x13c0: 636b 6167 652c 2061 6e64 2063 6f6e 6772
- 0x13d0: 6174 756c 6174 696f 6e73 2066 6f72 2079
- 0x13e0: 6f75 7220 6368 6f69 6365 206f 660a 6120
- 0x13f0: 4465 6269 616e 2073 7973 7465 6d21 3c2f
- 0x1400: 503e 0a0a 3c44 4956 2061 6c69 676e 3d22
- 0x1410: 6365 6e74 6572 223e 0a3c 6120 6872 6566
- 0x1420: 3d22 6874 7470 3a2f 2f77 7777 2e64 6562
- 0x1430: 6961 6e2e 6f72 672f 223e 0a3c 494d 4720
- 0x1440: 616c 6967 6e3d 226d 6964 646c 6522 2068
- 0x1450: 6569 6768 743d 2233 3022 2077 6964 7468
- 0x1460: 3d22 3235 2220 7372 633d 2269 636f 6e73
- 0x1470: 2f64 6562 6961 6e2f 6f70 656e 6c6f 676f
- 0x1480: 2d32 352e 6a70 6722 2061 6c74 3d22 4465
- 0x1490: 6269 616e 223e 0a3c 2f61 3e0a 3c61 2068
- 0x14a0: 7265 663d 2268 7474 703a 2f2f 7777 772e
- 0x14b0: 6170 6163 6865 2e6f 7267 2f22 3e0a 3c49
- 0x14c0: 4d47 2061 6c69 676e 3d22 6d69 6464 6c65
- 0x14d0: 2220 6865 6967 6874 3d22 3332 2220 7769
- 0x14e0: 6474 683d 2232 3539 2220 7372 633d 2269
- 0x14f0: 636f 6e73 2f61 7061 6368 655f 7062 2e70
- 0x1500: 6e67 2220 616c 743d 2241 7061 6368 6522
- 0x1510: 3e0a 3c2f 613e 0a3c 2f44 4956 3e0a 0a3c
- 0x1520: 212d 2d0a 2020 5468 6973 2070 6167 6520
- 0x1530: 7761 7320 696e 6974 6961 6c6c 7920 6372
- 0x1540: 6561 7465 6420 6279 204a 6f68 6e69 6520
- 0x1550: 496e 6772 616d 2028 6874 7470 3a2f 2f6e
- 0x1560: 6574 676f 642e 6e65 742f 290a 2020 4974
- 0x1570: 2077 6173 206c 6174 6572 2065 6469 7465
- 0x1580: 6420 6279 204d 6174 7468 6577 2057 696c
- 0x1590: 636f 7820 616e 6420 4a6f 7369 7020 526f
- 0x15a0: 6469 6e2e 0a20 204c 6173 7420 6d6f 6469
- 0x15b0: 6669 6564 3a20 2444 6174 653a 2032 3030
- 0x15c0: 342f 3036 2f32 3020 3135 3a33 333a 3537
- 0x15d0: 2024 2e0a 2020 2d2d 3e0a 0a3c 2f42 4f44
- 0x15e0: 593e 0a3c 2f48 544d 4c3e 0a
-23:57:35.941260 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5560 win 12383 <nop,nop,timestamp 1306300953 1306300953>
- 0x0000: 4500 0034 1b6e 4000 4006 2154 7f00 0001
- 0x0010: 7f00 0001 da70 0050 3758 8a49 377a a3a9
- 0x0020: 8010 305f 10ea 0000 0101 080a 4ddc 9219
- 0x0030: 4ddc 9219
-23:57:37.229575 IP 127.0.0.1.55920 > 127.0.0.1.80: F 203:203(0) ack 5560 win 12383 <nop,nop,timestamp 1306302241 1306300953>
- 0x0000: 4500 0034 1b70 4000 4006 2152 7f00 0001
- 0x0010: 7f00 0001 da70 0050 3758 8a49 377a a3a9
- 0x0020: 8011 305f 0be1 0000 0101 080a 4ddc 9721
- 0x0030: 4ddc 9219
-23:57:37.230839 IP 127.0.0.1.80 > 127.0.0.1.55920: F 5560:5560(0) ack 204 win 8192 <nop,nop,timestamp 1306302243 1306302241>
- 0x0000: 4500 0034 1fe8 4000 4006 1cda 7f00 0001
- 0x0010: 7f00 0001 0050 da70 377a a3a9 3758 8a4a
- 0x0020: 8011 2000 1735 0000 0101 080a 4ddc 9723
- 0x0030: 4ddc 9721
-23:57:37.230900 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5561 win 12383 <nop,nop,timestamp 1306302243 1306302243>
- 0x0000: 4500 0034 1b72 4000 4006 2150 7f00 0001
- 0x0010: 7f00 0001 da70 0050 3758 8a4a 377a a3aa
- 0x0020: 8010 305f 06d4 0000 0101 080a 4ddc 9723
- 0x0030: 4ddc 9723
diff --git a/contrib/tcpdump/tests/print-xx.out b/contrib/tcpdump/tests/print-xx.out
deleted file mode 100644
index 82323d4..0000000
--- a/contrib/tcpdump/tests/print-xx.out
+++ /dev/null
@@ -1,419 +0,0 @@
-23:57:35.938066 IP 127.0.0.1.55920 > 127.0.0.1.80: S 928549246:928549246(0) win 32767 <mss 16396,sackOK,timestamp 1306300950 0,nop,wscale 2>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500
- 0x0010: 003c 1b68 4000 4006 2152 7f00 0001 7f00
- 0x0020: 0001 da70 0050 3758 897e 0000 0000 a002
- 0x0030: 7fff 1421 0000 0204 400c 0402 080a 4ddc
- 0x0040: 9216 0000 0000 0103 0302
-23:57:35.938122 IP 127.0.0.1.80 > 127.0.0.1.55920: S 930778609:930778609(0) ack 928549247 win 32767 <mss 16396,sackOK,timestamp 1306300950 1306300950,nop,wscale 2>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500
- 0x0010: 003c 0000 4000 4006 3cba 7f00 0001 7f00
- 0x0020: 0001 0050 da70 377a 8df1 3758 897f a012
- 0x0030: 7fff 6eb1 0000 0204 400c 0402 080a 4ddc
- 0x0040: 9216 4ddc 9216 0103 0302
-23:57:35.938167 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 1 win 8192 <nop,nop,timestamp 1306300950 1306300950>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500
- 0x0010: 0034 1b6a 4000 4006 2158 7f00 0001 7f00
- 0x0020: 0001 da70 0050 3758 897f 377a 8df2 8010
- 0x0030: 2000 37d0 0000 0101 080a 4ddc 9216 4ddc
- 0x0040: 9216
-23:57:35.939423 IP 127.0.0.1.55920 > 127.0.0.1.80: P 1:203(202) ack 1 win 8192 <nop,nop,timestamp 1306300951 1306300950>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500
- 0x0010: 00fe 1b6c 4000 4006 208c 7f00 0001 7f00
- 0x0020: 0001 da70 0050 3758 897f 377a 8df2 8018
- 0x0030: 2000 fef2 0000 0101 080a 4ddc 9217 4ddc
- 0x0040: 9216 4745 5420 2f20 4854 5450 2f31 2e31
- 0x0050: 0d0a 486f 7374 3a20 6c6f 6361 6c68 6f73
- 0x0060: 740d 0a55 7365 722d 4167 656e 743a 2045
- 0x0070: 4c69 6e6b 732f 302e 3130 2e34 2d37 2d64
- 0x0080: 6562 6961 6e20 2874 6578 746d 6f64 653b
- 0x0090: 204c 696e 7578 2032 2e36 2e31 312d 312d
- 0x00a0: 3638 362d 736d 7020 6936 3836 3b20 3133
- 0x00b0: 3278 3536 2d32 290d 0a41 6363 6570 743a
- 0x00c0: 202a 2f2a 0d0a 4163 6365 7074 2d45 6e63
- 0x00d0: 6f64 696e 673a 2067 7a69 700d 0a41 6363
- 0x00e0: 6570 742d 4c61 6e67 7561 6765 3a20 656e
- 0x00f0: 0d0a 436f 6e6e 6563 7469 6f6e 3a20 4b65
- 0x0100: 6570 2d41 6c69 7665 0d0a 0d0a
-23:57:35.940474 IP 127.0.0.1.80 > 127.0.0.1.55920: . ack 203 win 8192 <nop,nop,timestamp 1306300952 1306300951>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500
- 0x0010: 0034 1fe4 4000 4006 1cde 7f00 0001 7f00
- 0x0020: 0001 0050 da70 377a 8df2 3758 8a49 8010
- 0x0030: 2000 3703 0000 0101 080a 4ddc 9218 4ddc
- 0x0040: 9217
-23:57:35.941232 IP 127.0.0.1.80 > 127.0.0.1.55920: P 1:5560(5559) ack 203 win 8192 <nop,nop,timestamp 1306300953 1306300951>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500
- 0x0010: 15eb 1fe6 4000 4006 0725 7f00 0001 7f00
- 0x0020: 0001 0050 da70 377a 8df2 3758 8a49 8018
- 0x0030: 2000 13e0 0000 0101 080a 4ddc 9219 4ddc
- 0x0040: 9217 4854 5450 2f31 2e31 2032 3030 204f
- 0x0050: 4b0d 0a44 6174 653a 2057 6564 2c20 3036
- 0x0060: 204a 756c 2032 3030 3520 3033 3a35 373a
- 0x0070: 3335 2047 4d54 0d0a 5365 7276 6572 3a20
- 0x0080: 4170 6163 6865 2f31 2e33 2e33 330d 0a4c
- 0x0090: 6173 742d 4d6f 6469 6669 6564 3a20 5375
- 0x00a0: 6e2c 2031 3520 4175 6720 3230 3034 2030
- 0x00b0: 303a 3433 3a34 3120 474d 540d 0a45 5461
- 0x00c0: 673a 2022 3665 3830 6630 2d31 3438 612d
- 0x00d0: 3431 3165 6231 6264 220d 0a41 6363 6570
- 0x00e0: 742d 5261 6e67 6573 3a20 6279 7465 730d
- 0x00f0: 0a43 6f6e 7465 6e74 2d4c 656e 6774 683a
- 0x0100: 2035 3235 380d 0a4b 6565 702d 416c 6976
- 0x0110: 653a 2074 696d 656f 7574 3d31 352c 206d
- 0x0120: 6178 3d31 3030 0d0a 436f 6e6e 6563 7469
- 0x0130: 6f6e 3a20 4b65 6570 2d41 6c69 7665 0d0a
- 0x0140: 436f 6e74 656e 742d 5479 7065 3a20 7465
- 0x0150: 7874 2f68 746d 6c3b 2063 6861 7273 6574
- 0x0160: 3d69 736f 2d38 3835 392d 310d 0a0d 0a3c
- 0x0170: 2144 4f43 5459 5045 2048 544d 4c20 5055
- 0x0180: 424c 4943 2022 2d2f 2f57 3343 2f2f 4454
- 0x0190: 4420 4854 4d4c 2034 2e30 3120 5472 616e
- 0x01a0: 7369 7469 6f6e 616c 2f2f 454e 223e 0a3c
- 0x01b0: 4854 4d4c 3e0a 3c48 4541 443e 0a20 2020
- 0x01c0: 3c4d 4554 4120 4854 5450 2d45 5155 4956
- 0x01d0: 3d22 436f 6e74 656e 742d 5479 7065 2220
- 0x01e0: 434f 4e54 454e 543d 2274 6578 742f 6874
- 0x01f0: 6d6c 3b20 6368 6172 7365 743d 6973 6f2d
- 0x0200: 3838 3539 2d31 223e 0a20 2020 3c4d 4554
- 0x0210: 4120 4e41 4d45 3d22 4465 7363 7269 7074
- 0x0220: 696f 6e22 2043 4f4e 5445 4e54 3d22 5468
- 0x0230: 6520 696e 6974 6961 6c20 696e 7374 616c
- 0x0240: 6c61 7469 6f6e 206f 6620 4465 6269 616e
- 0x0250: 2061 7061 6368 652e 223e 0a20 2020 3c54
- 0x0260: 4954 4c45 3e50 6c61 6365 686f 6c64 6572
- 0x0270: 2070 6167 653c 2f54 4954 4c45 3e0a 3c2f
- 0x0280: 4845 4144 3e0a 3c42 4f44 5920 5445 5854
- 0x0290: 3d22 2330 3030 3030 3022 2042 4743 4f4c
- 0x02a0: 4f52 3d22 2346 4646 4646 4622 204c 494e
- 0x02b0: 4b3d 2223 3030 3030 4546 2220 564c 494e
- 0x02c0: 4b3d 2223 3535 3138 3841 2220 414c 494e
- 0x02d0: 4b3d 2223 4646 3030 3030 223e 0a0a 3c48
- 0x02e0: 313e 506c 6163 6568 6f6c 6465 7220 7061
- 0x02f0: 6765 3c2f 4831 3e0a 3c48 323e 4966 2079
- 0x0300: 6f75 2061 7265 206a 7573 7420 6272 6f77
- 0x0310: 7369 6e67 2074 6865 2077 6562 3c2f 6832
- 0x0320: 3e0a 0a3c 503e 5468 6520 6f77 6e65 7220
- 0x0330: 6f66 2074 6869 7320 7765 6220 7369 7465
- 0x0340: 2068 6173 206e 6f74 2070 7574 2075 7020
- 0x0350: 616e 7920 7765 6220 7061 6765 7320 7965
- 0x0360: 742e 0a50 6c65 6173 6520 636f 6d65 2062
- 0x0370: 6163 6b20 6c61 7465 722e 3c2f 503e 0a0a
- 0x0380: 3c50 3e3c 534d 414c 4c3e 3c43 4954 453e
- 0x0390: 4d6f 7665 2061 6c6f 6e67 2c20 6e6f 7468
- 0x03a0: 696e 6720 746f 2073 6565 2068 6572 652e
- 0x03b0: 2e2e 3c2f 4349 5445 3e20 3a2d 293c 2f53
- 0x03c0: 4d41 4c4c 3e3c 2f50 3e0a 0a3c 4832 3e49
- 0x03d0: 6620 796f 7520 6172 6520 7472 7969 6e67
- 0x03e0: 2074 6f20 6c6f 6361 7465 2074 6865 2061
- 0x03f0: 646d 696e 6973 7472 6174 6f72 206f 6620
- 0x0400: 7468 6973 206d 6163 6869 6e65 3c2f 4832
- 0x0410: 3e0a 0a3c 503e 4966 2079 6f75 2077 616e
- 0x0420: 7420 746f 2072 6570 6f72 7420 736f 6d65
- 0x0430: 7468 696e 6720 6162 6f75 7420 7468 6973
- 0x0440: 2068 6f73 7427 7320 6265 6861 7669 6f72
- 0x0450: 2c20 706c 6561 7365 0a63 6f6e 7461 6374
- 0x0460: 2074 6865 2049 6e74 6572 6e65 7420 5365
- 0x0470: 7276 6963 6520 5072 6f76 6964 6572 2028
- 0x0480: 4953 5029 2069 6e76 6f6c 7665 6420 6469
- 0x0490: 7265 6374 6c79 2e3c 2f50 3e0a 0a3c 503e
- 0x04a0: 5365 6520 7468 6520 3c41 2068 7265 663d
- 0x04b0: 2268 7474 703a 2f2f 7777 772e 6162 7573
- 0x04c0: 652e 6e65 742f 223e 4e65 7477 6f72 6b20
- 0x04d0: 4162 7573 650a 436c 6561 7269 6e67 686f
- 0x04e0: 7573 653c 2f41 3e20 666f 7220 686f 7720
- 0x04f0: 746f 2064 6f20 7468 6973 2e3c 2f50 3e0a
- 0x0500: 0a3c 4832 3e49 6620 796f 7520 6172 6520
- 0x0510: 7468 6520 6164 6d69 6e69 7374 7261 746f
- 0x0520: 7220 6f66 2074 6869 7320 6d61 6368 696e
- 0x0530: 653c 2f48 323e 0a0a 3c50 3e54 6865 2069
- 0x0540: 6e69 7469 616c 2069 6e73 7461 6c6c 6174
- 0x0550: 696f 6e20 6f66 203c 4120 6872 6566 3d22
- 0x0560: 6874 7470 3a2f 2f77 7777 2e64 6562 6961
- 0x0570: 6e2e 6f72 672f 223e 4465 6269 616e 2773
- 0x0580: 0a61 7061 6368 653c 2f41 3e20 7765 6220
- 0x0590: 7365 7276 6572 2070 6163 6b61 6765 2077
- 0x05a0: 6173 2073 7563 6365 7373 6675 6c2e 3c2f
- 0x05b0: 503e 0a0a 3c50 3e3c 5354 524f 4e47 3e59
- 0x05c0: 6f75 2073 686f 756c 6420 7265 706c 6163
- 0x05d0: 6520 7468 6973 2070 6167 6520 7769 7468
- 0x05e0: 2079 6f75 7220 6f77 6e20 7765 6220 7061
- 0x05f0: 6765 7320 6173 0a73 6f6f 6e20 6173 2070
- 0x0600: 6f73 7369 626c 652e 3c2f 5354 524f 4e47
- 0x0610: 3e3c 2f50 3e0a 0a3c 503e 556e 6c65 7373
- 0x0620: 2079 6f75 2063 6861 6e67 6564 2069 7473
- 0x0630: 2063 6f6e 6669 6775 7261 7469 6f6e 2c20
- 0x0640: 796f 7572 206e 6577 2073 6572 7665 7220
- 0x0650: 6973 2063 6f6e 6669 6775 7265 6420 6173
- 0x0660: 2066 6f6c 6c6f 7773 3a0a 3c55 4c3e 0a3c
- 0x0670: 4c49 3e0a 436f 6e66 6967 7572 6174 696f
- 0x0680: 6e20 6669 6c65 7320 6361 6e20 6265 2066
- 0x0690: 6f75 6e64 2069 6e20 3c54 543e 2f65 7463
- 0x06a0: 2f61 7061 6368 653c 2f54 543e 2e3c 2f4c
- 0x06b0: 493e 0a0a 3c4c 493e 0a54 6865 203c 5454
- 0x06c0: 3e44 6f63 756d 656e 7452 6f6f 743c 2f54
- 0x06d0: 543e 2c20 7768 6963 6820 6973 2074 6865
- 0x06e0: 2064 6972 6563 746f 7279 2075 6e64 6572
- 0x06f0: 2077 6869 6368 2061 6c6c 2079 6f75 720a
- 0x0700: 4854 4d4c 2066 696c 6573 2073 686f 756c
- 0x0710: 6420 6578 6973 742c 2069 7320 7365 7420
- 0x0720: 746f 203c 5454 3e2f 7661 722f 7777 773c
- 0x0730: 2f54 543e 2e3c 2f4c 493e 0a0a 3c4c 493e
- 0x0740: 0a43 4749 2073 6372 6970 7473 2061 7265
- 0x0750: 206c 6f6f 6b65 6420 666f 7220 696e 203c
- 0x0760: 5454 3e2f 7573 722f 6c69 622f 6367 692d
- 0x0770: 6269 6e3c 2f54 543e 2c20 7768 6963 6820
- 0x0780: 6973 2077 6865 7265 0a44 6562 6961 6e20
- 0x0790: 7061 636b 6167 6573 2077 696c 6c20 706c
- 0x07a0: 6163 6520 7468 6569 7220 7363 7269 7074
- 0x07b0: 732e 3c2f 4c49 3e0a 0a3c 4c49 3e0a 4c6f
- 0x07c0: 6720 6669 6c65 7320 6172 6520 706c 6163
- 0x07d0: 6564 2069 6e20 3c54 543e 2f76 6172 2f6c
- 0x07e0: 6f67 2f61 7061 6368 653c 2f54 543e 2c20
- 0x07f0: 616e 6420 7769 6c6c 2062 6520 726f 7461
- 0x0800: 7465 640a 7765 656b 6c79 2e20 2054 6865
- 0x0810: 2066 7265 7175 656e 6379 206f 6620 726f
- 0x0820: 7461 7469 6f6e 2063 616e 2062 6520 6561
- 0x0830: 7369 6c79 2063 6861 6e67 6564 2062 7920
- 0x0840: 6564 6974 696e 670a 3c54 543e 2f65 7463
- 0x0850: 2f6c 6f67 726f 7461 7465 2e64 2f61 7061
- 0x0860: 6368 653c 2f54 543e 2e3c 2f4c 493e 0a0a
- 0x0870: 3c4c 493e 0a54 6865 2064 6566 6175 6c74
- 0x0880: 2064 6972 6563 746f 7279 2069 6e64 6578
- 0x0890: 2069 7320 3c54 543e 696e 6465 782e 6874
- 0x08a0: 6d6c 3c2f 5454 3e2c 206d 6561 6e69 6e67
- 0x08b0: 2074 6861 7420 7265 7175 6573 7473 0a66
- 0x08c0: 6f72 2061 2064 6972 6563 746f 7279 203c
- 0x08d0: 5454 3e2f 666f 6f2f 6261 722f 3c2f 5454
- 0x08e0: 3e20 7769 6c6c 2067 6976 6520 7468 6520
- 0x08f0: 636f 6e74 656e 7473 206f 6620 7468 6520
- 0x0900: 6669 6c65 203c 5454 3e2f 7661 722f 7777
- 0x0910: 772f 666f 6f2f 6261 722f 696e 6465 782e
- 0x0920: 6874 6d6c 3c2f 5454 3e0a 6966 2069 7420
- 0x0930: 6578 6973 7473 2028 6173 7375 6d69 6e67
- 0x0940: 2074 6861 7420 3c54 543e 2f76 6172 2f77
- 0x0950: 7777 3c2f 5454 3e20 6973 2079 6f75 7220
- 0x0960: 3c54 543e 446f 6375 6d65 6e74 526f 6f74
- 0x0970: 3c2f 5454 3e29 2e3c 2f4c 493e 0a0a 3c4c
- 0x0980: 493e 0a55 7365 7220 6469 7265 6374 6f72
- 0x0990: 6965 7320 6172 6520 656e 6162 6c65 642c
- 0x09a0: 2061 6e64 2075 7365 7220 646f 6375 6d65
- 0x09b0: 6e74 7320 7769 6c6c 2062 6520 6c6f 6f6b
- 0x09c0: 6564 2066 6f72 0a69 6e20 7468 6520 3c54
- 0x09d0: 543e 7075 626c 6963 5f68 746d 6c3c 2f54
- 0x09e0: 543e 2064 6972 6563 746f 7279 206f 6620
- 0x09f0: 7468 6520 7573 6572 7327 2068 6f6d 6573
- 0x0a00: 2e20 2054 6865 7365 2064 6972 730a 7368
- 0x0a10: 6f75 6c64 2062 6520 756e 6465 7220 3c54
- 0x0a20: 543e 2f68 6f6d 653c 2f54 543e 2c20 616e
- 0x0a30: 6420 7573 6572 7320 7769 6c6c 206e 6f74
- 0x0a40: 2062 6520 6162 6c65 2074 6f20 7379 6d6c
- 0x0a50: 696e 6b0a 746f 2066 696c 6573 2074 6865
- 0x0a60: 7920 646f 6e27 7420 6f77 6e2e 3c2f 4c49
- 0x0a70: 3e0a 0a3c 2f55 4c3e 0a41 6c6c 2074 6865
- 0x0a80: 2073 7461 6e64 6172 6420 6170 6163 6865
- 0x0a90: 206d 6f64 756c 6573 2061 7265 2061 7661
- 0x0aa0: 696c 6162 6c65 2077 6974 6820 7468 6973
- 0x0ab0: 2072 656c 6561 7365 2061 6e64 2061 7265
- 0x0ac0: 0a6e 6f77 206d 616e 6167 6564 2077 6974
- 0x0ad0: 6820 6465 6263 6f6e 662e 2020 5479 7065
- 0x0ae0: 203c 5454 3e64 706b 672d 7265 636f 6e66
- 0x0af0: 6967 7572 6520 6170 6163 6865 3c2f 5454
- 0x0b00: 3e20 746f 0a73 656c 6563 7420 7768 6963
- 0x0b10: 6820 6d6f 6475 6c65 7320 796f 7520 7761
- 0x0b20: 6e74 2065 6e61 626c 6564 2e20 204d 616e
- 0x0b30: 7920 6f74 6865 7220 6d6f 6475 6c65 7320
- 0x0b40: 6172 6520 6176 6169 6c61 626c 650a 7468
- 0x0b50: 726f 7567 6820 7468 6520 4465 6269 616e
- 0x0b60: 2070 6163 6b61 6765 2073 7973 7465 6d20
- 0x0b70: 7769 7468 2074 6865 206e 616d 6573 203c
- 0x0b80: 5454 3e6c 6962 6170 6163 6865 2d6d 6f64
- 0x0b90: 2d2a 3c2f 5454 3e2e 0a49 6620 796f 7520
- 0x0ba0: 6e65 6564 2074 6f20 636f 6d70 696c 6520
- 0x0bb0: 6120 6d6f 6475 6c65 2079 6f75 7273 656c
- 0x0bc0: 662c 2079 6f75 2077 696c 6c20 6e65 6564
- 0x0bd0: 2074 6f20 696e 7374 616c 6c20 7468 650a
- 0x0be0: 3c54 543e 6170 6163 6865 2d64 6576 3c2f
- 0x0bf0: 5454 3e20 7061 636b 6167 652e 0a0a 3c50
- 0x0c00: 3e4d 6f72 6520 646f 6375 6d65 6e74 6174
- 0x0c10: 696f 6e20 6f6e 2041 7061 6368 6520 6361
- 0x0c20: 6e20 6265 2066 6f75 6e64 206f 6e3a 0a3c
- 0x0c30: 554c 3e0a 3c4c 493e 0a54 6865 203c 4120
- 0x0c40: 4852 4546 3d22 2f64 6f63 2f61 7061 6368
- 0x0c50: 652d 646f 632f 6d61 6e75 616c 2f22 3e41
- 0x0c60: 7061 6368 6520 646f 6375 6d65 6e74 6174
- 0x0c70: 696f 6e3c 2f41 3e20 7374 6f72 6564 206f
- 0x0c80: 6e20 796f 7572 2073 6572 7665 722e 3c2f
- 0x0c90: 4c49 3e0a 0a3c 4c49 3e0a 5468 6520 3c41
- 0x0ca0: 2048 5245 463d 2268 7474 703a 2f2f 7777
- 0x0cb0: 772e 6170 6163 6865 2e6f 7267 2f22 3e41
- 0x0cc0: 7061 6368 6520 5072 6f6a 6563 743c 2f41
- 0x0cd0: 3e20 686f 6d65 2073 6974 652e 3c2f 4c49
- 0x0ce0: 3e0a 0a3c 4c49 3e0a 5468 6520 3c41 2048
- 0x0cf0: 5245 463d 2268 7474 703a 2f2f 7777 772e
- 0x0d00: 6170 6163 6865 2d73 736c 2e6f 7267 2f22
- 0x0d10: 3e41 7061 6368 652d 5353 4c3c 2f41 3e20
- 0x0d20: 686f 6d65 2073 6974 652e 3c2f 4c49 3e0a
- 0x0d30: 0a3c 4c49 3e0a 5468 6520 3c41 2048 5245
- 0x0d40: 463d 2268 7474 703a 2f2f 7065 726c 2e61
- 0x0d50: 7061 6368 652e 6f72 672f 223e 6d6f 6420
- 0x0d60: 7065 726c 3c2f 413e 2068 6f6d 6520 7369
- 0x0d70: 7465 2e3c 2f4c 493e 0a0a 3c4c 493e 0a54
- 0x0d80: 6865 203c 4120 4852 4546 3d22 6874 7470
- 0x0d90: 3a2f 2f77 7777 2e61 7061 6368 6577 6565
- 0x0da0: 6b2e 636f 6d2f 223e 4170 6163 6865 5765
- 0x0db0: 656b 3c2f 413e 206e 6577 736c 6574 7465
- 0x0dc0: 722e 3c2f 4c49 3e0a 0a3c 4c49 3e0a 5468
- 0x0dd0: 6520 3c41 2048 5245 463d 2268 7474 703a
- 0x0de0: 2f2f 7777 772e 6465 6269 616e 2e6f 7267
- 0x0df0: 2f64 6f63 2f22 3e44 6562 6961 6e20 5072
- 0x0e00: 6f6a 6563 740a 446f 6375 6d65 6e74 6174
- 0x0e10: 696f 6e3c 2f41 3e20 7768 6963 6820 636f
- 0x0e20: 6e74 6169 6e73 2048 4f57 544f 732c 2046
- 0x0e30: 4151 732c 2061 6e64 2073 6f66 7477 6172
- 0x0e40: 6520 7570 6461 7465 732e 3c2f 4c49 3e0a
- 0x0e50: 3c2f 554c 3e0a 0a3c 503e 596f 7520 6361
- 0x0e60: 6e20 616c 736f 2063 6f6e 7375 6c74 2074
- 0x0e70: 6865 206c 6973 7420 6f66 203c 4120 4852
- 0x0e80: 4546 3d22 6874 7470 3a2f 2f77 7777 2e62
- 0x0e90: 6f75 7465 6c6c 2e63 6f6d 2f66 6171 2f22
- 0x0ea0: 3e57 6f72 6c64 0a57 6964 6520 5765 6220
- 0x0eb0: 4672 6571 7565 6e74 6c79 2041 736b 6564
- 0x0ec0: 2051 7565 7374 696f 6e73 3c2f 413e 2066
- 0x0ed0: 6f72 2069 6e66 6f72 6d61 7469 6f6e 2e0a
- 0x0ee0: 0a3c 4832 3e4c 6574 206f 7468 6572 2070
- 0x0ef0: 656f 706c 6520 6b6e 6f77 2061 626f 7574
- 0x0f00: 2074 6869 7320 7365 7276 6572 3c2f 4832
- 0x0f10: 3e0a 0a3c 4120 4852 4546 3d22 6874 7470
- 0x0f20: 3a2f 2f6e 6574 6372 6166 742e 636f 6d2f
- 0x0f30: 223e 4e65 7463 7261 6674 3c2f 413e 2070
- 0x0f40: 726f 7669 6465 7320 616e 2069 6e74 6572
- 0x0f50: 6573 7469 6e67 2066 7265 650a 7365 7276
- 0x0f60: 6963 6520 666f 7220 7765 6220 7369 7465
- 0x0f70: 206d 6f6e 6974 6f72 696e 6720 616e 6420
- 0x0f80: 7374 6174 6973 7469 6320 636f 6c6c 6563
- 0x0f90: 7469 6f6e 2e0a 596f 7520 6361 6e20 6c65
- 0x0fa0: 7420 7468 656d 206b 6e6f 7720 6162 6f75
- 0x0fb0: 7420 796f 7572 2073 6572 7665 7220 7573
- 0x0fc0: 696e 6720 7468 6569 720a 3c41 2048 5245
- 0x0fd0: 463d 2268 7474 703a 2f2f 7570 7469 6d65
- 0x0fe0: 2e6e 6574 6372 6166 742e 636f 6d2f 223e
- 0x0ff0: 696e 7465 7266 6163 653c 2f41 3e2e 0a45
- 0x1000: 6e61 626c 696e 6720 7468 6520 6d6f 6e69
- 0x1010: 746f 7269 6e67 206f 6620 796f 7572 2073
- 0x1020: 6572 7665 7220 7769 6c6c 2070 726f 7669
- 0x1030: 6465 2061 2062 6574 7465 7220 676c 6f62
- 0x1040: 616c 206f 7665 7276 6965 770a 6f66 2077
- 0x1050: 686f 2069 7320 7573 696e 6720 7768 6174
- 0x1060: 2061 6e64 2077 6865 7265 2c20 616e 6420
- 0x1070: 6974 2077 6f75 6c64 2067 6976 6520 4465
- 0x1080: 6269 616e 2061 2062 6574 7465 720a 6f76
- 0x1090: 6572 7669 6577 206f 6620 7468 6520 6170
- 0x10a0: 6163 6865 2070 6163 6b61 6765 2075 7361
- 0x10b0: 6765 2e0a 0a3c 4832 3e41 626f 7574 2074
- 0x10c0: 6869 7320 7061 6765 3c2f 4832 3e0a 0a3c
- 0x10d0: 494d 4720 414c 4947 4e3d 2272 6967 6874
- 0x10e0: 2220 414c 543d 2222 2048 4549 4748 543d
- 0x10f0: 2232 3437 2220 5749 4454 483d 2232 3738
- 0x1100: 2220 5352 433d 2269 636f 6e73 2f6a 6865
- 0x1110: 3036 312e 706e 6722 3e0a 0a3c 503e 5468
- 0x1120: 6973 2069 7320 6120 706c 6163 6568 6f6c
- 0x1130: 6465 7220 7061 6765 2069 6e73 7461 6c6c
- 0x1140: 6564 2062 7920 7468 6520 3c41 0a48 5245
- 0x1150: 463d 2268 7474 703a 2f2f 7777 772e 6465
- 0x1160: 6269 616e 2e6f 7267 2f22 3e44 6562 6961
- 0x1170: 6e3c 2f41 3e0a 7265 6c65 6173 6520 6f66
- 0x1180: 2074 6865 2061 7061 6368 6520 5765 6220
- 0x1190: 7365 7276 6572 2070 6163 6b61 6765 2e0a
- 0x11a0: 0a3c 503e 5468 6973 2063 6f6d 7075 7465
- 0x11b0: 7220 6861 7320 696e 7374 616c 6c65 6420
- 0x11c0: 7468 6520 4465 6269 616e 2047 4e55 2f4c
- 0x11d0: 696e 7578 206f 7065 7261 7469 6e67 2073
- 0x11e0: 7973 7465 6d2c 0a62 7574 2069 7420 6861
- 0x11f0: 7320 3c73 7472 6f6e 673e 6e6f 7468 696e
- 0x1200: 6720 746f 2064 6f20 7769 7468 2074 6865
- 0x1210: 2044 6562 6961 6e0a 5072 6f6a 6563 743c
- 0x1220: 2f73 7472 6f6e 673e 2e20 506c 6561 7365
- 0x1230: 2064 6f20 3c73 7472 6f6e 673e 6e6f 743c
- 0x1240: 2f73 7472 6f6e 673e 2063 6f6e 7461 6374
- 0x1250: 2074 6865 2044 6562 6961 6e0a 5072 6f6a
- 0x1260: 6563 7420 6162 6f75 7420 6974 2e3c 2f50
- 0x1270: 3e0a 0a3c 503e 4966 2079 6f75 2066 696e
- 0x1280: 6420 6120 6275 6720 696e 2074 6869 7320
- 0x1290: 6170 6163 6865 2070 6163 6b61 6765 2c20
- 0x12a0: 6f72 2069 6e20 4170 6163 6865 2069 7473
- 0x12b0: 656c 662c 0a70 6c65 6173 6520 6669 6c65
- 0x12c0: 2061 2062 7567 2072 6570 6f72 7420 6f6e
- 0x12d0: 2069 742e 2020 496e 7374 7275 6374 696f
- 0x12e0: 6e73 206f 6e20 646f 696e 6720 7468 6973
- 0x12f0: 2c20 616e 6420 7468 650a 6c69 7374 206f
- 0x1300: 6620 3c41 2048 5245 463d 2268 7474 703a
- 0x1310: 2f2f 6275 6773 2e64 6562 6961 6e2e 6f72
- 0x1320: 672f 7372 633a 6170 6163 6865 223e 6b6e
- 0x1330: 6f77 6e20 6275 6773 3c2f 413e 206f 6620
- 0x1340: 7468 6973 0a70 6163 6b61 6765 2c20 6361
- 0x1350: 6e20 6265 2066 6f75 6e64 2069 6e20 7468
- 0x1360: 6520 0a3c 4120 4852 4546 3d22 6874 7470
- 0x1370: 3a2f 2f77 7777 2e64 6562 6961 6e2e 6f72
- 0x1380: 672f 4275 6773 2f52 6570 6f72 7469 6e67
- 0x1390: 223e 4465 6269 616e 2042 7567 2054 7261
- 0x13a0: 636b 696e 6720 5379 7374 656d 3c2f 413e
- 0x13b0: 2e0a 0a3c 503e 5468 616e 6b73 2066 6f72
- 0x13c0: 2075 7369 6e67 2074 6869 7320 7061 636b
- 0x13d0: 6167 652c 2061 6e64 2063 6f6e 6772 6174
- 0x13e0: 756c 6174 696f 6e73 2066 6f72 2079 6f75
- 0x13f0: 7220 6368 6f69 6365 206f 660a 6120 4465
- 0x1400: 6269 616e 2073 7973 7465 6d21 3c2f 503e
- 0x1410: 0a0a 3c44 4956 2061 6c69 676e 3d22 6365
- 0x1420: 6e74 6572 223e 0a3c 6120 6872 6566 3d22
- 0x1430: 6874 7470 3a2f 2f77 7777 2e64 6562 6961
- 0x1440: 6e2e 6f72 672f 223e 0a3c 494d 4720 616c
- 0x1450: 6967 6e3d 226d 6964 646c 6522 2068 6569
- 0x1460: 6768 743d 2233 3022 2077 6964 7468 3d22
- 0x1470: 3235 2220 7372 633d 2269 636f 6e73 2f64
- 0x1480: 6562 6961 6e2f 6f70 656e 6c6f 676f 2d32
- 0x1490: 352e 6a70 6722 2061 6c74 3d22 4465 6269
- 0x14a0: 616e 223e 0a3c 2f61 3e0a 3c61 2068 7265
- 0x14b0: 663d 2268 7474 703a 2f2f 7777 772e 6170
- 0x14c0: 6163 6865 2e6f 7267 2f22 3e0a 3c49 4d47
- 0x14d0: 2061 6c69 676e 3d22 6d69 6464 6c65 2220
- 0x14e0: 6865 6967 6874 3d22 3332 2220 7769 6474
- 0x14f0: 683d 2232 3539 2220 7372 633d 2269 636f
- 0x1500: 6e73 2f61 7061 6368 655f 7062 2e70 6e67
- 0x1510: 2220 616c 743d 2241 7061 6368 6522 3e0a
- 0x1520: 3c2f 613e 0a3c 2f44 4956 3e0a 0a3c 212d
- 0x1530: 2d0a 2020 5468 6973 2070 6167 6520 7761
- 0x1540: 7320 696e 6974 6961 6c6c 7920 6372 6561
- 0x1550: 7465 6420 6279 204a 6f68 6e69 6520 496e
- 0x1560: 6772 616d 2028 6874 7470 3a2f 2f6e 6574
- 0x1570: 676f 642e 6e65 742f 290a 2020 4974 2077
- 0x1580: 6173 206c 6174 6572 2065 6469 7465 6420
- 0x1590: 6279 204d 6174 7468 6577 2057 696c 636f
- 0x15a0: 7820 616e 6420 4a6f 7369 7020 526f 6469
- 0x15b0: 6e2e 0a20 204c 6173 7420 6d6f 6469 6669
- 0x15c0: 6564 3a20 2444 6174 653a 2032 3030 342f
- 0x15d0: 3036 2f32 3020 3135 3a33 333a 3537 2024
- 0x15e0: 2e0a 2020 2d2d 3e0a 0a3c 2f42 4f44 593e
- 0x15f0: 0a3c 2f48 544d 4c3e 0a
-23:57:35.941260 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5560 win 12383 <nop,nop,timestamp 1306300953 1306300953>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500
- 0x0010: 0034 1b6e 4000 4006 2154 7f00 0001 7f00
- 0x0020: 0001 da70 0050 3758 8a49 377a a3a9 8010
- 0x0030: 305f 10ea 0000 0101 080a 4ddc 9219 4ddc
- 0x0040: 9219
-23:57:37.229575 IP 127.0.0.1.55920 > 127.0.0.1.80: F 203:203(0) ack 5560 win 12383 <nop,nop,timestamp 1306302241 1306300953>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500
- 0x0010: 0034 1b70 4000 4006 2152 7f00 0001 7f00
- 0x0020: 0001 da70 0050 3758 8a49 377a a3a9 8011
- 0x0030: 305f 0be1 0000 0101 080a 4ddc 9721 4ddc
- 0x0040: 9219
-23:57:37.230839 IP 127.0.0.1.80 > 127.0.0.1.55920: F 5560:5560(0) ack 204 win 8192 <nop,nop,timestamp 1306302243 1306302241>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500
- 0x0010: 0034 1fe8 4000 4006 1cda 7f00 0001 7f00
- 0x0020: 0001 0050 da70 377a a3a9 3758 8a4a 8011
- 0x0030: 2000 1735 0000 0101 080a 4ddc 9723 4ddc
- 0x0040: 9721
-23:57:37.230900 IP 127.0.0.1.55920 > 127.0.0.1.80: . ack 5561 win 12383 <nop,nop,timestamp 1306302243 1306302243>
- 0x0000: 0000 0000 0000 0000 0000 0000 0800 4500
- 0x0010: 0034 1b72 4000 4006 2150 7f00 0001 7f00
- 0x0020: 0001 da70 0050 3758 8a4a 377a a3aa 8010
- 0x0030: 305f 06d4 0000 0101 080a 4ddc 9723 4ddc
- 0x0040: 9723
diff --git a/contrib/tcpdump/tftp.h b/contrib/tcpdump/tftp.h
index 4408304..6285404 100644
--- a/contrib/tcpdump/tftp.h
+++ b/contrib/tcpdump/tftp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/tftp.h,v 1.1.2.1 2007/09/14 01:03:12 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/tftp.h,v 1.1.4.1 2008-04-11 16:44:17 gianluca Exp $ (LBL) */
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
@@ -49,7 +49,7 @@
#define WRQ 02 /* write request */
#define DATA 03 /* data packet */
#define ACK 04 /* acknowledgement */
-#define ERROR 05 /* error code */
+#define TFTP_ERROR 05 /* error code */
#define OACK 06 /* option acknowledgement */
struct tftphdr {
diff --git a/contrib/tcpdump/timed.h b/contrib/tcpdump/timed.h
index 0a5c5fe..15135e7 100644
--- a/contrib/tcpdump/timed.h
+++ b/contrib/tcpdump/timed.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/timed.h,v 1.5 2002/12/11 07:14:12 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/timed.h,v 1.5.6.1 2008-02-05 19:46:58 guy Exp $ (LBL) */
/*
* Copyright (c) 1983, 1993
* The Regents of the University of California. All rights reserved.
@@ -44,12 +44,17 @@
#define TSPVERSION 1
#define ANYADDR NULL
+struct tsp_timeval {
+ u_int32_t tv_sec;
+ u_int32_t tv_usec;
+};
+
struct tsp {
u_int8_t tsp_type;
u_int8_t tsp_vers;
u_int16_t tsp_seq;
union {
- struct timeval tspu_time;
+ struct tsp_timeval tspu_time;
int8_t tspu_hopcnt;
} tsp_u;
int8_t tsp_name[256];
diff --git a/contrib/tcpdump/token.h b/contrib/tcpdump/token.h
index e466c84..1525038 100644
--- a/contrib/tcpdump/token.h
+++ b/contrib/tcpdump/token.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/token.h,v 1.6 2002/12/11 07:14:12 guy Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/token.h,v 1.6 2002-12-11 07:14:12 guy Exp $ (LBL) */
/*
* Copyright (c) 1998, Larry Lile
* All rights reserved.
diff --git a/contrib/tcpdump/udp.h b/contrib/tcpdump/udp.h
index dedc9c1..fb45d68 100644
--- a/contrib/tcpdump/udp.h
+++ b/contrib/tcpdump/udp.h
@@ -1,4 +1,4 @@
-/* @(#) $Header: /tcpdump/master/tcpdump/udp.h,v 1.8.2.2 2007/03/28 07:45:46 hannes Exp $ (LBL) */
+/* @(#) $Header: /tcpdump/master/tcpdump/udp.h,v 1.13 2007-08-08 17:20:58 hannes Exp $ (LBL) */
/*
* Copyright (c) 1982, 1986, 1993
* The Regents of the University of California. All rights reserved.
@@ -76,11 +76,15 @@ struct udphdr {
#define HSRP_PORT 1985 /*XXX*/
#define LMP_PORT 701 /* rfc4204 */
#define LWRES_PORT 921
+#define VQP_PORT 1589
#define ZEPHYR_SRV_PORT 2103
#define ZEPHYR_CLT_PORT 2104
#define MPLS_LSP_PING_PORT 3503 /* draft-ietf-mpls-lsp-ping-02.txt */
#define BFD_CONTROL_PORT 3784 /* draft-katz-ward-bfd-v4v6-1hop-00.txt */
#define BFD_ECHO_PORT 3785 /* draft-katz-ward-bfd-v4v6-1hop-00.txt */
+#define SFLOW_PORT 6343 /* http://www.sflow.org/developers/specifications.php */
+#define LWAPP_DATA_PORT 12222 /* draft-ohara-capwap-lwapp-04.txt */
+#define LWAPP_CONTROL_PORT 12223 /* draft-ohara-capwap-lwapp-04.txt */
#ifdef INET6
#define RIPNG_PORT 521 /*XXX*/
diff --git a/contrib/tcpdump/util.c b/contrib/tcpdump/util.c
index 912f6f3..6b723e5 100644
--- a/contrib/tcpdump/util.c
+++ b/contrib/tcpdump/util.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/util.c,v 1.95.2.6 2006/02/08 01:40:09 hannes Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/util.c,v 1.109 2007-01-29 09:59:42 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
@@ -44,6 +44,8 @@ static const char rcsid[] _U_ =
#include "interface.h"
+char * ts_format(register int, register int);
+
/*
* Print out a null-terminated filename (or other ascii string).
* If ep is NULL, assume no truncation check is needed.
@@ -139,6 +141,19 @@ fn_printzp(register const u_char *s, register u_int n,
}
/*
+ * Format the timestamp
+ */
+char *
+ts_format(register int sec, register int usec)
+{
+ static char buf[sizeof("00:00:00.000000")];
+ (void)snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%06u",
+ sec / 3600, (sec % 3600) / 60, sec % 60, usec);
+
+ return buf;
+}
+
+/*
* Print the timestamp
*/
void
@@ -149,14 +164,14 @@ ts_print(register const struct timeval *tvp)
time_t Time;
static unsigned b_sec;
static unsigned b_usec;
+ int d_usec;
+ int d_sec;
switch (tflag) {
case 0: /* Default */
s = (tvp->tv_sec + thiszone) % 86400;
- (void)printf("%02d:%02d:%02d.%06u ",
- s / 3600, (s % 3600) / 60, s % 60,
- (unsigned)tvp->tv_usec);
+ (void)printf("%s ", ts_format(s, tvp->tv_usec));
break;
case 1: /* No time stamp */
@@ -169,22 +184,27 @@ ts_print(register const struct timeval *tvp)
break;
case 3: /* Microseconds since previous packet */
+ case 5: /* Microseconds since first packet */
if (b_sec == 0) {
- printf("000000 ");
- } else {
- int d_usec = tvp->tv_usec - b_usec;
- int d_sec = tvp->tv_sec - b_sec;
-
- while (d_usec < 0) {
- d_usec += 1000000;
- d_sec--;
- }
- if (d_sec)
- printf("%d. ", d_sec);
- printf("%06d ", d_usec);
- }
- b_sec = tvp->tv_sec;
- b_usec = tvp->tv_usec;
+ /* init timestamp for first packet */
+ b_usec = tvp->tv_usec;
+ b_sec = tvp->tv_sec;
+ }
+
+ d_usec = tvp->tv_usec - b_usec;
+ d_sec = tvp->tv_sec - b_sec;
+
+ while (d_usec < 0) {
+ d_usec += 1000000;
+ d_sec--;
+ }
+
+ (void)printf("%s ", ts_format(d_sec, d_usec));
+
+ if (tflag == 3) { /* set timestamp for last packet */
+ b_sec = tvp->tv_sec;
+ b_usec = tvp->tv_usec;
+ }
break;
case 4: /* Default + Date*/
@@ -194,10 +214,9 @@ ts_print(register const struct timeval *tvp)
if (!tm)
printf("Date fail ");
else
- printf("%04d-%02d-%02d ",
- tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
- printf("%02d:%02d:%02d.%06u ",
- s / 3600, (s % 3600) / 60, s % 60, (unsigned)tvp->tv_usec);
+ printf("%04d-%02d-%02d %s ",
+ tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
+ ts_format(s, tvp->tv_usec));
break;
}
}
@@ -297,11 +316,12 @@ tok2str(register const struct tok *lp, register const char *fmt,
/*
* Convert a bit token value to a string; use "fmt" if not found.
- * this is useful for parsing bitfields, the output strings are comma seperated
+ * this is useful for parsing bitfields, the output strings are seperated
+ * if the s field is positive.
*/
-char *
-bittok2str(register const struct tok *lp, register const char *fmt,
- register int v)
+static char *
+bittok2str_internal(register const struct tok *lp, register const char *fmt,
+ register int v, register int sep)
{
static char buf[256]; /* our stringbuffer */
int buflen=0;
@@ -318,7 +338,8 @@ bittok2str(register const struct tok *lp, register const char *fmt,
*/
if (tokval == (v&rotbit)) {
/* ok we have found something */
- buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s, ",lp->s);
+ buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s",
+ lp->s, sep ? ", " : "");
break;
}
rotbit=rotbit<<1; /* no match - lets shift and try again */
@@ -326,6 +347,11 @@ bittok2str(register const struct tok *lp, register const char *fmt,
lp++;
}
+ /* user didn't want string seperation - no need to cut off trailing seperators */
+ if (!sep) {
+ return (buf);
+ }
+
if (buflen != 0) { /* did we find anything */
/* yep, set the the trailing zero 2 bytes before to eliminate the last comma & whitespace */
buf[buflen-2] = '\0';
@@ -341,6 +367,28 @@ bittok2str(register const struct tok *lp, register const char *fmt,
}
/*
+ * Convert a bit token value to a string; use "fmt" if not found.
+ * this is useful for parsing bitfields, the output strings are not seperated.
+ */
+char *
+bittok2str_nosep(register const struct tok *lp, register const char *fmt,
+ register int v)
+{
+ return (bittok2str_internal(lp, fmt, v, 0));
+}
+
+/*
+ * Convert a bit token value to a string; use "fmt" if not found.
+ * this is useful for parsing bitfields, the output strings are comma seperated.
+ */
+char *
+bittok2str(register const struct tok *lp, register const char *fmt,
+ register int v)
+{
+ return (bittok2str_internal(lp, fmt, v, 1));
+}
+
+/*
* Convert a value to a string using an array; the macro
* tok2strary() in <interface.h> is the public interface to
* this function and ensures that the second argument is
@@ -509,7 +557,8 @@ read_infile(char *fname)
void
safeputs(const char *s, int maxlen)
{
- int idx = 0;
+ int idx = 0;
+
while (*s && idx < maxlen) {
safeputchar(*s);
idx++;
@@ -526,5 +575,5 @@ safeputchar(int c)
if (ch < 0x80 && isprint(ch))
printf("%c", ch);
else
- printf("\\%03o", ch);
+ printf("\\0x%02x", ch);
}
diff --git a/contrib/tcpdump/vfprintf.c b/contrib/tcpdump/vfprintf.c
index 354406c..6f8407a 100644
--- a/contrib/tcpdump/vfprintf.c
+++ b/contrib/tcpdump/vfprintf.c
@@ -21,7 +21,7 @@
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/vfprintf.c,v 1.6 2003/11/16 09:36:45 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/tcpdump/vfprintf.c,v 1.6 2003-11-16 09:36:45 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
diff --git a/contrib/wpa/hostapd/wme.h b/contrib/wpa/hostapd/wme.h
index 4ee281a..3c80c01 100644
--- a/contrib/wpa/hostapd/wme.h
+++ b/contrib/wpa/hostapd/wme.h
@@ -27,7 +27,7 @@
* defined(__DragonFly__) */
-extern inline u16 tsinfo(int tag1d, int contention_based, int direction)
+static inline u16 tsinfo(int tag1d, int contention_based, int direction)
{
return (tag1d << 11) | (contention_based << 7) | (direction << 5) |
(tag1d << 1);
diff --git a/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c b/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
index bf6328e..9f54486 100644
--- a/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
+++ b/contrib/wpa/wpa_supplicant/ctrl_iface_unix.c
@@ -16,6 +16,7 @@
#include <sys/un.h>
#include <sys/stat.h>
#include <grp.h>
+#include <stddef.h>
#include "common.h"
#include "eloop.h"
@@ -69,7 +70,8 @@ static int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv,
dst->next = priv->ctrl_dst;
priv->ctrl_dst = dst;
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
- (u8 *) from->sun_path, fromlen - sizeof(from->sun_family));
+ (u8 *) from->sun_path,
+ fromlen - offsetof(struct sockaddr_un, sun_path));
return 0;
}
@@ -84,7 +86,7 @@ static int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv,
while (dst) {
if (fromlen == dst->addrlen &&
os_memcmp(from->sun_path, dst->addr.sun_path,
- fromlen - sizeof(from->sun_family)) == 0) {
+ fromlen - offsetof(struct sockaddr_un, sun_path)) == 0) {
if (prev == NULL)
priv->ctrl_dst = dst->next;
else
@@ -92,7 +94,7 @@ static int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv,
os_free(dst);
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
(u8 *) from->sun_path,
- fromlen - sizeof(from->sun_family));
+ fromlen - offsetof(struct sockaddr_un, sun_path));
return 0;
}
prev = dst;
@@ -115,10 +117,10 @@ static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
while (dst) {
if (fromlen == dst->addrlen &&
os_memcmp(from->sun_path, dst->addr.sun_path,
- fromlen - sizeof(from->sun_family)) == 0) {
+ fromlen - offsetof(struct sockaddr_un, sun_path)) == 0) {
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
"level", (u8 *) from->sun_path,
- fromlen - sizeof(from->sun_family));
+ fromlen - offsetof(struct sockaddr_un, sun_path));
dst->debug_level = atoi(level);
return 0;
}
@@ -339,6 +341,8 @@ wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
}
os_memset(&addr, 0, sizeof(addr));
+ /* XXX #ifdef */
+ addr.sun_len = sizeof(addr);
addr.sun_family = AF_UNIX;
fname = wpa_supplicant_ctrl_iface_path(wpa_s);
if (fname == NULL)
@@ -509,8 +513,8 @@ static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
next = dst->next;
if (level >= dst->debug_level) {
wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
- (u8 *) dst->addr.sun_path, dst->addrlen -
- sizeof(dst->addr.sun_family));
+ (u8 *) dst->addr.sun_path,
+ dst->addrlen - offsetof(struct sockaddr_un, sun_path));
msg.msg_name = (void *) &dst->addr;
msg.msg_namelen = dst->addrlen;
if (sendmsg(priv->sock, &msg, 0) < 0) {
@@ -637,6 +641,8 @@ wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
}
os_memset(&addr, 0, sizeof(addr));
+ /* XXX #ifdef */
+ addr.sun_len = sizeof(addr);
addr.sun_family = AF_UNIX;
os_strlcpy(addr.sun_path, global->params.ctrl_interface,
sizeof(addr.sun_path));
diff --git a/contrib/wpa/wpa_supplicant/wpa_supplicant.conf b/contrib/wpa/wpa_supplicant/wpa_supplicant.conf
index 43e81a1..f5143c8 100644
--- a/contrib/wpa/wpa_supplicant/wpa_supplicant.conf
+++ b/contrib/wpa/wpa_supplicant/wpa_supplicant.conf
@@ -1,5 +1,7 @@
##### Example wpa_supplicant configuration file ###############################
#
+# ***** Please check wpa_supplicant.conf(5) for details on these options *****
+#
# This file describes configuration file format and lists all available option.
# Please also take a look at simpler configuration examples in 'examples'
# subdirectory.
@@ -59,19 +61,6 @@
# DIR=/var/run/wpa_supplicant GROUP=0
# (group can be either group name or gid)
#
-# For UDP connections (default on Windows): The value will be ignored. This
-# variable is just used to select that the control interface is to be created.
-# The value can be set to, e.g., udp (ctrl_interface=udp)
-#
-# For Windows Named Pipe: This value can be used to set the security descriptor
-# for controlling access to the control interface. Security descriptor can be
-# set using Security Descriptor String Format (see http://msdn.microsoft.com/
-# library/default.asp?url=/library/en-us/secauthz/security/
-# security_descriptor_string_format.asp). The descriptor string needs to be
-# prefixed with SDDL=. For example, ctrl_interface=SDDL=D: would set an empty
-# DACL (which will reject all connections). See README-Windows.txt for more
-# information about SDDL string format.
-#
ctrl_interface=/var/run/wpa_supplicant
# IEEE 802.1X/EAPOL version
@@ -102,6 +91,8 @@ eapol_version=1
# the driver reports successful association; each network block should have
# explicit security policy (i.e., only one option in the lists) for
# key_mgmt, pairwise, group, proto variables
+#
+# For use in FreeBSD with the wlan module ap_scan must be set to 1.
ap_scan=1
# EAP fast re-authentication
@@ -221,7 +212,7 @@ fast_reauth=1
# scan_ssid:
# 0 = do not scan this SSID with specific Probe Request frames (default)
# 1 = scan with SSID-specific Probe Request frames (this can be used to
-# find APs that do not accept broadcast SSID or use multiple SSIDs;
+# find APs that hide (do not broadcast) SSID or use multiple SSIDs;
# this will add latency to scanning, so enable this only when needed)
#
# bssid: BSSID (optional); if set, this network block is used only when
@@ -237,7 +228,7 @@ fast_reauth=1
# policy, signal strength, etc.
# Please note that AP scanning with scan_ssid=1 and ap_scan=2 mode are not
# using this priority to select the order for scanning. Instead, they try the
-# networks in the order that used in the configuration file.
+# networks in the order that they are listed in the configuration file.
#
# mode: IEEE 802.11 operation mode
# 0 = infrastructure (Managed) mode, i.e., associate with an AP (default)
diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf
index 17c9f37..c7740a1 100644
--- a/etc/defaults/rc.conf
+++ b/etc/defaults/rc.conf
@@ -101,7 +101,7 @@ nisdomainname="NO" # Set to NIS domain if using NIS (or NO).
dhclient_program="/sbin/dhclient" # Path to dhcp client program.
dhclient_flags="" # Extra flags to pass to dhcp client.
#dhclient_flags_fxp0="" # Extra dhclient flags for fxp0 only
-background_dhclient="YES" # Start dhcp client in the background.
+background_dhclient="NO" # Start dhcp client in the background.
#background_dhclient_fxp0="YES" # Start dhcp client on fxp0 in the background.
synchronous_dhclient="NO" # Start dhclient directly on configured
# interfaces during startup.
@@ -197,6 +197,7 @@ ifconfig_lo0="inet 127.0.0.1" # default loopback device configuration.
#ifconfig_ed0_ipx="ipx 0x00010010" # Sample IPX address family entry.
#ifconfig_fxp0_name="net0" # Change interface name from fxp0 to net0.
#wlans_ath0="wlan0" # wlan(4) interfaces for ath0 device
+#wlandebug_wlan0="scan+auth+assoc" # Set debug flags with wlanddebug(8)
#ipv4_addrs_fxp0="192.168.0.1/24 192.168.1.1-5/28" # example IPv4 address entry.
#
#autobridge_interfaces="bridge0" # List of bridges to check
diff --git a/etc/mail/aliases b/etc/mail/aliases
index 682f878..ae0e7f1 100644
--- a/etc/mail/aliases
+++ b/etc/mail/aliases
@@ -11,6 +11,7 @@
#
# See also RFC 2142, `MAILBOX NAMES FOR COMMON SERVICES, ROLES
# AND FUNCTIONS', May 1997
+# http://tools.ietf.org/html/rfc2142
# Pretty much everything else in this file points to "root", so
# you would do well in either reading root's mailbox or forwarding
diff --git a/etc/mtree/BSD.include.dist b/etc/mtree/BSD.include.dist
index 8ea1eee..6358071 100644
--- a/etc/mtree/BSD.include.dist
+++ b/etc/mtree/BSD.include.dist
@@ -257,6 +257,8 @@
..
openssl
..
+ pcap
+ ..
protocols
..
readline
diff --git a/etc/netstart b/etc/netstart
index b964663..161db02 100755
--- a/etc/netstart
+++ b/etc/netstart
@@ -40,6 +40,7 @@ load_rc_config 'XXX'
_start=quietstart
/etc/rc.d/devd ${_start}
+/etc/rc.d/hostid ${_start}
/etc/rc.d/hostname ${_start}
/etc/rc.d/ipmon ${_start}
/etc/rc.d/ipfilter ${_start}
diff --git a/etc/network.subr b/etc/network.subr
index 0a64f96..66fe250 100644
--- a/etc/network.subr
+++ b/etc/network.subr
@@ -499,7 +499,7 @@ clone_down()
#
childif_create()
{
- local cfg child child_wlans create_args ifn i
+ local cfg child child_wlans create_args debug_flags ifn i
cfg=1
ifn=$1
@@ -509,10 +509,18 @@ childif_create()
for child in ${child_wlans}; do
create_args="wlandev $ifn `get_if_var $child create_args_IF`"
+ debug_flags="`get_if_var $child wlandebug_IF`"
+
if expr $child : 'wlan[0-9][0-9]*$' >/dev/null 2>&1; then
ifconfig $child create ${create_args} && cfg=0
+ if [ -n "${debug_flags}" ]; then
+ wlandebug -i $child ${debug_flags}
+ fi
else
i=`ifconfig wlan create ${create_args}`
+ if [ -n "${debug_flags}" ]; then
+ wlandebug -i $i ${debug_flags}
+ fi
ifconfig $i name $child && cfg=0
fi
if autoif $child; then
diff --git a/etc/rc.d/ipfw b/etc/rc.d/ipfw
index 44af170..2780943 100755
--- a/etc/rc.d/ipfw
+++ b/etc/rc.d/ipfw
@@ -23,10 +23,20 @@ ipfw_prestart()
if checkyesno dummynet_enable; then
required_modules="$required_modules dummynet"
fi
+
+ if checkyesno firewall_nat_enable; then
+ if ! checkyesno natd_enable; then
+ required_modules="$required_modules ipfw_nat"
+ fi
+ fi
}
ipfw_start()
{
+ local _firewall_type
+
+ _firewall_type=$1
+
# set the firewall rules script if none was specified
[ -z "${firewall_script}" ] && firewall_script=/etc/rc.firewall
@@ -34,7 +44,7 @@ ipfw_start()
if [ -f /etc/rc.d/natd ] ; then
/etc/rc.d/natd quietstart
fi
- /bin/sh "${firewall_script}"
+ /bin/sh "${firewall_script}" "${_firewall_type}"
echo 'Firewall rules loaded.'
elif [ "`ipfw list 65535`" = "65535 deny ip from any to any" ]; then
echo 'Warning: kernel has firewall functionality, but' \
@@ -67,4 +77,4 @@ ipfw_stop()
}
load_rc_config $name
-run_rc_command "$1"
+run_rc_command $*
diff --git a/gnu/usr.bin/cc/Makefile.inc b/gnu/usr.bin/cc/Makefile.inc
index 2281f74..d7ed8a8 100644
--- a/gnu/usr.bin/cc/Makefile.inc
+++ b/gnu/usr.bin/cc/Makefile.inc
@@ -18,6 +18,7 @@ GCC_TARGET= ${TARGET_ARCH}-undermydesk-freebsd
CFLAGS+= -DIN_GCC -DHAVE_CONFIG_H
CFLAGS+= -DPREFIX=\"${TOOLS_PREFIX}/usr\"
#CFLAGS+= -DWANT_COMPILER_INVARIANTS
+CSTD?= gnu89
# If building 64-bit longs for the i386, "_LARGE_LONG" should also be defined
# to get the proper sizes in limits.h
diff --git a/include/arpa/inet.h b/include/arpa/inet.h
index b670836..0848106 100644
--- a/include/arpa/inet.h
+++ b/include/arpa/inet.h
@@ -148,7 +148,6 @@ uint16_t ntohs(uint16_t);
in_addr_t inet_addr(const char *);
/*const*/ char *inet_ntoa(struct in_addr);
-char *inet_ntoa_r(struct in_addr, char *buf, socklen_t size);
const char *inet_ntop(int, const void * __restrict, char * __restrict,
socklen_t);
int inet_pton(int, const char * __restrict, void * __restrict);
@@ -162,6 +161,7 @@ in_addr_t inet_netof(struct in_addr);
in_addr_t inet_network(const char *);
char *inet_net_ntop(int, const void *, int, char *, size_t);
int inet_net_pton(int, const char *, void *, size_t);
+char *inet_ntoa_r(struct in_addr, char *buf, socklen_t size);
char *inet_cidr_ntop(int, const void *, int, char *, size_t);
int inet_cidr_pton(int, const char *, void *, int *);
unsigned inet_nsap_addr(const char *, unsigned char *, int);
diff --git a/include/ctype.h b/include/ctype.h
index dfc89cc..103619c 100644
--- a/include/ctype.h
+++ b/include/ctype.h
@@ -65,8 +65,6 @@ int tolower(int);
int toupper(int);
#if __XSI_VISIBLE
-int _tolower(int);
-int _toupper(int);
int isascii(int);
int toascii(int);
#endif
diff --git a/include/db.h b/include/db.h
index c192a88..e845fa8 100644
--- a/include/db.h
+++ b/include/db.h
@@ -47,11 +47,11 @@
#define RET_SPECIAL 1
#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */
-typedef u_int32_t pgno_t;
+typedef uint32_t pgno_t;
#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */
-typedef u_int16_t indx_t;
+typedef uint16_t indx_t;
#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */
-typedef u_int32_t recno_t;
+typedef uint32_t recno_t;
/* Key/data structure -- a Data-Base Thang. */
typedef struct {
@@ -101,11 +101,11 @@ typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
typedef struct __db {
DBTYPE type; /* Underlying db type. */
int (*close)(struct __db *);
- int (*del)(const struct __db *, const DBT *, u_int);
- int (*get)(const struct __db *, const DBT *, DBT *, u_int);
- int (*put)(const struct __db *, DBT *, const DBT *, u_int);
- int (*seq)(const struct __db *, DBT *, DBT *, u_int);
- int (*sync)(const struct __db *, u_int);
+ int (*del)(const struct __db *, const DBT *, unsigned int);
+ int (*get)(const struct __db *, const DBT *, DBT *, unsigned int);
+ int (*put)(const struct __db *, DBT *, const DBT *, unsigned int);
+ int (*seq)(const struct __db *, DBT *, DBT *, unsigned int);
+ int (*sync)(const struct __db *, unsigned int);
void *internal; /* Access method private. */
int (*fd)(const struct __db *);
} DB;
@@ -116,16 +116,16 @@ typedef struct __db {
/* Structure used to pass parameters to the btree routines. */
typedef struct {
#define R_DUP 0x01 /* duplicate keys */
- u_long flags;
- u_int cachesize; /* bytes to cache */
- int maxkeypage; /* maximum keys per page */
- int minkeypage; /* minimum keys per page */
- u_int psize; /* page size */
- int (*compare) /* comparison function */
- (const DBT *, const DBT *);
- size_t (*prefix) /* prefix function */
- (const DBT *, const DBT *);
- int lorder; /* byte order */
+ unsigned long flags;
+ unsigned int cachesize; /* bytes to cache */
+ int maxkeypage; /* maximum keys per page */
+ int minkeypage; /* minimum keys per page */
+ unsigned int psize; /* page size */
+ int (*compare) /* comparison function */
+ (const DBT *, const DBT *);
+ size_t (*prefix) /* prefix function */
+ (const DBT *, const DBT *);
+ int lorder; /* byte order */
} BTREEINFO;
#define HASHMAGIC 0x061561
@@ -133,11 +133,11 @@ typedef struct {
/* Structure used to pass parameters to the hashing routines. */
typedef struct {
- u_int bsize; /* bucket size */
- u_int ffactor; /* fill factor */
- u_int nelem; /* number of elements */
- u_int cachesize; /* bytes to cache */
- u_int32_t /* hash function */
+ unsigned int bsize; /* bucket size */
+ unsigned int ffactor; /* fill factor */
+ unsigned int nelem; /* number of elements */
+ unsigned int cachesize; /* bytes to cache */
+ uint32_t /* hash function */
(*hash)(const void *, size_t);
int lorder; /* byte order */
} HASHINFO;
@@ -147,12 +147,12 @@ typedef struct {
#define R_FIXEDLEN 0x01 /* fixed-length records */
#define R_NOKEY 0x02 /* key not required */
#define R_SNAPSHOT 0x04 /* snapshot the input */
- u_long flags;
- u_int cachesize; /* bytes to cache */
- u_int psize; /* page size */
- int lorder; /* byte order */
- size_t reclen; /* record length (fixed-length records) */
- u_char bval; /* delimiting byte (variable-length records */
+ unsigned long flags;
+ unsigned int cachesize; /* bytes to cache */
+ unsigned int psize; /* page size */
+ int lorder; /* byte order */
+ size_t reclen; /* record length (fixed-length records) */
+ unsigned char bval; /* delimiting byte (variable-length records */
char *bfname; /* btree file name */
} RECNOINFO;
@@ -164,14 +164,14 @@ typedef struct {
* P_32_COPY swap from one location to another
*/
#define M_32_SWAP(a) { \
- u_int32_t _tmp = a; \
+ uint32_t _tmp = a; \
((char *)&a)[0] = ((char *)&_tmp)[3]; \
((char *)&a)[1] = ((char *)&_tmp)[2]; \
((char *)&a)[2] = ((char *)&_tmp)[1]; \
((char *)&a)[3] = ((char *)&_tmp)[0]; \
}
#define P_32_SWAP(a) { \
- u_int32_t _tmp = *(u_int32_t *)a; \
+ uint32_t _tmp = *(uint32_t *)a; \
((char *)a)[0] = ((char *)&_tmp)[3]; \
((char *)a)[1] = ((char *)&_tmp)[2]; \
((char *)a)[2] = ((char *)&_tmp)[1]; \
@@ -191,12 +191,12 @@ typedef struct {
* P_16_COPY swap from one location to another
*/
#define M_16_SWAP(a) { \
- u_int16_t _tmp = a; \
+ uint16_t _tmp = a; \
((char *)&a)[0] = ((char *)&_tmp)[1]; \
((char *)&a)[1] = ((char *)&_tmp)[0]; \
}
#define P_16_SWAP(a) { \
- u_int16_t _tmp = *(u_int16_t *)a; \
+ uint16_t _tmp = *(uint16_t *)a; \
((char *)a)[0] = ((char *)&_tmp)[1]; \
((char *)a)[1] = ((char *)&_tmp)[0]; \
}
@@ -207,7 +207,9 @@ typedef struct {
#endif
__BEGIN_DECLS
+#if __BSD_VISIBLE
DB *dbopen(const char *, int, int, DBTYPE, const void *);
+#endif
#ifdef __DBINTERFACE_PRIVATE
DB *__bt_open(const char *, int, int, const BTREEINFO *, int);
diff --git a/include/dlfcn.h b/include/dlfcn.h
index 38f21b2..9fac620 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -47,6 +47,7 @@
#define RTLD_GLOBAL 0x100 /* Make symbols globally available. */
#define RTLD_LOCAL 0 /* Opposite of RTLD_GLOBAL, and the default. */
#define RTLD_TRACE 0x200 /* Trace loaded objects and exit. */
+#define RTLD_NODELETE 0x01000 /* Do not remove members. */
/*
* Request arguments for dlinfo().
diff --git a/include/grp.h b/include/grp.h
index 70b4a8a24..96584de 100644
--- a/include/grp.h
+++ b/include/grp.h
@@ -74,9 +74,11 @@ struct group *getgrnam(const char *);
#if __BSD_VISIBLE
const char *group_from_gid(gid_t, int);
#endif
-#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE
+#if __BSD_VISIBLE || __XSI_VISIBLE
/* XXX IEEE Std 1003.1, 2003 specifies `void setgrent(void)' */
int setgrent(void);
+#endif
+#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE
int getgrgid_r(gid_t, struct group *, char *, size_t,
struct group **);
int getgrnam_r(const char *, struct group *, char *, size_t,
diff --git a/include/mpool.h b/include/mpool.h
index b5be330..c74764d 100644
--- a/include/mpool.h
+++ b/include/mpool.h
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)mpool.h 8.2 (Berkeley) 7/14/94
+ * @(#)mpool.h 8.4 (Berkeley) 11/2/95
* $FreeBSD$
*/
@@ -47,7 +47,7 @@
* pool is handed an opaque MPOOL cookie which stores all of this information.
*/
#define HASHSIZE 128
-#define HASHKEY(pgno) ((pgno - 1) % HASHSIZE)
+#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE)
/* The BKT structures are the elements of the queues. */
typedef struct _bkt {
@@ -58,6 +58,7 @@ typedef struct _bkt {
#define MPOOL_DIRTY 0x01 /* page needs to be written */
#define MPOOL_PINNED 0x02 /* page is pinned into memory */
+#define MPOOL_INUSE 0x04 /* page address is valid */
u_int8_t flags; /* flags */
} BKT;
@@ -68,7 +69,7 @@ typedef struct MPOOL {
pgno_t curcache; /* current number of cached pages */
pgno_t maxcache; /* max number of cached pages */
pgno_t npages; /* number of pages in the file */
- u_long pagesize; /* file page size */
+ unsigned long pagesize; /* file page size */
int fd; /* file descriptor */
/* page in conversion routine */
void (*pgin)(void *, pgno_t, void *);
@@ -76,25 +77,32 @@ typedef struct MPOOL {
void (*pgout)(void *, pgno_t, void *);
void *pgcookie; /* cookie for page in/out routines */
#ifdef STATISTICS
- u_long cachehit;
- u_long cachemiss;
- u_long pagealloc;
- u_long pageflush;
- u_long pageget;
- u_long pagenew;
- u_long pageput;
- u_long pageread;
- u_long pagewrite;
+ unsigned long cachehit;
+ unsigned long cachemiss;
+ unsigned long pagealloc;
+ unsigned long pageflush;
+ unsigned long pageget;
+ unsigned long pagenew;
+ unsigned long pageput;
+ unsigned long pageread;
+ unsigned long pagewrite;
#endif
} MPOOL;
+#define MPOOL_IGNOREPIN 0x01 /* Ignore if the page is pinned. */
+#define MPOOL_PAGE_REQUEST 0x01 /* Allocate a new page with a
+ specific page number. */
+#define MPOOL_PAGE_NEXT 0x02 /* Allocate a new page with the next
+ page number. */
+
__BEGIN_DECLS
MPOOL *mpool_open(void *, int, pgno_t, pgno_t);
void mpool_filter(MPOOL *, void (*)(void *, pgno_t, void *),
void (*)(void *, pgno_t, void *), void *);
-void *mpool_new(MPOOL *, pgno_t *);
-void *mpool_get(MPOOL *, pgno_t, u_int);
-int mpool_put(MPOOL *, void *, u_int);
+void *mpool_new(MPOOL *, pgno_t *, unsigned int);
+void *mpool_get(MPOOL *, pgno_t, unsigned int);
+int mpool_delete(MPOOL *, void *);
+int mpool_put(MPOOL *, void *, unsigned int);
int mpool_sync(MPOOL *);
int mpool_close(MPOOL *);
#ifdef STATISTICS
diff --git a/include/ndbm.h b/include/ndbm.h
index e144ba8..1277e70 100644
--- a/include/ndbm.h
+++ b/include/ndbm.h
@@ -70,11 +70,15 @@ int dbm_delete(DBM *, datum);
int dbm_error(DBM *);
datum dbm_fetch(DBM *, datum);
datum dbm_firstkey(DBM *);
+#if __BSD_VISIBLE
long dbm_forder(DBM *, datum);
+#endif
datum dbm_nextkey(DBM *);
DBM *dbm_open(const char *, int, int);
int dbm_store(DBM *, datum, datum, int);
+#if __BSD_VISIBLE
int dbm_dirfno(DBM *);
+#endif
__END_DECLS
#endif /* !_NDBM_H_ */
diff --git a/include/netdb.h b/include/netdb.h
index cd7fc74..1c9ef27 100644
--- a/include/netdb.h
+++ b/include/netdb.h
@@ -217,67 +217,73 @@ struct addrinfo {
__BEGIN_DECLS
void endhostent(void);
void endnetent(void);
-void endnetgrent(void);
void endprotoent(void);
void endservent(void);
-void freehostent(struct hostent *);
+#if __BSD_VISIBLE || (__POSIX_VISIBLE && __POSIX_VISIBLE <= 200112)
struct hostent *gethostbyaddr(const void *, socklen_t, int);
+struct hostent *gethostbyname(const char *);
+#endif
+struct hostent *gethostent(void);
+struct netent *getnetbyaddr(uint32_t, int);
+struct netent *getnetbyname(const char *);
+struct netent *getnetent(void);
+struct protoent *getprotobyname(const char *);
+struct protoent *getprotobynumber(int);
+struct protoent *getprotoent(void);
+struct servent *getservbyname(const char *, const char *);
+struct servent *getservbyport(int, const char *);
+struct servent *getservent(void);
+void sethostent(int);
+/* void sethostfile(const char *); */
+void setnetent(int);
+void setprotoent(int);
+int getaddrinfo(const char *, const char *,
+ const struct addrinfo *, struct addrinfo **);
+int getnameinfo(const struct sockaddr *, socklen_t, char *,
+ size_t, char *, size_t, int);
+void freeaddrinfo(struct addrinfo *);
+const char *gai_strerror(int);
+void setservent(int);
+
+#if __BSD_VISIBLE
+void endnetgrent(void);
+void freehostent(struct hostent *);
int gethostbyaddr_r(const void *, socklen_t, int, struct hostent *,
char *, size_t, struct hostent **, int *);
-struct hostent *gethostbyname(const char *);
int gethostbyname_r(const char *, struct hostent *, char *, size_t,
struct hostent **, int *);
struct hostent *gethostbyname2(const char *, int);
int gethostbyname2_r(const char *, int, struct hostent *, char *,
size_t, struct hostent **, int *);
-struct hostent *gethostent(void);
int gethostent_r(struct hostent *, char *, size_t,
struct hostent **, int *);
struct hostent *getipnodebyaddr(const void *, size_t, int, int *);
struct hostent *getipnodebyname(const char *, int, int, int *);
-struct netent *getnetbyaddr(uint32_t, int);
int getnetbyaddr_r(uint32_t, int, struct netent *, char *, size_t,
struct netent**, int *);
-struct netent *getnetbyname(const char *);
int getnetbyname_r(const char *, struct netent *, char *, size_t,
struct netent **, int *);
-struct netent *getnetent(void);
int getnetent_r(struct netent *, char *, size_t, struct netent **,
int *);
int getnetgrent(char **, char **, char **);
-struct protoent *getprotobyname(const char *);
int getprotobyname_r(const char *, struct protoent *, char *,
size_t, struct protoent **);
-struct protoent *getprotobynumber(int);
int getprotobynumber_r(int, struct protoent *, char *, size_t,
struct protoent **);
-struct protoent *getprotoent(void);
int getprotoent_r(struct protoent *, char *, size_t,
struct protoent **);
-struct servent *getservbyname(const char *, const char *);
int getservbyname_r(const char *, const char *, struct servent *,
char *, size_t, struct servent **);
-struct servent *getservbyport(int, const char *);
int getservbyport_r(int, const char *, struct servent *, char *,
size_t, struct servent **);
-struct servent *getservent(void);
int getservent_r(struct servent *, char *, size_t,
struct servent **);
void herror(const char *);
__const char *hstrerror(int);
int innetgr(const char *, const char *, const char *, const char *);
-void sethostent(int);
-/* void sethostfile(const char *); */
-void setnetent(int);
-void setprotoent(int);
-int getaddrinfo(const char *, const char *,
- const struct addrinfo *, struct addrinfo **);
-int getnameinfo(const struct sockaddr *, socklen_t, char *,
- size_t, char *, size_t, int);
-void freeaddrinfo(struct addrinfo *);
-const char *gai_strerror(int);
void setnetgrent(const char *);
-void setservent(int);
+#endif
+
/*
* PRIVATE functions specific to the FreeBSD implementation
diff --git a/include/pthread.h b/include/pthread.h
index fad12b1..9edd48b 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -205,7 +205,6 @@ int pthread_join(pthread_t, void **);
int pthread_key_create(pthread_key_t *,
void (*) (void *));
int pthread_key_delete(pthread_key_t);
-int pthread_kill(pthread_t, int);
int pthread_mutexattr_init(pthread_mutexattr_t *);
int pthread_mutexattr_destroy(pthread_mutexattr_t *);
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *,
@@ -241,7 +240,6 @@ int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
pthread_t pthread_self(void);
int pthread_setspecific(pthread_key_t, const void *);
-int pthread_sigmask(int, const __sigset_t *, __sigset_t *);
int pthread_spin_init(pthread_spinlock_t *, int);
int pthread_spin_destroy(pthread_spinlock_t *);
@@ -253,9 +251,11 @@ int pthread_setcancelstate(int, int *);
int pthread_setcanceltype(int, int *);
void pthread_testcancel(void);
+#if __BSD_VISIBLE
int pthread_getprio(pthread_t);
int pthread_setprio(pthread_t, int);
void pthread_yield(void);
+#endif
int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *,
int *);
@@ -281,8 +281,10 @@ int pthread_getschedparam(pthread_t pthread, int *,
struct sched_param *);
int pthread_setschedparam(pthread_t, int,
const struct sched_param *);
+#if __XSI_VISIBLE
int pthread_getconcurrency(void);
int pthread_setconcurrency(int);
+#endif
void __pthread_cleanup_push_imp(void (*)(void *), void *,
struct _pthread_cleanup_info *);
diff --git a/include/pwd.h b/include/pwd.h
index 4503ddb..6906db8 100644
--- a/include/pwd.h
+++ b/include/pwd.h
@@ -152,10 +152,13 @@ __BEGIN_DECLS
struct passwd *getpwnam(const char *);
struct passwd *getpwuid(uid_t);
-#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500
+#if __XSI_VISIBLE >= 500
void endpwent(void);
struct passwd *getpwent(void);
void setpwent(void);
+#endif
+
+#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500
int getpwnam_r(const char *, struct passwd *, char *, size_t,
struct passwd **);
int getpwuid_r(uid_t, struct passwd *, char *, size_t,
diff --git a/include/setjmp.h b/include/setjmp.h
index 9564411..9e25f60 100644
--- a/include/setjmp.h
+++ b/include/setjmp.h
@@ -48,7 +48,7 @@
#include <machine/setjmp.h>
__BEGIN_DECLS
-#if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE
+#if __BSD_VISIBLE || __XSI_VISIBLE >= 600
void _longjmp(jmp_buf, int) __dead2;
int _setjmp(jmp_buf);
#endif
diff --git a/include/signal.h b/include/signal.h
index 8d7c281..7ad494d 100644
--- a/include/signal.h
+++ b/include/signal.h
@@ -58,11 +58,24 @@ typedef __pid_t pid_t;
#endif
#endif
+#if __POSIX_VISIBLE || __XSI_VISIBLE
+struct pthread; /* XXX */
+typedef struct pthread *__pthread_t;
+#if !defined(_PTHREAD_T_DECLARED) && __POSIX_VISIBLE >= 200809
+typedef __pthread_t pthread_t;
+#define _PTHREAD_T_DECLARED
+#endif
+#endif /* __POSIX_VISIBLE || __XSI_VISIBLE */
+
__BEGIN_DECLS
int raise(int);
#if __POSIX_VISIBLE || __XSI_VISIBLE
int kill(__pid_t, int);
+#ifndef _PTH_PTHREAD_H_ /* XXX kludge to work around GNU Pth brokenness */
+int pthread_kill(__pthread_t, int);
+int pthread_sigmask(int, const __sigset_t *, __sigset_t *);
+#endif
int sigaction(int, const struct sigaction * __restrict,
struct sigaction * __restrict);
int sigaddset(sigset_t *, int);
@@ -91,7 +104,7 @@ int sigaltstack(const stack_t * __restrict, stack_t * __restrict);
int sigpause(int);
#endif
-#if __POSIX_VISIBLE >= 200112
+#if __XSI_VISIBLE >= 600
int siginterrupt(int, int);
#endif
diff --git a/include/stdio.h b/include/stdio.h
index 78c62e8..8446d63 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -360,7 +360,7 @@ int vdprintf(int, const char * __restrict, __va_list);
#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
#define _WITH_GETLINE
#elif defined(_POSIX_C_SOURCE)
-#if _POSIX_C_SOURCE > 200809
+#if _POSIX_C_SOURCE >= 200809
#define _WITH_GETLINE
#endif
#endif
@@ -374,14 +374,14 @@ ssize_t getline(char ** __restrict, size_t * __restrict, FILE * __restrict);
#if defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
#define _WITH_DPRINTF
#elif defined(_POSIX_C_SOURCE)
-#if _POSIX_C_SOURCE > 200809
+#if _POSIX_C_SOURCE >= 200809
#define _WITH_DPRINTF
#endif
#endif
#endif
#ifdef _WITH_DPRINTF
-int dprintf(int, const char * __restrict, ...);
+int (dprintf)(int, const char * __restrict, ...);
#endif
#endif /* __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 */
diff --git a/include/stdlib.h b/include/stdlib.h
index cd15706..265398e 100644
--- a/include/stdlib.h
+++ b/include/stdlib.h
@@ -80,7 +80,6 @@ extern int __mb_cur_max;
__BEGIN_DECLS
void abort(void) __dead2;
-void abort2(const char *, int, void **) __dead2;
int abs(int) __pure2;
int atexit(void (*)(void));
double atof(const char *);
@@ -196,7 +195,7 @@ long jrand48(unsigned short[3]);
char *l64a(long);
void lcong48(unsigned short[7]);
long lrand48(void);
-#if !defined(_MKTEMP_DECLARED) && __XSI_VISIBLE <= 600
+#if !defined(_MKTEMP_DECLARED) && (__BSD_VISIBLE || __XSI_VISIBLE <= 600)
char *mktemp(char *);
#define _MKTEMP_DECLARED
#endif
@@ -240,6 +239,7 @@ extern void (*_malloc_message)(const char *, const char *, const char *,
void *alloca(size_t);
#endif
+void abort2(const char *, int, void **) __dead2;
__uint32_t
arc4random(void);
void arc4random_addrandom(unsigned char *, int);
diff --git a/include/string.h b/include/string.h
index 5923cb5..bd4ed2e 100644
--- a/include/string.h
+++ b/include/string.h
@@ -55,11 +55,13 @@ typedef __size_t size_t;
#endif
__BEGIN_DECLS
-#if __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE
+#if __XSI_VISIBLE >= 600
void *memccpy(void * __restrict, const void * __restrict, int, size_t);
#endif
void *memchr(const void *, int, size_t) __pure;
+#if __BSD_VISIBLE
void *memrchr(const void *, int, size_t) __pure;
+#endif
int memcmp(const void *, const void *, size_t) __pure;
void *memcpy(void * __restrict, const void * __restrict, size_t);
#if __BSD_VISIBLE
diff --git a/include/unistd.h b/include/unistd.h
index 704d935..4b567b8 100644
--- a/include/unistd.h
+++ b/include/unistd.h
@@ -328,7 +328,6 @@ int chown(const char *, uid_t, gid_t);
int close(int);
int dup(int);
int dup2(int, int);
-int eaccess(const char *, int);
int execl(const char *, const char *, ...);
int execle(const char *, const char *, ...);
int execlp(const char *, const char *, ...);
@@ -360,7 +359,6 @@ ssize_t read(int, void *, size_t);
int rmdir(const char *);
int setgid(gid_t);
int setpgid(pid_t, pid_t);
-void setproctitle(const char *_fmt, ...) __printf0like(1, 2);
pid_t setsid(void);
int setuid(uid_t);
unsigned int sleep(unsigned int);
@@ -431,7 +429,6 @@ int truncate(const char *, off_t);
#if __POSIX_VISIBLE >= 200809 || __BSD_VISIBLE
int faccessat(int, const char *, int, int);
-int fchmodat(int, const char *, mode_t, int);
int fchownat(int, const char *, uid_t, gid_t, int);
int fexecve(int, char *const [], char *const []);
int linkat(int, const char *, int, const char *, int);
@@ -470,7 +467,7 @@ void sync(void);
#endif /* __XSI_VISIBLE */
-#if __XSI_VISIBLE <= 500 || __BSD_VISIBLE
+#if (__XSI_VISIBLE && __XSI_VISIBLE <= 500) || __BSD_VISIBLE
int brk(const void *);
int chroot(const char *);
int getdtablesize(void);
@@ -479,7 +476,7 @@ char *getpass(const char *);
void *sbrk(intptr_t);
#endif
-#if __XSI_VISIBLE <= 600 || __BSD_VISIBLE
+#if (__XSI_VISIBLE && __XSI_VISIBLE <= 600) || __BSD_VISIBLE
char *getwd(char *); /* obsoleted by getcwd() */
useconds_t
ualarm(useconds_t, useconds_t);
@@ -497,6 +494,7 @@ const char *
int crypt_set_format(const char *);
int des_cipher(const char *, char *, long, int);
int des_setkey(const char *key);
+int eaccess(const char *, int);
void endusershell(void);
int exect(const char *, char * const *, char * const *);
int execvP(const char *, const char *, char * const *);
@@ -563,6 +561,7 @@ int setkey(const char *);
#endif
int setlogin(const char *);
void *setmode(const char *);
+void setproctitle(const char *_fmt, ...) __printf0like(1, 2);
int setresgid(gid_t, gid_t, gid_t);
int setresuid(uid_t, uid_t, uid_t);
int setrgid(gid_t);
diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile
index d73672e..4597374 100644
--- a/lib/libarchive/Makefile
+++ b/lib/libarchive/Makefile
@@ -77,6 +77,7 @@ SRCS= archive_check_magic.c \
# Man pages to be installed.
MAN= archive_entry.3 \
archive_read.3 \
+ archive_read_disk.3 \
archive_util.3 \
archive_write.3 \
archive_write_disk.3 \
@@ -186,6 +187,16 @@ MLINKS+= archive_read.3 archive_read_support_format_cpio.3
MLINKS+= archive_read.3 archive_read_support_format_iso9660.3
MLINKS+= archive_read.3 archive_read_support_format_tar.3
MLINKS+= archive_read.3 archive_read_support_format_zip.3
+MLINKS+= archive_read_disk.3 archive_read_disk_entry_from_file.3
+MLINKS+= archive_read_disk.3 archive_read_disk_gname.3
+MLINKS+= archive_read_disk.3 archive_read_disk_new.3
+MLINKS+= archive_read_disk.3 archive_read_disk_set_gname_lookup.3
+MLINKS+= archive_read_disk.3 archive_read_disk_set_standard_lookup.3
+MLINKS+= archive_read_disk.3 archive_read_disk_set_symlink_hybrid.3
+MLINKS+= archive_read_disk.3 archive_read_disk_set_symlink_logical.3
+MLINKS+= archive_read_disk.3 archive_read_disk_set_symlink_physical.3
+MLINKS+= archive_read_disk.3 archive_read_disk_set_uname_lookup.3
+MLINKS+= archive_read_disk.3 archive_read_disk_uname.3
MLINKS+= archive_util.3 archive_clear_error.3
MLINKS+= archive_util.3 archive_compression.3
MLINKS+= archive_util.3 archive_compression_name.3
diff --git a/lib/libarchive/archive.h b/lib/libarchive/archive.h
index 23b9a9d..da31d40 100644
--- a/lib/libarchive/archive.h
+++ b/lib/libarchive/archive.h
@@ -46,7 +46,7 @@
/* Get appropriate definitions of standard POSIX-style types. */
/* These should match the types used in 'struct stat' */
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
#define __LA_INT64_T __int64
# if defined(_WIN64)
# define __LA_SSIZE_T __int64
@@ -68,7 +68,7 @@
* .lib. The default here assumes you're building a DLL. Only
* libarchive source should ever define __LIBARCHIVE_BUILD.
*/
-#if ((defined __WIN32__) || (defined _WIN32)) && (!defined LIBARCHIVE_STATIC)
+#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC)
# ifdef __LIBARCHIVE_BUILD
# ifdef __GNUC__
# define __LA_DECL __attribute__((dllexport)) extern
diff --git a/lib/libarchive/archive_check_magic.c b/lib/libarchive/archive_check_magic.c
index e1d35c5..8f1fa2f 100644
--- a/lib/libarchive/archive_check_magic.c
+++ b/lib/libarchive/archive_check_magic.c
@@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#include <winbase.h>
#endif
@@ -56,7 +56,7 @@ errmsg(const char *m)
static void
diediedie(void)
{
-#if defined(_WIN32) && defined(_DEBUG)
+#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
/* Cause a breakpoint exception */
DebugBreak();
#endif
diff --git a/lib/libarchive/archive_entry.c b/lib/libarchive/archive_entry.c
index 37fc37b..4cafce2 100644
--- a/lib/libarchive/archive_entry.c
+++ b/lib/libarchive/archive_entry.c
@@ -83,7 +83,7 @@ __FBSDID("$FreeBSD$");
#elif defined makedev
/* There's a "makedev" macro. */
#define ae_makedev(maj, min) makedev((maj), (min))
-#elif defined mkdev || defined _WIN32 || defined __WIN32__
+#elif defined mkdev || ((defined _WIN32 || defined __WIN32__) && !defined(__CYGWIN__))
/* Windows. <sigh> */
#define ae_makedev(maj, min) mkdev((maj), (min))
#else
diff --git a/lib/libarchive/archive_entry.h b/lib/libarchive/archive_entry.h
index 93925a9..a2748fd 100644
--- a/lib/libarchive/archive_entry.h
+++ b/lib/libarchive/archive_entry.h
@@ -42,7 +42,7 @@
/* Get appropriate definitions of standard POSIX-style types. */
/* These should match the types used in 'struct stat' */
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
#define __LA_INT64_T __int64
#define __LA_UID_T unsigned int
#define __LA_GID_T unsigned int
@@ -71,7 +71,7 @@
* .lib. The default here assumes you're building a DLL. Only
* libarchive source should ever define __LIBARCHIVE_BUILD.
*/
-#if ((defined __WIN32__) || (defined _WIN32)) && (!defined LIBARCHIVE_STATIC)
+#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC)
# ifdef __LIBARCHIVE_BUILD
# ifdef __GNUC__
# define __LA_DECL __attribute__((dllexport)) extern
diff --git a/lib/libarchive/archive_read_disk.3 b/lib/libarchive/archive_read_disk.3
new file mode 100644
index 0000000..fd53095
--- /dev/null
+++ b/lib/libarchive/archive_read_disk.3
@@ -0,0 +1,308 @@
+.\" Copyright (c) 2003-2009 Tim Kientzle
+.\" 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$
+.\"
+.Dd March 10, 2009
+.Dt archive_read_disk 3
+.Os
+.Sh NAME
+.Nm archive_read_disk_new ,
+.Nm archive_read_disk_set_symlink_logical ,
+.Nm archive_read_disk_set_symlink_physical ,
+.Nm archive_read_disk_set_symlink_hybrid ,
+.Nm archive_read_disk_entry_from_file ,
+.Nm archive_read_disk_gname ,
+.Nm archive_read_disk_uname ,
+.Nm archive_read_disk_set_uname_lookup ,
+.Nm archive_read_disk_set_gname_lookup ,
+.Nm archive_read_disk_set_standard_lookup ,
+.Nm archive_read_close ,
+.Nm archive_read_finish
+.Nd functions for reading objects from disk
+.Sh SYNOPSIS
+.In archive.h
+.Ft struct archive *
+.Fn archive_read_disk_new "void"
+.Ft int
+.Fn archive_read_disk_set_symlink_logical "struct archive *"
+.Ft int
+.Fn archive_read_disk_set_symlink_physical "struct archive *"
+.Ft int
+.Fn archive_read_disk_set_symlink_hybrid "struct archive *"
+.Ft int
+.Fn archive_read_disk_gname "struct archive *" "gid_t"
+.Ft int
+.Fn archive_read_disk_uname "struct archive *" "uid_t"
+.Ft int
+.Fo archive_read_disk_set_gname_lookup
+.Fa "struct archive *"
+.Fa "void *"
+.Fa "const char *(*lookup)(void *, gid_t)"
+.Fa "void (*cleanup)(void *)"
+.Fc
+.Ft int
+.Fo archive_read_disk_set_uname_lookup
+.Fa "struct archive *"
+.Fa "void *"
+.Fa "const char *(*lookup)(void *, uid_t)"
+.Fa "void (*cleanup)(void *)"
+.Fc
+.Ft int
+.Fn archive_read_disk_set_standard_lookup "struct archive *"
+.Ft int
+.Fo archive_read_disk_entry_from_file
+.Fa "struct archive *"
+.Fa "struct archive_entry *"
+.Fa "int fd"
+.Fa "const struct stat *"
+.Fc
+.Ft int
+.Fn archive_read_close "struct archive *"
+.Ft int
+.Fn archive_read_finish "struct archive *"
+.Sh DESCRIPTION
+These functions provide an API for reading information about
+objects on disk.
+In particular, they provide an interface for populating
+.Tn struct archive_entry
+objects.
+.Bl -tag -width indent
+.It Fn archive_read_disk_new
+Allocates and initializes a
+.Tn struct archive
+object suitable for reading object information from disk.
+.It Xo
+.Fn archive_read_disk_set_symlink_logical ,
+.Fn archive_read_disk_set_symlink_physical ,
+.Fn archive_read_disk_set_symlink_hybrid
+.Xc
+This sets the mode used for handling symbolic links.
+The
+.Dq logical
+mode follows all symbolic links.
+The
+.Dq physical
+mode does not follow any symbolic links.
+The
+.Dq hybrid
+mode currently behaves identically to the
+.Dq logical
+mode.
+.It Xo
+.Fn archive_read_disk_gname ,
+.Fn archive_read_disk_uname
+.Xc
+Returns a user or group name given a gid or uid value.
+By default, these always return a NULL string.
+.It Xo
+.Fn archive_read_disk_set_gname_lookup ,
+.Fn archive_read_disk_set_uname_lookup
+.Xc
+These allow you to override the functions used for
+user and group name lookups.
+You may also provide a
+.Tn void *
+pointer to a private data structure and a cleanup function for
+that data.
+The cleanup function will be invoked when the
+.Tn struct archive
+object is destroyed or when new lookup functions are registered.
+.It Fn archive_read_disk_set_standard_lookup
+This convenience function installs a standard set of user
+and group name lookup functions.
+These functions use
+.Xr getpwid 3
+and
+.Xr getgrid 3
+to convert ids to names, defaulting to NULL if the names cannot
+be looked up.
+These functions also implement a simple memory cache to reduce
+the number of calls to
+.Xr getpwid 3
+and
+.Xr getgrid 3 .
+.It Fn archive_read_disk_entry_from_file
+Populates a
+.Tn struct archive_entry
+object with information about a particular file.
+The
+.Tn archive_entry
+object must have already been created with
+.Xr archive_entry_new 3
+and at least one of the source path or path fields must already be set.
+(If both are set, the source path will be used.)
+.Pp
+Information is read from disk using the path name from the
+.Tn struct archive_entry
+object.
+If a file descriptor is provided, some information will be obtained using
+that file descriptor, on platforms that support the appropriate
+system calls.
+.Pp
+If a pointer to a
+.Tn struct stat
+is provided, information from that structure will be used instead
+of reading from the disk where appropriate.
+This can provide performance benefits in scenarios where
+.Tn struct stat
+information has already been read from the disk as a side effect
+of some other operation.
+(For example, directory traversal libraries often provide this information.)
+.Pp
+Where necessary, user and group ids are converted to user and group names
+using the currently registered lookup functions above.
+This affects the file ownership fields and ACL values in the
+.Tn struct archive_entry
+object.
+.It Fn archive_read_close
+This currently does nothing.
+.It Fn archive_write_finish
+Invokes
+.Fn archive_write_close
+if it was not invoked manually, then releases all resources.
+.El
+More information about the
+.Va struct archive
+object and the overall design of the library can be found in the
+.Xr libarchive 3
+overview.
+.Sh EXAMPLE
+The following illustrates basic usage of the library by
+showing how to use it to copy an item on disk into an archive.
+.Bd -literal -offset indent
+void
+file_to_archive(struct archive *a, const char *name)
+{
+ char buff[8192];
+ size_t bytes_read;
+ struct archive *ard;
+ struct archive_entry *entry;
+ int fd;
+
+ ard = archive_read_disk_new();
+ archive_read_disk_set_standard_lookup(ard);
+ entry = archive_entry_new();
+ fd = open(name, O_RDONLY);
+ if (fd < 0)
+ return;
+ archive_entry_copy_sourcepath(entry, name);
+ archive_read_disk_entry_from_file(ard, entry, fd, NULL);
+ archive_write_header(a, entry);
+ while ((bytes_read = read(fd, buff, sizeof(buff))) > 0)
+ archive_write_data(a, buff, bytes_read);
+ archive_write_finish_entry(a);
+ archive_read_finish(ard);
+ archive_entry_free(entry);
+}
+.Ed
+.Sh RETURN VALUES
+Most functions return
+.Cm ARCHIVE_OK
+(zero) on success, or one of several negative
+error codes for errors.
+Specific error codes include:
+.Cm ARCHIVE_RETRY
+for operations that might succeed if retried,
+.Cm ARCHIVE_WARN
+for unusual conditions that do not prevent further operations, and
+.Cm ARCHIVE_FATAL
+for serious errors that make remaining operations impossible.
+The
+.Xr archive_errno 3
+and
+.Xr archive_error_string 3
+functions can be used to retrieve an appropriate error code and a
+textual error message.
+(See
+.Xr archive_util 3
+for details.)
+.Pp
+.Fn archive_read_disk_new
+returns a pointer to a newly-allocated
+.Tn struct archive
+object or NULL if the allocation failed for any reason.
+.Pp
+.Fn archive_read_disk_gname
+and
+.Fn archive_read_disk_uname
+return
+.Tn const char *
+pointers to the textual name or NULL if the lookup failed for any reason.
+The returned pointer points to internal storage that
+may be reused on the next call to either of these functions;
+callers should copy the string if they need to continue accessing it.
+.Pp
+.Sh SEE ALSO
+.Xr archive_read 3 ,
+.Xr archive_write 3 ,
+.Xr archive_write_disk 3 ,
+.Xr tar 1 ,
+.Xr libarchive 3
+.Sh HISTORY
+The
+.Nm libarchive
+library first appeared in
+.Fx 5.3 .
+The
+.Nm archive_read_disk
+interface was added to
+.Nm libarchive 2.6
+and first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm libarchive
+library was written by
+.An Tim Kientzle Aq kientzle@freebsd.org .
+.Sh BUGS
+The
+.Dq standard
+user name and group name lookup functions are not the defaults because
+.Xr getgrid 3
+and
+.Xr getpwid 3
+are sometimes too large for particular applications.
+The current design allows the application author to use a more
+compact implementation when appropriate.
+.Pp
+The full list of metadata read from disk by
+.Fn archive_read_disk_entry_from_file
+is necessarily system-dependent.
+.Pp
+The
+.Fn archive_read_disk_entry_from_file
+function reads as much information as it can from disk.
+Some method should be provided to limit this so that clients who
+do not need ACLs, for instance, can avoid the extra work needed
+to look up such information.
+.Pp
+This API should provide a set of methods for walking a directory tree.
+That would make it a direct parallel of the
+.Xr archive_read 3
+API.
+When such methods are implemented, the
+.Dq hybrid
+symbolic link mode will make sense.
diff --git a/lib/libarchive/archive_read_disk_set_standard_lookup.c b/lib/libarchive/archive_read_disk_set_standard_lookup.c
index cb12314..68e8074 100644
--- a/lib/libarchive/archive_read_disk_set_standard_lookup.c
+++ b/lib/libarchive/archive_read_disk_set_standard_lookup.c
@@ -47,14 +47,14 @@ __FBSDID("$FreeBSD$");
#include "archive.h"
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
int
archive_read_disk_set_standard_lookup(struct archive *a)
{
archive_set_error(a, -1, "Standard lookups not available on Windows");
return (ARCHIVE_FATAL);
}
-#else
+#else /* ! (_WIN32 && !__CYGWIN__) */
#define name_cache_size 127
static const char * const NO_NAME = "(noname)";
@@ -182,7 +182,7 @@ lookup_uname(void *data, uid_t uid)
static const char *
lookup_uname_helper(struct archive *a, id_t id)
{
- char buffer[64];
+ char buffer[512];
struct passwd pwent, *result;
int r;
@@ -210,7 +210,7 @@ lookup_gname(void *data, gid_t gid)
static const char *
lookup_gname_helper(struct archive *a, id_t id)
{
- char buffer[64];
+ char buffer[512];
struct group grent, *result;
int r;
@@ -226,4 +226,4 @@ lookup_gname_helper(struct archive *a, id_t id)
return strdup(grent.gr_name);
}
-#endif /* _WIN32 */
+#endif /* ! (_WIN32 && !__CYGWIN__) */
diff --git a/lib/libarchive/archive_read_support_compression_program.c b/lib/libarchive/archive_read_support_compression_program.c
index 4463255..21c2377 100644
--- a/lib/libarchive/archive_read_support_compression_program.c
+++ b/lib/libarchive/archive_read_support_compression_program.c
@@ -38,6 +38,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
+#ifdef HAVE_SIGNAL_H
+# include <signal.h>
+#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
@@ -61,7 +64,7 @@ archive_read_support_compression_program(struct archive *a, const char *cmd)
/* This capability is only available on POSIX systems. */
#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
- !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && !defined(_WIN32)
+ !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__))
/*
* On non-Posix systems, allow the program to build, but choke if
@@ -119,6 +122,8 @@ static int program_bidder_free(struct archive_read_filter_bidder *);
struct program_filter {
char *description;
pid_t child;
+ int exit_status;
+ int waitpid_return;
int child_stdin, child_stdout;
char *out_buf;
@@ -211,6 +216,73 @@ program_bidder_bid(struct archive_read_filter_bidder *self,
}
/*
+ * Shut down the child, return ARCHIVE_OK if it exited normally.
+ *
+ * Note that the return value is sticky; if we're called again,
+ * we won't reap the child again, but we will return the same status
+ * (including error message if the child came to a bad end).
+ */
+static int
+child_stop(struct archive_read_filter *self, struct program_filter *state)
+{
+ /* Close our side of the I/O with the child. */
+ if (state->child_stdin != -1) {
+ close(state->child_stdin);
+ state->child_stdin = -1;
+ }
+ if (state->child_stdout != -1) {
+ close(state->child_stdout);
+ state->child_stdout = -1;
+ }
+
+ if (state->child != 0) {
+ /* Reap the child. */
+ do {
+ state->waitpid_return
+ = waitpid(state->child, &state->exit_status, 0);
+ } while (state->waitpid_return == -1 && errno == EINTR);
+ state->child = 0;
+ }
+
+ if (state->waitpid_return < 0) {
+ /* waitpid() failed? This is ugly. */
+ archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
+ "Child process exited badly");
+ return (ARCHIVE_WARN);
+ }
+
+ if (WIFSIGNALED(state->exit_status)) {
+#ifdef SIGPIPE
+ /* If the child died because we stopped reading before
+ * it was done, that's okay. Some archive formats
+ * have padding at the end that we routinely ignore. */
+ /* The alternative to this would be to add a step
+ * before close(child_stdout) above to read from the
+ * child until the child has no more to write. */
+ if (WTERMSIG(state->exit_status) == SIGPIPE)
+ return (ARCHIVE_OK);
+#endif
+ archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
+ "Child process exited with signal %d",
+ WTERMSIG(state->exit_status));
+ return (ARCHIVE_WARN);
+ }
+
+ if (WIFEXITED(state->exit_status)) {
+ if (WEXITSTATUS(state->exit_status) == 0)
+ return (ARCHIVE_OK);
+
+ archive_set_error(&self->archive->archive,
+ ARCHIVE_ERRNO_MISC,
+ "Child process exited with status %d",
+ WEXITSTATUS(state->exit_status));
+ return (ARCHIVE_WARN);
+ }
+
+ return (ARCHIVE_WARN);
+}
+
+/*
* Use select() to decide whether the child is ready for read or write.
*/
static ssize_t
@@ -229,11 +301,10 @@ child_read(struct archive_read_filter *self, char *buf, size_t buf_len)
if (ret > 0)
return (ret);
- if (ret == 0 || (ret == -1 && errno == EPIPE)) {
- close(state->child_stdout);
- state->child_stdout = -1;
- return (0);
- }
+ if (ret == 0 || (ret == -1 && errno == EPIPE))
+ /* Child has closed its output; reap the child
+ * and return the status. */
+ return (child_stop(self, state));
if (ret == -1 && errno != EAGAIN)
return (-1);
@@ -352,8 +423,11 @@ program_filter_read(struct archive_read_filter *self, const void **buff)
while (state->child_stdout != -1 && total < state->out_buf_len) {
bytes = child_read(self, p, state->out_buf_len - total);
if (bytes < 0)
- return (bytes);
+ /* No recovery is possible if we can no longer
+ * read from the child. */
+ return (ARCHIVE_FATAL);
if (bytes == 0)
+ /* We got EOF from the child. */
break;
total += bytes;
p += bytes;
@@ -367,24 +441,17 @@ static int
program_filter_close(struct archive_read_filter *self)
{
struct program_filter *state;
- int status;
+ int e;
state = (struct program_filter *)self->data;
-
- /* Shut down the child. */
- if (state->child_stdin != -1)
- close(state->child_stdin);
- if (state->child_stdout != -1)
- close(state->child_stdout);
- while (waitpid(state->child, &status, 0) == -1 && errno == EINTR)
- continue;
+ e = child_stop(self, state);
/* Release our private data. */
free(state->out_buf);
free(state->description);
free(state);
- return (ARCHIVE_OK);
+ return (e);
}
#endif /* !defined(HAVE_PIPE) || !defined(HAVE_VFORK) || !defined(HAVE_FCNTL) */
diff --git a/lib/libarchive/archive_read_support_format_empty.c b/lib/libarchive/archive_read_support_format_empty.c
index bdecd65..db24d9d 100644
--- a/lib/libarchive/archive_read_support_format_empty.c
+++ b/lib/libarchive/archive_read_support_format_empty.c
@@ -59,12 +59,14 @@ archive_read_support_format_empty(struct archive *_a)
static int
archive_read_format_empty_bid(struct archive_read *a)
{
- const void *h;
+ ssize_t avail;
- h = __archive_read_ahead(a, 1, NULL);
- if (h != NULL)
- return (-1);
- return (1);
+ (void)__archive_read_ahead(a, 1, &avail);
+ /* Bid 1 if we successfully read exactly zero bytes. */
+ if (avail == 0)
+ return (1);
+ /* Otherwise, we don't bid on this. */
+ return (-1);
}
static int
diff --git a/lib/libarchive/archive_string.c b/lib/libarchive/archive_string.c
index 03186bf..111dcb1 100644
--- a/lib/libarchive/archive_string.c
+++ b/lib/libarchive/archive_string.c
@@ -40,7 +40,7 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_WCHAR_H
#include <wchar.h>
#endif
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#endif
@@ -115,11 +115,11 @@ __archive_string_ensure(struct archive_string *as, size_t s)
as->buffer_length = 32;
else if (as->buffer_length < 8192)
/* Buffers under 8k are doubled for speed. */
- as->buffer_length *= 2;
+ as->buffer_length += as->buffer_length;
else {
/* Buffers 8k and over grow by at least 25% each time. */
size_t old_length = as->buffer_length;
- as->buffer_length = (as->buffer_length * 5) / 4;
+ as->buffer_length += as->buffer_length / 4;
/* Be safe: If size wraps, release buffer and return NULL. */
if (as->buffer_length < old_length) {
free(as->s);
@@ -142,10 +142,12 @@ __archive_string_ensure(struct archive_string *as, size_t s)
}
struct archive_string *
-__archive_strncat(struct archive_string *as, const char *p, size_t n)
+__archive_strncat(struct archive_string *as, const void *_p, size_t n)
{
size_t s;
- const char *pp;
+ const char *p, *pp;
+
+ p = (const char *)_p;
/* Like strlen(p), except won't examine positions beyond p[n]. */
s = 0;
@@ -163,56 +165,18 @@ __archive_strappend_char(struct archive_string *as, char c)
return (__archive_string_append(as, &c, 1));
}
-#ifndef _WIN32
/*
- * Home-grown wctomb for UTF-8.
+ * Translates a wide character string into UTF-8 and appends
+ * to the archive_string. Note: returns NULL if conversion fails,
+ * but still leaves a best-effort conversion in the argument as.
*/
-static int
-my_wctomb_utf8(char *p, wchar_t wc)
-{
- if (p == NULL)
- /* UTF-8 doesn't use shift states. */
- return (0);
- if (wc <= 0x7f) {
- p[0] = (char)wc;
- return (1);
- }
- if (wc <= 0x7ff) {
- p[0] = 0xc0 | ((wc >> 6) & 0x1f);
- p[1] = 0x80 | (wc & 0x3f);
- return (2);
- }
- if (wc <= 0xffff) {
- p[0] = 0xe0 | ((wc >> 12) & 0x0f);
- p[1] = 0x80 | ((wc >> 6) & 0x3f);
- p[2] = 0x80 | (wc & 0x3f);
- return (3);
- }
- if (wc <= 0x1fffff) {
- p[0] = 0xf0 | ((wc >> 18) & 0x07);
- p[1] = 0x80 | ((wc >> 12) & 0x3f);
- p[2] = 0x80 | ((wc >> 6) & 0x3f);
- p[3] = 0x80 | (wc & 0x3f);
- return (4);
- }
- /* Unicode has no codes larger than 0x1fffff. */
- /*
- * Awkward point: UTF-8 <-> wchar_t conversions
- * can actually fail.
- */
- return (-1);
-}
-
-static int
-my_wcstombs(struct archive_string *as, const wchar_t *w,
- int (*func)(char *, wchar_t))
+struct archive_string *
+__archive_strappend_w_utf8(struct archive_string *as, const wchar_t *w)
{
- int n;
char *p;
+ unsigned wc;
char buff[256];
-
- /* Clear the shift state before starting. */
- (*func)(NULL, L'\0');
+ struct archive_string *return_val = as;
/*
* Convert one wide char at a time into 'buff', whenever that
@@ -227,67 +191,50 @@ my_wcstombs(struct archive_string *as, const wchar_t *w,
archive_strcat(as, buff);
p = buff;
}
- n = (*func)(p, *w++);
- if (n == -1)
- return (-1);
- p += n;
+ wc = *w++;
+ /* If this is a surrogate pair, assemble the full code point.*/
+ /* Note: wc must not be wchar_t here, because the full code
+ * point can be more than 16 bits! */
+ if (wc >= 0xD800 && wc <= 0xDBff
+ && *w >= 0xDC00 && *w <= 0xDFFF) {
+ wc -= 0xD800;
+ wc *= 0x400;
+ wc += (*w - 0xDC00);
+ wc += 0x10000;
+ ++w;
+ }
+ /* Translate code point to UTF8 */
+ if (wc <= 0x7f) {
+ *p++ = (char)wc;
+ } else if (wc <= 0x7ff) {
+ *p++ = 0xc0 | ((wc >> 6) & 0x1f);
+ *p++ = 0x80 | (wc & 0x3f);
+ } else if (wc <= 0xffff) {
+ *p++ = 0xe0 | ((wc >> 12) & 0x0f);
+ *p++ = 0x80 | ((wc >> 6) & 0x3f);
+ *p++ = 0x80 | (wc & 0x3f);
+ } else if (wc <= 0x1fffff) {
+ *p++ = 0xf0 | ((wc >> 18) & 0x07);
+ *p++ = 0x80 | ((wc >> 12) & 0x3f);
+ *p++ = 0x80 | ((wc >> 6) & 0x3f);
+ *p++ = 0x80 | (wc & 0x3f);
+ } else {
+ /* Unicode has no codes larger than 0x1fffff. */
+ /* TODO: use \uXXXX escape here instead of ? */
+ *p++ = '?';
+ return_val = NULL;
+ }
}
*p = '\0';
archive_strcat(as, buff);
- return (0);
-}
-
-/*
- * Translates a wide character string into UTF-8 and appends
- * to the archive_string. Note: returns NULL if conversion fails.
- */
-struct archive_string *
-__archive_strappend_w_utf8(struct archive_string *as, const wchar_t *w)
-{
- if (my_wcstombs(as, w, my_wctomb_utf8))
- return (NULL);
- return (as);
-}
-
-/*
- * Translates a wide character string into current locale character set
- * and appends to the archive_string. Note: returns NULL if conversion
- * fails.
- */
-struct archive_string *
-__archive_strappend_w_mbs(struct archive_string *as, const wchar_t *w)
-{
-#if HAVE_WCTOMB
- if (my_wcstombs(as, w, wctomb))
- return (NULL);
-#else
- /* TODO: Can we do better than this? Are there platforms
- * that have locale support but don't have wctomb()? */
- if (my_wcstombs(as, w, my_wctomb_utf8))
- return (NULL);
-#endif
- return (as);
+ return (return_val);
}
-
-/*
- * Home-grown mbtowc for UTF-8. Some systems lack UTF-8
- * (or even lack mbtowc()) and we need UTF-8 support for pax
- * format. So please don't replace this with a call to the
- * standard mbtowc() function!
- */
static int
-my_mbtowc_utf8(wchar_t *pwc, const char *s, size_t n)
+utf8_to_unicode(int *pwc, const char *s, size_t n)
{
int ch;
- /* Standard behavior: a NULL value for 's' just resets shift state. */
- if (s == NULL)
- return (0);
- /* If length argument is zero, don't look at the first character. */
- if (n <= 0)
- return (-1);
-
/*
* Decode 1-4 bytes depending on the value of the first byte.
*/
@@ -333,13 +280,15 @@ my_mbtowc_utf8(wchar_t *pwc, const char *s, size_t n)
}
/*
- * Return a wide-character string by converting this archive_string
- * from UTF-8.
+ * Return a wide-character Unicode string by converting this archive_string
+ * from UTF-8. We assume that systems with 16-bit wchar_t always use
+ * UTF16 and systems with 32-bit wchar_t can accept UCS4.
*/
wchar_t *
__archive_string_utf8_w(struct archive_string *as)
{
wchar_t *ws, *dest;
+ int wc, wc2;/* Must be large enough for a 21-bit Unicode code point. */
const char *src;
int n;
int err;
@@ -351,25 +300,68 @@ __archive_string_utf8_w(struct archive_string *as)
dest = ws;
src = as->s;
while (*src != '\0') {
- n = my_mbtowc_utf8(dest, src, 8);
+ n = utf8_to_unicode(&wc, src, 8);
if (n == 0)
break;
if (n < 0) {
free(ws);
return (NULL);
}
- dest++;
src += n;
+ if (wc >= 0xDC00 && wc <= 0xDBFF) {
+ /* This is a leading surrogate; some idiot
+ * has translated UTF16 to UTF8 without combining
+ * surrogates; rebuild the full code point before
+ * continuing. */
+ n = utf8_to_unicode(&wc2, src, 8);
+ if (n < 0) {
+ free(ws);
+ return (NULL);
+ }
+ if (n == 0) /* Ignore the leading surrogate */
+ break;
+ if (wc2 < 0xDC00 || wc2 > 0xDFFF) {
+ /* If the second character isn't a
+ * trailing surrogate, then someone
+ * has really screwed up and this is
+ * invalid. */
+ free(ws);
+ return (NULL);
+ } else {
+ src += n;
+ wc -= 0xD800;
+ wc *= 0x400;
+ wc += wc2 - 0xDC00;
+ wc += 0x10000;
+ }
+ }
+ if ((sizeof(wchar_t) < 4) && (wc > 0xffff)) {
+ /* We have a code point that won't fit into a
+ * wchar_t; convert it to a surrogate pair. */
+ wc -= 0x10000;
+ *dest++ = ((wc >> 10) & 0x3ff) + 0xD800;
+ *dest++ = (wc & 0x3ff) + 0xDC00;
+ } else
+ *dest++ = wc;
}
*dest++ = L'\0';
return (ws);
}
-#else
+#if defined(_WIN32) && !defined(__CYGWIN__)
-static struct archive_string *
-my_archive_strappend_w(struct archive_string *as,
- unsigned int codepage, const wchar_t *w)
+/*
+ * Translates a wide character string into current locale character set
+ * and appends to the archive_string. Note: returns NULL if conversion
+ * fails.
+ *
+ * Win32 builds use WideCharToMultiByte from the Windows API.
+ * (Maybe Cygwin should too? WideCharToMultiByte will know a
+ * lot more about local character encodings than the wcrtomb()
+ * wrapper is going to know.)
+ */
+struct archive_string *
+__archive_strappend_w_mbs(struct archive_string *as, const wchar_t *w)
{
char *p;
int l, wl;
@@ -386,9 +378,8 @@ my_archive_strappend_w(struct archive_string *as,
* And to set NULL for last argument is necessary when a codepage
* is not CP_ACP(current locale).
*/
- l = WideCharToMultiByte(codepage, 0, w, wl, p, l, NULL,
- (codepage == CP_ACP) ? &useDefaultChar : NULL);
- if (l == 0 || useDefaultChar) {
+ l = WideCharToMultiByte(CP_ACP, 0, w, wl, p, l, NULL, &useDefaultChar);
+ if (l == 0) {
free(p);
return (NULL);
}
@@ -397,50 +388,68 @@ my_archive_strappend_w(struct archive_string *as,
return (as);
}
-/*
- * Translates a wide character string into UTF-8 and appends
- * to the archive_string. Note: returns NULL if conversion fails.
- */
-struct archive_string *
-__archive_strappend_w_utf8(struct archive_string *as, const wchar_t *w)
-{
-
- return (my_archive_strappend_w(as, CP_UTF8, w));
-}
+#else
/*
* Translates a wide character string into current locale character set
* and appends to the archive_string. Note: returns NULL if conversion
* fails.
+ *
+ * Non-Windows uses ISO C wcrtomb() or wctomb() to perform the conversion
+ * one character at a time. If a non-Windows platform doesn't have
+ * either of these, fall back to the built-in UTF8 conversion.
*/
struct archive_string *
__archive_strappend_w_mbs(struct archive_string *as, const wchar_t *w)
{
-
- return (my_archive_strappend_w(as, CP_ACP, w));
-}
-
-/*
- * Return a wide-character string by converting this archive_string
- * from UTF-8.
- */
-wchar_t *
-__archive_string_utf8_w(struct archive_string *as)
-{
- wchar_t *ws;
+#if !defined(HAVE_WCTOMB) && !defined(HAVE_WCRTOMB)
+ /* If there's no built-in locale support, fall back to UTF8 always. */
+ return __archive_strappend_w_utf8(as, w);
+#else
+ /* We cannot use the standard wcstombs() here because it
+ * cannot tell us how big the output buffer should be. So
+ * I've built a loop around wcrtomb() or wctomb() that
+ * converts a character at a time and resizes the string as
+ * needed. We prefer wcrtomb() when it's available because
+ * it's thread-safe. */
int n;
+ char *p;
+ char buff[256];
+#if HAVE_WCRTOMB
+ mbstate_t shift_state;
- ws = (wchar_t *)malloc((as->length + 1) * sizeof(wchar_t));
- if (ws == NULL)
- __archive_errx(1, "Out of memory");
- n = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS,
- as->s, (int)as->length, ws, (int)as->length);
- if (n == 0) {
- free(ws);
- return (NULL);
+ memset(&shift_state, 0, sizeof(shift_state));
+#else
+ /* Clear the shift state before starting. */
+ wctomb(NULL, L'\0');
+#endif
+
+ /*
+ * Convert one wide char at a time into 'buff', whenever that
+ * fills, append it to the string.
+ */
+ p = buff;
+ while (*w != L'\0') {
+ /* Flush the buffer when we have <=16 bytes free. */
+ /* (No encoding has a single character >16 bytes.) */
+ if ((size_t)(p - buff) >= (size_t)(sizeof(buff) - MB_CUR_MAX)) {
+ *p = '\0';
+ archive_strcat(as, buff);
+ p = buff;
+ }
+#if HAVE_WCRTOMB
+ n = wcrtomb(p, *w++, &shift_state);
+#else
+ n = wctomb(p, *w++);
+#endif
+ if (n == -1)
+ return (NULL);
+ p += n;
}
- ws[n] = L'\0';
- return (ws);
+ *p = '\0';
+ archive_strcat(as, buff);
+ return (as);
+#endif
}
-#endif /* !_WIN32 */
+#endif /* _WIN32 && ! __CYGWIN__ */
diff --git a/lib/libarchive/archive_string.h b/lib/libarchive/archive_string.h
index 7960b8e..56ca7ca 100644
--- a/lib/libarchive/archive_string.h
+++ b/lib/libarchive/archive_string.h
@@ -99,8 +99,12 @@ __archive_string_ensure(struct archive_string *, size_t);
#define archive_string_ensure __archive_string_ensure
/* Append C string, which may lack trailing \0. */
+/* The source is declared void * here because this gets used with
+ * "signed char *", "unsigned char *" and "char *" arguments.
+ * Declaring it "char *" as with some of the other functions just
+ * leads to a lot of extra casts. */
struct archive_string *
-__archive_strncat(struct archive_string *, const char *, size_t);
+__archive_strncat(struct archive_string *, const void *, size_t);
#define archive_strncat __archive_strncat
/* Append a C string to an archive_string, resizing as necessary. */
diff --git a/lib/libarchive/archive_write_disk.c b/lib/libarchive/archive_write_disk.c
index 0d84156..60fa227 100644
--- a/lib/libarchive/archive_write_disk.c
+++ b/lib/libarchive/archive_write_disk.c
@@ -36,6 +36,9 @@ __FBSDID("$FreeBSD$");
#ifdef HAVE_SYS_EXTATTR_H
#include <sys/extattr.h>
#endif
+#ifdef HAVE_SYS_XATTR_H
+#include <sys/xattr.h>
+#endif
#ifdef HAVE_ATTR_XATTR_H
#include <attr/xattr.h>
#endif
@@ -414,7 +417,7 @@ _archive_write_header(struct archive *_a, struct archive_entry *entry)
a->mode &= ~S_ISVTX;
a->mode &= ~a->user_umask;
}
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
if (a->flags & ARCHIVE_EXTRACT_OWNER)
a->todo |= TODO_OWNER;
#endif
@@ -1217,7 +1220,7 @@ _archive_write_close(struct archive *_a)
if (p->fixup & TODO_TIMES) {
#ifdef HAVE_UTIMES
/* {f,l,}utimes() are preferred, when available. */
-#ifdef __timeval
+#if defined(_WIN32) && !defined(__CYGWIN__)
struct __timeval times[2];
#else
struct timeval times[2];
@@ -1474,7 +1477,7 @@ check_symlinks(struct archive_write_disk *a)
return (ARCHIVE_OK);
}
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__CYGWIN__)
/*
* 1. Convert a path separator from '\' to '/' .
* We shouldn't check multi-byte character directly because some
@@ -1544,7 +1547,7 @@ cleanup_pathname(struct archive_write_disk *a)
return (ARCHIVE_FAILED);
}
-#ifdef _WIN32
+#if defined(_WIN32) || defined(__CYGWIN__)
cleanup_pathname_win(a);
#endif
/* Skip leading '/'. */
@@ -1758,12 +1761,17 @@ create_dir(struct archive_write_disk *a, char *path)
static int
set_ownership(struct archive_write_disk *a)
{
+#ifndef __CYGWIN__
+/* unfortunately, on win32 there is no 'root' user with uid 0,
+ so we just have to try the chown and see if it works */
+
/* If we know we can't change it, don't bother trying. */
if (a->user_uid != 0 && a->user_uid != a->uid) {
archive_set_error(&a->archive, errno,
"Can't set UID=%d", a->uid);
return (ARCHIVE_WARN);
}
+#endif
#ifdef HAVE_FCHOWN
/* If we have an fd, we can avoid a race. */
@@ -1807,7 +1815,7 @@ set_time(int fd, int mode, const char *name,
time_t atime, long atime_nsec,
time_t mtime, long mtime_nsec)
{
-#ifdef __timeval
+#if defined(_WIN32) && !defined(__CYGWIN__)
struct __timeval times[2];
#else
struct timeval times[2];
@@ -1944,7 +1952,7 @@ set_mode(struct archive_write_disk *a, int mode)
return (r);
if (a->pst->st_gid != a->gid) {
mode &= ~ S_ISGID;
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
if (a->flags & ARCHIVE_EXTRACT_OWNER) {
/*
* This is only an error if you
@@ -1963,7 +1971,7 @@ set_mode(struct archive_write_disk *a, int mode)
if (a->pst->st_uid != a->uid
&& (a->todo & TODO_SUID)) {
mode &= ~ S_ISUID;
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
if (a->flags & ARCHIVE_EXTRACT_OWNER) {
archive_set_error(&a->archive, -1,
"Can't restore SUID bit");
@@ -1981,7 +1989,7 @@ set_mode(struct archive_write_disk *a, int mode)
*/
if (a->user_uid != a->uid) {
mode &= ~ S_ISUID;
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
if (a->flags & ARCHIVE_EXTRACT_OWNER) {
archive_set_error(&a->archive, -1,
"Can't make file SUID");
diff --git a/lib/libarchive/archive_write_disk_set_standard_lookup.c b/lib/libarchive/archive_write_disk_set_standard_lookup.c
index 39f5891..5329425 100644
--- a/lib/libarchive/archive_write_disk_set_standard_lookup.c
+++ b/lib/libarchive/archive_write_disk_set_standard_lookup.c
@@ -122,7 +122,7 @@ lookup_gid(void *private_data, const char *gname, gid_t gid)
if (grent != NULL)
gid = grent->gr_gid;
}
-#elif _WIN32
+#elif defined(_WIN32) && !defined(__CYGWIN__)
/* TODO: do a gname->gid lookup for Windows. */
#endif
b->id = gid;
@@ -159,7 +159,7 @@ lookup_uid(void *private_data, const char *uname, uid_t uid)
if (pwent != NULL)
uid = pwent->pw_uid;
}
-#elif _WIN32
+#elif defined(_WIN32) && !defined(__CYGWIN__)
/* TODO: do a uname->uid lookup for Windows. */
#endif
b->id = uid;
diff --git a/lib/libarchive/archive_write_set_compression_program.c b/lib/libarchive/archive_write_set_compression_program.c
index 3615021..e612f3b 100644
--- a/lib/libarchive/archive_write_set_compression_program.c
+++ b/lib/libarchive/archive_write_set_compression_program.c
@@ -29,7 +29,7 @@ __FBSDID("$FreeBSD$");
/* This capability is only available on POSIX systems. */
#if (!defined(HAVE_PIPE) || !defined(HAVE_FCNTL) || \
- !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && !defined(_WIN32)
+ !(defined(HAVE_FORK) || defined(HAVE_VFORK))) && (!defined(_WIN32) || defined(__CYGWIN__))
#include "archive.h"
/*
diff --git a/lib/libarchive/archive_write_set_format_mtree.c b/lib/libarchive/archive_write_set_format_mtree.c
index 2910a0d..0043030 100644
--- a/lib/libarchive/archive_write_set_format_mtree.c
+++ b/lib/libarchive/archive_write_set_format_mtree.c
@@ -320,7 +320,7 @@ mtree_indent(struct mtree_writer *mtree)
archive_string_empty(&mtree->ebuf);
}
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
static size_t
dir_len(struct archive_entry *entry)
{
@@ -334,7 +334,7 @@ dir_len(struct archive_entry *entry)
return (r - path + 1);
}
-#else
+#else /* _WIN32 && !__CYGWIN__ */
/*
* Note: We should use wide-character for findng '\' character,
* a directory separator on Windows, because some character-set have
@@ -376,7 +376,7 @@ alen:
return (0);
return (al + 1);
}
-#endif /* _WIN32 */
+#endif /* _WIN32 && !__CYGWIN__ */
static int
parent_dir_changed(struct archive_string *dir, struct archive_entry *entry)
diff --git a/lib/libarchive/test/main.c b/lib/libarchive/test/main.c
index 62a0a3f..01a0817 100644
--- a/lib/libarchive/test/main.c
+++ b/lib/libarchive/test/main.c
@@ -33,7 +33,7 @@
#include <locale.h>
#include <stdarg.h>
#include <time.h>
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
#include <crtdbg.h>
#include <windows.h>
#include <winbase.h>
@@ -93,7 +93,7 @@ static int assertions = 0;
static const char *refdir;
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
static void
invalid_parameter_handler(const wchar_t * expression,
@@ -798,7 +798,7 @@ static int test_run(int i, const char *tmpdir)
/* If there were no failures, we can remove the work dir. */
if (failures == failures_before) {
if (!keep_temp_files && chdir(tmpdir) == 0) {
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
systemf("rm -rf %s", tests[i].name);
#else
systemf("rmdir /S /Q %s", tests[i].name);
@@ -894,7 +894,7 @@ extract_reference_file(const char *name)
fclose(in);
}
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
#define DEV_NULL "NUL"
#else
#define DEV_NULL "/dev/null"
@@ -966,7 +966,7 @@ get_refdir(void)
strncat(tried, "\n", sizeof(tried) - strlen(tried) - 1);
}
-#if defined(_WIN32) && defined(_DEBUG)
+#if defined(_WIN32) && !defined(__CYGWIN__) && defined(_DEBUG)
DebugBreak();
#endif
printf("Unable to locate known reference file %s\n", KNOWNREF);
@@ -992,7 +992,7 @@ int main(int argc, char **argv)
(void)argc; /* UNUSED */
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
/* To stop to run the default invalid parameter handler. */
_set_invalid_parameter_handler(invalid_parameter_handler);
/* for open() to a binary mode. */
diff --git a/lib/libarchive/test/test.h b/lib/libarchive/test/test.h
index fcac91a..539c826 100644
--- a/lib/libarchive/test/test.h
+++ b/lib/libarchive/test/test.h
@@ -37,7 +37,7 @@
#elif defined(__FreeBSD__)
/* Building as part of FreeBSD system requires a pre-built config.h. */
#include "config_freebsd.h"
-#elif defined(_WIN32)
+#elif defined(_WIN32) && !defined(__CYGWIN__)
/* Win32 can't run the 'configure' script. */
#include "config_windows.h"
#else
@@ -45,7 +45,7 @@
#error Oops: No config.h and no pre-built configuration in test.h.
#endif
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
#include <dirent.h>
#else
#include <direct.h>
@@ -56,7 +56,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
#include <unistd.h>
#endif
#include <wchar.h>
@@ -69,10 +69,15 @@
#ifdef __FreeBSD__
#include <sys/cdefs.h> /* For __FBSDID */
#else
+/* Some non-FreeBSD platforms such as newlib-derived ones like
+ * cygwin, have __FBSDID, so this definition must be guarded.
+ */
+#ifndef __FBSDID
#define __FBSDID(a) /* null */
#endif
+#endif
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
#define snprintf sprintf_s
#define LOCALE_DE "deu"
#else
diff --git a/lib/libarchive/test/test_read_compress_program.c b/lib/libarchive/test/test_read_compress_program.c
index 020c8f8..1044197 100644
--- a/lib/libarchive/test/test_read_compress_program.c
+++ b/lib/libarchive/test/test_read_compress_program.c
@@ -35,14 +35,34 @@ static unsigned char archive[] = {
DEFINE_TEST(test_read_compress_program)
{
int r;
-
-#if ARCHIVE_VERSION_NUMBER < 1009000
- skipping("archive_read_support_compression_program()");
-#else
struct archive_entry *ae;
struct archive *a;
const char *extprog;
+ /*
+ * First, test handling when a non-existent compression
+ * program is requested.
+ */
+ assert((a = archive_read_new()) != NULL);
+ r = archive_read_support_compression_program(a, "nonexistent");
+ if (r == ARCHIVE_FATAL) {
+ skipping("archive_read_support_compression_program() "
+ "unsupported on this platform");
+ return;
+ }
+ assertEqualIntA(a, ARCHIVE_OK, r);
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_open_memory(a, archive, sizeof(archive)));
+ assertEqualIntA(a, ARCHIVE_FATAL,
+ archive_read_next_header(a, &ae));
+ assertEqualIntA(a, ARCHIVE_WARN, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
+
+ /*
+ * If we have "gunzip", try using that.
+ */
if ((extprog = external_gzip_program(1)) == NULL) {
skipping("There is no gzip uncompression "
"program in this platform");
@@ -51,28 +71,18 @@ DEFINE_TEST(test_read_compress_program)
assert((a = archive_read_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK,
archive_read_support_compression_none(a));
- r = archive_read_support_compression_program(a, extprog);
- if (r == ARCHIVE_FATAL) {
- skipping("archive_read_support_compression_program() "
- "unsupported on this platform");
- return;
- }
- assertEqualIntA(a, ARCHIVE_OK, r);
+ assertEqualIntA(a, ARCHIVE_OK,
+ archive_read_support_compression_program(a, extprog));
assertEqualIntA(a, ARCHIVE_OK,
archive_read_support_format_all(a));
assertEqualIntA(a, ARCHIVE_OK,
archive_read_open_memory(a, archive, sizeof(archive)));
assertEqualIntA(a, ARCHIVE_OK,
archive_read_next_header(a, &ae));
- assert(archive_compression(a) == ARCHIVE_COMPRESSION_PROGRAM);
- assert(archive_format(a) == ARCHIVE_FORMAT_TAR_USTAR);
- assert(0 == archive_read_close(a));
-#if ARCHIVE_VERSION_NUMBER < 2000000
- archive_read_finish(a);
-#else
- assert(0 == archive_read_finish(a));
-#endif
-#endif
+ assertEqualInt(archive_compression(a), ARCHIVE_COMPRESSION_PROGRAM);
+ assertEqualInt(archive_format(a), ARCHIVE_FORMAT_TAR_USTAR);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
+ assertEqualInt(ARCHIVE_OK, archive_read_finish(a));
}
diff --git a/lib/libarchive/test/test_read_disk.c b/lib/libarchive/test/test_read_disk.c
index e368398..ce10440 100644
--- a/lib/libarchive/test/test_read_disk.c
+++ b/lib/libarchive/test/test_read_disk.c
@@ -111,6 +111,11 @@ DEFINE_TEST(test_read_disk)
if (archive_read_disk_set_standard_lookup(a) != ARCHIVE_OK) {
skipping("standard uname/gname lookup");
} else {
+#if defined(__CYGWIN__)
+ skipping("standard uname/gname lookup; typically no user with uid=0 on cygwin platform");
+ i = 0;
+ p = zero_groups[0]; /* avoid unused warnings */
+#else
/* XXX Someday, we may need to generalize this the
* same way we generalized the group name check below.
* That's needed only if we encounter a system where
@@ -135,6 +140,7 @@ DEFINE_TEST(test_read_disk)
failure("group 0 didn't have any of the expected names");
assertEqualString(p, zero_groups[0]);
}
+#endif
}
/* Deregister again and verify the default lookups again. */
diff --git a/lib/libarchive/test/test_read_extract.c b/lib/libarchive/test/test_read_extract.c
index b58b364..887ddfd 100644
--- a/lib/libarchive/test/test_read_extract.c
+++ b/lib/libarchive/test/test_read_extract.c
@@ -32,13 +32,13 @@ DEFINE_TEST(test_read_extract)
{
struct archive_entry *ae;
struct archive *a;
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
struct stat st;
#endif
size_t used;
int i;
char *buff, *file_buff;
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
int fd;
ssize_t bytes_read;
#endif
@@ -138,7 +138,7 @@ DEFINE_TEST(test_read_extract)
assert(0 == archive_read_finish(a));
#endif
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
/* Test the entries on disk. */
/* This first entry was extracted with ARCHIVE_EXTRACT_PERM,
* so the permissions should have been restored exactly,
diff --git a/lib/libarchive/test/test_tar_large.c b/lib/libarchive/test/test_tar_large.c
index f56dc6c..b2b8e5d 100644
--- a/lib/libarchive/test/test_tar_large.c
+++ b/lib/libarchive/test/test_tar_large.c
@@ -53,7 +53,7 @@ struct memblock {
struct memblock *next;
size_t size;
void *buff;
- off_t filebytes;
+ int64_t filebytes;
};
/*
@@ -61,17 +61,17 @@ struct memblock {
* some accounting overhead.
*/
struct memdata {
- off_t filebytes;
+ int64_t filebytes;
void *buff;
struct memblock *first;
struct memblock *last;
};
/* The following size definitions simplify things below. */
-#define KB ((off_t)1024)
-#define MB ((off_t)1024 * KB)
-#define GB ((off_t)1024 * MB)
-#define TB ((off_t)1024 * GB)
+#define KB ((int64_t)1024)
+#define MB ((int64_t)1024 * KB)
+#define GB ((int64_t)1024 * MB)
+#define TB ((int64_t)1024 * GB)
#if ARCHIVE_VERSION_NUMBER < 2000000
static ssize_t memory_read_skip(struct archive *, void *, size_t request);
@@ -100,7 +100,7 @@ memory_write(struct archive *a, void *_private, const void *buff, size_t size)
if ((const char *)filedata <= (const char *)buff
&& (const char *)buff < (const char *)filedata + filedatasize) {
/* We don't need to store a block of file data. */
- private->last->filebytes += (off_t)size;
+ private->last->filebytes += (int64_t)size;
} else {
/* Yes, we're assuming the very first write is metadata. */
/* It's header or metadata, copy and save it. */
@@ -140,7 +140,7 @@ memory_read(struct archive *a, void *_private, const void **buff)
* We're returning file bytes, simulate it by
* passing blocks from the template data.
*/
- if (private->filebytes > (off_t)filedatasize)
+ if (private->filebytes > (int64_t)filedatasize)
size = (ssize_t)filedatasize;
else
size = (ssize_t)private->filebytes;
@@ -202,7 +202,7 @@ memory_read_skip(struct archive *a, void *_private, off_t skip)
DEFINE_TEST(test_tar_large)
{
/* The sizes of the entries we're going to generate. */
- static off_t tests[] = {
+ static int64_t tests[] = {
/* Test for 32-bit signed overflow. */
2 * GB - 1, 2 * GB, 2 * GB + 1,
/* Test for 32-bit unsigned overflow. */
@@ -218,7 +218,8 @@ DEFINE_TEST(test_tar_large)
struct memdata memdata;
struct archive_entry *ae;
struct archive *a;
- off_t filesize, writesize;
+ int64_t filesize;
+ size_t writesize;
filedatasize = (size_t)(1 * MB);
filedata = malloc(filedatasize);
@@ -243,11 +244,6 @@ DEFINE_TEST(test_tar_large)
archive_entry_set_mode(ae, S_IFREG | 0755);
filesize = tests[i];
- if (filesize < 0) {
- archive_entry_free(ae);
- skipping("32-bit off_t doesn't permit testing of very large files.");
- return;
- }
archive_entry_set_size(ae, filesize);
assertA(0 == archive_write_header(a, ae));
@@ -257,10 +253,11 @@ DEFINE_TEST(test_tar_large)
* Write the actual data to the archive.
*/
while (filesize > 0) {
- writesize = (off_t)filedatasize;
- if (writesize > filesize)
- writesize = filesize;
- assertA(writesize == archive_write_data(a, filedata, writesize));
+ writesize = filedatasize;
+ if ((int64_t)writesize > filesize)
+ writesize = (size_t)filesize;
+ assertA((int)writesize
+ == archive_write_data(a, filedata, writesize));
filesize -= writesize;
}
}
diff --git a/lib/libarchive/test/test_write_disk.c b/lib/libarchive/test/test_write_disk.c
index 72c9444..c0b22e5 100644
--- a/lib/libarchive/test/test_write_disk.c
+++ b/lib/libarchive/test/test_write_disk.c
@@ -52,7 +52,7 @@ static void create(struct archive_entry *ae, const char *msg)
* that automatically. */
if (archive_entry_filetype(ae) == AE_IFDIR)
st.st_mode &= ~S_ISGID;
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
assertEqualInt(st.st_mode, archive_entry_mode(ae) & ~UMASK);
#endif
}
@@ -99,7 +99,7 @@ static void create_reg_file(struct archive_entry *ae, const char *msg)
assert(0 == stat(archive_entry_pathname(ae), &st));
failure("st.st_mode=%o archive_entry_mode(ae)=%o",
st.st_mode, archive_entry_mode(ae));
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
assertEqualInt(st.st_mode, (archive_entry_mode(ae) & ~UMASK));
#endif
assertEqualInt(st.st_size, sizeof(data));
@@ -146,7 +146,7 @@ static void create_reg_file2(struct archive_entry *ae, const char *msg)
assert(0 == stat(archive_entry_pathname(ae), &st));
failure("st.st_mode=%o archive_entry_mode(ae)=%o",
st.st_mode, archive_entry_mode(ae));
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
assertEqualInt(st.st_mode, (archive_entry_mode(ae) & ~UMASK));
#endif
assertEqualInt(st.st_size, i);
@@ -183,7 +183,7 @@ static void create_reg_file3(struct archive_entry *ae, const char *msg)
assert(0 == stat(archive_entry_pathname(ae), &st));
failure("st.st_mode=%o archive_entry_mode(ae)=%o",
st.st_mode, archive_entry_mode(ae));
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
assertEqualInt(st.st_mode, (archive_entry_mode(ae) & ~UMASK));
#endif
assertEqualInt(st.st_size, 5);
@@ -212,14 +212,14 @@ static void create_reg_file4(struct archive_entry *ae, const char *msg)
assert(0 == stat(archive_entry_pathname(ae), &st));
failure("st.st_mode=%o archive_entry_mode(ae)=%o",
st.st_mode, archive_entry_mode(ae));
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
assertEqualInt(st.st_mode, (archive_entry_mode(ae) & ~UMASK));
#endif
failure(msg);
assertEqualInt(st.st_size, sizeof(data));
}
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
static void create_reg_file_win(struct archive_entry *ae, const char *msg)
{
static const char data[]="abcdefghijklmnopqrstuvwxyz";
@@ -257,7 +257,7 @@ static void create_reg_file_win(struct archive_entry *ae, const char *msg)
st.st_mode, archive_entry_mode(ae));
assertEqualInt(st.st_size, sizeof(data));
}
-#endif /* _WIN32 */
+#endif /* _WIN32 && !__CYGWIN__ */
#endif
DEFINE_TEST(test_write_disk)
@@ -326,7 +326,7 @@ DEFINE_TEST(test_write_disk)
create(ae, "Test creating a file over an existing dir.");
archive_entry_free(ae);
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(__CYGWIN__)
/* A file with unusable characters in its file name. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "f:i*l?e\"f<i>l|e");
@@ -342,6 +342,6 @@ DEFINE_TEST(test_write_disk)
create_reg_file_win(ae, "Test creating a regular file"
" with unusable characters in its file name");
archive_entry_free(ae);
-#endif /* _WIN32 */
+#endif /* _WIN32 && !__CYGWIN__ */
#endif
}
diff --git a/lib/libarchive/test/test_write_disk_failures.c b/lib/libarchive/test/test_write_disk_failures.c
index 03304d4..0d7b894 100644
--- a/lib/libarchive/test/test_write_disk_failures.c
+++ b/lib/libarchive/test/test_write_disk_failures.c
@@ -34,7 +34,7 @@ __FBSDID("$FreeBSD$");
DEFINE_TEST(test_write_disk_failures)
{
-#if ARCHIVE_VERSION_NUMBER < 1009000 || defined(_WIN32)
+#if ARCHIVE_VERSION_NUMBER < 1009000 || (defined(_WIN32) && !defined(__CYGWIN__))
skipping("archive_write_disk interface");
#else
struct archive_entry *ae;
diff --git a/lib/libarchive/test/test_write_disk_hardlink.c b/lib/libarchive/test/test_write_disk_hardlink.c
index f9bcfae..2ab2420 100644
--- a/lib/libarchive/test/test_write_disk_hardlink.c
+++ b/lib/libarchive/test/test_write_disk_hardlink.c
@@ -25,7 +25,14 @@
#include "test.h"
__FBSDID("$FreeBSD$");
+#if defined(_WIN32) && !defined(__CYGWIN__)
+/* Execution bits, Group members bits and others bits do not work. */
+#define UMASK 0177
+#define E_MASK (~0177)
+#else
#define UMASK 022
+#define E_MASK (~0)
+#endif
/*
* Exercise hardlink recreation.
@@ -36,7 +43,7 @@ __FBSDID("$FreeBSD$");
*/
DEFINE_TEST(test_write_disk_hardlink)
{
-#if ARCHIVE_VERSION_NUMBER < 1009000 || defined(_WIN32)
+#if ARCHIVE_VERSION_NUMBER < 1009000
skipping("archive_write_disk_hardlink tests");
#else
static const char data[]="abcdefghijklmnopqrstuvwxyz";
@@ -175,7 +182,7 @@ DEFINE_TEST(test_write_disk_hardlink)
* doesn't carry data for it, we consider it to be
* non-authoritive for meta data as well. This is consistent
* with GNU tar and BSD pax. */
- assertEqualInt(st.st_mode, (S_IFREG | 0755) & ~UMASK);
+ assertEqualInt(st.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
assertEqualInt(st.st_size, sizeof(data));
assertEqualInt(st.st_nlink, 2);
@@ -194,7 +201,7 @@ DEFINE_TEST(test_write_disk_hardlink)
* common file formats that store a size of zero for
* hardlinks. */
assert(0 == stat("link2a", &st));
- assertEqualInt(st.st_mode, (S_IFREG | 0755) & ~UMASK);
+ assertEqualInt(st.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
assertEqualInt(st.st_size, sizeof(data));
assertEqualInt(st.st_nlink, 2);
@@ -207,12 +214,12 @@ DEFINE_TEST(test_write_disk_hardlink)
/* Test #3 */
assert(0 == stat("link3a", &st));
- assertEqualInt(st.st_mode, (S_IFREG | 0755) & ~UMASK);
+ assertEqualInt(st.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
assertEqualInt(st.st_size, sizeof(data));
assertEqualInt(st.st_nlink, 2);
assert(0 == stat("link3b", &st2));
- assertEqualInt(st2.st_mode, (S_IFREG | 0755) & ~UMASK);
+ assertEqualInt(st2.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
assertEqualInt(st2.st_size, sizeof(data));
assertEqualInt(st2.st_nlink, 2);
assertEqualInt(st.st_ino, st2.st_ino);
@@ -220,12 +227,12 @@ DEFINE_TEST(test_write_disk_hardlink)
/* Test #4 */
assert(0 == stat("link4a", &st));
- assertEqualInt(st.st_mode, (S_IFREG | 0755) & ~UMASK);
+ assertEqualInt(st.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
assertEqualInt(st.st_size, sizeof(data));
assertEqualInt(st.st_nlink, 2);
assert(0 == stat("link4b", &st2));
- assertEqualInt(st2.st_mode, (S_IFREG | 0755) & ~UMASK);
+ assertEqualInt(st2.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
assertEqualInt(st2.st_size, sizeof(data));
assertEqualInt(st2.st_nlink, 2);
assertEqualInt(st.st_ino, st2.st_ino);
diff --git a/lib/libarchive/test/test_write_disk_perms.c b/lib/libarchive/test/test_write_disk_perms.c
index 87e2a2d..3d9be27 100644
--- a/lib/libarchive/test/test_write_disk_perms.c
+++ b/lib/libarchive/test/test_write_disk_perms.c
@@ -25,7 +25,7 @@
#include "test.h"
__FBSDID("$FreeBSD$");
-#if ARCHIVE_VERSION_NUMBER >= 1009000 && !defined(_WIN32)
+#if ARCHIVE_VERSION_NUMBER >= 1009000 && (!defined(_WIN32) || defined(__CYGWIN__))
#define UMASK 022
@@ -125,7 +125,7 @@ defaultgid(void)
DEFINE_TEST(test_write_disk_perms)
{
-#if ARCHIVE_VERSION_NUMBER < 1009000 || defined(_WIN32)
+#if ARCHIVE_VERSION_NUMBER < 1009000 || (defined(_WIN32) && !defined(__CYGWIN__))
skipping("archive_write_disk interface");
#else
struct archive *a;
diff --git a/lib/libarchive/test/test_write_disk_secure.c b/lib/libarchive/test/test_write_disk_secure.c
index 4c014b1..d417489 100644
--- a/lib/libarchive/test/test_write_disk_secure.c
+++ b/lib/libarchive/test/test_write_disk_secure.c
@@ -55,7 +55,7 @@ DEFINE_TEST(test_write_disk_secure)
archive_entry_free(ae);
assert(0 == archive_write_finish_entry(a));
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
/* Write a symlink to the dir above. */
assert((ae = archive_entry_new()) != NULL);
archive_entry_copy_pathname(ae, "link_to_dir");
@@ -187,7 +187,7 @@ DEFINE_TEST(test_write_disk_secure)
assert(0 == archive_write_finish(a));
#endif
-#ifndef _WIN32
+#if !defined(_WIN32) || defined(__CYGWIN__)
/* Test the entries on disk. */
assert(0 == lstat("dir", &st));
failure("dir: st.st_mode=%o", st.st_mode);
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index 2d97fbe..cf9ef3a 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -16,6 +16,7 @@ SHLIB_MAJOR= 7
WARNS?= 2
CFLAGS+=-I${.CURDIR}/include -I${.CURDIR}/../../include
CFLAGS+=-I${.CURDIR}/${MACHINE_ARCH}
+CFLAGS+=-DNLS
CLEANFILES+=tags
INSTALL_PIC_ARCHIVE=
PRECIOUSLIB=
diff --git a/lib/libc/db/README b/lib/libc/db/README
index bed2c92..1f9ae72 100644
--- a/lib/libc/db/README
+++ b/lib/libc/db/README
@@ -1,4 +1,5 @@
# @(#)README 8.27 (Berkeley) 9/1/94
+# $FreeBSD$
This is version 1.85 of the Berkeley DB code.
@@ -31,10 +32,3 @@ mpool The memory pool routines.
recno The fixed/variable length record routines.
test Test package.
-============================================
-Debugging:
-
-If you're running a memory checker (e.g. Purify) on DB, make sure that
-you recompile it with "-DPURIFY" in the CFLAGS, first. By default,
-allocated pages are not initialized by the DB code, and they will show
-up as reads of uninitialized memory in the buffer write routines.
diff --git a/lib/libc/db/Symbol.map b/lib/libc/db/Symbol.map
index 14df29f..225fd40 100644
--- a/lib/libc/db/Symbol.map
+++ b/lib/libc/db/Symbol.map
@@ -16,7 +16,6 @@ FBSD_1.0 {
dbm_dirfno;
mpool_open;
mpool_filter;
- mpool_new;
mpool_get;
mpool_put;
mpool_close;
@@ -24,6 +23,11 @@ FBSD_1.0 {
mpool_stat;
};
+FBSD_1.1 {
+ mpool_new;
+ mpool_delete;
+};
+
FBSDprivate_1.0 {
__bt_open;
__dbpanic;
diff --git a/lib/libc/db/btree/bt_debug.c b/lib/libc/db/btree/bt_debug.c
index 5275bb7..dc8b83d 100644
--- a/lib/libc/db/btree/bt_debug.c
+++ b/lib/libc/db/btree/bt_debug.c
@@ -61,7 +61,7 @@ __bt_dump(DB *dbp)
char *sep;
t = dbp->internal;
- (void)fprintf(stderr, "%s: pgsz %d",
+ (void)fprintf(stderr, "%s: pgsz %u",
F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize);
if (F_ISSET(t, R_RECNO))
(void)fprintf(stderr, " keys %u", t->bt_nrecs);
@@ -83,10 +83,9 @@ __bt_dump(DB *dbp)
}
#undef X
- for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
+ for (i = P_ROOT;
+ (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i)
__bt_dpage(h);
- (void)mpool_put(t->bt_mp, h, 0);
- }
}
/*
@@ -135,10 +134,8 @@ __bt_dnpage(DB *dbp, pgno_t pgno)
PAGE *h;
t = dbp->internal;
- if ((h = mpool_get(t->bt_mp, pgno, 0)) != NULL) {
+ if ((h = mpool_get(t->bt_mp, pgno, MPOOL_IGNOREPIN)) != NULL)
__bt_dpage(h);
- (void)mpool_put(t->bt_mp, h, 0);
- }
}
/*
@@ -157,7 +154,7 @@ __bt_dpage(PAGE *h)
indx_t cur, top;
char *sep;
- (void)fprintf(stderr, " page %d: (", h->pgno);
+ (void)fprintf(stderr, " page %u: (", h->pgno);
#undef X
#define X(flag, name) \
if (h->flags & flag) { \
@@ -174,7 +171,7 @@ __bt_dpage(PAGE *h)
(void)fprintf(stderr, ")\n");
#undef X
- (void)fprintf(stderr, "\tprev %2d next %2d", h->prevpg, h->nextpg);
+ (void)fprintf(stderr, "\tprev %2u next %2u", h->prevpg, h->nextpg);
if (h->flags & P_OVERFLOW)
return;
@@ -257,7 +254,8 @@ __bt_stat(DB *dbp)
t = dbp->internal;
pcont = pinternal = pleaf = 0;
nkeys = ifree = lfree = 0;
- for (i = P_ROOT; (h = mpool_get(t->bt_mp, i, 0)) != NULL; ++i) {
+ for (i = P_ROOT;
+ (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i)
switch (h->flags & P_TYPE) {
case P_BINTERNAL:
case P_RINTERNAL:
@@ -274,45 +272,41 @@ __bt_stat(DB *dbp)
++pcont;
break;
}
- (void)mpool_put(t->bt_mp, h, 0);
- }
/* Count the levels of the tree. */
for (i = P_ROOT, levels = 0 ;; ++levels) {
- h = mpool_get(t->bt_mp, i, 0);
+ h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN);
if (h->flags & (P_BLEAF|P_RLEAF)) {
if (levels == 0)
levels = 1;
- (void)mpool_put(t->bt_mp, h, 0);
break;
}
i = F_ISSET(t, R_RECNO) ?
GETRINTERNAL(h, 0)->pgno :
GETBINTERNAL(h, 0)->pgno;
- (void)mpool_put(t->bt_mp, h, 0);
}
- (void)fprintf(stderr, "%d level%s with %ld keys",
+ (void)fprintf(stderr, "%d level%s with %lu keys",
levels, levels == 1 ? "" : "s", nkeys);
if (F_ISSET(t, R_RECNO))
- (void)fprintf(stderr, " (%d header count)", t->bt_nrecs);
+ (void)fprintf(stderr, " (%u header count)", t->bt_nrecs);
(void)fprintf(stderr,
- "\n%u pages (leaf %d, internal %d, overflow %d)\n",
+ "\n%u pages (leaf %u, internal %u, overflow %u)\n",
pinternal + pleaf + pcont, pleaf, pinternal, pcont);
- (void)fprintf(stderr, "%ld cache hits, %ld cache misses\n",
+ (void)fprintf(stderr, "%lu cache hits, %lu cache misses\n",
bt_cache_hit, bt_cache_miss);
(void)fprintf(stderr, "%lu splits (%lu root splits, %lu sort splits)\n",
bt_split, bt_rootsplit, bt_sortsplit);
pleaf *= t->bt_psize - BTDATAOFF;
if (pleaf)
(void)fprintf(stderr,
- "%.0f%% leaf fill (%ld bytes used, %ld bytes free)\n",
+ "%.0f%% leaf fill (%lu bytes used, %lu bytes free)\n",
((double)(pleaf - lfree) / pleaf) * 100,
pleaf - lfree, lfree);
pinternal *= t->bt_psize - BTDATAOFF;
if (pinternal)
(void)fprintf(stderr,
- "%.0f%% internal fill (%ld bytes used, %ld bytes free\n",
+ "%.0f%% internal fill (%lu bytes used, %lu bytes free\n",
((double)(pinternal - ifree) / pinternal) * 100,
pinternal - ifree, ifree);
if (bt_pfxsaved)
diff --git a/lib/libc/db/btree/bt_open.c b/lib/libc/db/btree/bt_open.c
index fb7333e..47f3646 100644
--- a/lib/libc/db/btree/bt_open.c
+++ b/lib/libc/db/btree/bt_open.c
@@ -96,7 +96,7 @@ __bt_open(const char *fname, int flags, int mode, const BTREEINFO *openinfo, int
DB *dbp;
pgno_t ncache;
ssize_t nr;
- int machine_lorder;
+ int machine_lorder, saved_errno;
t = NULL;
@@ -156,9 +156,8 @@ __bt_open(const char *fname, int flags, int mode, const BTREEINFO *openinfo, int
goto einval;
/* Allocate and initialize DB and BTREE structures. */
- if ((t = (BTREE *)malloc(sizeof(BTREE))) == NULL)
+ if ((t = (BTREE *)calloc(1, sizeof(BTREE))) == NULL)
goto err;
- memset(t, 0, sizeof(BTREE));
t->bt_fd = -1; /* Don't close unopened fd on error. */
t->bt_lorder = b.lorder;
t->bt_order = NOT;
@@ -166,9 +165,8 @@ __bt_open(const char *fname, int flags, int mode, const BTREEINFO *openinfo, int
t->bt_pfx = b.prefix;
t->bt_rfd = -1;
- if ((t->bt_dbp = dbp = (DB *)malloc(sizeof(DB))) == NULL)
+ if ((t->bt_dbp = dbp = (DB *)calloc(1, sizeof(DB))) == NULL)
goto err;
- memset(t->bt_dbp, 0, sizeof(DB));
if (t->bt_lorder != machine_lorder)
F_SET(t, B_NEEDSWAP);
@@ -327,13 +325,15 @@ einval: errno = EINVAL;
eftype: errno = EFTYPE;
goto err;
-err: if (t) {
+err: saved_errno = errno;
+ if (t) {
if (t->bt_dbp)
free(t->bt_dbp);
if (t->bt_fd != -1)
(void)_close(t->bt_fd);
free(t);
}
+ errno = saved_errno;
return (NULL);
}
@@ -352,18 +352,25 @@ nroot(BTREE *t)
PAGE *meta, *root;
pgno_t npg;
- if ((meta = mpool_get(t->bt_mp, 0, 0)) != NULL) {
- mpool_put(t->bt_mp, meta, 0);
- return (RET_SUCCESS);
+ if ((root = mpool_get(t->bt_mp, 1, 0)) != NULL) {
+ if (root->lower == 0 &&
+ root->pgno == 0 &&
+ root->linp[0] == 0) {
+ mpool_delete(t->bt_mp, root);
+ errno = EINVAL;
+ } else {
+ mpool_put(t->bt_mp, root, 0);
+ return (RET_SUCCESS);
+ }
}
if (errno != EINVAL) /* It's OK to not exist. */
return (RET_ERROR);
errno = 0;
- if ((meta = mpool_new(t->bt_mp, &npg)) == NULL)
+ if ((meta = mpool_new(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL)
return (RET_ERROR);
- if ((root = mpool_new(t->bt_mp, &npg)) == NULL)
+ if ((root = mpool_new(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL)
return (RET_ERROR);
if (npg != P_ROOT)
@@ -383,14 +390,18 @@ static int
tmp(void)
{
sigset_t set, oset;
- int fd;
+ int fd, len;
char *envtmp = NULL;
char path[MAXPATHLEN];
if (issetugid() == 0)
envtmp = getenv("TMPDIR");
- (void)snprintf(path,
+ len = snprintf(path,
sizeof(path), "%s/bt.XXXXXXXXXX", envtmp ? envtmp : "/tmp");
+ if (len < 0 || len >= (int)sizeof(path)) {
+ errno = ENAMETOOLONG;
+ return(-1);
+ }
(void)sigfillset(&set);
(void)_sigprocmask(SIG_BLOCK, &set, &oset);
diff --git a/lib/libc/db/btree/bt_page.c b/lib/libc/db/btree/bt_page.c
index face4b1..ab5e359 100644
--- a/lib/libc/db/btree/bt_page.c
+++ b/lib/libc/db/btree/bt_page.c
@@ -90,5 +90,5 @@ __bt_new(BTREE *t, pgno_t *npg)
F_SET(t, B_METADIRTY);
return (h);
}
- return (mpool_new(t->bt_mp, npg));
+ return (mpool_new(t->bt_mp, npg, MPOOL_PAGE_NEXT));
}
diff --git a/lib/libc/db/btree/bt_put.c b/lib/libc/db/btree/bt_put.c
index 31931dc..e4016c0 100644
--- a/lib/libc/db/btree/bt_put.c
+++ b/lib/libc/db/btree/bt_put.c
@@ -197,7 +197,7 @@ delete: if (__bt_dleaf(t, key, h, idx) == RET_ERROR) {
* into the offset array, shift the pointers up.
*/
nbytes = NBLEAFDBT(key->size, data->size);
- if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t)) {
if ((status = __bt_split(t, h, key,
data, dflags, nbytes, idx)) != RET_SUCCESS)
return (status);
@@ -278,7 +278,7 @@ bt_fast(BTREE *t, const DBT *key, const DBT *data, int *exactp)
* have to search to get split stack.
*/
nbytes = NBLEAFDBT(key->size, data->size);
- if (h->upper - h->lower < nbytes + sizeof(indx_t))
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t))
goto miss;
if (t->bt_order == FORWARD) {
diff --git a/lib/libc/db/btree/bt_split.c b/lib/libc/db/btree/bt_split.c
index 8fbc2f0..18cd0ed 100644
--- a/lib/libc/db/btree/bt_split.c
+++ b/lib/libc/db/btree/bt_split.c
@@ -205,7 +205,7 @@ __bt_split(BTREE *t, PAGE *sp, const DBT *key, const DBT *data, int flags,
}
/* Split the parent page if necessary or shift the indices. */
- if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t)) {
sp = h;
h = h->pgno == P_ROOT ?
bt_root(t, h, &l, &r, &skip, nbytes) :
@@ -372,13 +372,10 @@ bt_page(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen)
}
/* Put the new left page for the split into place. */
- if ((l = (PAGE *)malloc(t->bt_psize)) == NULL) {
+ if ((l = (PAGE *)calloc(1, t->bt_psize)) == NULL) {
mpool_put(t->bt_mp, r, 0);
return (NULL);
}
-#ifdef PURIFY
- memset(l, 0xff, t->bt_psize);
-#endif
l->pgno = h->pgno;
l->nextpg = r->pgno;
l->prevpg = h->prevpg;
diff --git a/lib/libc/db/db/db.c b/lib/libc/db/db/db.c
index 7f18a8d..3cfd0a9 100644
--- a/lib/libc/db/db/db.c
+++ b/lib/libc/db/db/db.c
@@ -50,8 +50,8 @@ dbopen(const char *fname, int flags, int mode, DBTYPE type, const void *openinfo
#define DB_FLAGS (DB_LOCK | DB_SHMEM | DB_TXN)
#define USE_OPEN_FLAGS \
- (O_CREAT | O_EXCL | O_EXLOCK | O_NONBLOCK | O_RDONLY | \
- O_RDWR | O_SHLOCK | O_TRUNC)
+ (O_CREAT | O_EXCL | O_EXLOCK | O_NOFOLLOW | O_NONBLOCK | \
+ O_RDONLY | O_RDWR | O_SHLOCK | O_SYNC | O_TRUNC)
if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
switch (type) {
diff --git a/lib/libc/db/hash/README b/lib/libc/db/hash/README
index f29ccf7..80d6743 100644
--- a/lib/libc/db/hash/README
+++ b/lib/libc/db/hash/README
@@ -1,4 +1,5 @@
# @(#)README 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
This package implements a superset of the hsearch and dbm/ndbm libraries.
@@ -44,10 +45,6 @@ Test Programs:
NOTES:
-The file search.h is provided for using the hsearch compatible interface
-on BSD systems. On System V derived systems, search.h should appear in
-/usr/include.
-
The man page ../man/db.3 explains the interface to the hashing system.
The file hash.ps is a postscript copy of a paper explaining
the history, implementation, and performance of the hash package.
diff --git a/lib/libc/db/hash/hash.c b/lib/libc/db/hash/hash.c
index 3013f68..b58b36f 100644
--- a/lib/libc/db/hash/hash.c
+++ b/lib/libc/db/hash/hash.c
@@ -120,25 +120,15 @@ __hash_open(const char *file, int flags, int mode,
*/
hashp->flags = flags;
- new_table = 0;
- if (!file || (flags & O_TRUNC) ||
- (stat(file, &statbuf) && (errno == ENOENT))) {
- if (errno == ENOENT)
- errno = 0; /* Just in case someone looks at errno */
- new_table = 1;
- }
if (file) {
if ((hashp->fp = _open(file, flags, mode)) == -1)
RETURN_ERROR(errno, error0);
-
- /* if the .db file is empty, and we had permission to create
- a new .db file, then reinitialize the database */
- if ((flags & O_CREAT) &&
- _fstat(hashp->fp, &statbuf) == 0 && statbuf.st_size == 0)
- new_table = 1;
-
(void)_fcntl(hashp->fp, F_SETFD, 1);
- }
+ new_table = _fstat(hashp->fp, &statbuf) == 0 &&
+ statbuf.st_size == 0 && (flags & O_ACCMODE) != O_RDONLY;
+ } else
+ new_table = 1;
+
if (new_table) {
if (!(hashp = init_hash(hashp, file, info)))
RETURN_ERROR(errno, error1);
@@ -164,7 +154,7 @@ __hash_open(const char *file, int flags, int mode,
if (hashp->VERSION != HASHVERSION &&
hashp->VERSION != OLDHASHVERSION)
RETURN_ERROR(EFTYPE, error1);
- if (hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
+ if ((int32_t)hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
RETURN_ERROR(EFTYPE, error1);
/*
* Figure out how many segments we need. Max_Bucket is the
@@ -173,7 +163,6 @@ __hash_open(const char *file, int flags, int mode,
*/
nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) /
hashp->SGSIZE;
- hashp->nsegs = 0;
if (alloc_segs(hashp, nsegs))
/*
* If alloc_segs fails, table will have been destroyed
@@ -347,8 +336,7 @@ init_hash(HTAB *hashp, const char *file, const HASHINFO *info)
static int
init_htab(HTAB *hashp, int nelem)
{
- int nbuckets, nsegs;
- int l2;
+ int nbuckets, nsegs, l2;
/*
* Divide number of elements by the fill factor and determine a
@@ -428,6 +416,10 @@ hdestroy(HTAB *hashp)
for (i = 0; i < hashp->nmaps; i++)
if (hashp->mapp[i])
free(hashp->mapp[i]);
+ if (hashp->tmp_key)
+ free(hashp->tmp_key);
+ if (hashp->tmp_buf)
+ free(hashp->tmp_buf);
if (hashp->fp != -1)
(void)_close(hashp->fp);
@@ -495,8 +487,7 @@ flush_meta(HTAB *hashp)
whdrp = &whdr;
swap_header_copy(&hashp->hdr, whdrp);
#endif
- if ((lseek(fp, (off_t)0, SEEK_SET) == -1) ||
- ((wsize = _write(fp, whdrp, sizeof(HASHHDR))) == -1))
+ if ((wsize = pwrite(fp, whdrp, sizeof(HASHHDR), (off_t)0)) == -1)
return (-1);
else
if (wsize != sizeof(HASHHDR)) {
@@ -541,8 +532,7 @@ hash_put(const DB *dbp, DBT *key, const DBT *data, u_int32_t flag)
hashp = (HTAB *)dbp->internal;
if (flag && flag != R_NOOVERWRITE) {
- hashp->error = EINVAL;
- errno = EINVAL;
+ hashp->error = errno = EINVAL;
return (ERROR);
}
if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
@@ -721,7 +711,7 @@ hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag)
hashp->cndx = 1;
hashp->cpage = NULL;
}
-
+ next_bucket:
for (bp = NULL; !bp || !bp[0]; ) {
if (!(bufp = hashp->cpage)) {
for (bucket = hashp->cbucket;
@@ -736,12 +726,22 @@ hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag)
break;
}
hashp->cbucket = bucket;
- if (hashp->cbucket > hashp->MAX_BUCKET) {
+ if ((u_int32_t)hashp->cbucket > hashp->MAX_BUCKET) {
hashp->cbucket = -1;
return (ABNORMAL);
}
- } else
+ } else {
bp = (u_int16_t *)hashp->cpage->page;
+ if (flag == R_NEXT) {
+ hashp->cndx += 2;
+ if (hashp->cndx > bp[0]) {
+ hashp->cpage = NULL;
+ hashp->cbucket++;
+ hashp->cndx = 1;
+ goto next_bucket;
+ }
+ }
+ }
#ifdef DEBUG
assert(bp);
@@ -765,17 +765,12 @@ hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag)
if (__big_keydata(hashp, bufp, key, data, 1))
return (ERROR);
} else {
+ if (hashp->cpage == 0)
+ return (ERROR);
key->data = (u_char *)hashp->cpage->page + bp[ndx];
key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
data->size = bp[ndx] - bp[ndx + 1];
- ndx += 2;
- if (ndx > bp[0]) {
- hashp->cpage = NULL;
- hashp->cbucket++;
- hashp->cndx = 1;
- } else
- hashp->cndx = ndx;
}
return (SUCCESS);
}
@@ -858,7 +853,7 @@ hash_realloc(SEGMENT **p_ptr, int oldsize, int newsize)
u_int32_t
__call_hash(HTAB *hashp, char *k, int len)
{
- int n, bucket;
+ unsigned int n, bucket;
n = hashp->hash(k, len);
bucket = n & hashp->HIGH_MASK;
@@ -887,15 +882,18 @@ alloc_segs(HTAB *hashp, int nsegs)
errno = save_errno;
return (-1);
}
+ hashp->nsegs = nsegs;
+ if (nsegs == 0)
+ return (0);
/* Allocate segments */
- if ((store =
- (SEGMENT)calloc(nsegs << hashp->SSHIFT, sizeof(SEGMENT))) == NULL) {
+ if ((store = (SEGMENT)calloc(nsegs << hashp->SSHIFT,
+ sizeof(SEGMENT))) == NULL) {
save_errno = errno;
(void)hdestroy(hashp);
errno = save_errno;
return (-1);
}
- for (i = 0; i < nsegs; i++, hashp->nsegs++)
+ for (i = 0; i < nsegs; i++)
hashp->dir[i] = &store[i << hashp->SSHIFT];
return (0);
}
diff --git a/lib/libc/db/hash/hash.h b/lib/libc/db/hash/hash.h
index f35fb4e..8329413 100644
--- a/lib/libc/db/hash/hash.h
+++ b/lib/libc/db/hash/hash.h
@@ -71,11 +71,11 @@ typedef struct hashhdr { /* Disk resident portion */
int32_t ovfl_point; /* Where overflow pages are being
* allocated */
int32_t last_freed; /* Last overflow page freed */
- int32_t max_bucket; /* ID of Maximum bucket in use */
- int32_t high_mask; /* Mask to modulo into entire table */
- int32_t low_mask; /* Mask to modulo into lower half of
+ u_int32_t max_bucket; /* ID of Maximum bucket in use */
+ u_int32_t high_mask; /* Mask to modulo into entire table */
+ u_int32_t low_mask; /* Mask to modulo into lower half of
* table */
- int32_t ffactor; /* Fill factor */
+ u_int32_t ffactor; /* Fill factor */
int32_t nkeys; /* Number of keys in hash table */
int32_t hdrpages; /* Size of table header */
int32_t h_charkey; /* value of hash(CHARKEY) */
diff --git a/lib/libc/db/hash/hash_bigkey.c b/lib/libc/db/hash/hash_bigkey.c
index c2a1e03..c1914a5 100644
--- a/lib/libc/db/hash/hash_bigkey.c
+++ b/lib/libc/db/hash/hash_bigkey.c
@@ -86,7 +86,8 @@ int
__big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
{
u_int16_t *p;
- int key_size, n, val_size;
+ int key_size, n;
+ unsigned int val_size;
u_int16_t space, move_bytes, off;
char *cp, *key_data, *val_data;
@@ -117,18 +118,30 @@ __big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
return (-1);
n = p[0];
if (!key_size) {
- if (FREESPACE(p)) {
- move_bytes = MIN(FREESPACE(p), val_size);
+ space = FREESPACE(p);
+ if (space) {
+ move_bytes = MIN(space, val_size);
+ /*
+ * If the data would fit exactly in the
+ * remaining space, we must overflow it to the
+ * next page; otherwise the invariant that the
+ * data must end on a page with FREESPACE
+ * non-zero would fail.
+ */
+ if (space == val_size && val_size == val->size)
+ goto toolarge;
off = OFFSET(p) - move_bytes;
- p[n] = off;
memmove(cp + off, val_data, move_bytes);
val_data += move_bytes;
val_size -= move_bytes;
+ p[n] = off;
p[n - 2] = FULL_KEY_DATA;
FREESPACE(p) = FREESPACE(p) - move_bytes;
OFFSET(p) = off;
- } else
+ } else {
+ toolarge:
p[n - 2] = FULL_KEY;
+ }
}
p = (u_int16_t *)bufp->page;
cp = bufp->page;
@@ -238,12 +251,12 @@ __big_delete(HTAB *hashp, BUFHEAD *bufp)
n -= 2;
bp[0] = n;
FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
- OFFSET(bp) = hashp->BSIZE - 1;
+ OFFSET(bp) = hashp->BSIZE;
bufp->flags |= BUF_MOD;
if (rbufp)
__free_ovflpage(hashp, rbufp);
- if (last_bfp != rbufp)
+ if (last_bfp && last_bfp != rbufp)
__free_ovflpage(hashp, last_bfp);
hashp->NKEYS--;
diff --git a/lib/libc/db/hash/hash_buf.c b/lib/libc/db/hash/hash_buf.c
index 7eadbb9..4445fc5 100644
--- a/lib/libc/db/hash/hash_buf.c
+++ b/lib/libc/db/hash/hash_buf.c
@@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$");
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#ifdef DEBUG
#include <assert.h>
@@ -163,24 +164,38 @@ newbuf(HTAB *hashp, u_int32_t addr, BUFHEAD *prev_bp)
oaddr = 0;
bp = LRU;
+
+ /* It is bad to overwrite the page under the cursor. */
+ if (bp == hashp->cpage) {
+ BUF_REMOVE(bp);
+ MRU_INSERT(bp);
+ bp = LRU;
+ }
+
+ /* If prev_bp is part of bp overflow, create a new buffer. */
+ if (hashp->nbufs == 0 && prev_bp && bp->ovfl) {
+ BUFHEAD *ovfl;
+
+ for (ovfl = bp->ovfl; ovfl ; ovfl = ovfl->ovfl) {
+ if (ovfl == prev_bp) {
+ hashp->nbufs++;
+ break;
+ }
+ }
+ }
+
/*
* If LRU buffer is pinned, the buffer pool is too small. We need to
* allocate more buffers.
*/
- if (hashp->nbufs || (bp->flags & BUF_PIN)) {
+ if (hashp->nbufs || (bp->flags & BUF_PIN) || bp == hashp->cpage) {
/* Allocate a new one */
- if ((bp = (BUFHEAD *)malloc(sizeof(BUFHEAD))) == NULL)
+ if ((bp = (BUFHEAD *)calloc(1, sizeof(BUFHEAD))) == NULL)
return (NULL);
-#ifdef PURIFY
- memset(bp, 0xff, sizeof(BUFHEAD));
-#endif
- if ((bp->page = (char *)malloc(hashp->BSIZE)) == NULL) {
+ if ((bp->page = (char *)calloc(1, hashp->BSIZE)) == NULL) {
free(bp);
return (NULL);
}
-#ifdef PURIFY
- memset(bp->page, 0xff, hashp->BSIZE);
-#endif
if (hashp->nbufs)
hashp->nbufs--;
} else {
@@ -267,7 +282,7 @@ newbuf(HTAB *hashp, u_int32_t addr, BUFHEAD *prev_bp)
*/
#ifdef DEBUG1
(void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n",
- prev_bp->addr, (prev_bp->ovfl ? bp->ovfl->addr : 0),
+ prev_bp->addr, (prev_bp->ovfl ? prev_bp->ovfl->addr : 0),
(bp ? bp->addr : 0));
#endif
prev_bp->ovfl = bp;
@@ -319,8 +334,10 @@ __buf_free(HTAB *hashp, int do_free, int to_disk)
}
/* Check if we are freeing stuff */
if (do_free) {
- if (bp->page)
+ if (bp->page) {
+ (void)memset(bp->page, 0, hashp->BSIZE);
free(bp->page);
+ }
BUF_REMOVE(bp);
free(bp);
bp = LRU;
diff --git a/lib/libc/db/hash/hash_func.c b/lib/libc/db/hash/hash_func.c
index 2ca0a48..db32a75 100644
--- a/lib/libc/db/hash/hash_func.c
+++ b/lib/libc/db/hash/hash_func.c
@@ -43,60 +43,57 @@ __FBSDID("$FreeBSD$");
#include "page.h"
#include "extern.h"
+#ifdef notdef
static u_int32_t hash1(const void *, size_t) __unused;
static u_int32_t hash2(const void *, size_t) __unused;
static u_int32_t hash3(const void *, size_t) __unused;
+#endif
static u_int32_t hash4(const void *, size_t);
-/* Global default hash function */
+/* Default hash function. */
u_int32_t (*__default_hash)(const void *, size_t) = hash4;
+#ifdef notdef
/*
- * HASH FUNCTIONS
- *
* Assume that we've already split the bucket to which this key hashes,
* calculate that bucket, and check that in fact we did already split it.
*
- * This came from ejb's hsearch.
+ * EJB's original hsearch hash.
*/
-
#define PRIME1 37
#define PRIME2 1048583
-static u_int32_t
-hash1(keyarg, len)
- const void *keyarg;
- size_t len;
+u_int32_t
+hash1(const void *key, size_t len)
{
- const u_char *key;
u_int32_t h;
+ u_int8_t *k;
+ h = 0;
+ k = (u_int8_t *)key;
/* Convert string to integer */
- for (key = keyarg, h = 0; len--;)
- h = h * PRIME1 ^ (*key++ - ' ');
+ while (len--)
+ h = h * PRIME1 ^ (*k++ - ' ');
h %= PRIME2;
return (h);
}
/*
- * Phong's linear congruential hash
+ * Phong Vo's linear congruential hash
*/
#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
-static u_int32_t
-hash2(keyarg, len)
- const void *keyarg;
- size_t len;
+u_int32_t
+hash2(const void *key, size_t len)
{
- const u_char *e, *key;
u_int32_t h;
- u_char c;
+ u_int8_t *e, c, *k;
- key = keyarg;
- e = key + len;
- for (h = 0; key != e;) {
- c = *key++;
- if (!c && key > e)
+ k = (u_int8_t *)key;
+ e = k + len;
+ for (h = 0; k != e;) {
+ c = *k++;
+ if (!c && k > e)
break;
dcharhash(h, c);
}
@@ -110,101 +107,84 @@ hash2(keyarg, len)
* all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If
* this routine is heavily used enough, it's worth the ugly coding.
*
- * OZ's original sdbm hash
+ * Ozan Yigit's original sdbm hash.
*/
-static u_int32_t
-hash3(keyarg, len)
- const void *keyarg;
- size_t len;
+u_int32_t
+hash3(const void *key, size_t len)
{
- const u_char *key;
- size_t loop;
- u_int32_t h;
+ u_int32_t n, loop;
+ u_int8_t *k;
-#define HASHC h = *key++ + 65599 * h
+#define HASHC n = *k++ + 65599 * n
- h = 0;
- key = keyarg;
+ n = 0;
+ k = (u_int8_t *)key;
if (len > 0) {
loop = (len + 8 - 1) >> 3;
switch (len & (8 - 1)) {
case 0:
- do {
+ do { /* All fall throughs */
HASHC;
- /* FALLTHROUGH */
case 7:
HASHC;
- /* FALLTHROUGH */
case 6:
HASHC;
- /* FALLTHROUGH */
case 5:
HASHC;
- /* FALLTHROUGH */
case 4:
HASHC;
- /* FALLTHROUGH */
case 3:
HASHC;
- /* FALLTHROUGH */
case 2:
HASHC;
- /* FALLTHROUGH */
case 1:
HASHC;
} while (--loop);
}
+
}
- return (h);
+ return (n);
}
+#endif /* notdef */
-/* Hash function from Chris Torek. */
-static u_int32_t
-hash4(keyarg, len)
- const void *keyarg;
- size_t len;
+/* Chris Torek's hash function. */
+u_int32_t
+hash4(const void *key, size_t len)
{
- const u_char *key;
- size_t loop;
- u_int32_t h;
+ u_int32_t h, loop;
+ const u_int8_t *k;
-#define HASH4a h = (h << 5) - h + *key++;
-#define HASH4b h = (h << 5) + h + *key++;
+#define HASH4a h = (h << 5) - h + *k++;
+#define HASH4b h = (h << 5) + h + *k++;
#define HASH4 HASH4b
h = 0;
- key = keyarg;
+ k = key;
if (len > 0) {
loop = (len + 8 - 1) >> 3;
switch (len & (8 - 1)) {
case 0:
- do {
+ do { /* All fall throughs */
HASH4;
- /* FALLTHROUGH */
case 7:
HASH4;
- /* FALLTHROUGH */
case 6:
HASH4;
- /* FALLTHROUGH */
case 5:
HASH4;
- /* FALLTHROUGH */
case 4:
HASH4;
- /* FALLTHROUGH */
case 3:
HASH4;
- /* FALLTHROUGH */
case 2:
HASH4;
- /* FALLTHROUGH */
case 1:
HASH4;
} while (--loop);
}
+
}
return (h);
}
diff --git a/lib/libc/db/hash/hash_log2.c b/lib/libc/db/hash/hash_log2.c
index 33e0515..0586aa7 100644
--- a/lib/libc/db/hash/hash_log2.c
+++ b/lib/libc/db/hash/hash_log2.c
@@ -36,9 +36,10 @@ static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94";
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
-
#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
u_int32_t
__log2(u_int32_t num)
diff --git a/lib/libc/db/hash/hash_page.c b/lib/libc/db/hash/hash_page.c
index 0c01468..fa01775 100644
--- a/lib/libc/db/hash/hash_page.c
+++ b/lib/libc/db/hash/hash_page.c
@@ -53,7 +53,7 @@ __FBSDID("$FreeBSD$");
*/
#include "namespace.h"
-#include <sys/types.h>
+#include <sys/param.h>
#include <errno.h>
#include <fcntl.h>
@@ -124,9 +124,8 @@ putpair(char *p, const DBT *key, const DBT *val)
int
__delpair(HTAB *hashp, BUFHEAD *bufp, int ndx)
{
- u_int16_t *bp, newoff;
+ u_int16_t *bp, newoff, pairlen;
int n;
- u_int16_t pairlen;
bp = (u_int16_t *)bufp->page;
n = bp[0];
@@ -156,6 +155,14 @@ __delpair(HTAB *hashp, BUFHEAD *bufp, int ndx)
bp[i - 1] = bp[i + 1] + pairlen;
}
}
+ if (ndx == hashp->cndx) {
+ /*
+ * We just removed pair we were "pointing" to.
+ * By moving back the cndx we ensure subsequent
+ * hash_seq() calls won't skip over any entries.
+ */
+ hashp->cndx -= 2;
+ }
}
/* Finally adjust the page data */
bp[n] = OFFSET(bp) + pairlen;
@@ -405,17 +412,22 @@ __addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
if (!bufp)
return (-1);
bp = (u_int16_t *)bufp->page;
- } else
+ } else if (bp[bp[0]] != OVFLPAGE) {
+ /* Short key/data pairs, no more pages */
+ break;
+ } else {
/* Try to squeeze key on this page */
- if (FREESPACE(bp) > PAIRSIZE(key, val)) {
+ if (bp[2] >= REAL_KEY &&
+ FREESPACE(bp) >= PAIRSIZE(key, val)) {
squeeze_key(bp, key, val);
- return (0);
+ goto stats;
} else {
bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
if (!bufp)
return (-1);
bp = (u_int16_t *)bufp->page;
}
+ }
if (PAIRFITS(bp, key, val))
putpair(bufp->page, key, val);
@@ -432,6 +444,7 @@ __addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
if (__big_insert(hashp, bufp, key, val))
return (-1);
}
+stats:
bufp->flags |= BUF_MOD;
/*
* If the average number of keys per bucket exceeds the fill factor,
@@ -453,8 +466,7 @@ __addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
BUFHEAD *
__add_ovflpage(HTAB *hashp, BUFHEAD *bufp)
{
- u_int16_t *sp;
- u_int16_t ndx, ovfl_num;
+ u_int16_t *sp, ndx, ovfl_num;
#ifdef DEBUG1
int tmp1, tmp2;
#endif
@@ -505,8 +517,7 @@ int
__get_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_disk,
int is_bitmap)
{
- int fd, page, size;
- int rsize;
+ int fd, page, size, rsize;
u_int16_t *bp;
fd = hashp->fp;
@@ -520,8 +531,7 @@ __get_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_disk,
page = BUCKET_TO_PAGE(bucket);
else
page = OADDR_TO_PAGE(bucket);
- if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
- ((rsize = _read(fd, p, size)) == -1))
+ if ((rsize = pread(fd, p, size, (off_t)page << hashp->BSHIFT)) == -1)
return (-1);
bp = (u_int16_t *)p;
if (!rsize)
@@ -561,8 +571,7 @@ __get_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_disk,
int
__put_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_bitmap)
{
- int fd, page, size;
- int wsize;
+ int fd, page, size, wsize;
size = hashp->BSIZE;
if ((hashp->fp == -1) && open_temp(hashp))
@@ -570,8 +579,7 @@ __put_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_bitmap)
fd = hashp->fp;
if (hashp->LORDER != BYTE_ORDER) {
- int i;
- int max;
+ int i, max;
if (is_bitmap) {
max = hashp->BSIZE >> 2; /* divide by 4 */
@@ -587,8 +595,7 @@ __put_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_bitmap)
page = BUCKET_TO_PAGE(bucket);
else
page = OADDR_TO_PAGE(bucket);
- if ((lseek(fd, (off_t)page << hashp->BSHIFT, SEEK_SET) == -1) ||
- ((wsize = _write(fd, p, size)) == -1))
+ if ((wsize = pwrite(fd, p, size, (off_t)page << hashp->BSHIFT)) == -1)
/* Errno is set */
return (-1);
if (wsize != size) {
@@ -689,6 +696,7 @@ overflow_page(HTAB *hashp)
if (offset > SPLITMASK) {
if (++splitnum >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
hashp->OVFL_POINT = splitnum;
@@ -702,6 +710,7 @@ overflow_page(HTAB *hashp)
free_page++;
if (free_page >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
/*
@@ -727,6 +736,7 @@ overflow_page(HTAB *hashp)
if (++splitnum >= NCACHED) {
(void)_write(STDERR_FILENO, OVMSG,
sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0);
}
hashp->OVFL_POINT = splitnum;
@@ -770,8 +780,11 @@ found:
/* Calculate the split number for this page */
for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
offset = (i ? bit - hashp->SPARES[i - 1] : bit);
- if (offset >= SPLITMASK)
+ if (offset >= SPLITMASK) {
+ (void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
return (0); /* Out of overflow pages */
+ }
addr = OADDR_OF(i, offset);
#ifdef DEBUG2
(void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
@@ -833,13 +846,24 @@ static int
open_temp(HTAB *hashp)
{
sigset_t set, oset;
- static char namestr[] = "_hashXXXXXX";
+ int len;
+ char *envtmp = NULL;
+ char path[MAXPATHLEN];
+
+ if (issetugid() == 0)
+ envtmp = getenv("TMPDIR");
+ len = snprintf(path,
+ sizeof(path), "%s/_hash.XXXXXX", envtmp ? envtmp : "/tmp");
+ if (len < 0 || len >= (int)sizeof(path)) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
/* Block signals; make sure file goes away at process exit. */
(void)sigfillset(&set);
(void)_sigprocmask(SIG_BLOCK, &set, &oset);
- if ((hashp->fp = mkstemp(namestr)) != -1) {
- (void)unlink(namestr);
+ if ((hashp->fp = mkstemp(path)) != -1) {
+ (void)unlink(path);
(void)_fcntl(hashp->fp, F_SETFD, 1);
}
(void)_sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
diff --git a/lib/libc/db/man/mpool.3 b/lib/libc/db/man/mpool.3
index e9918a9..3de51c3 100644
--- a/lib/libc/db/man/mpool.3
+++ b/lib/libc/db/man/mpool.3
@@ -28,7 +28,7 @@
.\" @(#)mpool.3 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd June 4, 1993
+.Dd February 25, 1999
.Dt MPOOL 3
.Os
.Sh NAME
@@ -47,7 +47,9 @@
.Fa "void *pgcookie"
.Fc
.Ft void *
-.Fn mpool_new "MPOOL *mp" "pgno_t *pgnoaddr"
+.Fn mpool_new "MPOOL *mp" "pgno_t *pgnoaddr" "u_int flags"
+.Ft int
+.Fn mpool_delete "MPOOL *mp" "void *page"
.Ft void *
.Fn mpool_get "MPOOL *mp" "pgno_t pgno" "u_int flags"
.Ft int
@@ -99,11 +101,11 @@ Both functions are called with the
.Fa pgcookie
pointer, the page number and a pointer to the page to being read or written.
.Pp
-The
+The function
.Fn mpool_new
-function takes an
-.Ft MPOOL
-pointer and an address as arguments.
+takes an
+.Dv MPOOL
+pointer, an address, and a set of flags as arguments.
If a new page can be allocated, a pointer to the page is returned and
the page number is stored into the
.Fa pgnoaddr
@@ -113,6 +115,24 @@ Otherwise,
is returned and
.Va errno
is set.
+The flags value is formed by
+.Tn OR Ns 'ing
+the following values:
+.Bl -tag -width Ds
+.It Dv MPOOL_PAGE_REQUEST
+Allocate a new page with a specific page number.
+.It Dv MPOOL_PAGE_NEXT
+Allocate a new page with the next page number.
+.El
+.Pp
+The function
+.Fn mpool_delete
+deletes the specified page from a pool and frees the page.
+It takes an
+.Dv MPOOL
+pointer and a page as arguments.
+The page must have been generated by
+.Fn mpool_new .
.Pp
The
.Fn mpool_get
diff --git a/lib/libc/db/mpool/Makefile.inc b/lib/libc/db/mpool/Makefile.inc
index 9fef712..832e54d 100644
--- a/lib/libc/db/mpool/Makefile.inc
+++ b/lib/libc/db/mpool/Makefile.inc
@@ -3,4 +3,4 @@
.PATH: ${.CURDIR}/db/mpool
-SRCS+= mpool.c
+SRCS+= mpool.c mpool-compat.c
diff --git a/sys/dev/usb/usb_sw_transfer.h b/lib/libc/db/mpool/mpool-compat.c
index d2da0eb..9df76ff 100644
--- a/sys/dev/usb/usb_sw_transfer.h
+++ b/lib/libc/db/mpool/mpool-compat.c
@@ -1,6 +1,6 @@
-/* $FreeBSD$ */
/*-
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
+ * Copyright (c) 2009 Xin LI <delphij@FreeBSD.org>
+ * All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -22,41 +22,22 @@
* 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.
+ *
*/
-#ifndef _USB2_SW_TRANSFER_H_
-#define _USB2_SW_TRANSFER_H_
-
-/* Software transfer function state argument values */
-
-enum {
- USB_SW_TR_SETUP,
- USB_SW_TR_STATUS,
- USB_SW_TR_PRE_DATA,
- USB_SW_TR_POST_DATA,
- USB_SW_TR_PRE_CALLBACK,
-};
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
-struct usb2_sw_transfer;
+#include <db.h>
+#include <mpool.h>
-typedef void (usb2_sw_transfer_func_t)(struct usb2_xfer *, struct usb2_sw_transfer *);
-
-/*
- * The following structure is used to keep the state of a standard
- * root transfer.
- */
-struct usb2_sw_transfer {
- struct usb2_device_request req;
- struct usb2_xfer *xfer;
- uint8_t *ptr;
- uint16_t len;
- uint8_t state;
- usb2_error_t err;
-};
+void *__mpool_new__44bsd(MPOOL *, pgno_t *);
-/* prototypes */
+void *
+__mpool_new__44bsd(MPOOL *mp, pgno_t *pgnoaddr)
+{
-void usb2_sw_transfer(struct usb2_sw_transfer *std,
- usb2_sw_transfer_func_t *func);
+ return (mpool_new(mp, pgnoaddr, MPOOL_PAGE_NEXT));
+}
-#endif /* _USB2_SW_TRANSFER_H_ */
+__sym_compat(mpool_new, __mpool_new_44bsd, FBSD_1.0);
diff --git a/lib/libc/db/mpool/mpool.c b/lib/libc/db/mpool/mpool.c
index caaf47e..18bf8da 100644
--- a/lib/libc/db/mpool/mpool.c
+++ b/lib/libc/db/mpool/mpool.c
@@ -110,9 +110,7 @@ mpool_filter(MPOOL *mp, void (*pgin) (void *, pgno_t, void *),
* Get a new page of memory.
*/
void *
-mpool_new(mp, pgnoaddr)
- MPOOL *mp;
- pgno_t *pgnoaddr;
+mpool_new(MPOOL *mp, pgno_t *pgnoaddr, u_int flags)
{
struct _hqh *head;
BKT *bp;
@@ -131,8 +129,13 @@ mpool_new(mp, pgnoaddr)
*/
if ((bp = mpool_bkt(mp)) == NULL)
return (NULL);
- *pgnoaddr = bp->pgno = mp->npages++;
- bp->flags = MPOOL_PINNED;
+ if (flags == MPOOL_PAGE_REQUEST) {
+ mp->npages++;
+ bp->pgno = *pgnoaddr;
+ } else
+ bp->pgno = *pgnoaddr = mp->npages++;
+
+ bp->flags = MPOOL_PINNED | MPOOL_INUSE;
head = &mp->hqh[HASHKEY(bp->pgno)];
TAILQ_INSERT_HEAD(head, bp, hq);
@@ -140,6 +143,32 @@ mpool_new(mp, pgnoaddr)
return (bp->page);
}
+int
+mpool_delete(MPOOL *mp, void *page)
+{
+ struct _hqh *head;
+ BKT *bp;
+
+ bp = (BKT *)((char *)page - sizeof(BKT));
+
+#ifdef DEBUG
+ if (!(bp->flags & MPOOL_PINNED)) {
+ (void)fprintf(stderr,
+ "mpool_delete: page %d not pinned\n", bp->pgno);
+ abort();
+ }
+#endif
+
+ /* Remove from the hash and lru queues. */
+ head = &mp->hqh[HASHKEY(bp->pgno)];
+ TAILQ_REMOVE(head, bp, hq);
+ TAILQ_REMOVE(&mp->lqh, bp, q);
+
+ free(bp);
+ mp->curcache--;
+ return (RET_SUCCESS);
+}
+
/*
* mpool_get
* Get a page.
@@ -154,12 +183,6 @@ mpool_get(MPOOL *mp, pgno_t pgno,
off_t off;
int nr;
- /* Check for attempt to retrieve a non-existent page. */
- if (pgno >= mp->npages) {
- errno = EINVAL;
- return (NULL);
- }
-
#ifdef STATISTICS
++mp->pageget;
#endif
@@ -167,7 +190,7 @@ mpool_get(MPOOL *mp, pgno_t pgno,
/* Check for a page that is cached. */
if ((bp = mpool_look(mp, pgno)) != NULL) {
#ifdef DEBUG
- if (bp->flags & MPOOL_PINNED) {
+ if (!(flags & MPOOL_IGNOREPIN) && bp->flags & MPOOL_PINNED) {
(void)fprintf(stderr,
"mpool_get: page %d already pinned\n", bp->pgno);
abort();
@@ -193,20 +216,38 @@ mpool_get(MPOOL *mp, pgno_t pgno,
return (NULL);
/* Read in the contents. */
+ off = mp->pagesize * pgno;
+ if ((nr = pread(mp->fd, bp->page, mp->pagesize, off)) != (ssize_t)mp->pagesize) {
+ switch (nr) {
+ case -1:
+ /* errno is set for us by pread(). */
+ free(bp);
+ mp->curcache--;
+ return (NULL);
+ case 0:
+ /*
+ * A zero-length read means you need to create a
+ * new page.
+ */
+ memset(bp->page, 0, mp->pagesize);
+ break;
+ default:
+ /* A partial read is definitely bad. */
+ free(bp);
+ mp->curcache--;
+ errno = EINVAL;
+ return (NULL);
+ }
+ }
#ifdef STATISTICS
++mp->pageread;
#endif
- off = mp->pagesize * pgno;
- nr = pread(mp->fd, bp->page, mp->pagesize, off);
- if (nr != mp->pagesize) {
- if (nr >= 0)
- errno = EFTYPE;
- return (NULL);
- }
/* Set the page number, pin the page. */
bp->pgno = pgno;
- bp->flags = MPOOL_PINNED;
+ if (!(flags & MPOOL_IGNOREPIN))
+ bp->flags = MPOOL_PINNED;
+ bp->flags |= MPOOL_INUSE;
/*
* Add the page to the head of the hash chain and the tail
@@ -245,7 +286,8 @@ mpool_put(MPOOL *mp, void *page, u_int flags)
}
#endif
bp->flags &= ~MPOOL_PINNED;
- bp->flags |= flags & MPOOL_DIRTY;
+ if (flags & MPOOL_DIRTY)
+ bp->flags |= flags & MPOOL_DIRTY;
return (RET_SUCCESS);
}
@@ -329,18 +371,17 @@ mpool_bkt(MPOOL *mp)
bp->page = spage;
}
#endif
+ bp->flags = 0;
return (bp);
}
-new: if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL)
+new: if ((bp = (BKT *)calloc(1, sizeof(BKT) + mp->pagesize)) == NULL)
return (NULL);
#ifdef STATISTICS
++mp->pagealloc;
#endif
-#if defined(DEBUG) || defined(PURIFY)
- memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
-#endif
bp->page = (char *)bp + sizeof(BKT);
+ bp->flags = 0;
++mp->curcache;
return (bp);
}
@@ -363,9 +404,18 @@ mpool_write(MPOOL *mp, BKT *bp)
(mp->pgout)(mp->pgcookie, bp->pgno, bp->page);
off = mp->pagesize * bp->pgno;
- if (pwrite(mp->fd, bp->page, mp->pagesize, off) != mp->pagesize)
+ if (pwrite(mp->fd, bp->page, mp->pagesize, off) != (ssize_t)mp->pagesize)
return (RET_ERROR);
+ /*
+ * Re-run through the input filter since this page may soon be
+ * accessed via the cache, and whatever the user's output filter
+ * did may screw things up if we don't let the input filter
+ * restore the in-core copy.
+ */
+ if (mp->pgin)
+ (mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
+
bp->flags &= ~MPOOL_DIRTY;
return (RET_SUCCESS);
}
@@ -382,7 +432,8 @@ mpool_look(MPOOL *mp, pgno_t pgno)
head = &mp->hqh[HASHKEY(pgno)];
TAILQ_FOREACH(bp, head, hq)
- if (bp->pgno == pgno) {
+ if ((bp->pgno == pgno) &&
+ ((bp->flags & MPOOL_INUSE) == MPOOL_INUSE)) {
#ifdef STATISTICS
++mp->cachehit;
#endif
@@ -406,9 +457,9 @@ mpool_stat(MPOOL *mp)
int cnt;
char *sep;
- (void)fprintf(stderr, "%u pages in the file\n", mp->npages);
+ (void)fprintf(stderr, "%lu pages in the file\n", mp->npages);
(void)fprintf(stderr,
- "page size %lu, cacheing %u pages of %u page max cache\n",
+ "page size %lu, cacheing %lu pages of %lu page max cache\n",
mp->pagesize, mp->curcache, mp->maxcache);
(void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n",
mp->pageput, mp->pageget, mp->pagenew);
diff --git a/lib/libc/db/recno/rec_close.c b/lib/libc/db/recno/rec_close.c
index 8520c85..2d1ff84 100644
--- a/lib/libc/db/recno/rec_close.c
+++ b/lib/libc/db/recno/rec_close.c
@@ -150,7 +150,7 @@ __rec_sync(const DB *dbp, u_int flags)
status = (dbp->seq)(dbp, &key, &data, R_FIRST);
while (status == RET_SUCCESS) {
if (_write(t->bt_rfd, data.data, data.size) !=
- data.size)
+ (ssize_t)data.size)
return (RET_ERROR);
status = (dbp->seq)(dbp, &key, &data, R_NEXT);
}
@@ -162,7 +162,7 @@ __rec_sync(const DB *dbp, u_int flags)
while (status == RET_SUCCESS) {
iov[0].iov_base = data.data;
iov[0].iov_len = data.size;
- if (_writev(t->bt_rfd, iov, 2) != data.size + 1)
+ if (_writev(t->bt_rfd, iov, 2) != (ssize_t)(data.size + 1))
return (RET_ERROR);
status = (dbp->seq)(dbp, &key, &data, R_NEXT);
}
diff --git a/lib/libc/db/recno/rec_put.c b/lib/libc/db/recno/rec_put.c
index a6defc9..441cced 100644
--- a/lib/libc/db/recno/rec_put.c
+++ b/lib/libc/db/recno/rec_put.c
@@ -251,7 +251,7 @@ __rec_iput(BTREE *t, recno_t nrec, const DBT *data, u_int flags)
* the offset array, shift the pointers up.
*/
nbytes = NRLEAFDBT(data->size);
- if (h->upper - h->lower < nbytes + sizeof(indx_t)) {
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t)) {
status = __bt_split(t, h, NULL, data, dflags, nbytes, idx);
if (status == RET_SUCCESS)
++t->bt_nrecs;
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index a7997ab..0ee2ffb 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -9,7 +9,7 @@ SRCS+= __getosreldate.c __xuname.c \
alarm.c arc4random.c assert.c basename.c check_utility_compat.c \
clock.c closedir.c confstr.c \
crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \
- dlfcn.c dlfunc.c drand48.c erand48.c err.c errlst.c errno.c \
+ dlfcn.c drand48.c erand48.c err.c errlst.c errno.c \
exec.c fdevname.c feature_present.c fmtcheck.c fmtmsg.c fnmatch.c \
fpclassify.c frexp.c fstab.c ftok.c fts.c fts-compat.c ftw.c \
getbootfile.c getbsize.c \
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index afdecb5..fdc0449 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -223,8 +223,6 @@ FBSD_1.0 {
posix_madvise;
popen;
pclose;
- shm_open;
- shm_unlink;
pselect;
psignal;
raise;
diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c
index eac3f1a..4be8847 100644
--- a/lib/libc/gen/dlfcn.c
+++ b/lib/libc/gen/dlfcn.c
@@ -105,6 +105,14 @@ dlsym(void * __restrict handle, const char * __restrict name)
return NULL;
}
+#pragma weak dlfunc
+dlfunc_t
+dlfunc(void * __restrict handle, const char * __restrict name)
+{
+ _rtld_error(sorry);
+ return NULL;
+}
+
#pragma weak dlvsym
void *
dlvsym(void * __restrict handle, const char * __restrict name,
diff --git a/lib/libc/gen/dlfunc.c b/lib/libc/gen/dlfunc.c
deleted file mode 100644
index 72a683a..0000000
--- a/lib/libc/gen/dlfunc.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * This source file is in the public domain.
- * Garrett A. Wollman, 2002-05-28.
- *
- * $FreeBSD$
- */
-
-#include <dlfcn.h>
-
-/*
- * Implement the dlfunc() interface, which behaves exactly the same as
- * dlsym() except that it returns a function pointer instead of a data
- * pointer. This can be used by applications to avoid compiler warnings
- * about undefined behavior, and is intended as prior art for future
- * POSIX standardization. This function requires that all pointer types
- * have the same representation, which is true on all platforms FreeBSD
- * runs on, but is not guaranteed by the C standard.
- */
-dlfunc_t
-dlfunc(void * __restrict handle, const char * __restrict symbol)
-{
- union {
- void *d;
- dlfunc_t f;
- } rv;
-
- rv.d = dlsym(handle, symbol);
- return (rv.f);
-}
-
diff --git a/lib/libc/gen/dlopen.3 b/lib/libc/gen/dlopen.3
index 118e165..187f817 100644
--- a/lib/libc/gen/dlopen.3
+++ b/lib/libc/gen/dlopen.3
@@ -32,7 +32,7 @@
.\" @(#) dlopen.3 1.6 90/01/31 SMI
.\" $FreeBSD$
.\"
-.Dd September 10, 2002
+.Dd April 1, 2009
.Os
.Dt DLOPEN 3
.Sh NAME
@@ -123,7 +123,7 @@ call to
One of the following flags may be ORed into the
.Fa mode
argument:
-.Bl -tag -width RTLD_GLOBALX
+.Bl -tag -width RTLD_NODELETE
.It Dv RTLD_GLOBAL
Symbols from this shared object and its directed acyclic graph (DAG)
of needed objects will be available for resolving undefined references
@@ -141,6 +141,13 @@ the absolute pathnames of all objects, to standard output.
With this flag
.Fn dlopen
will return to the caller only in the case of error.
+.It Dv RTLD_NODELETE
+Prevents unload of the loaded object on
+.Fn dlclose .
+The same behaviour may be requested by
+.Fl "z nodelete"
+option of the static linker
+.Xr ld 1 .
.El
.Pp
If
diff --git a/lib/libc/gen/getcap.c b/lib/libc/gen/getcap.c
index 0f0bb20..d0e4a7b 100644
--- a/lib/libc/gen/getcap.c
+++ b/lib/libc/gen/getcap.c
@@ -189,7 +189,7 @@ getent(char **cap, u_int *len, char **db_array, int fd, const char *name,
{
DB *capdbp;
char *r_end, *rp, **db_p;
- int myfd, eof, foundit, retval, clen;
+ int myfd, eof, foundit, retval;
char *record, *cbuf;
int tc_not_resolved;
char pbuf[_POSIX_PATH_MAX];
@@ -251,14 +251,16 @@ getent(char **cap, u_int *len, char **db_array, int fd, const char *name,
return (retval);
}
/* save the data; close frees it */
- clen = strlen(record);
- cbuf = malloc(clen + 1);
- memcpy(cbuf, record, clen + 1);
+ cbuf = strdup(record);
if (capdbp->close(capdbp) < 0) {
free(cbuf);
return (-2);
}
- *len = clen;
+ if (cbuf == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+ *len = strlen(record);
*cap = cbuf;
return (retval);
} else {
diff --git a/lib/libc/i386/sys/Makefile.inc b/lib/libc/i386/sys/Makefile.inc
index 593956b..98a9c9e 100644
--- a/lib/libc/i386/sys/Makefile.inc
+++ b/lib/libc/i386/sys/Makefile.inc
@@ -2,11 +2,10 @@
# $FreeBSD$
.if !defined(COMPAT_32BIT)
-SRCS+= i386_clr_watch.c i386_get_ioperm.c \
- i386_set_ioperm.c i386_set_watch.c i386_vm86.c
+SRCS+= i386_clr_watch.c i386_set_watch.c i386_vm86.c
.endif
-SRCS+= i386_get_fsbase.c i386_get_gsbase.c i386_get_ldt.c \
- i386_set_fsbase.c i386_set_gsbase.c i386_set_ldt.c
+SRCS+= i386_get_fsbase.c i386_get_gsbase.c i386_get_ioperm.c i386_get_ldt.c \
+ i386_set_fsbase.c i386_set_gsbase.c i386_set_ioperm.c i386_set_ldt.c
MDASM= Ovfork.S brk.S cerror.S exect.S getcontext.S pipe.S ptrace.S \
reboot.S sbrk.S setlogin.S sigreturn.S syscall.S
diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c
index 941c315..830e464 100644
--- a/lib/libc/net/getaddrinfo.c
+++ b/lib/libc/net/getaddrinfo.c
@@ -102,7 +102,6 @@ __FBSDID("$FreeBSD$");
# define FAITH
#endif
-#define SUCCESS 0
#define ANY 0
#define YES 1
#define NO 0
@@ -165,19 +164,20 @@ struct explore {
static const struct explore explore[] = {
#if 0
- { PF_LOCAL, 0, ANY, ANY, NULL, 0x01 },
+ { PF_LOCAL, ANY, ANY, NULL, 0x01 },
#endif
#ifdef INET6
{ PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
{ PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+ { PF_INET6, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x03 },
+ { PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, "sctp", 0x07 },
{ PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
#endif
{ PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
{ PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+ { PF_INET, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x03 },
+ { PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, "sctp", 0x07 },
{ PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
- { PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
- { PF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
- { PF_UNSPEC, SOCK_RAW, ANY, NULL, 0x05 },
{ -1, 0, 0, NULL, 0 },
};
@@ -227,6 +227,8 @@ typedef union {
} querybuf;
static int str2number(const char *, int *);
+static int explore_copy(const struct addrinfo *, const struct addrinfo *,
+ struct addrinfo **);
static int explore_null(const struct addrinfo *,
const char *, struct addrinfo **);
static int explore_numeric(const struct addrinfo *, const char *,
@@ -237,6 +239,7 @@ static int get_canonname(const struct addrinfo *,
struct addrinfo *, const char *);
static struct addrinfo *get_ai(const struct addrinfo *,
const struct afd *, const char *);
+static struct addrinfo *copy_ai(const struct addrinfo *);
static int get_portmatch(const struct addrinfo *, const char *);
static int get_port(struct addrinfo *, const char *, int);
static const struct afd *find_afd(int);
@@ -365,12 +368,23 @@ getaddrinfo(const char *hostname, const char *servname,
struct addrinfo sentinel;
struct addrinfo *cur;
int error = 0;
- struct addrinfo ai;
- struct addrinfo ai0;
+ struct addrinfo ai, ai0, *afai;
struct addrinfo *pai;
+ const struct afd *afd;
const struct explore *ex;
+ struct addrinfo *afailist[sizeof(afdl)/sizeof(afdl[0])];
+ struct addrinfo *afai_unspec;
+ int found;
int numeric = 0;
+ /* ensure we return NULL on errors */
+ *res = NULL;
+
+ memset(&ai, 0, sizeof(ai));
+
+ memset(afailist, 0, sizeof(afailist));
+ afai_unspec = NULL;
+
memset(&sentinel, 0, sizeof(sentinel));
cur = &sentinel;
pai = &ai;
@@ -410,17 +424,22 @@ getaddrinfo(const char *hostname, const char *servname,
*/
if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
for (ex = explore; ex->e_af >= 0; ex++) {
- if (pai->ai_family != ex->e_af)
+ if (!MATCH_FAMILY(pai->ai_family, ex->e_af,
+ WILD_AF(ex)))
continue;
- if (ex->e_socktype == ANY)
+ if (!MATCH(pai->ai_socktype, ex->e_socktype,
+ WILD_SOCKTYPE(ex)))
continue;
- if (ex->e_protocol == ANY)
+ if (!MATCH(pai->ai_protocol, ex->e_protocol,
+ WILD_PROTOCOL(ex)))
continue;
- if (pai->ai_socktype == ex->e_socktype &&
- pai->ai_protocol != ex->e_protocol) {
- ERR(EAI_BADHINTS);
- }
+
+ /* matched */
+ break;
}
+
+ if (ex->e_af < 0)
+ ERR(EAI_BADHINTS);
}
}
@@ -452,49 +471,48 @@ getaddrinfo(const char *hostname, const char *servname,
ai0 = *pai;
- /* NULL hostname, or numeric hostname */
- for (ex = explore; ex->e_af >= 0; ex++) {
+ /*
+ * NULL hostname, or numeric hostname.
+ * If numeric representation of AF1 can be interpreted as FQDN
+ * representation of AF2, we need to think again about the code below.
+ */
+ found = 0;
+ for (afd = afdl; afd->a_af; afd++) {
*pai = ai0;
- /* PF_UNSPEC entries are prepared for DNS queries only */
- if (ex->e_af == PF_UNSPEC)
- continue;
-
- if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
- continue;
- if (!MATCH(pai->ai_socktype, ex->e_socktype, WILD_SOCKTYPE(ex)))
- continue;
- if (!MATCH(pai->ai_protocol, ex->e_protocol, WILD_PROTOCOL(ex)))
+ if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
continue;
if (pai->ai_family == PF_UNSPEC)
- pai->ai_family = ex->e_af;
- if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
- pai->ai_socktype = ex->e_socktype;
- if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
- pai->ai_protocol = ex->e_protocol;
+ pai->ai_family = afd->a_af;
- if (hostname == NULL)
- error = explore_null(pai, servname, &cur->ai_next);
- else
+ if (hostname == NULL) {
+ error = explore_null(pai, servname,
+ &afailist[afd - afdl]);
+
+ /*
+ * Errors from explore_null should be unexpected and
+ * be caught to avoid returning an incomplete result.
+ */
+ if (error != 0)
+ goto bad;
+ } else {
error = explore_numeric_scope(pai, hostname, servname,
- &cur->ai_next);
+ &afailist[afd - afdl]);
- if (error)
- goto free;
+ /*
+ * explore_numeric_scope returns an error for address
+ * families that do not match that of hostname.
+ * Thus we should not catch the error at this moment.
+ */
+ }
- while (cur && cur->ai_next)
- cur = cur->ai_next;
+ if (!error && afailist[afd - afdl])
+ found++;
}
-
- /*
- * XXX
- * If numreic representation of AF1 can be interpreted as FQDN
- * representation of AF2, we need to think again about the code below.
- */
- if (sentinel.ai_next) {
+ if (found) {
numeric = 1;
- goto good;
+ goto globcopy;
}
if (hostname == NULL)
@@ -507,42 +525,55 @@ getaddrinfo(const char *hostname, const char *servname,
/*
* hostname as alphabetical name.
- * we would like to prefer AF_INET6 than AF_INET, so we'll make a
- * outer loop by AFs.
*/
+ *pai = ai0;
+ error = explore_fqdn(pai, hostname, servname, &afai_unspec);
+
+globcopy:
for (ex = explore; ex->e_af >= 0; ex++) {
*pai = ai0;
- /* require exact match for family field */
- if (pai->ai_family != ex->e_af)
+ if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
continue;
-
if (!MATCH(pai->ai_socktype, ex->e_socktype,
- WILD_SOCKTYPE(ex))) {
+ WILD_SOCKTYPE(ex)))
continue;
- }
if (!MATCH(pai->ai_protocol, ex->e_protocol,
- WILD_PROTOCOL(ex))) {
+ WILD_PROTOCOL(ex)))
continue;
- }
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = ex->e_af;
if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
pai->ai_socktype = ex->e_socktype;
if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
pai->ai_protocol = ex->e_protocol;
- error = explore_fqdn(pai, hostname, servname,
- &cur->ai_next);
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ continue;
+
+ if (afai_unspec)
+ afai = afai_unspec;
+ else {
+ if ((afd = find_afd(pai->ai_family)) == NULL)
+ continue;
+ /* XXX assumes that afd points inside afdl[] */
+ afai = afailist[afd - afdl];
+ }
+ if (!afai)
+ continue;
+
+ error = explore_copy(pai, afai, &cur->ai_next);
+ if (error != 0)
+ goto bad;
while (cur && cur->ai_next)
cur = cur->ai_next;
}
- /* XXX inhibit errors if we have the result */
- if (sentinel.ai_next)
- error = 0;
-
-good:
/*
* ensure we return either:
* - error == 0, non-NULL *res
@@ -578,16 +609,22 @@ good:
}
}
*res = sentinel.ai_next;
- return SUCCESS;
} else
error = EAI_FAIL;
}
-free:
+
bad:
- if (sentinel.ai_next)
- freeaddrinfo(sentinel.ai_next);
- *res = NULL;
- return error;
+ if (afai_unspec)
+ freeaddrinfo(afai_unspec);
+ for (afd = afdl; afd->a_af; afd++) {
+ if (afailist[afd - afdl])
+ freeaddrinfo(afailist[afd - afdl]);
+ }
+ if (!*res)
+ if (sentinel.ai_next)
+ freeaddrinfo(sentinel.ai_next);
+
+ return (error);
}
static int
@@ -1039,6 +1076,41 @@ gai_addr2scopetype(struct sockaddr *sa)
}
}
+static int
+explore_copy(const struct addrinfo *pai, const struct addrinfo *src0,
+ struct addrinfo **res)
+{
+ int error;
+ struct addrinfo sentinel, *cur;
+ const struct addrinfo *src;
+
+ error = 0;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+
+ for (src = src0; src != NULL; src = src->ai_next) {
+ if (src->ai_family != pai->ai_family)
+ continue;
+
+ cur->ai_next = copy_ai(src);
+ if (!cur->ai_next) {
+ error = EAI_MEMORY;
+ goto fail;
+ }
+
+ cur->ai_next->ai_socktype = pai->ai_socktype;
+ cur->ai_next->ai_protocol = pai->ai_protocol;
+ cur = cur->ai_next;
+ }
+
+ *res = sentinel.ai_next;
+ return 0;
+
+fail:
+ freeaddrinfo(sentinel.ai_next);
+ return error;
+}
+
/*
* hostname == NULL.
* passive socket -> anyaddr (0.0.0.0 or ::)
@@ -1067,12 +1139,6 @@ explore_null(const struct addrinfo *pai, const char *servname,
} else
_close(s);
- /*
- * if the servname does not match socktype/protocol, ignore it.
- */
- if (get_portmatch(pai, servname) != 0)
- return 0;
-
afd = find_afd(pai->ai_family);
if (afd == NULL)
return 0;
@@ -1109,12 +1175,6 @@ explore_numeric(const struct addrinfo *pai, const char *hostname,
*res = NULL;
ai = NULL;
- /*
- * if the servname does not match socktype/protocol, ignore it.
- */
- if (get_portmatch(pai, servname) != 0)
- return 0;
-
afd = find_afd(pai->ai_family);
if (afd == NULL)
return 0;
@@ -1181,12 +1241,6 @@ explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
char *cp, *hostname2 = NULL, *scope, *addr;
struct sockaddr_in6 *sin6;
- /*
- * if the servname does not match socktype/protocol, ignore it.
- */
- if (get_portmatch(pai, servname) != 0)
- return 0;
-
afd = find_afd(pai->ai_family);
if (afd == NULL)
return 0;
@@ -1219,6 +1273,8 @@ explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
free(hostname2);
+ freeaddrinfo(*res);
+ *res = NULL;
return(EAI_NONAME); /* XXX: is return OK? */
}
sin6->sin6_scope_id = scopeid;
@@ -1227,6 +1283,10 @@ explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
free(hostname2);
+ if (error && *res) {
+ freeaddrinfo(*res);
+ *res = NULL;
+ }
return error;
#endif
}
@@ -1310,6 +1370,38 @@ get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
return ai;
}
+/* XXX need to malloc() the same way we do from other functions! */
+static struct addrinfo *
+copy_ai(const struct addrinfo *pai)
+{
+ struct addrinfo *ai;
+ size_t l;
+
+ l = sizeof(*ai) + pai->ai_addrlen;
+ if ((ai = (struct addrinfo *)malloc(l)) == NULL)
+ return NULL;
+ memset(ai, 0, l);
+ memcpy(ai, pai, sizeof(*ai));
+ ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+ memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen);
+
+ if (pai->ai_canonname) {
+ l = strlen(pai->ai_canonname) + 1;
+ if ((ai->ai_canonname = malloc(l)) == NULL) {
+ free(ai);
+ return NULL;
+ }
+ strlcpy(ai->ai_canonname, pai->ai_canonname, l);
+ } else {
+ /* just to make sure */
+ ai->ai_canonname = NULL;
+ }
+
+ ai->ai_next = NULL;
+
+ return ai;
+}
+
static int
get_portmatch(const struct addrinfo *ai, const char *servname)
{
@@ -1344,10 +1436,21 @@ get_port(struct addrinfo *ai, const char *servname, int matchonly)
return EAI_SERVICE;
case SOCK_DGRAM:
case SOCK_STREAM:
+ case SOCK_SEQPACKET:
allownumeric = 1;
break;
case ANY:
- allownumeric = 0;
+ switch (ai->ai_family) {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ allownumeric = 1;
+ break;
+ default:
+ allownumeric = 0;
+ break;
+ }
break;
default:
return EAI_SOCKTYPE;
@@ -1363,13 +1466,17 @@ get_port(struct addrinfo *ai, const char *servname, int matchonly)
} else {
if (ai->ai_flags & AI_NUMERICSERV)
return EAI_NONAME;
- switch (ai->ai_socktype) {
- case SOCK_DGRAM:
+
+ switch (ai->ai_protocol) {
+ case IPPROTO_UDP:
proto = "udp";
break;
- case SOCK_STREAM:
+ case IPPROTO_TCP:
proto = "tcp";
break;
+ case IPPROTO_SCTP:
+ proto = "sctp";
+ break;
default:
proto = NULL;
break;
diff --git a/lib/libc/nls/Makefile.inc b/lib/libc/nls/Makefile.inc
index 90a6741..9e19e85 100644
--- a/lib/libc/nls/Makefile.inc
+++ b/lib/libc/nls/Makefile.inc
@@ -8,3 +8,28 @@ SRCS+= msgcat.c
SYM_MAPS+=${.CURDIR}/nls/Symbol.map
MAN+= catclose.3 catgets.3 catopen.3
+
+# NOTE: C.msg should not be processed here, it's used as a template
+# for translators.
+
+NLSNAME= libc
+NLS+= be_BY.UTF-8
+NLS+= ca_ES.ISO8859-1
+NLS+= de_DE.ISO8859-1
+NLS+= el_GR.ISO8859-7
+NLS+= es_ES.ISO8859-1
+NLS+= fi_FI.ISO8859-1
+NLS+= fr_FR.ISO8859-1
+NLS+= hu_HU.ISO8859-2
+NLS+= it_IT.ISO8859-15
+NLS+= ko_KR.UTF-8
+NLS+= ko_KR.eucKR
+NLS+= mn_MN.UTF-8
+NLS+= nl_NL.ISO8859-1
+NLS+= no_NO.ISO8859-1
+NLS+= pl_PL.ISO8859-2
+NLS+= pt_BR.ISO8859-1
+NLS+= ru_RU.KOI8-R
+NLS+= sk_SK.ISO8859-2
+NLS+= sv_SE.ISO8859-1
+NLS+= uk_UA.UTF-8
diff --git a/lib/libc/nls/be_BY.UTF-8.msg b/lib/libc/nls/be_BY.UTF-8.msg
new file mode 100644
index 0000000..56bd038
--- /dev/null
+++ b/lib/libc/nls/be_BY.UTF-8.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for be_BY.UTF-8 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð½Ðµ дазволена
+$ ENOENT
+2 ÐÑма такога файлу ці каталогу
+$ ESRCH
+3 ÐÑма такога працÑÑу
+$ EINTR
+4 Перарваны ÑÑ–ÑÑ‚Ñмны выклік
+$ EIO
+5 Памылка ўводу/вываду
+$ ENXIO
+6 ПрыÑтаÑаванне не Ñканфігуравана
+$ E2BIG
+7 Ðадта доўгі ÑÐ¿Ñ–Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñž
+$ ENOEXEC
+8 Памылка фармату файлу, Ñкі выконваецца
+$ EBADF
+9 ÐекарÑктны дÑÑкрыптар файлу
+$ ECHILD
+10 ÐÑма дачÑрніх працÑÑаў
+$ EDEADLK
+11 Прадухілена ÑžÐ·Ð°ÐµÐ¼Ð½Ð°Ñ Ð±Ð»Ð°ÐºÑ–Ñ€Ð¾ÑžÐºÐ° Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð´Ð¾Ñтупу да Ñ€ÑÑурÑу
+$ ENOMEM
+12 Ðе даÑтае памÑці
+$ EACCES
+13 Ðе даÑтае прывілеÑÑž
+$ EFAULT
+14 ÐекарÑктны адраÑ
+$ ENOTBLK
+15 Ðеабходна блочнае прыÑтаÑаванне
+$ EBUSY
+16 ПрыÑтаÑаванне занÑтае
+$ EEXIST
+17 Файл Ñ–Ñнуе
+$ EXDEV
+18 СпаÑылка на іншае прыÑтаÑаванне
+$ ENODEV
+19 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð½Ðµ падтрымліваецца прыÑтаÑаваннем
+$ ENOTDIR
+20 Пазначаны файл не з'ÑўлÑецца каталогам
+$ EISDIR
+21 Пазначаны файл з'ÑўлÑецца каталогам
+$ EINVAL
+22 Ðедапушчальны аргумент
+$ ENFILE
+23 Ðадта шмат адчыненых файлаў у ÑÑ–ÑÑ‚Ñме
+$ EMFILE
+24 Ðадта шмат адчыненых файлаў
+$ ENOTTY
+25 Выклік ioctl не падтрымліваецца прыÑтаÑаваннем
+$ ETXTBSY
+26 ТекÑтавы файл занÑÑ‚Ñ‹
+$ EFBIG
+27 Ðадта вÑлікі файл
+$ ENOSPC
+28 Ðа прыÑтаÑаванні не заÑталоÑÑ Ð¼ÐµÑца
+$ ESPIPE
+29 Ðедапушчальнае пазіцыÑнаванне
+$ EROFS
+30 Ð¤Ð°Ð¹Ð»Ð°Ð²Ð°Ñ ÑÑ–ÑÑ‚Ñма толькі Ð´Ð»Ñ Ñ‡Ñ‹Ñ‚Ð°Ð½Ð½Ñ
+$ EMLINK
+31 Ðадта шмат ÑпаÑылак
+$ EPIPE
+32 Канал пашкоджаны
+$ EDOM
+33 Ðедапушчальнае значÑнне лічбавага аргументу
+$ ERANGE
+34 Ðадта вÑлікі Ñ€Ñзультат
+$ EAGAIN, EWOULDBLOCK
+35 РÑÑÑƒÑ€Ñ Ñ‡Ð°Ñова недаÑтупны
+$ EINPROGRESS
+36 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ñž працÑÑе выкананнÑ
+$ EALREADY
+37 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ ÑžÐ¶Ð¾ выконваецца
+$ ENOTSOCK
+38 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð· Ñокетам прыменена не да Ñокету
+$ EDESTADDRREQ
+39 Патрабуецца Ð°Ð´Ñ€Ð°Ñ Ð¿Ñ€Ñ‹Ð·Ð½Ð°Ñ‡ÑннÑ
+$ EMSGSIZE
+40 Ðадта доўгае паведамленне
+$ EPROTOTYPE
+41 ÐÑправільны тып пратаколу Ð´Ð»Ñ Ñокету
+$ ENOPROTOOPT
+42 Пратакол недаÑтупны
+$ EPROTONOSUPPORT
+43 Пратакол не падтрымліваецца
+$ ESOCKTNOSUPPORT
+44 Тып Ñокету не падтрымліваецца
+$ EOPNOTSUPP
+45 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð½Ðµ падтрымліваецца
+$ EPFNOSUPPORT
+46 СÑмейÑтва пратаколаў не падтрымліваецца
+$ EAFNOSUPPORT
+47 СÑмейÑтва адраÑоў не падтрымліваецца ÑÑмейÑтвам пратаколаў
+$ EADDRINUSE
+48 ÐÐ´Ñ€Ð°Ñ ÑžÐ¶Ð¾ выкарыÑтоўваецца
+$ EADDRNOTAVAIL
+49 Ðе магчыма прызначыць дадзены адраÑ
+$ ENETDOWN
+50 Сетка не працуе
+$ ENETUNREACH
+51 Сетка недаÑÑжна
+$ ENETRESET
+52 ЗлучÑнне прыпынена Ñеткай
+$ ECONNABORTED
+53 Праграма выклікала аварыйнае завÑршÑнне злучÑннÑ
+$ ECONNRESET
+54 ЗлучÑнне завÑршана Ñупрацьлеглым бокам
+$ ENOBUFS
+55 Ðе заÑталоÑÑ Ð¼ÐµÑца пад буфер
+$ EISCONN
+56 Сокет ужо падлучаны
+$ ENOTCONN
+57 Сокет не падлучаны
+$ ESHUTDOWN
+58 Ðе магчыма даÑылаць паÑÐ»Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ†Ñ†Ñ Ñокету
+$ ETOOMANYREFS
+59 Ðадта шмат ÑпаÑылак: не магчыма злучыць
+$ ETIMEDOUT
+60 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð¿ÐµÑ€Ð°Ð²Ñ‹Ñіла чаÑавы ліміт
+$ ECONNREFUSED
+61 У злучÑнні адмоўлена
+$ ELOOP
+62 Ðадта шмат узроўнÑÑž Ñімвальных ÑпаÑылак
+$ ENAMETOOLONG
+63 Ðадта доўгае Ñ–Ð¼Ñ Ñ„Ð°Ð¹Ð»Ñƒ
+$ EHOSTDOWN
+64 ХоÑÑ‚ не працуе
+$ EHOSTUNREACH
+65 ÐÑма маршруту да хоÑту
+$ ENOTEMPTY
+66 Каталог не пуÑÑ‚Ñ‹
+$ EPROCLIM
+67 Ðадта шмат працÑÑаў
+$ EUSERS
+68 Ðадта шмат карыÑтальнікаў
+$ EDQUOT
+69 Перавышана дыÑÐºÐ°Ð²Ð°Ñ ÐºÐ²Ð¾Ñ‚Ð°
+$ ESTALE
+70 СаÑтарÑлы дÑÑкрыптар файлу NFS
+$ EREMOTE
+71 Ðадта шмат дыÑтанцыйных пераходаў на шлÑху
+$ EBADRPC
+72 ÐекарÑÐºÑ‚Ð½Ð°Ñ Ñтруктура RPC
+$ ERPCMISMATCH
+73 ÐÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ RPC
+$ EPROGUNAVAIL
+74 Праграма RPC недаÑÑжнаÑ
+$ EPROGMISMATCH
+75 ÐÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ñ‹
+$ EPROCUNAVAIL
+76 ÐекарÑÐºÑ‚Ð½Ð°Ñ Ð¿Ñ€Ð°Ñ†Ñдура Ð´Ð»Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ñ‹
+$ ENOLCK
+77 Блакіроўкі недаÑтупны
+$ ENOSYS
+78 Ð¤ÑƒÐ½ÐºÑ†Ñ‹Ñ Ð½Ðµ Ñ€Ñалізавана
+$ EFTYPE
+79 ÐепадыходзÑчы тып ці фармат файлу
+$ EAUTH
+80 Памылка аўтÑнтыфікацыі
+$ ENEEDAUTH
+81 Ðеабходна аўтÑнтыфікацыÑ
+$ EIDRM
+82 ІдÑнтыфікатар выдалены
+$ ENOMSG
+83 ÐÑма Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ð°Ñ‚Ñ€Ñбнага тыпу
+$ EOVERFLOW
+84 Ðадта вÑлікае значÑнне Ð´Ð»Ñ Ð·Ð°Ñ…Ð¾ÑžÐ²Ð°Ð½Ð½Ñ Ñž пазначаным тыпе дадзеных
+$ ECANCELED
+85 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð°Ð´Ð¼ÐµÐ½ÐµÐ½Ð°
+$ EILSEQ
+86 ÐÐµÐ´Ð°Ð·Ð²Ð¾Ð»ÐµÐ½Ð°Ñ Ð¿Ð°ÑлÑдоўнаÑць байтаў
+$ ENOATTR
+87 Ðтрыбут не знойдзены
+$ EDOOFUS
+88 Памылка праграмаваннÑ
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Разрыў ÑувÑзі
+$ SIGINT
+2 Перарванне па Ñігналу
+$ SIGQUIT
+3 Выхад
+$ SIGILL
+4 ÐÐµÐ´Ð°Ð¿ÑƒÑˆÑ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ–Ð½ÑтрукцыÑ
+$ SIGTRAP
+5 ПаÑтка траÑіроўкі/кропкі ÑпыненнÑ
+$ SIGABRT
+6 ПаÑтка аварыйнага завÑршÑннÑ
+$ SIGEMT
+7 ПаÑтка EMT
+$ SIGFPE
+8 Памылка Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð¿Ñ€Ð°Ñ†Ñ‹ з Ñ€Ñчыўным лікам
+$ SIGKILL
+9 ПрымуÑова Ñпынены
+$ SIGBUS
+10 Памылка шыны
+$ SIGSEGV
+11 Памылка Ñегментацыі
+$ SIGSYS
+12 Ðедапушчальны ÑÑ–ÑÑ‚Ñмны выклік
+$ SIGPIPE
+13 Канал пашкоджаны
+$ SIGALRM
+14 Спрацаваў таймер
+$ SIGTERM
+15 Завершаны
+$ SIGURG
+16 Ðеабходны Ñ‚Ñрміновы ўвод-вывад
+$ SIGSTOP
+17 Прыпыненне (Ñігнал)
+$ SIGTSTP
+18 Прыпыненне
+$ SIGCONT
+19 ПрацÑг працы
+$ SIGCHLD
+20 Завершана праца дачÑрнÑга працÑÑу
+$ SIGTTIN
+21 Спынены (увод з Ñ‚Ñрміналу)
+$ SIGTTOU
+22 Спынены (увод на Ñ‚Ñрмінал)
+$ SIGIO
+23 Увод-вывад магчымы
+$ SIGXCPU
+24 Перавышана абмежаванне працÑÑарнага чаÑу
+$ SIGXFSZ
+25 Перавышаны макÑімальны памер файлу
+$ SIGVTALRM
+26 Вычарпаны віртуальны таймер
+$ SIGPROF
+27 Вычарпаны таймер прафілÑваннÑ
+$ SIGWINCH
+28 Змена памеру вакна
+$ SIGINFO
+29 Запыт інфармацыі
+$ SIGUSR1
+30 Сігнал карыÑтальніка 1
+$ SIGUSR2
+31 Сігнал карыÑтальніка 2
diff --git a/lib/libc/nls/ca_ES.ISO8859-1.msg b/lib/libc/nls/ca_ES.ISO8859-1.msg
new file mode 100644
index 0000000..e786c29
--- /dev/null
+++ b/lib/libc/nls/ca_ES.ISO8859-1.msg
@@ -0,0 +1,267 @@
+$ $FreeBSD$
+$
+$ Message catalog for ca_ES.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operació no permesa
+$ ENOENT
+2 Arxiu o directori inexistent
+$ ESRCH
+3 Procés inexistent
+$ EINTR
+4 Crida del sistema interrompuda
+$ EIO
+5 Error d'entrada/sortida
+$ ENXIO
+6 Dispositiu no configurat
+$ E2BIG
+7 Llista de paràmetres massa llarga
+$ ENOEXEC
+8 Error en el format de l'executable
+$ EBADF
+9 Descriptor d'arxiu incorrecte
+$ ECHILD
+10 No hi ha processos fills
+$ EDEADLK
+11 S'ha evitat el bloqueig del recurs
+$ ENOMEM
+12 No es pot assignar la memòria demanada
+$ EACCES
+13 Permís denegat
+$ EFAULT
+14 Adreça incorrecta
+$ ENOTBLK
+15 Es necessita un dispositiu de blocs
+$ EBUSY
+16 Dispositiu ocupat
+$ EEXIST
+17 L'arxiu ja existeix
+$ EXDEV
+18 Enllaç entre dispositius
+$ ENODEV
+19 Operació no suportada pel dispositiu
+$ ENOTDIR
+20 No és un directori
+$ EISDIR
+21 És un directori
+$ EINVAL
+22 Paràmetre incorrecte
+$ ENFILE
+23 Hi ha massa arxius oberts al sistema
+$ EMFILE
+24 Hi ha massa arxius oberts
+$ ENOTTY
+25 L'ioctl no és adecuat per al dispositiu
+$ ETXTBSY
+26 Arxiu de text ocupat
+$ EFBIG
+27 Arxiu massa gran
+$ ENOSPC
+28 No queda espai lliure en el dispositiu
+$ ESPIPE
+29 Cerca il·legal
+$ EROFS
+30 Sistema d'arxius de només lectura
+$ EMLINK
+31 Massa enllaços
+$ EPIPE
+32 Canal (pipe) trencat
+$ EDOM
+33 El resultat surt fora de rang
+$ ERANGE
+34 Resultat massa gran
+$ EAGAIN, EWOULDBLOCK
+35 El recurs no està disponible temporalment
+$ EINPROGRESS
+36 L'operació es troba en progrés actualment
+$ EALREADY
+37 L'operació ja es troba en progrés
+$ ENOTSOCK
+38 Operació de tipus socket en quelcom que no ho és
+$ EDESTADDRREQ
+39 Es requereix l'adreça de destí
+$ EMSGSIZE
+40 Missatge massa llarg
+$ EPROTOTYPE
+41 Tipus de protocol incorrecte per al socket
+$ ENOPROTOOPT
+42 Protocol no disponible
+$ EPROTONOSUPPORT
+43 Protocol no suportat
+$ ESOCKTNOSUPPORT
+44 Tipus de socket no suportat
+$ EOPNOTSUPP
+45 Operació no suportada
+$ EPFNOSUPPORT
+46 Família de protocols no suportada
+$ EAFNOSUPPORT
+47 Família d'adreces no suportada per la família de protocols
+$ EADDRINUSE
+48 L'adreça ja es troba en ús
+$ EADDRNOTAVAIL
+49 No es pot assignar l'adreça demanada
+$ ENETDOWN
+50 La xarxa no es troba disponible
+$ ENETUNREACH
+51 No es pot accedir a la xarxa
+$ ENETRESET
+52 La connexió a la xarxa s'ha perdut durant la reinicialització
+$ ECONNABORTED
+53 El programari ha causat l'avort de la connexió
+$ ECONNRESET
+54 L'interlocutor ha reinicialitzat la comunicació
+$ ENOBUFS
+55 No hi ha prou espai per a la memoria intermèdia (buffer)
+$ EISCONN
+56 El socket ja es troba connectat
+$ ENOTCONN
+57 El socket no es troba connectat
+$ ESHUTDOWN
+58 No es pot enviar desprès de la desconnexió del socket
+$ ETOOMANYREFS
+59 Hi ha massa referències: no es poden unir
+$ ETIMEDOUT
+60 El temps de connexió s'ha esgotat
+$ ECONNREFUSED
+61 Connexió rebutjada
+$ ELOOP
+62 Hi ha massa nivells d'enllaços simbòlics
+$ ENAMETOOLONG
+63 Nom d'arxiu massa llarg
+$ EHOSTDOWN
+64 La màquina no es troba disponible
+$ EHOSTUNREACH
+65 No hi ha cap camí fins a la màquina
+$ ENOTEMPTY
+66 El directori no està buit
+$ EPROCLIM
+67 Hi ha massa processos
+$ EUSERS
+68 Hi ha massa usuaris
+$ EDQUOT
+69 Quota de disc sobrepassada
+$ ESTALE
+70 Descriptor d'arxiu NFS incorrecte
+$ EREMOTE
+71 Massa nivells en el camí de destí
+$ EBADRPC
+72 L'estructura RPC es incorrecta
+$ ERPCMISMATCH
+73 La versió del RPC es incorrecta
+$ EPROGUNAVAIL
+74 El programa RPC no es troba disponible
+$ EPROGMISMATCH
+75 Versió incorrecta del programa
+$ EPROCUNAVAIL
+76 Procediment erroni per al programa
+$ ENOLCK
+77 No hi ha bloquejos disponibles
+$ ENOSYS
+78 Funció no implementada
+$ EFTYPE
+79 Tipus d'arxiu o de format inadequat
+$ EAUTH
+80 Error d'autenticació
+$ ENEEDAUTH
+81 Es necessita un autenticador
+$ EIDRM
+82 Identificador eliminat
+$ ENOMSG
+83 No hi ha missatges del tipus desitjat
+$ EOVERFLOW
+84 Valor massa gran per a ésser emmagatzemat en el tipus de dades
+$ EILSEQ
+85 Seqüència de bytes il·legal
+$ ENOTSUP
+86 No suportat
+$ ECANCELED
+87 Operació cancel·lada
+$ EBADMSG
+88 Missatje incorrecte o corrupte
+$ ENODATA
+89 No hi ha missatges disponibles
+$ ENOSR
+90 No hi ha recursos de tipus STREAM
+$ ENOSTR
+91 No és un STREAM
+$ ETIME
+92 Temps d'espera esgotat en el ioctl STREAM
+$ ENOATTR
+93 Atribut inexistent
+$ EMULTIHOP
+94 S'ha intentat un multisalt
+$ ENOLINK
+95 L'enllaç s'ha servit
+$ EPROTO
+96 Error de protocol
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fí de línia (hangup)
+$ SIGINT
+2 Interrupció
+$ SIGQUIT
+3 Finalització
+$ SIGILL
+4 Instrucció il·legal
+$ SIGTRAP
+5 Depuració (Trace/BPT)
+$ SIGABRT
+6 Crida d'avort
+$ SIGEMT
+7 Captura d'EMT
+$ SIGFPE
+8 Excepció de coma flotant
+$ SIGKILL
+9 Matat
+$ SIGBUS
+10 Error del bus
+$ SIGSEGV
+11 Error de segmentació
+$ SIGSYS
+12 Crida al sistema incorrecta
+$ SIGPIPE
+13 Canal (pipe) trencat
+$ SIGALRM
+14 Alarma de rellotge
+$ SIGTERM
+15 Finalitzat
+$ SIGURG
+16 Condició urgent d'E/S
+$ SIGSTOP
+17 Parat (per senyal)
+$ SIGTSTP
+18 Parat
+$ SIGCONT
+19 Continuant
+$ SIGCHLD
+20 El fill ha acabat
+$ SIGTTIN
+21 Parat (entrada de tty)
+$ SIGTTOU
+22 Parat (sortida de tty)
+$ SIGIO
+23 I/O permesa
+$ SIGXCPU
+24 S'ha sobrepassat el límit de temps de la CPU
+$ SIGXFSZ
+25 S'ha sobrepassat el límit de la longitud de l'arxiu
+$ SIGVTALRM
+26 El temporitzador virtual ha expirat
+$ SIGPROF
+27 El temporitzador del perfilador ha expirat
+$ SIGWINCH
+28 Canvis en la mida de la finestra
+$ SIGINFO
+29 Demanda d'informació
+$ SIGUSR1
+30 Senyal 1 definida per l'usuari
+$ SIGUSR2
+31 Senyal 2 definida per l'usuari
+$ SIGPWR
+32 Fallada/reinicialització de l'alimentació
diff --git a/lib/libc/nls/de_DE.ISO8859-1.msg b/lib/libc/nls/de_DE.ISO8859-1.msg
new file mode 100644
index 0000000..1bb4a3b
--- /dev/null
+++ b/lib/libc/nls/de_DE.ISO8859-1.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for de_DE.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operation nicht erlaubt
+$ ENOENT
+2 Datei oder Verzeichnis nicht gefunden
+$ ESRCH
+3 Prozess nicht gefunden
+$ EINTR
+4 Interrupt innerhalb eines Systemaufrufs
+$ EIO
+5 Ein-/Ausgabefehler
+$ ENXIO
+6 Gerät ist nicht konfiguriert
+$ E2BIG
+7 Argumentliste ist zu lang
+$ ENOEXEC
+8 Die Datei hat kein bekanntes ausführbares Format
+$ EBADF
+9 Ungültiger Dateideskriptor
+$ ECHILD
+10 Keine Kindprozesse
+$ EDEADLK
+11 Ein Deadlock wurde vermieden
+$ ENOMEM
+12 Kann nicht genug Speicher belegen
+$ EACCES
+13 Zugriff verweigert
+$ EFAULT
+14 Ungültige Adresse
+$ ENOTBLK
+15 Es wird ein Blockgerät benötigt
+$ EBUSY
+16 Das Gerät ist belegt
+$ EEXIST
+17 Datei existiert bereits
+$ EXDEV
+18 Link zwischen verschiedenen Geräten
+$ ENODEV
+19 Die Operation wird von diesem Gerät nicht unterstützt
+$ ENOTDIR
+20 Kein Verzeichnis
+$ EISDIR
+21 Ist ein Verzeichnis
+$ EINVAL
+22 Ungültiges Argument
+$ ENFILE
+23 Zu viele offene Dateien im System
+$ EMFILE
+24 Zu viele offene Dateien
+$ ENOTTY
+25 Ungültiger IOCTL für dieses Gerät
+$ ETXTBSY
+26 Datei wird benutzt
+$ EFBIG
+27 Datei zu groß
+$ ENOSPC
+28 Kein Platz mehr auf dem Gerät
+$ ESPIPE
+29 Ungültige Positionierung
+$ EROFS
+30 Dateisystem ist schreibgeschützt
+$ EMLINK
+31 Zu viele Links
+$ EPIPE
+32 Unterbrochene Pipe
+$ EDOM
+33 Numerisches Argument außerhalb des Wertebereichs
+$ ERANGE
+34 Ergebnis außerhalb des Wertebereichs
+$ EAGAIN, EWOULDBLOCK
+35 Ressource vorübergehend nicht verfügbar
+$ EINPROGRESS
+36 Operation wird gerade ausgeführt
+$ EALREADY
+37 Operation wird bereits ausgeführt
+$ ENOTSOCK
+38 Deskriptor ist kein Socket
+$ EDESTADDRREQ
+39 Zieladresse benötigt
+$ EMSGSIZE
+40 Nachricht zu lang
+$ EPROTOTYPE
+41 Ungültiger Protokolltyp für diesen Socket
+$ ENOPROTOOPT
+42 Protokoll nicht verfügbar
+$ EPROTONOSUPPORT
+43 Protokoll nicht unterstützt
+$ ESOCKTNOSUPPORT
+44 Sockettyp nicht unterstützt
+$ EOPNOTSUPP
+45 Operation nicht unterstützt
+$ EPFNOSUPPORT
+46 Protokollfamilie nicht unterstützt
+$ EAFNOSUPPORT
+47 Adressfamilie wird von der Protokollfamilie nicht unterstützt
+$ EADDRINUSE
+48 Adresse wird bereits benutzt
+$ EADDRNOTAVAIL
+49 Kann angeforderte Adresse nicht belegen
+$ ENETDOWN
+50 Netzwerk nicht verfügbar
+$ ENETUNREACH
+51 Netzwerk nicht erreichbar
+$ ENETRESET
+52 Netzwerk hat Verbindung mit Reset abgebrochen
+$ ECONNABORTED
+53 Software verursachte einen Verbindungsabbruch
+$ ECONNRESET
+54 Verbindung wurde von der Gegenstelle geschlossen
+$ ENOBUFS
+55 Keine Buffer verfügbar
+$ EISCONN
+56 Socket ist schon verbunden
+$ ENOTCONN
+57 Socket ist nicht verbunden
+$ ESHUTDOWN
+58 Kann nach einem Socket-Shutdown nicht mehr senden
+$ ETOOMANYREFS
+59 Zu viele Referenzen, kann nicht verbinden
+$ ETIMEDOUT
+60 Verbindungsabbruch durch Zeitüberschreitung
+$ ECONNREFUSED
+61 Verbindung wurde abgelehnt
+$ ELOOP
+62 Zu viele symbolische Links (zirkulär?)
+$ ENAMETOOLONG
+63 Dateiname zu lang
+$ EHOSTDOWN
+64 Host nicht verfügbar
+$ EHOSTUNREACH
+65 Keine Route zum Host
+$ ENOTEMPTY
+66 Verzeichnis ist nicht leer
+$ EPROCLIM
+67 Zu viele Prozesse
+$ EUSERS
+68 Zu viele Benutzer
+$ EDQUOT
+69 Platzlimit überschritten
+$ ESTALE
+70 Verwaister NFS-Dateideskriptor
+$ EREMOTE
+71 Zu viele Fernverweise in diesem Zugriff
+$ EBADRPC
+72 RPC-Struktur ist ungültig
+$ ERPCMISMATCH
+73 RPC-Version ist falsch
+$ EPROGUNAVAIL
+74 RPC-Programm nicht verfügbar
+$ EPROGMISMATCH
+75 Falsche Programmversion
+$ EPROCUNAVAIL
+76 Falsche Prozedur für dieses Programm
+$ ENOLCK
+77 Keine Dateisperren verfügbar
+$ ENOSYS
+78 Funktion nicht implementiert
+$ EFTYPE
+79 Ungültiger Dateityp oder Dateiformat
+$ EAUTH
+80 Authentifizierungsfehler
+$ ENEEDAUTH
+81 Authentikator benötigt
+$ EIDRM
+82 Identifizierung entfernt
+$ ENOMSG
+83 Keine Nachricht vom gewünschten Typ
+$ EOVERFLOW
+84 Wert zu groß, um in Datentyp zu speichern
+$ ECANCELED
+85 Operation abgebrochen
+$ EILSEQ
+86 Ungültige Byte-Sequenz
+$ ENOATTR
+87 Attribut nicht gefunden
+$ EDOOFUS
+88 Programmierfehler
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Verbindungsende
+$ SIGINT
+2 Unterbrechung
+$ SIGQUIT
+3 Programmende
+$ SIGILL
+4 Ungültiger Maschinenbefehl
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Fließkommafehler
+$ SIGKILL
+9 Unbedingter Programmabbruch
+$ SIGBUS
+10 Bus-Zugriffsfehler
+$ SIGSEGV
+11 Illegaler Speicherzugriff
+$ SIGSYS
+12 Ungültiger Systemaufruf
+$ SIGPIPE
+13 Unterbrochene Pipe
+$ SIGALRM
+14 Wecker
+$ SIGTERM
+15 Beendet
+$ SIGURG
+16 Dringende Ein/Ausgabeanforderung
+$ SIGSTOP
+17 Gestoppt (Signal)
+$ SIGTSTP
+18 Gestoppt
+$ SIGCONT
+19 Fortgesetzt
+$ SIGCHLD
+20 Kindprozess beendet
+$ SIGTTIN
+21 Gestoppt (Eingabe)
+$ SIGTTOU
+22 Gestoppt (Ausgabe)
+$ SIGIO
+23 Ein/Ausgabe möglich
+$ SIGXCPU
+24 CPU-Zeitlimit überschritten
+$ SIGXFSZ
+25 Dateigrößenlimit überschritten
+$ SIGVTALRM
+26 Virtueller Wecker abgelaufen
+$ SIGPROF
+27 Profil-Wecker abgelaufen
+$ SIGWINCH
+28 Fenstergröße hat sich verändert
+$ SIGINFO
+29 Informationsanforderung
+$ SIGUSR1
+30 Benutzerdefiniertes Signal 1
+$ SIGUSR2
+31 Benutzerdefiniertes Signal 2
diff --git a/lib/libc/nls/el_GR.ISO8859-7.msg b/lib/libc/nls/el_GR.ISO8859-7.msg
new file mode 100644
index 0000000..ca84929
--- /dev/null
+++ b/lib/libc/nls/el_GR.ISO8859-7.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for C locale (template)
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Ìç åðéôñåðôÞ åíÝñãåéá
+$ ENOENT
+2 Äåí õðÜñ÷åé ôÝôïéï áñ÷åßï Þ êáôÜëïãïò
+$ ESRCH
+3 Ç äéåñãáóßá áõôÞ äåí õðÜñ÷åé
+$ EINTR
+4 Ç êëÞóç óõóôÞìáôïò äéáêüðçêå
+$ EIO
+5 ÓöÜëìá åéóüäïõ/åîüäïõ
+$ ENXIO
+6 Ç óõóêåõÞ äåí Ý÷åé ñõèìéóôåß
+$ E2BIG
+7 Ç ëßóôá ôùí ðáñáìÝôñùí åßíáé ðïëý ìåãÜëç
+$ ENOEXEC
+8 ËáíèáóìÝíç ìïñöÞ åêôåëÝóéìïõ
+$ EBADF
+9 Ðñïâëçìáôéêüò ðåñéãñáöÝáò áñ÷åßïõ
+$ ECHILD
+10 Äåí õðÜñ÷ïõí åîáñôþìåíåò äéåñãáóßåò
+$ EDEADLK
+11 Áðïöåý÷èçêå áäéÝîïäï ðüñïõ
+$ ENOMEM
+12 Áäõíáìßá åê÷þñçóçò ìíÞìçò
+$ EACCES
+13 ¶ñíçóç ðñüóâáóçò
+$ EFAULT
+14 ËÜèïò äéåýèõíóç
+$ ENOTBLK
+15 Áðáéôåßôáé óõóêåõÞ ôýðïõ block
+$ EBUSY
+16 ÓõóêåõÞ êáôåéëçììÝíç
+$ EEXIST
+17 Ôï áñ÷åßï õðÜñ÷åé
+$ EXDEV
+18 Óýíäåóìïò ìåôáîý óõóêåõþí
+$ ENODEV
+19 Ç ëåéôïõñãßá äåí õðïóôçñßæåôáé áðü ôç óõóêåõÞ
+$ ENOTDIR
+20 Äåí åßíáé êáôÜëïãïò
+$ EISDIR
+21 Åßíáé êáôÜëïãïò
+$ EINVAL
+22 Ìç Ýãêõñç ðáñÜìåôñïò
+$ ENFILE
+23 ÕðåñâïëéêÜ ðïëëÜ áíïéêôÜ áñ÷åßá óôï óýóôçìá
+$ EMFILE
+24 ÕðåñâïëéêÜ ðïëëÜ áíïéêôÜ áñ÷åßá
+$ ENOTTY
+25 ÁêáôÜëëçëï ioctl ãéá ôç óõóêåõÞ
+$ ETXTBSY
+26 Ôï áñ÷åßï êåéìÝíïõ åßíáé êáôåéëçììÝíï
+$ EFBIG
+27 Ðïëý ìåãÜëï áñ÷åßï
+$ ENOSPC
+28 Äåí Ý÷åé ìåßíåé åëåýèåñïò ÷þñïò óôç óõóêåõÞ
+$ ESPIPE
+29 ÁêáôÜëëçëç áíß÷íåõóç
+$ EROFS
+30 Ôï óýóôçìá áñ÷åßùí åßíáé ìüíï ãéá áíÜãíùóç
+$ EMLINK
+31 ÐÜñá ðïëëïß óýíäåóìïé
+$ EPIPE
+32 Äéáêïðåßóá óùëÞíùóç
+$ EDOM
+33 Ôï áñéèìçôéêü üñéóìá åßíáé åêôüò ïñßùí
+$ ERANGE
+34 Ðïëý ìåãÜëï áðïôÝëåóìá
+$ EAGAIN, EWOULDBLOCK
+35 Ï ðüñïò äåí åßíáé äéáèÝóéìïò ðñïóùñéíÜ
+$ EINPROGRESS
+36 Ç ëåéôïõñãßá âñßóêåôáé óå åîÝëéîç ôþñá
+$ EALREADY
+37 Ç ëåéôïõñãßá åßíáé Þäç óå åîÝëéîç
+$ ENOTSOCK
+38 Ëåéôïõñãßá õðïäï÷Þò óå ìç-õðïäï÷Þ
+$ EDESTADDRREQ
+39 Áðáéôåßôáé äéåýèõíóç ðñïïñéóìïý
+$ EMSGSIZE
+40 Ðïëý ìåãÜëï ìÞíõìá
+$ EPROTOTYPE
+41 ËÜèïò ôýðïõ ðñùôüêïëëï ãéá õðïäï÷Þ
+$ ENOPROTOOPT
+42 Ôï ðñùôüêïëëï äåí åßíáé äéáèÝóéìï
+$ EPROTONOSUPPORT
+43 Ôï ðñùôüêïëëï äåí õðïóôçñßæåôáé
+$ ESOCKTNOSUPPORT
+44 Ï ôýðïò ôçò õðïäï÷Þò äåí õðóôçñßæåôáé
+$ EOPNOTSUPP
+45 Ç ëåéôïõñãßá äåí õðïóôçñßæåôáé
+$ EPFNOSUPPORT
+46 Äåí õðïóôçñßæåôáé ç ïéêïãÝíåéá ðñùôïêüëëùí
+$ EAFNOSUPPORT
+47 Ç ïéêïãÝíåéá äéåõèýíóåùí äåí õðïóôçñßæåôáé áðü ôçí ïéêïãÝíåéá ðñùôïêüëëùí
+$ EADDRINUSE
+48 Ç äéåýèõíóç ÷ñçóéìïðïéåßôáé Þäç
+$ EADDRNOTAVAIL
+49 Äåí ìðïñåß íá ãßíåé áíÜèåóç ôçò æçôïýìåíçò äéåýèõíóçò
+$ ENETDOWN
+50 Ôï äßêôõï äåí ëåéôïõñãåß
+$ ENETUNREACH
+51 Äåí õðÜñ÷åé äéáäñïìÞ ðñïò ôï äßêôõï
+$ ENETRESET
+52 Ôï äßêôõï äéÝêïøå ôç óýíäåóç êáôÜ ôçí åðáíáöïñÜ
+$ ECONNABORTED
+53 Ôï ëïãéóìéêü ðñïêÜëåóå ôåñìáôéóìü ôçò óýíäåóçò
+$ ECONNRESET
+54 Ç óýíäåóç ôåñìáôßóôçêå áðü ôçí Üëëç ìåñéÜ
+$ ENOBUFS
+55 Äåí õðÜñ÷åé äéáèÝóéìïò ðñïóùñéíüò ÷þñïò
+$ EISCONN
+56 Ç õðïäï÷Þ Ý÷åé Þäç óõíäåèåß
+$ ENOTCONN
+57 Ç õðïäï÷Þ äåí Ý÷åé óõíäåèåß
+$ ESHUTDOWN
+58 Äåí åßíáé äõíáôÞ ç áðïóôïëÞ ìåôÜ ôïí ôåñìáôéóìü ôçò õðïäï÷Þò
+$ ETOOMANYREFS
+59 ÐÜñá ðïëëÝò áíáöïñÝò: äåí ìðïñåß íá ãßíåé óõíÝíùóç
+$ ETIMEDOUT
+60 ÔÝëïò ÷ñüíïõ äéáäéêáóßáò
+$ ECONNREFUSED
+61 ¶ñíçóç óýíäåóçò
+$ ELOOP
+62 ÐÜñá ðïëëÜ åðßðåäá óõìâïëéêþí óõíäÝóåùí
+$ ENAMETOOLONG
+63 Ðïëý ìåãÜëï üíïìá áñ÷åßïõ
+$ EHOSTDOWN
+64 Ôï óýóôçìá äåí åßíáé óå ëåéôïõñãßá
+$ EHOSTUNREACH
+65 Äåí õðÜñ÷åé äéáäñïìÞ ðñïò ôï óýóôçìá
+$ ENOTEMPTY
+66 Ï êáôÜëïãïò äåí åßíáé Üäåéïò
+$ EPROCLIM
+67 ÕðåñâïëéêÜ ðïëëÝò äéåñãáóßåò
+$ EUSERS
+68 ÕðåñâïëéêÜ ðïëëïß ÷ñÞóôåò
+$ EDQUOT
+69 ÕðÝñâáóç ïñßùí ÷ñÞóçò äßóêïõ
+$ ESTALE
+70 ¶êõñï handle áñ÷åßïõ óôï NFS
+$ EREMOTE
+71 ÐÜñá ðïëëÜ áðïìáêñõóìÝíá åðßðåäá óôç äéáäñïìÞ
+$ EBADRPC
+72 Ç äïìÞ RPC åßíáé ðñïâëçìáôéêÞ
+$ ERPCMISMATCH
+73 ËáíèáóìÝíç Ýêäïóç RPC
+$ EPROGUNAVAIL
+74 Ôï ðñüãñáììá RPC äåí åßíáé äéáèÝóéìï
+$ EPROGMISMATCH
+75 ËáíèáóìÝíç Ýêäïóç ðñïãñÜììáôïò
+$ EPROCUNAVAIL
+76 ÐñïâëçìáôéêÞ äéáäéêáóßá ãéá ôï ðñüãñáììá
+$ ENOLCK
+77 Äåí õðÜñ÷ïõí äéáèÝóéìá êëåéäþìáôá
+$ ENOSYS
+78 Ç ëåéôïõñãßá äåí Ý÷åé õëïðïéçèåß
+$ EFTYPE
+79 ËáíèáóìÝíïò ôýðïò Þ ìïñöÞ áñ÷åßïõ
+$ EAUTH
+80 ÓöÜëìá êáôÜ ôçí ðéóôïðïßçóç áõèåíôéêüôçôáò
+$ ENEEDAUTH
+81 Áðáéôåßôáé ðéóôïðïéçôÞò áõèåíôéêüôçôáò
+$ EIDRM
+82 Ôï áíáãíùñéóôéêü Ý÷åé áöáéñåèåß
+$ ENOMSG
+83 Äåí õðÜñ÷åé ìÞíõìá ôïõ êáèïñéóìÝíïõ ôýðïõ
+$ EOVERFLOW
+84 Ç ôéìÞ åßíáé ðïëý ìåãÜëç ãéá íá áðïèçêåõèåß óôïí ôýðï äåäïìÝíùí
+$ ECANCELED
+85 Ç ëåéôïõñãßá áêõñþèçêå
+$ EILSEQ
+86 Ìç-Ýãêõñç áêïëïõèßá bytes
+$ ENOATTR
+87 Ôï ÷áñáêôçñéóôéêü äåí âñÝèçêå
+$ EDOOFUS
+88 ÓöÜëìá ðñïãñáììáôéóìïý
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Êëåßóéìï
+$ SIGINT
+2 ÄéáêïðÞ
+$ SIGQUIT
+3 Ôåñìáôéóìüò
+$ SIGILL
+4 Ìç-Ýãêõñç åíôïëÞ
+$ SIGTRAP
+5 Ðáãßäá Trace/BPT
+$ SIGABRT
+6 Ðáãßäá áêýñùóçò
+$ SIGEMT
+7 Ðáãßäá EMT
+$ SIGFPE
+8 Åîáßñåóç êéíçôÞò õðïäéáóôïëÞò
+$ SIGKILL
+9 Ôåñìáôßóôçêå
+$ SIGBUS
+10 ÓöÜëìá äéáýëïõ
+$ SIGSEGV
+11 ÓöÜëìá Segmentation
+$ SIGSYS
+12 ÊáêÞ êëÞóç óõóôÞìáôïò
+$ SIGPIPE
+13 ÄéáêïðÞ pipe
+$ SIGALRM
+14 Ñïëüé åéäïðïßçóçò
+$ SIGTERM
+15 Ôåñìáôßóôçêå
+$ SIGURG
+16 ¸êôáêôç êáôÜóôáóç É/Ï
+$ SIGSTOP
+17 Óå áíáìïíÞ (óÞìá)
+$ SIGTSTP
+18 Óå áíáìïíÞ
+$ SIGCONT
+19 Óõíå÷ßæåôáé
+$ SIGCHLD
+20 ÔÝëïò åîáñôþìåíçò äéåñãáóßáò
+$ SIGTTIN
+21 ÄéáêïðÞ (åßóïäïò tty)
+$ SIGTTOU
+22 ÄéáêïðÞ (Ýîïäïò tty)
+$ SIGIO
+23 Äõíáôüôçôá I/O
+$ SIGXCPU
+24 ÎåðåñÜóôçêå ôï üñéï ÷ñÞóçò ôçò CPU
+$ SIGXFSZ
+25 ÎåðåñÜóôçêå ôï ìÝãéóôï ìÝãåèïò áñ÷åßïõ
+$ SIGVTALRM
+26 ÅîáíôëÞèçêå ï åéêïíéêüò ÷ñïíïìåôñçôÞò
+$ SIGPROF
+27 ÅîáíôëÞèçêå ï ÷ñïíïìåôñçôÞò profiling
+$ SIGWINCH
+28 Ôï ìÝãåèïò ôïõ ðáñáèýñïõ áëëÜæåé
+$ SIGINFO
+29 Áßôçóç ãéá ðëçñïöïñßá
+$ SIGUSR1
+30 ÓÞìá 1 êáèïñéóìÝíï áðü ôï ÷ñÞóôç
+$ SIGUSR2
+31 ÓÞìá 2 êáèïñéóìÝíï áðü ôï ÷ñÞóôç
diff --git a/lib/libc/nls/es_ES.ISO8859-1.msg b/lib/libc/nls/es_ES.ISO8859-1.msg
new file mode 100644
index 0000000..8fc9c7d
--- /dev/null
+++ b/lib/libc/nls/es_ES.ISO8859-1.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for es_ES.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operación no permitida
+$ ENOENT
+2 Fichero o directorio inexistente
+$ ESRCH
+3 Proceso inexistente
+$ EINTR
+4 Llamada del sistema interrumpida
+$ EIO
+5 Error de Entrada/Salida
+$ ENXIO
+6 Dispositivo no configurado
+$ E2BIG
+7 La lista de argumentos es demasiado larga
+$ ENOEXEC
+8 Error en el formato del ejecutable
+$ EBADF
+9 Descriptor incorrecto de fichero
+$ ECHILD
+10 No hay procesos hijo
+$ EDEADLK
+11 Se ha evitado el bloqueo del recurso
+$ ENOMEM
+12 No se pudo asignar memoria
+$ EACCES
+13 Permiso denegado
+$ EFAULT
+14 Dirección incorrecta
+$ ENOTBLK
+15 Se necesita un dispositivo de bloques
+$ EBUSY
+16 Dispositivo ocupado
+$ EEXIST
+17 El fichero ya existe
+$ EXDEV
+18 Enlace entre dispositivos
+$ ENODEV
+19 Operación inadecuada para este dispositivo
+$ ENOTDIR
+20 No es un directorio
+$ EISDIR
+21 Es un directorio
+$ EINVAL
+22 Argumento inadecuado
+$ ENFILE
+23 Hay demasiados ficheros abiertos en el sistema
+$ EMFILE
+24 Hay demasiados ficheros abiertos
+$ ENOTTY
+25 ioctl inapropiado para el dispositivo
+$ ETXTBSY
+26 Fichero de texto ocupado
+$ EFBIG
+27 Fichero demasiado grande
+$ ENOSPC
+28 No queda espacio libre en el dispositivo
+$ ESPIPE
+29 Illegal seek
+$ EROFS
+30 Sistema de ficheros de solo lectura
+$ EMLINK
+31 Demasiados enlaces
+$ EPIPE
+32 Canal (pipe) roto
+$ EDOM
+33 Argumento numérico fuera de rango
+$ ERANGE
+34 El resultado es demasiado grande
+$ EAGAIN, EWOULDBLOCK
+35 el recurso no está disponible temporalmente
+$ EINPROGRESS
+36 Operación en proceso
+$ EALREADY
+37 La operación ya se está ejecutando
+$ ENOTSOCK
+38 Operación de socket inaceptable para el dispositivo
+$ EDESTADDRREQ
+39 Se necesita una dirección de destino
+$ EMSGSIZE
+40 Mensaje demasiado largo
+$ EPROTOTYPE
+41 Tipo erróneo de protocolo para el socket
+$ ENOPROTOOPT
+42 protocolo no disponible
+$ EPROTONOSUPPORT
+43 Protocolo no contemplado
+$ ESOCKTNOSUPPORT
+44 Tipo de socket no contemplado
+$ EOPNOTSUPP
+45 Operación no contemplada
+$ EPFNOSUPPORT
+46 Familia de protocolos no contemplada
+$ EAFNOSUPPORT
+47 Familia de direcciones no contemplada por la familia de protocolos
+$ EADDRINUSE
+48 La dirección ya está siendo usada
+$ EADDRNOTAVAIL
+49 No se pudo asignar la dirección requerida
+$ ENETDOWN
+50 La red no funciona
+$ ENETUNREACH
+51 No se ha podido acceder a la red
+$ ENETRESET
+52 La conexión de red se ha interrumpido al reinicializar
+$ ECONNABORTED
+53 Conexión perdida por problemas en el software
+$ ECONNRESET
+54 El interlocutor ha reinicializado la conexión
+$ ENOBUFS
+55 No queda espacio en el búfer
+$ EISCONN
+56 El socket ya estaba conectado
+$ ENOTCONN
+57 El socket no está conectado
+$ ESHUTDOWN
+58 No se puede enviar tras la desconexión del socket
+$ ETOOMANYREFS
+59 Demasiadas referencias: no se pueden unir
+$ ETIMEDOUT
+60 El tiempo de conexión ha expirado
+$ ECONNREFUSED
+61 Conexión rehusada
+$ ELOOP
+62 Demasiados niveles de enlaces simbólicos
+$ ENAMETOOLONG
+63 Nombre de fichero demasiado largo
+$ EHOSTDOWN
+64 La máquina está fuera de servicio
+$ EHOSTUNREACH
+65 No hay ruta hasta la máquina
+$ ENOTEMPTY
+66 Directorio no vacío
+$ EPROCLIM
+67 Demasiados procesos
+$ EUSERS
+68 Demasiados usuarios
+$ EDQUOT
+69 Cuota de disco sobrepasada
+$ ESTALE
+70 Descriptor de fichero NFS inválido
+$ EREMOTE
+71 Ruta con demasiados niveles
+$ EBADRPC
+72 La estructura de la RPC es errónea
+$ ERPCMISMATCH
+73 La versón de la RPC es errónea
+$ EPROGUNAVAIL
+74 La RPC no está accesible
+$ EPROGMISMATCH
+75 Versión errónea del programa
+$ EPROCUNAVAIL
+76 Procedimiento erróneo para el programa
+$ ENOLCK
+77 No hay bloqueos disponibles
+$ ENOSYS
+78 Función no realizada
+$ EFTYPE
+79 Tipo de fichero o formato inapropiado
+$ EAUTH
+80 Error de autentificación
+$ ENEEDAUTH
+81 Se necesita un autenticador
+$ EIDRM
+82 Identificador eliminado
+$ ENOMSG
+83 No hay mensajes del tipo deseado
+$ EOVERFLOW
+84 Valor demasiado grande para almacenarse en el tipo deseado
+$ ECANCELED
+85 Operación cancelada
+$ EILSEQ
+86 Illegal byte sequence
+$ ENOATTR
+87 Atributo no encontrado
+$ EDOOFUS
+88 Error de programación
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fín de línea (Hangup)
+$ SIGINT
+2 Interrumpido
+$ SIGQUIT
+3 Terminado
+$ SIGILL
+4 Illegal instruction
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Excepción de coma flotante
+$ SIGKILL
+9 Matado
+$ SIGBUS
+10 Error en el bus
+$ SIGSEGV
+11 Fallo de segmentación
+$ SIGSYS
+12 Llamada al sistema errónea
+$ SIGPIPE
+13 Canal (pipe) roto
+$ SIGALRM
+14 Alarma del reloj
+$ SIGTERM
+15 Terminado
+$ SIGURG
+16 Condición urgente de E/S
+$ SIGSTOP
+17 Detenido (señal)
+$ SIGTSTP
+18 Detenido
+$ SIGCONT
+19 Continuando
+$ SIGCHLD
+20 Proceso hijo terminado
+$ SIGTTIN
+21 Detenido (entrada tty)
+$ SIGTTOU
+22 Detenido (salida tty)
+$ SIGIO
+23 E/S posible
+$ SIGXCPU
+24 Se ha sobrepasado el tiempo límite de la CPU
+$ SIGXFSZ
+25 Se ha sobrepasado el límite de tamaño de fichero
+$ SIGVTALRM
+26 Temporizador virtual expirado
+$ SIGPROF
+27 Temporizador de perfilación expirado
+$ SIGWINCH
+28 Cambios en el tamaño de ventana
+$ SIGINFO
+29 Petición de información
+$ SIGUSR1
+30 Señal definida por el usuario n1
+$ SIGUSR2
+31 Señal definida por el usuario n2
diff --git a/lib/libc/nls/fi_FI.ISO8859-1.msg b/lib/libc/nls/fi_FI.ISO8859-1.msg
new file mode 100644
index 0000000..491f9a1
--- /dev/null
+++ b/lib/libc/nls/fi_FI.ISO8859-1.msg
@@ -0,0 +1,233 @@
+$ $FreeBSD$
+$
+$ Message catalog for fi_FI.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Toimintoa ei sallita
+$ ENOENT
+2 Tiedostoa tai hakemistoa ei löydy
+$ ESRCH
+3 Prosessia ei löydy
+$ EINTR
+4 Systeemikutsu keskeytyi
+$ EIO
+5 Syöttö/tulostusvirhe
+$ ENXIO
+6 Laitetta ei määritelty
+$ E2BIG
+7 Liikaa argumentteja
+$ ENOEXEC
+8 Tuntematon ohjelmatyyppi
+$ EBADF
+9 Virheellinen tiedosto-osoitin
+$ ECHILD
+10 Ei lapsiprosesseja
+$ EDEADLK
+11 Resurssin ristiinlukitus vältetty
+$ ENOMEM
+12 Muistinvaraus epäonnistui
+$ EACCES
+13 Lupa kielletty
+$ EFAULT
+14 Virheellinen osoite
+$ ENOTBLK
+15 Tarvitaan lohko-osoitettava laite
+$ EBUSY
+16 Laite käytössä
+$ EEXIST
+17 Tiedosto on jo olemassa
+$ EXDEV
+18 Laitteiden välinen linkki
+$ ENODEV
+19 Laite ei tue toimintoa
+$ ENOTDIR
+20 Kohde ei ole hakemisto
+$ EISDIR
+21 Kohde on hakemisto
+$ EINVAL
+22 Virheellinen argumentti
+$ ENFILE
+23 Järjestelmässä on liian monta avointa tiedostoa
+$ EMFILE
+24 Liian monta avointa tiedostoa
+$ ENOTTY
+25 Virheellinen ohjaustoiminto laitteelle
+$ ETXTBSY
+26 Tiedosto on käytössä
+$ EFBIG
+27 Tiedosto liian suuri
+$ ENOSPC
+28 Laitteella ei ole tilaa
+$ ESPIPE
+29 Virheellinen haku
+$ EROFS
+30 Vain luettava tiedostojärjestelmä
+$ EMLINK
+31 Liian monta linkkiä
+$ EPIPE
+32 Katkennut putki
+$ EDOM
+33 Numeerinen syöte virheellinen
+$ ERANGE
+34 Tulos liian suuri
+$ EAGAIN, EWOULDBLOCK
+35 Resurssi ei ole tilapäisesti saatavilla
+$ EINPROGRESS
+36 Toiminta on käynnissä
+$ EALREADY
+37 Toiminta oli jo käynnissä
+$ ENOTSOCK
+38 Socket-operaatio muulla kuin socketilla
+$ EDESTADDRREQ
+39 Tarvitaan kohdeosoite
+$ EMSGSIZE
+40 Sanoma liian pitkä
+$ EPROTOTYPE
+41 Väärä protokolla socketille
+$ ENOPROTOOPT
+42 Protokolla ei ole käytettävissä
+$ EPROTONOSUPPORT
+43 Protokollaa ei tueta
+$ ESOCKTNOSUPPORT
+44 Socket-tyyppiä ei tueta
+$ EOPNOTSUPP
+45 Toimintoa ei tueta
+$ EPFNOSUPPORT
+46 Protokollaperhettä ei tueta
+$ EAFNOSUPPORT
+47 Protokollaperhe ei tue osoiteperhettä
+$ EADDRINUSE
+48 Osoite on jo käytössä
+$ EADDRNOTAVAIL
+49 Ei pysty antamaan pyydettyä osoitetta
+$ ENETDOWN
+50 Verkko ei ole käytettävissä
+$ ENETUNREACH
+51 Verkkoon ei ole yhteyttä
+$ ENETRESET
+52 Verkko sulki yhteyden
+$ ECONNABORTED
+53 Ohjelmiston aiheuttama yhteyden keskeytyminen
+$ ECONNRESET
+54 Isäntä nollasi yhteyden
+$ ENOBUFS
+55 Puskuritila on lopussa
+$ EISCONN
+56 Yhteys on jo olemassa
+$ ENOTCONN
+57 Yhteyttä ei ole olemassa
+$ ESHUTDOWN
+58 Lähettäminen ei ole mahdollista yhteyden katkaisun jälkeen
+$ ETOOMANYREFS
+59 Liikaa viittauksia: ei voi yhdistää
+$ ETIMEDOUT
+60 Yhteyden aikavalvontakatkaisu
+$ ECONNREFUSED
+61 Yhteys hylätty
+$ ELOOP
+62 Liian monta peräkkäistä symbolista linkkiä
+$ ENAMETOOLONG
+63 Tiedoston nimi on liian pitkä
+$ EHOSTDOWN
+64 Isäntä ei vastaa
+$ EHOSTUNREACH
+65 Ei reittiä isäntään
+$ ENOTEMPTY
+66 Hakemisto ei ole tyhjä
+$ EPROCLIM
+67 Liian monta prosessia
+$ EUSERS
+68 Liian monta käyttäjää
+$ EDQUOT
+69 Levytilarajoitus ylittyi
+$ ESTALE
+70 Vanhentunut NFS-yhteys
+$ EREMOTE
+71 Liian monta verkkolevyä polussa
+$ EBADRPC
+72 Virheellinen RPC-pyyntö
+$ ERPCMISMATCH
+73 Väärä RPC-versio
+$ EPROGUNAVAIL
+74 RPC ei käytettävissä
+$ EPROGMISMATCH
+75 Väärä ohjelmaversio
+$ EPROCUNAVAIL
+76 Väärä RPC-pyyntö ohjelmalle
+$ ENOLCK
+77 Lukitus ei käytettävissä
+$ ENOSYS
+78 Toimintoa ei ole
+$ EFTYPE
+79 Väärä tiedostotyyppi tai -formaatti
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Katkaisu
+$ SIGINT
+2 Keskeytys
+$ SIGQUIT
+3 Lopetus
+$ SIGILL
+4 Laiton käsky
+$ SIGTRAP
+5 Jäljitys/BPT ansa
+$ SIGABRT
+6 Poistumisansa
+$ SIGEMT
+7 EMT-ansa
+$ SIGFPE
+8 Liukulukuvirhe
+$ SIGKILL
+9 Tapettu
+$ SIGBUS
+10 Väylävirhe
+$ SIGSEGV
+11 Suojausvirhe
+$ SIGSYS
+12 Virheellinen systeemikutsu
+$ SIGPIPE
+13 Katkennut putki
+$ SIGALRM
+14 Hälytyskello
+$ SIGTERM
+15 Lopetettu
+$ SIGURG
+16 Kiireellinen syöttö/tulostus
+$ SIGSTOP
+17 Pysäytetty (signaali)
+$ SIGTSTP
+18 Pysäytetty
+$ SIGCONT
+19 Jatkettu
+$ SIGCHLD
+20 Lapsiprosessi päättynyt
+$ SIGTTIN
+21 Pysäytetty (tty-syöte)
+$ SIGTTOU
+22 Pysäytetty (tty-tuloste)
+$ SIGIO
+23 Syöttö ja tulostus mahdollisia
+$ SIGXCPU
+24 Keskusyksikköaikarajoitus ylitetty
+$ SIGXFSZ
+25 Tiedoston kokorajoitus ylitetty
+$ SIGVTALRM
+26 Virtuaali-ajastin laukesi
+$ SIGPROF
+27 Profilointiajastin laukesi
+$ SIGWINCH
+28 Ikkunan koko muuttuu
+$ SIGINFO
+29 Informaatiopyyntö
+$ SIGUSR1
+30 Käyttäjän määriteltävä signaali 1
+$ SIGUSR2
+31 Käyttäjän määriteltävä signaali 2
+$ SIGPWR
+32 Virransaannin tilassa muutos
diff --git a/lib/libc/nls/fr_FR.ISO8859-1.msg b/lib/libc/nls/fr_FR.ISO8859-1.msg
new file mode 100644
index 0000000..35a8c4a
--- /dev/null
+++ b/lib/libc/nls/fr_FR.ISO8859-1.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for fr_FR.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Opération non autorisée
+$ ENOENT
+2 Fichier ou répertoire inexistant
+$ ESRCH
+3 Processus inconnu
+$ EINTR
+4 Appel système interrompu
+$ EIO
+5 Erreur d'entrée/sortie
+$ ENXIO
+6 Dispositif non configuré
+$ E2BIG
+7 Liste d'arguments trop longue
+$ ENOEXEC
+8 Format d'exécutable invalide
+$ EBADF
+9 Mauvais descripteur de fichier
+$ ECHILD
+10 Pas de processus fils
+$ EDEADLK
+11 Étreinte mortelle détectée
+$ ENOMEM
+12 Impossible d'allouer de la mémoire
+$ EACCES
+13 Permission refusée
+$ EFAULT
+14 Mauvaise adresse
+$ ENOTBLK
+15 Dispositif en mode bloc requis
+$ EBUSY
+16 Dispositif occupé
+$ EEXIST
+17 Le fichier existe
+$ EXDEV
+18 Lien inter-unités
+$ ENODEV
+19 Opération non supportée par le dispositif
+$ ENOTDIR
+20 Pas un répertoire
+$ EISDIR
+21 Est un répertoire
+$ EINVAL
+22 Argument invalide
+$ ENFILE
+23 Trop de fichiers ouverts sur le système
+$ EMFILE
+24 Trop de fichiers ouverts
+$ ENOTTY
+25 Fonction inadaptée au dispositif
+$ ETXTBSY
+26 Fichier en cours d'utilisation
+$ EFBIG
+27 Fichier trop grand
+$ ENOSPC
+28 Plus d'espace disponible
+$ ESPIPE
+29 Recherche illégale
+$ EROFS
+30 Système de fichier en lecture seulement
+$ EMLINK
+31 Trop de liens
+$ EPIPE
+32 Tube déconnecté
+$ EDOM
+33 Argument numérique hors définition
+$ ERANGE
+34 Résultat trop grand
+$ EAGAIN, EWOULDBLOCK
+35 Ressource indisponible temporairement
+$ EINPROGRESS
+36 Opération en cours
+$ EALREADY
+37 Opération déjà en cours
+$ ENOTSOCK
+38 Opération de type socket sur un descripteur de fichier
+$ EDESTADDRREQ
+39 Adresse de destination obligatoire
+$ EMSGSIZE
+40 Message trop long
+$ EPROTOTYPE
+41 Mauvais type de protocole pour la socket
+$ ENOPROTOOPT
+42 Protocole non disponible
+$ EPROTONOSUPPORT
+43 Protocole non supporté
+$ ESOCKTNOSUPPORT
+44 Type de socket non supporté
+$ EOPNOTSUPP
+45 Opération non supporté
+$ EPFNOSUPPORT
+46 Famille de protocole non supportée
+$ EAFNOSUPPORT
+47 Famille d'adresse non supportée par la famille de protocole
+$ EADDRINUSE
+48 Adresse en cours d'utilisation
+$ EADDRNOTAVAIL
+49 Impossible d'assigner l'adresse demandée
+$ ENETDOWN
+50 Plus de réseau
+$ ENETUNREACH
+51 Réseau inaccessible
+$ ENETRESET
+52 Connexion coupée par le réseau
+$ ECONNABORTED
+53 Connexion interrompue
+$ ECONNRESET
+54 Connexion interrompue par l'hôte distant
+$ ENOBUFS
+55 Tampon saturé
+$ EISCONN
+56 La socket est déjà connectée
+$ ENOTCONN
+57 La socket n'est pas connectée
+$ ESHUTDOWN
+58 Impossible d'envoyer après la coupure
+$ ETOOMANYREFS
+59 Trop de références : lien impossible
+$ ETIMEDOUT
+60 Dépassement du délai d'attente
+$ ECONNREFUSED
+61 Connexion refusée
+$ ELOOP
+62 Trop de niveaux de liens symboliques
+$ ENAMETOOLONG
+63 Nom de fichier trop long
+$ EHOSTDOWN
+64 Hôte distant arrêté
+$ EHOSTUNREACH
+65 Pas de route vers l'hôte distant
+$ ENOTEMPTY
+66 Répertoire non vide
+$ EPROCLIM
+67 Trop de processus
+$ EUSERS
+68 Trop d'utilisateurs
+$ EDQUOT
+69 Quota de disque dépassé
+$ ESTALE
+70 Identificateur de fichier NFS périmé
+$ EREMOTE
+71 Trop de niveaux extérieurs dans le path
+$ EBADRPC
+72 Mauvaise structure RPC
+$ ERPCMISMATCH
+73 Mauvaise version RPC
+$ EPROGUNAVAIL
+74 Prog. RPC indisponible
+$ EPROGMISMATCH
+75 Mauvaise version de programme
+$ EPROCUNAVAIL
+76 Mauvaise procédure pour le programme
+$ ENOLCK
+77 Plus de verrous disponibles
+$ ENOSYS
+78 Fonction non implémentée
+$ EFTYPE
+79 Type de fichier ou format inapproprié
+$ EAUTH
+80 Erreur d'authentification
+$ ENEEDAUTH
+81 Authentification requise
+$ EIDRM
+82 Identifiant retiré
+$ ENOMSG
+83 Aucun message du type souhaité
+$ EOVERFLOW
+84 Valeur trop grande pour le type de donnée
+$ ECANCELED
+85 Opération annulée
+$ EILSEQ
+86 Séquence d'octets illégale
+$ ENOATTR
+87 Attribut non trouvé
+$ EDOOFUS
+88 Erreur de programmation
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fin de connexion
+$ SIGINT
+2 Interruption
+$ SIGQUIT
+3 Quitter
+$ SIGILL
+4 Instruction illégale
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Exception sur virgule flottante
+$ SIGKILL
+9 Tué
+$ SIGBUS
+10 Bus error
+$ SIGSEGV
+11 Segmentation fault
+$ SIGSYS
+12 Bad system call
+$ SIGPIPE
+13 Broken pipe
+$ SIGALRM
+14 Alarm clock
+$ SIGTERM
+15 Terminé
+$ SIGURG
+16 Urgent I/O condition
+$ SIGSTOP
+17 Suspended (signal)
+$ SIGTSTP
+18 Suspended
+$ SIGCONT
+19 Continued
+$ SIGCHLD
+20 Child exited
+$ SIGTTIN
+21 Stopped (tty input)
+$ SIGTTOU
+22 Stopped (tty output)
+$ SIGIO
+23 I/O possible
+$ SIGXCPU
+24 Cputime limit exceeded
+$ SIGXFSZ
+25 Filesize limit exceeded
+$ SIGVTALRM
+26 Virtual timer expired
+$ SIGPROF
+27 Profiling timer expired
+$ SIGWINCH
+28 Window size changes
+$ SIGINFO
+29 Information request
+$ SIGUSR1
+30 User defined signal 1
+$ SIGUSR2
+31 User defined signal 2
diff --git a/lib/libc/nls/hu_HU.ISO8859-2.msg b/lib/libc/nls/hu_HU.ISO8859-2.msg
new file mode 100644
index 0000000..90b597b
--- /dev/null
+++ b/lib/libc/nls/hu_HU.ISO8859-2.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for hu_HU.ISO8859-2 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Nem engedélyezett mûvelet
+$ ENOENT
+2 Fájl vagy könyvtár nem található
+$ ESRCH
+3 Processz nem található
+$ EINTR
+4 Megszakított rendszerhívás
+$ EIO
+5 B/K hiba
+$ ENXIO
+6 Konfigurálatlan eszköz
+$ E2BIG
+7 Túl hosszú argumentumlista
+$ ENOEXEC
+8 Hibás végrehajtható formátum
+$ EBADF
+9 Rossz fájlleíró
+$ ECHILD
+10 Nem létezõ gyermek processz
+$ EDEADLK
+11 Resource deadlock avoided
+$ ENOMEM
+12 Memória nem foglalható le
+$ EACCES
+13 Hozzáférés megtagadva
+$ EFAULT
+14 Rossz cím
+$ ENOTBLK
+15 Blokkos eszköz szükséges
+$ EBUSY
+16 Eszköz foglalt
+$ EEXIST
+17 Fájl létezik
+$ EXDEV
+18 Kereszthivatkozás eszközökön
+$ ENODEV
+19 A mûvelet nem támogatott az eszköz által
+$ ENOTDIR
+20 Nem könyvtár
+$ EISDIR
+21 Könyvtár
+$ EINVAL
+22 Érvénytelen argumentum
+$ ENFILE
+23 Túl sok megnyitott fájl a rendszerben
+$ EMFILE
+24 Túl sok megnyitott fájl
+$ ENOTTY
+25 Nem megfelelõ ioctl az eszközhöz
+$ ETXTBSY
+26 Szöveges fájl foglalt
+$ EFBIG
+27 Fájl túl nagy
+$ ENOSPC
+28 Nincs hely az eszközön
+$ ESPIPE
+29 Érvénytelen seek
+$ EROFS
+30 Csak olvasható fájlrendszer
+$ EMLINK
+31 Túl sok link
+$ EPIPE
+32 Hibás csõvezeték
+$ EDOM
+33 Numerikus argumentum nem esik a tartományba
+$ ERANGE
+34 Az esermény túl nagy
+$ EAGAIN, EWOULDBLOCK
+35 Az erõforrás ideiglenesen nem érhetõ el
+$ EINPROGRESS
+36 A mûvelet folyamatban van
+$ EALREADY
+37 A mûvelet már folyamatban van
+$ ENOTSOCK
+38 Socket mûvelet nem socketen
+$ EDESTADDRREQ
+39 Cél cím szükséges
+$ EMSGSIZE
+40 Túl hosszú üzenet
+$ EPROTOTYPE
+41 Rossz protokolltípus a sockethez
+$ ENOPROTOOPT
+42 Protokoll nem érhetõ el
+$ EPROTONOSUPPORT
+43 Protokoll nem támogatott
+$ ESOCKTNOSUPPORT
+44 Sockettípus nem támogatott
+$ EOPNOTSUPP
+45 Mûvelet nem támogatott
+$ EPFNOSUPPORT
+46 Protokollcsalád nem támogatott
+$ EAFNOSUPPORT
+47 A címcsalád nem támogatott a protokollcsalád által
+$ EADDRINUSE
+48 A cím már használatban van
+$ EADDRNOTAVAIL
+49 A kért cím nem osztható ki
+$ ENETDOWN
+50 A hálózat nem mûködik
+$ ENETUNREACH
+51 A hálózat nem érhetõ el
+$ ENETRESET
+52 A hálózat megszakította a kapcsolatot
+$ ECONNABORTED
+53 A szoftver megszakította a kapcsolatot
+$ ECONNRESET
+54 A kapcsolatot megszakította a peer
+$ ENOBUFS
+55 Nincs rendelkezésre álló pufferterület
+$ EISCONN
+56 A socket már kapcsolódva van
+$ ENOTCONN
+57 A socket nincs kapcsolódva
+$ ESHUTDOWN
+58 Nem küldhetõ el a socket lebontása után
+$ ETOOMANYREFS
+59 Túl sok hivatkozás: nem illeszthetõ össze
+$ ETIMEDOUT
+60 A mûvelet túllépte a rendelkezésre álló idõt
+$ ECONNREFUSED
+61 Kapcsolat elutasítva
+$ ELOOP
+62 Túl sok szint a szimbolikus linkekben
+$ ENAMETOOLONG
+63 Túl hosszú fájlnév
+$ EHOSTDOWN
+64 A kiszolgáló nem érhetõ el
+$ EHOSTUNREACH
+65 Nincs útvonal a kiszolgálóhoz
+$ ENOTEMPTY
+66 Könyvtár nem üres
+$ EPROCLIM
+67 Túl sok processz
+$ EUSERS
+68 Túl sok felhasználó
+$ EDQUOT
+69 A lemezkvóta túllépve
+$ ESTALE
+70 Elavult NFS fájlkezelõ
+$ EREMOTE
+71 Túl sok szint a távoli útvonalban
+$ EBADRPC
+72 Rossz RPC struktúra
+$ ERPCMISMATCH
+73 Rossz RPC verzió
+$ EPROGUNAVAIL
+74 RPC program nem érhetõ el
+$ EPROGMISMATCH
+75 Rossz programverzió
+$ EPROCUNAVAIL
+76 Rossz eljárás a programhoz
+$ ENOLCK
+77 Nincs elérhetõ zárolás
+$ ENOSYS
+78 Nem implementált funkció
+$ EFTYPE
+79 Nem megfelelõ fájltípus vagy formátum
+$ EAUTH
+80 Azonosítási hiba
+$ ENEEDAUTH
+81 Azonosítás szükséges
+$ EIDRM
+82 Azonosító eltávolítva
+$ ENOMSG
+83 Nincs üzenet a kívánt típusból
+$ EOVERFLOW
+84 Az érték túl nagy az adott adattípusban való tároláshoz
+$ ECANCELED
+85 Mûvelet törölva
+$ EILSEQ
+86 Érvénytelen bájtsorrend
+$ ENOATTR
+87 Attribútum nem található
+$ EDOOFUS
+88 Programozási hiba
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Hangup
+$ SIGINT
+2 Megszakítás
+$ SIGQUIT
+3 Kilépés
+$ SIGILL
+4 Érvénytelen mûvelet
+$ SIGTRAP
+5 Trace/BPT csapda
+$ SIGABRT
+6 Abort csapda
+$ SIGEMT
+7 EMT csapda
+$ SIGFPE
+8 Lebegõpontos kivétel
+$ SIGKILL
+9 Megölve
+$ SIGBUS
+10 Busz hiba
+$ SIGSEGV
+11 Szegmentációs hiba
+$ SIGSYS
+12 Rossz rendszerhívás
+$ SIGPIPE
+13 Hibás csõvezeték
+$ SIGALRM
+14 Idõzítési riasztás
+$ SIGTERM
+15 Befejezve
+$ SIGURG
+16 Sürgõs B/K feltétel
+$ SIGSTOP
+17 Elaltatva (szignál)
+$ SIGTSTP
+18 Elaltatva
+$ SIGCONT
+19 Folytatva
+$ SIGCHLD
+20 Gyermek befejezõdött
+$ SIGTTIN
+21 Leállítva (tty bevitel)
+$ SIGTTOU
+22 Leállítva (tty kivitel)
+$ SIGIO
+23 B/K lehetséges
+$ SIGXCPU
+24 Processzoridõ-korlátozás túllépve
+$ SIGXFSZ
+25 ájlméret-korlátozás túllépve
+$ SIGVTALRM
+26 Virtuális idõzítõ lejárt
+$ SIGPROF
+27 Profilidõzítõ lejárt
+$ SIGWINCH
+28 Ablakméret-változások
+$ SIGINFO
+29 Információkérés
+$ SIGUSR1
+30 Felhasználói szignál 1
+$ SIGUSR2
+31 Felhasználói szignál 2
diff --git a/lib/libc/nls/it_IT.ISO8859-15.msg b/lib/libc/nls/it_IT.ISO8859-15.msg
new file mode 100644
index 0000000..da3734d
--- /dev/null
+++ b/lib/libc/nls/it_IT.ISO8859-15.msg
@@ -0,0 +1,231 @@
+$ $FreeBSD$
+$
+$ Message catalog for it_IT.ISO8859-15 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operazione non permessa
+$ ENOENT
+2 File o directory inesistente
+$ ESRCH
+3 Processo inesistente
+$ EINTR
+4 Chiamata di sistema interrotta
+$ EIO
+5 Errore di input/output
+$ ENXIO
+6 Periferica non configurata
+$ E2BIG
+7 Lista degli argomenti troppo lunga
+$ ENOEXEC
+8 Errore nel formato eseguibile
+$ EBADF
+9 Descrittore di file non valido
+$ ECHILD
+10 Nessun processo figlio
+$ EDEADLK
+11 Situazione di deadlock evitata
+$ ENOMEM
+12 Impossibile allocare memoria
+$ EACCES
+13 Permesso negato
+$ EFAULT
+14 Indirizzo non valido
+$ ENOTBLK
+15 Periferica a blocchi necessaria
+$ EBUSY
+16 Periferica occupata
+$ EEXIST
+17 Il file esiste
+$ EXDEV
+18 Link improprio
+$ ENODEV
+19 Operazione non supportata dalla periferica
+$ ENOTDIR
+20 Non è una directory
+$ EISDIR
+21 E' una directory
+$ EINVAL
+22 Argomento non valido
+$ ENFILE
+23 Troppi file aperti nel sistema
+$ EMFILE
+24 Troppi file aperti
+$ ENOTTY
+25 Ioctl inappropriata per la periferica
+$ ETXTBSY
+26 File di testo occupato
+$ EFBIG
+27 File troppo grande
+$ ENOSPC
+28 Spazio sulla periferica esaurito
+$ ESPIPE
+29 Ricerca non valida
+$ EROFS
+30 Filesystem di sola lettura
+$ EMLINK
+31 Troppi link
+$ EPIPE
+32 Pipe rotta
+$ EDOM
+33 Argomento numerico fuori dal dominio
+$ ERANGE
+34 Risultato troppo grande
+$ EAGAIN, EWOULDBLOCK
+35 Risorsa temporaneamente non disponibile
+$ EINPROGRESS
+36 Operazione in esecuzione
+$ EALREADY
+37 Operazione già in esecuzione
+$ ENOTSOCK
+38 Operazione sui socket eseguita su un non-socket
+$ EDESTADDRREQ
+39 Indirizzo destinazione necessario
+$ EMSGSIZE
+40 Messaggio troppo lungo
+$ EPROTOTYPE
+41 Tipo di protocollo non valido per il socket
+$ ENOPROTOOPT
+42 Protocollo non disponibile
+$ EPROTONOSUPPORT
+43 Protocollo non supportato
+$ ESOCKTNOSUPPORT
+44 Tipo di socket non supportato
+$ EOPNOTSUPP
+45 Operazione non supportata
+$ EPFNOSUPPORT
+46 Famiglia di protocolli non supportata
+$ EAFNOSUPPORT
+47 Famiglia di indirizzi non supportata dalla famiglia di protocolli
+$ EADDRINUSE
+48 Indirizzo già in uso
+$ EADDRNOTAVAIL
+49 Impossibile assegnare l'indirizzo richiesto
+$ ENETDOWN
+50 Network fuori uso
+$ ENETUNREACH
+51 Network non raggiungibile
+$ ENETRESET
+52 Network dropped connection on reset
+$ ECONNABORTED
+53 Interruzione della connessione causata dal software
+$ ECONNRESET
+54 Connessione azzerata dal corrispondente
+$ ENOBUFS
+55 Spazio del buffer esaurito
+$ EISCONN
+56 Socket già connesso
+$ ENOTCONN
+57 Socket non connesso
+$ ESHUTDOWN
+58 Impossibile inviare dopo la chiusura del socket
+$ ETOOMANYREFS
+59 Troppe referenze: impossibile raccordare
+$ ETIMEDOUT
+60 Connessione scaduta
+$ ECONNREFUSED
+61 Connection rifiutata
+$ ELOOP
+62 Troppi livelli di link simbolici
+$ ENAMETOOLONG
+63 Nome di file troppo lungo
+$ EHOSTDOWN
+64 Host fuori uso
+$ EHOSTUNREACH
+65 Host irraggiungibile
+$ ENOTEMPTY
+66 Directory non vuota
+$ EPROCLIM
+67 Troppi processi
+$ EUSERS
+68 Troppi utenti
+$ EDQUOT
+69 Quota disco superata
+$ ESTALE
+70 Manipolatore di file NFS scaduto
+$ EREMOTE
+71 Troppi livelli remoti nel path
+$ EBADRPC
+72 Struttura RPC non valida
+$ ERPCMISMATCH
+73 Versione RPC non corrispondente
+$ EPROGUNAVAIL
+74 Programma RPC non disponibile
+$ EPROGMISMATCH
+75 Versione del programma non corrispodente
+$ EPROCUNAVAIL
+76 Procedura non disponibile
+$ ENOLCK
+77 Nessun lock disponibile
+$ ENOSYS
+78 Funzione non implementata
+$ EFTYPE
+79 Tipo di file o formato inappropriato
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Hangup
+$ SIGINT
+2 Interruzione
+$ SIGQUIT
+3 Chiusura
+$ SIGILL
+4 Istruzione illegale
+$ SIGTRAP
+5 Trappola Trace/breakpoint
+$ SIGABRT
+6 Trappola abort()
+$ SIGEMT
+7 Trappola EMT
+$ SIGFPE
+8 Errore di virgola mobile
+$ SIGKILL
+9 Ucciso
+$ SIGBUS
+10 Errore di bus
+$ SIGSEGV
+11 Errore di segmentazione
+$ SIGSYS
+12 Chiamata di sistema non valida
+$ SIGPIPE
+13 Pipe rotta
+$ SIGALRM
+14 Sveglia
+$ SIGTERM
+15 Terminato
+$ SIGURG
+16 I/O urgente
+$ SIGSTOP
+17 Processo fermato
+$ SIGTSTP
+18 Stop da terminale
+$ SIGCONT
+19 Continuato
+$ SIGCHLD
+20 Processo figlio uscito
+$ SIGTTIN
+21 Input da terminale per processo in background
+$ SIGTTOU
+22 Output a terminale per processo in background
+$ SIGIO
+23 I/O possibile
+$ SIGXCPU
+24 Limite del tempo di CPU superato
+$ SIGXFSZ
+25 Limite della dimensione del file superato
+$ SIGVTALRM
+26 Timer virtuale scaduto
+$ SIGPROF
+27 Timer di profilo expired
+$ SIGWINCH
+28 Cambio di dimensione della finestra
+$ SIGINFO
+29 Richiesta di informazioni
+$ SIGUSR1
+30 Segnale definito dall'utente 1
+$ SIGUSR2
+31 Segnale definito dall'utente 2
diff --git a/lib/libc/nls/mn_MN.UTF-8.msg b/lib/libc/nls/mn_MN.UTF-8.msg
new file mode 100644
index 0000000..29ab4c1
--- /dev/null
+++ b/lib/libc/nls/mn_MN.UTF-8.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for mn_MN.UTF-8 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ҮйлдÑл зөвшөөрөгдөхгүй
+$ ENOENT
+2 Тийм файл ÑÑвÑл Ñан алга
+$ ESRCH
+3 Тийм процеÑÑ Ð±Ð°Ð¹Ñ…Ð³Ò¯Ð¹
+$ EINTR
+4 СиÑтемийн таÑалдÑан дуудлага
+$ EIO
+5 Оролт/гаралтын алдаа
+$ ENXIO
+6 Төхөөрөмж тохируулагдаагүй
+$ E2BIG
+7 Дагавар өгөгдлийн жагÑаалт Ñ…ÑÑ‚Ñрхий урт
+$ ENOEXEC
+8 Exec Ñ…ÑлбÑршилтийн алдаа
+$ EBADF
+9 Файлын буруу тодорхойлогч
+$ ECHILD
+10 ХүүхÑд процеÑÑ Ð°Ð»Ð³Ð°
+$ EDEADLK
+11 Эх Ò¯Ò¯ÑвÑрийн Ð³Ð°Ñ†Ð°Ð°Ð½Ð°Ð°Ñ Ð·Ð°Ð¹Ð»ÑхийÑÑн
+$ ENOMEM
+12 Санах ойд зай байрлуулж чадахгүй байна
+$ EACCES
+13 Ð—Ó©Ð²ÑˆÓ©Ó©Ñ€Ó©Ñ…Ó©Ó©Ñ Ñ‚Ð°Ñ‚Ð³Ð°Ð»Ð·Ñан
+$ EFAULT
+14 Буруу хаÑг
+$ ENOTBLK
+15 Блок төхөөрөмж шаардагдÑан
+$ EBUSY
+16 Төхөөрөмж завгүй
+$ EEXIST
+17 Файл байна
+$ EXDEV
+18 Төхөөрөмж хоорондын холбооÑ
+$ ENODEV
+19 Үйлдлийг төхөөрөмж дÑмжÑÑгүй
+$ ENOTDIR
+20 Сан биш
+$ EISDIR
+21 Сан мөн
+$ EINVAL
+22 Дагавар өгөгдөл буруу
+$ ENFILE
+23 СиÑтемд Ñ…ÑÑ‚Ñрхий олон нÑÑлттÑй файл байна
+$ EMFILE
+24 Ð¥ÑÑ‚Ñрхий олон нÑÑлттÑй файл байна
+$ ENOTTY
+25 ТөхөөрөмжтÑй тохирохгүй ioctl үйлдÑл
+$ ETXTBSY
+26 ТекÑÑ‚ файл завгүй
+$ EFBIG
+27 Файл Ñ…ÑÑ‚Ñрхий том
+$ ENOSPC
+28 Төхөөрөмж дÑÑÑ€ зай үлдÑÑнгүй
+$ ESPIPE
+29 Хайлт буруу
+$ EROFS
+30 Зөвхөн-уншигдах файлын ÑиÑтем
+$ EMLINK
+31 Ð¥ÑÑ‚Ñрхий олон Ñ…Ð¾Ð»Ð±Ð¾Ð¾Ñ Ð±Ð°Ð¹Ð½Ð°
+$ EPIPE
+32 ЭвдÑрхий хоолой
+$ EDOM
+33 Тоон дагавар өгөгдөл Ñ‚Ð°Ð»Ð±Ð°Ñ€Ð°Ð°Ñ Ð³Ð°Ð´Ð½Ð° байна
+$ ERANGE
+34 Үр дүн Ñ…ÑÑ‚Ñрхий том
+$ EAGAIN, EWOULDBLOCK
+35 Эх Ò¯Ò¯ÑвÑÑ€ түр зуур боломжгүй байна
+$ EINPROGRESS
+36 ҮйлдÑл одоо хийгдÑж байна
+$ EALREADY
+37 ҮйлдÑл аль Ñ…Ñдийн хийгдÑж байна
+$ ENOTSOCK
+38 Сокет Ð±ÑƒÑ Ð·Ò¯Ð¹Ð» дÑÑÑ€ Ñокет үйлдÑл
+$ EDESTADDRREQ
+39 Очих хаÑг шаардагдÑан
+$ EMSGSIZE
+40 Ð—ÑƒÑ€Ð²Ð°Ñ Ð¼ÑдÑÑ Ñ…ÑÑ‚Ñрхий урт
+$ EPROTOTYPE
+41 Сокетийн хувьд протокол буруу төрлийнх байна
+$ ENOPROTOOPT
+42 Протокол байхгүй
+$ EPROTONOSUPPORT
+43 Протокол дÑмжигдÑÑгүй
+$ ESOCKTNOSUPPORT
+44 Сокетийн төрөл дÑмжигдÑÑгүй
+$ EOPNOTSUPP
+45 ҮйлдÑл дÑмжигдÑÑгүй
+$ EPFNOSUPPORT
+46 Протоколын гÑÑ€ бүл дÑмжигдÑÑгүй
+$ EAFNOSUPPORT
+47 ХаÑгийн гÑÑ€ бүлийг протоколын гÑÑ€ бүл дÑмжÑÑгүй
+$ EADDRINUSE
+48 ХаÑг ашиглагдаж байна
+$ EADDRNOTAVAIL
+49 Ð¥Ò¯ÑÑÑн хаÑгийг өгч чадахгүй
+$ ENETDOWN
+50 СүлжÑÑ ÑƒÐ½Ð°Ñан байна
+$ ENETUNREACH
+51 СүлжÑÑнд хүрÑÑ… боломжгүй
+$ ENETRESET
+52 Салгалт хийгдÑÑ…Ñд ÑүлжÑÑ Ñ…Ð¾Ð»Ð±Ð¾Ð»Ñ‚Ñ‹Ð³ унагалаа
+$ ECONNABORTED
+53 Програм Ñ…Ð°Ð½Ð³Ð°Ð¼Ð¶Ð°Ð°Ñ Ð±Ð¾Ð»Ð¶ холболт зогÑлоо
+$ ECONNRESET
+54 Холболтыг харилцагч Ñалгалаа
+$ ENOBUFS
+55 Буфферийн зай байхгүй
+$ EISCONN
+56 Сокет аль Ñ…Ñдийн холбогдÑон
+$ ENOTCONN
+57 Сокет холбогдоогүй
+$ ESHUTDOWN
+58 Сокет унтарÑны дараа илгÑÑж чадахгүй
+$ ETOOMANYREFS
+59 Ð¥ÑÑ‚Ñрхий их хамаарлууд байна: залгаж чадахгүй
+$ ETIMEDOUT
+60 Үйлдлийн хугацаа дууÑÑан
+$ ECONNREFUSED
+61 Холболт Ñ‚Ð¾Ð³Ñ‚Ð¾Ð¾Ñ…Ð¾Ð¾Ñ Ñ‚Ð°Ñ‚Ð³Ð°Ð»Ð·Ð»Ð°Ð°
+$ ELOOP
+62 ТÑмдÑгт холбооÑуудын түвшин Ñ…ÑÑ‚Ñрхий олон байна
+$ ENAMETOOLONG
+63 Файлын нÑÑ€ Ñ…ÑÑ‚Ñрхий урт
+$ EHOSTDOWN
+64 Төв компьютер зогÑÑон байна
+$ EHOSTUNREACH
+65 Төв компьютер Ñ€Ò¯Ò¯ чиглүүлÑлт байхгүй
+$ ENOTEMPTY
+66 Сан хооÑон биш
+$ EPROCLIM
+67 Ð¥ÑÑ‚Ñрхий олон үйлдÑл байна
+$ EUSERS
+68 Ð¥ÑÑ‚Ñрхий олон Ñ…ÑÑ€ÑглÑгч байна
+$ EDQUOT
+69 ДиÑкийн Ñ…Ñзгаар Ñ…ÑмжÑÑ Ñ…ÑÑ‚ÑÑ€ÑÑн
+$ ESTALE
+70 ХуучирÑан NFS файлын жолоо
+$ EREMOTE
+71 Зам Ñ…ÑÑ‚Ñрхий алÑлагдÑан түвшинтÑй байна
+$ EBADRPC
+2 RPC бүтÑц буруу
+$ ERPCMISMATCH
+73 RPC-ийн хувилбар буруу
+$ EPROGUNAVAIL
+74 RPC програм байхгүй
+$ EPROGMISMATCH
+75 Програмын хувилбар буруу
+$ EPROCUNAVAIL
+76 Програмын хувьд процедур буруу
+$ ENOLCK
+77 ТүгжÑÑ Ð±Ð°Ð¹Ñ…Ð³Ò¯Ð¹
+$ ENOSYS
+78 Функц гүйцÑтгÑгдÑÑгүй
+$ EFTYPE
+79 Файлын төрөл ÑÑвÑл Ñ…ÑлбÑршилт тохироогүй
+$ EAUTH
+80 ÐÑвтрүүлÑÑ… алдаа
+$ ENEEDAUTH
+81 ÐÑвтррүүлÑгч Ñ…ÑÑ€ÑгтÑй
+$ EIDRM
+82 Танигч уÑтгагдÑан
+$ ENOMSG
+83 Ð¥Ò¯ÑÑÑн төрлийн Ð·ÑƒÑ€Ð²Ð°Ñ Ð¼ÑдÑÑ Ð±Ð°Ð¹Ñ…Ð³Ò¯Ð¹
+$ EOVERFLOW
+84 Утга нь өгөгдлийн төрөлд хадгалагдаж болохооргүй Ñ…ÑÑ‚Ñрхий том байна
+$ ECANCELED
+85 ҮйлдÑл зогÑоогдÑон
+$ EILSEQ
+86 Байтын дараалал буруу
+$ ENOATTR
+87 Ðтрибут олдÑонгүй
+$ EDOOFUS
+88 Програмчлалын алдаа
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 ЗогÑоох (Hangup)
+$ SIGINT
+2 ТаÑалдал
+$ SIGQUIT
+3 Гарах
+$ SIGILL
+4 Буруу заавар
+$ SIGTRAP
+5 Мөр/BPT занга
+$ SIGABRT
+6 ТаÑлан зогÑоох занга
+$ SIGEMT
+7 EMT занга
+$ SIGFPE
+8 Хөвөгч цÑгийн онцгой алдаа
+$ SIGKILL
+9 ХөнөөÑөн
+$ SIGBUS
+10 Шугамын алдаа
+$ SIGSEGV
+11 Сегментийн гÑмтÑл
+$ SIGSYS
+12 СиÑтемийн буруу дуудлага
+$ SIGPIPE
+13 ЭвдÑрхий хоолой
+$ SIGALRM
+14 СÑрүүлÑгт цаг
+$ SIGTERM
+15 ТөгÑÑөн
+$ SIGURG
+16 Яаралтай I/O нөхцөл
+$ SIGSTOP
+17 Түр зогÑÑон (дохио)
+$ SIGTSTP
+18 Түр зогÑÑон
+$ SIGCONT
+19 ҮргÑлжилÑÑн
+$ SIGCHLD
+20 ХүүхÑд процеÑÑ Ð³Ð°Ñ€Ñан
+$ SIGTTIN
+21 ЗогÑÑон (tty оролт)
+$ SIGTTOU
+22 ЗогÑÑон (tty гаралт)
+$ SIGIO
+23 I/O боломжтой
+$ SIGXCPU
+24 CPU-ийн хугацааны Ñ…Ñзгаар Ñ…ÑÑ‚ÑÑ€ÑÑн
+$ SIGXFSZ
+25 Файлын Ñ…ÑмжÑÑний Ñ…Ñзгаар Ñ…ÑÑ‚ÑÑ€ÑÑн
+$ SIGVTALRM
+26 Виртуал цаг Ñ…Ñмжигчийн хугацаа дууÑÑан
+$ SIGPROF
+27 Профил хийх цаг Ñ…Ñмжигчийн хугацаа дууÑÑан
+$ SIGWINCH
+28 Цонхны Ñ…ÑмжÑÑний өөрчлөлт
+$ SIGINFO
+29 ÐœÑдÑÑллийн Ñ…Ò¯ÑÑлт
+$ SIGUSR1
+30 Ð¥ÑÑ€ÑглÑгчийн тодорхойлÑон дохио 1
+$ SIGUSR2
+31 Ð¥ÑÑ€ÑглÑгчийн тодорхойлÑон дохио 2
diff --git a/lib/libc/nls/nl_NL.ISO8859-1.msg b/lib/libc/nls/nl_NL.ISO8859-1.msg
new file mode 100644
index 0000000..47103d4
--- /dev/null
+++ b/lib/libc/nls/nl_NL.ISO8859-1.msg
@@ -0,0 +1,267 @@
+$ $FreeBSD$
+$
+$ Message catalog for nl_NL.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Bewerking niet toegestaan
+$ ENOENT
+2 Bestand of map niet gevonden
+$ ESRCH
+3 Taak bestaat niet
+$ EINTR
+4 Onderbroken systeemaanroep
+$ EIO
+5 Invoer/uitvoer fout
+$ ENXIO
+6 Apparaat niet geconfigureerd
+$ E2BIG
+7 Argumentenlijst is te lang
+$ ENOEXEC
+8 Programma kan niet worden uitgevoerd
+$ EBADF
+9 Ongeldige bestandsverwijzing
+$ ECHILD
+10 Geen kindprocessen
+$ EDEADLK
+11 Een deadlock is vermeden
+$ ENOMEM
+12 Kan geen geheugen meer verkrijgen
+$ EACCES
+13 Toegang geweigerd
+$ EFAULT
+14 Ongeldig adres
+$ ENOTBLK
+15 Een per blok adresseerbaar apparaat is vereist
+$ EBUSY
+16 Apparaat is bezig
+$ EEXIST
+17 Bestand bestaat reeds
+$ EXDEV
+18 Verwijzing tussen bestanden op verschillende bestandssystemen
+$ ENODEV
+19 Bewerking wordt niet ondersteund door dit apparaat
+$ ENOTDIR
+20 Dit is geen map
+$ EISDIR
+21 Dit is een map
+$ EINVAL
+22 Ongeldig argument
+$ ENFILE
+23 Te veel open bestanden in het systeem
+$ EMFILE
+24 Te veel open bestanden
+$ ENOTTY
+25 ioctl niet van toepassing op dit apparaat
+$ ETXTBSY
+26 Programmabestand is bezig
+$ EFBIG
+27 Bestand is te groot
+$ ENOSPC
+28 Geen ruimte meer op dit apparaat
+$ ESPIPE
+29 Onuitvoerbare zoekopdracht
+$ EROFS
+30 Van dit bestandssysteem kan alleen worden gelezen
+$ EMLINK
+31 Te veel bestandsverwijzingen
+$ EPIPE
+32 Gebroken pijp
+$ EDOM
+33 Numeriek argument valt buiten domein
+$ ERANGE
+34 Resultaat te groot of te klein
+$ EAGAIN, EWOULDBLOCK
+35 Middel tijdelijk onbeschikbaar
+$ EINPROGRESS
+36 Bewerking in gang gezet
+$ EALREADY
+37 Bewerking is al in gang gezet
+$ ENOTSOCK
+38 Voor deze bewerking is een contactpunt vereist
+$ EDESTADDRREQ
+39 Een bestemmingsadres is vereist
+$ EMSGSIZE
+40 Te grote bericht
+$ EPROTOTYPE
+41 Protocol past niet bij dit contactpunt
+$ ENOPROTOOPT
+42 Protocol is niet beschikbaar
+$ EPROTONOSUPPORT
+43 Protocol is niet ondersteund
+$ ESOCKTNOSUPPORT
+44 Dit soort contactpunt is niet ondersteund
+$ EOPNOTSUPP
+45 Bewerking niet ondersteund
+$ EPFNOSUPPORT
+46 Protocolfamilie niet ondersteund
+$ EAFNOSUPPORT
+47 Adressenfamilie niet ondersteund door protocolfamilie
+$ EADDRINUSE
+48 Adres is al in gebruik
+$ EADDRNOTAVAIL
+49 Het gevraagde adres kan niet worden toegekend
+$ ENETDOWN
+50 Netwerk is plat
+$ ENETUNREACH
+51 Netwerk is onbereikbaar
+$ ENETRESET
+52 Netwerk onderbrak verbinding tijdens herstart
+$ ECONNABORTED
+53 Verbroken verbinding veroorzaakt door software
+$ ECONNRESET
+54 Verbinding werd aan de andere kant verbroken
+$ ENOBUFS
+55 Geen bufferruimte meer beschikbaar
+$ EISCONN
+56 Dit contactpunt is al verbonden
+$ ENOTCONN
+57 Contactpunt is niet verbonden
+$ ESHUTDOWN
+58 Een afgesloten contactpunt kan geen gegevens meer verzenden
+$ ETOOMANYREFS
+59 Te veel verwijzingen: splitsen niet mogelijk
+$ ETIMEDOUT
+60 Verbinding te lang niet mogelijk
+$ ECONNREFUSED
+61 Verbinding geweigerd
+$ ELOOP
+62 Te veel niveaus van symbolische verwijzingen
+$ ENAMETOOLONG
+63 Bestandsnaam te lang
+$ EHOSTDOWN
+64 Bestemming niet actief
+$ EHOSTUNREACH
+65 Bestemming niet bereikbaar
+$ ENOTEMPTY
+66 Directory is niet leeg
+$ EPROCLIM
+67 Te veel taken
+$ EUSERS
+68 Te veel gebruikers
+$ EDQUOT
+69 Schijfquota overschreden
+$ ESTALE
+70 Verlopen NFS-bestandsverwijzing
+$ EREMOTE
+71 Te veel verwijzingen op afstand in dit pad
+$ EBADRPC
+72 RPC-argumentstructuur is incorrect
+$ ERPCMISMATCH
+73 RPC-versie is verkeerd
+$ EPROGUNAVAIL
+74 RPC-programma niet beschikbaar
+$ EPROGMISMATCH
+75 Programmaversie is verkeerd
+$ EPROCUNAVAIL
+76 Taak kan niet door dit programma worden uitgevoerd
+$ ENOLCK
+77 Geen sloten beschikbaar
+$ ENOSYS
+78 Deze systeemfunctie is niet geimplementeerd
+$ EFTYPE
+79 Bestandsformaat niet van toepassing
+$ EAUTH
+80 Aanmeldingsfout
+$ ENEEDAUTH
+81 Aanmeldingsprocedure benodigd
+$ EIDRM
+82 De aanwijzer is verwijderd
+$ ENOMSG
+83 Geen bericht van het gewenste type
+$ EOVERFLOW
+84 Waarde te groot om te bewaren in gegevenstype
+$ EILSEQ
+85 Ongeldige bytereeks
+$ ENOTSUP
+86 Niet ondersteund
+$ ECANCELED
+87 Bewerking geannuleerd
+$ EBADMSG
+88 Verkeerd of defect bericht
+$ ENODATA
+89 Geen bericht beschikbaar
+$ ENOSR
+90 Geen STREAM-voorraad
+$ ENOSTR
+91 Dit is geen STREAM
+$ ETIME
+92 STREAM-ioctl verlopen
+$ ENOATTR
+93 Attribuut niet gevonden
+$ EMULTIHOP
+94 Multihopverzoek
+$ ENOLINK
+95 Verbinding werd verstoord
+$ EPROTO
+96 Protocolfout
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Opgehangen
+$ SIGINT
+2 Onderbroken
+$ SIGQUIT
+3 Opgegeven
+$ SIGILL
+4 Verboden instructie
+$ SIGTRAP
+5 Spoor/BPT-val
+$ SIGABRT
+6 Abort-val
+$ SIGEMT
+7 EMT-val
+$ SIGFPE
+8 Drijvende kommafout
+$ SIGKILL
+9 Gedood
+$ SIGBUS
+10 Busfout
+$ SIGSEGV
+11 Segmentatiefout
+$ SIGSYS
+12 Verkeerde systeemaanroep
+$ SIGPIPE
+13 Gebroken pijp
+$ SIGALRM
+14 Wekker
+$ SIGTERM
+15 Beeindigd
+$ SIGURG
+16 Dringende I/O opgemerkt
+$ SIGSTOP
+17 Gestopt (signaal)
+$ SIGTSTP
+18 Gestopt
+$ SIGCONT
+19 Voortgezet
+$ SIGCHLD
+20 Kindproces beeindigd
+$ SIGTTIN
+21 Gestopt (TTY-invoer)
+$ SIGTTOU
+22 Gestopt (TTY-uitvoer)
+$ SIGIO
+23 I/O mogelijk
+$ SIGXCPU
+24 Te veel CPU-tijd verbruikt
+$ SIGXFSZ
+25 Maximale bestandsgrootte overschreden
+$ SIGVTALRM
+26 Virtuele wekker
+$ SIGPROF
+27 Profiling-wekker
+$ SIGWINCH
+28 Venstergrootte veranderd
+$ SIGINFO
+29 Informatieverzoek
+$ SIGUSR1
+30 Gebruikersignaal 1
+$ SIGUSR2
+31 Gebruikersignaal 2
+$ SIGPWR
+32 Stroomuitval/stroominschakeling
diff --git a/lib/libc/nls/no_NO.ISO8859-1.msg b/lib/libc/nls/no_NO.ISO8859-1.msg
new file mode 100644
index 0000000..2598f4d
--- /dev/null
+++ b/lib/libc/nls/no_NO.ISO8859-1.msg
@@ -0,0 +1,231 @@
+$ $FreeBSD$
+$
+$ Message catalog for no_NO.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operasjonen er ikke tillatt
+$ ENOENT
+2 Filen eller katalogen finnes ikke
+$ ESRCH
+3 Prosessen finnes ikke
+$ EINTR
+4 Avbrudt systemkall
+$ EIO
+5 I/O feil
+$ ENXIO
+6 Enheten er ikke konfigurert
+$ E2BIG
+7 Argumentlisten er for lang
+$ ENOEXEC
+8 Ukjent kjørbart format
+$ EBADF
+9 Ugyldig fildeskriptor
+$ ECHILD
+10 Ingen barneprosess
+$ EDEADLK
+11 Vranglås unngått
+$ ENOMEM
+12 Kan ikke allokere nok minne
+$ EACCES
+13 Ingen adgang
+$ EFAULT
+14 Ugyldig adresse
+$ ENOTBLK
+15 Blokk-enhet påkrevd
+$ EBUSY
+16 Enheten er opptatt
+$ EEXIST
+17 Filen finnes
+$ EXDEV
+18 Link mellom forskjellige enheter
+$ ENODEV
+19 Operasjonen er ikke støttet av enheten
+$ ENOTDIR
+20 Ikke en katalog
+$ EISDIR
+21 Er en katalog
+$ EINVAL
+22 Ugyldig argument
+$ ENFILE
+23 For mange åpne filer i systemet
+$ EMFILE
+24 For mange åpne filer
+$ ENOTTY
+25 Ugyldig ioctl for enheten
+$ ETXTBSY
+26 Kjørbar fil i bruk
+$ EFBIG
+27 Filen er for stor
+$ ENOSPC
+28 Ingen ledig plass på enheten
+$ ESPIPE
+29 Ugyldig seek operasjon
+$ EROFS
+30 Filsystemet er skrivebeskyttet
+$ EMLINK
+31 For mange linker
+$ EPIPE
+32 Brudt pipe
+$ EDOM
+33 Numerisk argument utenfor arbeidsområdet
+$ ERANGE
+34 Resultatet er for stort
+$ EAGAIN, EWOULDBLOCK
+35 Ressurs midlertidig utilgjengelig
+$ EINPROGRESS
+36 Operasjonen er nå i gang
+$ EALREADY
+37 Operasjonen er allerede i gang
+$ ENOTSOCK
+38 Deskriptoren er ikke en socket
+$ EDESTADDRREQ
+39 Mottakeradresse er påkrevd
+$ EMSGSIZE
+40 Meldingen er for lang
+$ EPROTOTYPE
+41 Ugyldig protokolltype for denne socketen
+$ ENOPROTOOPT
+42 Protokollen er ikke tilgjengelig
+$ EPROTONOSUPPORT
+43 Protokollen er ikke støttet
+$ ESOCKTNOSUPPORT
+44 Socket-typen er ikke støttet
+$ EOPNOTSUPP
+45 Operasjonen er ikke støttet
+$ EPFNOSUPPORT
+46 Protokollfamilien er ikke støttet
+$ EAFNOSUPPORT
+47 Adressetypen er ikke støttet av protokollfamilien
+$ EADDRINUSE
+48 Adressen er allerede i bruk
+$ EADDRNOTAVAIL
+49 Kan ikke bruke den ønskede adressen
+$ ENETDOWN
+50 Nettverket er nede
+$ ENETUNREACH
+51 Nettverket er utilgjengelig
+$ ENETRESET
+52 Nettverket kuttet forbindelsen ved reset
+$ ECONNABORTED
+53 Programvaren forårsaket brudd av forbindelsen
+$ ECONNRESET
+54 Forbindelsen avbrudt av korrespondenten
+$ ENOBUFS
+55 Buffer-plass ikke tilgjengelig
+$ EISCONN
+56 Socketen er allerede forbundet
+$ ENOTCONN
+57 Socketen er ikke forbundet
+$ ESHUTDOWN
+58 Kan ikke sende etter at socketen er tatt ned
+$ ETOOMANYREFS
+59 For mange referanser: kan ikke slå dem sammen
+$ ETIMEDOUT
+60 Tiden til forbindelsen utløp
+$ ECONNREFUSED
+61 Forbindelse nektet
+$ ELOOP
+62 For mange nivåer med symbolske linker
+$ ENAMETOOLONG
+63 Filnavnet er for langt
+$ EHOSTDOWN
+64 Maskinen er nede
+$ EHOSTUNREACH
+65 Ingen rute til maskinen
+$ ENOTEMPTY
+66 Katalogen er ikke tom
+$ EPROCLIM
+67 For mange prosesser
+$ EUSERS
+68 For mange brukere
+$ EDQUOT
+69 Diskkvote overskredet
+$ ESTALE
+70 Fastlåst NFS fildeskriptor
+$ EREMOTE
+71 For mange nivåer med remote i stien
+$ EBADRPC
+72 Ugyldig RPC struktur
+$ ERPCMISMATCH
+73 Feil RPC versjon
+$ EPROGUNAVAIL
+74 RPC program ikke tilgjengelig
+$ EPROGMISMATCH
+75 Feil programversjon
+$ EPROCUNAVAIL
+76 Prosedyren finnes ikke i programmet
+$ ENOLCK
+77 Ingen låsing tilgjengelig
+$ ENOSYS
+78 Funksjonen er ikke implementert
+$ EFTYPE
+79 Ugyldig filtype eller format
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Hangup
+$ SIGINT
+2 Avbrudd
+$ SIGQUIT
+3 Avslutt
+$ SIGILL
+4 Ugyldig instruksjon
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Flyttallsfeil
+$ SIGKILL
+9 Drept
+$ SIGBUS
+10 Buss feil
+$ SIGSEGV
+11 Segmenteringsfeil
+$ SIGSYS
+12 Ugyldig systemkall
+$ SIGPIPE
+13 Brudt pipe
+$ SIGALRM
+14 Alarmklokke
+$ SIGTERM
+15 Terminert
+$ SIGURG
+16 Urgent I/O condition
+$ SIGSTOP
+17 Stoppet (signal)
+$ SIGTSTP
+18 Stoppet
+$ SIGCONT
+19 Fortsetter
+$ SIGCHLD
+20 Barn avsluttet
+$ SIGTTIN
+21 Stoppet (tty input)
+$ SIGTTOU
+22 Stoppet (tty output)
+$ SIGIO
+23 I/O mulig
+$ SIGXCPU
+24 CPU-tid overskredet
+$ SIGXFSZ
+25 Maksimal filstørrelse overskredet
+$ SIGVTALRM
+26 Virtuell timer utløpt
+$ SIGPROF
+27 Profileringstimer utløpt
+$ SIGWINCH
+28 Vindustørrelse endres
+$ SIGINFO
+29 Informasjonsforespørsel
+$ SIGUSR1
+30 Brukerdefinert signal 1
+$ SIGUSR2
+31 Brukerdefinert signal 2
diff --git a/lib/libc/nls/pt_BR.ISO8859-1.msg b/lib/libc/nls/pt_BR.ISO8859-1.msg
new file mode 100644
index 0000000..fb1c100
--- /dev/null
+++ b/lib/libc/nls/pt_BR.ISO8859-1.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for pt_BR.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operação não permitida
+$ ENOENT
+2 Nenhum arquivo ou diretório encontrado
+$ ESRCH
+3 Nenhum processo encontrado
+$ EINTR
+4 Chamada de sistema interrompida
+$ EIO
+5 Erro de entrada/saída
+$ ENXIO
+6 Dispositivo não configurado
+$ E2BIG
+7 Lista de argumentos muito grande
+$ ENOEXEC
+8 Erro no formato de execução
+$ EBADF
+9 Erro no descritor de arquivo
+$ ECHILD
+10 Nenhum processo filho
+$ EDEADLK
+11 Bloqueio de recurso evitado
+$ ENOMEM
+12 Impossível alocar memória
+$ EACCES
+13 Permissão negada
+$ EFAULT
+14 Endereço errado
+$ ENOTBLK
+15 Dispositivo de bloco requerido
+$ EBUSY
+16 Dispositivo ocupado
+$ EEXIST
+17 Arquivo existe
+$ EXDEV
+18 Ligação entre dispositivos
+$ ENODEV
+19 Operação não suportada pelo dispositivo
+$ ENOTDIR
+20 Não é um diretório
+$ EISDIR
+21 É um diretório
+$ EINVAL
+22 Argumento inválido
+$ ENFILE
+23 Muitos arquivos abertos no sistema
+$ EMFILE
+24 Muitos arquivos abertos no sistema
+$ ENOTTY
+25 ioctl inapropriado para o dispositivo
+$ ETXTBSY
+26 Arquivo texto sendo utilizado
+$ EFBIG
+27 Arquivo muito grande
+$ ENOSPC
+28 Sem espaço no dispositivo
+$ ESPIPE
+29 seek ilegal
+$ EROFS
+30 Sistema de arquivos apenas para leitura
+$ EMLINK
+31 Muitos links
+$ EPIPE
+32 pipe quebrado
+$ EDOM
+33 Argumento numérico fora do domínio
+$ ERANGE
+34 Resultado muito grande
+$ EAGAIN, EWOULDBLOCK
+35 Recurso temporariamente indisponível
+$ EINPROGRESS
+36 Operação em progresso agora
+$ EALREADY
+37 Operação em progresso pronta
+$ ENOTSOCK
+38 Operação de socket em um não-socket
+$ EDESTADDRREQ
+39 Endereço de destino requerido
+$ EMSGSIZE
+40 Mensagem muito grande
+$ EPROTOTYPE
+41 Tipo de protocolo errado para socket
+$ ENOPROTOOPT
+42 Protocolo não disponível
+$ EPROTONOSUPPORT
+43 Protocolo não suportado
+$ ESOCKTNOSUPPORT
+44 Tipo de socket não suportado
+$ EOPNOTSUPP
+45 Operação não permitida
+$ EPFNOSUPPORT
+46 Família de protocolo não suportada
+$ EAFNOSUPPORT
+47 Família de endereços não suportada pela família de protocolos
+$ EADDRINUSE
+48 Endereço já está em uso
+$ EADDRNOTAVAIL
+49 Impossível obter endereço solicitado
+$ ENETDOWN
+50 Rede está parada
+$ ENETUNREACH
+51 Rede está inalcançável
+$ ENETRESET
+52 Conexão de rede perdida durante reset
+$ ECONNABORTED
+53 Conexão abortada por software
+$ ECONNRESET
+54 Conexão reiniciada pelo outro ponto
+$ ENOBUFS
+55 Sem espaço de buffer disponível
+$ EISCONN
+56 Socket já está conectado
+$ ENOTCONN
+57 Socket não está conectado
+$ ESHUTDOWN
+58 Impossível enviar depois que o socket foi finalizado
+$ ETOOMANYREFS
+59 Muitas referências: impossível ligar
+$ ETIMEDOUT
+60 Tempo de operação expirou
+$ ECONNREFUSED
+61 Conexão recusada
+$ ELOOP
+62 Muitos níveis de links simbólicos
+$ ENAMETOOLONG
+63 Nome de arquivo muito grande
+$ EHOSTDOWN
+64 Host está desligado
+$ EHOSTUNREACH
+65 Sem rota para o host
+$ ENOTEMPTY
+66 Diretório não está vazio
+$ EPROCLIM
+67 Muitos processos
+$ EUSERS
+68 Muitos usuários
+$ EDQUOT
+69 Quota de disco excedida
+$ ESTALE
+70 Manipulador de arquivo NFS velho
+$ EREMOTE
+71 Muitos níveis no caminho remoto
+$ EBADRPC
+72 Estrutura RPC incorreta
+$ ERPCMISMATCH
+73 Versão RPC incorreta
+$ EPROGUNAVAIL
+74 Programa RPC indisponível
+$ EPROGMISMATCH
+75 Versão do programa incorreta
+$ EPROCUNAVAIL
+76 Procedimento incorreto para o programa
+$ ENOLCK
+77 Nenhum lock disponível
+$ ENOSYS
+78 Função não implementada
+$ EFTYPE
+79 Tipo de arquivo ou formato inapropriados
+$ EAUTH
+80 Erro de autenticação
+$ ENEEDAUTH
+81 Necessidade de autenticador
+$ EIDRM
+82 Identificador removido
+$ ENOMSG
+83 Nenhuma mensagem do tipo desejado
+$ EOVERFLOW
+84 Valor muito grande para ser armazenado neste tipo de dado
+$ ECANCELED
+85 Operação cancelada
+$ EILSEQ
+86 Sequência de bytes ilegal
+$ ENOATTR
+87 Atributo não encontrado
+$ EDOOFUS
+88 Erro de programação
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fim da linha (Hangup)
+$ SIGINT
+2 Interrupção
+$ SIGQUIT
+3 Saída
+$ SIGILL
+4 Instrução ilegal
+$ SIGTRAP
+5 Trap de Trace/BPT
+$ SIGABRT
+6 Abortar trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Exceção de ponto flutuante
+$ SIGKILL
+9 Morreu
+$ SIGBUS
+10 Erro de barramento
+$ SIGSEGV
+11 Falha de segmentação
+$ SIGSYS
+12 Chamada de sistema incorreta
+$ SIGPIPE
+13 Pipe incorreto
+$ SIGALRM
+14 Alarme do relógio
+$ SIGTERM
+15 Terminado
+$ SIGURG
+16 Condição urgente de E/S
+$ SIGSTOP
+17 Suspendido (sinal)
+$ SIGTSTP
+18 Suspendido
+$ SIGCONT
+19 Continuado
+$ SIGCHLD
+20 Filho saiu
+$ SIGTTIN
+21 Parado (entrada de tty)
+$ SIGTTOU
+22 Parado (saída de tty)
+$ SIGIO
+23 E/S possível
+$ SIGXCPU
+24 Limite de tempo de CPU excedido
+$ SIGXFSZ
+25 Tamanho de arquivo excedido
+$ SIGVTALRM
+26 Temporizador virtual expirou
+$ SIGPROF
+27 Temporizador de profiling expirou
+$ SIGWINCH
+28 Mudança no tamanho de janela
+$ SIGINFO
+29 Requisição de informação
+$ SIGUSR1
+30 Sinal 1 definido pelo usuário
+$ SIGUSR2
+31 Sinal 2 definido pelo usuário
diff --git a/lib/libc/nls/ru_RU.KOI8-R.msg b/lib/libc/nls/ru_RU.KOI8-R.msg
index 55233b9..431bc27 100644
--- a/lib/libc/nls/ru_RU.KOI8-R.msg
+++ b/lib/libc/nls/ru_RU.KOI8-R.msg
@@ -114,7 +114,7 @@ $ ENETRESET
$ ECONNABORTED
53 ðÒÏÇÒÁÍÍÁ ×ÙÚ×ÁÌÁ Á×ÁÒÉÊÎÏÅ ÐÒÅËÒÁÝÅÎÉÅ ÐÏÄËÌÀÞÅÎÉÑ
$ ECONNRESET
-54 ðÏÄËÌÀÞÅÎÉÅ ÓÂÒÏÛÅÎÏ ÐÒÏÔÉ×ÏÐÏÌÏÖÎÏÊ ÓÔÒÏÎÏÊ
+54 ðÏÄËÌÀÞÅÎÉÅ ÓÂÒÏÛÅÎÏ ÐÒÏÔÉ×ÏÐÏÌÏÖÎÏÊ ÓÔÏÒÏÎÏÊ
$ ENOBUFS
55 îÅ ÏÓÔÁÌÏÓØ ÍÅÓÔÁ ÐÏÄ ÂÕÆÅÒ
$ EISCONN
@@ -146,7 +146,7 @@ $ EUSERS
$ EDQUOT
69 ðÒÅ×ÚÏÊÄÅÎÁ ÄÉÓËÏ×ÁÑ Ë×ÏÔÁ
$ ESTALE
-70 õÓÔÁÒÅ×ÛÉÊ ÄÅËÒÉÐÔÏÒ ÆÁÊÌÁ NFS
+70 õÓÔÁÒÅ×ÛÉÊ ÄÅÓËÒÉÐÔÏÒ ÆÁÊÌÁ NFS
$ EREMOTE
71 óÌÉÛËÏÍ ÍÎÏÇÏ ÄÉÓÔÁÎÃÉÏÎÎÙÈ ÐÅÒÅÈÏÄÏ× × ÐÕÔÉ
$ EBADRPC
@@ -180,9 +180,9 @@ $ ECANCELED
$ EILSEQ
86 îÅÄÏÐÕÓÔÉÍÁÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÓÔØ ÂÁÊÔÏ×
$ ENOATTR
-87 áÔÔÒÉÂÕÔ ÎÅ ÎÁÊÄÅÎ
+87 áÔÒÉÂÕÔ ÎÅ ÎÁÊÄÅÎ
$ EDOOFUS
-88 ïÛÉÂËÁ ÐÒÏÇÒÁÍÉÒÏ×ÁÎÉÑ
+88 ïÛÉÂËÁ ÐÒÏÇÒÁÍÍÉÒÏ×ÁÎÉÑ
$
$ strsignal() support catalog
$
diff --git a/lib/libc/nls/sk_SK.ISO8859-2.msg b/lib/libc/nls/sk_SK.ISO8859-2.msg
new file mode 100644
index 0000000..8efa17d
--- /dev/null
+++ b/lib/libc/nls/sk_SK.ISO8859-2.msg
@@ -0,0 +1,267 @@
+$ $FreeBSD$
+$
+$ Message catalog for sk_SK.ISO8859-2 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operácia nie je povolená
+$ ENOENT
+2 Neexistujúci súbor alebo adresár
+$ ESRCH
+3 Proces neexistuje
+$ EINTR
+4 Systémové volanie preru¹ené
+$ EIO
+5 Chyba vstupu/výstupu
+$ ENXIO
+6 Zariadenie nie je nakonfigurované
+$ E2BIG
+7 Príli¹ dlhý zoznam argumentov
+$ ENOEXEC
+8 Chybný formát spusteného súboru
+$ EBADF
+9 Chybný deskriptor súboru
+$ ECHILD
+10 Neexistuje ¾iaden potomok procesu
+$ EDEADLK
+11 Bolo zabránené zablokovaniu prostriedku
+$ ENOMEM
+12 Nie je mo¾né prideli» pamä»
+$ EACCES
+13 Prístup odmietnutý
+$ EFAULT
+14 Chybná adresa
+$ ENOTBLK
+15 Vy¾adované blokové zariadenie
+$ EBUSY
+16 Zariadenie je pou¾ívané
+$ EEXIST
+17 Súbor existuje
+$ EXDEV
+18 Odkaz medzi zariadeniami
+$ ENODEV
+19 Operácia nie je zariadením podporovaná
+$ ENOTDIR
+20 Nie je adresár
+$ EISDIR
+21 Je adresár
+$ EINVAL
+22 Chybný argument
+$ ENFILE
+23 Priveµa otvorených súborov v systéme
+$ EMFILE
+24 Priveµa otvorených súborov
+$ ENOTTY
+25 Nevhodné ioctl pre dané zariadenie
+$ ETXTBSY
+26 Textový súbor je pou¾ívaný
+$ EFBIG
+27 Súbor je príli¹ veµký
+$ ENOSPC
+28 Na zariadení nie je voµné miesto
+$ ESPIPE
+29 Neprípustné nastavenie pozície
+$ EROFS
+30 Súborový systém je len na èítanie
+$ EMLINK
+31 Priveµa odkazov
+$ EPIPE
+32 Preru¹ená rúra
+$ EDOM
+33 Èíselný argument mimo definièný obor
+$ ERANGE
+34 Výsledok príli¹ veµký alebo príli¹ malý
+$ EAGAIN, EWOULDBLOCK
+35 Zdroj je doèasne nedostupný
+$ EINPROGRESS
+36 Operácia práve prebieha
+$ EALREADY
+37 Operácia u¾ prebieha
+$ ENOTSOCK
+38 Socketová operácia na objekte, ktorý nie je socket
+$ EDESTADDRREQ
+39 Vy¾adovaná cieµová adresa
+$ EMSGSIZE
+40 Príli¹ dlhá správa
+$ EPROTOTYPE
+41 Protokol nie je socketom podporovaný
+$ ENOPROTOOPT
+42 Protokol nie je k dispozícii
+$ EPROTONOSUPPORT
+43 Protokol nie je podporovaný
+$ ESOCKTNOSUPPORT
+44 Typ socketu nie je podporovaný
+$ EOPNOTSUPP
+45 Operácia nie je podporovaná
+$ EPFNOSUPPORT
+46 Rodina protokolov nie je podporovaná
+$ EAFNOSUPPORT
+47 Rodina adries nie je podporovaná rodinou protokolov
+$ EADDRINUSE
+48 Adresa je u¾ pou¾ívaná
+$ EADDRNOTAVAIL
+49 Nie je mo¾né prideli» po¾adovanú adresu
+$ ENETDOWN
+50 Sie» je nefunkèná
+$ ENETUNREACH
+51 Sie» je nedostupná
+$ ENETRESET
+52 Sie» zru¹ila spojenie po resete
+$ ECONNABORTED
+53 Program spôsobil ukonèenie spojenia
+$ ECONNRESET
+54 Spojenie zru¹ené druhou stranou
+$ ENOBUFS
+55 Vyrovnávacia pamä» nie je k dispozícii
+$ EISCONN
+56 Socket je u¾ pripojený
+$ ENOTCONN
+57 Socket nie je pripojený
+$ ESHUTDOWN
+58 Nie je mo¾né posiela» po uzavretí socketu
+$ ETOOMANYREFS
+59 Príli¹ mnoho odkazov: nie je mo¾né spoji»
+$ ETIMEDOUT
+60 Èasový limit pre spojenie vypr¹al
+$ ECONNREFUSED
+61 Spojenie odmietnuté
+$ ELOOP
+62 Priveµa úrovní symbolických odkazov
+$ ENAMETOOLONG
+63 Meno súboru príli¹ dlhé
+$ EHOSTDOWN
+64 Vzdialený uzol je odpojený
+$ EHOSTUNREACH
+65 Neexistuje cesta k vzdialenému uzlu
+$ ENOTEMPTY
+66 Adresár nie je prázdny
+$ EPROCLIM
+67 Priveµa procesov
+$ EUSERS
+68 Priveµa pou¾ívateµov
+$ EDQUOT
+69 Disková kvóta prekroèená
+$ ESTALE
+70 Zastaralý NFS súborový ukazateµ
+$ EREMOTE
+71 Priveµa úrovní vzdialeného v ceste
+$ EBADRPC
+72 RPC ¹truktúra je chybná
+$ ERPCMISMATCH
+73 Chybná verzia RPC
+$ EPROGUNAVAIL
+74 RPC program nie je k dispozícii
+$ EPROGMISMATCH
+75 Chybná verzia RPC programu
+$ EPROCUNAVAIL
+76 Chybná RPC procedúra pre program
+$ ENOLCK
+77 Zámky nie sú k dispozícii
+$ ENOSYS
+78 Funkcia nie je implementovaná
+$ EFTYPE
+79 Nevhodný typ alebo formát súboru
+$ EAUTH
+80 Overenie práv neúspe¹né
+$ ENEEDAUTH
+81 Vy¾adovaný overovací objekt
+$ EIDRM
+82 Identifikátor odstránený
+$ ENOMSG
+83 Neexistuje správa ¾elaného typu
+$ EOVERFLOW
+84 Hodnota je pre daný dátový typ priveµká
+$ EILSEQ
+85 Neprípustná postupnos» bajtov
+$ ENOTSUP
+86 Nie je podporované
+$ ECANCELED
+87 Operácia zru¹ená
+$ EBADMSG
+88 Chybná alebo poru¹ená správa
+$ ENODATA
+89 ®iadna správa nie je k dispozícii
+$ ENOSR
+90 ®iadne STREAM zdroje
+$ ENOSTR
+91 Nie je STREAM
+$ ETIME
+92 Èasový limit pre STREAM ioctl vypr¹al
+$ ENOATTR
+93 Atribút nenájdený
+$ EMULTIHOP
+94 Pokus o spojenie cez viacero uzlov
+$ ENOLINK
+95 Odkaz bol pretrhnutý
+$ EPROTO
+96 Chyba protokolu
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Terminál odpojený
+$ SIGINT
+2 Preru¹enie
+$ SIGQUIT
+3 Koniec
+$ SIGILL
+4 Chybná in¹trukcia
+$ SIGTRAP
+5 Trasovacia/ladiaca in¹trukcia
+$ SIGABRT
+6 Násilné ukonèenie
+$ SIGEMT
+7 Emulovaná in¹trukcia
+$ SIGFPE
+8 Výnimka pohyblivej rádovej èiarky
+$ SIGKILL
+9 Zabité
+$ SIGBUS
+10 Chyba na zbernici
+$ SIGSEGV
+11 Chyba segmentácie
+$ SIGSYS
+12 Chybné systémové volanie
+$ SIGPIPE
+13 Preru¹ená rúra
+$ SIGALRM
+14 Budík
+$ SIGTERM
+15 Ukonèené
+$ SIGURG
+16 Naliehavý vstupný/výstupný stav
+$ SIGSTOP
+17 Pozastavené (signál)
+$ SIGTSTP
+18 Pozastavené
+$ SIGCONT
+19 Pokraèovanie
+$ SIGCHLD
+20 Potomok procesu ukonèený
+$ SIGTTIN
+21 Pozastavené (terminálový vstup)
+$ SIGTTOU
+22 Pozastavené (terminálový výstup)
+$ SIGIO
+23 Vstup/výstup mo¾ný
+$ SIGXCPU
+24 Prekroèený èasový limit pre procesor
+$ SIGXFSZ
+25 Prekroèený limit veµkosti súboru
+$ SIGVTALRM
+26 Vypr¹al virtuálny èasovaè
+$ SIGPROF
+27 Vypr¹al profilovací èasovaè
+$ SIGWINCH
+28 Veµkos» okna zmenená
+$ SIGINFO
+29 ®iados» o informáciu
+$ SIGUSR1
+30 Pou¾ívateµom definovaný signál 1
+$ SIGUSR2
+31 Pou¾ívateµom definovaný signál 2
+$ SIGPWR
+32 Zlyhanie/opakované spustenie napájania
diff --git a/lib/libc/nls/sv_SE.ISO8859-1.msg b/lib/libc/nls/sv_SE.ISO8859-1.msg
new file mode 100644
index 0000000..13cdd23
--- /dev/null
+++ b/lib/libc/nls/sv_SE.ISO8859-1.msg
@@ -0,0 +1,233 @@
+$ $FreeBSD$
+$
+$ Message catalog for sv_SE.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Otillåten operation
+$ ENOENT
+2 Filen eller katalogen finns ej
+$ ESRCH
+3 Denna process finns ej
+$ EINTR
+4 Avbrutet systemanrop
+$ EIO
+5 In-/utmatningsfel
+$ ENXIO
+6 Enheten är ej konfigurerad
+$ E2BIG
+7 Argumentlistan är för lång
+$ ENOEXEC
+8 Ej körbar fil
+$ EBADF
+9 Felaktigt filhandtag
+$ ECHILD
+10 Inga barnprocesser
+$ EDEADLK
+11 Undvek resursdödläge
+$ ENOMEM
+12 Kan ej erhålla minne
+$ EACCES
+13 Tillstånd nekas
+$ EFAULT
+14 Felaktig adress
+$ ENOTBLK
+15 Blockenhet krävs
+$ EBUSY
+16 Enheten är upptagen
+$ EEXIST
+17 Filen finns redan
+$ EXDEV
+18 Länken korsar enheter
+$ ENODEV
+19 Enheten stöder ej operationen
+$ ENOTDIR
+20 Är ej en katalog
+$ EISDIR
+21 Är en katalog
+$ EINVAL
+22 Ogiltigt argument
+$ ENFILE
+23 För många öppna filer i systemet
+$ EMFILE
+24 För många öppna filer
+$ ENOTTY
+25 Olämplig ioctl för enheten
+$ ETXTBSY
+26 Programfilen är upptagen
+$ EFBIG
+27 Filen är för stor
+$ ENOSPC
+28 Inget utrymme kvar på enheten
+$ ESPIPE
+29 Otillåten sökning
+$ EROFS
+30 Skrivskyddat filsystem
+$ EMLINK
+31 För många länkar
+$ EPIPE
+32 Avbruten kommunikationskanal
+$ EDOM
+33 Numeriskt argument utanför domänen
+$ ERANGE
+34 Resultatet är för stort
+$ EAGAIN, EWOULDBLOCK
+35 Resursen är tillfälligt otillgänglig
+$ EINPROGRESS
+36 Operationen är igång
+$ EALREADY
+37 Operationen är redan igång
+$ ENOTSOCK
+38 Sockeloperation på icke-sockel
+$ EDESTADDRREQ
+39 Destinationsadress erfordras
+$ EMSGSIZE
+40 För långt meddelande
+$ EPROTOTYPE
+41 Fel protokolltyp för sockeln
+$ ENOPROTOOPT
+42 Protokollet otillgängligt
+$ EPROTONOSUPPORT
+43 Protokollet är ej understött
+$ ESOCKTNOSUPPORT
+44 Sockeltypen är ej understödd
+$ EOPNOTSUPP
+45 Operationen är ej understödd
+$ EPFNOSUPPORT
+46 Protokollfamiljen är ej understödd
+$ EAFNOSUPPORT
+47 Adressfamiljen är ej understödd av protokollfamiljen
+$ EADDRINUSE
+48 Adressen är upptagen
+$ EADDRNOTAVAIL
+49 Kan ej tilldela den begärda adressen
+$ ENETDOWN
+50 Nätverket fungerar inte
+$ ENETUNREACH
+51 Nätverket är ej kontaktbart
+$ ENETRESET
+52 Nätverket tappade kontakten vid återställningen
+$ ECONNABORTED
+53 Mjukvara orsakade nedkoppling
+$ ECONNRESET
+54 Motparten avbröt uppkopplingen
+$ ENOBUFS
+55 Inget buffertutrymme tillgängligt
+$ EISCONN
+56 Sockeln är redan uppkopplad
+$ ENOTCONN
+57 Sockeln är ej uppkopplad
+$ ESHUTDOWN
+58 Kan ej sända efter att sockeln nedkopplats
+$ ETOOMANYREFS
+59 För många referenser: kan inte delas
+$ ETIMEDOUT
+60 Uppkopplingstiden tog slut
+$ ECONNREFUSED
+61 Uppkopplingen nekad
+$ ELOOP
+62 För många nivåer av symboliska länkar
+$ ENAMETOOLONG
+63 Alldeles för långt filnamn
+$ EHOSTDOWN
+64 Värddatorn är nere
+$ EHOSTUNREACH
+65 Väg till värddatorn saknas
+$ ENOTEMPTY
+66 Katalogen ej tom
+$ EPROCLIM
+67 För många processer
+$ EUSERS
+68 För många användare
+$ EDQUOT
+69 Diskkvot överskriden
+$ ESTALE
+70 Inaktuellt NFS-filhandtag
+$ EREMOTE
+71 För många fjärrnivåer i sökvägen
+$ EBADRPC
+72 Felaktig RPC-struktur
+$ ERPCMISMATCH
+73 Felaktig RPC-version
+$ EPROGUNAVAIL
+74 RPC-programmet otillgängligt
+$ EPROGMISMATCH
+75 Fel programversion
+$ EPROCUNAVAIL
+76 Felaktig procedur för programmet
+$ ENOLCK
+77 Inga lås tillgängliga
+$ ENOSYS
+78 Funktionen är ej implementerad
+$ EFTYPE
+79 Olämplig filtyp eller format
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Lägg på
+$ SIGINT
+2 Avbryt
+$ SIGQUIT
+3 Avsluta
+$ SIGILL
+4 Olaglig instruktion
+$ SIGTRAP
+5 Spår- eller brytpunktsfälla
+$ SIGABRT
+6 Avslutsfälla
+$ SIGEMT
+7 Emuleringsfälla
+$ SIGFPE
+8 Flyttalsavbrott
+$ SIGKILL
+9 Dräpt
+$ SIGBUS
+10 Bussfel
+$ SIGSEGV
+11 Segmentfel
+$ SIGSYS
+12 Felaktigt systemanrop
+$ SIGPIPE
+13 Avbruten kommunikationskanal
+$ SIGALRM
+14 Äggklocka
+$ SIGTERM
+15 Terminerad
+$ SIGURG
+16 Brådskande In/Ut-tillstånd
+$ SIGSTOP
+17 Stoppad (signal)
+$ SIGTSTP
+18 Stoppad
+$ SIGCONT
+19 Fortsätter
+$ SIGCHLD
+20 Barn avslutat
+$ SIGTTIN
+21 Stoppad (terminalinmatning)
+$ SIGTTOU
+22 Stoppad (terminalutmatning)
+$ SIGIO
+23 In- och utmatning möjlig
+$ SIGXCPU
+24 Cputidsgränsen överskriden
+$ SIGXFSZ
+25 Filstorleksgränsen överskriden
+$ SIGVTALRM
+26 Virtuella äggklockan ringde
+$ SIGPROF
+27 Profileringsäggklockan ringde
+$ SIGWINCH
+28 Fönsterstorleken ändras
+$ SIGINFO
+29 Informationsförfrågan
+$ SIGUSR1
+30 Användardefinierad signal 1
+$ SIGUSR2
+31 Användardefinierad signal 2
+$ SIGPWR
+32 Kraftbortfall/omstart
diff --git a/lib/libc/nls/uk_UA.UTF-8.msg b/lib/libc/nls/uk_UA.UTF-8.msg
new file mode 100644
index 0000000..e6ea2f77
--- /dev/null
+++ b/lib/libc/nls/uk_UA.UTF-8.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for uk_UA.UTF-8 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð½Ðµ дозволена
+$ ENOENT
+2 Ðемає такого файлу або каталогу
+$ ESRCH
+3 Ðемає такого процеÑу
+$ EINTR
+4 Перервано виклик функції
+$ EIO
+5 Помилка вводу-виводу
+$ ENXIO
+6 Ðемає такого приÑтрою або адреÑи
+$ E2BIG
+7 Перелік аргументів надто довгий
+$ ENOEXEC
+8 Помилка формату виконуваного файлу
+$ EBADF
+9 Ðевірний деÑкриптор файлу
+$ ECHILD
+10 Ðемає дочірнього процеÑу
+$ EDEADLK
+11 Уникнуто взаємне Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÑурÑів
+$ ENOMEM
+12 Ðе доÑтатньо пам'ÑÑ‚Ñ–
+$ EACCES
+13 Відмова у доÑтупі
+$ EFAULT
+14 Ðевірна адреÑа
+$ ENOTBLK
+15 Потрібен блочний приÑтрій
+$ EBUSY
+16 РеÑÑƒÑ€Ñ Ð·Ð°Ð¹Ð½Ñтий
+$ EEXIST
+17 Файл вже Ñ–Ñнує
+$ EXDEV
+18 ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð·Ð° межі приÑтрою
+$ ENODEV
+19 Ðемає такого приÑтрою
+$ ENOTDIR
+20 Це не каталог
+$ EISDIR
+21 Це каталог
+$ EINVAL
+22 Ðедозволений аргумент
+$ ENFILE
+23 Забагато відкритих файлів у ÑиÑтемі
+$ EMFILE
+24 Забагато відкритих файлів
+$ ENOTTY
+25 Це не термінал
+$ ETXTBSY
+26 ТекÑтовий файл зайнÑтий
+$ EFBIG
+27 Файл надто великий
+$ ENOSPC
+28 Ðе залишилоÑÑŒ міÑÑ†Ñ Ð½Ð° приÑтрої
+$ ESPIPE
+29 Ðедозволене позиціонуваннÑ
+$ EROFS
+30 Файлова ÑиÑтема лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ
+$ EMLINK
+31 Забагато поÑилань
+$ EPIPE
+32 Канал зруйновано
+$ EDOM
+33 Помилка облаÑÑ‚Ñ– визначеннÑ
+$ ERANGE
+34 Результат надто великий
+$ EAGAIN, EWOULDBLOCK
+35 РеÑÑƒÑ€Ñ Ñ‚Ð¸Ð¼Ñ‡Ð°Ñово не доÑтупний
+$ EINPROGRESS
+36 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ñƒ процеÑÑ– виконаннÑ
+$ EALREADY
+37 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð²Ð¶Ðµ виконуєтьÑÑ
+$ ENOTSOCK
+38 Це не Ñокет
+$ EDESTADDRREQ
+39 Ðеобхідна адреÑа призначеннÑ
+$ EMSGSIZE
+40 ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð°Ð´Ñ‚Ð¾ довге
+$ EPROTOTYPE
+41 Помилковий тип протоколу Ð´Ð»Ñ Ñокету
+$ ENOPROTOOPT
+42 Ðемає такого протоколу
+$ EPROTONOSUPPORT
+43 Протокол не підтримуєтьÑÑ
+$ ESOCKTNOSUPPORT
+44 Цей тип Ñокету не підтримуєтьÑÑ
+$ EOPNOTSUPP
+45 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð½Ðµ підтримуєтьÑÑ
+$ EPFNOSUPPORT
+46 Родина протоколів не підтримуєтьÑÑ
+$ EAFNOSUPPORT
+47 Родина Ð°Ð´Ñ€ÐµÑ Ð½Ðµ підтримуєтьÑÑ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð¾Ð¼
+$ EADDRINUSE
+48 ÐдреÑа вже викориÑтовуєтьÑÑ
+$ EADDRNOTAVAIL
+49 ÐдреÑа недоÑÑжна
+$ ENETDOWN
+50 Мережа не працює
+$ ENETUNREACH
+51 Мережа недоÑÑжна
+$ ENETRESET
+52 З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð¾ мережею
+$ ECONNABORTED
+53 З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð¾
+$ ECONNRESET
+54 З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð¾ протилежною Ñтороною
+$ ENOBUFS
+55 Ðемає вільних буферів
+$ EISCONN
+56 Сокет вже під'єднано
+$ ENOTCONN
+57 Сокет не під'єднано
+$ ESHUTDOWN
+58 Ðе можу відіÑлати піÑÐ»Ñ Ð·Ð°ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñокету протилежною Ñтороною
+$ ETOOMANYREFS
+59 Забагато поÑилань: не можу з'єднати
+$ ETIMEDOUT
+60 Вийшов ліміт чаÑу Ð´Ð»Ñ Ð·'єднаннÑ
+$ ECONNREFUSED
+61 Відмова у з'єднанні
+$ ELOOP
+62 Забагато рівнів Ñимволічних поÑилань
+$ ENAMETOOLONG
+63 Ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ надто довге
+$ EHOSTDOWN
+64 ХоÑÑ‚ не працює
+$ EHOSTUNREACH
+65 ХоÑÑ‚ недоÑÑжний
+$ ENOTEMPTY
+66 Каталог не порожній
+$ EPROCLIM
+67 Забагато процеÑів
+$ EUSERS
+68 Забагато кориÑтувачів
+$ EDQUOT
+69 Перевищена диÑкова квота
+$ ESTALE
+70 ЗаÑтарілий деÑкриптор файлу NFS
+$ EREMOTE
+71 Віддалений об'єкт
+$ EBADRPC
+72 Погана Ñтруктура RPC
+$ ERPCMISMATCH
+73 Ðевірна верÑÑ–Ñ RPC
+$ EPROGUNAVAIL
+74 Програма RPC недоÑÑжна
+$ EPROGMISMATCH
+75 Ðевірна верÑÑ–Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸
+$ EPROCUNAVAIL
+76 Погана процедура Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸
+$ ENOLCK
+77 Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ доÑтупне
+$ ENOSYS
+78 Функцію не реалізовано
+$ EFTYPE
+79 Ðепридатний тип чи формат файлу
+$ EAUTH
+80 Помилка аутентифікації
+$ ENEEDAUTH
+81 Потрібна аутентифікаціÑ
+$ EIDRM
+82 Ідентифікатор вилучено
+$ ENOMSG
+83 Ðемає Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð±Ð°Ð¶Ð°Ð½Ð¾Ð³Ð¾ типу
+$ EOVERFLOW
+84 Завелике Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ типу даних
+$ ECANCELED
+85 Операцію ÑкаÑовано
+$ EILSEQ
+86 Ðедозволена поÑлідовніÑÑ‚ÑŒ байтів
+$ ENOATTR
+87 Ðтрибут не знайдено
+$ EDOOFUS
+88 Помилка програмуваннÑ
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 ВідключеннÑ
+$ SIGINT
+2 ПерериваннÑ
+$ SIGQUIT
+3 Вихід
+$ SIGILL
+4 ÐеприпуÑтима інÑтрукціÑ
+$ SIGTRAP
+5 ПаÑтка траÑуваннÑ
+$ SIGABRT
+6 Ðварійне завершеннÑ
+$ SIGEMT
+7 ÐŸÐµÑ€ÐµÑ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ ÐµÐ¼ÑƒÐ»ÑŒÐ¾Ð²Ð°Ð½Ð¾Ñ— інÑтрукції
+$ SIGFPE
+8 Помилка роботи з плаваючою крапкою
+$ SIGKILL
+9 Вбито
+$ SIGBUS
+10 Помилка шини
+$ SIGSEGV
+11 ÐŸÐ¾Ñ€ÑƒÑˆÐµÐ½Ð½Ñ Ñегментації
+$ SIGSYS
+12 Поганий ÑиÑтемний виклик
+$ SIGPIPE
+13 Канал зруйновано
+$ SIGALRM
+14 Таймер вичерпано
+$ SIGTERM
+15 ЗавершеннÑ
+$ SIGURG
+16 Ðевідкладний Ñтан на Ñокеті
+$ SIGSTOP
+17 Призупинено (Ñигнал)
+$ SIGTSTP
+18 Призупинено
+$ SIGCONT
+19 ÐŸÑ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸
+$ SIGCHLD
+20 Зміна ÑтатуÑу дочірнього процеÑу
+$ SIGTTIN
+21 Зупинено (ввід з терміналу)
+$ SIGTTOU
+22 Зупинено (вивід на термінал)
+$ SIGIO
+23 Ввід-вивід можливий
+$ SIGXCPU
+24 Перевищено ліміт процеÑорного чаÑу
+$ SIGXFSZ
+25 Перевищено ліміт макÑимального розміру файла
+$ SIGVTALRM
+26 Віртуальний таймер вичерпано
+$ SIGPROF
+27 Таймер Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ñ‡ÐµÑ€Ð¿Ð°Ð½Ð¾
+$ SIGWINCH
+28 Розмір вікна змінено
+$ SIGINFO
+29 Запит інформації
+$ SIGUSR1
+30 Сигнал кориÑтувача 1
+$ SIGUSR2
+31 Сигнал кориÑтувача 2
diff --git a/lib/libc/rpc/clnt_bcast.c b/lib/libc/rpc/clnt_bcast.c
index eef0ca5..612007e 100644
--- a/lib/libc/rpc/clnt_bcast.c
+++ b/lib/libc/rpc/clnt_bcast.c
@@ -461,7 +461,7 @@ rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp,
#ifdef RPC_DEBUG
perror("sendto");
#endif
- warnx("clnt_bcast: cannot send"
+ warnx("clnt_bcast: cannot send "
"broadcast packet");
stat = RPC_CANTSEND;
continue;
diff --git a/lib/libc/rpc/getnetconfig.c b/lib/libc/rpc/getnetconfig.c
index 1bb3368..773650c 100644
--- a/lib/libc/rpc/getnetconfig.c
+++ b/lib/libc/rpc/getnetconfig.c
@@ -418,18 +418,6 @@ getnetconfigent(netid)
return (NULL);
}
- if (strcmp(netid, "unix") == 0) {
- fprintf(stderr, "The local transport is called \"unix\" ");
- fprintf(stderr, "in /etc/netconfig.\n");
- fprintf(stderr, "Please change this to \"local\" manually ");
- fprintf(stderr, "or run mergemaster(8).\n");
- fprintf(stderr, "See UPDATING entry 20021216 for details.\n");
- fprintf(stderr, "Continuing in 10 seconds\n\n");
- fprintf(stderr, "This warning will be removed 20030301\n");
- sleep(10);
-
- }
-
/*
* Look up table if the entries have already been read and parsed in
* getnetconfig(), then copy this entry into a buffer and return it.
diff --git a/lib/libc/stdio/getdelim.c b/lib/libc/stdio/getdelim.c
index fb02889..7af154f 100644
--- a/lib/libc/stdio/getdelim.c
+++ b/lib/libc/stdio/getdelim.c
@@ -120,7 +120,6 @@ getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
goto error;
}
- linelen = 0;
if (*linecapp == 0)
*linep = NULL;
@@ -128,9 +127,12 @@ getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
/* If fp is at EOF already, we just need space for the NUL. */
if (__sferror(fp) || expandtofit(linep, 1, linecapp))
goto error;
- goto done;
+ FUNLOCKFILE(fp);
+ (*linep)[0] = '\0';
+ return (-1);
}
+ linelen = 0;
while ((endp = memchr(fp->_p, delim, fp->_r)) == NULL) {
if (sappend(linep, &linelen, linecapp, fp->_p, fp->_r))
goto error;
diff --git a/lib/libc/stdio/getline.3 b/lib/libc/stdio/getline.3
index 096331a..0465f93 100644
--- a/lib/libc/stdio/getline.3
+++ b/lib/libc/stdio/getline.3
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 28, 2009
+.Dd March 29, 2009
.Dt GETLINE 3
.Os
.Sh NAME
@@ -79,7 +79,7 @@ and
functions return the number of characters written, excluding the
terminating
.Dv NUL .
-The value \-1 is returned if an error occurs.
+The value \-1 is returned if an error occurs, or if end-of-file is reached.
.Sh EXAMPLES
The following code fragment reads lines from a file and
writes them to standard output.
diff --git a/lib/libc/string/memchr.3 b/lib/libc/string/memchr.3
index 5cbaf6c..ae2a22c 100644
--- a/lib/libc/string/memchr.3
+++ b/lib/libc/string/memchr.3
@@ -83,7 +83,8 @@ bytes.
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wmemchr 3
.Sh STANDARDS
The
.Fn memchr
diff --git a/lib/libc/string/memcmp.3 b/lib/libc/string/memcmp.3
index a7be20b..507b930 100644
--- a/lib/libc/string/memcmp.3
+++ b/lib/libc/string/memcmp.3
@@ -72,7 +72,8 @@ Zero-length strings are always identical.
.Xr strcasecmp 3 ,
.Xr strcmp 3 ,
.Xr strcoll 3 ,
-.Xr strxfrm 3
+.Xr strxfrm 3 ,
+.Xr wmemcmp 3
.Sh STANDARDS
The
.Fn memcmp
diff --git a/lib/libc/string/memcpy.3 b/lib/libc/string/memcpy.3
index 80a8629..3f2e2dd 100644
--- a/lib/libc/string/memcpy.3
+++ b/lib/libc/string/memcpy.3
@@ -64,7 +64,8 @@ returns the original value of
.Xr bcopy 3 ,
.Xr memccpy 3 ,
.Xr memmove 3 ,
-.Xr strcpy 3
+.Xr strcpy 3 ,
+.Xr wmemcpy 3
.Sh STANDARDS
The
.Fn memcpy
diff --git a/lib/libc/string/memmove.3 b/lib/libc/string/memmove.3
index 19c2987..8a1d52b 100644
--- a/lib/libc/string/memmove.3
+++ b/lib/libc/string/memmove.3
@@ -65,7 +65,8 @@ function returns the original value of
.Xr bcopy 3 ,
.Xr memccpy 3 ,
.Xr memcpy 3 ,
-.Xr strcpy 3
+.Xr strcpy 3 ,
+.Xr wmemmove 3
.Sh STANDARDS
The
.Fn memmove
diff --git a/lib/libc/string/memset.3 b/lib/libc/string/memset.3
index 58877f0..1dc287d 100644
--- a/lib/libc/string/memset.3
+++ b/lib/libc/string/memset.3
@@ -60,7 +60,8 @@ The
function returns its first argument.
.Sh SEE ALSO
.Xr bzero 3 ,
-.Xr swab 3
+.Xr swab 3 ,
+.Xr wmemset 3
.Sh STANDARDS
The
.Fn memset
diff --git a/lib/libc/string/strcasecmp.3 b/lib/libc/string/strcasecmp.3
index f94abec..2b2ef3e 100644
--- a/lib/libc/string/strcasecmp.3
+++ b/lib/libc/string/strcasecmp.3
@@ -83,7 +83,8 @@ is greater than
.Xr strcmp 3 ,
.Xr strcoll 3 ,
.Xr strxfrm 3 ,
-.Xr tolower 3
+.Xr tolower 3 ,
+.Xr wcscasecmp 3
.Sh HISTORY
The
.Fn strcasecmp
diff --git a/lib/libc/string/strcat.3 b/lib/libc/string/strcat.3
index e24ed9d..0290994 100644
--- a/lib/libc/string/strcat.3
+++ b/lib/libc/string/strcat.3
@@ -144,7 +144,8 @@ foo(const char *arbitrary_string)
.Xr memmove 3 ,
.Xr strcpy 3 ,
.Xr strlcat 3 ,
-.Xr strlcpy 3
+.Xr strlcpy 3 ,
+.Xr wcscat 3
.Sh STANDARDS
The
.Fn strcat
diff --git a/lib/libc/string/strchr.3 b/lib/libc/string/strchr.3
index 7c867a3..984eb06 100644
--- a/lib/libc/string/strchr.3
+++ b/lib/libc/string/strchr.3
@@ -85,7 +85,8 @@ if the character does not appear in the string.
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcschr 3
.Sh STANDARDS
The functions
.Fn strchr
diff --git a/lib/libc/string/strcmp.3 b/lib/libc/string/strcmp.3
index 7c5877b..1e13ed8 100644
--- a/lib/libc/string/strcmp.3
+++ b/lib/libc/string/strcmp.3
@@ -89,7 +89,8 @@ is greater than
.Xr memcmp 3 ,
.Xr strcasecmp 3 ,
.Xr strcoll 3 ,
-.Xr strxfrm 3
+.Xr strxfrm 3 ,
+.Xr wcscmp 3
.Sh STANDARDS
The
.Fn strcmp
diff --git a/lib/libc/string/strcpy.3 b/lib/libc/string/strcpy.3
index 619b4e7..157abcc 100644
--- a/lib/libc/string/strcpy.3
+++ b/lib/libc/string/strcpy.3
@@ -189,7 +189,8 @@ and
.Xr memccpy 3 ,
.Xr memcpy 3 ,
.Xr memmove 3 ,
-.Xr strlcpy 3
+.Xr strlcpy 3 ,
+.Xr wcscpy 3
.Sh STANDARDS
The
.Fn strcpy
diff --git a/lib/libc/string/strdup.3 b/lib/libc/string/strdup.3
index 080f4e7..04a2816 100644
--- a/lib/libc/string/strdup.3
+++ b/lib/libc/string/strdup.3
@@ -71,7 +71,8 @@ always
terminating the copied string.
.Sh SEE ALSO
.Xr free 3 ,
-.Xr malloc 3
+.Xr malloc 3 ,
+.Xr wcsdup 3
.Sh HISTORY
The
.Fn strdup
@@ -80,4 +81,4 @@ function first appeared in
The
.Fn strndup
function was added in
-.Fx 8.0 .
+.Fx 7.2 .
diff --git a/lib/libc/string/strlcpy.3 b/lib/libc/string/strlcpy.3
index aaef572..19d3621 100644
--- a/lib/libc/string/strlcpy.3
+++ b/lib/libc/string/strlcpy.3
@@ -192,7 +192,8 @@ As a matter of fact, the first version of this manual page got it wrong.
.Sh SEE ALSO
.Xr snprintf 3 ,
.Xr strncat 3 ,
-.Xr strncpy 3
+.Xr strncpy 3 ,
+.Xr wcslcpy 3
.Sh HISTORY
The
.Fn strlcpy
diff --git a/lib/libc/string/strlen.3 b/lib/libc/string/strlen.3
index f7aa033..bdbf4ff 100644
--- a/lib/libc/string/strlen.3
+++ b/lib/libc/string/strlen.3
@@ -77,7 +77,9 @@ or
.Fa maxlen ,
whichever is smaller.
.Sh SEE ALSO
-.Xr string 3
+.Xr string 3 ,
+.Xr wcslen 3 ,
+.Xr wcswidth 3
.Sh STANDARDS
The
.Fn strlen
diff --git a/lib/libc/string/strpbrk.3 b/lib/libc/string/strpbrk.3
index 0a16757..7ed0ec7 100644
--- a/lib/libc/string/strpbrk.3
+++ b/lib/libc/string/strpbrk.3
@@ -67,7 +67,8 @@ returns NULL.
.Xr strsep 3 ,
.Xr strspn 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcspbrk 3
.Sh STANDARDS
The
.Fn strpbrk
diff --git a/lib/libc/string/strspn.3 b/lib/libc/string/strspn.3
index 6fc3280..72a1d32 100644
--- a/lib/libc/string/strspn.3
+++ b/lib/libc/string/strspn.3
@@ -74,7 +74,8 @@ returns the number of characters spanned.
.Xr strrchr 3 ,
.Xr strsep 3 ,
.Xr strstr 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcsspn 3
.Sh STANDARDS
The
.Fn strspn
diff --git a/lib/libc/string/strstr.3 b/lib/libc/string/strstr.3
index 7468ccc..74ebdff 100644
--- a/lib/libc/string/strstr.3
+++ b/lib/libc/string/strstr.3
@@ -135,7 +135,8 @@ ptr = strnstr(largestring, smallstring, 4);
.Xr strrchr 3 ,
.Xr strsep 3 ,
.Xr strspn 3 ,
-.Xr strtok 3
+.Xr strtok 3 ,
+.Xr wcsstr 3
.Sh STANDARDS
The
.Fn strstr
diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
index 02ed73b..9e3c3c6 100644
--- a/lib/libc/sys/Symbol.map
+++ b/lib/libc/sys/Symbol.map
@@ -265,6 +265,8 @@ FBSD_1.0 {
setsockopt;
settimeofday;
setuid;
+ shm_open;
+ shm_unlink;
shmat;
shmctl;
shmdt;
@@ -876,6 +878,10 @@ FBSDprivate_1.0 {
__sys_settimeofday;
_setuid;
__sys_setuid;
+ _shm_open;
+ __sys_shm_open;
+ _shm_unlink;
+ __sys_shm_unlink;
_shmat;
__sys_shmat;
_shmctl;
diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2
index 44fc1ea..9d8f550 100644
--- a/lib/libc/sys/ptrace.2
+++ b/lib/libc/sys/ptrace.2
@@ -2,7 +2,7 @@
.\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $
.\"
.\" This file is in the public domain.
-.Dd April 9, 2007
+.Dd March 27, 2009
.Dt PTRACE 2
.Os
.Sh NAME
@@ -77,7 +77,8 @@ special case noted below, all
.Fn ptrace
calls are made by the tracing process, and the
.Fa pid
-argument specifies the process ID of the traced process.
+argument specifies the process ID of the traced process
+or a corresponding thread ID.
The
.Fa request
argument
@@ -311,6 +312,21 @@ with the array size specified by
The return value from
.Fn ptrace
is the count of array entries filled in.
+.It PT_SETSTEP
+This request will turn on single stepping of the specified process.
+.It PT_CLEARSTEP
+This request will turn off single stepping of the specified process.
+.It PT_SUSPEND
+This request will suspend the specified thread.
+.It PT_RESUME
+This request will resume the specified thread.
+.It PT_TO_SCE
+This request will trace the specified process on each system call entry.
+.It PT_TO_SCX
+This request will trace the specified process on each system call exit.
+.It PT_SYSCALL
+This request will trace the specified process
+on each system call entry and exit.
.El
.Pp
Additionally, machine-specific requests can exist.
diff --git a/lib/libkvm/kvm_powerpc.c b/lib/libkvm/kvm_powerpc.c
index 24ab7fb..7e4941a 100644
--- a/lib/libkvm/kvm_powerpc.c
+++ b/lib/libkvm/kvm_powerpc.c
@@ -1,8 +1,5 @@
-/* $NetBSD: kvm_powerpc.c,v 1.4 1998/02/03 06:50:07 mycroft Exp $ */
-
/*-
- * Copyright (C) 1996 Wolfgang Solfrank.
- * Copyright (C) 1996 TooLs GmbH.
+ * Copyright (c) 2008, Juniper Networks, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -13,91 +10,209 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by TooLs GmbH.
- * 4. The name of TooLs GmbH may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * 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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * PowerPC machine dependent routines for kvm.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/kerneldump.h>
+#include <sys/mman.h>
#include <vm/vm.h>
#include <db.h>
+#include <elf.h>
#include <limits.h>
#include <kvm.h>
#include <stdlib.h>
#include "kvm_private.h"
-void
-_kvm_freevtop(kd)
- kvm_t *kd;
-{
- if (kd->vmst != 0)
- free(kd->vmst);
-}
+struct vmstate {
+ void *map;
+ size_t mapsz;
+ size_t dmphdrsz;
+ Elf32_Ehdr *eh;
+ Elf32_Phdr *ph;
+};
-int
-_kvm_initvtop(kd)
- kvm_t *kd;
+static int
+valid_elf_header(Elf32_Ehdr *eh)
{
- return 0;
+
+ if (!IS_ELF(*eh))
+ return (0);
+ if (eh->e_ident[EI_CLASS] != ELFCLASS32)
+ return (0);
+ if (eh->e_ident[EI_DATA] != ELFDATA2MSB)
+ return (0);
+ if (eh->e_ident[EI_VERSION] != EV_CURRENT)
+ return (0);
+ if (eh->e_ident[EI_OSABI] != ELFOSABI_STANDALONE)
+ return (0);
+ if (be16toh(eh->e_type) != ET_CORE)
+ return (0);
+ if (be16toh(eh->e_machine) != EM_PPC)
+ return (0);
+ /* Can't think of anything else to check... */
+ return (1);
}
-int
-_kvm_kvatop(kd, va, pa)
- kvm_t *kd;
- u_long va;
- off_t *pa;
+static size_t
+dump_header_size(struct kerneldumpheader *dh)
{
- _kvm_err(kd, 0, "vatop not yet implemented!");
- return 0;
+
+ if (strcmp(dh->magic, KERNELDUMPMAGIC) != 0)
+ return (0);
+ if (strcmp(dh->architecture, "powerpc") != 0)
+ return (0);
+ /* That should do it... */
+ return (sizeof(*dh));
}
-off_t
-_kvm_pa2off(kd, pa)
- kvm_t *kd;
- u_long pa;
+/*
+ * Map the ELF headers into the process' address space. We do this in two
+ * steps: first the ELF header itself and using that information the whole
+ * set of headers.
+ */
+static int
+powerpc_maphdrs(kvm_t *kd)
{
- _kvm_err(kd, 0, "pa2off not yet implemented!");
- return 0;
+ struct vmstate *vm;
+ size_t mapsz;
+
+ vm = kd->vmst;
+
+ vm->mapsz = PAGE_SIZE;
+ vm->map = mmap(NULL, vm->mapsz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0);
+ if (vm->map == MAP_FAILED) {
+ _kvm_err(kd, kd->program, "cannot map corefile");
+ return (-1);
+ }
+ vm->dmphdrsz = 0;
+ vm->eh = vm->map;
+ if (!valid_elf_header(vm->eh)) {
+ /*
+ * Hmmm, no ELF header. Maybe we still have a dump header.
+ * This is normal when the core file wasn't created by
+ * savecore(8), but instead was dumped over TFTP. We can
+ * easily skip the dump header...
+ */
+ vm->dmphdrsz = dump_header_size(vm->map);
+ if (vm->dmphdrsz == 0)
+ goto inval;
+ vm->eh = (void *)((uintptr_t)vm->map + vm->dmphdrsz);
+ if (!valid_elf_header(vm->eh))
+ goto inval;
+ }
+ mapsz = be16toh(vm->eh->e_phentsize) * be16toh(vm->eh->e_phnum) +
+ be32toh(vm->eh->e_phoff);
+ munmap(vm->map, vm->mapsz);
+
+ /* Map all headers. */
+ vm->mapsz = vm->dmphdrsz + mapsz;
+ vm->map = mmap(NULL, vm->mapsz, PROT_READ, MAP_PRIVATE, kd->pmfd, 0);
+ if (vm->map == MAP_FAILED) {
+ _kvm_err(kd, kd->program, "cannot map corefle headers");
+ return (-1);
+ }
+ vm->eh = (void *)((uintptr_t)vm->map + vm->dmphdrsz);
+ vm->ph = (void *)((uintptr_t)vm->eh + be32toh(vm->eh->e_phoff));
+ return (0);
+
+ inval:
+ munmap(vm->map, vm->mapsz);
+ vm->map = MAP_FAILED;
+ _kvm_err(kd, kd->program, "invalid corefile");
+ return (-1);
}
/*
- * Machine-dependent initialization for ALL open kvm descriptors,
- * not just those for a kernel crash dump. Some architectures
- * have to deal with these NOT being constants! (i.e. m68k)
+ * Determine the offset within the corefile corresponding the virtual
+ * address. Return the number of contiguous bytes in the corefile or
+ * 0 when the virtual address is invalid.
*/
+static size_t
+powerpc_va2off(kvm_t *kd, u_long va, off_t *ofs)
+{
+ struct vmstate *vm = kd->vmst;
+ Elf32_Phdr *ph;
+ int nph;
+
+ ph = vm->ph;
+ nph = be16toh(vm->eh->e_phnum);
+ while (nph && (va < be32toh(ph->p_vaddr) ||
+ va >= be32toh(ph->p_vaddr) + be32toh(ph->p_memsz))) {
+ nph--;
+ ph = (void *)((uintptr_t)ph + be16toh(vm->eh->e_phentsize));
+ }
+ if (nph == 0)
+ return (0);
+
+ /* Segment found. Return file offset and range. */
+ *ofs = vm->dmphdrsz + be32toh(ph->p_offset) +
+ (va - be32toh(ph->p_vaddr));
+ return (be32toh(ph->p_memsz) - (va - be32toh(ph->p_vaddr)));
+}
+
+void
+_kvm_freevtop(kvm_t *kd)
+{
+ struct vmstate *vm = kd->vmst;
+
+ if (vm == NULL)
+ return;
+
+ if (vm->eh != MAP_FAILED) {
+ munmap(vm->eh, vm->mapsz);
+ vm->eh = MAP_FAILED;
+ }
+ free(vm);
+ kd->vmst = NULL;
+}
+
+int
+_kvm_initvtop(kvm_t *kd)
+{
+
+ kd->vmst = (struct vmstate *)_kvm_malloc(kd, sizeof(*kd->vmst));
+ if (kd->vmst == NULL) {
+ _kvm_err(kd, kd->program, "out of virtual memory");
+ return (-1);
+ }
+ if (powerpc_maphdrs(kd) == -1) {
+ free(kd->vmst);
+ kd->vmst = NULL;
+ return (-1);
+ }
+ return (0);
+}
+
int
-_kvm_mdopen(kd)
- kvm_t *kd;
+_kvm_kvatop(kvm_t *kd, u_long va, off_t *ofs)
{
+ struct vmstate *vm;
-#ifdef FBSD_NOT_YET
- kd->usrstack = USRSTACK;
- kd->min_uva = VM_MIN_ADDRESS;
- kd->max_uva = VM_MAXUSER_ADDRESS;
-#endif
+ vm = kd->vmst;
+ if (vm->ph->p_paddr == ~0U)
+ return ((int)powerpc_va2off(kd, va, ofs));
+ _kvm_err(kd, kd->program, "Raw corefile not supported");
return (0);
}
diff --git a/lib/libpcap/Makefile b/lib/libpcap/Makefile
index 4f43279..38a2131 100644
--- a/lib/libpcap/Makefile
+++ b/lib/libpcap/Makefile
@@ -10,57 +10,80 @@ SRCS= grammar.y tokdefs.h version.h pcap-bpf.c \
pcap.c inet.c fad-getad.c gencode.c optimize.c nametoaddr.c \
etherent.c savefile.c bpf_filter.c bpf_image.c bpf_dump.c \
scanner.l version.c
+
+# Old compatibility headers
INCS= pcap.h pcap-int.h pcap-namedb.h pcap-bpf.h
-MAN= pcap.3
-MLINKS= pcap.3 pcap_open_live.3 \
- pcap.3 pcap_open_dead.3 \
- pcap.3 pcap_open_offline.3 \
- pcap.3 pcap_fopen_offline.3 \
- pcap.3 pcap_dump_open.3 \
- pcap.3 pcap_dump_fopen.3 \
- pcap.3 pcap_setnonblock.3 \
- pcap.3 pcap_getnonblock.3 \
- pcap.3 pcap_findalldevs.3 \
- pcap.3 pcap_freealldevs.3 \
- pcap.3 pcap_lookupdev.3 \
- pcap.3 pcap_lookupnet.3 \
- pcap.3 pcap_dispatch.3 \
- pcap.3 pcap_loop.3 \
- pcap.3 pcap_dump.3 \
- pcap.3 pcap_compile.3 \
- pcap.3 pcap_setfilter.3 \
- pcap.3 pcap_freecode.3 \
- pcap.3 pcap_setdirection.3 \
- pcap.3 pcap_next.3 \
- pcap.3 pcap_next_ex.3 \
- pcap.3 pcap_breakloop.3 \
- pcap.3 pcap_inject.3 \
- pcap.3 pcap_sendpacket.3 \
- pcap.3 pcap_datalink.3 \
- pcap.3 pcap_list_datalinks.3 \
- pcap.3 pcap_set_datalink.3 \
- pcap.3 pcap_datalink_name_to_val.3 \
- pcap.3 pcap_datalink_val_to_name.3 \
- pcap.3 pcap_datalink_val_to_description.3 \
- pcap.3 pcap_snapshot.3 \
- pcap.3 pcap_is_swapped.3 \
- pcap.3 pcap_major_version.3 \
- pcap.3 pcap_minor_version.3 \
- pcap.3 pcap_stats.3 \
- pcap.3 pcap_file.3 \
- pcap.3 pcap_fileno.3 \
- pcap.3 pcap_get_selectable_fd.3 \
- pcap.3 pcap_perror.3 \
- pcap.3 pcap_geterr.3 \
- pcap.3 pcap_strerror.3 \
- pcap.3 pcap_lib_version.3 \
- pcap.3 pcap_close.3 \
- pcap.3 pcap_dump_flush.3 \
- pcap.3 pcap_dump_ftell.3 \
- pcap.3 pcap_dump_file.3 \
- pcap.3 pcap_dump_close.3
-
-CLEANFILES=tokdefs.h version.h version.c
+
+PCAPINCS= pcap/pcap.h pcap/namedb.h pcap/bpf.h
+PCAPINCSDIR= ${INCLUDEDIR}/pcap
+INCSGROUPS= INCS PCAPINCS
+
+MAN= pcap.3 \
+ pcap_activate.3 \
+ pcap_breakloop.3 \
+ pcap_can_set_rfmon.3 \
+ pcap_close.3 \
+ pcap_compile.3 \
+ pcap_create.3 \
+ pcap_datalink.3 \
+ pcap_datalink_name_to_val.3 \
+ pcap_datalink_val_to_name.3 \
+ pcap_dump.3 \
+ pcap_dump_close.3 \
+ pcap_dump_file.3 \
+ pcap_dump_flush.3 \
+ pcap_dump_ftell.3 \
+ pcap_dump_open.3 \
+ pcap_file.3 \
+ pcap_fileno.3 \
+ pcap_findalldevs.3 \
+ pcap_free_datalinks.3 \
+ pcap_freealldevs.3 \
+ pcap_freecode.3 \
+ pcap_get_selectable_fd.3 \
+ pcap_geterr.3 \
+ pcap_inject.3 \
+ pcap_is_swapped.3 \
+ pcap_lib_version.3 \
+ pcap_list_datalinks.3 \
+ pcap_lookupdev.3 \
+ pcap_lookupnet.3 \
+ pcap_loop.3 \
+ pcap_major_version.3 \
+ pcap_next_ex.3 \
+ pcap_offline_filter.3 \
+ pcap_open_dead.3 \
+ pcap_open_live.3 \
+ pcap_open_offline.3 \
+ pcap_set_buffer_size.3 \
+ pcap_set_datalink.3 \
+ pcap_set_promisc.3 \
+ pcap_set_rfmon.3 \
+ pcap_set_snaplen.3 \
+ pcap_set_timeout.3 \
+ pcap_setdirection.3 \
+ pcap_setfilter.3 \
+ pcap_setnonblock.3 \
+ pcap_snapshot.3 \
+ pcap_stats.3 \
+ pcap_statustostr.3 \
+ pcap_strerror.3 \
+ pcap-savefile.5 \
+ pcap-filter.7 \
+ pcap-linktype.7
+MLINKS= pcap_datalink_val_to_name.3 pcap_datalink_val_to_description.3 \
+ pcap_dump_open.3 pcap_dump_fopen.3 \
+ pcap_geterr.3 pcap_perror.3 \
+ pcap_inject.3 pcap_sendpacket.3 \
+ pcap_loop.3 pcap_dispatch.3 \
+ pcap_major_version.3 pcap_minor_version.3 \
+ pcap_next_ex.3 pcap_next.3 \
+ pcap_open_offline.3 pcap_fopen_offline.3 \
+ pcap_setnonblock.3 pcap_getnonblock.3
+
+# Our man pages are a special copy from the distdir. See below.
+CLEANFILES+=${MAN}
+CLEANFILES+=tokdefs.h version.h version.c
YFLAGS+=-p pcapyy
LFLAGS+=-Ppcapyy
@@ -74,7 +97,7 @@ CFLAGS+=-DINET6
CFLAGS+=-DHAVE_NET_PFVAR_H
.endif
-SHLIB_MAJOR=5
+SHLIB_MAJOR=6
#
# Magic to grab sources out of src/contrib
@@ -95,4 +118,20 @@ version.h: ${PCAP_DISTDIR}/VERSION
tokdefs.h: grammar.h
ln -sf grammar.h tokdefs.h
+
+#
+# Magic to convert the man pages to something non Solarish
+#
+.for _page in ${MAN}
+${_page}:
+ if [ -f ${PCAP_DISTDIR}/${_page:S/3$/3pcap/} ]; then \
+ F=${_page:S/3$/3pcap/}; \
+ elif [ -f ${PCAP_DISTDIR}/${_page:S/5$/manfile/} ]; then \
+ F=${_page:S/5$/manfile/}; \
+ else \
+ F=${_page:S/7$/manmisc/}; \
+ fi; \
+ sed -e 's/3PCAP/3/g' ${PCAP_DISTDIR}/$$F > ${_page}
+.endfor
+
.include <bsd.lib.mk>
diff --git a/lib/libpcap/config.h b/lib/libpcap/config.h
index 78bb0db..f4dec9c 100644
--- a/lib/libpcap/config.h
+++ b/lib/libpcap/config.h
@@ -17,6 +17,9 @@
/* define if you have a cloning BPF device */
#define HAVE_CLONING_BPF 1
+/* define if you have dag_get_stream_erf_types() */
+/* #undef HAVE_DAG_GET_STREAM_ERF_TYPES */
+
/* define if you have the DAG API */
/* #undef HAVE_DAG_API */
@@ -30,12 +33,18 @@
don't. */
#define HAVE_DECL_ETHER_HOSTTON 1
+/* if passive_req_t primitive exists */
+/* #undef HAVE_DLPI_PASSIVE */
+
/* define if you have a /dev/dlpi */
/* #undef HAVE_DEV_DLPI */
/* Define to 1 if you have the `ether_hostton' function. */
#define HAVE_ETHER_HOSTTON 1
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#define HAVE_FSEEKO 1
+
/* on HP-UX 10.20 or later */
/* #undef HAVE_HPUX10_20_OR_LATER */
@@ -48,9 +57,18 @@
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
+/* if libdlpi exists */
+/* #undef HAVE_LIBDLPI */
+
/* Define to 1 if you have the <limits.h> header file. */
#define HAVE_LIMITS_H 1
+/* if tp_vlan_tci exists */
+/* #undef HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI */
+
+/* Define to 1 if you have the <linux/wireless.h> header file. */
+/* #undef HAVE_LINUX_WIRELESS_H */
+
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
@@ -60,6 +78,9 @@
/* Define to 1 if you have the <netinet/if_ether.h> header file. */
#define HAVE_NETINET_IF_ETHER_H 1
+/* Define to 1 if you have the <net/if_media.h> header file. */
+#define HAVE_NET_IF_MEDIA_H 1
+
/* Define to 1 if you have the <net/pfvar.h> header file. */
/* See Makefile */
/* #undef HAVE_NET_PFVAR_H */
@@ -84,6 +105,9 @@
/* if struct sockaddr_storage exists */
#define HAVE_SOCKADDR_STORAGE 1
+
+/* define if socklen_t is defined */
+#define HAVE_SOCKLEN_T 1
/* On solaris */
/* #undef HAVE_SOLARIS */
@@ -139,6 +163,9 @@
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
+/* define if the system supports zerocopy BPF */
+#define HAVE_ZEROCOPY_BPF 1
+
/* define if your compiler has __attribute__ */
#define HAVE___ATTRIBUTE__ 1
@@ -148,6 +175,9 @@
/* if unaligned access fails */
/* #undef LBL_ALIGN */
+/* path for device for USB sniffing */
+/* #undef LINUX_USB_MON_DEV */
+
/* Define to 1 if netinet/ether.h declares `ether_hostton' */
/* #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
@@ -175,6 +205,15 @@
/* /dev/dlpi directory */
/* #undef PCAP_DEV_PREFIX */
+/* target host supports Bluetooth sniffing */
+/* #undef PCAP_SUPPORT_BT */
+
+/* target host supports USB sniffing */
+/* #undef PCAP_SUPPORT_USB */
+
+/* include ACN support */
+/* #undef SITA */
+
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
@@ -184,6 +223,15 @@
/* needed on HP-UX */
/* #undef _HPUX_SOURCE */
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+/* #undef _LARGEFILE_SOURCE */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
/* define on AIX to get certain functions */
/* #undef _SUN */
@@ -199,5 +247,8 @@
/* if we have u_int32_t */
/* #undef u_int32_t */
+/* if we have u_int64_t */
+/* #undef u_int64_t */
+
/* if we have u_int8_t */
/* #undef u_int8_t */
diff --git a/lib/libpmc/pmc.h b/lib/libpmc/pmc.h
index ee3f772..5b1ad07 100644
--- a/lib/libpmc/pmc.h
+++ b/lib/libpmc/pmc.h
@@ -29,6 +29,7 @@
#ifndef _PMC_H_
#define _PMC_H_
+#include <sys/cdefs.h>
#include <sys/pmc.h>
/*
@@ -68,6 +69,7 @@ struct pmc_pmcinfo {
* Prototypes
*/
+__BEGIN_DECLS
int pmc_allocate(const char *_ctrspec, enum pmc_mode _mode, uint32_t _flags,
int _cpu, pmc_id_t *_pmcid);
int pmc_attach(pmc_id_t _pmcid, pid_t _pid);
@@ -105,5 +107,6 @@ const char *pmc_name_of_state(enum pmc_state _ps);
int pmc_event_names_of_class(enum pmc_class _cl, const char ***_eventnames,
int *_nevents);
+__END_DECLS
#endif
diff --git a/lib/libpmc/pmclog.h b/lib/libpmc/pmclog.h
index e3e5c89..b7c9c84 100644
--- a/lib/libpmc/pmclog.h
+++ b/lib/libpmc/pmclog.h
@@ -33,6 +33,7 @@
#ifndef _PMCLOG_H_
#define _PMCLOG_H_
+#include <sys/cdefs.h>
#include <sys/pmclog.h>
enum pmclog_state {
@@ -158,10 +159,12 @@ struct pmclog_ev {
#define PMCLOG_FD_NONE (-1)
+__BEGIN_DECLS
void *pmclog_open(int _fd);
int pmclog_feed(void *_cookie, char *_data, int _len);
int pmclog_read(void *_cookie, struct pmclog_ev *_ev);
void pmclog_close(void *_cookie);
+__END_DECLS
#endif
diff --git a/lib/libstand/gets.c b/lib/libstand/gets.c
index 575134c..7d54b00 100644
--- a/lib/libstand/gets.c
+++ b/lib/libstand/gets.c
@@ -74,7 +74,7 @@ ngets(char *buf, int n)
putchar('\n');
break;
default:
- if ((n < 1) || ((lp - buf) < n)) {
+ if ((n < 1) || ((lp - buf) < n - 1)) {
*lp++ = c;
putchar(c);
}
diff --git a/lib/libthr/Makefile b/lib/libthr/Makefile
index eba30d8..ee981d8 100644
--- a/lib/libthr/Makefile
+++ b/lib/libthr/Makefile
@@ -25,6 +25,7 @@ CFLAGS+=-I${.CURDIR}/../../libexec/rtld-elf
CFLAGS+=-I${.CURDIR}/../../libexec/rtld-elf/${MACHINE_ARCH}
CFLAGS+=-I${.CURDIR}/../libthread_db
CFLAGS+=-Winline
+LDFLAGS+=-Wl,-znodelete
VERSION_DEF=${.CURDIR}/../libc/Versions.def
SYMBOL_MAPS=${.CURDIR}/pthread.map
diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c
index bc410d1..afb5a1d 100644
--- a/lib/libthr/thread/thr_fork.c
+++ b/lib/libthr/thread/thr_fork.c
@@ -173,8 +173,11 @@ _fork(void)
/* Ready to continue, unblock signals. */
_thr_signal_unblock(curthread);
- if (unlock_malloc)
+ if (unlock_malloc) {
+ __isthreaded = 1;
_malloc_postfork();
+ __isthreaded = 0;
+ }
/* Run down atfork child handlers. */
TAILQ_FOREACH(af, &_thr_atfork_list, qe) {
diff --git a/lib/libufs/block.c b/lib/libufs/block.c
index 5450a5d..212cdc6 100644
--- a/lib/libufs/block.c
+++ b/lib/libufs/block.c
@@ -64,8 +64,10 @@ bread(struct uufsd *disk, ufs2_daddr_t blockno, void *data, size_t size)
*/
if (((intptr_t)data) & 0x3f) {
p2 = malloc(size);
- if (p2 == NULL)
+ if (p2 == NULL) {
ERROR(disk, "allocate bounce buffer");
+ goto fail;
+ }
}
cnt = pread(disk->d_fd, p2, size, (off_t)(blockno * disk->d_bsize));
if (cnt == -1) {
@@ -115,8 +117,10 @@ bwrite(struct uufsd *disk, ufs2_daddr_t blockno, const void *data, size_t size)
*/
if (((intptr_t)data) & 0x3f) {
p2 = malloc(size);
- if (p2 == NULL)
+ if (p2 == NULL) {
ERROR(disk, "allocate bounce buffer");
+ return (-1);
+ }
memcpy(p2, data, size);
data = p2;
}
diff --git a/lib/libusb/libusb.3 b/lib/libusb/libusb.3
index 3883fe7..60979d5 100644
--- a/lib/libusb/libusb.3
+++ b/lib/libusb/libusb.3
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd Feb 14, 2009
+.Dd April 5, 2009
.Dt LIBUSB 3
.Os
.Sh NAME
@@ -43,9 +43,165 @@ USB access library (libusb -lusb)
.
.
.Sh SYNOPSIS
-.
-.
.In libusb20.h
+.Ft int
+.Fn libusb20_tr_close "struct libusb20_transfer *xfer"
+.Ft int
+.Fn libusb20_tr_open "struct libusb20_transfer *xfer" "uint32_t max_buf_size" "uint32_t max_frame_count" "uint8_t ep_no"
+.Ft struct libusb20_transfer*
+.Fn libusb20_tr_get_pointer "struct libusb20_device *pdev" "uint16_t tr_index"
+.Ft uint16_t
+.Fn libusb20_tr_get_time_complete "struct libusb20_transfer *xfer"
+.Ft uint32_t
+.Fn libusb20_tr_get_actual_frames "struct libusb20_transfer *xfer"
+.Ft uint32_t
+.Fn libusb20_tr_get_actual_length "struct libusb20_transfer *xfer"
+.Ft uint32_t
+.Fn libusb20_tr_get_max_frames "struct libusb20_transfer *xfer"
+.Ft uint32_t
+.Fn libusb20_tr_get_max_packet_length "struct libusb20_transfer *xfer"
+.Ft uint32_t
+.Fn libusb20_tr_get_max_total_length "struct libusb20_transfer *xfer"
+.Ft uint8_t
+.Fn libusb20_tr_get_status "struct libusb20_transfer *xfer"
+.Ft uint8_t
+.Fn libusb20_tr_pending "struct libusb20_transfer *xfer"
+.Ft void
+.Fn libusb20_tr_callback_wrapper "struct libusb20_transfer *xfer"
+.Ft void
+.Fn libusb20_tr_clear_stall_sync "struct libusb20_transfer *xfer"
+.Ft void
+.Fn libusb20_tr_drain "struct libusb20_transfer *xfer"
+.Ft void
+.Fn libusb20_tr_set_buffer "struct libusb20_transfer *xfer" "void *buffer" "uint16_t fr_index"
+.Ft void
+.Fn libusb20_tr_set_callback "struct libusb20_transfer *xfer" "libusb20_tr_callback_t *cb"
+.Ft void
+.Fn libusb20_tr_set_flags "struct libusb20_transfer *xfer" "uint8_t flags"
+.Ft void
+.Fn libusb20_tr_set_length "struct libusb20_transfer *xfer" "uint32_t length" "uint16_t fr_index"
+.Ft void
+.Fn libusb20_tr_set_priv_sc0 "struct libusb20_transfer *xfer" "void *sc0"
+.Ft void
+.Fn libusb20_tr_set_priv_sc1 "struct libusb20_transfer *xfer" "void *sc1"
+.Ft void
+.Fn libusb20_tr_set_timeout "struct libusb20_transfer *xfer" "uint32_t timeout"
+.Ft void
+.Fn libusb20_tr_set_total_frames "struct libusb20_transfer *xfer" "uint32_t nframes"
+.Ft void
+.Fn libusb20_tr_setup_bulk "struct libusb20_transfer *xfer" "void *pbuf" "uint32_t length" "uint32_t timeout"
+.Ft void
+.Fn libusb20_tr_setup_control "struct libusb20_transfer *xfer" "void *psetup" "void *pbuf" "uint32_t timeout"
+.Ft void
+.Fn libusb20_tr_setup_intr "struct libusb20_transfer *xfer" "void *pbuf" "uint32_t length" "uint32_t timeout"
+.Ft void
+.Fn libusb20_tr_setup_isoc "struct libusb20_transfer *xfer" "void *pbuf" "uint32_t length" "uint61_t fr_index"
+.Ft void
+.Fn libusb20_tr_start "struct libusb20_transfer *xfer"
+.Ft void
+.Fn libusb20_tr_stop "struct libusb20_transfer *xfer"
+.Ft void
+.Fn libusb20_tr_submit "struct libusb20_transfer *xfer"
+.Ft void *
+.Fn libusb20_tr_get_priv_sc0 "struct libusb20_transfer *xfer"
+.Ft void *
+.Fn libusb20_tr_get_priv_sc1 "struct libusb20_transfer *xfer"
+.Ft const char *
+.Fn libusb20_dev_get_backend_name "struct libusb20_device *"
+.Ft int
+.Fn libusb20_dev_get_info "struct libusb20_device *pdev" "struct usb2_device_info *pinfo"
+.Ft int
+.Fn libusb20_dev_get_iface_desc "struct libusb20_device *pdev" "uint8_t iface_index" "char *buf" "uint8_t len"
+.Ft const char *
+.Fn libusb20_dev_get_desc "struct libusb20_device *pdev"
+.Ft int
+.Fn libusb20_dev_claim_interface "struct libusb20_device *pdev" "uint8_t iface_index"
+.Ft int
+.Fn libusb20_dev_close "struct libusb20_device *pdev"
+.Ft int
+.Fn libusb20_dev_detach_kernel_driver "struct libusb20_device *pdev" "uint8_t iface_index"
+.Ft int
+.Fn libusb20_dev_set_config_index "struct libusb20_device *pdev" "uint8_t configIndex"
+.Ft int
+.Fn libusb20_dev_get_debug "struct libusb20_device *pdev"
+.Ft int
+.Fn libusb20_dev_get_fd "struct libusb20_device *pdev"
+.Ft int
+.Fn libusb20_dev_kernel_driver_active "struct libusb20_device *pdev" "uint8_t iface_index"
+.Ft int
+.Fn libusb20_dev_open "struct libusb20_device *pdev" "uint16_t transfer_max"
+.Ft int
+.Fn libusb20_dev_process "struct libusb20_device *pdev"
+.Ft int
+.Fn libusb20_dev_release_interface "struct libusb20_device *pdev" "uint8_t iface_index"
+.Ft int
+.Fn libusb20_dev_request_sync "struct libusb20_device *pdev" "struct LIBUSB20_CONTROL_SETUP_DECODED *setup" "void *data" "uint16_t *pactlen" "uint32_t timeout" "uint8_t flags"
+.Ft int
+.Fn libusb20_dev_req_string_sync "struct libusb20_device *pdev" "uint8_t index" "uint16_t langid" "void *ptr" "uint16_t len"
+.Ft int
+.Fn libusb20_dev_req_string_simple_sync "struct libusb20_device *pdev" "uint8_t index" "void *ptr" "uint16_t len"
+.Ft int
+.Fn libusb20_dev_reset "struct libusb20_device *pdev"
+.Ft int
+.Fn libusb20_dev_set_power_mode "struct libusb20_device *pdev" "uint8_t power_mode"
+.Ft uint8_t
+.Fn libusb20_dev_get_power_mode "struct libusb20_device *pdev"
+.Ft int
+.Fn libusb20_dev_set_alt_index "struct libusb20_device *pdev" "uint8_t iface_index" "uint8_t alt_index"
+.Ft int
+.Fn libusb20_dev_get_device_desc "struct libusb20_device *pdev" "uint8_t iface_indexr", "char *buf" "uint8_t len"
+.Ft struct libusb20_config *
+.Fn libusb20_dev_alloc_config "struct libusb20_device *pdev" "uint8_t config_index"
+.Ft struct libusb20_device *
+.Fn libusb20_dev_alloc "void"
+.Ft uint8_t
+.Fn libusb20_dev_get_address "struct libusb20_device *pdev"
+.Ft uint8_t
+.Fn libusb20_dev_get_bus_number "struct libusb20_device *pdev"
+.Ft uint8_t
+.Fn libusb20_dev_get_mode "struct libusb20_device *pdev"
+.Ft uint8_t
+.Fn libusb20_dev_get_speed "struct libusb20_device *pdev"
+.Ft uint8_t
+.Fn libusb20_dev_get_config_index "struct libusb20_device *pdev"
+.Ft void
+.Fn libusb20_dev_free "struct libusb20_device *pdev"
+.Ft void
+.Fn libusb20_dev_set_debug "struct libusb20_device *pdev" "int debug"
+.Ft void
+.Fn libusb20_dev_wait_process "struct libusb20_device *pdev" "int timeout"
+.Ft int
+.Fn libusb20_be_get_template "struct libusb20_backend *pbe" "int *ptemp"
+.Ft int
+.Fn libusb20_be_set_template "struct libusb20_backend *pbe" "int temp"
+.Ft int
+.Fn libusb20_be_get_dev_quirk "struct libusb20_backend *pber", "uint16_t index" "struct libusb20_quirk *pq"
+.Ft int
+.Fn libusb20_be_get_quirk_name "struct libusb20_backend *pbe" "uint16_t index" "struct libusb20_quirk *pq"
+.Ft int
+.Fn libusb20_be_add_dev_quirk "struct libusb20_backend *pbe" "struct libusb20_quirk *pq"
+.Ft int
+.Fn libusb20_be_remove_dev_quirk "struct libusb20_backend *pbe" "struct libusb20_quirk *pq"
+.Ft struct libusb20_backend *
+.Fn libusb20_be_alloc_linux "void"
+.Ft struct libusb20_device *
+.Fn libusb20_be_device_foreach "struct libusb20_backend *pbe" "struct libusb20_device *pdev"
+.Ft void
+.Fn libusb20_be_dequeue_device "struct libusb20_backend *pbe" "struct libusb20_device *pdev"
+.Ft void
+.Fn libusb20_be_enqueue_device "struct libusb20_backend *pbe" "struct libusb20_device *pdev"
+.Ft void
+.Fn libusb20_be_free "struct libusb20_backend *pbe"
+.Ft uint8_t
+.Fn libusb20_me_get_1 "const struct libusb20_me_struct *me" "uint16_t off"
+.Ft uint16_t
+.Fn libusb20_me_get_2 "const struct libusb20_me_struct *me" "uint16_t off"
+.Ft uint16_t
+.Fn libusb20_me_encode "void *pdata" "uint16_t len" "const void *pdecoded"
+.Ft uint16_t
+.Fn libusb20_me_decode "const void *pdata" "uint16_t len" "void *pdecoded"
+.Ft "const uint8_t *"
+.Fn libusb20_desc_foreach "const struct libusb20_me_struct *me" "const uint8_t *pdesc"
.
.
.Sh DESCRIPTION
@@ -60,9 +216,9 @@ USB through the USB file system interface.
.
.Pp
.
-.Fn libusb20_tr_close pxfer
-This function will release all kernel resources associated with an USB
-.Fa pxfer .
+.Fn libusb20_tr_close
+will release all kernel resources associated with an USB
+.Fa xfer .
.
This function returns zero upon success.
.
@@ -70,8 +226,8 @@ Non-zero return values indicate a LIBUSB20_ERROR value.
.
.Pp
.
-.Fn libusb20_tr_open pxfer max_buf_size max_frame_count ep_no
-This function will allocate kernel resources like
+.Fn libusb20_tr_open
+will allocate kernel resources like
.Fa max_buf_size
and
.Fa max_frame_count
@@ -86,8 +242,8 @@ Non-zero return values indicate a LIBUSB20_ERROR value.
.
.Pp
.
-.Fn libusb20_tr_get_pointer pdev tr_index
-This function will return a pointer to the allocated USB transfer according to the
+.Fn libusb20_tr_get_pointer
+will return a pointer to the allocated USB transfer according to the
.Fa pdev
and
.Fa tr_index
@@ -97,33 +253,33 @@ This function returns NULL in case of failure.
.
.Pp
.
-.Fn libusb20_tr_get_time_complete pxfer
-This function will return the completion time of an USB transfer in
+.Fn libusb20_tr_get_time_complete
+will return the completion time of an USB transfer in
millisecond units. This function is most useful for isochronous USB
transfers when doing echo cancelling.
.
.Pp
.
-.Fn libusb20_tr_get_actual_frames pxfer
-This function will return the actual number of USB frames after an USB
+.Fn libusb20_tr_get_actual_frames
+will return the actual number of USB frames after an USB
transfer completed. A value of zero means that no data was transferred.
.
.Pp
.
-.Fn libusb20_tr_get_actual_length pxfer
-This function will return the sum of the actual length for all
+.Fn libusb20_tr_get_actual_length
+will return the sum of the actual length for all
transferred USB frames for the given USB transfer.
.
.Pp
.
-.Fn libusb20_tr_get_max_frames pxfer
-This function will return the maximum number of USB frames that were
+.Fn libusb20_tr_get_max_frames
+will return the maximum number of USB frames that were
allocated when an USB transfer was setup for the given USB transfer.
.
.Pp
.
-.Fn libusb20_tr_get_max_packet_length pxfer
-This function will return the maximum packet length in bytes
+.Fn libusb20_tr_get_max_packet_length
+will return the maximum packet length in bytes
associated with the given USB transfer.
.
The packet length can be used round up buffer sizes so that short USB
@@ -132,33 +288,33 @@ packets are avoided for proxy buffers.
.
.Pp
.
-.Fn libusb20_tr_get_max_total_length pxfer
-This function will return the maximum value for the length sum of all
+.Fn libusb20_tr_get_max_total_length
+function will return the maximum value for the length sum of all
USB frames associated with an USB transfer.
.
.Pp
.
-.Fn libusb20_tr_get_status pxfer
-This function will return the status of an USB transfer.
+.Fn libusb20_tr_get_status
+will return the status of an USB transfer.
.
Status values are defined by a set of LIBUSB20_TRANSFER_XXX enums.
.
.Pp
.
-.Fn libusb20_tr_pending pxfer
-This function will return non-zero if the given USB transfer is
+.Fn libusb20_tr_pending
+will return non-zero if the given USB transfer is
pending for completion.
.
Else this function returns zero.
.
.Pp
.
-.Fn libusb20_tr_callback_wrapper pxfer
+.Fn libusb20_tr_callback_wrapper
This is an internal function used to wrap asynchronous USB callbacks.
.
.Pp
.
-.Fn libusb20_tr_clear_stall_sync pxfer
+.Fn libusb20_tr_clear_stall_sync
This is an internal function used to synchronously clear the stall on
the given USB transfer.
.
@@ -171,14 +327,14 @@ been called.
.
.Pp
.
-.Fn libusb20_tr_drain pxfer
-This function will stop the given USB transfer and will not return
+.Fn libusb20_tr_drain
+will stop the given USB transfer and will not return
until the USB transfer has been stopped in hardware.
.
.Pp
.
-.Fn libusb20_tr_set_buffer pxfer pbuf fr_index
-This function is used to set the
+.Fn libusb20_tr_set_buffer
+is used to set the
.Fa buffer
pointer for the given USB transfer and
.Fa fr_index .
@@ -188,16 +344,16 @@ Typically the frame index is zero.
.
.Pp
.
-.Fn libusb20_tr_set_callback pxfer pcallback
-This function is used to set the USB callback for asynchronous USB
+.Fn libusb20_tr_set_callback
+is used to set the USB callback for asynchronous USB
transfers.
.
The callback type is defined by libusb20_tr_callback_t.
.
.Pp
.
-.Fn libusb20_tr_set_flags pxfer flags
-This function is used to set various USB flags for the given USB transfer.
+.Fn libusb20_tr_set_flags
+is used to set various USB flags for the given USB transfer.
.Bl -tag
.It LIBUSB20_TRANSFER_SINGLE_SHORT_NOT_OK
Report a short frame as error.
@@ -211,23 +367,23 @@ Will do a clear-stall before starting the transfer.
.
.Pp
.
-.Fn libusb20_tr_set_length pxfer length fr_index
-This function sets the length of a given USB transfer and frame index.
+.Fn libusb20_tr_set_length
+sets the length of a given USB transfer and frame index.
.
.Pp
.
-.Fn libusb20_tr_set_priv_sc0 pxfer psc0
-This function sets private driver pointer number zero.
+.Fn libusb20_tr_set_priv_sc0
+sets private driver pointer number zero.
.
.Pp
.
-.Fn libusb20_tr_set_priv_sc1 pxfer psc1
-This function sets private driver pointer number one.
+.Fn libusb20_tr_set_priv_sc1
+sets private driver pointer number one.
.
.Pp
.
-.Fn libusb20_tr_set_timeout pxfer timeout
-This function sets the timeout for the given USB transfer.
+.Fn libusb20_tr_set_timeout
+sets the timeout for the given USB transfer.
.
A timeout value of zero means no timeout.
.
@@ -235,36 +391,36 @@ The timeout is given in milliseconds.
.
.Pp
.
-.Fn libusb20_tr_set_total_frames pxfer nframes
-This function sets the total number of frames that should be executed when the USB transfer is submitted.
+.Fn libusb20_tr_set_total_frames
+sets the total number of frames that should be executed when the USB transfer is submitted.
.
The total number of USB frames must be less than the maximum number of USB frames associated with the given USB transfer.
.
.Pp
.
-.Fn libusb20_tr_setup_bulk pxfer pbuf length timeout
-This function is a helper function for setting up a single frame USB BULK transfer.
+.Fn libusb20_tr_setup_bulk
+is a helper function for setting up a single frame USB BULK transfer.
.
.Pp
.
-.Fn libusb20_tr_setup_control pxfer psetup pbuf timeout
-This function is a helper function for setting up a single or dual
+.Fn libusb20_tr_setup_control
+is a helper function for setting up a single or dual
frame USB CONTROL transfer depending on the control transfer length.
.
.Pp
.
-.Fn libusb20_tr_setup_intr pxfer pbuf length timeout
-This function is a helper function for setting up a single frame USB INTERRUPT transfer.
+.Fn libusb20_tr_setup_intr
+is a helper function for setting up a single frame USB INTERRUPT transfer.
.
.Pp
.
-.Fn libusb20_tr_setup_isoc pxfer pbuf length fr_index
-This function is a helper function for setting up a multi frame USB ISOCHRONOUS transfer.
+.Fn libusb20_tr_setup_isoc
+is a helper function for setting up a multi frame USB ISOCHRONOUS transfer.
.
.Pp
.
-.Fn libusb20_tr_start pxfer
-This function will get the USB transfer started, if not already
+.Fn libusb20_tr_start
+will get the USB transfer started, if not already
started.
.
This function will not get the transfer queued in hardware.
@@ -273,29 +429,29 @@ This function is non-blocking.
.
.Pp
.
-.Fn libusb20_tr_stop pxfer
-This function will get the USB transfer stopped, if not already stopped.
+.Fn libusb20_tr_stop
+will get the USB transfer stopped, if not already stopped.
.
This function is non-blocking, which means that the actual stop can
happen after the return of this function.
.
.Pp
.
-.Fn libusb20_tr_submit pxfer
-This function will get the USB transfer queued in hardware.
+.Fn libusb20_tr_submit
+will get the USB transfer queued in hardware.
.
.
.Pp
.
-.Fn libusb20_tr_get_priv_sc0 pxfer
-This function returns private driver pointer number zero associated
+.Fn libusb20_tr_get_priv_sc0
+returns private driver pointer number zero associated
with an USB transfer.
.
.
.Pp
.
-.Fn libusb20_tr_get_priv_sc1 pxfer
-This function returns private driver pointer number one associated
+.Fn libusb20_tr_get_priv_sc1
+returns private driver pointer number one associated
with an USB transfer.
.
.
@@ -303,13 +459,13 @@ with an USB transfer.
.
.Pp
.
-.Fn libusb20_dev_get_backend_name pdev
-This function returns a zero terminated string describing the backend used.
+.Fn libusb20_dev_get_backend_name
+returns a zero terminated string describing the backend used.
.
.Pp
.
-.Fn libusb20_dev_get_info pdev pinfo
-This function retrives the BSD specific usb2_device_info structure into the memory location given by
+.Fn libusb20_dev_get_info
+retrives the BSD specific usb2_device_info structure into the memory location given by
.Fa pinfo .
The USB device given by
.Fa pdev
@@ -318,8 +474,8 @@ This function returns zero on success else a LIBUSB20_ERROR value is returned.
.
.Pp
.
-.Fn libusb20_dev_get_iface_desc pdev iface_index pbuf len
-This function retrieves the kernel interface description for the given USB
+.Fn libusb20_dev_get_iface_desc
+retrieves the kernel interface description for the given USB
.Fa iface_index .
The format of the USB interface description is: "drivername<unit>: <description>"
The description string is always zero terminated.
@@ -331,13 +487,13 @@ This function returns zero on success else a LIBUSB20_ERROR value is returned.
.
.Pp
.
-.Fn libusb20_dev_get_desc pdev
-This function returns a zero terminated string describing the given USB device.
+.Fn libusb20_dev_get_desc
+returns a zero terminated string describing the given USB device.
The format of the string is: "drivername<unit>: <description>"
.
.Pp
.
-.Fn libusb20_dev_claim_interface pdev iface_index
+.Fn libusb20_dev_claim_interface
This function will try to claim the given USB interface given by
.Fa iface_index .
This function returns zero on success else a LIBUSB20_ERROR value is
@@ -345,16 +501,16 @@ returned.
.
.Pp
.
-.Fn libusb20_dev_close pdev
-This function will close the given USB device.
+.Fn libusb20_dev_close
+will close the given USB device.
.
This function returns zero on success else a LIBUSB20_ERROR value is
returned.
.
.Pp
.
-.Fn libusb20_dev_detach_kernel_driver pdev iface_index
-This function will try to detach the kernel driver for the USB interface given by
+.Fn libusb20_dev_detach_kernel_driver
+will try to detach the kernel driver for the USB interface given by
.Fa iface_index .
.
This function returns zero on success else a LIBUSB20_ERROR value is
@@ -362,8 +518,8 @@ returned.
.
.Pp
.
-.Fn libusb20_dev_set_config_index pdev config_index
-This function will try to set the configuration index on an USB
+.Fn libusb20_dev_set_config_index
+will try to set the configuration index on an USB
device.
.
The first configuration index is zero.
@@ -374,13 +530,13 @@ This function returns zero on success else a LIBUSB20_ERROR value is returned.
.
.Pp
.
-.Fn libusb20_dev_get_debug pdev
-This function returns the debug level of an USB device.
+.Fn libusb20_dev_get_debug
+returns the debug level of an USB device.
.
.Pp
.
-.Fn libusb20_dev_get_fd pdev
-This function returns the file descriptor of the given USB device.
+.Fn libusb20_dev_get_fd
+returns the file descriptor of the given USB device.
.
A negative value is returned when no file descriptor is present.
.
@@ -388,16 +544,16 @@ The file descriptor can be used for polling purposes.
.
.Pp
.
-.Fn libusb20_dev_kernel_driver_active pdev iface_index
-This function returns a non-zero value if a kernel driver is active on
+.Fn libusb20_dev_kernel_driver_active
+returns a non-zero value if a kernel driver is active on
the given USB interface.
.
Else zero is returned.
.
.Pp
.
-.Fn libusb20_dev_open pdev transfer_max
-This function opens an USB device so that setting up USB transfers
+.Fn libusb20_dev_open
+opens an USB device so that setting up USB transfers
becomes possible.
.
The number of USB transfers can be zero which means only control
@@ -411,8 +567,8 @@ opened.
.
.Pp
.
-.Fn libusb20_dev_process pdev
-This function is called to sync kernel USB transfers with userland USB
+.Fn libusb20_dev_process
+is called to sync kernel USB transfers with userland USB
transfers.
.
This function returns zero on success else a LIBUSB20_ERROR value is
@@ -421,16 +577,16 @@ detached.
.
.Pp
.
-.Fn libusb20_dev_release_interface pdev iface_index
-This function will try to release a claimed USB interface for the specified USB device.
+.Fn libusb20_dev_release_interface
+will try to release a claimed USB interface for the specified USB device.
.
This function returns zero on success else a LIBUSB20_ERROR value is
returned.
.
.Pp
.
-.Fn libusb20_dev_request_sync pdev psetup pdata pactlen timeout flags
-This function will perform a synchronous control request on the given
+.Fn libusb20_dev_request_sync
+will perform a synchronous control request on the given
USB device.
.
Before this call will succeed the USB device must be opened.
@@ -452,8 +608,8 @@ returned.
.
.Pp
.
-.Fn libusb20_dev_req_string_sync pdev index lang_id pbuf len
-This function will synchronously request an USB string by language ID
+.Fn libusb20_dev_req_string_sync
+will synchronously request an USB string by language ID
and string index into the given buffer limited by a maximum length.
.
This function returns zero on success else a LIBUSB20_ERROR value is
@@ -461,8 +617,8 @@ returned.
.
.Pp
.
-.Fn libusb20_dev_req_string_simple_sync pdev index pbuf len
-This function will synchronously request an USB string using the
+.Fn libusb20_dev_req_string_simple_sync
+will synchronously request an USB string using the
default language ID and convert the string into ASCII before storing
the string into the given buffer limited by a maximum length which
includes the terminating zero.
@@ -473,8 +629,8 @@ returned.
.
.Pp
.
-.Fn libusb20_dev_reset pdev
-This function will try to BUS reset the given USB device and restore
+.Fn libusb20_dev_reset
+will try to BUS reset the given USB device and restore
the last set USB configuration.
.
This function returns zero on success else a LIBUSB20_ERROR value is
@@ -482,8 +638,8 @@ returned.
.
.Pp
.
-.Fn libusb20_dev_set_power_mode pdev power_mode
-This function sets the power mode of the USB device.
+.Fn libusb20_dev_set_power_mode
+sets the power mode of the USB device.
.
Valid power modes:
.Bl -tag
@@ -499,14 +655,14 @@ returned.
.
.Pp
.
-.Fn libusb20_dev_get_power_mode pdev
-This function returns the currently selected power mode for the given
+.Fn libusb20_dev_get_power_mode
+returns the currently selected power mode for the given
USB device.
.
.Pp
.
-.Fn libusb20_dev_set_alt_index pdev iface_index alt_index
-This function will try to set the given alternate index for the given
+.Fn libusb20_dev_set_alt_index
+will try to set the given alternate index for the given
USB interface index.
.
This function returns zero on success else a LIBUSB20_ERROR value is
@@ -514,41 +670,41 @@ returned.
.
.Pp
.
-.Fn libusb20_dev_get_device_desc pdev
-This function returns a pointer to the decoded and host endian version
+.Fn libusb20_dev_get_device_desc
+returns a pointer to the decoded and host endian version
of the device descriptor.
.
The USB device need not be opened when calling this function.
.
.Pp
.
-.Fn libusb20_dev_alloc_config pdev config_index
-This function will read out and decode the USB config descriptor for
+.Fn libusb20_dev_alloc_config
+will read out and decode the USB config descriptor for
the given USB device and config index. This function returns a pointer
to the decoded configuration which must eventually be passed to
free(). NULL is returned in case of failure.
.
.Pp
.
-.Fn libusb20_dev_alloc void
-This is an internal function to allocate a new USB device.
+.Fn libusb20_dev_alloc
+is an internal function to allocate a new USB device.
.
.Pp
.
-.Fn libusb20_dev_get_address pdev
-This function returns the internal and not necessarily the real
+.Fn libusb20_dev_get_address
+returns the internal and not necessarily the real
hardware address of the given USB device.
.
.Pp
.
-.Fn libusb20_dev_get_bus_number pdev
-This function return the internal bus number which the given USB
+.Fn libusb20_dev_get_bus_number
+returns the internal bus number which the given USB
device belongs to.
.
.Pp
.
-.Fn libusb20_dev_get_mode pdev
-This function returns the current operation mode of the USB entity.
+.Fn libusb20_dev_get_mode
+returns the current operation mode of the USB entity.
.
Valid return values are:
.Bl -tag
@@ -558,8 +714,8 @@ Valid return values are:
.
.Pp
.
-.Fn libusb20_dev_get_speed pdev
-This function returns the current speed of the given USB device.
+.Fn libusb20_dev_get_speed
+returns the current speed of the given USB device.
.
.Bl -tag
.It LIBUSB20_SPEED_UNKNOWN
@@ -572,25 +728,25 @@ This function returns the current speed of the given USB device.
.
.Pp
.
-.Fn libusb20_dev_get_config_index pdev
+.Fn libusb20_dev_get_config_index
This function returns the currently select config index for the given
USB device.
.
.Pp
.
-.Fn libusb20_dev_free pdev
-This function will free the given USB device and all associated USB
+.Fn libusb20_dev_free
+will free the given USB device and all associated USB
transfers.
.
.Pp
.
-.Fn libusb20_dev_set_debug pdev debug_level
-This function will set the debug level for the given USB device.
+.Fn libusb20_dev_set_debug
+will set the debug level for the given USB device.
.
.Pp
.
-.Fn libusb20_dev_wait_process pdev timeout
-This function will wait until a pending USB transfer has completed on
+.Fn libusb20_dev_wait_process
+function will wait until a pending USB transfer has completed on
the given USB device.
.
A timeout value can be specified which is passed on to the
@@ -599,8 +755,8 @@ function.
.
.Sh USB BACKEND OPERATIONS
.
-.Fn libusb20_be_get_template pbackend ptemp
-This function will return the currently selected global USB device
+.Fn libusb20_be_get_template
+will return the currently selected global USB device
side mode template into the integer pointer
.Fa ptemp .
This function returns zero on success else a LIBUSB20_ERROR value is
@@ -608,8 +764,8 @@ returned.
.
.Pp
.
-.Fn libusb20_be_set_template pbackend temp
-This function will set the global USB device side mode template to
+.Fn libusb20_be_set_template
+will set the global USB device side mode template to
.Fa temp .
The new template is not activated until after the next USB
enumeration.
@@ -623,7 +779,7 @@ returned.
.
.Pp
.
-.Fn libusb20_be_get_dev_quirk pbackend index pquirk
+.Fn libusb20_be_get_dev_quirk
This function will return the device quirk according to
.Fa index
into the libusb20_quirk structure pointed to by
@@ -636,8 +792,8 @@ returned.
.
.Pp
.
-.Fn libusb20_be_get_quirk_name pbackend index pquirk
-This function will return the quirk name according to
+.Fn libusb20_be_get_quirk_name
+will return the quirk name according to
.Fa index
into the libusb20_quirk structure pointed to by
.Fa pq .
@@ -649,8 +805,8 @@ returned.
.
.Pp
.
-.Fn libusb20_be_add_dev_quirk pbackend pquirk
-This function will add the libusb20_quirk structure pointed to by the
+.Fn libusb20_be_add_dev_quirk
+will add the libusb20_quirk structure pointed to by the
.Fa pq
argument into the device quirk list.
.
@@ -662,8 +818,8 @@ returned.
.
.Pp
.
-.Fn libusb20_be_remove_dev_quirk pbackend pquirk
-This function will remove the quirk matching the libusb20_quirk structure pointed to by the
+.Fn libusb20_be_remove_dev_quirk
+will remove the quirk matching the libusb20_quirk structure pointed to by the
.Fa pq
argument from the device quirk list.
.
@@ -673,15 +829,15 @@ returned.
If the given quirk does not exist LIBUSB20_ERROR_NOT_FOUND is
returned.
.
-.Fn libusb20_be_alloc_linux void
+.Fn libusb20_be_alloc_linux
These functions are used to allocate a specific USB backend or the
operating system default USB backend. Allocating a backend is a way to
scan for currently present USB devices.
.
.Pp
.
-.Fn libusb20_be_device_foreach pbackend pdev
-This function is used to iterate USB devices present in a USB backend.
+.Fn libusb20_be_device_foreach
+is used to iterate USB devices present in a USB backend.
.
The starting value of
.Fa pdev
@@ -693,23 +849,23 @@ If NULL is returned the end of the USB device list has been reached.
.
.Pp
.
-.Fn libusb20_be_dequeue_device pbackend pdev
-This function will dequeue the given USB device pointer from the
+.Fn libusb20_be_dequeue_device
+will dequeue the given USB device pointer from the
backend USB device list.
.
Dequeued USB devices will not be freed when the backend is freed.
.
.Pp
.
-.Fn libusb20_be_enqueue_device pbackend pdev
+.Fn libusb20_be_enqueue_device
This function will enqueue the given USB device pointer in the backend USB device list.
.
Enqueued USB devices will get freed when the backend is freed.
.
.Pp
.
-.Fn libusb20_be_free pbackend
-This function will free the given backend and all USB devices in its device list.
+.Fn libusb20_be_free
+will free the given backend and all USB devices in its device list.
.
.
.Sh USB DESCRIPTOR PARSING
diff --git a/lib/libusb/libusb20.h b/lib/libusb/libusb20.h
index 89cb75e..5125f91 100644
--- a/lib/libusb/libusb20.h
+++ b/lib/libusb/libusb20.h
@@ -274,6 +274,8 @@ int libusb20_be_get_dev_quirk(struct libusb20_backend *pbe, uint16_t index, stru
int libusb20_be_get_quirk_name(struct libusb20_backend *pbe, uint16_t index, struct libusb20_quirk *pq);
int libusb20_be_add_dev_quirk(struct libusb20_backend *pbe, struct libusb20_quirk *pq);
int libusb20_be_remove_dev_quirk(struct libusb20_backend *pbe, struct libusb20_quirk *pq);
+int libusb20_be_get_template(struct libusb20_backend *pbe, int *ptemp);
+int libusb20_be_set_template(struct libusb20_backend *pbe, int temp);
/* USB backend operations */
diff --git a/lib/msun/src/math.h b/lib/msun/src/math.h
index 521ee3f..601d0ce 100644
--- a/lib/msun/src/math.h
+++ b/lib/msun/src/math.h
@@ -249,7 +249,6 @@ double rint(double);
double j0(double);
double j1(double);
double jn(int, double);
-double scalb(double, double);
double y0(double);
double y1(double);
double yn(int, double);
@@ -257,6 +256,10 @@ double yn(int, double);
#if __XSI_VISIBLE <= 500 || __BSD_VISIBLE
double gamma(double);
#endif
+
+#if __XSI_VISIBLE <= 600 || __BSD_VISIBLE
+double scalb(double, double);
+#endif
#endif /* __BSD_VISIBLE || __XSI_VISIBLE */
#if __BSD_VISIBLE || __ISO_C_VISIBLE >= 1999
diff --git a/lib/msun/src/math_private.h b/lib/msun/src/math_private.h
index 46d65cc..49553db 100644
--- a/lib/msun/src/math_private.h
+++ b/lib/msun/src/math_private.h
@@ -190,6 +190,27 @@ do { \
void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
#ifdef _COMPLEX_H
+
+/*
+ * C99 specifies that complex numbers have the same representation as
+ * an array of two elements, where the first element is the real part
+ * and the second element is the imaginary part.
+ */
+typedef union {
+ float complex f;
+ float a[2];
+} float_complex;
+typedef union {
+ double complex f;
+ double a[2];
+} double_complex;
+typedef union {
+ long double complex f;
+ long double a[2];
+} long_double_complex;
+#define REALPART(z) ((z).a[0])
+#define IMAGPART(z) ((z).a[1])
+
/*
* Inline functions that can be used to construct complex values.
*
@@ -203,31 +224,31 @@ void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
static __inline float complex
cpackf(float x, float y)
{
- float complex z;
+ float_complex z;
- __real__ z = x;
- __imag__ z = y;
- return (z);
+ REALPART(z) = x;
+ IMAGPART(z) = y;
+ return (z.f);
}
static __inline double complex
cpack(double x, double y)
{
- double complex z;
+ double_complex z;
- __real__ z = x;
- __imag__ z = y;
- return (z);
+ REALPART(z) = x;
+ IMAGPART(z) = y;
+ return (z.f);
}
static __inline long double complex
cpackl(long double x, long double y)
{
- long double complex z;
+ long_double_complex z;
- __real__ z = x;
- __imag__ z = y;
- return (z);
+ REALPART(z) = x;
+ IMAGPART(z) = y;
+ return (z.f);
}
#endif /* _COMPLEX_H */
diff --git a/lib/msun/src/s_cimag.c b/lib/msun/src/s_cimag.c
index aa25423..cbf6720 100644
--- a/lib/msun/src/s_cimag.c
+++ b/lib/msun/src/s_cimag.c
@@ -27,10 +27,12 @@
*/
#include <complex.h>
+#include "math_private.h"
double
cimag(double complex z)
{
+ const double_complex z1 = { .f = z };
- return (__imag__ z);
+ return (IMAGPART(z1));
}
diff --git a/lib/msun/src/s_cimagf.c b/lib/msun/src/s_cimagf.c
index 6bd00d9..4e483a2 100644
--- a/lib/msun/src/s_cimagf.c
+++ b/lib/msun/src/s_cimagf.c
@@ -27,10 +27,12 @@
*/
#include <complex.h>
+#include "math_private.h"
float
cimagf(float complex z)
{
+ const float_complex z1 = { .f = z };
- return (__imag__ z);
+ return (IMAGPART(z1));
}
diff --git a/lib/msun/src/s_cimagl.c b/lib/msun/src/s_cimagl.c
index 581f443..c50e967 100644
--- a/lib/msun/src/s_cimagl.c
+++ b/lib/msun/src/s_cimagl.c
@@ -27,10 +27,12 @@
*/
#include <complex.h>
+#include "math_private.h"
long double
cimagl(long double complex z)
{
+ const long_double_complex z1 = { .f = z };
- return (__imag__ z);
+ return (IMAGPART(z1));
}
diff --git a/libexec/bootpd/rtmsg.c b/libexec/bootpd/rtmsg.c
index 071a7d1..b691edc 100644
--- a/libexec/bootpd/rtmsg.c
+++ b/libexec/bootpd/rtmsg.c
@@ -208,7 +208,7 @@ static int rtmsg(cmd)
rtm->rtm_addrs |= RTA_GATEWAY;
rtm->rtm_rmx.rmx_expire = expire_time;
rtm->rtm_inits = RTV_EXPIRE;
- rtm->rtm_flags |= (RTF_HOST | RTF_STATIC);
+ rtm->rtm_flags |= (RTF_HOST | RTF_STATIC | RTF_LLDATA);
sin_m.sin_other = 0;
if (doing_proxy) {
if (export_only)
diff --git a/libexec/ftpd/extern.h b/libexec/ftpd/extern.h
index d869f67..895f8ae 100644
--- a/libexec/ftpd/extern.h
+++ b/libexec/ftpd/extern.h
@@ -73,6 +73,35 @@ void yyerror(char *);
int yyparse(void);
int ls_main(int, char **);
+extern int assumeutf8;
+extern char cbuf[];
+extern union sockunion data_dest;
+extern int epsvall;
+extern int form;
+extern int ftpdebug;
+extern int guest;
+extern union sockunion his_addr;
+extern char *homedir;
+extern int hostinfo;
+extern char *hostname;
+extern int maxtimeout;
+extern int logged_in;
+extern int logging;
+extern int noepsv;
+extern int noguestretr;
+extern int noretr;
+extern int paranoid;
+extern struct passwd *pw;
+extern int pdata;
+extern char proctitle[];
+extern int readonly;
+extern off_t restart_point;
+extern int timeout;
+extern char tmpline[];
+extern int type;
+extern char *typenames[]; /* defined in <arpa/ftp.h> included from ftpd.c */
+extern int usedefault;
+
struct sockaddr_in;
struct sockaddr_in6;
union sockunion {
diff --git a/libexec/ftpd/ftpcmd.y b/libexec/ftpd/ftpcmd.y
index fcef73e..07ece34 100644
--- a/libexec/ftpd/ftpcmd.y
+++ b/libexec/ftpd/ftpcmd.y
@@ -76,31 +76,6 @@ __FBSDID("$FreeBSD$");
#include "extern.h"
#include "pathnames.h"
-extern union sockunion data_dest, his_addr;
-extern int hostinfo;
-extern int logged_in;
-extern struct passwd *pw;
-extern int guest;
-extern char *homedir;
-extern int paranoid;
-extern int logging;
-extern int type;
-extern int form;
-extern int ftpdebug;
-extern int timeout;
-extern int maxtimeout;
-extern int pdata;
-extern char *hostname;
-extern char proctitle[];
-extern int usedefault;
-extern char tmpline[];
-extern int readonly;
-extern int assumeutf8;
-extern int noepsv;
-extern int noretr;
-extern int noguestretr;
-extern char *typenames[]; /* defined in <arpa/ftp.h> included from ftpd.c */
-
off_t restart_point;
static int cmd_type;
@@ -110,8 +85,6 @@ static int state;
char cbuf[512];
char *fromname = NULL;
-extern int epsvall;
-
%}
%union {
diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c
index 59dc71c..32c15f8 100644
--- a/libexec/ftpd/ftpd.c
+++ b/libexec/ftpd/ftpd.c
@@ -105,9 +105,6 @@ __FBSDID("$FreeBSD$");
static char version[] = "Version 6.00LS";
#undef main
-extern off_t restart_point;
-extern char cbuf[];
-
union sockunion ctrl_addr;
union sockunion data_source;
union sockunion data_dest;
diff --git a/libexec/rtld-elf/Symbol.map b/libexec/rtld-elf/Symbol.map
index 20f8d60..ce1e3e5 100644
--- a/libexec/rtld-elf/Symbol.map
+++ b/libexec/rtld-elf/Symbol.map
@@ -8,6 +8,7 @@ FBSD_1.0 {
dlerror;
dlopen;
dlsym;
+ dlfunc;
dlvsym;
dladdr;
dllockinit;
diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c
index f489edd..028ac80 100644
--- a/libexec/rtld-elf/map_object.c
+++ b/libexec/rtld-elf/map_object.c
@@ -91,8 +91,7 @@ map_object(int fd, const char *path, const struct stat *sb)
/*
* Scan the program header entries, and save key information.
*
- * We rely on there being exactly two load segments, text and data,
- * in that order.
+ * We expect that the loadable segments are ordered by load address.
*/
phdr = (Elf_Phdr *) ((char *)hdr + hdr->e_phoff);
phsize = hdr->e_phnum * sizeof (phdr[0]);
@@ -153,8 +152,8 @@ map_object(int fd, const char *path, const struct stat *sb)
mapsize = base_vlimit - base_vaddr;
base_addr = hdr->e_type == ET_EXEC ? (caddr_t) base_vaddr : NULL;
- mapbase = mmap(base_addr, mapsize, convert_prot(segs[0]->p_flags),
- convert_flags(segs[0]->p_flags), fd, base_offset);
+ mapbase = mmap(base_addr, mapsize, PROT_NONE, MAP_ANON | MAP_PRIVATE |
+ MAP_NOCORE, -1, 0);
if (mapbase == (caddr_t) -1) {
_rtld_error("%s: mmap of entire address space failed: %s",
path, strerror(errno));
@@ -167,7 +166,7 @@ map_object(int fd, const char *path, const struct stat *sb)
return NULL;
}
- for (i = 0; i <= nsegs; i++) {
+ for (i = 0; i <= nsegs; i++) {
/* Overlay the segment onto the proper region. */
data_offset = trunc_page(segs[i]->p_offset);
data_vaddr = trunc_page(segs[i]->p_vaddr);
@@ -175,8 +174,7 @@ map_object(int fd, const char *path, const struct stat *sb)
data_addr = mapbase + (data_vaddr - base_vaddr);
data_prot = convert_prot(segs[i]->p_flags);
data_flags = convert_flags(segs[i]->p_flags) | MAP_FIXED;
- /* Do not call mmap on the first segment - this is redundant */
- if (i && mmap(data_addr, data_vlimit - data_vaddr, data_prot,
+ if (mmap(data_addr, data_vlimit - data_vaddr, data_prot,
data_flags, fd, data_offset) == (caddr_t) -1) {
_rtld_error("%s: mmap of data failed: %s", path, strerror(errno));
return NULL;
@@ -207,9 +205,8 @@ map_object(int fd, const char *path, const struct stat *sb)
bss_vlimit = round_page(segs[i]->p_vaddr + segs[i]->p_memsz);
bss_addr = mapbase + (bss_vaddr - base_vaddr);
if (bss_vlimit > bss_vaddr) { /* There is something to do */
- if (mmap(bss_addr, bss_vlimit - bss_vaddr, data_prot,
- MAP_PRIVATE|MAP_FIXED|MAP_ANON, -1, 0) == (caddr_t) -1) {
- _rtld_error("%s: mmap of bss failed: %s", path,
+ if (mprotect(bss_addr, bss_vlimit - bss_vaddr, data_prot) == -1) {
+ _rtld_error("%s: mprotect of bss failed: %s", path,
strerror(errno));
return NULL;
}
@@ -348,6 +345,8 @@ obj_free(Obj_Entry *obj)
free(obj->vertab);
if (obj->origin_path)
free(obj->origin_path);
+ if (obj->z_origin)
+ free(obj->rpath);
if (obj->priv)
free(obj->priv);
if (obj->path)
diff --git a/libexec/rtld-elf/rtld.1 b/libexec/rtld-elf/rtld.1
index 011a693..839d5f1 100644
--- a/libexec/rtld-elf/rtld.1
+++ b/libexec/rtld-elf/rtld.1
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 15, 2008
+.Dd April 1, 2009
.Dt RTLD 1
.Os
.Sh NAME
@@ -58,6 +58,25 @@ to be called on a per-object basis, giving a shared object an opportunity
to perform any extra set-up before execution of the program proper begins.
This is useful for C++ libraries that contain static constructors.
.Pp
+When resolving dependencies for the loaded objects,
+.Nm
+may be allowed to translate dynamic token strings in rpath and soname
+by setting
+.Fl "z origin"
+option of the static linker
+.Xr ld 1 .
+The following strings are recognized now:
+.Bl -tag -width ".Pa $PLATFORM"
+.It Pa $ORIGIN
+Translated to the full path of the loaded object.
+.It Pa $OSNAME
+Translated to the name of the operating system implementation.
+.It Pa $OSREL
+Translated to the release level of the operating system.
+.It Pa $PLATFORM
+Translated to the machine hardware platform.
+.El
+.Pp
The
.Nm
utility itself is loaded by the kernel together with any dynamically-linked
@@ -116,6 +135,11 @@ If set, disables the use of
and
.Ev LD_LIBMAP .
This variable is unset for set-user-ID and set-group-ID programs.
+.It Ev LD_ELF_HINTS_PATH
+This variable will override the default location of
+.Dq hints
+file.
+This variable is unset for set-user-ID and set-group-ID programs.
.It Ev LD_LIBRARY_PATH
A colon separated list of directories, overriding the default search path
for shared libraries.
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index f67093a..40ed6ed 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -41,6 +41,7 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/uio.h>
+#include <sys/utsname.h>
#include <sys/ktrace.h>
#include <dlfcn.h>
@@ -118,6 +119,7 @@ static void objlist_remove_unref(Objlist *);
static void *path_enumerate(const char *, path_enum_proc, void *);
static int relocate_objects(Obj_Entry *, bool, Obj_Entry *);
static int rtld_dirname(const char *, char *);
+static int rtld_dirname_abs(const char *, char *);
static void rtld_exit(void);
static char *search_library_path(const char *, const char *);
static const void **get_program_var_addr(const char *);
@@ -134,6 +136,9 @@ static void unlink_object(Obj_Entry *);
static void unload_object(Obj_Entry *);
static void unref_dag(Obj_Entry *);
static void ref_dag(Obj_Entry *);
+static int origin_subst_one(char **res, const char *real, const char *kw,
+ const char *subst, char *may_free);
+static char *origin_subst(const char *real, const char *origin_path);
static int rtld_verify_versions(const Objlist *);
static int rtld_verify_object_versions(Obj_Entry *);
static void object_add_name(Obj_Entry *, const char *);
@@ -157,6 +162,7 @@ static char *ld_debug; /* Environment variable for debugging */
static char *ld_library_path; /* Environment variable for search path */
static char *ld_preload; /* Environment variable for libraries to
load first */
+static char *ld_elf_hints_path; /* Environment variable for alternative hints path */
static char *ld_tracing; /* Called from ldd to print libs */
static char *ld_utrace; /* Use utrace() to log events. */
static Obj_Entry *obj_list; /* Head of linked list of shared objects */
@@ -194,6 +200,7 @@ static func_ptr_type exports[] = {
(func_ptr_type) &dlerror,
(func_ptr_type) &dlopen,
(func_ptr_type) &dlsym,
+ (func_ptr_type) &dlfunc,
(func_ptr_type) &dlvsym,
(func_ptr_type) &dladdr,
(func_ptr_type) &dllockinit,
@@ -365,17 +372,23 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
unsetenv(LD_ "LIBRARY_PATH");
unsetenv(LD_ "LIBMAP_DISABLE");
unsetenv(LD_ "DEBUG");
+ unsetenv(LD_ "ELF_HINTS_PATH");
}
ld_debug = getenv(LD_ "DEBUG");
libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL;
libmap_override = getenv(LD_ "LIBMAP");
ld_library_path = getenv(LD_ "LIBRARY_PATH");
ld_preload = getenv(LD_ "PRELOAD");
+ ld_elf_hints_path = getenv(LD_ "ELF_HINTS_PATH");
dangerous_ld_env = libmap_disable || (libmap_override != NULL) ||
- (ld_library_path != NULL) || (ld_preload != NULL);
+ (ld_library_path != NULL) || (ld_preload != NULL) ||
+ (ld_elf_hints_path != NULL);
ld_tracing = getenv(LD_ "TRACE_LOADED_OBJECTS");
ld_utrace = getenv(LD_ "UTRACE");
+ if ((ld_elf_hints_path == NULL) || strlen(ld_elf_hints_path) == 0)
+ ld_elf_hints_path = _PATH_ELF_HINTS;
+
if (ld_debug != NULL && *ld_debug != '\0')
debug = 1;
dbg("%s is initialized, base address = %p", __progname,
@@ -412,7 +425,25 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
die();
}
- obj_main->path = xstrdup(argv0);
+ if (aux_info[AT_EXECPATH] != 0) {
+ char *kexecpath;
+ char buf[MAXPATHLEN];
+
+ kexecpath = aux_info[AT_EXECPATH]->a_un.a_ptr;
+ dbg("AT_EXECPATH %p %s", kexecpath, kexecpath);
+ if (kexecpath[0] == '/')
+ obj_main->path = kexecpath;
+ else if (getcwd(buf, sizeof(buf)) == NULL ||
+ strlcat(buf, "/", sizeof(buf)) >= sizeof(buf) ||
+ strlcat(buf, kexecpath, sizeof(buf)) >= sizeof(buf))
+ obj_main->path = xstrdup(argv0);
+ else
+ obj_main->path = xstrdup(buf);
+ } else {
+ dbg("No AT_EXECPATH");
+ obj_main->path = xstrdup(argv0);
+ }
+ dbg("obj_main path %s", obj_main->path);
obj_main->mainprog = true;
/*
@@ -614,6 +645,83 @@ basename(const char *name)
return p != NULL ? p + 1 : name;
}
+static struct utsname uts;
+
+static int
+origin_subst_one(char **res, const char *real, const char *kw, const char *subst,
+ char *may_free)
+{
+ const char *p, *p1;
+ char *res1;
+ int subst_len;
+ int kw_len;
+
+ res1 = *res = NULL;
+ p = real;
+ subst_len = kw_len = 0;
+ for (;;) {
+ p1 = strstr(p, kw);
+ if (p1 != NULL) {
+ if (subst_len == 0) {
+ subst_len = strlen(subst);
+ kw_len = strlen(kw);
+ }
+ if (*res == NULL) {
+ *res = xmalloc(PATH_MAX);
+ res1 = *res;
+ }
+ if ((res1 - *res) + subst_len + (p1 - p) >= PATH_MAX) {
+ _rtld_error("Substitution of %s in %s cannot be performed",
+ kw, real);
+ if (may_free != NULL)
+ free(may_free);
+ free(res);
+ return (false);
+ }
+ memcpy(res1, p, p1 - p);
+ res1 += p1 - p;
+ memcpy(res1, subst, subst_len);
+ res1 += subst_len;
+ p = p1 + kw_len;
+ } else {
+ if (*res == NULL) {
+ if (may_free != NULL)
+ *res = may_free;
+ else
+ *res = xstrdup(real);
+ return (true);
+ }
+ *res1 = '\0';
+ if (may_free != NULL)
+ free(may_free);
+ if (strlcat(res1, p, PATH_MAX - (res1 - *res)) >= PATH_MAX) {
+ free(res);
+ return (false);
+ }
+ return (true);
+ }
+ }
+}
+
+static char *
+origin_subst(const char *real, const char *origin_path)
+{
+ char *res1, *res2, *res3, *res4;
+
+ if (uts.sysname[0] == '\0') {
+ if (uname(&uts) != 0) {
+ _rtld_error("utsname failed: %d", errno);
+ return (NULL);
+ }
+ }
+ if (!origin_subst_one(&res1, real, "$ORIGIN", origin_path, NULL) ||
+ !origin_subst_one(&res2, res1, "$OSNAME", uts.sysname, res1) ||
+ !origin_subst_one(&res3, res2, "$OSREL", uts.release, res2) ||
+ !origin_subst_one(&res4, res3, "$PLATFORM", uts.machine, res3))
+ return (NULL);
+ return (res4);
+}
+
static void
die(void)
{
@@ -790,11 +898,8 @@ digest_dynamic(Obj_Entry *obj, int early)
#endif
case DT_FLAGS:
- if (dynp->d_un.d_val & DF_ORIGIN) {
- obj->origin_path = xmalloc(PATH_MAX);
- if (rtld_dirname(obj->path, obj->origin_path) == -1)
- die();
- }
+ if ((dynp->d_un.d_val & DF_1_ORIGIN) && trust)
+ obj->z_origin = true;
if (dynp->d_un.d_val & DF_SYMBOLIC)
obj->symbolic = true;
if (dynp->d_un.d_val & DF_TEXTREL)
@@ -826,6 +931,17 @@ digest_dynamic(Obj_Entry *obj, int early)
break;
#endif
+ case DT_FLAGS_1:
+ if ((dynp->d_un.d_val & DF_1_ORIGIN) && trust)
+ obj->z_origin = true;
+ if (dynp->d_un.d_val & DF_1_GLOBAL)
+ /* XXX */;
+ if (dynp->d_un.d_val & DF_1_BIND_NOW)
+ obj->bind_now = true;
+ if (dynp->d_un.d_val & DF_1_NODELETE)
+ obj->z_nodelete = true;
+ break;
+
default:
if (!early) {
dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag,
@@ -844,8 +960,17 @@ digest_dynamic(Obj_Entry *obj, int early)
obj->pltrelsize = 0;
}
- if (dyn_rpath != NULL)
- obj->rpath = obj->strtab + dyn_rpath->d_un.d_val;
+ if (obj->z_origin && obj->origin_path == NULL) {
+ obj->origin_path = xmalloc(PATH_MAX);
+ if (rtld_dirname_abs(obj->path, obj->origin_path) == -1)
+ die();
+ }
+
+ if (dyn_rpath != NULL) {
+ obj->rpath = (char *)obj->strtab + dyn_rpath->d_un.d_val;
+ if (obj->z_origin)
+ obj->rpath = origin_subst(obj->rpath, obj->origin_path);
+ }
if (dyn_soname != NULL)
object_add_name(obj, obj->strtab + dyn_soname->d_un.d_val);
@@ -1003,7 +1128,10 @@ find_library(const char *xname, const Obj_Entry *refobj)
xname);
return NULL;
}
- return xstrdup(xname);
+ if (refobj != NULL && refobj->z_origin)
+ return origin_subst(xname, refobj->origin_path);
+ else
+ return xstrdup(xname);
}
if (libmap_disable || (refobj == NULL) ||
@@ -1122,7 +1250,7 @@ gethints(void)
/* Keep from trying again in case the hints file is bad. */
hints = "";
- if ((fd = open(_PATH_ELF_HINTS, O_RDONLY)) == -1)
+ if ((fd = open(ld_elf_hints_path, O_RDONLY)) == -1)
return NULL;
if (read(fd, &hdr, sizeof hdr) != sizeof hdr ||
hdr.magic != ELFHINTS_MAGIC ||
@@ -1297,15 +1425,21 @@ is_exported(const Elf_Sym *def)
static int
load_needed_objects(Obj_Entry *first)
{
- Obj_Entry *obj;
+ Obj_Entry *obj, *obj1;
for (obj = first; obj != NULL; obj = obj->next) {
Needed_Entry *needed;
for (needed = obj->needed; needed != NULL; needed = needed->next) {
- needed->obj = load_object(obj->strtab + needed->name, obj);
- if (needed->obj == NULL && !ld_tracing)
+ obj1 = needed->obj = load_object(obj->strtab + needed->name, obj);
+ if (obj1 == NULL && !ld_tracing)
return -1;
+ if (obj1 != NULL && obj1->z_nodelete && !obj1->ref_nodel) {
+ dbg("obj %s nodelete", obj1->path);
+ init_dag(obj1);
+ ref_dag(obj1);
+ obj1->ref_nodel = true;
+ }
}
}
@@ -1851,12 +1985,13 @@ dlopen(const char *name, int mode)
Obj_Entry **old_obj_tail;
Obj_Entry *obj;
Objlist initlist;
- int result, lockstate;
+ int result, lockstate, nodelete;
LD_UTRACE(UTRACE_DLOPEN_START, NULL, NULL, 0, mode, name);
ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1";
if (ld_tracing != NULL)
environ = (char **)*get_program_var_addr("environ");
+ nodelete = mode & RTLD_NODELETE;
objlist_init(&initlist);
@@ -1904,6 +2039,11 @@ dlopen(const char *name, int mode)
if (ld_tracing)
goto trace;
}
+ if (obj != NULL && (nodelete || obj->z_nodelete) && !obj->ref_nodel) {
+ dbg("obj %s nodelete", obj->path);
+ ref_dag(obj);
+ obj->z_nodelete = obj->ref_nodel = true;
+ }
}
LD_UTRACE(UTRACE_DLOPEN_STOP, obj, NULL, 0, obj ? obj->dl_refcount : 0,
@@ -2031,6 +2171,19 @@ dlsym(void *handle, const char *name)
SYMLOOK_DLSYM);
}
+dlfunc_t
+dlfunc(void *handle, const char *name)
+{
+ union {
+ void *d;
+ dlfunc_t f;
+ } rv;
+
+ rv.d = do_dlsym(handle, name, __builtin_return_address(0), NULL,
+ SYMLOOK_DLSYM);
+ return (rv.f);
+}
+
void *
dlvsym(void *handle, const char *name, const char *version)
{
@@ -2309,6 +2462,23 @@ rtld_dirname(const char *path, char *bname)
return (0);
}
+static int
+rtld_dirname_abs(const char *path, char *base)
+{
+ char base_rel[PATH_MAX];
+
+ if (rtld_dirname(path, base) == -1)
+ return (-1);
+ if (base[0] == '/')
+ return (0);
+ if (getcwd(base_rel, sizeof(base_rel)) == NULL ||
+ strlcat(base_rel, "/", sizeof(base_rel)) >= sizeof(base_rel) ||
+ strlcat(base_rel, base, sizeof(base_rel)) >= sizeof(base_rel))
+ return (-1);
+ strcpy(base, base_rel);
+ return (0);
+}
+
static void
linkmap_add(Obj_Entry *obj)
{
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index c76bc76..1d7ffb2 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -195,7 +195,7 @@ typedef struct Struct_Obj_Entry {
const Elf_Hashelt *chains; /* Hash table chain array */
unsigned long nchains; /* Number of chains */
- const char *rpath; /* Search path specified in object */
+ char *rpath; /* Search path specified in object */
Needed_Entry *needed; /* Shared objects needed by this one (%) */
STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we
@@ -216,6 +216,9 @@ typedef struct Struct_Obj_Entry {
bool init_done : 1; /* Already have added object to init list */
bool tls_done : 1; /* Already allocated offset for static TLS */
bool phdr_alloc : 1; /* Phdr is allocated and needs to be freed. */
+ bool z_origin : 1; /* Process rpath and soname tokens */
+ bool z_nodelete : 1; /* Do not unload the object and dependencies */
+ bool ref_nodel : 1; /* refcount increased to prevent dlclose */
struct link_map linkmap; /* for GDB and dlinfo() */
Objlist dldags; /* Object belongs to these dlopened DAGs (%) */
diff --git a/release/doc/en_US.ISO8859-1/hardware/article.sgml b/release/doc/en_US.ISO8859-1/hardware/article.sgml
index d855fd0..79eda0a 100644
--- a/release/doc/en_US.ISO8859-1/hardware/article.sgml
+++ b/release/doc/en_US.ISO8859-1/hardware/article.sgml
@@ -858,6 +858,8 @@
&hwlist.rum;
+ &hwlist.uath;
+
&hwlist.upgt;
&hwlist.ural;
@@ -1468,8 +1470,6 @@
&hwlist.umct;
- &hwlist.uscanner;
-
&hwlist.umass;
<para>[&arch.amd64;, &arch.i386;, &arch.pc98;] Audio Devices
diff --git a/release/doc/ja_JP.eucJP/hardware/common/dev.sgml b/release/doc/ja_JP.eucJP/hardware/common/dev.sgml
index 8300c1b..a681565 100644
--- a/release/doc/ja_JP.eucJP/hardware/common/dev.sgml
+++ b/release/doc/ja_JP.eucJP/hardware/common/dev.sgml
@@ -802,8 +802,6 @@
&hwlist.umct;
- &hwlist.uscanner;
-
&hwlist.umass;
<para arch="i386,pc98,amd64">¥ª¡¼¥Ç¥£¥ª¥Ç¥Ð¥¤¥¹ (&man.uaudio.4; ¥É¥é¥¤¥Ð)</para>
diff --git a/release/doc/ru_RU.KOI8-R/hardware/common/dev.sgml b/release/doc/ru_RU.KOI8-R/hardware/common/dev.sgml
index d3ac250..9a26570 100644
--- a/release/doc/ru_RU.KOI8-R/hardware/common/dev.sgml
+++ b/release/doc/ru_RU.KOI8-R/hardware/common/dev.sgml
@@ -816,8 +816,6 @@
&hwlist.umct;
- &hwlist.uscanner;
-
&hwlist.umass;
<para arch="i386,pc98,amd64">áÕÄÉÏ ÕÓÔÒÏÊÓÔ×Á (ÄÒÁÊ×ÅÒ &man.uaudio.4;)
diff --git a/release/doc/share/misc/dev.archlist.txt b/release/doc/share/misc/dev.archlist.txt
index cfe254c..137584d 100644
--- a/release/doc/share/misc/dev.archlist.txt
+++ b/release/doc/share/misc/dev.archlist.txt
@@ -149,7 +149,6 @@ tl i386,pc98,amd64
trm i386,amd64
twa i386,amd64
twe i386,amd64
-txp i386,pc98,ia64,amd64
ubsa i386,pc98,amd64
ubsec i386,pc98,amd64
ubser i386,pc98,amd64
@@ -163,7 +162,6 @@ umodem i386,pc98,amd64
uplcom i386,pc98,amd64
ural i386,amd64
urio i386,pc98,amd64,powerpc
-uscanner i386,pc98,amd64,powerpc
uvisor i386,pc98,amd64
uvscom i386,pc98,amd64
vge i386,pc98,amd64
diff --git a/release/doc/zh_CN.GB2312/hardware/article.sgml b/release/doc/zh_CN.GB2312/hardware/article.sgml
index 2a62fc6..52683be 100644
--- a/release/doc/zh_CN.GB2312/hardware/article.sgml
+++ b/release/doc/zh_CN.GB2312/hardware/article.sgml
@@ -1210,8 +1210,6 @@
&hwlist.umct;
- &hwlist.uscanner;
-
&hwlist.umass;
<para>[&arch.amd64;, &arch.i386;, &arch.pc98;] ÉùÒôÉ豸 (&man.uaudio.4; Çý¶¯³ÌÐò)
diff --git a/release/picobsd/bridge/PICOBSD b/release/picobsd/bridge/PICOBSD
index 9f36fdf..150a44d 100644
--- a/release/picobsd/bridge/PICOBSD
+++ b/release/picobsd/bridge/PICOBSD
@@ -3,8 +3,8 @@
#
# Line starting with #PicoBSD contains PicoBSD build parameters
#marker def_sz init MFS_inodes floppy_inodes
-#PicoBSD 3200 init 8192 32768
-options MD_ROOT_SIZE=3200 # same as def_sz
+#PicoBSD 8000 init 8192 32768
+options MD_ROOT_SIZE=8000 # same as def_sz
hints "PICOBSD.hints"
@@ -45,6 +45,7 @@ options DUMMYNET
device if_bridge
options HZ=1000
+device random # used by ssh
device pci
# Floppy drives
@@ -64,7 +65,6 @@ device atkbd
device vga # VGA screen
# syscons is the default console driver, resembling an SCO console
-
device sc
# Serial (COM) ports
@@ -88,14 +88,12 @@ device uart
# The following Ethernet NICs are all PCI devices.
#
device miibus
-#device de # DEC/Intel DC21x4x (``Tulip'')
-#device lnc
device fxp # Intel EtherExpress PRO/100B (82557, 82558)
+device nfe # nVidia nForce MCP on-board Ethernet
#device xl # 3Com
device rl # RealTek 8129/8139
+device re # RealTek 8139C+/8169/8169S/8110S
device sis # National/SiS
-#device vx # 3Com 3c590, 3c595 (``Vortex'')
-#device wx # Intel Gigabit Ethernet Card (``Wiseman'')
device dc # DEC/Intel 21143 and various workalikes
device ed
@@ -109,7 +107,7 @@ device md # Memory "disks"
#device faith 1 # IPv6-to-IPv4 relaying (translation)
device tap
-#options DEVICE_POLLING
+#options DEVICE_POLLING
# The `bpf' device enables the Berkeley Packet Filter.
# Be aware of the administrative consequences of enabling this!
diff --git a/release/picobsd/bridge/config b/release/picobsd/bridge/config
index 4183c2e..af409a1 100644
--- a/release/picobsd/bridge/config
+++ b/release/picobsd/bridge/config
@@ -3,5 +3,4 @@
# it should only contain variable definitions -- it is sourced
# by the shell much like rc.conf* files
-o_no_devfs="" # we have devfs.
-fd_size="2880"
+fd_size="4096"
diff --git a/release/picobsd/bridge/crunch.conf b/release/picobsd/bridge/crunch.conf
index 3db93ba..39c1b1f 100644
--- a/release/picobsd/bridge/crunch.conf
+++ b/release/picobsd/bridge/crunch.conf
@@ -1,39 +1,55 @@
#
# $FreeBSD$
#
-# configuration file for "bridge" floppy.
-# Depending on your needs, almost surely you will need to
-# modify your configuration to add/remove/change programs used in
-# the floppy image. Remember that some programs also require
-# matching kernel options to enable device drivers etc.
+# Configuration file for "bridge" images..
#
-# Next to most of the programs i have tried to indicate the approximate
-# space consumed, but beware that these values change from release
-# to release, and might depend on the presence of other programs which
-# share the same libraries.
+# Depending on your needs, you will almost surely need to
+# add/remove/change programs according to your needs.
+# Remember that some programs require matching kernel options to
+# enable device drivers etc.
#
-# NOTE: the string "/usr/src" will be automatically replaced with the
-# correct value set in 'build' script - you should change it there
+# To figure out how much space is used by each program, do
+#
+# size build_dir-bridge/crunch/*lo
+#
+# Remember that programs require libraries, which add up to the
+# total size. The final binary is build_dir-bridge/mfs.tree/stand/crunch
+# and you can check which libraries it uses with
+#
+# ldd build_dir-bridge/mfs.tree/stand/crunch
-# Default build options. Basically tell the Makefiles which understand
-# that to use the most compact possible version of the code.
+# crunchgen configuration to build the crunched binary, see "man crunchgen"
+# We need to specify generic build options, the places where to look
+# for sources, and the list of program and libraries we want to put
+# in the crunched binary.
#
-buildopts -DNO_PAM -DRELEASE_CRUNCH -DPPP_NO_NETGRAPH -DTRACEROUTE_NO_IPSEC -DNO_INET6
+# NOTE: the string "/usr/src" below will be automatically replaced with
+# the path set in the 'build' script.
+
+# Default build options. Basically tell the Makefiles
+# that to use the most compact possible version of the code.
+
+buildopts -DNO_PAM -DRELEASE_CRUNCH -DPPP_NO_NETGRAPH
+buildopts -DTRACEROUTE_NO_IPSEC -DNO_INET6
buildopts -DWITHOUT_IPX
-# directories where to look for sources of various binaries.
+# Directories where to look for sources of various binaries.
# @__CWD__@ is a magic keyword in the picobsd's (Makefile.conf)
-# which is replaced with the picobsd directory.
+# which is replaced with the directory with the picobsd configuration
+# corresponding to your image. This way you can have custom sources
+# in that directory overriding system programs.
+
srcdirs @__CWD__@/src
-# Some programs are especially written for PicoBSD and reside here
-# Make this first in the list so we can override standard programs
-# with the picobsd-specific ones.
+# Some programs are especially written for PicoBSD and reside in
+# release/picobsd/tinyware.
+# Put this entry near the head of the list to override standard binaries.
+
srcdirs /usr/src/release/picobsd/tinyware
-#
-# standard locations
-#
+# Other standard locations for sources.
+# If a program uses its own source directory, add
+
srcdirs /usr/src/bin
srcdirs /usr/src/sbin/i386
srcdirs /usr/src/sbin
@@ -41,145 +57,124 @@ srcdirs /usr/src/usr.bin
srcdirs /usr/src/gnu/usr.bin
srcdirs /usr/src/usr.sbin
srcdirs /usr/src/libexec
-#
-# And there are others (mostly ports) which reside in their specific
-# directories. For them, we use the "special" commands to tell
-# crunchgen where to look for sources, objects, which Makefile
-# variables contain the list of sources and objects, and so on.
-# init is almost always necessary.
-progs init # 4KB.
+# For programs that reside in different places, the best option
+# is to use the command "special XXX srcdir YYY" where XXX is the
+# program name and YYY is the directory path.
+# "special XXX ..." can be used to specify more options, see again
+# the crunchgen manpage.
+
+#--- Basic configuraton
+# init is always necessary (unless you have a replacement, oinit)
+progs init
+
# fsck is almost always necessary, unless you have everything on the
# image and use 'tar' or something similar to read/write raw blocks
# from the floppy.
-progs fsck # 24KB.
-# ifconfig is needed if you want to configure interfaces...
-progs ifconfig # 4KB.
-#
+
+progs fsck
+
+# ifconfig is needed if you want to configure interfaces.
+progs ifconfig
+
# You will also need a shell and a bunch of utilities.
# The standard shell is not that large, but you need many
# external programs. In fact most of them do not take much space
-# as they merely issue a system call, and print the result; the
-# libraries are already needed anyways, so they end up using almost
-# no additional memory.
-# There are a few exceptions such as 'less', which in 4.x is
-# rather large.
-progs sh # 36KB.
+# as they merely issue a system call, and print the result.
+# For a more compact version of shell and utilities, you could
+# try busybox, however most system management commands in busybox
+# will not work as they use linux-specific interfaces.
+
+progs sh
ln sh -sh
-progs echo # 0KB.
-progs pwd
-progs mkdir rmdir
+
+# the small utilities
+progs echo
+progs pwd mkdir rmdir
progs chmod chown
-progs mv ln # 0KB.
+ln chown chgrp
+progs mv ln cp rm ls
+progs cat tail tee
+progs test
+ln test [
+
progs mount
-progs minigzip # 0KB.
+progs minigzip
ln minigzip gzip
-progs cp # 0KB.
-progs rm
-progs ls
progs kill
-progs df # 0KB.
-progs ps # 4KB.
-progs ns # 4KB.
+progs df
+progs ps
+progs ns # this is the
ln ns netstat
-progs vm # 0KB.
-progs cat # 0KB.
-progs test # 0KB.
-ln test [
-progs hostname # 0KB.
-progs login # 4KB.
-progs getty # 4KB.
-progs stty # 4KB.
-progs w # 0KB.
-progs msg # 0KB.
+progs vm
+progs hostname
+progs login
+progs getty
+progs stty
+progs w
+progs msg
ln msg dmesg
-progs reboot # 0KB.
-progs less # 36KB
-#ln less more
-#progs more # 12KB
-special more srcdir /usr/ports/misc/44bsd-more/work
+progs reboot
progs sysctl
-progs swapon # 0KB.
-progs pwd_mkdb # 0KB.
+progs swapon
+progs pwd_mkdb
progs umount
-progs du # 0KB.
-progs tail # 0KB.
-progs tee # 0KB.
-progs passwd # 0KB.
+progs du
+progs passwd
+
+progs route
-progs route # 8KB
-# progs mount_msdosfs
-# progs comcontrol
-#
# If you want to run natd, remember the alias library
-#progs natd # 20KB
-#libs -lalias # natd
-#
+#progs natd
+#libs_so -lalias # natd
+
# ppp is rather large. Note that as of Jan.01, RELEASE_CRUNCH
# makes ppp not use libalias, so you cannot have aliasing.
-#progs ppp # 112KB
+#progs ppp
# You need an editor. ee is relatively small, though there are
# smaller ones. vi is much larger.
# The editor also usually need a curses library.
-progs ee # 32KB.
-libs -lncurses
-# progs vi # ??
-# libs -lcurses # for vi
+progs ee
-#progs tcpdump # 100KB.
-special tcpdump srcdir /usr/src/usr.sbin/tcpdump/tcpdump
+progs arp
-progs arp # 0KB.
+# these require libgeom
+# progs bsdlabel fdisk mdconfig
-progs bsdlabel # 4KB.
-progs fdisk # 4KB.
-progs vnconfig # 0KB.
-
-#progs grep # 16KB.
-progs date # 4KB.
-#progs mount_nfs # 0KB.
+progs kldload kldunload kldstat
+progs kldxref
+#progs grep
+progs date
+progs ping
+#progs routed
+progs ipfw
+progs traceroute
+progs mdmfs
+ln mdmfs mount_mfs
+# Various filesystem support -- remember to enable the kernel parts
+# progs mount_msdosfs
+progs mount_nfs
+# progs mount_cd9660
ln mount_nfs nfs
-progs ping # 4KB.
-#progs routed # 32KB.
-progs ipfw # 12KB.
-progs traceroute # 0KB.
-# progs mount_cd9660 # 4KB.
-# ln mount_cd9660 cd9660
-# progs newfs # 12KB.
+ln mount_cd9660 cd9660
+#progs newfs
#ln newfs mount_mfs
-ln chown chgrp
# ln mount_msdosfs msdos
-# If you need to access the box remotely, and maybe copy files
-# from/to it, you can use telnet, rsh or ssh.
-# inetd is only needed for telnet and rshd
-#progs inetd # 12KB.
-#progs telnet # 20KB.
-#progs telnetd # 12KB.
-#progs ftp # 28KB.
-#progs tar # 32KB.
-
-# Check the ssh license! If you want to use this,
-# go to /usr/ports/security/ssh-picobsd, do a make extract configure
-# You also need to install /usr/ports/math/libgmp-freebsd
-#progs sshd # includes ssh and scp
-special sshd objvar SSHD_OBJS
-special sshd srcdir /usr/ports/picobsd/ssh-picobsd/work/ssh-1.2.27
-special sshd objdir /usr/ports/picobsd/ssh-picobsd/work/ssh-1.2.27
-ln sshd ssh
-ln sshd ssh1
-ln sshd scp
-#libs /usr/local/lib/libgmp.a
-
-libs -ll # used by sh
-libs -lufs # used by mount
-### ee uses ncurses instead of curses
-libs -ledit -lutil -lmd -lcrypt -lmp -lm -lkvm
-# libs -lmytinfo
-libs -lz -lpcap -lwrap
-libs -ltermcap -lgnuregex # -lcurses
-libs -lgeom
-libs -lsbuf
-libs -lbsdxml # used by ifconfig
+# For a small ssh client/server use dropbear
+
+# Now the libraries
+libs_so -lc # the C library
+libs_so -ll # used by sh (really ?)
+libs_so -lufs # used by mount
+### ee uses ncurses but as a dependency
+#libs_so -lncurses
+libs_so -lm
+libs_so -ledit -lutil
+libs_so -lcrypt
+libs_so -lkvm
+libs_so -lz
+libs_so -lbsdxml
+libs_so -lsbuf
diff --git a/release/picobsd/build/picobsd b/release/picobsd/build/picobsd
index a3b3cf5..e5f58cd 100755
--- a/release/picobsd/build/picobsd
+++ b/release/picobsd/build/picobsd
@@ -3,17 +3,17 @@
# $FreeBSD$
# This file requires sysutils/makefs to run
#
-# The new PicoBSD build script. Invoked as
+# The PicoBSD build script. Invoked as
#
-# picobsd [options] floppy_type site_name
+# picobsd [options] image_type [site_name]
#
-# Where floppy_type is a directory where the picobsd config info
-# is held, and ${floppy_type}/floppy.tree.${site_name} contains
+# Where image_type is a directory with the picobsd config info,
+# and ${image_type}/floppy.tree.${site_name} contains
# optional site-specific configuration.
#
# For Options, see the bottom of the file where the processing is
# done. The picobsd(8) manpage might be of some help, but code and docs
-# tend to lose sync over time...
+# tend to lose sync over time.
#
# This script depends on the following files:
#
@@ -33,36 +33,42 @@
# floppy.tree/ local additions to ${PICO_TREE}/mfs_free
# floppy.tree.${site}/ same as above, site specific.
# mfs_tree/ local additions to the mfs_free
-# buildtree.mk optional makefile to build an extension for floppy tree
+# buildtree.mk optional Makefile to build an extension for floppy tree
# (generated in buildtree/ )
#
#--- The main entry point is at the end.
#
-# There are two set of initialization. The first one (set_defaults)
-# is done on entry to the script, and is used to set default values
-# for all variables which do not depend on floppy type and source tree.
+# There are two initialization functions:
#
-# The second set is done after command line parsing, e.g.
-# to resolve dependencies on the source tree.
+# + set_defaults
+# is run on entry to the script, and is used to set default values
+# for all variables that do not depend on image type and source tree.
#
-# Naming:
+# + set_build_parameters
+# is run after command line parsing
+#
+# VARIABLE NAMES:
# + variables that control operation (e.g. verbosity) and are generally
# set from the command line have o_ ("option") as a name prefix
#
-# + variables which contain pathnames and values that should not change
+# + variables that contain pathnames and values that should not change
# have c_ ("constant") as a name prefix
#
# + variables exported to Makefiles and subshells are CAPITAL
#
# + variables local to the script are lowercase, possibly with
-# an l_ ("local") prefix
+# an l_ ("local") prefix.
+#
+# There are unfortunately exceptions:
+# name, l_usrtree, l_objtree
# SRC points to your FreeBSD source tree.
# l_usrtree points to the /usr subdir for the source tree.
# Normally /usr or ${SRC}/../usr
# l_objtree points to the obj tree. Normally ${l_usrtree}/obj-pico
+# c_label is either bsdlabel or disklabel
# PICO_TREE is where standard picobsd stuff resides.
# Normally ${SRC}/release/picobsd
# You can set SRC with --src <directory>
@@ -71,28 +77,27 @@
# MY_TREE (set later) is where this floppy type resides.
# BUILDDIR is the build directory
-# set some default values for variables.
-# needs to be done as the first thing in the script.
-
# log something on stdout if verbose.
o_verbose=0 # this needs to be here!
-log() {
+log() { # message
local foo
[ ${o_verbose} -gt 0 ] && printf "\n*** %s\n" "$*"
[ ${o_verbose} -gt 1 ] && read -p "=== Press enter to continue" foo
return 0
}
-logverbose() {
+# unconditionally log and wait for input
+logverbose() { # message
local foo
printf "\n*** %s\n" "$*"
read -p "=== Press enter to continue" foo
return 0
}
-set_defaults() {
- # no way to use logging in this function, variable not set yet.
+# set some default values for variables.
+# needs to be done as the first thing in the script.
+set_defaults() { # no arguments
# EDITOR is the editor you use
# fd_size floppy size in KB (default to 1440). You can use 1480,
# 1720, 2880, etc. but beware that only 1440 and 1480 will boot
@@ -101,15 +106,20 @@ set_defaults() {
fd_size=${fd_size:-1440}
o_use_loader="yes" # use /boot/loader
- o_all_in_mfs="yes" # put all files in mfs so you can boot and run
- # the image via diskless boot.
- o_clean="" # do not clean
+ # You should not change it unless you are really short
+ # of space, and your kernel is small enough that the
+ # bootblocks manage to load it.
+
+ o_all_in_mfs="yes" # put all files in mfs so you can boot
+ # and run the image via diskless boot.
+ o_clean="" # set if you want to clean prev.builds.
o_interactive="" # default is interactive
o_verbose=0 # verbose level, 0 is silent
o_tarv="" # tar verbose flag, "" or "v"
- o_init_src="" # non "" if we need to init libs and includes.
+ o_init_src="" # set to build libs and includes.
o_makeopts=${MAKEOPTS:--s} # make options, be silent by default
- o_no_devfs=yes # we do not want devfs
+ o_no_devfs= # default is use devfs.
+ # You should only set it when building 4.x images
o_do_modules="" # do not build modules
SRC="/usr/src" # default location for sources
@@ -132,13 +142,13 @@ set_defaults() {
c_img=picobsd.bin # filename used for the picobsd image
generate_iso="NO" # don't generate the iso image
- # select the right memory disk name
+ # select the right disklabel program
case `uname -r` in
- 7.*|6.*|5.*)
- l_label="bsdlabel"
+ 4.*)
+ c_label="disklabel"
;;
*)
- l_label="disklabel"
+ c_label="bsdlabel"
;;
esac
@@ -150,8 +160,9 @@ set_defaults() {
trap fail 15
}
-# use the new build infrastructure
-create_includes_and_libraries2() {
+# use the new build infrastructure to create libraries
+# and also to build a specific target
+create_includes_and_libraries2() { # opt_dir opt_target
local no
log "create_includes_and_libraries2() for ${SRC}"
if [ ${OSVERSION} -ge 600000 ] ; then
@@ -163,7 +174,11 @@ create_includes_and_libraries2() {
export MAKEOBJDIRPREFIX
( cd ${SRC};
# make -DNOCLEAN -DNOPROFILE -DNOGAMES -DNOLIBC_R -DPICOBSD buildworld
- make _+_= $no toolchain _includes _libraries
+ if [ -d "$1" ] ; then
+ cd $1 ; make $2 # specific target, e.g. ld-elf.so
+ else
+ make _+_= $no toolchain _includes _libraries
+ fi
)
}
@@ -173,7 +188,7 @@ create_includes_and_libraries() {
log "create_includes_and_libraries() for ${SRC}"
# Optionally creates include directory and libraries.
- mkdir -p ${l_usrtree}/include # the include directory...
+ mkdir -p ${l_usrtree}/include # the include directory...
mkdir -p ${l_usrtree}/share/misc # a few things go here
mkdir -p ${l_usrtree}/lib # libraries
mkdir -p ${l_usrtree}/sbin # some binaries
@@ -210,11 +225,12 @@ create_includes_and_libraries() {
log "Libraries done"
}
-# set_type <type> looks in user or system directories for the floppy type
-# specified as first argument, and sets variables according to the config.
-# file. Also sets MY_TREE and BUILDDIR and SITE
+# set_type <the_type> [the_site] looks in user or system directories
+# for the directory named as the first argument, reads the configuration
+# files and sets variables according to the config.
+# Also sets MY_TREE and BUILDDIR and SITE
-set_type() {
+set_type() { # the_type the_site
local a i
log "set_type() : Type '$1' site '$2'"
@@ -242,7 +258,7 @@ set_type() {
clean_tree() {
log "clean_tree()"
- if [ "${name}" = "" ] ; then
+ if [ -z "${name}" ] ; then
echo "---> Wrong floppy type"
exit 3
fi
@@ -271,7 +287,7 @@ build_iso_image() {
# Main build procedure.
build_image() {
log "build_image() <${name}>"
- [ "${name}" != "" ] || fail $? bad_type
+ [ -n "${name}" ] || fail $? bad_type
clear
set_msgs
printf "${MSG}---> We'll use the sources living in ${SRC}\n\n"
@@ -281,9 +297,8 @@ build_image() {
# variables.
#
. ${PICO_TREE}/build/config
- if [ -f ${MY_TREE}/config ] ; then
- . ${MY_TREE}/config
- fi
+ [ -f "${MY_TREE}/config" ] && . ${MY_TREE}/config
+ [ -f "${o_additional_config}" ] && . ${o_additional_config}
# location of the object directory
PICO_OBJ=${l_objtree}/picobsd/${THETYPE}
@@ -309,34 +324,13 @@ build_image() {
fill_floppy_image # copies everything into the floppy
}
-build_package() {
- local z msg
-
- log "build_package()"
- rm -rf build.status
- echo "##############################################" >>build.status
- echo "## `date` ">>build.status
- echo "##############################################" >>build.status
- for z in bridge dial router net isp ; do
- set_type ${z}
- echo "---------------------------------------------">>build.status
- echo "Building TYPE=${z}, SIZE=${MFS_SIZE}" >>build.status
- msg="(ok)" # error message
- build_image || msg="** FAILED! **"
- echo " ${msg}">>build.status
- # where do i put things ?
- # clean_tree
- done
- exit 0
-}
-
# Set build parameters interactively
main_dialog() {
local ans i l
log "main_dialog()"
- while [ true ] ; do
+ while true ; do
set_msgs
rm ${c_reply}
dialog --menu "PicoBSD build menu -- (29 sep 2001)" 19 70 12 \
@@ -529,6 +523,106 @@ populate_floppy_fs() { # OK
) || true
}
+# Copy the specified files to the destination filesystem.
+# Each file is specified as a pair "src dst", dst is assumed to be
+# a directory (and created with mkdir -p) if it has a trailing /
+# Be careful to escape metacharacters.
+# You can use ${CROSS} to point to the root of the cross build
+# (remember that it might be incomplete)
+
+do_copyfiles() { # rootdir varname
+ log Copy files to $1
+ local root=$1
+ local srcs dst
+ local CROSS=${_SHLIBDIRPREFIX}
+ eval set "\${${2}}"
+ srcs=""
+ for dst in $* ; do
+ [ -z "$srcs" ] && srcs=$dst && continue
+ eval srcs="$srcs" # expand wildcard and vars
+ case x"$dst" in
+ */ ) mkdir -p ${root}/${dst} ;;
+ # * ) mkdir -p `dirname ${root}/${dst}` ;;
+ esac
+ cp -p ${srcs} ${root}/${dst} || true
+ srcs=""
+ done
+}
+
+# do_links is a helper function to create links between programs
+# in stand/
+# This is done reading the names and destination from variable
+# links in a config file, in the format
+# : dst names
+
+do_links() { # rootdir varname
+ local root=$1
+ local l i dst
+ eval l="\${${2}}"
+ dst=""
+ log "Create links for ${l}"
+ (cd ${root}/stand
+ for i in $l ; do
+ if [ "$dst" = ":" -o "$i" = ":" ] ; then
+ dst=$i
+ elif [ -n "${dst}" ] ; then
+ ln -s ${dst} ${i}
+ fi
+ done
+ )
+}
+
+# find_progs is a helper function to locate the named programs
+# or libraries in ${o_objdir} or ${_SHLIBDIRPREFIX},
+# and return the full pathnames.
+# Sets ${u_progs} to the list of programs, and ${u_libs}
+# to the list of shared libraries used.
+#
+# You can use it e.g. in a local configuration file by writing
+#
+# do_copyfiles_user() {
+# local dst=$1
+# find_progs nvi sed less grep
+# cp -p ${u_progs} ${dst}/bin
+# cp -p ${u_libs} ${dst}/lib
+# mkdir -p ${dst}/libexec
+# find_progs ld-elf.so.1
+# cp -p ${u_progs} ${dst}/libexec
+# }
+
+find_progs() { # programs
+ local i
+ u_progs="`find_progs_helper $*`"
+ local o=${o_objdir:-${_SHLIBDIRPREFIX}}
+ [ -z "${u_progs}" ] && return 1 # not found, error
+ i="`ldd ${u_progs} | grep -v '^/' | awk '{print $1}' | sort | uniq`"
+ u_libs="`find_progs_helper $i`"
+ return 0
+}
+
+find_progs_helper() { # programs
+ local progs="$*"
+ local i o places names
+ local subdirs="bin sbin usr.bin usr.sbin libexec lib \
+ gnu/usr.bin gnu/lib \
+ secure/usr.bin secure/usr.sbin secure/libexec secure/lib"
+ names="" # files to search
+ o=""
+ for i in $progs ; do
+ # plain programs come out verbatim
+ [ -f "$i" ] && echo $i && continue
+ names="${names} ${o} -name $i"
+ o="-o"
+ done
+ [ -z "${names}" ] && return 0
+ places="" # places to search
+ o=${o_objdir:-${_SHLIBDIRPREFIX}/..}
+ for i in $subdirs ; do
+ [ -d "${o}/${i}" ] && places="${places} ${o}/${i}"
+ done
+ find ${places} -type f \( ${names} \)
+}
+
# Populate the memory filesystem with binaries and non-variable
# configuration files.
# First do an mtree pass, then create directory links and device entries,
@@ -537,7 +631,7 @@ populate_floppy_fs() { # OK
# Finally, if required, make a copy of the floppy.tree onto /fd
populate_mfs_tree() {
- local a dst MFS_TREE
+ local i j a dst MFS_TREE
log "populate_mfs_tree()"
dst=${BUILDDIR}/mfs.tree
@@ -552,12 +646,15 @@ populate_mfs_tree() {
log "Running mtree using $a..."
mtree -deU -f $a -p ${dst} > /dev/null || fail $? mtree
- # XXX create links
+ # Create symlinks using relative pathnames, so it is possible
+ # to follow them also when building the image.
+ # Note that names in STAND_LINKS should not have a leading /
for i in ${STAND_LINKS}; do
- ln -s /stand ${dst}/$i
+ j=`echo $i | sed -E 's:^[^/]+::;s:/[^/]+:../:g'`
+ ln -s ${j}stand ${dst}/$i
done
- ln -s /dev/null ${dst}/var/run/log
- ln -s /etc/termcap ${dst}/usr/share/misc/termcap
+ ln -s ../../dev/null ${dst}/var/run/log
+ ln -s ../../../etc/termcap ${dst}/usr/share/misc/termcap
### now build the crunched binaries ###
(
@@ -615,7 +712,7 @@ populate_mfs_tree() {
fi
# 4.x compatibility - create device nodes
- if [ "${o_no_devfs}" != "" ] ; then
+ if [ -n "${o_no_devfs}" ] ; then
# create device entries using MAKEDEV
(cd ${dst}/dev
ln -s ${SRC}/etc/MAKEDEV ; chmod 555 MAKEDEV
@@ -629,6 +726,24 @@ populate_mfs_tree() {
(cd ${dst}; chown -R root . )
fi
+ # If we are building a shared 'crunch', take the libraries
+ # and the dynamic loader as well
+ find_progs ${dst}/stand/crunch
+ if [ -n "${u_libs}" ] ; then
+ mkdir -p ${dst}/lib && cp -p ${u_libs} ${dst}/lib
+ mkdir -p ${dst}/libexec
+ create_includes_and_libraries2 libexec/rtld-elf
+ find_progs ld-elf.so.1 && cp -p ${u_progs} ${dst}/libexec
+ fi
+
+ [ -n "${copy_files}" ] && do_copyfiles ${dst} copy_files
+ do_copyfiles_user ${dst} || true
+ [ -n "${links}" ] && do_links ${dst} links
+ strip ${dst}/libexec/* ${dst}/lib/* ${dst}/stand/* 2> /dev/null || true
+
+ # The 'import_files' mechanism is deprecated, as it requires
+ # root permissions to follow the symlinks, and also does
+ # not let you rename the entries.
if [ -n "${import_files}" ] ; then
log "importing ${import_files} into mfs"
# We do it in a chroot environment on the target so
@@ -641,6 +756,7 @@ populate_mfs_tree() {
rm -rf ${dst}/rescue
fi
+ # final step -- build the mfs image
(cd ${BUILDDIR}
# override the owner
echo "/set uid=0 gid=0" > mtree.out
@@ -789,22 +905,22 @@ fill_floppy_image() {
(cd ${BUILDDIR}
makefs -t ffs -o bsize=4096 -o fsize=512 \
-s ${blocks}k -f 50 ${c_img} ${dst}
- # ${l_label} -f `pwd`/${c_img}
- ${l_label} -w -f `pwd`/${c_img} auto # write in a label
+
+ ${c_label} -w -f `pwd`/${c_img} auto # write in a label
# copy partition c: into a: with some sed magic
- ${l_label} -f `pwd`/${c_img} | sed -e '/ c:/{p;s/c:/a:/;}' | \
- ${l_label} -R -f `pwd`/${c_img} /dev/stdin
- ${l_label} -f `pwd`/${c_img}
+ ${c_label} -f `pwd`/${c_img} | sed -e '/ c:/{p;s/c:/a:/;}' | \
+ ${c_label} -R -f `pwd`/${c_img} /dev/stdin
+ ${c_label} -f `pwd`/${c_img}
ls -l ${c_img}
- ${l_label} -f `pwd`/${c_img}
+ ${c_label} -f `pwd`/${c_img}
logverbose "after disklabel"
)
echo "BUILDDIR ${BUILDDIR}"
if [ "${generate_iso}" = "YES" ]; then
echo "generate_iso ${generate_iso}"
- #build_iso_image()
+ # build_iso_image # XXX not implemented yet
exit 1
fi
@@ -832,7 +948,6 @@ fill_floppy_image() {
# needs to be done once).
set_build_parameters() {
- log "set_build_parameters() SRC is ${SRC}"
if [ "${SRC}" = "/usr/src" ] ; then
l_usrtree=${USR:-/usr}
else
@@ -859,6 +974,19 @@ set_build_parameters() {
CONFIG=${l_usrtree}/sbin/config
export CONFIG
fi
+
+ # if we have o_objdir, find where bin/ is
+ if [ ! -z "${o_objdir}" ] ; then
+ if [ -d ${o_objdir}/bin ] ; then
+ # fine
+ elif [ -d "${o_objdir}${SRC}/bin" ] ; then
+ o_objdir="${o_objdir}${SRC}"
+ log "Changing objdir to ${o_objdir}"
+ else
+ log "Cannot find objdir in ${o_objdir}, sorry"
+ o_objdir=""
+ fi
+ fi
}
#-------------------------------------------------------------------
@@ -867,9 +995,10 @@ set_build_parameters() {
set_defaults
while [ true ]; do
+ log "Parsing $1"
case $1 in
--src) # set the source path instead of /usr/src
- SRC=`(cd $2; pwd)`
+ SRC=`realpath $2`
shift
;;
--init)
@@ -916,6 +1045,17 @@ while [ true ]; do
generate_iso="YES"
;;
+ --cfg) # read additional config from this file
+ o_additional_config=`realpath $2`
+ shift
+ ;;
+
+ --objdir) # Place with results of a previous buildworld
+ # useful if you want to copy shared binaries and libs
+ o_objdir=`realpath $2`
+ shift
+ ;;
+
*)
break
;;
@@ -923,12 +1063,10 @@ while [ true ]; do
esac
shift
done
+
set_build_parameters # things that depend on ${SRC}
set_type $1 $2 # type and site, respectively
-# If $1="package", it creates a neat set of floppies
-[ "$1" = "package" ] && build_package
-
[ "${o_interactive}" != "NO" ] && main_dialog
if [ "${o_clean}" = "YES" ] ; then
diff --git a/release/picobsd/floppy.tree/etc/rc1 b/release/picobsd/floppy.tree/etc/rc1
index 780311d..00b12ea 100644
--- a/release/picobsd/floppy.tree/etc/rc1
+++ b/release/picobsd/floppy.tree/etc/rc1
@@ -45,7 +45,6 @@ mount -a -t nfs
[ -n "$network_pass2_done" ] && network_pass3
pwd_mkdb -p ./master.passwd
-dev_mkdb
[ -f /etc/syslog.conf -a -f /stand/syslogd ] && \
{ echo "Starting syslogd."; syslogd ${syslogd_flags} ; }
diff --git a/release/picobsd/mfs_tree/etc/rc b/release/picobsd/mfs_tree/etc/rc
index 3013718..217224e 100644
--- a/release/picobsd/mfs_tree/etc/rc
+++ b/release/picobsd/mfs_tree/etc/rc
@@ -23,5 +23,5 @@ for i in *; do
[ -f $i.gz ] && rm $i
done
gzip -d *.gz
-. rc1
+. /etc/rc1
exit 0
diff --git a/release/picobsd/tinyware/simple_httpd/Makefile b/release/picobsd/tinyware/simple_httpd/Makefile
index cb4b149..abd4bd8 100644
--- a/release/picobsd/tinyware/simple_httpd/Makefile
+++ b/release/picobsd/tinyware/simple_httpd/Makefile
@@ -3,5 +3,6 @@
PROG=simple_httpd
SRCS= simple_httpd.c
NO_MAN=
+WARNS?=6
.include <bsd.prog.mk>
diff --git a/release/picobsd/tinyware/simple_httpd/simple_httpd.c b/release/picobsd/tinyware/simple_httpd/simple_httpd.c
index ab35b55..0d53a09 100644
--- a/release/picobsd/tinyware/simple_httpd/simple_httpd.c
+++ b/release/picobsd/tinyware/simple_httpd/simple_httpd.c
@@ -42,6 +42,7 @@
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -278,7 +279,7 @@ http_request(void)
/*printf("HTTP/1.0 200 OK\nContent-type: text/html\n\n\n");*/
printf("HTTP/1.0 200 OK\r\n");
/* Plug in environment variable, others in log_line */
- putenv("SERVER_SOFTWARE=FreeBSD/PicoBSD");
+ setenv("SERVER_SOFTWARE", "FreeBSD/PicoBSD", 1);
execlp (filename,filename,par,(char *)0);
}
@@ -331,7 +332,7 @@ http_request(void)
http_output(httpd_server_ident);
http_date();
- sprintf(buff, "Content-length: %lld\r\n", file_status.st_size);
+ sprintf(buff, "Content-length: %jd\r\n", (intmax_t)file_status.st_size);
write(con_sock, buff, strlen(buff));
strcpy(buff, "Content-type: ");
diff --git a/release/sparc64/mkisoimages.sh b/release/sparc64/mkisoimages.sh
index b101306d..333cf1b 100644
--- a/release/sparc64/mkisoimages.sh
+++ b/release/sparc64/mkisoimages.sh
@@ -31,8 +31,8 @@ if [ "x$1" = "x-b" ]; then
dd if=/dev/zero of=${IMG} bs=512 count=1024
MD=`mdconfig -a -t vnode -f ${IMG}`
sunlabel -w -B -b $4/boot/boot1 ${MD} auto
- newfs -O1 -o space -m 0 /dev/${MD}c
- mount /dev/${MD}c ${MNT}
+ newfs -O1 -o space -m 0 /dev/${MD}
+ mount /dev/${MD} ${MNT}
mkdir ${MNT}/boot
cp $4/boot/loader ${MNT}/boot
umount ${MNT}
diff --git a/rescue/rescue/Makefile b/rescue/rescue/Makefile
index 77f5963..16db60b 100644
--- a/rescue/rescue/Makefile
+++ b/rescue/rescue/Makefile
@@ -118,7 +118,7 @@ CRUNCH_PROGS_sbin= atacontrol badsect \
mount_udf mount_unionfs newfs \
newfs_msdos nos-tun ping reboot \
restore rcorder route routed rtquery rtsol savecore \
- slattach spppcontrol startslip swapon sysctl tunefs umount
+ spppcontrol swapon sysctl tunefs umount
.if ${MK_ATM} != "no"
CRUNCH_PROGS_sbin+= atmconfig
diff --git a/sbin/Makefile b/sbin/Makefile
index 0b6bc02..649f4a2 100644
--- a/sbin/Makefile
+++ b/sbin/Makefile
@@ -82,9 +82,7 @@ SUBDIR= adjkerntz \
${_sconfig} \
setkey \
shutdown \
- slattach \
spppcontrol \
- ${_startslip} \
${_sunlabel} \
swapon \
sysctl \
@@ -130,10 +128,6 @@ _quotacheck= quotacheck
_routed= routed
.endif
-.if ${MK_SLIP} != "no"
-_startslip= startslip
-.endif
-
.if ${MACHINE_ARCH} == "i386"
.if ${MACHINE} == "i386"
_fdisk= fdisk
diff --git a/sbin/fdisk_pc98/fdisk.c b/sbin/fdisk_pc98/fdisk.c
index 161c1f5..b66bad4 100644
--- a/sbin/fdisk_pc98/fdisk.c
+++ b/sbin/fdisk_pc98/fdisk.c
@@ -84,8 +84,6 @@ struct mboot {
static struct mboot mboot;
static int fd;
-#define ACTIVE 0x80
-
static uint dos_cyls;
static uint dos_heads;
static uint dos_sectors;
@@ -520,7 +518,7 @@ change_active(int which)
active = -1;
for (i = 0; i < NDOSPART; i++) {
- if ((partp[i].dp_sid & ACTIVE) == 0)
+ if ((partp[i].dp_sid & PC98_SID_ACTIVE) == 0)
continue;
printf("Partition %d is marked active\n", i + 1);
if (active == -1)
@@ -545,7 +543,7 @@ setactive:
active = new;
} while (!ok("Are you happy with this choice"));
if (active > 0 && active <= 8)
- partp[active-1].dp_sid |= ACTIVE;
+ partp[active-1].dp_sid |= PC98_SID_ACTIVE;
}
static void
diff --git a/sbin/geom/class/label/glabel.8 b/sbin/geom/class/label/glabel.8
index cbff2b4..bc1994e 100644
--- a/sbin/geom/class/label/glabel.8
+++ b/sbin/geom/class/label/glabel.8
@@ -91,12 +91,18 @@ Currently supported file systems are:
.Pp
.Bl -bullet -offset indent -compact
.It
-UFS1 (directory
+UFS1 volume names (directory
.Pa /dev/ufs/ ) .
.It
-UFS2 (directory
+UFS2 volume names (directory
.Pa /dev/ufs/ ) .
.It
+UFS1 file system IDs (directory
+.Pa /dev/ufsid/ ) .
+.It
+UFS2 file system IDs (directory
+.Pa /dev/ufsid/ ) .
+.It
MSDOSFS (FAT12, FAT16, FAT32) (directory
.Pa /dev/msdosfs/ ) .
.It
diff --git a/sbin/gvinum/gvinum.8 b/sbin/gvinum/gvinum.8
index 83b6876..c8e7709 100644
--- a/sbin/gvinum/gvinum.8
+++ b/sbin/gvinum/gvinum.8
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 23, 2006
+.Dd April 10, 2009
.Dt GVINUM 8
.Os
.Sh NAME
@@ -40,6 +40,13 @@
.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
@@ -49,7 +56,10 @@ 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 create Op Ar description-file
+.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 gvinum.
+.It Ic create Oo Fl f Oc Op Ar description-file
Create a volume as described in
.Ar description-file .
If no
@@ -57,6 +67,22 @@ If no
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
@@ -76,6 +102,14 @@ The
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
@@ -85,12 +119,19 @@ part of the move.
This can currently only be done when the subdisk is
not being accessed.
.Pp
-If the subdisk(s) form part of a RAID-5 plex, the disk(s) will need to be set
-to the
+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
+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
@@ -105,6 +146,11 @@ Exit
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
@@ -143,9 +189,21 @@ flag forces state changes regardless of whether they are legal.
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
@@ -217,15 +275,88 @@ is invoked.
directory with device nodes for
.Nm
objects
-.It Pa /dev/gvinum/plex
-directory containing device nodes for
-.Nm
-plexes
-.It Pa /dev/gvinum/sd
-directory containing device nodes for
-.Nm
-subdisks
.El
+.Sh EXAMPLES
+To create a mirror on disks /dev/ad1 and /dev/ad2, create a filesystem, mount,
+unmount and then stop Ic gvinum:
+.Pp
+.Dl "gvinum mirror /dev/ad1 /dev/ad2"
+.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/ad1 /dev/ad2 /dev/ad3 and /dev/ad4
+named "data" and create a filesystem:
+.Pp
+.Dl "gvinum mirror -s -n data /dev/ad1 /dev/ad2 /dev/ad3 /dev/ad4"
+.Dl "newfs /dev/gvinum/data"
+.Pp
+To create a raid5 array on disks /dev/ad1 /dev/ad2 and /dev/ad3, with stripesize
+493k you can use the raid5 command:
+.Pp
+.Dl "gvinum raid5 -s 493k /dev/ad1 /dev/ad2 /dev/ad3"
+.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/ad2"
+.Dl "drive gvinumdrive2 device /dev/???"
+.Dl "drive gvinumdrive0 device /dev/ad1"
+.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/ad4"
+.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/ad4"
+.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.
+.Pp
.Sh SEE ALSO
.Xr geom 4 ,
.Xr geom 8
@@ -255,9 +386,13 @@ documentation were added by
.An "Chris Jones"
through the 2005 Google Summer
of Code program.
+.Ic a partial rewrite of gvinum was done by "Lukas Ertl" and "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 le@FreeBSD.org
.An Chris Jones Aq soc-cjones@FreeBSD.org
+.An Ulf Lilleengen Aq lulf@FreeBSD.org
.Sh BUGS
Currently,
.Nm
@@ -271,10 +406,6 @@ initsize flag to
.Ic start
is ignored.
.Pp
-The
-.Ic stop
-command does not work.
-.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.
@@ -291,18 +422,10 @@ Specifically, the following commands from
.Xr vinum 4
are not supported:
.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.
-.It Ic concat Oo Fl fv Oc Oo Fl n Ar name Oc Ar drives
-Create a concatenated volume from the specified drives.
.It Ic debug
Cause the volume manager to enter the kernel debugger.
.It Ic debug Ar flags
Set debugging flags.
-.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 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.
@@ -310,17 +433,9 @@ drives in the system if no drive names are specified.
List information about volume manager state.
.It Ic label Ar volume
Create a volume label.
-.It Ic mirror Oo Fl fsv Oc Oo Fl n Ar name Oc Ar drives
-Create a mirrored volume from the specified drives.
.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.
-.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.
.El
diff --git a/sbin/gvinum/gvinum.c b/sbin/gvinum/gvinum.c
index ea33b75..7f97f9d 100644
--- a/sbin/gvinum/gvinum.c
+++ b/sbin/gvinum/gvinum.c
@@ -1,5 +1,7 @@
/*
- * Copyright (c) 2004 Lukas Ertl, 2005 Chris Jones
+ * 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
@@ -43,6 +45,7 @@
#include <ctype.h>
#include <err.h>
+#include <errno.h>
#include <libgeom.h>
#include <stdint.h>
#include <stdio.h>
@@ -54,12 +57,18 @@
#include "gvinum.h"
+void gvinum_attach(int, char **);
+void gvinum_concat(int, char **);
void gvinum_create(int, char **);
+void gvinum_detach(int, char **);
+void gvinum_grow(int, char **);
void gvinum_help(void);
void gvinum_list(int, char **);
void gvinum_move(int, char **);
+void gvinum_mirror(int, char **);
void gvinum_parityop(int, char **, int);
void gvinum_printconfig(int, char **);
+void gvinum_raid5(int, char **);
void gvinum_rename(int, char **);
void gvinum_resetconfig(void);
void gvinum_rm(int, char **);
@@ -67,9 +76,16 @@ void gvinum_saveconfig(void);
void gvinum_setstate(int, char **);
void gvinum_start(int, char **);
void gvinum_stop(int, char **);
+void gvinum_stripe(int, char **);
void parseline(int, char **);
void printconfig(FILE *, char *);
+char *create_drive(char *);
+void create_volume(int, char **, char *);
+char *find_name(const char *, int, int);
+char *find_drive(const char *);
+char *find_pattern(char *, char *);
+
int
main(int argc, char **argv)
{
@@ -111,6 +127,44 @@ main(int argc, char **argv)
exit(0);
}
+/* Attach a plex to a volume or a subdisk to a plex. */
+void
+gvinum_attach(int argc, char **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);
+}
+
void
gvinum_create(int argc, char **argv)
{
@@ -120,19 +174,30 @@ gvinum_create(int argc, char **argv)
struct gv_sd *s;
struct gv_volume *v;
FILE *tmp;
- int drives, errors, fd, line, plexes, plex_in_volume;
- int sd_in_plex, status, subdisks, tokens, volumes;
+ 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], *ed;
+ char buf[BUFSIZ], buf1[BUFSIZ], commandline[BUFSIZ], *ed, *sdname;
char original[BUFSIZ], tmpfile[20], *token[GV_MAXARGS];
char plex[GV_MAXPLEXNAME], volume[GV_MAXVOLNAME];
- if (argc == 2) {
- if ((tmp = fopen(argv[1], "r")) == NULL) {
- warn("can't open '%s' for reading", argv[1]);
- return;
- }
- } else {
+ 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[1], "r")) == NULL) {
+ warn("can't open '%s' for reading", argv[1]);
+ return;
+ }
+ }
+ }
+
+ /* We didn't get a file. */
+ if (tmp == NULL) {
snprintf(tmpfile, sizeof(tmpfile), "/tmp/gvinum.XXXXXX");
if ((fd = mkstemp(tmpfile)) == -1) {
@@ -167,9 +232,11 @@ gvinum_create(int argc, char **argv)
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 = 0;
+ plex_in_volume = sd_in_plex = undeffd = 0;
+ plex[0] = '\0';
errors = 0;
line = 1;
while ((fgets(buf, BUFSIZ, tmp)) != NULL) {
@@ -187,7 +254,7 @@ gvinum_create(int argc, char **argv)
* Copy the original input line in case we need it for error
* output.
*/
- strncpy(original, buf, sizeof(buf));
+ strlcpy(original, buf, sizeof(original));
tokens = gv_tokenize(buf, token, GV_MAXARGS);
if (tokens <= 0) {
@@ -214,7 +281,7 @@ gvinum_create(int argc, char **argv)
* Set default volume name for following plex
* definitions.
*/
- strncpy(volume, v->name, sizeof(volume));
+ strlcpy(volume, v->name, sizeof(volume));
snprintf(buf1, sizeof(buf1), "volume%d", volumes);
gctl_ro_param(req, buf1, sizeof(*v), v);
@@ -236,13 +303,13 @@ gvinum_create(int argc, char **argv)
/* Default name. */
if (strlen(p->name) == 0) {
- snprintf(p->name, GV_MAXPLEXNAME, "%s.p%d",
+ snprintf(p->name, sizeof(p->name), "%s.p%d",
volume, plex_in_volume++);
}
/* Default volume. */
if (strlen(p->volume) == 0) {
- snprintf(p->volume, GV_MAXVOLNAME, "%s",
+ snprintf(p->volume, sizeof(p->volume), "%s",
volume);
}
@@ -250,7 +317,7 @@ gvinum_create(int argc, char **argv)
* Set default plex name for following subdisk
* definitions.
*/
- strncpy(plex, p->name, GV_MAXPLEXNAME);
+ strlcpy(plex, p->name, sizeof(plex));
snprintf(buf1, sizeof(buf1), "plex%d", plexes);
gctl_ro_param(req, buf1, sizeof(*p), p);
@@ -270,13 +337,21 @@ gvinum_create(int argc, char **argv)
/* Default name. */
if (strlen(s->name) == 0) {
- snprintf(s->name, GV_MAXSDNAME, "%s.s%d",
- plex, sd_in_plex++);
+ 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, GV_MAXPLEXNAME, "%s", plex);
+ snprintf(s->plex, sizeof(s->plex), "%s", plex);
snprintf(buf1, sizeof(buf1), "sd%d", subdisks);
gctl_ro_param(req, buf1, sizeof(*s), s);
@@ -320,7 +395,284 @@ gvinum_create(int argc, char **argv)
warnx("create failed: %s", errstr);
}
gctl_free(req);
- gvinum_list(0, NULL);
+}
+
+/* Create a concatenated volume. */
+void
+gvinum_concat(int argc, char **argv)
+{
+
+ if (argc < 2) {
+ warnx("usage:\tconcat [-fv] [-n name] drives\n");
+ return;
+ }
+ create_volume(argc, argv, "concat");
+}
+
+
+/* Create a drive quick and dirty. */
+char *
+create_drive(char *device)
+{
+ struct gv_drive *d;
+ struct gctl_req *req;
+ const char *errstr;
+ char *drivename, *dname;
+ int drives, i, flags, volumes, subdisks, plexes;
+
+ flags = plexes = subdisks = volumes = 0;
+ drives = 1;
+ dname = NULL;
+
+ drivename = find_drive(device);
+ 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));
+ strlcpy(d->device, device, sizeof(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);
+ gctl_free(req);
+ return (NULL);
+ } else {
+ gctl_free(req);
+ /* 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)) {
+ free(dname);
+ return (drivename);
+ }
+ free(dname);
+ dname = NULL;
+ usleep(100000); /* Sleep for 0.1s */
+ }
+ }
+ gctl_free(req);
+ return (drivename);
+}
+
+/*
+ * General routine for creating a volume. Mainly for use by concat, mirror,
+ * raid5 and stripe commands.
+ */
+void
+create_volume(int argc, char **argv, 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>. */
+char *
+find_pattern(char *line, 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 a prefix. */
+char *
+find_name(const char *prefix, int type, int namelen)
+{
+ struct gctl_req *req;
+ char comment[1], buf[GV_CFG_LEN - 1], *name, *sname, *ptr;
+ const char *errstr;
+ int i, n, begin, len, conflict;
+ char line[1024];
+
+ comment[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_rw_param(req, "config", sizeof(buf), buf);
+ 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);
+}
+
+char *
+find_drive(const char *device)
+{
+
+ /* Strip possible /dev/ in front. */
+ if (strncmp(device, "/dev/", 5) == 0)
+ device += 5;
+ return (find_name("gvinumdrive", GV_TYPE_DRIVE, GV_MAXDRIVENAME));
+}
+
+/* Detach a plex or subdisk from its parent. */
+void
+gvinum_detach(int argc, char **argv)
+{
+ const char *errstr;
+ struct gctl_req *req;
+ int flags, i;
+
+ 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);
}
void
@@ -329,8 +681,18 @@ gvinum_help(void)
printf("COMMANDS\n"
"checkparity [-f] plex\n"
" Check the parity blocks of a RAID-5 plex.\n"
- "create description-file\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"
@@ -341,18 +703,22 @@ gvinum_help(void)
" 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\n"
" Reset the complete gvinum configuration\n"
- "rm [-r] volume | plex | subdisk | drive\n"
+ "rm [-r] [-f] volume | plex | subdisk | drive\n"
" Remove an object.\n"
"saveconfig\n"
" Save vinum configuration to disk after configuration"
@@ -363,6 +729,8 @@ gvinum_help(void)
" 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"
);
return;
@@ -488,6 +856,18 @@ gvinum_list(int argc, char **argv)
return;
}
+/* Create a mirrored volume. */
+void
+gvinum_mirror(int argc, char **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 [...]' */
void
gvinum_move(int argc, char **argv)
@@ -553,8 +933,7 @@ void
gvinum_parityop(int argc, char **argv, int rebuild)
{
struct gctl_req *req;
- int flags, i, rv;
- off_t offset;
+ int flags, i;
const char *errstr;
char *op, *msg;
@@ -591,47 +970,32 @@ gvinum_parityop(int argc, char **argv, int rebuild)
return;
}
- do {
- rv = 0;
- req = gctl_get_handle();
- gctl_ro_param(req, "class", -1, "VINUM");
- gctl_ro_param(req, "verb", -1, "parityop");
- gctl_ro_param(req, "flags", sizeof(int), &flags);
- gctl_ro_param(req, "rebuild", sizeof(int), &rebuild);
- gctl_rw_param(req, "rv", sizeof(int), &rv);
- gctl_rw_param(req, "offset", sizeof(off_t), &offset);
- gctl_ro_param(req, "plex", -1, argv[0]);
- errstr = gctl_issue(req);
- if (errstr) {
- warnx("%s\n", errstr);
- gctl_free(req);
- break;
- }
- gctl_free(req);
- if (flags & GV_FLAG_V) {
- printf("\r%s at %s ... ", msg,
- gv_roughlength(offset, 1));
- }
- if (rv == 1) {
- printf("Parity incorrect at offset 0x%jx\n",
- (intmax_t)offset);
- if (!rebuild)
- break;
- }
- fflush(stdout);
+ 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]);
- /* Clear the -f flag. */
- flags &= ~GV_FLAG_F;
- } while (rv >= 0);
+ errstr = gctl_issue(req);
+ if (errstr)
+ warnx("%s\n", errstr);
+ gctl_free(req);
+}
+
+/* Create a RAID-5 volume. */
+void
+gvinum_raid5(int argc, char **argv)
+{
- if ((rv == 2) && (flags & GV_FLAG_V)) {
- if (rebuild)
- printf("Rebuilt parity on %s\n", argv[0]);
- else
- printf("%s has correct parity\n", argv[0]);
+ if (argc < 2) {
+ warnx("usage:\traid5 [-fv] [-s stripesize] [-n name] drives\n");
+ return;
}
+ create_volume(argc, argv, "raid5");
}
+
void
gvinum_rename(int argc, char **argv)
{
@@ -697,8 +1061,11 @@ gvinum_rm(int argc, char **argv)
flags = 0;
optreset = 1;
optind = 1;
- while ((j = getopt(argc, argv, "r")) != -1) {
+ while ((j = getopt(argc, argv, "rf")) != -1) {
switch (j) {
+ case 'f':
+ flags |= GV_FLAG_F;
+ break;
case 'r':
flags |= GV_FLAG_R;
break;
@@ -728,7 +1095,6 @@ gvinum_rm(int argc, char **argv)
return;
}
gctl_free(req);
- gvinum_list(0, NULL);
}
void
@@ -763,7 +1129,6 @@ gvinum_resetconfig(void)
return;
}
gctl_free(req);
- gvinum_list(0, NULL);
printf("gvinum configuration obliterated\n");
}
@@ -833,28 +1198,134 @@ gvinum_start(int argc, char **argv)
}
gctl_free(req);
- gvinum_list(0, NULL);
}
void
gvinum_stop(int argc, char **argv)
{
- int fileid;
+ int err, fileid;
fileid = kldfind(GVINUMMOD);
if (fileid == -1) {
warn("cannot find " GVINUMMOD);
return;
}
- if (kldunload(fileid) != 0) {
+
+ /*
+ * 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 " GVINUMMOD " 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 " GVINUMMOD);
return;
}
- warnx(GVINUMMOD " unloaded");
+ printf("done\n");
exit(0);
}
+/* Create a striped volume. */
+void
+gvinum_stripe(int argc, char **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. */
+void
+gvinum_grow(int argc, char **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;
+
+ 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(argv[2]);
+ if (drive == NULL) {
+ warn("unable to find an appropriate drive name");
+ free(s);
+ free(d);
+ return;
+ }
+ strlcpy(d->name, drive, sizeof(d->name));
+ if (strncmp(argv[2], "/dev/", 5) == 0)
+ strlcpy(d->device, (argv[2] + 5), sizeof(d->device));
+ else
+ strlcpy(d->device, argv[2], sizeof(d->device));
+ 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);
+}
+
void
parseline(int argc, char **argv)
{
@@ -865,6 +1336,14 @@ parseline(int argc, char **argv)
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"))
@@ -877,12 +1356,16 @@ parseline(int argc, char **argv)
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"))
@@ -897,6 +1380,8 @@ parseline(int argc, char **argv)
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"))
diff --git a/sbin/ifconfig/ifclone.c b/sbin/ifconfig/ifclone.c
index 8fba9ff..aba974e 100644
--- a/sbin/ifconfig/ifclone.c
+++ b/sbin/ifconfig/ifclone.c
@@ -54,9 +54,9 @@ list_cloners(void)
int idx;
int s;
- s = socket(AF_INET, SOCK_DGRAM, 0);
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
if (s == -1)
- err(1, "socket(AF_INET,SOCK_DGRAM)");
+ err(1, "socket(AF_LOCAL,SOCK_DGRAM)");
memset(&ifcr, 0, sizeof(ifcr));
diff --git a/sbin/ifconfig/ifconfig.c b/sbin/ifconfig/ifconfig.c
index 3b6138d..73c8025 100644
--- a/sbin/ifconfig/ifconfig.c
+++ b/sbin/ifconfig/ifconfig.c
@@ -441,22 +441,23 @@ static const struct cmd setifdstaddr_cmd =
DEF_CMD("ifdstaddr", 0, setifdstaddr);
static int
-ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *afp)
+ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp)
{
- const struct afswtch *nafp;
+ const struct afswtch *afp, *nafp;
const struct cmd *p;
struct callback *cb;
int s;
strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name);
+ afp = uafp != NULL ? uafp : af_getbyname("inet");
top:
- if (afp == NULL)
- afp = af_getbyname("inet");
ifr.ifr_addr.sa_family =
afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ?
- AF_INET : afp->af_af;
+ AF_LOCAL : afp->af_af;
- if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0)
+ if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0 &&
+ (uafp != NULL || errno != EPROTONOSUPPORT ||
+ (s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0))
err(1, "socket(family %u,SOCK_DGRAM", ifr.ifr_addr.sa_family);
while (argc > 0) {
@@ -803,11 +804,12 @@ status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
if (afp == NULL) {
allfamilies = 1;
- afp = af_getbyname("inet");
- } else
+ ifr.ifr_addr.sa_family = AF_LOCAL;
+ } else {
allfamilies = 0;
-
- ifr.ifr_addr.sa_family = afp->af_af == AF_LINK ? AF_INET : afp->af_af;
+ ifr.ifr_addr.sa_family =
+ afp->af_af == AF_LINK ? AF_LOCAL : afp->af_af;
+ }
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
diff --git a/sbin/ifconfig/ifgroup.c b/sbin/ifconfig/ifgroup.c
index 88774a6..9eaac3b 100644
--- a/sbin/ifconfig/ifgroup.c
+++ b/sbin/ifconfig/ifgroup.c
@@ -131,9 +131,9 @@ printgroup(const char *groupname)
int len, cnt = 0;
int s;
- s = socket(AF_INET, SOCK_DGRAM, 0);
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
if (s == -1)
- err(1, "socket(AF_INET,SOCK_DGRAM)");
+ err(1, "socket(AF_LOCAL,SOCK_DGRAM)");
bzero(&ifgr, sizeof(ifgr));
strlcpy(ifgr.ifgr_name, groupname, sizeof(ifgr.ifgr_name));
if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1) {
diff --git a/sbin/ifconfig/ifieee80211.c b/sbin/ifconfig/ifieee80211.c
index 16615a3..aafb26e 100644
--- a/sbin/ifconfig/ifieee80211.c
+++ b/sbin/ifconfig/ifieee80211.c
@@ -78,6 +78,9 @@
#include <net/route.h>
#include <net80211/ieee80211_ioctl.h>
+#include <net80211/ieee80211_freebsd.h>
+#include <net80211/ieee80211_superg.h>
+#include <net80211/ieee80211_tdma.h>
#include <assert.h>
#include <ctype.h>
@@ -3020,13 +3023,6 @@ list_scan(int s)
} while (len >= sizeof(struct ieee80211req_scan_result));
}
-#ifdef __FreeBSD__
-#include <net80211/ieee80211_freebsd.h>
-#endif
-#ifdef __NetBSD__
-#include <net80211/ieee80211_netbsd.h>
-#endif
-
static void
scan_and_wait(int s)
{
diff --git a/sbin/ipfw/dummynet.c b/sbin/ipfw/dummynet.c
index 5c83db9..c6e6b37 100644
--- a/sbin/ipfw/dummynet.c
+++ b/sbin/ipfw/dummynet.c
@@ -69,6 +69,7 @@ static struct _s_x dummynet_params[] = {
{ "dst-ip6", TOK_DSTIP6},
{ "src-ipv6", TOK_SRCIP6},
{ "src-ip6", TOK_SRCIP6},
+ { "profile", TOK_PIPE_PROFILE},
{ "dummynet-params", TOK_NULL },
{ NULL, 0 } /* terminator */
};
@@ -248,6 +249,19 @@ print_flowset_parms(struct dn_flow_set *fs, char *prefix)
prefix, qs, plr, fs->rq_elements, fs->rq_size, red);
}
+static void
+print_extra_delay_parms(struct dn_pipe *p, char *prefix)
+{
+ double loss;
+ if (p->samples_no <= 0)
+ return;
+
+ loss = p->loss_level;
+ loss /= p->samples_no;
+ printf("%s profile: name \"%s\" loss %f samples %d\n",
+ prefix, p->name, loss, p->samples_no);
+}
+
void
ipfw_list_pipes(void *data, uint nbytes, int ac, char *av[])
{
@@ -296,6 +310,9 @@ ipfw_list_pipes(void *data, uint nbytes, int ac, char *av[])
sprintf(prefix, "%05d: %s %4d ms ",
p->pipe_nr, buf, p->delay);
+
+ print_extra_delay_parms(p, prefix);
+
print_flowset_parms(&(p->fs), prefix);
if (co.verbose)
printf(" V %20llu\n", align_uint64(&p->V) >> MY_M);
@@ -346,9 +363,284 @@ ipfw_delete_pipe(int pipe_or_queue, int i)
return i;
}
+/*
+ * Code to parse delay profiles.
+ *
+ * Some link types introduce extra delays in the transmission
+ * of a packet, e.g. because of MAC level framing, contention on
+ * the use of the channel, MAC level retransmissions and so on.
+ * From our point of view, the channel is effectively unavailable
+ * for this extra time, which is constant or variable depending
+ * on the link type. Additionally, packets may be dropped after this
+ * time (e.g. on a wireless link after too many retransmissions).
+ * We can model the additional delay with an empirical curve
+ * that represents its distribution.
+ *
+ * cumulative probability
+ * 1.0 ^
+ * |
+ * L +-- loss-level x
+ * | ******
+ * | *
+ * | *****
+ * | *
+ * | **
+ * | *
+ * +-------*------------------->
+ * delay
+ *
+ * The empirical curve may have both vertical and horizontal lines.
+ * Vertical lines represent constant delay for a range of
+ * probabilities; horizontal lines correspond to a discontinuty
+ * in the delay distribution: the pipe will use the largest delay
+ * for a given probability.
+ *
+ * To pass the curve to dummynet, we must store the parameters
+ * in a file as described below, and issue the command
+ *
+ * ipfw pipe <n> config ... bw XXX profile <filename> ...
+ *
+ * The file format is the following, with whitespace acting as
+ * a separator and '#' indicating the beginning a comment:
+ *
+ * samples N
+ * the number of samples used in the internal
+ * representation (2..1024; default 100);
+ *
+ * loss-level L
+ * The probability above which packets are lost.
+ * (0.0 <= L <= 1.0, default 1.0 i.e. no loss);
+ *
+ * name identifier
+ * Optional a name (listed by "ipfw pipe show")
+ * to identify the distribution;
+ *
+ * "delay prob" | "prob delay"
+ * One of these two lines is mandatory and defines
+ * the format of the following lines with data points.
+ *
+ * XXX YYY
+ * 2 or more lines representing points in the curve,
+ * with either delay or probability first, according
+ * to the chosen format.
+ * The unit for delay is milliseconds.
+ *
+ * Data points does not need to be ordered or equal to the number
+ * specified in the "samples" line. ipfw will sort and interpolate
+ * the curve as needed.
+ *
+ * Example of a profile file:
+
+ name bla_bla_bla
+ samples 100
+ loss-level 0.86
+ prob delay
+ 0 200 # minimum overhead is 200ms
+ 0.5 200
+ 0.5 300
+ 0.8 1000
+ 0.9 1300
+ 1 1300
+
+ * Internally, we will convert the curve to a fixed number of
+ * samples, and when it is time to transmit a packet we will
+ * model the extra delay as extra bits in the packet.
+ *
+ */
+
+#define ED_MAX_LINE_LEN 256+ED_MAX_NAME_LEN
+#define ED_TOK_SAMPLES "samples"
+#define ED_TOK_LOSS "loss-level"
+#define ED_TOK_NAME "name"
+#define ED_TOK_DELAY "delay"
+#define ED_TOK_PROB "prob"
+#define ED_SEPARATORS " \t\n"
+#define ED_MIN_SAMPLES_NO 2
+
+/*
+ * returns 1 if s is a non-negative number, with at least one '.'
+ */
+static int
+is_valid_number(const char *s)
+{
+ int i, dots_found = 0;
+ int len = strlen(s);
+
+ for (i = 0; i<len; ++i)
+ if (!isdigit(s[i]) && (s[i] !='.' || ++dots_found > 1))
+ return 0;
+ return 1;
+}
+
+struct point {
+ double prob;
+ double delay;
+};
+
+int
+compare_points(const void *vp1, const void *vp2)
+{
+ const struct point *p1 = vp1;
+ const struct point *p2 = vp2;
+ double res = 0;
+
+ res = p1->prob - p2->prob;
+ if (res == 0)
+ res = p1->delay - p2->delay;
+ if (res < 0)
+ return -1;
+ else if (res > 0)
+ return 1;
+ else
+ return 0;
+}
+
+#define ED_EFMT(s) EX_DATAERR,"error in %s at line %d: "#s,filename,lineno
+
+static void
+load_extra_delays(const char *filename, struct dn_pipe *p)
+{
+ char line[ED_MAX_LINE_LEN];
+ FILE *f;
+ int lineno = 0;
+ int i;
+
+ int samples = -1;
+ double loss = -1.0;
+ char profile_name[ED_MAX_NAME_LEN];
+ int delay_first = -1;
+ int do_points = 0;
+ struct point points[ED_MAX_SAMPLES_NO];
+ int points_no = 0;
+
+ profile_name[0] = '\0';
+ f = fopen(filename, "r");
+ if (f == NULL)
+ err(EX_UNAVAILABLE, "fopen: %s", filename);
+
+ while (fgets(line, ED_MAX_LINE_LEN, f)) { /* read commands */
+ char *s, *cur = line, *name = NULL, *arg = NULL;
+
+ ++lineno;
+
+ /* parse the line */
+ while (cur) {
+ s = strsep(&cur, ED_SEPARATORS);
+ if (s == NULL || *s == '#')
+ break;
+ if (*s == '\0')
+ continue;
+ if (arg)
+ errx(ED_EFMT("too many arguments"));
+ if (name == NULL)
+ name = s;
+ else
+ arg = s;
+ }
+ if (name == NULL) /* empty line */
+ continue;
+ if (arg == NULL)
+ errx(ED_EFMT("missing arg for %s"), name);
+
+ if (!strcasecmp(name, ED_TOK_SAMPLES)) {
+ if (samples > 0)
+ errx(ED_EFMT("duplicate ``samples'' line"));
+ if (atoi(arg) <=0)
+ errx(ED_EFMT("invalid number of samples"));
+ samples = atoi(arg);
+ if (samples>ED_MAX_SAMPLES_NO)
+ errx(ED_EFMT("too many samples, maximum is %d"),
+ ED_MAX_SAMPLES_NO);
+ do_points = 0;
+ } else if (!strcasecmp(name, ED_TOK_LOSS)) {
+ if (loss != -1.0)
+ errx(ED_EFMT("duplicated token: %s"), name);
+ if (!is_valid_number(arg))
+ errx(ED_EFMT("invalid %s"), arg);
+ loss = atof(arg);
+ if (loss > 1)
+ errx(ED_EFMT("%s greater than 1.0"), name);
+ do_points = 0;
+ } else if (!strcasecmp(name, ED_TOK_NAME)) {
+ if (profile_name[0] != '\0')
+ errx(ED_EFMT("duplicated token: %s"), name);
+ strncpy(profile_name, arg, sizeof(profile_name) - 1);
+ profile_name[sizeof(profile_name)-1] = '\0';
+ do_points = 0;
+ } else if (!strcasecmp(name, ED_TOK_DELAY)) {
+ if (do_points)
+ errx(ED_EFMT("duplicated token: %s"), name);
+ delay_first = 1;
+ do_points = 1;
+ } else if (!strcasecmp(name, ED_TOK_PROB)) {
+ if (do_points)
+ errx(ED_EFMT("duplicated token: %s"), name);
+ delay_first = 0;
+ do_points = 1;
+ } else if (do_points) {
+ if (!is_valid_number(name) || !is_valid_number(arg))
+ errx(ED_EFMT("invalid point found"));
+ if (delay_first) {
+ points[points_no].delay = atof(name);
+ points[points_no].prob = atof(arg);
+ } else {
+ points[points_no].delay = atof(arg);
+ points[points_no].prob = atof(name);
+ }
+ if (points[points_no].prob > 1.0)
+ errx(ED_EFMT("probability greater than 1.0"));
+ ++points_no;
+ } else {
+ errx(ED_EFMT("unrecognised command '%s'"), name);
+ }
+ }
+
+ if (samples == -1) {
+ warnx("'%s' not found, assuming 100", ED_TOK_SAMPLES);
+ samples = 100;
+ }
+
+ if (loss == -1.0) {
+ warnx("'%s' not found, assuming no loss", ED_TOK_LOSS);
+ loss = 1;
+ }
+
+ /* make sure that there are enough points. */
+ if (points_no < ED_MIN_SAMPLES_NO)
+ errx(ED_EFMT("too few samples, need at least %d"),
+ ED_MIN_SAMPLES_NO);
+
+ qsort(points, points_no, sizeof(struct point), compare_points);
+
+ /* interpolation */
+ for (i = 0; i<points_no-1; ++i) {
+ double y1 = points[i].prob * samples;
+ double x1 = points[i].delay;
+ double y2 = points[i+1].prob * samples;
+ double x2 = points[i+1].delay;
+
+ int index = y1;
+ int stop = y2;
+
+ if (x1 == x2) {
+ for (; index<stop; ++index)
+ p->samples[index] = x1;
+ } else {
+ double m = (y2-y1)/(x2-x1);
+ double c = y1 - m*x1;
+ for (; index<stop ; ++index)
+ p->samples[index] = (index - c)/m;
+ }
+ }
+ p->samples_no = samples;
+ p->loss_level = loss * samples;
+ strncpy(p->name, profile_name, sizeof(p->name));
+}
+
void
ipfw_config_pipe(int ac, char **av)
{
+ int samples[ED_MAX_SAMPLES_NO];
struct dn_pipe p;
int i;
char *end;
@@ -611,6 +903,15 @@ end_mask:
ac--; av++;
break;
+ case TOK_PIPE_PROFILE:
+ if (co.do_pipe != 1)
+ errx(EX_DATAERR, "extra delay only valid for pipes");
+ NEED1("extra delay needs the file name\n");
+ p.samples = &samples[0];
+ load_extra_delays(av[0], &p);
+ --ac; ++av;
+ break;
+
default:
errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]);
}
@@ -620,6 +921,9 @@ end_mask:
errx(EX_DATAERR, "pipe_nr must be > 0");
if (p.delay > 10000)
errx(EX_DATAERR, "delay must be < 10000");
+ if (p.samples_no > 0 && p.bandwidth == 0)
+ errx(EX_DATAERR,
+ "profile requires a bandwidth limit");
} else { /* co.do_pipe == 2, queue */
if (p.fs.parent_nr == 0)
errx(EX_DATAERR, "pipe must be > 0");
@@ -713,7 +1017,18 @@ end_mask:
weight *= 1 - w_q;
p.fs.lookup_weight = (int)(weight * (1 << SCALE_RED));
}
- i = do_cmd(IP_DUMMYNET_CONFIGURE, &p, sizeof p);
+ if (p.samples_no <= 0) {
+ i = do_cmd(IP_DUMMYNET_CONFIGURE, &p, sizeof p);
+ } else {
+ struct dn_pipe_max pm;
+ int len = sizeof(pm);
+
+ memcpy(&pm.pipe, &p, sizeof(pm.pipe));
+ memcpy(&pm.samples, samples, sizeof(pm.samples));
+
+ i = do_cmd(IP_DUMMYNET_CONFIGURE, &pm, len);
+ }
+
if (i)
err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE");
}
diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index 997be62..58985cd 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,7 +1,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 27, 2008
+.Dd April 9, 2009
.Dt IPFW 8
.Os
.Sh NAME
@@ -136,12 +136,13 @@ If the ruleset includes one or more rules with the
.Cm keep-state
or
.Cm limit
-option, then
+option,
.Nm
-assumes a
+will have a
.Em stateful
behaviour, i.e., upon a match it will create dynamic rules matching
-the exact parameters (addresses and ports) of the matching packet.
+the exact parameters (source and destination addresses and ports)
+of the matching packet.
.Pp
These dynamic rules, which have a limited lifetime, are checked
at the first occurrence of a
@@ -165,6 +166,21 @@ Counters can be displayed or reset with
.Nm
commands.
.Pp
+Each rule belongs to one of 32 different
+.Em sets
+, and there are
+.Nm
+commands to atomically manipulate sets, such as enable,
+disable, swap sets, move all rules in a set to another
+one, delete all rules in a set.
+These can be useful to
+install temporary configurations, or to test them.
+See Section
+.Sx SETS OF RULES
+for more information on
+.Em sets .
+.Pp
+.Pp
Rules can be added with the
.Cm add
command; deleted individually or in groups with the
@@ -183,48 +199,36 @@ and
.Cm resetlog
commands.
.Pp
-Also, each rule belongs to one of 32 different
-.Em sets
-, and there are
-.Nm
-commands to atomically manipulate sets, such as enable,
-disable, swap sets, move all rules in a set to another
-one, delete all rules in a set.
-These can be useful to
-install temporary configurations, or to test them.
-See Section
-.Sx SETS OF RULES
-for more information on
-.Em sets .
-.Pp
-The following options are available:
+.Ss COMMAND OPTIONS
+The following general options are available when invoking
+.Nm :
.Bl -tag -width indent
.It Fl a
-While listing, show counter values.
+Show counter values when listing rules.
The
.Cm show
-command just implies this option.
+command implies this option.
.It Fl b
Only show the action and the comment, not the body of a rule.
Implies
.Fl c .
.It Fl c
When entering or showing rules, print them in compact form,
-i.e., without the optional "ip from any to any" string
+i.e., omitting the "ip from any to any" string
when this does not carry any additional information.
.It Fl d
-While listing, show dynamic rules in addition to static ones.
+When listing, show dynamic rules in addition to static ones.
.It Fl e
-While listing, if the
+When listing and
.Fl d
-option was specified, also show expired dynamic rules.
+is specified, also show expired dynamic rules.
.It Fl f
Do not ask for confirmation for commands that can cause problems
if misused,
.No i.e. Cm flush .
If there is no tty associated with the process, this is implied.
.It Fl i
-While listing a table (see the
+When listing a table (see the
.Sx LOOKUP TABLES
section below for more information on lookup tables), format values
as IP addresses. By default, values are shown as integers.
@@ -234,47 +238,48 @@ them to the kernel.
.It Fl N
Try to resolve addresses and service names in output.
.It Fl q
-While
-.Cm add Ns ing ,
-.Cm nat Ns ing ,
-.Cm zero Ns ing ,
-.Cm resetlog Ns ging
+Be quiet when executing the
+.Cm add ,
+.Cm nat ,
+.Cm zero ,
+.Cm resetlog
or
-.Cm flush Ns ing ,
-be quiet about actions
+.Cm flush
+commands;
(implies
.Fl f ) .
-This is useful for adjusting rules by executing multiple
+This is useful when updating rulesets by executing multiple
.Nm
commands in a script
(e.g.,
.Ql sh\ /etc/rc.firewall ) ,
-or by processing a file of many
+or by processing a file with many
.Nm
rules across a remote login session.
It also stops a table add or delete
from failing if the entry already exists or is not present.
-If a
-.Cm flush
-is performed in normal (verbose) mode (with the default kernel
-configuration), it prints a message.
-Because all rules are flushed, the message might not be delivered
-to the login session, causing the remote login session to be closed
-and the remainder of the ruleset to not be processed.
+.Pp
+The reason why this option may be important is that
+for some of these actions,
+.Nm
+may print a message; if the action results in blocking the
+traffic to the remote client,
+the remote login session will be closed
+and the rest of the ruleset will not be processed.
Access to the console would then be required to recover.
.It Fl S
-While listing rules, show the
+When listing rules, show the
.Em set
each rule belongs to.
If this flag is not specified, disabled rules will not be
listed.
.It Fl s Op Ar field
-While listing pipes, sort according to one of the four
+When listing pipes, sort according to one of the four
counters (total or current packets or bytes).
.It Fl t
-While listing, show last match timestamp (converted with ctime()).
+When listing, show last match timestamp converted with ctime().
.It Fl T
-While listing, show last match timestamp (as seconds from the epoch).
+When listing, show last match timestamp as seconds from the epoch.
This form can be more convenient for postprocessing by scripts.
.El
.Pp
@@ -589,7 +594,7 @@ The tag acts as an internal marker (it is not sent out over
the wire) that can be used to identify these packets later on.
This can be used, for example, to provide trust between interfaces
and to start doing policy-based filtering.
-A packet can have mutiple tags at the same time.
+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
@@ -606,10 +611,10 @@ To delete previously applied tag, use the
keyword.
.Pp
Note: since tags are kept with the packet everywhere in kernelspace,
-they can be set and unset anywhere in kernel network subsystem
-(using
+they can be set and unset anywhere in the kernel network subsystem
+(using the
.Xr mbuf_tags 9
-facility), not only by means of
+facility), not only by means of the
.Xr ipfw 4
.Cm tag
and
@@ -862,10 +867,43 @@ actions.
.It Cm setfib Ar fibnum
The packet is tagged so as to use the FIB (routing table)
.Ar fibnum
-in any subsequent forwarding decisions. Initially this is
-limited to the values 0 through 15. See
+in any subsequent forwarding decisions.
+Initially this is limited to the values 0 through 15, see
.Xr setfib 8 .
Processing continues at the next rule.
+.It Cm reass
+Queue and reassemble ip fragments.
+If the packet is not fragmented, counters are updated and processing continues with the next rule.
+If the packet is the last logical fragment, the packet is reassembled and, if
+.Va net.inet.ip.fw.one_pass
+is set to 0, processing continues with the next rule, else packet is allowed to pass and search terminates.
+If the packet is a fragment in the middle, it is consumed and processing stops immediately.
+.Pp
+Fragments handling can be tuned via
+.Va net.inet.ip.maxfragpackets
+and
+.Va net.inet.ip.maxfragsperpacket
+which limit, respectively, the maximum number of processable fragments (default: 800) and
+the maximum number of fragments per packet (default: 16).
+.Pp
+NOTA BENE: since fragments do not contain port numbers, they should be avoided with the
+.Nm reass
+rule.
+Alternatively, direction-based (like
+.Nm in
+/
+.Nm out
+) and source-based (like
+.Nm via
+) match patterns can be used to select fragments.
+.Pp
+Usually a simple rule like:
+.Bd -literal -offset indent
+# reassemble incoming fragments
+ipfw add reass all from any to any in
+.Ed
+.Pp
+is all you need at the beginning of your ruleset.
.El
.Ss RULE BODY
The body of a rule contains zero or more patterns (such as
@@ -1166,7 +1204,7 @@ Destination options
.Pq Cm dstopt ,
IPSec authentication headers
.Pq Cm ah ,
-and IPSec encapsulated security payload headers
+and IPsec encapsulated security payload headers
.Pq Cm esp .
.It Cm fib Ar fibnum
Matches a packet that has been tagged to use
@@ -1175,7 +1213,7 @@ the given FIB (routing table) number.
Matches IPv6 packets containing any of the flow labels given in
.Ar labels .
.Ar labels
-is a comma seperate list of numeric flow labels.
+is a comma separated list of numeric flow labels.
.It Cm frag
Matches packets that are fragments and not the first
fragment of an IP datagram.
@@ -1784,17 +1822,47 @@ for more examples on how to use dynamic rules.
.Nm
is also the user interface for the
.Nm dummynet
-traffic shaper.
+traffic shaper and network emulator, a subsystem that
+can artificially queue, delay or drop packets
+emulator the behaviour of certain network links
+or queueing systems.
.Pp
.Nm dummynet
-operates by first using the firewall to classify packets and divide them into
-.Em flows ,
+operates by first using the firewall to select packets
using any match pattern that can be used in
.Nm
rules.
-Depending on local policies, a flow can contain packets for a single
-TCP connection, or from/to a given host, or entire subnet, or a
-protocol type, etc.
+Matching packets are then passed to either of two
+different objects, which implement the traffic regulation:
+.Bl -hang -offset XXXX
+.It Em pipe
+A pipe emulates a link with given bandwidth, propagation delay,
+queue size and packet loss rate.
+Packets are queued in front of the pipe as they come out from the classifier,
+and then transferred to the pipe according to the pipe's parameters.
+.It Em queue
+A queue
+is an abstraction used to implement the WF2Q+
+(Worst-case Fair Weighted Fair Queueing) policy, which is
+an efficient variant of the WFQ policy.
+.Pp
+The queue associates a
+.Em weight
+and a reference pipe to each flow (a flow is a set of packets
+with the same addresses and ports after masking).
+All backlogged flows (i.e., those
+with packets queued) linked to the same pipe share the pipe's
+bandwidth proportionally to their weights.
+Note that weights are not priorities; a flow with a lower weight
+is still guaranteed to get its fraction of the bandwidth even if a
+flow with a higher weight is permanently backlogged.
+.El
+.Pp
+In practice,
+.Em pipes
+can be used to set hard limits to the bandwidth that a flow can use, whereas
+.Em queues
+can be used to determine how different flows share the available bandwidth.
.Pp
There are two modes of
.Nm dummynet
@@ -1827,37 +1895,7 @@ mode can be enabled by setting the
.Xr sysctl 8
variable to a non-zero value.
.Pp
-Packets belonging to the same flow are then passed to either of two
-different objects, which implement the traffic regulation:
-.Bl -hang -offset XXXX
-.It Em pipe
-A pipe emulates a link with given bandwidth, propagation delay,
-queue size and packet loss rate.
-Packets are queued in front of the pipe as they come out from the classifier,
-and then transferred to the pipe according to the pipe's parameters.
-.Pp
-.It Em queue
-A queue
-is an abstraction used to implement the WF2Q+
-(Worst-case Fair Weighted Fair Queueing) policy, which is
-an efficient variant of the WFQ policy.
-.br
-The queue associates a
-.Em weight
-and a reference pipe to each flow, and then all backlogged (i.e.,
-with packets queued) flows linked to the same pipe share the pipe's
-bandwidth proportionally to their weights.
-Note that weights are not priorities; a flow with a lower weight
-is still guaranteed to get its fraction of the bandwidth even if a
-flow with a higher weight is permanently backlogged.
-.Pp
-.El
-In practice,
-.Em pipes
-can be used to set hard limits to the bandwidth that a flow can use, whereas
-.Em queues
-can be used to determine how different flows share the available bandwidth.
-.Pp
+.Ss PIPE AND QUEUE CONFIGURATION
The
.Em pipe
and
@@ -1904,6 +1942,83 @@ with
to reduce
the granularity to 1ms or less).
Default value is 0, meaning no delay.
+.Pp
+.It Cm profile Ar filename
+A file specifying the additional overhead incurred in the transmission
+of a packet on the link.
+.Pp
+Some link types introduce extra delays in the transmission
+of a packet, e.g. because of MAC level framing, contention on
+the use of the channel, MAC level retransmissions and so on.
+From our point of view, the channel is effectively unavailable
+for this extra time, which is constant or variable depending
+on the link type. Additionally, packets may be dropped after this
+time (e.g. on a wireless link after too many retransmissions).
+We can model the additional delay with an empirical curve
+that represents its distribution.
+.Bd -literal -offset indent
+ cumulative probability
+ 1.0 ^
+ |
+ L +-- loss-level x
+ | ******
+ | *
+ | *****
+ | *
+ | **
+ | *
+ +-------*------------------->
+ delay
+.Ed
+The empirical curve may have both vertical and horizontal lines.
+Vertical lines represent constant delay for a range of
+probabilities.
+Horizontal lines correspond to a discontinuty in the delay
+distribution: the pipe will use the largest delay for a
+given probability.
+.Pp
+The file format is the following, with whitespace acting as
+a separator and '#' indicating the beginning a comment:
+.Bl -tag -width indent
+.It Cm samples Ar N
+the number of samples used in the internal
+representation (2..1024; default 100);
+.It Cm loss-level Ar L
+The probability above which packets are lost.
+(0.0 <= L <= 1.0, default 1.0 i.e. no loss);
+.It Cm name Ar identifier
+Optional a name (listed by "ipfw pipe show")
+to identify the distribution;
+.It Cm "delay prob" | "prob delay"
+One of these two lines is mandatory and defines
+the format of the following lines with data points.
+.It Ar XXX Ar YYY
+2 or more lines representing points in the curve,
+with either delay or probability first, according
+to the chosen format.
+The unit for delay is milliseconds.
+Data points do not need to be ordered or equal to the number
+specified in the "samples" line.
+The
+.Nm
+utility will sort and interpolate
+the curve as needed.
+.El
+.Pp
+Example of a profile file:
+.Bd -literal -offset indent
+name bla_bla_bla
+samples 100
+loss-level 0.86
+prob delay
+0 200 # minimum overhead is 200ms
+0.5 200
+0.5 300
+0.8 1000
+0.9 1300
+1 1300
+#configuration file end
+.Ed
.El
.Pp
The following parameters can be configured for a queue:
@@ -2101,7 +2216,7 @@ If you are logged in over a network, loading the
version of
.Nm
is probably not as straightforward as you would think.
-I recommend the following command line:
+The following command line is recommended:
.Bd -literal -offset indent
kldload ipfw && \e
ipfw add 32000 allow ip from any to any
@@ -2131,6 +2246,11 @@ If no socket is bound to the destination port, or if the divert module is
not loaded, or if the kernel was not compiled with divert socket support,
the packets are dropped.
.Sh NETWORK ADDRESS TRANSLATION (NAT)
+.Pp
+.Nm
+support in-kernel NAT using the kernel version of
+.Xr libalias 3 .
+.Pp
The nat configuration command is the following:
.Bd -ragged -offset indent
.Bk -words
@@ -2141,14 +2261,13 @@ The nat configuration command is the following:
.Ek
.Ed
.Pp
-.
The following parameters can be configured:
.Bl -tag -width indent
.It Cm ip Ar ip_address
Define an ip address to use for aliasing.
.It Cm if Ar nic
-Use ip addres of NIC for aliasing, dynamically changing
-it if NIC's ip address change.
+Use ip address of NIC for aliasing, dynamically changing
+it if NIC's ip address changes.
.It Cm log
Enable logging on this nat instance.
.It Cm deny_in
@@ -2171,27 +2290,26 @@ To let the packet continue after being (de)aliased, set the sysctl variable
.Va net.inet.ip.fw.one_pass
to 0.
For more information about aliasing modes, refer to
-.Xr libalias 3
-.
+.Xr libalias 3 .
See Section
.Sx EXAMPLES
for some examples about nat usage.
-.Sh REDIRECT AND LSNAT SUPPORT IN IPFW
+.Ss REDIRECT AND LSNAT SUPPORT IN IPFW
Redirect and LSNAT support follow closely the syntax used in
-.Xr natd 8
-.
+.Xr natd 8 .
See Section
.Sx EXAMPLES
for some examples on how to do redirect and lsnat.
-.Sh SCTP NAT SUPPORT
-Sctp nat can be configured in a simillar manner to TCP through the
-ipfw command line tool
-.Xr ipfw 8
-, the main difference is that
+.Ss SCTP NAT SUPPORT
+SCTP nat can be configured in a similar manner to TCP through the
+.Nm
+command line tool.
+The main difference is that
.Nm sctp nat
-does not do port
-translation. Since the local and global side ports will be the same,
-there is no need to specify both. Ports are redirected as follows:
+does not do port translation.
+Since the local and global side ports will be the same,
+there is no need to specify both.
+Ports are redirected as follows:
.Bd -ragged -offset indent
.Bk -words
.Cm nat
@@ -2203,15 +2321,16 @@ there is no need to specify both. Ports are redirected as follows:
.Ek
.Ed
.Pp
-.
Most
-.B sctp nat
+.Nm sctp nat
configuration can be done in real-time through the
-.B sysctl(8)
-interface. All may be changed dynamically, though the hash_table size will only
-change for new
-.Nm nat
-instances. See
+.Xr sysctl 8
+interface.
+All may be changed dynamically, though the hash_table size will only
+change for new
+.Nm nat
+instances.
+See
.Sx SYSCTL VARIABLES
for more info.
.Sh SYSCTL VARIABLES
@@ -2238,22 +2357,23 @@ ports and vtags match but global address does not)
will accept and process all OOTB global AddIP messages.
.El
.Pp
-Option 1 should never be selected as this forms a security risk. An attacker can
+Option 1 should never be selected as this forms a security risk.
+An attacker can
establish multiple fake associations by sending AddIP messages.
.It Va net.inet.ip.alias.sctp.chunk_proc_limit: No 5
Defines the maximum number of chunks in an SCTP packet that will be parsed for a
-packet that matches an existing association. This value is enforced to be greater or equal
-than
+packet that matches an existing association.
+This value is enforced to be greater or equal than
.Cm net.inet.ip.alias.sctp.initialising_chunk_proc_limit .
A high value is
a DoS risk yet setting too low a value may result in important control chunks in
the packet not being located and parsed.
.It Va net.inet.ip.alias.sctp.error_on_ootb: No 1
-Defines when the
+Defines when the
.Nm nat
-responds to any Out-of-the-Blue (OOTB) packets with ErrorM
-packets. An OOTB packet is a packet that arrives with no existing association
-registered in the
+responds to any Out-of-the-Blue (OOTB) packets with ErrorM packets.
+An OOTB packet is a packet that arrives with no existing association
+registered in the
.Nm nat
and is not an INIT or ASCONF-AddIP packet:
.Bl -tag -width indent
@@ -2263,8 +2383,8 @@ ErrorM is never sent in response to OOTB packets.
ErrorM is only sent to OOTB packets received on the local side.
.It Cm 2
ErrorM is sent to the local side and on the global side ONLY if there is a
-partial match (ports and vtags match but the source global IP does not). This
-value is only useful if the
+partial match (ports and vtags match but the source global IP does not).
+This value is only useful if the
.Nm nat
is tracking global IP addresses.
.It Cm 3
@@ -2273,20 +2393,21 @@ ErrorM is sent in response to all OOTB packets on both the local and global side
.El
.Pp
At the moment the default is 0, since the ErrorM packet is not yet
-supported by most SCTP stacks. When it is supported, and if not tracking
+supported by most SCTP stacks.
+When it is supported, and if not tracking
global addresses, we recommend setting this value to 1 to allow
multi-homed local hosts to function with the
.Nm nat .
To track global addresses, we recommend setting this value to 2 to
allow global hosts to be informed when they need to (re)send an
-ASCONF-AddIP. Value 3 should never be chosen (except for debugging) as
-the
+ASCONF-AddIP.
+Value 3 should never be chosen (except for debugging) as the
.Nm nat
will respond to all OOTB global packets (a DoS risk).
.It Va net.inet.ip.alias.sctp.hashtable_size: No 2003
Size of hash tables used for
.Nm nat
-lookups (100 < prime_number > 1000001)
+lookups (100 < prime_number > 1000001).
This value sets the
.Nm hash table
size for any future created
@@ -2294,26 +2415,33 @@ size for any future created
instance and therefore must be set prior to creating a
.Nm nat
instance.
-The table sizes my be changed to suit specific needs. If there will be few
-concurrent associations, and memory is scarce, you may make these smaller. If
-there will be many thousands (or millions) of concurrent associations, you
-should make these larger. A prime number is best for the table size. The sysctl
+The table sizes may be changed to suit specific needs.
+If there will be few
+concurrent associations, and memory is scarce, you may make these smaller.
+If there will be many thousands (or millions) of concurrent associations, you
+should make these larger.
+A prime number is best for the table size.
+The sysctl
update function will adjust your input value to the next highest prime number.
.It Va net.inet.ip.alias.sctp.holddown_time: No 0
Hold association in table for this many seconds after receiving a
-SHUTDOWN-COMPLETE. This allows endpoints to correct shutdown gracefully if a
+SHUTDOWN-COMPLETE.
+This allows endpoints to correct shutdown gracefully if a
shutdown_complete is lost and retransmissions are required.
.It Va net.inet.ip.alias.sctp.init_timer: No 15
Timeout value while waiting for (INIT-ACK|AddIP-ACK).
This value cannot be 0.
.It Va net.inet.ip.alias.sctp.initialising_chunk_proc_limit: No 2
Defines the maximum number of chunks in an SCTP packet that will be parsed when
-no existing association exists that matches that packet. Ideally this packet
-will only be an INIT or ASCONF-AddIP packet. A higher value may become a DoS
+no existing association exists that matches that packet.
+Ideally this packet
+will only be an INIT or ASCONF-AddIP packet.
+A higher value may become a DoS
risk as malformed packets can consume processing resources.
.It Va net.inet.ip.alias.sctp.param_proc_limit: No 25
Defines the maximum number of parameters within a chunk that will be parsed in a
-packet. As for other similar sysctl variables, larger values pose a DoS risk.
+packet.
+As for other similar sysctl variables, larger values pose a DoS risk.
.It Va net.inet.ip.alias.sctp.log_level: No 0
Level of detail in the system log messages (0 \- minimal, 1 \- event,
2 \- info, 3 \- detail, 4 \- debug, 5 \- max debug). May be a good
@@ -2335,7 +2463,7 @@ association is limited to this value
.El
.Pp
This variable is fully dynamic, the new value will be adopted for all newly
-arriving associations, existing association are treated as they were previously.
+arriving associations, existing associations are treated as they were previously.
Global tracking will decrease the number of collisions within the
.Nm nat
at a cost
@@ -2552,10 +2680,10 @@ by adding the following to the top of a ruleset:
This rule drops all incoming packets that appear to be coming from another
directly connected system but on the wrong interface.
For example, a packet with a source address of
-.Li 192.168.0.0/24
-, configured on
-.Li fxp0
-, but coming in on
+.Li 192.168.0.0/24 ,
+configured on
+.Li fxp0 ,
+but coming in on
.Li fxp1
would be dropped.
.Ss DYNAMIC RULES
@@ -2815,7 +2943,7 @@ Or a redirect rule with mixed modes could looks like:
.Dl " redirect_port tcp 192.168.0.1:80,192.168.0.10:22"
.Dl " 500 # LSNAT"
.Pp
-or it could be splitted in:
+or it could be split in:
.Pp
.Dl "ipfw nat 1 config redirect_addr 10.0.0.1 10.0.0.66"
.Dl "ipfw nat 2 config redirect_port tcp 192.168.0.1:80 500"
@@ -2866,23 +2994,33 @@ API based upon code written by
.An Daniel Boulet
for BSDI.
.Pp
+Dummynet has been introduced by Luigi Rizzo in 1997-1998.
+.Pp
+Some early work (1999-2000) on the
+.Nm dummynet
+traffic shaper supported by Akamba Corp.
+.Pp
+The ipfw core (ipfw2) has been completely redesigned and
+reimplemented by Luigi Rizzo in summer 2002. Further
+actions and
+options have been added by various developer over the years.
+.Pp
.An -nosplit
In-kernel NAT support written by
.An Paolo Pisati Aq piso@FreeBSD.org
as part of a Summer of Code 2005 project.
.Pp
-Work on
-.Nm dummynet
-traffic shaper supported by Akamba Corp.
-.Pp
-Sctp
+SCTP
.Nm nat
support has been developed by
.An The Centre for Advanced Internet Architectures (CAIA) Aq http://www.caia.swin.edu.au .
The primary developers and maintainers are David Hayes and Jason But.
For further information visit:
.Aq http://www.caia.swin.edu.au/urp/SONATA
-.
+.Pp
+Delay profiles have been developed by Alessandro Cerri and
+Luigi Rizzo, supported by the
+European Commission within Projects Onelab and Onelab2.
.Sh BUGS
The syntax has grown over the years and sometimes it might be confusing.
Unfortunately, backward compatibility prevents cleaning up mistakes
@@ -2933,8 +3071,8 @@ or quoted appropriately.
.Pp
Due to the architecture of
.Xr libalias 3 ,
-ipfw nat is not compatible with the tcp segmentation offloading
-(TSO). Thus, to reliably nat your network traffic, please disable TSO
+ipfw nat is not compatible with the TCP segmentation offloading (TSO).
+Thus, to reliably nat your network traffic, please disable TSO
on your NICs using
.Xr ifconfig 8 .
.Pp
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index c0dfac3..9d95ec4 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -211,6 +211,7 @@ static struct _s_x rule_actions[] = {
{ "check-state", TOK_CHECKSTATE },
{ "//", TOK_COMMENT },
{ "nat", TOK_NAT },
+ { "reass", TOK_REASS },
{ "setfib", TOK_SETFIB },
{ NULL, 0 } /* terminator */
};
@@ -1089,6 +1090,10 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth)
case O_SETFIB:
PRINT_UINT_ARG("setfib ", cmd->arg1);
break;
+
+ case O_REASS:
+ printf("reass");
+ break;
default:
printf("** unrecognized action %d len %d ",
@@ -2781,6 +2786,10 @@ chkarg:
ac--; av++;
break;
}
+
+ case TOK_REASS:
+ action->opcode = O_REASS;
+ break;
default:
errx(EX_DATAERR, "invalid action %s\n", av[-1]);
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index 442e7b6..5b49f55 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -95,6 +95,7 @@ enum tokens {
TOK_UNREACH,
TOK_CHECKSTATE,
TOK_NAT,
+ TOK_REASS,
TOK_ALTQ,
TOK_LOG,
@@ -152,6 +153,7 @@ enum tokens {
TOK_MASK,
TOK_BW,
TOK_DELAY,
+ TOK_PIPE_PROFILE,
TOK_RED,
TOK_GRED,
TOK_DROPTAIL,
diff --git a/sbin/ipfw/main.c b/sbin/ipfw/main.c
index a83dd5f..3916057 100644
--- a/sbin/ipfw/main.c
+++ b/sbin/ipfw/main.c
@@ -54,7 +54,7 @@ help(void)
"RULE-BODY: check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]\n"
"ACTION: check-state | allow | count | deny | unreach{,6} CODE |\n"
" skipto N | {divert|tee} PORT | forward ADDR |\n"
-" pipe N | queue N | nat N | setfib FIB\n"
+" pipe N | queue N | nat N | setfib FIB | reass\n"
"PARAMS: [log [logamount LOGLIMIT]] [altq QUEUE_NAME]\n"
"ADDR: [ MAC dst src ether_type ] \n"
" [ ip from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n"
diff --git a/sbin/newfs_msdos/newfs_msdos.8 b/sbin/newfs_msdos/newfs_msdos.8
index 213b09d..c96e5f5 100644
--- a/sbin/newfs_msdos/newfs_msdos.8
+++ b/sbin/newfs_msdos/newfs_msdos.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd December 8, 2007
+.Dd April 11, 2009
.Dt NEWFS_MSDOS 8
.Os
.Sh NAME
@@ -72,9 +72,11 @@ to determine geometry, if required.
If
.Ar special
does not contain a
-.Ar / ,
-it is assumed to be a device name and
-.Ar /dev
+.Ar /
+and
+.Fl C
+is not used, it is assumed to be a device name and
+.Ar /dev/
is prepended to the name to construct the actual device name.
To work a file in the current directory use
.Ar ./filename
@@ -91,13 +93,14 @@ number is in sectors, kilobytes, megabytes or gigabytes, respectively.
.It Fl B Ar boot
Get bootstrap from file.
.It Fl C Ar create-size
-Create the image file with the specified size. A suffix character appended
-to the size is interpreted as for the
+Create the image file with the specified size.
+A suffix character appended to the size is interpreted as for the
.Fl @
-option. The file is created by truncating any existing file with the
-same name, seeking just before the required size and writing
-a single 0 byte. As a consequence, the space occupied on disk
-may be smaller than the size specified as a parameter.
+option.
+The file is created by truncating any existing file with the same name and
+resizing it to the requested size.
+If the file system supports sparse files, the space occupied on disk may be
+smaller than the size specified as parameter.
.It Fl F Ar FAT-type
FAT type (one of 12, 16, or 32).
.It Fl I Ar volid
@@ -161,13 +164,14 @@ Number of sectors per track.
.El
.Sh NOTES
If some parameters (e.g. size, number of sectors, etc.) are not specified
-through options or disktype, the program tries to generate them
-automatically. In particular, the size is determined as the
-device or file size minus the offset specified with the
+through options or disktype, the program tries to generate them automatically.
+In particular, the size is determined as the device or file size minus the
+offset specified with the
.Fl @
-option. When the geometry is not available, it is assumed to be
-63 sectors, 255 heads. The size is then rounded to become
-a multiple of the track size and avoid complaints by some filesystem code.
+option.
+When the geometry is not available, it is assumed to be 63 sectors, 255 heads.
+The size is then rounded to become a multiple of the track size and avoid
+complaints by some filesystem code.
.Pp
FAT file system parameters occupy a "Boot Sector BPB (BIOS Parameter
Block)" in the first of the "reserved" sectors which precede the actual
diff --git a/sbin/newfs_msdos/newfs_msdos.c b/sbin/newfs_msdos/newfs_msdos.c
index 1a8b81f..f09578a 100644
--- a/sbin/newfs_msdos/newfs_msdos.c
+++ b/sbin/newfs_msdos/newfs_msdos.c
@@ -168,7 +168,7 @@ struct bpb {
static struct {
const char *name;
struct bpb bpb;
-} stdfmt[] = {
+} const stdfmt[] = {
{"160", {512, 1, 1, 2, 64, 320, 0xfe, 1, 8, 1, BPBGAP}},
{"180", {512, 1, 1, 2, 64, 360, 0xfc, 2, 9, 1, BPBGAP}},
{"320", {512, 2, 1, 2, 112, 640, 0xff, 1, 8, 2, BPBGAP}},
@@ -181,7 +181,7 @@ static struct {
{"2880", {512, 2, 1, 2, 240, 5760, 0xf0, 9, 36, 2, BPBGAP}}
};
-static u_int8_t bootcode[] = {
+static const u_int8_t bootcode[] = {
0xfa, /* cli */
0x31, 0xc0, /* xor ax,ax */
0x8e, 0xd0, /* mov ss,ax */
@@ -232,13 +232,13 @@ static void usage(void);
int
main(int argc, char *argv[])
{
- static char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:u:";
- static const char *opt_B, *opt_L, *opt_O, *opt_f;
- static u_int opt_F, opt_I, opt_S, opt_a, opt_b, opt_c, opt_e;
- static u_int opt_h, opt_i, opt_k, opt_m, opt_n, opt_o, opt_r;
- static u_int opt_s, opt_u;
- static int opt_N;
- static int Iflag, mflag, oflag;
+ static const char opts[] = "@:NB:C:F:I:L:O:S:a:b:c:e:f:h:i:k:m:n:o:r:s:u:";
+ const char *opt_B = NULL, *opt_L = NULL, *opt_O = NULL, *opt_f = NULL;
+ u_int opt_F = 0, opt_I = 0, opt_S = 0, opt_a = 0, opt_b = 0, opt_c = 0;
+ u_int opt_e = 0, opt_h = 0, opt_i = 0, opt_k = 0, opt_m = 0, opt_n = 0;
+ u_int opt_o = 0, opt_r = 0, opt_s = 0, opt_u = 0;
+ int opt_N = 0;
+ int Iflag = 0, mflag = 0, oflag = 0;
char buf[MAXPATHLEN];
struct stat sb;
struct timeval tv;
@@ -255,7 +255,7 @@ main(int argc, char *argv[])
time_t now;
u_int fat, bss, rds, cls, dir, lsn, x, x1, x2;
int ch, fd, fd1;
- static off_t opt_create=0, opt_ofs=0;
+ off_t opt_create = 0, opt_ofs = 0;
while ((ch = getopt(argc, argv, opts)) != -1)
switch (ch) {
@@ -349,31 +349,33 @@ main(int argc, char *argv[])
if (argc < 1 || argc > 2)
usage();
fname = *argv++;
- if (!strchr(fname, '/')) {
+ if (!opt_create && !strchr(fname, '/')) {
snprintf(buf, sizeof(buf), "%s%s", _PATH_DEV, fname);
if (!(fname = strdup(buf)))
err(1, NULL);
}
dtype = *argv;
if (opt_create) {
- off_t pos;
-
if (opt_N)
errx(1, "create (-C) is incompatible with -N");
fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd == -1)
errx(1, "failed to create %s", fname);
- pos = lseek(fd, opt_create - 1, SEEK_SET);
- if (write(fd, "\0", 1) != 1)
+ if (ftruncate(fd, opt_create))
errx(1, "failed to initialize %jd bytes", (intmax_t)opt_create);
- pos = lseek(fd, 0, SEEK_SET);
- } else if ((fd = open(fname, opt_N ? O_RDONLY : O_RDWR)) == -1 ||
- fstat(fd, &sb))
+ } else if ((fd = open(fname, opt_N ? O_RDONLY : O_RDWR)) == -1)
+ err(1, "%s", fname);
+ if (fstat(fd, &sb))
err(1, "%s", fname);
+ if (opt_create) {
+ if (!S_ISREG(sb.st_mode))
+ warnx("warning, %s is not a regular file", fname);
+ } else {
+ if (!S_ISCHR(sb.st_mode))
+ warnx("warning, %s is not a character device", fname);
+ }
if (!opt_N)
check_mounted(fname, sb.st_mode);
- if (!S_ISCHR(sb.st_mode))
- warnx("warning, %s is not a character device", fname);
if (opt_ofs && opt_ofs != lseek(fd, opt_ofs, SEEK_SET))
errx(1, "cannot seek to %jd", (intmax_t)opt_ofs);
memset(&bpb, 0, sizeof(bpb));
@@ -983,30 +985,31 @@ setstr(u_int8_t *dest, const char *src, size_t len)
static void
usage(void)
{
- fprintf(stderr,
- "usage: newfs_msdos [ -options ] special [disktype]\n");
- fprintf(stderr, "where the options are:\n");
- fprintf(stderr, "\t-N don't create file system: "
- "just print out parameters\n");
- fprintf(stderr, "\t-B get bootstrap from file\n");
- fprintf(stderr, "\t-F FAT type (12, 16, or 32)\n");
- fprintf(stderr, "\t-I volume ID\n");
- fprintf(stderr, "\t-L volume label\n");
- fprintf(stderr, "\t-O OEM string\n");
- fprintf(stderr, "\t-S bytes/sector\n");
- fprintf(stderr, "\t-a sectors/FAT\n");
- fprintf(stderr, "\t-b block size\n");
- fprintf(stderr, "\t-c sectors/cluster\n");
- fprintf(stderr, "\t-e root directory entries\n");
- fprintf(stderr, "\t-f standard format\n");
- fprintf(stderr, "\t-h drive heads\n");
- fprintf(stderr, "\t-i file system info sector\n");
- fprintf(stderr, "\t-k backup boot sector\n");
- fprintf(stderr, "\t-m media descriptor\n");
- fprintf(stderr, "\t-n number of FATs\n");
- fprintf(stderr, "\t-o hidden sectors\n");
- fprintf(stderr, "\t-r reserved sectors\n");
- fprintf(stderr, "\t-s file system size (sectors)\n");
- fprintf(stderr, "\t-u sectors/track\n");
- exit(1);
+ fprintf(stderr,
+ "usage: newfs_msdos [ -options ] special [disktype]\n"
+ "where the options are:\n"
+ "\t-@ create file system at specified offset\n"
+ "\t-B get bootstrap from file\n"
+ "\t-C create image file with specified size\n"
+ "\t-F FAT type (12, 16, or 32)\n"
+ "\t-I volume ID\n"
+ "\t-L volume label\n"
+ "\t-N don't create file system: just print out parameters\n"
+ "\t-O OEM string\n"
+ "\t-S bytes/sector\n"
+ "\t-a sectors/FAT\n"
+ "\t-b block size\n"
+ "\t-c sectors/cluster\n"
+ "\t-e root directory entries\n"
+ "\t-f standard format\n"
+ "\t-h drive heads\n"
+ "\t-i file system info sector\n"
+ "\t-k backup boot sector\n"
+ "\t-m media descriptor\n"
+ "\t-n number of FATs\n"
+ "\t-o hidden sectors\n"
+ "\t-r reserved sectors\n"
+ "\t-s file system size (sectors)\n"
+ "\t-u sectors/track\n");
+ exit(1);
}
diff --git a/sbin/recoverdisk/recoverdisk.c b/sbin/recoverdisk/recoverdisk.c
index dee3d2c..f4a6b5d 100644
--- a/sbin/recoverdisk/recoverdisk.c
+++ b/sbin/recoverdisk/recoverdisk.c
@@ -306,6 +306,7 @@ main(int argc, char * const argv[])
free(lp);
}
PRINT_STATUS(start, i, len, state, d, t);
+ save_worklist();
printf("\nCompleted\n");
return (0);
}
diff --git a/sbin/route/route.c b/sbin/route/route.c
index 90ea509..1b0985e 100644
--- a/sbin/route/route.c
+++ b/sbin/route/route.c
@@ -713,7 +713,7 @@ newroute(argc, argv)
#ifdef INET6
if (af == AF_INET6) {
rtm_addrs &= ~RTA_NETMASK;
- memset((void *)&so_mask, 0, sizeof(so_mask));
+ memset((void *)&so_mask, 0, sizeof(so_mask));
}
#endif
}
@@ -803,21 +803,23 @@ inet_makenetandmask(net, sin, bits)
addr = net << IN_CLASSC_NSHIFT;
else
addr = net;
-
+ /*
+ * If no /xx was specified we must cacluate the
+ * CIDR address.
+ */
+ if ((bits == 0) && (addr != 0)) {
+ u_long i, j;
+ for(i=0,j=0xff; i<4; i++) {
+ if (addr & j) {
+ break;
+ }
+ j <<= 8;
+ }
+ /* i holds the first non zero bit */
+ bits = 32 - (i*8);
+ }
if (bits != 0)
mask = 0xffffffff << (32 - bits);
- else if (net == 0)
- mask = 0;
- else if (IN_CLASSA(addr))
- mask = IN_CLASSA_NET;
- else if (IN_CLASSB(addr))
- mask = IN_CLASSB_NET;
- else if (IN_CLASSC(addr))
- mask = IN_CLASSC_NET;
- else if (IN_MULTICAST(addr))
- mask = IN_CLASSD_NET;
- else
- mask = 0xffffffff;
sin->sin_addr.s_addr = htonl(addr);
sin = &so_mask.sin;
diff --git a/sbin/routed/Makefile b/sbin/routed/Makefile
index 1ac16c4..99b07f5 100644
--- a/sbin/routed/Makefile
+++ b/sbin/routed/Makefile
@@ -7,6 +7,10 @@ MAN= routed.8
SUBDIR= rtquery
LDADD= -lmd
DPADD= ${LIBMD}
+.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64"
+WARNS?= 6
+.else
WARNS?= 0
+.endif
.include <bsd.prog.mk>
diff --git a/sbin/routed/defs.h b/sbin/routed/defs.h
index ff6e8ab..c42cd80 100644
--- a/sbin/routed/defs.h
+++ b/sbin/routed/defs.h
@@ -60,6 +60,7 @@
* years have been simplified and integrated.
*/
+#include <assert.h>
#include <stdio.h>
#include <netdb.h>
#include <stdlib.h>
@@ -80,6 +81,7 @@
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
+#include <sys/queue.h>
#ifdef sgi
#define _USER_ROUTE_TREE
#include <net/radix.h>
@@ -149,12 +151,10 @@
#define MaxMaxAdvertiseInterval 1800
#define MinMaxAdvertiseInterval 4
#define DefMaxAdvertiseInterval 600
-#define DEF_PreferenceLevel 0
#define MIN_PreferenceLevel 0x80000000
#define MAX_INITIAL_ADVERT_INTERVAL 16
#define MAX_INITIAL_ADVERTS 3
-#define MAX_RESPONSE_DELAY 2
#define MAX_SOLICITATION_DELAY 1
#define SOLICITATION_INTERVAL 3
@@ -262,10 +262,10 @@ struct rt_entry {
* handles "logical" or "IS_REMOTE" interfaces (remote gateways).
*/
struct interface {
- struct interface *int_next, **int_prev;
+ LIST_ENTRY(interface) int_list;
+ LIST_ENTRY(interface) remote_list;
struct interface *int_ahash, **int_ahash_prev;
struct interface *int_bhash, **int_bhash_prev;
- struct interface *int_rlink, **int_rlink_prev;
struct interface *int_nhash, **int_nhash_prev;
char int_name[IF_NAME_LEN+1];
u_short int_index;
@@ -353,6 +353,7 @@ struct interface {
#define iff_up(f) ((f) & IFF_UP)
+LIST_HEAD(ifhead, interface);
/* Information for aggregating routes */
#define NUM_AG_SLOTS 32
@@ -390,7 +391,7 @@ struct ag_info {
/* parameters for interfaces */
-extern struct parm {
+struct parm {
struct parm *parm_next;
char parm_name[IF_NAME_LEN+1];
naddr parm_net;
@@ -403,7 +404,7 @@ extern struct parm {
int parm_rdisc_pref; /* signed IRDP preference */
int parm_rdisc_int; /* IRDP advertising interval */
struct auth parm_auth[MAX_AUTH_KEYS];
-} *parms;
+};
/* authority for internal networks */
extern struct intnet {
@@ -442,24 +443,21 @@ extern struct ws_buf {
struct netinfo *base;
struct netinfo *lim;
enum output_type type;
-} v12buf, v2buf;
+} v12buf;
extern pid_t mypid;
extern naddr myaddr; /* main address of this system */
extern int stopint; /* !=0 to stop */
-extern int sock_max;
extern int rip_sock; /* RIP socket */
-extern struct interface *rip_sock_mcast; /* current multicast interface */
+extern const struct interface *rip_sock_mcast; /* current multicast interface */
extern int rt_sock; /* routing socket */
extern int rt_sock_seqno;
extern int rdisc_sock; /* router-discovery raw socket */
-extern int seqno; /* sequence number for messages */
extern int supplier; /* process should supply updates */
extern int supplier_set; /* -s or -q requested */
-extern int lookforinterfaces; /* 1=probe for new up interfaces */
extern int ridhosts; /* 1=reduce host routes */
extern int mhome; /* 1=want multi-homed host route */
extern int advertise_mhome; /* 1=must continue advertising it */
@@ -472,7 +470,6 @@ extern time_t now_stale;
extern time_t now_expire;
extern time_t now_garbage;
-extern struct timeval next_bcast; /* next general broadcast */
extern struct timeval age_timer; /* next check of old routes */
extern struct timeval no_flash; /* inhibit flash update until then */
extern struct timeval rdisc_timer; /* next advert. or solicitation */
@@ -483,10 +480,9 @@ extern struct timeval ifinit_timer; /* time to check interfaces */
extern naddr loopaddr; /* our address on loopback */
extern int tot_interfaces; /* # of remote and local interfaces */
extern int rip_interfaces; /* # of interfaces doing RIP */
-extern struct interface *ifnet; /* all interfaces */
-extern struct interface *remote_if; /* remote interfaces */
+extern struct ifhead ifnet; /* all interfaces */
+extern struct ifhead remote_if; /* remote interfaces */
extern int have_ripv1_out; /* have a RIPv1 interface */
-extern int have_ripv1_in;
extern int need_flash; /* flash update needed */
extern struct timeval need_kern; /* need to update kernel table */
extern u_int update_seqno; /* a route has changed */
@@ -508,21 +504,21 @@ extern struct radix_node_head *rhead;
#define dup2(x,y) BSDdup2(x,y)
#endif /* sgi */
-extern void fix_sock(int, const char *);
-extern void fix_select(void);
-extern void rip_off(void);
-extern void rip_on(struct interface *);
+void fix_sock(int, const char *);
+void fix_select(void);
+void rip_off(void);
+void rip_on(struct interface *);
-extern void bufinit(void);
-extern int output(enum output_type, struct sockaddr_in *,
+void bufinit(void);
+int output(enum output_type, struct sockaddr_in *,
struct interface *, struct rip *, int);
-extern void clr_ws_buf(struct ws_buf *, struct auth *);
-extern void rip_query(void);
-extern void rip_bcast(int);
-extern void supply(struct sockaddr_in *, struct interface *,
+void clr_ws_buf(struct ws_buf *, struct auth *);
+void rip_query(void);
+void rip_bcast(int);
+void supply(struct sockaddr_in *, struct interface *,
enum output_type, int, int, int);
-extern void msglog(const char *, ...) PATTRIB(1,2);
+void msglog(const char *, ...) PATTRIB(1,2);
struct msg_limit {
time_t reuse;
struct msg_sub {
@@ -531,118 +527,110 @@ struct msg_limit {
# define MSG_SUBJECT_N 8
} subs[MSG_SUBJECT_N];
};
-extern void msglim(struct msg_limit *, naddr,
+void msglim(struct msg_limit *, naddr,
const char *, ...) PATTRIB(3,4);
#define LOGERR(msg) msglog(msg ": %s", strerror(errno))
-extern void logbad(int, const char *, ...) PATTRIB(2,3);
+void logbad(int, const char *, ...) PATTRIB(2,3);
#define BADERR(dump,msg) logbad(dump,msg ": %s", strerror(errno))
#ifdef DEBUG
#define DBGERR(dump,msg) BADERR(dump,msg)
#else
#define DBGERR(dump,msg) LOGERR(msg)
#endif
-extern char *naddr_ntoa(naddr);
-extern const char *saddr_ntoa(struct sockaddr *);
-
-extern void *rtmalloc(size_t, const char *);
-extern void timevaladd(struct timeval *, struct timeval *);
-extern void intvl_random(struct timeval *, u_long, u_long);
-extern int getnet(char *, naddr *, naddr *);
-extern int gethost(char *, naddr *);
-extern void gwkludge(void);
-extern const char *parse_parms(char *, int);
-extern const char *check_parms(struct parm *);
-extern void get_parms(struct interface *);
-
-extern void lastlog(void);
-extern void trace_close(int);
-extern void set_tracefile(const char *, const char *, int);
-extern void tracelevel_msg(const char *, int);
-extern void trace_off(const char*, ...) PATTRIB(1,2);
-extern void set_tracelevel(void);
-extern void trace_flush(void);
-extern void trace_misc(const char *, ...) PATTRIB(1,2);
-extern void trace_act(const char *, ...) PATTRIB(1,2);
-extern void trace_pkt(const char *, ...) PATTRIB(1,2);
-extern void trace_add_del(const char *, struct rt_entry *);
-extern void trace_change(struct rt_entry *, u_int, struct rt_spare *,
+char *naddr_ntoa(naddr);
+const char *saddr_ntoa(struct sockaddr *);
+
+void *rtmalloc(size_t, const char *);
+void timevaladd(struct timeval *, struct timeval *);
+void intvl_random(struct timeval *, u_long, u_long);
+int getnet(char *, naddr *, naddr *);
+int gethost(char *, naddr *);
+void gwkludge(void);
+const char *parse_parms(char *, int);
+const char *check_parms(struct parm *);
+void get_parms(struct interface *);
+
+void lastlog(void);
+void trace_close(int);
+void set_tracefile(const char *, const char *, int);
+void tracelevel_msg(const char *, int);
+void trace_off(const char*, ...) PATTRIB(1,2);
+void set_tracelevel(void);
+void trace_flush(void);
+void trace_misc(const char *, ...) PATTRIB(1,2);
+void trace_act(const char *, ...) PATTRIB(1,2);
+void trace_pkt(const char *, ...) PATTRIB(1,2);
+void trace_add_del(const char *, struct rt_entry *);
+void trace_change(struct rt_entry *, u_int, struct rt_spare *,
const char *);
-extern void trace_if(const char *, struct interface *);
-extern void trace_upslot(struct rt_entry *, struct rt_spare *,
+void trace_if(const char *, struct interface *);
+void trace_upslot(struct rt_entry *, struct rt_spare *,
struct rt_spare *);
-extern void trace_rip(const char*, const char*, struct sockaddr_in *,
+void trace_rip(const char*, const char*, struct sockaddr_in *,
struct interface *, struct rip *, int);
-extern char *addrname(naddr, naddr, int);
-extern char *rtname(naddr, naddr, naddr);
-
-extern void rdisc_age(naddr);
-extern void set_rdisc_mg(struct interface *, int);
-extern void set_supplier(void);
-extern void if_bad_rdisc(struct interface *);
-extern void if_ok_rdisc(struct interface *);
-extern void read_rip(int, struct interface *);
-extern void read_rt(void);
-extern void read_d(void);
-extern void rdisc_adv(void);
-extern void rdisc_sol(void);
-
-extern void sigalrm(int);
-extern void sigterm(int);
-
-extern void sigtrace_on(int);
-extern void sigtrace_off(int);
-
-extern void flush_kern(void);
-extern void age(naddr);
-
-extern void ag_flush(naddr, naddr, void (*)(struct ag_info *));
-extern void ag_check(naddr, naddr, naddr, naddr, char, char, u_int,
+char *addrname(naddr, naddr, int);
+char *rtname(naddr, naddr, naddr);
+
+void rdisc_age(naddr);
+void set_rdisc_mg(struct interface *, int);
+void set_supplier(void);
+void if_bad_rdisc(struct interface *);
+void if_ok_rdisc(struct interface *);
+void read_rip(int, struct interface *);
+void read_rt(void);
+void read_d(void);
+void rdisc_adv(void);
+void rdisc_sol(void);
+
+void sigtrace_on(int);
+void sigtrace_off(int);
+
+void flush_kern(void);
+void age(naddr);
+
+void ag_flush(naddr, naddr, void (*)(struct ag_info *));
+void ag_check(naddr, naddr, naddr, naddr, char, char, u_int,
u_short, u_short, void (*)(struct ag_info *));
-extern void del_static(naddr, naddr, naddr, int);
-extern void del_redirects(naddr, time_t);
-extern struct rt_entry *rtget(naddr, naddr);
-extern struct rt_entry *rtfind(naddr);
-extern void rtinit(void);
-extern void rtadd(naddr, naddr, u_int, struct rt_spare *);
-extern void rtchange(struct rt_entry *, u_int, struct rt_spare *, char *);
-extern void rtdelete(struct rt_entry *);
-extern void rts_delete(struct rt_entry *, struct rt_spare *);
-extern void rtbad_sub(struct rt_entry *);
-extern void rtswitch(struct rt_entry *, struct rt_spare *);
-extern void rtbad(struct rt_entry *);
+void del_static(naddr, naddr, naddr, int);
+void del_redirects(naddr, time_t);
+struct rt_entry *rtget(naddr, naddr);
+struct rt_entry *rtfind(naddr);
+void rtinit(void);
+void rtadd(naddr, naddr, u_int, struct rt_spare *);
+void rtchange(struct rt_entry *, u_int, struct rt_spare *, char *);
+void rtdelete(struct rt_entry *);
+void rts_delete(struct rt_entry *, struct rt_spare *);
+void rtbad_sub(struct rt_entry *);
+void rtswitch(struct rt_entry *, struct rt_spare *);
#define S_ADDR(x) (((struct sockaddr_in *)(x))->sin_addr.s_addr)
#define INFO_DST(I) ((I)->rti_info[RTAX_DST])
#define INFO_GATE(I) ((I)->rti_info[RTAX_GATEWAY])
#define INFO_MASK(I) ((I)->rti_info[RTAX_NETMASK])
#define INFO_IFA(I) ((I)->rti_info[RTAX_IFA])
-#define INFO_IFP(I) ((I)->rti_info[RTAX_IFP])
#define INFO_AUTHOR(I) ((I)->rti_info[RTAX_AUTHOR])
#define INFO_BRD(I) ((I)->rti_info[RTAX_BRD])
void rt_xaddrs(struct rt_addrinfo *, struct sockaddr *, struct sockaddr *,
int);
-extern naddr std_mask(naddr);
-extern naddr ripv1_mask_net(naddr, struct interface *);
-extern naddr ripv1_mask_host(naddr,struct interface *);
+naddr std_mask(naddr);
+naddr ripv1_mask_net(naddr, struct interface *);
+naddr ripv1_mask_host(naddr,struct interface *);
#define on_net(a,net,mask) (((ntohl(a) ^ (net)) & (mask)) == 0)
-extern int check_dst(naddr);
-extern struct interface *check_dup(naddr, naddr, naddr, int);
-extern int check_remote(struct interface *);
-extern int addrouteforif(struct interface *);
-extern void ifinit(void);
-extern int walk_bad(struct radix_node *, struct walkarg *);
-extern int if_ok(struct interface *, const char *);
-extern void if_sick(struct interface *);
-extern void if_bad(struct interface *);
-extern void if_link(struct interface *);
-extern struct interface *ifwithaddr(naddr, int, int);
-extern struct interface *ifwithname(char *, naddr);
-extern struct interface *ifwithindex(u_short, int);
-extern struct interface *iflookup(naddr);
-
-extern struct auth *find_auth(struct interface *);
-extern void end_md5_auth(struct ws_buf *, struct auth *);
+int check_dst(naddr);
+struct interface *check_dup(naddr, naddr, naddr, int);
+int check_remote(struct interface *);
+void ifinit(void);
+int walk_bad(struct radix_node *, struct walkarg *);
+int if_ok(struct interface *, const char *);
+void if_sick(struct interface *);
+void if_link(struct interface *);
+struct interface *ifwithaddr(naddr addr, int bcast, int remote);
+struct interface *ifwithindex(u_short, int);
+struct interface *iflookup(naddr);
+
+struct auth *find_auth(struct interface *);
+void end_md5_auth(struct ws_buf *, struct auth *);
#if defined(__FreeBSD__) || defined(__NetBSD__)
#include <md5.h>
@@ -653,7 +641,7 @@ typedef struct {
u_int32_t count[2]; /* # of bits, modulo 2^64 (LSB 1st) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
-extern void MD5Init(MD5_CTX*);
-extern void MD5Update(MD5_CTX*, u_char*, u_int);
-extern void MD5Final(u_char[MD5_DIGEST_LEN], MD5_CTX*);
+void MD5Init(MD5_CTX*);
+void MD5Update(MD5_CTX*, u_char*, u_int);
+void MD5Final(u_char[MD5_DIGEST_LEN], MD5_CTX*);
#endif
diff --git a/sbin/routed/if.c b/sbin/routed/if.c
index 09b03af..61ac412 100644
--- a/sbin/routed/if.c
+++ b/sbin/routed/if.c
@@ -41,7 +41,8 @@ __RCSID("$Revision: 2.27 $");
#ident "$Revision: 2.27 $"
#endif
-struct interface *ifnet; /* all interfaces */
+struct ifhead ifnet = LIST_HEAD_INITIALIZER(ifnet); /* all interfaces */
+struct ifhead remote_if = LIST_HEAD_INITIALIZER(ifnet); /* remote interfaces */
/* hash table for all interfaces, big enough to tolerate ridiculous
* numbers of IP aliases. Crazy numbers of aliases such as 7000
@@ -50,26 +51,25 @@ struct interface *ifnet; /* all interfaces */
*/
#define AHASH_LEN 211 /* must be prime */
#define AHASH(a) &ahash_tbl[(a)%AHASH_LEN]
-struct interface *ahash_tbl[AHASH_LEN];
+static struct interface *ahash_tbl[AHASH_LEN];
#define BHASH_LEN 211 /* must be prime */
#define BHASH(a) &bhash_tbl[(a)%BHASH_LEN]
-struct interface *bhash_tbl[BHASH_LEN];
+static struct interface *bhash_tbl[BHASH_LEN];
-struct interface *remote_if; /* remote interfaces */
/* hash for physical interface names.
* Assume there are never more 100 or 200 real interfaces, and that
* aliases are put on the end of the hash chains.
*/
#define NHASH_LEN 97
-struct interface *nhash_tbl[NHASH_LEN];
+static struct interface *nhash_tbl[NHASH_LEN];
int tot_interfaces; /* # of remote and local interfaces */
int rip_interfaces; /* # of interfaces doing RIP */
-int foundloopback; /* valid flag for loopaddr */
+static int foundloopback; /* valid flag for loopaddr */
naddr loopaddr; /* our address on loopback */
-struct rt_spare loop_rts;
+static struct rt_spare loop_rts;
struct timeval ifinit_timer;
static struct timeval last_ifinit;
@@ -78,9 +78,12 @@ static struct timeval last_ifinit;
&& timercmp(&ifinit_timer, &now, >))
int have_ripv1_out; /* have a RIPv1 interface */
-int have_ripv1_in;
+static int have_ripv1_in;
+static void if_bad(struct interface *);
+static int addrouteforif(struct interface *);
+
static struct interface**
nhash(char *p)
{
@@ -101,11 +104,7 @@ if_link(struct interface *ifp)
{
struct interface **hifp;
- ifp->int_prev = &ifnet;
- ifp->int_next = ifnet;
- if (ifnet != 0)
- ifnet->int_prev = &ifp->int_next;
- ifnet = ifp;
+ LIST_INSERT_HEAD(&ifnet, ifp, int_list);
hifp = AHASH(ifp->int_addr);
ifp->int_ahash_prev = hifp;
@@ -121,13 +120,8 @@ if_link(struct interface *ifp)
*hifp = ifp;
}
- if (ifp->int_state & IS_REMOTE) {
- ifp->int_rlink_prev = &remote_if;
- ifp->int_rlink = remote_if;
- if (remote_if != 0)
- remote_if->int_rlink_prev = &ifp->int_rlink;
- remote_if = ifp;
- }
+ if (ifp->int_state & IS_REMOTE)
+ LIST_INSERT_HEAD(&remote_if, ifp, remote_list);
hifp = nhash(ifp->int_name);
if (ifp->int_state & IS_ALIAS) {
@@ -182,7 +176,7 @@ ifwithaddr(naddr addr,
/* find the interface with a name
*/
-struct interface *
+static struct interface *
ifwithname(char *name, /* "ec0" or whatever */
naddr addr) /* 0 or network address */
{
@@ -217,7 +211,7 @@ ifwithindex(u_short ifindex,
struct interface *ifp;
for (;;) {
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if (ifp->int_index == ifindex)
return ifp;
}
@@ -245,7 +239,7 @@ iflookup(naddr addr)
maybe = 0;
for (;;) {
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if (ifp->int_if_flags & IFF_POINTOPOINT) {
/* finished with a match */
if (ifp->int_dstaddr == addr)
@@ -322,7 +316,7 @@ ripv1_mask_net(naddr addr, /* in network byte order */
* such interface, prefer the interface with the longest
* match.
*/
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if (on_net(addr, ifp->int_std_net, ifp->int_std_mask)
&& ifp->int_ripv1_mask > mask
&& ifp->int_ripv1_mask != HOST_MASK)
@@ -394,7 +388,7 @@ check_dup(naddr addr, /* IP address, so network byte order */
{
struct interface *ifp;
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if (ifp->int_mask != mask)
continue;
@@ -459,11 +453,7 @@ ifdel(struct interface *ifp)
ifp->int_state |= IS_BROKE;
- /* unlink the interface
- */
- *ifp->int_prev = ifp->int_next;
- if (ifp->int_next != 0)
- ifp->int_next->int_prev = ifp->int_prev;
+ LIST_REMOVE(ifp, int_list);
*ifp->int_ahash_prev = ifp->int_ahash;
if (ifp->int_ahash != 0)
ifp->int_ahash->int_ahash_prev = ifp->int_ahash_prev;
@@ -475,16 +465,13 @@ ifdel(struct interface *ifp)
if (ifp->int_bhash != 0)
ifp->int_bhash->int_bhash_prev = ifp->int_bhash_prev;
}
- if (ifp->int_state & IS_REMOTE) {
- *ifp->int_rlink_prev = ifp->int_rlink;
- if (ifp->int_rlink != 0)
- ifp->int_rlink->int_rlink_prev = ifp->int_rlink_prev;
- }
+ if (ifp->int_state & IS_REMOTE)
+ LIST_REMOVE(ifp, remote_list);
if (!(ifp->int_state & IS_ALIAS)) {
/* delete aliases when the main interface dies
*/
- for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
+ LIST_FOREACH(ifp1, &ifnet, int_list) {
if (ifp1 != ifp
&& !strcmp(ifp->int_name, ifp1->int_name))
ifdel(ifp1);
@@ -551,7 +538,7 @@ if_sick(struct interface *ifp)
/* Mark an interface dead.
*/
-void
+static void
if_bad(struct interface *ifp)
{
struct interface *ifp1;
@@ -570,7 +557,7 @@ if_bad(struct interface *ifp)
trace_if("Chg", ifp);
if (!(ifp->int_state & IS_ALIAS)) {
- for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
+ LIST_FOREACH(ifp1, &ifnet, int_list) {
if (ifp1 != ifp
&& !strcmp(ifp->int_name, ifp1->int_name))
if_bad(ifp1);
@@ -606,7 +593,7 @@ if_ok(struct interface *ifp,
ifp->int_data.ts = 0;
if (!(ifp->int_state & IS_ALIAS)) {
- for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
+ LIST_FOREACH(ifp1, &ifnet, int_list) {
if (ifp1 != ifp
&& !strcmp(ifp->int_name, ifp1->int_name))
if_ok(ifp1, type);
@@ -653,7 +640,7 @@ rt_xaddrs(struct rt_addrinfo *info,
void
ifinit(void)
{
- static char *sysctl_buf;
+ static struct ifa_msghdr *sysctl_buf;
static size_t sysctl_buf_size = 0;
uint complaints = 0;
static u_int prev_complaints = 0;
@@ -672,7 +659,8 @@ ifinit(void)
size_t needed;
int mib[6];
struct if_msghdr *ifm;
- struct ifa_msghdr *ifam, *ifam_lim, *ifam2;
+ void *ifam_lim;
+ struct ifa_msghdr *ifam, *ifam2;
int in, ierr, out, oerr;
struct intnet *intnetp;
struct rt_addrinfo info;
@@ -687,7 +675,7 @@ ifinit(void)
: CHECK_QUIET_INTERVAL);
/* mark all interfaces so we can get rid of those that disappear */
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next)
+ LIST_FOREACH(ifp, &ifnet, int_list)
ifp->int_state &= ~(IS_CHECKED | IS_DUP);
/* Fetch the interface list, without too many system calls
@@ -715,10 +703,9 @@ ifinit(void)
"ifinit sysctl");
}
- ifam_lim = (struct ifa_msghdr *)(sysctl_buf + needed);
- for (ifam = (struct ifa_msghdr *)sysctl_buf;
- ifam < ifam_lim;
- ifam = ifam2) {
+ /* XXX: thanks to malloc(3), alignment can be presumed OK */
+ ifam_lim = (char *)sysctl_buf + needed;
+ for (ifam = sysctl_buf; (void *)ifam < ifam_lim; ifam = ifam2) {
ifam2 = (struct ifa_msghdr*)((char*)ifam + ifam->ifam_msglen);
@@ -963,7 +950,8 @@ ifinit(void)
trace_act("interface %s has been off"
" %ld seconds; forget it",
ifp->int_name,
- now.tv_sec-ifp->int_data.ts);
+ (long)now.tv_sec-
+ ifp->int_data.ts);
ifdel(ifp);
}
continue;
@@ -1111,7 +1099,7 @@ ifinit(void)
if (!(prev_complaints & COMP_NETMASK)
&& !(ifp->int_if_flags & IFF_POINTOPOINT)
&& ifp->int_addr != RIP_DEFAULT) {
- for (ifp1 = ifnet; 0 != ifp1; ifp1 = ifp1->int_next) {
+ LIST_FOREACH(ifp1, &ifnet, int_list) {
if (ifp1->int_mask == ifp->int_mask)
continue;
if (ifp1->int_if_flags & IFF_POINTOPOINT)
@@ -1188,9 +1176,7 @@ ifinit(void)
}
}
- for (ifp = ifnet; ifp != 0; ifp = ifp1) {
- ifp1 = ifp->int_next; /* because we may delete it */
-
+ LIST_FOREACH_SAFE(ifp, &ifnet, int_list, ifp1) {
/* Forget any interfaces that have disappeared.
*/
if (!(ifp->int_state & (IS_CHECKED | IS_REMOTE))) {
@@ -1213,7 +1199,7 @@ ifinit(void)
have_ripv1_in = 1;
}
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
/* Ensure there is always a network route for interfaces,
* after any dead interfaces have been deleted, which
* might affect routes for point-to-point links.
@@ -1326,7 +1312,7 @@ check_net_syn(struct interface *ifp)
* Create route to other end if a point-to-point link,
* otherwise a route to this (sub)network.
*/
-int /* 0=bad interface */
+static int /* 0=bad interface */
addrouteforif(struct interface *ifp)
{
struct rt_entry *rt;
diff --git a/sbin/routed/input.c b/sbin/routed/input.c
index f655346..8f8eefc 100644
--- a/sbin/routed/input.c
+++ b/sbin/routed/input.c
@@ -96,7 +96,7 @@ read_rip(int sock,
cc+sizeof(inbuf.ifname));
/* check the remote interfaces first */
- for (aifp = remote_if; aifp; aifp = aifp->int_rlink) {
+ LIST_FOREACH(aifp, &remote_if, remote_list) {
if (aifp->int_addr == from.sin_addr.s_addr)
break;
}
@@ -931,7 +931,7 @@ ck_passwd(struct interface *aifp,
u_char hash[RIP_AUTH_PW_LEN];
int i, len;
-
+ assert(aifp != NULL);
if ((void *)NA >= lim || NA->a_family != RIP_AF_AUTH) {
msglim(use_authp, from, "missing password from %s",
naddr_ntoa(from));
@@ -980,7 +980,7 @@ ck_passwd(struct interface *aifp,
"unknown MD5 RIPv2 auth len %#x"
" instead of %#x from %s",
NA->au.a_md5.md5_auth_len,
- RIP_AUTH_MD5_HASH_LEN,
+ (unsigned)RIP_AUTH_MD5_HASH_LEN,
naddr_ntoa(from));
if (na2->a_family != RIP_AF_AUTH)
msglim(use_authp, from,
diff --git a/sbin/routed/main.c b/sbin/routed/main.c
index 674d232..85bc9e8 100644
--- a/sbin/routed/main.c
+++ b/sbin/routed/main.c
@@ -38,9 +38,9 @@
#include <fcntl.h>
#include <sys/file.h>
-__COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\n"
+__COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993 "
"The Regents of the University of California."
- " All rights reserved.\n");
+ " All rights reserved.");
#ifdef __NetBSD__
__RCSID("$NetBSD$");
#include <util.h>
@@ -54,46 +54,49 @@ __RCSID("$Revision: 2.31 $");
pid_t mypid;
naddr myaddr; /* system address */
-char myname[MAXHOSTNAMELEN+1];
+static char myname[MAXHOSTNAMELEN+1];
-int verbose;
+static int verbose;
int supplier; /* supply or broadcast updates */
int supplier_set;
-int ipforwarding = 1; /* kernel forwarding on */
+static int ipforwarding = 1; /* kernel forwarding on */
-int default_gateway; /* 1=advertise default */
-int background = 1;
+static int default_gateway; /* 1=advertise default */
+static int background = 1;
int ridhosts; /* 1=reduce host routes */
int mhome; /* 1=want multi-homed host route */
int advertise_mhome; /* 1=must continue advertising it */
int auth_ok = 1; /* 1=ignore auth if we do not care */
struct timeval epoch; /* when started */
-struct timeval clk, prev_clk;
+struct timeval clk;
+static struct timeval prev_clk;
static int usec_fudge;
struct timeval now; /* current idea of time */
time_t now_stale;
time_t now_expire;
time_t now_garbage;
-struct timeval next_bcast; /* next general broadcast */
+static struct timeval next_bcast; /* next general broadcast */
struct timeval no_flash = { /* inhibit flash update */
EPOCH+SUPPLY_INTERVAL, 0
};
-struct timeval flush_kern_timer;
+static struct timeval flush_kern_timer;
-fd_set fdbits;
-int sock_max;
+static fd_set fdbits;
+static int sock_max;
int rip_sock = -1; /* RIP socket */
-struct interface *rip_sock_mcast; /* current multicast interface */
+const struct interface *rip_sock_mcast; /* current multicast interface */
int rt_sock; /* routing socket */
int rt_sock_seqno;
static int get_rip_sock(naddr, int);
static void timevalsub(struct timeval *, struct timeval *, struct timeval *);
+static void sigalrm(int s UNUSED);
+static void sigterm(int sig);
int
main(int argc,
@@ -529,7 +532,9 @@ usage:
n--;
}
- for (ifp = ifnet; n > 0 && 0 != ifp; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
+ if (n <= 0)
+ break;
if (ifp->int_rip_sock >= 0
&& FD_ISSET(ifp->int_rip_sock, &ibits)) {
read_rip(ifp->int_rip_sock, ifp);
@@ -541,7 +546,7 @@ usage:
/* ARGSUSED */
-void
+static void
sigalrm(int s UNUSED)
{
/* Historically, SIGALRM would cause the daemon to check for
@@ -553,7 +558,7 @@ sigalrm(int s UNUSED)
/* watch for fatal signals */
-void
+static void
sigterm(int sig)
{
stopint = sig;
@@ -578,7 +583,7 @@ fix_select(void)
if (sock_max <= rip_sock)
sock_max = rip_sock+1;
}
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if (ifp->int_rip_sock >= 0) {
FD_SET(ifp->int_rip_sock, &fdbits);
if (sock_max <= ifp->int_rip_sock)
@@ -690,7 +695,7 @@ rip_off(void)
/* get non-broadcast sockets to listen to queries.
*/
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if (ifp->int_state & IS_REMOTE)
continue;
if (ifp->int_rip_sock < 0) {
@@ -761,7 +766,7 @@ rip_on(struct interface *ifp)
* since that would let two daemons bind to the broadcast
* socket.
*/
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if (ifp->int_rip_sock >= 0) {
(void)close(ifp->int_rip_sock);
ifp->int_rip_sock = -1;
@@ -776,7 +781,7 @@ rip_on(struct interface *ifp)
if (next_bcast.tv_sec < now.tv_sec+MIN_WAITTIME)
next_bcast.tv_sec = now.tv_sec+MIN_WAITTIME;
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
ifp->int_query_time = NEVER;
rip_mcast_on(ifp);
}
diff --git a/sbin/routed/output.c b/sbin/routed/output.c
index c555c21..53eb4a5 100644
--- a/sbin/routed/output.c
+++ b/sbin/routed/output.c
@@ -46,7 +46,7 @@ u_int update_seqno;
/* walk the tree of routes with this for output
*/
-struct {
+static struct {
struct sockaddr_in to;
naddr to_mask;
naddr to_net;
@@ -69,11 +69,11 @@ struct {
/* A buffer for what can be heard by both RIPv1 and RIPv2 listeners */
struct ws_buf v12buf;
-union pkt_buf ripv12_buf;
+static union pkt_buf ripv12_buf;
/* Another for only RIPv2 listeners */
-struct ws_buf v2buf;
-union pkt_buf rip_v2_buf;
+static struct ws_buf v2buf;
+static union pkt_buf rip_v2_buf;
@@ -107,6 +107,7 @@ output(enum output_type type,
int soc;
int serrno;
+ assert(ifp != NULL);
osin = *dst;
if (osin.sin_port == 0)
osin.sin_port = htons(RIP_PORT);
@@ -139,7 +140,8 @@ output(enum output_type type,
flags = MSG_DONTROUTE;
break;
case OUT_MULTICAST:
- if (ifp->int_if_flags & IFF_POINTOPOINT) {
+ if ((ifp->int_if_flags & (IFF_POINTOPOINT|IFF_MULTICAST)) ==
+ IFF_POINTOPOINT) {
msg = "Send pt-to-pt";
} else if (ifp->int_state & IS_DUP) {
trace_act("abort multicast output via %s"
@@ -671,6 +673,7 @@ supply(struct sockaddr_in *dst,
struct rt_entry *rt;
int def_metric;
+ assert(ifp != NULL);
ws.state = 0;
ws.gen_limit = 1024;
@@ -832,7 +835,7 @@ rip_bcast(int flash)
flash ? "dynamic update" : "all routes",
rtime.tv_sec + ((float)rtime.tv_usec)/1000000.0);
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
/* Skip interfaces not doing RIP.
* Do try broken interfaces to see if they have healed.
*/
@@ -859,7 +862,13 @@ rip_bcast(int flash)
} else if (ifp->int_if_flags & IFF_POINTOPOINT) {
/* point-to-point hardware interface */
dst.sin_addr.s_addr = ifp->int_dstaddr;
- type = OUT_UNICAST;
+ if (vers == RIPv2 &&
+ ifp->int_if_flags & IFF_MULTICAST &&
+ !(ifp->int_state & IS_NO_RIP_MCAST)) {
+ type = OUT_MULTICAST;
+ } else {
+ type = OUT_UNICAST;
+ }
} else if (ifp->int_state & IS_REMOTE) {
/* remote interface */
@@ -900,7 +909,7 @@ rip_query(void)
memset(&buf, 0, sizeof(buf));
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
/* Skip interfaces those already queried.
* Do not ask via interfaces through which we don't
* accept input. Do not ask via interfaces that cannot
diff --git a/sbin/routed/parms.c b/sbin/routed/parms.c
index 356ac8e..078f886 100644
--- a/sbin/routed/parms.c
+++ b/sbin/routed/parms.c
@@ -43,7 +43,7 @@ __RCSID("$Revision: 2.26 $");
#endif
-struct parm *parms;
+static struct parm *parms;
struct intnet *intnets;
struct r1net *r1nets;
struct tgate *tgates;
@@ -350,7 +350,7 @@ gwkludge(void)
/* After all of the parameter lines have been read,
* apply them to any remote interfaces.
*/
- for (ifp = ifnet; 0 != ifp; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
get_parms(ifp);
tot_interfaces++;
@@ -437,9 +437,7 @@ parse_ts(time_t *tp,
u_int bufsize)
{
struct tm tm;
-#if defined(sgi) || defined(__NetBSD__)
char *ptr;
-#endif
if (0 > parse_quote(valp, "| ,\n\r", delimp,
buf,bufsize)
@@ -450,25 +448,11 @@ parse_ts(time_t *tp,
}
strcat(buf,"\n");
memset(&tm, 0, sizeof(tm));
-#if defined(sgi) || defined(__NetBSD__)
ptr = strptime(buf, "%y/%m/%d@%H:%M\n", &tm);
if (ptr == NULL || *ptr != '\0') {
sprintf(buf,"bad timestamp %.25s", val0);
return buf;
}
-#else
- if (5 != sscanf(buf, "%u/%u/%u@%u:%u\n",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
- &tm.tm_hour, &tm.tm_min)
- || tm.tm_mon < 1 || tm.tm_mon > 12
- || tm.tm_mday < 1 || tm.tm_mday > 31) {
- sprintf(buf,"bad timestamp %.25s", val0);
- return buf;
- }
- tm.tm_mon--;
- if (tm.tm_year <= 37) /* assume small years are in the */
- tm.tm_year += 100; /* 3rd millenium */
-#endif
if ((*tp = mktime(&tm)) == -1) {
sprintf(buf,"bad timestamp %.25s", val0);
@@ -495,7 +479,7 @@ get_passwd(char *tgt,
int i;
u_long l;
-
+ assert(val != NULL);
if (!safe)
return "ignore unsafe password";
@@ -658,6 +642,8 @@ parse_parms(char *line,
if (0 > parse_quote(&line, " #,\n\r",&delim,
buf,sizeof(buf)))
return bad_str(tgt);
+ } else {
+ val0 = NULL;
}
if (delim != '\0') {
for (;;) {
diff --git a/sbin/routed/radix.c b/sbin/routed/radix.c
index 7f37688..7685f78 100644
--- a/sbin/routed/radix.c
+++ b/sbin/routed/radix.c
@@ -51,18 +51,22 @@ __RCSID("$Revision: 2.23 $");
#define min(a,b) (((a)<(b))?(a):(b))
int max_keylen;
-struct radix_mask *rn_mkfreelist;
-struct radix_node_head *mask_rnhead;
+static struct radix_mask *rn_mkfreelist;
+static struct radix_node_head *mask_rnhead;
static char *addmask_key;
-static char normal_chars[] = {0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, -1};
+static const uint8_t normal_chars[] =
+ { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
static char *rn_zeros, *rn_ones;
#define rn_masktop (mask_rnhead->rnh_treetop)
-#undef Bcmp
#define Bcmp(a, b, l) (l == 0 ? 0 \
: memcmp((caddr_t)(a), (caddr_t)(b), (size_t)l))
static int rn_satisfies_leaf(char *, struct radix_node *, int);
+static struct radix_node *rn_addmask(void *n_arg, int search, int skip);
+static struct radix_node *rn_addroute(void *v_arg, void *n_arg,
+ struct radix_node_head *head, struct radix_node treenodes[2]);
+static struct radix_node *rn_match(void *v_arg, struct radix_node_head *head);
/*
* The data structure for the keys is a radix tree with one way
@@ -98,7 +102,7 @@ static int rn_satisfies_leaf(char *, struct radix_node *, int);
* that governs a subtree.
*/
-struct radix_node *
+static struct radix_node *
rn_search(void *v_arg,
struct radix_node *head)
{
@@ -114,7 +118,7 @@ rn_search(void *v_arg,
return (x);
}
-struct radix_node *
+static struct radix_node *
rn_search_m(void *v_arg,
struct radix_node *head,
void *m_arg)
@@ -132,7 +136,7 @@ rn_search_m(void *v_arg,
return x;
}
-int
+static int
rn_refines(void* m_arg, void *n_arg)
{
caddr_t m = m_arg, n = n_arg;
@@ -158,7 +162,7 @@ rn_refines(void* m_arg, void *n_arg)
return (!masks_are_equal);
}
-struct radix_node *
+static struct radix_node *
rn_lookup(void *v_arg, void *m_arg, struct radix_node_head *head)
{
struct radix_node *x;
@@ -197,7 +201,7 @@ rn_satisfies_leaf(char *trial,
return 1;
}
-struct radix_node *
+static struct radix_node *
rn_match(void *v_arg,
struct radix_node_head *head)
{
@@ -321,7 +325,7 @@ int rn_saveinfo;
int rn_debug = 1;
#endif
-struct radix_node *
+static struct radix_node *
rn_newpair(void *v, int b, struct radix_node nodes[2])
{
struct radix_node *tt = nodes, *t = tt + 1;
@@ -336,7 +340,7 @@ rn_newpair(void *v, int b, struct radix_node nodes[2])
return t;
}
-struct radix_node *
+static struct radix_node *
rn_insert(void* v_arg,
struct radix_node_head *head,
int *dupentry,
@@ -404,7 +408,7 @@ on1:
return (tt);
}
-struct radix_node *
+static struct radix_node *
rn_addmask(void *n_arg, int search, int skip)
{
caddr_t netmask = (caddr_t)n_arg;
@@ -512,7 +516,7 @@ rn_new_radix_mask(struct radix_node *tt,
return m;
}
-struct radix_node *
+static struct radix_node *
rn_addroute(void *v_arg,
void *n_arg,
struct radix_node_head *head,
@@ -655,7 +659,7 @@ on2:
return tt;
}
-struct radix_node *
+static struct radix_node *
rn_delete(void *v_arg,
void *netmask_arg,
struct radix_node_head *head)
@@ -846,7 +850,7 @@ rn_walktree(struct radix_node_head *h,
}
int
-rn_inithead(void **head, int off)
+rn_inithead(struct radix_node_head **head, int off)
{
struct radix_node_head *rnh;
struct radix_node *t, *tt, *ttt;
@@ -887,7 +891,7 @@ rn_init(void)
addmask_key = cplim = rn_ones + max_keylen;
while (cp < cplim)
*cp++ = -1;
- if (rn_inithead((void **)&mask_rnhead, 0) == 0)
+ if (rn_inithead(&mask_rnhead, 0) == 0)
panic("rn_init 2");
}
diff --git a/sbin/routed/radix.h b/sbin/routed/radix.h
index 6cf196f..5cc177e 100644
--- a/sbin/routed/radix.h
+++ b/sbin/routed/radix.h
@@ -80,7 +80,7 @@ struct radix_node {
* Annotations to tree concerning potential routes applying to subtrees.
*/
-extern struct radix_mask {
+struct radix_mask {
short rm_b; /* bit offset; -1-index(netmask) */
char rm_unused; /* cf. rn_bmask */
u_char rm_flags; /* cf. rn_flags */
@@ -90,7 +90,7 @@ extern struct radix_mask {
struct radix_node *rmu_leaf; /* for normal routes */
} rm_rmu;
int rm_refs; /* # of references to this struct */
-} *rn_mkfreelist;
+};
#define rm_mask rm_rmu.rmu_mask
#define rm_leaf rm_rmu.rmu_leaf /* extra field would make 32 bytes */
@@ -132,30 +132,14 @@ struct radix_node_head {
};
-#define Bcmp(a, b, n) memcmp(((void *)(a)), ((void *)(b)), (n))
#define Bcopy(a, b, n) memmove(((void *)(b)), ((void *)(a)), (size_t)(n))
#define Bzero(p, n) memset((void *)(p), 0, (size_t)(n));
#define Free(p) free((void *)p);
void rn_init(void);
-int rn_inithead(void **, int);
-int rn_refines(void *, void *);
+int rn_inithead(struct radix_node_head **head, int off);
int rn_walktree(struct radix_node_head *,
int (*)(struct radix_node *, struct walkarg *),
struct walkarg *);
-struct radix_node
- *rn_addmask(void *, int, int),
- *rn_addroute(void *, void *, struct radix_node_head *,
- struct radix_node [2]),
- *rn_delete(void *, void *, struct radix_node_head *),
- *rn_insert(void *, struct radix_node_head *, int *,
- struct radix_node [2]),
- *rn_match(void *, struct radix_node_head *),
- *rn_newpair(void *, int, struct radix_node[2]),
- *rn_search(void *, struct radix_node *),
- *rn_search_m(void *, struct radix_node *, void *);
-
-struct radix_node *rn_lookup(void *, void *, struct radix_node_head *);
-
#endif /* __RADIX_H_ */
diff --git a/sbin/routed/rdisc.c b/sbin/routed/rdisc.c
index 496f212..260f6e0 100644
--- a/sbin/routed/rdisc.c
+++ b/sbin/routed/rdisc.c
@@ -73,7 +73,7 @@ union ad_u {
int rdisc_sock = -1; /* router-discovery raw socket */
-struct interface *rdisc_sock_mcast; /* current multicast interface */
+static const struct interface *rdisc_sock_mcast; /* current multicast interface */
struct timeval rdisc_timer;
int rdisc_ok; /* using solicited route */
@@ -87,7 +87,9 @@ struct dr { /* accumulated advertisements */
time_t dr_life; /* lifetime in host byte order */
n_long dr_recv_pref; /* received but biased preference */
n_long dr_pref; /* preference adjusted by metric */
-} *cur_drp, drs[MAX_ADS];
+};
+static const struct dr *cur_drp;
+static struct dr drs[MAX_ADS];
/* convert between signed, balanced around zero,
* and unsigned zero-based preferences */
@@ -171,6 +173,8 @@ set_rdisc_mg(struct interface *ifp,
struct group_req gr;
struct sockaddr_in *sin;
+ assert(ifp != NULL);
+
if (rdisc_sock < 0) {
/* Create the raw socket so that we can hear at least
* broadcast router discovery packets.
@@ -278,7 +282,7 @@ set_supplier(void)
/* Switch router discovery multicast groups from soliciting
* to advertising.
*/
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if (ifp->int_state & IS_BROKE)
continue;
ifp->int_rdisc_cnt = 0;
@@ -817,7 +821,7 @@ rdisc_adv(void)
rdisc_timer.tv_sec = now.tv_sec + NEVER;
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if (0 != (ifp->int_state & (IS_NO_ADV_OUT | IS_BROKE)))
continue;
@@ -859,7 +863,7 @@ rdisc_sol(void)
rdisc_timer.tv_sec = now.tv_sec + NEVER;
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if (0 != (ifp->int_state & (IS_NO_SOL_OUT | IS_BROKE))
|| ifp->int_rdisc_cnt >= MAX_SOLICITATIONS)
continue;
@@ -942,7 +946,6 @@ read_d(void)
#endif
union {
struct ip ip;
- u_short s[512/2];
u_char b[512];
} pkt;
} buf;
diff --git a/sbin/routed/table.c b/sbin/routed/table.c
index 9fd4cb8..8054a49 100644
--- a/sbin/routed/table.c
+++ b/sbin/routed/table.c
@@ -48,6 +48,7 @@ static void masktrim(struct sockaddr_in *ap);
#else
static void masktrim(struct sockaddr_in_new *ap);
#endif
+static void rtbad(struct rt_entry *);
struct radix_node_head *rhead; /* root of the radix tree */
@@ -66,7 +67,7 @@ int stopint;
int total_routes;
/* zap any old routes through this gateway */
-naddr age_bad_gate;
+static naddr age_bad_gate;
/* It is desirable to "aggregate" routes, to combine differing routes of
@@ -93,7 +94,7 @@ naddr age_bad_gate;
* sorted first by address, with the smallest address first.
*/
-struct ag_info ag_slots[NUM_AG_SLOTS], *ag_avail, *ag_corsest, *ag_finest;
+static struct ag_info ag_slots[NUM_AG_SLOTS], *ag_avail, *ag_corsest, *ag_finest;
/* #define DEBUG_AG */
#ifdef DEBUG_AG
@@ -606,12 +607,10 @@ ag_check(naddr dst,
CHECK_AG();
}
-
-#define NAME0_LEN 14
static const char *
rtm_type_name(u_char type)
{
- static const char *rtm_types[] = {
+ static const char * const rtm_types[] = {
"RTM_ADD",
"RTM_DELETE",
"RTM_CHANGE",
@@ -1631,7 +1630,7 @@ rtinit(void)
/* Initialize the radix trees */
max_keylen = sizeof(struct sockaddr_in);
rn_init();
- rn_inithead((void**)&rhead, 32);
+ rn_inithead(&rhead, 32);
/* mark all of the slots in the table free */
ag_avail = ag_slots;
@@ -1886,7 +1885,7 @@ rts_delete(struct rt_entry *rt,
/* Get rid of a bad route, and try to switch to a replacement.
*/
-void
+static void
rtbad(struct rt_entry *rt)
{
struct rt_spare new;
@@ -1918,7 +1917,7 @@ rtbad_sub(struct rt_entry *rt)
* If so, see if it is used by any other interfaces, such
* as a point-to-point interface with the same local address.
*/
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
/* Retain it if another interface needs it.
*/
if (ifp->int_addr == rt->rt_ifp->int_addr) {
@@ -1935,7 +1934,7 @@ rtbad_sub(struct rt_entry *rt)
* interface that justifies it.
*/
if (rt->rt_state & RS_NET_SYN) {
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if ((ifp->int_state & IS_NEED_NET_SYN)
&& rt->rt_mask == ifp->int_std_mask
&& rt->rt_dst == ifp->int_std_addr) {
@@ -2105,7 +2104,7 @@ age(naddr bad_gate)
/* Check for dead IS_REMOTE interfaces by timing their
* transmissions.
*/
- for (ifp = ifnet; ifp; ifp = ifp->int_next) {
+ LIST_FOREACH(ifp, &ifnet, int_list) {
if (!(ifp->int_state & IS_REMOTE))
continue;
@@ -2124,8 +2123,8 @@ age(naddr bad_gate)
" %ld:%ld",
ifp->int_name,
naddr_ntoa(ifp->int_dstaddr),
- (now.tv_sec - ifp->int_act_time)/60,
- (now.tv_sec - ifp->int_act_time)%60);
+ (long)(now.tv_sec - ifp->int_act_time)/60,
+ (long)(now.tv_sec - ifp->int_act_time)%60);
if_sick(ifp);
}
diff --git a/sbin/routed/trace.c b/sbin/routed/trace.c
index 320056f..8797e57 100644
--- a/sbin/routed/trace.c
+++ b/sbin/routed/trace.c
@@ -51,14 +51,12 @@ __RCSID("$Revision: 2.27 $");
#define stat stat64
#endif
-#define NRECORDS 50 /* size of circular trace buffer */
-
int tracelevel, new_tracelevel;
FILE *ftrace; /* output trace file */
static const char *sigtrace_pat = "%s";
static char savetracename[PATH_MAX];
char inittracename[PATH_MAX];
-int file_trace; /* 1=tracing to file, not stdout */
+static int file_trace; /* 1=tracing to file, not stdout */
static void trace_dump(void);
static void tmsg(const char *, ...) PATTRIB(1,2);
@@ -255,13 +253,13 @@ void
tracelevel_msg(const char *pat,
int dump) /* -1=no dump, 0=default, 1=force */
{
- static const char *off_msgs[MAX_TRACELEVEL] = {
+ static const char * const off_msgs[MAX_TRACELEVEL] = {
"Tracing actions stopped",
"Tracing packets stopped",
"Tracing packet contents stopped",
"Tracing kernel changes stopped",
};
- static const char *on_msgs[MAX_TRACELEVEL] = {
+ static const char * const on_msgs[MAX_TRACELEVEL] = {
"Tracing actions started",
"Tracing packets started",
"Tracing packet contents started",
@@ -473,13 +471,13 @@ struct bits {
const char *bits_name;
};
-static struct bits if_bits[] = {
+static const struct bits if_bits[] = {
{ IFF_LOOPBACK, 0, "LOOPBACK" },
{ IFF_POINTOPOINT, 0, "PT-TO-PT" },
{ 0, 0, 0}
};
-static struct bits is_bits[] = {
+static const struct bits is_bits[] = {
{ IS_ALIAS, 0, "ALIAS" },
{ IS_SUBNET, 0, "" },
{ IS_REMOTE, (IS_NO_RDISC
@@ -523,7 +521,7 @@ static struct bits is_bits[] = {
{ 0, 0, "%#x"}
};
-static struct bits rs_bits[] = {
+static const struct bits rs_bits[] = {
{ RS_IF, 0, "IF" },
{ RS_NET_INT, RS_NET_SYN, "NET_INT" },
{ RS_NET_SYN, 0, "NET_SYN" },
@@ -870,7 +868,7 @@ trace_dump(void)
lastlog();
(void)fputs("current daemon state:\n", ftrace);
- for (ifp = ifnet; ifp != 0; ifp = ifp->int_next)
+ LIST_FOREACH(ifp, &ifnet, int_list)
trace_if("", ifp);
(void)rn_walktree(rhead, walk_trace, 0);
}
diff --git a/sbin/slattach/Makefile b/sbin/slattach/Makefile
deleted file mode 100644
index 84b0c12..0000000
--- a/sbin/slattach/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-# @(#)Makefile 5.4 (Berkeley) 5/11/90
-#
-# $FreeBSD$
-
-PROG= slattach
-WARNS?= 0
-MAN= slattach.8
-MLINKS= slattach.8 slip.8
-LDADD= -lutil
-DPADD= ${LIBUTIL}
-
-.include <bsd.prog.mk>
diff --git a/sbin/slattach/slattach.8 b/sbin/slattach/slattach.8
deleted file mode 100644
index a359dd2..0000000
--- a/sbin/slattach/slattach.8
+++ /dev/null
@@ -1,271 +0,0 @@
-.\" Copyright (c) 1986, 1991 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.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)slattach.8 6.4 (Berkeley) 3/16/91
-.\"
-.\" $FreeBSD$
-.\"
-.Dd April 4, 1993
-.Dt SLATTACH 8
-.Os
-.Sh NAME
-.Nm slattach
-.Nd attach serial lines as network interfaces
-.Sh SYNOPSIS
-.Nm
-.Op Fl acfhLlnz
-.Op Fl e Ar exit-command
-.Op Fl K Ar keepalive
-.Op Fl O Ar outfill
-.Op Fl r Ar redial-command
-.Op Fl S Ar unit
-.Op Fl s Ar baudrate
-.Op Fl u Ar unit-command
-.Ar ttyname
-.Sh DESCRIPTION
-The
-.Nm
-utility is used to assign a tty line to a network interface,
-and to define the network source and destination addresses.
-.Pp
-The following options are available:
-.Bl -tag -width indent
-.It Fl a
-Autoenable the VJ header compression option, if the other end of the link
-is capable of VJ header compression then it will be used otherwise normal
-headers will be used.
-.It Fl c
-Enable the VJ header compression option.
-Note that both ends of the link
-must be able to use VJ header compression for this to work.
-.It Fl e Ar exit-command
-Specify a command to be invoked within a shell
-.Ql sh \-c Ar exit-command
-before
-.Nm
-exits.
-.It Fl f
-Disable the invocation of daemon() to run
-.Nm
-in the background.
-.It Fl h
-Turn on cts/rts style flow control on the slip port, by default no flow
-control is done.
-.It Fl l
-Disable modem control (CLOCAL) and ignore carrier detect on the slip
-port.
-By default the
-.Ar redial-command
-is invoked upon carrier drop and
-.Nm
-aborts if no
-.Ar redial-command
-is specified.
-.It Fl n
-Throw away ICMP packets.
-The slip interface will ignore ICMP packets
-to prevent slow lines being saturated by ICMP responses.
-.It Fl r Ar redial-command
-Specify a command to be invoked within a shell
-.Ql sh \-c Ar redial-command
-whenever carrier is lost on the modem line.
-Empty
-.Ar redial-command
-(i.e.\&
-.Fl r Qq "" )
-cause connection reestablishing on leased line
-without any external command invoked.
-.It Fl s Ar baudrate
-Specify the speed of the connection.
-If not specified, the
-default of 9600 is used.
-.It Fl u Ar unit-command
-When the line is switched to slip discipline, run
-.Dq Nm "sh -c" Ar unit-command old new
-where
-.Ar old
-and
-.Ar new
-are the slip unit numbers when the line was
-last opened and the unit number of the current slip connection
-respectively.
-The unit number can change after redialing if you are
-using more than one slip line.
-When
-.Nm
-is connected for the first time,
-.Dq Nm "sh -c" Ar unit-command \-1 new
-is run.
-When
-.Nm
-is disconnected,
-.Dq Nm "sh -c" Ar unit-command old \-1
-is run.
-The
-.Nm
-utility will abort if the unit number
-changes and
-.Dq Fl u Ar \%unit-command
-was not specified.
-.It Fl z
-Force redial
-.Ar redial-command
-upon startup irrespective of carrier.
-.It Fl L
-Use uucp-style device locking.
-You need it unless you start
-.Nm
-from external program which already does uucp locking.
-Default case is no uucp locking to satisfy such programs.
-.It Fl K Ar keepalive
-Set SLIP "keep alive" timeout in seconds.
-If FRAME_END is not received in
-this amount of time, re-connect occurs.
-The default value is no timeout.
-.It Fl O Ar outfill
-Set SLIP "out fill" timeout in seconds.
-It forces at least one FRAME_END
-to be sent during this time period, which is necessary for the "keep alive"
-timeout on the remote side.
-The default value is no timeout.
-.It Fl S Ar unit
-Set the SLIP unit number directly.
-Use with caution, because no check is made
-for two interfaces with same number.
-By default sliplogin dynamically assigns the unit number.
-.It Ar ttyname
-Specify the name of the tty device.
-.Ar Ttyname
-should be a string of the form
-.Ql ttyXX
-or
-.Ql /dev/ttyXX .
-.El
-.Pp
-Only the super-user may attach a network interface.
-.Pp
-To detach the interface, use
-.Dq Li ifconfig interface-name down
-after killing off the
-.Nm
-process using
-.Ql kill -INT .
-.Ar Interface-name
-is the name that is shown by
-.Xr netstat 1 .
-.Pp
-To setup
-.Nm
-to redial the phone when carrier is lost, use the
-.Fl r Ar redial-command
-option to specify a script or executable that will reconnect the
-serial line to the slip server.
-For example, the script could redial
-the server and log in, etc.
-.Pp
-To reconfigure the network interface in case the slip unit number
-changes, use the
-.Fl u Ar unit-command
-option to specify a script or executable that will be invoked as
-.Ql sh \-c Ar unit-command old new
-where
-.Ar old
-and
-.Ar new
-are the slip unit numbers before and after
-reconnecting the line.
-The unit number can change if you have more
-than one line disconnect at the same time.
-The first to succeed in
-reconnecting will get the lowest unit number.
-.Pp
-To kill
-.Nm
-use
-.Ql kill -INT
-(SIGINT) which causes it to close the tty and exit.
-.Pp
-To force a redial, use
-.Ql kill -HUP
-(SIGHUP) which causes
-.Nm
-to think carrier was lost and thus invoke
-.Ql sh \-c Ar redial-command
-to reconnect to the server.
-.Pp
-If you use a hard-wired connection rather than a modem, invoke
-.Nm
-with the
-.Fl l
-option in order to ignore carrier on the slip line.
-.Sh FILES
-.Bl -tag -width /usr/share/examples/slattach/* -compact
-.It Pa /var/run/slattach.<tty>.pid
-with
-.Ar tty
-replaced by the terminal path name component of
-.Ar ttyname .
-This file contains the numerical process ID of the
-.Nm
-process and can be examined by scripts in order to send a signal to
-.Nm
-.It Pa /usr/share/examples/slattach/*
-.El
-.Sh EXAMPLES
-.Bd -literal -offset indent -compact
-slattach ttyd8
-slattach \-s 4800 /dev/ttyd1
-slattach \-c \-s 38400 /dev/cuad1
-slattach \-r 'kermit -y dial.script >kermit.log 2>&1'
-.Ed
-.Sh DIAGNOSTICS
-Look for error messages in
-.Pa /var/log/messages
-.No ( Nm
-is a daemon).
-Messages indicating the specified interface does not exit, the
-requested address is unknown, the user is not privileged and tried to
-alter an interface's configuration are logged there.
-The
-.Nm
-utility
-also logs failure to set the controlling terminal or failure to install
-signal handlers.
-Upon connection and redial the ttyname and baud rate
-are logged and on shutdown the ttyname is logged.
-.Sh SEE ALSO
-.Xr netstat 1 ,
-.Xr startslip 1 ,
-.Xr netintro 4 ,
-.Xr ifconfig 8 ,
-.Xr rc 8 ,
-.Xr sliplogin 8
-.Sh HISTORY
-The
-.Nm
-utility appeared in
-.Bx 4.3 .
diff --git a/sbin/slattach/slattach.c b/sbin/slattach/slattach.c
deleted file mode 100644
index afdfce8..0000000
--- a/sbin/slattach/slattach.c
+++ /dev/null
@@ -1,599 +0,0 @@
-/*
- * Copyright (c) 1988 Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Rick Adams.
- *
- * 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.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1988 Regents of the University of California.\n\
- All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "from: @(#)slattach.c 4.6 (Berkeley) 6/1/90";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-
-#include <err.h>
-#include <fcntl.h>
-#include <libutil.h>
-#include <paths.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include <net/if.h>
-#include <net/slip.h>
-
-#define DEFAULT_BAUD 9600
-
-void sighup_handler(); /* SIGHUP handler */
-void sigint_handler(); /* SIGINT handler */
-void sigterm_handler(); /* SIGTERM handler */
-void sigurg_handler(); /* SIGURG handler */
-void exit_handler(int ret); /* run exit_cmd iff specified upon exit. */
-void setup_line(int cflag); /* configure terminal settings */
-void slip_discipline(); /* switch to slip line discipline */
-void configure_network(); /* configure slip interface */
-void acquire_line(); /* get tty device as controlling terminal */
-static void usage(void);
-
-int fd = -1;
-char *dev = (char *)0; /* path name of the tty (e.g. /dev/tty01) */
-char *dvname; /* basename of dev */
-int locked = 0; /* uucp lock active */
-int flow_control = 0; /* non-zero to enable hardware flow control. */
-int modem_control = HUPCL; /* !CLOCAL+HUPCL iff we watch carrier. */
-int comstate; /* TIOCMGET current state of serial driver */
-int redial_on_startup = 0; /* iff non-zero execute redial_cmd on startup */
-speed_t speed = DEFAULT_BAUD; /* baud rate of tty */
-int slflags = 0; /* compression flags */
-int unit = -1; /* slip device unit number */
-int foreground = 0; /* act as daemon if zero, else don't fork. */
-int keepal = 0; /* keepalive timeout */
-int outfill = 0; /* outfill timeout */
-int sl_unit = -1; /* unit number */
-int uucp_lock = 0; /* do uucp locking */
-int exiting = 0; /* already running exit_handler */
-
-struct termios tty; /* tty configuration/state */
-
-char tty_path[32]; /* path name of the tty (e.g. /dev/tty01) */
-char pidfilename[40]; /* e.g. /var/run/slattach.tty01.pid */
-char *redial_cmd = 0; /* command to exec upon shutdown. */
-char *config_cmd = 0; /* command to exec if slip unit changes. */
-char *exit_cmd = 0; /* command to exec before exiting. */
-
-static void
-usage()
-{
- fprintf(stderr, "%s\n%s\n%s\n",
-"usage: slattach [-acfhLlnz] [-e exit-command] [-K keepalive] [-O outfill]",
-" [-r redial-command] [-S unit] [-s baudrate] [-u unit-command]",
-" ttyname");
- /* do not exit here */
-}
-
-int
-main(int argc, char **argv)
-{
- int option;
-
- while ((option = getopt(argc, argv, "ace:fhlnr:s:u:zLK:O:S:")) != -1) {
- switch (option) {
- case 'a':
- slflags |= IFF_LINK2;
- slflags &= ~IFF_LINK0;
- break;
- case 'c':
- slflags |= IFF_LINK0;
- slflags &= ~IFF_LINK2;
- break;
- case 'e':
- exit_cmd = strdup (optarg);
- break;
- case 'f':
- foreground = 1;
- break;
- case 'h':
- flow_control |= CRTSCTS;
- break;
- case 'l':
- modem_control = CLOCAL; /* clear HUPCL too */
- break;
- case 'n':
- slflags |= IFF_LINK1;
- break;
- case 'r':
- redial_cmd = strdup (optarg);
- break;
- case 's':
- speed = atoi(optarg);
- break;
- case 'u':
- config_cmd = strdup (optarg);
- break;
- case 'z':
- redial_on_startup = 1;
- break;
- case 'L':
- uucp_lock = 1;
- break;
- case 'K':
- keepal = atoi(optarg);
- break;
- case 'O':
- outfill = atoi(optarg);
- break;
- case 'S':
- sl_unit = atoi(optarg);
- break;
- case '?':
- default:
- usage();
- exit_handler(1);
- }
- }
-
- if (optind == argc - 1)
- dev = argv[optind];
-
- if (optind < (argc - 1))
- warnx("too many args, first='%s'", argv[optind]);
- if (optind > (argc - 1))
- warnx("not enough args");
- if (dev == (char *)0) {
- usage();
- exit_handler(2);
- }
- if (strncmp(_PATH_DEV, dev, sizeof(_PATH_DEV) - 1)) {
- strcpy(tty_path, _PATH_DEV);
- strcat(tty_path, "/");
- strncat(tty_path, dev, 10);
- dev = tty_path;
- }
- dvname = strrchr(dev, '/'); /* always succeeds */
- dvname++; /* trailing tty pathname component */
- snprintf(pidfilename, sizeof(pidfilename),
- "%sslattach.%s.pid", _PATH_VARRUN, dvname);
- printf("%s\n",pidfilename);
-
- if (!foreground)
- daemon(0,0); /* fork, setsid, chdir /, and close std*. */
- /* daemon() closed stderr, so log errors from here on. */
- openlog("slattach",LOG_CONS|LOG_PID,LOG_DAEMON);
-
- acquire_line(); /* get tty device as controlling terminal */
- setup_line(0); /* configure for slip line discipline */
- slip_discipline(); /* switch to slip line discipline */
-
- /* upon INT log a timestamp and exit. */
- if (signal(SIGINT,sigint_handler) == SIG_ERR)
- syslog(LOG_NOTICE,"cannot install SIGINT handler: %m");
- /* upon TERM log a timestamp and exit. */
- if (signal(SIGTERM,sigterm_handler) == SIG_ERR)
- syslog(LOG_NOTICE,"cannot install SIGTERM handler: %m");
- /* upon HUP redial and reconnect. */
- if (signal(SIGHUP,sighup_handler) == SIG_ERR)
- syslog(LOG_NOTICE,"cannot install SIGHUP handler: %m");
-
- if (redial_on_startup)
- sighup_handler();
- else if (!(modem_control & CLOCAL)) {
- if (ioctl(fd, TIOCMGET, &comstate) < 0)
- syslog(LOG_NOTICE,"cannot get carrier state: %m");
- if (!(comstate & TIOCM_CD)) { /* check for carrier */
- /* force a redial if no carrier */
- kill (getpid(), SIGHUP);
- } else
- configure_network();
- } else
- configure_network(); /* configure the network if needed. */
-
- for (;;) {
- sigset_t mask;
- sigemptyset(&mask);
- sigsuspend(&mask);
- }
-}
-
-/* Close all FDs, fork, reopen tty port as 0-2, and make it the
- controlling terminal for our process group. */
-void acquire_line()
-{
- int ttydisc = TTYDISC;
- int oflags;
- FILE *pidfile;
-
- /* reset to tty discipline */
- if (fd >= 0 && ioctl(fd, TIOCSETD, &ttydisc) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
- exit_handler(1);
- }
-
- (void)close(STDIN_FILENO); /* close FDs before forking. */
- (void)close(STDOUT_FILENO);
- (void)close(STDERR_FILENO);
- if (fd > 2)
- (void)close(fd);
-
- signal(SIGHUP, SIG_IGN); /* ignore HUP signal when parent dies. */
- if (daemon(0,0)) { /* fork, setsid, chdir /, and close std*. */
- syslog(LOG_ERR, "daemon(0,0): %m");
- exit_handler(1);
- }
-
- while (getppid () != 1)
- sleep (1); /* Wait for parent to die. */
-
- /* create PID file */
- if((pidfile = fopen(pidfilename, "w"))) {
- fprintf(pidfile, "%ld\n", (long)getpid());
- fclose(pidfile);
- }
-
- if (signal(SIGHUP,sighup_handler) == SIG_ERR) /* Re-enable HUP signal */
- syslog(LOG_NOTICE,"cannot install SIGHUP handler: %m");
-
- if (uucp_lock) {
- /* unlock not needed here, always re-lock with new pid */
- int res;
- if ((res = uu_lock(dvname)) != UU_LOCK_OK) {
- if (res != UU_LOCK_INUSE)
- syslog(LOG_ERR, "uu_lock: %s", uu_lockerr(res));
- syslog(LOG_ERR, "can't lock %s", dev);
- exit_handler(1);
- }
- locked = 1;
- }
-
- if ((fd = open(dev, O_RDWR | O_NONBLOCK, 0)) < 0) {
- syslog(LOG_ERR, "open(%s) %m", dev);
- exit_handler(1);
- }
- /* Turn off O_NONBLOCK for dumb redialers, if any. */
- if ((oflags = fcntl(fd, F_GETFL)) == -1) {
- syslog(LOG_ERR, "fcntl(F_GETFL) failed: %m");
- exit_handler(1);
- }
- if (fcntl(fd, F_SETFL, oflags & ~O_NONBLOCK) == -1) {
- syslog(LOG_ERR, "fcntl(F_SETFL) failed: %m");
- exit_handler(1);
- }
- (void)dup2(fd, STDIN_FILENO);
- (void)dup2(fd, STDOUT_FILENO);
- (void)dup2(fd, STDERR_FILENO);
- if (fd > 2)
- (void)close (fd);
- fd = STDIN_FILENO;
-
- /* acquire the serial line as a controlling terminal. */
- if (ioctl(fd, TIOCSCTTY, 0) < 0) {
- syslog(LOG_ERR,"ioctl(TIOCSCTTY): %m");
- exit_handler(1);
- }
- /* Make us the foreground process group associated with the
- slip line which is our controlling terminal. */
- if (tcsetpgrp(fd, getpid()) < 0)
- syslog(LOG_NOTICE,"tcsetpgrp failed: %m");
-}
-
-/* Set the tty flags and set DTR. */
-/* Call as setup_line(CLOCAL) to force clocal assertion. */
-void setup_line(int cflag)
-{
- tty.c_lflag = tty.c_iflag = tty.c_oflag = 0;
- tty.c_cflag = CREAD | CS8 | flow_control | modem_control | cflag;
- cfsetispeed(&tty, speed);
- cfsetospeed(&tty, speed);
- /* set the line speed and flow control */
- if (tcsetattr(fd, TCSAFLUSH, &tty) < 0) {
- syslog(LOG_ERR, "tcsetattr(TCSAFLUSH): %m");
- exit_handler(1);
- }
- /* set data terminal ready */
- if (ioctl(fd, TIOCSDTR) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCSDTR): %m");
- exit_handler(1);
- }
-}
-
-/* Put the line in slip discipline. */
-void slip_discipline()
-{
- struct ifreq ifr;
- int slipdisc = SLIPDISC;
- int s, tmp_unit = -1;
-
- /* Switch to slip line discipline. */
- if (ioctl(fd, TIOCSETD, &slipdisc) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
- exit_handler(1);
- }
-
- if (sl_unit >= 0 && ioctl(fd, SLIOCSUNIT, &sl_unit) < 0) {
- syslog(LOG_ERR, "ioctl(SLIOCSUNIT): %m");
- exit_handler(1);
- }
-
- /* find out what unit number we were assigned */
- if (ioctl(fd, SLIOCGUNIT, (caddr_t)&tmp_unit) < 0) {
- syslog(LOG_ERR, "ioctl(SLIOCGUNIT): %m");
- exit_handler(1);
- }
-
- if (tmp_unit < 0) {
- syslog(LOG_ERR, "bad unit (%d) from ioctl(SLIOCGUNIT)",tmp_unit);
- exit_handler(1);
- }
-
- if (keepal > 0) {
- signal(SIGURG, sigurg_handler);
- if (ioctl(fd, SLIOCSKEEPAL, &keepal) < 0) {
- syslog(LOG_ERR, "ioctl(SLIOCSKEEPAL): %m");
- exit_handler(1);
- }
- }
- if (outfill > 0 && ioctl(fd, SLIOCSOUTFILL, &outfill) < 0) {
- syslog(LOG_ERR, "ioctl(SLIOCSOUTFILL): %m");
- exit_handler(1);
- }
-
- /* open a socket as the handle to the interface */
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- syslog(LOG_ERR, "socket: %m");
- exit_handler(1);
- }
- sprintf(ifr.ifr_name, "sl%d", tmp_unit);
-
- /* get the flags for the interface */
- if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
- syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
- exit_handler(1);
- }
-
- /* Assert any compression or no-icmp flags. */
-#define SLMASK (~(IFF_LINK0 | IFF_LINK1 | IFF_LINK2))
- ifr.ifr_flags &= SLMASK;
- ifr.ifr_flags |= slflags;
- if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
- syslog(LOG_ERR, "ioctl (SIOCSIFFLAGS): %m");
- exit_handler(1);
- }
- close(s);
-}
-
-/* configure the interface, e.g. by passing the unit number to a script. */
-void configure_network()
-{
- int new_unit;
-
- /* find out what unit number we were assigned */
- if (ioctl(fd, SLIOCGUNIT, (caddr_t)&new_unit) < 0) {
- syslog(LOG_ERR, "ioctl(SLIOCGUNIT): %m");
- exit_handler(1);
- }
- /* iff the unit number changes either invoke config_cmd or punt. */
- if (config_cmd) {
- char *s;
- s = (char*) malloc(strlen(config_cmd) + 32);
- if (s == NULL) {
- syslog(LOG_ERR, "malloc failed");
- exit(1);
- }
- sprintf (s, "%s %d %d", config_cmd, unit, new_unit);
- syslog(LOG_NOTICE, "configuring %s (sl%d):", dev, unit);
- syslog(LOG_NOTICE, " '%s'", s);
- system(s);
- free (s);
- unit = new_unit;
- } else {
- /* don't compare unit numbers if this is the first time to attach. */
- if (unit < 0)
- unit = new_unit;
- if (new_unit != unit) {
- syslog(LOG_ERR,
- "slip unit changed from sl%d to sl%d, but no -u CMD was specified!",
- unit, new_unit);
- exit_handler(1);
- }
- syslog(LOG_NOTICE,"sl%d connected to %s at %d baud",unit,dev,speed);
- }
-}
-
-/* sighup_handler() is invoked when carrier drops, eg. before redial. */
-void sighup_handler()
-{
- if(exiting) return;
-
- if (redial_cmd == NULL) {
- syslog(LOG_NOTICE,"SIGHUP on %s (sl%d); exiting", dev, unit);
- exit_handler(1);
- }
-again:
- /* invoke a shell for redial_cmd or punt. */
- if (*redial_cmd) { /* Non-empty redial command */
- syslog(LOG_NOTICE,"SIGHUP on %s (sl%d); running '%s'",
- dev, unit, redial_cmd);
- acquire_line(); /* reopen dead line */
- setup_line(CLOCAL);
- if (locked) {
- if (uucp_lock)
- uu_unlock(dvname); /* for redial */
- locked = 0;
- }
- if (system(redial_cmd))
- goto again;
- if (uucp_lock) {
- int res;
- if ((res = uu_lock(dvname)) != UU_LOCK_OK) {
- if (res != UU_LOCK_INUSE)
- syslog(LOG_ERR, "uu_lock: %s", uu_lockerr(res));
- syslog(LOG_ERR, "can't relock %s after %s, aborting",
- dev, redial_cmd);
- exit_handler(1);
- }
- locked = 1;
- }
- /* Now check again for carrier (dial command is done): */
- if (!(modem_control & CLOCAL)) {
- tty.c_cflag &= ~CLOCAL;
- if (tcsetattr(fd, TCSAFLUSH, &tty) < 0) {
- syslog(LOG_ERR, "tcsetattr(TCSAFLUSH): %m");
- exit_handler(1);
- }
- ioctl(fd, TIOCMGET, &comstate);
- if (!(comstate & TIOCM_CD)) { /* check for carrier */
- /* force a redial if no carrier */
- goto again;
- }
- } else
- setup_line(0);
- } else { /* Empty redial command */
- syslog(LOG_NOTICE,"SIGHUP on %s (sl%d); reestablish connection",
- dev, unit);
- acquire_line(); /* reopen dead line */
- setup_line(0); /* restore ospeed from hangup (B0) */
- /* If modem control, just wait for carrier before attaching.
- If no modem control, just fall through immediately. */
- if (!(modem_control & CLOCAL)) {
- int carrier = 0;
-
- syslog(LOG_NOTICE, "waiting for carrier on %s (sl%d)",
- dev, unit);
- /* Now wait for carrier before attaching line. */
- /* We must poll since CLOCAL prevents signal. */
- while (! carrier) {
- sleep(2);
- ioctl(fd, TIOCMGET, &comstate);
- if (comstate & TIOCM_CD)
- carrier = 1;
- }
- syslog(LOG_NOTICE, "carrier now present on %s (sl%d)",
- dev, unit);
- }
- }
- slip_discipline();
- configure_network();
-}
-/* Signal handler for SIGINT. We just log and exit. */
-void sigint_handler()
-{
- if(exiting) return;
- syslog(LOG_NOTICE,"SIGINT on %s (sl%d); exiting",dev,unit);
- exit_handler(0);
-}
-/* Signal handler for SIGURG. */
-void sigurg_handler()
-{
- int ttydisc = TTYDISC;
-
- signal(SIGURG, SIG_IGN);
- if(exiting) return;
- syslog(LOG_NOTICE,"SIGURG on %s (sl%d); hangup",dev,unit);
- if (ioctl(fd, TIOCSETD, &ttydisc) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
- exit_handler(1);
- }
- cfsetospeed(&tty, B0);
- if (tcsetattr(fd, TCSANOW, &tty) < 0) {
- syslog(LOG_ERR, "tcsetattr(TCSANOW): %m");
- exit_handler(1);
- }
- /* Need to go to sighup handler in any case */
- if (modem_control & CLOCAL)
- kill (getpid(), SIGHUP);
-
-}
-/* Signal handler for SIGTERM. We just log and exit. */
-void sigterm_handler()
-{
- if(exiting) return;
- syslog(LOG_NOTICE,"SIGTERM on %s (sl%d); exiting",dev,unit);
- exit_handler(0);
-}
-/* Run config_cmd if specified before exiting. */
-void exit_handler(int ret)
-{
- if(exiting) return;
- exiting = 1;
- /*
- * First close the slip line in case exit_cmd wants it (like to hang
- * up a modem or something).
- */
- if (fd != -1)
- close(fd);
- if (uucp_lock && locked)
- uu_unlock(dvname);
-
- /* Remove the PID file */
- (void)unlink(pidfilename);
-
- if (config_cmd) {
- char *s;
- s = (char*) malloc(strlen(config_cmd) + 32);
- if (s == NULL) {
- syslog(LOG_ERR, "malloc failed");
- exit(1);
- }
- sprintf (s, "%s %d -1", config_cmd, unit);
- syslog(LOG_NOTICE, "deconfiguring %s (sl%d):", dev, unit);
- syslog(LOG_NOTICE, " '%s'", s);
- system(s);
- free (s);
- }
- /* invoke a shell for exit_cmd. */
- if (exit_cmd) {
- syslog(LOG_NOTICE,"exiting after running %s", exit_cmd);
- system(exit_cmd);
- }
- exit(ret);
-}
-
-/* local variables: */
-/* c-indent-level: 8 */
-/* c-argdecl-indent: 0 */
-/* c-label-offset: -8 */
-/* c-continued-statement-offset: 8 */
-/* c-brace-offset: 0 */
-/* comment-column: 32 */
-/* end: */
diff --git a/sbin/startslip/Makefile b/sbin/startslip/Makefile
deleted file mode 100644
index 1bf91dd..0000000
--- a/sbin/startslip/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 6/5/93
-# $FreeBSD$
-
-PROG= startslip
-WARNS?= 3
-DPADD= ${LIBUTIL}
-LDADD= -lutil
-
-.include <bsd.prog.mk>
diff --git a/sbin/startslip/startslip.1 b/sbin/startslip/startslip.1
deleted file mode 100644
index 2d6f43b..0000000
--- a/sbin/startslip/startslip.1
+++ /dev/null
@@ -1,213 +0,0 @@
-.\" Copyright (c) 1990, 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)startslip.1 8.1 (Berkeley) 6/5/93
-.\" $FreeBSD$
-.\"
-.Dd June 5, 1993
-.Dt STARTSLIP 1
-.Os
-.Sh NAME
-.Nm startslip
-.Nd dial up and login to a slip server
-.Sh SYNOPSIS
-.Nm
-.Op Fl d
-.Op Fl b Ar speed
-.Oo
-.Fl s Ar string1
-.Op Fl s Ar string2 Op Ar ...\&
-.Oc
-.Op Fl h
-.Op Fl l
-.Op Fl L
-.Op Fl A Ar annexname
-.Op Fl U Ar upscript
-.Op Fl D Ar downscript
-.Op Fl t Ar script_timeout
-.Op Fl W Ar maxtries
-.Op Fl w Ar retry_pause
-.Op Fl K Ar keepalive
-.Op Fl O Ar outfill
-.Op Fl S Ar unit
-.Ar device user password
-.Sh DESCRIPTION
-The
-.Nm
-utility opens the specified
-.Ar device .
-Once carrier is asserted (if modem control is enabled)
-.Nm
-attempts to login as the specified
-.Ar user
-with the given
-.Ar password .
-Standard login: & Password: scheme assumed unless Annex option
-specified (see
-.Fl A ) .
-If successful, it puts the device into the slip line discipline,
-calls
-.Ar upscript
-and goes to wait mode.
-If carrier drops (modem control enabled) or a
-.Dv SIGHUP
-is sent to
-.Nm ,
-it closes the device, calls
-.Ar downscript
-and attempts to repeat the dialup and login sequence.
-If a
-.Dv SIGTERM
-is send to
-.Nm ,
-it closes the device, calls
-.Ar downscript
-and exits.
-When
-.Nm
-called twice on the same device, previous copy killed by a
-.Dv SIGTERM
-before any operation.
-.Pp
-The following options are available:
-.Bl -tag -width indent
-.It Fl d
-Print out debugging information.
-.It Fl b Ar speed
-Determine the baud rate used for
-.Ar device ,
-default value is 9600.
-.It Fl t Ar script_timeout
-Set login script timeout in seconds, default value is 90.
-.It Fl w Ar retry_pause
-Set connecting retry pause in seconds (increased from one retry to another),
-default value is 60.
-.It Fl W Ar maxtries
-Set maximum number of connection retries for one session,
-default value is 6.
-Value 0 means infinite count.
-.It Fl s Ar stringN
-The optional
-.Ar stringN
-is written to
-.Ar device .
-Return character is added automatically.
-For a dialup modem,
-the string is used to specify a dial sequence.
-No string written by default.
-You can specify several
-.Fl s Ar stringN
-arguments to use with each try, f.e.
-several host phone numbers.
-.It Fl A Ar annexname
-The
-.Nm
-utility assumes it is connecting to a Xylogics Annex box and engages in an
-appropriate dialog using the
-.Ar user
-and
-.Ar password
-arguments.
-The
-.Ar annexname
-argument is a string that is used to match against the Annex prompt
-to determine when a connection has been established.
-.It Fl h
-Use hardware (CTS/RTS) flow control for
-.Ar device .
-Default value is no flow control.
-.It Fl l
-Disable modem control (waiting for carrier and carrier drop sense) for
-.Ar device .
-Modem control is enabled by default.
-.It Fl U Ar upscript
-Specify a script to run when a SLIP interface becomes connected.
-This may
-contain
-.Xr ifconfig 8 ,
-.Xr route 8 ,
-and other appropriate commands.
-The arguments that
-are passed to the script are "slX up".
-Default value is
-.Pa /sbin/ifconfig .
-Dial sequence number (see
-.Fl s )
-passed via
-.Ev LINE
-environment variable.
-.It Fl D Ar downscript
-Specify a script to run when a SLIP connection goes away.
-The arguments that
-are passed to the script are "slX down".
-Default value is
-.Pa /sbin/ifconfig .
-Dial sequence number (see
-.Fl s )
-passed via
-.Ev LINE
-environment variable.
-.It Fl K Ar keepalive
-Set SLIP "keep alive" timeout in seconds.
-If FRAME_END not received during this
-time period, a reconnect will occur.
-Active "out fill" timeout expected from other
-side.
-Default value is no timeout.
-.It Fl O Ar outfill
-Set SLIP "out fill" timeout in seconds.
-It causes at least one FRAME_END
-to be sent during this timeout.
-Needed for "keep alive" timeout on other side.
-Default value is no timeout.
-.It Fl S Ar unit
-Set SLIP unit number directly.
-Use with caution, no check for two
-interfaces with same number made.
-Default is dynamic assignment.
-.It Fl L
-Use uucp-style device locking.
-You need it unless you start
-.Nm
-from external program which already does uucp locking.
-Default case is no uucp locking to satisfy such programs.
-.El
-.Sh FILES
-.Bl -tag -width /var/run/startslip.<device>.pid -compact
-.It Pa /var/run/startslip.<device>.pid
-pid stored here
-.It Pa /usr/share/examples/startslip/*
-.El
-.Sh SEE ALSO
-.Xr uustat 1 Pq Pa ports/net/freebsd-uucp ,
-.Xr slattach 8 ,
-.Xr sliplogin 8
-.Sh HISTORY
-The
-.Nm
-appeared in
-.Bx 4.4 .
diff --git a/sbin/startslip/startslip.c b/sbin/startslip/startslip.c
deleted file mode 100644
index 2d4d3bf..0000000
--- a/sbin/startslip/startslip.c
+++ /dev/null
@@ -1,595 +0,0 @@
-/*-
- * Copyright (c) 1990, 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static const char copyright[] =
-"@(#) Copyright (c) 1990, 1991, 1993\n\
- The Regents of the University of California. All rights reserved.\n";
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)startslip.c 8.1 (Berkeley) 6/5/93";
-#endif
-static const char rcsid[] =
- "$FreeBSD$";
-#endif /* not lint */
-
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include <err.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libutil.h>
-#include <paths.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <termios.h>
-#include <unistd.h>
-
-#include <net/slip.h>
-
-#define DEFAULT_BAUD B9600
-int speed = DEFAULT_BAUD;
-#define FC_NONE 0 /* flow control: none */
-#define FC_HW 1 /* flow control: hardware (RTS/CTS) */
-int flowcontrol = FC_NONE;
-int modem_control = 1; /* !CLOCAL+HUPCL iff we watch carrier. */
-int sl_unit = -1;
-int uucp_lock = 0; /* uucp locking */
-char *annex;
-char *username;
-int hup;
-int terminate;
-int locked = 0; /* uucp lock active */
-int logged_in = 0;
-int wait_time = 60; /* then back off */
-int script_timeout = 90; /* connect script default timeout */
-time_t conn_time, start_time;
-int MAXTRIES = 6; /* w/60 sec and doubling, takes an hour */
-#define PIDFILE "%sstartslip.%s.pid"
-
-#define MAXDIALS 20
-char *dials[MAXDIALS];
-int diali, dialc;
-
-int fd = -1;
-FILE *pfd;
-char *dvname, *devicename;
-char pidfile[80];
-
-#ifdef DEBUG
-int debug = 1;
-#undef LOG_ERR
-#undef LOG_INFO
-#define syslog fprintf
-#define LOG_ERR stderr
-#define LOG_INFO stderr
-#else
-int debug = 0;
-#endif
-#define printd if (debug) printf
-
-int carrier(void);
-void down(int);
-int getline(char *, int, int, time_t);
-void sighup(int);
-void sigterm(int);
-void sigurg(int);
-static void usage(void);
-
-int
-main(int argc, char **argv)
-{
- char *cp, **ap;
- int ch, disc;
- FILE *wfd = NULL;
- char *dialerstring = 0, buf[BUFSIZ];
- int unitnum, keepal = 0, outfill = 0;
- char unitname[32];
- char *password;
- char *upscript = NULL, *downscript = NULL;
- int first = 1, tries = 0;
- time_t fintimeout;
- long lpid;
- pid_t pid;
- struct termios t;
-
- while ((ch = getopt(argc, argv, "dhlb:s:t:w:A:U:D:W:K:O:S:L")) != -1)
- switch (ch) {
- case 'd':
- debug = 1;
- break;
- case 'b':
- speed = atoi(optarg);
- break;
- case 's':
- if (diali >= MAXDIALS)
- errx(1, "max dial strings number (%d) exceeded", MAXDIALS);
- dials[diali++] = strdup(optarg);
- break;
- case 't':
- script_timeout = atoi(optarg);
- break;
- case 'w':
- wait_time = atoi(optarg);
- break;
- case 'W':
- MAXTRIES = atoi(optarg);
- break;
- case 'A':
- annex = strdup(optarg);
- break;
- case 'U':
- upscript = strdup(optarg);
- break;
- case 'D':
- downscript = strdup(optarg);
- break;
- case 'L':
- uucp_lock = 1;
- break;
- case 'l':
- modem_control = 0;
- break;
- case 'h':
- flowcontrol = FC_HW;
- break;
- case 'K':
- keepal = atoi(optarg);
- break;
- case 'O':
- outfill = atoi(optarg);
- break;
- case 'S':
- sl_unit = atoi(optarg);
- break;
- case '?':
- default:
- usage();
- }
- argc -= optind;
- argv += optind;
-
- if (argc != 3)
- usage();
-
- /*
- * Copy these so they exist after we clobber them.
- */
- devicename = strdup(argv[0]);
- username = strdup(argv[1]);
- password = strdup(argv[2]);
-
- /*
- * Security hack. Do not want private information such as the
- * password and possible phone number to be left around.
- * So we clobber the arguments.
- */
- for (ap = argv - optind + 1; ap < argv + 3; ap++)
- for (cp = *ap; *cp != 0; cp++)
- *cp = '\0';
-
- openlog("startslip", LOG_PID|LOG_PERROR, LOG_DAEMON);
-
- if (debug)
- setbuf(stdout, NULL);
-
- signal(SIGTERM, sigterm);
- if ((dvname = strrchr(devicename, '/')) == NULL)
- dvname = devicename;
- else
- dvname++;
- if (snprintf(pidfile, sizeof(pidfile), PIDFILE, _PATH_VARRUN, dvname)
- >= (int)sizeof(pidfile))
- usage();
-
- if ((pfd = fopen(pidfile, "r")) != NULL) {
- if (fscanf(pfd, "%ld\n", &lpid) == 1) {
- pid = lpid;
- if (pid == lpid && pid > 0)
- kill(pid, SIGTERM);
- }
- fclose(pfd);
- pfd = NULL; /* not remove pidfile yet */
- sleep(5); /* allow down script to be completed */
- } else
-restart:
- signal(SIGHUP, SIG_IGN);
- signal(SIGURG, SIG_IGN);
- hup = 0;
- if (wfd) {
- printd("fclose, ");
- fclose(wfd);
- conn_time = time(NULL) - start_time;
- if (uucp_lock)
- uu_unlock(dvname);
- locked = 0;
- wfd = NULL;
- fd = -1;
- sleep(5);
- } else if (fd >= 0) {
- printd("close, ");
- close(fd);
- conn_time = time(NULL) - start_time;
- if (uucp_lock)
- uu_unlock(dvname);
- locked = 0;
- fd = -1;
- sleep(5);
- }
- if (logged_in) {
- syslog(LOG_INFO, "%s: connection time elapsed: %ld secs",
- username, (long)conn_time);
- sprintf(buf, "LINE=%d %s %s down",
- diali ? (dialc - 1) % diali : 0,
- downscript ? downscript : _PATH_IFCONFIG , unitname);
- (void) system(buf);
- logged_in = 0;
- }
- if (terminate)
- down(0);
- tries++;
- if (MAXTRIES > 0 && tries > MAXTRIES) {
- syslog(LOG_ERR, "%s: exiting login after %d tries", username, tries);
- /* ???
- if (first)
- */
- down(3);
- }
- if (tries > 1) {
- syslog(LOG_INFO, "%s: sleeping %d seconds (%d tries)",
- username, wait_time * (tries - 1), tries);
- sleep(wait_time * (tries - 1));
- if (terminate)
- goto restart;
- }
-
- if (daemon(1, debug) < 0) {
- syslog(LOG_ERR, "%s: daemon: %m", username);
- down(2);
- }
-
- pid = getpid();
- printd("restart: pid %ld: ", (long)pid);
- if ((pfd = fopen(pidfile, "w")) != NULL) {
- fprintf(pfd, "%ld\n", (long)pid);
- fclose(pfd);
- }
- printd("open");
- if (uucp_lock) {
- int res;
- if ((res = uu_lock(dvname)) != UU_LOCK_OK) {
- if (res != UU_LOCK_INUSE)
- syslog(LOG_ERR, "uu_lock: %s", uu_lockerr(res));
- syslog(LOG_ERR, "%s: can't lock %s", username, devicename);
- goto restart;
- }
- locked = 1;
- }
- if ((fd = open(devicename, O_RDWR | O_NONBLOCK)) < 0) {
- syslog(LOG_ERR, "%s: open %s: %m", username, devicename);
- if (first)
- down(1);
- else {
- if (uucp_lock)
- uu_unlock(dvname);
- locked = 0;
- goto restart;
- }
- }
- printd(" %d", fd);
- signal(SIGHUP, sighup);
- if (ioctl(fd, TIOCSCTTY, 0) < 0) {
- syslog(LOG_ERR, "%s: ioctl (TIOCSCTTY): %m", username);
- down(2);
- }
- if (tcsetpgrp(fd, getpid()) < 0) {
- syslog(LOG_ERR, "%s: tcsetpgrp failed: %m", username);
- down(2);
- }
- printd(", ioctl\n");
- if (tcgetattr(fd, &t) < 0) {
- syslog(LOG_ERR, "%s: tcgetattr(%s): %m", username, devicename);
- down(2);
- }
- cfmakeraw(&t);
- switch (flowcontrol) {
- case FC_HW:
- t.c_cflag |= (CRTS_IFLOW|CCTS_OFLOW);
- break;
- case FC_NONE:
- t.c_cflag &= ~(CRTS_IFLOW|CCTS_OFLOW);
- break;
- }
- if (modem_control)
- t.c_cflag |= HUPCL;
- else
- t.c_cflag &= ~(HUPCL);
- t.c_cflag |= CLOCAL; /* until modem commands passes */
- cfsetispeed(&t, speed);
- cfsetospeed(&t, speed);
- if (tcsetattr(fd, TCSAFLUSH, &t) < 0) {
- syslog(LOG_ERR, "%s: tcsetattr(%s): %m", username, devicename);
- down(2);
- }
- sleep(2); /* wait for flakey line to settle */
- if (hup || terminate)
- goto restart;
-
- wfd = fdopen(fd, "w+");
- if (wfd == NULL) {
- syslog(LOG_ERR, "%s: can't fdopen %s: %m", username, devicename);
- down(2);
- }
- setbuf(wfd, NULL);
-
- if (diali > 0)
- dialerstring = dials[dialc++ % diali];
- if (dialerstring) {
- syslog(LOG_INFO, "%s: dialer string: %s\\r", username, dialerstring);
- fprintf(wfd, "%s\r", dialerstring);
- }
- printd("\n");
-
- fintimeout = time(NULL) + script_timeout;
- if (modem_control) {
- printd("waiting for carrier\n");
- while (time(NULL) < fintimeout && !carrier()) {
- sleep(1);
- if (hup || terminate)
- goto restart;
- }
- if (!carrier())
- goto restart;
- t.c_cflag &= ~(CLOCAL);
- if (tcsetattr(fd, TCSANOW, &t) < 0) {
- syslog(LOG_ERR, "%s: tcsetattr(%s): %m", username, devicename);
- down(2);
- }
- /* Only now we able to receive HUP on carrier drop! */
- }
-
- /*
- * Log in
- */
- printd("look for login: ");
- for (;;) {
- if (getline(buf, BUFSIZ, fd, fintimeout) == 0 || hup || terminate)
- goto restart;
- if (annex) {
- if (bcmp(buf, annex, strlen(annex)) == 0) {
- fprintf(wfd, "slip\r");
- printd("Sent \"slip\"\n");
- continue;
- }
- if (bcmp(&buf[1], "sername:", 8) == 0) {
- fprintf(wfd, "%s\r", username);
- printd("Sent login: %s\n", username);
- continue;
- }
- if (bcmp(&buf[1], "assword:", 8) == 0) {
- fprintf(wfd, "%s\r", password);
- printd("Sent password: %s\n", password);
- break;
- }
- } else {
- if (strstr(&buf[1], "ogin:") != NULL) {
- fprintf(wfd, "%s\r", username);
- printd("Sent login: %s\n", username);
- continue;
- }
- if (strstr(&buf[1], "assword:") != NULL) {
- fprintf(wfd, "%s\r", password);
- printd("Sent password: %s\n", password);
- break;
- }
- }
- }
-
- sleep(5); /* Wait until login completed */
- if (hup || terminate)
- goto restart;
- start_time = time(NULL);
- /*
- * Attach
- */
- printd("setd");
- disc = SLIPDISC;
- if (ioctl(fd, TIOCSETD, &disc) < 0) {
- syslog(LOG_ERR, "%s: ioctl (%s, TIOCSETD): %m",
- username, devicename);
- down(2);
- }
- if (sl_unit >= 0 && ioctl(fd, SLIOCSUNIT, &sl_unit) < 0) {
- syslog(LOG_ERR, "%s: ioctl(SLIOCSUNIT): %m", username);
- down(2);
- }
- if (ioctl(fd, SLIOCGUNIT, &unitnum) < 0) {
- syslog(LOG_ERR, "%s: ioctl(SLIOCGUNIT): %m", username);
- down(2);
- }
- sprintf(unitname, "sl%d", unitnum);
-
- if (keepal > 0) {
- signal(SIGURG, sigurg);
- if (ioctl(fd, SLIOCSKEEPAL, &keepal) < 0) {
- syslog(LOG_ERR, "%s: ioctl(SLIOCSKEEPAL): %m", username);
- down(2);
- }
- }
- if (outfill > 0 && ioctl(fd, SLIOCSOUTFILL, &outfill) < 0) {
- syslog(LOG_ERR, "%s: ioctl(SLIOCSOUTFILL): %m", username);
- down(2);
- }
-
- sprintf(buf, "LINE=%d %s %s up",
- diali ? (dialc - 1) % diali : 0,
- upscript ? upscript : _PATH_IFCONFIG , unitname);
- (void) system(buf);
-
- printd(", ready\n");
- if (!first)
- syslog(LOG_INFO, "%s: reconnected on %s (%d tries)", username, unitname, tries);
- else
- syslog(LOG_INFO, "%s: connected on %s", username, unitname);
- first = 0;
- tries = 0;
- logged_in = 1;
- while (hup == 0 && terminate == 0) {
- sigpause(0L);
- printd("sigpause return\n");
- }
- goto restart;
- return(0); /* not reached */
-}
-
-void
-sighup(int sig __unused)
-{
-
- printd("hup\n");
- if (hup == 0 && logged_in)
- syslog(LOG_INFO, "%s: got hangup signal", username);
- hup = 1;
-}
-
-void
-sigurg(int sig __unused)
-{
-
- printd("urg\n");
- if (hup == 0 && logged_in)
- syslog(LOG_INFO, "%s: got dead line signal", username);
- hup = 1;
-}
-
-void
-sigterm(int sig __unused)
-{
-
- printd("terminate\n");
- if (terminate == 0 && logged_in)
- syslog(LOG_INFO, "%s: got terminate signal", username);
- terminate = 1;
-}
-
-int
-getline(char *buf, int size, int fd, time_t fintimeout)
-{
- int i;
- int ret;
- fd_set readfds;
- struct timeval tv;
- time_t timeout;
-
- size--;
- for (i = 0; i < size; i++) {
- if (hup || terminate)
- return (0);
- if ((timeout = fintimeout - time(NULL)) <= 0)
- goto tout;
- FD_ZERO(&readfds);
- FD_SET(fd, &readfds);
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
- if ((ret = select(fd + 1, &readfds, NULL, NULL, &tv)) < 0) {
- if (errno != EINTR)
- syslog(LOG_ERR, "%s: getline: select: %m", username);
- } else {
- if (! ret) {
- tout:
- printd("getline: timed out\n");
- return (0);
- }
- if ((ret = read(fd, &buf[i], 1)) == 1) {
- buf[i] &= 0177;
- if (buf[i] == '\r' || buf[i] == '\0') {
- i--;
- continue;
- }
- if (buf[i] != '\n' && buf[i] != ':')
- continue;
- buf[i + 1] = '\0';
- printd("Got %d: %s", i + 1, buf);
- return (i+1);
- }
- if (ret <= 0) {
- if (ret < 0) {
- syslog(LOG_ERR, "%s: getline: read: %m", username);
- } else
- syslog(LOG_ERR, "%s: read returned 0", username);
- buf[i] = '\0';
- printd("returning %d after %d: %s\n", ret, i, buf);
- return (0);
- }
- }
- }
- return (0);
-}
-
-int
-carrier(void)
-{
- int comstate;
-
- if (ioctl(fd, TIOCMGET, &comstate) < 0) {
- syslog(LOG_ERR, "%s: ioctl (%s, TIOCMGET): %m",
- username, devicename);
- down(2);
- }
- return !!(comstate & TIOCM_CD);
-}
-
-void
-down(int code)
-{
- if (fd > -1)
- close(fd);
- if (pfd)
- unlink(pidfile);
- if (uucp_lock && locked)
- uu_unlock(dvname);
- exit(code);
-}
-
-static void
-usage(void)
-{
- (void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
-"usage: startslip [-d] [-b speed] [-s string1 [-s string2 [...]]] [-h] [-l]",
-" [-L] [-A annexname] [-U upscript] [-D downscript]",
-" [-t script_timeout] [-W maxtries] [-w retry_pause]",
-" [-K keepalive] [-O outfill] [-S unit] device user password");
- exit(1);
-}
diff --git a/share/man/man3/pthread.3 b/share/man/man3/pthread.3
index dff3886..5fe2afd 100644
--- a/share/man/man3/pthread.3
+++ b/share/man/man3/pthread.3
@@ -30,7 +30,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 19, 2007
+.Dd April 1, 2009
.Dt PTHREAD 3
.Os
.Sh NAME
@@ -469,15 +469,15 @@ cancellation stack.
.Sh IMPLEMENTATION NOTES
The current
.Fx
-POSIX thread implementation is built in two libraries,
-.Lb libthr ,
-and
-.Lb libkse .
-They contain both thread-safe versions of
+POSIX thread implementation is built into the
+.Lb libthr
+library.
+It contains thread-safe versions of
.Lb libc
functions and the thread functions.
-Threaded applications are linked with one of these libraries.
+Threaded applications are linked with this library.
.Sh SEE ALSO
+.Xr libthr 3 ,
.Xr pthread_atfork 3 ,
.Xr pthread_cancel 3 ,
.Xr pthread_cleanup_pop 3 ,
diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index e5af601..9cc8d7c 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -26,6 +26,7 @@ MAN= aac.4 \
ale.4 \
altq.4 \
amd.4 \
+ ${_amdtemp.4} \
${_amdsmb.4} \
amr.4 \
an.4 \
@@ -94,7 +95,6 @@ MAN= aac.4 \
fd.4 \
fdc.4 \
firewire.4 \
- fla.4 \
fpa.4 \
fwe.4 \
fwip.4 \
@@ -155,7 +155,6 @@ MAN= aac.4 \
ixgbe.4 \
jme.4 \
joy.4 \
- ${_k8temp.4} \
kbdmux.4 \
keyboard.4 \
kld.4 \
@@ -290,7 +289,6 @@ MAN= aac.4 \
ppbus.4 \
ppc.4 \
ppi.4 \
- ppp.4 \
psm.4 \
pst.4 \
pt.4 \
@@ -325,7 +323,6 @@ MAN= aac.4 \
sio.4 \
sis.4 \
sk.4 \
- sl.4 \
smb.4 \
smbus.4 \
smp.4 \
@@ -391,6 +388,7 @@ MAN= aac.4 \
u3g.4 \
uark.4 \
uart.4 \
+ uath.4 \
ubsa.4 \
ubsec.4 \
ubser.4 \
@@ -421,7 +419,6 @@ MAN= aac.4 \
urio.4 \
${_urtw.4} \
usb.4 \
- uscanner.4 \
uslcom.4 \
utopia.4 \
uvisor.4 \
@@ -533,7 +530,6 @@ MLINKS+=pccbb.4 cbb.4
MLINKS+=pcm.4 snd.4 \
pcm.4 sound.4
MLINKS+=pcn.4 if_pcn.4
-MLINKS+=ppp.4 if_ppp.4
MLINKS+=ral.4 if_ral.4
MLINKS+=re.4 if_re.4
MLINKS+=rl.4 if_rl.4
@@ -546,7 +542,6 @@ MLINKS+=scsi.4 CAM.4 \
MLINKS+=sf.4 if_sf.4
MLINKS+=sis.4 if_sis.4
MLINKS+=sk.4 if_sk.4
-MLINKS+=sl.4 if_sl.4
MLINKS+=smp.4 SMP.4
MLINKS+=sn.4 if_sn.4
MLINKS+=snd_envy24.4 snd_ak452x.4
@@ -567,6 +562,7 @@ MLINKS+=tun.4 if_tun.4
MLINKS+=tx.4 if_tx.4
MLINKS+=txp.4 if_txp.4
MLINKS+=u3g.4 u3gstub.4
+MLINKS+=uath.4 if_uath.4
MLINKS+=udav.4 if_udav.4
MLINKS+=upgt.4 if_upgt.4
MLINKS+=ural.4 if_ural.4
@@ -593,6 +589,7 @@ _acpi_panasonic.4=acpi_panasonic.4
_acpi_sony.4= acpi_sony.4
_acpi_toshiba.4=acpi_toshiba.4
_amdsmb.4= amdsmb.4
+_amdtemp.4= amdtemp.4
_asmc.4= asmc.4
_coretemp.4= coretemp.4
_cpuctl.4= cpuctl.4
@@ -610,7 +607,6 @@ _ipmi.4= ipmi.4
_io.4= io.4
_linux.4= linux.4
_ndis.4= ndis.4
-_k8temp.4= k8temp.4
_nfe.4= nfe.4
_nfsmb.4= nfsmb.4
_nve.4= nve.4
diff --git a/share/man/man4/k8temp.4 b/share/man/man4/amdtemp.4
index dd378ef..fb6fc77 100644
--- a/share/man/man4/k8temp.4
+++ b/share/man/man4/amdtemp.4
@@ -26,39 +26,47 @@
.\" $FreeBSD$
.\"
.Dd April 8, 2008
-.Dt K8TEMP 4
+.Dt AMDTEMP 4
.Os
.Sh NAME
-.Nm k8temp
-.Nd device driver for AMD K8 on-die digital thermal sensor
+.Nm amdtemp
+.Nd device driver for AMD K8, K10 and K11 on-die digital thermal sensor
.Sh SYNOPSIS
To compile this driver into the kernel,
place the following line in your
kernel configuration file:
.Bd -ragged -offset indent
-.Cd "device k8temp"
+.Cd "device amdtemp"
.Ed
.Pp
Alternatively, to load the driver as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
-k8temp_load="YES"
+amdtemp_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
driver provides support for the on-die digital thermal sensor present
-in AMD K8 processors.
+in AMD K8, K10 and K11 processors.
.Pp
-The
+For the K8 family, the
.Nm
driver reports each cores' temperature through a sysctl node in the
corresponding CPU devices's sysctl tree, named
-.Va dev.k8temp.%d.sensor{0,1}.core{0,1} .
+.Va dev.amdtemp.%d.sensor{0,1}.core{0,1} .
+The driver also creates
.Va dev.cpu.%d.temperature
-is also created and it displays the maximum temperature of the two sensors
+displaying the maximum temperature of the two sensors
located in each CPU core.
+.Pp
+For the K10 and K11 families, the driver creates
+.Va dev.cpu.%d.temperature
+with the temperature of each core.
+.Sh BUGS
+AMD K9 is not supported because temperature reporting has been replaced
+by Maltese.
.Sh SEE ALSO
.Xr sysctl 8
.Sh HISTORY
@@ -69,3 +77,4 @@ driver first appeared in
.Sh AUTHORS
.An
.An Rui Paulo Aq rpaulo@FreeBSD.org
+.An Norikatsu Shigemura Aq nork@FreeBSD.org
diff --git a/share/man/man4/ath.4 b/share/man/man4/ath.4
index 7719b0e..5b7b356 100644
--- a/share/man/man4/ath.4
+++ b/share/man/man4/ath.4
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"/
-.Dd January 13, 2009
+.Dd March 25, 2009
.Dt ATH 4
.Os
.Sh NAME
@@ -59,8 +59,6 @@ driver provides support for wireless network adapters based on
the Atheros AR5210, AR5211, AR5212, and AR5416 programming APIs.
These APIs are used by a wide variety of chips; most all chips with
a PCI and/or CardBus interface are supported.
-Chip-specific support is provided by the Atheros Hardware Access Layer
-(HAL).
.Pp
Supported features include 802.11 and 802.3 frames, power management, BSS,
IBSS, TDMA, and host-based access point operation modes.
@@ -129,7 +127,7 @@ The driver also support
.Cm tdma
operation when compiled with
.Cd "options AH_SUPPORT_TDMA"
-(and the wlan module is build with
+(and the wlan module is built with
.Cd "options IEEE80211_SUPPORT_TDMA"
to enable the associated 802.11 support).
For more information on configuring this device, see
@@ -142,10 +140,8 @@ Wireless cards in Cardbus slots may be inserted and ejected on the fly.
.Sh HARDWARE
The
.Nm
-driver supports most Atheros Cardbus or PCI cards,
+driver supports all Atheros Cardbus and PCI cards,
except those that are based on the AR5005VL chipset.
-More recent parts may require a hal that is not part of
-.Fb .
.Pp
A list of cards that are supported can be found at
.Pa http://customerproducts.atheros.com/customerproducts/default.asp .
@@ -252,13 +248,6 @@ This should not happen.
The Atheros Hardware Access Layer was unable to reset the hardware
when switching channels during scanning.
This should not happen.
-.It "ath%d: unable to allocate channel table"
-The driver was unable to allocate memory for the table used to hold
-the set of available channels.
-.It "ath%d: unable to collect channel list from hal"
-A problem occurred while querying the HAL to find the set of available
-channels for the device.
-This should not happen.
.It "ath%d: failed to enable memory mapping"
The driver was unable to enable memory-mapped I/O to the PCI device registers.
This should not happen.
@@ -294,15 +283,6 @@ The
device driver first appeared in
.Fx 5.2 .
.Sh CAVEATS
-Different regulatory domains have different default channels for adhoc
-mode.
-See
-.Xr ifconfig 8
-for information on how to change the channel.
-Different regulatory domains may not be able to communicate with each
-other with 802.11a as different regulatory domains do not necessarily
-have overlapping channels.
-.Pp
Revision A1 of the D-LINK DWL-G520 and DWL-G650 are based on an
Intersil PrismGT chip and are not supported by this driver.
.Sh BUGS
diff --git a/share/man/man4/ath_hal.4 b/share/man/man4/ath_hal.4
index 36b189a..f023906 100644
--- a/share/man/man4/ath_hal.4
+++ b/share/man/man4/ath_hal.4
@@ -1,5 +1,5 @@
.\"-
-.\" Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
+.\" Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
.\" All rights reserved.
.\""
.\" Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"/
-.Dd November 30, 2008
+.Dd March 25, 2009
.Dt ATH_HAL 4
.Os
.Sh NAME
@@ -52,10 +52,13 @@ or
.\".Cd "device ath_rf2136"
.\".Cd "device ath_rf2137"
.Cd "device ath_ar9160"
+.Cd "device ath_ar9280"
.Cd "options AH_SUPPORT_AR5416"
.Sh DESCRIPTION
The hal provides hardware support for wireless network adapters based on
-the Atheros AR5210, AR5211, AR5212, AR5416, and AR9160 chips.
+the Atheros AR5210, AR5211, AR5212, AR5213, AR2413, AR2417, AR2425,
+AR5413, AR5416, AR5418, AR5424, AR9160, and AR9280 chips (and companion
+RF/baseband parts).
This code is part of the
.Xr ath 4
driver but configured separately to allow fine-grained control
@@ -63,7 +66,8 @@ over the set of chips supported.
Selecting
.Nm
enables support for all PCI and Cardbus devices.
-Note this includes AR5416 devices and must be accompanied by the
+Note this includes AR5416, AR9160, and AR9280 devices and
+must be accompanied by the
AH_SUPPORT_AR5416
option to enable the extended hardware descriptor format used by
AR5416 and later devices.
diff --git a/share/man/man4/bce.4 b/share/man/man4/bce.4
index 93e3bc0..41c9fe9 100644
--- a/share/man/man4/bce.4
+++ b/share/man/man4/bce.4
@@ -28,7 +28,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 15, 2009
+.Dd April 7, 2009
.Dt BCE 4
.Os
.Sh NAME
@@ -109,8 +109,18 @@ option can also be used to select either
or
.Cm half-duplex
modes.
-.It Cm 1000baseTX
-Set 1000baseTX operation over twisted pair.
+.It Cm 1000baseSX
+Sets 1000Mbps operation.
+Only
+.Cm full-duplex
+mode is supported at this speed.
+.It Cm 1000baseT
+Set 1000baseT operation over twisted pair.
+Only
+.Cm full-duplex
+mode is supported.
+.It Cm 2500BaseSX
+Set 2500Mbps operation.
Only
.Cm full-duplex
mode is supported.
diff --git a/share/man/man4/ed.4 b/share/man/man4/ed.4
index 49920e2..8988549 100644
--- a/share/man/man4/ed.4
+++ b/share/man/man4/ed.4
@@ -30,7 +30,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 27, 2008
+.Dd April 9, 2009
.Dt ED 4
.Os
.Sh NAME
@@ -66,12 +66,6 @@ Tamarack's TC5299J chips all support internal or external MII/PHY combinations.
Realtek's PCI and ISA RTL80x9-based cards are also supported.
For these chipsets, autonegotiation and status reporting are supported.
.Pp
-The
-.Nm
-driver uses a unique multi-buffering mechanism to achieve high transmit performance.
-When using 16bit ISA cards, as high as 97% of the theoretical maximum performance of
-the IEEE 802.3 CSMA Ethernet is possible.
-.Pp
In addition to the standard port and IRQ specifications, the
.Nm
driver also supports a number of
@@ -183,7 +177,7 @@ Danpex EN-6200P2
.It
D-Link DE-298, DE-298P (flags 0x500000) (PC-98)
.It
-D-Link DE-650/660
+D-Link DE-660, DE-660+
.It
D-Link IC-CARD/IC-CARD+ Ethernet
.It
@@ -299,6 +293,8 @@ TDK DFL5610WS Ethernet/Modem PC Card
.It
Telecom Device SuperSocket RE450T
.It
+Toshiba LANCT00A PC Card
+.It
VIA VT86C926
.It
Winbond W89C940
@@ -307,6 +303,17 @@ Winbond W89C940F
.El
.Pp
C-Bus, ISA, PCI and PC Card devices are supported.
+.Pp
+The
+.Nm
+driver does not support the following Ethernet NICs:
+.Pp
+.Bl -bullet -compact
+.It
+Mitsubishi LAN Adapter B8895
+.It
+D-Link DE-650
+.El
.Sh DIAGNOSTICS
.Bl -diag
.It "ed%d: failed to clear shared memory at %x - check configuration."
@@ -362,6 +369,8 @@ The device is using a different I/O port than the driver knows about.
Attempts to get the MAC address failed.
.It "ed%d: Missing mii!"
Probing for an MII bus has failed.
+This indicates a coding error in the PC Card attachment, because a PHY
+is required for the chips that generate this error message.
.El
.Sh CAVEATS
Early revision DS8390 chips have problems.
@@ -382,14 +391,17 @@ on the 16bit cards.
This can lead to ring-buffer overruns resulting in
dropped packets during heavy network traffic.
.Pp
-16bit Compex cards identify themselves as being 8bit.
-While these cards will
-work in 8bit mode, much higher performance can be achieved by specifying
-.Cd "flags 0x04"
-(force 16bit mode) in your kernel config file.
-In addition, you should also specify
-.Cd "iosiz 16384"
-to take advantage of the extra 8K of shared memory that 16bit mode provides.
+The Mitsubishi B8895 PC Card uses a DP83902, but its ASIC part is
+undocumented.
+Neither the NE2000 nor the WD83x0 drivers work with this card.
+.Pp
+The D-LINK DE-650 has funky resources that differ from other cards and could
+likely be made to work.
+Its shared memory interface conflicts with other resources on many
+laptops and cannot be moved.
+The pccard(4) layer does not support activating a CFE that it fails to
+allocate all the resources for.
+.Pp
.Sh SEE ALSO
.Xr altq 4 ,
.Xr arp 4 ,
@@ -416,7 +428,9 @@ packets are received.
As a result, it may throw out some good packets which
have been received but not yet transferred from the card to main memory.
.Pp
-The
-.Nm
+The
+.Nm
+driver is slow by today's standards.
+.Pp
PC Card attachment supports the D-Link DMF650TX LAN/Modem card's Ethernet
port only at this time.
diff --git a/share/man/man4/fla.4 b/share/man/man4/fla.4
deleted file mode 100644
index 1a02deb..0000000
--- a/share/man/man4/fla.4
+++ /dev/null
@@ -1,59 +0,0 @@
-.\" Copyright (c) 2003 David E. O'Brien
-.\" 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
-.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
-.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
-.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-.\" POSSIBILITY OF SUCH DAMAGE.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd July 13, 2003
-.Dt FLA 4
-.Os
-.Sh NAME
-.Nm fla
-.Nd M-systems DiskOnChip
-.Sh SYNOPSIS
-.Cd "device fla"
-.Sh DESCRIPTION
-DiskOnChip is a family of high-performance,
-single-chip flash disks available in a wide range of capacities.
-The
-.Nm
-driver supports the following in the family of M-systems DiskOnChip:
-.Pp
-.Bl -bullet -compact
-.It
-DiskOnChip2000 (8, 12, 24, 32, 40, 72, 144 MB)
-.It
-DiskOnChipMillenium (8 MB)
-.It
-DiskOnChipMillenium TSOP (8 MB)
-.El
-.Sh SEE ALSO
-.Xr config 8
-.Pp
-.Pa http://www.m-sys.com
-.Sh HISTORY
-The
-.Nm
-driver
-appeared in
-.Fx 3.3 .
diff --git a/share/man/man4/lagg.4 b/share/man/man4/lagg.4
index e2ee3e9..6d43c42 100644
--- a/share/man/man4/lagg.4
+++ b/share/man/man4/lagg.4
@@ -16,7 +16,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 17, 2007
+.Dd March 29, 2009
.Dt LAGG 4
.Os
.Sh NAME
@@ -142,10 +142,14 @@ Whenever the wired master interface is unplugged, the wireless failover
device will be used:
.Bd -literal -offset indent
# ifconfig em0 up
-# ifconfig ath0 nwid my_net up
-# ifconfig lagg0 laggproto failover laggport em0 laggport ath0 \e
+# ifconfig ath0 ether 00:11:22:33:44:55
+# ifconfig create wlan0 wlandev ath0 ssid my_net up
+# ifconfig lagg0 laggproto failover laggport em0 laggport wlan0 \e
192.168.1.1 netmask 255.255.255.0
.Ed
+.Pp
+(Note the mac address of the wireless device is forced to match the wired
+device as a workaround.)
.Sh SEE ALSO
.Xr ng_fec 4 ,
.Xr ng_one2many 4 ,
@@ -172,6 +176,3 @@ There is no way to configure LACP administrative variables, including system
and port priorities.
The current implementation always performs active-mode LACP and uses 0x8000 as
system and port priorities.
-.Pp
-WPA security does not currently work correctly with a wireless interface added
-to the lagg port.
diff --git a/share/man/man4/lo.4 b/share/man/man4/lo.4
index 86dd47e..12bf792 100644
--- a/share/man/man4/lo.4
+++ b/share/man/man4/lo.4
@@ -1,5 +1,7 @@
.\" Copyright (c) 1983, 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
+.\" The Regents of the University of California.
+.\" Copyright (c) 2009 Robert N. M. Watson
+.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
@@ -9,10 +11,6 @@
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
@@ -32,7 +30,7 @@
.\" @(#)lo.4 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd June 5, 1993
+.Dd March 15, 2009
.Dt LO 4
.Os
.Sh NAME
@@ -58,6 +56,20 @@ The loopback should
.Em never
be configured first unless no hardware
interfaces exist.
+.Pp
+If the transmit checksum offload capability flag is enabled on a loopback
+interface, checksums will not be generated by IP, UDP, or TCP for packets
+sent on the interface.
+.Pp
+If the receive checksum offload capability flag is enabled on a loopback
+interface, checksums will not be validated by IP, UDP, or TCP for packets
+received on the interface.
+.Pp
+By default, both receive and transmit checksum flags will be enabled, in
+order to avoid the overhead of checksumming for local communication where
+data corruption is unlikely.
+If transmit checksum generation is disabled, then validation should also be
+disabled in order to avoid packets being dropped due to invalid checksums.
.Sh DIAGNOSTICS
.Bl -diag
.It lo%d: can't handle af%d.
@@ -74,8 +86,5 @@ The
.Nm
device appeared in
.Bx 4.2 .
-.Sh BUGS
-Previous versions of the system enabled the loopback interface
-automatically, using a nonstandard Internet address (127.1).
-Use of that address is now discouraged; a reserved host address
-for the local network should be used instead.
+The current checksum generation and validation avoidance policy appeared in
+.Fx 8.0 .
diff --git a/share/man/man4/malo.4 b/share/man/man4/malo.4
index 8d1ab1e..60c9e3d 100644
--- a/share/man/man4/malo.4
+++ b/share/man/man4/malo.4
@@ -31,7 +31,7 @@
.\"
.\" $FreeBSD$
.\"/
-.Dd April 13, 2008
+.Dd March 26, 2009
.Dt MALO 4
.Os
.Sh NAME
@@ -121,4 +121,4 @@ ifconfig wlan create wlandev malo0 ssid my_net \e
The
.Nm
device driver first appeared in
-.Fx 8.0 .
+.Fx 7.1 .
diff --git a/share/man/man4/man4.i386/fe.4 b/share/man/man4/man4.i386/fe.4
index bacee58..22bbf2a 100644
--- a/share/man/man4/man4.i386/fe.4
+++ b/share/man/man4/man4.i386/fe.4
@@ -149,7 +149,7 @@ Allied Telesis RE1000, RE1000Plus, ME1500 (110-pin)
.It
CONTEC C-NET(98)P2, C-NET (9N)E (110-pin), C-NET(9N)C (ExtCard)
.It
-CONTEC C-NET(PC)C PCMCIA Ethernet
+CONTEC C-NET(PC)C PC Card Ethernet
.It
Eagle Tech NE200T
.It
@@ -159,11 +159,11 @@ Fujitsu FMV-J182, FMV-J182A
.It
Fujitsu MB86960A, MB86965A
.It
-Fujitsu MBH10303, MBH10302 Ethernet PCMCIA
+Fujitsu MBH10303, MBH10302 PC Card Ethernet
.It
Fujitsu Towa LA501 Ethernet
.It
-HITACHI HT-4840-11
+HITACHI HT-4840-11 PC Card Ethernet
.It
NextCom J Link NC5310
.It
@@ -173,7 +173,7 @@ RATOC REX-9880/9881/9882/9883
.It
TDK LAC-98012, LAC-98013, LAC-98025, LAC-9N011 (110-pin)
.It
-TDK LAK-CD021, LAK-CD021A, LAK-CD021BX
+TDK LAK-CD011, LAK-CD021, LAK-CD021A, LAK-CD021BX
.It
Ungermann-Bass Access/PC N98C+(PC85152, PC85142), Access/NOTE
N98(PC86132) (110-pin)
diff --git a/share/man/man4/man4.powerpc/pmu.4 b/share/man/man4/man4.powerpc/pmu.4
index 4a876bb..872f8ac 100644
--- a/share/man/man4/man4.powerpc/pmu.4
+++ b/share/man/man4/man4.powerpc/pmu.4
@@ -43,15 +43,14 @@ kernel configuration file:
The
.Nm
driver provides support for the Power Management Unit (PMU) found in Apple
-Core99 hardware. This includes late G3 laptops, all G4 machines, early G5
+Core99 hardware.
+This includes late G3 laptops, all G4 machines, early G5
desktops and all G5 XServes.
-.Ed
.Pp
The Apple PMU controller is a multi-purpose ASIC that provides power
management and thermal control, as well as an ADB bus for the internal
keyboard and mouse on laptops.
.Sh HARDWARE
-.Pp
Chips supported by the
.Nm
driver include:
@@ -62,13 +61,13 @@ Apple KeyLargo PMU
.It
Apple K2-KeyLargo PMU
.El
-.Pp
.Sh SYSCTL VARIABLES
The
.Nm
driver provides power management services in addition to an
.Xr adb 4
-interface. The following sysctls can be used to control the
+interface.
+The following sysctls can be used to control the
power management behavior and to examine current system power and
thermal conditions.
.Bl -tag -width indent
@@ -84,7 +83,8 @@ The current battery charge, in milliamp hours.
.It Va dev.pmu.%d.batteries.%d.maxcharge
The battery's self-reported maximum charge, in milliamp hours.
.It Va dev.pmu.%d.batteries.%d.rate
-The current into the battery, in milliamps. While the battery is discharging,
+The current into the battery, in milliamps.
+While the battery is discharging,
this will be negative.
.It Va dev.pmu.%d.batteries.%d.voltage
Battery voltage, in millivolts.
@@ -92,9 +92,10 @@ Battery voltage, in millivolts.
Estimated time until full battery charge (or discharge), in minutes.
.It Va dev.pmu.%d.batteries.%d.life
Current fraction of the battery's maximum charge, in percent.
+.El
.Sh SEE ALSO
-.Xr adb 4 ,
-.Xr acpi 4
+.Xr acpi 4 ,
+.Xr adb 4
.Sh HISTORY
The
.Nm
@@ -111,4 +112,4 @@ driver was written by
.Aq macallan@NetBSD.org
and ported to FreeBSD by
.An Nathan Whitehorn
-.Aq nwhitehorn@freebsd.org .
+.Aq nwhitehorn@FreeBSD.org .
diff --git a/share/man/man4/pccbb.4 b/share/man/man4/pccbb.4
index 27ef584..d8d955e 100644
--- a/share/man/man4/pccbb.4
+++ b/share/man/man4/pccbb.4
@@ -34,6 +34,7 @@
.Cd device cbb
.Cd device pccard
.Cd device cardbus
+.Cd device exca
.Sh DESCRIPTION
The
.Nm
@@ -178,4 +179,5 @@ debugging problems with the bridge chipset.
.El
.Sh SEE ALSO
.Xr cardbus 4 ,
-.Xr pccard 4
+.Xr pccard 4 ,
+.Xr exca 4
diff --git a/share/man/man4/ppp.4 b/share/man/man4/ppp.4
deleted file mode 100644
index 4e9ad61..0000000
--- a/share/man/man4/ppp.4
+++ /dev/null
@@ -1,84 +0,0 @@
-.\" $NetBSD: ppp.4,v 1.1 1996/08/10 21:26:12 explorer Exp $
-.\"
-.\" Copyright (c) 1983, 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" From: @(#)lo.4 8.1 (Berkeley) 6/5/93
-.\" $FreeBSD$
-.\"
-.Dd August 10, 1996
-.Dt PPP 4
-.Os
-.Sh NAME
-.Nm ppp
-.Nd point to point protocol network interface
-.Sh SYNOPSIS
-.Cd "device ppp"
-.Sh DESCRIPTION
-The
-.Nm
-interface allows serial lines to be used as network interfaces using the
-.Em point-to-point
-protocol.
-The
-.Nm
-interface can use various types of compression and has many features over
-the
-.Xr sl 4
-protocol.
-.Pp
-Each
-.Nm
-interface is created at runtime using interface cloning.
-This is most easily done with the
-.Xr ifconfig 8
-.Cm create
-command or using the
-.Va cloned_interfaces
-variable in
-.Xr rc.conf 5 .
-.Sh DIAGNOSTICS
-.Bl -diag
-.It ppp%d: af%d not supported.
-The interface was handed
-a message with addresses formatted in an unsuitable address
-family; the packet was dropped.
-.El
-.Sh SEE ALSO
-.Xr inet 4 ,
-.Xr intro 4 ,
-.Xr sl 4 ,
-.Xr pppd 8 ,
-.Xr pppstats 8
-.Sh BUGS
-Currently, only the
-.Xr ip 4
-protocol is supported.
diff --git a/share/man/man4/sl.4 b/share/man/man4/sl.4
deleted file mode 100644
index a861b4e..0000000
--- a/share/man/man4/sl.4
+++ /dev/null
@@ -1,82 +0,0 @@
-.\" $NetBSD: sl.4,v 1.1 1996/08/10 21:26:14 explorer Exp $
-.\"
-.\" Copyright (c) 1983, 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" From: @(#)lo.4 8.1 (Berkeley) 6/5/93
-.\" $FreeBSD$
-.\"
-.Dd August 10, 1996
-.Dt SL 4
-.Os
-.Sh NAME
-.Nm sl
-.Nd slip network interface
-.Sh SYNOPSIS
-.Cd "device sl" Op Ar count
-.Sh DESCRIPTION
-The
-.Nm
-interface allows serial lines to be used as network interfaces using the
-.Em slip
-protocol.
-The
-.Nm
-interface can use Van Jacobson TCP header compression and ICMP filtering.
-This is arranged by using the various link-level flags to the
-.Xr ifconfig 8
-command:
-.Pp
-.Bl -tag -width LINK0X -compact
-.It Em link0
-Enable VJ header compression.
-.It Em link1
-Suppress ICMP traffic.
-.It Em link2
-Enable VJ header compression autodetection.
-This will turn on the
-.Em link0
-flag as soon as the first VJ-compressed packet has been seen by
-the driver.
-.El
-.Sh DIAGNOSTICS
-.Bl -diag
-.It sl%d: af%d not supported.
-The interface was handed
-a message with addresses formatted in an unsuitable address
-family; the packet was dropped.
-.El
-.Sh SEE ALSO
-.Xr inet 4 ,
-.Xr intro 4 ,
-.Xr slattach 8 ,
-.Xr sliplogin 8 ,
-.Xr slstat 8
diff --git a/share/man/man4/textdump.4 b/share/man/man4/textdump.4
index d166b31..65c04ed 100644
--- a/share/man/man4/textdump.4
+++ b/share/man/man4/textdump.4
@@ -98,7 +98,7 @@ sysctl.
.El
.Pp
Kernel textdumps may be extracted using
-.Xr bsdtar 1 .
+.Xr tar 1 .
.Sh CONFIGURATION
The
.Nm
@@ -153,7 +153,7 @@ These scripts may also be configured using the
.Xr ddb 8
utility.
.Sh SEE ALSO
-.Xr bsdtar 1 ,
+.Xr tar 1 ,
.Xr ddb 4 ,
.Xr tar 5 ,
.Xr ddb 8 ,
diff --git a/share/man/man4/uath.4 b/share/man/man4/uath.4
new file mode 100644
index 0000000..52a5fb6
--- /dev/null
+++ b/share/man/man4/uath.4
@@ -0,0 +1,189 @@
+.\"
+.\" Copyright (c) 2006
+.\" Damien Bergamini <damien.bergamini@free.fr>
+.\"
+.\" 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 7, 2009
+.Dt UATH 4
+.Os
+.Sh NAME
+.Nm uath
+.Nd Atheros USB IEEE 802.11a/b/g wireless network device
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd "device ehci"
+.Cd "device uhci"
+.Cd "device ohci"
+.Cd "device usb"
+.Cd "device uath"
+.Cd "device wlan"
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+if_uath_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver supports USB 2.0 wireless network devices based on Atheros
+Communications fifth generation AR5005UG and AR5005UX chipsets.
+.Pp
+The AR5005UG chipset is made of an AR5523 multiprotocol MAC/baseband processor
+and an AR2112 Radio-on-a-Chip that can operate between 2300 and 2500 MHz
+(802.11b/g).
+.Pp
+The AR5005UX chipset is made of an AR5523 multiprotocol MAC/baseband processor
+and an AR5112 dual band Radio-on-a-Chip that can operate between 2300 and
+2500 MHz (802.11b/g) or 4900 and 5850 MHz (802.11a).
+.Pp
+The AR5005UG and AR5005UX chipsets both have an integrated 32-bit MIPS
+R4000-class processor that runs a firmware and manages, among other things,
+the automatic control of the transmit rate and the calibration of the radio.
+.Pp
+.Nm
+supports
+.Cm station ,
+and
+.Cm monitor
+mode operation.
+Only one virtual interface may be configured at any time.
+For more information on configuring this device, see
+.Xr ifconfig 8 .
+.Sh FIRMWARE
+.Nm
+requires firmware that is downloaded to the device.
+This is normally done by the
+.Xr uathload 8
+utility that is launched by
+.Xr devd 8
+when the device is inserted.
+.Xr uathload
+includes the firmware in the binary program.
+This firmware is licensed for general use and is included in the base system.
+.Sh HARDWARE
+The
+.Nm
+driver should work with the following adapters:
+.Pp
+.Bl -column -compact "TRENDware International TEW-444UB" "AR5005UX" -offset 6n
+.It Em "Adapter Chipset"
+.\".It Belkin F6D3050 AR5005UX
+.It Li "Compex WLU108AG" Ta AR5005UX
+.It Li "Compex WLU108G" Ta AR5005UG
+.\".It Li "D-Link DWL-AG132" Ta AR5005UX
+.It Li "D-Link DWL-G132" Ta AR5005UG
+.\".It Li "Edimax EW-7315Ug" Ta AR5005UG (AR2414???)
+.\".It Li "Lancom USB-54ag" Ta AR5005UX
+.\".It Li "NEC WL54TU" Ta AR5005UX
+.It Li "IODATA WN-G54/US" Ta AR5005UG
+.It Li "MELCO WLI-U2-KAMG54" Ta AR5005UX
+.It Li "Netgear WG111T" Ta AR5005UG
+.It Li "Netgear WG111U" Ta AR5005UX
+.It Li "Netgear WPN111" Ta AR5005UG
+.It Li "Olitec 000544" Ta AR5005UG
+.It Li "PLANET WDL-U357" Ta AR5005UX
+.\".It Li "Senao WUB-8004" Ta AR5005UX
+.It Li "Siemens Gigaset 108" Ta AR5005UG
+.It Li "SMC SMCWUSBT-G" Ta AR5005UG
+.It Li "SMC SMCWUSBT-G2" Ta AR5005UG
+.\".It Li "SparkLAN WL-685GS" Ta AR5005UG
+.It Li "SparkLAN WL-785A" Ta AR5005UX
+.It Li "TP-Link TL-WN620G" Ta AR5005UG
+.It Li "TRENDware International TEW-444UB" Ta AR5005UG
+.It Li "TRENDware International TEW-504UB" Ta AR5005UX
+.It Li "Unex Technology UR054ag" Ta AR5005UX
+.\".It Li "Wistron NeWeb DCUA-81" Ta AR5005UX
+.\".It Li "Wistron NeWeb DRUA-81" Ta AR5005UG
+.\".It Li "Wistron NeWeb DRUA-82" Ta AR5005UX
+.\".It Li "ZyXEL G-200 v2" Ta AR5005UG
+.It Li "ZyXEL XtremeMIMO M-202" Ta AR5005UX
+.El
+.Pp
+An up to date list can be found at
+.Pa http://customerproducts.atheros.com/customerproducts/default.asp .
+.Sh EXAMPLES
+Join an existing BSS network (i.e., connect to an access point):
+.Pp
+.Bd -literal -offset indent
+ifconfig wlan create wlandev uath0 inet 192.168.0.20 \e
+ netmask 0xffffff00
+.Ed
+.Pp
+Join a specific BSS network with network name
+.Dq Li my_net :
+.Pp
+.Dl "ifconfig wlan create wlandev uath0 ssid my_net up"
+.Pp
+Join a specific BSS network with 64-bit WEP encryption:
+.Bd -literal -offset indent
+ifconfig wlan create wlandev uath0 ssid my_net \e
+ wepmode on wepkey 0x1234567890 weptxkey 1 up
+.Ed
+.Pp
+Join a specific BSS network with 128-bit WEP encryption:
+.Bd -literal -offset indent
+ifconfig wlan create wlandev uath0 wlanmode adhoc ssid my_net \e
+ wepmode on wepkey 0x01020304050607080910111213 weptxkey 1
+.Ed
+.Sh DIAGNOSTICS
+.Bl -diag
+.It "uath%d: could not send command (error=%s)"
+An attempt to send a command to the firmware failed.
+.It "uath%d: timeout waiting for command reply"
+A read command was sent to the firmware but the firmware failed to reply in
+time.
+.It "uath%d: device timeout"
+A frame dispatched to the hardware for transmission did not complete in time.
+The driver will reset the hardware.
+This should not happen.
+.El
+.Sh SEE ALSO
+.Xr netintro 4 ,
+.Xr usb 4 ,
+.Xr wlan 4 ,
+.Xr wlan_ccmp 4 ,
+.Xr wlan_tkip 4 ,
+.Xr wlan_wep 4 ,
+.Xr devd 8 ,
+.Xr ifconfig 8 ,
+.Xr uathload 8 ,
+.Xr wpa_supplicant 8
+.Sh HISTORY
+The
+.Nm
+driver first appeared in
+.Ox 4.0 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Nm
+driver was written by
+.An Weongyo Jeong Aq weongyo@freebsd.org
+and
+.An Sam Leffler Aq sam@freebsd.org .
+It is distantly related to a driver written by
+.An Damien Bergamini Aq damien@openbsd.org .
+.Sh CAVEATS
+Atheros proprietary 108 Mbps mode (aka Super AG mode) is not supported.
+.Pp
+Dual-band adapters are presently not working;
+to workaround, restriction operation to 2.4GHz channels.
diff --git a/share/man/man4/usb.4 b/share/man/man4/usb.4
index f9af2f4..665ab57 100644
--- a/share/man/man4/usb.4
+++ b/share/man/man4/usb.4
@@ -422,7 +422,6 @@ specifications can be found at:
.Xr ums 4 ,
.Xr uplcom 4 ,
.Xr urio 4 ,
-.Xr uscanner 4 ,
.Xr uvscom 4 ,
.Xr usbdevs 8
.Sh HISTORY
diff --git a/share/man/man4/uscanner.4 b/share/man/man4/uscanner.4
deleted file mode 100644
index c135732..0000000
--- a/share/man/man4/uscanner.4
+++ /dev/null
@@ -1,164 +0,0 @@
-.\" Copyright (c) 2000, Jeroen Ruigrok van der Werven <asmodai@FreeBSD.org>
-.\" All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by Bill Paul.
-.\" 4. Neither the name of the author nor the names of any co-contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY NICK HIBMA 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 NICK HIBMA OR THE VOICES IN HIS HEAD
-.\" 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 December 23, 2008
-.Dt USCANNER 4
-.Os
-.Sh NAME
-.Nm uscanner
-.Nd USB Scanners
-.Sh SYNOPSIS
-To compile this driver into the kernel,
-place the following line in your
-kernel configuration file:
-.Bd -ragged -offset indent
-.Cd "device uscanner"
-.Ed
-.Pp
-Alternatively, to load the driver as a
-module at boot time, place the following line in
-.Xr loader.conf 5 :
-.Bd -literal -offset indent
-uscanner_load="YES"
-.Ed
-.Sh DESCRIPTION
-The
-.Nm
-driver provides support for scanners that attach to the USB port.
-For each scanner attached it will provide an entry like
-.Pa /dev/uscanner0
-in
-.Pa /dev .
-User-space programs, e.g. SANE,
-can in turn use the device entry throgh a suitable
-backend driver (see
-.Nm ports/graphics/sane-backends )
-to control the scanner itself.
-.Pp
-In case of multifunction USB devices (e.g. scanner/printer/card reader),
-this driver only attaches to the USB interface that controls
-the scanner; for the other USB interface you need separate drivers, e.g.
-.Nm ulpt ,
-.Nm umass ,
-and so on.
-.Pp
-.Nm usb
-and one of
-.Nm uhci
-or
-.Nm ohci
-must be configured in the kernel as well.
-.Sh HARDWARE
-Because there is no standard device class for USB scanners, this driver
-will only recognise devices whose USB IDs are explicitly listed in the
-table in the driver itself.
-.Pp
-The following devices are supported to date:
-.Pp
-.Bl -bullet -compact
-.It
-Acer Acerscan: 320U, 620U, 640U, 640BT, 1240U, C310U;
-.It
-AGFA SnapScan: 1212U, 1236U, e20, e25, e26, e40, e50, e52, SnapScan Touch;
-.It
-Avision 1200U
-.It
-Canon CanoScan: D660U, N656U, N676U, N1220U, LIDE 20, LIDE 25, LIDE 30;
-.It
-Epson Perfection: 610, 636U / 636Photo, 640U, 1200U / 1200Photo,
-1240U / 1240Photo, 1250, 1260, 1270,
-1600, 1640SU, 1650, 1660, 1670,
-2480,
-3200, 3500, 3590,
-4200, 4990;
-.It
-Epson: GT-8400UF, GT-9300UF, GT-9700F;
-.It
-Epson Stylus: Photo RX425, CX3650, DX-5000, DX-5050, CX5400, DX-6000,
-DX-6050, DX-8400/50 (and possibly more in the CX-5000 and DX-3800..DX-7000
-family);
-.It
-Hewlett Packard: Photosmart S20
-.It
-Hewlett Packard Scanjet: 2200C,
-3300C, 3400CSE,
-4100C, 4200C, 4300C,
-4470C,
-5200C, 5300C, 5400C,
-6200C, 6300C,
-8200C, 8250C, 8290C;
-.It
-KYE ColorPage Vivid-Pro
-.It
-Microtek Phantom: 336CX, C6;
-.It
-Microtek ScanMaker: V6UL V6USL, X6U;
-.It
-Minolta 5400
-.It
-Mustek: 600 CU, 1200 CU, 1200 UB, 1200 USB;
-.It
-Mustek BearPaw: 1200F, 1200TA;
-.It
-NatSemi BearPaw 1200
-.It
-Nikon CoolScan LS40 ED
-.It
-Primax 6200
-.It
-Primax Colorado: 1200u, 600u, USB 19200, USB 9600;
-.It
-Primax: G2-200, G2-300, G2-600, G2600, G2E-300, G2E-3002, G2E-600, G2E600,
-G2X-300,
-G600,
-ReadyScan 636i;
-.It
-Ultima 1200 UB Plus
-.It
-UMAX Astra: 1220U, 1236U, 2000U, 2100U, 2200U, 3400;
-.It
-Visioneer OneTouch: 3000, 5300, 7600, 6100, 6200, 8100, 8600;
-.El
-.Sh SEE ALSO
-.Xr ohci 4 ,
-.Xr uhci 4 ,
-.Xr usb 4
-.\".Sh HISTORY
-.Sh AUTHORS
-.An -nosplit
-The
-.Nm
-driver was written by
-.An Nick Hibma Aq n_hibma@FreeBSD.org .
-.Pp
-This manual page was written by
-.An Jeroen Ruigrok van der Werven Aq asmodai@FreeBSD.org .
diff --git a/share/man/man4/wlan.4 b/share/man/man4/wlan.4
index 4235b84..93d18ec 100644
--- a/share/man/man4/wlan.4
+++ b/share/man/man4/wlan.4
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 12, 2008
+.Dd March 26, 2009
.Dt WLAN 4
.Os
.Sh NAME
@@ -164,11 +164,10 @@ was used to be compatible with
.Sh SEE ALSO
.Xr an 4 ,
.Xr ath 4 ,
-.Xr bwi 4 ,
.Xr ipw 4 ,
.Xr iwi 4 ,
.Xr iwn 4 ,
-.Xr mwl 4 ,
+.Xr malo 4 ,
.Xr netintro 4 ,
.Xr ral 4 ,
.Xr rum 4 ,
diff --git a/share/man/man4/wpi.4 b/share/man/man4/wpi.4
index 4a827b3..f424d74 100644
--- a/share/man/man4/wpi.4
+++ b/share/man/man4/wpi.4
@@ -116,11 +116,11 @@ unload/reload the driver to continue.
.It "wpi%d: Radio transmitter is switched off"
The hardware switch controlling the radio is currently turned off.
Data transmission is not possible in this state.
+.El
.Sh BUGS
Not all the error messages are documented here.
.Pp
Background scanning is not currently supported.
-.El
.Sh SEE ALSO
.Xr wpifw 4 ,
.Xr pci 4 ,
diff --git a/share/man/man5/devfs.rules.5 b/share/man/man5/devfs.rules.5
index 3722cea..cc641ec 100644
--- a/share/man/man5/devfs.rules.5
+++ b/share/man/man5/devfs.rules.5
@@ -101,12 +101,12 @@ The first line declares and starts a new ruleset, with the name
and the number 10.
.Pp
To make all the
-.Xr uscanner 4
+.Xr ulpt 4
devices accessible to their owner and the
.Dq Li usb
group, a similar rule may be used:
.Pp
-.Dl "add path 'uscanner*' mode 0660 group usb"
+.Dl "add path 'ulpt*' mode 0660 group usb"
.Sh SEE ALSO
.Xr glob 3 ,
.Xr devfs 5 ,
diff --git a/share/man/man5/rc.conf.5 b/share/man/man5/rc.conf.5
index 77e835c..84b686a 100644
--- a/share/man/man5/rc.conf.5
+++ b/share/man/man5/rc.conf.5
@@ -1169,6 +1169,15 @@ One or more
.Xr wlan 4
devices must be created for each wireless devices as of
.Fx 8.0 .
+Debugging flags for
+.Xr wlan 4
+devices as set by
+.Xr wlandebug 8
+may be specified with an
+.Va wlandebug_ Ns Aq Ar interface
+variable.
+The contents of this variable will be passed directly to
+.Xr wlandebug 8 .
.Pp
If the
.Va ifconfig_ Ns Aq Ar interface
@@ -4065,6 +4074,7 @@ Default
.Xr sysctl 8 ,
.Xr syslogd 8 ,
.Xr timed 8 ,
+.Xr wlandebug 8 ,
.Xr yp 8 ,
.Xr ypbind 8 ,
.Xr ypserv 8 ,
diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5
index 2c0f560..b83f906 100644
--- a/share/man/man5/src.conf.5
+++ b/share/man/man5/src.conf.5
@@ -1,7 +1,7 @@
.\" DO NOT EDIT-- this file is automatically generated.
-.\" from FreeBSD: head/tools/build/options/makeman 174548 2007-12-12 16:39:32Z ru
+.\" from FreeBSD: head/tools/build/options/makeman 188848 2009-02-20 11:09:55Z mtm
.\" $FreeBSD$
-.Dd September 23, 2008
+.Dd April 5, 2009
.Dt SRC.CONF 5
.Os
.Sh NAME
@@ -462,7 +462,7 @@ On amd64, set to not build 32-bit library set and a
.Nm ld-elf32.so.1
runtime linker.
.It Va WITHOUT_LIBPTHREAD
-.\" from FreeBSD: head/tools/build/options/WITHOUT_LIBPTHREAD 172498 2007-10-09 17:53:33Z obrien
+.\" from FreeBSD: head/tools/build/options/WITHOUT_LIBPTHREAD 188848 2009-02-20 11:09:55Z mtm
Set to not build the
.Nm libpthread
providing library,
@@ -721,11 +721,6 @@ as a set-user-ID root program.
Set to not build the
.Bx 4.4
legacy docs.
-.It Va WITHOUT_SLIP
-.\" from FreeBSD: head/tools/build/options/WITHOUT_SLIP 183242 2008-09-21 22:02:26Z sam
-Set to not build
-.Xr sliplogin 8
-and related programs.
.It Va WITHOUT_SSP
.\" from FreeBSD: head/tools/build/options/WITHOUT_SSP 180012 2008-06-25 21:33:28Z ru
Set to not build world with propolice stack smashing protection.
diff --git a/share/man/man7/operator.7 b/share/man/man7/operator.7
index b092bef..e7c35cd 100644
--- a/share/man/man7/operator.7
+++ b/share/man/man7/operator.7
@@ -32,19 +32,20 @@
.\" @(#)operator.7 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
-.Dd January 22, 2003
+.Dd April 8, 2009
.Dt OPERATOR 7
.Os
.Sh NAME
.Nm operator
-.Nd C operator precedence and order of evaluation
+.Nd C and C++ operator precedence and order of evaluation
.Sh DESCRIPTION
.Bd -ragged -offset indent -compact
-.Bl -column "= += -= *= /= %= <<= >>= &= ^= |="
+.Bl -column "! ~ ++ -- - (type) * & sizeof new delete"
.It Sy "Operator Associativity"
.It "-------- -------------"
.It "() [] -> . left to right"
-.It "! ~ ++ -- - (type) * & sizeof right to left"
+.It "! ~ ++ -- - (type) * & sizeof new delete right to left"
+.It "->* .* left to right
.It "* / % left to right"
.It "+ - left to right"
.It "<< >> left to right"
@@ -56,7 +57,8 @@
.It "&& left to right"
.It "|| left to right"
.It "?: right to left"
-.It "= += -= *= /= %= <<= >>= &= ^= |= right to left"
+.It "= += -= *= /= %= <<= >>= &= ^= |= throw right to left"
+.It "?: (C++, third operand) right to left"
.It ", left to right"
.El
.Ed
diff --git a/share/man/man8/diskless.8 b/share/man/man8/diskless.8
index 64e8795..a7282ea 100644
--- a/share/man/man8/diskless.8
+++ b/share/man/man8/diskless.8
@@ -376,7 +376,6 @@ As a minimum, you normally need to have the following in
.Bd -literal -offset indent
<SERVER>:<ROOT> / nfs ro 0 0
<SERVER>:/usr /usr nfs ro 0 0
-proc /proc procfs rw 0 0
.Ed
.Pp
You also need to create a customized version of
diff --git a/share/man/man8/nanobsd.8 b/share/man/man8/nanobsd.8
index 6fee39a..cb953ec 100644
--- a/share/man/man8/nanobsd.8
+++ b/share/man/man8/nanobsd.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 28, 2006
+.Dd March 16, 2009
.Dt NANOBSD 8
.Os
.Sh NAME
@@ -33,7 +33,7 @@
applications
.Sh SYNOPSIS
.Nm
-.Op Fl bhkw
+.Op Fl bhknw
.Op Fl c Ar config-file
.Sh DESCRIPTION
The
@@ -59,6 +59,12 @@ Display usage information.
Skip the
.Cm buildkernel
stage of the build.
+.It Fl n
+Do not cleanup before each build stage.
+This suppresses the normal cleanup work done before the
+.Cm buildworld
+stage and adds -DNO_CLEAN to the make command line
+used for each build stage (world and kernel).
.It Fl w
Skip the
.Cm buildworld
diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile
index e70ca9c..4901fb4 100644
--- a/share/man/man9/Makefile
+++ b/share/man/man9/Makefile
@@ -201,6 +201,7 @@ MAN= accept_filter.9 \
random.9 \
random_harvest.9 \
redzone.9 \
+ refcount.9 \
resettodr.9 \
resource_int_value.9 \
rijndael.9 \
@@ -330,7 +331,6 @@ MAN= accept_filter.9 \
VOP_GETVOBJECT.9 \
VOP_INACTIVE.9 \
VOP_IOCTL.9 \
- VOP_LEASE.9 \
VOP_LINK.9 \
VOP_LISTEXTATTR.9 \
VOP_LOCK.9 \
@@ -920,6 +920,9 @@ MLINKS+=random.9 arc4rand.9 \
random.9 arc4random.9 \
random.9 read_random.9 \
random.9 srandom.9
+MLINKS+=refcount.9 refcount_acquire.9 \
+ refcount.9 refcount_init.9 \
+ refcount.9 refcount_release.9
MLINKS+=resource_int_value.9 resource_long_value.9 \
resource_int_value.9 resource_string_value.9
MLINKS+=rman.9 rman_activate_resource.9 \
diff --git a/share/man/man9/VOP_ACCESS.9 b/share/man/man9/VOP_ACCESS.9
index e959fda..76073db 100644
--- a/share/man/man9/VOP_ACCESS.9
+++ b/share/man/man9/VOP_ACCESS.9
@@ -68,40 +68,6 @@ The vnode will be locked on entry and should remain locked on return.
.Sh RETURN VALUES
If the file is accessible in the specified way, then zero is returned,
otherwise an appropriate error code is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_access(struct vnode *vp, accmode_t accmode, struct ucred *cred, struct thread *td)
-{
- int error;
-
- /*
- * Disallow write attempts on read-only file systems;
- * unless the file is a socket, fifo, or a block or
- * character device resident on the filesystem.
- */
- if (accmode & VWRITE) {
- switch (vp->v_type) {
- case VDIR:
- case VLNK:
- case VREG:
- if (vp->v_mount->mnt_flag & MNT_RDONLY)
- return EROFS;
-
- break;
- }
- }
-
- /* If immutable bit set, nobody gets to write it. */
- if ((accmode & VWRITE) && vp has immutable bit set)
- return (EPERM);
-
- error = vaccess(vp->v_type, mode of vp, owner of vp,
- group of vp, ap->a_accmode, ap->a_cred, NULL);
-
- return (error);
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EPERM
diff --git a/share/man/man9/VOP_ATTRIB.9 b/share/man/man9/VOP_ATTRIB.9
index 79e8e05..f14b1a5 100644
--- a/share/man/man9/VOP_ATTRIB.9
+++ b/share/man/man9/VOP_ATTRIB.9
@@ -84,68 +84,6 @@ otherwise an appropriate error is returned.
.Fn VOP_SETATTR
returns zero if the attributes were changed successfully, otherwise an
appropriate error is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_getattr(struct vnode *vp, struct vattr *vap, struct ucred *cred)
-{
-
- /*
- * Fill in the contents of *vap with information from
- * the file system.
- */
- ...;
-
- return 0;
-}
-
-int
-vop_setattr(struct vnode *vp, struct vattr *vap, struct ucred *cred)
-{
-
- /*
- * Check for unsettable attributes.
- */
- if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
- (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
- (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
- ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) {
- return (EINVAL);
- }
-
- if (vap->va_flags != VNOVAL) {
- /*
- * Set the immutable and append flags of the file.
- */
- }
-
- if (vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL) {
- /*
- * Change owner and/or group of the file.
- */
- }
-
- if (vap->va_size != VNOVAL) {
- /*
- * Truncate the file to the specified size.
- */
- }
-
- if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) {
- /*
- * Change access and/or modification time of file.
- */
- }
-
- if (vap->va_mode != (mode_t)VNOVAL) {
- /*
- * Change permissions of file.
- */
- }
-
- return 0;
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EPERM
diff --git a/share/man/man9/VOP_CREATE.9 b/share/man/man9/VOP_CREATE.9
index 691c93b..2f30328 100644
--- a/share/man/man9/VOP_CREATE.9
+++ b/share/man/man9/VOP_CREATE.9
@@ -80,67 +80,6 @@ If successful, the vnode for the new object is placed in
.Fa *vpp
and zero is returned.
Otherwise, an appropriate error is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_create(struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp
- struct vattr *vap)
-{
- int mode = MAKEIMODE(vap->va_type, vap->va_mode);
- struct vnode *vp;
- int error;
-
- *vpp = NULL;
- if ((mode & IFMT) == 0)
- mode |= IFREG;
-
- error = SOMEFS_VALLOC(dvp, mode, cnp->cn_cred, &vp);
- if (error)
- return error;
-
- /*
- * Update the permissions for the new vnode, including
- * copying the group from the directory.
- */
- ...;
-
-#ifdef QUOTA
- /*
- * Possibly check quota information.
- */
- ...;
-#endif
-
- /*
- * Enter new vnode in directory, taking care that the vnode
- * hits the disk before the directory contents are changed.
- */
- error = ...;
-
- if (error)
- goto bad;
-
- *vpp = vp;
-
- return 0;
-
-bad:
- /*
- * Write error occurred trying to update the inode
- * or the directory so must deallocate the inode.
- */
- vput(vp);
-
- /*
- * Deallocate file system resources for vp.
- */
- ...;
-
- return error;
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er ENOSPC
diff --git a/share/man/man9/VOP_FSYNC.9 b/share/man/man9/VOP_FSYNC.9
index 5f7ddd2..5439813 100644
--- a/share/man/man9/VOP_FSYNC.9
+++ b/share/man/man9/VOP_FSYNC.9
@@ -79,61 +79,6 @@ The file should be locked on entry.
.Sh RETURN VALUES
Zero is returned if the call is successful, otherwise an appropriate
error code is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_fsync(struct vnode *vp, int waitfor, struct thread *td)
-{
- struct buf *bp;
- struct buf *nbp;
- struct timeval tv;
- int s;
-
-loop:
- s = splbio();
- for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) {
- nbp = bp->b_vnbufs.le_next;
-
- /*
- * Ignore buffers which are already being written.
- */
- if (bp->b_flags & B_BUSY)
- continue;
-
- /*
- * Make sure the buffer is dirty.
- */
- if ((bp->b_flags & B_DELWRI) == 0)
- panic("vop_fsync: not dirty");
-
- vfs_bio_awrite(bp);
- splx(s);
- goto loop;
- }
- splx(s);
-
- if (waitfor == MNT_WAIT) {
- s = splbio();
- while (vp->v_numoutput) {
- vp->v_flag |= VBWAIT;
- tsleep((caddr_t)&vp->v_numoutput, PRIBIO + 1, "vopfsn");
- }
- splx(s);
-#ifdef DIAGNOSTIC
- if (vp->v_dirtyblkhd.lh_first) {
- vprint("vop_fsync: dirty", vp);
- goto loop;
- }
-#endif
- }
-
- /*
- * Write out the on-disc version of the vnode.
- */
- tv = time;
- return VOP_UPDATE(vp, &tv, &tv, waitfor == MNT_WAIT);
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er ENOSPC
diff --git a/share/man/man9/VOP_INACTIVE.9 b/share/man/man9/VOP_INACTIVE.9
index f74b020..75bd53b 100644
--- a/share/man/man9/VOP_INACTIVE.9
+++ b/share/man/man9/VOP_INACTIVE.9
@@ -74,38 +74,6 @@ prior to returning.
For VOP_RECLAIM, the
.Fa vp
will not be locked on entry and should be left unlocked on return.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_inactive(struct vnode *vp, struct thread *td)
-{
- if (link count of vp == 0) {
- /*
- * Reclaim space in file system for vp.
- */
- ...;
- }
- VOP_UNLOCK(vp, 0, td);
-
- return 0;
-}
-
-int
-vop_reclaim(struct vnode *vp, struct thread *td)
-{
- /*
- * Clean out the name cache.
- */
- cache_purge(vp);
-
- /*
- * Free file system related data.
- */
- ...;
-
- return 0;
-}
-.Ed
.Sh SEE ALSO
.Xr vnode 9
.Sh AUTHORS
diff --git a/share/man/man9/VOP_IOCTL.9 b/share/man/man9/VOP_IOCTL.9
index 6b2f94a..7b45484 100644
--- a/share/man/man9/VOP_IOCTL.9
+++ b/share/man/man9/VOP_IOCTL.9
@@ -67,16 +67,6 @@ If successful, zero is returned, otherwise an appropriate error code.
If the ioctl is not recognized or not handled,
.Er ENOTTY
should be returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_ioctl(struct vnode *vp, int command, caddr_t data, int fflag,
- struct ucred *cred, struct thread *td)
-{
-
- return ENOTTY;
-}
-.Ed
.Sh SEE ALSO
.Xr vnode 9
.Sh AUTHORS
diff --git a/share/man/man9/VOP_LEASE.9 b/share/man/man9/VOP_LEASE.9
deleted file mode 100644
index becf68b..0000000
--- a/share/man/man9/VOP_LEASE.9
+++ /dev/null
@@ -1,61 +0,0 @@
-.\" -*- nroff -*-
-.\"
-.\" Copyright (c) 1996 Doug Rabson
-.\"
-.\" All rights reserved.
-.\"
-.\" This program is free software.
-.\"
-.\" 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.
-.\"
-.\" $FreeBSD$
-.\"
-.Dd September 24, 1999
-.Os
-.Dt VOP_LEASE 9
-.Sh NAME
-.Nm VOP_LEASE
-.Nd "validate a vnode for a particular set of credentials and operation type"
-.Sh SYNOPSIS
-.In sys/param.h
-.In sys/mount.h
-.Ft int
-.Fn VOP_LEASE "struct vnode *vp" "struct thread *td" "struct ucred *cred" "int type"
-.Sh DESCRIPTION
-This entry point is currently not implemented.
-The idea is to
-validate a vnode for a particular set of user credentials and operation type.
-The two operation types supported are
-.Dv LEASE_READ
-and
-.Dv LEASE_WRITE .
-.Sh RETURN VALUES
-The function currently returns 0 in all cases.
-.Sh ERRORS
-.Sh SEE ALSO
-.Xr VOP_READ 9 ,
-.Xr VOP_WRITE 9
-.Sh LOCKS
-The vnode must be exclusively locked on entry, and should remain exclusively
-locked on return.
-.Sh AUTHORS
-This manual page was written by
-.An Matt Dillon .
diff --git a/share/man/man9/VOP_LINK.9 b/share/man/man9/VOP_LINK.9
index 559526c..b7fbb7b 100644
--- a/share/man/man9/VOP_LINK.9
+++ b/share/man/man9/VOP_LINK.9
@@ -66,37 +66,6 @@ the vnodes locked on return.
.Sh RETURN VALUES
Zero is returned if the file was linked successfully, otherwise an
error is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_link(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
-{
- int error = 0;
-
- if (vp->v_mount != dvp->v_mount)
- return (EXDEV);
-
- if (vp would have too many links)
- return (EMLINK);
-
- if (vp is immutable)
- return (EPERM);
-
- /*
- * Increment link count of vp and write back the on-disc version of it.
- */
- ...;
-
- if (!error) {
- /*
- * Add the new name to the directory.
- */
- ...;
- }
-
- return error;
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EMLINK
diff --git a/share/man/man9/VOP_LOCK.9 b/share/man/man9/VOP_LOCK.9
index ab4c53c..cdf1714 100644
--- a/share/man/man9/VOP_LOCK.9
+++ b/share/man/man9/VOP_LOCK.9
@@ -116,72 +116,6 @@ also does not want a thread specified as argument but it
assumes curthread to be used.
.Sh RETURN VALUES
Zero is returned on success, otherwise an error is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-struct vopnode {
- int von_flag;
- /*
- * Other file system specific data.
- */
- ...;
-};
-#define VON_LOCKED 1
-#define VON_WANTED 2
-#define VTOVON(vp) ((struct vopnode *) (vp)->v_data)
-
-int
-vop_lock(struct vnode *vp)
-{
- struct vopnode* vop;
-
-start:
- while (vp->v_flag & VXLOCK) {
- vp->v_flag |= VXWANT;
- tsleep((caddr_t)vp, PINOD, "voplk1", 0);
- }
- if (vp->v_tag == VT_NON)
- return ENOENT;
-
- vop = VTOVON(vp);
- if (vop->von_flag & VON_LOCKED) {
- vop->von_flag |= VON_WANTED;
- tsleep((caddr_t) vop, PINOD, "voplk2", 0);
- goto start;
- }
-
- vop->von_flag |= VON_LOCKED;
-
- return 0;
-}
-
-int
-vop_unlock(struct vnode *vp)
-{
- struct vopnode *vop = VTOVON(vp);
-
- if ((vop->von_flag & VON_LOCKED) == 0) {
- panic("vop_unlock not locked");
- }
- vop->von_flag &= ~VON_LOCKED;
- if (vop->von_flag & VON_WANTED) {
- vop->von_flag &= ~VON_WANTED;
- wakeup((caddr_t) vop);
- }
-
- return 0;
-}
-
-int
-vop_islocked(struct vnode *vp)
-{
- struct vopnode *vop = VTOVON(vp);
-
- if (vop->von_flag & VON_LOCKED)
- return 1;
- else
- return 0;
-}
-.Ed
.Sh SEE ALSO
.Xr vnode 9
.Sh AUTHORS
diff --git a/share/man/man9/VOP_LOOKUP.9 b/share/man/man9/VOP_LOOKUP.9
index 270f83f..ba5a260 100644
--- a/share/man/man9/VOP_LOOKUP.9
+++ b/share/man/man9/VOP_LOOKUP.9
@@ -156,260 +156,6 @@ is specified and the operation would succeed, the special return value
.Er EJUSTRETURN
is returned.
Otherwise, an appropriate error code is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_lookup(struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp)
-{
- int error;
- int nameiop = cnp->cn_nameiop;
- int flags = cnp->cn_flags;
- int lockparent = flags & LOCKPARENT;
- int islastcn = flags & ISLASTCN;
- struct vnode *vp = NULL;
-
- /*
- * Check accessibility of directory.
- */
- if (dvp->v_type != VDIR)
- return ENOTDIR;
-
- error = VOP_ACCESS(dvp, VEXEC, cred, cnp->cn_thread);
- if (error)
- return (error);
-
- if (islastcn && (dvp->v_mount->mnt_flag & MNT_RDONLY) &&
- (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
- return (EROFS);
-
- /*
- * Check name cache for directory/name pair. This returns ENOENT
- * if the name is known not to exist, -1 if the name was found, or
- * zero if not.
- */
- error = cache_lookup(dvp, vpp, cnp);
- if (error) {
- int vpid;
-
- if (error = ENOENT)
- return error;
-
- vp = *vpp;
- if (dvp == vp) { /* lookup on "." */
- VREF(vp);
- error = 0;
- } else if (flags & ISDOTDOT) {
- /*
- * We need to unlock the directory before getting
- * the locked vnode for ".." to avoid deadlocks.
- */
- VOP_UNLOCK(dvp);
- error = vget(vp, 1);
- if (!error) {
- if (lockparent && islastcn)
- error = VOP_LOCK(dvp);
- }
- } else {
- error = vget(vp, 1);
- if (error || !(lockparent && islastcn)) {
- VOP_UNLOCK(dvp);
- }
- }
-
- /*
- * Check that the capability number did not change
- * while we were waiting for the lock.
- */
- if (!error) {
- if (vpid == vp->v_id) {
- /*
- * dvp is locked if lockparent && islastcn.
- * vp is locked.
- */
- return (0);
- }
- vput(vp);
-
- if (dvp != vp && lockparent && islastcn)
- VOP_UNLOCK(pdp);
- }
-
- /*
- * Re-lock dvp for the directory search below.
- */
- error = VOP_LOCK(dvp);
- if (error) {
- return (error);
- }
-
- *vpp = NULL;
- }
-
- /*
- * Search dvp for the component cnp->cn_nameptr.
- */
- ...;
-
- if (!found) {
- if ((nameiop == CREATE || nameiop == RENAME)
- && islastcn
- && directory dvp has not been removed) {
- /*
- * Check for write access on directory.
- */
-
- /*
- * Possibly record the position of a slot in the directory
- * large enough for the new component name. This can be
- * recorded in the vnode private data for dvp.
- * Set the SAVENAME flag to hold onto the pathname for use
- * later in VOP_CREATE or VOP_RENAME.
- */
- cnp->cn_flags |= SAVENAME;
- if (!lockparent)
- /*
- * Note that the extra data recorded above is only
- * useful if lockparent is specified.
- */
- VOP_UNLOCK(dvp);
-
- return EJUSTRETURN;
- }
-
- /*
- * Consider inserting name into cache.
- */
- if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE)
- cache_enter(dvp, NULL, cnp);
-
- return ENOENT;
- } else {
- /*
- * If deleting, and at end of pathname, return parameters
- * which can be used to remove file. If the wantparent flag
- * isn't set, we return only the directory, otherwise we go on
- * and lock the inode, being careful with ".".
- */
- if (nameiop == DELETE && islastcn) {
- /*
- * Check for write access on directory.
- */
- error = VOP_ACCESS(dvp, VWRITE, cred, cnp->cn_thread);
- if (error)
- return (error);
-
- if (found entry is same as dvp) {
- VREF(dvp);
- *vpp = dvp;
- return 0;
- }
-
- error = VFS_VGET(dvp->v_mount, ..., &vp);
- if (error)
- return error;
-
- if (directory is sticky
- && cred->cr_uid != 0
- && cred->cr_uid != owner of dvp
- && owner of vp != cred->cr_uid) {
- vput(vp);
- return EPERM;
- }
- *vpp = vp;
- if (!lockparent)
- VOP_UNLOCK(dvp);
-
- return 0;
- }
-
- /*
- * If rewriting (RENAME), return the inode and the
- * information required to rewrite the present directory
- * Must get inode of directory entry to verify it's a
- * regular file, or empty directory.
- */
- if (nameiop == RENAME && wantparent && islastcn) {
- error = VOP_ACCESS(dvp, VWRITE, cred, cnp->cn_thread);
- if (error)
- return (error);
-
- /*
- * Check for "."
- */
- if (found entry is same as dvp)
- return EISDIR;
-
- error = VFS_VGET(dvp->v_mount, ..., &vp);
- if (error)
- return error;
- *vpp = vp;
- /*
- * Save the name for use in VOP_RENAME later.
- */
- cnp->cn_flags |= SAVENAME;
- if (!lockparent)
- VOP_UNLOCK(dvp);
-
- return 0;
- }
-
- /*
- * Step through the translation in the name. We do not `vput' the
- * directory because we may need it again if a symbolic link
- * is relative to the current directory. Instead we save it
- * unlocked as "pdp". We must get the target inode before unlocking
- * the directory to insure that the inode will not be removed
- * before we get it. We prevent deadlock by always fetching
- * inodes from the root, moving down the directory tree. Thus
- * when following backward pointers ".." we must unlock the
- * parent directory before getting the requested directory.
- * There is a potential race condition here if both the current
- * and parent directories are removed before the VFS_VGET for the
- * inode associated with ".." returns. We hope that this occurs
- * infrequently since we cannot avoid this race condition without
- * implementing a sophisticated deadlock detection algorithm.
- * Note also that this simple deadlock detection scheme will not
- * work if the file system has any hard links other than ".."
- * that point backwards in the directory structure.
- */
- if (flags & ISDOTDOT) {
- VOP_UNLOCK(dvp); /* race to get the inode */
- error = VFS_VGET(dvp->v_mount, ..., &vp);
- if (error) {
- VOP_LOCK(dvp);
- return (error);
- }
- if (lockparent && islastcn) {
- error = VOP_LOCK(dvp);
- if (error) {
- vput(vp);
- return error;
- }
- }
- *vpp = vp;
- } else if (found entry is same as dvp) {
- VREF(dvp); /* we want ourself, ie "." */
- *vpp = dvp;
- } else {
- error = VFS_VGET(dvp->v_mount, ..., &vp);
- if (error)
- return (error);
- if (!lockparent || !islastcn)
- VOP_UNLOCK(dvp);
- *vpp = vp;
- }
-
- /*
- * Insert name into cache if appropriate.
- */
- if (cnp->cn_flags & MAKEENTRY)
- cache_enter(dvp, *vpp, cnp);
- return (0);
- }
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er ENOTDIR
diff --git a/share/man/man9/VOP_OPENCLOSE.9 b/share/man/man9/VOP_OPENCLOSE.9
index 959e095..58e601b 100644
--- a/share/man/man9/VOP_OPENCLOSE.9
+++ b/share/man/man9/VOP_OPENCLOSE.9
@@ -94,18 +94,6 @@ expects an unlocked, referenced vnode and will dereference the vnode prior
to returning.
.Sh RETURN VALUES
Zero is returned on success, otherwise an error code is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_open(struct vnode *vp, int mode, struct ucred *cred, struct thread *td,
- struct file *fp)
-{
- /*
- * Most file systems don't do much here.
- */
- return 0;
-}
-.Ed
.Sh SEE ALSO
.Xr vnode 9 ,
.Xr VOP_LOOKUP 9
diff --git a/share/man/man9/VOP_RDWR.9 b/share/man/man9/VOP_RDWR.9
index 28f495f..b010523 100644
--- a/share/man/man9/VOP_RDWR.9
+++ b/share/man/man9/VOP_RDWR.9
@@ -85,141 +85,6 @@ Data already in VMIO space.
The file should be locked on entry and will still be locked on exit.
.Sh RETURN VALUES
Zero is returned on success, otherwise an error code is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_read(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
-{
- struct buf *bp;
- off_t bytesinfile;
- daddr_t lbn, nextlbn;
- long size, xfersize, blkoffset;
- int error;
-
- size = block size of file system;
-
- for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
- bytesinfile = size of file - uio->uio_offset;
- if (bytesinfile <= 0)
- break;
-
- lbn = uio->uio_offset / size;
- blkoffset = uio->uio_offset - lbn * size;
-
- xfersize = size - blkoffset;
- if (uio->uio_resid < xfersize)
- xfersize = uio->uio_resid;
- if (bytesinfile < xfersize)
- xfersize = bytesinfile;
-
- error = bread(vp, lbn, size, NOCRED, &bp);
- if (error) {
- brelse(bp);
- bp = NULL;
- break;
- }
-
- /*
- * We should only get non-zero b_resid when an I/O error
- * has occurred, which should cause us to break above.
- * However, if the short read did not cause an error,
- * then we want to ensure that we do not uiomove bad
- * or uninitialized data.
- */
- size -= bp->b_resid;
- if (size < xfersize) {
- if (size == 0)
- break;
- xfersize = size;
- }
-
- error = uiomove((char *)bp->b_data + blkoffset, (int)xfersize, uio);
- if (error)
- break;
-
- bqrelse(bp);
- }
- if (bp != NULL)
- bqrelse(bp);
-
- return (error);
-}
-
-int
-vop_write(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *cred)
-{
- struct buf *bp;
- off_t bytesinfile;
- daddr_t lbn, nextlbn;
- off_t osize;
- long size, resid, xfersize, blkoffset;
- int flags;
- int error;
-
- osize = size of file;
- size = block size of file system;
- resid = uio->uio_resid;
- if (ioflag & IO_SYNC)
- flags = B_SYNC;
- else
- flags = 0;
-
- for (error = 0; uio->uio_resid > 0;) {
- lbn = uio->uio_offset / size;
- blkoffset = uio->uio_offset - lbn * size;
-
- xfersize = size - blkoffset;
- if (uio->uio_resid < xfersize)
- xfersize = uio->uio_resid;
-
- if (uio->uio_offset + xfersize > size of file)
- vnode_pager_setsize(vp, uio->uio_offset + xfersize);
-
- if (size > xfersize)
- flags |= B_CLRBUF;
- else
- flags &= ~B_CLRBUF;
-
- error = find_block_in_file(vp, lbn, blkoffset + xfersize,
- cred, &bp, flags);
- if (error)
- break;
-
- if (uio->uio_offset + xfersize > size of file)
- set size of file to uio->uio_offset + xfersize;
-
- error = uiomove((char *)bp->b_data + blkoffset, (int) xfersize, uio);
- /* XXX ufs does not check the error here. Why? */
-
- if (ioflag & IO_VMIO)
- bp->b_flags |= B_RELBUF; /* ??? */
-
- if (ioflag & IO_SYNC)
- bwrite(bp);
- else if (xfersize + blkoffset == size)
- bawrite(bp);
- else
- bdwrite(bp);
-
- if (error || xfersize == 0)
- break;
- }
-
- if (error) {
- if (ioflag & IO_UNIT) {
- /* call private routine to truncate file. */
- your_truncate(vp, osize, ioflag & IO_SYNC, cred, uio->uio_td);
- uio->uio_offset -= resid - uio->uio_resid;
- uio->uio_resid = resid;
- }
- } else if (resid > uio->uio_resid && (ioflag & IO_SYNC)) {
- struct timeval tv;
- error = VOP_UPDATE(vp, &tv, &tv, 1); /* XXX what does this do? */
- }
-
- return (error);
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EFBIG
diff --git a/share/man/man9/VOP_READDIR.9 b/share/man/man9/VOP_READDIR.9
index bf4c6b2..5b94438 100644
--- a/share/man/man9/VOP_READDIR.9
+++ b/share/man/man9/VOP_READDIR.9
@@ -96,70 +96,6 @@ Memory for the cookies should be allocated using:
*cookies = (u_int*)#
malloc(*ncookies * sizeof(u_int), M_TEMP, M_WAITOK);
.Ed
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_readdir(struct vnode *vp, struct uio *uio, struct ucred *cred,
- int *eofflag, int *ncookies, u_int **cookies)
-{
- off_t off;
- int error = 0;
-
- /*
- * Remember the original offset to use later in generating cookies.
- */
- off = uio->uio_offset;
-
- /*
- * Read directory contents starting at uio->uio_offset into buffer
- * pointed to by uio.
- */
- ...;
-
- if (!error && ncookies != NULL) {
- struct dirent *dpStart;
- struct dirent *dpEnd;
- struct dirent *dp;
- int count;
- u_int *cookiebuf;
- u_int *cookiep;
-
- if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
- panic("vop_readdir: unexpected uio from NFS server");
-
- /*
- * Parse the stuff just read into the uio.
- */
- dpStart = (struct dirent *)
- ((char *)uio->uio_iov->iov_base - (uio->uio_offset - off));
- dpEnd = (struct dirent *) uio->uio_iov->iov_base;
-
- /*
- * Count number of entries.
- */
- for (dp = dpStart, count = 0;
- dp < dpEnd;
- dp = (struct dirent *)((caddr_t) dp + dp->d_reclen))
- count++;
-
- cookiebuf = (u_int *) malloc(count * sizeof(u_int), M_TEMP, M_WAITOK);
- for (dp = dpStart; cookiep = cookiebuf;
- dp < dpEnd;
- dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) {
- off += dp->d_reclen;
- *cookiep++ = (u_int) off;
- }
- *ncookies = count;
- *cookies = cookiebuf;
- }
-
- if (eofflag && uio->uio_offset is past the end of the directory) {
- *eofflag = TRUE;
- }
-
- return error;
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EINVAL
diff --git a/share/man/man9/VOP_READLINK.9 b/share/man/man9/VOP_READLINK.9
index 0fb5e47..f98222f 100644
--- a/share/man/man9/VOP_READLINK.9
+++ b/share/man/man9/VOP_READLINK.9
@@ -54,21 +54,6 @@ The credentials of the caller.
The vnode should be locked on entry and will still be locked on exit.
.Sh RETURN VALUES
Zero is returned on success, otherwise an error code is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_readlink(struct vnode *vp, struct uio *uio, struct ucred *cred)
-{
- int error = 0;
-
- /*
- * Read the target of the symlink.
- */
- ...;
-
- return error;
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EIO
diff --git a/share/man/man9/VOP_REMOVE.9 b/share/man/man9/VOP_REMOVE.9
index aa04405..0a10ed2 100644
--- a/share/man/man9/VOP_REMOVE.9
+++ b/share/man/man9/VOP_REMOVE.9
@@ -62,27 +62,6 @@ and
should be locked on entry and remain locked on return.
.Sh RETURN VALUES
Zero is returned on success, otherwise an error code is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_remove(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
-{
- int error = 0;
-
- if (vp is immutable) {
- error = EPERM;
- goto out;
- }
-
- /*
- * Remove name cnp->cn_nameptr from directory and update link count
- * of vp.
- */
- ...;
-
- return error;
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EPERM
diff --git a/share/man/man9/VOP_RENAME.9 b/share/man/man9/VOP_RENAME.9
index 4c2e58a..8797585 100644
--- a/share/man/man9/VOP_RENAME.9
+++ b/share/man/man9/VOP_RENAME.9
@@ -72,205 +72,6 @@ The VOP routine is expected to
.Xr vput 9
both prior to
returning.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_rename(struct vnode *fdvp, struct vnode *fvp, struct componentname *fcnp,
- struct vnode *tdvp, struct vnode *tvp, struct componentname *tcnp)
-{
- int doingdirectory = 0;
- int error = 0;
-
- /*
- * Check for cross-device rename.
- */
- if (fvp->v_mount != tdvp->v_mount) {
- error = EXDEV;
- abortit:
- if (tdvp == tvp)
- vrele(tdvp);
- else
- vput(tdvp);
- if (tvp)
- vput(tvp);
- vrele(fdvp);
- vrele(fvp);
- return error;
- }
-
- if (tvp exists and is immutable) {
- error = EPERM;
- goto abortit;
- }
-
- /*
- * POSIX: "If the old argument and the new argument
- * both refer to links to the same existing file,
- * the rename() function shall return successfully
- * and perform no other action."
- * The upper layers already handle this case.
- */
- KASSERT(fvp != tvp, ("vop_rename: source and destination are the same"));
-
- if (fvp is immutable) {
- error = EPERM;
- goto abortit;
- }
-
- error = VOP_LOCK(fvp);
- if (error)
- goto abortit;
-
- if (vp is a directory) {
- /*
- * Avoid ".", "..", and aliases of "." for obvious reasons.
- */
- if ((fcnp->cn_namelen == 1 && fcnp->cn_nameptr[0] == '.')
- || fdvp == fvp
- || ((fcnp->cn_flags | tcnp->cn_flags) & ISDOTDOT)) {
- VOP_UNLOCK(fvp);
- error = EINVAL;
- goto abortit;
- }
- doingdirectory = 1;
- }
- vrele(fdvp);
-
- /*
- * Bump link count on fvp while we are moving stuff around. If we
- * crash before completing the work, the link count may be wrong
- * but correctable.
- */
- ...;
-
- /*
- * If ".." must be changed (ie the directory gets a new
- * parent) then the source directory must not be in the
- * directory hierarchy above the target, as this would
- * orphan everything below the source directory. Also
- * the user must have write permission in the source so
- * as to be able to change "..".
- */
- error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred, tcnp->cn_thread);
- VOP_UNLOCK(fvp);
- if (doingdirectory && fdvp != tdvp) {
- /*
- * Check for pathname conflict.
- */
- ...;
- }
-
- /*
- * If the target doesn't exist, link the target to the source and
- * unlink the source. Otherwise, rewrite the target directory to
- * reference the source and remove the original entry.
- */
- if (tvp == NULL) {
- /*
- * Account for ".." in new directory.
- */
- if (doingdirectory && fdvp != tdvp) {
- /*
- * Increase link count of tdvp.
- */
- ...;
- }
-
- /*
- * Add name in new directory.
- */
- ...;
-
- if (error) {
- if (doingdirectory && fdvp != tdvp) {
- /*
- * Decrease link count if tdvp.
- */
- ...;
- }
- goto bad;
- }
- vput(tdvp);
- } else {
- /*
- * Target must be empty if a directory and have no links
- * to it. Also, ensure source and target are compatible
- * (both directories, or both not directories).
- */
- if (tvp is a directory) {
- if (tvp is not empty) {
- error = ENOTEMPTY;
- goto bad;
- }
- if (!doingdirectory) {
- error = ENOTDIR;
- goto bad;
- }
- /*
- * Update name cache since directory is going away.
- */
- cache_purge(tdvp);
- } else if (doingdirectory) {
- error = ENOTDIR;
- goto bad;
- }
-
- /*
- * Change name tcnp in tdvp to point at fvp.
- */
- ...;
-
- /*
- * If the target directory is in same directory as the source
- * directory, decrement the link count on the parent of the
- * target directory. This accounts for the fact that a
- * directory links back to its parent with "..".
- */
- if (doingdirectory && fdvp == tdvp) {
- /*
- * Decrement link count of tdvp.
- */
- ...;
- }
- vput(tdvp);
-
- /*
- * Decrement the link count of tvp since the directory no
- * longer points at it.
- */
- ...;
- if (doingdirectory) {
- /*
- * Clean up the old directory tvp.
- */
- ...;
- }
- vput(tvp);
- }
-
- /*
- * Unlink the source. If a directory was moved to a new parent,
- * update its ".." entry. Gobs of ugly UFS code omitted here.
- */
- ...;
-
-bad:
- if (tvp)
- vput(tvp);
- vput(tdvp);
-out:
- if (VOP_LOCK(fvp) == 0) {
- /*
- * Decrement link count of fvp.
- */
- ...;
- vput(fvp);
- } else
- vrele(fvp);
-
- return error;
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er EPERM
diff --git a/share/man/man9/VOP_VPTOCNP.9 b/share/man/man9/VOP_VPTOCNP.9
index 295bab9..892b4a6 100644
--- a/share/man/man9/VOP_VPTOCNP.9
+++ b/share/man/man9/VOP_VPTOCNP.9
@@ -70,30 +70,6 @@ parent directory vnode will be unlocked on a successful exit. However, it
will have its hold count incremented.
.Sh RETURN VALUES
Zero is returned on success, otherwise an error code is returned.
-.Sh PSEUDOCODE
-.Bd -literal
-int
-vop_vptocnp(struct vnode *vp, struct vnode **dvp, char *buf, int *buflen)
-{
- int error = 0;
-
- /*
- * Translate the vnode to its component name.
- *
- * Decrement the component name's length from buflen.
- *
- * Obtain the vnode's parent directory vnode.
- */
- ...;
-
- /*
- * Increment the parent directory's hold count.
- */
- vhold(*dvp);
-
- return error;
-}
-.Ed
.Sh ERRORS
.Bl -tag -width Er
.It Bq Er ENOMEM
diff --git a/share/man/man9/acl.9 b/share/man/man9/acl.9
index dc3f7ad..4ab1e40 100644
--- a/share/man/man9/acl.9
+++ b/share/man/man9/acl.9
@@ -135,66 +135,6 @@ The process has no read, write or execute permissions
to the associated file.
.El
.El
-.Sh IMPLEMENTATION NOTES
-.Bd -literal
-typedef mode_t *acl_permset_t;
-
-/* internal ACL structure */
-struct acl {
- int acl_cnt;
- struct acl_entry acl_entry[ACL_MAX_ENTRIES];
-};
-
-/* external ACL structure */
-struct acl_t_struct {
- struct acl ats_acl;
- int ats_cur_entry;
-};
-typedef struct acl_t_struct *acl_t;
-
-/*
- * Possible valid values for ae_tag field.
- */
-#define ACL_UNDEFINED_TAG 0x00000000
-#define ACL_USER_OBJ 0x00000001
-#define ACL_USER 0x00000002
-#define ACL_GROUP_OBJ 0x00000004
-#define ACL_GROUP 0x00000008
-#define ACL_MASK 0x00000010
-#define ACL_OTHER 0x00000020
-#define ACL_OTHER_OBJ ACL_OTHER
-
-/*
- * Possible valid values for acl_type_t arguments.
- */
-#define ACL_TYPE_ACCESS 0x00000000
-#define ACL_TYPE_DEFAULT 0x00000001
-#define ACL_TYPE_AFS 0x00000002
-#define ACL_TYPE_CODA 0x00000003
-#define ACL_TYPE_NTFS 0x00000004
-#define ACL_TYPE_NWFS 0x00000005
-
-/*
- * Possible flags in ae_perm field.
- */
-#define ACL_EXECUTE 0x0001
-#define ACL_WRITE 0x0002
-#define ACL_READ 0x0004
-#define ACL_PERM_NONE 0x0000
-#define ACL_PERM_BITS (ACL_EXECUTE | ACL_WRITE | ACL_READ)
-#define ACL_POSIX1E_BITS (ACL_EXECUTE | ACL_WRITE | ACL_READ)
-
-/*
- * Possible entry_id values for acl_get_entry()
- */
-#define ACL_FIRST_ENTRY 0
-#define ACL_NEXT_ENTRY 1
-
-/*
- * Undefined value in ae_id field
- */
-#define ACL_UNDEFINED_ID ((uid_t)-1)
-.Ed
.Sh SEE ALSO
.Xr acl 3 ,
.Xr vaccess_acl_posix1e 9 ,
diff --git a/share/man/man9/bus_dma.9 b/share/man/man9/bus_dma.9
index 5850db6..dc5ae4b 100644
--- a/share/man/man9/bus_dma.9
+++ b/share/man/man9/bus_dma.9
@@ -561,15 +561,6 @@ Are as follows:
.It Dv BUS_DMA_NOWAIT
The load should not be deferred in case of insufficient mapping resources,
and instead should return immediately with an appropriate error.
-.It Dv BUS_DMA_NOCACHE
-The allocated memory will not be cached in the processor caches.
-All memory accesses appear on the bus and are executed
-without reordering.
-On the amd64 and i386 architectures this flag results in the
-Strong Uncacheable PAT to be set for the allocated virtual address range.
-The
-.Dv BUS_DMA_NOCACHE
-flag is currently implemented on amd64, i386 and sparc64.
.El
.El
.Pp
@@ -785,6 +776,15 @@ the
flag is currently implemented on arm and sparc64.
.It Dv BUS_DMA_ZERO
Causes the allocated memory to be set to all zeros.
+.It Dv BUS_DMA_NOCACHE
+The allocated memory will not be cached in the processor caches.
+All memory accesses appear on the bus and are executed
+without reordering.
+On the amd64 and i386 architectures this flag results in the
+Strong Uncacheable PAT to be set for the allocated virtual address range.
+The
+.Dv BUS_DMA_NOCACHE
+flag is currently implemented on amd64, i386 and sparc64.
.El
.It Fa mapp
Pointer to a
diff --git a/share/man/man9/refcount.9 b/share/man/man9/refcount.9
new file mode 100644
index 0000000..e7702a2
--- /dev/null
+++ b/share/man/man9/refcount.9
@@ -0,0 +1,96 @@
+.\"
+.\" Copyright (c) 2009 Advanced Computing Technologies LLC
+.\" Written by: John H. Baldwin <jhb@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 January 20, 2009
+.Dt REFCOUNT 9
+.Os
+.Sh NAME
+.Nm refcount ,
+.Nm refcount_init ,
+.Nm refcount_acquire ,
+.Nm refcount_release
+.Nd manage a simple reference counter
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/refcount.h
+.Ft void
+.Fn refcount_init "volatile u_int *count, u_int value"
+.Ft void
+.Fn refcount_acquire "volatile u_int *count"
+.Ft int
+.Fn refcount_release "volatile u_int *count"
+.Sh DESCRIPTION
+The
+.Nm
+functions provide an API to manage a simple reference counter.
+The caller provides the storage for the counter in an unsigned integer.
+A pointer to this integer is passed via
+.Fa count .
+Usually the counter is used to manage the lifetime of an object and is
+stored as a member of the object.
+.Pp
+The
+.Fn refcount_init
+function is used to set the initial value of the counter to
+.Fa value .
+It is normally used when creating a reference-counted object.
+.Pp
+The
+.Fn refcount_acquire
+function is used to acquire a new reference.
+The caller is responsible for ensuring that it holds a valid reference
+while obtaining a new reference.
+For example,
+if an object is stored on a list and the list holds a reference on the
+object, then holding a lock that protects the list provides sufficient
+protection for acquiring a new reference.
+.Pp
+The
+.Fn refcount_release
+function is used to release an existing reference.
+The function returns a non-zero value if the reference being released was
+the last reference;
+otherwise, it returns zero.
+.Pp
+Note that these routines do not provide any inter-CPU synchronization,
+data protection,
+or memory ordering guarantees except for managing the counter.
+The caller is responsible for any additional synchronization needed by
+consumers of any containing objects.
+In addition,
+the caller is also responsible for managing the life cycle of any containing
+objects including explicitly releasing any resources when the last reference
+is released.
+.Sh RETURN VALUES
+The
+.Nm refcount_release
+function returns non-zero when releasing the last reference and zero when
+releasing any other reference.
+.Sh HISTORY
+These functions were introduced in
+.Fx 6.0 .
diff --git a/share/man/man9/vm_map_lock.9 b/share/man/man9/vm_map_lock.9
index 619f8c7..7095709 100644
--- a/share/man/man9/vm_map_lock.9
+++ b/share/man/man9/vm_map_lock.9
@@ -73,7 +73,6 @@ The
.Fn vm_map_lock_read
macro obtains a read-lock on
.Fa map .
-Currently this is implemented as an exclusive lock.
.Pp
The
.Fn vm_map_unlock_read
@@ -93,23 +92,18 @@ macro attempts to obtain a read-lock on
.Fa map .
It returns FALSE if the lock cannot be immediately acquired;
otherwise return TRUE with the lock acquired.
-Currently this is implemented as an exclusive lock.
.Pp
The
.Fn vm_map_lock_upgrade
macro attempts to atomically upgrade a read-lock on
.Fa map
to an exclusive lock.
-As read-locks are currently implemented as exclusive locks,
-this macro is a no-op.
.Pp
The
.Fn vm_map_lock_downgrade
macro attempts to downgrade an exclusive lock on
.Fa map
to a read-lock.
-As read-locks are currently implemented as exclusive locks,
-this macro is a no-op.
.Sh IMPLEMENTATION NOTES
Currently, all of the locking macros implement their locks as sleep locks.
.Sh SEE ALSO
diff --git a/share/misc/committers-ports.dot b/share/misc/committers-ports.dot
index b1d9bb0..ac082c2 100644
--- a/share/misc/committers-ports.dot
+++ b/share/misc/committers-ports.dot
@@ -127,6 +127,7 @@ mharo [label="Michael Haro\nmharo@FreeBSD.org\n1999/04/13"]
osa [label="Sergey A. Osokin\nosa@FreeBSD.org\n2003/06/04"]
pat [label="Patrick Li\npat@FreeBSD.org\n2001/11/14"]
pav [label="Pav Lucistnik\npav@FreeBSD.org\n2003/11/12"]
+pgj [label="Gabor Pali\npgj@FreeBSD.org\n2009/04/12"]
philip [label="Philip Paeps\nphilip@FreeBSD.org\n2005/10/19"]
pgollucci [label="Philip M. Gollucci\npgollucci@FreeBSD.org\n2008/07/21"]
rafan [label="Rong-En Fan\nrafan@FreeBSD.org\n2006/06/23"]
@@ -216,6 +217,7 @@ flz -> johans
flz -> laszlof
gabor -> lippe
+gabor -> pgj
garga -> acm
garga -> alepulver
@@ -317,6 +319,7 @@ stas -> araujo
steve -> netchild
tabthorpe -> jadawin
+tabthorpe -> pgj
thierry -> jadawin
diff --git a/share/misc/committers-src.dot b/share/misc/committers-src.dot
index 366070f..2e671b8 100644
--- a/share/misc/committers-src.dot
+++ b/share/misc/committers-src.dot
@@ -88,6 +88,7 @@ eik [label="Oliver Eikemeier\neik@FreeBSD.org\n2004/05/20"]
emaste [label="Ed Maste\nemaste@FreeBSD.org\n2005/10/04"]
emax [label="Maksim Yevmenkin\nemax@FreeBSD.org\n2003/10/12"]
eri [label="Ermal Luci\neri@FreeBSD.org\n2008/06/11"]
+fabient [label="Fabien Thomas\nfabient@FreeBSD.org\n2009/03/16"]
fanf [label="Tony Finch\nfanf@FreeBSD.org\n2002/05/05"]
fjoe [label="Max Khon\nfjoe@FreeBSD.org\n2001/08/06"]
flz [label="Florent Thoumie\nflz@FreeBSD.org\n2006/03/30"]
@@ -314,6 +315,7 @@ jkh -> wes
jkh -> yar
jkoshy -> kaiw
+jkoshy -> fabient
jlemon -> bmilekic
jlemon -> brooks
diff --git a/share/misc/iso3166 b/share/misc/iso3166
index c6f65c0..2e952b3 100644
--- a/share/misc/iso3166
+++ b/share/misc/iso3166
@@ -13,7 +13,7 @@
# been deleted unless necessary to distinguish two countries.
#
# The ISO3166 Maintenance Agency can be found at:
-# http://www.iso.ch/iso/en/prods-services/iso3166ma/index.html
+# http://www.iso.org/iso/country_codes.htm
#
# two three number name
AF AFG 004 Afghanistan
@@ -43,7 +43,7 @@ BJ BEN 204 Benin
BM BMU 060 Bermuda
BT BTN 064 Bhutan
BO BOL 068 Bolivia
-BA BIH 070 Bosnia and Herzegowina
+BA BIH 070 Bosnia and Herzegovina
BW BWA 072 Botswana
BV BVT 074 Bouvet Island
BR BRA 076 Brazil
@@ -65,8 +65,8 @@ CX CXR 162 Christmas Island
CC CCK 166 Cocos (Keeling) Islands
CO COL 170 Colombia
KM COM 174 Comoros
-CG COG 178 Congo (Rep.)
-CD COD 180 Congo (Dem. Rep.)
+CG COG 178 Congo
+CD COD 180 Congo, the Democratic Republic of the
CK COK 184 Cook Islands
CR CRI 188 Costa Rica
CI CIV 384 Cote d'Ivoire
@@ -86,7 +86,7 @@ GQ GNQ 226 Equatorial Guinea
ER ERI 232 Eritrea
EE EST 233 Estonia
ET ETH 231 Ethiopia
-FK FLK 238 Falkland Islands
+FK FLK 238 Falkland Islands (Malvinas)
FO FRO 234 Faroe Islands
FJ FJI 242 Fiji
FI FIN 246 Finland
@@ -111,14 +111,14 @@ GN GIN 324 Guinea
GW GNB 624 Guinea-Bissau
GY GUY 328 Guyana
HT HTI 332 Haiti
-HM HMD 334 Heard and McDonald Islands
+HM HMD 334 Heard Island and McDonald Islands
HN HND 340 Honduras
HK HKG 344 Hong Kong
HU HUN 348 Hungary
IS ISL 352 Iceland
IN IND 356 India
ID IDN 360 Indonesia
-IR IRN 364 Iran
+IR IRN 364 Iran, Islamic Republic of
IQ IRQ 368 Iraq
IE IRL 372 Ireland
IM IMN 833 Isle of Man
@@ -131,8 +131,8 @@ JO JOR 400 Jordan
KZ KAZ 398 Kazakhstan
KE KEN 404 Kenya
KI KIR 296 Kiribati
-KP PRK 408 Korea (Democratic People's Republic of)
-KR KOR 410 Korea (Republic of)
+KP PRK 408 Korea, Democratic People's Republic of
+KR KOR 410 Korea, Republic of
KW KWT 414 Kuwait
KG KGZ 417 Kyrgyzstan
LA LAO 418 Lao People's Democratic Republic
@@ -145,7 +145,7 @@ LI LIE 438 Liechtenstein
LT LTU 440 Lithuania
LU LUX 442 Luxembourg
MO MAC 446 Macao
-MK MKD 807 Macedonia (The Former Yugoslav Republic of)
+MK MKD 807 Macedonia, the Former Yugoslav Republic of
MG MDG 450 Madagascar
MW MWI 454 Malawi
MY MYS 458 Malaysia
@@ -158,8 +158,8 @@ MR MRT 478 Mauritania
MU MUS 480 Mauritius
YT MYT 175 Mayotte
MX MEX 484 Mexico
-FM FSM 583 Micronesia (Federated States of)
-MD MDA 498 Moldova
+FM FSM 583 Micronesia, Federated States of
+MD MDA 498 Moldova, Republic of
MC MCO 492 Monaco
MN MNG 496 Mongolia
ME MNE 499 Montenegro
@@ -184,9 +184,9 @@ NO NOR 578 Norway
OM OMN 512 Oman
PK PAK 586 Pakistan
PW PLW 585 Palau
-PS PSE 275 Occupied Palestinian Territory
+PS PSE 275 Palestinian Territory, Occupied
PA PAN 591 Panama
-PG PNG 598 Papua-New Guinea
+PG PNG 598 Papua New Guinea
PY PRY 600 Paraguay
PE PER 604 Peru
PH PHL 608 Philippines
@@ -202,7 +202,7 @@ RW RWA 646 Rwanda
BL BLM 652 Saint Barthelemy
KN KNA 659 Saint Kitts and Nevis
LC LCA 662 Saint Lucia
-MF MAF 663 Saint Martin (French part)
+MF MAF 663 Saint Martin
VC VCT 670 Saint Vincent and the Grenadines
WS WSM 882 Samoa
SM SMR 674 San Marino
@@ -221,18 +221,18 @@ ZA ZAF 710 South Africa
GS SGS 239 South Georgia and the South Sandwich Islands
ES ESP 724 Spain
LK LKA 144 Sri Lanka
-SH SHN 654 St. Helena
-PM SPM 666 St. Pierre and Miquelon
+SH SHN 654 Saint Helena
+PM SPM 666 Saint Pierre and Miquelon
SD SDN 736 Sudan
SR SUR 740 Suriname
-SJ SJM 744 Svalbard and Jan Mayen Islands
+SJ SJM 744 Svalbard and Jan Mayen
SZ SWZ 748 Swaziland
SE SWE 752 Sweden
CH CHE 756 Switzerland
SY SYR 760 Syrian Arab Republic
-TW TWN 158 Taiwan
+TW TWN 158 Taiwan, Province of China
TJ TJK 762 Tajikistan
-TZ TZA 834 Tanzania
+TZ TZA 834 Tanzania, United Republic of
TH THA 764 Thailand
TG TGO 768 Togo
TK TKL 772 Tokelau
@@ -252,12 +252,12 @@ UM UMI 581 United States Minor Outlying Islands
UY URY 858 Uruguay
UZ UZB 860 Uzbekistan
VU VUT 548 Vanuatu
-VA VAT 336 Vatican City State
+VA VAT 336 Holy See (Vatican City State)
VE VEN 862 Venezuela
VN VNM 704 Viet Nam
-VG VGB 092 Virgin Islands (British)
-VI VIR 850 Virgin Islands (U.S.)
-WF WLF 876 Wallis and Futuna Islands
+VG VGB 092 Virgin Islands, British
+VI VIR 850 Virgin Islands, U.S.
+WF WLF 876 Wallis and Futuna
EH ESH 732 Western Sahara
YE YEM 887 Yemen
ZM ZMB 894 Zambia
diff --git a/share/misc/operator b/share/misc/operator
index b293f31..758737b 100644
--- a/share/misc/operator
+++ b/share/misc/operator
@@ -1,19 +1,21 @@
-Operator Associativity
------------------------------------------------------
-() [] -> . left to right
-! ~ ++ -- - (type) * & sizeof right to left
-* / % left to right
-+ - left to right
-<< >> left to right
-< <= > >= left to right
-== != left to right
-& left to right
-^ left to right
-| left to right
-&& left to right
-|| left to right
-?: right to left
-= += -= *= /= %= <<= >>= &= ^= |= right to left
-, left to right
+Operator Associativity
+-------------------------------------------------------------
+() [] -> . left to right
+! ~ ++ -- - (type) * & sizeof new delete right to left
+->* .* left to right
+* / % left to right
++ - left to right
+<< >> left to right
+< <= > >= left to right
+== != left to right
+& left to right
+^ left to right
+| left to right
+&& left to right
+|| left to right
+?: right to left
+= += -= *= /= %= <<= >>= &= ^= |= throw right to left
+?: (C++, third operand) right to left
+, left to right
$FreeBSD$
diff --git a/share/mk/bsd.cpu.mk b/share/mk/bsd.cpu.mk
index b1b06cf..8278d47 100644
--- a/share/mk/bsd.cpu.mk
+++ b/share/mk/bsd.cpu.mk
@@ -119,7 +119,7 @@ _CPUCFLAGS = -mcpu=${CPUTYPE}
MACHINE_CPU = booke
_CPUCFLAGS = -Wa,-me500 -msoft-float
. else
-_CPUCFLAGS = -mcpu=${CPUTYPE}
+_CPUCFLAGS = -mcpu=${CPUTYPE} -mno-powerpc64
. endif
. elif ${MACHINE_ARCH} == "mips"
. if ${CPUTYPE} == "mips32"
diff --git a/share/mk/bsd.own.mk b/share/mk/bsd.own.mk
index 7912430..a4523ba 100644
--- a/share/mk/bsd.own.mk
+++ b/share/mk/bsd.own.mk
@@ -372,7 +372,6 @@ WITH_IDEA=
SENDMAIL \
SETUID_LOGIN \
SHAREDOCS \
- SLIP \
SSP \
SYSINSTALL \
SYMVER \
diff --git a/share/mk/bsd.sys.mk b/share/mk/bsd.sys.mk
index 197c1d6..34e04f8 100644
--- a/share/mk/bsd.sys.mk
+++ b/share/mk/bsd.sys.mk
@@ -8,22 +8,23 @@
# for GCC: http://gcc.gnu.org/onlinedocs/gcc-3.0.4/gcc_3.html#IDX143
+# the default is gnu99 for now
+CSTD ?= gnu99
+
.if !defined(NO_WARNS) && ${CC} != "icc"
-. if defined(CSTD)
-. if ${CSTD} == "k&r"
+. if ${CSTD} == "k&r"
CFLAGS += -traditional
-. elif ${CSTD} == "c89" || ${CSTD} == "c90"
+. elif ${CSTD} == "c89" || ${CSTD} == "c90"
CFLAGS += -std=iso9899:1990
-. elif ${CSTD} == "c94" || ${CSTD} == "c95"
+. elif ${CSTD} == "c94" || ${CSTD} == "c95"
CFLAGS += -std=iso9899:199409
-. elif ${CSTD} == "c99"
+. elif ${CSTD} == "c99"
CFLAGS += -std=iso9899:1999
-. else
+. else
CFLAGS += -std=${CSTD}
-. endif
+. endif
# -pedantic is problematic because it also imposes namespace restrictions
#CFLAGS += -pedantic
-. endif
. if defined(WARNS)
. if ${WARNS} >= 1
CWARNFLAGS += -Wsystem-headers
diff --git a/share/skel/dot.login b/share/skel/dot.login
index 894021a..b8688f9 100644
--- a/share/skel/dot.login
+++ b/share/skel/dot.login
@@ -5,4 +5,4 @@
# see also csh(1), environ(7).
#
-[ -x /usr/games/fortune ] && /usr/games/fortune freebsd-tips
+if ( -x /usr/games/fortune ) /usr/games/fortune freebsd-tips
diff --git a/share/skel/dot.profile b/share/skel/dot.profile
index 2e1ca0c..3a8bd3e 100644
--- a/share/skel/dot.profile
+++ b/share/skel/dot.profile
@@ -21,4 +21,4 @@ PAGER=more; export PAGER
# set ENV to a file invoked each time sh is started for interactive use.
ENV=$HOME/.shrc; export ENV
-[ -x /usr/games/fortune ] && /usr/games/fortune freebsd-tips
+if [ -x /usr/games/fortune ] ; then /usr/games/fortune freebsd-tips ; fi
diff --git a/share/timedef/Makefile b/share/timedef/Makefile
index 12a2e4b..8178cff 100644
--- a/share/timedef/Makefile
+++ b/share/timedef/Makefile
@@ -126,10 +126,9 @@ GB2312_GBK= zh_CN
ISO8859-1_ISO8859-1= ${DE_LINKS} ${FR_LINKS} ${GB_LINKS} ${IT_LINKS} \
${NL_LINKS} ${NO_LINKS} en_US:af_ZA
ISO8859-1_ISO8859-15= ca_ES da_DK de_AT de_DE en_GB en_US es_ES eu_ES \
- fi_FI fr_FR is_IS it_IT la_LN nl_NL nn_NO no_NO pt_PT \
+ fi_FI fr_FR is_IS it_IT la_LN nb_NO nl_NL nn_NO no_NO pt_PT \
sv_SE \
- ${DE_LINKS} ${FR_LINKS} ${GB_LINKS} ${IT_LINKS} ${NL_LINKS} \
- ${NO_LINKS}
+ ${DE_LINKS} ${FR_LINKS} ${GB_LINKS} ${IT_LINKS} ${NL_LINKS}
ISO8859-1_US-ASCII= ${GB_LINKS} en_GB en_US la_LN
ISO8859-1_ISO8859-2= la_LN
ISO8859-1_ISO8859-4= la_LN
diff --git a/share/zoneinfo/africa b/share/zoneinfo/africa
index 34a62b9..0a6185d 100644
--- a/share/zoneinfo/africa
+++ b/share/zoneinfo/africa
@@ -1,4 +1,4 @@
-# @(#)africa 8.17
+# @(#)africa 8.18
# <pre>
# This data is by no means authoritative; if you think you know better,
@@ -564,6 +564,40 @@ Zone Indian/Mayotte 3:00:56 - LMT 1911 Jul # Mamoutzou
# <a href="http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html">
# http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html
# </a>
+
+# From Steffen Thorsen (2009-03-17):
+# Morocco will observe DST from 2009-06-01 00:00 to 2009-08-21 00:00 according
+# to many sources, such as
+# <a href="http://news.marweb.com/morocco/entertainment/morocco-daylight-saving.html">
+# http://news.marweb.com/morocco/entertainment/morocco-daylight-saving.html
+# </a>
+# <a href="http://www.medi1sat.ma/fr/depeche.aspx?idp=2312">
+# http://www.medi1sat.ma/fr/depeche.aspx?idp=2312
+# </a>
+# (French)
+#
+# Our summary:
+# <a href="http://www.timeanddate.com/news/time/morocco-starts-dst-2009.html">
+# http://www.timeanddate.com/news/time/morocco-starts-dst-2009.html
+# </a>
+
+# From Alexander Krivenyshev (2009-03-17):
+# Here is a link to official document from Royaume du Maroc Premier Ministre,
+# Ministere de la Modernisation des Secteurs Publics
+#
+# Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 june 1967)
+# concerning the amendment of the legal time, the Ministry of Modernization of
+# Public Sectors announced that the official time in the Kingdom will be
+# advanced 60 minutes from Sunday 31 May 2009 at midnight.
+#
+# <a href="http://www.mmsp.gov.ma/francais/Actualites_fr/PDF_Actualites_Fr/HeureEte_FR.pdf">
+# http://www.mmsp.gov.ma/francais/Actualites_fr/PDF_Actualites_Fr/HeureEte_FR.pdf
+# </a>
+#
+# <a href="http://www.worldtimezone.com/dst_news/dst_news_morocco03.html">
+# http://www.worldtimezone.com/dst_news/dst_news_morocco03.html
+# </a>
+
# RULE NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Morocco 1939 only - Sep 12 0:00 1:00 S
@@ -583,6 +617,8 @@ Rule Morocco 1978 only - Jun 1 0:00 1:00 S
Rule Morocco 1978 only - Aug 4 0:00 0 -
Rule Morocco 2008 only - Jun 1 0:00 1:00 S
Rule Morocco 2008 only - Sep 1 0:00 0 -
+Rule Morocco 2009 only - Jun 1 0:00 1:00 S
+Rule Morocco 2009 only - Aug 21 0:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Africa/Casablanca -0:30:20 - LMT 1913 Oct 26
0:00 Morocco WE%sT 1984 Mar 16
@@ -787,6 +823,43 @@ Zone Africa/Lome 0:04:52 - LMT 1893
# Ending : the last Sunday of October at 03:00 ...
# http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=1188&Itemid=50
+# From Steffen Thorsen (2009-03-16):
+# According to several news sources, Tunisia will not observe DST this year.
+# (Arabic)
+# <a href="http://www.elbashayer.com/?page=viewn&nid=42546">
+# http://www.elbashayer.com/?page=viewn&nid=42546
+# </a>
+# <a href="http://www.babnet.net/kiwidetail-15295.asp">
+# http://www.babnet.net/kiwidetail-15295.asp
+# </a>
+#
+# We have also confirmed this with the US embassy in Tunisia.
+# We have a wrap-up about this on the following page:
+# <a href="http://www.timeanddate.com/news/time/tunisia-cancels-dst-2009.html">
+# http://www.timeanddate.com/news/time/tunisia-cancels-dst-2009.html
+# </a>
+
+# From Alexander Krivenyshev (2009-03-17):
+# Here is a link to Tunis Afrique Presse News Agency
+#
+# Standard time to be kept the whole year long (tap.info.tn):
+#
+# (in English)
+# <a href="http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=26813&Itemid=157">
+# http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=26813&Itemid=157
+# </a>
+#
+# (in Arabic)
+# <a href="http://www.tap.info.tn/ar/index.php?option=com_content&task=view&id=61240&Itemid=1">
+# http://www.tap.info.tn/ar/index.php?option=com_content&task=view&id=61240&Itemid=1
+# </a>
+
+# From Arthur David Olson (2009--3-18):
+# The Tunis Afrique Presse News Agency notice contains this: "This measure is due to the fact
+# that the fasting month of ramadan coincides with the period concerned by summer time.
+# Therefore, the standard time will be kept unchanged the whole year long."
+# So foregoing DST seems to be an exception (albeit one that may be repeated in the future).
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Tunisia 1939 only - Apr 15 23:00s 1:00 S
Rule Tunisia 1939 only - Nov 18 23:00s 0 -
@@ -811,8 +884,10 @@ Rule Tunisia 1989 only - Mar 26 0:00s 1:00 S
Rule Tunisia 1990 only - May 1 0:00s 1:00 S
Rule Tunisia 2005 only - May 1 0:00s 1:00 S
Rule Tunisia 2005 only - Sep 30 1:00s 0 -
-Rule Tunisia 2006 max - Mar lastSun 2:00s 1:00 S
-Rule Tunisia 2006 max - Oct lastSun 2:00s 0 -
+Rule Tunisia 2006 2008 - Mar lastSun 2:00s 1:00 S
+Rule Tunisia 2006 2008 - Oct lastSun 2:00s 0 -
+Rule Tunisia 2010 max - Mar lastSun 2:00s 1:00 S
+Rule Tunisia 2010 max - Oct lastSun 2:00s 0 -
# Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
# more precise 0:09:21.
# Shanks & Pottenger say the 1911 switch was on Mar 9; go with Howse's Mar 11.
diff --git a/share/zoneinfo/asia b/share/zoneinfo/asia
index 7eedb2b..cc30cdb 100644
--- a/share/zoneinfo/asia
+++ b/share/zoneinfo/asia
@@ -1,4 +1,4 @@
-# @(#)asia 8.25
+# @(#)asia 8.26
# <pre>
# This data is by no means authoritative; if you think you know better,
@@ -1969,8 +1969,29 @@ Rule Syria 2007 only - Nov Fri>=1 0:00 0 -
# http://sana.sy/ara/2/2008/10/07/195459.htm
# </a>
-Rule Syria 2008 max - Apr Fri>=1 0:00 1:00 S
+# From Steffen Thorsen (2009-03-19):
+# Syria will start DST on 2009-03-27 00:00 this year according to many sources,
+# two examples:
+#
+# <a href="http://www.sana.sy/eng/21/2009/03/17/217563.htm">
+# http://www.sana.sy/eng/21/2009/03/17/217563.htm
+# </a>
+# (English, Syrian Arab News # Agency)
+# <a href="http://thawra.alwehda.gov.sy/_View_news2.asp?FileName=94459258720090318012209">
+# http://thawra.alwehda.gov.sy/_View_news2.asp?FileName=94459258720090318012209
+# </a>
+# (Arabic, gov-site)
+#
+# We have not found any sources saying anything about when DST ends this year.
+#
+# Our summary
+# <a href="http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html">
+# http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html
+# </a>
+
+Rule Syria 2008 only - Apr Fri>=1 0:00 1:00 S
Rule Syria 2008 max - Nov 1 0:00 0 -
+Rule Syria 2009 max - Mar lastFri 0:00 1:00 S
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Damascus 2:25:12 - LMT 1920 # Dimashq
diff --git a/share/zoneinfo/northamerica b/share/zoneinfo/northamerica
index 04a74c7..7fd6ea6 100644
--- a/share/zoneinfo/northamerica
+++ b/share/zoneinfo/northamerica
@@ -1,4 +1,4 @@
-# @(#)northamerica 8.26
+# @(#)northamerica 8.27
# <pre>
# also includes Central America and the Caribbean
@@ -2258,6 +2258,25 @@ Zone America/Costa_Rica -5:36:20 - LMT 1890 # San Jose
# From Arthur David Olson (2008-03-12):
# Assume Sun>=15 (third Sunday) going forward.
+# From Alexander Krivenyshev (2009-03-04)
+# According to the Radio Reloj - Cuba will start Daylight Saving Time on
+# midnight between Saturday, March 07, 2009 and Sunday, March 08, 2009-
+# not on midnight March 14 / March 15 as previously thought.
+#
+# <a href="http://www.worldtimezone.com/dst_news/dst_news_cuba05.html">
+# http://www.worldtimezone.com/dst_news/dst_news_cuba05.html
+# (in Spanish)
+# </a>
+
+# From Arthur David Olson (2009-03-09)
+# I listened over the Internet to
+# <a href="http://media.enet.cu/readioreloj">
+# http://media.enet.cu/readioreloj
+# </a>
+# this morning; when it was 10:05 a. m. here in Bethesda, Maryland the
+# the time was announced as "diez cinco"--the same time as here, indicating
+# that has indeed switched to DST. Assume second Sunday from 2009 forward.
+
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Cuba 1928 only - Jun 10 0:00 1:00 D
Rule Cuba 1928 only - Oct 10 0:00 0 S
@@ -2290,7 +2309,8 @@ Rule Cuba 1998 2003 - Oct lastSun 0:00s 0 S
Rule Cuba 2000 2004 - Apr Sun>=1 0:00s 1:00 D
Rule Cuba 2006 max - Oct lastSun 0:00s 0 S
Rule Cuba 2007 only - Mar Sun>=8 0:00s 1:00 D
-Rule Cuba 2008 max - Mar Sun>=15 0:00s 1:00 D
+Rule Cuba 2008 only - Mar Sun>=15 0:00s 1:00 D
+Rule Cuba 2009 max - Mar Sun>=8 0:00s 1:00 D
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone America/Havana -5:29:28 - LMT 1890
diff --git a/share/zoneinfo/southamerica b/share/zoneinfo/southamerica
index e882637..5824b7f 100644
--- a/share/zoneinfo/southamerica
+++ b/share/zoneinfo/southamerica
@@ -1,4 +1,4 @@
-# @(#)southamerica 8.33
+# @(#)southamerica 8.34
# <pre>
# This data is by no means authoritative; if you think you know better,
@@ -351,6 +351,50 @@ Rule Arg 2008 max - Oct Sun>=15 0:00 1:00 S
# keep America/Cordoba a single region rather than splitting it into the
# other 5 subregions.
+# From Mariano Absatz (2009-03-13):
+# Yesterday (with our usual 2-day notice) the Province of San Luis
+# decided that next Sunday instead of "staying" @utc-03:00 they will go
+# to utc-04:00 until the second Saturday in October...
+#
+# The press release is at
+# <a href="http://www.sanluis.gov.ar/SL/Paginas/NoticiaDetalle.asp?TemaId=1&InfoPrensaId=3102">
+# http://www.sanluis.gov.ar/SL/Paginas/NoticiaDetalle.asp?TemaId=1&InfoPrensaId=3102
+# </a>
+# (I couldn't find the decree, but
+# <a href="http://www.sanluis.gov.ar">
+# www.sanluis.gov.ar
+# <a/>
+# is the official page for the Province Government).
+#
+# There's also a note in only one of the major national papers (La Nación) at
+# <a href="http://www.lanacion.com.ar/nota.asp?nota_id=1107912">
+# http://www.lanacion.com.ar/nota.asp?nota_id=1107912
+# </a>
+#
+# The press release says:
+# (...) anunció que el próximo domingo a las 00:00 los puntanos deberán
+# atrasar una hora sus relojes.
+#
+# A partir de entonces, San Luis establecerá el huso horario propio de
+# la Provincia. De esta manera, durante el periodo del calendario anual
+# 2009, el cambio horario quedará comprendido entre las 00:00 del tercer
+# domingo de marzo y las 24:00 del segundo sábado de octubre.
+# Quick&dirty translation
+# (...) announced that next Sunday, at 00:00, Puntanos (the San Luis
+# inhabitants) will have to turn back one hour their clocks
+#
+# Since then, San Luis will establish its own Province timezone. Thus,
+# during 2009, this timezone change will run from 00:00 the third Sunday
+# in March until 24:00 of the second Saturday in October.
+
+# From Arthur David Olson (2009-03-16):
+# The unofficial claim at
+# <a href="http://www.timeanddate.com/news/time/san-luis-new-time-zone.html">
+# http://www.timeanddate.com/news/time/san-luis-new-time-zone.html
+# </a>
+# is that "The province will most likely follow the next daylight saving schedule,
+# which is planned for the second Sunday in October."
+
#
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
#
@@ -498,7 +542,8 @@ Zone America/Argentina/San_Luis -4:25:24 - LMT 1894 Oct 31
-3:00 - ART 2004 May 31
-4:00 - WART 2004 Jul 25
-3:00 Arg AR%sT 2008 Jan 21
- -3:00 - ART
+ -3:00 - ART 2009 Mar 15
+ -4:00 Arg WAR%sT
#
# Santa Cruz (SC)
Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
diff --git a/sys/amd64/acpica/Makefile b/sys/amd64/acpica/Makefile
new file mode 100644
index 0000000..7437280
--- /dev/null
+++ b/sys/amd64/acpica/Makefile
@@ -0,0 +1,33 @@
+# $FreeBSD$
+
+# Correct path for kernel builds
+# Don't rely on the kernel's .depend file
+.ifdef MAKESRCPATH
+.PATH: ${MAKESRCPATH}
+DEPENDFILE=
+.else
+MAKESRCPATH= ${.CURDIR}
+CLEANFILES= acpi_wakecode.h acpi_wakedata.h acpi_wakecode.bin acpi_wakecode.o
+.endif
+.if ${CC} == "icc"
+CFLAGS+= -restrict
+NOSTDINC= -X
+.else
+NOSTDINC= -nostdinc
+.endif
+CFLAGS+= ${NOSTDINC} -include opt_global.h -I. -I${MAKESRCPATH}/../..
+
+all: acpi_wakecode.h acpi_wakedata.h
+
+acpi_wakecode.o: acpi_wakecode.S assym.s
+
+acpi_wakecode.bin: acpi_wakecode.o
+ objcopy -S -O binary acpi_wakecode.o acpi_wakecode.bin
+
+acpi_wakecode.h: acpi_wakecode.bin
+ sh ${MAKESRCPATH}/genwakecode.sh > acpi_wakecode.h
+
+acpi_wakedata.h: acpi_wakecode.bin
+ sh ${MAKESRCPATH}/genwakedata.sh > acpi_wakedata.h
+
+.include <bsd.prog.mk>
diff --git a/sys/amd64/acpica/acpi_machdep.c b/sys/amd64/acpica/acpi_machdep.c
index e9e9235..c69f14a 100644
--- a/sys/amd64/acpica/acpi_machdep.c
+++ b/sys/amd64/acpica/acpi_machdep.c
@@ -31,25 +31,51 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/sysctl.h>
#include <contrib/dev/acpica/acpi.h>
#include <dev/acpica/acpivar.h>
#include <machine/nexusvar.h>
+SYSCTL_DECL(_debug_acpi);
+
+int acpi_resume_beep;
+TUNABLE_INT("debug.acpi.resume_beep", &acpi_resume_beep);
+SYSCTL_INT(_debug_acpi, OID_AUTO, resume_beep, CTLFLAG_RW, &acpi_resume_beep,
+ 0, "Beep the PC speaker when resuming");
+
+int acpi_reset_video;
+TUNABLE_INT("hw.acpi.reset_video", &acpi_reset_video);
+
static int intr_model = ACPI_INTR_PIC;
+static struct apm_clone_data acpi_clone;
int
acpi_machdep_init(device_t dev)
{
- struct acpi_softc *sc;
+ struct acpi_softc *sc;
sc = devclass_get_softc(devclass_find("acpi"), 0);
+
+ /* Create a fake clone for /dev/acpi. */
+ STAILQ_INIT(&sc->apm_cdevs);
+ acpi_clone.cdev = sc->acpi_dev_t;
+ acpi_clone.acpi_sc = sc;
+ ACPI_LOCK(acpi);
+ STAILQ_INSERT_TAIL(&sc->apm_cdevs, &acpi_clone, entries);
+ ACPI_UNLOCK(acpi);
+ sc->acpi_clone = &acpi_clone;
acpi_install_wakeup_handler(sc);
if (intr_model != ACPI_INTR_PIC)
acpi_SetIntrModel(intr_model);
+ SYSCTL_ADD_UINT(&sc->acpi_sysctl_ctx,
+ SYSCTL_CHILDREN(sc->acpi_sysctl_tree), OID_AUTO,
+ "reset_video", CTLFLAG_RW, &acpi_reset_video, 0,
+ "Call the VESA reset BIOS vector on the resume path");
+
return (0);
}
diff --git a/sys/amd64/acpica/acpi_switch.S b/sys/amd64/acpica/acpi_switch.S
new file mode 100644
index 0000000..892dd11
--- /dev/null
+++ b/sys/amd64/acpica/acpi_switch.S
@@ -0,0 +1,190 @@
+/*-
+ * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
+ * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
+ * Copyright (c) 2008-2009 Jung-uk Kim <jkim@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asmacros.h>
+#include <machine/specialreg.h>
+
+#include "acpi_wakedata.h"
+#include "assym.s"
+
+#define WAKEUP_DECL(member) \
+ .set WAKEUP_ ## member, wakeup_ ## member - wakeup_ctx
+
+ WAKEUP_DECL(xpcb)
+ WAKEUP_DECL(gdt)
+ WAKEUP_DECL(efer)
+ WAKEUP_DECL(pat)
+ WAKEUP_DECL(star)
+ WAKEUP_DECL(lstar)
+ WAKEUP_DECL(cstar)
+ WAKEUP_DECL(sfmask)
+ WAKEUP_DECL(cpu)
+
+#define WAKEUP_CTX(member) WAKEUP_ ## member (%rdi)
+#define WAKEUP_PCB(member) PCB_ ## member(%r11)
+#define WAKEUP_XPCB(member) XPCB_ ## member(%r11)
+
+ENTRY(acpi_restorecpu)
+ /* Switch to KPML4phys. */
+ movq %rsi, %rax
+ movq %rax, %cr3
+
+ /* Restore GDT. */
+ lgdt WAKEUP_CTX(gdt)
+ jmp 1f
+1:
+
+ /* Fetch PCB. */
+ movq WAKEUP_CTX(xpcb), %r11
+
+ /* Force kernel segment registers. */
+ movl $KDSEL, %eax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movl $KUF32SEL, %eax
+ movw %ax, %fs
+ movl $KUG32SEL, %eax
+ movw %ax, %gs
+
+ movl $MSR_FSBASE, %ecx
+ movl WAKEUP_PCB(FSBASE), %eax
+ movl 4 + WAKEUP_PCB(FSBASE), %edx
+ wrmsr
+ movl $MSR_GSBASE, %ecx
+ movl WAKEUP_PCB(GSBASE), %eax
+ movl 4 + WAKEUP_PCB(GSBASE), %edx
+ wrmsr
+ movl $MSR_KGSBASE, %ecx
+ movl WAKEUP_XPCB(KGSBASE), %eax
+ movl 4 + WAKEUP_XPCB(KGSBASE), %edx
+ wrmsr
+
+ /* Restore EFER. */
+ movl $MSR_EFER, %ecx
+ movl WAKEUP_CTX(efer), %eax
+ wrmsr
+
+ /* Restore PAT. */
+ movl $MSR_PAT, %ecx
+ movl WAKEUP_CTX(pat), %eax
+ movl 4 + WAKEUP_CTX(pat), %edx
+ wrmsr
+
+ /* Restore fast syscall stuff. */
+ movl $MSR_STAR, %ecx
+ movl WAKEUP_CTX(star), %eax
+ movl 4 + WAKEUP_CTX(star), %edx
+ wrmsr
+ movl $MSR_LSTAR, %ecx
+ movl WAKEUP_CTX(lstar), %eax
+ movl 4 + WAKEUP_CTX(lstar), %edx
+ wrmsr
+ movl $MSR_CSTAR, %ecx
+ movl WAKEUP_CTX(cstar), %eax
+ movl 4 + WAKEUP_CTX(cstar), %edx
+ wrmsr
+ movl $MSR_SF_MASK, %ecx
+ movl WAKEUP_CTX(sfmask), %eax
+ wrmsr
+
+ /* Restore CR0, CR2 and CR4. */
+ movq WAKEUP_XPCB(CR0), %rax
+ movq %rax, %cr0
+ movq WAKEUP_XPCB(CR2), %rax
+ movq %rax, %cr2
+ movq WAKEUP_XPCB(CR4), %rax
+ movq %rax, %cr4
+
+ /* Restore descriptor tables. */
+ lidt WAKEUP_XPCB(IDT)
+ lldt WAKEUP_XPCB(LDT)
+
+#define SDT_SYSTSS 9
+#define SDT_SYSBSY 11
+
+ /* Clear "task busy" bit and reload TR. */
+ movq PCPU(TSS), %rax
+ andb $(~SDT_SYSBSY | SDT_SYSTSS), 5(%rax)
+ movw WAKEUP_XPCB(TR), %ax
+ ltr %ax
+
+#undef SDT_SYSTSS
+#undef SDT_SYSBSY
+
+ /* Restore other callee saved registers. */
+ movq WAKEUP_PCB(R15), %r15
+ movq WAKEUP_PCB(R14), %r14
+ movq WAKEUP_PCB(R13), %r13
+ movq WAKEUP_PCB(R12), %r12
+ movq WAKEUP_PCB(RBP), %rbp
+ movq WAKEUP_PCB(RSP), %rsp
+ movq WAKEUP_PCB(RBX), %rbx
+
+ /* Restore debug registers. */
+ movq WAKEUP_PCB(DR0), %rax
+ movq %rax, %dr0
+ movq WAKEUP_PCB(DR1), %rax
+ movq %rax, %dr1
+ movq WAKEUP_PCB(DR2), %rax
+ movq %rax, %dr2
+ movq WAKEUP_PCB(DR3), %rax
+ movq %rax, %dr3
+ movq WAKEUP_PCB(DR6), %rax
+ movq %rax, %dr6
+ movq WAKEUP_PCB(DR7), %rax
+ movq %rax, %dr7
+
+ /* Restore return address. */
+ movq WAKEUP_PCB(RIP), %rax
+ movq %rax, (%rsp)
+
+ /* Indicate the CPU is resumed. */
+ xorl %eax, %eax
+ movl %eax, WAKEUP_CTX(cpu)
+
+ ret
+END(acpi_restorecpu)
+
+ENTRY(acpi_savecpu)
+ /* Fetch XPCB and save CPU context. */
+ movq %rdi, %r10
+ call savectx2
+ movq %r10, %r11
+
+ /* Patch caller's return address and stack pointer. */
+ movq (%rsp), %rax
+ movq %rax, WAKEUP_PCB(RIP)
+ movq %rsp, %rax
+ movq %rax, WAKEUP_PCB(RSP)
+
+ movl $1, %eax
+ ret
+END(acpi_savecpu)
diff --git a/sys/amd64/acpica/acpi_wakecode.S b/sys/amd64/acpica/acpi_wakecode.S
new file mode 100644
index 0000000..4e82f53
--- /dev/null
+++ b/sys/amd64/acpica/acpi_wakecode.S
@@ -0,0 +1,286 @@
+/*-
+ * Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
+ * Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
+ * Copyright (c) 2003 Peter Wemm
+ * Copyright (c) 2008-2009 Jung-uk Kim <jkim@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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$
+ */
+
+#define LOCORE
+
+#include <machine/asmacros.h>
+#include <machine/specialreg.h>
+
+#include "assym.s"
+
+/*
+ * Resume entry point for real mode.
+ *
+ * If XFirmwareWakingVector is zero and FirmwareWakingVector is non-zero
+ * in FACS, the BIOS enters here in real mode after POST with CS set to
+ * (FirmwareWakingVector >> 4) and IP set to (FirmwareWakingVector & 0xf).
+ * Depending on the previous sleep state, we may need to initialize more
+ * of the system (i.e., S3 suspend-to-RAM vs. S4 suspend-to-disk).
+ *
+ * Note: If XFirmwareWakingVector is non-zero, it should disable address
+ * translation/paging and interrupts, load all segment registers with
+ * a flat 4 GB address space, and set EFLAGS.IF to zero. Currently
+ * this mode is not supported by this code.
+ */
+
+ .data /* So we can modify it */
+
+ ALIGN_TEXT
+wakeup_start:
+ .code16
+ /*
+ * Set up segment registers for real mode, a small stack for
+ * any calls we make, and clear any flags.
+ */
+ cli /* make sure no interrupts */
+ cld
+ mov %cs, %ax /* copy %cs to %ds. Remember these */
+ mov %ax, %ds /* are offsets rather than selectors */
+ mov %ax, %ss
+ movw $PAGE_SIZE - 8, %sp
+ xorw %ax, %ax
+ pushw %ax
+ popfw
+
+ /* To debug resume hangs, beep the speaker if the user requested. */
+ testb $~0, resume_beep - wakeup_start
+ jz 1f
+ movb $0, resume_beep - wakeup_start
+ movb $0xc0, %al
+ outb %al, $0x42
+ movb $0x04, %al
+ outb %al, $0x42
+ inb $0x61, %al
+ orb $0x3, %al
+ outb %al, $0x61
+1:
+
+ /* Re-initialize video BIOS if the reset_video tunable is set. */
+ testb $~0, reset_video - wakeup_start
+ jz 1f
+ movb $0, reset_video - wakeup_start
+ lcall $0xc000, $3
+
+ /* Re-start in case the previous BIOS call clobbers them. */
+ jmp wakeup_start
+1:
+
+ /*
+ * Find relocation base and patch the gdt descript and ljmp targets
+ */
+ xorl %ebx, %ebx
+ mov %cs, %bx
+ sall $4, %ebx /* %ebx is now our relocation base */
+
+ /*
+ * Load the descriptor table pointer. We'll need it when running
+ * in 16-bit protected mode.
+ */
+ lgdtl bootgdtdesc - wakeup_start
+
+ /* Enable protected mode */
+ movl $CR0_PE, %eax
+ mov %eax, %cr0
+
+ /*
+ * Now execute a far jump to turn on protected mode. This
+ * causes the segment registers to turn into selectors and causes
+ * %cs to be loaded from the gdt.
+ *
+ * The following instruction is:
+ * ljmpl $bootcode32 - bootgdt, $wakeup_32 - wakeup_start
+ * but gas cannot assemble that. And besides, we patch the targets
+ * in early startup and its a little clearer what we are patching.
+ */
+wakeup_sw32:
+ .byte 0x66 /* size override to 32 bits */
+ .byte 0xea /* opcode for far jump */
+ .long wakeup_32 - wakeup_start /* offset in segment */
+ .word bootcode32 - bootgdt /* index in gdt for 32 bit code */
+
+ /*
+ * At this point, we are running in 32 bit legacy protected mode.
+ */
+ .code32
+wakeup_32:
+
+ mov $bootdata32 - bootgdt, %eax
+ mov %ax, %ds
+
+ /* Turn on the PAE and PSE bits for when paging is enabled */
+ mov %cr4, %eax
+ orl $(CR4_PAE | CR4_PSE), %eax
+ mov %eax, %cr4
+
+ /*
+ * Enable EFER.LME so that we get long mode when all the prereqs are
+ * in place. In this case, it turns on when CR0_PG is finally enabled.
+ * Pick up a few other EFER bits that we'll use need we're here.
+ */
+ movl $MSR_EFER, %ecx
+ rdmsr
+ orl $EFER_LME | EFER_SCE, %eax
+ wrmsr
+
+ /*
+ * Point to the embedded page tables for startup. Note that this
+ * only gets accessed after we're actually in 64 bit mode, however
+ * we can only set the bottom 32 bits of %cr3 in this state. This
+ * means we are required to use a temporary page table that is below
+ * the 4GB limit. %ebx is still our relocation base. We could just
+ * subtract 3 * PAGE_SIZE, but that would be too easy.
+ */
+ leal wakeup_pagetables - wakeup_start(%ebx), %eax
+ movl (%eax), %eax
+ mov %eax, %cr3
+
+ /*
+ * Finally, switch to long bit mode by enabling paging. We have
+ * to be very careful here because all the segmentation disappears
+ * out from underneath us. The spec says we can depend on the
+ * subsequent pipelined branch to execute, but *only if* everthing
+ * is still identity mapped. If any mappings change, the pipeline
+ * will flush.
+ */
+ mov %cr0, %eax
+ orl $CR0_PG, %eax
+ mov %eax, %cr0
+
+ /*
+ * At this point paging is enabled, and we are in "compatability" mode.
+ * We do another far jump to reload %cs with the 64 bit selector.
+ * %cr3 points to a 4-level page table page.
+ * We cannot yet jump all the way to the kernel because we can only
+ * specify a 32 bit linear address. So, yet another trampoline.
+ *
+ * The following instruction is:
+ * ljmp $bootcode64 - bootgdt, $wakeup_64 - wakeup_start
+ * but gas cannot assemble that. And besides, we patch the targets
+ * in early startup and its a little clearer what we are patching.
+ */
+wakeup_sw64:
+ .byte 0xea /* opcode for far jump */
+ .long wakeup_64 - wakeup_start /* offset in segment */
+ .word bootcode64 - bootgdt /* index in gdt for 64 bit code */
+
+ /*
+ * Yeehar! We're running in 64-bit mode! We can mostly ignore our
+ * segment registers, and get on with it.
+ * Note that we are running at the correct virtual address, but with
+ * a 1:1 1GB mirrored mapping over entire address space. We had better
+ * switch to a real %cr3 promptly so that we can get to the direct map
+ * space. Remember that jmp is relative and that we've been relocated,
+ * so use an indirect jump.
+ */
+ ALIGN_TEXT
+ .code64
+wakeup_64:
+ mov $bootdata64 - bootgdt, %eax
+ mov %ax, %ds
+
+ /* Restore arguments and return. */
+ movq wakeup_ctx - wakeup_start(%rbx), %rdi
+ movq wakeup_kpml4 - wakeup_start(%rbx), %rsi
+ movq wakeup_retaddr - wakeup_start(%rbx), %rax
+ jmp *%rax
+
+ .data
+
+resume_beep:
+ .byte 0
+reset_video:
+ .byte 0
+
+ ALIGN_DATA
+bootgdt:
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x00000000
+
+bootcode64:
+ .long 0x0000ffff
+ .long 0x00af9b00
+
+bootdata64:
+ .long 0x0000ffff
+ .long 0x00af9300
+
+bootcode32:
+ .long 0x0000ffff
+ .long 0x00cf9b00
+
+bootdata32:
+ .long 0x0000ffff
+ .long 0x00cf9300
+bootgdtend:
+
+wakeup_pagetables:
+ .long 0
+
+bootgdtdesc:
+ .word bootgdtend - bootgdt /* Length */
+ .long bootgdt - wakeup_start /* Offset plus %ds << 4 */
+
+ ALIGN_DATA
+wakeup_retaddr:
+ .quad 0
+wakeup_kpml4:
+ .quad 0
+
+wakeup_ctx:
+ .quad 0
+wakeup_xpcb:
+ .quad 0
+wakeup_gdt:
+ .word 0
+ .quad 0
+
+ ALIGN_DATA
+wakeup_efer:
+ .quad 0
+wakeup_pat:
+ .quad 0
+wakeup_star:
+ .quad 0
+wakeup_lstar:
+ .quad 0
+wakeup_cstar:
+ .quad 0
+wakeup_sfmask:
+ .quad 0
+wakeup_cpu:
+ .long 0
+dummy:
diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c
index 53868e4..2f9d8a0 100644
--- a/sys/amd64/acpica/acpi_wakeup.c
+++ b/sys/amd64/acpica/acpi_wakeup.c
@@ -1,6 +1,8 @@
/*-
* Copyright (c) 2001 Takanori Watanabe <takawata@jp.freebsd.org>
* Copyright (c) 2001 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
+ * Copyright (c) 2003 Peter Wemm
+ * Copyright (c) 2008-2009 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,18 +31,390 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/systm.h>
#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/memrange.h>
+#include <sys/smp.h>
+#include <sys/types.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/intr_machdep.h>
+#include <machine/pcb.h>
+#include <machine/pmap.h>
+#include <machine/specialreg.h>
+#include <machine/vmparam.h>
+
+#ifdef SMP
+#include <machine/apicreg.h>
+#include <machine/smp.h>
+#endif
#include <contrib/dev/acpica/acpi.h>
#include <dev/acpica/acpivar.h>
+#include "acpi_wakecode.h"
+#include "acpi_wakedata.h"
+
+/* Make sure the code is less than a page and leave room for the stack. */
+CTASSERT(sizeof(wakecode) < PAGE_SIZE - 1024);
+
+#ifndef _SYS_CDEFS_H_
+#error this file needs sys/cdefs.h as a prerequisite
+#endif
+
+extern int acpi_resume_beep;
+extern int acpi_reset_video;
+
+#ifdef SMP
+extern struct xpcb *stopxpcbs;
+#else
+static struct xpcb *stopxpcbs;
+#endif
+
+int acpi_restorecpu(struct xpcb *, vm_offset_t);
+int acpi_savecpu(struct xpcb *);
+
+static void acpi_alloc_wakeup_handler(void);
+static void acpi_stop_beep(void *);
+
+#ifdef SMP
+static int acpi_wakeup_ap(struct acpi_softc *, int);
+static void acpi_wakeup_cpus(struct acpi_softc *, cpumask_t);
+#endif
+
+#define WAKECODE_VADDR(sc) ((sc)->acpi_wakeaddr + (3 * PAGE_SIZE))
+#define WAKECODE_PADDR(sc) ((sc)->acpi_wakephys + (3 * PAGE_SIZE))
+#define WAKECODE_FIXUP(offset, type, val) do { \
+ type *addr; \
+ addr = (type *)(WAKECODE_VADDR(sc) + offset); \
+ *addr = val; \
+} while (0)
+
+/* Turn off bits 1&2 of the PIT, stopping the beep. */
+static void
+acpi_stop_beep(void *arg)
+{
+ outb(0x61, inb(0x61) & ~0x3);
+}
+
+#ifdef SMP
+static int
+acpi_wakeup_ap(struct acpi_softc *sc, int cpu)
+{
+ int vector = (WAKECODE_PADDR(sc) >> 12) & 0xff;
+ int apic_id = cpu_apic_ids[cpu];
+ int ms;
+
+ WAKECODE_FIXUP(wakeup_xpcb, struct xpcb *, &stopxpcbs[cpu]);
+ WAKECODE_FIXUP(wakeup_gdt, uint16_t, stopxpcbs[cpu].xpcb_gdt.rd_limit);
+ WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t,
+ stopxpcbs[cpu].xpcb_gdt.rd_base);
+ WAKECODE_FIXUP(wakeup_cpu, int, cpu);
+
+ /* do an INIT IPI: assert RESET */
+ lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
+ APIC_LEVEL_ASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, apic_id);
+
+ /* wait for pending status end */
+ lapic_ipi_wait(-1);
+
+ /* do an INIT IPI: deassert RESET */
+ lapic_ipi_raw(APIC_DEST_ALLESELF | APIC_TRIGMOD_LEVEL |
+ APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_INIT, 0);
+
+ /* wait for pending status end */
+ DELAY(10000); /* wait ~10mS */
+ lapic_ipi_wait(-1);
+
+ /*
+ * next we do a STARTUP IPI: the previous INIT IPI might still be
+ * latched, (P5 bug) this 1st STARTUP would then terminate
+ * immediately, and the previously started INIT IPI would continue. OR
+ * the previous INIT IPI has already run. and this STARTUP IPI will
+ * run. OR the previous INIT IPI was ignored. and this STARTUP IPI
+ * will run.
+ */
+
+ /* do a STARTUP IPI */
+ lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
+ APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
+ vector, apic_id);
+ lapic_ipi_wait(-1);
+ DELAY(200); /* wait ~200uS */
+
+ /*
+ * finally we do a 2nd STARTUP IPI: this 2nd STARTUP IPI should run IF
+ * the previous STARTUP IPI was cancelled by a latched INIT IPI. OR
+ * this STARTUP IPI will be ignored, as only ONE STARTUP IPI is
+ * recognized after hardware RESET or INIT IPI.
+ */
+
+ lapic_ipi_raw(APIC_DEST_DESTFLD | APIC_TRIGMOD_EDGE |
+ APIC_LEVEL_DEASSERT | APIC_DESTMODE_PHY | APIC_DELMODE_STARTUP |
+ vector, apic_id);
+ lapic_ipi_wait(-1);
+ DELAY(200); /* wait ~200uS */
+
+ /* Wait up to 5 seconds for it to start. */
+ for (ms = 0; ms < 5000; ms++) {
+ if (*(int *)(WAKECODE_VADDR(sc) + wakeup_cpu) == 0)
+ return (1); /* return SUCCESS */
+ DELAY(1000);
+ }
+ return (0); /* return FAILURE */
+}
+
+#define WARMBOOT_TARGET 0
+#define WARMBOOT_OFF (KERNBASE + 0x0467)
+#define WARMBOOT_SEG (KERNBASE + 0x0469)
+
+#define CMOS_REG (0x70)
+#define CMOS_DATA (0x71)
+#define BIOS_RESET (0x0f)
+#define BIOS_WARM (0x0a)
+
+static void
+acpi_wakeup_cpus(struct acpi_softc *sc, cpumask_t wakeup_cpus)
+{
+ uint32_t mpbioswarmvec;
+ cpumask_t map;
+ int cpu;
+ u_char mpbiosreason;
+
+ /* save the current value of the warm-start vector */
+ mpbioswarmvec = *((uint32_t *)WARMBOOT_OFF);
+ outb(CMOS_REG, BIOS_RESET);
+ mpbiosreason = inb(CMOS_DATA);
+
+ /* setup a vector to our boot code */
+ *((volatile u_short *)WARMBOOT_OFF) = WARMBOOT_TARGET;
+ *((volatile u_short *)WARMBOOT_SEG) = WAKECODE_PADDR(sc) >> 4;
+ outb(CMOS_REG, BIOS_RESET);
+ outb(CMOS_DATA, BIOS_WARM); /* 'warm-start' */
+
+ /* Wake up each AP. */
+ for (cpu = 1; cpu < mp_ncpus; cpu++) {
+ map = 1ul << cpu;
+ if ((wakeup_cpus & map) != map)
+ continue;
+ if (acpi_wakeup_ap(sc, cpu) == 0) {
+ /* restore the warmstart vector */
+ *(uint32_t *)WARMBOOT_OFF = mpbioswarmvec;
+ panic("acpi_wakeup: failed to resume AP #%d (PHY #%d)",
+ cpu, cpu_apic_ids[cpu]);
+ }
+ }
+
+ /* restore the warmstart vector */
+ *(uint32_t *)WARMBOOT_OFF = mpbioswarmvec;
+
+ outb(CMOS_REG, BIOS_RESET);
+ outb(CMOS_DATA, mpbiosreason);
+}
+#endif
+
int
acpi_sleep_machdep(struct acpi_softc *sc, int state)
{
- return (0);
+ struct savefpu *stopfpu;
+#ifdef SMP
+ cpumask_t wakeup_cpus;
+#endif
+ register_t cr3, rf;
+ ACPI_STATUS status;
+ int ret;
+
+ ret = -1;
+
+ if (sc->acpi_wakeaddr == 0ul)
+ return (ret);
+
+#ifdef SMP
+ wakeup_cpus = PCPU_GET(other_cpus);
+#endif
+
+ AcpiSetFirmwareWakingVector(WAKECODE_PADDR(sc));
+
+ rf = intr_disable();
+ intr_suspend();
+
+ /*
+ * Temporarily switch to the kernel pmap because it provides
+ * an identity mapping (setup at boot) for the low physical
+ * memory region containing the wakeup code.
+ */
+ cr3 = rcr3();
+ load_cr3(KPML4phys);
+
+ stopfpu = &stopxpcbs[0].xpcb_pcb.pcb_save;
+ if (acpi_savecpu(&stopxpcbs[0])) {
+ fpugetregs(curthread, stopfpu);
+
+#ifdef SMP
+ if (wakeup_cpus != 0 && suspend_cpus(wakeup_cpus) == 0) {
+ device_printf(sc->acpi_dev,
+ "Failed to suspend APs: CPU mask = 0x%jx\n",
+ (uintmax_t)(wakeup_cpus & ~stopped_cpus));
+ goto out;
+ }
+#endif
+
+ WAKECODE_FIXUP(resume_beep, uint8_t, (acpi_resume_beep != 0));
+ WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));
+
+ WAKECODE_FIXUP(wakeup_xpcb, struct xpcb *, &stopxpcbs[0]);
+ WAKECODE_FIXUP(wakeup_gdt, uint16_t,
+ stopxpcbs[0].xpcb_gdt.rd_limit);
+ WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t,
+ stopxpcbs[0].xpcb_gdt.rd_base);
+ WAKECODE_FIXUP(wakeup_cpu, int, 0);
+
+ /* Call ACPICA to enter the desired sleep state */
+ if (state == ACPI_STATE_S4 && sc->acpi_s4bios)
+ status = AcpiEnterSleepStateS4bios();
+ else
+ status = AcpiEnterSleepState(state);
+
+ if (status != AE_OK) {
+ device_printf(sc->acpi_dev,
+ "AcpiEnterSleepState failed - %s\n",
+ AcpiFormatException(status));
+ goto out;
+ }
+
+ for (;;)
+ ia32_pause();
+ } else {
+ fpusetregs(curthread, stopfpu);
+#ifdef SMP
+ if (wakeup_cpus != 0)
+ acpi_wakeup_cpus(sc, wakeup_cpus);
+#endif
+ acpi_resync_clock(sc);
+ ret = 0;
+ }
+
+out:
+#ifdef SMP
+ if (wakeup_cpus != 0)
+ restart_cpus(wakeup_cpus);
+#endif
+
+ load_cr3(cr3);
+ intr_resume();
+ intr_restore(rf);
+
+ AcpiSetFirmwareWakingVector(0);
+
+ if (ret == 0 && mem_range_softc.mr_op != NULL &&
+ mem_range_softc.mr_op->reinit != NULL)
+ mem_range_softc.mr_op->reinit(&mem_range_softc);
+
+ /* If we beeped, turn it off after a delay. */
+ if (acpi_resume_beep)
+ timeout(acpi_stop_beep, NULL, 3 * hz);
+
+ return (ret);
}
+static vm_offset_t acpi_wakeaddr;
+
+static void
+acpi_alloc_wakeup_handler(void)
+{
+ void *wakeaddr;
+
+ if (!cold)
+ return;
+
+ /*
+ * Specify the region for our wakeup code. We want it in the low 1 MB
+ * region, excluding video memory and above (0xa0000). We ask for
+ * it to be page-aligned, just to be safe.
+ */
+ wakeaddr = contigmalloc(4 * PAGE_SIZE, M_DEVBUF, M_NOWAIT, 0, 0x9ffff,
+ PAGE_SIZE, 0ul);
+ if (wakeaddr == NULL) {
+ printf("%s: can't alloc wake memory\n", __func__);
+ return;
+ }
+ stopxpcbs = malloc(mp_ncpus * sizeof(*stopxpcbs), M_DEVBUF, M_NOWAIT);
+ if (stopxpcbs == NULL) {
+ contigfree(wakeaddr, 4 * PAGE_SIZE, M_DEVBUF);
+ printf("%s: can't alloc CPU state memory\n", __func__);
+ return;
+ }
+ acpi_wakeaddr = (vm_offset_t)wakeaddr;
+}
+
+SYSINIT(acpiwakeup, SI_SUB_KMEM, SI_ORDER_ANY, acpi_alloc_wakeup_handler, 0);
+
void
acpi_install_wakeup_handler(struct acpi_softc *sc)
{
+ uint64_t *pt4, *pt3, *pt2;
+ int i;
+
+ if (acpi_wakeaddr == 0ul)
+ return;
+
+ sc->acpi_wakeaddr = acpi_wakeaddr;
+ sc->acpi_wakephys = vtophys(acpi_wakeaddr);
+
+ bcopy(wakecode, (void *)WAKECODE_VADDR(sc), sizeof(wakecode));
+
+ /* Patch GDT base address, ljmp targets and page table base address. */
+ WAKECODE_FIXUP((bootgdtdesc + 2), uint32_t,
+ WAKECODE_PADDR(sc) + bootgdt);
+ WAKECODE_FIXUP((wakeup_sw32 + 2), uint32_t,
+ WAKECODE_PADDR(sc) + wakeup_32);
+ WAKECODE_FIXUP((wakeup_sw64 + 1), uint32_t,
+ WAKECODE_PADDR(sc) + wakeup_64);
+ WAKECODE_FIXUP(wakeup_pagetables, uint32_t, sc->acpi_wakephys);
+
+ /* Save pointers to some global data. */
+ WAKECODE_FIXUP(wakeup_retaddr, void *, acpi_restorecpu);
+ WAKECODE_FIXUP(wakeup_kpml4, uint64_t, KPML4phys);
+ WAKECODE_FIXUP(wakeup_ctx, vm_offset_t,
+ WAKECODE_VADDR(sc) + wakeup_ctx);
+ WAKECODE_FIXUP(wakeup_efer, uint64_t, rdmsr(MSR_EFER));
+ WAKECODE_FIXUP(wakeup_pat, uint64_t, rdmsr(MSR_PAT));
+ WAKECODE_FIXUP(wakeup_star, uint64_t, rdmsr(MSR_STAR));
+ WAKECODE_FIXUP(wakeup_lstar, uint64_t, rdmsr(MSR_LSTAR));
+ WAKECODE_FIXUP(wakeup_cstar, uint64_t, rdmsr(MSR_CSTAR));
+ WAKECODE_FIXUP(wakeup_sfmask, uint64_t, rdmsr(MSR_SF_MASK));
+
+ /* Build temporary page tables below realmode code. */
+ pt4 = (uint64_t *)acpi_wakeaddr;
+ pt3 = pt4 + (PAGE_SIZE) / sizeof(uint64_t);
+ pt2 = pt3 + (PAGE_SIZE) / sizeof(uint64_t);
+
+ /* Create the initial 1GB replicated page tables */
+ for (i = 0; i < 512; i++) {
+ /*
+ * Each slot of the level 4 pages points
+ * to the same level 3 page
+ */
+ pt4[i] = (uint64_t)(sc->acpi_wakephys + PAGE_SIZE);
+ pt4[i] |= PG_V | PG_RW | PG_U;
+
+ /*
+ * Each slot of the level 3 pages points
+ * to the same level 2 page
+ */
+ pt3[i] = (uint64_t)(sc->acpi_wakephys + (2 * PAGE_SIZE));
+ pt3[i] |= PG_V | PG_RW | PG_U;
+
+ /* The level 2 page slots are mapped with 2MB pages for 1GB. */
+ pt2[i] = i * (2 * 1024 * 1024);
+ pt2[i] |= PG_V | PG_RW | PG_PS | PG_U;
+ }
+
+ if (bootverbose)
+ device_printf(sc->acpi_dev, "wakeup code va %p pa %p\n",
+ (void *)sc->acpi_wakeaddr, (void *)sc->acpi_wakephys);
}
diff --git a/sys/amd64/acpica/genwakecode.sh b/sys/amd64/acpica/genwakecode.sh
new file mode 100755
index 0000000..c9d0077
--- /dev/null
+++ b/sys/amd64/acpica/genwakecode.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+# $FreeBSD$
+#
+file2c -sx 'static char wakecode[] = {' '};' <acpi_wakecode.bin
+
+exit 0
diff --git a/sys/amd64/acpica/genwakedata.sh b/sys/amd64/acpica/genwakedata.sh
new file mode 100755
index 0000000..6d4181e
--- /dev/null
+++ b/sys/amd64/acpica/genwakedata.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+# $FreeBSD$
+#
+nm -n --defined-only acpi_wakecode.o | while read offset dummy what
+do
+ echo "#define ${what} 0x${offset}"
+done
+
+exit 0
diff --git a/sys/amd64/amd64/amd64_mem.c b/sys/amd64/amd64/amd64_mem.c
index 2b5a73d..d7959fd 100644
--- a/sys/amd64/amd64/amd64_mem.c
+++ b/sys/amd64/amd64/amd64_mem.c
@@ -73,11 +73,13 @@ static void amd64_mrinit(struct mem_range_softc *sc);
static int amd64_mrset(struct mem_range_softc *sc,
struct mem_range_desc *mrd, int *arg);
static void amd64_mrAPinit(struct mem_range_softc *sc);
+static void amd64_mrreinit(struct mem_range_softc *sc);
static struct mem_range_ops amd64_mrops = {
amd64_mrinit,
amd64_mrset,
- amd64_mrAPinit
+ amd64_mrAPinit,
+ amd64_mrreinit
};
/* XXX for AP startup hook */
@@ -668,6 +670,30 @@ amd64_mrAPinit(struct mem_range_softc *sc)
wrmsr(MSR_MTRRdefType, mtrrdef);
}
+/*
+ * Re-initialise running CPU(s) MTRRs to match the ranges in the descriptor
+ * list.
+ *
+ * XXX Must be called with interrupts enabled.
+ */
+static void
+amd64_mrreinit(struct mem_range_softc *sc)
+{
+#ifdef SMP
+ /*
+ * We should use ipi_all_but_self() to call other CPUs into a
+ * locking gate, then call a target function to do this work.
+ * The "proper" solution involves a generalised locking gate
+ * implementation, not ready yet.
+ */
+ smp_rendezvous(NULL, (void *)amd64_mrAPinit, NULL, sc);
+#else
+ disable_intr(); /* disable interrupts */
+ amd64_mrAPinit(sc);
+ enable_intr();
+#endif
+}
+
static void
amd64_mem_drvinit(void *unused)
{
diff --git a/sys/amd64/amd64/apic_vector.S b/sys/amd64/amd64/apic_vector.S
index 14a6f87..cebafc8 100644
--- a/sys/amd64/amd64/apic_vector.S
+++ b/sys/amd64/amd64/apic_vector.S
@@ -219,6 +219,20 @@ IDTVEC(cpustop)
movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
call cpustop_handler
+ jmp doreti
+
+/*
+ * Executed by a CPU when it receives an IPI_SUSPEND from another CPU.
+ */
+ .text
+ SUPERALIGN_TEXT
+IDTVEC(cpususpend)
+ PUSH_FRAME
+
+ movq lapic, %rax
+ movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
+
+ call cpususpend_handler
POP_FRAME
iretq
@@ -235,6 +249,5 @@ IDTVEC(rendezvous)
call smp_rendezvous_action
movq lapic, %rax
movl $0, LA_EOI(%rax) /* End Of Interrupt to APIC */
- POP_FRAME /* Why not doreti? */
- iretq
+ jmp doreti
#endif /* SMP */
diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S
index bc1a4bb..6fc8290 100644
--- a/sys/amd64/amd64/cpu_switch.S
+++ b/sys/amd64/amd64/cpu_switch.S
@@ -75,8 +75,6 @@ ENTRY(cpu_throw)
1:
movq TD_PCB(%rdi),%r8 /* Old pcb */
movl PCPU(CPUID), %eax
- movq PCB_FSBASE(%r8),%r9
- movq PCB_GSBASE(%r8),%r10
/* release bit from old pm_active */
movq TD_PROC(%rdi), %rdx /* oldtd->td_proc */
movq P_VMSPACE(%rdx), %rdx /* proc->p_vmspace */
@@ -110,28 +108,6 @@ ENTRY(cpu_switch)
movq %rbx,PCB_RBX(%r8)
movq %rax,PCB_RIP(%r8)
- /*
- * Reread fs and gs bases. Explicit fs segment register load
- * by the usermode code may change actual fs base without
- * updating pcb_{fs,gs}base.
- *
- * %rdx still contains the mtx, save %rdx around rdmsr.
- */
- movq %rdx,%r11
- movl $MSR_FSBASE,%ecx
- rdmsr
- shlq $32,%rdx
- leaq (%rax,%rdx),%r9
- movl $MSR_KGSBASE,%ecx
- rdmsr
- shlq $32,%rdx
- leaq (%rax,%rdx),%r10
- movq %r11,%rdx
-
- testl $PCB_32BIT,PCB_FLAGS(%r8)
- jnz store_seg
-done_store_seg:
-
testl $PCB_DBREGS,PCB_FLAGS(%r8)
jnz store_dr /* static predict not taken */
done_store_dr:
@@ -192,36 +168,47 @@ sw1:
testl $TDP_KTHREAD,TD_PFLAGS(%rsi)
jnz do_kthread
- testl $PCB_32BIT,PCB_FLAGS(%r8)
- jnz load_seg
-done_load_seg:
+ /*
+ * Load ldt register
+ */
+ movq TD_PROC(%rsi),%rcx
+ cmpq $0, P_MD+MD_LDT(%rcx)
+ jne do_ldt
+ xorl %eax,%eax
+ld_ldt: lldt %ax
- cmpq PCB_FSBASE(%r8),%r9
- jz 1f
- /* Restore userland %fs */
-restore_fsbase:
- movl $MSR_FSBASE,%ecx
+ /* Restore fs base in GDT */
movl PCB_FSBASE(%r8),%eax
- movl PCB_FSBASE+4(%r8),%edx
- wrmsr
-1:
- cmpq PCB_GSBASE(%r8),%r10
- jz 2f
- /* Restore userland %gs */
- movl $MSR_KGSBASE,%ecx
+ movq PCPU(FS32P),%rdx
+ movw %ax,2(%rdx)
+ shrl $16,%eax
+ movb %al,4(%rdx)
+ shrl $8,%eax
+ movb %al,7(%rdx)
+
+ /* Restore gs base in GDT */
movl PCB_GSBASE(%r8),%eax
- movl PCB_GSBASE+4(%r8),%edx
- wrmsr
-2:
+ movq PCPU(GS32P),%rdx
+ movw %ax,2(%rdx)
+ shrl $16,%eax
+ movb %al,4(%rdx)
+ shrl $8,%eax
+ movb %al,7(%rdx)
-do_tss:
+do_kthread:
+ /* Do we need to reload tss ? */
+ movq PCPU(TSSP),%rax
+ movq PCB_TSSP(%r8),%rdx
+ testq %rdx,%rdx
+ cmovzq PCPU(COMMONTSSP),%rdx
+ cmpq %rax,%rdx
+ jne do_tss
+done_tss:
+ movq %r8,PCPU(RSP0)
+ movq %r8,PCPU(CURPCB)
/* Update the TSS_RSP0 pointer for the next interrupt */
- movq PCPU(TSSP), %rax
- movq %r8, PCPU(RSP0)
- movq %r8, PCPU(CURPCB)
- addq $COMMON_TSS_RSP0, %rax
- movq %rsi, PCPU(CURTHREAD) /* into next thread */
- movq %r8, (%rax)
+ movq %r8,COMMON_TSS_RSP0(%rdx)
+ movq %rsi,PCPU(CURTHREAD) /* into next thread */
/* Test if debug registers should be restored. */
testl $PCB_DBREGS,PCB_FLAGS(%r8)
@@ -250,45 +237,6 @@ done_load_dr:
* We use jumps rather than call in order to avoid the stack.
*/
-do_kthread:
- /*
- * Copy old fs/gsbase to new kthread pcb for future switches
- * This maintains curpcb->pcb_[fg]sbase as caches of the MSR
- */
- movq %r9,PCB_FSBASE(%r8)
- movq %r10,PCB_GSBASE(%r8)
- jmp do_tss
-
-store_seg:
- mov %gs,PCB_GS(%r8)
- testl $PCB_GS32BIT,PCB_FLAGS(%r8)
- jnz 2f
-1: mov %ds,PCB_DS(%r8)
- mov %es,PCB_ES(%r8)
- mov %fs,PCB_FS(%r8)
- jmp done_store_seg
-2: movq PCPU(GS32P),%rax
- movq (%rax),%rax
- movq %rax,PCB_GS32SD(%r8)
- jmp 1b
-
-load_seg:
- testl $PCB_GS32BIT,PCB_FLAGS(%r8)
- jnz 2f
-1: movl $MSR_GSBASE,%ecx
- rdmsr
- mov PCB_GS(%r8),%gs
- wrmsr
- mov PCB_DS(%r8),%ds
- mov PCB_ES(%r8),%es
- mov PCB_FS(%r8),%fs
- jmp restore_fsbase
- /* Restore userland %gs while preserving kernel gsbase */
-2: movq PCPU(GS32P),%rax
- movq PCB_GS32SD(%r8),%rcx
- movq %rcx,(%rax)
- jmp 1b
-
store_dr:
movq %dr7,%rax /* yes, do the save */
movq %dr0,%r15
@@ -326,8 +274,30 @@ load_dr:
movq %rax,%dr7
jmp done_load_dr
+do_tss: movq %rdx,PCPU(TSSP)
+ movq %rdx,%rcx
+ movq PCPU(TSS),%rax
+ movw %rcx,2(%rax)
+ shrq $16,%rcx
+ movb %cl,4(%rax)
+ shrq $8,%rcx
+ movb %cl,7(%rax)
+ shrq $8,%rcx
+ movl %ecx,8(%rax)
+ movb $0x89,5(%rax) /* unset busy */
+ movl $TSSSEL,%eax
+ ltr %ax
+ jmp done_tss
+
+do_ldt: movq PCPU(LDT),%rax
+ movq P_MD+MD_LDT_SD(%rcx),%rdx
+ movq %rdx,(%rax)
+ movq P_MD+MD_LDT_SD+8(%rcx),%rdx
+ movq %rdx,8(%rax)
+ movl $LDTSEL,%eax
+ jmp ld_ldt
END(cpu_switch)
-
+
/*
* savectx(pcb)
* Update pcb, saving current processor state.
@@ -386,3 +356,68 @@ ENTRY(savectx)
ret
END(savectx)
+
+/*
+ * savectx2(xpcb)
+ * Update xpcb, saving current processor state.
+ */
+ENTRY(savectx2)
+ /* Fetch XPCB. */
+ movq %rdi,%r8
+
+ /* Save caller's return address. */
+ movq (%rsp),%rax
+ movq %rax,PCB_RIP(%r8)
+
+ movq %rbx,PCB_RBX(%r8)
+ movq %rsp,PCB_RSP(%r8)
+ movq %rbp,PCB_RBP(%r8)
+ movq %r12,PCB_R12(%r8)
+ movq %r13,PCB_R13(%r8)
+ movq %r14,PCB_R14(%r8)
+ movq %r15,PCB_R15(%r8)
+
+ movq %cr0,%rax
+ movq %rax,XPCB_CR0(%r8)
+ movq %cr2,%rax
+ movq %rax,XPCB_CR2(%r8)
+ movq %cr4,%rax
+ movq %rax,XPCB_CR4(%r8)
+
+ movq %dr0,%rax
+ movq %rax,PCB_DR0(%r8)
+ movq %dr1,%rax
+ movq %rax,PCB_DR1(%r8)
+ movq %dr2,%rax
+ movq %rax,PCB_DR2(%r8)
+ movq %dr3,%rax
+ movq %rax,PCB_DR3(%r8)
+ movq %dr6,%rax
+ movq %rax,PCB_DR6(%r8)
+ movq %dr7,%rax
+ movq %rax,PCB_DR7(%r8)
+
+ sgdt XPCB_GDT(%r8)
+ sidt XPCB_IDT(%r8)
+ sldt XPCB_LDT(%r8)
+ str XPCB_TR(%r8)
+
+ movl $MSR_FSBASE,%ecx
+ rdmsr
+ shlq $32,%rdx
+ leaq (%rax,%rdx),%rax
+ movq %rax,PCB_FSBASE(%r8)
+ movl $MSR_GSBASE,%ecx
+ rdmsr
+ shlq $32,%rdx
+ leaq (%rax,%rdx),%rax
+ movq %rax,PCB_GSBASE(%r8)
+ movl $MSR_KGSBASE,%ecx
+ rdmsr
+ shlq $32,%rdx
+ leaq (%rax,%rdx),%rax
+ movq %rax,XPCB_KGSBASE(%r8)
+
+ movl $1, %eax
+ ret
+END(savectx2)
diff --git a/sys/amd64/amd64/db_interface.c b/sys/amd64/amd64/db_interface.c
index b297616..287c236 100644
--- a/sys/amd64/amd64/db_interface.c
+++ b/sys/amd64/amd64/db_interface.c
@@ -139,7 +139,11 @@ void
db_show_mdpcpu(struct pcpu *pc)
{
-#if 0
- db_printf("currentldt = 0x%x\n", pc->pc_currentldt);
-#endif
+ db_printf("curpmap = %p\n", pc->pc_curpmap);
+ db_printf("tssp = %p\n", pc->pc_tssp);
+ db_printf("commontssp = %p\n", pc->pc_commontssp);
+ db_printf("rsp0 = 0x%lx\n", pc->pc_rsp0);
+ db_printf("gs32p = %p\n", pc->pc_gs32p);
+ db_printf("ldt = %p\n", pc->pc_ldt);
+ db_printf("tss = %p\n", pc->pc_tss);
}
diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c
index 9676963..73ffac5 100644
--- a/sys/amd64/amd64/db_trace.c
+++ b/sys/amd64/amd64/db_trace.c
@@ -69,12 +69,10 @@ static db_varfcn_t db_ss;
#define DB_OFFSET(x) (db_expr_t *)offsetof(struct trapframe, x)
struct db_variable db_regs[] = {
{ "cs", DB_OFFSET(tf_cs), db_frame },
-#if 0
{ "ds", DB_OFFSET(tf_ds), db_frame },
{ "es", DB_OFFSET(tf_es), db_frame },
{ "fs", DB_OFFSET(tf_fs), db_frame },
{ "gs", DB_OFFSET(tf_gs), db_frame },
-#endif
{ "ss", NULL, db_ss },
{ "rax", DB_OFFSET(tf_rax), db_frame },
{ "rcx", DB_OFFSET(tf_rcx), db_frame },
@@ -94,7 +92,7 @@ struct db_variable db_regs[] = {
{ "r15", DB_OFFSET(tf_r15), db_frame },
{ "rip", DB_OFFSET(tf_rip), db_frame },
{ "rflags", DB_OFFSET(tf_rflags), db_frame },
-#define DB_N_SHOW_REGS 20 /* Don't show registers after here. */
+#define DB_N_SHOW_REGS 24 /* Don't show registers after here. */
{ "dr0", NULL, db_dr0 },
{ "dr1", NULL, db_dr1 },
{ "dr2", NULL, db_dr2 },
@@ -316,6 +314,7 @@ db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td)
strcmp(name, "Xtimerint") == 0 ||
strcmp(name, "Xipi_intr_bitmap_handler") == 0 ||
strcmp(name, "Xcpustop") == 0 ||
+ strcmp(name, "Xcpususpend") == 0 ||
strcmp(name, "Xrendezvous") == 0)
frame_type = INTERRUPT;
else if (strcmp(name, "Xfast_syscall") == 0)
@@ -327,6 +326,7 @@ db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td)
/* XXX: These are interrupts with trap frames. */
else if (strcmp(name, "Xtimerint") == 0 ||
strcmp(name, "Xcpustop") == 0 ||
+ strcmp(name, "Xcpususpend") == 0 ||
strcmp(name, "Xrendezvous") == 0 ||
strcmp(name, "Xipi_intr_bitmap_handler") == 0)
frame_type = TRAP_INTERRUPT;
@@ -355,7 +355,7 @@ db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td)
rbp = tf->tf_rbp;
switch (frame_type) {
case TRAP:
- db_printf("--- trap %#lr", tf->tf_trapno);
+ db_printf("--- trap %#r", tf->tf_trapno);
break;
case SYSCALL:
db_printf("--- syscall");
diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
index 4f6d178..c5e19cf 100644
--- a/sys/amd64/amd64/elf_machdep.c
+++ b/sys/amd64/amd64/elf_machdep.c
@@ -84,7 +84,8 @@ static Elf64_Brandinfo freebsd_brand_info = {
.interp_path = "/libexec/ld-elf.so.1",
.sysvec = &elf64_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf64_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -99,7 +100,8 @@ static Elf64_Brandinfo freebsd_brand_oinfo = {
.interp_path = "/usr/libexec/ld-elf.so.1",
.sysvec = &elf64_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf64_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S
index 897bfec..daa5c25 100644
--- a/sys/amd64/amd64/exception.S
+++ b/sys/amd64/amd64/exception.S
@@ -42,6 +42,7 @@
#include <machine/asmacros.h>
#include <machine/psl.h>
#include <machine/trap.h>
+#include <machine/specialreg.h>
#include "assym.s"
@@ -99,7 +100,7 @@ MCOUNT_LABEL(btrap)
/* Traps that we leave interrupts disabled for.. */
#define TRAP_NOEN(a) \
subq $TF_RIP,%rsp; \
- movq $(a),TF_TRAPNO(%rsp) ; \
+ movl $(a),TF_TRAPNO(%rsp) ; \
movq $0,TF_ADDR(%rsp) ; \
movq $0,TF_ERR(%rsp) ; \
jmp alltraps_noen
@@ -111,7 +112,7 @@ IDTVEC(bpt)
/* Regular traps; The cpu does not supply tf_err for these. */
#define TRAP(a) \
subq $TF_RIP,%rsp; \
- movq $(a),TF_TRAPNO(%rsp) ; \
+ movl $(a),TF_TRAPNO(%rsp) ; \
movq $0,TF_ADDR(%rsp) ; \
movq $0,TF_ERR(%rsp) ; \
jmp alltraps
@@ -139,7 +140,7 @@ IDTVEC(xmm)
/* This group of traps have tf_err already pushed by the cpu */
#define TRAP_ERR(a) \
subq $TF_ERR,%rsp; \
- movq $(a),TF_TRAPNO(%rsp) ; \
+ movl $(a),TF_TRAPNO(%rsp) ; \
movq $0,TF_ADDR(%rsp) ; \
jmp alltraps
IDTVEC(tss)
@@ -164,6 +165,10 @@ alltraps:
testb $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
jz alltraps_testi /* already running with kernel GS.base */
swapgs
+ movw %fs,TF_FS(%rsp)
+ movw %gs,TF_GS(%rsp)
+ movw %es,TF_ES(%rsp)
+ movw %ds,TF_DS(%rsp)
alltraps_testi:
testl $PSL_I,TF_RFLAGS(%rsp)
jz alltraps_pushregs
@@ -185,6 +190,7 @@ alltraps_pushregs_no_rdi:
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
+ movl $TF_HASSEGS,TF_FLAGS(%rsp)
FAKE_MCOUNT(TF_RIP(%rsp))
#ifdef KDTRACE_HOOKS
/*
@@ -193,7 +199,7 @@ alltraps_pushregs_no_rdi:
* interrupt. For all other trap types, just handle them in
* the usual way.
*/
- cmpq $T_BPTFLT,TF_TRAPNO(%rsp)
+ cmpl $T_BPTFLT,TF_TRAPNO(%rsp)
jne calltrap
/* Check if there is no DTrace hook registered. */
@@ -228,13 +234,17 @@ calltrap:
.type alltraps_noen,@function
alltraps_noen:
testb $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
- jz alltraps_pushregs /* already running with kernel GS.base */
+ jz 1f /* already running with kernel GS.base */
swapgs
+1: movw %fs,TF_FS(%rsp)
+ movw %gs,TF_GS(%rsp)
+ movw %es,TF_ES(%rsp)
+ movw %ds,TF_DS(%rsp)
jmp alltraps_pushregs
IDTVEC(dblfault)
subq $TF_ERR,%rsp
- movq $T_DOUBLEFLT,TF_TRAPNO(%rsp)
+ movl $T_DOUBLEFLT,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
movq %rdi,TF_RDI(%rsp)
@@ -252,6 +262,11 @@ IDTVEC(dblfault)
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
+ movw %fs,TF_FS(%rsp)
+ movw %gs,TF_GS(%rsp)
+ movw %es,TF_ES(%rsp)
+ movw %ds,TF_DS(%rsp)
+ movl $TF_HASSEGS,TF_FLAGS(%rsp)
testb $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
jz 1f /* already running with kernel GS.base */
swapgs
@@ -262,7 +277,7 @@ IDTVEC(dblfault)
IDTVEC(page)
subq $TF_ERR,%rsp
- movq $T_PAGEFLT,TF_TRAPNO(%rsp)
+ movl $T_PAGEFLT,TF_TRAPNO(%rsp)
testb $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
jz 1f /* already running with kernel GS.base */
swapgs
@@ -270,6 +285,10 @@ IDTVEC(page)
movq %rdi,TF_RDI(%rsp) /* free up a GP register */
movq %cr2,%rdi /* preserve %cr2 before .. */
movq %rdi,TF_ADDR(%rsp) /* enabling interrupts. */
+ movw %fs,TF_FS(%rsp)
+ movw %gs,TF_GS(%rsp)
+ movw %es,TF_ES(%rsp)
+ movw %ds,TF_DS(%rsp)
testl $PSL_I,TF_RFLAGS(%rsp)
jz alltraps_pushregs_no_rdi
sti
@@ -283,17 +302,19 @@ IDTVEC(page)
*/
IDTVEC(prot)
subq $TF_ERR,%rsp
- movq $T_PROTFLT,TF_TRAPNO(%rsp)
+ movl $T_PROTFLT,TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq %rdi,TF_RDI(%rsp) /* free up a GP register */
leaq doreti_iret(%rip),%rdi
cmpq %rdi,TF_RIP(%rsp)
- je 2f /* kernel but with user gsbase!! */
+ je 1f /* kernel but with user gsbase!! */
testb $SEL_RPL_MASK,TF_CS(%rsp) /* Did we come from kernel? */
- jz 1f /* already running with kernel GS.base */
-2:
- swapgs
-1:
+ jz 2f /* already running with kernel GS.base */
+1: swapgs
+2: movw %fs,TF_FS(%rsp)
+ movw %gs,TF_GS(%rsp)
+ movw %es,TF_ES(%rsp)
+ movw %ds,TF_DS(%rsp)
testl $PSL_I,TF_RFLAGS(%rsp)
jz alltraps_pushregs_no_rdi
sti
@@ -316,6 +337,10 @@ IDTVEC(fast_syscall)
movq %rcx,TF_RIP(%rsp) /* %rcx original value is in %r10 */
movq PCPU(SCRATCH_RSP),%r11 /* %r11 already saved */
movq %r11,TF_RSP(%rsp) /* user stack pointer */
+ movw %fs,TF_FS(%rsp)
+ movw %gs,TF_GS(%rsp)
+ movw %es,TF_ES(%rsp)
+ movw %ds,TF_DS(%rsp)
sti
movq $KUDSEL,TF_SS(%rsp)
movq $KUCSEL,TF_CS(%rsp)
@@ -333,40 +358,11 @@ IDTVEC(fast_syscall)
movq %r13,TF_R13(%rsp) /* C preserved */
movq %r14,TF_R14(%rsp) /* C preserved */
movq %r15,TF_R15(%rsp) /* C preserved */
+ movl $TF_HASSEGS,TF_FLAGS(%rsp)
FAKE_MCOUNT(TF_RIP(%rsp))
movq %rsp, %rdi
call syscall
movq PCPU(CURPCB),%rax
- testq $PCB_FULLCTX,PCB_FLAGS(%rax)
- jne 3f
-1: /* Check for and handle AST's on return to userland */
- cli
- movq PCPU(CURTHREAD),%rax
- testl $TDF_ASTPENDING | TDF_NEEDRESCHED,TD_FLAGS(%rax)
- je 2f
- sti
- movq %rsp, %rdi
- call ast
- jmp 1b
-2: /* restore preserved registers */
- MEXITCOUNT
- movq TF_RDI(%rsp),%rdi /* bonus; preserve arg 1 */
- movq TF_RSI(%rsp),%rsi /* bonus: preserve arg 2 */
- movq TF_RDX(%rsp),%rdx /* return value 2 */
- movq TF_RAX(%rsp),%rax /* return value 1 */
- movq TF_RBX(%rsp),%rbx /* C preserved */
- movq TF_RBP(%rsp),%rbp /* C preserved */
- movq TF_R12(%rsp),%r12 /* C preserved */
- movq TF_R13(%rsp),%r13 /* C preserved */
- movq TF_R14(%rsp),%r14 /* C preserved */
- movq TF_R15(%rsp),%r15 /* C preserved */
- movq TF_RFLAGS(%rsp),%r11 /* original %rflags */
- movq TF_RIP(%rsp),%rcx /* original %rip */
- movq TF_RSP(%rsp),%r9 /* user stack pointer */
- movq %r9,%rsp /* original %rsp */
- swapgs
- sysretq
-3: /* Requested full context restore, use doreti for that */
andq $~PCB_FULLCTX,PCB_FLAGS(%rax)
MEXITCOUNT
jmp doreti
@@ -405,7 +401,7 @@ IDTVEC(fast_syscall32)
IDTVEC(nmi)
subq $TF_RIP,%rsp
- movq $(T_NMI),TF_TRAPNO(%rsp)
+ movl $(T_NMI),TF_TRAPNO(%rsp)
movq $0,TF_ADDR(%rsp)
movq $0,TF_ERR(%rsp)
movq %rdi,TF_RDI(%rsp)
@@ -423,6 +419,11 @@ IDTVEC(nmi)
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
+ movw %fs,TF_FS(%rsp)
+ movw %gs,TF_GS(%rsp)
+ movw %es,TF_ES(%rsp)
+ movw %ds,TF_DS(%rsp)
+ movl $TF_HASSEGS,TF_FLAGS(%rsp)
xorl %ebx,%ebx
testb $SEL_RPL_MASK,TF_CS(%rsp)
jnz nmi_fromuserspace
@@ -515,9 +516,7 @@ outofnmi:
nocallchain:
#endif
testl %ebx,%ebx
- jz nmi_kernelexit
- swapgs
- jmp nmi_restoreregs
+ jnz doreti_exit
nmi_kernelexit:
/*
* Put back the preserved MSR_GSBASE value.
@@ -633,7 +632,55 @@ doreti_ast:
*/
doreti_exit:
MEXITCOUNT
- movq TF_RDI(%rsp),%rdi
+ movq PCPU(CURTHREAD),%r8
+ movq TD_PCB(%r8),%r8
+
+ /*
+ * Do not reload segment registers for kernel.
+ * Since we do not reload segments registers with sane
+ * values on kernel entry, descriptors referenced by
+ * segments registers may be not valid. This is fatal
+ * for the usermode, but is innocent for the kernel.
+ */
+ testb $SEL_RPL_MASK,TF_CS(%rsp)
+ jz ld_regs
+
+ testl $TF_HASSEGS,TF_FLAGS(%rsp)
+ je set_segs
+
+do_segs:
+ /* Restore %fs and fsbase */
+ movw TF_FS(%rsp),%ax
+ .globl ld_fs
+ld_fs: movw %ax,%fs
+ cmpw $KUF32SEL,%ax
+ jne 1f
+ movl $MSR_FSBASE,%ecx
+ movl PCB_FSBASE(%r8),%eax
+ movl PCB_FSBASE+4(%r8),%edx
+ wrmsr
+1:
+ /* Restore %gs and gsbase */
+ movw TF_GS(%rsp),%si
+ pushfq
+ cli
+ movl $MSR_GSBASE,%ecx
+ rdmsr
+ .globl ld_gs
+ld_gs: movw %si,%gs
+ wrmsr
+ popfq
+ cmpw $KUG32SEL,%si
+ jne 1f
+ movl $MSR_KGSBASE,%ecx
+ movl PCB_GSBASE(%r8),%eax
+ movl PCB_GSBASE+4(%r8),%edx
+ wrmsr
+1: .globl ld_es
+ld_es: movw TF_ES(%rsp),%es
+ .globl ld_ds
+ld_ds: movw TF_DS(%rsp),%ds
+ld_regs:movq TF_RDI(%rsp),%rdi
movq TF_RSI(%rsp),%rsi
movq TF_RDX(%rsp),%rdx
movq TF_RCX(%rsp),%rcx
@@ -657,6 +704,14 @@ doreti_exit:
doreti_iret:
iretq
+set_segs:
+ movw $KUDSEL,%ax
+ movw %ax,TF_DS(%rsp)
+ movw %ax,TF_ES(%rsp)
+ movw $KUF32SEL,TF_FS(%rsp)
+ movw $KUG32SEL,TF_GS(%rsp)
+ jmp do_segs
+
/*
* doreti_iret_fault. Alternative return code for
* the case where we get a fault in the doreti_exit code
@@ -671,7 +726,12 @@ doreti_iret_fault:
testl $PSL_I,TF_RFLAGS(%rsp)
jz 1f
sti
-1: movq %rdi,TF_RDI(%rsp)
+1: movw %fs,TF_FS(%rsp)
+ movw %gs,TF_GS(%rsp)
+ movw %es,TF_ES(%rsp)
+ movw %ds,TF_DS(%rsp)
+ movl $TF_HASSEGS,TF_FLAGS(%rsp)
+ movq %rdi,TF_RDI(%rsp)
movq %rsi,TF_RSI(%rsp)
movq %rdx,TF_RDX(%rsp)
movq %rcx,TF_RCX(%rsp)
@@ -686,11 +746,48 @@ doreti_iret_fault:
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
- movq $T_PROTFLT,TF_TRAPNO(%rsp)
+ movl $T_PROTFLT,TF_TRAPNO(%rsp)
movq $0,TF_ERR(%rsp) /* XXX should be the error code */
movq $0,TF_ADDR(%rsp)
FAKE_MCOUNT(TF_RIP(%rsp))
jmp calltrap
+
+ ALIGN_TEXT
+ .globl ds_load_fault
+ds_load_fault:
+ movl $T_PROTFLT,TF_TRAPNO(%rsp)
+ movzwl TF_DS(%rsp),%edx
+ movl %edx,TF_ERR(%rsp)
+ movw $KUDSEL,TF_DS(%rsp)
+ jmp calltrap
+
+ ALIGN_TEXT
+ .globl es_load_fault
+es_load_fault:
+ movl $T_PROTFLT,TF_TRAPNO(%rsp)
+ movzwl TF_ES(%rsp),%edx
+ movl %edx,TF_ERR(%rsp)
+ movw $KUDSEL,TF_ES(%rsp)
+ jmp calltrap
+
+ ALIGN_TEXT
+ .globl fs_load_fault
+fs_load_fault:
+ movl $T_PROTFLT,TF_TRAPNO(%rsp)
+ movzwl TF_FS(%rsp),%edx
+ movl %edx,TF_ERR(%rsp)
+ movw $KUF32SEL,TF_FS(%rsp)
+ jmp calltrap
+
+ ALIGN_TEXT
+ .globl gs_load_fault
+gs_load_fault:
+ popfq
+ movl $T_PROTFLT,TF_TRAPNO(%rsp)
+ movzwl TF_GS(%rsp),%edx
+ movl %edx,TF_ERR(%rsp)
+ movw $KUG32SEL,TF_GS(%rsp)
+ jmp calltrap
#ifdef HWPMC_HOOKS
ENTRY(end_exceptions)
#endif
diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c
index 8f16c46..10cb6c2 100644
--- a/sys/amd64/amd64/fpu.c
+++ b/sys/amd64/amd64/fpu.c
@@ -101,7 +101,7 @@ static void fpu_clean_state(void);
SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD,
NULL, 1, "Floating point instructions executed in hardware");
-static struct savefpu fpu_cleanstate;
+static struct savefpu fpu_initialstate;
/*
* Initialize the floating point unit. On the boot CPU we generate a
@@ -123,13 +123,13 @@ fpuinit(void)
mxcsr = __INITIAL_MXCSR__;
ldmxcsr(mxcsr);
if (PCPU_GET(cpuid) == 0) {
- fxsave(&fpu_cleanstate);
- if (fpu_cleanstate.sv_env.en_mxcsr_mask)
- cpu_mxcsr_mask = fpu_cleanstate.sv_env.en_mxcsr_mask;
+ fxsave(&fpu_initialstate);
+ if (fpu_initialstate.sv_env.en_mxcsr_mask)
+ cpu_mxcsr_mask = fpu_initialstate.sv_env.en_mxcsr_mask;
else
cpu_mxcsr_mask = 0xFFBF;
- bzero(fpu_cleanstate.sv_fp, sizeof(fpu_cleanstate.sv_fp));
- bzero(fpu_cleanstate.sv_xmm, sizeof(fpu_cleanstate.sv_xmm));
+ bzero(fpu_initialstate.sv_fp, sizeof(fpu_initialstate.sv_fp));
+ bzero(fpu_initialstate.sv_xmm, sizeof(fpu_initialstate.sv_xmm));
}
start_emulating();
intr_restore(savecrit);
@@ -416,10 +416,11 @@ fpudna(void)
if ((pcb->pcb_flags & PCB_FPUINITDONE) == 0) {
/*
- * This is the first time this thread has used the FPU,
- * explicitly load sanitized registers.
+ * This is the first time this thread has used the FPU or
+ * the PCB doesn't contain a clean FPU state. Explicitly
+ * load an initial state.
*/
- fxrstor(&fpu_cleanstate);
+ fxrstor(&fpu_initialstate);
if (pcb->pcb_initial_fpucw != __INITIAL_FPUCW__)
fldcw(&pcb->pcb_initial_fpucw);
pcb->pcb_flags |= PCB_FPUINITDONE;
@@ -453,7 +454,7 @@ fpugetregs(struct thread *td, struct savefpu *addr)
register_t s;
if ((td->td_pcb->pcb_flags & PCB_FPUINITDONE) == 0) {
- bcopy(&fpu_cleanstate, addr, sizeof(fpu_cleanstate));
+ bcopy(&fpu_initialstate, addr, sizeof(fpu_initialstate));
addr->sv_env.en_cw = td->td_pcb->pcb_initial_fpucw;
return (_MC_FPOWNED_NONE);
}
@@ -479,7 +480,6 @@ fpusetregs(struct thread *td, struct savefpu *addr)
s = intr_disable();
if (td == PCPU_GET(fpcurthread)) {
- fpu_clean_state();
fxrstor(addr);
intr_restore(s);
} else {
@@ -498,10 +498,10 @@ fpusetregs(struct thread *td, struct savefpu *addr)
* In order to avoid leaking this information across processes, we clean
* these values by performing a dummy load before executing fxrstor().
*/
-static double dummy_variable = 0.0;
static void
fpu_clean_state(void)
{
+ static float dummy_variable = 0.0;
u_short status;
/*
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
index 1924be7..8bf1162 100644
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -72,13 +72,16 @@ __FBSDID("$FreeBSD$");
#include <machine/pcb.h>
#include <machine/sigframe.h>
#include <machine/proc.h>
-#include <machine/specialreg.h>
#include <machine/segments.h>
ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace));
ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap));
ASSYM(PM_ACTIVE, offsetof(struct pmap, pm_active));
+ASSYM(P_MD, offsetof(struct proc, p_md));
+ASSYM(MD_LDT, offsetof(struct mdproc, md_ldt));
+ASSYM(MD_LDT_SD, offsetof(struct mdproc, md_ldt_sd));
+
ASSYM(TD_LOCK, offsetof(struct thread, td_lock));
ASSYM(TD_FLAGS, offsetof(struct thread, td_flags));
ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
@@ -132,16 +135,13 @@ ASSYM(PCB_RBX, offsetof(struct pcb, pcb_rbx));
ASSYM(PCB_RIP, offsetof(struct pcb, pcb_rip));
ASSYM(PCB_FSBASE, offsetof(struct pcb, pcb_fsbase));
ASSYM(PCB_GSBASE, offsetof(struct pcb, pcb_gsbase));
-ASSYM(PCB_DS, offsetof(struct pcb, pcb_ds));
-ASSYM(PCB_ES, offsetof(struct pcb, pcb_es));
-ASSYM(PCB_FS, offsetof(struct pcb, pcb_fs));
-ASSYM(PCB_GS, offsetof(struct pcb, pcb_gs));
ASSYM(PCB_DR0, offsetof(struct pcb, pcb_dr0));
ASSYM(PCB_DR1, offsetof(struct pcb, pcb_dr1));
ASSYM(PCB_DR2, offsetof(struct pcb, pcb_dr2));
ASSYM(PCB_DR3, offsetof(struct pcb, pcb_dr3));
ASSYM(PCB_DR6, offsetof(struct pcb, pcb_dr6));
ASSYM(PCB_DR7, offsetof(struct pcb, pcb_dr7));
+ASSYM(PCB_TSSP, offsetof(struct pcb, pcb_tssp));
ASSYM(PCB_DBREGS, PCB_DBREGS);
ASSYM(PCB_32BIT, PCB_32BIT);
ASSYM(PCB_GS32BIT, PCB_GS32BIT);
@@ -155,6 +155,18 @@ ASSYM(PCB_GS32SD, offsetof(struct pcb, pcb_gs32sd));
ASSYM(PCB_SIZE, sizeof(struct pcb));
+ASSYM(XPCB_PCB, offsetof(struct xpcb, xpcb_pcb));
+ASSYM(XPCB_CR0, offsetof(struct xpcb, xpcb_cr0));
+ASSYM(XPCB_CR2, offsetof(struct xpcb, xpcb_cr2));
+ASSYM(XPCB_CR4, offsetof(struct xpcb, xpcb_cr4));
+ASSYM(XPCB_KGSBASE, offsetof(struct xpcb, xpcb_kgsbase));
+ASSYM(XPCB_GDT, offsetof(struct xpcb, xpcb_gdt));
+ASSYM(XPCB_IDT, offsetof(struct xpcb, xpcb_idt));
+ASSYM(XPCB_LDT, offsetof(struct xpcb, xpcb_ldt));
+ASSYM(XPCB_TR, offsetof(struct xpcb, xpcb_tr));
+
+ASSYM(XPCB_SIZE, sizeof(struct xpcb));
+
ASSYM(COMMON_TSS_RSP0, offsetof(struct amd64tss, tss_rsp0));
ASSYM(TF_R15, offsetof(struct trapframe, tf_r15));
@@ -180,7 +192,13 @@ ASSYM(TF_CS, offsetof(struct trapframe, tf_cs));
ASSYM(TF_RFLAGS, offsetof(struct trapframe, tf_rflags));
ASSYM(TF_RSP, offsetof(struct trapframe, tf_rsp));
ASSYM(TF_SS, offsetof(struct trapframe, tf_ss));
+ASSYM(TF_DS, offsetof(struct trapframe, tf_ds));
+ASSYM(TF_ES, offsetof(struct trapframe, tf_es));
+ASSYM(TF_FS, offsetof(struct trapframe, tf_fs));
+ASSYM(TF_GS, offsetof(struct trapframe, tf_gs));
+ASSYM(TF_FLAGS, offsetof(struct trapframe, tf_flags));
ASSYM(TF_SIZE, sizeof(struct trapframe));
+ASSYM(TF_HASSEGS, TF_HASSEGS);
ASSYM(SIGF_HANDLER, offsetof(struct sigframe, sf_ahu.sf_handler));
ASSYM(SIGF_UC, offsetof(struct sigframe, sf_uc));
@@ -202,7 +220,11 @@ ASSYM(PC_SCRATCH_RSP, offsetof(struct pcpu, pc_scratch_rsp));
ASSYM(PC_CURPMAP, offsetof(struct pcpu, pc_curpmap));
ASSYM(PC_TSSP, offsetof(struct pcpu, pc_tssp));
ASSYM(PC_RSP0, offsetof(struct pcpu, pc_rsp0));
+ASSYM(PC_FS32P, offsetof(struct pcpu, pc_fs32p));
ASSYM(PC_GS32P, offsetof(struct pcpu, pc_gs32p));
+ASSYM(PC_LDT, offsetof(struct pcpu, pc_ldt));
+ASSYM(PC_COMMONTSSP, offsetof(struct pcpu, pc_commontssp));
+ASSYM(PC_TSS, offsetof(struct pcpu, pc_tss));
ASSYM(LA_VER, offsetof(struct LAPIC, version));
ASSYM(LA_TPR, offsetof(struct LAPIC, tpr));
@@ -217,10 +239,12 @@ ASSYM(KDSEL, GSEL(GDATA_SEL, SEL_KPL));
ASSYM(KUCSEL, GSEL(GUCODE_SEL, SEL_UPL));
ASSYM(KUDSEL, GSEL(GUDATA_SEL, SEL_UPL));
ASSYM(KUC32SEL, GSEL(GUCODE32_SEL, SEL_UPL));
+ASSYM(KUF32SEL, GSEL(GUFS32_SEL, SEL_UPL));
+ASSYM(KUG32SEL, GSEL(GUGS32_SEL, SEL_UPL));
+ASSYM(TSSSEL, GSEL(GPROC0_SEL, SEL_KPL));
+ASSYM(LDTSEL, GSEL(GUSERLDT_SEL, SEL_KPL));
ASSYM(SEL_RPL_MASK, SEL_RPL_MASK);
-ASSYM(MSR_GSBASE, MSR_GSBASE);
-
#ifdef HWPMC_HOOKS
ASSYM(PMC_FN_USER_CALLCHAIN, PMC_FN_USER_CALLCHAIN);
#endif
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 3a2b170..4a5871a 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -159,7 +159,7 @@ extern vm_offset_t ksym_start, ksym_end;
#define ICH_PMBASE 0x400
#define ICH_SMI_EN ICH_PMBASE + 0x30
-int _udatasel, _ucodesel, _ucode32sel;
+int _udatasel, _ucodesel, _ucode32sel, _ufssel, _ugssel;
int cold = 1;
@@ -192,10 +192,13 @@ struct mtx icu_lock;
struct mem_range_softc mem_range_softc;
+struct mtx dt_lock; /* lock for GDT and LDT */
+
static void
cpu_startup(dummy)
void *dummy;
{
+ uintmax_t memsize;
char *sysenv;
/*
@@ -226,8 +229,18 @@ cpu_startup(dummy)
#ifdef PERFMON
perfmon_init();
#endif
- printf("usable memory = %ju (%ju MB)\n", ptoa((uintmax_t)physmem),
- ptoa((uintmax_t)physmem) / 1048576);
+ sysenv = getenv("smbios.memory.enabled");
+ if (sysenv != NULL) {
+ memsize = (uintmax_t)strtoul(sysenv, (char **)NULL, 10);
+ freeenv(sysenv);
+ } else
+ memsize = 0;
+ if (memsize > 0)
+ printf("real memory = %ju (%ju MB)\n", memsize << 10,
+ memsize >> 10);
+ else
+ printf("real memory = %ju (%ju MB)\n", ptoa((uintmax_t)Maxmem),
+ ptoa((uintmax_t)Maxmem) / 1048576);
realmem = Maxmem;
/*
* Display any holes after the first chunk of extended memory.
@@ -250,7 +263,7 @@ cpu_startup(dummy)
vm_ksubmap_init(&kmi);
- printf("avail memory = %ju (%ju MB)\n",
+ printf("avail memory = %ju (%ju MB)\n",
ptoa((uintmax_t)cnt.v_free_count),
ptoa((uintmax_t)cnt.v_free_count) / 1048576);
@@ -267,7 +280,7 @@ cpu_startup(dummy)
* Send an interrupt to process.
*
* Stack is set up to allow sigcode stored
- * at top to call routine, followed by kcall
+ * at top to call routine, followed by call
* to sigreturn routine below. After sigreturn
* resets the signal mask, the stack, and the
* frame pointer, it returns to the user
@@ -305,6 +318,8 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
get_fpcontext(td, &sf.sf_uc.uc_mcontext);
fpstate_drop(td);
+ sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase;
+ sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase;
/* Allocate space for the signal handler context. */
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
@@ -359,6 +374,11 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
regs->tf_rip = PS_STRINGS - *(p->p_sysent->sv_szsigcode);
regs->tf_rflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucodesel;
+ regs->tf_ds = _udatasel;
+ regs->tf_es = _udatasel;
+ regs->tf_fs = _ufssel;
+ regs->tf_gs = _ugssel;
+ regs->tf_flags = TF_HASSEGS;
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
@@ -390,9 +410,16 @@ sigreturn(td, uap)
ksiginfo_t ksi;
error = copyin(uap->sigcntxp, &uc, sizeof(uc));
- if (error != 0)
+ if (error != 0) {
+ printf("sigreturn (pid %d): copyin failed\n", p->p_pid);
return (error);
+ }
ucp = &uc;
+ if ((ucp->uc_mcontext.mc_flags & ~_MC_FLAG_MASK) != 0) {
+ printf("sigreturn (pid %d): mc_flags %x\n", p->p_pid,
+ ucp->uc_mcontext.mc_flags);
+ return (EINVAL);
+ }
regs = td->td_frame;
rflags = ucp->uc_mcontext.mc_rflags;
/*
@@ -409,7 +436,8 @@ sigreturn(td, uap)
* one less debugger trap, so allowing it is fairly harmless.
*/
if (!EFL_SECURE(rflags & ~PSL_RF, regs->tf_rflags & ~PSL_RF)) {
- printf("sigreturn: rflags = 0x%lx\n", rflags);
+ printf("sigreturn (pid %d): rflags = 0x%lx\n", p->p_pid,
+ rflags);
return (EINVAL);
}
@@ -420,7 +448,7 @@ sigreturn(td, uap)
*/
cs = ucp->uc_mcontext.mc_cs;
if (!CS_SECURE(cs)) {
- printf("sigreturn: cs = 0x%x\n", cs);
+ printf("sigreturn (pid %d): cs = 0x%x\n", p->p_pid, cs);
ksiginfo_init_trap(&ksi);
ksi.ksi_signo = SIGBUS;
ksi.ksi_code = BUS_OBJERR;
@@ -431,9 +459,13 @@ sigreturn(td, uap)
}
ret = set_fpcontext(td, &ucp->uc_mcontext);
- if (ret != 0)
+ if (ret != 0) {
+ printf("sigreturn (pid %d): set_fpcontext\n", p->p_pid);
return (ret);
+ }
bcopy(&ucp->uc_mcontext.mc_rdi, regs, sizeof(*regs));
+ td->td_pcb->pcb_fsbase = ucp->uc_mcontext.mc_fsbase;
+ td->td_pcb->pcb_gsbase = ucp->uc_mcontext.mc_gsbase;
PROC_LOCK(p);
#if defined(COMPAT_43)
@@ -727,22 +759,16 @@ exec_setregs(td, entry, stack, ps_strings)
{
struct trapframe *regs = td->td_frame;
struct pcb *pcb = td->td_pcb;
+
+ mtx_lock(&dt_lock);
+ if (td->td_proc->p_md.md_ldt != NULL)
+ user_ldt_free(td);
+ else
+ mtx_unlock(&dt_lock);
- critical_enter();
- wrmsr(MSR_FSBASE, 0);
- wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */
pcb->pcb_fsbase = 0;
pcb->pcb_gsbase = 0;
- critical_exit();
pcb->pcb_flags &= ~(PCB_32BIT | PCB_GS32BIT);
- load_ds(_udatasel);
- load_es(_udatasel);
- load_fs(_udatasel);
- load_gs(_udatasel);
- pcb->pcb_ds = _udatasel;
- pcb->pcb_es = _udatasel;
- pcb->pcb_fs = _udatasel;
- pcb->pcb_gs = _udatasel;
pcb->pcb_initial_fpucw = __INITIAL_FPUCW__;
bzero((char *)regs, sizeof(struct trapframe));
@@ -752,6 +778,11 @@ exec_setregs(td, entry, stack, ps_strings)
regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
regs->tf_ss = _udatasel;
regs->tf_cs = _ucodesel;
+ regs->tf_ds = _udatasel;
+ regs->tf_es = _udatasel;
+ regs->tf_fs = _ufssel;
+ regs->tf_gs = _ugssel;
+ regs->tf_flags = TF_HASSEGS;
/*
* Reset the hardware debug registers if they were in use.
@@ -815,90 +846,130 @@ CTASSERT(sizeof(struct nmi_pcpu) == 16);
struct amd64tss common_tss[MAXCPU];
-/* software prototypes -- in more palatable form */
+/*
+ * Software prototypes -- in more palatable form.
+ *
+ * Keep GUFS32, GUGS32, GUCODE32 and GUDATA at the same
+ * slots as corresponding segments for i386 kernel.
+ */
struct soft_segment_descriptor gdt_segs[] = {
/* GNULL_SEL 0 Null Descriptor */
-{ 0x0, /* segment base address */
- 0x0, /* length */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, /* long */
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
-/* GCODE_SEL 1 Code Descriptor for kernel */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMERA, /* segment type */
- SEL_KPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 1, /* long */
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
-/* GDATA_SEL 2 Data Descriptor for kernel */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_KPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 1, /* long */
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
-/* GUCODE32_SEL 3 32 bit Code Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMERA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, /* long */
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
-/* GUDATA_SEL 4 32/64 bit Data Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, /* long */
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
-/* GUCODE_SEL 5 64 bit Code Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMERA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 1, /* long */
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
-/* GPROC0_SEL 6 Proc 0 Tss Descriptor */
-{
- 0x0, /* segment base address */
- sizeof(struct amd64tss)-1,/* length */
- SDT_SYSTSS, /* segment type */
- SEL_KPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, /* long */
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_long = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
+/* GNULL2_SEL 1 Null Descriptor */
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_long = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
+/* GUFS32_SEL 2 32 bit %gs Descriptor for user */
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_long = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
+/* GUGS32_SEL 3 32 bit %fs Descriptor for user */
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_long = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
+/* GCODE_SEL 4 Code Descriptor for kernel */
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = SEL_KPL,
+ .ssd_p = 1,
+ .ssd_long = 1,
+ .ssd_def32 = 0,
+ .ssd_gran = 1 },
+/* GDATA_SEL 5 Data Descriptor for kernel */
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_KPL,
+ .ssd_p = 1,
+ .ssd_long = 1,
+ .ssd_def32 = 0,
+ .ssd_gran = 1 },
+/* GUCODE32_SEL 6 32 bit Code Descriptor for user */
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_long = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
+/* GUDATA_SEL 7 32/64 bit Data Descriptor for user */
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_long = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
+/* GUCODE_SEL 8 64 bit Code Descriptor for user */
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_long = 1,
+ .ssd_def32 = 0,
+ .ssd_gran = 1 },
+/* GPROC0_SEL 9 Proc 0 Tss Descriptor */
+{ .ssd_base = 0x0,
+ .ssd_limit = sizeof(struct amd64tss) + IOPAGES * PAGE_SIZE - 1,
+ .ssd_type = SDT_SYSTSS,
+ .ssd_dpl = SEL_KPL,
+ .ssd_p = 1,
+ .ssd_long = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* Actually, the TSS is a system descriptor which is double size */
-{ 0x0, /* segment base address */
- 0x0, /* length */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, /* long */
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
-/* GUGS32_SEL 8 32 bit GS Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, /* long */
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_long = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
+/* GUSERLDT_SEL 11 LDT Descriptor */
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_long = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
+/* GUSERLDT_SEL 12 LDT Descriptor, double size */
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_long = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
};
void
@@ -1329,12 +1400,12 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
/*
* make gdt memory segments
*/
- gdt_segs[GPROC0_SEL].ssd_base = (uintptr_t)&common_tss[0];
-
for (x = 0; x < NGDT; x++) {
- if (x != GPROC0_SEL && x != (GPROC0_SEL + 1))
+ if (x != GPROC0_SEL && x != (GPROC0_SEL + 1) &&
+ x != GUSERLDT_SEL && x != (GUSERLDT_SEL) + 1)
ssdtosd(&gdt_segs[x], &gdt[x]);
}
+ gdt_segs[GPROC0_SEL].ssd_base = (uintptr_t)&common_tss[0];
ssdtosyssd(&gdt_segs[GPROC0_SEL],
(struct system_segment_descriptor *)&gdt[GPROC0_SEL]);
@@ -1352,6 +1423,10 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
PCPU_SET(curthread, &thread0);
PCPU_SET(curpcb, thread0.td_pcb);
PCPU_SET(tssp, &common_tss[0]);
+ PCPU_SET(commontssp, &common_tss[0]);
+ PCPU_SET(tss, (struct system_segment_descriptor *)&gdt[GPROC0_SEL]);
+ PCPU_SET(ldt, (struct system_segment_descriptor *)&gdt[GUSERLDT_SEL]);
+ PCPU_SET(fs32p, &gdt[GUFS32_SEL]);
PCPU_SET(gs32p, &gdt[GUGS32_SEL]);
/*
@@ -1364,6 +1439,7 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
*/
mutex_init();
mtx_init(&icu_lock, "icu", NULL, MTX_SPIN | MTX_NOWITNESS);
+ mtx_init(&dt_lock, "descriptor tables", NULL, MTX_DEF);
/* exceptions */
for (x = 0; x < NIDT; x++)
@@ -1452,7 +1528,8 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
common_tss[0].tss_ist2 = (long) np;
/* Set the IO permission bitmap (empty due to tss seg limit) */
- common_tss[0].tss_iobase = sizeof(struct amd64tss);
+ common_tss[0].tss_iobase = sizeof(struct amd64tss) +
+ IOPAGES * PAGE_SIZE;
gsel_tss = GSEL(GPROC0_SEL, SEL_KPL);
ltr(gsel_tss);
@@ -1480,10 +1557,12 @@ hammer_time(u_int64_t modulep, u_int64_t physfree)
_ucodesel = GSEL(GUCODE_SEL, SEL_UPL);
_udatasel = GSEL(GUDATA_SEL, SEL_UPL);
_ucode32sel = GSEL(GUCODE32_SEL, SEL_UPL);
+ _ufssel = GSEL(GUFS32_SEL, SEL_UPL);
+ _ugssel = GSEL(GUGS32_SEL, SEL_UPL);
load_ds(_udatasel);
load_es(_udatasel);
- load_fs(_udatasel);
+ load_fs(_ufssel);
/* setup proc 0's pcb */
thread0.td_pcb->pcb_flags = 0;
@@ -1605,6 +1684,17 @@ fill_regs(struct thread *td, struct reg *regs)
regs->r_rflags = tp->tf_rflags;
regs->r_rsp = tp->tf_rsp;
regs->r_ss = tp->tf_ss;
+ if (tp->tf_flags & TF_HASSEGS) {
+ regs->r_ds = tp->tf_ds;
+ regs->r_es = tp->tf_es;
+ regs->r_fs = tp->tf_fs;
+ regs->r_gs = tp->tf_gs;
+ } else {
+ regs->r_ds = 0;
+ regs->r_es = 0;
+ regs->r_fs = 0;
+ regs->r_gs = 0;
+ }
return (0);
}
@@ -1638,6 +1728,13 @@ set_regs(struct thread *td, struct reg *regs)
tp->tf_rflags = rflags;
tp->tf_rsp = regs->r_rsp;
tp->tf_ss = regs->r_ss;
+ if (0) { /* XXXKIB */
+ tp->tf_ds = regs->r_ds;
+ tp->tf_es = regs->r_es;
+ tp->tf_fs = regs->r_fs;
+ tp->tf_gs = regs->r_gs;
+ tp->tf_flags = TF_HASSEGS;
+ }
td->td_pcb->pcb_flags |= PCB_FULLCTX;
return (0);
}
@@ -1757,8 +1854,15 @@ get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
mcp->mc_cs = tp->tf_cs;
mcp->mc_rsp = tp->tf_rsp;
mcp->mc_ss = tp->tf_ss;
+ mcp->mc_ds = tp->tf_ds;
+ mcp->mc_es = tp->tf_es;
+ mcp->mc_fs = tp->tf_fs;
+ mcp->mc_gs = tp->tf_gs;
+ mcp->mc_flags = tp->tf_flags;
mcp->mc_len = sizeof(*mcp);
get_fpcontext(td, mcp);
+ mcp->mc_fsbase = td->td_pcb->pcb_fsbase;
+ mcp->mc_gsbase = td->td_pcb->pcb_gsbase;
return (0);
}
@@ -1776,7 +1880,8 @@ set_mcontext(struct thread *td, const mcontext_t *mcp)
int ret;
tp = td->td_frame;
- if (mcp->mc_len != sizeof(*mcp))
+ if (mcp->mc_len != sizeof(*mcp) ||
+ (mcp->mc_flags & ~_MC_FLAG_MASK) != 0)
return (EINVAL);
rflags = (mcp->mc_rflags & PSL_USERCHANGE) |
(tp->tf_rflags & ~PSL_USERCHANGE);
@@ -1802,6 +1907,17 @@ set_mcontext(struct thread *td, const mcontext_t *mcp)
tp->tf_rflags = rflags;
tp->tf_rsp = mcp->mc_rsp;
tp->tf_ss = mcp->mc_ss;
+ tp->tf_flags = mcp->mc_flags;
+ if (tp->tf_flags & TF_HASSEGS) {
+ tp->tf_ds = mcp->mc_ds;
+ tp->tf_es = mcp->mc_es;
+ tp->tf_fs = mcp->mc_fs;
+ tp->tf_gs = mcp->mc_gs;
+ }
+ if (mcp->mc_flags & _MC_HASBASES) {
+ td->td_pcb->pcb_fsbase = mcp->mc_fsbase;
+ td->td_pcb->pcb_gsbase = mcp->mc_gsbase;
+ }
td->td_pcb->pcb_flags |= PCB_FULLCTX;
return (0);
}
@@ -2062,45 +2178,24 @@ user_dbreg_trap(void)
#ifdef KDB
/*
- * Provide inb() and outb() as functions. They are normally only
- * available as macros calling inlined functions, thus cannot be
- * called from the debugger.
- *
- * The actual code is stolen from <machine/cpufunc.h>, and de-inlined.
+ * Provide inb() and outb() as functions. They are normally only available as
+ * inline functions, thus cannot be called from the debugger.
*/
-#undef inb
-#undef outb
-
/* silence compiler warnings */
-u_char inb(u_int);
-void outb(u_int, u_char);
+u_char inb_(u_short);
+void outb_(u_short, u_char);
u_char
-inb(u_int port)
+inb_(u_short port)
{
- u_char data;
- /*
- * We use %%dx and not %1 here because i/o is done at %dx and not at
- * %edx, while gcc generates inferior code (movw instead of movl)
- * if we tell it to load (u_short) port.
- */
- __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
- return (data);
+ return inb(port);
}
void
-outb(u_int port, u_char data)
+outb_(u_short port, u_char data)
{
- u_char al;
- /*
- * Use an unnecessary assignment to help gcc's register allocator.
- * This make a large difference for gcc-1.40 and a tiny difference
- * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for
- * best results. gcc-2.6.0 can't handle this.
- */
- al = data;
- __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
+ outb(port, data);
}
#endif /* KDB */
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index c65f6f8..59e3e9b 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
#include <machine/apicreg.h>
#include <machine/cputypes.h>
+#include <machine/cpufunc.h>
#include <machine/md_var.h>
#include <machine/mp_watchdog.h>
#include <machine/pcb.h>
@@ -100,9 +101,8 @@ extern pt_entry_t *KPTphys;
/* SMP page table page */
extern pt_entry_t *SMPpt;
-extern int _udatasel;
-
struct pcb stoppcbs[MAXCPU];
+struct xpcb *stopxpcbs = NULL;
/* Variables needed for SMP tlb shootdown. */
vm_offset_t smp_tlb_addr1;
@@ -344,6 +344,9 @@ cpu_mp_start(void)
/* Install an inter-CPU IPI for CPU stop/restart */
setidt(IPI_STOP, IDTVEC(cpustop), SDT_SYSIGT, SEL_KPL, 0);
+ /* Install an inter-CPU IPI for CPU suspend/resume */
+ setidt(IPI_SUSPEND, IDTVEC(cpususpend), SDT_SYSIGT, SEL_KPL, 0);
+
/* Set boot_cpu_id if needed. */
if (boot_cpu_id == -1) {
boot_cpu_id = PCPU_GET(apic_id);
@@ -458,7 +461,8 @@ init_secondary(void)
/* Init tss */
common_tss[cpu] = common_tss[0];
common_tss[cpu].tss_rsp0 = 0; /* not used until after switch */
- common_tss[cpu].tss_iobase = sizeof(struct amd64tss);
+ common_tss[cpu].tss_iobase = sizeof(struct amd64tss) +
+ IOPAGES * PAGE_SIZE;
common_tss[cpu].tss_ist1 = (long)&doublefault_stack[PAGE_SIZE];
/* The NMI stack runs on IST2. */
@@ -467,12 +471,13 @@ init_secondary(void)
/* Prepare private GDT */
gdt_segs[GPROC0_SEL].ssd_base = (long) &common_tss[cpu];
- ssdtosyssd(&gdt_segs[GPROC0_SEL],
- (struct system_segment_descriptor *)&gdt[NGDT * cpu + GPROC0_SEL]);
for (x = 0; x < NGDT; x++) {
- if (x != GPROC0_SEL && x != (GPROC0_SEL + 1))
+ if (x != GPROC0_SEL && x != (GPROC0_SEL + 1) &&
+ x != GUSERLDT_SEL && x != (GUSERLDT_SEL + 1))
ssdtosd(&gdt_segs[x], &gdt[NGDT * cpu + x]);
}
+ ssdtosyssd(&gdt_segs[GPROC0_SEL],
+ (struct system_segment_descriptor *)&gdt[NGDT * cpu + GPROC0_SEL]);
ap_gdt.rd_limit = NGDT * sizeof(gdt[0]) - 1;
ap_gdt.rd_base = (long) &gdt[NGDT * cpu];
lgdt(&ap_gdt); /* does magic intra-segment return */
@@ -486,8 +491,14 @@ init_secondary(void)
pc->pc_prvspace = pc;
pc->pc_curthread = 0;
pc->pc_tssp = &common_tss[cpu];
+ pc->pc_commontssp = &common_tss[cpu];
pc->pc_rsp0 = 0;
+ pc->pc_tss = (struct system_segment_descriptor *)&gdt[NGDT * cpu +
+ GPROC0_SEL];
+ pc->pc_fs32p = &gdt[NGDT * cpu + GUFS32_SEL];
pc->pc_gs32p = &gdt[NGDT * cpu + GUGS32_SEL];
+ pc->pc_ldt = (struct system_segment_descriptor *)&gdt[NGDT * cpu +
+ GUSERLDT_SEL];
/* Save the per-cpu pointer for use by the NMI handler. */
np->np_pcpu = (register_t) pc;
@@ -596,7 +607,7 @@ init_secondary(void)
load_cr4(rcr4() | CR4_PGE);
load_ds(_udatasel);
load_es(_udatasel);
- load_fs(_udatasel);
+ load_fs(_ufssel);
mtx_unlock_spin(&ap_boot_mtx);
/* wait until all the AP's are up */
@@ -1145,6 +1156,41 @@ cpustop_handler(void)
}
/*
+ * Handle an IPI_SUSPEND by saving our current context and spinning until we
+ * are resumed.
+ */
+void
+cpususpend_handler(void)
+{
+ struct savefpu *stopfpu;
+ register_t cr3, rf;
+ int cpu = PCPU_GET(cpuid);
+ int cpumask = PCPU_GET(cpumask);
+
+ rf = intr_disable();
+ cr3 = rcr3();
+ stopfpu = &stopxpcbs[cpu].xpcb_pcb.pcb_save;
+ if (savectx2(&stopxpcbs[cpu])) {
+ fpugetregs(curthread, stopfpu);
+ wbinvd();
+ atomic_set_int(&stopped_cpus, cpumask);
+ } else
+ fpusetregs(curthread, stopfpu);
+
+ /* Wait for resume */
+ while (!(started_cpus & cpumask))
+ ia32_pause();
+
+ atomic_clear_int(&started_cpus, cpumask);
+ atomic_clear_int(&stopped_cpus, cpumask);
+
+ /* Restore CR3 and enable interrupts */
+ load_cr3(cr3);
+ lapic_setup(0);
+ intr_restore(rf);
+}
+
+/*
* This is called once the rest of the system is up and running and we're
* ready to let the AP's out of the pen.
*/
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index f9cbad2..883b7ed 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -542,7 +542,7 @@ pmap_bootstrap(vm_paddr_t *firstaddr)
* Initialize the kernel pmap (which is statically allocated).
*/
PMAP_LOCK_INIT(kernel_pmap);
- kernel_pmap->pm_pml4 = (pdp_entry_t *) (KERNBASE + KPML4phys);
+ kernel_pmap->pm_pml4 = (pdp_entry_t *)PHYS_TO_DMAP(KPML4phys);
kernel_pmap->pm_root = NULL;
kernel_pmap->pm_active = -1; /* don't allow deactivation */
TAILQ_INIT(&kernel_pmap->pm_pvchunk);
@@ -1351,7 +1351,7 @@ pmap_pinit0(pmap_t pmap)
{
PMAP_LOCK_INIT(pmap);
- pmap->pm_pml4 = (pml4_entry_t *)(KERNBASE + KPML4phys);
+ pmap->pm_pml4 = (pml4_entry_t *)PHYS_TO_DMAP(KPML4phys);
pmap->pm_root = NULL;
pmap->pm_active = 0;
TAILQ_INIT(&pmap->pm_pvchunk);
@@ -1442,8 +1442,6 @@ _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex, int flags)
* it isn't already there.
*/
- pmap->pm_stats.resident_count++;
-
if (ptepindex >= (NUPDE + NUPDPE)) {
pml4_entry_t *pml4;
vm_pindex_t pml4index;
@@ -1469,7 +1467,8 @@ _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex, int flags)
if (_pmap_allocpte(pmap, NUPDE + NUPDPE + pml4index,
flags) == NULL) {
--m->wire_count;
- vm_page_free(m);
+ atomic_subtract_int(&cnt.v_wire_count, 1);
+ vm_page_free_zero(m);
return (NULL);
}
} else {
@@ -1501,7 +1500,8 @@ _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex, int flags)
if (_pmap_allocpte(pmap, NUPDE + pdpindex,
flags) == NULL) {
--m->wire_count;
- vm_page_free(m);
+ atomic_subtract_int(&cnt.v_wire_count, 1);
+ vm_page_free_zero(m);
return (NULL);
}
pdp = (pdp_entry_t *)PHYS_TO_DMAP(*pml4 & PG_FRAME);
@@ -1514,7 +1514,9 @@ _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex, int flags)
if (_pmap_allocpte(pmap, NUPDE + pdpindex,
flags) == NULL) {
--m->wire_count;
- vm_page_free(m);
+ atomic_subtract_int(&cnt.v_wire_count,
+ 1);
+ vm_page_free_zero(m);
return (NULL);
}
} else {
@@ -1530,6 +1532,8 @@ _pmap_allocpte(pmap_t pmap, vm_pindex_t ptepindex, int flags)
*pd = VM_PAGE_TO_PHYS(m) | PG_U | PG_RW | PG_V | PG_A | PG_M;
}
+ pmap->pm_stats.resident_count++;
+
return m;
}
@@ -2338,6 +2342,7 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva,
mpte = pmap_lookup_pt_page(pmap, sva);
if (mpte != NULL) {
pmap_remove_pt_page(pmap, mpte);
+ pmap->pm_stats.resident_count--;
KASSERT(mpte->wire_count == NPTEPG,
("pmap_remove_pde: pte page wire count error"));
mpte->wire_count = 0;
@@ -3847,6 +3852,7 @@ pmap_remove_pages(pmap_t pmap)
mpte = pmap_lookup_pt_page(pmap, pv->pv_va);
if (mpte != NULL) {
pmap_remove_pt_page(pmap, mpte);
+ pmap->pm_stats.resident_count--;
KASSERT(mpte->wire_count == NPTEPG,
("pmap_remove_pages: pte page wire count error"));
mpte->wire_count = 0;
@@ -4689,7 +4695,7 @@ if (oldpmap) /* XXX FIXME */
oldpmap->pm_active &= ~PCPU_GET(cpumask);
pmap->pm_active |= PCPU_GET(cpumask);
#endif
- cr3 = vtophys(pmap->pm_pml4);
+ cr3 = DMAP_TO_PHYS((vm_offset_t)pmap->pm_pml4);
td->td_pcb->pcb_cr3 = cr3;
load_cr3(cr3);
critical_exit();
diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c
index 7f022d0..834dd2c 100644
--- a/sys/amd64/amd64/sys_machdep.c
+++ b/sys/amd64/amd64/sys_machdep.c
@@ -36,16 +36,39 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/sysproto.h>
-#include <machine/specialreg.h>
-#include <machine/sysarch.h>
-#include <machine/pcb.h>
+#include <sys/uio.h>
#include <vm/vm.h>
#include <vm/pmap.h>
+#include <vm/vm_kern.h> /* for kernel_map */
+#include <vm/vm_extern.h>
+
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+#include <machine/specialreg.h>
+#include <machine/sysarch.h>
+#include <machine/tss.h>
#include <machine/vmparam.h>
+#include <security/audit/audit.h>
+
+int max_ldt_segment = 1024;
+#define LD_PER_PAGE 512
+#define NULL_LDT_BASE ((caddr_t)NULL)
+
+#ifdef notyet
+#ifdef SMP
+static void set_user_ldt_rv(struct vmspace *vmsp);
+#endif
+#endif
+static void user_ldt_derefl(struct proc_ldt *pldt);
+
#ifndef _SYS_SYSPROTO_H_
struct sysarch_args {
int op;
@@ -54,6 +77,83 @@ struct sysarch_args {
#endif
int
+sysarch_ldt(struct thread *td, struct sysarch_args *uap, int uap_space)
+{
+ struct i386_ldt_args *largs, la;
+ struct user_segment_descriptor *lp;
+ int error = 0;
+
+ /*
+ * XXXKIB check that the BSM generation code knows to encode
+ * the op argument.
+ */
+ AUDIT_ARG(cmd, uap->op);
+ if (uap_space == UIO_USERSPACE) {
+ error = copyin(uap->parms, &la, sizeof(struct i386_ldt_args));
+ if (error != 0)
+ return (error);
+ largs = &la;
+ } else
+ largs = (struct i386_ldt_args *)uap->parms;
+ if (largs->num > max_ldt_segment || largs->num <= 0)
+ return (EINVAL);
+
+ switch (uap->op) {
+ case I386_GET_LDT:
+ error = amd64_get_ldt(td, largs);
+ break;
+ case I386_SET_LDT:
+ if (largs->descs != NULL) {
+ lp = (struct user_segment_descriptor *)
+ kmem_alloc(kernel_map, largs->num *
+ sizeof(struct user_segment_descriptor));
+ if (lp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ error = copyin(largs->descs, lp, largs->num *
+ sizeof(struct user_segment_descriptor));
+ if (error == 0)
+ error = amd64_set_ldt(td, largs, lp);
+ kmem_free(kernel_map, (vm_offset_t)lp, largs->num *
+ sizeof(struct user_segment_descriptor));
+ } else {
+ error = amd64_set_ldt(td, largs, NULL);
+ }
+ break;
+ }
+ return (error);
+}
+
+void
+update_gdt_gsbase(struct thread *td, uint32_t base)
+{
+ struct user_segment_descriptor *sd;
+
+ if (td != curthread)
+ return;
+ critical_enter();
+ sd = PCPU_GET(gs32p);
+ sd->sd_lobase = base & 0xffffff;
+ sd->sd_hibase = (base >> 24) & 0xff;
+ critical_exit();
+}
+
+void
+update_gdt_fsbase(struct thread *td, uint32_t base)
+{
+ struct user_segment_descriptor *sd;
+
+ if (td != curthread)
+ return;
+ critical_enter();
+ sd = PCPU_GET(fs32p);
+ sd->sd_lobase = base & 0xffffff;
+ sd->sd_hibase = (base >> 24) & 0xff;
+ critical_exit();
+}
+
+int
sysarch(td, uap)
struct thread *td;
register struct sysarch_args *uap;
@@ -62,8 +162,36 @@ sysarch(td, uap)
struct pcb *pcb = curthread->td_pcb;
uint32_t i386base;
uint64_t a64base;
+ struct i386_ioperm_args iargs;
+
+ if (uap->op == I386_GET_LDT || uap->op == I386_SET_LDT)
+ return (sysarch_ldt(td, uap, UIO_USERSPACE));
+ /*
+ * XXXKIB check that the BSM generation code knows to encode
+ * the op argument.
+ */
+ AUDIT_ARG(cmd, uap->op);
+ switch (uap->op) {
+ case I386_GET_IOPERM:
+ case I386_SET_IOPERM:
+ if ((error = copyin(uap->parms, &iargs,
+ sizeof(struct i386_ioperm_args))) != 0)
+ return (error);
+ break;
+ default:
+ break;
+ }
- switch(uap->op) {
+ switch (uap->op) {
+ case I386_GET_IOPERM:
+ error = amd64_get_ioperm(td, &iargs);
+ if (error == 0)
+ error = copyout(&iargs, uap->parms,
+ sizeof(struct i386_ioperm_args));
+ break;
+ case I386_SET_IOPERM:
+ error = amd64_set_ioperm(td, &iargs);
+ break;
case I386_GET_FSBASE:
i386base = pcb->pcb_fsbase;
error = copyout(&i386base, uap->parms, sizeof(i386base));
@@ -71,10 +199,9 @@ sysarch(td, uap)
case I386_SET_FSBASE:
error = copyin(uap->parms, &i386base, sizeof(i386base));
if (!error) {
- critical_enter();
- wrmsr(MSR_FSBASE, i386base);
pcb->pcb_fsbase = i386base;
- critical_exit();
+ td->td_frame->tf_fs = _ufssel;
+ update_gdt_fsbase(td, i386base);
}
break;
case I386_GET_GSBASE:
@@ -84,10 +211,9 @@ sysarch(td, uap)
case I386_SET_GSBASE:
error = copyin(uap->parms, &i386base, sizeof(i386base));
if (!error) {
- critical_enter();
- wrmsr(MSR_KGSBASE, i386base);
pcb->pcb_gsbase = i386base;
- critical_exit();
+ td->td_frame->tf_gs = _ugssel;
+ update_gdt_gsbase(td, i386base);
}
break;
case AMD64_GET_FSBASE:
@@ -98,13 +224,10 @@ sysarch(td, uap)
error = copyin(uap->parms, &a64base, sizeof(a64base));
if (!error) {
if (a64base < VM_MAXUSER_ADDRESS) {
- critical_enter();
- wrmsr(MSR_FSBASE, a64base);
pcb->pcb_fsbase = a64base;
- critical_exit();
- } else {
+ td->td_frame->tf_fs = _ufssel;
+ } else
error = EINVAL;
- }
}
break;
@@ -116,13 +239,10 @@ sysarch(td, uap)
error = copyin(uap->parms, &a64base, sizeof(a64base));
if (!error) {
if (a64base < VM_MAXUSER_ADDRESS) {
- critical_enter();
- wrmsr(MSR_KGSBASE, a64base);
pcb->pcb_gsbase = a64base;
- critical_exit();
- } else {
+ td->td_frame->tf_gs = _ugssel;
+ } else
error = EINVAL;
- }
}
break;
@@ -132,3 +252,424 @@ sysarch(td, uap)
}
return (error);
}
+
+int
+amd64_set_ioperm(td, uap)
+ struct thread *td;
+ struct i386_ioperm_args *uap;
+{
+ int i, error;
+ char *iomap;
+ struct amd64tss *tssp;
+ struct system_segment_descriptor *tss_sd;
+ u_long *addr;
+ struct pcb *pcb;
+
+ if ((error = priv_check(td, PRIV_IO)) != 0)
+ return (error);
+ if ((error = securelevel_gt(td->td_ucred, 0)) != 0)
+ return (error);
+ if (uap->start + uap->length > IOPAGES * PAGE_SIZE * NBBY)
+ return (EINVAL);
+
+ /*
+ * XXX
+ * While this is restricted to root, we should probably figure out
+ * whether any other driver is using this i/o address, as so not to
+ * cause confusion. This probably requires a global 'usage registry'.
+ */
+ pcb = td->td_pcb;
+ if (pcb->pcb_tssp == NULL) {
+ tssp = (struct amd64tss *)kmem_alloc(kernel_map,
+ ctob(IOPAGES+1));
+ if (tssp == NULL)
+ return (ENOMEM);
+ iomap = (char *)&tssp[1];
+ addr = (u_long *)iomap;
+ for (i = 0; i < (ctob(IOPAGES) + 1) / sizeof(u_long); i++)
+ *addr++ = ~0;
+ critical_enter();
+ /* Takes care of tss_rsp0. */
+ memcpy(tssp, &common_tss[PCPU_GET(cpuid)],
+ sizeof(struct amd64tss));
+ tssp->tss_iobase = sizeof(*tssp);
+ pcb->pcb_tssp = tssp;
+ tss_sd = PCPU_GET(tss);
+ tss_sd->sd_lobase = (u_long)tssp & 0xffffff;
+ tss_sd->sd_hibase = ((u_long)tssp >> 24) & 0xfffffffffful;
+ tss_sd->sd_type = SDT_SYSTSS;
+ ltr(GSEL(GPROC0_SEL, SEL_KPL));
+ PCPU_SET(tssp, tssp);
+ critical_exit();
+ } else
+ iomap = (char *)&pcb->pcb_tssp[1];
+ for (i = uap->start; i < uap->start + uap->length; i++) {
+ if (uap->enable)
+ iomap[i >> 3] &= ~(1 << (i & 7));
+ else
+ iomap[i >> 3] |= (1 << (i & 7));
+ }
+ return (error);
+}
+
+int
+amd64_get_ioperm(td, uap)
+ struct thread *td;
+ struct i386_ioperm_args *uap;
+{
+ int i, state;
+ char *iomap;
+
+ if (uap->start >= IOPAGES * PAGE_SIZE * NBBY)
+ return (EINVAL);
+ if (td->td_pcb->pcb_tssp == NULL) {
+ uap->length = 0;
+ goto done;
+ }
+
+ iomap = (char *)&td->td_pcb->pcb_tssp[1];
+
+ i = uap->start;
+ state = (iomap[i >> 3] >> (i & 7)) & 1;
+ uap->enable = !state;
+ uap->length = 1;
+
+ for (i = uap->start + 1; i < IOPAGES * PAGE_SIZE * NBBY; i++) {
+ if (state != ((iomap[i >> 3] >> (i & 7)) & 1))
+ break;
+ uap->length++;
+ }
+
+done:
+ return (0);
+}
+
+/*
+ * Update the GDT entry pointing to the LDT to point to the LDT of the
+ * current process.
+ */
+void
+set_user_ldt(struct mdproc *mdp)
+{
+
+ critical_enter();
+ *PCPU_GET(ldt) = mdp->md_ldt_sd;
+ lldt(GSEL(GUSERLDT_SEL, SEL_KPL));
+ critical_exit();
+}
+
+#ifdef notyet
+#ifdef SMP
+static void
+set_user_ldt_rv(struct vmspace *vmsp)
+{
+ struct thread *td;
+
+ td = curthread;
+ if (vmsp != td->td_proc->p_vmspace)
+ return;
+
+ set_user_ldt(&td->td_proc->p_md);
+}
+#endif
+#endif
+
+struct proc_ldt *
+user_ldt_alloc(struct proc *p, int force)
+{
+ struct proc_ldt *pldt, *new_ldt;
+ struct mdproc *mdp;
+ struct soft_segment_descriptor sldt;
+
+ mtx_assert(&dt_lock, MA_OWNED);
+ mdp = &p->p_md;
+ if (!force && mdp->md_ldt != NULL)
+ return (mdp->md_ldt);
+ mtx_unlock(&dt_lock);
+ new_ldt = malloc(sizeof(struct proc_ldt), M_SUBPROC, M_WAITOK);
+ new_ldt->ldt_base = (caddr_t)kmem_alloc(kernel_map,
+ max_ldt_segment * sizeof(struct user_segment_descriptor));
+ if (new_ldt->ldt_base == NULL) {
+ FREE(new_ldt, M_SUBPROC);
+ mtx_lock(&dt_lock);
+ return (NULL);
+ }
+ new_ldt->ldt_refcnt = 1;
+ sldt.ssd_base = (uint64_t)new_ldt->ldt_base;
+ sldt.ssd_limit = max_ldt_segment *
+ sizeof(struct user_segment_descriptor) - 1;
+ sldt.ssd_type = SDT_SYSLDT;
+ sldt.ssd_dpl = SEL_KPL;
+ sldt.ssd_p = 1;
+ sldt.ssd_long = 0;
+ sldt.ssd_def32 = 0;
+ sldt.ssd_gran = 0;
+ mtx_lock(&dt_lock);
+ pldt = mdp->md_ldt;
+ if (pldt != NULL && !force) {
+ kmem_free(kernel_map, (vm_offset_t)new_ldt->ldt_base,
+ max_ldt_segment * sizeof(struct user_segment_descriptor));
+ free(new_ldt, M_SUBPROC);
+ return (pldt);
+ }
+
+ mdp->md_ldt = new_ldt;
+ if (pldt != NULL) {
+ bcopy(pldt->ldt_base, new_ldt->ldt_base, max_ldt_segment *
+ sizeof(struct user_segment_descriptor));
+ user_ldt_derefl(pldt);
+ }
+ ssdtosyssd(&sldt, &p->p_md.md_ldt_sd);
+ if (p == curproc)
+ set_user_ldt(mdp);
+
+ return (mdp->md_ldt);
+}
+
+void
+user_ldt_free(struct thread *td)
+{
+ struct proc *p = td->td_proc;
+ struct mdproc *mdp = &p->p_md;
+ struct proc_ldt *pldt;
+
+ mtx_assert(&dt_lock, MA_OWNED);
+ if ((pldt = mdp->md_ldt) == NULL) {
+ mtx_unlock(&dt_lock);
+ return;
+ }
+
+ mdp->md_ldt = NULL;
+ bzero(&mdp->md_ldt_sd, sizeof(mdp->md_ldt_sd));
+ if (td == curthread)
+ lldt(GSEL(GNULL_SEL, SEL_KPL));
+ user_ldt_deref(pldt);
+}
+
+static void
+user_ldt_derefl(struct proc_ldt *pldt)
+{
+
+ if (--pldt->ldt_refcnt == 0) {
+ kmem_free(kernel_map, (vm_offset_t)pldt->ldt_base,
+ max_ldt_segment * sizeof(struct user_segment_descriptor));
+ free(pldt, M_SUBPROC);
+ }
+}
+
+void
+user_ldt_deref(struct proc_ldt *pldt)
+{
+
+ mtx_assert(&dt_lock, MA_OWNED);
+ user_ldt_derefl(pldt);
+ mtx_unlock(&dt_lock);
+}
+
+/*
+ * Note for the authors of compat layers (linux, etc): copyout() in
+ * the function below is not a problem since it presents data in
+ * arch-specific format (i.e. i386-specific in this case), not in
+ * the OS-specific one.
+ */
+int
+amd64_get_ldt(td, uap)
+ struct thread *td;
+ struct i386_ldt_args *uap;
+{
+ int error = 0;
+ struct proc_ldt *pldt;
+ int num;
+ struct user_segment_descriptor *lp;
+
+#ifdef DEBUG
+ printf("amd64_get_ldt: start=%d num=%d descs=%p\n",
+ uap->start, uap->num, (void *)uap->descs);
+#endif
+
+ if ((pldt = td->td_proc->p_md.md_ldt) != NULL) {
+ lp = &((struct user_segment_descriptor *)(pldt->ldt_base))
+ [uap->start];
+ num = min(uap->num, max_ldt_segment);
+ } else
+ return (EINVAL);
+
+ if ((uap->start > (unsigned int)max_ldt_segment) ||
+ ((unsigned int)num > (unsigned int)max_ldt_segment) ||
+ ((unsigned int)(uap->start + num) > (unsigned int)max_ldt_segment))
+ return(EINVAL);
+
+ error = copyout(lp, uap->descs, num *
+ sizeof(struct user_segment_descriptor));
+ if (!error)
+ td->td_retval[0] = num;
+
+ return(error);
+}
+
+int
+amd64_set_ldt(td, uap, descs)
+ struct thread *td;
+ struct i386_ldt_args *uap;
+ struct user_segment_descriptor *descs;
+{
+ int error = 0, i;
+ int largest_ld;
+ struct mdproc *mdp = &td->td_proc->p_md;
+ struct proc_ldt *pldt;
+ struct user_segment_descriptor *dp;
+ struct proc *p;
+
+#ifdef DEBUG
+ printf("amd64_set_ldt: start=%d num=%d descs=%p\n",
+ uap->start, uap->num, (void *)uap->descs);
+#endif
+
+ p = td->td_proc;
+ if (descs == NULL) {
+ /* Free descriptors */
+ if (uap->start == 0 && uap->num == 0)
+ uap->num = max_ldt_segment;
+ if (uap->num <= 0)
+ return (EINVAL);
+ if ((pldt = mdp->md_ldt) == NULL ||
+ uap->start >= max_ldt_segment)
+ return (0);
+ largest_ld = uap->start + uap->num;
+ if (largest_ld > max_ldt_segment)
+ largest_ld = max_ldt_segment;
+ i = largest_ld - uap->start;
+ mtx_lock(&dt_lock);
+ bzero(&((struct user_segment_descriptor *)(pldt->ldt_base))
+ [uap->start], sizeof(struct user_segment_descriptor) * i);
+ mtx_unlock(&dt_lock);
+ return (0);
+ }
+
+ if (!(uap->start == LDT_AUTO_ALLOC && uap->num == 1)) {
+ /* verify range of descriptors to modify */
+ largest_ld = uap->start + uap->num;
+ if (uap->start >= max_ldt_segment ||
+ uap->num < 0 || largest_ld > max_ldt_segment)
+ return (EINVAL);
+ }
+
+ /* Check descriptors for access violations */
+ for (i = 0; i < uap->num; i++) {
+ dp = &descs[i];
+
+ switch (dp->sd_type) {
+ case SDT_SYSNULL: /* system null */
+ dp->sd_p = 0;
+ break;
+ case SDT_SYS286TSS:
+ case SDT_SYSLDT:
+ case SDT_SYS286BSY:
+ case SDT_SYS286CGT:
+ case SDT_SYSTASKGT:
+ case SDT_SYS286IGT:
+ case SDT_SYS286TGT:
+ case SDT_SYSNULL2:
+ case SDT_SYSTSS:
+ case SDT_SYSNULL3:
+ case SDT_SYSBSY:
+ case SDT_SYSCGT:
+ case SDT_SYSNULL4:
+ case SDT_SYSIGT:
+ case SDT_SYSTGT:
+ /* I can't think of any reason to allow a user proc
+ * to create a segment of these types. They are
+ * for OS use only.
+ */
+ return (EACCES);
+ /*NOTREACHED*/
+
+ /* memory segment types */
+ case SDT_MEMEC: /* memory execute only conforming */
+ case SDT_MEMEAC: /* memory execute only accessed conforming */
+ case SDT_MEMERC: /* memory execute read conforming */
+ case SDT_MEMERAC: /* memory execute read accessed conforming */
+ /* Must be "present" if executable and conforming. */
+ if (dp->sd_p == 0)
+ return (EACCES);
+ break;
+ case SDT_MEMRO: /* memory read only */
+ case SDT_MEMROA: /* memory read only accessed */
+ case SDT_MEMRW: /* memory read write */
+ case SDT_MEMRWA: /* memory read write accessed */
+ case SDT_MEMROD: /* memory read only expand dwn limit */
+ case SDT_MEMRODA: /* memory read only expand dwn lim accessed */
+ case SDT_MEMRWD: /* memory read write expand dwn limit */
+ case SDT_MEMRWDA: /* memory read write expand dwn lim acessed */
+ case SDT_MEME: /* memory execute only */
+ case SDT_MEMEA: /* memory execute only accessed */
+ case SDT_MEMER: /* memory execute read */
+ case SDT_MEMERA: /* memory execute read accessed */
+ break;
+ default:
+ return(EINVAL);
+ /*NOTREACHED*/
+ }
+
+ /* Only user (ring-3) descriptors may be present. */
+ if ((dp->sd_p != 0) && (dp->sd_dpl != SEL_UPL))
+ return (EACCES);
+ }
+
+ if (uap->start == LDT_AUTO_ALLOC && uap->num == 1) {
+ /* Allocate a free slot */
+ mtx_lock(&dt_lock);
+ pldt = user_ldt_alloc(p, 0);
+ if (pldt == NULL) {
+ mtx_unlock(&dt_lock);
+ return (ENOMEM);
+ }
+
+ /*
+ * start scanning a bit up to leave room for NVidia and
+ * Wine, which still user the "Blat" method of allocation.
+ */
+ i = 16;
+ dp = &((struct user_segment_descriptor *)(pldt->ldt_base))[i];
+ for (; i < max_ldt_segment; ++i, ++dp) {
+ if (dp->sd_type == SDT_SYSNULL)
+ break;
+ }
+ if (i >= max_ldt_segment) {
+ mtx_unlock(&dt_lock);
+ return (ENOSPC);
+ }
+ uap->start = i;
+ error = amd64_set_ldt_data(td, i, 1, descs);
+ mtx_unlock(&dt_lock);
+ } else {
+ largest_ld = uap->start + uap->num;
+ if (largest_ld > max_ldt_segment)
+ return (EINVAL);
+ mtx_lock(&dt_lock);
+ if (user_ldt_alloc(p, 0) != NULL) {
+ error = amd64_set_ldt_data(td, uap->start, uap->num,
+ descs);
+ }
+ mtx_unlock(&dt_lock);
+ }
+ if (error == 0)
+ td->td_retval[0] = uap->start;
+ return (error);
+}
+
+int
+amd64_set_ldt_data(struct thread *td, int start, int num,
+ struct user_segment_descriptor *descs)
+{
+ struct mdproc *mdp = &td->td_proc->p_md;
+ struct proc_ldt *pldt = mdp->md_ldt;
+
+ mtx_assert(&dt_lock, MA_OWNED);
+
+ /* Fill in range */
+ bcopy(descs,
+ &((struct user_segment_descriptor *)(pldt->ldt_base))[start],
+ num * sizeof(struct user_segment_descriptor));
+ return (0);
+}
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index a519414..467feaf 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -171,6 +171,52 @@ SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW,
extern char *syscallnames[];
+/* #define DEBUG 1 */
+#ifdef DEBUG
+static void
+report_seg_fault(const char *segn, struct trapframe *frame)
+{
+ struct proc_ldt *pldt;
+ struct trapframe *pf;
+
+ pldt = curproc->p_md.md_ldt;
+ printf("%d: %s load fault %lx %p %d\n",
+ curproc->p_pid, segn, frame->tf_err,
+ pldt != NULL ? pldt->ldt_base : NULL,
+ pldt != NULL ? pldt->ldt_refcnt : 0);
+ kdb_backtrace();
+ pf = (struct trapframe *)frame->tf_rsp;
+ printf("rdi %lx\n", pf->tf_rdi);
+ printf("rsi %lx\n", pf->tf_rsi);
+ printf("rdx %lx\n", pf->tf_rdx);
+ printf("rcx %lx\n", pf->tf_rcx);
+ printf("r8 %lx\n", pf->tf_r8);
+ printf("r9 %lx\n", pf->tf_r9);
+ printf("rax %lx\n", pf->tf_rax);
+ printf("rbx %lx\n", pf->tf_rbx);
+ printf("rbp %lx\n", pf->tf_rbp);
+ printf("r10 %lx\n", pf->tf_r10);
+ printf("r11 %lx\n", pf->tf_r11);
+ printf("r12 %lx\n", pf->tf_r12);
+ printf("r13 %lx\n", pf->tf_r13);
+ printf("r14 %lx\n", pf->tf_r14);
+ printf("r15 %lx\n", pf->tf_r15);
+ printf("fs %x\n", pf->tf_fs);
+ printf("gs %x\n", pf->tf_gs);
+ printf("es %x\n", pf->tf_es);
+ printf("ds %x\n", pf->tf_ds);
+ printf("tno %x\n", pf->tf_trapno);
+ printf("adr %lx\n", pf->tf_addr);
+ printf("flg %x\n", pf->tf_flags);
+ printf("err %lx\n", pf->tf_err);
+ printf("rip %lx\n", pf->tf_rip);
+ printf("cs %lx\n", pf->tf_cs);
+ printf("rfl %lx\n", pf->tf_rflags);
+ printf("rsp %lx\n", pf->tf_rsp);
+ printf("ss %lx\n", pf->tf_ss);
+}
+#endif
+
/*
* Exception, fault, and trap interface to the FreeBSD kernel.
* This common code is called from assembly language IDT gate entry
@@ -258,6 +304,9 @@ trap(struct trapframe *frame)
*/
printf("kernel trap %d with interrupts disabled\n",
type);
+#ifdef DEBUG
+ report_seg_fault("hlt", frame);
+#endif
/*
* We shouldn't enable interrupts while holding a
* spin lock or servicing an NMI.
@@ -470,6 +519,38 @@ trap(struct trapframe *frame)
frame->tf_rip = (long)doreti_iret_fault;
goto out;
}
+ if (frame->tf_rip == (long)ld_ds) {
+#ifdef DEBUG
+ report_seg_fault("ds", frame);
+#endif
+ frame->tf_rip = (long)ds_load_fault;
+ frame->tf_ds = _udatasel;
+ goto out;
+ }
+ if (frame->tf_rip == (long)ld_es) {
+#ifdef DEBUG
+ report_seg_fault("es", frame);
+#endif
+ frame->tf_rip = (long)es_load_fault;
+ frame->tf_es = _udatasel;
+ goto out;
+ }
+ if (frame->tf_rip == (long)ld_fs) {
+#ifdef DEBUG
+ report_seg_fault("fs", frame);
+#endif
+ frame->tf_rip = (long)fs_load_fault;
+ frame->tf_fs = _ufssel;
+ goto out;
+ }
+ if (frame->tf_rip == (long)ld_gs) {
+#ifdef DEBUG
+ report_seg_fault("gs", frame);
+#endif
+ frame->tf_rip = (long)gs_load_fault;
+ frame->tf_gs = _ugssel;
+ goto out;
+ }
if (PCPU_GET(curpcb)->pcb_onfault != NULL) {
frame->tf_rip =
(long)PCPU_GET(curpcb)->pcb_onfault;
@@ -564,6 +645,9 @@ trap(struct trapframe *frame)
trapsignal(td, &ksi);
#ifdef DEBUG
+{
+ register_t rg,rgk, rf;
+
if (type <= MAX_TRAP_MSG) {
uprintf("fatal process exception: %s",
trap_msg[type]);
@@ -571,6 +655,17 @@ trap(struct trapframe *frame)
uprintf(", fault VA = 0x%lx", frame->tf_addr);
uprintf("\n");
}
+ rf = rdmsr(0xc0000100);
+ rg = rdmsr(0xc0000101);
+ rgk = rdmsr(0xc0000102);
+ uprintf("pid %d TRAP %d rip %lx err %lx addr %lx cs %lx ss %lx ds %x "
+ "es %x fs %x fsbase %lx %lx gs %x gsbase %lx %lx %lx\n",
+ curproc->p_pid, type, frame->tf_rip, frame->tf_err,
+ frame->tf_addr,
+ frame->tf_cs, frame->tf_ss, frame->tf_ds, frame->tf_es,
+ frame->tf_fs, td->td_pcb->pcb_fsbase, rf,
+ frame->tf_gs, td->td_pcb->pcb_gsbase, rg, rgk);
+}
#endif
user:
diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c
index 1e87bdc..928be34 100644
--- a/sys/amd64/amd64/vm_machdep.c
+++ b/sys/amd64/amd64/vm_machdep.c
@@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/specialreg.h>
+#include <machine/tss.h>
#include <vm/vm.h>
#include <vm/vm_extern.h>
@@ -102,11 +103,24 @@ cpu_fork(td1, p2, td2, flags)
{
register struct proc *p1;
struct pcb *pcb2;
- struct mdproc *mdp2;
+ struct mdproc *mdp1, *mdp2;
+ struct proc_ldt *pldt;
+ pmap_t pmap2;
p1 = td1->td_proc;
- if ((flags & RFPROC) == 0)
+ if ((flags & RFPROC) == 0) {
+ if ((flags & RFMEM) == 0) {
+ /* unshare user LDT */
+ mdp1 = &p1->p_md;
+ mtx_lock(&dt_lock);
+ if ((pldt = mdp1->md_ldt) != NULL &&
+ pldt->ldt_refcnt > 1 &&
+ user_ldt_alloc(p1, 1) == NULL)
+ panic("could not copy LDT");
+ mtx_unlock(&dt_lock);
+ }
return;
+ }
/* Ensure that p1's pcb is up to date. */
fpuexit(td1);
@@ -150,7 +164,8 @@ cpu_fork(td1, p2, td2, flags)
* Set registers for trampoline to user mode. Leave space for the
* return address on stack. These are the kernel mode register values.
*/
- pcb2->pcb_cr3 = vtophys(vmspace_pmap(p2->p_vmspace)->pm_pml4);
+ pmap2 = vmspace_pmap(p2->p_vmspace);
+ pcb2->pcb_cr3 = DMAP_TO_PHYS((vm_offset_t)pmap2->pm_pml4);
pcb2->pcb_r12 = (register_t)fork_return; /* fork_trampoline argument */
pcb2->pcb_rbp = 0;
pcb2->pcb_rsp = (register_t)td2->td_frame - sizeof(void *);
@@ -168,6 +183,32 @@ cpu_fork(td1, p2, td2, flags)
td2->td_md.md_spinlock_count = 1;
td2->td_md.md_saved_flags = PSL_KERNEL | PSL_I;
+ /* As an i386, do not copy io permission bitmap. */
+ pcb2->pcb_tssp = NULL;
+
+ /* Copy the LDT, if necessary. */
+ mdp1 = &td1->td_proc->p_md;
+ mdp2 = &p2->p_md;
+ mtx_lock(&dt_lock);
+ if (mdp1->md_ldt != NULL) {
+ if (flags & RFMEM) {
+ mdp1->md_ldt->ldt_refcnt++;
+ mdp2->md_ldt = mdp1->md_ldt;
+ bcopy(&mdp1->md_ldt_sd, &mdp2->md_ldt_sd, sizeof(struct
+ system_segment_descriptor));
+ } else {
+ mdp2->md_ldt = NULL;
+ mdp2->md_ldt = user_ldt_alloc(p2, 0);
+ if (mdp2->md_ldt == NULL)
+ panic("could not copy LDT");
+ amd64_set_ldt_data(td2, 0, max_ldt_segment,
+ (struct user_segment_descriptor *)
+ mdp1->md_ldt->ldt_base);
+ }
+ } else
+ mdp2->md_ldt = NULL;
+ mtx_unlock(&dt_lock);
+
/*
* Now, cpu_switch() can schedule the new process.
* pcb_rsp is loaded pointing to the cpu_switch() stack frame
@@ -202,25 +243,49 @@ cpu_set_fork_handler(td, func, arg)
void
cpu_exit(struct thread *td)
{
+
+ /*
+ * If this process has a custom LDT, release it.
+ */
+ mtx_lock(&dt_lock);
+ if (td->td_proc->p_md.md_ldt != 0)
+ user_ldt_free(td);
+ else
+ mtx_unlock(&dt_lock);
}
void
cpu_thread_exit(struct thread *td)
{
+ struct pcb *pcb;
if (td == PCPU_GET(fpcurthread))
fpudrop();
+ pcb = td->td_pcb;
+
/* Disable any hardware breakpoints. */
- if (td->td_pcb->pcb_flags & PCB_DBREGS) {
+ if (pcb->pcb_flags & PCB_DBREGS) {
reset_dbregs();
- td->td_pcb->pcb_flags &= ~PCB_DBREGS;
+ pcb->pcb_flags &= ~PCB_DBREGS;
}
}
void
cpu_thread_clean(struct thread *td)
{
+ struct pcb *pcb;
+
+ pcb = td->td_pcb;
+
+ /*
+ * Clean TSS/iomap
+ */
+ if (pcb->pcb_tssp != NULL) {
+ kmem_free(kernel_map, (vm_offset_t)pcb->pcb_tssp,
+ ctob(IOPAGES + 1));
+ pcb->pcb_tssp = NULL;
+ }
}
void
@@ -245,6 +310,8 @@ cpu_thread_alloc(struct thread *td)
void
cpu_thread_free(struct thread *td)
{
+
+ cpu_thread_clean(td);
}
/*
@@ -287,7 +354,6 @@ cpu_set_upcall(struct thread *td, struct thread *td0)
* Set registers for trampoline to user mode. Leave space for the
* return address on stack. These are the kernel mode register values.
*/
- pcb2->pcb_cr3 = vtophys(vmspace_pmap(td->td_proc->p_vmspace)->pm_pml4);
pcb2->pcb_r12 = (register_t)fork_return; /* trampoline arg */
pcb2->pcb_rbp = 0;
pcb2->pcb_rsp = (register_t)td->td_frame - sizeof(void *); /* trampoline arg */
@@ -295,6 +361,7 @@ cpu_set_upcall(struct thread *td, struct thread *td0)
pcb2->pcb_rip = (register_t)fork_trampoline;
/*
* If we didn't copy the pcb, we'd need to do the following registers:
+ * pcb2->pcb_cr3: cloned above.
* pcb2->pcb_dr*: cloned above.
* pcb2->pcb_savefpu: cloned above.
* pcb2->pcb_onfault: cloned above (always NULL here?).
@@ -356,6 +423,11 @@ cpu_set_upcall_kse(struct thread *td, void (*entry)(void *), void *arg,
((register_t)stack->ss_sp + stack->ss_size) & ~0x0f;
td->td_frame->tf_rsp -= 8;
td->td_frame->tf_rip = (register_t)entry;
+ td->td_frame->tf_ds = _udatasel;
+ td->td_frame->tf_es = _udatasel;
+ td->td_frame->tf_fs = _ufssel;
+ td->td_frame->tf_gs = _ugssel;
+ td->td_frame->tf_flags = TF_HASSEGS;
/*
* Pass the address of the mailbox for this kse to the uts
@@ -373,25 +445,11 @@ cpu_set_user_tls(struct thread *td, void *tls_base)
#ifdef COMPAT_IA32
if (td->td_proc->p_sysent->sv_flags & SV_ILP32) {
- if (td == curthread) {
- critical_enter();
- td->td_pcb->pcb_gsbase = (register_t)tls_base;
- wrmsr(MSR_KGSBASE, td->td_pcb->pcb_gsbase);
- critical_exit();
- } else {
- td->td_pcb->pcb_gsbase = (register_t)tls_base;
- }
+ td->td_pcb->pcb_gsbase = (register_t)tls_base;
return (0);
}
#endif
- if (td == curthread) {
- critical_enter();
- td->td_pcb->pcb_fsbase = (register_t)tls_base;
- wrmsr(MSR_FSBASE, td->td_pcb->pcb_fsbase);
- critical_exit();
- } else {
- td->td_pcb->pcb_fsbase = (register_t)tls_base;
- }
+ td->td_pcb->pcb_fsbase = (register_t)tls_base;
return (0);
}
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 197de84..663420f 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -200,7 +200,7 @@ device ppi # Parallel port interface device
device de # DEC/Intel DC21x4x (``Tulip'')
device em # Intel PRO/1000 Gigabit Ethernet Family
device igb # Intel PRO/1000 PCIE Server Gigabit Family
-device ixgb # Intel PRO/10GbE Ethernet Card
+device ixgbe # Intel PRO/10GbE PCIE Ethernet Family
device le # AMD Am7900 LANCE and Am79C9xx PCnet
device ti # Alteon Networks Tigon I/II gigabit Ethernet
device txp # 3Com 3cR990 (``Typhoon'')
@@ -295,7 +295,6 @@ device ums # Mouse
device ural # Ralink Technology RT2500USB wireless NICs
device rum # Ralink Technology RT2501USB wireless NICs
device urio # Diamond Rio 500 MP3 player
-device uscanner # Scanners
# USB Serial devices
device uark # Technologies ARK3116 based serial adapters
device ubsa # Belkin F5U103 and compatible serial adapters
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index 76dca9d..95ae9be 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -400,10 +400,10 @@ device ichwd
# Temperature sensors:
#
# coretemp: on-die sensor on Intel Core and newer CPUs
-# k8temp: on-die sensor on AMD K8 CPUs
+# amdtemp: on-die sensor on AMD K8/K10/K11 CPUs
#
device coretemp
-device k8temp
+device amdtemp
#
# CPU control pseudo-device. Provides access to MSRs, CPUID info and
diff --git a/sys/amd64/ia32/ia32_exception.S b/sys/amd64/ia32/ia32_exception.S
index 4820f53..76c5d5a 100644
--- a/sys/amd64/ia32/ia32_exception.S
+++ b/sys/amd64/ia32/ia32_exception.S
@@ -60,6 +60,11 @@ IDTVEC(int0x80_syscall)
movq %r13,TF_R13(%rsp)
movq %r14,TF_R14(%rsp)
movq %r15,TF_R15(%rsp)
+ movw %fs,TF_FS(%rsp)
+ movw %gs,TF_GS(%rsp)
+ movw %es,TF_ES(%rsp)
+ movw %ds,TF_DS(%rsp)
+ movl $TF_HASSEGS,TF_FLAGS(%rsp)
FAKE_MCOUNT(TF_RIP(%rsp))
movq %rsp, %rdi
call ia32_syscall
diff --git a/sys/mips/atheros/uart_cpu_ar71xx.c b/sys/amd64/ia32/ia32_misc.c
index 4d6b7e7..2fa1972 100644
--- a/sys/mips/atheros/uart_cpu_ar71xx.c
+++ b/sys/amd64/ia32/ia32_misc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2009 Oleksandr Tymoshenko
+ * Copyright (c) 2009 Konstantin Belousov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,57 +22,50 @@
* 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 "opt_uart.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_compat.h"
+
#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
#include <sys/systm.h>
-#include <sys/bus.h>
-
-#include <machine/bus.h>
-
-#include <dev/uart/uart.h>
-#include <dev/uart/uart_cpu.h>
+#include <sys/uio.h>
-#include <mips/atheros/ar71xxreg.h>
+#include <machine/cpu.h>
+#include <machine/sysarch.h>
-bus_space_tag_t uart_bus_space_io;
-bus_space_tag_t uart_bus_space_mem;
-
-int
-uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
-{
- return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
-}
+#include <compat/freebsd32/freebsd32_util.h>
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_proto.h>
int
-uart_cpu_getdev(int devtype, struct uart_devinfo *di)
+freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
{
- di->ops = uart_getops(&uart_ns8250_class);
- di->bas.chan = 0;
- di->bas.bst = MIPS_BUS_SPACE_MEM;
- di->bas.regshft = 2;
- /* TODO: calculate proper AHB freq using PLL registers */
- di->bas.rclk = 85000000;
- di->baudrate = 115200;
- di->databits = 8;
- di->stopbits = 1;
- di->parity = UART_PARITY_NONE;
+ struct sysarch_args uap1;
+ struct i386_ldt_args uapl;
+ struct i386_ldt_args32 uapl32;
+ int error;
- /* TODO: check if uart_bus_space_io mandatory to set */
- uart_bus_space_io = MIPS_BUS_SPACE_IO;
- uart_bus_space_mem = MIPS_BUS_SPACE_MEM;
- /*
- * FIXME:
- * 3 is to compensate big endian, uart operates
- * with bus_space_read_1/bus_space_write_1 and hence gets
- * highest byte instead of lowest one. Actual fix will involve
- * MIPS bus_space fixing.
- */
- di->bas.bsh = MIPS_PHYS_TO_KSEG1(AR71XX_UART_ADDR) + 3;
- return (0);
+ if (uap->op == I386_SET_LDT || uap->op == I386_GET_LDT) {
+ if ((error = copyin(uap->parms, &uapl32, sizeof(uapl32))) != 0)
+ return (error);
+ uap1.op = uap->op;
+ uap1.parms = (char *)&uapl;
+ uapl.start = uapl32.start;
+ uapl.descs = (struct user_segment_descriptor *)(uintptr_t)
+ uapl32.descs;
+ uapl.num = uapl32.num;
+ return (sysarch_ldt(td, &uap1, UIO_SYSSPACE));
+ } else {
+ uap1.op = uap->op;
+ uap1.parms = uap->parms;
+ return (sysarch(td, &uap1));
+ }
}
diff --git a/sys/amd64/ia32/ia32_reg.c b/sys/amd64/ia32/ia32_reg.c
index 8abc6fc..49dd4e2 100644
--- a/sys/amd64/ia32/ia32_reg.c
+++ b/sys/amd64/ia32/ia32_reg.c
@@ -85,9 +85,17 @@ fill_regs32(struct thread *td, struct reg32 *regs)
tp = td->td_frame;
pcb = td->td_pcb;
- regs->r_fs = pcb->pcb_fs;
- regs->r_es = pcb->pcb_es;
- regs->r_ds = pcb->pcb_ds;
+ if (tp->tf_flags & TF_HASSEGS) {
+ regs->r_gs = tp->tf_gs;
+ regs->r_fs = tp->tf_fs;
+ regs->r_es = tp->tf_es;
+ regs->r_ds = tp->tf_ds;
+ } else {
+ regs->r_gs = _ugssel;
+ regs->r_fs = _ufssel;
+ regs->r_es = _udatasel;
+ regs->r_ds = _udatasel;
+ }
regs->r_edi = tp->tf_rdi;
regs->r_esi = tp->tf_rsi;
regs->r_ebp = tp->tf_rbp;
@@ -100,7 +108,6 @@ fill_regs32(struct thread *td, struct reg32 *regs)
regs->r_eflags = tp->tf_rflags;
regs->r_esp = tp->tf_rsp;
regs->r_ss = tp->tf_ss;
- regs->r_gs = pcb->pcb_gs;
return (0);
}
@@ -114,14 +121,11 @@ set_regs32(struct thread *td, struct reg32 *regs)
if (!EFL_SECURE(regs->r_eflags, tp->tf_rflags) || !CS_SECURE(regs->r_cs))
return (EINVAL);
pcb = td->td_pcb;
-#if 0
- load_fs(regs->r_fs);
- pcb->pcb_fs = regs->r_fs;
- load_es(regs->r_es);
- pcb->pcb_es = regs->r_es;
- load_ds(regs->r_ds);
- pcb->pcb_ds = regs->r_ds;
-#endif
+ tp->tf_gs = regs->r_gs;
+ tp->tf_fs = regs->r_fs;
+ tp->tf_es = regs->r_es;
+ tp->tf_ds = regs->r_ds;
+ tp->tf_flags = TF_HASSEGS;
tp->tf_rdi = regs->r_edi;
tp->tf_rsi = regs->r_esi;
tp->tf_rbp = regs->r_ebp;
@@ -134,10 +138,6 @@ set_regs32(struct thread *td, struct reg32 *regs)
tp->tf_rflags = regs->r_eflags;
tp->tf_rsp = regs->r_esp;
tp->tf_ss = regs->r_ss;
-#if 0
- load_gs(regs->r_gs);
- pcb->pcb_gs = regs->r_gs;
-#endif
return (0);
}
@@ -166,7 +166,8 @@ fill_fpregs32(struct thread *td, struct fpreg32 *regs)
penv_87->en_fcs = td->td_frame->tf_cs;
penv_87->en_opcode = penv_xmm->en_opcode;
penv_87->en_foo = penv_xmm->en_rdp;
- penv_87->en_fos = td->td_pcb->pcb_ds;
+ /* Entry into the kernel always sets TF_HASSEGS */
+ penv_87->en_fos = td->td_frame->tf_ds;
/* FPU registers */
for (i = 0; i < 8; ++i)
diff --git a/sys/amd64/ia32/ia32_signal.c b/sys/amd64/ia32/ia32_signal.c
index 019faba..37e8013 100644
--- a/sys/amd64/ia32/ia32_signal.c
+++ b/sys/amd64/ia32/ia32_signal.c
@@ -85,8 +85,6 @@ static void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *);
static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp);
static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp);
-extern int _ucode32sel, _udatasel;
-
#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
@@ -134,10 +132,11 @@ ia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags)
PROC_LOCK(curthread->td_proc);
mcp->mc_onstack = sigonstack(tp->tf_rsp);
PROC_UNLOCK(curthread->td_proc);
- mcp->mc_gs = td->td_pcb->pcb_gs;
- mcp->mc_fs = td->td_pcb->pcb_fs;
- mcp->mc_es = td->td_pcb->pcb_es;
- mcp->mc_ds = td->td_pcb->pcb_ds;
+ /* Entry into kernel always sets TF_HASSEGS */
+ mcp->mc_gs = tp->tf_gs;
+ mcp->mc_fs = tp->tf_fs;
+ mcp->mc_es = tp->tf_es;
+ mcp->mc_ds = tp->tf_ds;
mcp->mc_edi = tp->tf_rdi;
mcp->mc_esi = tp->tf_rsi;
mcp->mc_ebp = tp->tf_rbp;
@@ -158,6 +157,8 @@ ia32_get_mcontext(struct thread *td, struct ia32_mcontext *mcp, int flags)
mcp->mc_ss = tp->tf_ss;
mcp->mc_len = sizeof(*mcp);
ia32_get_fpcontext(td, mcp);
+ mcp->mc_fsbase = td->td_pcb->pcb_fsbase;
+ mcp->mc_gsbase = td->td_pcb->pcb_gsbase;
return (0);
}
@@ -182,11 +183,11 @@ ia32_set_mcontext(struct thread *td, const struct ia32_mcontext *mcp)
ret = ia32_set_fpcontext(td, mcp);
if (ret != 0)
return (ret);
-#if 0 /* XXX deal with load_fs() and friends */
+ tp->tf_gs = mcp->mc_gs;
tp->tf_fs = mcp->mc_fs;
tp->tf_es = mcp->mc_es;
tp->tf_ds = mcp->mc_ds;
-#endif
+ tp->tf_flags = TF_HASSEGS;
tp->tf_rdi = mcp->mc_edi;
tp->tf_rsi = mcp->mc_esi;
tp->tf_rbp = mcp->mc_ebp;
@@ -199,9 +200,6 @@ ia32_set_mcontext(struct thread *td, const struct ia32_mcontext *mcp)
tp->tf_rflags = rflags;
tp->tf_rsp = mcp->mc_esp;
tp->tf_ss = mcp->mc_ss;
-#if 0 /* XXX deal with load_gs() and friends */
- td->td_pcb->pcb_gs = mcp->mc_gs;
-#endif
td->td_pcb->pcb_flags |= PCB_FULLCTX;
return (0);
}
@@ -326,10 +324,6 @@ freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
- sf.sf_uc.uc_mcontext.mc_gs = rgs();
- sf.sf_uc.uc_mcontext.mc_fs = rfs();
- __asm __volatile("mov %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es));
- __asm __volatile("mov %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds));
sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
@@ -345,6 +339,10 @@ freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
+ sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds;
+ sf.sf_uc.uc_mcontext.mc_es = regs->tf_es;
+ sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs;
+ sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs;
/* Allocate space for the signal handler context. */
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
@@ -394,10 +392,8 @@ freebsd4_ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
regs->tf_rflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucode32sel;
regs->tf_ss = _udatasel;
- load_ds(_udatasel);
- td->td_pcb->pcb_ds = _udatasel;
- load_es(_udatasel);
- td->td_pcb->pcb_es = _udatasel;
+ regs->tf_ds = _udatasel;
+ regs->tf_es = _udatasel;
/* leave user %fs and %gs untouched */
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
@@ -441,10 +437,6 @@ ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
sf.sf_uc.uc_stack.ss_flags = (td->td_pflags & TDP_ALTSTACK)
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
- sf.sf_uc.uc_mcontext.mc_gs = rgs();
- sf.sf_uc.uc_mcontext.mc_fs = rfs();
- __asm __volatile("mov %%es,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_es));
- __asm __volatile("mov %%ds,%0" : "=rm" (sf.sf_uc.uc_mcontext.mc_ds));
sf.sf_uc.uc_mcontext.mc_edi = regs->tf_rdi;
sf.sf_uc.uc_mcontext.mc_esi = regs->tf_rsi;
sf.sf_uc.uc_mcontext.mc_ebp = regs->tf_rbp;
@@ -460,9 +452,15 @@ ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
sf.sf_uc.uc_mcontext.mc_eflags = regs->tf_rflags;
sf.sf_uc.uc_mcontext.mc_esp = regs->tf_rsp;
sf.sf_uc.uc_mcontext.mc_ss = regs->tf_ss;
+ sf.sf_uc.uc_mcontext.mc_ds = regs->tf_ds;
+ sf.sf_uc.uc_mcontext.mc_es = regs->tf_es;
+ sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs;
+ sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs;
sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext);
fpstate_drop(td);
+ sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase;
+ sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase;
/* Allocate space for the signal handler context. */
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
@@ -514,11 +512,9 @@ ia32_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
regs->tf_rflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucode32sel;
regs->tf_ss = _udatasel;
- load_ds(_udatasel);
- td->td_pcb->pcb_ds = _udatasel;
- load_es(_udatasel);
- td->td_pcb->pcb_es = _udatasel;
- /* leave user %fs and %gs untouched */
+ regs->tf_ds = _udatasel;
+ regs->tf_es = _udatasel;
+ /* XXXKIB leave user %fs and %gs untouched */
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
@@ -591,7 +587,6 @@ freebsd4_freebsd32_sigreturn(td, uap)
return (EINVAL);
}
- /* Segment selectors restored by sigtramp.S */
regs->tf_rdi = ucp->uc_mcontext.mc_edi;
regs->tf_rsi = ucp->uc_mcontext.mc_esi;
regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
@@ -606,6 +601,10 @@ freebsd4_freebsd32_sigreturn(td, uap)
regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
regs->tf_rsp = ucp->uc_mcontext.mc_esp;
regs->tf_ss = ucp->uc_mcontext.mc_ss;
+ regs->tf_ds = ucp->uc_mcontext.mc_ds;
+ regs->tf_es = ucp->uc_mcontext.mc_es;
+ regs->tf_fs = ucp->uc_mcontext.mc_fs;
+ regs->tf_gs = ucp->uc_mcontext.mc_gs;
PROC_LOCK(p);
td->td_sigmask = ucp->uc_sigmask;
@@ -678,7 +677,6 @@ freebsd32_sigreturn(td, uap)
if (ret != 0)
return (ret);
- /* Segment selectors restored by sigtramp.S */
regs->tf_rdi = ucp->uc_mcontext.mc_edi;
regs->tf_rsi = ucp->uc_mcontext.mc_esi;
regs->tf_rbp = ucp->uc_mcontext.mc_ebp;
@@ -693,6 +691,11 @@ freebsd32_sigreturn(td, uap)
regs->tf_rflags = ucp->uc_mcontext.mc_eflags;
regs->tf_rsp = ucp->uc_mcontext.mc_esp;
regs->tf_ss = ucp->uc_mcontext.mc_ss;
+ regs->tf_ds = ucp->uc_mcontext.mc_ds;
+ regs->tf_es = ucp->uc_mcontext.mc_es;
+ regs->tf_fs = ucp->uc_mcontext.mc_fs;
+ regs->tf_gs = ucp->uc_mcontext.mc_gs;
+ regs->tf_flags = TF_HASSEGS;
PROC_LOCK(p);
td->td_sigmask = ucp->uc_sigmask;
@@ -715,20 +718,14 @@ ia32_setregs(td, entry, stack, ps_strings)
struct trapframe *regs = td->td_frame;
struct pcb *pcb = td->td_pcb;
- critical_enter();
- wrmsr(MSR_FSBASE, 0);
- wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */
+ mtx_lock(&dt_lock);
+ if (td->td_proc->p_md.md_ldt != NULL)
+ user_ldt_free(td);
+ else
+ mtx_unlock(&dt_lock);
+
pcb->pcb_fsbase = 0;
pcb->pcb_gsbase = 0;
- critical_exit();
- load_ds(_udatasel);
- load_es(_udatasel);
- load_fs(_udatasel);
- load_gs(_udatasel);
- pcb->pcb_ds = _udatasel;
- pcb->pcb_es = _udatasel;
- pcb->pcb_fs = _udatasel;
- pcb->pcb_gs = _udatasel;
pcb->pcb_initial_fpucw = __INITIAL_FPUCW_I386__;
bzero((char *)regs, sizeof(struct trapframe));
@@ -738,6 +735,12 @@ ia32_setregs(td, entry, stack, ps_strings)
regs->tf_ss = _udatasel;
regs->tf_cs = _ucode32sel;
regs->tf_rbx = ps_strings;
+ regs->tf_ds = _udatasel;
+ regs->tf_es = _udatasel;
+ regs->tf_fs = _ufssel;
+ regs->tf_gs = _ugssel;
+ regs->tf_flags = TF_HASSEGS;
+
load_cr0(rcr0() | CR0_MP | CR0_TS);
fpstate_drop(td);
diff --git a/sys/amd64/ia32/ia32_sigtramp.S b/sys/amd64/ia32/ia32_sigtramp.S
index 1cd220a..9455169 100644
--- a/sys/amd64/ia32/ia32_sigtramp.S
+++ b/sys/amd64/ia32/ia32_sigtramp.S
@@ -45,8 +45,6 @@ ia32_sigcode:
calll *IA32_SIGF_HANDLER(%esp)
leal IA32_SIGF_UC(%esp),%eax /* get ucontext */
pushl %eax
- mov IA32_UC_ES(%eax),%es /* restore %es */
- mov IA32_UC_DS(%eax),%ds /* restore %ds */
movl $SYS_sigreturn,%eax
pushl %eax /* junk to fake return addr. */
int $0x80 /* enter kernel with args */
@@ -60,8 +58,6 @@ freebsd4_ia32_sigcode:
calll *IA32_SIGF_HANDLER(%esp)
leal IA32_SIGF_UC4(%esp),%eax/* get ucontext */
pushl %eax
- mov IA32_UC4_ES(%eax),%es /* restore %es */
- mov IA32_UC4_DS(%eax),%ds /* restore %ds */
movl $344,%eax /* 4.x SYS_sigreturn */
pushl %eax /* junk to fake return addr. */
int $0x80 /* enter kernel with args */
diff --git a/sys/amd64/include/apicvar.h b/sys/amd64/include/apicvar.h
index ea971ec..3cc028d 100644
--- a/sys/amd64/include/apicvar.h
+++ b/sys/amd64/include/apicvar.h
@@ -130,6 +130,7 @@
#define IPI_IS_BITMAPED(x) ((x) <= IPI_BITMAP_LAST)
#define IPI_STOP (APIC_IPI_INTS + 7) /* Stop CPU until restarted. */
+#define IPI_SUSPEND (APIC_IPI_INTS + 8) /* Suspend CPU until restarted. */
/*
* The spurious interrupt can share the priority class with the IPIs since
diff --git a/sys/amd64/include/asmacros.h b/sys/amd64/include/asmacros.h
index 788f39f..0bf0029 100644
--- a/sys/amd64/include/asmacros.h
+++ b/sys/amd64/include/asmacros.h
@@ -161,7 +161,12 @@
movq %r12,TF_R12(%rsp) ; \
movq %r13,TF_R13(%rsp) ; \
movq %r14,TF_R14(%rsp) ; \
- movq %r15,TF_R15(%rsp)
+ movq %r15,TF_R15(%rsp) ; \
+ movw %fs,TF_FS(%rsp) ; \
+ movw %gs,TF_GS(%rsp) ; \
+ movw %es,TF_ES(%rsp) ; \
+ movw %ds,TF_DS(%rsp) ; \
+ movl $TF_HASSEGS,TF_FLAGS(%rsp)
#define POP_FRAME \
movq TF_RDI(%rsp),%rdi ; \
diff --git a/sys/amd64/include/cpufunc.h b/sys/amd64/include/cpufunc.h
index cec9b4a..15fc0e9 100644
--- a/sys/amd64/include/cpufunc.h
+++ b/sys/amd64/include/cpufunc.h
@@ -164,70 +164,12 @@ halt(void)
__asm __volatile("hlt");
}
-#if !defined(__GNUCLIKE_BUILTIN_CONSTANT_P) || __GNUCLIKE_ASM < 3
-
-#define inb(port) inbv(port)
-#define outb(port, data) outbv(port, data)
-
-#else /* __GNUCLIKE_BUILTIN_CONSTANT_P && __GNUCLIKE_ASM >= 3 */
-
-/*
- * The following complications are to get around gcc not having a
- * constraint letter for the range 0..255. We still put "d" in the
- * constraint because "i" isn't a valid constraint when the port
- * isn't constant. This only matters for -O0 because otherwise
- * the non-working version gets optimized away.
- *
- * Use an expression-statement instead of a conditional expression
- * because gcc-2.6.0 would promote the operands of the conditional
- * and produce poor code for "if ((inb(var) & const1) == const2)".
- *
- * The unnecessary test `(port) < 0x10000' is to generate a warning if
- * the `port' has type u_short or smaller. Such types are pessimal.
- * This actually only works for signed types. The range check is
- * careful to avoid generating warnings.
- */
-#define inb(port) __extension__ ({ \
- u_char _data; \
- if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \
- && (port) < 0x10000) \
- _data = inbc(port); \
- else \
- _data = inbv(port); \
- _data; })
-
-#define outb(port, data) ( \
- __builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \
- && (port) < 0x10000 \
- ? outbc(port, data) : outbv(port, data))
-
static __inline u_char
-inbc(u_int port)
+inb(u_int port)
{
u_char data;
- __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
- return (data);
-}
-
-static __inline void
-outbc(u_int port, u_char data)
-{
- __asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
-}
-
-#endif /* __GNUCLIKE_BUILTIN_CONSTANT_P && __GNUCLIKE_ASM >= 3*/
-
-static __inline u_char
-inbv(u_int port)
-{
- u_char data;
- /*
- * We use %%dx and not %1 here because i/o is done at %dx and not at
- * %edx, while gcc generates inferior code (movw instead of movl)
- * if we tell it to load (u_short) port.
- */
- __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
+ __asm volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
return (data);
}
@@ -236,7 +178,7 @@ inl(u_int port)
{
u_int data;
- __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
+ __asm volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
return (data);
}
@@ -278,33 +220,20 @@ inw(u_int port)
{
u_short data;
- __asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
+ __asm volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
return (data);
}
static __inline void
-outbv(u_int port, u_char data)
+outb(u_int port, u_char data)
{
- u_char al;
- /*
- * Use an unnecessary assignment to help gcc's register allocator.
- * This make a large difference for gcc-1.40 and a tiny difference
- * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for
- * best results. gcc-2.6.0 can't handle this.
- */
- al = data;
- __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
+ __asm volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
}
static __inline void
outl(u_int port, u_int data)
{
- /*
- * outl() and outw() aren't used much so we haven't looked at
- * possible micro-optimizations such as the unnecessary
- * assignment for them.
- */
- __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
+ __asm volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
}
static __inline void
@@ -334,7 +263,7 @@ outsl(u_int port, const void *addr, size_t cnt)
static __inline void
outw(u_int port, u_short data)
{
- __asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
+ __asm volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
}
static __inline void
@@ -535,12 +464,9 @@ cpu_mwait(int extensions, int hints)
static __inline void
load_fs(u_int sel)
{
- register u_int32_t fsbase __asm("ecx");
-
/* Preserve the fsbase value across the selector load */
- fsbase = MSR_FSBASE;
- __asm __volatile("rdmsr; mov %0,%%fs; wrmsr"
- : : "rm" (sel), "c" (fsbase) : "eax", "edx");
+ __asm __volatile("rdmsr; mov %0,%%fs; wrmsr"
+ : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx");
}
#ifndef MSR_GSBASE
@@ -549,16 +475,13 @@ load_fs(u_int sel)
static __inline void
load_gs(u_int sel)
{
- register u_int32_t gsbase __asm("ecx");
-
/*
* Preserve the gsbase value across the selector load.
* Note that we have to disable interrupts because the gsbase
* being trashed happens to be the kernel gsbase at the time.
*/
- gsbase = MSR_GSBASE;
- __asm __volatile("pushfq; cli; rdmsr; mov %0,%%gs; wrmsr; popfq"
- : : "rm" (sel), "c" (gsbase) : "eax", "edx");
+ __asm __volatile("pushfq; cli; rdmsr; mov %0,%%gs; wrmsr; popfq"
+ : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx");
}
#else
/* Usable by userland */
diff --git a/sys/amd64/include/elf.h b/sys/amd64/include/elf.h
index a4c7f79..e5c95f7 100644
--- a/sys/amd64/include/elf.h
+++ b/sys/amd64/include/elf.h
@@ -81,16 +81,14 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-/*
- * The following non-standard values are used in Linux ELF binaries.
- */
#define AT_NOTELF 10 /* Program is not ELF ?? */
#define AT_UID 11 /* Real uid. */
#define AT_EUID 12 /* Effective uid. */
#define AT_GID 13 /* Real gid. */
#define AT_EGID 14 /* Effective gid. */
+#define AT_EXECPATH 15 /* Path to the executable. */
-#define AT_COUNT 15 /* Count of defined aux entry types. */
+#define AT_COUNT 16 /* Count of defined aux entry types. */
/*
* Relocation types.
diff --git a/sys/amd64/include/endian.h b/sys/amd64/include/endian.h
index 24e59e4..712b5a5 100644
--- a/sys/amd64/include/endian.h
+++ b/sys/amd64/include/endian.h
@@ -69,25 +69,6 @@ extern "C" {
#if defined(__GNUCLIKE_ASM) && defined(__GNUCLIKE_BUILTIN_CONSTANT_P)
-#define __word_swap_int_var(x) \
-__extension__ ({ register __uint32_t __X = (x); \
- __asm ("rorl $16, %0" : "+r" (__X)); \
- __X; })
-
-#ifdef __OPTIMIZE__
-
-#define __word_swap_int_const(x) \
- ((((x) & 0xffff0000) >> 16) | \
- (((x) & 0x0000ffff) << 16))
-#define __word_swap_int(x) (__builtin_constant_p(x) ? \
- __word_swap_int_const(x) : __word_swap_int_var(x))
-
-#else /* __OPTIMIZE__ */
-
-#define __word_swap_int(x) __word_swap_int_var(x)
-
-#endif /* __OPTIMIZE__ */
-
#define __byte_swap_int_var(x) \
__extension__ ({ register __uint32_t __X = (x); \
__asm ("bswap %0" : "+r" (__X)); \
@@ -135,26 +116,6 @@ __extension__ ({ register __uint64_t __X = (x); \
#endif /* __OPTIMIZE__ */
-#define __byte_swap_word_var(x) \
-__extension__ ({ register __uint16_t __X = (x); \
- __asm ("xchgb %h0, %b0" : "+Q" (__X)); \
- __X; })
-
-#ifdef __OPTIMIZE__
-
-#define __byte_swap_word_const(x) \
- ((((x) & 0xff00) >> 8) | \
- (((x) & 0x00ff) << 8))
-
-#define __byte_swap_word(x) (__builtin_constant_p(x) ? \
- __byte_swap_word_const(x) : __byte_swap_word_var(x))
-
-#else /* __OPTIMIZE__ */
-
-#define __byte_swap_word(x) __byte_swap_word_var(x)
-
-#endif /* __OPTIMIZE__ */
-
static __inline __uint64_t
__bswap64(__uint64_t _x)
{
@@ -172,8 +133,7 @@ __bswap32(__uint32_t _x)
static __inline __uint16_t
__bswap16(__uint16_t _x)
{
-
- return (__byte_swap_word(_x));
+ return (_x << 8 | _x >> 8);
}
#define __htonl(x) __bswap32(x)
diff --git a/sys/amd64/include/frame.h b/sys/amd64/include/frame.h
index 26c9dd0..12722a4 100644
--- a/sys/amd64/include/frame.h
+++ b/sys/amd64/include/frame.h
@@ -64,9 +64,13 @@ struct trapframe {
register_t tf_r13;
register_t tf_r14;
register_t tf_r15;
- register_t tf_trapno;
+ uint32_t tf_trapno;
+ uint16_t tf_fs;
+ uint16_t tf_gs;
register_t tf_addr;
- register_t tf_flags;
+ uint32_t tf_flags;
+ uint16_t tf_es;
+ uint16_t tf_ds;
/* below portion defined in hardware */
register_t tf_err;
register_t tf_rip;
@@ -76,4 +80,7 @@ struct trapframe {
register_t tf_ss;
};
+#define TF_HASSEGS 0x1
+/* #define _MC_HASBASES 0x2 */
+
#endif /* _MACHINE_FRAME_H_ */
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index 2125b9f..892e19d 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -60,6 +60,11 @@ extern char sigcode[];
extern int szsigcode;
extern uint64_t *vm_page_dump;
extern int vm_page_dump_size;
+extern int _udatasel;
+extern int _ucodesel;
+extern int _ucode32sel;
+extern int _ufssel;
+extern int _ugssel;
typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss);
struct thread;
@@ -72,6 +77,14 @@ void busdma_swi(void);
void cpu_setregs(void);
void doreti_iret(void) __asm(__STRING(doreti_iret));
void doreti_iret_fault(void) __asm(__STRING(doreti_iret_fault));
+void ld_ds(void) __asm(__STRING(ld_ds));
+void ld_es(void) __asm(__STRING(ld_es));
+void ld_fs(void) __asm(__STRING(ld_fs));
+void ld_gs(void) __asm(__STRING(ld_gs));
+void ds_load_fault(void) __asm(__STRING(ds_load_fault));
+void es_load_fault(void) __asm(__STRING(es_load_fault));
+void fs_load_fault(void) __asm(__STRING(fs_load_fault));
+void gs_load_fault(void) __asm(__STRING(gs_load_fault));
void dump_add_page(vm_paddr_t);
void dump_drop_page(vm_paddr_t);
void initializecpu(void);
diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h
index e6a5add..7361049 100644
--- a/sys/amd64/include/pcb.h
+++ b/sys/amd64/include/pcb.h
@@ -62,10 +62,6 @@ struct pcb {
#define PCB_32BIT 0x40 /* process has 32 bit context (segs etc) */
#define PCB_FULLCTX 0x80 /* full context restore on sysret */
- u_int32_t pcb_ds;
- u_int32_t pcb_es;
- u_int32_t pcb_fs;
- u_int32_t pcb_gs;
u_int64_t pcb_dr0;
u_int64_t pcb_dr1;
u_int64_t pcb_dr2;
@@ -80,6 +76,20 @@ struct pcb {
/* 32-bit segment descriptor */
struct user_segment_descriptor pcb_gs32sd;
+ /* local tss, with i/o bitmap; NULL for common */
+ struct amd64tss *pcb_tssp;
+};
+
+struct xpcb {
+ struct pcb xpcb_pcb;
+ register_t xpcb_cr0;
+ register_t xpcb_cr2;
+ register_t xpcb_cr4;
+ register_t xpcb_kgsbase;
+ struct region_descriptor xpcb_gdt;
+ struct region_descriptor xpcb_idt;
+ struct region_descriptor xpcb_ldt;
+ uint16_t xpcb_tr;
};
#ifdef _KERNEL
@@ -87,6 +97,7 @@ struct trapframe;
void makectx(struct trapframe *, struct pcb *);
void savectx(struct pcb *);
+int savectx2(struct xpcb *);
#endif
#endif /* _AMD64_PCB_H_ */
diff --git a/sys/amd64/include/pcpu.h b/sys/amd64/include/pcpu.h
index 23818ca..139281a 100644
--- a/sys/amd64/include/pcpu.h
+++ b/sys/amd64/include/pcpu.h
@@ -62,12 +62,20 @@
char pc_monitorbuf[128] __aligned(128); /* cache line */ \
struct pcpu *pc_prvspace; /* Self-reference */ \
struct pmap *pc_curpmap; \
- struct amd64tss *pc_tssp; \
+ struct amd64tss *pc_tssp; /* TSS segment active on CPU */ \
+ struct amd64tss *pc_commontssp;/* Common TSS for the CPU */ \
register_t pc_rsp0; \
register_t pc_scratch_rsp; /* User %rsp in syscall */ \
u_int pc_apic_id; \
u_int pc_acpi_id; /* ACPI CPU id */ \
- struct user_segment_descriptor *pc_gs32p \
+ /* Pointer to the CPU %fs descriptor */ \
+ struct user_segment_descriptor *pc_fs32p; \
+ /* Pointer to the CPU %gs descriptor */ \
+ struct user_segment_descriptor *pc_gs32p; \
+ /* Pointer to the CPU LDT descriptor */ \
+ struct system_segment_descriptor *pc_ldt; \
+ /* Pointer to the CPU TSS descriptor */ \
+ struct system_segment_descriptor *pc_tss
PCPU_XEN_FIELDS
#ifdef _KERNEL
diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h
index 36d3667..c95a9f9 100644
--- a/sys/amd64/include/pmap.h
+++ b/sys/amd64/include/pmap.h
@@ -160,13 +160,7 @@ typedef u_int64_t pml4_entry_t;
#define PDESHIFT (3)
/*
- * Address of current and alternate address space page table maps
- * and directories.
- * XXX it might be saner to just direct map all of physical memory
- * into the kernel using 2MB pages. We have enough space to do
- * it (2^47 bits of KVM, while current max physical addressability
- * is 2^40 physical bits). Then we can get rid of the evil hole
- * in the page tables and the evil overlapping.
+ * Address of current address space page table maps and directories.
*/
#ifdef _KERNEL
#define addr_PTmap (KVADDR(PML4PML4I, 0, 0, 0))
@@ -243,6 +237,10 @@ struct md_page {
TAILQ_HEAD(,pv_entry) pv_list;
};
+/*
+ * The kernel virtual address (KVA) of the level 4 page table page is always
+ * within the direct map (DMAP) region.
+ */
struct pmap {
struct mtx pm_mtx;
pml4_entry_t *pm_pml4; /* KVA of level 4 page table */
diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h
index a3ebd79..33d5181 100644
--- a/sys/amd64/include/proc.h
+++ b/sys/amd64/include/proc.h
@@ -33,6 +33,13 @@
#ifndef _MACHINE_PROC_H_
#define _MACHINE_PROC_H_
+#include <machine/segments.h>
+
+struct proc_ldt {
+ caddr_t ldt_base;
+ int ldt_refcnt;
+};
+
/*
* Machine-dependent part of the proc structure for AMD64.
*/
@@ -42,6 +49,8 @@ struct mdthread {
};
struct mdproc {
+ struct proc_ldt *md_ldt; /* (t) per-process ldt */
+ struct system_segment_descriptor md_ldt_sd;
};
#ifdef _KERNEL
@@ -55,6 +64,18 @@ struct mdproc {
(char *)&td; \
} while (0)
+void set_user_ldt(struct mdproc *);
+struct proc_ldt *user_ldt_alloc(struct proc *, int);
+void user_ldt_free(struct thread *);
+void user_ldt_deref(struct proc_ldt *);
+struct sysarch_args;
+int sysarch_ldt(struct thread *td, struct sysarch_args *uap, int uap_space);
+int amd64_set_ldt_data(struct thread *td, int start, int num,
+ struct user_segment_descriptor *descs);
+
+extern struct mtx dt_lock;
+extern int max_ldt_segment;
+
#endif /* _KERNEL */
#endif /* !_MACHINE_PROC_H_ */
diff --git a/sys/amd64/include/reg.h b/sys/amd64/include/reg.h
index 9ca092f..89211a3 100644
--- a/sys/amd64/include/reg.h
+++ b/sys/amd64/include/reg.h
@@ -56,8 +56,12 @@ struct reg {
register_t r_rdx;
register_t r_rcx;
register_t r_rax;
- register_t r_trapno;
- register_t r_err;
+ uint32_t r_trapno;
+ uint16_t r_fs;
+ uint16_t r_gs;
+ uint32_t r_err;
+ uint16_t r_es;
+ uint16_t r_ds;
register_t r_rip;
register_t r_cs;
register_t r_rflags;
diff --git a/sys/amd64/include/segments.h b/sys/amd64/include/segments.h
index 1c83d1c..3dca80a 100644
--- a/sys/amd64/include/segments.h
+++ b/sys/amd64/include/segments.h
@@ -108,12 +108,29 @@ struct gate_descriptor {
u_int64_t sd_xx1:32;
} __packed;
+/*
+ * Generic descriptor
+ */
+union descriptor {
+ struct user_segment_descriptor sd;
+ struct gate_descriptor gd;
+};
+
/* system segments and gate types */
#define SDT_SYSNULL 0 /* system null */
+#define SDT_SYS286TSS 1 /* system 286 TSS available */
#define SDT_SYSLDT 2 /* system 64 bit local descriptor table */
+#define SDT_SYS286BSY 3 /* system 286 TSS busy */
+#define SDT_SYS286CGT 4 /* system 286 call gate */
+#define SDT_SYSTASKGT 5 /* system task gate */
+#define SDT_SYS286IGT 6 /* system 286 interrupt gate */
+#define SDT_SYS286TGT 7 /* system 286 trap gate */
+#define SDT_SYSNULL2 8 /* system null again */
#define SDT_SYSTSS 9 /* system available 64 bit TSS */
+#define SDT_SYSNULL3 10 /* system null again */
#define SDT_SYSBSY 11 /* system busy 64 bit TSS */
#define SDT_SYSCGT 12 /* system 64 bit call gate */
+#define SDT_SYSNULL4 13 /* system null again */
#define SDT_SYSIGT 14 /* system 64 bit interrupt gate */
#define SDT_SYSTGT 15 /* system 64 bit trap gate */
@@ -195,15 +212,19 @@ struct region_descriptor {
* Entries in the Global Descriptor Table (GDT)
*/
#define GNULL_SEL 0 /* Null Descriptor */
-#define GCODE_SEL 1 /* Kernel Code Descriptor */
-#define GDATA_SEL 2 /* Kernel Data Descriptor */
-#define GUCODE32_SEL 3 /* User 32 bit code Descriptor */
-#define GUDATA_SEL 4 /* User 32/64 bit Data Descriptor */
-#define GUCODE_SEL 5 /* User 64 bit Code Descriptor */
-#define GPROC0_SEL 6 /* TSS for entering kernel etc */
-/* slot 7 is second half of GPROC0_SEL */
-#define GUGS32_SEL 8 /* User 32 bit GS Descriptor */
-#define NGDT 9
+#define GNULL2_SEL 1 /* Null Descriptor */
+#define GUFS32_SEL 2 /* User 32 bit %fs Descriptor */
+#define GUGS32_SEL 3 /* User 32 bit %gs Descriptor */
+#define GCODE_SEL 4 /* Kernel Code Descriptor */
+#define GDATA_SEL 5 /* Kernel Data Descriptor */
+#define GUCODE32_SEL 6 /* User 32 bit code Descriptor */
+#define GUDATA_SEL 7 /* User 32/64 bit Data Descriptor */
+#define GUCODE_SEL 8 /* User 64 bit Code Descriptor */
+#define GPROC0_SEL 9 /* TSS for entering kernel etc */
+/* slot 10 is second half of GPROC0_SEL */
+#define GUSERLDT_SEL 11 /* LDT */
+/* slot 11 is second half of GUSERLDT_SEL */
+#define NGDT 13
#ifdef _KERNEL
extern struct user_segment_descriptor gdt[];
@@ -218,6 +239,9 @@ void ssdtosd(struct soft_segment_descriptor *ssdp,
struct user_segment_descriptor *sdp);
void ssdtosyssd(struct soft_segment_descriptor *ssdp,
struct system_segment_descriptor *sdp);
+void update_gdt_gsbase(struct thread *td, uint32_t base);
+void update_gdt_fsbase(struct thread *td, uint32_t base);
+
#endif /* _KERNEL */
#endif /* !_MACHINE_SEGMENTS_H_ */
diff --git a/sys/amd64/include/signal.h b/sys/amd64/include/signal.h
index 7a4c2a7..228e2d9 100644
--- a/sys/amd64/include/signal.h
+++ b/sys/amd64/include/signal.h
@@ -78,9 +78,13 @@ struct sigcontext {
long sc_r13;
long sc_r14;
long sc_r15;
- long sc_trapno;
+ int sc_trapno;
+ short sc_fs;
+ short sc_gs;
long sc_addr;
- long sc_flags;
+ int sc_flags;
+ short sc_es;
+ short sc_ds;
long sc_err;
long sc_rip;
long sc_cs;
@@ -95,7 +99,11 @@ struct sigcontext {
long sc_fpformat;
long sc_ownedfp;
long sc_fpstate[64] __aligned(16);
- long sc_spare[8];
+
+ long sc_fsbase;
+ long sc_gsbase;
+
+ long sc_spare[6];
};
#endif /* __BSD_VISIBLE */
diff --git a/sys/amd64/include/smp.h b/sys/amd64/include/smp.h
index 06222f8..d2ff189 100644
--- a/sys/amd64/include/smp.h
+++ b/sys/amd64/include/smp.h
@@ -48,11 +48,13 @@ inthand_t
IDTVEC(invlcache), /* Write back and invalidate cache */
IDTVEC(ipi_intr_bitmap_handler), /* Bitmap based IPIs */
IDTVEC(cpustop), /* CPU stops & waits to be restarted */
+ IDTVEC(cpususpend), /* CPU suspends & waits to be resumed */
IDTVEC(rendezvous); /* handle CPU rendezvous */
/* functions in mp_machdep.c */
void cpu_add(u_int apic_id, char boot_cpu);
void cpustop_handler(void);
+void cpususpend_handler(void);
void init_secondary(void);
void ipi_selected(u_int cpus, u_int ipi);
void ipi_all_but_self(u_int ipi);
diff --git a/sys/amd64/include/sysarch.h b/sys/amd64/include/sysarch.h
index 67c8a4a..6c3e6c9 100644
--- a/sys/amd64/include/sysarch.h
+++ b/sys/amd64/include/sysarch.h
@@ -35,6 +35,15 @@
#ifndef _MACHINE_SYSARCH_H_
#define _MACHINE_SYSARCH_H_
+#define I386_GET_LDT 0
+#define I386_SET_LDT 1
+#define LDT_AUTO_ALLOC 0xffffffff
+ /* I386_IOPL */
+#define I386_GET_IOPERM 3
+#define I386_SET_IOPERM 4
+
+/* XXX Not implementable #define I386_VM86 6 */
+
#define I386_GET_FSBASE 7
#define I386_SET_FSBASE 8
#define I386_GET_GSBASE 9
@@ -46,6 +55,18 @@
#define AMD64_GET_GSBASE 130
#define AMD64_SET_GSBASE 131
+struct i386_ldt_args {
+ unsigned int start;
+ struct user_segment_descriptor *descs __packed;
+ unsigned int num;
+};
+
+struct i386_ioperm_args {
+ unsigned int start;
+ unsigned int length;
+ int enable;
+};
+
#ifndef _KERNEL
#include <sys/cdefs.h>
@@ -56,6 +77,15 @@ int amd64_set_fsbase(void *);
int amd64_set_gsbase(void *);
int sysarch(int, void *);
__END_DECLS
+#else
+struct thread;
+union descriptor;
+
+int amd64_get_ldt(struct thread *, struct i386_ldt_args *);
+int amd64_set_ldt(struct thread *, struct i386_ldt_args *,
+ struct user_segment_descriptor *);
+int amd64_get_ioperm(struct thread *, struct i386_ioperm_args *);
+int amd64_set_ioperm(struct thread *, struct i386_ioperm_args *);
#endif
#endif /* !_MACHINE_SYSARCH_H_ */
diff --git a/sys/amd64/include/ucontext.h b/sys/amd64/include/ucontext.h
index 5c13803..c5bbd65 100644
--- a/sys/amd64/include/ucontext.h
+++ b/sys/amd64/include/ucontext.h
@@ -32,9 +32,16 @@
#ifndef _MACHINE_UCONTEXT_H_
#define _MACHINE_UCONTEXT_H_
+/*
+ * mc_trapno bits. Shall be in sync with TF_XXX.
+ */
+#define _MC_HASSEGS 0x1
+#define _MC_HASBASES 0x2
+#define _MC_FLAG_MASK (_MC_HASSEGS | _MC_HASBASES)
+
typedef struct __mcontext {
/*
- * The first 20 fields must match the definition of
+ * The first 24 fields must match the definition of
* sigcontext. So that we can support sigcontext
* and ucontext_t at the same time.
*/
@@ -54,9 +61,13 @@ typedef struct __mcontext {
__register_t mc_r13;
__register_t mc_r14;
__register_t mc_r15;
- __register_t mc_trapno;
+ __uint32_t mc_trapno;
+ __uint16_t mc_fs;
+ __uint16_t mc_gs;
__register_t mc_addr;
- __register_t mc_flags;
+ __uint32_t mc_flags;
+ __uint16_t mc_es;
+ __uint16_t mc_ds;
__register_t mc_err;
__register_t mc_rip;
__register_t mc_cs;
@@ -65,6 +76,7 @@ typedef struct __mcontext {
__register_t mc_ss;
long mc_len; /* sizeof(mcontext_t) */
+
#define _MC_FPFMT_NODEV 0x10000 /* device not present or configured */
#define _MC_FPFMT_XMM 0x10002
long mc_fpformat;
@@ -76,7 +88,11 @@ typedef struct __mcontext {
* See <machine/fpu.h> for the internals of mc_fpstate[].
*/
long mc_fpstate[64] __aligned(16);
- long mc_spare[8];
+
+ __register_t mc_fsbase;
+ __register_t mc_gsbase;
+
+ long mc_spare[6];
} mcontext_t;
#endif /* !_MACHINE_UCONTEXT_H_ */
diff --git a/sys/amd64/linux32/linux.h b/sys/amd64/linux32/linux.h
index 94372d6..0e30382 100644
--- a/sys/amd64/linux32/linux.h
+++ b/sys/amd64/linux32/linux.h
@@ -179,8 +179,8 @@ struct l_mmap_argv {
l_int prot;
l_int flags;
l_int fd;
- l_off_t pgoff;
-} __packed;
+ l_ulong pgoff;
+};
/*
* stat family of syscalls
diff --git a/sys/amd64/linux32/linux32_locore.s b/sys/amd64/linux32/linux32_locore.s
index 6045925..36e1abf 100644
--- a/sys/amd64/linux32/linux32_locore.s
+++ b/sys/amd64/linux32/linux32_locore.s
@@ -11,8 +11,6 @@
NON_GPROF_ENTRY(linux_sigcode)
call *LINUX_SIGF_HANDLER(%esp)
leal LINUX_SIGF_SC(%esp),%ebx /* linux scp */
- mov LINUX_SC_ES(%ebx),%es
- mov LINUX_SC_DS(%ebx),%ds
movl %esp, %ebx /* pass sigframe */
push %eax /* fake ret addr */
movl $LINUX_SYS_linux_sigreturn,%eax /* linux_sigreturn() */
@@ -24,8 +22,6 @@ linux_rt_sigcode:
call *LINUX_RT_SIGF_HANDLER(%esp)
leal LINUX_RT_SIGF_UC(%esp),%ebx /* linux ucp */
leal LINUX_RT_SIGF_SC(%ebx),%ecx /* linux sigcontext */
- mov LINUX_SC_ES(%ecx),%es
- mov LINUX_SC_DS(%ecx),%ds
push %eax /* fake ret addr */
movl $LINUX_SYS_linux_rt_sigreturn,%eax /* linux_rt_sigreturn() */
int $0x80 /* enter kernel with args */
diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c
index eb91623..42ea070 100644
--- a/sys/amd64/linux32/linux32_machdep.c
+++ b/sys/amd64/linux32/linux32_machdep.c
@@ -716,8 +716,8 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
sd.sd_long, sd.sd_def32, sd.sd_gran);
#endif
td2->td_pcb->pcb_gsbase = (register_t)info.base_addr;
- td2->td_pcb->pcb_gs32sd = sd;
- td2->td_pcb->pcb_gs = GSEL(GUGS32_SEL, SEL_UPL);
+/* XXXKIB td2->td_pcb->pcb_gs32sd = sd; */
+ td2->td_frame->tf_gs = GSEL(GUGS32_SEL, SEL_UPL);
td2->td_pcb->pcb_flags |= PCB_GS32BIT | PCB_32BIT;
}
}
@@ -1359,12 +1359,9 @@ linux_set_thread_area(struct thread *td,
sd.sd_gran);
#endif
- critical_enter();
td->td_pcb->pcb_gsbase = (register_t)info.base_addr;
- td->td_pcb->pcb_gs32sd = *PCPU_GET(gs32p) = sd;
td->td_pcb->pcb_flags |= PCB_32BIT | PCB_GS32BIT;
- wrmsr(MSR_KGSBASE, td->td_pcb->pcb_gsbase);
- critical_exit();
+ update_gdt_gsbase(td, info.base_addr);
return (0);
}
diff --git a/sys/amd64/linux32/linux32_sysvec.c b/sys/amd64/linux32/linux32_sysvec.c
index a834c98..a82c182 100644
--- a/sys/amd64/linux32/linux32_sysvec.c
+++ b/sys/amd64/linux32/linux32_sysvec.c
@@ -290,7 +290,6 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
return 0;
}
-extern int _ucodesel, _ucode32sel, _udatasel;
extern unsigned long linux_sznonrtsigcode;
static void
@@ -360,13 +359,7 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
bsd_to_linux_sigset(mask, &frame.sf_sc.uc_sigmask);
- frame.sf_sc.uc_mcontext.sc_mask = frame.sf_sc.uc_sigmask.__bits[0];
- frame.sf_sc.uc_mcontext.sc_gs = rgs();
- frame.sf_sc.uc_mcontext.sc_fs = rfs();
- __asm __volatile("mov %%es,%0" :
- "=rm" (frame.sf_sc.uc_mcontext.sc_es));
- __asm __volatile("mov %%ds,%0" :
- "=rm" (frame.sf_sc.uc_mcontext.sc_ds));
+ frame.sf_sc.uc_mcontext.sc_mask = frame.sf_sc.uc_sigmask.__bits[0];
frame.sf_sc.uc_mcontext.sc_edi = regs->tf_rdi;
frame.sf_sc.uc_mcontext.sc_esi = regs->tf_rsi;
frame.sf_sc.uc_mcontext.sc_ebp = regs->tf_rbp;
@@ -376,6 +369,10 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
frame.sf_sc.uc_mcontext.sc_eax = regs->tf_rax;
frame.sf_sc.uc_mcontext.sc_eip = regs->tf_rip;
frame.sf_sc.uc_mcontext.sc_cs = regs->tf_cs;
+ frame.sf_sc.uc_mcontext.sc_gs = regs->tf_gs;
+ frame.sf_sc.uc_mcontext.sc_fs = regs->tf_fs;
+ frame.sf_sc.uc_mcontext.sc_es = regs->tf_es;
+ frame.sf_sc.uc_mcontext.sc_ds = regs->tf_ds;
frame.sf_sc.uc_mcontext.sc_eflags = regs->tf_rflags;
frame.sf_sc.uc_mcontext.sc_esp_at_signal = regs->tf_rsp;
frame.sf_sc.uc_mcontext.sc_ss = regs->tf_ss;
@@ -413,11 +410,11 @@ linux_rt_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
regs->tf_rflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucode32sel;
regs->tf_ss = _udatasel;
- load_ds(_udatasel);
- td->td_pcb->pcb_ds = _udatasel;
- load_es(_udatasel);
- td->td_pcb->pcb_es = _udatasel;
- /* leave user %fs and %gs untouched */
+ regs->tf_ds = _udatasel;
+ regs->tf_es = _udatasel;
+ regs->tf_fs = _ufssel;
+ regs->tf_gs = _ugssel;
+ regs->tf_flags = TF_HASSEGS;
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
@@ -495,10 +492,10 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
* Build the signal context to be used by sigreturn.
*/
frame.sf_sc.sc_mask = lmask.__bits[0];
- frame.sf_sc.sc_gs = rgs();
- frame.sf_sc.sc_fs = rfs();
- __asm __volatile("mov %%es,%0" : "=rm" (frame.sf_sc.sc_es));
- __asm __volatile("mov %%ds,%0" : "=rm" (frame.sf_sc.sc_ds));
+ frame.sf_sc.sc_gs = regs->tf_gs;
+ frame.sf_sc.sc_fs = regs->tf_fs;
+ frame.sf_sc.sc_es = regs->tf_es;
+ frame.sf_sc.sc_ds = regs->tf_ds;
frame.sf_sc.sc_edi = regs->tf_rdi;
frame.sf_sc.sc_esi = regs->tf_rsi;
frame.sf_sc.sc_ebp = regs->tf_rbp;
@@ -535,11 +532,11 @@ linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
regs->tf_rflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucode32sel;
regs->tf_ss = _udatasel;
- load_ds(_udatasel);
- td->td_pcb->pcb_ds = _udatasel;
- load_es(_udatasel);
- td->td_pcb->pcb_es = _udatasel;
- /* leave user %fs and %gs untouched */
+ regs->tf_ds = _udatasel;
+ regs->tf_es = _udatasel;
+ regs->tf_fs = _ufssel;
+ regs->tf_gs = _ugssel;
+ regs->tf_flags = TF_HASSEGS;
PROC_LOCK(p);
mtx_lock(&psp->ps_mtx);
}
@@ -624,7 +621,6 @@ linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args)
/*
* Restore signal context.
*/
- /* Selectors were restored by the trampoline. */
regs->tf_rdi = frame.sf_sc.sc_edi;
regs->tf_rsi = frame.sf_sc.sc_esi;
regs->tf_rbp = frame.sf_sc.sc_ebp;
@@ -634,6 +630,10 @@ linux_sigreturn(struct thread *td, struct linux_sigreturn_args *args)
regs->tf_rax = frame.sf_sc.sc_eax;
regs->tf_rip = frame.sf_sc.sc_eip;
regs->tf_cs = frame.sf_sc.sc_cs;
+ regs->tf_ds = frame.sf_sc.sc_ds;
+ regs->tf_es = frame.sf_sc.sc_es;
+ regs->tf_fs = frame.sf_sc.sc_fs;
+ regs->tf_gs = frame.sf_sc.sc_gs;
regs->tf_rflags = eflags;
regs->tf_rsp = frame.sf_sc.sc_esp_at_signal;
regs->tf_ss = frame.sf_sc.sc_ss;
@@ -722,7 +722,10 @@ linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
/*
* Restore signal context
*/
- /* Selectors were restored by the trampoline. */
+ regs->tf_gs = context->sc_gs;
+ regs->tf_fs = context->sc_fs;
+ regs->tf_es = context->sc_es;
+ regs->tf_ds = context->sc_ds;
regs->tf_rdi = context->sc_edi;
regs->tf_rsi = context->sc_esi;
regs->tf_rbp = context->sc_ebp;
@@ -827,27 +830,30 @@ exec_linux_setregs(td, entry, stack, ps_strings)
struct trapframe *regs = td->td_frame;
struct pcb *pcb = td->td_pcb;
+ mtx_lock(&dt_lock);
+ if (td->td_proc->p_md.md_ldt != NULL)
+ user_ldt_free(td);
+ else
+ mtx_unlock(&dt_lock);
+
critical_enter();
wrmsr(MSR_FSBASE, 0);
wrmsr(MSR_KGSBASE, 0); /* User value while we're in the kernel */
pcb->pcb_fsbase = 0;
pcb->pcb_gsbase = 0;
critical_exit();
- load_ds(_udatasel);
- load_es(_udatasel);
- load_fs(_udatasel);
- load_gs(_udatasel);
- pcb->pcb_ds = _udatasel;
- pcb->pcb_es = _udatasel;
- pcb->pcb_fs = _udatasel;
- pcb->pcb_gs = _udatasel;
pcb->pcb_initial_fpucw = __LINUX_NPXCW__;
bzero((char *)regs, sizeof(struct trapframe));
regs->tf_rip = entry;
regs->tf_rsp = stack;
regs->tf_rflags = PSL_USER | (regs->tf_rflags & PSL_T);
+ regs->tf_gs = _ugssel;
+ regs->tf_fs = _ufssel;
+ regs->tf_es = _udatasel;
+ regs->tf_ds = _udatasel;
regs->tf_ss = _udatasel;
+ regs->tf_flags = TF_HASSEGS;
regs->tf_cs = _ucode32sel;
regs->tf_rbx = ps_strings;
load_cr0(rcr0() | CR0_MP | CR0_TS);
@@ -1047,6 +1053,16 @@ struct sysentvec elf_linux_sysvec = {
.sv_flags = SV_ABI_LINUX | SV_ILP32 | SV_IA32
};
+static char GNULINUX_ABI_VENDOR[] = "GNU";
+
+static Elf_Brandnote linux32_brandnote = {
+ .hdr.n_namesz = sizeof(GNULINUX_ABI_VENDOR),
+ .hdr.n_descsz = 16,
+ .hdr.n_type = 1,
+ .vendor = GNULINUX_ABI_VENDOR,
+ .flags = 0
+};
+
static Elf32_Brandinfo linux_brand = {
.brand = ELFOSABI_LINUX,
.machine = EM_386,
@@ -1055,7 +1071,8 @@ static Elf32_Brandinfo linux_brand = {
.interp_path = "/lib/ld-linux.so.1",
.sysvec = &elf_linux_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &linux32_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
static Elf32_Brandinfo linux_glibc2brand = {
@@ -1066,7 +1083,8 @@ static Elf32_Brandinfo linux_glibc2brand = {
.interp_path = "/lib/ld-linux.so.2",
.sysvec = &elf_linux_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &linux32_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
Elf32_Brandinfo *linux_brandlist[] = {
diff --git a/sys/amd64/pci/pci_cfgreg.c b/sys/amd64/pci/pci_cfgreg.c
index 8f757a7..61a2db5 100644
--- a/sys/amd64/pci/pci_cfgreg.c
+++ b/sys/amd64/pci/pci_cfgreg.c
@@ -119,6 +119,7 @@ pci_docfgregread(int bus, int slot, int func, int reg, int bytes)
{
if (cfgmech == CFGMECH_PCIE &&
+ (bus >= pcie_minbus && bus <= pcie_maxbus) &&
(bus != 0 || !(1 << slot & pcie_badslots)))
return (pciereg_cfgread(bus, slot, func, reg, bytes));
else
@@ -158,6 +159,7 @@ pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
{
if (cfgmech == CFGMECH_PCIE &&
+ (bus >= pcie_minbus && bus <= pcie_maxbus) &&
(bus != 0 || !(1 << slot & pcie_badslots)))
pciereg_cfgwrite(bus, slot, func, reg, data, bytes);
else
diff --git a/sys/arm/arm/elf_machdep.c b/sys/arm/arm/elf_machdep.c
index 693eab1..174deeb 100644
--- a/sys/arm/arm/elf_machdep.c
+++ b/sys/arm/arm/elf_machdep.c
@@ -84,7 +84,8 @@ static Elf32_Brandinfo freebsd_brand_info = {
.interp_path = "/libexec/ld-elf.so.1",
.sysvec = &elf32_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -99,7 +100,8 @@ static Elf32_Brandinfo freebsd_brand_oinfo = {
.interp_path = "/usr/libexec/ld-elf.so.1",
.sysvec = &elf32_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
diff --git a/sys/arm/arm/locore.S b/sys/arm/arm/locore.S
index b465edc..e56a91c 100644
--- a/sys/arm/arm/locore.S
+++ b/sys/arm/arm/locore.S
@@ -110,7 +110,7 @@ from_ram:
nop
#endif
adr r7, Lunmapped
- bic r7, r7, #0xff000000
+ bic r7, r7, #0xf0000000
orr r7, r7, #PHYSADDR
@@ -144,7 +144,7 @@ Lunmapped:
ldmia r4!, {r1,r2,r3} /* # of sections, VA, PA|attr */
cmp r1, #0
adrne r5, 2b
- bicne r5, r5, #0xff000000
+ bicne r5, r5, #0xf0000000
orrne r5, r5, #PHYSADDR
movne pc, r5
diff --git a/sys/arm/arm/trap.c b/sys/arm/arm/trap.c
index fc03b52..e6150c0 100644
--- a/sys/arm/arm/trap.c
+++ b/sys/arm/arm/trap.c
@@ -520,7 +520,8 @@ dab_fatal(trapframe_t *tf, u_int fsr, u_int far, struct thread *td, struct ksig
printf(", pc =%08x\n\n", tf->tf_pc);
#ifdef KDB
- kdb_trap(fsr, 0, tf);
+ if (debugger_on_panic || kdb_active)
+ kdb_trap(fsr, 0, tf);
#endif
panic("Fatal abort");
/*NOTREACHED*/
@@ -530,7 +531,7 @@ dab_fatal(trapframe_t *tf, u_int fsr, u_int far, struct thread *td, struct ksig
* dab_align() handles the following data aborts:
*
* FAULT_ALIGN_0 - Alignment fault
- * FAULT_ALIGN_0 - Alignment fault
+ * FAULT_ALIGN_1 - Alignment fault
*
* These faults are fatal if they happen in kernel mode. Otherwise, we
* deliver a bus error to the process.
diff --git a/sys/arm/at91/files.at91 b/sys/arm/at91/files.at91
index 9142749..c9aafbc 100644
--- a/sys/arm/at91/files.at91
+++ b/sys/arm/at91/files.at91
@@ -13,12 +13,10 @@ arm/at91/at91_spi.c optional at91_spi \
dependency "spibus_if.h"
arm/at91/at91_tc.c optional at91_tc
arm/at91/at91_twi.c optional at91_twi
-arm/at91/at91_udp.c optional at91_udp
arm/at91/if_ate.c optional ate
arm/at91/uart_bus_at91usart.c optional uart
arm/at91/uart_cpu_at91rm9200usart.c optional uart
arm/at91/uart_dev_at91usart.c optional uart
-dev/usb/controller/ohci_atmelarm.c optional ohci
#
# All the boards we support
#
diff --git a/sys/arm/conf/AVILA b/sys/arm/conf/AVILA
index 510e8af..cd1d338 100644
--- a/sys/arm/conf/AVILA
+++ b/sys/arm/conf/AVILA
@@ -111,7 +111,6 @@ device wlan_tkip # 802.11 TKIP support
device wlan_xauth
device ath # Atheros pci/cardbus NIC's
-options ATH_SUPPORT_TDMA
options ATH_DEBUG
options ATH_DIAGAPI
#options ATH_TX99_DIAG
diff --git a/sys/arm/conf/CAMBRIA b/sys/arm/conf/CAMBRIA
index c938b91..70655de 100644
--- a/sys/arm/conf/CAMBRIA
+++ b/sys/arm/conf/CAMBRIA
@@ -114,7 +114,6 @@ device wlan_tkip # 802.11 TKIP support
device wlan_xauth
device ath # Atheros pci/cardbus NIC's
-options ATH_SUPPORT_TDMA
options ATH_DEBUG
options ATH_DIAGAPI
#options ATH_TX99_DIAG
diff --git a/sys/arm/conf/HL200 b/sys/arm/conf/HL200
index 5bbce3f..de322ec 100644
--- a/sys/arm/conf/HL200
+++ b/sys/arm/conf/HL200
@@ -103,7 +103,6 @@ device umass # Disks/Mass storage - Requires scbus and da
device ural # Ralink Technology RT2500USB wireless NICs
device rum # Ralink Technology RT2501USB wireless NICs
device urio # Diamond Rio 500 MP3 player
-device uscanner # Scanners
# USB Ethernet, requires miibus
device miibus
device aue # ADMtek USB Ethernet
diff --git a/sys/arm/conf/KB920X b/sys/arm/conf/KB920X
index 00af54b..1f688f8 100644
--- a/sys/arm/conf/KB920X
+++ b/sys/arm/conf/KB920X
@@ -104,7 +104,6 @@ device umass # Disks/Mass storage - Requires scbus and da
device ural # Ralink Technology RT2500USB wireless NICs
device rum # Ralink Technology RT2501USB wireless NICs
device urio # Diamond Rio 500 MP3 player
-device uscanner # Scanners
# USB Ethernet, requires miibus
device miibus
device aue # ADMtek USB Ethernet
diff --git a/sys/arm/include/atomic.h b/sys/arm/include/atomic.h
index 71e31c3..9f16220 100644
--- a/sys/arm/include/atomic.h
+++ b/sys/arm/include/atomic.h
@@ -264,22 +264,23 @@ atomic_clear_32(volatile uint32_t *address, uint32_t clearmask)
static __inline uint32_t
atomic_fetchadd_32(volatile uint32_t *p, uint32_t v)
{
- uint32_t start, ras_start = ARM_RAS_START;
+ uint32_t start, tmp, ras_start = ARM_RAS_START;
__asm __volatile("1:\n"
"adr %1, 1b\n"
"str %1, [%0]\n"
"adr %1, 2f\n"
"str %1, [%0, #4]\n"
- "ldr %1, [%2]\n"
- "add %1, %1, %3\n"
- "str %0, [%2]\n"
+ "ldr %1, [%3]\n"
+ "mov %2, %1\n"
+ "add %2, %2, %4\n"
+ "str %2, [%3]\n"
"2:\n"
- "mov %3, #0\n"
- "str %3, [%0]\n"
- "mov %3, #0xffffffff\n"
- "str %3, [%0, #4]\n"
- : "+r" (ras_start), "=r" (start), "+r" (p), "+r" (v)
+ "mov %2, #0\n"
+ "str %2, [%0]\n"
+ "mov %2, #0xffffffff\n"
+ "str %2, [%0, #4]\n"
+ : "+r" (ras_start), "=r" (start), "=r" (tmp), "+r" (p), "+r" (v)
: : "memory");
return (start);
}
diff --git a/sys/arm/include/elf.h b/sys/arm/include/elf.h
index c516864..ee2843f 100644
--- a/sys/arm/include/elf.h
+++ b/sys/arm/include/elf.h
@@ -75,8 +75,9 @@ __ElfType(Auxinfo);
#define AT_EUID 12 /* Effective uid. */
#define AT_GID 13 /* Real gid. */
#define AT_EGID 14 /* Effective gid. */
+#define AT_EXECPATH 15 /* Path to the executable. */
-#define AT_COUNT 15 /* Count of defined aux entry types. */
+#define AT_COUNT 16 /* Count of defined aux entry types. */
#define R_ARM_COUNT 33 /* Count of defined relocation types. */
diff --git a/sys/arm/include/vmparam.h b/sys/arm/include/vmparam.h
index bc82fd0..d54671d 100644
--- a/sys/arm/include/vmparam.h
+++ b/sys/arm/include/vmparam.h
@@ -141,8 +141,6 @@
#define SGROWSIZ (128*1024)
#define MAXSLP 20
-#define VM_PROT_READ_IS_EXEC
-
#ifdef ARM_USE_SMALL_ALLOC
#define UMA_MD_SMALL_ALLOC
#endif /* ARM_USE_SMALL_ALLOC */
diff --git a/sys/boot/forth/loader.conf b/sys/boot/forth/loader.conf
index 7443d68..59a5018 100644
--- a/sys/boot/forth/loader.conf
+++ b/sys/boot/forth/loader.conf
@@ -275,6 +275,7 @@ if_tl_load="NO" # Texas Instruments TNETE100 ("ThunderLAN")
if_tx_load="NO" # SMC 83c17x Fast Ethernet
if_txp_load="NO" # 3Com 3XP Typhoon/Sidewinder (3CR990)
if_vge_load="NO" # VIA VT6122 PCI Gigabit Ethernet
+if_uath_load="NO" # Atheros USB wireless for AR5005UG & AR5005UX
if_udav_load="NO" # Davicom DM9601 USB Ethernet
if_upgt_load="NO" # Conexant/Intersil PrismGT USB wireless
if_ural_load="NO" # Ralink Technology USB wireless
@@ -379,7 +380,6 @@ ulpt_load="NO" # Printer
ums_load="NO" # Mouse
umass_load="NO" # Mass Storage Devices
umodem_load="NO" # Modems
-uscanner_load="NO" # Scanners
if_aue_load="NO" # ADMtek USB ethernet
if_axe_load="NO" # ASIX Electronics AX88172 USB ethernet
if_cue_load="NO" # CATC USB ethernet
@@ -402,7 +402,7 @@ accf_http_load="NO" # Wait for full HTTP request accept filter
random_load="NO" # Random device
speaker_load="NO" # AT speaker module
coretemp_load="NO" # Intel Core CPU temperature monitor
-k8temp_load="NO" # AMD K8 temperature monitor
+amdtemp_load="NO" # AMD K8/K10/K11 temperature monitor
##############################################################
### ACPI settings ##########################################
diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile
index 3430bef..9a2a3fa 100644
--- a/sys/boot/i386/libi386/Makefile
+++ b/sys/boot/i386/libi386/Makefile
@@ -31,6 +31,10 @@ CFLAGS+= -DDISK_DEBUG
.if !defined(BOOT_HIDE_SERIAL_NUMBERS)
# Export serial numbers, UUID, and asset tag from loader.
CFLAGS+= -DSMBIOS_SERIAL_NUMBERS
+.if defined(BOOT_LITTLE_ENDIAN_UUID)
+# Use little-endian UUID format as defined in SMBIOS 2.6.
+CFLAGS+= -DSMBIOS_LITTLE_ENDIAN_UUID
+.endif
.endif
.if !defined(LOADER_NO_GPT_SUPPORT)
diff --git a/sys/boot/i386/libi386/bioscd.c b/sys/boot/i386/libi386/bioscd.c
index 93de958..a6dba0c 100644
--- a/sys/boot/i386/libi386/bioscd.c
+++ b/sys/boot/i386/libi386/bioscd.c
@@ -173,9 +173,9 @@ bc_add(int biosdev)
static void
bc_print(int verbose)
{
- int i;
char line[80];
-
+ int i;
+
for (i = 0; i < nbcinfo; i++) {
sprintf(line, " cd%d: Device 0x%x\n", i,
bcinfo[i].bc_sp.sp_devicespec);
@@ -235,7 +235,7 @@ bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
if (dblk % (BIOSCD_SECSIZE / DEV_BSIZE) != 0)
return (EINVAL);
dblk /= (BIOSCD_SECSIZE / DEV_BSIZE);
- DEBUG("read %d from %d to %p", blks, dblk, buf);
+ DEBUG("read %d from %lld to %p", blks, dblk, buf);
if (rsize)
*rsize = 0;
@@ -244,9 +244,9 @@ bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
return (EIO);
}
#ifdef BD_SUPPORT_FRAGS
- DEBUG("bc_strategy: frag read %d from %d+%d to %p",
+ DEBUG("frag read %d from %lld+%d to %p",
fragsize, dblk, blks, buf + (blks * BIOSCD_SECSIZE));
- if (fragsize && bc_read(unit, dblk + blks, 1, fragsize)) {
+ if (fragsize && bc_read(unit, dblk + blks, 1, fragbuf)) {
DEBUG("frag read error");
return(EIO);
}
@@ -257,11 +257,15 @@ bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
return (0);
}
+/* Max number of sectors to bounce-buffer at a time. */
+#define CD_BOUNCEBUF 8
+
static int
bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
{
- u_int result, retry;
- static unsigned short packet[8];
+ u_int maxfer, resid, result, retry, x;
+ caddr_t bbuf, p, xp;
+ static struct edd_packet packet;
int biosdev;
#ifdef DISK_DEBUG
int error;
@@ -275,47 +279,77 @@ bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
if (blks == 0)
return (0);
+ /* Decide whether we have to bounce */
+ if (VTOP(dest) >> 20 != 0) {
+ /*
+ * The destination buffer is above first 1MB of
+ * physical memory so we have to arrange a suitable
+ * bounce buffer.
+ */
+ x = min(CD_BOUNCEBUF, (unsigned)blks);
+ bbuf = alloca(x * BIOSCD_SECSIZE);
+ maxfer = x;
+ } else {
+ bbuf = NULL;
+ maxfer = 0;
+ }
+
biosdev = bc_unit2bios(unit);
- /*
- * Loop retrying the operation a couple of times. The BIOS
- * may also retry.
- */
- for (retry = 0; retry < 3; retry++) {
- /* If retrying, reset the drive */
- if (retry > 0) {
+ resid = blks;
+ p = dest;
+
+ while (resid > 0) {
+ if (bbuf)
+ xp = bbuf;
+ else
+ xp = p;
+ x = resid;
+ if (maxfer > 0)
+ x = min(x, maxfer);
+
+ /*
+ * Loop retrying the operation a couple of times. The BIOS
+ * may also retry.
+ */
+ for (retry = 0; retry < 3; retry++) {
+ /* If retrying, reset the drive */
+ if (retry > 0) {
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x13;
+ v86.eax = 0;
+ v86.edx = biosdev;
+ v86int();
+ }
+
+ packet.len = 0x10;
+ packet.count = x;
+ packet.offset = VTOPOFF(xp);
+ packet.seg = VTOPSEG(xp);
+ packet.lba = dblk;
v86.ctl = V86_FLAGS;
v86.addr = 0x13;
- v86.eax = 0;
+ v86.eax = 0x4200;
v86.edx = biosdev;
+ v86.ds = VTOPSEG(&packet);
+ v86.esi = VTOPOFF(&packet);
v86int();
+ result = (v86.efl & PSL_C);
+ if (result == 0)
+ break;
}
-
- packet[0] = 0x10;
- packet[1] = blks;
- packet[2] = VTOPOFF(dest);
- packet[3] = VTOPSEG(dest);
- packet[4] = dblk & 0xffff;
- packet[5] = dblk >> 16;
- packet[6] = 0;
- packet[7] = 0;
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- v86.eax = 0x4200;
- v86.edx = biosdev;
- v86.ds = VTOPSEG(packet);
- v86.esi = VTOPOFF(packet);
- v86int();
- result = (v86.efl & PSL_C);
- if (result == 0)
- break;
- }
#ifdef DISK_DEBUG
- error = (v86.eax >> 8) & 0xff;
+ error = (v86.eax >> 8) & 0xff;
#endif
- DEBUG("%d sectors from %ld to %p (0x%x) %s", blks, dblk, dest,
- VTOP(dest), result ? "failed" : "ok");
- DEBUG("unit %d status 0x%x", unit, error);
+ DEBUG("%d sectors from %lld to %p (0x%x) %s", x, dblk, p,
+ VTOP(p), result ? "failed" : "ok");
+ DEBUG("unit %d status 0x%x", unit, error);
+ if (bbuf != NULL)
+ bcopy(bbuf, p, x * BIOSCD_SECSIZE);
+ p += (x * BIOSCD_SECSIZE);
+ dblk += x;
+ resid -= x;
+ }
/* hexdump(dest, (blks * BIOSCD_SECSIZE)); */
return(0);
diff --git a/sys/boot/i386/libi386/biosdisk.c b/sys/boot/i386/libi386/biosdisk.c
index 9d31325..a54418f 100644
--- a/sys/boot/i386/libi386/biosdisk.c
+++ b/sys/boot/i386/libi386/biosdisk.c
@@ -1125,14 +1125,6 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf, siz
/* Max number of sectors to bounce-buffer if the request crosses a 64k boundary */
#define FLOPPY_BOUNCEBUF 18
-struct edd_packet {
- uint16_t len;
- uint16_t count;
- uint16_t offset;
- uint16_t seg;
- uint64_t lba;
-};
-
static int
bd_edd_io(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest, int write)
{
diff --git a/sys/boot/i386/libi386/libi386.h b/sys/boot/i386/libi386/libi386.h
index ccae099..4ac5cb5 100644
--- a/sys/boot/i386/libi386/libi386.h
+++ b/sys/boot/i386/libi386/libi386.h
@@ -52,6 +52,14 @@ struct i386_devdesc
} d_kind;
};
+struct edd_packet {
+ uint16_t len;
+ uint16_t count;
+ uint16_t offset;
+ uint16_t seg;
+ uint64_t lba;
+};
+
int i386_getdev(void **vdev, const char *devspec, const char **path);
char *i386_fmtdev(void *vdev);
int i386_setcurrdev(struct env_var *ev, int flags, const void *value);
diff --git a/sys/boot/i386/libi386/smbios.c b/sys/boot/i386/libi386/smbios.c
index dd39cc2..51044d6 100644
--- a/sys/boot/i386/libi386/smbios.c
+++ b/sys/boot/i386/libi386/smbios.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2005, 2006 Jung-uk Kim <jkim@FreeBSD.org>
+ * Copyright (c) 2005-2009 Jung-uk Kim <jkim@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include <stand.h>
#include <bootstrap.h>
+#include <sys/endian.h>
#include "btxv86.h"
#include "libi386.h"
@@ -37,17 +38,18 @@ __FBSDID("$FreeBSD$");
* Detect SMBIOS and export information about the SMBIOS into the
* environment.
*
- * System Management BIOS Reference Specification, v2.4 Final
- * http://www.dmtf.org/standards/published_documents/DSP0134.pdf
+ * System Management BIOS Reference Specification, v2.6 Final
+ * http://www.dmtf.org/standards/published_documents/DSP0134_2.6.0.pdf
*/
/*
- * Spec. 2.1.1 SMBIOS Structure Table Entry Point
+ * 2.1.1 SMBIOS Structure Table Entry Point
*
- * 'The SMBIOS Entry Point structure, described below, can be located by
- * application software by searching for the anchor-string on paragraph
- * (16-byte) boundaries within the physical memory address range
- * 000F0000h to 000FFFFFh.'
+ * "On non-EFI systems, the SMBIOS Entry Point structure, described below, can
+ * be located by application software by searching for the anchor-string on
+ * paragraph (16-byte) boundaries within the physical memory address range
+ * 000F0000h to 000FFFFFh. This entry point encapsulates an intermediate anchor
+ * string that is used by some existing DMI browsers."
*/
#define SMBIOS_START 0xf0000
#define SMBIOS_LENGTH 0x10000
@@ -55,87 +57,174 @@ __FBSDID("$FreeBSD$");
#define SMBIOS_SIG "_SM_"
#define SMBIOS_DMI_SIG "_DMI_"
+#define SMBIOS_GET8(base, off) (*(uint8_t *)((base) + (off)))
+#define SMBIOS_GET16(base, off) (*(uint16_t *)((base) + (off)))
+#define SMBIOS_GET32(base, off) (*(uint32_t *)((base) + (off)))
+
+#define SMBIOS_GETLEN(base) SMBIOS_GET8(base, 0x01)
+#define SMBIOS_GETSTR(base) ((base) + SMBIOS_GETLEN(base))
+
+static uint32_t smbios_enabled_memory = 0;
+static uint32_t smbios_old_enabled_memory = 0;
static uint8_t smbios_enabled_sockets = 0;
static uint8_t smbios_populated_sockets = 0;
-static uint8_t *smbios_parse_table(const uint8_t *dmi);
-static void smbios_setenv(const char *name, const uint8_t *dmi,
- const int offset);
-static uint8_t smbios_checksum(const caddr_t addr, const uint8_t len);
-static uint8_t *smbios_sigsearch(const caddr_t addr, const uint32_t len);
+static uint8_t
+smbios_checksum(const caddr_t addr, const uint8_t len)
+{
+ uint8_t sum;
+ int i;
-#ifdef SMBIOS_SERIAL_NUMBERS
-static void smbios_setuuid(const char *name, const uint8_t *dmi,
- const int offset);
-#endif
+ for (sum = 0, i = 0; i < len; i++)
+ sum += SMBIOS_GET8(addr, i);
+ return (sum);
+}
-void
-smbios_detect(void)
+static caddr_t
+smbios_sigsearch(const caddr_t addr, const uint32_t len)
{
- uint8_t *smbios, *dmi, *addr;
- uint16_t i, length, count;
- uint32_t paddr;
- char buf[4];
+ caddr_t cp;
- /* locate and validate the SMBIOS */
- smbios = smbios_sigsearch(PTOV(SMBIOS_START), SMBIOS_LENGTH);
- if (smbios == NULL)
- return;
+ /* Search on 16-byte boundaries. */
+ for (cp = addr; cp < addr + len; cp += SMBIOS_STEP)
+ if (strncmp(cp, SMBIOS_SIG, 4) == 0 &&
+ smbios_checksum(cp, SMBIOS_GET8(cp, 0x05)) == 0 &&
+ strncmp(cp + 0x10, SMBIOS_DMI_SIG, 5) == 0 &&
+ smbios_checksum(cp + 0x10, 0x0f) == 0)
+ return (cp);
+ return (NULL);
+}
- length = *(uint16_t *)(smbios + 0x16); /* Structure Table Length */
- paddr = *(uint32_t *)(smbios + 0x18); /* Structure Table Address */
- count = *(uint16_t *)(smbios + 0x1c); /* No of SMBIOS Structures */
-
- for (dmi = addr = PTOV(paddr), i = 0;
- dmi - addr < length && i < count; i++)
- dmi = smbios_parse_table(dmi);
- sprintf(buf, "%d", smbios_enabled_sockets);
- setenv("smbios.socket.enabled", buf, 1);
- sprintf(buf, "%d", smbios_populated_sockets);
- setenv("smbios.socket.populated", buf, 1);
+static void
+smbios_setenv(const char *name, caddr_t addr, const int offset)
+{
+ caddr_t cp;
+ int i, idx;
+
+ idx = SMBIOS_GET8(addr, offset);
+ if (idx != 0) {
+ cp = SMBIOS_GETSTR(addr);
+ for (i = 1; i < idx; i++)
+ cp += strlen(cp) + 1;
+ setenv(name, cp, 1);
+ }
}
-static uint8_t *
-smbios_parse_table(const uint8_t *dmi)
+#ifdef SMBIOS_SERIAL_NUMBERS
+
+#define UUID_SIZE 16
+#define UUID_TYPE uint32_t
+#define UUID_STEP sizeof(UUID_TYPE)
+#define UUID_ALL_BITS (UUID_SIZE / UUID_STEP)
+#define UUID_GET(base, off) (*(UUID_TYPE *)((base) + (off)))
+
+static void
+smbios_setuuid(const char *name, const caddr_t addr, const int ver)
{
- uint8_t *dp;
+ char uuid[37];
+ int i, ones, zeros;
+ UUID_TYPE n;
+ uint32_t f1;
+ uint16_t f2, f3;
+
+ for (i = 0, ones = 0, zeros = 0; i < UUID_SIZE; i += UUID_STEP) {
+ n = UUID_GET(addr, i) + 1;
+ if (zeros == 0 && n == 0)
+ ones++;
+ else if (ones == 0 && n == 1)
+ zeros++;
+ else
+ break;
+ }
- switch(dmi[0]) {
- case 0: /* Type 0: BIOS */
- smbios_setenv("smbios.bios.vendor", dmi, 0x04);
- smbios_setenv("smbios.bios.version", dmi, 0x05);
- smbios_setenv("smbios.bios.reldate", dmi, 0x08);
+ if (ones != UUID_ALL_BITS && zeros != UUID_ALL_BITS) {
+ /*
+ * 3.3.2.1 System UUID
+ *
+ * "Although RFC 4122 recommends network byte order for all
+ * fields, the PC industry (including the ACPI, UEFI, and
+ * Microsoft specifications) has consistently used
+ * little-endian byte encoding for the first three fields:
+ * time_low, time_mid, time_hi_and_version. The same encoding,
+ * also known as wire format, should also be used for the
+ * SMBIOS representation of the UUID."
+ *
+ * Note: We use network byte order for backward compatibility
+ * unless SMBIOS version is 2.6+ or little-endian is forced.
+ */
+#ifndef SMBIOS_LITTLE_ENDIAN_UUID
+ if (ver < 0x0206) {
+ f1 = ntohl(SMBIOS_GET32(addr, 0));
+ f2 = ntohs(SMBIOS_GET16(addr, 4));
+ f3 = ntohs(SMBIOS_GET16(addr, 6));
+ } else
+#endif
+ {
+ f1 = le32toh(SMBIOS_GET32(addr, 0));
+ f2 = le16toh(SMBIOS_GET16(addr, 4));
+ f3 = le16toh(SMBIOS_GET16(addr, 6));
+ }
+ sprintf(uuid,
+ "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ f1, f2, f3, SMBIOS_GET8(addr, 8), SMBIOS_GET8(addr, 9),
+ SMBIOS_GET8(addr, 10), SMBIOS_GET8(addr, 11),
+ SMBIOS_GET8(addr, 12), SMBIOS_GET8(addr, 13),
+ SMBIOS_GET8(addr, 14), SMBIOS_GET8(addr, 15));
+ setenv(name, uuid, 1);
+ }
+}
+
+#undef UUID_SIZE
+#undef UUID_TYPE
+#undef UUID_STEP
+#undef UUID_ALL_BITS
+#undef UUID_GET
+
+#endif
+
+static caddr_t
+smbios_parse_table(const caddr_t addr, const int ver)
+{
+ caddr_t cp;
+ int proc, size, osize, type;
+
+ type = SMBIOS_GET8(addr, 0); /* 3.1.2 Structure Header Format */
+ switch(type) {
+ case 0: /* 3.3.1 BIOS Information (Type 0) */
+ smbios_setenv("smbios.bios.vendor", addr, 0x04);
+ smbios_setenv("smbios.bios.version", addr, 0x05);
+ smbios_setenv("smbios.bios.reldate", addr, 0x08);
break;
- case 1: /* Type 1: System */
- smbios_setenv("smbios.system.maker", dmi, 0x04);
- smbios_setenv("smbios.system.product", dmi, 0x05);
- smbios_setenv("smbios.system.version", dmi, 0x06);
+ case 1: /* 3.3.2 System Information (Type 1) */
+ smbios_setenv("smbios.system.maker", addr, 0x04);
+ smbios_setenv("smbios.system.product", addr, 0x05);
+ smbios_setenv("smbios.system.version", addr, 0x06);
#ifdef SMBIOS_SERIAL_NUMBERS
- smbios_setenv("smbios.system.serial", dmi, 0x07);
- smbios_setuuid("smbios.system.uuid", dmi, 0x08);
+ smbios_setenv("smbios.system.serial", addr, 0x07);
+ smbios_setuuid("smbios.system.uuid", addr + 0x08, ver);
#endif
break;
- case 2: /* Type 2: Base Board (or Module) */
- smbios_setenv("smbios.planar.maker", dmi, 0x04);
- smbios_setenv("smbios.planar.product", dmi, 0x05);
- smbios_setenv("smbios.planar.version", dmi, 0x06);
+ case 2: /* 3.3.3 Base Board (or Module) Information (Type 2) */
+ smbios_setenv("smbios.planar.maker", addr, 0x04);
+ smbios_setenv("smbios.planar.product", addr, 0x05);
+ smbios_setenv("smbios.planar.version", addr, 0x06);
#ifdef SMBIOS_SERIAL_NUMBERS
- smbios_setenv("smbios.planar.serial", dmi, 0x07);
+ smbios_setenv("smbios.planar.serial", addr, 0x07);
#endif
break;
- case 3: /* Type 3: System Enclosure or Chassis */
- smbios_setenv("smbios.chassis.maker", dmi, 0x04);
- smbios_setenv("smbios.chassis.version", dmi, 0x06);
+ case 3: /* 3.3.4 System Enclosure or Chassis (Type 3) */
+ smbios_setenv("smbios.chassis.maker", addr, 0x04);
+ smbios_setenv("smbios.chassis.version", addr, 0x06);
#ifdef SMBIOS_SERIAL_NUMBERS
- smbios_setenv("smbios.chassis.serial", dmi, 0x07);
- smbios_setenv("smbios.chassis.tag", dmi, 0x08);
+ smbios_setenv("smbios.chassis.serial", addr, 0x07);
+ smbios_setenv("smbios.chassis.tag", addr, 0x08);
#endif
break;
- case 4: /* Type 4: Processor Information */
+ case 4: /* 3.3.5 Processor Information (Type 4) */
/*
* Offset 18h: Processor Status
*
@@ -153,99 +242,106 @@ smbios_parse_table(const uint8_t *dmi)
* 5-6h - Reserved
* 7h - Other
*/
- if ((dmi[0x18] & 0x07) == 1)
+ proc = SMBIOS_GET8(addr, 0x18);
+ if ((proc & 0x07) == 1)
smbios_enabled_sockets++;
- if (dmi[0x18] & 0x40)
+ if ((proc & 0x40) != 0)
smbios_populated_sockets++;
break;
- default: /* skip other types */
+ case 6: /* 3.3.7 Memory Module Information (Type 6, Obsolete) */
+ /*
+ * Offset 0Ah: Enabled Size
+ *
+ * Bit 7 Bank connection
+ * 1 - Double-bank connection
+ * 0 - Single-bank connection
+ * Bit 6:0 Size (n), where 2**n is the size in MB
+ * 7Dh - Not determinable (Installed Size only)
+ * 7Eh - Module is installed, but no memory
+ * has been enabled
+ * 7Fh - Not installed
+ */
+ osize = SMBIOS_GET8(addr, 0x0a) & 0x7f;
+ if (osize > 0 && osize < 22)
+ smbios_old_enabled_memory += 1 << (osize + 10);
break;
- }
-
- /* find structure terminator */
- dp = __DECONST(uint8_t *, dmi + dmi[1]);
- while (dp[0] != 0 || dp[1] != 0)
- dp++;
- return(dp + 2);
-}
+ case 17: /* 3.3.18 Memory Device (Type 17) */
+ /*
+ * Offset 0Ch: Size
+ *
+ * Bit 15 Granularity
+ * 1 - Value is in kilobytes units
+ * 0 - Value is in megabytes units
+ * Bit 14:0 Size
+ */
+ size = SMBIOS_GET16(addr, 0x0c);
+ if (size != 0 && size != 0xffff)
+ smbios_enabled_memory += (size & 0x8000) != 0 ?
+ (size & 0x7fff) : (size << 10);
+ break;
-static void
-smbios_setenv(const char *name, const uint8_t *dmi, const int offset)
-{
- char *cp = __DECONST(char *, dmi + dmi[1]);
- int i;
+ default: /* skip other types */
+ break;
+ }
- /* skip undefined string */
- if (dmi[offset] == 0)
- return;
+ /* Find structure terminator. */
+ cp = SMBIOS_GETSTR(addr);
+ while (SMBIOS_GET16(cp, 0) != 0)
+ cp++;
- for (i = 0; i < dmi[offset] - 1; i++)
- cp += strlen(cp) + 1;
- setenv(name, cp, 1);
+ return (cp + 2);
}
-static uint8_t
-smbios_checksum(const caddr_t addr, const uint8_t len)
+void
+smbios_detect(void)
{
- const uint8_t *cp = addr;
- uint8_t sum;
- int i;
-
- for (sum = 0, i = 0; i < len; i++)
- sum += cp[i];
+ char buf[16];
+ caddr_t addr, dmi, smbios;
+ size_t count, length;
+ uint32_t paddr;
+ int i, major, minor, ver;
- return(sum);
-}
+ /* Search signatures and validate checksums. */
+ smbios = smbios_sigsearch(PTOV(SMBIOS_START), SMBIOS_LENGTH);
+ if (smbios == NULL)
+ return;
-static uint8_t *
-smbios_sigsearch(const caddr_t addr, const uint32_t len)
-{
- caddr_t cp;
+ length = SMBIOS_GET16(smbios, 0x16); /* Structure Table Length */
+ paddr = SMBIOS_GET32(smbios, 0x18); /* Structure Table Address */
+ count = SMBIOS_GET16(smbios, 0x1c); /* No of SMBIOS Structures */
+ ver = SMBIOS_GET8(smbios, 0x1e); /* SMBIOS BCD Revision */
- /* search on 16-byte boundaries */
- for (cp = addr; cp < addr + len; cp += SMBIOS_STEP) {
- /* compare signature, validate checksum */
- if (!strncmp(cp, SMBIOS_SIG, 4)) {
- if (smbios_checksum(cp, *(uint8_t *)(cp + 0x05)))
- continue;
- if (strncmp(cp + 0x10, SMBIOS_DMI_SIG, 5))
- continue;
- if (smbios_checksum(cp + 0x10, 0x0f))
- continue;
-
- return(cp);
- }
+ if (ver != 0) {
+ major = ver >> 4;
+ minor = ver & 0x0f;
+ if (major > 9 || minor > 9)
+ ver = 0;
}
-
- return(NULL);
-}
-
-#ifdef SMBIOS_SERIAL_NUMBERS
-static void
-smbios_setuuid(const char *name, const uint8_t *dmi, const int offset)
-{
- const uint8_t *idp = dmi + offset;
- int i, f = 0, z = 0;
- char uuid[37];
-
- for (i = 0; i < 16; i++) {
- if (idp[i] == 0xff)
- f++;
- else if (idp[i] == 0x00)
- z++;
- else
- break;
+ if (ver == 0) {
+ major = SMBIOS_GET8(smbios, 0x06); /* SMBIOS Major Version */
+ minor = SMBIOS_GET8(smbios, 0x07); /* SMBIOS Minor Version */
}
- if (f != 16 && z != 16) {
- sprintf(uuid, "%02x%02x%02x%02x-"
- "%02x%02x-%02x%02x-%02x%02x-"
- "%02x%02x%02x%02x%02x%02x",
- idp[0], idp[1], idp[2], idp[3],
- idp[4], idp[5], idp[6], idp[7], idp[8], idp[9],
- idp[10], idp[11], idp[12], idp[13], idp[14], idp[15]);
- setenv(name, uuid, 1);
+ ver = (major << 8) | minor;
+
+ addr = PTOV(paddr);
+ for (dmi = addr, i = 0; dmi < addr + length && i < count; i++)
+ dmi = smbios_parse_table(dmi, ver);
+
+ sprintf(buf, "%d.%d", major, minor);
+ setenv("smbios.version", buf, 1);
+ if (smbios_enabled_memory > 0 || smbios_old_enabled_memory > 0) {
+ sprintf(buf, "%u", smbios_enabled_memory > 0 ?
+ smbios_enabled_memory : smbios_old_enabled_memory);
+ setenv("smbios.memory.enabled", buf, 1);
+ }
+ if (smbios_enabled_sockets > 0) {
+ sprintf(buf, "%u", smbios_enabled_sockets);
+ setenv("smbios.socket.enabled", buf, 1);
+ }
+ if (smbios_populated_sockets > 0) {
+ sprintf(buf, "%u", smbios_populated_sockets);
+ setenv("smbios.socket.populated", buf, 1);
}
}
-#endif
diff --git a/sys/boot/pc98/libpc98/Makefile b/sys/boot/pc98/libpc98/Makefile
index cc93af0..1a28b6b 100644
--- a/sys/boot/pc98/libpc98/Makefile
+++ b/sys/boot/pc98/libpc98/Makefile
@@ -5,8 +5,9 @@ INTERNALLIB=
.PATH: ${.CURDIR}/../../i386/libi386
-SRCS= bioscd.c biosdisk.c biosmem.c biospnp.c biospci.c biossmap.c \
- bootinfo.c bootinfo32.c comconsole.c devicename.c elf32_freebsd.c \
+SRCS= bioscd.c biosdisk.c biosmem.c biospnp.c \
+ biospci.c biossmap.c bootinfo.c bootinfo32.c \
+ comconsole.c devicename.c elf32_freebsd.c \
i386_copy.c i386_module.c nullconsole.c pxe.c pxetramp.s \
time.c vidconsole.c
diff --git a/sys/boot/pc98/libpc98/bioscd.c b/sys/boot/pc98/libpc98/bioscd.c
index 40d455b..3e1ba71 100644
--- a/sys/boot/pc98/libpc98/bioscd.c
+++ b/sys/boot/pc98/libpc98/bioscd.c
@@ -170,9 +170,9 @@ bc_add(int biosdev)
static void
bc_print(int verbose)
{
- int i;
char line[80];
-
+ int i;
+
for (i = 0; i < nbcinfo; i++) {
sprintf(line, " cd%d: Device 0x%x\n", i,
bcinfo[i].bc_sp.sp_devicespec);
@@ -232,7 +232,7 @@ bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
if (dblk % (BIOSCD_SECSIZE / DEV_BSIZE) != 0)
return (EINVAL);
dblk /= (BIOSCD_SECSIZE / DEV_BSIZE);
- DEBUG("read %d from %d to %p", blks, dblk, buf);
+ DEBUG("read %d from %lld to %p", blks, dblk, buf);
if (rsize)
*rsize = 0;
@@ -241,9 +241,9 @@ bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
return (EIO);
}
#ifdef BD_SUPPORT_FRAGS
- DEBUG("bc_strategy: frag read %d from %d+%d to %p",
+ DEBUG("frag read %d from %lld+%d to %p",
fragsize, dblk, blks, buf + (blks * BIOSCD_SECSIZE));
- if (fragsize && bc_read(unit, dblk + blks, 1, fragsize)) {
+ if (fragsize && bc_read(unit, dblk + blks, 1, fragbuf)) {
DEBUG("frag read error");
return(EIO);
}
@@ -254,11 +254,14 @@ bc_strategy(void *devdata, int rw, daddr_t dblk, size_t size, char *buf,
return (0);
}
+/* Max number of sectors to bounce-buffer at a time. */
+#define CD_BOUNCEBUF 8
+
static int
bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
{
- u_int result, retry;
- static unsigned short packet[8];
+ u_int maxfer, resid, result, retry, x;
+ caddr_t bbuf, p, xp;
int biosdev;
#ifdef DISK_DEBUG
int error;
@@ -272,40 +275,73 @@ bc_read(int unit, daddr_t dblk, int blks, caddr_t dest)
if (blks == 0)
return (0);
+ /* Decide whether we have to bounce */
+ if (VTOP(dest) >> 20 != 0) {
+ /*
+ * The destination buffer is above first 1MB of
+ * physical memory so we have to arrange a suitable
+ * bounce buffer.
+ */
+ x = min(CD_BOUNCEBUF, (unsigned)blks);
+ bbuf = alloca(x * BIOSCD_SECSIZE);
+ maxfer = x;
+ } else {
+ bbuf = NULL;
+ maxfer = 0;
+ }
+
biosdev = bc_unit2bios(unit);
- /*
- * Loop retrying the operation a couple of times. The BIOS
- * may also retry.
- */
- for (retry = 0; retry < 3; retry++) {
- /* If retrying, reset the drive */
- if (retry > 0) {
+ resid = blks;
+ p = dest;
+
+ while (resid > 0) {
+ if (bbuf)
+ xp = bbuf;
+ else
+ xp = p;
+ x = resid;
+ if (maxfer > 0)
+ x = min(x, maxfer);
+
+ /*
+ * Loop retrying the operation a couple of times. The BIOS
+ * may also retry.
+ */
+ for (retry = 0; retry < 3; retry++) {
+ /* If retrying, reset the drive */
+ if (retry > 0) {
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x1b;
+ v86.eax = 0x0300 | biosdev;
+ v86int();
+ }
+
v86.ctl = V86_FLAGS;
v86.addr = 0x1b;
- v86.eax = 0x0300 | biosdev;
+ v86.eax = 0x0600 | (biosdev & 0x7f);
+ v86.ebx = x * BIOSCD_SECSIZE;
+ v86.ecx = dblk & 0xffff;
+ v86.edx = (dblk >> 16) & 0xffff;
+ v86.ebp = VTOPOFF(xp);
+ v86.es = VTOPSEG(xp);
v86int();
+ result = (v86.efl & PSL_C);
+ if (result == 0)
+ break;
}
-
- v86.ctl = V86_FLAGS;
- v86.addr = 0x1b;
- v86.eax = 0x0600 | (biosdev & 0x7f);
- v86.ebx = blks * BIOSCD_SECSIZE;
- v86.ecx = dblk & 0xffff;
- v86.edx = (dblk >> 16) & 0xffff;
- v86.ebp = VTOPOFF(dest);
- v86.es = VTOPSEG(dest);
- v86int();
- result = (v86.efl & PSL_C);
- if (result == 0)
- break;
- }
#ifdef DISK_DEBUG
- error = (v86.eax >> 8) & 0xff;
+ error = (v86.eax >> 8) & 0xff;
#endif
- DEBUG("%d sectors from %ld to %p (0x%x) %s", blks, dblk, dest,
- VTOP(dest), result ? "failed" : "ok");
- DEBUG("unit %d status 0x%x", unit, error);
+ DEBUG("%d sectors from %lld to %p (0x%x) %s", x, dblk, p,
+ VTOP(p), result ? "failed" : "ok");
+ DEBUG("unit %d status 0x%x", unit, error);
+ if (bbuf != NULL)
+ bcopy(bbuf, p, x * BIOSCD_SECSIZE);
+ p += (x * BIOSCD_SECSIZE);
+ dblk += x;
+ resid -= x;
+ }
/* hexdump(dest, (blks * BIOSCD_SECSIZE)); */
return(0);
diff --git a/sys/boot/pc98/libpc98/biosdisk.c b/sys/boot/pc98/libpc98/biosdisk.c
index dc5f82d..2f18285 100644
--- a/sys/boot/pc98/libpc98/biosdisk.c
+++ b/sys/boot/pc98/libpc98/biosdisk.c
@@ -269,17 +269,8 @@ bd_print(int verbose)
/* Check for a "dedicated" disk */
for (j = 0; j < od->od_nslices; j++) {
- switch(dptr[j].dp_mid) {
- case DOSMID_386BSD:
- sprintf(line, " disk%ds%d", i, j + 1);
- bd_printbsdslice(od,
- dptr[j].dp_scyl * od->od_hds * od->od_sec +
- dptr[j].dp_shd * od->od_sec + dptr[j].dp_ssect,
- line, verbose);
- break;
- default:
- break;
- }
+ sprintf(line, " disk%ds%d", i, j + 1);
+ bd_printslice(od, &dptr[j], line, verbose);
}
}
bd_closedisk(od);
@@ -311,6 +302,52 @@ display_size(uint64_t size)
}
/*
+ * Print information about slices on a disk. For the size calculations we
+ * assume a 512 byte sector.
+ */
+static void
+bd_printslice(struct open_disk *od, struct pc98_partition *dp, char *prefix,
+ int verbose)
+{
+ int cylsecs, start, size;
+ char stats[80];
+ char line[80];
+
+ cylsecs = od->od_hds * od->od_sec;
+ start = dp->dp_scyl * cylsecs + dp->dp_shd * od->od_sec + dp->dp_ssect;
+ size = (dp->dp_ecyl - dp->dp_scyl + 1) * cylsecs;
+
+ if (verbose)
+ sprintf(stats, " %s (%d - %d)", display_size(size),
+ start, start + size);
+ else
+ stats[0] = '\0';
+
+ switch(dp->dp_mid & PC98_MID_MASK) {
+ case PC98_MID_386BSD:
+ bd_printbsdslice(od, start, prefix, verbose);
+ return;
+ case 0x00: /* unused partition */
+ return;
+ case 0x01:
+ sprintf(line, "%s: FAT-12%s\n", prefix, stats);
+ break;
+ case 0x11:
+ case 0x20:
+ case 0x21:
+ case 0x22:
+ case 0x23:
+ case 0x24:
+ sprintf(line, "%s: FAT-16%s\n", prefix, stats);
+ break;
+ default:
+ sprintf(line, "%s: Unknown fs: 0x%x %s\n", prefix, dp->dp_mid,
+ stats);
+ }
+ pager_output(line);
+}
+
+/*
* Print out each valid partition in the disklabel of a FreeBSD slice.
* For size calculations, we assume a 512 byte sector size.
*/
@@ -349,7 +386,7 @@ bd_printbsdslice(struct open_disk *od, daddr_t offset, char *prefix,
/* Only print out statistics in verbose mode */
if (verbose)
- sprintf(line, " %s%c: %s %s (%d - %d)\n", prefix, 'a' + i,
+ sprintf(line, " %s%c: %s %s (%d - %d)\n", prefix, 'a' + i,
(lp->d_partitions[i].p_fstype == FS_SWAP) ? "swap " :
(lp->d_partitions[i].p_fstype == FS_VINUM) ? "vinum" :
"FFS ",
@@ -625,9 +662,9 @@ bd_bestslice(struct open_disk *od)
dp = &od->od_slicetab[0];
for (i = 0; i < od->od_nslices; i++, dp++) {
- switch(dp->dp_mid & 0x7f) {
- case DOSMID_386BSD & 0x7f: /* FreeBSD */
- if ((dp->dp_mid & 0x80) &&
+ switch(dp->dp_mid & PC98_MID_MASK) {
+ case PC98_MID_386BSD: /* FreeBSD */
+ if ((dp->dp_mid & PC98_MID_BOOTABLE) &&
(preflevel > PREF_FBSD_ACT)) {
pref = i;
preflevel = PREF_FBSD_ACT;
@@ -643,7 +680,7 @@ bd_bestslice(struct open_disk *od)
case 0x22:
case 0x23:
case 0x63:
- if ((dp->dp_mid & 0x80) &&
+ if ((dp->dp_mid & PC98_MID_BOOTABLE) &&
(preflevel > PREF_DOS_ACT)) {
pref = i;
preflevel = PREF_DOS_ACT;
diff --git a/sys/boot/pc98/libpc98/time.c b/sys/boot/pc98/libpc98/time.c
index b8dbe02..5d832bb 100644
--- a/sys/boot/pc98/libpc98/time.c
+++ b/sys/boot/pc98/libpc98/time.c
@@ -33,23 +33,21 @@ __FBSDID("$FreeBSD$");
#include "bootstrap.h"
#include "libi386.h"
+static int bios_seconds(void);
+
/*
- * Return the time in seconds since the beginning of the day.
- *
- * If we pass midnight, don't wrap back to 0.
+ * Return the BIOS time-of-day value.
*
* XXX uses undocumented BCD support from libstand.
*/
-
-time_t
-time(time_t *t)
+static int
+bios_seconds(void)
{
- static time_t lasttime, now;
int hr, minute, sec;
unsigned char bios_time[6];
-
+
v86.ctl = 0;
- v86.addr = 0x1c; /* int 0x1c, function 0 */
+ v86.addr = 0x1c; /* int 0x1c, function 0 */
v86.eax = 0x0000;
v86.es = VTOPSEG(bios_time);
v86.ebx = VTOPOFF(bios_time);
@@ -59,7 +57,20 @@ time(time_t *t)
minute = bcd2bin(bios_time[4]);
sec = bcd2bin(bios_time[5]);
- now = hr * 3600 + minute * 60 + sec;
+ return (hr * 3600 + minute * 60 + sec);
+}
+
+/*
+ * Return the time in seconds since the beginning of the day.
+ */
+time_t
+time(time_t *t)
+{
+ static time_t lasttime;
+ time_t now;
+
+ now = bios_seconds();
+
if (now < lasttime)
now += 24 * 3600;
lasttime = now;
diff --git a/sys/boot/pc98/loader/Makefile b/sys/boot/pc98/loader/Makefile
index 91d5150..9f2e32f 100644
--- a/sys/boot/pc98/loader/Makefile
+++ b/sys/boot/pc98/loader/Makefile
@@ -18,6 +18,7 @@ CFLAGS+= -DLOADER_TFTP_SUPPORT
CFLAGS+= -DLOADER_NFS_SUPPORT
.endif
+# Include bcache code.
HAVE_BCACHE= yes
# Enable PnP and ISA-PnP code.
diff --git a/sys/boot/pc98/loader/main.c b/sys/boot/pc98/loader/main.c
index 83e9bdf..6573990 100644
--- a/sys/boot/pc98/loader/main.c
+++ b/sys/boot/pc98/loader/main.c
@@ -145,6 +145,14 @@ main(void)
bc_add(initial_bootdev);
}
+ archsw.arch_autoload = i386_autoload;
+ archsw.arch_getdev = i386_getdev;
+ archsw.arch_copyin = i386_copyin;
+ archsw.arch_copyout = i386_copyout;
+ archsw.arch_readin = i386_readin;
+ archsw.arch_isainb = isa_inb;
+ archsw.arch_isaoutb = isa_outb;
+
/*
* March through the device switch probing for things.
*/
@@ -163,14 +171,6 @@ main(void)
extract_currdev(); /* set $currdev and $loaddev */
setenv("LINES", "24", 1); /* optional */
-
- archsw.arch_autoload = i386_autoload;
- archsw.arch_getdev = i386_getdev;
- archsw.arch_copyin = i386_copyin;
- archsw.arch_copyout = i386_copyout;
- archsw.arch_readin = i386_readin;
- archsw.arch_isainb = isa_inb;
- archsw.arch_isaoutb = isa_outb;
interact(); /* doesn't return */
@@ -188,7 +188,8 @@ static void
extract_currdev(void)
{
struct i386_devdesc new_currdev;
- int major, biosdev = -1;
+ int major;
+ int biosdev = -1;
/* Assume we are booting from a BIOS disk by default */
new_currdev.d_dev = &biosdisk;
diff --git a/sys/cddl/compat/opensolaris/sys/vnode.h b/sys/cddl/compat/opensolaris/sys/vnode.h
index 616e11a..68288a7 100644
--- a/sys/cddl/compat/opensolaris/sys/vnode.h
+++ b/sys/cddl/compat/opensolaris/sys/vnode.h
@@ -217,7 +217,6 @@ zfs_vn_rdwr(enum uio_rw rw, vnode_t *vp, caddr_t base, ssize_t len,
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
if (rw == UIO_WRITE) {
ioflag = IO_SYNC;
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
} else {
ioflag = IO_DIRECT;
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
index 45ec88b..3ae43f1 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c
@@ -940,6 +940,8 @@ top:
/* NB: we already did dmu_tx_wait() if necessary */
goto top;
}
+ if (error == 0)
+ VOP_UNLOCK(*xvpp, 0);
return (error);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
index f213d10..7792f6e 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c
@@ -4577,7 +4577,6 @@ vop_deleteextattr {
ZFS_EXIT(zfsvfs);
return (error);
}
- VOP_LEASE(nd.ni_dvp, td, ap->a_cred, LEASE_WRITE);
error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
vput(nd.ni_dvp);
@@ -4639,7 +4638,6 @@ vop_setextattr {
return (error);
}
- VOP_LEASE(vp, td, ap->a_cred, LEASE_WRITE);
VATTR_NULL(&va);
va.va_size = 0;
error = VOP_SETATTR(vp, &va, ap->a_cred);
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
index 08d6510..84e832c 100644
--- a/sys/compat/freebsd32/freebsd32.h
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -191,4 +191,10 @@ struct thr_param32 {
uint32_t spare[3];
};
+struct i386_ldt_args32 {
+ uint32_t start;
+ uint32_t descs;
+ uint32_t num;
+};
+
#endif /* !_COMPAT_FREEBSD32_FREEBSD32_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_ioctl.c b/sys/compat/freebsd32/freebsd32_ioctl.c
index 5cca29a..122bb4d 100644
--- a/sys/compat/freebsd32/freebsd32_ioctl.c
+++ b/sys/compat/freebsd32/freebsd32_ioctl.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/cdio.h>
#include <sys/fcntl.h>
+#include <sys/filio.h>
#include <sys/file.h>
#include <sys/ioccom.h>
#include <sys/mdioctl.h>
@@ -178,6 +179,22 @@ freebsd32_ioctl_ioc_read_toc(struct thread *td,
return error;
}
+static int
+freebsd32_ioctl_fiodgname(struct thread *td,
+ struct freebsd32_ioctl_args *uap, struct file *fp)
+{
+ struct fiodgname_arg fgn;
+ struct fiodgname_arg32 fgn32;
+ int error;
+
+ if ((error = copyin(uap->data, &fgn32, sizeof fgn32)) != 0)
+ return (error);
+ CP(fgn32, fgn, len);
+ PTRIN_CP(fgn32, fgn, buf);
+ error = fo_ioctl(fp, FIODGNAME, (caddr_t)&fgn, td->td_ucred, td);
+ fdrop(fp, td);
+ return (error);
+}
int
freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap)
@@ -210,6 +227,9 @@ freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap)
case CDIOREADTOCHEADER_32:
return freebsd32_ioctl_ioc_toc_header(td, uap, fp);
+ case FIODGNAME_32:
+ return freebsd32_ioctl_fiodgname(td, uap, fp);
+
default:
fdrop(fp, td);
ap.fd = uap->fd;
diff --git a/sys/compat/freebsd32/freebsd32_ioctl.h b/sys/compat/freebsd32/freebsd32_ioctl.h
index 7844066..fddf553 100644
--- a/sys/compat/freebsd32/freebsd32_ioctl.h
+++ b/sys/compat/freebsd32/freebsd32_ioctl.h
@@ -62,11 +62,17 @@ struct md_ioctl32 {
int md_pad[MDNPAD32]; /* padding for future ideas */
};
+struct fiodgname_arg32 {
+ int len;
+ caddr_t32 buf;
+};
+
#define CDIOREADTOCENTRYS_32 _IOWR('c', 5, struct ioc_read_toc_entry32)
#define CDIOREADTOCHEADER_32 _IOR('c', 4, struct ioc_toc_header32)
#define MDIOCATTACH_32 _IOC(IOC_INOUT, 'm', 0, sizeof(struct md_ioctl32) + 4)
#define MDIOCDETACH_32 _IOC(IOC_INOUT, 'm', 1, sizeof(struct md_ioctl32) + 4)
#define MDIOCQUERY_32 _IOC(IOC_INOUT, 'm', 2, sizeof(struct md_ioctl32) + 4)
#define MDIOCLIST_32 _IOC(IOC_INOUT, 'm', 3, sizeof(struct md_ioctl32) + 4)
+#define FIODGNAME_32 _IOW('f', 120, struct fiodgname_arg32)
#endif /* _COMPAT_FREEBSD32_IOCTL_H_ */
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 59809d8..1acf5e8 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -2043,8 +2043,9 @@ freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
error = copyin(uap->jail, &version, sizeof(uint32_t));
if (error)
return (error);
+
switch (version) {
- case 0:
+ case 0:
{
/* FreeBSD single IPv4 jails. */
struct jail32_v0 j32_v0;
diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h
index 625378f..bcca32b 100644
--- a/sys/compat/freebsd32/freebsd32_proto.h
+++ b/sys/compat/freebsd32/freebsd32_proto.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 185878 2008-12-10 20:56:19Z jhb
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 190621 2009-04-01 13:11:50Z kib
*/
#ifndef _FREEBSD32_SYSPROTO_H_
@@ -119,6 +119,10 @@ struct freebsd32_adjtime_args {
char delta_l_[PADL_(struct timeval32 *)]; struct timeval32 * delta; char delta_r_[PADR_(struct timeval32 *)];
char olddelta_l_[PADL_(struct timeval32 *)]; struct timeval32 * olddelta; char olddelta_r_[PADR_(struct timeval32 *)];
};
+struct freebsd32_sysarch_args {
+ char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)];
+ char parms_l_[PADL_(char *)]; char * parms; char parms_r_[PADR_(char *)];
+};
struct freebsd32_semsys_args {
char which_l_[PADL_(int)]; int which; char which_r_[PADR_(int)];
char a2_l_[PADL_(int)]; int a2; char a2_r_[PADR_(int)];
@@ -456,6 +460,7 @@ int freebsd32_writev(struct thread *, struct freebsd32_writev_args *);
int freebsd32_settimeofday(struct thread *, struct freebsd32_settimeofday_args *);
int freebsd32_utimes(struct thread *, struct freebsd32_utimes_args *);
int freebsd32_adjtime(struct thread *, struct freebsd32_adjtime_args *);
+int freebsd32_sysarch(struct thread *, struct freebsd32_sysarch_args *);
int freebsd32_semsys(struct thread *, struct freebsd32_semsys_args *);
int freebsd32_msgsys(struct thread *, struct freebsd32_msgsys_args *);
int freebsd32_shmsys(struct thread *, struct freebsd32_shmsys_args *);
@@ -682,6 +687,7 @@ int freebsd6_freebsd32_ftruncate(struct thread *, struct freebsd6_freebsd32_ftru
#define FREEBSD32_SYS_AUE_freebsd32_settimeofday AUE_SETTIMEOFDAY
#define FREEBSD32_SYS_AUE_freebsd32_utimes AUE_UTIMES
#define FREEBSD32_SYS_AUE_freebsd32_adjtime AUE_ADJTIME
+#define FREEBSD32_SYS_AUE_freebsd32_sysarch AUE_SYSARCH
#define FREEBSD32_SYS_AUE_freebsd32_semsys AUE_SEMSYS
#define FREEBSD32_SYS_AUE_freebsd32_msgsys AUE_MSGSYS
#define FREEBSD32_SYS_AUE_freebsd32_shmsys AUE_SHMSYS
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
index d491d83..b6e2b6e 100644
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 185878 2008-12-10 20:56:19Z jhb
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 190621 2009-04-01 13:11:50Z kib
*/
#define FREEBSD32_SYS_syscall 0
@@ -159,7 +159,7 @@
/* 162 is obsolete getdomainname */
/* 163 is obsolete setdomainname */
/* 164 is obsolete uname */
-#define FREEBSD32_SYS_sysarch 165
+#define FREEBSD32_SYS_freebsd32_sysarch 165
#define FREEBSD32_SYS_rtprio 166
#define FREEBSD32_SYS_freebsd32_semsys 169
#define FREEBSD32_SYS_freebsd32_msgsys 170
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
index 88a5e83..cf3f1cc 100644
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 185878 2008-12-10 20:56:19Z jhb
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 190621 2009-04-01 13:11:50Z kib
*/
const char *freebsd32_syscallnames[] = {
@@ -172,7 +172,7 @@ const char *freebsd32_syscallnames[] = {
"obs_getdomainname", /* 162 = obsolete getdomainname */
"obs_setdomainname", /* 163 = obsolete setdomainname */
"obs_uname", /* 164 = obsolete uname */
- "sysarch", /* 165 = sysarch */
+ "freebsd32_sysarch", /* 165 = freebsd32_sysarch */
"rtprio", /* 166 = rtprio */
"#167", /* 167 = nosys */
"#168", /* 168 = nosys */
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
index e0177c8..9e75246 100644
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -3,7 +3,7 @@
*
* DO NOT EDIT-- this file is automatically generated.
* $FreeBSD$
- * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 185878 2008-12-10 20:56:19Z jhb
+ * created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 190621 2009-04-01 13:11:50Z kib
*/
#include "opt_compat.h"
@@ -203,7 +203,7 @@ struct sysent freebsd32_sysent[] = {
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 162 = obsolete getdomainname */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 163 = obsolete setdomainname */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 164 = obsolete uname */
- { AS(sysarch_args), (sy_call_t *)sysarch, AUE_SYSARCH, NULL, 0, 0 }, /* 165 = sysarch */
+ { AS(freebsd32_sysarch_args), (sy_call_t *)freebsd32_sysarch, AUE_SYSARCH, NULL, 0, 0 }, /* 165 = freebsd32_sysarch */
{ AS(rtprio_args), (sy_call_t *)rtprio, AUE_RTPRIO, NULL, 0, 0 }, /* 166 = rtprio */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 167 = nosys */
{ 0, (sy_call_t *)nosys, AUE_NULL, NULL, 0, 0 }, /* 168 = nosys */
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index 25cb81c..4d571f2 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -298,7 +298,7 @@
162 AUE_NULL OBSOL getdomainname
163 AUE_NULL OBSOL setdomainname
164 AUE_NULL OBSOL uname
-165 AUE_SYSARCH NOPROTO { int sysarch(int op, char *parms); }
+165 AUE_SYSARCH STD { int freebsd32_sysarch(int op, char *parms); }
166 AUE_RTPRIO NOPROTO { int rtprio(int function, pid_t pid, \
struct rtprio *rtp); }
167 AUE_NULL UNIMPL nosys
diff --git a/sys/compat/ia32/ia32_signal.h b/sys/compat/ia32/ia32_signal.h
index f2be96d..6ebb0de 100644
--- a/sys/compat/ia32/ia32_signal.h
+++ b/sys/compat/ia32/ia32_signal.h
@@ -59,7 +59,9 @@ struct ia32_mcontext {
* See <i386/include/npx.h> for the internals of mc_fpstate[].
*/
u_int32_t mc_fpstate[128] __aligned(16);
- u_int32_t mc_spare2[8];
+ u_int32_t mc_fsbase;
+ u_int32_t mc_gsbase;
+ u_int32_t mc_spare2[6];
};
struct ia32_ucontext {
diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
index 0b32b9a..af8168e 100644
--- a/sys/compat/ia32/ia32_sysvec.c
+++ b/sys/compat/ia32/ia32_sysvec.c
@@ -148,7 +148,8 @@ static Elf32_Brandinfo ia32_brand_info = {
.interp_path = "/libexec/ld-elf.so.1",
.sysvec = &ia32_freebsd_sysvec,
.interp_newpath = "/libexec/ld-elf32.so.1",
- .flags = BI_CAN_EXEC_DYN
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(ia32, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -163,7 +164,8 @@ static Elf32_Brandinfo ia32_brand_oinfo = {
.interp_path = "/usr/libexec/ld-elf.so.1",
.sysvec = &ia32_freebsd_sysvec,
.interp_newpath = "/libexec/ld-elf32.so.1",
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(oia32, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -187,15 +189,21 @@ ia32_copyout_strings(struct image_params *imgp)
char *stringp, *destp;
u_int32_t *stack_base;
struct freebsd32_ps_strings *arginfo;
+ size_t execpath_len;
int szsigcode;
/*
* Calculate string base and vector table pointers.
* Also deal with signal trampoline code for this exec type.
*/
+ if (imgp->execpath != NULL && imgp->auxargs != NULL)
+ execpath_len = strlen(imgp->execpath) + 1;
+ else
+ execpath_len = 0;
arginfo = (struct freebsd32_ps_strings *)FREEBSD32_PS_STRINGS;
szsigcode = *(imgp->proc->p_sysent->sv_szsigcode);
destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
+ roundup(execpath_len, sizeof(char *)) -
roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
/*
@@ -206,6 +214,15 @@ ia32_copyout_strings(struct image_params *imgp)
((caddr_t)arginfo - szsigcode), szsigcode);
/*
+ * Copy the image path for the rtld.
+ */
+ if (execpath_len != 0) {
+ imgp->execpathp = (uintptr_t)arginfo - szsigcode - execpath_len;
+ copyout(imgp->execpath, (void *)imgp->execpathp,
+ execpath_len);
+ }
+
+ /*
* If we have a valid auxargs ptr, prepare some room
* on the stack.
*/
@@ -221,9 +238,9 @@ ia32_copyout_strings(struct image_params *imgp)
* the arg and env vector sets,and imgp->auxarg_size is room
* for argument of Runtime loader.
*/
- vectp = (u_int32_t *) (destp - (imgp->args->argc + imgp->args->envc + 2 +
- imgp->auxarg_size) * sizeof(u_int32_t));
-
+ vectp = (u_int32_t *) (destp - (imgp->args->argc +
+ imgp->args->envc + 2 + imgp->auxarg_size + execpath_len) *
+ sizeof(u_int32_t));
} else
/*
* The '+ 2' is for the null pointers at the end of each of
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 5cc1f7d..52f6e94 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -75,6 +75,7 @@ __FBSDID("$FreeBSD$");
#include <sys/vmmeter.h>
#include <sys/vnode.h>
#include <sys/vimage.h>
+#include <sys/bus.h>
#include <net/if.h>
#include <net/route.h>
@@ -90,6 +91,9 @@ __FBSDID("$FreeBSD$");
#include <machine/clock.h>
+#include <geom/geom.h>
+#include <geom/geom_int.h>
+
#if defined(__i386__) || defined(__amd64__)
#include <machine/cputypes.h>
#include <machine/md_var.h>
@@ -359,6 +363,9 @@ linprocfs_domtab(PFS_FILL_ARGS)
sbuf_printf(sb, "/sys %s sysfs %s", mntto,
mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
} else {
+ /* For Linux msdosfs is called vfat */
+ if (strcmp(fstype, "msdosfs") == 0)
+ fstype = "vfat";
sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
}
@@ -383,6 +390,69 @@ linprocfs_domtab(PFS_FILL_ARGS)
}
/*
+ * Filler function for proc/partitions
+ *
+ */
+static int
+linprocfs_dopartitions(PFS_FILL_ARGS)
+{
+ struct g_class *cp;
+ struct g_geom *gp;
+ struct g_provider *pp;
+ struct nameidata nd;
+ const char *lep;
+ char *dlep, *flep;
+ size_t lep_len;
+ int error;
+ int major, minor;
+
+ /* resolve symlinks etc. in the emulation tree prefix */
+ NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
+ flep = NULL;
+ error = namei(&nd);
+ lep = linux_emul_path;
+ if (error == 0) {
+ if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
+ lep = dlep;
+ vrele(nd.ni_vp);
+ VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
+ }
+ lep_len = strlen(lep);
+
+ g_topology_lock();
+ error = 0;
+ sbuf_printf(sb, "major minor #blocks name rio rmerge rsect "
+ "ruse wio wmerge wsect wuse running use aveq\n");
+
+ LIST_FOREACH(cp, &g_classes, class) {
+ if (strcmp(cp->name, "DISK") == 0 ||
+ strcmp(cp->name, "PART") == 0)
+ LIST_FOREACH(gp, &cp->geom, geom) {
+ LIST_FOREACH(pp, &gp->provider, provider) {
+ if (linux_driver_get_major_minor(
+ pp->name, &major, &minor) != 0) {
+ major = 0;
+ minor = 0;
+ }
+ sbuf_printf(sb, "%d %d %lld %s "
+ "%d %d %d %d %d "
+ "%d %d %d %d %d %d\n",
+ major, minor,
+ (long long)pp->mediasize, pp->name,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0);
+ }
+ }
+ }
+ g_topology_unlock();
+
+ if (flep != NULL)
+ free(flep, M_TEMP);
+ return (error);
+}
+
+
+/*
* Filler function for proc/stat
*/
static int
@@ -1206,6 +1276,8 @@ linprocfs_init(PFS_INIT_ARGS)
NULL, NULL, NULL, PFS_RD);
pfs_create_file(root, "mtab", &linprocfs_domtab,
NULL, NULL, NULL, PFS_RD);
+ pfs_create_file(root, "partitions", &linprocfs_dopartitions,
+ NULL, NULL, NULL, PFS_RD);
pfs_create_link(root, "self", &procfs_docurproc,
NULL, NULL, NULL, 0);
pfs_create_file(root, "stat", &linprocfs_dostat,
diff --git a/sys/compat/linux/linux_emul.h b/sys/compat/linux/linux_emul.h
index 7125c92..2c1b3ca 100644
--- a/sys/compat/linux/linux_emul.h
+++ b/sys/compat/linux/linux_emul.h
@@ -31,8 +31,6 @@
#ifndef _LINUX_EMUL_H_
#define _LINUX_EMUL_H_
-#include <compat/linux/linux_futex.h>
-
struct linux_emuldata_shared {
int refs;
pid_t group_pid;
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index b368429..54ab6a2 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -1109,6 +1109,9 @@ linux_mount(struct thread *td, struct linux_mount_args *args)
} else if (strcmp(fstypename, "proc") == 0) {
strcpy(fstypename, "linprocfs");
fsdata = NULL;
+ } else if (strcmp(fstypename, "vfat") == 0) {
+ strcpy(fstypename, "msdosfs");
+ fsdata = NULL;
} else {
return (ENODEV);
}
@@ -1135,6 +1138,12 @@ linux_mount(struct thread *td, struct linux_mount_args *args)
"fstype", fstypename,
"fspath", mntonname,
NULL);
+ } else if (strcmp(fstypename, "msdosfs") == 0) {
+ error = kernel_vmount(fsflags,
+ "fstype", fstypename,
+ "fspath", mntonname,
+ "from", mntfromname,
+ NULL);
} else
error = EOPNOTSUPP;
return (error);
diff --git a/sys/compat/linux/linux_futex.c b/sys/compat/linux/linux_futex.c
index b19d290..e1d214f 100644
--- a/sys/compat/linux/linux_futex.c
+++ b/sys/compat/linux/linux_futex.c
@@ -40,18 +40,17 @@ __KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.7 2006/07/24 19:01:49 manu Exp $")
#include "opt_compat.h"
#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/time.h>
#include <sys/systm.h>
-#include <sys/proc.h>
-#include <sys/queue.h>
#include <sys/imgact.h>
+#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mutex.h>
#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
#include <sys/sched.h>
#include <sys/sx.h>
-#include <sys/malloc.h>
#ifdef COMPAT_LINUX32
#include <machine/../linux32/linux.h>
@@ -60,8 +59,8 @@ __KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.7 2006/07/24 19:01:49 manu Exp $")
#include <machine/../linux/linux.h>
#include <machine/../linux/linux_proto.h>
#endif
-#include <compat/linux/linux_emul.h>
#include <compat/linux/linux_futex.h>
+#include <compat/linux/linux_emul.h>
struct futex;
@@ -276,13 +275,6 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
FUTEX_SYSTEM_UNLOCK;
break;
- case LINUX_FUTEX_FD:
-#ifdef DEBUG
- printf("linux_sys_futex: unimplemented op %d\n",
- args->op);
-#endif
- return (ENOSYS);
-
case LINUX_FUTEX_WAKE_OP:
FUTEX_SYSTEM_LOCK;
#ifdef DEBUG
diff --git a/sys/compat/linux/linux_futex.h b/sys/compat/linux/linux_futex.h
index d658925..ca8b768 100644
--- a/sys/compat/linux/linux_futex.h
+++ b/sys/compat/linux/linux_futex.h
@@ -38,7 +38,7 @@
#define LINUX_FUTEX_WAIT 0
#define LINUX_FUTEX_WAKE 1
-#define LINUX_FUTEX_FD 2
+#define LINUX_FUTEX_FD 2 /* unused */
#define LINUX_FUTEX_REQUEUE 3
#define LINUX_FUTEX_CMP_REQUEUE 4
#define LINUX_FUTEX_WAKE_OP 5
diff --git a/sys/compat/ndis/subr_ntoskrnl.c b/sys/compat/ndis/subr_ntoskrnl.c
index 237da31..69bea9e 100644
--- a/sys/compat/ndis/subr_ntoskrnl.c
+++ b/sys/compat/ndis/subr_ntoskrnl.c
@@ -1197,6 +1197,11 @@ IofCompleteRequest(irp *ip, uint8_t prioboost)
sl++;
} while (ip->irp_currentstackloc <= (ip->irp_stackcnt + 1));
+ if (ip->irp_usriostat != NULL)
+ *ip->irp_usriostat = ip->irp_iostat;
+ if (ip->irp_usrevent != NULL)
+ KeSetEvent(ip->irp_usrevent, prioboost, FALSE);
+
/* Handle any associated IRPs. */
if (ip->irp_flags & IRP_ASSOCIATED_IRP) {
@@ -1220,16 +1225,10 @@ IofCompleteRequest(irp *ip, uint8_t prioboost)
/* With any luck, these conditions will never arise. */
- if (ip->irp_flags & (IRP_PAGING_IO|IRP_CLOSE_OPERATION)) {
- if (ip->irp_usriostat != NULL)
- *ip->irp_usriostat = ip->irp_iostat;
- if (ip->irp_usrevent != NULL)
- KeSetEvent(ip->irp_usrevent, prioboost, FALSE);
- if (ip->irp_flags & IRP_PAGING_IO) {
- if (ip->irp_mdl != NULL)
- IoFreeMdl(ip->irp_mdl);
- IoFreeIrp(ip);
- }
+ if (ip->irp_flags & IRP_PAGING_IO) {
+ if (ip->irp_mdl != NULL)
+ IoFreeMdl(ip->irp_mdl);
+ IoFreeIrp(ip);
}
return;
diff --git a/sys/compat/ndis/subr_usbd.c b/sys/compat/ndis/subr_usbd.c
index a07e2cc..bb72732 100644
--- a/sys/compat/ndis/subr_usbd.c
+++ b/sys/compat/ndis/subr_usbd.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_error.h>
+#include <dev/usb/usb_parse.h>
#include <dev/usb/usb_request.h>
#include <compat/ndis/pe_var.h>
@@ -76,6 +77,38 @@ __FBSDID("$FreeBSD$");
static driver_object usbd_driver;
static usb2_callback_t usbd_non_isoc_callback;
+static usb2_callback_t usbd_ctrl_callback;
+
+#define USBD_CTRL_READ_PIPE 0
+#define USBD_CTRL_WRITE_PIPE 1
+#define USBD_CTRL_MAX_PIPE 2
+#define USBD_CTRL_READ_BUFFER_SP 256
+#define USBD_CTRL_READ_BUFFER_SIZE \
+ (sizeof(struct usb2_device_request) + USBD_CTRL_READ_BUFFER_SP)
+#define USBD_CTRL_WRITE_BUFFER_SIZE \
+ (sizeof(struct usb2_device_request))
+static struct usb2_config usbd_default_epconfig[USBD_CTRL_MAX_PIPE] = {
+ [USBD_CTRL_READ_PIPE] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* control pipe */
+ .direction = UE_DIR_ANY,
+ .if_index = 0,
+ .bufsize = USBD_CTRL_READ_BUFFER_SIZE,
+ .flags = { .short_xfer_ok = 1, },
+ .callback = &usbd_ctrl_callback,
+ .timeout = 5000, /* 5 seconds */
+ },
+ [USBD_CTRL_WRITE_PIPE] = {
+ .type = UE_CONTROL,
+ .endpoint = 0x00, /* control pipe */
+ .direction = UE_DIR_ANY,
+ .if_index = 0,
+ .bufsize = USBD_CTRL_WRITE_BUFFER_SIZE,
+ .flags = { .proxy_buffer = 1, },
+ .callback = &usbd_ctrl_callback,
+ .timeout = 5000, /* 5 seconds */
+ }
+};
static int32_t usbd_func_bulkintr(irp *);
static int32_t usbd_func_vendorclass(irp *);
@@ -83,6 +116,9 @@ static int32_t usbd_func_selconf(irp *);
static int32_t usbd_func_abort_pipe(irp *);
static usb2_error_t usbd_setup_endpoint(irp *, uint8_t,
struct usb2_endpoint_descriptor *);
+static usb2_error_t usbd_setup_endpoint_default(irp *, uint8_t);
+static usb2_error_t usbd_setup_endpoint_one(irp *, uint8_t,
+ struct ndisusb_ep *, struct usb2_config *);
static int32_t usbd_func_getdesc(irp *);
static union usbd_urb *usbd_geturb(irp *);
static struct ndisusb_ep*usbd_get_ndisep(irp *, usb_endpoint_descriptor_t *);
@@ -557,6 +593,57 @@ usbd_func_selconf(ip)
}
static usb2_error_t
+usbd_setup_endpoint_one(ip, ifidx, ne, epconf)
+ irp *ip;
+ uint8_t ifidx;
+ struct ndisusb_ep *ne;
+ struct usb2_config *epconf;
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ struct ndis_softc *sc = device_get_softc(dev);
+ struct usb2_xfer *xfer;
+ usb2_error_t status;
+
+ InitializeListHead(&ne->ne_active);
+ InitializeListHead(&ne->ne_pending);
+ KeInitializeSpinLock(&ne->ne_lock);
+
+ status = usb2_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer,
+ epconf, 1, sc, &sc->ndisusb_mtx);
+ if (status != USB_ERR_NORMAL_COMPLETION) {
+ device_printf(dev, "couldn't setup xfer: %s\n",
+ usb2_errstr(status));
+ return (status);
+ }
+ xfer = ne->ne_xfer[0];
+ xfer->priv_fifo = ne;
+
+ return (status);
+}
+
+static usb2_error_t
+usbd_setup_endpoint_default(ip, ifidx)
+ irp *ip;
+ uint8_t ifidx;
+{
+ device_t dev = IRP_NDIS_DEV(ip);
+ struct ndis_softc *sc = device_get_softc(dev);
+ usb2_error_t status;
+
+ if (ifidx > 0)
+ device_printf(dev, "warning: ifidx > 0 isn't supported.\n");
+
+ status = usbd_setup_endpoint_one(ip, ifidx, &sc->ndisusb_dread_ep,
+ &usbd_default_epconfig[USBD_CTRL_READ_PIPE]);
+ if (status != USB_ERR_NORMAL_COMPLETION)
+ return (status);
+
+ status = usbd_setup_endpoint_one(ip, ifidx, &sc->ndisusb_dwrite_ep,
+ &usbd_default_epconfig[USBD_CTRL_WRITE_PIPE]);
+ return (status);
+}
+
+static usb2_error_t
usbd_setup_endpoint(ip, ifidx, ep)
irp *ip;
uint8_t ifidx;
@@ -587,11 +674,11 @@ usbd_setup_endpoint(ip, ifidx, ep)
cfg.type = UE_GET_XFERTYPE(ep->bmAttributes);
cfg.endpoint = UE_GET_ADDR(ep->bEndpointAddress);
cfg.direction = UE_GET_DIR(ep->bEndpointAddress);
- cfg.mh.callback = &usbd_non_isoc_callback;
- cfg.mh.bufsize = UGETW(ep->wMaxPacketSize);
- cfg.mh.flags.proxy_buffer = 1;
+ cfg.callback = &usbd_non_isoc_callback;
+ cfg.bufsize = UGETW(ep->wMaxPacketSize);
+ cfg.flags.proxy_buffer = 1;
if (UE_GET_DIR(ep->bEndpointAddress) == UE_DIR_IN)
- cfg.mh.flags.short_xfer_ok = 1;
+ cfg.flags.short_xfer_ok = 1;
status = usb2_transfer_setup(sc->ndisusb_dev, &ifidx, ne->ne_xfer,
&cfg, 1, sc, &sc->ndisusb_mtx);
@@ -643,62 +730,54 @@ usbd_func_vendorclass(ip)
irp *ip;
{
device_t dev = IRP_NDIS_DEV(ip);
+ int32_t error;
struct ndis_softc *sc = device_get_softc(dev);
+ struct ndisusb_ep *ne;
+ struct ndisusb_xfer *nx;
struct usbd_urb_vendor_or_class_request *vcreq;
- uint8_t type = 0;
union usbd_urb *urb;
- struct usb2_device_request req;
- usb2_error_t status;
+
+ if (!(sc->ndisusb_status & NDISUSB_STATUS_SETUP_EP)) {
+ /*
+ * XXX In some cases the interface number isn't 0. However
+ * some driver (eg. RTL8187L NDIS driver) calls this function
+ * before calling URB_FUNCTION_SELECT_CONFIGURATION.
+ */
+ error = usbd_setup_endpoint_default(ip, 0);
+ if (error != USB_ERR_NORMAL_COMPLETION)
+ return usbd_usb2urb(error);
+ sc->ndisusb_status |= NDISUSB_STATUS_SETUP_EP;
+ }
urb = usbd_geturb(ip);
vcreq = &urb->uu_vcreq;
+ ne = (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ?
+ &sc->ndisusb_dread_ep : &sc->ndisusb_dwrite_ep;
+ IRP_NDISUSB_EP(ip) = ne;
+ ip->irp_cancelfunc = (cancel_func)usbd_irpcancel_wrap;
- switch (urb->uu_hdr.uuh_func) {
- case URB_FUNCTION_CLASS_DEVICE:
- type = UT_CLASS | UT_DEVICE;
- break;
- case URB_FUNCTION_CLASS_INTERFACE:
- type = UT_CLASS | UT_INTERFACE;
- break;
- case URB_FUNCTION_CLASS_OTHER:
- type = UT_CLASS | UT_OTHER;
- break;
- case URB_FUNCTION_CLASS_ENDPOINT:
- type = UT_CLASS | UT_ENDPOINT;
- break;
- case URB_FUNCTION_VENDOR_DEVICE:
- type = UT_VENDOR | UT_DEVICE;
- break;
- case URB_FUNCTION_VENDOR_INTERFACE:
- type = UT_VENDOR | UT_INTERFACE;
- break;
- case URB_FUNCTION_VENDOR_OTHER:
- type = UT_VENDOR | UT_OTHER;
- break;
- case URB_FUNCTION_VENDOR_ENDPOINT:
- type = UT_VENDOR | UT_ENDPOINT;
- break;
- default:
- /* never reached. */
- break;
+ nx = malloc(sizeof(struct ndisusb_xfer), M_USBDEV, M_NOWAIT | M_ZERO);
+ if (nx == NULL) {
+ device_printf(IRP_NDIS_DEV(ip), "out of memory\n");
+ return (USBD_STATUS_NO_MEMORY);
}
+ nx->nx_ep = ne;
+ nx->nx_priv = ip;
+ KeAcquireSpinLockAtDpcLevel(&ne->ne_lock);
+ InsertTailList((&ne->ne_pending), (&nx->nx_next));
+ KeReleaseSpinLockFromDpcLevel(&ne->ne_lock);
- type |= (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ?
- UT_READ : UT_WRITE;
- type |= vcreq->uvc_reserved1;
-
- req.bmRequestType = type;
- req.bRequest = vcreq->uvc_req;
- USETW(req.wIndex, vcreq->uvc_idx);
- USETW(req.wValue, vcreq->uvc_value);
- USETW(req.wLength, vcreq->uvc_trans_buflen);
+ /* we've done to setup xfer. Let's transfer it. */
+ ip->irp_iostat.isb_status = STATUS_PENDING;
+ ip->irp_iostat.isb_info = 0;
+ USBD_URB_STATUS(urb) = USBD_STATUS_PENDING;
+ IoMarkIrpPending(ip);
- NDISUSB_LOCK(sc);
- status = usb2_do_request(sc->ndisusb_dev, &sc->ndisusb_mtx, &req,
- vcreq->uvc_trans_buf);
- NDISUSB_UNLOCK(sc);
+ error = usbd_taskadd(ip, NDISUSB_TASK_VENDOR);
+ if (error != USBD_STATUS_SUCCESS)
+ return (error);
- return usbd_usb2urb(status);
+ return (USBD_STATUS_PENDING);
}
static void
@@ -706,8 +785,9 @@ usbd_irpcancel(dobj, ip)
device_object *dobj;
irp *ip;
{
+ device_t dev = IRP_NDIS_DEV(ip);
+ struct ndis_softc *sc = device_get_softc(dev);
struct ndisusb_ep *ne = IRP_NDISUSB_EP(ip);
- uint8_t irql;
if (ne == NULL) {
ip->irp_cancel = TRUE;
@@ -719,10 +799,10 @@ usbd_irpcancel(dobj, ip)
* Make sure that the current USB transfer proxy is
* cancelled and then restarted.
*/
- KeRaiseIrql(DISPATCH_LEVEL, &irql);
+ NDISUSB_LOCK(sc);
usb2_transfer_stop(ne->ne_xfer[0]);
usb2_transfer_start(ne->ne_xfer[0]);
- KeLowerIrql(irql);
+ NDISUSB_UNLOCK(sc);
ip->irp_cancel = TRUE;
IoReleaseCancelSpinLock(ip->irp_cancelirql);
@@ -870,6 +950,146 @@ extra:
}
}
+static void
+usbd_ctrl_callback(struct usb2_xfer *xfer)
+{
+ irp *ip;
+ struct ndis_softc *sc = xfer->priv_sc;
+ struct ndisusb_ep *ne = xfer->priv_fifo;
+ struct ndisusb_xfer *nx;
+ uint8_t irql;
+ union usbd_urb *urb;
+ struct usbd_urb_vendor_or_class_request *vcreq;
+ uint8_t type = 0;
+ struct usb2_device_request req;
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ nx = usbd_aq_getfirst(sc, ne);
+ if (nx == NULL)
+ return;
+
+ ip = nx->nx_priv;
+ urb = usbd_geturb(ip);
+ vcreq = &urb->uu_vcreq;
+
+ if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) {
+ usb2_copy_out(xfer->frbuffers + 1, 0,
+ vcreq->uvc_trans_buf, xfer->frlengths[1]);
+ nx->nx_urbactlen += xfer->frlengths[1];
+ }
+
+ usbd_xfer_complete(sc, ne, nx, USB_ERR_NORMAL_COMPLETION);
+ /* fall through */
+ case USB_ST_SETUP:
+next:
+ /* get next transfer */
+ KeAcquireSpinLock(&ne->ne_lock, &irql);
+ if (IsListEmpty(&ne->ne_pending)) {
+ KeReleaseSpinLock(&ne->ne_lock, irql);
+ return;
+ }
+ nx = CONTAINING_RECORD(ne->ne_pending.nle_flink,
+ struct ndisusb_xfer, nx_next);
+ RemoveEntryList(&nx->nx_next);
+ /* add a entry to the active queue's tail. */
+ InsertTailList((&ne->ne_active), (&nx->nx_next));
+ KeReleaseSpinLock(&ne->ne_lock, irql);
+
+ ip = nx->nx_priv;
+ urb = usbd_geturb(ip);
+ vcreq = &urb->uu_vcreq;
+
+ switch (urb->uu_hdr.uuh_func) {
+ case URB_FUNCTION_CLASS_DEVICE:
+ type = UT_CLASS | UT_DEVICE;
+ break;
+ case URB_FUNCTION_CLASS_INTERFACE:
+ type = UT_CLASS | UT_INTERFACE;
+ break;
+ case URB_FUNCTION_CLASS_OTHER:
+ type = UT_CLASS | UT_OTHER;
+ break;
+ case URB_FUNCTION_CLASS_ENDPOINT:
+ type = UT_CLASS | UT_ENDPOINT;
+ break;
+ case URB_FUNCTION_VENDOR_DEVICE:
+ type = UT_VENDOR | UT_DEVICE;
+ break;
+ case URB_FUNCTION_VENDOR_INTERFACE:
+ type = UT_VENDOR | UT_INTERFACE;
+ break;
+ case URB_FUNCTION_VENDOR_OTHER:
+ type = UT_VENDOR | UT_OTHER;
+ break;
+ case URB_FUNCTION_VENDOR_ENDPOINT:
+ type = UT_VENDOR | UT_ENDPOINT;
+ break;
+ default:
+ /* never reached. */
+ break;
+ }
+
+ type |= (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) ?
+ UT_READ : UT_WRITE;
+ type |= vcreq->uvc_reserved1;
+
+ req.bmRequestType = type;
+ req.bRequest = vcreq->uvc_req;
+ USETW(req.wIndex, vcreq->uvc_idx);
+ USETW(req.wValue, vcreq->uvc_value);
+ USETW(req.wLength, vcreq->uvc_trans_buflen);
+
+ nx->nx_urbbuf = vcreq->uvc_trans_buf;
+ nx->nx_urblen = vcreq->uvc_trans_buflen;
+ nx->nx_urbactlen = 0;
+
+ usb2_copy_in(xfer->frbuffers, 0, &req, sizeof(req));
+ xfer->frlengths[0] = sizeof(req);
+ xfer->nframes = 1;
+ if (vcreq->uvc_trans_flags & USBD_TRANSFER_DIRECTION_IN) {
+ if (vcreq->uvc_trans_buflen >= USBD_CTRL_READ_BUFFER_SP)
+ device_printf(sc->ndis_dev,
+ "warning: not enough buffer space (%d).\n",
+ vcreq->uvc_trans_buflen);
+ xfer->frlengths[1] = MIN(xfer->max_data_length,
+ vcreq->uvc_trans_buflen);
+ xfer->nframes = 2;
+ } else {
+ if (nx->nx_urblen > 0)
+ device_printf(sc->ndis_dev,
+ "warning: not enough write buffer space"
+ " (%d).\n", nx->nx_urblen);
+ /*
+ * XXX with my local tests there was no cases to require
+ * a extra buffer until now but it'd need to update in
+ * the future if it needs to be.
+ */
+ if (nx->nx_urblen > 0) {
+ usb2_copy_in(xfer->frbuffers + 1 , 0,
+ nx->nx_urbbuf, nx->nx_urblen);
+ xfer->frlengths[1] = nx->nx_urblen;
+ xfer->nframes = 2;
+ }
+ }
+ usb2_start_hardware(xfer);
+ break;
+ default:
+ nx = usbd_aq_getfirst(sc, ne);
+ if (nx == NULL)
+ return;
+ if (xfer->error != USB_ERR_CANCELLED) {
+ xfer->flags.stall_pipe = 1;
+ device_printf(sc->ndis_dev, "usb xfer warning (%s)\n",
+ usb2_errstr(xfer->error));
+ }
+ usbd_xfer_complete(sc, ne, nx, xfer->error);
+ if (xfer->error != USB_ERR_CANCELLED)
+ goto next;
+ break;
+ }
+}
+
static struct ndisusb_ep *
usbd_get_ndisep(ip, ep)
irp *ip;
@@ -900,6 +1120,7 @@ usbd_xfertask(dobj, arg)
struct ndisusb_xferdone *nd;
struct ndisusb_xfer *nq;
struct usbd_urb_bulk_or_intr_transfer *ubi;
+ struct usbd_urb_vendor_or_class_request *vcreq;
union usbd_urb *urb;
usb2_error_t status;
void *priv;
@@ -920,18 +1141,19 @@ usbd_xfertask(dobj, arg)
ip = priv;
urb = usbd_geturb(ip);
- KASSERT(urb->uu_hdr.uuh_func ==
- URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER,
- ("function(%d) isn't for bulk or interrupt",
- urb->uu_hdr.uuh_func));
-
ip->irp_cancelfunc = NULL;
IRP_NDISUSB_EP(ip) = NULL;
switch (status) {
case USB_ERR_NORMAL_COMPLETION:
- ubi = &urb->uu_bulkintr;
- ubi->ubi_trans_buflen = nq->nx_urbactlen;
+ if (urb->uu_hdr.uuh_func ==
+ URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER) {
+ ubi = &urb->uu_bulkintr;
+ ubi->ubi_trans_buflen = nq->nx_urbactlen;
+ } else {
+ vcreq = &urb->uu_vcreq;
+ vcreq->uvc_trans_buflen = nq->nx_urbactlen;
+ }
ip->irp_iostat.isb_info = nq->nx_urbactlen;
ip->irp_iostat.isb_status = STATUS_SUCCESS;
USBD_URB_STATUS(urb) = USBD_STATUS_SUCCESS;
@@ -1035,6 +1257,12 @@ usbd_task(dobj, arg)
usb2_transfer_stop(ne->ne_xfer[0]);
usb2_transfer_start(ne->ne_xfer[0]);
break;
+ case NDISUSB_TASK_VENDOR:
+ ne = (urb->uu_vcreq.uvc_trans_flags &
+ USBD_TRANSFER_DIRECTION_IN) ?
+ &sc->ndisusb_dread_ep : &sc->ndisusb_dwrite_ep;
+ usb2_transfer_start(ne->ne_xfer[0]);
+ break;
default:
break;
}
@@ -1206,12 +1434,11 @@ USBD_ParseConfigurationDescriptorEx(conf, start, intfnum,
int32_t intfsubclass;
int32_t intfproto;
{
- char *pos;
+ struct usb2_descriptor *next = NULL;
usb_interface_descriptor_t *desc;
- for (pos = start; pos < ((char *)conf + UGETW(conf->wTotalLength));
- pos += desc->bLength) {
- desc = (usb_interface_descriptor_t *)pos;
+ while ((next = usb2_desc_foreach(conf, next)) != NULL) {
+ desc = (usb_interface_descriptor_t *)next;
if (desc->bDescriptorType != UDESC_INTERFACE)
continue;
if (!(intfnum == -1 || desc->bInterfaceNumber == intfnum))
diff --git a/sys/compat/svr4/svr4_sysvec.c b/sys/compat/svr4/svr4_sysvec.c
index 0030e3a..54406f5 100644
--- a/sys/compat/svr4/svr4_sysvec.c
+++ b/sys/compat/svr4/svr4_sysvec.c
@@ -204,6 +204,7 @@ Elf32_Brandinfo svr4_brand = {
.interp_path = "/lib/libc.so.1",
.sysvec = &svr4_sysvec,
.interp_newpath = NULL,
+ .brand_note = NULL,
.flags = 0
};
diff --git a/sys/conf/Makefile.mips b/sys/conf/Makefile.mips
index e03432c..443065a 100644
--- a/sys/conf/Makefile.mips
+++ b/sys/conf/Makefile.mips
@@ -28,73 +28,35 @@ S= ../../..
.endif
.include "$S/conf/kern.pre.mk"
-SYSTEM_LD:= ${SYSTEM_LD:$S/conf/ldscript.$M=ldscript.$M}
-SYSTEM_DEP:= ${SYSTEM_DEP:$S/conf/ldscript.$M=ldscript.$M}
-
# XXX: Such sweeping assumptions...
MACHINE=mips
MACHINE_ARCH=mips
-KERNLOADADDR?=0x80001000
-# This obscure value is defined by CFE for WR160N
-# To be changed later
-TRAMPLOADADDR?=0x807963c0
MKMODULESENV+= MACHINE=${MACHINE} MACHINE_ARCH=${MACHINE_ARCH}
# We default to the MIPS32 ISA, if none specified in the
# kernel configuration file.
ARCH_FLAGS?=-march=mips32
-EXTRA_FLAGS=-fno-pic -mno-abicalls -mno-dsp -G0
HACK_EXTRA_FLAGS=-shared
.if defined(TARGET_BIG_ENDIAN)
CFLAGS+=-EB
SYSTEM_LD+=-EB
-EXTRA_FLAGS+=-EB
-TRAMP_LDFLAGS+=-Wl,-EB
HACK_EXTRA_FLAGS+=-EB -Wl,-EB
.else
CFLAGS+=-EL
SYSTEM_LD+=-EL
-EXTRA_FLAGS+=-EL
-TRAMP_LDFLAGS+=-Wl,-EL
HACK_EXTRA_FLAGS+=-EL -Wl,-EL
.endif
# We add the -fno-pic flag to kernels because otherwise performance
# is extremely poor, as well as -mno-abicalls to force no ABI usage.
-CFLAGS+=${EXTRA_FLAGS} $(ARCH_FLAGS)
-HACK_EXTRA_FLAGS+=${EXTRA_FLAGS} $(ARCH_FLAGS)
+CFLAGS+=-fno-pic -mno-abicalls -G0 $(ARCH_FLAGS)
+HACK_EXTRA_FLAGS+=-fno-pic -mno-abicalls -G0 $(ARCH_FLAGS)
# XXX hardcoded kernel entry point
ASM_CFLAGS+=${CFLAGS} -D_LOCORE -DLOCORE
-KERNEL_EXTRA=trampoline
-trampoline: ${KERNEL_KO}.tramp.bin
-${KERNEL_KO}.tramp.bin: ${KERNEL_KO} $S/$M/$M/elf_trampoline.c \
- $S/$M/$M/inckern.S
- ${OBJCOPY} --strip-symbol '$$d' --strip-symbol '$$a' \
- -g --strip-symbol '$$t' ${FULLKERNEL} ${KERNEL_KO}.tmp
- sed s/${KERNLOADADDR}/${TRAMPLOADADDR}/ ldscript.$M | \
- sed s/" + SIZEOF_HEADERS"// > ldscript.$M.tramp.noheader
- # Generate .S file that setups stack and jumps to trampoline
- echo "#include <machine/asm.h>" >tmphack.S
- echo "ENTRY(_start)" >>tmphack.S
- echo "la t0, kernel_end" >>tmphack.S
- echo "move sp, t0" >>tmphack.S
- echo "add sp, 0x2000" >>tmphack.S
- echo "and sp, ~0x7" >>tmphack.S
- echo "la t0, _startC" >>tmphack.S
- echo "j t0" >>tmphack.S
- echo "END(_start)" >>tmphack.S
- echo "#define KERNNAME \"${KERNEL_KO}.tmp\"" >opt_kernname.h
- ${CC} -O -nostdlib -I. -I$S ${EXTRA_FLAGS} ${TRAMP_LDFLAGS} -Xlinker \
- -T -Xlinker ldscript.$M.tramp.noheader tmphack.S \
- $S/$M/$M/elf_trampoline.c $S/$M/$M/inckern.S \
- -o ${KERNEL_KO}.tramp.noheader
- ${OBJCOPY} -S -O binary ${KERNEL_KO}.tramp.noheader \
- ${KERNEL_KO}.tramp.bin \
-
%BEFORE_DEPEND
%OBJS
@@ -107,12 +69,6 @@ ${KERNEL_KO}.tramp.bin: ${KERNEL_KO} $S/$M/$M/elf_trampoline.c \
%CLEAN
-CLEAN+= ldscript.$M ldscript.$M.tramp.noheader \
- ${KERNEL_KO}.tramp.noheader ${KERNEL_KO}.tramp.bin
-
-ldscript.$M: $S/conf/ldscript.$M
- cat $S/conf/ldscript.$M|sed s/KERNLOADADDR/${KERNLOADADDR}/g \
- > ldscript.$M
%RULES
.include "$S/conf/kern.post.mk"
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index d48436e..8a172ac 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -765,10 +765,6 @@ device arcnet
# of synchronous PPP links (like `cx', `ar').
device sppp
-# The `sl' device implements the Serial Line IP (SLIP) service.
-# The `ppp' device implements the Point-to-Point Protocol.
-
-
# The `bpf' device enables the Berkeley Packet Filter. Be
# aware of the legal and administrative consequences of enabling this
# option. The number of devices determines the maximum number of
@@ -837,15 +833,6 @@ device enc
device lagg
#
-# The PPP_BSDCOMP option enables support for compress(1) style entire
-# packet compression, the PPP_DEFLATE is for zlib/gzip style compression.
-# PPP_FILTER enables code for filtering the ppp data stream and selecting
-# events for resetting the demand dial activity timer - requires bpf.
-# See pppd(8) for more details.
-#
-
-
-#
# Internet family options:
#
# MROUTING enables the kernel multicast packet forwarder, which works
@@ -1942,7 +1929,7 @@ device xl # 3Com 3c90x (``Boomerang'', ``Cyclone'')
device de # DEC/Intel DC21x4x (``Tulip'')
device em # Intel Pro/1000 Gigabit Ethernet
device igb # Intel Pro/1000 PCIE Gigabit Ethernet
-#device ixgbe # Intel Pro/10Gbe PCIE Ethernet
+device ixgbe # Intel Pro/10Gbe PCIE Ethernet
device le # AMD Am7900 LANCE and Am79C9xx PCnet
device mxge # Myricom Myri-10G 10GbE NIC
device nxge # Neterion Xframe 10GbE Server/Storage Adapter
@@ -2426,8 +2413,6 @@ device umodem
device ums
# Diamond Rio 500 MP3 player
device urio
-# USB scanners
-device uscanner
#
# USB serial support
device ucom
@@ -2678,7 +2663,6 @@ options SC_DEBUG_LEVEL=5 # Syscons debug level
options SC_RENDER_DEBUG # syscons rendering debugging
options SHOW_BUSYBUFS # List buffers that prevent root unmount
-options SLIP_IFF_OPTS
options VFS_BIO_DEBUG # VFS buffer I/O debugging
options KSTACK_MAX_PAGES=32 # Maximum pages to give the kernel stack
diff --git a/sys/conf/files b/sys/conf/files
index 6a14ef9..b7d30e0 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -515,16 +515,19 @@ dev/ath/if_ath_pci.c optional ath pci \
compile-with "${NORMAL_C} -I$S/dev/ath"
dev/ath/ah_osdep.c optional ath \
compile-with "${NORMAL_C} -I$S/dev/ath"
+#
dev/ath/ath_hal/ah.c optional ath \
compile-with "${NORMAL_C} -I$S/dev/ath"
dev/ath/ath_hal/ah_eeprom_v1.c optional ath_hal | ath_ar5210 \
compile-with "${NORMAL_C} -I$S/dev/ath"
dev/ath/ath_hal/ah_eeprom_v3.c optional ath_hal | ath_ar5211 | ath_ar5212 \
compile-with "${NORMAL_C} -I$S/dev/ath"
-dev/ath/ath_hal/ah_eeprom_v14.c optional ath_hal | ath_ar5416 | ath_ar9160 \
+dev/ath/ath_hal/ah_eeprom_v14.c \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath"
dev/ath/ath_hal/ah_regdomain.c optional ath \
compile-with "${NORMAL_C} -I$S/dev/ath"
+# ar5210
dev/ath/ath_hal/ar5210/ar5210_attach.c optional ath_hal | ath_ar5210 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5210/ar5210_beacon.c optional ath_hal | ath_ar5210 \
@@ -545,6 +548,7 @@ dev/ath/ath_hal/ar5210/ar5210_reset.c optional ath_hal | ath_ar5210 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5210/ar5210_xmit.c optional ath_hal | ath_ar5210 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+# ar5211
dev/ath/ath_hal/ar5211/ar5211_attach.c optional ath_hal | ath_ar5211 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5211/ar5211_beacon.c optional ath_hal | ath_ar5211 \
@@ -565,123 +569,134 @@ dev/ath/ath_hal/ar5211/ar5211_reset.c optional ath_hal | ath_ar5211 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5211/ar5211_xmit.c optional ath_hal | ath_ar5211 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+# ar5212
dev/ath/ath_hal/ar5212/ar5212_ani.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_attach.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_beacon.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_eeprom.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_gpio.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_interrupts.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_keycache.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_misc.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_phy.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_power.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_recv.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_reset.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_rfgain.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5212/ar5212_xmit.c \
- optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 \
- compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
-dev/ath/ath_hal/ar5212/ar2316.c optional ath_rf2316 \
- compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
-dev/ath/ath_hal/ar5212/ar2317.c optional ath_rf2317 \
- compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
-dev/ath/ath_hal/ar5212/ar2413.c optional ath_hal | ath_rf2413 \
- compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
-dev/ath/ath_hal/ar5212/ar2425.c optional ath_hal | ath_rf2425 | ath_rf2417 \
- compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
-dev/ath/ath_hal/ar5212/ar5111.c optional ath_hal | ath_rf5111 \
- compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
-dev/ath/ath_hal/ar5212/ar5112.c optional ath_hal | ath_rf5112 \
- compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
-dev/ath/ath_hal/ar5212/ar5413.c optional ath_hal | ath_rf5413 \
- compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
-dev/ath/ath_hal/ar5416/ar2133.c optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+# ar5416 (depends on ar5212)
dev/ath/ath_hal/ar5416/ar5416_ani.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_attach.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_beacon.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_cal.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_cal_iq.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_cal_adcgain.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_cal_adcdc.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_eeprom.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_gpio.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_interrupts.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_keycache.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_misc.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_phy.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_power.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_recv.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_reset.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
dev/ath/ath_hal/ar5416/ar5416_xmit.c \
- optional ath_hal | ath_ar5416 | ath_ar9160 \
+ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+# ar9160 (depends on ar5416)
dev/ath/ath_hal/ar5416/ar9160_attach.c optional ath_hal | ath_ar9160 \
compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+# ar9280 (depends on ar5416)
+dev/ath/ath_hal/ar5416/ar9280_attach.c optional ath_hal | ath_ar9280 \
+ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+# rf backends
+dev/ath/ath_hal/ar5212/ar2316.c optional ath_rf2316 \
+ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+dev/ath/ath_hal/ar5212/ar2317.c optional ath_rf2317 \
+ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+dev/ath/ath_hal/ar5212/ar2413.c optional ath_hal | ath_rf2413 \
+ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+dev/ath/ath_hal/ar5212/ar2425.c optional ath_hal | ath_rf2425 | ath_rf2417 \
+ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+dev/ath/ath_hal/ar5212/ar5111.c optional ath_hal | ath_rf5111 \
+ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+dev/ath/ath_hal/ar5212/ar5112.c optional ath_hal | ath_rf5112 \
+ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+dev/ath/ath_hal/ar5212/ar5413.c optional ath_hal | ath_rf5413 \
+ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+dev/ath/ath_hal/ar5416/ar2133.c optional ath_hal | ath_ar5416 | ath_ar9160 \
+ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+dev/ath/ath_hal/ar5416/ar9280.c optional ath_hal | ath_ar9280 \
+ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal"
+# ath rate control algorithms
dev/ath/ath_rate/amrr/amrr.c optional ath_rate_amrr \
compile-with "${NORMAL_C} -I$S/dev/ath"
dev/ath/ath_rate/onoe/onoe.c optional ath_rate_onoe \
compile-with "${NORMAL_C} -I$S/dev/ath"
dev/ath/ath_rate/sample/sample.c optional ath_rate_sample \
compile-with "${NORMAL_C} -I$S/dev/ath"
+#
dev/bce/if_bce.c optional bce
dev/bfe/if_bfe.c optional bfe
dev/bge/if_bge.c optional bge
@@ -1058,6 +1073,8 @@ dev/ixgbe/ixgbe_common.c optional ixgbe \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/ixgbe/ixgbe_82598.c optional ixgbe \
compile-with "${NORMAL_C} -I$S/dev/ixgbe"
+dev/ixgbe/ixgbe_82599.c optional ixgbe \
+ compile-with "${NORMAL_C} -I$S/dev/ixgbe"
dev/jme/if_jme.c optional jme pci
dev/joy/joy.c optional joy
dev/joy/joy_isa.c optional joy isa
@@ -1088,6 +1105,7 @@ dev/mfi/mfi_cam.c optional mfip scbus
dev/mii/acphy.c optional miibus | acphy
dev/mii/amphy.c optional miibus | amphy
dev/mii/atphy.c optional miibus | atphy
+dev/mii/axphy.c optional miibus | axphy
dev/mii/bmtphy.c optional miibus | bmtphy
dev/mii/brgphy.c optional miibus | brgphy
dev/mii/ciphy.c optional miibus | ciphy
@@ -1291,7 +1309,6 @@ dev/random/probe.c optional random
dev/random/randomdev.c optional random
dev/random/randomdev_soft.c optional random
dev/random/yarrow.c optional random
-dev/ray/if_ray.c optional ray pccard
dev/rc/rc.c optional rc
dev/re/if_re.c optional re
dev/rndtest/rndtest.c optional rndtest
@@ -1409,8 +1426,6 @@ dev/sound/midi/synth_if.m optional sound
dev/spibus/spibus.c optional spibus \
dependency "spibus_if.h"
dev/spibus/spibus_if.m optional spibus
-dev/sr/if_sr.c optional sr
-dev/sr/if_sr_pci.c optional sr pci
dev/ste/if_ste.c optional ste pci
dev/stg/tmc18c30.c optional stg
dev/stg/tmc18c30_isa.c optional stg isa
@@ -1487,15 +1502,6 @@ legacy/dev/usb/ehci_ddb.c optional oehci
legacy/dev/usb/ehci_pci.c optional oehci pci
legacy/dev/usb/hid.c optional ousb
legacy/dev/usb/if_aue.c optional oaue
-legacy/dev/usb/if_axe.c optional oaxe
-legacy/dev/usb/if_cdce.c optional ocdce
-legacy/dev/usb/if_cue.c optional ocue
-legacy/dev/usb/if_kue.c optional okue
-legacy/dev/usb/if_ural.c optional oural
-legacy/dev/usb/if_rue.c optional orue
-legacy/dev/usb/if_rum.c optional orum
-legacy/dev/usb/if_udav.c optional oudav
-legacy/dev/usb/if_zyd.c optional ozyd
legacy/dev/usb/ohci.c optional oohci
legacy/dev/usb/ohci_pci.c optional oohci pci
legacy/dev/usb/sl811hs.c optional oslhci
@@ -1581,7 +1587,6 @@ dev/usb/usb_msctest.c optional usb
dev/usb/usb_parse.c optional usb
dev/usb/usb_process.c optional usb
dev/usb/usb_request.c optional usb
-dev/usb/usb_sw_transfer.c optional usb
dev/usb/usb_transfer.c optional usb
dev/usb/usb_util.c optional usb
#
@@ -1653,10 +1658,6 @@ dev/usb/template/usb_template_cdce.c optional usb_template
dev/usb/template/usb_template_msc.c optional usb_template
dev/usb/template/usb_template_mtp.c optional usb_template
#
-# USB image drivers
-#
-dev/usb/image/uscanner.c optional uscanner
-#
# USB END
#
dev/utopia/idtphy.c optional utopia
@@ -2145,7 +2146,6 @@ net/bpf_jitter.c optional bpf_jitter
net/bpf_filter.c optional bpf | netgraph_bpf
net/bpf_zerocopy.c optional bpf
net/bridgestp.c optional bridge | if_bridge
-net/bsd_comp.c optional ppp_bsdcomp
net/ieee8023ad_lacp.c optional lagg
net/if.c standard
net/if_arcsubr.c optional arcnet
@@ -2169,8 +2169,6 @@ net/if_loop.c optional loop
net/if_llatbl.c standard
net/if_media.c standard
net/if_mib.c standard
-net/if_ppp.c optional ppp
-net/if_sl.c optional sl
net/if_spppfr.c optional sppp | netgraph_sppp
net/if_spppsubr.c optional sppp | netgraph_sppp
net/if_stf.c optional stf
@@ -2180,8 +2178,6 @@ net/if_vlan.c optional vlan
net/mppcc.c optional netgraph_mppc_compression
net/mppcd.c optional netgraph_mppc_compression
net/netisr.c standard
-net/ppp_deflate.c optional ppp_deflate
-net/ppp_tty.c optional ppp
net/pfil.c optional ether | inet
net/radix.c standard
net/radix_mpath.c standard
@@ -2189,20 +2185,20 @@ net/raw_cb.c standard
net/raw_usrreq.c standard
net/route.c standard
net/rtsock.c standard
-net/slcompress.c optional netgraph_vjc | ppp | sl | sppp | \
+net/slcompress.c optional netgraph_vjc | sppp | \
netgraph_sppp
net/zlib.c optional crypto | geom_uzip | ipsec | \
- mxge | ppp_deflate | netgraph_deflate | \
+ mxge | netgraph_deflate | \
ddb_ctf
net80211/ieee80211.c optional wlan
-net80211/ieee80211_acl.c optional wlan_acl
+net80211/ieee80211_acl.c optional wlan wlan_acl
net80211/ieee80211_adhoc.c optional wlan
-net80211/ieee80211_amrr.c optional wlan_amrr
+net80211/ieee80211_amrr.c optional wlan wlan_amrr
net80211/ieee80211_crypto.c optional wlan
-net80211/ieee80211_crypto_ccmp.c optional wlan_ccmp
+net80211/ieee80211_crypto_ccmp.c optional wlan wlan_ccmp
net80211/ieee80211_crypto_none.c optional wlan
-net80211/ieee80211_crypto_tkip.c optional wlan_tkip
-net80211/ieee80211_crypto_wep.c optional wlan_wep
+net80211/ieee80211_crypto_tkip.c optional wlan wlan_tkip
+net80211/ieee80211_crypto_wep.c optional wlan wlan_wep
net80211/ieee80211_ddb.c optional wlan ddb
net80211/ieee80211_dfs.c optional wlan
net80211/ieee80211_freebsd.c optional wlan
@@ -2217,13 +2213,14 @@ net80211/ieee80211_phy.c optional wlan
net80211/ieee80211_power.c optional wlan
net80211/ieee80211_proto.c optional wlan
net80211/ieee80211_regdomain.c optional wlan
-net80211/ieee80211_rssadapt.c optional wlan_rssadapt
+net80211/ieee80211_rssadapt.c optional wlan wlan_rssadapt
net80211/ieee80211_scan.c optional wlan
net80211/ieee80211_scan_sta.c optional wlan
net80211/ieee80211_sta.c optional wlan
-net80211/ieee80211_tdma.c optional wlan
+net80211/ieee80211_superg.c optional wlan ieee80211_support_superg
+net80211/ieee80211_tdma.c optional wlan ieee80211_support_tdma
net80211/ieee80211_wds.c optional wlan
-net80211/ieee80211_xauth.c optional wlan_xauth
+net80211/ieee80211_xauth.c optional wlan wlan_xauth
netatalk/aarp.c optional netatalk
netatalk/at_control.c optional netatalk
netatalk/at_proto.c optional netatalk
@@ -2472,6 +2469,7 @@ nfsserver/nfs_srvsock.c optional nfsserver
nfsserver/nfs_srvcache.c optional nfsserver
nfsserver/nfs_srvsubs.c optional nfsserver
nfsserver/nfs_syscalls.c optional nfsserver
+nfs/nfs_nfssvc.c optional nfsserver
nlm/nlm_advlock.c optional nfslockd nfsclient
nlm/nlm_prot_clnt.c optional nfslockd
nlm/nlm_prot_impl.c optional nfslockd
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 97f5ee5..56e17d1 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -69,6 +69,19 @@ hptrr_lib.o optional hptrr \
#
amd64/acpica/OsdEnvironment.c optional acpi
amd64/acpica/acpi_machdep.c optional acpi
+amd64/acpica/acpi_switch.S optional acpi
+acpi_wakecode.h optional acpi \
+ dependency "$S/amd64/acpica/acpi_wakecode.S assym.s" \
+ compile-with "${MAKE} -f $S/amd64/acpica/Makefile ${.TARGET} MAKESRCPATH=$S/amd64/acpica" \
+ no-obj no-implicit-rule before-depend \
+ clean "acpi_wakecode.h acpi_wakecode.o acpi_wakecode.bin"
+#
+acpi_wakedata.h optional acpi \
+ dependency "$S/amd64/acpica/acpi_wakecode.S assym.s" \
+ compile-with "${MAKE} -f $S/amd64/acpica/Makefile ${.TARGET} MAKESRCPATH=$S/amd64/acpica" \
+ no-obj no-implicit-rule before-depend \
+ clean "acpi_wakedata.h acpi_wakecode.o acpi_wakecode.bin"
+#
amd64/acpica/acpi_wakeup.c optional acpi
amd64/acpica/madt.c optional acpi
amd64/amd64/amd64_mem.c optional mem
@@ -136,6 +149,7 @@ dev/agp/agp_amd64.c optional agp
dev/agp/agp_i810.c optional agp
dev/agp/agp_intel.c optional agp
dev/agp/agp_via.c optional agp
+dev/amdtemp/amdtemp.c optional amdtemp
dev/arcmsr/arcmsr.c optional arcmsr pci
dev/asmc/asmc.c optional asmc isa
dev/atkbdc/atkbd.c optional atkbd atkbdc
@@ -169,6 +183,7 @@ dev/ipmi/ipmi_smbus.c optional ipmi smbus
dev/ipmi/ipmi_smbios.c optional ipmi
dev/ipmi/ipmi_ssif.c optional ipmi smbus
dev/ipmi/ipmi_pci.c optional ipmi pci
+dev/ipmi/ipmi_linux.c optional ipmi compat_linux32
dev/fdc/fdc.c optional fdc
dev/fdc/fdc_acpi.c optional fdc
dev/fdc/fdc_isa.c optional fdc isa
@@ -187,7 +202,6 @@ dev/hwpmc/hwpmc_core.c optional hwpmc
dev/hwpmc/hwpmc_piv.c optional hwpmc
dev/hwpmc/hwpmc_tsc.c optional hwpmc
dev/hwpmc/hwpmc_x86.c optional hwpmc
-dev/k8temp/k8temp.c optional k8temp
dev/kbd/kbd.c optional atkbd | sc | ukbd | usb2_input_kbd
dev/mem/memutil.c optional mem
dev/nfe/if_nfe.c optional nfe pci
@@ -218,6 +232,7 @@ amd64/ia32/ia32_reg.c optional compat_ia32
amd64/ia32/ia32_signal.c optional compat_ia32
amd64/ia32/ia32_sigtramp.S optional compat_ia32
amd64/ia32/ia32_syscall.c optional compat_ia32
+amd64/ia32/ia32_misc.c optional compat_ia32
compat/freebsd32/freebsd32_ioctl.c optional compat_ia32
compat/freebsd32/freebsd32_misc.c optional compat_ia32
compat/freebsd32/freebsd32_syscalls.c optional compat_ia32
@@ -269,6 +284,7 @@ i386/bios/smbios.c optional smbios
i386/bios/vpd.c optional vpd
i386/cpufreq/powernow.c optional cpufreq
i386/cpufreq/est.c optional cpufreq
+i386/cpufreq/hwpstate.c optional cpufreq
i386/cpufreq/p4tcc.c optional cpufreq
#
libkern/memmove.c standard
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 069e3b9..13f0417 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -128,10 +128,8 @@ dev/agp/agp_nvidia.c optional agp
dev/agp/agp_sis.c optional agp
dev/agp/agp_via.c optional agp
dev/aic/aic_isa.c optional aic isa
+dev/amdtemp/amdtemp.c optional amdtemp
dev/arcmsr/arcmsr.c optional arcmsr pci
-dev/ar/if_ar.c optional ar
-dev/ar/if_ar_isa.c optional ar isa
-dev/ar/if_ar_pci.c optional ar pci
dev/asmc/asmc.c optional asmc isa
dev/atkbdc/atkbd.c optional atkbd atkbdc
dev/atkbdc/atkbd_atkbdc.c optional atkbd atkbdc
@@ -198,7 +196,7 @@ dev/ipmi/ipmi_smbus.c optional ipmi smbus
dev/ipmi/ipmi_smbios.c optional ipmi
dev/ipmi/ipmi_ssif.c optional ipmi smbus
dev/ipmi/ipmi_pci.c optional ipmi pci
-dev/k8temp/k8temp.c optional k8temp
+dev/ipmi/ipmi_linux.c optional ipmi compat_linux
dev/kbd/kbd.c optional atkbd | sc | ukbd | usb2_input_kbd
dev/le/if_le_isa.c optional le isa
dev/mem/memutil.c optional mem
@@ -218,7 +216,6 @@ dev/sio/sio_pccard.c optional sio pccard
dev/sio/sio_pci.c optional sio pci
dev/sio/sio_puc.c optional sio puc
dev/speaker/spkr.c optional speaker
-dev/sr/if_sr_isa.c optional sr isa
dev/syscons/apm/apm_saver.c optional apm_saver apm
dev/syscons/scterm-teken.c optional sc
dev/syscons/scvesactl.c optional sc vga vesa
@@ -245,6 +242,7 @@ i386/bios/smapi_bios.S optional smapi
i386/bios/smbios.c optional smbios
i386/bios/vpd.c optional vpd
i386/cpufreq/est.c optional cpufreq
+i386/cpufreq/hwpstate.c optional cpufreq
i386/cpufreq/p4tcc.c optional cpufreq
i386/cpufreq/powernow.c optional cpufreq
i386/cpufreq/smist.c optional cpufreq
diff --git a/sys/conf/files.ia64 b/sys/conf/files.ia64
index 62e36a5..706d64e 100644
--- a/sys/conf/files.ia64
+++ b/sys/conf/files.ia64
@@ -70,6 +70,7 @@ ia64/acpica/madt.c optional acpi
ia64/disasm/disasm_decode.c standard
ia64/disasm/disasm_extract.c standard
ia64/disasm/disasm_format.c standard
+ia64/ia32/ia32_misc.c optional compat_ia32
ia64/ia32/ia32_reg.c optional compat_ia32
ia64/ia32/ia32_signal.c optional compat_ia32
ia64/ia32/ia32_trap.c optional compat_ia32
diff --git a/sys/conf/files.mips b/sys/conf/files.mips
index bbedd96..1e233d7 100644
--- a/sys/conf/files.mips
+++ b/sys/conf/files.mips
@@ -96,7 +96,3 @@ dev/cfe/cfe_api.c optional cfe
dev/cfe/cfe_console.c optional cfe_console
#dev/cfe/cfe_resource.c optional cfe # not yet needed
-dev/siba/siba.c optional siba
-dev/siba/siba_pcib.c optional siba pci
-dev/siba/siba_cc.c optional siba
-#mips/sentry5/siba_mips.c optional siba # not yet
diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98
index f8c6f0a..a6b62b1 100644
--- a/sys/conf/files.pc98
+++ b/sys/conf/files.pc98
@@ -85,8 +85,6 @@ dev/agp/agp_nvidia.c optional agp
dev/agp/agp_sis.c optional agp
dev/agp/agp_via.c optional agp
dev/aic/aic_cbus.c optional aic isa
-dev/ar/if_ar.c optional ar
-dev/ar/if_ar_pci.c optional ar pci
dev/ce/ceddk.c optional ce
dev/ce/if_ce.c optional ce
dev/ce/tau32-ddk.c optional ce
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc
index 4c40219..00ac74a 100644
--- a/sys/conf/files.powerpc
+++ b/sys/conf/files.powerpc
@@ -76,13 +76,13 @@ powerpc/aim/interrupt.c optional aim
powerpc/aim/locore.S optional aim no-obj
powerpc/aim/machdep.c optional aim
powerpc/aim/mmu_oea.c optional aim
+powerpc/aim/mmu_oea64.c optional aim
powerpc/aim/mp_cpudep.c optional aim smp
powerpc/aim/nexus.c optional aim
powerpc/aim/ofw_machdep.c optional aim
powerpc/aim/ofwmagic.S optional aim
powerpc/aim/swtch.S optional aim
powerpc/aim/trap.c optional aim
-powerpc/aim/uio_machdep.c optional aim
powerpc/aim/uma_machdep.c optional aim
powerpc/aim/vm_machdep.c optional aim
powerpc/booke/clock.c optional e500
@@ -93,7 +93,6 @@ powerpc/booke/machdep.c optional e500
powerpc/booke/pmap.c optional e500
powerpc/booke/swtch.S optional e500
powerpc/booke/trap.c optional e500
-powerpc/booke/uio_machdep.c optional e500
powerpc/booke/vm_machdep.c optional e500
powerpc/fpu/fpu_add.c optional fpu_emu
powerpc/fpu/fpu_compare.c optional fpu_emu
@@ -112,10 +111,11 @@ powerpc/mpc85xx/opic.c optional mpc85xx
powerpc/mpc85xx/pci_ocp.c optional pci mpc85xx
powerpc/ofw/ofw_pcibus.c optional pci aim
powerpc/ofw/ofw_pcib_pci.c optional pci aim
+powerpc/ofw/ofw_real.c optional aim
powerpc/ofw/ofw_syscons.c optional sc aim
-powerpc/powermac/ata_kauai.c optional powermac ata
-powerpc/powermac/ata_macio.c optional powermac ata
-powerpc/powermac/ata_dbdma.c optional powermac ata
+powerpc/powermac/ata_kauai.c optional powermac ata | powermac atamacio
+powerpc/powermac/ata_macio.c optional powermac ata | powermac atamacio
+powerpc/powermac/ata_dbdma.c optional powermac ata | powermac atamacio
powerpc/powermac/dbdma.c optional powermac pci
powerpc/powermac/grackle.c optional powermac pci
powerpc/powermac/hrowpic.c optional powermac pci
@@ -127,6 +127,7 @@ powerpc/powermac/uninorth.c optional powermac pci
powerpc/powermac/cuda.c optional powermac cuda
powerpc/powermac/pmu.c optional powermac pmu
powerpc/powermac/macgpio.c optional powermac pci
+powerpc/powermac/cpcht.c optional powermac pci
powerpc/powerpc/altivec.c optional aim
powerpc/powerpc/atomic.S standard
powerpc/powerpc/autoconf.c standard
@@ -139,6 +140,7 @@ powerpc/powerpc/db_disasm.c optional ddb
powerpc/powerpc/db_hwwatch.c optional ddb
powerpc/powerpc/db_interface.c optional ddb
powerpc/powerpc/db_trace.c optional ddb
+powerpc/powerpc/dump_machdep.c standard
powerpc/powerpc/elf_machdep.c standard
powerpc/powerpc/fpu.c optional aim
powerpc/powerpc/fuswintr.c standard
@@ -158,6 +160,7 @@ powerpc/powerpc/stack_machdep.c optional ddb | stack
powerpc/powerpc/suswintr.c standard
powerpc/powerpc/syncicache.c standard
powerpc/powerpc/sys_machdep.c standard
+powerpc/powerpc/uio_machdep.c standard
powerpc/psim/iobus.c optional psim
powerpc/psim/ata_iobus.c optional ata psim
powerpc/psim/openpic_iobus.c optional psim
diff --git a/sys/conf/ldscript.mips b/sys/conf/ldscript.mips
index 3e55dba..ca4a70b 100644
--- a/sys/conf/ldscript.mips
+++ b/sys/conf/ldscript.mips
@@ -43,7 +43,7 @@ PROVIDE (_DYNAMIC = 0);
SECTIONS
{
/* Read-only sections, merged into text segment: */
- . = KERNLOADADDR + SIZEOF_HEADERS;
+ . = 0x80100000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index f141a8c..134e46e 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -100,7 +100,13 @@ for dir in /bin /usr/bin /usr/local/bin; do
done
if [ -n "$svnversion" -a -d "${SRCDIR}/.svn" ] ; then
- svn=" r`cd $SRCDIR && $svnversion`"
+ # If we are called from the kernel build, limit
+ # the scope of svnversion to sys/ .
+ if [ -e "${SRCDIR}/sys/conf/newvers.sh" ] ; then
+ svn=" r`cd $SRCDIR/sys && $svnversion`"
+ else
+ svn=" r`cd $SRCDIR && $svnversion`"
+ fi
else
svn=""
fi
diff --git a/sys/conf/options b/sys/conf/options
index bf39e9a..dc5707e 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -407,9 +407,6 @@ MROUTING opt_mrouting.h
NCP
NETATALK opt_atalk.h
NFSLOCKD
-PPP_BSDCOMP opt_ppp.h
-PPP_DEFLATE opt_ppp.h
-PPP_FILTER opt_ppp.h
RADIX_MPATH opt_mpath.h
ROUTETABLES opt_route.h
COMPAT_ROUTE_FLAGS opt_route.h
@@ -748,7 +745,6 @@ ATH_TXBUF opt_ath.h
ATH_RXBUF opt_ath.h
ATH_DIAGAPI opt_ath.h
ATH_TX99_DIAG opt_ath.h
-ATH_SUPPORT_TDMA opt_ath.h
# options for the Atheros hal
AH_SUPPORT_AR5416 opt_ah.h
@@ -792,6 +788,7 @@ INTR_FILTER
IEEE80211_DEBUG opt_wlan.h
IEEE80211_DEBUG_REFCNT opt_wlan.h
IEEE80211_AMPDU_AGE opt_wlan.h
+IEEE80211_SUPPORT_SUPERG opt_wlan.h
IEEE80211_SUPPORT_TDMA opt_wlan.h
# 802.11 TDMA support
diff --git a/sys/conf/options.mips b/sys/conf/options.mips
index 7c38616..42e0263 100644
--- a/sys/conf/options.mips
+++ b/sys/conf/options.mips
@@ -45,8 +45,8 @@ YAMON opt_global.h
CFE opt_global.h
CFE_CONSOLE opt_global.h
-KERNLOADADDR opt_global.h
-TRAMPLOADADDR opt_global.h
+KERNPHYSADDR opt_global.h
+KERNVIRTADDR opt_global.h
PHYSADDR opt_global.h
SOFTFLOAT opt_global.h
diff --git a/sys/contrib/dev/uath/ar5523.bin.uu b/sys/contrib/dev/uath/ar5523.bin.uu
new file mode 100644
index 0000000..6fa430d
--- /dev/null
+++ b/sys/contrib/dev/uath/ar5523.bin.uu
@@ -0,0 +1,3359 @@
+/*-
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the following conditions are met:
+ * 1. The materials contained herein are unmodified and are used
+ * unmodified.
+ * 2. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following NO
+ * ''WARRANTY'' disclaimer below (''Disclaimer''), without
+ * modification.
+ * 3. Redistributions in binary form must reproduce at minimum a
+ * disclaimer similar to the Disclaimer below and any redistribution
+ * must be conditioned upon including a substantially similar
+ * Disclaimer requirement for further binary redistribution.
+ * 4. Neither the names of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote
+ * product derived from this software without specific prior written
+ * permission.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT,
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
+ * FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+begin 755 ar5523.bin
+M0!I@`#P;``@#>M@D$V``#0`````#X`@A/!N``"=[!@@\'X``)_\`-`-_V"($
+M$0`!``````-_V"``(/@A`V``"``````\&P`0`WK8)!-@``T``````^`((3P;
+M@``G>P8`/!^``"?_`'0#?]@B!!$``0`````#?]@@`"#X(0-@``@`````)!H`
+M`D":@``#X`@A/`*``"1"!!`\'X``)_\`K`!?$"($$0`!``````!?$"``(/@A
+M`$``"```````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````0!IH```````S6@!_/!N``"=[`@`#
+M>M@@CWL```-@``@``````````````````````````````````````````$`:
+M:```````,UH`?SP;@``G>P(``WK8((][```#8``(````````````````````
+M```````````````````````D&@"`/!N``"=[`@"/>P"``V``"```````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M``````!`@&@``````#P"$``T0O\`0()@`````````````````"0"``)`@H``
+M`````````````````^`((3P:@``G6@MT/!^``"?_!&0#7]`B!!$``0`````#
+M7]`@`"#X(0-`^`D``````^`((3P:@`(G6D:X/!^``"?_!)0#7]`B!!$``0``
+M```#7]`@`"#X(0-`^`D`````0`)@```````\`___-&,`_P!#$"1`@F``````
+M````````````/`2``B2$5_``@.@A/`$?_S0A__\#H>@D/`&@``.AZ"5`!(``
+M`````````````````^`((3P:@`(G6J6$/!^``"?_!1@#7]`B!!$``0`````#
+M7]`@`"#X(3P!'_\T(?__`T'0)#P!H``#0=`E`T#X"0`````\'(`#)YS&L#P$
+M@`(DA%?P`(#H(3P(@``\"8``)2D!P#P+@``E:P'DC2(``"$I``2M`@``(0@`
+M!!4K__L`````-`0`$#P%@``DI09T/`:``"3&`@"LQ0``(,8`!""$__\4@/_\
+M`````#P$@``DA`(`/`6``"2E!X"LA0``/`6``"2E"RBLA0`D/`6``"2E!G2L
+MA0"`K(4`A*R%`(@,``*L``````P`:5H`````#`!J>P`````,`&D:``````@`
+M;<\\'P``$````0````!`&F``/!O__S=[__`#6]`D0)I@````````````````
+M`$`:\`````````````````!`FG``````````````````0!I@`#P;_[\W>___
+M`UO0)$":8``D&@"(/!N``"=[`@"/>P"(`V``"``````#H-@A([W^L*^Z`(BO
+MH```KZ$`!*^B``BOHP`,KZ0`$*^E`!2OI@`8KZ<`'*^H`""OJ0`DKZH`**^K
+M`"ROK``PKZT`-*^N`#BOKP`\K[``0*^Q`$2OL@!(K[,`3*^T`%"OM0!4K[8`
+M6*^W`%RON`!@K[D`9*^\`'"OO@!XK[\`?```(!```"@2KZ0`@*^E`(2ONP!T
+M0`AH`$`)8`!`"C@`0`M``$`,&`!`#7@`0`YP`*^H`)BOJ0",KZH`E*^K`)RO
+MK`"DKZT`H*^N`)`\'(`#)YS&L`.@@"$CO?_@0!I@`#P;__\W>__P`UO0)$":
+M8``````````````````,`&D.`@`@(0@``DT``````Z#8(2.]_K"ON@"(KZ``
+M`*^A``2OH@`(KZ,`#*^D`!"OI0`4KZ8`&*^G`!ROJ``@KZD`)*^J`"BOJP`L
+MKZP`,*^M`#2OK@`XKZ\`/*^P`$"OL0!$K[(`2*^S`$ROM`!0K[4`5*^V`%BO
+MMP!<K[@`8*^Y`&2OO`!PK[X`>*^_`'P``"`0```H$J^D`("OI0"$K[L`=$`)
+M8`!`"C@`0`MP`*^I`(ROJ@"4KZL`D#P<@`,GG,:P/`*``B1"1E2,1```((0`
+M`:Q$```#H(`A)[W_X$`#8```````0`)H````````0Q`D``(2@C!"`'\\`X``
+M)&,*/`!#$""`4@```D"((20!``02(0`#`````!````P`````/!&@P#8Q`!".
+M,0``,C$`?SP#@``D8PH\`'$8((!Q```F,0`&`B"0(0``````$8B`0!I@`#P;
+M__\W>__P`UO0)$":8``````````````````\"H`")4HQ>`%14""-2@``/`6`
+M`B2E,?``L2@@C*4```)`("$!0/@)``````!`D"$\!8`")*4R:`"Q*"",I0``
+M`@`P(0P`=7,`0"`A`D`0(2.]`"!``F``/`/__S1C__X`0Q`D0()@````````
+M`````````(^H`)2/J0"`CZH`A$"(.``!(``1`4``$X^A``2/H@`(CZ,`#(^D
+M`!"/I0`4CZ8`&(^G`!R/J``@CZD`)(^J`"B/JP`LCZP`,(^M`#2/K@`XCZ\`
+M/(^P`$"/L0!$C[(`2(^S`$R/M`!0C[4`5(^V`%B/MP!<C[@`8(^Y`&2/O`!P
+MC[X`>(^_`'R/NP",-!K_``-:T"<#>M@D0!I@````````````,UK_``-ZV"6/
+MN@"0C[T`=#=[``)`FV``````````````````0)IP````````````````````
+M``]"```8`````````0`"``$``P`!``(``0`$``$``@`!``,``0`"``$`!0`!
+M``(``0`#``$``@`!``0``0`"``$``P`!``(``0`#X``(``````.@&"$`H.@A
+M([W_X*^C``BOOP`0`(#X"0````"/OP`0C[T`"`/@``@`````/`2``B2$1Z@\
+M!8`#)*6B'#"&``,4P``2``````"D.",`!SE"``<Y0`"'."&L@```K(``!*R`
+M``BL@``,K(``$*R``!2L@``8K(``'"2$`"`4Y/_V`````!"D``4`````H(``
+M`"2$``$4A?_]``````/@``@`````0!IP`$`;:``'8@`!(UH`!(];```\&@`'
+M-UH`#1=;``@`````-!H`.#P;@``G>P(``WK8((][```#8``(`````#0:`"0(
+M``&=`````#P)H,`U*0"0C24``"0$``0`I"@EK24``#P)H+,U*0`<C24``#"E
+M``$0H``,`````#P)H+,U*0`<C24``#P$__PTA/__`*0H)"0$````I"@EK24`
+M`!````D`````/`F@LS4I`!R-)0``)`3`_P"D*"0D!`L``*0H):TE```#X``(
+M`````".]_UBOL`!`K[$`1*^R`$BOLP!,K[0`4*^U`%2OM@!8K[<`7*^^`'BO
+MOP!\K[\`D".H`*BOJ`!T0`E@`*^I`(RLO0``C)T``(^D`!"/L`!`C[$`1(^R
+M`$B/LP!,C[0`4(^U`%2/M@!8C[<`7(^^`'B/OP!\CZ8`C(^]`'1``F``)`,`
+M!P##,"0`8!@G`$,0)`!&$"4#X``(0()@``````"LGP`LK)X`**R<`"2LEP`@
+MK)8`'*R5`!BLE``4K),`$*R2``RLD0`(K)``!*R=```#X``()`(```````",
+MGP`LC)X`*(R<`"2,EP`@C)8`'(R5`!B,E``4C),`$(R2``R,D0`(C)``!(R=
+M```#X``(`*`0(0`````GO?_PK[\```P``TL``$`AC[\```/@``@GO0`0)[W_
+M\*^R``BOLP`,K[$`!*^P````P$@A`0"0(0#@6"$`H'`A%,`!``"`4"$`AQ`K
+M$$``9#0"__\`1Q`K%$``60#@*"$D`@`(+.,!``!`,"$``S`+/`.``@#%$`8D
+M8Q9\`$,0(9!$```D`@`@`(8@(0!$.",0X``(``LT`@!'$",`3A`&`.H8!`!B
+M4"4`ZU@$`.YP!``+-`(!1@`;,6K__P`.)`)0P``!```!S0``$!(``!@0``,<
+M``!D&"4``"@2``````````!P2D@"`&D0*U!```L`:1@C`&L8(0!K$"L40``&
+M)*7__P!I$"M00``$`&D8(R2E__\`:Q@A`&D8(P!F`!M0P``!```!S3'$__\`
+M`!`2```8$``#'```9!@E```P$@``````````<$I(`@!I$"L00``+``44``!K
+M&"$`:Q`K%$``!B3&__\`:1`K$$``!``%%```:Q@A),;__P`%%```1C`E`&EP
+M(P``F"$20``$`.[(!@``P"&N6```KED`!`)@$"&/L@`(C[,`#(^Q``2/L```
+M`,`8(0/@``@GO0`0/`(`_S1"__\D`P`0`$<0*R0$`!@`8#`A$`#_I0"",`L4
+MX``*`$L0*R0"``$`1@`;4.```0```<T``%@2```````````T`O__`$L0*Q1`
+M`(8\`@#_)`(`""UC`0``0"@A``,H"SP#@`(`JQ`&)&,6?`!#$"&01```)`(`
+M(`"%("$`1#@C%.``.@!'>",!2U`C)!,``0`+9`(Q:/__`4P`&P`.+`)1@``!
+M```!S0``(!(``!@0``,<``!E&"4``&@2``````````!PB$@"`&D0*U!```L`
+M:1@C`&L8(0!K$"L40``&)(W__P!I$"M00``$`&D8(R6M__\`:Q@A`&D8(P!L
+M`!LQQ/__48```0```<T``!`2```8$``#'```9!@E``!0$@``````````<$A(
+M`@!I$"L00``+``T4``!K&"$`:Q`K%$``!B5*__\`:1`K$$``!``-%```:Q@A
+M)4K__P`-%```2C`E$`#_F`!I<",`ZU@$`>H@!@`+9`(`C``;,6C__P'N&`8`
+MZA`$`$-0)0`*+`)1@``!```!S0&`:"$`[G`$```P$@``(!``!"0``(48)0``
+M>!(``````````'#(2`(`:1`K$$``"@$`F"$`:Q@A`&L0*Q1```8DS___`&D0
+M*U!```0`:1@C)>___P!K&"$`:1@C`&T`&S%$__]1H``!```!S0``$!(``!@0
+M``,<``!D&"4``#`2``````````!P4T@"`&D0*Q!```L`#Q0``&L8(0!K$"L4
+M0``&),;__P!I$"L00``$``\4`"3&__\`:Q@A``\4``!&F"40`/^.`&E0(S1"
+M__\D`P`0`$L0*R0$`!@`8"@A$`#_>0""*`L`AA`K$$``!S0"__\``#`A``"8
+M(1$`_U$`H,@A$`#_30%`P"$`1A`K%$``?#P"`/\D`@`(+,,!``!`*"$``R@+
+M/`.``@"I$`8D8Q9\`$,0(9!$```D`@`@`(4@(0!$.",4X``1`$=X(P$J$"L4
+M0``%`<L@(P'+$"L40``'```P(0'+(",!Q!`K`4D8(P!B4",`@'`A)`8``1)`
+M_S```)@A$`#_W@'`R"$!ZQ`&`.D8!`!B2"4`"60"`>H@!@",`!LQ,___`>X0
+M!@#J&`0`8E`E``HL`E&```$```'-`.M8!```,!(``"`0``0D``"%&"4``$`2
+M``````````!PTV@"`&T0*Q!```H`[G`$`&D8(0!I$"L40``&),C__P!M$"M0
+M0``$`&T8(R4(__\`:1@A`&T8(P!L`!LQ1/__48```0```<T``!`2```8$``#
+M'```9"@E```P$@``````````<%-H`@"M$"L00``+``@4``"I*"$`J1`K%$``
+M!B3&__\`K1`K$$``!``(%``DQO__`*DH(0`(%```1C`E`,L`&0"M*",``&`0
+M````````````K!`K``!H$@``````````%$``$`&K(",1A0`,`<T0*Q)`_N(`
+M`)@A`<T8(P"L(",!PQ`K`()0(P'J*`0`XQ@&`*/()1``_M<`ZL`&$$#_]`&K
+M(",!I!`K`8D8(P!B8",`@&@A$`#_[B3&__\T0O__)`,`$`!&$"LD!``8`&`H
+M(1``_X,`@B@+)[W_X*^_`!`,``3L`Z!`(8^B``"/HP`$C[\`$`/@``@GO0`@
+M)[W_\*^R``BOLP`,K[$`!*^P````P$@A`0"0(0#@6"$`H'`A%,`!``"`4"$`
+MAQ`K$$``9#0"__\`1Q`K%$``60#@*"$D`@`(+.,!``!`,"$``S`+/`.``@#%
+M$`8D8Q9\`$,0(9!$```D`@`@`(8@(0!$.",0X``(``LT`@!'$",`3A`&`.H8
+M!`!B4"4`ZU@$`.YP!``+-`(!1@`;,6K__P`.)`)0P``!```!S0``$!(``!@0
+M``,<``!D&"4``"@2``````````!P2D@"`&D0*U!```L`:1@C`&L8(0!K$"L4
+M0``&)*7__P!I$"M00``$`&D8(R2E__\`:Q@A`&D8(P!F`!M0P``!```!S3'$
+M__\``!`2```8$``#'```9!@E```P$@``````````<$I(`@!I$"L00``+``44
+M``!K&"$`:Q`K%$``!B3&__\`:1`K$$``!``%%```:Q@A),;__P`%%```1C`E
+M`&EP(P``F"$20``$`.[(!@``P"&N6```KED`!`)@$"&/L@`(C[,`#(^Q``2/
+ML````,`8(0/@``@GO0`0/`(`_S1"__\D`P`0`$<0*R0$`!@`8#`A$`#_I0""
+M,`L4X``*`$L0*R0"``$`1@`;4.```0```<T``%@2```````````T`O__`$L0
+M*Q1``(8\`@#_)`(`""UC`0``0"@A``,H"SP#@`(`JQ`&)&,6?`!#$"&01```
+M)`(`(`"%("$`1#@C%.``.@!'>",!2U`C)!,``0`+9`(Q:/__`4P`&P`.+`)1
+M@``!```!S0``(!(``!@0``,<``!E&"4``&@2``````````!PB$@"`&D0*U!`
+M``L`:1@C`&L8(0!K$"L40``&)(W__P!I$"M00``$`&D8(R6M__\`:Q@A`&D8
+M(P!L`!LQQ/__48```0```<T``!`2```8$``#'```9!@E``!0$@``````````
+M<$A(`@!I$"L00``+``T4``!K&"$`:Q`K%$``!B5*__\`:1`K$$``!``-%```
+M:Q@A)4K__P`-%```2C`E$`#_F`!I<",`ZU@$`>H@!@`+9`(`C``;,6C__P'N
+M&`8`ZA`$`$-0)0`*+`)1@``!```!S0&`:"$`[G`$```P$@``(!``!"0``(48
+M)0``>!(``````````'#(2`(`:1`K$$``"@$`F"$`:Q@A`&L0*Q1```8DS___
+M`&D0*U!```0`:1@C)>___P!K&"$`:1@C`&T`&S%$__]1H``!```!S0``$!(`
+M`!@0``,<``!D&"4``#`2``````````!P4T@"`&D0*Q!```L`#Q0``&L8(0!K
+M$"L40``&),;__P!I$"L00``$``\4`"3&__\`:Q@A``\4``!&F"40`/^.`&E0
+M(S1"__\D`P`0`$L0*R0$`!@`8"@A$`#_>0""*`L`AA`K$$``!S0"__\``#`A
+M``"8(1$`_U$`H,@A$`#_30%`P"$`1A`K%$``?#P"`/\D`@`(+,,!``!`*"$`
+M`R@+/`.``@"I$`8D8Q9\`$,0(9!$```D`@`@`(4@(0!$.",4X``1`$=X(P$J
+M$"L40``%`<L@(P'+$"L40``'```P(0'+(",!Q!`K`4D8(P!B4",`@'`A)`8`
+M`1)`_S```)@A$`#_W@'`R"$!ZQ`&`.D8!`!B2"4`"60"`>H@!@",`!LQ,___
+M`>X0!@#J&`0`8E`E``HL`E&```$```'-`.M8!```,!(``"`0``0D``"%&"4`
+M`$`2``````````!PTV@"`&T0*Q!```H`[G`$`&D8(0!I$"L40``&),C__P!M
+M$"M00``$`&T8(R4(__\`:1@A`&T8(P!L`!LQ1/__48```0```<T``!`2```8
+M$``#'```9"@E```P$@``````````<%-H`@"M$"L00``+``@4``"I*"$`J1`K
+M%$``!B3&__\`K1`K$$``!``(%``DQO__`*DH(0`(%```1C`E`,L`&0"M*",`
+M`&`0````````````K!`K``!H$@``````````%$``$`&K(",1A0`,`<T0*Q)`
+M_N(``)@A`<T8(P"L(",!PQ`K`()0(P'J*`0`XQ@&`*/()1``_M<`ZL`&$$#_
+M]`&K(",!I!`K`8D8(P!B8",`@&@A$`#_[B3&__\T0O__)`,`$`!&$"LD!``8
+M`&`H(1``_X,`@B@+)[W_X#P$H)"OOP`0#``&C`.@*"&/OP`0`^``"">]`"`G
+MO?_0K[``$`"`@"$D!`!<K[0`(*^S`!ROL0`4K[\`)*^R`!@,`'I7`*"@(0!`
+MF"$00``*)!$``B0&`%P`0"`A#`!PJ@``*"$"`"`A#``=90.@*"$00``+`$"(
+M(5:```&ND0``C[\`)(^T`""/LP`<C[(`&(^Q`!2/L``0`^``"">]`#"/H@``
+M`$`@(0P`!L^N8@`$%$#_\0!`B"$,`!FN`F`@(11`_^T`0(@A#``2D`)@("$4
+M0/_I`$"((0P`&=D"8"`A`$"0(1!`_^0D$0`"C[````!`("$,`!G1)`4'(`!`
+MB"$D`@<@K@(;[`)`*"$"8"`A#``<@JYR```\`X`"K'-'J!``_]6N8@`()[W_
+M\*^P``"OOP`$#``4GP"`@"$"`"`A#``4K```*"$00``&)`,`%H^_``2/L```
+M`&`0(0/@``@GO0`0#``?*P(`("$`0!@A)@4;<`(`("$40/_U)`8``0P`-X4`
+M`````$`8(20%``$40/_O`@`@(0P`%*P`````)`,`%A``_^H``A@*K*0`!`/@
+M``BLX```)[W_H*^S`$P`H)@A```H(:^Q`$2OOP!0K[(`2*^P`$`,`!2L`("(
+M(11``!6OH@`PCB(7W!1``"T#H"`A#`!Z=0````"/I@`@CZ4`'#P$@`(DT,0`
+M`!`7P@("$"$``I!##`!P="2$"(@"("`A#``)M@)`*"&OH@`P$$``"P.@("$2
+M8``"CZ(`,*YB``"/OP!0C[,`3(^R`$B/L0!$C[``0`/@``@GO0!@#`!Z=0``
+M``"/H@`@`B`@(210Q``,``RQ`@`H(3P$@`(DA`BD`@`H(0)`,"$40/_JKZ(`
+M,`P`<'0`````)`(``:XB%]P"("`A#``'5R>E`#"/H@`P4$#_X*X@%^@0`/_>
+M`````">]_^"OL0`4K[``$*^_`!B,@Q?@)`(``0"@B"$`@(`A`Z`H(1!B``NO
+MH```$B``!JX`%^B/OP`8C[$`%(^P`!`#X``()[T`((^B```0`/_YKB(```P`
+M!Y4`````CZ(``!1`__("`"`A#`!1E``````"`"`A#``4K"0%``$0`/_K````
+M`">]_^"OL@`(`*"0(0``*"&OLP`,K[$`!*^P``"OOP`0#``4K`"`@"$D$P`!
+M`$"((1!```L"`"`A$D```JX`%^BN40``C[\`$(^S``R/L@`(C[$`!(^P```#
+MX``()[T`(*X`&QP,``A^KA,;)`P`"A@"`"`A#`!Q7``````D8P#(+&4`R(X$
+M&`@`11`A`$`P(20(```D"0#(#`!Q=`!@."$,`'%<`````"1C`,@L90#(C@08
+M0`!%$"$`0#`A)`@``"0)`,@,`'%T`&`X(8X"``0,`!T8C$0```(`("$,`"D\
+M/`6```P`!_8"`"`AKA,7X!``_]$`````)[W_\*^R``BOL0`$K[```*^_``R,
+M@A?@)!(``0"@B"$`@(`A$%(`"@``*"$2(``"KA(7Z*X@``"/OP`,C[(`"(^Q
+M``2/L````^``"">]`!`,`!2L`````#P%@``,`"EL`@`@(0P`<7N.!!@(#`!Q
+M>XX$&$`,``LT`@`@(0P`$7<"`"`A#``(E0(`("$D!0`!#``*2`(`("$,``@'
+M`@`@(8X"``0,`!T*C$0``*X`%^`0`/_>`````">]__"OL````*"`(:^Q``0`
+MP"@A`("((0(`("&OOP`,K[(`"`P`!S8`P)`A#`!1E`(`("$"("`A)`4`"```
+M,"$,`!$9)`<``59```&N0```C[\`#(^R``B/L0`$C[````/@``@GO0`0)[W_
+M\*^Q``2OL````("((0"@@"&OOP`(#``4;20%``$"("`A$@``"SP%``0,`"D\
+M``````(@("$,`!1M```H(8^_``B/L0`$C[````/@``@GO0`0#``I;#P%``00
+M`/_V`B`@(2>]__`D`@`!K((<S*R"',BOL``````H(0"`@"&OOP`$#`!K-"0$
+M`!&.!!S,#`!K-"0%``&/OP`$C[````/@``@GO0`0)[W_\*^P``"L@!S(`("`
+M(20%``&OOP`$#`!K-"0$`!&.!!S,#`!K-```*"&/OP`$C[````/@``@GO0`0
+M)[W_\*^P````H(`A)`4``:^_``ROL@`(K[$`!`"`D"$,`!1M`,"((28$`!`,
+M`&LT)`4``0(`("$,`&LT)`4``0(`("$,`&LE`B`H(0)`("$,`!1M```H(8^_
+M``R/L@`(C[$`!(^P```#X``()[T`$">]_]"OM0`4`*"H(20%``&OOP`@K[<`
+M'*^V`!BOM``0K[,`#`$`H"$`X)@AK[(`"*^Q``0`P)`A`("((:^P```,`!1M
+M/!:``CP0@`(FI``0/!>``@``*"&N$C.`KM,SA`P`:S2N]#.(`J`@(0P`:S0D
+M!0`!CB4``(X$,X`\`O_QC*-`$#1"__\`!"1``&(8)#P"``X`@B`D`&08):RC
+M0!".)0``CL0SA#P"_X^,HT`0-$+__P`$)0``8A@D/`(`<`""("0`9!@EK*-`
+M$(XE``".Y#.(/`+_?XRC0!`T0O__``0EP`!B&"0\`@"``((@)`!D&"6LHT`0
+M`B`@(0P`%&T``"@AC[\`((^W`!R/M@`8C[4`%(^T`!"/LP`,C[(`"(^Q``2/
+ML````^``"">]`#`GO?_PK[```"0&``0`@(`AK[\`!`P`-@X``"@A#`!1O28$
+M'8P00``'`@`@(0P`-;2,10`D#``UN`(`("$,`#7H`@`@(0P`<=`F!!K(C[\`
+M!(^P```#X``()[T`$">]__```"@A)`8``Z^P``"OOP`$#``V#@"`@"$,`''"
+M)@0:R`P`<+4`````#``U_0(`("$,`#6_`@`@(0P`<+H`````#``(VP(`("$D
+M`@`!K@(;)(^_``2/L````^``"">]`!",I0`H)`/_\#"B``\D0@`G`$,X)`"C
+M&"0`9Q`A`$,0*Q1```<`8#`AO'$``"1C`!``QQ`A`$,0*Q!`__L`````D*(`
+M`"0#`(`P0@#\4$,`!)2C`!0``"`A`^``"`"`$"&4@AQ>5&+__```("&4HP`2
+ME((<7%1B__@``"`AE((<6I2C`!`48O_S)`0``1``__(`````C((:_(Q#```#
+MX``(K(,:_(R"&ORLH@```^``"*R%&OPGO?_@)`(``:^P``"OOP`<K[8`&*^U
+M`!2OM``0K[,`#*^R``BOL0`$`("`(:R"&R0F%AV,#`!1O0+`("$`0(@A$$``
+MD0``("&,0P``C$(`)!!B`(Z/OP`<`@`@(0P`-L\"("@A`$"H(20"``T2H@"&
+M)`0``8XD`"B.`QKT)`7_\#""``\D0@`0EC0`0`!%,"0`A2@D`*80(0!T&"$`
+M11`KK@,:]"8S`$`DDO_\%$``!P"@&"&\L0``)*4`$`!F$"$`11`K$$#_^P``
+M``"F5``"#`!1OP+`("&2`AKX$$``9@(@*"$D`@`=$J(`5B:#`$"2`AKXHD(`
+M`(X"&^PD0O_\`$,0*Q1``$,D`__\DD0``99"``(TA``!)$(``P!#&"0P@@`"
+MHD0``:9#``(``(@A%$``!"9%``0P8O_\`D(0(21%``260@`")$(`0*9"``*.
+M`AKT)`,`%:RC``0D0@!`K*(``(X"&U268P`")*0`#*RB``BL@P`$K(``"(X"
+M&O2LM0`,E@,;<*R"``R28@`&C@8:W*R"`!"28@`*K((`%()G``FL@P`<K(<`
+M&))B``2L@@`HDF(`"ZR"`"R28@`%K((`())B``@L10`@)$/_X`!E$`H0P``#
+MK((`)%*@``&N!Q?`C@(`!`)`*"$,`!K'C$0``!(@``0"("@AC@(`!`P`&L>,
+M1```H@`:^!``_XBN`!KT#``(TP(`("$`0(@AD@(:^"8E``0D0@`!HB(``"0"
+M``.B(@`!)`(`0!``_\2F(@`"D@,:^`)`*"$D8@`!H@(:^))"``&B0P``,$(`
+M_J)"``&.`@`$#``:QXQ$```0`/]P)A8=C`P`"*X"`"`A$`#_F*X"&MR/OP`<
+MC[8`&(^U`!2/M``0C[,`#(^R``B/L0`$C[````"`$"$#X``()[T`(">]__"O
+ML0`$K[````#`B"$`H(`A)`4``:^_``ROL@`(#``4;0"`D"$"`"`A#``W=`(@
+M*"$"`#`A`@`H(0P`4=@F1!V,`D`@(0P`%&T``"@AC[\`#(^R``B/L0`$C[``
+M``/@``@GO0`0)[W_\*^_``"0H@`!,$(``A!```8DI_^D#``(UP````"/OP``
+M`^``"">]`!"@H```H*```8R&&^RDH``"`.`H(0P`"8@DQO_\$`#_]H^_```G
+MO?_0K[\`(*^W`!ROM@`8K[,`#*^Q``2OL```K[4`%*^T`!"OL@`(C((;[`"`
+MF"$DA!V,)%``H`"P`!JN8!M44@```0```<T``+`2#`!1KP``B"$00``1`$"X
+M(1(@``0"X!`A#`!Z:@(@("$"X!`AC[\`((^W`!R/M@`8C[4`%(^T`!"/LP`,
+MC[(`"(^Q``2/L````^``"">]`#!RT!@")`(``:YB';0D<``0#`!Z5P(`("$0
+M0``R`$"((0!`("$``"@A`@`P(0!`D"$,`'"J)C4`8`+V$"JN<1JX`B"@(:YP
+M&KP00``5`J"((0+`@"&.9AOLKE0`)*Y5`"BN40`$`D`H(0)@("$,``F(),;_
+M_(YB&^PF$/__`B(H(0)"&"$"HB`A`H(0(21R`%PDE0!<)%0`7!8`_^XDL0!<
+M)I$`$!K```BN8!K\`L"`(0(@*"$"8"`A#``(UR80__\6`/_[)C$`1"9P&L@,
+M`'&T`@`@(0P`<<D"`"`A$`#_O0+@$"$0`/^V)!<``B>]__"OL````("`(:^_
+M``0,`''0)(0:F`P`<=`F!!J$)`(``:X"&K2/OP`$C[````/@``@GO0`0)[W_
+M\*^R``BOL0`$K[```*^_``P`@)`A`("`(201``..`@`($$``#R8%``@`H!@A
+M)`0``R0"``$DA/__K&(`-*1@`#"D8``R!('_^R1C``@DI0!<K@``6*X``%P,
+M`!#@`D`@(28Q__\&(?_M)A`!'(^_``R/L@`(C[$`!(^P```#X``()[T`$">]
+M__"OL0`$`("((:X@&K0DA!J$K[\`"*^P```,`''"`*"`(0P`<<(F)!J8$@``
+M"P(@("$,``U[`B`@(0P`"B8"("`AKB`;'(^_``B/L0`$C[````/@``@GO0`0
+M#``.V0`````0`/_S`````(RB`#P\`X?_-&/__SP$?_\`0Q`D-(3__SP#_O\T
+M8___`$00)`!#$"2LH``$)[W_\*R@```DI`!<K*``"*RB`#RLH``,K*``(*R@
+M`!"LI0`DK*``%*R@`"BLH``8K*4`,*RE`"RLH``<K[\```P`&RD`````C[\`
+M``/@``@GO0`0)[W_\"2E__ROL0`$K[\`"*^P```0H``'`("((8RP```"("`A
+M#``*8R2E_Z06`/_[`@`H(8^_``B/L0`$C[````/@``@GO0`0)[W_\*^Q``2O
+MOP`(K[````"`B"&,L``@#``*8P(@("$6`/_\`@`H(8^_``B/L0`$C[````/@
+M``@GO0`0)[W_X*^_`!"OLP`,K[$`!*^P``"OL@`(C((`!`"@F"$D!0`4C%(`
+M``#`B"$,`!L*`D`@(0!`@"$"(#`AK%,`"`!`("$,`!L^)`4`&`)`("$,`!J]
+M`@`H(8^_`!"/LP`,C[(`"(^Q``2/L```)`(``0/@``@GO0`@)[W_X*^S``RO
+ML@`(K[```#P"@`*OOP`0K[$`!(Q%1ZPD@P`T)((`+`"`@"&L@@`PK(,`.*R`
+M`"RL@``T``"0(1B@`!0``)@A#`!Z5R0$``PF4@`!`$"((0!`("$``"@A$$``
+M%R0&``P,`'"J`````#P"@`*,0D>LC@,`.*X@```"0A`JKA$`.*QQ```40/_N
+MKB,`!"8$`"0,`'&'```H(0)@$"&/OP`0C[,`#(^R``B/L0`$C[````/@``@G
+MO0`@$`#_]R03``(GO?_PK[$`!*^_``BOL```C)``!`P`<+4`H(@AC@0`-(R%
+M```0H``3C((`!*RB``2.`@`PC(,`!*R1``BL@@`$C@(`,*QE``"N!``PK(``
+M``P`<+JL1```#`!QHR8$`"2/OP`(C[$`!(^P```#X``()[T`$!``_^ZN`@`X
+M)[W_\*^Q``0`@(@A)(0`)*^_``@,`'&.K[````P`<+4`````CB0`+(R%```0
+MH``3C((`!*RB``2.(@`XC(,`!(R0``BL@@`$CB(`.*QE``"N)``XK(```*R`
+M``@,`'"ZK$0```(`$"&/OP`(C[$`!(^P```#X``()[T`$!``_^ZN(@`P)[W_
+MX*^Q`!2OL``0K[\`'*^R`!B,D@`$`("`(0.@*"$F1``D#`!QJJ^@``"/H@``
+M'$``!P``B"&/OP`<C[(`&(^Q`!2/L``0`^``"">]`"`,``L3`D`@(1!`__<`
+M0"@A,$(`#R1"`"LD`__P`$,P)`"C&"0`9A`A`$,0*Q1```<`8"`AO'$``"1C
+M`!``AA`A`$,0*Q!`__L`````C*,`""0"`!`08@`*``````P`"H,"`"`ACZ(`
+M`"8Q``$"(A`J%$#_XX^_`!P0`/_=C[(`&`P`"O0"`"`A$`#_]X^B```GO?_P
+MK[(`"*^P``"OOP`,K[$`!(R1``0D`@`!``"`(0(@("&N(A?8#``*@R8R&JP"
+M0"`A#`!QAP``*"$,``ZZ`B`@(2H#``440``.)A```5!@``TF,!J8#`!Q7```
+M```D8P!D+&0`9`!$$"$`0#`A`&`X(0P`<94"0"`A$`#_[P`````F,!J8#`!Q
+MT`(`("$,`'&C)B07T`P`<8XF)!?(`@`@(:X@%]@,`''"`````(^_``R/L@`(
+MC[$`!(^P```#X``()[T`$">]_]"OL0`DK[\`+*^R`"BOL``@`*"((8R2``0`
+M`%`A``!P(1"@`'X``'@AC*T`#(RD`!`QH@`/``(8P`!B&",``QC``D,8(20"
+M__\0@@`8)'D8>``$$,``1!`A``(0P`!$$",``A"``D(0(8Q$``@D`P`!KZ,`
+M!!2```<D3P`(C*(`%%!```6-[@!8C*4`!!2@`&\"0"`AC>X`6!'``&DD`@`&
+MC<,`!%!B`&<``'@A)BG__(XL`!@!((`A)CC_H!$@`#\D!@`<`29`(24J_Z0E
+M"``$K4@`!(TK``"10P`.)`7P```+$"L``A$`,&,`[P!B&"6A0P`.CB(``)5#
+M``HE9_^D)$+_Y#!"#_\`91@D`&(8):5#``J.0AOLE40`#@`+.`H`1A`C)$+_
+M_`&"&"L!@Q`+`(4@)#!"#_\`@B`EI40`#I5&``ZM)_^DC4(`/"0#_?\`#2E`
+M`$,0)#"E`@``#1E"/`3^_S2$__\`11`E,&,``0!$$"0``QX``$,0):U"`#RM
+M2``HCB,`$##&#_\D`O__)&0`!*U'`""M6``PK4\`4*U.`$P08@`C`89@(ZU$
+M`#@!8$@A%6#_PP``,"$"`$@A$2``#`%`@"$E*O^DC4,`/(TK```\`G__-$+_
+M_P!B&"0!8$@AK4,`/*U9`%@58/_VK5``+`)`("$#("@A`P`P(0P`#TL``#@A
+MCB(`%%!```.N``!4CB(`!*X"`%2/OP`LC[(`*(^Q`"2/L``@`^``"">]`#`D
+M`G__$`#_W:U"`#@``'@A$`#_F0``<"$,``JD`Z`P(:X@``0"0"`A#``*@P(@
+M*"$0`/_NC[\`+">]_]"OL0`4K[\`(*^S`!ROL@`8K[``$`"`B"$,`'#^C)(`
+M!`!`("$,`'$!```H(0(@("$,``L3)E,:F`)@("$,`''"`$"`(0)`("$,`!1M
+M)`4``8X#``@D`@`0`@`H(1!B`!X"("`ACD(7X`(`*"$40``6`D`@(0P`"H,`
+M````)B0`)`P`<:H#H"@ACZ(`````@"$00``$`B`@(0P`"Q,``````$"`(58`
+M_^N.`P`(#`!QT`)@("$"0"`A#``4;0``*"$0`/_;`B`@(0P`"YX"("`A$`#_
+MZR8D`"0,``ML`````!``_^<F)``D)[W_X*^S``ROL@`(K[$`!*^_`!"OL```
+M`("((0P`"L*,D``$/!.``A!```D`0)`A`D`0(8^_`!"/LP`,C[(`"(^Q``2/
+ML````^``"">]`"`,`'&T)@0:F#P%@``\!X`"/`B``CP+@`(D!``!)FID$"2E
+M,.@"(#`A).<(Q"4(6!`E:V08#`!PRR0)#``,`'#DCF1D$!``_^<"0!`A)[W_
+M\*^P``"OOP`$C((;]`"`@"&,0@!$%$``!20$.@"/OP`$C[````/@``@GO0`0
+M)`(`!PP`>E>N`AL`)$("`"0#_@``0Q`DK@(=Q!``__2N`AL$)[W_X*^_`!RO
+MM@`8K[4`%*^T`!"OL@`(K[$`!*^P``"OLP`,C((;[`"`B"$DD!AX)%4`7`"U
+M`!H\`H`"4J```0```<V,E@`$``"@(0``D"$``"@2#``,G*Q%1ZR.(QOT)`(`
+M!JQB`&@,`%&O`@`@(292``$`0)@A)A``.!9@`"(J0@`&%$#_^"8D&JP``"@A
+MKB`7V`P`<8<\$H`")B07R`P`<8<``"@A)B07T`P`<8<``"@ACD)'K'!5@`(,
+M`'I7`@`@(1!``#$`0*`A`@`P(0!`("$,`'"J```H(8Y"1ZRN,!IXKC0:=`)B
+M$"HFD`!<%$``&P``D"$,``QU`L`@(1!``!``0)@A$H``!`)@$"$,`'IJ`H`@
+M(0)@$"&/OP`<C[8`&(^U`!2/M``0C[,`#(^R``B/L0`$C[````/@``@GO0`@
+M)C`:A`P`<;0"`"`A#`!QR0(`("$0`/_P`F`0(28%_Z0,``IC`B`@(3P"@`*,
+M0D>L)E(``0)"$"H40/_X`A6`(1``_]P`````$`#_WB03``(GO?_`K[``,*^_
+M`#BOL0`TC((;](S+```D#``!C$,`"`%L$`0`@(`A`&(8)!1@`"D`H$@A+*(`
+M!A!``"8`!1#`C,H`&(S#`!2,QP`0C,0`!`!%$".,Q0`(C,8`#``"$,`"`A`A
+M,4@`"*^C``"OJP`(KZ0`#*^E`!"OI@`4KZ<`("11&'BOJ@`$KZ``&*^@`!RO
+MH``D$0``!J^@`"@5(``6`````(X"'<0D0AP`KZ(`*`(`("$,`$IH`Z`H(0!`
+M&"&.`AOTC$(`:`!B$"M40``&KB,`)(^_`#B/L0`TC[``,`/@``@GO0!`#`!Q
+MM`(@("$0`/_YC[\`.%$L_^R.`AW$)`+_]P%"$"00`/_IKZ(`!">]__"OL@`(
+MK[$`!*^P``"OOP`,`("`(0``D"$DD1G(C@,:<"0"``$"0A`$`&(8)`)`*"$4
+M8``+`@`@(292``$N0@`&%$#_]B8Q`!R/OP`,C[(`"(^Q``2/L````^``"">]
+M`!`,`$J'``````(`("$"0"@A#``-%@(@,"$0`/_P)E(``2>]__"OL@`(K[$`
+M!*^P``"OOP`,`("`(0``D"$DD1AXC@(:<"0#``$"0Q@$`$,0)%!```DF4@`!
+MC@(;]`)`*"$"`"`AC$(`"`!#$"040``+)`8`!"92``$N0@`&%$#_\"8Q`#B/
+MOP`,C[(`"(^Q``2/L````^``"">]`!`,`$JV)E(``0(`("$,`!#@`B`H(1``
+M__(N0@`&)[W_\*^_``2OL```C*8`.`P`2[4`H(`AC@(`+(^_``2/L```K$``
+M0`/@``@GO0`0)[W_L*^U`#2OM``PK[,`+*^_`$"OMP`\K[8`.*^R`"BOL0`D
+MK[``((RR`!0`H*@A`("8(1)``&XDE`2`CD(`/`1!``0``+`ACD(`(!!``.8`
+M0)`ACD(`4%!```6.40`LC$(``%!```&N0`!0CE$`+(XB`$`40``')C<`0`)@
+M("$,`$VK`B`H(20#``T00P!9C[\`0`)@("$,`!"&`B`H(11``,\D`@`!CB,`
+M0*Y@&QP08@`&CE``4%(```6.H@`<CF(;:!1``+\"8"`ACJ(`'"1"__\2```*
+MKJ(`'(ZB`"2.!`!0``(0P`!0$"&40P`P)(3__ZX$`%`D8___I$,`,(XB`#P\
+M`X``KC$`,`!#$"6N(@`\KC$`+(ZB`!12(@`$CNL```!`L"&NL0`4CNL``"0"
+M``$18@!5CDH`*(Z"`#".@P`T)&,``2QD``$`1!`AKH(`,*Z#`#2.H@`P4$``
+M!H[C``",0P`PCB(`,!!#`#\"8"`ACN,``"0"``%08@`"KZ``!*^B``26X@`(
+MEN,`!(XD`%2OH@`,KZ,`"*^@`!`4@``HKZ``%%+```^.L@`44M$`#8ZR`!2.
+MP@!4`L"`(11``!:.U@`@`@`H(0P`"F,"8"`A4L``!(ZR`!16T?_WCL(`5(ZR
+M`!160/^5CD(`/(^_`$"/MP`\C[8`.(^U`#2/M``PC[,`+(^R`"B/L0`DC[``
+M(`/@``@GO0!0#`!PN@````".!0!4`F`@(0P`"J0#H#`A#`!PM0`````0`/_B
+MK@``5`P`<+H`````CB4`5`)@("$,``JD`Z`P(0P`<+4`````$`#_T*X@`%0,
+M`"EL/`6``*Z@`#`"8"`A#``I/#P%@``0`/^\CN,``))$`#R.A@`0CH<`%```
+M$"$PA``!)(0``0#D."$`Y"`K`,(P(0#$,"&NA@`0KH<`%)9$``J.B``XCHD`
+M/(YE!:@PA`__`21((0$D("L!`D`A`01`(:Z(`#BNB0`\!*(``:Y@!:B.8ANP
+M$$L`(B5"``200P``,&(``51```HD`@#_CH(`&(Z#`!PD8P`!+&0``0!$$"&N
+M@@`8KH,`'!``_XR.H@`P$$,`"@````".@@`HCH,`+"1C``$L9``!`$00(:Z"
+M`"BN@P`L$`#_@8ZB`#".@@`@CH,`)"1C``$L9``!`$00(:Z"`""N@P`D$`#_
+M>(ZB`#"50P`(EF(<7E!B``.50P`&$`#_VB5"`!"68AQ<%&+_UR5"`!"50P`$
+MEF(<6E1B_],E0@`0CH(!+"1"``$0`/_TKH(!+`*@*"$,`!`!`B`P(5!`_X6.
+ML@`4$`#_/8ZB`!P0`/^#KB``0(YB%]A00/^!C[\`0`P`<:,F9!JL$`#_?8^_
+M`$",@P`4$&``""0$``&,8@`\!$,`!0``("&,8@`@$$```@```````"`A`^``
+M"`"`$"$GO?_PK[$`!*^_``@`@(@AK[```(XB&\P00``4)(08>`P`#JX`````
+M)B08L`P`#JX``H`K)B08Z`P`#JX``H`*)B09(`P`#JX``H`*4$```0``@"$"
+M`!`AC[\`"(^Q``2/L````^``"">]`!`,``ZN`````!``__<``H`K)[W_\*^P
+M``"OOP`$#`!PM0"`@"&.`AO,)@48>!!```L"`"`A#``-K0`````F!1BP#``-
+MK0(`("$F!1CH#``-K0(`("$F!1D@`@`@(0P`#:T`````#`!PN@````"/OP`$
+MC[````/@``@GO0`0C*<`*```2"&0X@`!,$(`!!1``!",J``LD.(`%C!#``]4
+M8``-C*(`/)4"`$8``"`A``(1`J#B`!>1`@!',$(`#P`"$0``8A`EH.(`%@/@
+M``@`@!`AC*(`/``"%H(P0@`!5$``#Y#B``&5"0!&D.,`%C$B``\``A$`,&,`
+M#P!B&"4`"1$"H.,`%J#B`!>,H@`\/`,$``!#$"6LH@`\D.(``3!"``000/_I
+M`2`@(8T&`"!0P/_F`2`@(8S(`"PD!/_PC,<`*"4#``@P8@`/)$(`)P!D&"0`
+M1"@D`&40(0!#$"L40``'`&`@(;QQ```D8P`0`(40(0!#$"L00/_[`````(S"
+M`#P``A:",$(``51```Z0X@`!D.,`%C$B``\``A$`,&,`#P!B&"4`"1$"H.,`
+M%J#B`!>,P@`\/`,$``!#$"6LP@`\D.(``3!"``140/_8C08`(!``_[T!("`A
+M)[W_X*^S``P`P)@AK[4`%*^T`!"OL0`$K[```*^_`!BOL@`(`("@(0"@B"$,
+M`'"U``"H(1)@`$("8(`AC@(`/``"%D(P0@`!%$``58X2`%`20`!4`H`@(8Y"
+M`%000`!1`````!*@`$R.`@`LC$,``(Q"`""NHP``KJ(`((X&`"PF1`!<`@`H
+M(:S``""LP```#`!1V`````".0@!X)$(``:Y"`'@2H``"`F"`(8ZP`"!6`/_C
+MC@(`/!)@`"$`````EB,`-%!@`!&.(@`8CF0`*)""`!8P10`/4*``"Z8@`#0`
+M`Q$"H((`%Y(B`#60@P`!,$(`#P`"$0``HA`E-&,`"*"#``&@@@`6CB(`&%1`
+M`!VL4P`@)`(``:XB`"RN,P`4KC4`&`````^.(@`L5$``$(YF`"2.)0`D#`!*
+MG`*`("$,`'"Z`````(^_`!B/M0`4C[0`$(^S``R/L@`(C[$`!(^P`````!`A
+M`^``"">]`"".)0`D#`!*E0*`("$0`/_MKB``+(XC`!B.8@`DK&(``!``_^2N
+M-0`8$`#_N(Q3`"`"@"`A#``-H0(`*"&.@ALX4$``&(XB`!Q2```6CB(`'(X"
+M`#P``A9",$(``11```D"@"`ACB8`&(XG`#".*``D#`!*_@(`*"%40``*CB(`
+M'`*`("$,`"EL/`6``(X"`#`"@"`A/`6```P`*3RN(@`PCB(`'"1"``$20``*
+MKB(`'(XB`"2.1`!0``(0P`!2$"&40P`P)(0``:Y$`%`D8P`!I$,`,!``_Y>.
+M%0`L)[W_\*^R``BOOP`,K[$`!*^P``",H@!4%$``!P"`D"$DL0!<CB(`'!1`
+M``F.)@`4KB``&*X@`!2/OP`,C[(`"(^Q``2/L````^``"">]`!",P@`LC,4`
+M6`)`("&,4``@K$```*Q``"`,``]+```X(8XB`!P"`#`A)$+__Q1`__2N(@`<
+M$`#_ZZX@`!@GO?_@K[0`$*^S``ROL0`$K[\`%*^R``BOL```C-``,(RB`"2,
+MPP!`CA(`4``"$,``H(@A`D(H(20"``(`@*`A$&(`.22S`#".(P`4C&(`/`1"
+M`"V,8@`@C@(`/#P#`@".!P`L`$,0):X"`#R.(@`<EF4``)9D``(D0O__KB(`
+M'(Y"`%".0P!4C.8`("2E__\D0O__)(3__R1C__^.,``4IF0``J9E``"N0@!0
+MKD,`5!3```*N)@`4KB``&*S@```"`#`AK.``(`(@*"$``#@A#``/2P*`("$"
+M@"`A#``/W@)`*"$``!`AC[\`%(^T`!"/LP`,C[(`"(^Q``2/L````^``"">]
+M`""L8````&`H(:XB`!0"@"`A#``*8ZQ@`"`0`/_.C@(`/)2C`#".0@!4)`8`
+M`:YF``0`0Q`AKD(`5*9C``*.`P`\/`6'_S2E__\``Q;",$(`#R1"``$P0@`/
+M``(6P`!E&"0`8A@EK@,`/(R"&V@``Q[",&,`#P!#$"M40``%CD(`5(R"&K14
+M0``1C((%@(Y"`%268P`")`7__R1"__^N0@!4CH(%A"1C__^F8P`")$(``0P`
+M5NZN@@6$`H`@(0P`#]X"0"@A$`#_QB0"__\D0@`!K((%@(X"`#P``A;",$(`
+M#Q!&``8`````C@,`*)!B``$T0@`($`#_DJ!B``$,``[T`@`H(1``__BF(@`T
+M)[W_\*^Q``2OL```K[\`"`"@@"&.`P!`C*4`,"0"``$`@(@A$&(`3HRD`%".
+M(AMH$$``1@``$"%0@`!%C[\`"(RB`"B00@`!,$(`!!!``"6.`P`@$&``/0``
+M$"&,<``LC@(`,(Q"`"B00@`6,$(`#Q!``#LF!``(,((`#R0#__`D0@`G`(,@
+M)`!#*"0`A1`A`$00*Q1```<`@!@AO)$``"2$`!``91`A`$00*Q!`__L`````
+M`B`@(0(`*"$,`$Z')`8``1!``"$D`O__C@(`,(Q"`"B00@`!,$(`!!1`_]V.
+M`P`@$&``&0``$"&,<``L)`3_\"8#``@P8@`/)$(`)P!D&"0`1"@D`&40(0!#
+M$"L40``'`&`@(;QQ```D8P`0`(40(0!#$"L00/_[``````(@("$"`"@A#`!.
+MAR0&``$D`___``(8"P!@$"&/OP`(C[$`!(^P```#X``()[T`$!``__H``!`A
+M)[W_T*^Q`"0`H(@AK[(`**^P`""OOP`L#`!PM0"`D"&.,``4$@``&0````".
+M0@2PCD,$M(X$`%0D8P`!+&4``0!%$"&N0@2PKD,$M!2``!<D`@`!C@(`+(Q0
+M`"`6`/_S`````(XP`!02```(`D`@(:X@`#"N(``4KB``&*X@`!RF(``T#``*
+ME0(`*"$,`'"Z`````(^_`"R/L@`HC[$`)(^P`"`#X``()[T`,*^B``2OH``(
+MKZ``#*^@`!`,`'"ZKZ``%(X%`%0"0"`A#``*I`.@,"$,`'"U`````!``_]VN
+M``!4)[W_\"2"`%2OL@`(K[$`!*^P``"OOP`,`("`(0"@B"$`0"`A$.``(0#`
+MD"$,`'&.``````P`<+4`````C@0`3(R%```0H``7C((`!*RB``2.`@!(C(,`
+M!*R1``BL@@`$C@(`2*QE``"LD@`,K(```*X$`$@,`'"ZK$0```P`<:,F!``\
+M```@(8^_``R/L@`(C[$`!(^P````@!`A`^``"">]`!`0`/_JK@(`4`P`<9P`
+M````)`,``11#__,D!``"$`#_W``````GO?_PK[````"`@"$DA``\K[\`#*^Q
+M``2OL@`(#`!QC@"@B"$,`'"U`````(X%`$2,HP``$&``'(RB``2L8@`$C*(`
+M!"8$`%2,L@`($B```ZQ#``",H@`,KB(``(X"`%`D`___K*```*RB``2.`@!0
+MK*,`"*X%`%"L10``#`!QHZR@``P,`'"Z``````)`$"&/OP`,C[(`"(^Q``2/
+ML````^``"">]`!`0`/_EK@(`2">]_^"OOP`4K[``$(R0``2OH```)@0`/`P`
+M<:H#H"@ACZ(```(`("$40``()Z4`!(^B``!40/_X)@0`/(^_`!2/L``0`^``
+M"">]`"`,`!%+`````!``__>/H@``)[W_\"2E__^OL0`$K[\`#*^R``BOL```
+M+*(`&0"`B"$00``4C)(`!#P#@`(`!1"`)&,(X`!#$"&,0@```$``"`````",
+MA```#``;"B0%`!$`0(`A)D8$@`!`("$D!0$X#``;/@````".)```#``:O0(`
+M*"&/OP`,C[(`"(^Q``2/L````^``"">]`!```#`A`D`@(0P`+H$D!0`"CB0`
+M``P`&PHD!0`2`$"`(29&!(@`0"`A$`#_ZB0%``B,A```#``;"B0%`!..)```
+M`$"`(20"`@`0`/_EK@(```P`$ZB,A``$$`#_Y(^_``P,`!/`C(0`!!``_^"/
+MOP`,)[W_T*^S`!ROOP`@K[(`&*^Q`!2OL``0C)(`!`"`F"$#H"@A`F`@(0P`
+M$4LF41?L`B`@(0P`<<(`0(`A`D`@(0P`%&TD!0`!CZ8```(`*"$,`!&.`F`@
+M(0)`("$,`!1M```H(0P`<=`"("`A$`#_[0.@*"$GO?_@K[0`$*^S``ROOP`<
+MK[8`&*^U`!2OL@`(K[$`!*^P``",D0`$``"@(0``F"&.(A?@5$``"HXB%]PF
+M,!K(#`!QP@(`("$,`''0`@`@(8XB%^!00/_Z)C`:R(XB%]P00``X`````"8V
+M&N`,`''"`L`@(8XC'*0D`@`#$&(`-0`````D!0`!`B`@(0P`%&TF,AK()C4:
+MA`P`<<D"0"`A)!```0*@("$,`'')`@*@"Q*``!H"`I@+$F``$P```````(`A
+M#``(VP(@("&.(@`$)A```0P`'0.,1```#``.V0(@("&.(@`$#``=`XQ$```\
+M`H`"D$)$:!!```,J`P!D%&#_\``````2@``$``````P`<=`"0"`A``"@(5)@
+M``4"("`A#`!QT`*@("$``)@A`B`@(0P`%&T``"@A#`!QT`+`("$,`'#U````
+M`!``_[@`````#`!I/S0$PU`0`/_*)`4``2>]__"OOP``C*(`!`"@("$``#`A
+MC$(7Q"0%`!@40``$```X(8^_```#X``()[T`$`P`$1D`````$`#_^X^_```G
+MO?_P`*`@(0``,"$D!0`9K[\```P`$1D``#@AC[\```/@``@GO0`0)[W_\*^_
+M``BOL0`$K[```(R0``0,`'%9`("((0!`("$,`'%7)@4;7(X$&UP\!8``)@<8
+M""8(&!`"(#`A#`!Q822E20P,`'%<`````"1C`,@L90#(C@08"`!%$"$D"```
+M)`D`R`!`,"$,`'%T`&`X(8X$&UP\!8``)@<80"8(&$@"(#`A#`!Q822E24P,
+M`'%<`````"1C`,B.!!A`+&4`R`!%$"$`0#`A)`@``"0)`,@,`'%T`&`X(8^_
+M``B/L0`$C[````/@``@GO0`0)[W_X"2"`$0D@P!,K[$`!`"`B"&OOP`8K[4`
+M%*^S``ROL@`(K[0`$*^P```DA``\KB(`2*XC`%```"@AKB``1*X@`$PF,P!4
+M#`!QAXXT``0"8"`A#`!QAP``*"$``*@A``"0(0P`>E<D!``0)E(``0!`@"$`
+M0"`A```H(1!``#XD!@`0#`!PJ@````".(@!0)`/__ZXP`%"N````K@(`!*Q0
+M```"8"`AK@,`"`P`<:.N```,*D(``A1`_^H`````#`!QM":$%^P\$(`"/`6`
+M`#P'@`(\"(`"/`N``B8*;+@DI4>H).<)1"4(9+@E:VS``B`P(20)"``,`'#+
+M)`0``8X$;+@,`'#D/!"``CP%@``\!X`"/`B``CP+@`(F"GE@)*5'-"3G"50E
+M"&U@)6MY:"0$``$"(#`A#`!PRR0)#``,`'#DC@1Y8`P`$ET"("`A`J`0(8^_
+M`!B/M0`4C[0`$(^S``R/L@`(C[$`!(^P```#X``()[T`(!``__4D%0`")[W_
+MT*^P`!``H(`AK[\`(*^S`!ROL@`8`("8(:^Q`!0,`'%"KZ``!`P`*.@"`"`A
+M%$``$B02``$,`'%0`F`@(20"``$20@`)``````)`$"&/OP`@C[,`'(^R`!B/
+ML0`4C[``$`/@``@GO0`P#`!Q20)@("$0`/_V`D`0(0(`("$#H"@A#``H[2>F
+M``0`0(@A,$(``11``%`"`"`A,B(`(%1``$:.`@2$,B((`!1``#X"`"`A,B(`
+M0!1``#<"`"`A/`(`!`(B$"040``O`@`@(3(B`(`00``2`````(X"&\Q00``B
+MC@48G(^B``0P0@`(5$``&HX%&42/H@`$,$(`!%1``!*.!1D,CZ(`!#!"``)4
+M0``*C@48U"0"_W\"(H@D$B#_Q:^@``".`AV$)!(``P!1$"40`/_`K@(=A`P`
+M2IP"`"`A$`#_]20"_W\,`$J<`@`@(1``_^V/H@`$#`!*G`(`("$0`/_ECZ(`
+M!(^B``0`LA@$`$,0)!!`_^D`````$`#_[@`````,`"EL/`4`!!``_]`R(@"`
+M#``I;"0%`$`0`/_(/`(`!`P`2@HD!0`!)`+W_Q``_[\"(H@D`@`@(20%`"`D
+M0@`!#``I;*X"!(00`/^V,B((``P`*6PD!0`!$`#_KS(B`"`GO?_@K[0`$*^R
+M``BOL```K[\`%*^S``ROL0`$C,,<I"0"``(`@*`A)`4``0#`@"$`P"`A$&(`
+M%@``D"$,`!1M/!,`!`(`("$,`"EL/`6``(X1'82N`!V$`@`@(0P`*3P\!8``
+M$B``!`(S$"0"`"`A%$``$S(R`"`"0"@A#``I/`(`("$"`"`A#``4;0``*"$,
+M`'%0`H`@(0P`<4D"@"`AC[\`%(^T`!"/LP`,C[(`"(^Q``2/L````^``"">]
+M`"`,`#>``````%1```..!``$$`#_Z0)3D"4``#`A```X(0P`$1DD!0`#4$#_
+MY`)`*"$0`/_A`E.0)2>]__"OL```K[\`!(R"%^`00``/`("`(8R"%]P00``,
+M)`(``HR#'*008@`))`(``1!B``B/OP`$#`!PM0`````,`##@`@`@(0P`<+H`
+M````C[\`!(^P```#X``()[T`$">]_]"OL0`DK[\`+*^R`"BOL``@C((7X!!`
+M`"8`@(@AC((7W!!``",D`@`"C(,<I!!B`"`D$@`!$'(`'X^_`"P,`'"U````
+M`(XB&QQ40``%CC`;0(XB&R140``@CB(;S(XP&T`GH@`0`B`@(0``*"$``#`A
+M```X(0``0"$``$@A``!0(20+``&OH@``#`!7EZ^R``0\`@`$`@*`)!8```L"
+M("`A#``-6@(@("$,`'"ZKB`;)(^_`"R/L@`HC[$`)(^P`"`#X``()[T`,`P`
+M*3P\!0`$$`#_\P````!00``4CB(8E```*"$`!1#``$40(P`"$,``41`AC$,8
+ME"2B``$P10#_$&```RRD``0D`@`!KB(;'!"`_^4`````CB(;'!1`_^(`!1#`
+M$`#_\0!%$",00/_>)`(``1``_]RN(AL<)[W_X"0#``&OLP`,K[(`"*^Q``2O
+ML```K[\`$`"@D"$`P)@A`("`(1"C`$8``(@A4*``,(R"'*0D`@`"$*(`$R0"
+M``,0H@`,`````%(@``&N$ARD5F```:YQ``"/OP`0C[,`#(^R``B/L0`$C[``
+M``/@``@GO0`@#``4K"0%``(D$0`6$`#_\0`"B`H,`"EL/`6```(`("$,`!2L
+M```H(201`!8"`"`A#``(E0`"B`HD!0`!#``*2`(`("&.`@`$#``="HQ$```,
+M`%&4`@`@(0(`("&N`!?@#``I/#P%@``"`"`A#``4K"0%``$0`/_7`````!!#
+M``D``````@`@(0``*"$,`!2L`````%1`_\\D$0`6$`#_S0````",@A?@4$#_
+M]P(`("&,@@`$#``=&(Q$```,`''0)@0:X!``__`"`"`AC((7X%1```2,@@`$
+M`@`@(1``_^LD!0`!#``="HQ$```,`''")@0:X!``__D"`"`A)[W_\*^P```P
+ML`#_K[\`#*^R``BOL0`$``"0(0P`<+4`@(@A#`!Q-``````2```:CB(<K!1`
+M``@D0@`!CB(<J`(@("$``"@A%$``#R0&``&.(ARL)$(``:XB'*P,`'$[````
+M``P`<+H``````D`0(8^_``R/L@`(C[$`!(^P```#X``()[T`$`P`-.4D$@`6
+M$`#_[P`"D`HD0O__%$#_[ZXB'*R.(ARH`B`@(20&``$00/_J`$`H(0P`-.4D
+M$@`6$`#_Y@`"D`HGO?_PK[````"`@"&OOP`$#`!QM"2$&N"N`!RDK@`<K*X`
+M'*B/OP`$C[````/@``@GO0`0)[W_\*^R``BOL0`$K[```*^_``P`@(`A#`!P
+MM0"@B"$D`@`!$B(`(P``D"%2(``7C@(<K"0"``)2(@`*C@(<K`P`<+H`````
+M`D`0(8^_``R/L@`(C[$`!(^P```#X``()[T`$!!```,"`"`A$`#_]*X1'*@D
+M!0`"#``TY20&``$D$@`6$`#_^0`"D`H00``#`@`@(1``_^JN`!RH```H(0P`
+M-.4D!@`!)!(`%A``__D``I`*C@(<K%1`_^&N$1RH`@`@(1``_^PD!0`!)[W_
+M\*^R``BOL0`$K[```*^_``P`H(@A`("`(1"@`#<``)`A)`(``1"B``DD!0`$
+M)!+__P)`$"&/OP`,C[(`"(^Q``2/L````^``"">]`!`,`#3E)`8``8X#%]PD
+M$@`6$&``!``"D`J.`A?@$%$`&3P%@``60/_O)`(``8X#'*A08@`/C@(<K"0"
+M``(48O_J`D`0(8X"'*P40/_G`D`0(0(`("$D!0`"#``TY20&``%40/_@)!(`
+M%A``_]\"0!`A%$#_\B0"``("`"`A$`#_]B0%``$,`"D\`@`@(0P`-;@"`"`A
+M#``UZ`(`("$,`'"Z`````!``_]\`````C((<J!1``!X`````C@(7W!!```4F
+M!1MPC@,7X"0"``$08@`,``````(`("$,`#>%)`8``1!```0`0)`A)!(`%A9`
+M_[X"0!`A`@`@(1``_]<D!0`##`!PM0`````"`"`A#``I;#P%@``,`#7]`@`@
+M(0P`-;\"`"`A$`#_\0`````,`#3E)`8``202`!80`/_?``*0"B>]__`D@@`4
+M)(,`'*^R``BOL```K[\`#*^Q``0`@(`AK((`&*R#`""L@``4K(``'```D"$,
+M`'I7)`0`#`!`B"$2(``1)`(``@(@("$``"@A#`!PJB0&``R.`@`@)E(``2I#
+M``*N$0`@KB```*XB``048/_PK%$``"8$``P,`'&'```H(0``$"&/OP`,C[(`
+M"(^Q``2/L````^``"">]`!`GO?_PK[\``(R&`!R,R```$0``$0"`."&,P@`$
+MK0(`!(SB`!B,PP`$).0`#*S"``2,X@`8K&@``*S%``BLP```K.8`&`P`<:.L
+M1@``C[\```/@``@GO0`0C,(`!!``__"L@@`@)[W_\*^Q``0`@(@A)(0`#*^_
+M``@,`'&.K[````P`<+4`````CB0`%(R%```0H``3C((`!*RB``2.(@`@C(,`
+M!(R0``BL@@`$CB(`(*QE``"N)``@K(```*R```@,`'"ZK$0```(`$"&/OP`(
+MC[$`!(^P```#X``()[T`$!``_^ZN(@`8,*8`#R>]_?`D`O_P),,`3Z^T`@``
+M8A@D`*"@(0"B*"0`HQ`AK[$!]*^_`@ROM@((K[4"!*^S`?ROL@'XK[`!\`!%
+M$"L`@(@AC),`!(R6``"OH`"TKZ``H!1```<`H"`AO+$``"2E`!``@Q`A`$40
+M*Q!`__L`````CH,``"QB`$%40``1CH(`#`!F$"$D0@`/)`/_\`!#*"0"@Q@D
+M`&40(0!#$"L40``'`&`@(;QQ```D8P`0`(40(0!#$"L00/_[`````(Z"``P4
+M0`.[CI``!```J"$F!?__+*(`0Q!``!L\`X`"``40@"1C"80`0Q`AC$(```!`
+M``@`````)Z4`H">F`*0,`!MH`H`@(0*`("$GI0"@#``;:">F`*@"@"`A)Z4`
+MH`P`&V@GI@"L`H`@(2>F`+`,`!MH)Z4`H`(@("$"8"@A#``'PR>F`+02H``'
+M`L`@(8Z"``@"H"@AKJ(`"(^B`+0,`!J]KJ(`#(^_`@R/M@((C[4"!(^T`@"/
+MLP'\C[(!^(^Q`?2/L`'P`^``"">]`A`"@"`A)Z4`H`P`&V@GI@"XCZ8`N`(@
+M("$"8"@A#``&\">G`+00`/_D``````)@("$,`%>0)Z4`M!``_]\``````H`@
+M(2>E`*`,`!MH)Z8`O(^E`+P"8"`A)Z8`P```."$,`%!<)Z@`Q(^E`,`,`!LW
+M`J`@(8^B`,`00``1CZ4`O`*@("$GI0#(#``;5R>F`,R/I0"\CZ<`R`)@("$G
+MI@#0#`!07">H`,2/I0#0`J`@(0P`&V$`````$`#_OP`````"8"`A)Z8`P">G
+M`-0,`%!<)Z@`Q(^E`-0"H"`A#``;-P`````0`/^T`````">E`*`GI@#8#``;
+M:`*`("$"@"`A)Z4`H`P`&V@GI@#<CZ(`W!!```P"@"`A)Z4`H`P`&W(GI@#@
+MCZ4`V(^F`-R/IP#@`F`@(0P`5P0GJ`#D$`#_G@`````GI0"@#``;:">F`.B/
+MI0#8CZ<`Z`)@("$0`/_U```P(0*`("$GI0"@#``;:">F`.R/I0#L`F`@(2>F
+M`/```#@A#`!8(2>H`/2/I0#P#``;-P*@("&/H@#P4$``#H^E`.P"H"`A)Z4`
+M^`P`&U<GI@#\CZ4`[(^G`/@"8"`A)Z8`\`P`6"$GJ`#TCZ4`\!``_[<"H"`A
+M`F`@(2>F`/`GIP$`#`!8(2>H`/2/I0$`$`#_N@*@("$"("`A)`4``0``,"$,
+M`!$9```X(1``_VH``````F`@(0P`!O,GI0"T/`2``@P`<'0DA`ET$J#_:X^_
+M`@P,`"YR`F`@(0*@("$0`/^F`$`H(0)@("$,``<V)Z4`M!``_U@``````F`@
+M(0P`!U<GI0"T$`#_4P`````"8"`A#``'E2>E`+00`/].`````">E`*`GI@$$
+M#``;:`*`("$"@"`A)Z4`H`P`&V@GI@$(`H`@(2>E`*`,`!MH)Z8!#`*`("$G
+MI0"@#``;<B>F`1"/I0$$CZ8!"(^G`1`,`%#?`F`@(1``_S<`````)Z4`H">F
+M`10,`!MH`H`@(0*`("$GI0"@#``;:">F`1@"@"`A)Z4`H`P`&V@GI@$<CZ4!
+M%(^F`1B/J`$<`F`@(0P`42<``#@A$`#_(P`````GI0"@`H`@(0P`&V@GI@$@
+MCZ4!("0"__\0H@`%``````P`46P"8"`A$`#_%P`````,`%&4`F`@(1``_Q,`
+M````#`!QHR9D%\@,`'&.)F07T!``_PT``````H`@(2>E`*`,`!MH)Z8!/(^E
+M`3P"8"`A#``4$">F`+00`/\#``````*`("$GI0"@#``;:">F`42/I0%$#``'
+MW0)@("$0`/[Z`````">E`*`GI@%(#``;:`*`("$"@"`A)Z4`H`P`&V@GI@%,
+MCZ4!2(^F`4P,``@6`F`@(1``_NP`````)Z4`H">F`5`,`!MH`H`@(0*`("$G
+MI0"@#``;:">F`50"@"`A)Z4`H`P`&V@GI@%8`H`@(2>E`*`,`!MH)Z8!7(^E
+M`5"/I@%4CZ<!6(^H`5P,``@R`F`@(1``_M0`````)Z4`H">F`6`,`!MH`H`@
+M(0*`("$GI0"@#``;:">F`60GL``0`H`@(2>E`*`,`!MR)Z8!:`(`("$``"@A
+M#`!PJB0&`!R/HP%DCZ(!:)>E`6("8"`A`@`P(:^B`!2OHP`D#`!/@*^C`!P0
+M`/ZX``````*`("$GI0"@#``;:">F`6R/I@%L`F`@(0P`3\@``"@A$`#^K@``
+M```,`!VR`F`@(1``_JH``````H`@(2>E`*`,`!MH)Z8!<(^E`7`,`"F>`F`@
+M(1``_J$`````)Z0`,```*"$,`'"J)`8`!@*`("$GI0"@#``;:">F`70"@"`A
+M)Z4`H`P`&V@GI@%X`H`@(2>E`*`,`!MH)Z8!?`*`("$GI0"@#``;<B>F`8"/
+MI@&`EZ4`-```@"&4QP`4E,0`!"3#``@XX@`'$*0`,P!B@`L`P(@ACZ,!="QB
+M``040``8``,0P`!#$"$``A#``$,0(P`"$(`"8A`A)$/[F"0"``<0X@`B)`(`
+M!*1B`18D`@`#$.(`&B0"`!`0X@`8)`(`$5#B`!>48@$6).+__BQ"``(40``"
+M)`0`""0$``2D9`$8#``(E0)@("&.8AM4`F`@(0(@,"$D0@`!KF(;5(^E`72/
+MJ`%X#``IO`(`."$,``A^`F`@(1``_ED`````E&(!%B1"``00`/_HI&(!%J1@
+M`1@0`/_KI&`!%I>C`#*4P@`"%&+_S`#`B"&7HP`PE,(``!1B_\<``(@A$`#_
+MQX^C`70GI0"@)Z8!A`P`&V@"@"`A`H`@(2>E`*`,`!MH)Z8!B`*`("$GI0"@
+M#``;:">F`8R/IP&,CZ4!A(^F`8@,`"P_`F`@(8^C`80``A0```(D`RQB``04
+M0/XQ``,0P`!#$"$``A#``$,0(P`"$(`"8A`A$`#^*J1$_*P"@"`A)Z4`H`P`
+M&V@GI@%`CZ4!0`P`5W\"8"`A$`#^(0`````GI0"@)Z8!D`P`&V@"@"`A`H`@
+M(2>E`*`,`!MH)Z8!E`*`("$GI0"@#``;:">F`9@"@"`A)Z4`H`P`&V@GI@&<
+M)Z4`H">F`9P"@"`A#``;:(^P`9P"@"`A)Z4`H`P`&W(GI@&@CZ8!E(^G`9B/
+MJ`&@CZD!D`)@("$"`%`A#`!0$@``*"$0`/W^`````">E`*`GI@&D#``;:`*`
+M("$"@"`A)Z4`H`P`&W(GI@&HCZ4!J`P`+2("8"`A$`#]\0`````GL``X`F`@
+M(0P`+>T"`"@A`J`@(0(`,"$D!0`(#``;/@`````0`/WF``````P`+@0"8"`A
+M$`#]X@`````D`@`"KF(;L`P`+A("8"`A$`#]W``````GI0"@)Z8!K`P`&V@"
+M@"`A`H`@(2>E`*`,`!MH)Z8!L">E`*`GI@&P`H`@(0P`&VB/L`&P`H`@(2>E
+M`*`,`!MR)Z8!M(^C`:PD`O__$&(`)0`#$,``0Q`A``(0P`!#$"./I0&T``(0
+M@`)B$"$D1@`0`*88)3!C``,D1``($&``'R2G`"``X!@AB*(``)BB``.(IP`$
+MF*<`!XBH``B8J``+B*D`#)BI``^HP@``N,(``ZC'``2XQP`'J,@`"+C(``NH
+MR0`,N,D`#R2E`!`4H__N),8`$("B``"@P@``#`!2Q0(`*"$6`/VACZ4!M`P`
+M+BX"8"`A$`#]G0````",H@``C*,`!(RH``B,J0`,K,(``*S#``2LR``(K,D`
+M#"2E`!`4I__V),8`$!``_^H``````H`@(2>E`*`,`!MH)Z8!N(Z"``P00``?
+MCZ,!N"0"``408@`()`(`!!1B_80"8"`A```P(0P`+H$D!0`$$`#^(0*@("$"
+M8"`A)Z8`0`P`+H$D!0`%CZ(`0">F`%@"H"`AKZ(`6(^B`$0D!0`4KZ(`7(^B
+M`$BOH@!@CZ(`3*^B`&27H@!2IZ(`:)>B`%80`/^"IZ(`:H^E`;@"8"`A#``N
+M@0``,"$0`/UE``````P`+PX"8"`A$`#^`P*@("$GI0"@)Z8!O`P`&V@"@"`A
+M`H`@(2>E`*`,`!MH)Z8!P(^E`;R/I@'`#``RH0)@("$0`/U3``````P`,XT"
+M8"`A$`#]3P`````"@"`A)Z4`H`P`&V@GI@'DCZ4!Y`P`,\$"8"`A$`#]1@``
+M```"@"`A)Z4`H`P`&V@GI@'HCF8<_(^E`>@,`#,5`F`@(1``_3RN8AS\)Z4`
+MH">F`30,`!MH`H`@(0*`("$GI0"@#``;:">F`3B/I0$TCZ8!.`P`-@4"8"`A
+M$`#]+@`````GI0"@)Z8!+`P`&V@"@"`A`H`@(2>E`*`,`!MH)Z8!,(^E`2R/
+MI@$P#``V#@)@("$0`/T@``````P`2'\"8"`AKF(%L"9E&W`,`#KG`F`@(1``
+M_1@`````)[`!Q`*`("$GI0"@#``;:`(`,"$"@"`A)Z4`H`(`,"$,`!MHE[(!
+MQB>E`*`GI@'(`H`@(0P`&VB7L0'&`H`@(2>E`*`,`!MH)Z8!S`*`("$GI0"@
+M#``;:">F`=`"@"`A)Z4`H`P`&V@"`#`A`@`P(0*`("$GI0"@#``;:(^P`<2/
+MIP'(CZ@!S(^I`="/JP'$)Z(`M`)@("$"0"@A`B`P(0(`4"&OH@``#`!7EZ^@
+M``00`/SJ``````P`.F<"8"`A$`#\Y@`````"@"`A)Z4`H`P`&V@GI@'4CZ4!
+MU`P`0=<"8"`A$`#\W0`````"@"`A)Z4`H`P`&V@GI@'8CZ(!V`*`("$GI0"@
+M``*`P`("@",,`!MH)Z8!W``0B("/H@'<`G&((28Q&<BOH@!\`H`@(2>E`*"N
+M(@`$#``;:">F`=R/H@'<`H`@(2>E`*"OH@"`)Z8!W`P`&VBN(@`(CZ(!W`*`
+M("$GI0"@KZ(`A">F`=P,`!MHKB(`#(^B`=P`$(#``H`@(:^B`)`GI0"@KB(`
+M$">F`=P,`!MH`G"`(280&'B/H@'<C@4`)`)@("&N(@`8)Z8`<`P`2C.OH@!T
+M$`#\IP`````"@"`A)Z4`H`P`&V@GI@$D)Z4`H">F`20"@"`A#``;:(^P`20"
+M@"`A)Z4`H`P`&W(GI@$HCZ8!*``0$,``4!`CC,,````"$(``4Q`AK$,9R(S#
+M``0D0AG()`<``:Q#``2,PP`(`@<X!`)@("&L0P`(C,,`#`(`*"&L0P`,C,,`
+M$*Q#`!",PP`4K$,`%(S#`!BL0P`8CF(:<(^F`2@`1Q`E#``-%JYB&G`0`/Q[
+M``````*`("$GI0"@#``;:">F`>"/HP'@`F`@(0`#$,``0Q`C``(0P`!3$"$,
+M`$J'C$48G!``_&T``````H`@(2>E`*`,`!MH)Z8![)>B`>X0`/QFIF(;\`+`
+M("$,`!L*`@`H(11`_$,`0*@A)`(``A``_&:OH@"T)[W_\*^Q``2OOP`(`("(
+M(0P`</ZOL````$`@(0P`<0$``"@A#``5A`(@("$`0(`A`B`@(0P`%:4`0"@A
+M#``;'@(`("$0`/_W`````">]__"OL@`(K[$`!*^P``"OOP`,`("`(0P`%4,\
+M$H`#/`6``#P'@`(\"(`"/`N``P!`B"$F2HH()*5F;`(`,"$DYPJ0)0AZ""5K
+MBA`D!``!$$``""0)$``"(!`AC[\`#(^R``B/L0`$C[````/@``@GO0`0#`!P
+MRP`````,`'#DCD2*"!``__4"(!`A)`(``:R"`#`\`H`"K$5$1#P"@`*L140\
+M`^``"```$"$GO?_0K[0`(*^R`!BOL0`4K[``$*^_`"0\$(`"K[,`'(X%,N`\
+M!H``/`>```"`B"$DQFI0```@(23G:K@GJ@`!)Z@`!`P`66L#H$@A/`*``HQ4
+M1$`\`H`"C$9$.(X#,N"3H@``CZ4`!*QQ``"@8@`(K&4`!).B``&.!#+@``"0
+M(:""``F.`C+@K$8`$*Q4``P\$X`"CG`RX`P`>E<"@"`ACF,RX``2B(`",(`A
+MK@(`%`(CB"&.)``4#``;'B92``$J0@`"5$#_\SP3@`*.9#+@#``:VB02``\\
+M$(`"C@(RX"92__\,`'I7C$0`#(X$,N`,`!KW`$`H(09#__@\$(`"C@(RX(^_
+M`"2/M``@C[,`'(^R`!B/L0`4C[``$`/@``@GO0`P)[W_T#"B``\D0@!-)`/_
+M\*^R`!@`H)`A`$,H)`)#&"0`91`A`$,0*Z^Q`!2OOP`@`("((:^S`!ROL``0
+M%$``!P!@("&\<0``)&,`$`"%$"$`0Q`K$$#_^P````"20@`!DD0``)(C`$`0
+M@P`2,%,``8XC`#B.(@`\K&```(XD`#0D0@`!$(``!:XB`#P,`!LIC)```!8`
+M__T"`"`AKB``1*X@`#2B(`!`DD(``!1``$(`````DD(``%1```6.(@!$KC(`
+M-*XR`#BN(`!$CB(`1)9#``*.)``X`$,0(:R2``"N(@!$%F``"ZXR`#B2(@!`
+M)$(``:(B`$"/OP`@C[,`'(^R`!B/L0`4C[``$`/@``@GO0`PKD```(XC``".
+M(@`THB``0"1D`"0D4@`$KB``-`.@*"&,<``$#`!QJJ^@``".0P`()`(`$!!B
+M``J/H@``5$``"8XB``".`A?8)`,``5!#``6.(@``C@(:M!!#``<F$!J8CB(`
+M``)`*"$,``KTC$0`!!``_]V/OP`@#`!QR0(`("%00/_XCB(``(XD```,``N>
+M`D`H(0P`<=`"`"`A$`#_TH^_`"`,`!LI`D`@(1``_\Z/OP`@)[W_\*^_```0
+MX``-,*(`_Q!```8`P"@A#``:(@````"/OP```^``"">]`!",A```#``5:P#`
+M*"$0`/_ZC[\``!!```4`P"`A#``;*0`````0`/_TC[\```P`&QX`P"`A$`#_
+M\(^_```GO?_P,*(`_Z^_```40``&`,`H(0P`&Q8`````C[\```/@``@GO0`0
+MC((```P`":*,1``$$`#_^H^_```GO?_PK[\``(RG``",A``$`*`P(0P`6@0`
+M`"@AC[\```/@``@GO0`0)[W_\*^_```\`H`"C$(RY`"@,"$00``+D(4`,Y3"
+M``(D1P`$#`!:!(R$``2/OP``)`0``3P#@`*L9#+D`^``"">]`!`0`/_W)`<'
+M("2"`!PGO?_PK(``)```*"&OOP``#`!QAP!`("&/OP```^``"">]`!`GO?_P
+MK[````"`@"$DA``<K[\`"`P`<8ZOL0`$#`!PM0````".$0`DCB(```P`<+JN
+M`@`D`B`0(8^_``B/L0`$C[````/@``@GO0`0)[W_\*^P````@(`AK[\`"*^Q
+M``0,`'"U`*"((8X"`"2N(@``KA$`)`P`<+HF$``<#`!QHP(`("&/OP`(C[$`
+M!(^P```#X``()[T`$">]__"OOP`$K[````P`&N0`H(`AK%``!(^_``2/L```
+M)`,`(*Q#```#X``()[T`$">]__"LH``$K[\```P`&O<`````C[\```/@``@G
+MO0`0)[W_\*^_```\`H`"C$(RX`"`,"$``"@A#`!9[HQ$``2/OP```^``"">]
+M`!`GO?_PK[\``#P"@`*,0S+@`(`P(3P"B(B090`SC&0`!#1"B(@,`%GNK,(`
+M`(^_```#X``()[T`$(R"````@A`AK$4``(R"```D0@`$`^``"*R"```GO?_P
+MK[\`"*^Q``2OL````("((8R$````H(`A)`+__`(D("$`P"@AK)````(`,"$D
+MA``$)A```PP`<)T"`H`DCB(``(^_``@`4!`A)$(`!*XB``"/L```C[$`!`/@
+M``@GO0`0C(,``"0"`@``0Q`C$*```@"#("&LI```5,```:S"```#X``(````
+M`(R#```DI0`#)`+__`"B*"0`91@A`^``"*R#```0H``"```8(8RC````@Q`A
+MC$(`(!"@``(D8P`$K*,```/@``BLP@``C*(```""("$0P``")(0`(*S$```#
+MX``(`````">]__"OOP`$K[````P`:_(`@(`A)`,``:X#``RN`@``K@``"*X`
+M``2/OP`$C[````/@``@GO0`0)[W_\*^P``"OOP`$C((`.`"`@"$40``F)`0`
+M`0P`:LDD!``!#`!K\@````"N`@`L#`!K]20$``*.`@`````H(0P`%-^,1``$
+M%$``$P````".`@`P%$``#```("&.`@`X%$``!0``("&/OP`$C[````/@``@G
+MO0`0#`!K#P`````0`/_ZC[\`!`P`:P$`````$`#_\XX"`#@,`&OUC@0`+`P`
+M:LD``"`A$`#_[8X"`#@,`&L/`````!``_]@`````)[W_\*^P``"OOP`$C((`
+M.`"`@"$40``=)`0``8X"```D!0`!#``4WXQ$``000``%`````(^_``2/L```
+M`^``"">]`!`,`&OUC@0`+`P`:LD``"`AC@(`,!1```@D!``!C@(`.!!`__,`
+M`"`A#`!K#P`````0`/_PC[\`!`P`:P$`````$`#_]XX"`#@,`&L/`````!``
+M_^*.`@``)[W_\*^P``"OOP`(K[$`!(S#`"@D`@`!$&(`!@#`@"&/OP`(C[$`
+M!(^P```#X``()[T`$*S``#P,`'$T``````P`&[<"`"`AC@(`*!1``"```"`A
+M$(``$`````".`@`\/`,``C1C2?`D0@`!K@(`/(X"`#P`8A@K$&``!P````".
+M`@``C$(`!(Q1%^@D`@`!$B(`"@`````,`!S\C@0`!"0$``4,`'%)``````P`
+M<3L`````$`#_VX^_``@,`!N'`@`@(20$``L0`/_VKA$`*`P`'0..!``$#``=
+M(XX$``0\`P`"`$`@(1!```XT8TGPC@(`/"1"``&N`@`\C@(`/`!B$"M00``(
+MC@(`*(X"``",0@`$C$,7Z"0"``$08O_-`````(X"`"@40/_I`````!``_\@`
+M````)[W_\*^Q``2OL````*"((:^_``@,`'%"`("`(0(`("$"(#`A#``;W@``
+M*"&/OP`(C[$`!(^P```D`@`!`^``"">]`!`GO?_PK[```#P'@```@(`A/`B`
+M`"2)`"0DB@`().=PL"0$``LE"&]X```H(:^_``0,`'$(`@`P(8X"`"040``%
+M`$`@(8^_``2/L````^``"">]`!`,`'$F`````!``__J/OP`$)[W_\"0#``&O
+ML```K[\`"*^Q``00HP`1`("`(5"@`!*,@@`H)`(``A"B``PD`@`#4*(`!HR"
+M`"B/OP`(C[$`!(^P```#X``()[T`$%1`__JL@``H$`#_^8^_``BN```\$`#_
+M]H^_``@40/_TC[\`"(R"``",0@`$C%$7Z%8C__"/L0`$#``<]8R$``0,`'%"
+M)`0`!0P`&X<"`"`AKA$`*`P`<4DD!``+$`#_Y(^_``@GO?_PK[(`"`"`D"$D
+M!`!`K[$`!*^P``"OOP`,#`!Z5P"@B"$`0(`A$@``%```$"$``"@A)`8`0`P`
+M<*H"`"`A)@0`+*X2``"N$0`$#``;>:X``"@,`'%))`0`!`P`'#T"`"`AC@0`
+M!#P%@``DI7%8#``<UP(`,"$"`!`AC[\`#(^R``B/L0`$C[````/@``@GO0`0
+M)[W_\*^_``",@@`H%$``!```*"&/OP```^``"">]`!``0/@)C(0`+!``__N/
+MOP``)[W_\*^_``",@@`H%$``!"0%``&/OP```^``"">]`!``0/@)C(0`+!``
+M__N/OP``)[W_\*^_``",@@`H%$``!"0%``*/OP```^``"">]`!``0/@)C(0`
+M+!``__N/OP``)[W_\*^_``",@@`H%$``!"0%``./OP```^``"">]`!``0/@)
+MC(0`+!``__N/OP``)[W_\*^_``2OL````("`(8R$``2N!@`L/`:``*X%`"@D
+MQG*<#`!9U```*"&.!``$/`:``"3&<LP,`%G4)`4``8X$``0\!H``),9R_`P`
+M6=0D!0`"C@0`!#P&@``DQG,L#`!9U"0%``./OP`$C[````/@``@GO0`0)[W_
+M\*^_```,`%K'C(0`!(^_```#X``()[T`$">]__"OOP``#`!:SXR$``2/OP``
+M`^``"">]`!`GO?_PK[\```P`6N",A``$C[\```/@``@GO0`0)[W_\*^_``2O
+ML````("`(0P`6M>,A``$#``<_`(`("$,`!T#`@`@(8^_``2/L````^``"">]
+M`!`GO?_PK[```*^_``0,`!SU`("`(0P`6MN.!``$C[\`!(^P```#X``()[T`
+M$">]__"OOP``#`!:](R$``2/OP```^``"">]`!",@@`````H(8Q"0"`P1@#_
+M/`.``@`%$(`D8S,P`$,@(92"```DI0`!$,(`!2RC``A48/_X/`.``@/@``@`
+M`!`A`^``")2"``(D`A0`I((`"B0""9ZD@@`()`(`!:2"`!0D`@`$K((`8"0"
+M`!ZD@@`<)`()*J2"`'0D`@`'K((`>"0"``\D`P`")`4``20&``,D!P`\H((`
+M4R0"$`"LA0!(H(8`?*"#`'VL@@!4I(<`6JR```2@@P`6H(``%ZR%`'"LA@``
+MK(``:*R``&RL@`!,K(``9*R``#2D@`!<I(<`6*2``%X#X``(I(``?B>]_^"O
+ML````("`(20$'<BOLP`,K[$`!*^_`!"OL@`(#`!Z5P"@F"$00`!``$"((0!`
+M("$``"@A#`!PJB0&'<@\`J#`-$(`H(Q#```"("`AKC```#!B`/```A$",&,`
+M#ZXC!'P,`!TJKB($>`!`&"$``(`A/`*``B12,N@`$!#``%(0(91"```00P`&
+M)`(`"280``$J`@`)%$#_]SP"@`(D`@`)$@(`%20#``$,`'I7)`0`O*XB&_00
+M0``0)`/__P``*"$D!@"\#`!PJ@!`("$,`!T\)B0;:``0$,``4A`AC$(`!`!`
+M^`D"("`A%$``"P!`@"&N<0```@`8(8^_`!"/LP`,C[(`"(^Q``2/L````&`0
+M(0/@``@GO0`@#`!Z:HXD&_00`/_SKB`;]!``__(D$``")[W_\"0%``X``#`A
+MK[(`"*^Q``2OL```K[\`#`P`'<X`@)`A`$"((11```<``(`AC[\`#(^R``B/
+ML0`$C[````/@``@GO0`0`@`H(0P`*9X"0"`A)@(``3!0__\"$1`K%$#_^@(`
+M*"$0`/_RC[\`#(R"&_0LHP`4`*!`(21'`#008``*```H(3P"@`(`"!B`)$(*
+M[`!B$"&,0@```$``"```````9Q`AC$4```/@``@`H!`A,,(@`%!`__R4Y0!$
+M$`#_^I3E`$`PPB``4$#_]Y3E`$80`/_UE.4`0B0"`!`0P@`/+,(`$1!```8D
+M`@`1)`(``U#"_^V,Y0!($`#_ZR0%``$0PO_I```H(20"`"!4PO_F)`4``1``
+M_^2,Y0!,C((;S!!`_^&,Y0!0C.(`5!``_]X`HB@D)`(`$%#"_]N,Y0!@+,(`
+M$1!```8D`@`1)`(``U3"_]4D!0`!$`#_TXSE`%@0PO_1```H(20"`"!4PO_.
+M)`4``1``_\R,Y0!<)[W_L#P%@`(\!H`"K[``,*^_`$BOM0!$K[0`0*^S`#RO
+ML@`XK[$`-"3""XPDHPN$C*<+A(QH``2,20`,C$,`!(S&"XR,0@`(```H(0"`
+M@"&OIP`(KZ@`#*^F`!BOHP`<KZ(`(`P`.FZOJ0`D%$``:@!`("&.!0``C*)`
+M(#!#`/\P1``/``,9`B0"``6F`QSP$&(`[Z8$'/(T`H```*(0(8Q"&!@``#@A
+MI@(<]``'2(`!/1`AC@,``(Q1``@``"@A`'$8(8QC``"L0P`0C@(````%'```
+M91@E`%$0(:Q#``".`@``)*4``2RD`0``41`AC$(``%1#`$@D!``6%(#_](X"
+M`````#`A)Z4`&(RC```DQ@`!`%$0(:Q#``"."```+,0`!"2E``0!$1`AC$(`
+M`%1B`#DD!``65(#_](X"```!/1`AC$,`"(Q$`!`DX@`!,$?__P$#&"$LX@`"
+MK&0``!1`_],`!TB`#`!I/R0$`&2.`@``-`2``"0#``<`1!`AK$,8`(X"```D
+M`QP6```X(0!$$"&L0QC0C@,``"3B``$P1___-`:```!F&"$\`@`!+.0`"*QB
+M&(!4@/_XC@,``(X"```D!0`(`$80(8Q$'```!"8",((`#P`"$0``!"$"#`!8
+ME`""("4`0"`A,$,`\*8"'/8D`@`P$&(`D#""``\"`"`A)`4`P0P`+*\#H#`A
+M$$``"R0$`!:/OP!(C[4`1(^T`$"/LP`\C[(`.(^Q`#2/L``P`(`0(0/@``@G
+MO0!0)[4``@(`("$D!0`<#``LKP*@,"$40/_P)`0`%I>B``(40`!K)!0$```4
+M$$`D4?Z`#`!Z5P(@("$`0)@A$$#_YB0$``("(#`A`$`@(0P`<*H``"@AC@(;
+M]"01`,`"-!@KK%,`M!!@``P"8)`A`B`H(0(`("$"H#`A#``LKR8Q``$40``*
+M`C08*Y>B``*F0@``%&#_]B92``("@"@A#``@YP)@("$00``*`````!)@``8D
+M!0`6#`!Z:@)@("&.`AOTK$``M"0%`!80`/_#`*`@(0P`>E<D!``X$$#_]`!`
+MB"$`0"`A```H(0P`<*HD!@`XC@(;]`(@("$,`"#UK%$``!1`_^J7H@```@`@
+M(0)@*"$,`"7=IB(``!1`_^0F)@`"`@`@(0P`+*\D!0`_%$#_WP(`("&.!1OT
+M#``@MB2E`*040/_:``````P`'],"`"`A%$#_UB8%&Z(,`"QX`@`@(8H#&Z*:
+M`QNE%&``!20"__^6`ANF$$``$#P"``,D`O__4&(`"98#&Z:6`ANBE@0;I)8#
+M&Z8``"@AI@(;J*8#&ZP0`/_)I@0;JC0"__]48O_WE@(;HCP"``,T0G^_J@(;
+MHKH"&Z4D`JJJ$`#_[Z8"&Z8P0O_P`@`@(20%`!L"H#`A#``LKP`"HP`40/][
+M)`0`%I>B``(0`/^,`H*@)2Q"``440/]U)`0`%A``_VX"`"`A+((``A1`_W`D
+M!``6$`#_#S0"@``GO?_PK[$`!*^P``"OOP`,K[(`"(R"&_0`@(@A)`0`(`P`
+M>E>,4@"T$$``%P!`@"$`0"`A```H(0P`<*HD!@`@CB(;]`(`*"$"("`A#`!(
+M#JQ0``0``(`A`@`H(0(@("$,`"F>)A```2H"`(`40/_[`@`H(8XE&_0,`#\Y
+M`B`@(11```\`````$D```P`````,`'IJ`D`@(0P`'WP"("`A)`0`%H^_``R/
+ML@`(C[$`!(^P````@!`A`^``"">]`!`,`#3``B`@(0P`+V0"("`ACB0;]#P#
+M@`(D8RRT/!"``CP'@``\"(``/`J``ZR#`!BN(A?$)@E'L"3G2\`E"$VH)4JA
+M8```*"$"(#`A#`!Q"```("$,`'$FC@1'L`P`<4D``"`A#`!Z:@)`("&.(QOT
+M)`(`"@``("&L8@!H$`#_V:Q@`+0GO?_@K[0`$*^_`!2OLP`,K[(`"*^Q``2O
+ML```C)(;](Y0```2```=`("@(8X$``04@`!!`````(X$``@4@``Z`````(X$
+M``P4@``S`````(X$`!`4@``L````````F"$"`(@ACB(`%"9S``$40``B`$`@
+M(8XB`!PF,0`,%$``&@!`("$N8@`#5$#_]XXB`!0,`'IJ`@`@(:Y```".1``$
+M%(``#0`````"@"`A#``_1@)`*"&/OP`4C[0`$(^S``R/L@`(C[$`!(^P````
+M`!`A`^``"">]`"`,`'IJ`````!``__&N0``$#`!Z:@`````0`/_E+F(``PP`
+M>FH`````$`#_W8XB`!P,`'IJ``"8(1``_]0"`(@A#`!Z:@`````0`/_,C@0`
+M$`P`>FH`````$`#_Q8X$``P,`'IJ`````!``_[Z.!``(C(,;]"0"``XD8P`T
+M`^``"``#$`LGO?_0K[0`(*^R`!BOL``0K[\`)*^S`!ROL0`4C)$;]"0%`+\#
+MH#`ACB(```"`D"&GH``$#``LKXQ3``0F,``T%$``I@!`H"&.0AOTEZ,``(Q"
+M``"N(P`TE$(``"Q"4`,40`"_)Z8`!`)`("$,`"RO)`4`RA1``)D`0*`AEZ(`
+M!#!"#\```A%"-$(``:X"`#R.0AOTC$(``)1"```L0E`!$$``IR>F``*GH``"
+MEF(`$I9D`!"68P`4``(0@`""("4``QC`EF4```"#("4T@@`"`$4@"I9C``(`
+M@"@A-*(`$)>D````0R@*,*(``11```.N!```)`+__0"B*"0PH@`(%$``!"0"
+M"0@D`O_O`*(H)"0""0BF`@!$ED(<]C!"`/`L0@`P$$``A*X%``260QSP)`(`
+M!Q!B``4D`@G$)`(`"A!B``(D`@G$)`(*K*8"`$:7J``")`(3.*8"`$`D`A?4
+MI@(`0C$#``(D`@`!K@(`8*X``%P48``(```P(99#'/`L8@`&4$``!"0&``$D
+M`@`%4&(`8I9#'/*61!SP)`(``:X&`%@L@P`&K@(`4*X``$P08`!8```P(20"
+M``50@@!2ED(<\C$$__\`!!!".$(``20'``$P0@`!,0,``:X&`%2N`@!(K@<`
+M"*X'``P48``#```P(3"B``D``C`K``00PCA"``$P0@`!,0,`!*X&`!"N`@`4
+M%&```P``,"$PH@`)``(P*Y9B``:.9``8``49`C!C``&N!@`8K@,`(*X'`"2N
+M`@`HK@<`'!"```0``"@ACF(`'%1```,D`@`!)`4``20"``$Q`P'PK@(`,*X%
+M`"P48``"``,1`B0"``HQ`_``$&``'ZX"`#0``QL")`(``0!B$`2N`@`XCD(;
+M](Q#``"7H@`$,$(/P``"(4*48@``+$)0`Q1```.N!``\-((``:X"`#R"8@`@
+M`D`@(:X"`&2"8@`A#``?SJX"`&@"@!`AC[\`)(^T`""/LP`<C[(`&(^Q`!2/
+ML``0`^``"">]`#`0`/_D)`(`@"Q"``@40/^N,03__Q``_ZLD!@`!)`(``A!B
+M``,L8@`$5$#_G)9$'/`0`/^9)`8``1``_X0D`@G$`D`@(0P`+*\D!0#)%$#_
+MXP!`H"&7H@`"$`#_5*9B`#@"0"`A#``LKR0%`,H40/_;`$"@(9>B``0P0@P`
+M``(90JX#`#P0`/]"IZ(`!">]_]"OLP`<K[(`&*^Q`!2OL``0K[\`(`"@D"$`
+M@)@A``"((0"@@"$F)0"P`F`@(0P`+*\#H#`A)C$``0!`."$40``(*B0`!I>B
+M``"3HP`!``(2`J(#``"B`@`!%(#_\B80``*20P`+)`(`_Q!B``H``(@AHD``
+M#(^_`""/LP`<C[(`&(^Q`!2/L``0`.`0(0/@``@GO0`P`E$@(0)1*".`A@``
+MD*(`"B8Q``$J(P`%H((``!1@__B@I@`*$`#_[:)```LD!P#``.40*Q!```<`
+M`#`AE((``"3G``$`Y1@K`,(P)A1@__LDA``".,/__R0"`!8#X``(``,0"B>]
+M__"OL````("`(:^_``0,`'I7)`0!6*X"``000`!")`,``@!`("$``"@A#`!P
+MJB0&`5@,`'I7)`0#9*X"``@00``Y)`,``@!`("$``"@A#`!PJB0&`V2."0`(
+M)`(`"B0(``FE(@`4)`(``Z4B`AXE(P`<)`(`"R4(__^D8@``!0'__21C`#0`
+M`$`A`2`X(3P#@`(\`H`"``@@0"1C%X0D0A=\`((0(0"#&"&41@``E&,``"4(
+M``$`B2`A)`(`"RD%``.D@P(@I(8")J3B`C*DX@+.%*#_[B3G`#0,`'I7)`0`
+MB*X"``P00``/)`,``@!`("$``"@A#`!PJB0&`(@,`'I7)`0(`*X"`!`00``&
+M)`,``@!`("$``"@A#`!PJB0&"````!@AC[\`!(^P````8!`A`^``"">]`!`G
+MO?_@K[\`$*^S``ROL@`(K[$`!*^P``",@AOT`*!((3##__^,4P``EF(``"Q"
+M,`,40``ICG``")8&`!0``)`A`D80*U!``!"6`@`4`@`X(0`#$$``21`AE$@`
+M`"92``(D8P`!,00`_P`($@("1B@KI.(``*3D``(P8___%*#_]"3G``26`@`4
+M$$``#```D"$"`(@AEB4``)9D`````#`A#``HGB92``&6`P`4IB(```)#&"L4
+M8/_W)C$``H^_`!"/LP`,C[(`"(^Q``2/L````^``"">]`"```Q!``$40(91(
+M```D8P`!,&/__P!@*"$`"#%```@8@@`($D(PQ@!_,&,`?P`%($"F!@`$I@(`
+M`*8#``(`B2`AE(@``"2E``$PH___`&`@(0`($L(`""C```@9`@#","4PI0!_
+M,&,`?P`$$$"F!0`(I@8`!*8#``8`21`AE$@``"2$``$P@___`&`@(0`($T(`
+M"#A```@9@@"B*"4PYP!_,&,`?P`$$$"F!P`,I@4`"*8#``H`21`AE$@``"2$
+M``$PA/__``@I@``(,\(`"!("``@80C"E`'\P0@!_`.8X)3!C`'\`!"!`I@4`
+M$J8"``ZF!P`,I@,`$`")("&4B`````@2@@"B*"40`/^HI@4`$B>]_\"OMP`L
+MK[4`)*^Q`!2OOP`TK[X`,*^V`"BOM``@K[,`'*^R`!BOL``0C((;]##&__^O
+MI0``C%0``*^F``0``+@ACH(`!(Z2``@``(@AE%X`$@``J"$D`@`!```@(1*B
+M`'>/HP`$4J``<997`!0D`@`"$J(`9P`````2X`!5``"P(0`#$$"/HP```("8
+M(0!#@"&68@``)B<`"*8B``"6"@``)A```@`*((``"BD"``HR@C"E`#\PA``_
+MIB0`'J8F``2F)0`"E@H``"80``(`"DN"``I!```*$@(`"AB"`(D@)3$(`#\P
+M0@`_,&,`/Z8H`"2F)``>IB(`(*8C`"*6"@``)A```@`*&P(`"A&"`0-`)3!"
+M`#\Q0P`_IB@`)*8B`":F(P`HE@H``"80``(`"D"```H9`@`*$H(Q"``_,&,`
+M/Z8H`"ZF(@`JIB,`+)8*```F$``"``HC@@`*&((`"A("`01`)3!"`#\P8P`_
+MIB@`+J8B`#"F(P`R#``H>I:$``"6)P`&$.``#0``,"$"("@AA*(`'B3&``$`
+MQR`K``(80`!B&"$``QC``&(8(0`#&$"DHP`>%(#_]B2E``(FU@`!`M<0*R8Q
+M`#040/^Q)G,``B:U``$NH@`#5$#_GR0"``&/OP`TC[X`,(^W`"R/M@`HC[4`
+M)(^T`""/LP`<C[(`&(^Q`!2/L``0`^``"">]`$!3P/_P)K4``997`AXD8P!&
+M)E$"+!``_Y0F1`(@)&,`!291`!80`/^0`D`@(5/`_^4FM0`!EE<"'B1C`#<F
+M40+($`#_B29$`B8GO?^PK[X`0*^W`#ROM@`XK[4`-*^T`#"OL@`HK[``(*^_
+M`$2OLP`LK[$`)(R"&_0Y(P`!`2#P(8Q$```PUO__`0"H(8R"``24A````*"X
+M(21)`1"OH@`<)$(!"@!#2`LP\O__``"@(:^D`!@"P(`A%\``HP``0"$#TA`K
+M$$``(0`2$$(`$!!``%6((9(B``$`%!A`CZ0`&```,"$`?9@A$$``%P!`*"$,
+M`"B>`````":#``$P=/__EB,````4*$``O8@A``,:`H^D`!@``#`AIF(``!!@
+M``H`8"@A#``HG@`````F`P`!,'#__R:#``$P=/__`I(8*Q1@_^*F(@```!(0
+M0@+"$"$P4/__IO0`%!*``&$``$`A``@@0`"($"$`G1@A``(0@)1C````2!`A
+M``(00`!7,"$`$"A``)<@(:2#````M2@AI,,`&)2C```F`@`!,%#__P`#$$`P
+M0@$`,&,`_P!B&".DPP`<E*,````0($``E2`A``,3P@`"$@```QH"`&(8(Z3#
+M`""4@P``)@(``3!0__\``Q!`,$(!`#!C`/\`8A@CI,,`))2#````$"!``)4@
+M(0`#$\(``A(```,:`@!B2".DR0`HE((``"8#``$P</__,$(`'Z3"`!Z4@@``
+M`!`H0`"U*"$``A%",$(`'Z3"`"*4@@``)@,``3!P__\``A*",$(`'Z3"`":4
+MHP```!`00`!5."$``Q!`,$(!`#!C`/\`8A@CI,,`+)2C``"/I0`8``,3P@`"
+M$@```QH"`&(8(Z3#`"Z4X@``+*1``P`"&$`P8P$`,$(`_P!#$",4@``=I,(`
+M,*3)`"J4X@````(2`C!"`#^DP@`:)0(``3!(__\!%!@K)@(``11@_Z$P4/__
+MCZ,`'``>$$"/OP!$`$,0(91"`'Z/O@!`C[8`.*;B`!:/M0`TC[<`/(^T`#"/
+MLP`LC[(`*(^Q`"2/L``@`^``"">]`%"4X@``)`,``:3#`!H``AO"``,:```"
+M$@(`0Q`C$`#_X:3"`"H`"!!``$D0(91%```E`P`!,&C__R0"`/\`%!A`+08`
+M`R:$``$010`#`'T8(3"4__^D90``%,#_\P`($$`0`/]TIO0`%">]__"OL```
+M,+#__P`0$$"OL0`$`("((0!`("&OL@`(K[\`#`P`>E<`P)`AKB(``!!``#,D
+M`P`"`!`@@`"0("$`!""``)`@(0P`>E<`!""`$$``,JXB``BF,``$$@``)P``
+M,"$`!D"```880`$&$"$`<B`ACB4````"$(".)P`(E(0```!&$"$``A"``&48
+M(0!'$"&D9``````H(:1$```!!A`A``(0@``%&(``1A`A`&48(0`"$(``1R`A
+M``,8@`!D&"$DH@`!I&4`!#!%__\LH@`$%$#_\J1@``8DP@`!,$;__R0"``.D
+M@@!"`-`8*R0"``048/_;I((`!@``&"&/OP`,C[(`"(^Q``2/L````&`0(0/@
+M``@GO0`0#`!Z:HXD```0`/_V)`,``I2#`!8GO?_P)`+>K0"`8"&GH@`"I*,`
+M!J>B````8#@A```P(0``("$`AQ`',$(``1A```@LPP`"$&``@```$"$`!AA`
+M),(``0!]&"$P1O__I&0``"2"``$P1/__+((`!!1`__(`AQ`'E8(`%```2"$0
+M0`!QI*(`!``)&$``:1@A``,8@`!I&"$`"4"```,80`$)$"$!@Q@A``(0@(RJ
+M``B49``8`$D0(0`"$(``2A`AI$0``"1F`!B4PP`2I$,``I>C``(T`MZM$&(`
+M7@``("$!"1@A``,8@`!I&"$`!!"``$00(0`#6(`D@P`!``(0@#!D__\!:C@A
+M`$<0(2R#``048/_SI$``!I>C``"4Q``"``,0@`!#$"$``A"``$<0(:1$``B7
+MHP`"``,0@`!#$"$``A"``$<0(20#`!2D0P`(EZ,``@`#$(``0Q`A``(0@`!'
+M$"$D`P`CI$,`"I>C``(``Q"``$,0(0`"$(``1Q`A)`,`/Z1#``R7I`````00
+M@`!$$"$``A"``6(0(0!*$"$D1``$)`(`!*2"``*4PP`&E((`!`!#$"&D@@`&
+ME,,`"@!#$"&D@@`(E,,`#@!#$"&D@@`*E,(`!*2"``R4P@`(I((`#I3"``RD
+M@@`0E,(`$*2"`!*7I``"``00@`!$$"$``A"``6(0(0!*$"$D1``$)`(``Z2"
+M``*4P@`4I((`#)3"`!:D@@`.E,(`&*2"`!"4H@`$)2,``3!I__\!(A`K%$#_
+MD@`)&$`D`@`!`^``"">]`!`!"1@A``,8@`!I&"$`!!"``$00(0`#.(`D@P`!
+M,&3__P`"$(``ZA@A`$,0(2R#``048/_SI$``!I>D````!!"``$00(0`"$(``
+MXA`A`$H0(21$``0D`@`$I((``I3"``*D@@`$E,,`!@!#$"&D@@`&E,,`"@!#
+M$"&D@@`(E,,`#@!#$"&D@@`*E,(`!*2"``R4P@`(I((`#I3"``RD@@`0E,(`
+M$!``_\VD@@`2)[W^L*^W`3ROM@$XK[4!-*^S`2ROL@$HK[$!)*^P`2"OOP%`
+MK[0!,(R"&_0`@+`A`*"X(8Q"```PT?__`."0(8Q4``0``)@A``"H(0``@"$D
+M`@`!4@(`-I:"`!)2```XEH(`$"0"``)2`@`QEH(`%`.@("$``"@A#`!PJB0&
+M`1P"P"`A`Z`H(0(@,"$"H#@A`N!`(0P`(E4"`$@AEZ4`%`)`("$,`",F`Z`P
+M(0!`F"$40``3`$`8(0.@("$,`"-Q`D`H(1!```XD`___EZ,`%``#$(``0Q`A
+M`B(0(18```,P4?__)B(`!3!1__\F$``!+@(``Q1`_]8F4@`,`F`8(8^_`4"/
+MMP$\C[8!.(^U`32/M`$PC[,!+(^R`2B/L0$DC[`!(`!@$"$#X``()[T!4%!`
+M_^\F$``!$`#_S205``-00/_K)A```1``_\DD%0`*)[W_P*^W`"ROM``@K[\`
+M-*^^`#"OM@`HK[4`)*^S`!ROL@`8K[$`%*^P`!",@AOT,,;__Z^E``",4P``
+MKZ<`"*^F``2.8@`$``"X(0``H"&47@`2)`(``0``D"$``*@A$H(`<H^Q``12
+M@`!JCF,`#"0"``(2@@!=)B(`:::@```2X``X``"P(99B``"/I0```!$@0"8C
+M``$`A2`A+$(P`S!Q__\40`!/E)`````0$@*F0@`(ED4`"!"@`$@F(@`!%H``
+M1)9D`````#`A#``HG@````"F0@`(EF(``"Q",`,40``Z`!`8P``0&0``$!""
+M,$(`/S!C`#^F0P`$ID(`!I9B``"/I0```!$@0"8C``$`A2`A+$(P`S!Q__\4
+M0``CE)```)9#``0`$","`!`1@@!D&"4P0@`_,@0`/Z9#``2F0@`"ID0``):B
+M```D0@`!IJ(``";6``$"UQ`K%$#_RB92``HFE``!+H(``Q1`_[HD`@`!CZ(`
+M"(^_`#2/O@`PI%$``(^W`"R/M@`HC[4`)(^T`""/LP`<C[(`&(^Q`!2/L``0
+M`^``"">]`$"60P`$`!`@0@`0*T(`$!'"`&48)3!"`#\0`/_=,(0`/Q``_\@`
+M$!#"$`#_O20&``$0`/_=,%'__Q``_[(`$!)"%\``!#!1__\F(@`&$`#_VC!1
+M__^.8@`,)!<``R15`%(0`/^;)%(`5"8B`%4P4?__`&"H(207``@0`/^5)'(`
+M`B8B`&4P4?__$\#_\"8B``2.8@`,)!<``B15`'(0`/^,)%(`=">]_]"OM@`8
+MK[0`$*^Q``2OOP`@K[<`'*^U`!2OLP`,K[(`"*^P``",@AOT`*"@(3#1__^,
+M50````"P(8ZC``248@$6$$``$8ZR`!``%KA``N,0(91"`1@40``7EJ(``"8C
+M``@F)``'+$(P`P!@B"$`@H@+CJ,`!";6``&48@$6`L(0*Q1`__$F4@!`C[\`
+M((^W`!R/M@`8C[4`%(^T`!"/LP`,C[(`"(^Q``2/L````^``"">]`#`L0C`#
+M%$``0``1$$``5#`A``"8(0)`*"&4R```)G,``BYD``@Q`P#_``@2`J2B``"D
+MHP`(),8``B8Q``$4@/_V)*4`$``1$$``5$@A``"8(0)`."&5*```)G,``BYF
+M``@`""&"``@2`@`(&X(P0@`_,&,``3"$``$Q!0`_I.(``JSC``2DY0`*K.0`
+M#"4I``(F,0`!%,#_[R3G`!```)@A`D"`(8X"``!00``/)G,``8ZB``0"XA`A
+ME$(!&#!#``<08``.```P(20"``,08@`,EJ0``)8%```D!@`!#``HGB9S``&F
+M`@``+F(`"!1`_^TF$``($`#_LHZC``26I```$`#_]I8%````5!`AE$@``"8Q
+M``$`$2!```@I0``(&((`"!)",*4`?S!C`'^F10`0ID(``*9#``@`E"`AE(@`
+M`"8Q``$`$3!```@:P@`((,``"!$"`*,H)3"$`'\P0@!_ID0`(*9%`!"F0@`8
+M`-0P(93(```F,0`!`!$H0``(&T(`"#!```@1@@"#("4PQ@!_,$(`?Z9&`#"F
+M1``@ID(`*`"T*"&4J```)C$``0`1.$``""/"``@I```($@(`"!B"`,0P)3"E
+M`#\P0@!_,&,`/Z9%``JF0@`XID,``J9&`#``]#@AE.@``"8Q``$`$2!```@;
+M`@`($8(`HR@E,$(`/S$#`#^F10`*ID(`$J9#`!H`E"`AE(@``"8Q``$`$2A`
+M``@@@``(&0(`"!*",(0`/S!C`#^F1``RID(`(J9#`"H`M"@AE*@``"8Q``$`
+M"!H"``@3@@""("4P8P`_ID0`,A``_XZF0P`Z)[W_T*^U`"2OM``@K[,`'*^_
+M`"BOL@`8K[$`%*^P`!",@AOT`*`P(0"@H"&,4@```("8(0``J"$,`"8TCD4`
+M!)9B'/8P0@#P+$(`,%1```:60@``CD(`!)1"`"@00``I)`,`%I9"```D$`"0
+M)!$`0"Q",`,"`#`A`B(P"P)@("$,`"%$`H`H(99"```"`#`A+$-``"Q",`,4
+M8``&`B(P"XY"``240P`H)`(``1!B`",F1P`4`F`@(0P`(;X"@"@AED,``"QB
+M0``40``8+&,P`XY"``240@`L)$+^ZS!&__\"8"`A`H`H(0P`)($#H#@AEZ8`
+M``)@("$,`"45`H`H(0*@&"&/OP`HC[4`)(^T`""/LP`<C[(`&(^Q`!2/L``0
+M`&`0(0/@``@GO0`P)`8`D"0"`$`0`/_J`$,P"P)@("$,`"0M`H`H(0!`J"$4
+M0/_M`$`8(1``_]N60P``)[W_T*^V`!BOLP`,K[(`"*^_`""OMP`<K[4`%*^T
+M`!"OL0`$K[```(R"&_0`H)`A`,"8(8Q"``"45```)`(`#Z"B`"(NEC`#)`(`
+M#Q;``BVDH@`F/`*``B17,V@D`@`@I*(!%H[B```D4?]``!$00`!3$"&44```
+M`!`3@@`0&L(`$"D"`!`PP@`0.((`$$!",&,`!P`02\(P0@`!,*4`?S#&``$P
+MYP`!,0@``:9#``:F0@`$ID4`"*9)``"F1@`"ID<`%`P`*+RF2``2CN0`!#(#
+M``$`0Q`E))'_0``1&$"F0@`0`',8(91P```N@T``))'_00`0$@*B0@`@%&``
+M%:)0`"$`$1!``%,0(910```DD?]"`!$80``0$X*F0@`H`',8(0`0*P(`$"-"
+ME'```#"$``$PI0`!`!`3@C!"``$R`P__KD0`&*Y%`!RF0P`LKD(`-```J"$`
+M%1"``%<0(8Q)``@`%6!``9(X(24Q_T``$1!``%,0(910```E,?]!).8`B``0
+M*0``$!("`!`8@@`1($`PI0`_,$(`?S!C`#^DQ0`"I.(`/*3C`$8`DR`AE)``
+M`"4Q_T(`$2!``!`;`@`0$8(`HR@E,$(`/S(#`#^DQ0`"`),@(:3B`)"DXP"6
+ME)```"4Q_T,`$2!``!`H@``0$0(`$!J",*4`/S!"`#\DZP"FI.,`G*3B`*(`
+MDR`AI64``I20```E,?]$`!%`0``0(X(`$#$``!`2`@`0&((`I"@E,,8`/S!"
+M`#\P8P`_).H`N*5E``(!$T`AI.(`KJ3C`+2E1@`"E1```"4Q_T4`$2!``!`;
+M`@`0$8(`PS`E,$(`/S(#`#^E1@`"`),@(:3B`,"DXP#&E)````*R0"$`$!("
+MH0(`:"0"``$2H@&3)3'_1BJB``(40`&$)`(``A*B`7T`$!$"%J``%P`1$$``
+M4Q`AE%```)9&`.HF,0`!`!`[P@`0$P(`$!I"`!`A@@`0*,(`QS`E,$(`!S!C
+M``<PA``',*4`!S('``>F1@#JID(`[*9#`.:F1`#HID4`XJ9'`.0`$1!``%,0
+M(910```F,0`!`9)0(3($`/\`$!H"`!$00*5#`%"E1`!6`%,0(910```F,0`!
+M`!$80#($`/\`$!("I4(`7*5$`&(`<Q@AE'```"5%`'`F,0`!`!`2`C($`/\R
+M`P"`H0(`;1!@``2DI``".((`_P`"$">DH@`"`!$00`!3$"&44```+H5``"8Q
+M``$`$!E"`!`@0C!C`/\PA``/,@(``:5"`(2E0P!X%*``!J5$`'X2H`$T`!`3
+M0B0"``(2H@$N`!`30A;``!$N@C`$`!$00`!3$"&44````9(8(0`0$8(P0@!_
+MI&(`S"0"``$2H@$<)C$``2JB``(40`$4)`(``A*B`0T`$!#"+H(P!!1``00`
+M%1!``!480`!R&"$`$"-")&,`T``1$$"D9``"`%,0(910```F,0`!`!`0P#!"
+M`#@`@B`E)`(``A*B`.VD9``"%J``"2Z"0``4H``'`!`8P@`0$@(P0@`_,&,`
+M'Z9"`0*F0P$&+H)``!1``#`FH@`!)`(``1*B`,$D`@`"$J(`:P`1$$`6H``I
+M)J(``2Z"0`$40``F)J(``0`1$$``4Q`AE%```"Z#4``F,0`!,@(`/Q1@`!VF
+M0@#8`!`1@@`0,T(P0@!_`!$80*9&`$RF0@!"`',8(91P```F,0`!`!$H0#("
+M``<``A#``!`8P@`0(D(`PC`E,&,`/Z)$`&NF1@!,ID,`W@"S*"&4L```)C$`
+M`3("``$``A'``((@)0`0$$*B1`!KHD(`<":B``$P5?__+J(``Q1`_O\`%1"`
+M4L``$X[B`!0`$1!``%,0(910```F,0`!`!$@0``0$,(R`P`',$(`!Z9#`/JF
+M0@#^`),@(920````$!#",$(`!S(#``>F0P#\ID(!`([B`!261P$6``"H(1#@
+M``\D4?]``!$00`!3,"&4T```)J,``@`5$$`P=?__`%(0(3(#`/\`$"("`J<H
+M*Z1#`1JD1`$8%*#_]23&``(2P``+C[\`("0"_\HD`___)`0`'*9"`'(D`@`/
+MID0`6J9#`':F0@!6ID,`=*9$`%B/MP`<C[8`&(^U`!2/M``0C[,`#(^R``B/
+ML0`$C[````/@``@GO0`P`%,0(910```"@"`A)`8``0P`*)XR!0#_)C$``0`0
+M*@("@"`A)`8``0P`*)ZF0@$*`!$80*9"`0P`<Q@AE'```"8Q``$`$2!``!`1
+MPC(#`'\P0@`_ID,`"J9"``X`DR`AE)```"0&``$"@"`A#``HGC(%`/\N@T`!
+MID(!#A1@``0F,0`!`!`2`C!"`#^F0@#<`!$00`!3$"&44```+H1``B8Q``$`
+M$!%",$(`/S(#`!^F0@$$%(``!J9#`0@`$1!``%,0(910```F,0`!HE``(BZ"
+M4``40/^*)J(``0`0$@(`$#/",$(`?P`1&$"F1@!.ID(`1`!S&"&4<```)C$`
+M`0`1*$`R`@`?``(00``0&4(`$"+"`,(P)3!C`#^B1`!LID8`3J9#`.``LR@A
+ME+```"8Q``$R`@`'``(10`""("4`$!#"HD0`;!``_VRB0@!Q`!$00`!3$"&4
+M4````H`@(20&``$,`"B>,@4`_R8Q``$`$"H"`H`@(20&``$,`"B>ID(!$``1
+M&$``<Q@AID(!$I1P```"@"`A)`8``0P`*)XR!0#_+H-``:9"`1048/]3)C$`
+M`0`0$@(P0@`_$`#_3Z9"`-H`$!#",$(`_RZ#0`848/\0ID(`)``0$L(0`/\-
+MID(`)@!2$"$D`P`*I$,`TB0"``\0`/\0ID(`)#!"``<R`P`'ID,`_!``_O"F
+M0@$`%J#^[RZ",`0R`@`_$`#^ZZ9"``P`$!#",$(`!S(#``>F0P#Z$`#^Y:9"
+M`/XP0@`!$`#^T:9"`#`P0@`!$`#^SJ9"`"XP0@`',@,`!Z9"`/80`/Z`ID,`
+M^!:@_I8`$1!``!`00``0&4(`$""",&,`!S"$``<P0@`'ID,`[J9$`/`0`/YT
+MID(`Z@`0$0(P0@`',@,`!Z9"`/(0`/YNID,`]"0"`!"DH@$6/`*``A``_=0D
+M5S-0,(3__RR$,`(PI?__%(``'3#&__\\`H`")$D7I```0"$`"!!``$D0(91$
+M```D`@!D/`-1ZP!$$",`10`8-&.%'R4"``$P2/__+0(`"W"&`````"`2````
+M````````@P`8``0GPP``&!```QE#`&08(Z3C```40/_J).<``@/@``@`````
+M/`*``A``_^0D21>,,*7__R0"`/\P@___$*(`"20'`/\0P``)``40@"QB,`-0
+M0``")*((_"2B"6`P0O__`$`X(0/@``@`X!`A`$40(21"$L`L8S`#$&#_^3!"
+M__\LH@`_%$``!``%$(``11`A$`#_\B1"%2(`11`A``(00!``_^XD0A/L)[W_
+MX"0%`+\#H#`AK[``$*^_`!0,`"RO`("`(1!```8``!@AC[\`%(^P`!``8!`A
+M`^``"">]`"".`AOT)`,`SR0%`,J,0@```@`@(0.@,"&40@``+$)```P`+*\`
+M8B@+C@(;])>C``",1```,&:``#!C"`"4@@```$`@(2Q"0``X0@```,(8"S!B
+M__\LA$````(KPCB$`````A+"`*00"Z>C``"GH@``$`#_WC!#__^,@@``C$)`
+M"#A"``$#X``(+$(``2>]_^"OLP`,K[$`!*^P``"OM``0K[(`"*S```",BP``
+M)`+__P"@F"&-:0"``,"`(0"`4"$D!?__$2(`.```B"&,@QM`/`0!!32$V#`!
+M(Q@D/`(`@`$D0"0Q)0`%`&)H)#4"``$`14`+/!(`(#!G``4P9@%`-0(`0`!R
+MR"0Q)0%`,&P`@`!D&"0`14`+-&(``0!'&`LT8@!`/!0#_SP8(``Q+P`@,2X`
+M@!&@``(`1A@+C7$`C`&#&"4"."`D$:```@!X$"4`1!@+`'(0)0!9&`L!XQ@E
+M$<``#`!@*"&-8P"$)`+_?P$B2"0`=!@D``,<`JX#`````Q0`C4,```!4$"0U
+M"`"`K&(`A(U"``"N:```K$D`@(U"``",0@"`C[0`$(^S``R/L@`(C[$`!(^P
+M````H!`A`^``"">]`"`\`@$%-$+8,#"H`$`PJ0`!,*H`@`2A``\`@#`AC(,;
+M](QB`!000``#)$3__ZQD`!2,8@`4%$```R0"``&,PP``K&(`)`/@``@`````
+M`^``"`````",@P```*(H)(QB`"0X0@`!+$<``5#@``6,PAM`K&``)(R"``",
+M0@`DC,(;0(S$```T0P%``&@0"S1#``4`:1`+`4(0)0!%$"6L@@"@C,0``(R#
+M`*`0X/_FK,(;0"0"``&L@@`D$`#_Y``````$HP`+C(,``(R#&_2,8@`4)$(`
+M`:QB`!2,@@``K$``)(R"``",0@`D`^``"`````",8@`D.$(``2Q'``$0X``%
+M,*(`0*Q@`"2,@@``C$(`)#"B`$`00``#C(8;0"0"_K\`PC`D,*(``1!```0P
+MH@"`)`+_^@#","0PH@"`$$``!#P"`04D`O]_`,(P)#P"`04T0M@PC(,```"B
+M*"0`!1`G`,(P)*QF`*",@P``C&(`H!#@_]VLAAM`)`(``:QB`"0#X``(````
+M`(R#```T`H@```4I0`"B*"$`91@AK&```(R"```D`P`'`$40(:Q```2,@@``
+M`$40(:Q```B,@@```$40(:Q```R,@@```$40(:Q``!",@@```$40(:Q#`!2,
+M@@```$40(:Q``!B,@@```$40(:Q``!P#X``(`````">]_X"OM0!D/!6JJC:U
+MJJHD`@`'K[X`<*^W`&ROM`!@K[(`6*^Q`%0`P)`AK[\`=*^V`&BOLP!<K[``
+M4`#@B"&OH@`T`("@(0"@N"$`"*@*KZ``!*^@`````#`A$.``00``\"&4XP`,
+M+&(`(1!``!,``Q"`/`.``B1C"^0`0Q`AC$(```!```@`````E.4`-"3P`#8D
+M`@`%KZ(`-"0"`&@0H@(#**(`:1!``?\D`@"`)`(`*%"B``Z2`@`%C[\`=(^^
+M`'"/MP!LC[8`:(^U`&2/M`!@C[,`7(^R`%B/L0!4C[``4`/@``@GO0"`D@(`
+M!9(#``22!``&D@4`!P`"$@``8A@E``0D``!D&"4`!2X``&48)0!U&"8P8___
+M``,0)S!"__^OH@`4KZ,`!)(#``&2`@``D@0``I(%``,``QH``$,0)0`$)```
+M1!`E``4N``!%$"4`51`F``(8)Z^C``ROH@``$D``%#0%@`"20@`#DD,``I)$
+M``&210`%``(6```#'`"21@`$DD<```!#$"4`!"(``$00)0`%*@``IC`E`$?P
+M)0`>\$(`!A?``\+P)0`&,$(T!8``-,:``*^E`$2OI@!($B``!:^@`#R6(P`,
+M)`(`$!!B`"H"@"`A```P(0.@."$`%Q#`CH,```!&$"&,Y0`,``(0@#0(B```
+M2!`A),8``0!B&"$LQ``(K.(`"*QE```4@/_S).<`"(Z"````%R%`CZ,```""
+M$"$`2!`AK$,``(Z"```T`X@$`((0(0!#$"&/HP`$K$,``(Z"```T`X@8`((0
+M(0!#$"&L7@``CH(```""("$T`H@<`((@(8^B`$BL@@``$`#_D8^_`'0D!0`2
+M#``=SB0&`!`00/_4```P(1)``0,GI``(```H(0P`<*HD!@!`)`(`!"8P`!2O
+MH@`TD@,`#9("``R2!``.D@4`#P`#&@``0Q`E``0D``!$$"4`!2X``$40)0!5
+M$":OH@`LD@,`"Y("``J2!``,D@4`#0`#&@``0Q`E``0D``!$$"4`!2X``$40
+M)0!5$"8P0O__KZ(`))(#``>2`@`&D@0`"``#&@"2!0`)`$,0)0`$)```1!`E
+MCZ0`!(^C````!2X``$40)0`$("<`51`F,(3__P`#&"<T!8```@"0(:^B`!RO
+MI``4KZ,`#*^E`$2OH``\,O/__P``,"$#H#@A`!,0P(Z$````1A`AC.4`##0#
+MB````A"``$,0(23&``$`@B`A+,,`"*SB``BLA0``%&#_\R3G``@F,`!&)N(`
+M0">D``@``"@A)`8`0`P`<*HP4___D@,``9($``*2(@!&D@4``P`#&@``0Q`E
+M``0D``!$$"4`!2X``$40):^B``R2`P`%D@(`!)($``:2!0`'``,:``!#$"4`
+M!"0``$00)0`%+@``11`EKZ(`'```,"$#H#@A`!,0P(Z#````1A`AC.4`#``"
+M$(`T"(@``$@0(23&``$`8A@A+,0`"*SB``BL90``%(#_\R3G``B.@@``CZ,`
+M```7L4`"PA`A`$@0(:Q#``".@@``-`.(!">D``@"PA`A`$,0(8^C``0``"@A
+M)`8`0*Q#```FX@`@#`!PJC!3__\D`@`$KZ(`-))#``V20@`,DD0`#I)%``\`
+M`QH``$,0)0`$)```1!`E``4N``!%$"4`51`FKZ(`+))#``N20@`*DD0`#))%
+M``T``QH``$,0)0`$)```1!`E``4N``!%$"4`51`F,$+__Z^B`"220P`'DD(`
+M!I)$``B210`)``,:``!#$"4`!"0``$00)0`%+@``11`ECZ0`!`!5$":/HP``
+MKZ(`'(^B`$@`!"`G,(3__P`#&">OI``4KZ,`#*^^`#ROH@!$```P(0.@."$`
+M$Q#`CH0```!&$"&,Y0`,-`.(```"$(``0Q`A),8``0""("$LPP`(K.(`"*R%
+M```48/_S).<`""8P`$XFX@!@)Z0`"```*"$D!@!`#`!PJC!3__^2`P`!DB(`
+M3I($``*2!0`#``,:``!#$"4`!"0``$00)0`%+@``11`EKZ(`#)(#``62`@`$
+MD@0`!I(%``<``QH``$,0)0`$)```1!`E``4N``!%$"6OH@`<```P(0.@."$`
+M$Q#`CH0```!&$"&,Y0`,-`.(```"$(``0Q`A),8``0""("$LPP`(K.(`"*R%
+M```48/_S).<`"(Z"```T`XP``L(0(0!#$"&/HP``K$,``(Z"```T`XP$`L(0
+M(0!#$"&/HP`$K$,``!``_HB/OP!T)[(`"`)`("$``"@A#`!PJB0&`$`D`@`$
+MKZ(`-"8P`!22`P`-D@(`#)($``Z2!0`/``,:``!#$"4`!"0``$00)0`%+@``
+M11`E`%40)J^B`"R2`P`+D@(`"I($``R2!0`-``,:``!#$"4`!"0``$00)0`%
+M+@``11`E`%40)C!"__^OH@`DD@,`!Y("``:2!``(D@4`"0`#&@``0Q`E``0D
+M``!$$"4`!2X``$40)8^D``0`51`FCZ,``*^B`!R/H@!(``0@)S"$__\``Q@G
+MKZ0`%*^C``ROO@`\KZ(`1#+S__\``#`A`Z`X(0`3$,".A````$80(8SE``PT
+M`X@```(0@`!#$"$DQ@`!`((@(2S#``BLX@`(K(4``!1@__,DYP`()C``3@)`
+M("$FX@!````H(20&`$`,`'"J,%/__Y(#``&2(@!.D@0``I(%``,``QH``$,0
+M)0`$)```1!`E``4N``!%$"6OH@`,D@,`!9("``22!``&D@4`!P`#&@``0Q`E
+M``0D``!$$"4`!2X``$40):^B`!P``#`A`Z`X(0`3$,".@P```$80(8SE``P`
+M`A"`-`B(``!($"$DQ@`!`&(8(2S$``BLX@`(K&4``!2`__,DYP`(CH(````7
+M(4"/HP```((0(0!($"&L0P``CH(```""("$T`H@$`((@(1``_G2/H@`$%*+^
+M!8^_`'0D`@!H$*(`)I(#``V2`@`,D@0`#I(%``\``QH``$,0)0`$)```1!`E
+M``4N``!%$"4`51`FKZ(`+)(#``N2`@`*D@0`#)(%``T``QH``$,0)0`$)```
+M1!`E``4N``!%$"4`51`F,$+__Z^B`"22`P`'D@(`!I($``B2!0`)``,:``!#
+M$"4`!"0``$00)0`%+@``11`E`%40)A``_>BOH@`<D@(`#)($``Z2!0`/``,:
+M``!#$"4`!"0``$00)0`%+@``11`E`%40)A``_]HP0@#_E.4`"B0"`&@0H@`-
+M)/``%"BB`&D00``&)`(`@"0"`"A0HOV^KZ``-!``_;TD`@!H5*+]NR0"`&@0
+M`/VW)`(``Q``_;4D`@`!C((;])3E`#0D`P`&C$0`C"0"``<D\``V`$08"A``
+M_:VOHP`TE.4`"B3P`!00`/VH)`(`!)3E``HD\``4$`#]I"0"``<D`W__$*,`
+M%0`'4"N,@AOT,*7__P!@2"&,0@!$`*=("Q!```X`H$`A)`(`$!#"``DDI0`@
+MC((```$$&"&L2`0`C((``*Q*!`2@9QT!`^``"`$@$"$0`/_W,*C__Q``__LD
+M"7__,,;__RS&``T4P``1```8(8R"&_0D`P`!B$0`I)A$`*>(1@"HF$8`JXA'
+M`*R81P"O@$@`L*BD``"XI``#J*8`!+BF``>HIP`(N*<`"Z"H``P#X``(`&`0
+M(8R$&_0PI?__C(,`-!!E``(``!`AK(4`-`/@``@``````^``"```$"$GO?_@
+MK[$`%`.@,"$`H(@A)`4`'Z^R`!BOOP`<`("0(0P`+*^OL``0`D`@(0.@,"$0
+M0``))`4`'B0$`!:/OP`<C[(`&(^Q`!2/L``0`(`0(0/@``@GO0`@E[```).C
+M``$`$!("HB,``0P`+*^B(@```D`@(20%`!T40/_O`Z`P(9>B``"3HP`!`@*`
+M(0`"$@*B(P`##``LKZ(B``(40/_G)`0`%I>B``"3HP`!/`4``@("@"$``A("
+M```@(32E__VB(@`$$@#_W*(C``46!?_<C[\`'!``_]HD!``6)[W_\`"@("&O
+MOP``#`!K4B0%``&/OP`````0(0/@``@GO0`0`^``"`````",AP``)`(``20#
+M``*,YD`0`$48"B0"_Y\`PC`D``,90`##,"6LYD`0C(8``#P"@`*,0S.`C,5`
+M$#P"__$T0O__`*(H)``#'$`\`@`.`&(8)`"C*"6LQ4`0C(8``#P"@`*,0S.$
+MC,5`$#P"_X\T0O__`*(H)``#'0`\`@!P`&(8)`"C*"6LQ4`0C(4``#P"@`*,
+M0S.(C*1`$#P"_W\T0O__`((@)``#'<`\`@"``&(8)`"#("6LI$`0`^``"```
+M````@$`A$*``,P#`2"&(HP``F*,``XBB``"8H@`#B*0``)BD``.4I@`$,&/_
+M`(BJ``"8J@`#``,:```"%@``!"("`$,0)3"$_P`PPP#_`$00)0`*+@(``QH`
+M``8R`@!%*"4`9A@EC0(``#0$@``\!O^``$00(:Q%``B-`@``-,;__P!$$"&L
+M0P`,C0,```!D&"&,8@`,,$+__ZQB``P1(``+).(`!(T#`````A0``&0@(3P#
+M`'\`0Q@DC((`(!#@``(`1A`D`$,0):R"`"`#X``(````````&"$0`/_B```H
+M(2>]_]"OOP`@K[,`'*^R`!BOL0`4K[``$(RC`!",I@`4`*"`(5!@``$```'-
+M`,,`&XX"``P#H"@A`("((0``F!(```````````!B`!L``)`2#``M[0````"/
+MHP`$CZ(``(X&``2.!0`(``,=@``"$H(`8D@EC@,``(X(``PE(@`"),;__P!H
+M("$F9___`((8*P3``*&N!```5&#_]XX#``!PR#@"C@(`$(X#`!@`Y#`A<*(@
+M`JX&``0`AA`A$&``C*X"``B.)```-`6``#P#`!``A2`AC((`!`!#$"6L@@`$
+MCB(``(X#`!0`11`AK$,`)(XB``".`P`8`$40(:Q#`#B.(P``C@(`"`!E&"$`
+M`A#`K&(`,(XB``".`P``-!*```!2$"&L0P`HCB,``)8&``X\$___`'(8(8QB
+M`"`"("`A/`6```!3$"0`1A`EK&(`(`P`*6P`````CB(;0(XD```\`__[-&/_
+M_P!#$"2N(AM`K((`H(XB'82.)```/`7__P!#$"2N(AV$C@(`(`"2("&,@P`8
+M-*4`_P`"$@``91@D,$+_``!B&"6L@P`8CB(;0(XD```\`P`$`$,0):XB&T`\
+M!8``K((`H`P`*3P"("`AC@,`'(X"``P`0Q`K5$```:X#``R.`@`0`$,0*U1`
+M``&N`P`0C@,`#(X"`!!08@`ZC@(`!(X"``2.(P``/`8`!P`"$,`TQO__)$+_
+MZ`!R&"$`1A`DK&(`U(XC```\!0#_-*7__P!R&"&,8@#4/`<*`#P$`!@`11`D
+M`$<0):QB`-2.(P``C[\`(`!R&"&,8@#4`$00):QB`-2.`@``CB,````"$,`D
+M0O_H`$80)`!R&"&L8@#8CB,```!R&"&,8@#8`$40)`!'$"6L8@#8CB(``)8#
+M``X`4A`AK$,`W(XD``".`P`0C[$`%`"2("&,@@#<``,<``!S&"2/L@`8C[,`
+M'(^P`!`P0O__`$,0):R"`-P#X``()[T`,!``_\:N`@``CB,``#0"@``\!/_O
+M`&(8(8QB``0TA/__`$00)*QB``00`/^!CB(``"2E__\HH@``)D;__Q``_UP`
+MXB@+C((``#0&@```1A`AC$(`3*BB``"XH@`#C((```!&$"&,0P!0C$(`4*BB
+M``2XH@`'B*(`!)BB``<00P`&`````(R"````1A`AC$(`3*BB``"XH@`#`^``
+M"`````",@P``-`6``#P&`0``91@AC&(`(`!&$"6L8@`@C(,```!E&"&,8@`@
+M`$80):QB`"`#X``(`````(R#```T!X```(!`(0!G$"&,1``$C&(`%#P%_Y^5
+M!AMR-$(`(*QB`!2-`P``-*7__SP"`((`A2`D`((@)0!G&"$PQC<`)`(4`*QD
+M``10P@`#C0,```/@``@`````)`(#<*T`'/RL8A!P$`#_^@````"4@AMR```8
+M(3!"`@`00``UC(D<")"K```18``.``!`(0"H$"&00@`!)0@``0$+4"HP1@!_
+M,$(`@!!```0`PS@K5.```0!@,"$PPP#_%4#_]0"H$"&-)@``&,``"0``."$E
+M)0`RD*(``!!#``4DI0`8).<``0#F$"I40/_[D*(``!C```L``$`A)24`,P#H
+M$"I40``"H*<``*"H``"-(@``)0@``0$"$"H40/_X)*4`&%!@``Z,@P````,0
+M0BQ"``-00``*C(,``(R$```T`H``/`,"``""("&,@@`$`$,0):R"``0#X``(
+M`````#0"@``\!/W_`&(8(8QB``0TA/__`$00)*QB``0#X``(`````(R#```T
+M`H```&(H(8RB&&0``A3",$,!`#!$`?\08``".((!_P`"(">,H@!0C*,`3`!#
+M$"8#X``(`$00)B2C__\L8@`%`*#`(1!``#L`@'`A``,0@#P#@`(D8PRL`$,0
+M(8Q"````0``(`````(R"```T#X``)(T$@`!/$"&,1`"0C:(`3(VC`%B-QP2`
+M`$00(:VB`$R-P@``C:@`8(VD`%"-I0!4`$\0(8Q"`(R-J0!DC:L`:`!B&"&M
+MHP!8C<P``(VJ`&P!CS`AC,(`E`#B."&MQP2`C,,`B(V&!A```!`A`((@(0$&
+M0"&MJ`!@C<(```"C*"$`HS@KC$(&%`"'("&MI`!0K:4`5`$B2"&MJ0!DC<(`
+M`(Q"!A@!8E@AK:L`:(W"``",0@8<`4)0(20"``(3`@`$K:H`;```("$#X``(
+M`(`0(8W&``"-I``(C:4`#```$"$`SS`AC,,`F`""("$`HR@A`*,P*P"&("&M
+MI``(K:4`#!``__$``"`AC(0``(R#`$`T8@`$K((`0(W$```D`O_[`&(8)*R#
+M`$`0`/_G```@(8R"```T`X`````@(0!#$"&,10#XC$,`]"RB`&040/_>````
+M`#P"4>LT0H4?`*(`&0``$!```BE")`(`9`!E`!M0H``!```!S0``&!(0`/_2
+M`$,@(U#`_]```"`AC((``#0#@```0Q`AC$4`[*S%``",@@```$,0(8Q$`/"L
+MQ``$C<(```!#$"&,0@#TK,(`"(W"````0Q`AC$(`^*S"``R-P@```$,0(8Q#
+M`.R,0@#P`&48)@!$$"8``Q@K``(0*ZS"`!`0`/^SK,,`%(R"```T`X```$,0
+M(8Q"&&0``A,"`^``"#!"`'\PI?__)(0%O```&"&4@@``$$4`"22$`$@00``(
+M``,4`"1C``$L8@!`5$#_^92"```#X``(```0(0`#%``#X``(``(4`R>]__"O
+ML```)`4``@"`@"&OOP`$#``N@0``,"&.`@``-`2``#P#``(`1!`AK$`!)(X"
+M``"/OP`$`$00(:Q``2B.`@``K$``0(X"````1!`AK$,!,(X"``"/L```/`,"
+M``!$$"&L0P$X`^``"">]`!`GO?_P```H(20&`$BOOP`$K[````P`<*H`@(`A
+M/`(`/S1"_SBN`@!$)`(!]*X"`!`D`@!DK@(`'"0"`"BN`@`D/`,`/R0"``<D
+M!`#(K@(`(#1C_@PD`@`"K@0`&*("``2N`P!`K@0`%*(```:B```'H@``!:(`
+M``B/OP`$C[````/@``@GO0`0)[W_\*^R``BOL0`$K[```*^_``P`@(`A``"0
+M(221!;P"("`A#``O0B92``$N0@!`%$#_^R8Q`$B.`@``C@,%_#0%@```11`A
+MK$,!+(X"``".`P8``@`@(0!%$"&L0P$T#``O)@`````D`@'TK@(7O(^_``R/
+ML@`(C[$`!(^P```D`@`!`^``"">]`!`GO?_PK[\`!*^P``",D`6X/`(`0`"`
+M0"&.`P`0`$,@(P!#$"H00``EK@``#*X``$".`P`8/`(`0`!#(",`0Q`J4$``
+M`JX$`$2N``!$C0(``(X#`$`T!X```$<0(:Q#`2R-`@``C@,`1`$`("$`1Q`A
+MK$,!-(T"```\`P`")`4``@!'$"&L0P$PC0(``#P#`@```#`A`$<0(:Q#`3@,
+M`"Z!`````*X``#RN```XC[\`!(^P```#X``()[T`$!``_]RN!`!`)[W_\*^Q
+M``2OOP`(K[```(R#%\``@(@AC)`%N"AB```D9`!_`&`H(0""*`L`!2G#``41
+MP`!B$",H0@!`5$``!0"@("$D8P#^*((```!B(`L`!"'#CB(7Q!!``!2/OP`(
+MD@(``Q!``$TD0@`!D@,`!"QB``(40`!$)&(``8X"`"0`1!`J4$``'XX"`""2
+M`@`&$$``$B0"``&2`P`%+&(``A1```8D8@`!C[\`"(^Q``2/L````^``"">]
+M`!`P1@#_`B`@(20%``2B`@`%#``Q5@`````0`/_UC[\`"`(@("$D!0`"H@(`
+M!@P`,58``#`A`B`@(20%``6B```$$`#_\P``,"$`1!`J4$``"Y8B&W*2`@`&
+M4$#_X9(#``6B```&`B`@(20%``(,`#%6)`8``1``_]J2`P`%,$(0`!!`_]N/
+MOP`(D@(`!A!```@D`@`!D@(`!5!`_]6/OP`(H@``!0(@("$0`/_E)`4`!*("
+M``8"("`A)`4``@P`,58``#`A$`#_])("``4P1@#_`B`@(20%``40`/_-H@(`
+M!#!&`/\"("`A)`4``1``_\BB`@`#C(,7P">]__"OOP``*&(``"1E`'\`8#`A
+M`*(P"P`&,<,`!A'``&(0(RA"`$`40``JC(<%N"1C`/XHH@```&(H"P`%&<.,
+M@A?$$$``#8^_``"0X@`#$$``'"1"``&,X@`@`$,0*E!```^4@AMRD.,`!2QB
+M``(40``$)&(``8^_```#X``()[T`$#!&`/\D!0`$H.(`!0P`,58`````$`#_
+M^(^_```P0A``$$#_]8^_``"0X@`%$$#_\B0%``2@X``%$`#_]```,"$P1@#_
+M)`4``1``__"@X@`#$`#_V@#`&"$GO?_PK[(`"*^Q``2OL```K[\`#)2%&W`,
+M`"\5`("`(0`"&,``8A@A``,8P`(#D"&60P6\E@(;<"91!;P"("`A$&(`+ZX1
+M!;@,`"]"`````)8"&W"F0@6\E@(;<@`"$@(P0@`/HB(``I(F``,"`"`A#``Q
+M5B0%``&2)@`$`@`@(0P`,58D!0`%DB8`!@(`("$D!0`"#``Q5BS&``&2)@`'
+M`@`@(0P`,58D!0`#DB8`!20%``0,`#%6`@`@(0P`+X<"`"`AC@(``#0$@``\
+M`P`"`$00(:Q#`3".`@``C[\`#(^R``B/L0`$C[````!$$"$\`P(`K$,!.`/@
+M``@GO0`0E@(;<I(C``(``A(",$(`#Q1B_\T`````$`#_U)(F``.,@Q?`)[W_
+M\*^_```H8@``)&8`?P!@."$`PC@+``<YPP`'$<``8A`C*$(`0!1``"Z,A06X
+M)&,`_BC"````8C`+``89PXRB`"0`0Q`J5$``#)"B``2,H@`@`$,0*E!```60
+MH@`%D*(`!E1``!R@H``&D*(`!11``!4D0O__D*(`!!1```XD0O__D*(``U1`
+M``0D0O__C[\```/@``@GO0`0H*(``S!&`/\D!0`!#``Q5@`````0`/_XC[\`
+M`*"B``0P1@#_$`#_^20%``6@H@`%,$8`_Q``__4D!0`$)`8``1``__(D!0`"
+M$`#_U@#@&"$GO?_PK[$`!*^_``BOL```C((7Q`"`B"$40``&C)`%N(^_``B/
+ML0`$C[````/@``@GO0`0#``R>P````".`P`,`B`@(20%``(`8A@AK@,`#`P`
+M+H$``#`ACB(``#0$@`".!0!``$08(8QG`2R,9@$T`.40*Q1``%$`````C@,`
+M1`##$"M00``.`,,P(XX#`$0`PQ`K4$#_XX^_``B.(@```$00(:Q#`32.(@``
+M/`,"``!$$"&L0P$X$`#_VH^_``@`Y2@CK@4`.*X&`#R.(Q>\C@0`#``#$(``
+M0Q`A`$00*Q!``!L`9!`KC@(`%#P#$&(T8TW3<((0`@!#`!D``!`0``(1@@!%
+M$"L40``)`````(X"`!QP@A`"`$,`&0``$!```A&"`$80*Q!```4`````#``O
+MAP(@("$0`/^ZC[\`"`P`,*0"("`A$`#_^0`````00/^S/`,08HX"`!`T8TW3
+M<((0`@!#`!D``!`0``(1@@!%$"L40``-`````(X"`!AP@A`"`$,`&0``$!``
+M`A&"`$80*U!`_Z./OP`(#``P)`(@("$0`/_B``````P`+[@"("`A$`#_W@``
+M``"L90$LCB(``#P#``(`1!`AK$,!,!``_Z^.`P!$)*7__RRB``4GO?]P`(!H
+M(1!``%(`P&`A/`.``@`%$(`D8PVL`$,0(8Q"````0``(`````#P"@`(\!H`"
+M)$,-*(VE``",1`THC&(`!(S##3`T"H````Q(@`$]2"&OH@`$`*HH(:^C``BO
+MI```C2,``(RD&%`\`O`/-$+__P""("0``QT`/`(/\`!B&"0`@R`E/`B``B3&
+M#3"LI!A0C,(`!(T##3B-I@``KZ(`#*^C`!``RC`AC2(`"(S%&%P\`__`/`0`
+M/S1C?_\TA(````(3P`!$$"0`HR@D`*(H)3P'@`(E"`TXK,487(SC#4"-`@`$
+MC:4``*^C`!BOH@`4`*HH(8TB`!",I!A<)`.`?P`"$<``@R`D,$)_@`""("6L
+MI!A<).<-0(SC``2-I0``/`+\`Z^C`!P`JB@AC*086(TC`!@T0O__`((@)``#
+M'(`\`@/\`&(8)`"#("6LI!A8`^``"">]`)`\`H`"/`B``B1##4B,1`U(C&(`
+M!(T##5``!F`KC:8````,6(`!?5@A-`Z``*^C`"BOH@`DKZ0`(`#.,"&-8@`@
+MC,48;#P#_^`\!``?-&,__S2$P````A.``$00)`"C*"0`HB@EK,48;#P'@`(E
+M"`U0C0(`!(SC#5B-I0``KZ(`+*^C`#``KB@AC*08;(UC`"@\`O`?-$+__P""
+M("0``QU`/`(/X`!B&"0`@R`EK*08;#P&@`(DYPU8C.(`!(S##6"-J```KZ(`
+M-*^C`#@!#D`AC6,`,(T$&&@\!X`"/`+_`3P)@`(DY0UH-$+__R3&#6",Q@`$
+MC*4`!"4J#7",YPUH`((@)(TI#7`\`@#^``,<0`!B&"0`@R`EC4H`!*^F`#RO
+MI0!$KZ<`0*^I`$BM!!AHC:4``(UD`#@\`H#_`*XH(8RC&&@T0O__``0F``!B
+M&"0\`G\``((@)`!D&"6LHQAHC:4``(UD`$`D`__@`*XH(8RB&&@PA``?KZH`
+M3`!#$"0`1!`EK*(8:(VD``"-9@!()`/`_P".("&,@AAL``8R`##&/P``0Q`D
+M`$80):R"&&Q1@``(C:(``(VC````;A@AC&(8;#1"``&L8AAL$`#_B@`````D
+M!/_^`$X0(8Q#&&P`9!@DK$,8;!``_X,`````/`*``B1##7B,A0``C&8`!(Q$
+M#7@`#!@K-`*````#&(``HB@A`'T8(:^D`%"OI@!4C&0`4(RB(@@D`__`,(0`
+M/P!#$"0`1!`EK*(B"!``_VX`````/`*``B1##8",1`V`C&4`"(QB``2-I@``
+M``P8@*^D`%BOH@!<KZ4`8`!]&"$T`H```,(P(8QB`%B,PQA8/`3__#P%``,`
+M`A,`-(0/_S2E\```9!@D`$40)`!B&"6LPQA8$`#_5``````\`X`")&(-C(Q$
+M``2,:@V,C$L`'(Q&``B,1P`,C$@`$(Q)`!2,0@`8C:4````,&("OI`!LKZ(`
+M@`!]&"$T`H``KZH`:*^F`'"OIP!TKZ@`>*^I`'ROJP"$`*(H(8QB`&B,HQDD
+M)`3_`0`"$$``9!@D,$(`_@!B&"6LHQDD$`#_,P````",A06XC(,``#0"@`",
+MI@`T`&(8(8QJ`.PD!/__C&D`\(QG`/A0P``0K*D`,#P(OJ8`YA`K`.H8(Q1`
+M``HU"')1C*(`+(RD`#``:1@C`&88(P!B&"$`9!@A`&@`&0``&!```R/"K*D`
+M,*RG`#2LJ@`L`^``"`"`$"&,@P``-`*``#"E``<`8A@AK&4`6*R%&T@#X``(
+MK(`;3(R"&_0`@&`A,,8W`(Q"````H&@A)8X;:(Q$``0D`A4`$,(`-0``&"$L
+MPA4!$$``!P`#$$`D`A(`$,(`,20"%`!0P@`!)`,``@`#$$``1!`AE$4`EI1&
+M`+241`"0E$@`G)1#`*Z41P"ZE$D`HI1*`,``!2F`E$L`QI1"`*@`A2`E``8Q
+M@``(0P``9A@E``<[``"(("4`"4R```(6``!G&"4`"E2``(D@)0!J&"4`"UX`
+M`((@)20"``$1H@`-`&LH)3FB``(`HB`*C8(``#0#@`"MS0`T`$,0(:Q$&6"-
+M@@```$,0(:Q%&60#X``(`````!``__4`@"@A$`#_TR0#``(0`/_1)`,``2>]
+M__"OOP``C*H!$``'/@`Q"`#_``<^`Q%(`!DDJ0"4K*@!$(R"!9@D0@`!K((%
+MF"0"``&A(@`_C((;4!1```,D`@`"4,(`!($B`":/OP```^``"">]`!`D`P`!
+M`&@P"B1"``(`XA`J%$#_^`#`*"$,`#*9`````!``__6/OP``C((;4!1`__*/
+MOP``D2,`/X$B`#\D9@`!``8>`"A"``,00/_K``,>`R0"``$D!0`"`$HH"B0"
+M``,48O_EH28`/Q``_^L`````E(,;<B0"%``P8S<`$&(``P`````#X``(`*`0
+M(1"F__T`````$*``!8R#```D`@&,K&(0<!``__<`````$`#__"0"`W`0H``U
+M`(`X(1#``"^,@@``-`.```!#$"$D`P`?K$,8<(SB```T!8``)`,``P!%$"&L
+M0QGPC.0``#P#_/\T8___C()`$#1"``*L@D`0C.0``(R"0!``0Q`D/`,"``!#
+M$"6L@D`0C.0``"0#P'\`A2`AC((`'`!#$"0T0@"`K((`'(SB```D`P`]`$40
+M(:Q#`02,X@``)`,`-`!%$"&L0QATC.(``"0#``T`11`AK$,8>(SB```D`P`_
+M`$40(:Q#&?0#X``(`````#0#@```0Q`A$`#_TB0#``^,A```/`/\_S1C__^,
+M@D`0-`6```!#$"2L@D`0C.0``"0#__V,@D`0`$,0)*R"0!",X@``)`,`#`!%
+M$"&L0QGPC.(``"0#``$`11`AK$,!!(SD```D`\!_`(4@(8R"`!P`0Q`D-$(3
+M@*R"`!R,X@``)`,`?P!%$"&L0QATC.(``"0#``X`11`AK$,8>(SB```D`P#_
+M`$40(:Q#&?00P``&C.(``"0#`!\`11`AK$,8<`/@``@`````)`,`#Q``__L`
+M11`A)[W_\*^R``BOL0`$K[\`#*^P``",@@``-`.```"`B"$`0Q`AC$(`S#!"
+M``$00``'``"0(8^_``R/L@`(C[$`!(^P```#X``()[T`$(XC```T$(``)`0`
+M/`!P&"&,8@#,-$(``:QB`,P,`&D_`````(XB````4!`AC$(`S#!"``$00``-
+M)!``"0P`:3\D!``"CB(``#0#@``F$/__`$,0(8Q"`,PP0@`!$$```R0"__\6
+M`O_U`````"92``$J0@`"5$#_XXXC```0`/_;C[\`##P+_]\\#=`^/`S0/CP*
+M&2\\"1DK-`B``#0'@``U:___-:U&2#6,9X@U2K44-2FU%!"@`!0`@#`AC(,`
+M``!H&"&,8@#`-$(`@*QB`,",@P``/`0`(`!H&"&,8@`$`$00):QB``2,P@``
+M`$@0(:Q-(@B,P@```$@0(:Q*&7`#X``(K,`;4(R#```D!/]_`&<8(8QB`,``
+M1!`DK&(`P(S#````9Q@AC&(`!`!+$"2L8@`$C,(```!'$"&L3"((C,(```!'
+M$"&L21EP)`(``0/@``BLPAM0C((;])2#&^8D!@`!`(`X(1!F``>,0@``5&``
+M/(SB``",0@`$C$(`-%!``#B,X@``C.(``#0%@``D`P`/`$40(:Q#&'",X@``
+M)`,`#93D'/8`11`AK$,8=(SB```D`P`,,(0`\`!%$"&L0QAXC.(``"0#``4L
+MA``P`$40(:Q&&?",X@```$40(:Q#&?04@``<C.(``"0#`!0`11`AK$,9^(SD
+M```T!H``)`/`?P"&("&,@@`</`7\_S2E__\`0Q`D-$(`@*R"`!R,X@``)`,`
+M/0!&$"&L0P$$C.,``(QB0!`T0@`"K&)`$(SC``",8D`0`$40)*QB0!`#X``(
+M`````"0#`!@0`/_E`$40(30%@``D`P`/`$40(:Q#&'",X@``)`,`?Y3D'/8`
+M11`AK$,8=(SB```D`P`.,(0`\`!%$"&L0QAXC.,``"0"``PLA``P`&48(:QB
+M&?",X@``)`,`_P!%$"&L0QGT%(``!HSB```D`P`4`$40(:Q#&?@#X``(````
+M`"0#`!@0`/_[`$40(8R"&_24@QOF/`C\_R0)``$U"/__-`>```"`,"$0:0`'
+MC$(``!1@`#D`````C$(`!(Q"`#000``U`````(S#``"4Q1SVC&)`$#"E`/`L
+MI0`P`$@0)*QB0!",Q```)`/__8R"0!``0Q`DK()`$(S"```D`\!_`$<0(:Q)
+M`02,Q````(<@(8R"`!P`0Q`D-$(/@*R"`!R,P@``)`,`#P!'$"&L0QAPC,(`
+M`"0#`'\`1Q`AK$,8=(S"```D`P`.`$<0(:Q#&'B,P@``)`,`#`!'$"&L0QGP
+MC,(``"0#`/\`1Q`AK$,9]!2@``:,P@``)`,`%`!'$"&L0QGX`^``"``````D
+M`P`8`$<0(:Q#&?@#X``(``````"`."$``#`A),(``0#F("$P1@#_+,,`("0"
+M__\48/_ZH((`!)#B``,D0O__,$8`_R0"`/\0P@`1``800`!&$"$``A#``$<0
+M(21"`"B00P`(),7__P#C("&@A@`$D$(`"0!B&"4`XQ@AH&8`!"0"`/\PI@#_
+M%,+_\0`&$$`#X``(`````">]__"OL```/!"``B80-LBOL0`$K)`<!`"`B"&O
+MOP`(#``TGP(`("$\`H`")$(]0`!`("$,`#2?KB(<"#P"@`(D0C.,`$`@(0P`
+M-)^N(AP`/`*``B1".@0`0"`A#``TGZXB'`P"`"`A#``TGZXP'!`\!(`")(1`
+MP`P`-)^N)!P4C[\`"(^Q``2/L````^``"">]`!`GO?_@+*(`!:^S``ROL```
+MK[\`$*^R``BOL0`$`("`(1!``,0D$P`6/`.``@`%$(`D8PX$`$,0(8Q"````
+M0``(`````(R$```T`H``/`,`!`""("&,@@`$`$,0):R"``00P``/``"8(8X%
+M```D`]__/`3__(RB0!`TA/__`$,0)*RB0!".!0``/`,``HRB0`0`1!`D`$,0
+M):RB0`0``)@A`F`0(8^_`!"/LP`,C[(`"(^Q``2/L````^``"">]`"!0P``:
+M``"8(8R$```\`__\-&/__XR"0`0``(@A`$,0)*R"0`2.`@``/`,``8Q"0!``
+M0Q`D4$``#0``F"$,`&D_)`0`R(X%```\`__\-&/__XRB0`0F,0`!*B0`%`!#
+M$"2LHD`$5(#_\(X"```68/_<-`*``(X#```\!/_[`&(8(8QB``0TA/__`$00
+M)*QB``00`/_4`F`0(8R$```T`H``/`,`!`""("&,@@`$`$,0):R"``10P/_*
+M``"8(8X$```\`__\-&/__XR"0!`T0B``K()`$(X$``",@D`$`$,0)#P#``$`
+M0Q`EK()`!!``_[P``)@A$,#_NP)@$"&,AP``)`+__20%``&,XT`,)`8``0``
+MB"$`8A@DK.-`#(X#``",8D`0-$(@`*QB0!`,`#,F`````(X$```\`__\-&/_
+M_XR"0`0`0Q`D/`,``0!#$"6L@D`$C@(``#P2``&,0D`0`%(0)%1`_YX``)@A
+M#`!I/R0$``J.!```/`/__#1C__^,@D`$)C$``2HE`9``0Q`D`%(0):R"0`2.
+M`P``C&)`##1"``&L8D`,5*#_ZXX"```0`/^,`F`0(1#`_XDD`O_^C(4``#P$
+M__R,HT`,-(3__P``B"$`8A@DK*-`#(X#``",8D`$`$00)*QB0`2.`@``/`,`
+M`8Q"0!``0Q`D4$``$0``F"$,`&D_)`0`"HX$```\`__\-&/__XR"0`0F,0`!
+M*B4!D`!#$"2L@D`$C@,``(QB0`PT0@`"K&)`#%2@_^R.`@``C@8``#P#__PT
+M8___C,)`!`(`("$``"@A`$,0)*S"0`0,`#,F```P(1``_UT"8!`A$`#_6B03
+M`!&,@@``K$4`#`/@``@`````C(,``"0"``2L8@`()`(``:R"%^0#X``(````
+M`">]__"OL@`(K[```*^_``ROL0`$C(,``"0"`"``@(`AK&(`"(R"&[0P0@!`
+M$$``!202`^B,@AP<)`,G$#A"``4`8I`*$D``#0``B"&.`@``)`0`"B8Q``&,
+M0@`(,$(`!!!```T``!`A#`!I/P`````",A`K5$#_]HX"```D`@`6C[\`#(^R
+M``B/L0`$C[````/@``@GO0`0K@`7Y!``__F/OP`,)[W_\*^P``"OOP`$C((7
+MQ!1```P`@(`AC@0``#0"@`"/OP`$`((@(8R"`$B/L```)`/_WP!#$"2L@@!(
+M`^``"">]`!`,`#!<`````!``__..!```C(,``#0"@```8A@AC&(`2#1"`""L
+M8@!(`^``"`````",@@``-`.```!#$"&L10!`C((```!#$"&L1@!$`^``"```
+M```LP@`%`(!((1!``#0`H$`A/`.``@`&$(`D8PY@`$,0(8Q"````0``(````
+M`#"E`#\Q`@0`-*,`0(R$````HA@*-`:``#$%"``T8@"``$48"P"&("&M*!M$
+MK(,`/(TB&T2-(P``)`<`(#!%`$``X"`A,$(`@`!F&"$0H``#``(@"CP"`@(`
+M@B`E-((`"`!%(`NL9`$,C2(;1`#@("$P0P!`,$(`@!1@``\``B`*5(``#HTC
+M``"-(@``)`3_[XQ#`#0`9!@DK$,`-(TB```D!/_WC$,`-`!D&"2L0P`T`^``
+M"`````"-(P``C&(`-#1"`!"L8@`T$`#_]8TB``",A!M$C28``#0'@```A2`E
+M,((`/S"%!``T0P!``$48"C1B`(``QS`A,(4(``!%&`N,P@`\C,(!#*TD&T2L
+MPP`\C2(;1(TC```D!@`@,$4`0`#`("$P0@"``&<8(1"@``,``B`*/`("`@""
+M("4T@@`(`$4@"ZQD`0R-(AM$$`#_R`#`("&,A1M$``@0)XR&````HB@D,*(`
+M/S"D!``T0P!``$08"C0'@``T8@"``,<P(3"D"```1!@+C,(`/(S"`0P0`/_>
+MK24;1#"D`#\Q`@0`C24``#2#`$``@A@*-`:``#$$"``T8@"``$08"P"F*"&L
+MHP`\C2,````($((P10`@,00`0`!F&"$0@``#`*`P(3P"`@(`HC`E-,(`"`!$
+M,`NL9@$,5(#_L8TC``!0H/^CC2(``!``_ZV-(P``C(0;1(TF```T!X``,(,`
+M/S"%!``T8@!``&40"C"$"``T0P"``&00"P#',"&LP@`\C2(;1(TC```D!@`@
+M,$4`0`#`("$P0@"``&<8(1"@``,``B`*/`("`@""("4T@@`(`$4@"ZQD`0R-
+M(AM$`,`@(3!#`$`P0@"`%&```P`"(`I0@``,C2(``(TC``",8@`T-$(`$*QB
+M`#2-(@``)`3_]XQ#`#0`9!@DK$,`-`/@``@`````)`3_[XQ#`#0`9!@DK$,`
+M-!``__6-(@```*`P(22E``@PH@`/)`/_\"1"`"<`HR@D`$,X)`"G$"$GO?_P
+M`$40*Z^_``2OL````(!`(11```<`H!@AO+$``"2E`!``9Q`A`$40*Q!`__L`
+M````)-``$)("``<P0@`!$$``2R0$``V,QP`@)`3_\"3C``@P8@`/)$(`)P!D
+M&"0`1"@D`&40(0!#$"L40``'`&`@(;QQ```D8P`0`(40(0!#$"L00/_[````
+M`"3B`!"00@`',$(``51```B@P`!$C0(``(S#`"0D!``-C$(`#!!#`#"/OP`$
+MH,``1)8"``0P0G__I,(`0I8#``"6`@`"``,9`C!"#_^DP@!`D@(`!J##`$D`
+M`A!"H,(`2)("`````A$"H,(`2HX"`````A/",$(`'Z#"`$>2`@`$``(1PJ#"
+M`$N2`@`'``(00C!"``$40``8)0(<&)("``<``A"",$(``11```XD!``;D@(`
+M!P`"$0(P0@`!$$``#B4"'!B2`@`'``(1`C!"``$00``"```8(9(#``8D!``<
+MH,,`18^_``2/L````(`0(0/@``@GO0`0C$,`/!!@`#BLP@!,C@(````"$\(P
+M0@`?`&(0(9!"``2@P@!&D@(`!P`"$$(P0@`!5$``#XT"&U"2`@`'``(0PC!"
+M``$00``@`````)#"`$0T0@`!H,(`1)("``(``A%",$(``11`_^$D!``:C0(;
+M4!!```H`````D,,`2HT"&TA00P`&K0`;3(T"&TPD0@`!+$,``Q!@``>M`AM,
+MD@(``B0$`!T``A$",$(``1``_\\``B`*D,4`2@P`,ID!`"`A$`#_]@````"2
+M`@`'``(10C!"``$00/_@`````)#"`$00`/_<-$(``A``_\T``!`AK(``"*R`
+M``RL@``0K(``%"2$``B,@@`$)`/P`#"E#_\`0Q`D`$40)0/@``BL@@`$C((`
+M`(Q"``@P0@`$`^``"``"$"LGO?^@K[X`4*^W`$ROM@!(K[4`1*^T`$"OL0`T
+MK[\`5*^S`#ROL@`XK[``,(R"&_0`H*`A)(4<&(Q#`!B,0@```("((:^C`!RO
+MI@`(``#P(0``L"&OH``4KZ(`&"27&V@``*@AKZ4`)!*``)(D`___)`8`$`P`
+M'<XD!0`2/`8(```",`J/H@`($$``!*^F`"".(@``C$(10*^B`!2.(@``-`.`
+M``(@("$`0Q`AC$,`6"00``&OHP`0C$,`!#P"`B``8A@D#``T6J^C``P,`$A_
+M`B`@(0(@("$,`#IN`H`H(8^D`!``0!@A`@0@"A1``'&OI``0EH(``HXC&_0P
+M1#<`)`(5`!""`F*L<``4*((5`1!``E8D`B0`)`(2`!""`E$D`A0`4(("320>
+M``26(QSVCB0``#0"@``P8P#P`((@(2QC`#`D`@`'K((8`!!@`>X"("`A#`!)
+M;@*`*"&6)QST+.(`0A1``#`PY/__CB0``):%```T`H``/`,``@""("$T8Z`"
+M)`()M*R#&"P0H@'/CZ,`&(QB``0\`V9F-&-F9Y1"`"0`0P`8``(7PP``&!``
+M`QA#`&(@(Y:"``(D`Q0`,$(W`!!#`;`T`X``CB(```!#$"&L0!E,CB0``#0&
+M@``D`OW_`(8@(8R#(B@\!?_^-*4#_P!B&"2L@R(HCB,```!F&"&,8B(H`$40
+M)#1""`"L8B(HCB(``"0#``\`1A`AK$,`8##D__\L@@!#%$``!BR"`$2.(@``
+M-`.```!#$"&L0")4+((`1%1```Z.(@``CB4``"0#@!\\!/__C*(2,#2$?_\`
+M0Q`D-$(!X*RB$C".(P``C&(`,`!$$"2L8@`PCB(``#00@``D`P`.`%`0(:Q#
+M&'@"("`A`H`H(0.@,"$D!P`_#`!`MB0(``$00``.)`/__X^_`%2/O@!0C[<`
+M3(^V`$B/M0!$C[0`0(^S`#R/L@`XC[$`-(^P`#``8!`A`^``"">]`&"/I``<
+MCZ8`&`/`."&,@@`$C,4`!`(@("$"@#`A`$#X"0.@0"&6@@`",$($`!1``5@"
+M("`ACZ(`&`(@("$"@#`A#``_58Q%``2/HP`($&``!`````".(@``CZ0`%*Q$
+M$4"*XP`ZFN,`/8KB`#J:X@`]BN0`.IKD`#V*Y@`ZFN8`/3!C_P```QH`CB4`
+M```"%@``!"("`$,0)3"$_P"6XP`^`$00)0`&-@(`1A`E`+`H(:RB``"/I@`,
+M,&(`_XXD`````QH"``(2`([E`$@`0Q`E`,(8)20"``(0H@$I`)`@(8^E`"`\
+M`A"``&48)8^F`"0`8A`EK((`!(C#`$*8PP!%B,(`0IC"`$6(Q`!"F,0`10#`
+M*"&(I@!"F*8`13!C_P```QH```(6```$(@(`0Q`E,(3_``!$$"4`!C8"CB4`
+M``!&$"6/I@`D-!"```"P*"&4PP!&K*(`"(XD```P8@#_``(2```#&@(`0Q`E
+M`)`@(:R"``R.(@``EH,``H^D`!``4!`A,&,W`*Q$`%@D`A0`4&(`]HXE'/R.
+M(P``)`+__X^E`!RL8@"`CB0``"0#``J,H@``K(,`%(XF```D`P<``B`@(0#0
+M,"&LPP`8`$#X"0*`*"$40/]]`$`8(8XB&_Q00``/CB4```!`("$``)`AC(4`
+M`"92``$0H``(+D8`@8XB``",@P`$)(0`"`!%$"&L0P``5,#_]XR%``".)0``
+M-`.```"C&"&,8@!8KB`;3#!"`/^N(AM(C&(B"#!"(`!00``#KB`;4"0"``&N
+M(AM0-`*```"B$"&6@P`"C$(9%#!C`@`08`"[,$0__SP#NBX`!!"`-&.+HP!#
+M`!D``!`0``(1`C00@```L!@A)$0`9"0"``&L8A@<#`!I/R02``&.(@``)`,X
+M``!0$"&,4Q@(K$,8"(XB````4!`AC$(<)#!"`!`40`"5`````(XB```T!H``
+MEN0`'`!&$"&L4Q@(CB,```!F&"&,8AA@-$(``:QB&&".(P```&88(8QB&&`T
+M0@`"K&(88%"``(*.(AOTEH(``B0#$@`P0C<`$$,`?"0"``*.)1OTC*,`+!!B
+M`'@D`P`!CB0``*RC`"P`AB`AC((9(#1"\`"L@AD@CB,``#P$``$`9A@AC&(9
+M(`!$$"6L8AD@#``].0(@("$``)`ACB0``"0#``$"0Q@$`!(0@"92``$`1!`A
+M+D0`"JQ#$`!4@/_XCB0``(XC```\`@`(-$((H*XB&T"L8@"@CB4``#P#``<\
+M!@"`C*(`K`(@("$`0Q`EK*(`K(XB&T".(P```$80):XB&T",8@"@`$80):QB
+M`*".)0``/`,@`(RB`*P`0Q`EK*(`K`P`+'8`````%$``/P```````)`ACB(`
+M`#00@``D!``*`%`0(8Q"&&`P0@`!$$``!B92``$,`&D_`````"Y"`&140/_V
+MCB(```P`,_8"("`ACB,``#0"@``\!/Y_`&(8(8QB`"`TA/__`$00)*QB`"".
+M(ANT,$(`0!1``!\"@"@A`B`@(0P`,\$``"@AEB,<\"QB``900``.CB(``"0"
+M``508@`(EB(<\HXB```T`X```$,0(20#`%*L0P$($`#^Q0``&"$L0@`(%$#_
+M^(XB```\`P`!-&,`J@!0$"&L0P$8CB(``"0#,A``4!`AK$,!'!``_^Z.(@``
+M#``Z*P(@("$0`/_@`B`@(0P`++@"("`A$`#_P```D"&.(AOT$`#_DZQ``"P,
+M`&D_)`0`R"Y"`!000/]H)E(``8XB```T`X```$,0(8Q"'"0P0@`0%$#_]0``
+M```0`/]@CB(``#P"S,PT0LS-`((`&0``$!`0`/]'``(0P@(@("$,`#,5+*8`
+M`1``_PB.(P``CZ(`(`!B&"40`/[8/`(0@@P`0&X"@"@A$`#^IX^B`!B/HP`8
+MCB4````$(".,8@`$``0D@#P#`/R`0@`B`(,@)#0#@````A`C``(1@#!"#\``
+MHR@A`$00):RB&4P0`/Y%CB0``(^F`!@\`F9F-$)F9XS#``2$9``FE&,`)`!D
+M&",`8@`8``,?PP``$!```A!#`$,0(P`"%``0`/XM``(D`PP`:3\D!``!`!Z`
+M@```F"$D$@`H/`.``B1C%[P`$Q#``$,0(8Q$```"`Q@ACB(``(QE```FM0`!
+M`$00(3*C`#\F4O__)A``&"9S``,D!``!K$4``!!@`#L`````!D'_[CP#@`(,
+M`&D_)`0``0``@"$\`H`"`!`8P"1"&Y0`8A@AC&0``(XB``",90`$)K4``0!$
+M$"$RHP`_)A```20$``&L10``$&``(P`````J`@$>%$#_\#P"@`(,`&D_)`0`
+M`0`6@(```)@A)!(`/SP#@`(D8R2$`!,0@`!#$"&,1````@,8(8XB``",90``
+M)K4``0!$$"$RHP`_)E+__R80``PF<P`#)`0``:Q%```08``%``````9!_^X\
+M`X`"$`#]RP(@("$,`&D_`````!``__D`````#`!I/P`````0`/_<*@(!'@P`
+M:3\`````$`#_PP`````0`/VS)!8``A``__TD'@`#$((`!B0")0!4@OVNEB,<
+M]B0>``(0`/VJ)!8``1``__TD'@`!$`#_\B0>``4`@#@AC(0``#0&@``D`__\
+M`(8@(8R"`,"4J``"`$,0)#1"``*L@@#`C.0``"0#_\,Q!2```(8@(8R"`,``
+M0Q`D-$(`&*R"`,",X@```$8P(8S"`,@P0___/`(G$!2@``,`8B`E/`(J^`!B
+M("4Q`B``,$7__S$""``T"8``K,0`R!!``!DD`\``C.0```")("&,@@`4`$,0
+M)#1#$3`T0@^@`&40"JR"`!2,X@```$D@(8R"`,0P0___/`(%>!2@``,`8A`E
+M/`(&!`!B$"6L@@#$)`,$L"0"!2@Q!"```$08"HSB``"L0Q!P`^``"```$"$G
+MO?_PK[\```P`.\\D!0`"C[\```/@``@GO0`0)[W_X*^V`!BOM0`4K[0`$*^S
+M``ROL@`(K[```*^_`!ROL0`$`*"8(0"`@"$D%@`!``"0(0``J"$0H``F``"@
+M(92E``*4@ASV,*,W`#!"`/`X8Q0`-*0"`"Q"`#`40``&`(,H"C"C`@`D%`#K
+M)`(`Z@!#H`HD$@`(,*,&`"0"!@`08@!6,*,$`#9"``$`0Y`*,*(@`#9#``(P
+MI`@`$(``30!BD`J.`ANT,$(`0%!```2N`!V()`(``392`!"N`AV(,*,!`"0"
+M``,``*@A`$.H"P``L"$"`"`A#``[SR0%`!,00``,`$"((0(@$"&/OP`<C[8`
+M&(^U`!2/M``0C[,`#(^R``B/L0`$C[````/@``@GO0`@`@`@(0``*"$,`#3E
+M)`8``11`__``0(@A`@`@(0P`.\\``"@A%L#_ZP!`B"&690`"C@(``#03@``P
+MHP(``%,@(8R&&'P48``1,*,W`"0"%``08@`.`````%#4``6.`@``K)08?`P`
+M:3\D!`$LC@(```!3$"&L4B(`C@(```!3$"&L51@$$`#_U`(@$"&LE1@$C@(`
+M``!3$"&L4B(`$-3_S20$`2R.`@```%,0(:Q4&'P,`&D_`````!``_\<"(!`A
+M$`#_NJX`'8@0`/^L-E(`!">]__"OL0`$K[```*^_``B,BQOT)`(``0"`@"&-
+M8P`L`*"((1!B`#\DA!MHEB(``B0#$@`P0C<`$$,`!"0"``*-8P`L4&(`(HX%
+M```"("@A#``]!`(`("&6)0`",*(``11``!4D`P`8C@,``#0"@``PI"```&(8
+M(8QB&&`T0@`"K&(88!2```D`````E@(<]C!"`/`L0@`P%$``!P``&"$PH@0`
+M$$``!8^_``@,`$AQ`@`@(0``&"&/OP`(C[$`!(^P````8!`A`^``"">]`!`T
+M!H``D(0`4P"F*"&,HQD@/`+__S1"#_\`!",``&(8)#"$\```9!@EK*,9((X$
+M```D`@`!K6(`+`"&("&,@QD@/`(``0!B&"6L@QD@$`#_S`(@*"&.`@``-`.`
+M``!#$"&,0AD@/`,``0!#$"140/^\EB(``JU@`"P``"`AC@,``#0"@``DA``!
+M`&(H(8RJ'!`LAP`*C*8<%(RH'!@10``#`````!3```@`!AA"C*(9(#P#``$`
+M0Q`EK*(9(%3@__".`P````880@`*$$(`0Q`A``(9PA!@_ZD`!B'"*((``E1`
+M_Z<"("@A``@0(P!#`!I08``!```!S8X(```T"8``)`/X'P$)0"&-!QD@`.,X
+M)"0#``*M8P`L)`,`'P``$!(``A8```(6`P%$`!LH1?_@*$8`(`!F$`HXI0``
+M)`/_X`!E$`L``A%`,$('X`#B."6M!QD@C@<``"0"_^``Z3@AC.89(`#","0D
+M`@`/```@$B2$_X`H@__P*(4`$`!%(`HX8P``)`+_\`!#(`LPA``?`,0P):SF
+M&2".`P```&D8(8QB&2`T0@@`K&(9(!``_W0"("@A)[W_X*^S``ROL@`(K[$`
+M!*^P``"OOP`0C(,```"`B"$D$___C&(`""00``8``)`A-$(`(*QB``B,@P``
+MC&((@#1"`_^L8@B`,@(`!!!```DR`@`"CB(``(Q"``@P0@`$%$``!#("``(D
+M`O_[`@*`)#("``(00``*,@(``8XB``",0@A`,$(#_Q1```4R`@`!)`+__0("
+M@"0V$``!,@(``1!```T``#`ACB0`````*"&,@@H`)*4``2RC``HP0@`#`,(P
+M(11@__HDA``$%,```B0"__X"`H`D$@``#B0$`#(,`&D_)E(``2Y"``H40/_7
+M,@(`!`)@$"&/OP`0C[,`#(^R``B/L0`$C[````/@``@GO0`@$`#_]P``F"$G
+MO?_@K[,`##"B`!$D$___K[$`!*^P``"OOP`0K[(`"`"@@"$`@(@A$$``)P"E
+MF`L``"@A#``TY20&``$00``)`$`8(8^_`!"/LP`,C[(`"(^Q``2/L````&`0
+M(0/@``@GO0`@CB(```(@("&L0``DCB(``(Q"`"0,`#N(`````!!``$HD`O_O
+M#`!I/R0$``^.(@``)`0``380`!.,0@`,#`!JO``````,`&G3``````P`::L`
+M````#`!I/R0$``H,`&J\```@(0P`:3\D!``/CB(``"0$``\R<P`#C$,`#*Q0
+M0``,`&D_,A```P``D"&.(@``)E(``0(@("&,0D`````H(0!3$"004``2)`8`
+M`1(```@`````#`!I/R0$`#(N0B<05$#_\XXB```0`/_%)`,`%@P`-.4`````
+M%$#_]@````".(@``K$!``!``__(`````#``TY0````!40``$CB(;](XB``",
+M0@#`CB(;](Q#`%PD`@`#4&(``XXD```0`/^P```8(3P#__$T8___C()`$`!#
+M$"0\`P`(`$,0):R"0!`0`/^G```8(20$``\,`&D_`@*`)(XB``",0@`,$`#_
+MP0`````GO?_@K[0`$*^S``ROL@`(K[$`!*^_`!2OL```E*,``I2E````@)`A
+M,&(@````H"$``)@A$$``LC"Q__^,@AOTE$0`=#!B(``00`"KCD(;])1#`'8P
+MI?__`*00*Q1``#LD`@`.`&40*Q1``#@D`@`.+B(2P!!``%4\`\S,/`5F9B8D
+M]W`TI69G`(4`&``$%\,``!@0``,80P!B&",``Q"``$,0(12"`#DF)/=0`!$0
+M0"1"[N``10`8``"@(0`"%\,``!@0``,8@P!B@",`$!"`,%``_P(`("$,`%B4
+M)`4`"`!`@"$D`@FT$B(`(#0"@`".1```)`/_[P""("&,@B($`$,0)*R"(@0`
+M$QB``!`1``!#$"4`%"!`CD,```!$$"4T11`!-`2``#"B`/\`9!@AK&(8G(Y"
+M````!1H",&4`?P!$$"&L11C8```0(8^_`!2/M``0C[,`#(^R``B/L0`$C[``
+M``/@``@GO0`@CD(``#0#@```0Q`AC$,B!#1C`!"L0R($$`#_X0`3&(``A0`8
+M``07PP``&!```QA#`&(8(P`#$(``0Q`A5(+_Z"0"``X`$1!`)$+NH`!%`!@D
+M%``!```8$!``_[\``A?#-&/,S0(C`!D``!@0``,9`@`#$(``0Q`A``(0@`(B
+M$",P0O__%$``!#P"S,PN(A0`$$``,#P"S,PT0LS-`B(`&0``(!``!!C"``,0
+M@`!#$"$``A!``B(0(S!"__\00``7``08@@`#$(``0Q`A`B(0(S!"__\40/_"
+M)`(`#CP$9F8F(NU`-(1F9P!$`!@``A?#)`4`"```(!``!"!##`!8E`""(",`
+M0(`A)`0``0P`6)0D!0`"$`#_H0!`F"$\!&9F)B+M0#2$9F<`1``8``(7PR0%
+M``@``"`0``0@@P""(",,`%B4``0@0`!`@"$0`/_O)`0``CP$9F8F(NU`-(1F
+M9P!$`!@``A?#)`4`"```(!``!"##`((@(PP`6)0`!""``$"`(1``_^$D!``#
+M$`#_5I1#`'J,@AOT$`#_3Y1$`'B4IP`")`(5````,"$PXS<`$&(`)0``0"$H
+M8A4!$$``)B0")``D`A(`$&(`(20"%`!08@`!)`8``HR#```T`H```&(8(8QB
+M&&`P0@`"%$``%`````",A!OTC&(89``&&$",A`````(4PC!&`?^,@@`$,,0!
+M``!B&"$0@``#A&,`<CC"`?\``C`G`&80*E!```2DI@`*`0<0):2B``*DI@`*
+M`^``"``````0`/_C)`8``A``_^$D!@`!$&(``R0")0!48O_>C(,`````,"$0
+M`/_:)`@``8R"&[2,@P```(`H(0`"$((P0@`!K&($((RB&[R,HP``/`0`$``"
+M$@(P0@`'K&(&`(RC```TA`(!```X(8QB!@`DIAT!-$(`"*QB!@",H@``K$0&
+M!(RB``"L0`8@C*(``*Q'!`"0Q```C*(``"3G``$LXP"`K$0$!!1@__@DQ@`!
+M`^``"``````GO?_`K[X`,*^W`"ROM@`HK[4`)*^T`""OL@`8K[\`-*^S`!RO
+ML0`4K[``$)3"``*,@QOT,.?__S!*-P`D`A4``*!((0#`D"$`@*@A`0#P(:^G
+M``",<0`$``"@(0``L"$``+@AKZ``"*^@``P``"@A$4(!-HQS`"`I0A4!$$`!
+M/R0")``D`A(`$4(!-B0"%`!10@$OE2(`]H^B```\!(`"/`.``@`",(``!2A`
+M)(0GC"1C)Z0`J2@A`,0@(0##&"$\`H`"C(0``(QC``"4IP#2C$(GB)2E`(2N
+M9``$KF,`"*^G``2N8@``)F,`#"0$`"<\`H`")$(GO`#"$"&,0@``)(3__R3&
+M`!BL8@``!('_^"1C``0F<``,`@`@(20&``$D!P$N#``^V```0"&7Q0```@`@
+M(20&``(D!P$.#``^V```0"&7Q0`"`@`@(20&``(D!P$!#``^V```0"&60@`"
+M,$($`%1``,Z.(@`<ED(``C!"$``00`#``L`H(8^E``@"`"`A)`8``R0'`1\,
+M`#[8``!`(8^E``P"`"`A)`8``R0'`2(,`#[8``!`(9:C'/8D`@`U$&(`ER0%
+M``(D`@!%$&(`E20&``*/H@``)F,`K"0$``P``C"`/`*``B1"*WP`PA`AC$(`
+M`"2$__\DQ@`8K&(```2!__@D8P`$ED(``C!"!`!40`![CB(`'(^E``0F9`"L
+M)`8`!B0'``X,`#[8``!`(0P`:3\D!``!/`*``HQ#)X2.H@``CF0``":4``$`
+M0Q`A,H,`/ZQ$```08`!E``````P`:3\D!``!/`*``HQ#)XR.H@``CF0`!":4
+M``$`0Q`A,H,`/ZQ$```08`!5``````P`:3\D!``!/`*``HQ#)Z2.H@``CF0`
+M"":4``$`0Q`A,H,`/ZQ$```08`!%`````"0$``$,`&D_)G``#```D"$D$0`G
+M/`*``B1")[P"0A`AC$,``(ZB``".!0``)I0``0!#$"$R@P`_)C'__R80``0F
+M4@`8)`0``:Q%```08``L``````8A__`\`H`"#`!I/R0$``$F<`"L``"0(201
+M``P\`H`")$(K?`)"$"&,0P``CJ(``(X%```FE``!`$,0(3*#`#\F,?__)A``
+M!"92`!@D!``!K$4``!!@`!$`````!B'_\#P"@`*.HAOTC[\`-(^^`#"/MP`L
+MC[8`*(^U`"2/M``@C[,`'(^R`!B/L0`4C[``$*Q``#`#X``()[T`0`P`:3\`
+M````$`#_[0`````,`&D_`````!``_](`````#`!I/R0$``$0`/^Z)`0``0P`
+M:3\D!``!$`#_J0`````,`&D_)`0``1``_YD`````)F0`K"0&``*$10``)`<`
+M)0P`/M@``$`A$`#_@(^E``0D!@`")`<`6B0(``(,`#[8`@`@(0(`("$``"@A
+M)`8``B0'`%P,`#[8)`@``@(`("$D!0`")`8``B0'`%X,`#[8)`@``@(`("$`
+M`"@A)`8``20'`/X,`#[8)`@``A``_U:/H@``)`8``R0'`1<"`"`A#``^V```
+M0"$"`"`A`N`H(20&``,0`/]")`<!&@(`("$D!@`!A$4``B0'`*@,`#[8)`@`
+M`XXB`!P"`"`A)`8``81%``0D!P"I#``^V"0(``..(@`<`@`@(20&``&$10`&
+M)`<`J@P`/M@D"``#CB(`'`(`("$D!@`!A$4`""0'`*X,`#[8)`@``XXB`!P"
+M`"`A)`8``81%``HD!P"O#``^V"0(``..(@`<`@`@(20&``&$10`,)`<`L`P`
+M/M@D"``#$`#_"I9"``*5(@#VE2<`^"0%``*OH@`($`#^SJ^G``R5(@#RE2<`
+M]"0%``&OH@`($`#^R*^G``P10@`#)`(E`!5"_L6/H@``ED,``"1B\%\L0@3K
+M$$``!21BZW25-@#BE3<`Y!``_KL``"@A+$(`\!!```0D8NJ$E38`YA``__F5
+M-P#H+$(`X1!```0L8A9=E38`ZA``__.5-P#L5$#^K0``*"&5-@#N$`#_[I4W
+M`/`GO?_@K[(`"*^P````@)`A`."`(0"@("$`P"@AK[,`#*^Q``0!`)@A)A#_
+M_Z^_`!`,`%B4`,"((0!`0"$R!P`'&B``'@`0$,(``A"``%*`(0#Q("$D!@`(
+M*((`"0#"(`HD`@`!`.(8!`""$`0D8___)$+__XX%````0Q`F`!,8P`!B$`0`
+MZ"`$`&0@!``"&"<`@B`D`*,H)`(G$"$`QS`C`*0H)211__BN!0```,A`!@``
+M."$>(/_F)A``!(^_`!"/LP`,C[(`"(^Q``2/L````^``"">]`"`DQO__)[W_
+M\*^_````H%`A,,@`!P``8"$`!A#"`*!((1B@`!P``%@A``(0@`!$,"$!"2@A
+M**,`"20"``@`0R@*)`(``0$"(`0`HA`$)(3__XS#```D0O__`$00)@`'(,``
+M@A`$`&(8)`"#&`8!*!`A`0,8!@%C&`0`J"@C)$G_^`&#8"4!95@A``!`(1T@
+M_^@DQ@`$`8`@(0P`6)0!0"@AC[\```/@``@GO0`0)[W_\"0$`."OOP`$K[``
+M``P`>E<`H(`AK@(`((^_``2/L`````(8*P!@$"$#X``()[T`$">]__"OL```
+MK[\`!(RB`"``H(`A%$``!0!`("&/OP`$C[````/@``@GO0`0#`!Z:@`````0
+M`/_YK@``(">]_]"OO@`@K[8`&*^T`!"OLP`,K[(`"*^Q``2OOP`DK[<`'*^U
+M`!2OL```C((;]`#`\"&4Q@`"C$,```"`B"$PPO__``(B`@`"$P(P4P`!,,@W
+M`"0"%0``H)`AE'<``#"4``$1`@#U``"P(2D"%0$00`#V)`(D`"0"$@`1`@#Q
+M)`(4`%$"``$D%@`"CB<``#0"@```%JA``.(X(0*R@"&,XAD0E@,`BB0$_`8`
+M1!`D``,9``!#$"6.)1N<-$(``0(@("$PQO__K.(9$`P`,J$`````*NI0`!5`
+M``:6!``\4H``!8XE````$Q!``%(0(91$`$*.)0``-`*````$(<``HB@AC*(8
+M1"0#P'\PA#^``$,0)`!$$"6LHAA$`M(P(15```6`Q0!H4H``!(XD```"<A`A
+M@$4`:XXD```T`H``)`/_``""("&,@AA0,*4`_P!#$"0`11`EK((84!5```6`
+MQ@!M4H``!(XE```"<A`A@$8`<(XE```T`H``/`3__P"B*"&,HQA0``82`#2$
+M`/\P0O\``&08)`!B&"4"LA`AK*,84!5```:40@!&4H``!8XG````$Q!``%(0
+M(91"`$R.)P``-`B```*R2"$`Z#@AC.082#P%__P\!@`#E2,`7#2E#_\TQO``
+M``(3``!&$"0`A2`DE28`8@""("6LY!A(/`(`_P`#)`".)0```((@)``#'@``
+M!A(``&08)3!"_P``8A@E,,8`_P!F&"4`J"@AK*,8-(XE``"5)`!0/`/__P"H
+M*"&,HA@H-&,`_P`$(@``0Q`D`$00):RB&"B.)@``E2,`5CP%__@`R#`AC,(8
+M9#P$``<TA/````,;`#2E#_\`9!@D`$40)`!#$"4JXS`#K,(89!1@``LD!``"
+ME\(``#!"`!]00``(CB4``"1"__8L0@`-5$``!(XE``"5(@#,)$0``HXE```T
+M!H``)`/_`0"F*"&,HADD``0@0#"$`/<`0Q`D`$00):RB&22.)0```!,00`!2
+M0"$E!P$``*8H(83B``*,HQD@)`3X'P`"$4``9!@D,$('X`!B&"6LHQD@CB4`
+M`(3D``8D`__@`*8H(8RB&2`PA``?*N=``0!#$"0`1!`EK*(9((XC````9A@A
+MC&(9(#1""`"L8AD@%.``&"KB4`$"LA`A%4```Y1$`-A6@``!E00`WI?"``(D
+M`Q4`,$(W`!!#`"D`````CB8``#0"@``\!?\#`,(P(8S#(@P`!"2`-*7__SP"
+M`/P`91@D`((@)`!D&"6LPR(,*N)0`11```J/OP`DED(`.#!"`@`00``1CB(`
+M`#0#@```0Q`A)`,!_ZQ#&>"/OP`DC[X`((^W`!R/M@`8C[4`%(^T`!"/LP`,
+MC[(`"(^Q``2/L````^``"">]`#`T`X```$,0(:Q`&>`0`/_QC[\`)!5`_^0J
+MXE`!$`#_UHXF```0`/\3)!8``A``_Q$D%@`!$0(``R0")0!5`O\.CB<``!``
+M_PL``+`AE*8``I2E```\`F0`,,8!`#P#R```9A`+`$4`&U"@``$```'-`(!0
+M(20(`!\``$@2`0D0!C!"``%40``%C48``"4(__]5`/_[`0D0!HU&```D`@`F
+M`$A`(S0'@``D`P`7`,<P(0!H&",D`@`!C,48%`!B$`0D`P`8`&@8(P$B$"$\
+M!``!`&(0!C2$__\`I"@D``(40`"B*"6LQ1@4C48``"4#__`\!?_^`,<P(8S"
+M&!0\!``!``,;0#2E'_\TA.```$40)`!D&"0`0Q`EK,(8%`/@``@`````/`*`
+M`B>]_\`D0@]\`Z`8(21$`$",10``C$8`!(Q'``B,2``,K&4``*QF``2L9P`(
+MK&@`#"1"`!`41/_V)&,`$`/@``@GO0!`)[W_$*^^`.`GO@`0``<\`*^W`-RO
+MM@#8K[(`R*^Q`,0`H)`A`("((0``*"$#P"`A`,"X(2>V`)`D!@"`KZ@`M*^_
+M`.2OM`#0K[``P*^U`-0`!X0##`!PJJ^S`,P"P"`A```H(0P`<*HD!@`@ED(`
+M`HXC&_0``$`A,$(@`(QT```00`#\KZ``N(8B&\"6(QO``@`@(0!0$"I40``!
+M`&`@(0`$%````H0#*@(`0!1```("`#@A)`<`/P`'%````H0#*@(`/U!```26
+M(QO$%@``"">U`+*6(QO$/`*``B1"+,```QA``&(8(81H```GM0"RK[4``(Z&
+M``PGLP"P`@!((0(@("$"P"@A`D`X(0*`4"$,`$4$`F!8(3P"@`*,0D/\6$``
+M!(XB&_0,`$"D`L`@(8XB&_0"8#`A`J`X(8Q"`!@"X$@A`B`@(8Q"``@GI0`0
+M`$#X"0)`0"&6(QSVEZ(`KC!C`/`D0@`$+&,`,!1@`+^GH@"NEZ,`LB0"`#\#
+MP"`A`$,0(S!%__\``#`AE(,`@"3&``$HQP`0`*,8(3!B__\L0@!`%$```Z2#
+M`(`D`@`_I((`@!3@__4DA``"CB(;](Q#``"D10`DC&(`!)1"`"@L0@`"$$``
+M)SP"@`*6(AST+$(`0A!```>/H@"TED(``B0#%``P0C<`4$,`?)9#``"/H@"T
+M%$``!30%H8"/H@"X$$``&#P"@`(T!:&````P(0`&$(`GHP`0`$,0(91#``"4
+M0@`"CB0````#&@```A(`-$(`_S1C`/\``A0`,&/__R3&``$`0S@E`(4@(22B
+M``0HPP`@K(<``!1@_^TP1?__/`*``HQ"0_PH0@`"$$``5P````"7HP"6EZ0`
+ME)>B`)(P8P`_,(0`/P`$)````QX`,$(`/P!D&"4``A(``&(8)9>B`)"7I`"<
+MCB4``#!"`#\`8C@EEZ,`GI>B`)HPA``_,&,`/P`$)````QX`,$(`/P!D&"4`
+M`A(``&(8)9>B`)@T!H```*8H(3!"`#^LIQDTEZ0`H@!B."67HP"DEZ(`KC"$
+M`#\P8P`_``0D```#'@`P0@`_`&08)0`"$@".)0```&(8)9>B`*``IB@AK*<9
+M.#!"`#\`8C@EEZ0`JI>C`*R7H@"HCB4``#!C`#\PA``_``0D```#'@`P0@`_
+M`*8H(0!D&"4``A(`K*<B-`!B&"67H@"FCB4``(^_`.0P0@`_`&(X)0"F*"&L
+MIR(XCB,``(^^`."/MP#<C[8`V(^U`-2/M`#0C[,`S(^R`,B/L0#$C[``P```
+M$"$`9A@A)`0`/ZQD&3P#X``()[T`\`P`0*0GI`"0$`#_J)>C`)8D`@FT$&(`
+M$#P#9F:.@@`$-&-F9Y1"`"0`0P`8``(7PP``&!```QA#`&(X(P+`*"$"("`A
+M#`!&;2>F`!`D`@`!$`#_=*^B`+B.@P`$/`)F9C1"9F>$9``FE&,`)`!D&",`
+M8@`8``,?PP``$!```A!#`$,0(P`"%``0`/_L``(\`Q``_U,``"@AAB(;PI8C
+M&\(0`/\%`@`@(2RC`$``H#@A)`(`/P!#.`HGO?_@``<\`"2%&W``!SP#`Z`P
+M(:^_`!`,`$"V``!`(8^_`!`#X``()[T`(#"$__\PI?__,,;__P`'/```"$0`
+M`,1((P"%4",`Q1@C``<4`Q#%``P`""0#`2(`&%!@``$```'-<40`````$!(`
+M``````````!#`!H``!@2``,4```"%`,#X``(`````)2C````!"0`,,;__P`$
+M)`,`!A!``*(0(0!D&"H48``$A$+__JS@```#X``(K0````""$"H40``$),+_
+M_ZSB```#X``(K0(``!#```X``!@A``,00`!%2"&5(@``$$0`#21J``&5(@`"
+M`((0*A1```<D8@`!,4/__P!F$"L40/_U``,00`/@``@`````$`#_[*SC``"L
+MXP```^``"*T#```GO?_0K[<`'#"7__\`!SP`+N(``J^V`!BOM0`4K[0`$*^S
+M``ROL@`(K[$`!*^_`""OL````*"((0#`L"$!`*@A``>D`P``F"$D$@`!%$``
+M-```&"$``(`A`!(00`!1$"&40@```%`0*Q!```H`$Q!`)N+__P)"$"H00``&
+M`!,00"9B``$F0P`!,%/__S!R__\`$Q!``!(80`!6("$`=D`A`%$0(0!Q&"&4
+M9@``A(<``)1%``"%"```#`!!Y@(`("$``B0```0D`P`0&$``=1@A`)0@*A2`
+M``RD8@``+@(`0!!```HF`@`!`@`0(28#``$P</__``(00`!5$"$N`P!`%&#_
+M^:14```F`@`!,%#__RX"`$`40/_1`!(00"0#``&/OP`@C[<`'(^V`!B/M0`4
+MC[0`$(^S``R/L@`(C[$`!(^P````8!`A`^``"">]`#"$@@!^A(,```"`2"$`
+M0Q`C*$(`?Q1``$24A`!^)(+_@@`"%````E0#``04```")`,DA___)`(`/R4F
+M`'XDQO_^A,,``"1"__\``A0``.,8*A!@``,``A0#!$'_^23&__X`0#`A)`<`
+M/R3#__\P8O__+$(`/Q!``!(`!A!``$D0(81"````1!`J%$``#0`#%````C0#
+M``800"3#__\`24`A,&+__RQ"`#\00``%`````(4"````1!`J$$#_]0`#%``0
+MP``,).+__P`'&$`DA/_^``(4``!E&"$`!"0```(\`Z1F```$X?_@``0D`P/@
+M``@!0!`A!.#__0``````!Q!``$4H(23B__^4HP`"``(4```"/`.DHP``!.'_
+M^B2E__X0`/_R`````!``_[\`8%`AA((`?H2H````@%`A)`P`0`!($",H0@!_
+M%$``392#`'XD8O^"``(4```";`,``Q0```(D`R0)`#\DB___)4@`?B4(__Z%
+M`P``)2+__P`"%``!8Q@J$&```P`"3`,%(?_Y)0C__I2B`'X!($`A)`D`/Z3B
+M``"$X@```$00*E!``#$``&`A%0```P````!5@``M``!@(1D```X`"!!``$H8
+M(81B````1!`J%$``"24"__\``A0```)$`QD```4D8__^A&(```!$$"H00/_Y
+M)0+__Q4```,E(O__$8``#0```````A0```D80"2$__X`9A@A``0D```"3`,!
+M#!`EI&(```4A_]P`!"0#`^``"`&@$"$%(/_]```````)$$``1C`A)2+__Y3#
+M``(``A0```),`Z3#```%(?_Z),;__A``__(``````*!0(1``_](D"``_$`#_
+MM@$`:"$GO?O0K[X$(*^_!"2OMP0<K[8$&*^U!!2OM`00K[,$#*^R!`BOL00$
+MK[`$`)4"``*,@QOTKZ0#R#!$-P`D`A4`KZ@#V*^E`\ROI@/0KZ<#U`$@\"&,
+M8P``$((!QJ^@`]PH@A4!$$`!R"0")``D`A(`$((!PR0"%`!0@@&_)&,`+(^D
+M`]2/I0/0CZ8#W(2#``"$I```)`+>K:>B`[JGH@.X``,<0``$)$"4Q0`&``0D
+M`P`#'`.OI`/@KZ,#Y```J"$``(@A)Z0#N`(E$`<P0@`!&$``!2ZC``(08`#A
+M)K4``:21```DA``")C$``2XB``040/_V`B40!X^H`]R/IP/8E08`!(3D``"-
+M!0``)Z<#P`P`0?XGJ`/$C[8#P(^B`\0`5A`K%$``@``6$(``5A`A``(0@`!6
+M$"$``A"`KZ(#[*^@`_"/HP/<CZ0#[(QB``B7HP.Z`$2H(30"WJT08@%"E[$#
+MN">W`0@"X"`A`!&`@`(1@"$`$("``A6`(984``8F!0`()[,!(``4B$`"(#`A
+M#`!PG280`!`"`"@A`B`P(0P`<)T"8"`AAJ<``B>R`S@"@"`A`N`H(0)@,"$,
+M`$(F`D!`(1!``*:/I@/P`D`@(2>E`[@`W1`A)$,!.#!B``,00`$4KZ8#Z`"@
+M$"&(AP``F(<``XB(``28B``'B(4`")B%``N(A@`,F(8`#ZAG``"X9P`#J&@`
+M!+AH``>H90`(N&4`"ZAF``RX9@`/)(0`$!2"_^XD8P`0E[$#N@+@("$`$8"`
+M`A&`(0`0@(`"%8`AEA0`!B8%``@F$``0`!2(0`P`<)T"(#`A`@`H(0(@,"$,
+M`'"=`F`@(8:G``("@"`A`N`H(0)@,"$,`$(F`D!`(1!``'./IP/H`D!`(0#]
+M$"$D0P(X,&(``Q!``-4GI`.X`(`0(8D$``"9!``#B04`!)D%``>)!@`(F08`
+M"XD'``R9!P`/J&0``+AD``.H90`$N&4`!ZAF``BX9@`+J&<`#+AG``\E"``0
+M%0+_[B1C`!"/J`/PCZ,#[(^B`\0FU@`!)0@`@"1C`%0`5A`KKZ@#\!!`_XBO
+MHP/LCZ<#W(^F`\"/I0/$C.0````&$$"7IP.Z`$00(0`%&$``9!@AE%0``#0"
+MWJT`IJ@C$.(`@91S`````(@A`Z"0(0`5@8"/J`/8`A&`(0`0@$`"'8`AAD<!
+M.)4$``"&"`$X`H`H(0P`0>8"8#`ACZ,#V(9'`CB&"`(XE&0```*`*"&F0@`(
+M`F`P(0P`0>8F,0`!+B,`0*9"`(@48/_I)E(``B0"``(40`!%AZ,!!H^G`^``
+M9Q`J%$``!(^H`^0`:!`J$$``*8^E`\R/I0/,#`!">B>D``@`0$@A``(?PI>B
+M`(:7I0.XCZ8#T``"%````B?"CZ<#U``"%`,!(Q@A`$00(0`"$$,``QA#I\4`
+M`J>B``"GQ0``I,,``*3B``"/J`/4CZ,#R)4"``",9!OT)`,`/P!B&".D@P`D
+MC[\$)(^^!""/MP0<C[8$&(^U!!2/M`00C[,$#(^R!`B/L00$C[`$``/@``@G
+MO00P#`!">B>D`(@`0$@A``(?PI>B`0:7I0.Z`2,8(0`"%````B?"``(4`P!$
+M$"$``A!#I\4``H^D`]"GH@``I\4``(^E`]0``QA#I(,``!``_]FDH@``CZ8#
+MS">D``@GI0"(#`!"QB>G``(`0$@AEZ,``@`")\*7H@"&``,<```#+\(``A0`
+M``(WP@`#'`,``A0#EZ@#N)>G`[H`91@A`$80(8^E`]"/I@/4`20@(0`$($,`
+M`QA#``(00Z2D``"GHP``I,(``*?'``(0`/^ZI\@`````B"$#H(`A`!41@`!1
+M$"$``A!``%T0(81(`3B/H@/8A@<!.`*`*"&41````F`P(0P`0>8F,0`!+B,`
+M0*8"``@48/_Q)A```H^E`\P,`$)Z)Z0`"`!`2"$``A_"EZ(`AI>E`[B/I@/4
+M``(4```")\(``A0#`$00(8^D`]`!(Q@A``(00P`#&$.D@P``IZ(``*3"``"G
+MQ0`"$`#_DJ?%``"-`@``C04`!(T&``B-!P`,K&(``*QE``2L9@`(K&<`#"4(
+M`!`5!/_V)&,`$!``_S6/J`/PC(<``(R(``2,@@`(C(8`#*QG``"L:``$K&(`
+M"*QF``PDA``0%(7_]B1C`!`0`/[VE[$#NB>S`0@"8"`A`!&`@`(1@"$`$("`
+M`A6`(984``8F!0`()[(!(``4B$`"(#`A#`!PG280`!`"`"@A`B`P(0P`<)T"
+M0"`AAJ<``B>P`S@"@"`A`F`H(0)`,"$,`$(F`@!`(1!`_V6/I0/P`@!`(0"]
+M$"$D0P$X,&(``Q!``!<GI`.X`(`0(8D&``"9!@`#B0<`!)D'``>)!``(F00`
+M"XD%``R9!0`/J&8``+AF``.H9P`$N&<`!ZAD``BX9``+J&4`#+AE``\E"``0
+M%0+_[B1C`!`0`/[RCZ@#\(T&``"-!P`$C0(`"(T%``RL9@``K&<`!*QB``BL
+M90`,)0@`$!4$__8D8P`0$`#^Y8^H`_`D8P`L$`#^0:^C`]P0`/_])&,`(!""
+M``,D`B4`%(+^/(^D`]00`/_W)&,`%">]_Y"OJP`HCZL`<"0"`#^OO@!@K[<`
+M7*^V`%BOM0!4K[0`4*^R`$BOL0!$K[``0*^_`&2OLP!,`."@(:^B`"PD`O_!
+ME.<``I:#``RE8@``CZ(`*`%`D"&-2@`$)`L`/Z1+````"$0```E,```#&$"5
+M0@$6``A$`P`)3`,P8___KZ@`(*^I`"2OHP`PDI,`#@"`J"$`H(`A`,"X(3#^
+M-P`D%@`_``"((1!``!2OH``T`!$00`!*$"&40@$8,$/__Q!@``<R9/__,$(`
+M!P`1,8`09`$E-$(`X%""`22.10`0CDH`!"8C``$P<?__E4(!%@(B$"L40/_O
+M`!$00#/"-P"OH@`XCZ,`."0"%`!08@#JCD(`!*^V`"PSP@0`$$``:H*3``\S
+MT1``4B``X9;G``"6YP!2)N8`5`*@("$"@"@A#`!'&@.@0"&/HP`PEH0``@!S
+M$","PA@J`L,0"P`"%``PA`$`$(``%``"3`.60P``+&(P`11``!&7H@`&CD4`
+M!"QB0`"4HP`(`2,@*@$D&`L``QP`%$``"``#3`-2(``'EZ(`!I2B``H!(A@J
+M`2,0"P`"%````DP#EZ(`!H^K`"`!(A@J`2,0"P`"%````A0#``L@0`!$(",`
+M!"0```1,`Z^B`#0%(`"P`2`0(8^C`"0``A0```),`P$C$"I40``!`2`8(9:D
+M&\8``Q0`$(```P`"3`,`!!1```),`Y>B``27HP`"EZ0```$B*"H!(S`J`20X
+M*@$E$`L!)A@+`2<@"Z8"``JF`P`,I@0`#J8)``BF"0`&I@D`!*8)``*F"0``
+MED(``"Q"0`!40``,I@D`'C/#$``08`"*CD(`!)1"``X!(A`J5$``!`$@$"$0
+M8`""CD(`!)1"``ZF`@`>E@(`#H^K`"B.I!OTI6(``)8#`````Q0```(4`ZZB
+M!9RL@@`HCZ(`<*1#```SP@(`%$``%8^C`#@D`A0`4&(`$Y;G`'*/HP!PCZ0`
+M-(^_`&2$8@``KJ0%H(^^`&"NH@6<C[<`7(^V`%B/M0!4C[0`4(^S`$R/L@!(
+MC[$`1(^P`$`#X``()[T`<);G`'("H"`A)N8`=`*`*"$,`$<:)Z@`$(^D`#"/
+MJP`L`),8(P%C$"H!8A@+EZ(`%@`#'````TP#`2(8*@!`4"$!(Q`+CZ,`-`!B
+M$"H00``(CZL`(`$J$"H!("`A`4(@"@`$%````A0#KZ(`-(^K`"`!*A`J`4)(
+M"@`+$$`!(A`C``(4```"3`,%(``X`2`0(8^C`"0``A0```),`P$C$"H00``"
+M`&`P(0$@,"&7I0`0EZ,`%)>D`!(`!A0```),`P$E$"H!(B@+`2HP*@$C."H!
+M)$`J`2`0(0%&$`H!)Q@+`2@@"Z8"`!"F`P`4I@0`&*8%`!RF`P`2I@0`%J8%
+M`!J6HAO&$$``#(^D`"@``A!`I@(`$*8"`!:F`@`4I@(`$I:B&\8``A!`I@(`
+M&*8"`!RF`@`:CZ0`*)8#`!J$@@```&(0*E1```&D@P``CZL`<)8#`!"%8@``
+M`$,0*E1`_Y>E8P``$`#_EH^C`'`0`/_(```0(1``_W^40@`,$`#_=Y1"``P0
+M`/]0```0(1``_R$FY@`",F,`^#1S``&40@$6$$#_%```B"&.0P`$`!$00`!#
+M$"&40@$8,$/__Q!@``<R9/__,$(`!P`1,8`09``,-$(`X%""``N.10`0CD(`
+M!"8C``$P<?__E$(!%@(B$"M40/_NCD,`!!``_O\SP@0`CD4`$):$```,`$;<
+M`*8H(8^K`"P`0#`A`$`@(0%B*"LR8P#X)`(`X%1B_O*OI@`L5*```0%@("$P
+MA/__$`#_YZ^D`"R.10`0EH0```P`1MP`IB@A`$`P(0!`("$"PB@K,F,`^"0"
+M`.!48O[;`,"P(52@``$"P"`A$`#^T#"6__^,@AOT`*!@(2>]_^",0@``)`4`
+M"(Q"``2`3@`BB8(``)F"``.)@P`$F8,`!XF$``B9A``+B8@`#)F(``^KH@``
+MNZ(``ZNC``2[HP`'JZ0`"+ND``NKJ``,NZ@`#XF"`!"9@@`3B8,`%)F#`!>)
+MA``8F80`&XF(`!R9B``?JZ(`$+NB`!.KHP`4NZ,`%ZND`!B[I``;JZ@`'+NH
+M`!\`!5A``7T8(91B`````$@A``!H(0!.$".D8@```7U`(84"```$0@`!I0``
+M`"0"``@1(@`Y``D00`!,$"&40P``A0H``"4B``$P2?__$4,`)Y4$```M(@`0
+M5$#_\0%]0"$!?2`AA((``"A"`$`40``$`6P0(20"`#^D@@```6P0(91"``"$
+MA```)*4``0!'$",H0P````,0"P`"$$``1A`AE$,````$($`PI?__`(8@(2RB
+M``\40/_2I(,``"0%``@`!1A``'T0(91$```DH@`!,$7__P!L&"$LH@`/%$#_
+M^*1D```#X``()[T`(!%```4D@@`!+:(`,Q1```(D@O__)((``:4"```EH@`!
+M,$W__Q``_]```$@A$`#_SB0)``\GO?_`K[,`+*^R`"BOL0`D,)+__Z^_`#"O
+ML``@`*"((203`#\``"`A``00P`!1$"&40P````000"2&``$08``%`%TH(3#$
+M__\L@@`(%$#_]J2C````@(`A)Z<`$`)`("$GJ``2`Z`H(0P`1[L"`#`A$@``
+M"P``("&7I0`0``000`!=$"&40@``$$4`!22#``$P9/__`)`0*Q1`__D`!!!`
+MEZ,`$)>B`!(08@`/``00P`!1$"&,0@`$$$```P`$$,``41`AE%,``@)@$"&/
+MOP`PC[,`+(^R`"B/L0`DC[``(`/@``@GO0!`%'+_\0`````0`/_T`%$0(2>]
+M_\"OL``@,/#__Z^V`#BOM0`TK[0`,*^S`"ROL@`H`*"8(:^_`#ROL0`D`,"0
+M(0$`J"$``*`A``"P(1(```T``"@A``40@`!%$"$``A!``%(0(91$``@DHP`!
+M``400#!E__\`71`A`+`8*Q1@__6D1```EF0```.@*"$GIP`0)Z@`$@P`1[L"
+M`#`A$@``#@``*"&7IP`0EZ8`$@`%$$``71`AE$,``"2D``$`9Q`F$&8`-P"B
+MH`HPA?__`+`0*Q1`__<`!1!``!2`@``6B(`"%(`A`C:((0`0@$``$8A``C*(
+M(0(2@"&6!P`&EB@`!I9D``"7I0`0EZ8`$@P`1X```$@AIJ(`!I8'``26*``$
+MEF0``)>E`!"7I@`2#`!'@```2"&FH@`$E@<``I8H``*69```EZ4`$)>F`!(,
+M`$>```!((::B``*6!P``EB@``)9D``"7I0`0EZ8`$@P`1X```$@AIJ(``(^_
+M`#R/M@`XC[4`-(^T`#"/LP`LC[(`*(^Q`"2/L``@`^``"">]`$`0`/_-`*"P
+M(3#G__\Q"/__<.@0`C"*__\PI?__,,;__R0$`&000``>```8(20"``$0Q0`I
+M`$D@"P%%&",``Q!``$,0(0`"$,``0Q`A``(0@`#%&",`0P`:4&```0```<T`
+M`!`2``(4```"'`,$8``:*&(`951```PD`@!D42``!S$"__\`"!!``$@0(0`"
+M$,``2!`A``(0@#!"__\`0!@A`^``"`!@$"$`0Q`C`$<`&%"```$```'-<&@`
+M````$!(```````````!$`!H``!@2$`#_\C!B__]1(/_P,.+__P`'$$``1Q`A
+M``(0P!``_^D`1Q`AE*L```"@4"$PA/__,67__P`%&$``!!!``&48(0!$$"$`
+M`QC``&48(0`"$,``1!`A,,;__P`#&(```DB`)&/_]@`&$$`!0A`A`2,8*Q!@
+M``641/_^I.L``)5"```#X``(I0(````$$$``1!`A``(0P`!$$"$``A"`)$(`
+M"@!)$"L00``$`````*3D```#X``(I00``!#``!\``%@A``LH0`"J$"&40P``
+M``,00`!#$"$``A#``$,0(0`"$(`!(A@C`$D0(RAC``H$0``<*$0`"A2``!8`
+MJA`A`*H@(92#``(E8@`!,$O__P`#$$``0Q`A``(0P`!#$"$``A"`)$+_]@$B
+M$"L40``%`68H*Q2@_^0`"RA``^``"`````"4@@``I.(``!``_\V4@@`"E$,`
+M`*3C```0`/_)E$(``%!@_^<`JB`A$`#_^0"J$"$\`H`")$8N/#P"@`(D0RS,
+ME((<]B3(``@P0@#P+$(`,!1```\D9P`(C,0`!"0"`%6LH@`0)`(``:RB`!@`
+M!!#``$00(0`"$(`D`P`4`$@0(:RC``RLH@`<`^``"*RD``",9``$)`(`(ZRB
+M`!`D`@`!K*(`&``$$,``1!`A``(0@"0#`!2LHP`,$`#_\@!'$"$GO?_PK[``
+M`*^_``24@ASV`*"`(3!"`/`L0@`P%$``(20%``<,`$GM``````!`("$D!@`D
+M```X(0P`/PXD!0`!)`,``20'`&L``#`A$$,`$"0$`&N.!0`$``!`(0#E$"L0
+M0``&`*88*Q1@``,`A2@K$*```X^_``0D"``!C[\`!(^P```!`!`A`^``"">]
+M`!`D`@`W)`<`4R0$`%,0`/_MK@(`$`P`2>T``````$`@(20&`"4``#@A#``_
+M#B0%``8X1``_)`8`0``$,`HDPP`W),4`(P!D*`LD`P`4``08"R1"``0D!P`R
+M`$0X"ZX#``RN!0`0$`#_UR3$`#*,A1OTC(0``#0#@`",H@`HA*8`)`"#("$`
+M1A`A``(20#!"?@`T0H``K((9,"0"``$#X``(K*(`,">]__"OL0`$K[\`"*^P
+M``",A1OT`("((8RP``2.`@`8$$``!R0$__^,HP`P)`(``5!B``F.(@``CB(;
+M](Q$`#"/OP`(C[$`!(^P````@!`A`^``"">]`!`T`X```$,0(8Q$&3`P@H``
+M5$#_](XB&_0`!!W",&,``P`$)D(D`@`"$&(`):X$``26(ASV,$(`\"Q"`#`0
+M0``6`B`@(8XB&_26)AMR`B`@(:Q``#`,`$@R`@`H(51`_^&.(AOT#`!(SP(`
+M("%00/_=CB(;]`(`*"$,`$C;`B`@(1A`_]<D`@`"CB,;]*QB`#`0`/_3K&``
+M+`P`23L"`"@AC@0`!(X#`!0`@Q`K5$#_Y:X```0`@Q`C$`#_XJX"``26(AST
+M+$(`0A1```4D@@`%C*(``(Q"``2`0@`B`((0(1``_].N`@`$C(,`!(R"``P`
+M0Q`K$$``!0``*"&,@@`0`&(0*Q1```(`````)`4``0/@``@`H!`AE((<]C!"
+M`/`L0@`P%$``60"@,"$\`H`")$(N/(S%```\`X`#K&**L#P"@`.,1XJP``40
+MP`!%$"&,Q``$C,@`$``"$(``XA`A)$(`"`"(&"L48``>K,(`'!"@`!HD`___
+MK,0`"(S#```\`H`#C$2*L"1G__\`!QC`C,(`'`!G&"$``QB``&08(:S'``",
+M10`0C&(`&(S$``@D8P`(`$40(P`"$$``@B`C`(@0*ZS#`!P40``#K,0`"%3@
+M_^N,PP``)`,``0/@``@`8!`AC,D`#`$D$"L40/_[```8(8SB```D0O__$*+_
+M]R0#__ZLQ``(C.(``"1"__\`HA`K$$#_\20#``*,PP``/`*``XQ(BK`D9P`!
+M``<8P(S"`!P`9Q@A``,8@*S'````:!@AC$4`$(QB`!B,Q``()&,`"`!%$",`
+M`A!``((@(P$D$"NLPP`<%$``!JS$``B-`@``)$+__P#B$"M40/_HC,,``!``
+M_]4D`P`"/`*``A``_Z@D0BS,)[W_\*^Q``2LH``4`*"((20%``>OOP`,K[(`
+M"*^P```,`$GM`("`(0!`("$D!0`!)`8`)`P`/PX``#@A`$"0(20"``%20@`'
+MCB(`'(^_``R/L@`(C[$`!(^P```#X``()[T`$`(`("$D!0`'#`!)[810````
+M0"`A)`4`!"0&`"`,`#\.```X(1(2``X`0!@A4@#_[JX@`!0D`@`"$@(`!P`#
+M$$`D`@`#%@+_Z8^_``P``Q!`$`#_Y:XB`!00`/_])$+_^Q``_^&N(@`4)[W_
+MX*^U`!2OM``0K[\`&*^S``ROL@`(K[$`!*^P``"4H@`"`*"H(3!"`0`00`!Q
+M`("@(8R0'`2.`@``&$``'@``F"$F$0`HDB8`"Y(H``@"`"`A``800`!&$"$`
+M`A#``%`0(8Q#`"@\`H`")$)$```#&(``8A@AC&(````(0(`T`X<`)`4`#@``
+M."$`0/@)`0.0(0!`,"&.`P``CH(``"9S``$"8Q@J`%(0(:Q&```48/_E)C$`
+M&):B``(P0@$`%$``"H^_`!B.D!P,C@(``!A```8``)@AC@,`*"0"``(08@`*
+M)A$`*(^_`!B/M0`4C[0`$(^S``R/L@`(C[$`!(^P```#X``()[T`()(F``L\
+M`H`")%5$```&$$``1A`A``(0P`!0$"&,0@`HDB@`"#0#AP```A"``%40(8Q"
+M````"$"``@`@(20%``X``#@A`$#X"0$#D"$`0#`ACH(```(`("$D!0`.`%(0
+M(:Q&``"2(P`))`<``29S``$``Q"`%&``"P)"D"&.`@```F(0*A!`_]4F,0`8
+MCB,``"0"``)08O_;DB8`"Q``_]"/OP`8DB8`"P`&$$``1A`A``(0P`!0$"&,
+M0@`H``(0@`!5$"&,0@```$#X"0``````0#`ACH(```!2$"&L1@``$`#_YXX"
+M```0`/^0C)`<%)2"'/8P0@#P+$(`,!1``!,PI?__C(,;]"2E__\LH@`'$$``
+M#HQD`"`\`X`"``40@"1C#[P`0Q`AC$(```!```@``````^``"`"`$"$#X``(
+M)((`!`/@``@D@@`(`^``"```$"$#X``()((`#`/@``@D@@"L)[W_\*^Q``2O
+ML````("((0"@@"&OOP`(#``I;#P%@`".)P``)`/\#P(@("&,X@`P/`6```!#
+M0"0P0@/P``(1`BQ&`"42```3+$,``A#```TD0@`!``(1`#!"`_`!`A`EK.(`
+M,`P`*3P`````)`(``8^_``B/L0`$C[````/@``@GO0`0#``I/#P%@``0`/_X
+M```0(1!@_^\D0O__$`#_^0(@("&,P@`4C,<`$"0#``$`0Q`$`(!((0#`0"$`
+MXQ@$C,8`#"1"__\\!``/-(3\`"1C__\``A*``$00)(TG```P8P/_`&(8)0`&
+M-0`\`@_P`,(P)``%*(``9A@E`.4X(:SC$$"-)```C0,`(#P"``\T0O__`&(X
+M)!!@``,`A2`A/`(`$`#B."6-`@`$K(<0P#!&`"`P0@`$$$``!CP$`""-(@``
+M`$40(8Q#$0``9!@EK$,1`!#```8`````C2,```!E&"&,8A$`-$("`*QB$0`#
+MX``(`````">]__"OOP`$K[```(R(&_2,L``(C*,`!(T'``@D`@`!`@)(!`#I
+M."4P:@`",&,``0"@,"&M!P`($&``!`(`*"&-`@`,`$D0):T"``P10``$````
+M`(T"`!``21`EK0(`$`P`3HL``````@`0(8^_``2/L````^``"">]`!",A!OT
+M)`(``0"B$`2,A@`(C(<`#(R#`!```A`G`,(P)`!B&"0`XC@DK(,`$*R&``@#
+MX``(K(<`#(R"````!2B`)*4(``!%$"&L1@```^``"`````",@P``)`(``0"B
+M$`2L8@A``^``"`````",@AOTC$,`""0"``$`HC`$`&88)``%*(`DI0H`$&``
+M"@``$"&,A````(40(8Q"```P0@`#%$``!`````",@@A``$80)``"$"L#X``(
+M`````">]__``!A!`K[(`"*^Q``2OL```K[\`#`!&$"$`@(@A``(0P(R$````
+M1A`A)`,``0"C&`0`H)`A``*`@*R#"(`"("`A#`!*H@)`*"$F$/__$$``!R0$
+M``H&`@`&CB(```P`:3\`````$`#_]@(@("&.(@``C[\`#(^R``B/L0`$C[``
+M`*Q`"(`#X``()[T`$!"@`!4`H#@AD*(`#@`"$0(P0@`!$$``$8SB``@\`]__
+M``8@*S1C__\`0Q`D``0G0`!$$"6LX@`(C.<`(%#@``>,X@`(D.(`#@`"$0(P
+M0@`!5$#_\HSB``B,X@`(/`/?_P`&("LT8___`$,0)``$+T`\`_]_`$40)31C
+M__\`0Q`D``0EP`!$$"4#X``(K.(`"``($,``2!`C)[W_P``"$("OO@`PK[<`
+M+*^V`"BOM``@K[,`'*^R`!BOL0`4K[``$*^_`#2OM0`D`$00(8Q"&=@`@)`A
+M`*#P(:^B``2/HP`$)`(``:^F````X)@A``"@(0``L"$``+@AKZ(`"*^@``P`
+M`(@A%&``#B2P``B/H@`,C[\`-(^^`#"/MP`LC[8`*(^U`"2/M``@C[,`'(^R
+M`!B/L0`4C[``$`/@``@GO0!`#``I;#P%@``28``:)`/_\"9T``@R@@`/)$(`
+M)P!#*"0"@Q@D`&40(0!#$"L40``'`&`@(;QQ```D8P`0`(40(0!#$"L00/_[
+M``````)`("$"8"@A#`!.AR0&``&OH@`(CH(``(Z#``@``HV",'9__S(Q``$"
+M0"`A#``I/#P%@`".`P``/`*`0(X%``P`8A@DC@0`"(^B``@`!34",)5__P`#
+M&"L40``+,,8`'U!@``H#P"@A5B``2H_"`$R/HP`$`M40(0!7$",`8A`K$$``
+M$`*W$",#P"@A`D`@(0P`2MHD!@`!CZ,`#!!@_[B/H@``4$#_MX^B``R,10`P
+M`D`@(0P`2MH``#`A$`#_L8^B``P"0"`A/`6```P`*6P"PK`A$F``'"9E``@P
+MH@`/CH0`""0#__`D0@`G`*,H)`!#,"0D`H```((@)#+#?_\`IA`A`(,@)0!%
+M$"NNA``(%$``!P"@&"&\L0``)*4`$`!F$"$`11`K$$#_^P`````"8"@A`D`@
+M(0P`3H<D!@`!+$(``:^B``P"0"`A#``I/#P%@`"/H@`,$$#_S`/`*"&.!```
+MC@4`"#P"_[\T0O__/`-__P""("0T8___)`*```"#("0`HB@DK@4`"!``_[ZN
+M!```)`4`#HQ#`#P`9A`AD$8`!`!@("$`!A!``$80(0`"$,``0Q`AC$,`*#P"
+M@`(D0D0```,8@`!B&"&,8@```$#X"20'``$0`/^E`$"X(2>]_\"OM``@K[(`
+M&*^Q`!2OL``0K[\`-*^^`#"OMP`LK[8`**^U`"2OLP`<C((;-`"`D"&,O@`H
+M`*"`(0#`H"$DL0`(C+,`4(RD`$P40``1KZ```%)@``63PP``CF(`!!1```P`
+M````D\,``#!B``P40``')`(``3!C`/`D`@!`$&(`!"0"`%`08@`")`(``:^B
+M```0@`'*`````(R6`#R.`@`L`D`@(0(`*"&L0``8K$``'`P`4Z```````$"X
+M(0`"$$".)0```%<0(98D``H``A#``L(0(3P#`#\`HR@E)%4`))*F``^N)0``
+MKB0`"(Y"&\@\`^'_-&/__R1"``$P0@`/``(4``""("4`HR@DKB0`"*XE``"3
+MPP``CB0`!#P%_P\P8P#\.&,`4"0"``,``Q`+-*7__P`"%0``A2`D`((@):XD
+M``0`!A!``$80(9/#`````A#``L(0(21&`"0P8P`,)`(`"%!B`8R3P@`!)`)_
+M_Q*"``P\`O_PCB0`!(XE```T0A__,H,`?P""("0``QM`/`)```"B*"4`@R`E
+MKB0`!*XE```28``9/`2?_Y9B`1B.(P`$``(0@C!"``,TA/__``(70`!D&"0`
+M8A@EKB,`!(X"`"B00@`!,$(`0!!```,``"`AEF(!%@`"((*.(@`$/`/G_S"$
+M``,T8___`$,0)``$)L``1!`EKB(`!)/"``23Q```,$<``3"#``PD`@`($&(!
+M1S"#`/`D`P`#CB0`!#P"^?\T0O__,&,``P""("0``QY``(,@):XD``2.0AMH
+M4$`!,9/"`!828`$N/`+^_XX#`%B.)```C&,`)#1"__\`@B`D``,8P`)C&"$D
+M8P`PC&(`!``"$"L``A8``((@):XD``"L8``$$.``\XXD``".)0`$/`+_OS1"
+M__\\`W__`((@)#1C__\\`@$``*(H)0"#("2N)0`$KB0``(ZC``0D`@`#4&(`
+MW(XB```28``&```@(99"&W(D`Q0`,$(W`%!#`-*.8@`L$(``-X^C``".0ALX
+M$$``-`````".H@`$%$``,0`````4X``O`````(Y#&SP``Q!``$,0(0`"$,"/
+MHP```%80(21"`"@08``#D$0`")!"``D`@B`ECB,`##P4_@\P@@`?-I3__P`"
+M%0``=!@D`&(8):XC``R3P@`!,$(`!%1```:.8P`LD\(`%C!"``]00``&CB0`
+M`(YC`"PD`@`!$&(`CP(`("&.)`````05@C!"``$40``+CZ,``(Y#&]0D`@`!
+M$&(`@#P#@``\`O^_-$+__P""$"0`0Q`EKB(``(^C```08``#DJ0`#)*B``T`
+M@B`ECB(`#"0#_^`PA``?`$,0)`!$$"6N(@`,CZ(``%!```*6LP`2EK,`%(XC
+M```\`H!``&(0)%!``"F.1`6,CB(`"``#'8(D%(```%00)#!C``$48`!'KB(`
+M"``7$$``5Q`A``(0P`!6$"&,0P`H/`*``B1"1````QB``&(8(8XE``",8@``
+MCZ<``(XP``@PI0__`L`@(0!`^`D"X#`ACB,`"#(0?_\"`H`A,A!__P!T&"22
+M)0`$`'`8)3!B?_\PI0`!`%,@(0"%$`H`=!@D,$)__P!B&"6N(P`(CD0%C!"`
+M`"*6H@`(``08P`!D&"$``A'`/`3,S`!B&"$TA,S-`&0`&0``&!```QC"DB(`
+M!*Y#!8P``!@A,$(``0)B&`HP8@#_``(2```#&@(`0Q`E``(:`J/"``.CPP`"
+MC[\`-(^^`#"/MP`LC[8`*(^U`"2/M``@C[,`'(^R`!B/L0`4C[``$`/@``@G
+MO0!`$`#_YP`"&<".(@`,CZ<```+`("$``A4",$(`'P+"$"&01@`$``800`!&
+M$"$``A#``%80(8Q#`"@\`H`")$)$```#&(``8A@AC&(```!`^`DD!0`.CB,`
+M"#!"?_\`=!@D`&(8)1``_Z*N(P`(/`-__SP"`$``@A`E-&/__Q``_X``0Q`D
+M#`!6R0+@*"$`0+@A``(00`!7$"$``A#``L(0(215`"22I@`/``800`!&$"$`
+M`A#``L(0(21&`"2/H@``$$```Y#$``R0P@`-`((@)8XC``PP@@`?``(5``!T
+M&"0`8A@E$`#_9ZXC``PX0@`!$`#_+2Q$``$\`_^_-&/__SP$?_\`0Q`D-(3_
+M_P!$$"00`/\>KB(``)9#&]P\!?^_,((/_P!B&"HTI?__``,=@`"%("0`@R`E
+MKB0``)("`#PP0@`!4$``!(X"`#P`A1`DKB(``(X"`#P``A;",$(`#U!```:.
+M(P``CB(``#P#`$``0Q`EKB(``(XC```\`G__-$+__P!B&"2N(P``CZ,``!!@
+M``.0Q``,D,(`#0""("6.(@`,/`/^#S"$`!\T8___`$,0)``$)0``1!`E$`#^
+M[ZXB``R3P@`6CB,``#P$_O\P0@`/+$(``32$__\`9!@D``(6``!B&"40`/[7
+MKB,``"0"`$`08OZY)`,``Q)@_K<D`G__AF,!%%!B_K0D`P`#5.#^LB0#``..
+M(@``,$(/_RA"`0$40/ZM)`,``HX"`%B,0@`D+$(``E!`_JF.)``$$`#^IHY#
+M&]`P0@!`$$#^="0"?_\6@OYR`````)9"&_"N`@`X$`#^;0!`H"$,`%)>ED0;
+M<@`"$(``4A`A$`#^,XQ6'``GO?_0K[(`"`"@D"$DI0`(,*(`#Z^U`!2OLP`,
+MK[$`!*^P``"OOP`@K[<`'*^V`!BOM``0)`/_\"1"`">.5``P`*,H)`!#,"0`
+MIA`A`$40*P"`J"$F4``8)I,`"(Z6`%".EP`H))$$@!1```<`H!@AO+$``"2E
+M`!``9A`A`$40*Q!`__L``````J`@(0)`*"$,`$Z')`8``1!``&8D`P`-D@(`
+M`XYC``PP0@`!$$``J3!I`!\D`@`!KD(`0)8"``8``A!",$(/_Z9"`$:6`@``
+MID(`1)("``*2`P`#HDD`2C!"``\``QD"`$,0(:9"`$B28@`$,$(``1!``)(`
+M````$L``!20*`!Z"P@"Z%$```@!`4"$D"@`>D@(``S!"``$00`!K*4+_[!1`
+M``Z.(P$()`(!)Q!B`&0``Q#``$,0(0`*(<`\`V9F`$00(31C9F<`0P`8``(7
+MPP``&!```QB#`&(8(Y("``(P0@`/%$``!:XC`0B2`@`#``(1`A!``!8`````
+MCB0`>(XE`'R.8@``)*4``0`"%8(LHP`!`(,@(3!"``&N)`!XKB4`?!1``$$`
+M`#`AD@(``C!"``\00``X``88@``"&(``<1@AC&(`P"1"``&L8@#`D@(`!0`"
+M$<(00``$`````(XB`%PD0@`!KB(`7)("``,``A#",$(``11```P``!@ACJ(;
+M1#!"``$00``)C[\`()+B``0P0@`!%$``!H^W`!R.@@!,5$``#8Q"`#R/OP`@
+MC[<`'(^V`!B/M0`4C[0`$(^S``R/L@`(C[$`!(^P````8!`A`^``"">]`#"2
+M"``#CF<```!)$"&2"P`$D$8`!)9)`$@`"$!",.</_S$(``$Q:P`!`J`@(0P`
+M5/,"P"@A$`#_Y@``&"$`<1@AC&(`@"1"``$0`/_*K&(`@)("``.2`P`"``(1
+M`A``_[XP9@`/$`#_I@`*&<"2`@`#CB,`0``"$$(D8P`!,$(``1!```6N(P!`
+MCB(`1"1"``$0`/^_KB(`1)("``,``A#",$(``1!```4`````CB(`<"1"``$0
+M`/^VKB(`<)("``,``A"",$(``1!`_[$`````CB(`2"1"``$0`/^MKB(`2(X"
+M``0``A+`$`#_<@`"5@.2`@`#``(00C!"``%00/]5)`(``Q``_U,D`@`")*4`
+M&)"B``<#X``(,$(``8S*````P#@A`*!8(0"`0"$10`"V``5(@(S#`!2,Q``0
+M)`(``0!B&`2,Q0`,`((0!"1C__\\!``/)$+__P`#&H`TA/P`C08```!D&"0P
+M0@/_`$,0)0`%+0`\`P_P`*,H)`!%$"4`R3`AK,(00(T"&V@\!0`($$``O32E
+M(`"-!!O()`(`#RR#`!``0R`*``01`#!"`/`P@P`/`$,0)0!%*"6-`@``)`,(
+M``!)$"&L11"`C0(```!)$"&L0PG`C.4`&%"@`!.,Y``DC.,`'(T$```\`@#_
+M-$+__P"B$"0``QX``$,0)0")("&L@@C`C0,``(SE`!P`:1@AC&()P#1$`0$T
+M0@`!`(40"ZQB"<",Y``D4(``"HT$``"-`@``/`,`_S1C__\`@Q@D/`0!``!D
+M&"4`21`AK$,)`(T$``",XP`@/`(`#S1"__\`B2`A$&```P!B*"0\`@`0`*(H
+M):R%$,",X@`@4$``"XSE``2,X@`$,$(`$%!```>,Y0`$C0,```!I&"&,8@G`
+M-$("`*QB"<",Y0`$,*(`!!!```@PH@`@C0(``#P$`"``21`AC$,1``!D&"6L
+M0Q$`,*(`(!!```<D`@`"C0,```!I&"&,8A$`-$("`*QB$0`D`@`"44(`5XT#
+M```D`@`#44(`2(T#```D`@`$44(`/XT#```PH@`(4$``%(T$``",X@`H4$``
+M$8T$``"-`P````L00"1"`%"L8@L`C.,`*(T"``"L0PL$C0,``(T"&P"L8@L(
+MC0,```!I&"&,8@G`-$(0`*QB"<"-!```C04;]"0&_`",@@"DC*,`##P'_```
+M1A`D,&,#_P!#$"6L@@"DC00``(RC``PTY___C((`J#!C`_\`1A`D`$,0):R"
+M`*B-!```C*,`#(R"`*PP8P/_`$80)`!#$"6L@@"LC08``(RB`!`\!`/_C,,`
+MI``"%```1!`D`&<8)`!B&"6LPP"DC0,```!I&"&,8A$`-$(!`*QB$0`#X``(
+M``````!I&"&,8@G`-$(`(*QB"<`0`/^^,*(`"#P$``0`:1@AC&()P#1"`&*L
+M8@G`C0,```!I&"&,8A$``$00):QB$0`0`/^O)`(`!#P$`"4`:1@AC&()P#1"
+M`**L8@G`C0,```!I&"&,8A$``$00):QB$0`0`/^@)`(``SP%``@0`/]+-*4@
+MJB>]__"OL0`$K[```*^_``B,H@"$)`8`!`"@@"$40``&`("((8^_``B/L0`$
+MC[````/@``@GO0`0#`!*MHRE`&R.!0!L#`!*AP(@("$,`'IJC@0`A!``__.N
+M``"$)[W_X*^S``ROL@`(K[$`!*^_`!"OL````("8(0#`B"$0P``I))(<&(Y0
+M`(02```M`````"8$``@``"@A#`!PJB0&`!B6`@`.C@0`*(XE``2.)@`,,$(/
+M_PP`<)T`@B`AE@(`#HXD``R6`P`.,$(/_P!$$"$D!/``,$(/_P!D&"0`8A@E
+MI@,`#HXQ```6(/_M`````)8"``Z6`P`*KA(`3#!"#_\D0@`$`&08)#!"#_\`
+M8A@EI@,`"@)@("$"`"@A#`!8H0``,"&/OP`0C[,`#(^R``B/L0`$C[````/@
+M``@GO0`@#`!Z5R0$`-P`0(`A`$`@(0``*"$,`'"J)`8`7"8"`%RN4`"$K@``
+M`*X``""N`@`$K@(`*!``_\:N$``D)[W_L*^P`#``@(`AK[,`/*^Q`#2OOP!`
+MK[(`.`.@("$``"@A)A$<&`#`F"$D!@`L#`!PJHXR`(2.(@`$C@8;]``"&$``
+M8A@A/`*``B1"+ZP``QB``&(8(8QD``2,90`(C&,``"2$``$D`@`%KZ(`"*^E
+M`!2OI``0KZ,`#(S#``@D`@`")`8`!#!C`"`"`"`A)`4`!11@`!VOH@``#`!1
+MKR8$'&`00``))`/__X^_`$"/LP`\C[(`.(^Q`#2/L``P`&`0(0/@``@GO0!0
+M`@`@(0P`2F@#H"@ACD8`)`!`*"&N(@!L#`!*E0(`("&.)0!L#`!*G`(`("$"
+M`"`A#`!9$@)@*"$0`/_I```8(0P`2K8`````CZ4`"`P`2H<"`"`A$`#_W@``
+M```GO?_@K[$`!"0"__\DD1P8K[8`&*^U`!2OM``0K[,`#*^R``BOL```K[\`
+M'#P%``0`@(`A`,"8(0#@H"$!`)`A`4"H(0$@L"$0X@`FIB8`@@P`4EZ4A!MR
+M.$D``0(`("$"0"@A`F`P(0*`."&N(@`$`$`8(1*@``0X2``$)`(``P!(&`H`
+M"1@*``,0@`!0$"&,0AP`KA48`*XV`!RN`AQ4ED(``*8B`$*60@`"IB(`1)9"
+M``0,`"SJIB(`1H^_`!R/M@`8C[4`%(^T`!"/LP`,C[(`"(^Q``2/L````^``
+M"">]`"`D`@`!K((;L"0"``:L@`6,K(`8``P`*6RN(@`$`@`@(0)`*"$``#`A
+M#``LZ@``."$"`"`A#`!/:0(@*"$0`/_GC[\`'"2E__XLH@`F``!((1!``"0`
+M`%`A/`.``@`%$(`D8P_8`$,0(8Q"````0``(`````(R)!'@50``%`````%3@
+M``&LZ0``5,```:S```!5```!K0H```/@``@`````$`#_]8R)!'P0`/_SE(D<
+M\!``__&4B1SR$`#_[Y2)'/00`/_ME(D<]A``_^N4B1SX$`#_Z0``2"&,@AOT
+M$`#_YHQ)`#00`/_D)`H`#HR"&_00`/_AC$D`<(R"&_00`/_>C$D`.(R"&_00
+M`/_;C$D`/(R"&_00`/_8C$D`0(R"&_00`/_5C$D`1(R"&_00`/_2C$D`2(R"
+M&_00`/_/C$D`3(R"&_00`/_,C$D`4(R"&_00`/_)C$D`5(R"&_00`/_&C$D`
+M6(R"&_00`/_#C$D`7(R"&_00`/_`C$D`8(R"&_00`/^]C$D`9(R"&_00`/^Z
+MC$D`:(R"&_2,0@!L)$G__RTB``500/^T)`D`!!``_[(`````C((;]!``_Z^4
+M20!TC((;]!``_ZR420!VC((;]!``_ZF420!XC((;]!``_Z:420!ZC((;]!``
+M_Z.,20!\C((;]!``_Z",20"`C((;]!``_YV,20"$C((;]!``_YJ,20"(C((;
+M]!``_Y>,20",C((;]!``_Y2,20"0C((;]!``_Y&,20"4C((;]!``_XZ,20"8
+MC((;]!``_XN,20"<``40P`!%$"$``A#``$40(R>]_^```A"`K[,`#*^R``BO
+ML0`$K[```*^_`!``@H`AC@(`"`"`D"$`X)@A$$``""81``B/OP`0C[,`#(^R
+M``B/L0`$C[````/@``@GO0`@`B`@(0``*"$,`'"J)`8!'"9$'!@0@/_S)`(`
+M!HR#``008O_P)`(``:X"``@F`P`\)`4``R0"``$DI?__K&(```2A__TD8P`(
+M`F`X(28B``0F8P`@C.4``(SF``2,Z``(C.D`#*Q%``"L1@`$K$@`"*Q)``PD
+MYP`0%./_]B1"`!",XP``C.4`!(SF``BL0P``K$4`!*Q&``BN)`!8#`!39P(@
+M("$"("`A#`!2Q0``*"$,`'&T)B0`7!``_\N/OP`0``40P`!%$"$``A#``$40
+M(P`"$(``@B`A)[W_\"0"``:OOP``$,(`#B2%``@LP@`'$$``!R0"``<D`@`"
+M4,(``:RH``2/OP```^``"">]`!!0PO_\K*@`+!``__N/OP``)(0`$`$$$"4P
+M0@`#$$``'"4#`"``8!`AB0,``)D#``.)!@`$F08`!XD'``B9!P`+B0D`#)D)
+M``^H@P``N(,``ZB&``2XA@`'J(<`"+B'``NHB0`,N(D`#R4(`!`5`O_N)(0`
+M$($"``"@@@```*`@(0P`4L4D!0`!$`#_VX^_``"-`@``C08`!(T'``B-"0`,
+MK((``*R&``2LAP`(K(D`#"4(`!`5`__V)(0`$!``_^T```````40P`!%$"$`
+M`A#``$40(R>]__```A"`K[````""@"&OL@`(K[$`!*^_``PF$0`(CB(`>`"`
+MD"$\!8`"/`2``B2$$)PDI1!P%$``#B0&`0<,`'&[)@0`9`(@("$``"@A#`!P
+MJB0&`1RN```(C[\`#(^R``B/L0`$C[````/@``@GO0`0#`!P=``````F!0!D
+M#``0X`)`("$0`/_M`````">]__"OL@`(K[$`!*^P``"OOP`,`("0(0``B"$D
+MD``(C@(```(@*"$F$`$<)C$``11```H"0"`A*B(`!%1`__F.`@``C[\`#(^R
+M``B/L0`$C[````/@``@GO0`0#`!1;``````0`/_U*B(`!">]__"OL``````H
+M(20&`#BOOP`$#`!PJ@"`@"$,`'&T`@`@(8^_``2/L``````0(0/@``@GO0`0
+M`^``"(R"`!0GO?_PK[$`!*^P``"OOP`(#`!PM0"`B"&.,``4$@``"0````".
+M`@`@`%`8)@`#$`H40``"KB(`%*X@`!BN```@K@````P`<+H``````@`0(8^_
+M``B/L0`$C[````/@``@GO0`0)[W_\*^Q``0`@(@AK[(`"*^P``"OOP`,`,"`
+M(0P`<+4`H)`ACB(`*%!``!6N```@C@(`)*X0`""N`@``CB(`&%1```JL4@`@
+MKC(`%`P`<+JN,``8C[\`#(^R``B/L0`$C[````/@``@GO0`0CD,`)(XB`!BL
+M0P``$`#_]`````"N````$`#_[HXB`!@PQO__``800`!&$"$``A#``$00(91#
+M`"P\`A!B-$)-TP`#&(``8@`9``40P```&!```QF"`$,0(21"`!4`0P`;4&``
+M`0```<T``!`2``(0@"1"`"0#X``(,$+__S#&__\`!A!``$80(0`"$,``1!`A
+ME$,`+#P"$&(T0DW3``,8P`!B`!D`!1#````8$``#&8(`0Q`A)$(`%0!#`!M0
+M8``!```!S0``$!(``A"`)$(`%@/@``@P0O__,,;__P`&&$``9A@A``,8P`!D
+M&"$`!1(```4HP`!%$",D8P`HE&8`!``"$(``11`A``(0P`!&`!L``"@2$.``
+M!"0$`,"08P`))`(`8`!#(`L`A1`A)$(`"C!"__]0P``!```!S0/@``@`````
+M,,;__P`&$$``1A`A``(0P`!$$"&41``L/`(08C1"3=,`!!B``&(`&0`%$,`L
+MA`/H```8$``#&8(`0Q`A)$(`%0!#`!M08``!```!S0``$!(``A"`)$,`7"1"
+M`+T`9!`*`^``"#!"__\P@___,&((`!1```TD!``%,&("`!1```HD!``",&4W
+M`"0"%``0H@`&)`0``R0"%0`0H@`#)`0`!#!B`0```B`K`^``"`"`$"$#X``(
+MK(``.#"E`/\D`@`!`*(0!`!`&"$0P``%``(H)XR"`#@`0Q`E`^``"*R"`#B,
+M@@`X$`#__`!%$"0PI0#_%*``!(R#`#@``!`A`^``"*#````DI?__!*``"@``
+M$"$D`@`!`*(0!`!B$"040``')`(``22E__\$H__[`*(0!```$"$#X``(H,``
+M``/@``B@Q0``C*H`.*#@``"0H@`\)`@``0$"$"L00``C,,8`_P`($$``2!`A
+M``(0P``&&$``1$@A)`(``0!F&"$!`A`$``,8P`%"$"000``1`&08(94I`"R4
+M8@`L`2(0*U!```V0H@`\D.,````#$$``0Q`A``(0P!!@``4`1!`AE$(`+`!)
+M$"M00``#D*(`/*#H``"0H@`\)0,``3!H`/\!`A`K%$#_X``($$"0X@``%$``
+M`R0#``&@Y@`````8(0/@``@`8!`A)[W_T*^W`!ROM@`8K[$`!*^P``"OOP`D
+MK[X`(*^U`!2OM``0K[,`#*^R``B,@@!8))$`E"26``B,4P`\)`(`$Z(B`#P`
+M`+@A%*``$0``@"$`$!A``'`0(0`"$,``4Q`AD$(`-`!Q&"&@8``!H&(``)(B
+M`#PF`P`!,'``_P("$"L00``#`````!"@__(`$!A`#`!2<`(@("&2P@``CG0`
+M`!1``#,``*@A&H``$@``@"$`$!!``%`0(0`"$,``4Q`AC$,`)"0"``$"L4`A
+M)J<``0(`*"$"("`A$&(`'"0&``$F`@`!,%``_P(4$"H40/_Q`!`00*(U`&&2
+M8@,PHB(`8B;B``&B(@`\DF,#+P+C$"M40``!`N`8(:(C`#V/OP`DC[X`((^W
+M`!R/M@`8C[4`%(^T`!"/LP`,C[(`"(^Q``2/L````^``"">]`#"A$`!C#`!2
+M<C#U`/\"%Q`K$$```@(`&"$"X!@A$`#_W3!W`/\``(`A$$``&0``\"$:@``1
+M``"0(0`2$$``4A`A``(0P`!3("$"T!`AD$,``9""`#(P8P!_,$(`?U!B`"J,
+M@P`D)D(``3!2`/\"5!`J%$#_\@`2$$"2P@``)@,``3!P`/\"`A`K%$#_Z0``
+M``"2*``\``"`(0(($"L00``5CBD`.``0$$``4!`A``(0P"0&``$`4R@A`@80
+M!`$B$"0"L2`A)@<``1!```8FHP`!H)``8XRB`"@GQ``!$$8`"#!U`/\P\`#_
+M`@@0*Q1`_^X`$!!`HC4`81``_ZZB/@!B$`#_^#">`/\D`@`!`D`H(0(@("$4
+M8O_3)`8``0P`4G(``````E<0*Q!```("0!@A`N`8(1``_\LP=P#_)[W_\*^P
+M```DD`"4`@`@(0``*"&OOP`$#`!PJB0&`'P,`'%<```````#*(``HR@A``4H
+M0*X%`%2/OP`$C[````/@``@GO0`0``0F```%+@``!"8#``4N`P`&-@``!C8#
+M`(40*@"F0"H40``(`(8X*A$```0`H!@A`,`8(0#$$"H`@A@*`^``"`!@$"$0
+MX/_]`(`8(0#`&"$`IA`J$`#_^0"B&`N0IP``,(3__Q#@``L``!@A``,00`!%
+M$"&40@`"`((0*Q1```4D9@`!,,/__P!G$"M40/_X``,00`/@``@`8!`A)[W_
+MP*^^`#"OM0`DK[,`'*^Q`!2OOP`TK[<`+*^V`"BOM``@K[(`&*^P`!"4@AMR
+ME*,`"HRW`%```A("`("8(0"@J"$P<0__,%X``8RV`$R,HP`H```0(9"%&`,2
+MX``:D(08!XZB`#P``A)",$(``11```V.U``\CF(;V%!```N.H@`\D&(`!#!"
+M``%40``'CJ(`/)!B```D`P`(,$(`#!!#`!T`````CJ(`/"0#_?\`0Q`DKJ(`
+M/(YB'!12@@`.DL(`@);"`!Z/OP`TC[X`,(^W`"R/M@`HC[4`)(^T`""/LP`<
+MC[(`&(^Q`!2/L``0`^``"">]`$!00/_SEL(`'I:D``J.A0,T#`!3D#"$#_\0
+M`/_NC[\`-!"@``\F\`"4)`(``5""`0"2`@`]5(``"X($`":2`P`]``,00`!#
+M$"$``A#``%00(8Q#`"@D`@`!4&(`\)*"``."!``F@@4`*`P`4WF"!@`I#`!Q
+M7`!`D"$``RB`C@8`4`"C*"$`!2A``*8@(RR"`+D40`#;```8(20#``HN(@,A
+M%$``!)(&`&$D8@`!``(6```"'@.2!P!B`D,0(P`"%@`"0Q@J``(6`SAC```D
+MQ/__``"0(3#H`/\`0Y`*,(0`_P``8"$1```'``!((1?``+\!!A`K`(<0(S!$
+M`/\0@`!H``"((0$P6"$`B1`J`(`P(11``!N1:`!C`)`0(21'`&.0\0``),;_
+M_P#)4"H`$1!``%$8(0`#&,``="`A`%`8(8!B```"0A`J%$``"R3G__^08P`!
+ME(0`+B0"`&0`0Q`C<((8`@!L$"L40``#``````!@8"$"($`A44#_ZI#Q``"B
+M$@`GCJ(`/``"%L(P0P`/$&``!@$`B"&.8AMH``(00@!#$"M40``!D7$`8Y(#
+M`#T`<1`K4$``,)+C`-"2!P`\)&(``0!@B"$P0P#_`&<0*P.@4"$OR0`!)`L`
+M`1!``!.."``X``,00`!#$"$``A#``%0@(20"``$`8A`$`0(0)!!```8D9@`!
+M$2``=B0"``&,@@`H%$L`<R0"``$PPP#_`&<0*Q1`__```Q!`H4``````$"%0
+M0``0DN,`T(X"`%B.@P,D`*(0(P!B&"M08``*DN,`T)("`%TL0@`$5$``!I+C
+M`-"3L0``K@4`6*(``%VB$0`^DN,`T"1B__\`41`J4$``!(YC'!PD8O__,%$`
+M_XYC'!PD`@`%4&(`0XYC&^"2P@"`$$#_2@(@$"&6H@`*/`1KRC2$&O,P0@__
+M``(8@`!B&"$``QD``&0`&``1$$``41`A``(0P`!4$"&40@`L```8$``#*0(`
+M11`K$$#_.`(@$"&2`P`\)B(``3!$`/\`@Q@K`Z!((2_(``$D"@`!$&``%(X'
+M`#@`!!!``$00(0`"$,``5!@A)`(``0""$`0`XA`D$$``!B2&``$1```8)`(`
+M`8QB`"@42@`5)`(``9("`#PPQ`#_`((0*Q1`_^\`!!!`H2``````$"$00/\8
+M`B`0(9.Q````$1!``%$0(0`"$,``5!`AE$(`+`!%$"M40/_9D@,`/!``_PT"
+M(!`A$`#_\J$D```"(Q`K$$``"0)@("&.8@6H4$#_NI+"`(``0Q`K5$#_MJY@
+M!:@0`/^UDL(`@`P`5NXD!0`!$`#_L9+"`(`0`/^3H4,``!!`_T8!,%@A`,<0
+M(Q``_T(P20#_+((`&11`_R8N(@,A)(+_YP`"%0`0`/\A``(>`Y*#`S``0Q`C
+M)$+__Q``_PVB`@`]``(80`!B&"$``QC``'08(8QB`"@01/[[`````!``__62
+M@@`#)[W_L``*5@`Q:P#_K[X`0*^W`#ROM0`T`("X(:^T`#"OL0`D`*"H(:^_
+M`$2OM@`XK[,`+*^R`"BOL``@`,"((:^H```!(*`A``KV`PP`<5ROJP`$``,H
+M@`"C*"$`!2!`KZ0`"*^@`!"2XQ@#$J`!"9+D&`>.H@!8)K``E!!@``2,4P`\
+M)`(``5""`8B28@,O`!&P0`+0D"&21``!CZ,``#""`/\08`$=KZ(`#"0"``$0
+M8@$3)(,`(Y("`#PF)0`!`*(0*A!``!D```````480`!E$"$``A#``%,0(21&
+M`"@`<"`A`M$0(0`"$,``4Q`AC$,`*(S"```"T#@A)*4``11#``HDQ@`8D.,`
+M`9""``$`0Q`K5$```:"#``&2`@`\`*(0*A1`_^\DA``"6B``%9("`#Z"`@`F
+M@@0`)P`1&$``<"@A)$+__@!$&"J`I@```(,0"P`"%@```AX#),(``@!#$"H0
+M0`#@D*0``"2"``2@H@``)`0``:(1`%ROI``0D@(`/E!```,`$1!`$%$`#@`1
+M$$``4!`A@$,````#$(``0Q`A``(00`!`&"$D1``/*$(```""&`L``QD#H@,`
+M*:(#`":B`P`HH@``/@`1D$`"4!`AD$(``2Q"`#T40``0CZ(`$!H@``X"41@A
+MD@0`/0`#&,``!!!``$00(0`"$,``<Q@A`%,0(91C`"R40@`L`$,0*Q!``*T"
+M`"@ACZ(`$!!``$@`$3A`D@(`/"1"__\"(A`J$$``'0(@*"$`$1A``'$0(0`"
+M$,``4S@A`'`P(0)1$"$``A#``%,0(8Q#`"B,X@!`%$,`$22E``&`X@`U@,,`
+M`(#$``*0Z``U`&(8(0"#("HDYP`8$(```Y#"````2!`AH,(``I("`#PD0O__
+M`*(0*A1`_^HDQ@`")B7__P2@`",`!1A``&40(0`"$,``4S@A`'`P(0`1$$``
+M41`A``(0P`!3$"&,0P`HC.(`*%1#`!@`$3A`@.0`-8##``"`P@`"D.@`-0!D
+M&"$`1"`J`$,0*A!```J0PP`"$(``;0!H$".@P```@,(``(#C`#0`0Q`J$$``
+M`I#D`#2@Q```)*7__R3&__X$H?_C).?_Z``1.$``\!`AD$(``8^C``P`0Q`K
+M4$``&8X"`%0F)?__!*``%0`%&$``91`A``(0P`!3$"$D1@`H`'`@(0#Q$"$`
+M`A#``%,0(8Q#`"B,P@``)*7__Q1#``@DQO_HD(,``Y""``$`8A`K5$```:"#
+M``$$H?_R)(3__HX"`%2/I``(CF,#*`""$",`0Q`K5$``&(X"`'B2`@`\$$``
+M$```*"$F9@`T`@`@(8"#``"`P@``)*4``23&`!@`0Q`J$$```Y"#```D8O__
+MH((``)("`#P`HA`J%$#_]"2$``*/I0`(K@4`5(YC`RB.`@!XCZ0`"``#&$(`
+M@A`C`$,0*Q1``!:/OP!$D@(`/!!``!```"@A`@`P(9##``$DI0`!``,0P`!#
+M$",`0!@A)$0`!RA"````@A@+``,8PZ##``&2`@`\`*(0*A1`__,DQ@`"CZ4`
+M"*X%`'B/OP!$C[X`0(^W`#R/M@`XC[4`-(^T`#"/LP`LC[(`*(^Q`"2/L``@
+M`^``"">]`%`0`/^4H,(``#(F`/\F!P`]#`!2E0)@("&/I0`($`#_3JX%`%@D
+M8P`"`,,0*A!`_Q\D@@`"$`#_'J"C```P8@#_+$(`911`_NNB0P`!)`(`9!``
+M_NBB0@`!*H,`"B0"``D`0Z`*/`*``B1"1!``%!B`CZ4`#`!B&"&,8P````40
+MP@""$",``QC"`$,0(:)"``&/J``$`N`@(0*@*"$"@#`A#``RXP/`."&2`@`H
+MD@,`)I(%`#ZB`@`IH@,`**(>`":/H@`(,*0`_Q"```.N`@!0$)$`-"J"``)>
+M@/\,`!&00)(#`%TD`@#_$$,``B1B``&B`@!=`M$0(0`"$,``4Q`A)$<`,(#B
+M``0#PA`J5$#^_P`1D$".`@`P4B(`!8X"`"RN$0`PK@``+*X``#2.`@`LC@,`
+M-"1"``$`?B`A*$,`!*X$`#048/[PK@(`+*X``"RN```T`M`H(22"``*`I@``
+M*$,``"2$``4`@Q`+``(0@R3#``(`0Q`J$$``!Y"C``"`X@`$`$80*A!```0D
+M!``!)&+__Z"B```D!``!$`#^VJ^D`!!40``#H@4`/1``_\JB```^DD(``2Q"
+M`"Y40``$H@``/B0"`!2B0@`!H@``/HYB`R2/HP`(``(00@!B$",0`/^]K@(`
+M6"1"``$"(A`J$$#^=P`1L$"28@,P`!%`0`$1&"$"(B@A``400`!%$"$``QC`
+M``(0P`!S&"$`4Q`AD&,`,)!"`#!08OYH`*"((8YG```DI0`!`*<0*A!`_F0`
+MH#`A``400`!%$"$``A#``%,0(21$`#`!$1`A``(0P`!3$"&00P`PD((``!!B
+M``<DA``8),8``0#'$"H40/_W`1$0(1``_E(`$;!`$`#^3P#`B"$GO?_@K[``
+M$*^_`!ROL@`8K[$`%(R"`$R,A`!0,+#__XQ2`#P0@``3`@`0(221`)2CL```
+MDZ<```(@("$#H#`A``<00`!'$"$``A#``%(0(8Q#`"@D`@`"$&(`#`#@*"$,
+M`%)_`````!1`__.3IP```@`0(8^_`!R/L@`8C[$`%(^P`!`#X``()[T`(!``
+M__D`X!`A%*```P`````#X``(K(`%J`2B``R,@QP<&*``!B0"``6,@QP<4&(`
+M!(R"!:@#X``(`````(R"!:@`11`A`^``"*R"!:@D`@`%%&+_\P`````0`/_V
+M`````"2E__\GO?_@+*(`(J^U`!2OM``0K[(`"*^Q``2OL```K[\`&*^S``P`
+M@(@A`,"0(0#@@"$!`*@A$$``"P``H"$\`X`"``40@"1C$+P`0Q`AC$(```!`
+M``@`````#``L;@#@*"$`0*`A5J```:ZT``"/OP`8C[4`%(^T`!"/LP`,C[(`
+M"(^Q``2/L````^``"">]`"`0`/_TKB<;V*XG'#00`/_QK(`;V!``_^^N)QO(
+M$`#_[:XG&V@0`/_KIB<;W!``_^FN)QO@$`#_YZR`!:@0`/_EKB<;U!``_^.N
+M)QNT$`#_X:(G&[L0`/_?HB<;Y1``_]VN)QO,)(0;H@P`<)T`X"@A$`#_V```
+M```\$X`#CF2*M!"```8\`H`#C$**N!!&``H`````#`!Z:@`````,`'I7`D`@
+M(:YBBK0\`H`#K%**N#P3@`..9(JT5(```P(`*"$0`/_$)!0``@P`<)T"0#`A
+MCF**M!``_[^N(AO\$`#_O:XG&VP0`/^[KB<;O!``_[FN)QN<$`#_MZ8G&\00
+M`/^UIB<;P!``_[.F)QO"$`#_L:8G&\8PX@#_$`#_KJR"&S@PX@#_$`#_JZR"
+M&SP0`/^IKB<;-(R"``0`X"@A#``9T8Q$```40``"`$"@(:XP&^P0`/^@KC`;
+MZ">]__"OL```K(4;"`"`@"&OOP`$#``4;20%``&.!1L(#``LN@(`("$"`"`A
+M#``4;0``*"&/OP`$C[````/@``@GO0`0)[W_\*^_```,`&M,`````(^_```#
+MX``()[T`$">]_]``H!`AK[```#P%@```@(`AK[\`)*^^`""OMP`<K[8`&*^U
+M`!2OM``0K[,`#*^R``@`X)@A,-+__Z^Q``0!`*`A`2"H(0%`\"$!8+`A,%'_
+M_PP`*6R/MP`T#`!Q>XX$&`@"`"`A```H(0``,"$,`"SJ```X(1;@`!,`%B@K
+M,B,W`"0")0"F$AMPIA,;?*(4&WZB%1M_IA$;<A!B`&```"@A)`(5`%!B``$D
+M!0`!C@080`P`<7NN!1@$#`!QPB8$%^P`%B@K#``*2`(`("$,``B5`@`@(0P`
+M<30`````#`!PM0`````F!1MP`\`P(0P`-X4"`"`ACZ,`,!+``#FL8@``#`!P
+MN@`````,`'$[``````(`("$,`"D\/`6``!;@``0`````C@(;5"1"``&N`AM4
+M#``(?@(`("$,``H8`@`@(1+@`!@`````#`!Q7``````D8P#(C@08""QE`,@`
+M11`A`$`P(20(```D"0#(#`!Q=`!@."&/OP`DC[X`((^W`!R/M@`8C[4`%(^T
+M`!"/LP`,C[(`"(^Q``2/L````^``"">]`#`,`''0)@07[`P`<5P`````)&,`
+MR"QE`,B.!!A``$40(0!`,"$D"```)`D`R`P`<70`8#@A$`#_VP`````,`%)>
+M`B`@(0`"&(``<!@AC&,<`(X$&^BN`AP<K@,<5!"```0``!@A,B(@`%1```$D
+M`P`!$`#_NJ(#')@0`/^C)`4``22E__\GO?_@+*(`#Z^U`!2OM``0K[,`#*^R
+M``BOL0`$K[```*^_`!@`P*`A`."`(0$`J"$``(@A``"0(1!``%@``)@A/`.`
+M`@`%$(`D8Q%$`$,0(8Q"````0``(`````!#@`",D$@#,`.`8(22"&QPDA1M<
+MC$8``(Q'``2,2``(C$D`#*QF``"L9P`$K&@`"*QI``PD0@`0%$7_]B1C`!`D
+M@QOH)@(`0"2$&VB,A0``C(8`!(R'``B,B``,K$4``*Q&``2L1P`(K$@`#"2$
+M`!`4@__V)$(`$(R)``",@P`$C(4`"*Q)``"L0P`$K$4`"!9@``<`````%D``
+M`P````!6```!KA$``%:```&ND@``5J```:ZS``"/OP`8C[4`%(^T`!"/LP`,
+MC[(`"(^Q``2/L````^``"">]`""4@AMR$`#_ZP`"BP(0`/_IE)$;<!``_^>,
+MD1LL$`#_Y8R1&S`0`/_CC)$;2!``_^&,D1M,$`#_WXR1&U`0X/_=)!(`!B2%
+M&Z@D!@`&#`!PG0#@("$0`/_7`````!``_]6,D1M4$`#_TR03``X0X/_1)!(`
+M$`#@*"$,`"Q8)`8`$!``_\P`````$`#_RHR1&^P`@#@A```P(1"@``@``!@A
+M`,<0!B3&``$P0@`!``,80`#%("L4@/_Z`&(8)0/@``@`8!`A)[W_\*^R``BO
+ML0`$K[```*^_``R,H@!,)+``"`"@B"&020!`C$H`/*R@`!R,HP`<``D00`!)
+M$"$``A#`K*,`&`!*0"&1!0`PC@,`#(X'``0D`O_@`&(8)#"E`!\D`N__`.(X
+M)`!E&"6N!P`$K@,`#(T#`"@D`@`#`(`X(1!B`"L`P)`AC@,`"(X$``0\`O_P
+M-$+__P!B&"0\`@$``((@)3P"``$`8A@EK@0`!*X#``B.(@`(/`,`/SP$X?\`
+M0Q`E-(3__S)#``\`1!`D``,>0`!#$"6N(@`(C@(`!#P#_P\T8___`$,0)#P#
+M`#``0Q`E/`,&``!#$"6N`@`$CB(`"(XD`"0\`P"``$,0):XB``BN)```C[\`
+M#(^R``B/L0`$C[````/@``@GO0`0CB(`"#P#@``\!?X/`$,0):XB``B0A!T`
+MC.8<5(X#``P`!!!``$00(0`"$,``1A`AD$(`,#2E__\`91@D,$(`'P`"%0``
+M8A@EK@,`#(T#`"@\`H`")$)$```#&(``8A@ACB4`"(QB```!0"`A,*4/_P$@
+M,"$`0/@)```X(8X#``@D!(``,$)__P!D&"0`8A@E$`#_L:X#``@GO?_@K[``
+M$`"@@"$#H"@AK[$`%*^_`!@,`"WM`("((5(```$```'-CZ,`!(^B```T"8``
+M``,=@``"$H(`8A@E`'`X(0#P$"$D0O__`%``&XXC``"6)1N"-`B```!I&"$R
+M"O__```0$@``````````<%`X`JQG`"B.(@````<8P"1F__P`21`AK$8`+(XB
+M```D9O^P`.4@(0!)$"&L1@`PCB(``"3C``$`92`*`$@0(:Q$`#2.(@``/`,`
+M@`(#,"4`2!`AK$8`((XB&X@00``AC[\`&(XB``".)1N0`$@0(:Q*`0".)```
+MCB,;B`"(("&,@@$```,<`#!"__\`0Q`EK((!`(XB&XR.(P```.(0(0!H&"$P
+M0O__K&(`_!"@``>.(@``/`0``@!($"&,0P#\`&08):Q#`/R.(@``/`0``0!)
+M$"&,0P#\`&08):Q#`/R/OP`8C[$`%(^P`!`#X``()[T`(">]_]"OL@`(,)(`
+M_Z^W`!ROM@`8K[4`%*^T`!"OLP`,K[```*^_`""OL0`$`*"@(0#`J"$`X+`A
+M`0"X(0$@@"$!0)@A$D``#"0"``&/OP`@C[<`'(^V`!B/M0`4C[0`$(^S``R/
+ML@`(C[$`!(^P```#X``()[T`,`P`>E<D!``L`$"((1(@__$D`@`"`B`@(0``
+M*"$,`'"J)`8`+"0"``*N\0``/`:``:("```D`@`*)B@`&"3&:<P``"`A```H
+M(0(@."&B8@``KC0`!*XU``BN-@`,#`!@6:(@```,`'I7)`0%$`!`@"$00``J
+MKB(`%`!`("$``"@A#`!PJB0&!1`F!P`(K@<`#*X0``2,Y@`$K@``"*X````"
+M`"`A```H(22E``$D@@`0+*,`0*R``!"LP@``)(0`%!1@__D`0#`A`B`@(0)`
+M*"$,`%\JK.(`!!1```,`````$`#_O```$"$,`&!(`B`@(8XE`!@,`&"'`D`@
+M(8XD`!0,`'IJ`$"`(0P`>FH"("`A`@`0(1``_Z^NX```#`!Z:@(@("$0`/^K
+M)`(``B>]__`LH@`$K[(`"*^Q``2OL```K[\`#`"@B"$`@(`A%$``"`#`D"$D
+M`O__C[\`#(^R``B/L0`$C[````/@``@GO0`0#`!A$9"$``"2!````!$0@`!0
+M$"$,`&$BK%(`'!``__(``!`A,*4`_R>]__`LH@`*K[\``!!```TD!___/`.`
+M`@`%$(`D8T1`)*4``0!#$"$0@``&,*4`_XQ'```,`&(NC(0`$"0'__\``C@*
+MC[\```#@$"$#X``()[T`$#"E`/\GO?_P+*(``J^_```00``()`/__R2E``$0
+M@``%,*4`_PP`8E^,A``0)`/__P`"&`J/OP```&`0(0/@``@GO0`0)[W_\*^_
+M```\`H`"D$)$:`"`2"$`X%`A,*,`_Q!``!<PQ`#_)&7__P#@,"$PI0#_$(``
+M#P$`."$D9?__)`(``3"E`/\0@@`$`4`P(8^_```#X``()[T`$(TD``2-(@`,
+M`$#X"0`````0`/_YC[\``(TD``00`/_ZC2(`"(TG`!0D:___.((``8SC``@L
+M1@`!)`4``1!@_^TDY``(C&(``!1```*LX@`(K(0`!*!K``B@9@`)K&H`#*QH
+M`!"@8``$C.(`!(TD`!BL8```K.,`!`P`8(.L0P``$`#_W8^_```GO?_P/`*`
+M`J^_``"00T1H``40@`"@0"$08``+`$00(8Q"`!P40``$`````(^_```#X``(
+M)[T`$`!`^`F,A``$$`#_^X^_``",A@`4)`4``8S#``@08/_U),<`"(QB```4
+M0``"K,(`"*SG``0D`@`!H&(`!*QH``B,P@`$C(0`&*Q@``"LPP`$#`!@@ZQ#
+M```0`/_GC[\``">]_^"OL0`$K[\`%*^T`!"OLP`,K[(`"*^P```\`H`"D$)$
+M:!!```D`@(@AC[\`%(^T`!"/LP`,C[(`"(^Q``2/L````^``"">]`"".,@`4
+MD(0```P`83,F4P`(CE````P`84R2)```$@#_\8^_`!0,`&$SDB0``(Y"``".
+M%```C$(``!1```*N0@``KE(`!`P`84R2)```D@(`!"0#``%00P`BC@(`"%1`
+M``<"`"`AD@(`"5!``!N2!0`(4$,`$I(%``@"`"`A```H(0P`<*HD!@`,#`!A
+M,Y(D``".8@`$K@```*YP``2L4```DB0```P`84P"@(`A%H#_W8^_`!00`/_,
+MC[0`$(XB``R.)``$C@8`#`!`^`F.!P`0$`#_Z@(`("$0`/_YCB(`"``"$(``
+M41`AC$(`'%!`_^,"`"`A`$#X"8XD``00`/_?`@`@(2>]__"OOP``#`!A,Y"$
+M``"/OP`````0(0/@``@GO0`0)[W_\*^_```,`&%,D(0``(^_`````!`A`^``
+M"">]`!`\`H`"H$!$:`/@``@``!`A)`,``3P"@`*@0T1H`^``"```$"$GO?_P
+MK[```*^_``0,`'"U`("`(0P`6L<"`"`A#`!F*8X$`!`,`%IS`@`@(0P`6L\"
+M`"`A#`!PN@````"/OP`$C[``````$"$#X``()[T`$">]__"OOP``#`!H%HR$
+M`!"/OP```^``"">]`!`GO?_PK[$`!*^P```PT0#_,+``_P(`*"$"(#`AK[(`
+M"*^_``P,`&'W`("0(0)`("$"`"@A%$``"0(@,"$``!@AC[\`#(^R``B/L0`$
+MC[````!@$"$#X``()[T`$`P`8A8`````%$#_]@!`&"$"0"`A`@`H(0P`8?<"
+M(#`A%$#_\"0#``<0`/_N```8(2>]__"OOP``/`*``I!&10,PI0#_`*`X(0``
+M0"$``"@A#`!AYP``2"&/OP```^``"">]`!`PI0#_)[W_\`"@,"&OOP``#`!A
+M8P``*"&/OP```^``"">]`!`GO?_PK[```#"P`/^OL0`$`@`H(:^_``@,`%LK
+M`("((0(`,"$"("`A#`!:^P``*"$"("`A#`!;'@(`*"&/OP`(C[$`!(^P```#
+MX``()[T`$">]__"OOP``/`*``I!#1&D`P#@A)`(`0#AC``(D!@(``$,P"S#G
+M`/\PI0#_)`@``@P`8><``$@AC[\```/@``@GO0`0)[W_\##&`/^OOP``#`!A
+M8S"E`/^/OP```^``"">]`!`GO?_PK[$`!*^P```PT0#_,+#__Z^R``@"`"@A
+M`("0(:^_``P,`%M9`B`P(0)`("$"`"@A#`!:^P(@,"$"0"`A`@`H(0P`6T@"
+M(#`AC[\`#(^R``B/L0`$C[````/@``@GO0`0)[W_\*^R``BOOP`,K[$`!*^P
+M```0H``.`("0(9##``,D`@"!$&(`/2AB`((00``E)`(`@B0"`(`08@`+/!&`
+M`@)`("$``"@A#`!C$@``,"&/OP`,C[(`"(^Q``2/L````^``"">]`!`F,$?"
+M`@`P(0P`8J4D!0`&EB-'P@(`,"$"0"`A,&(`_P`"$@```QH"`$,0)0``*"$D
+M!P`"IB)'P@P`8E\``````D`@(0``*"$``#`A#`!B+@``."$0`/_EC[\`#%1B
+M_]\"0"`AD,,`!SP0@`(F$4?",&,`#S1E`!`"(#`A/`*``@P`8J6@0T?&E@-'
+MP@(@,"$"0"`A,&(`_P`"$@```QH"`$,0)0``*"$D!P`"$`#_XJ8"1\(\`H`"
+M)$9'P0``*"$D!P`!$`#_W*!`1\$GO?_@K[(`&*^P`!``H)`A`,"`(20%``$#
+MH#`AK[$`%*^_`!P,`&*E`("((9>B```L0@`"$$``"@(@("$20``,C[\`')(#
+M``-08``DE@,``"0"``)08@`+E@(```(@("$``"@A#`!C$@``,"&/OP`<C[(`
+M&(^Q`!2/L``0`^``"">]`"`40/_V`B`@(9("``<\$(`#,$(`#S1%`!`#H#`A
+M#`!BI:("BKR2!8J\`B`@(0``,"$TI0`0#`!BUP`````"("`A```H(0``,"$,
+M`&)?```X(1``_^:/OP`<)`(``11B_]\"("`A`Z`P(0P`8J4D!0`&EZ(```(@
+M("$D!0`&,$+__0!`,"$0`/_KIZ(``">]_^"OL0`4K[``$*^_`!ROL@`8`,"`
+M(1"@`$@`@(@AD,,``U!@`"*4PP``)`(``E!B``N4P@```B`@(0``*"$,`&,2
+M```P(8^_`!R/L@`8C[$`%(^P`!`#X``()[T`(!1`__<``"@AD-``!P.@,"$R
+M$``/-A``$`P`8J4"`"@A`B`@(0(`*"$D!@`!#`!BUP`````"("`A```H(0``
+M,"$,`&)?```X(1``_^B/OP`<)!(``1!R`!<D`@`"5&+_WP(@("&0P@`'%$#_
+MW#P"@`*00D1I%&+_V@``*"$D!0`!#`!BI0.@,"&7H@``+$(``Q!`_]$\`X`"
+ME@(`!JQR1&PP0O\`/`.``J1B1'`0`/_B`B`@(0.@,"$,`&*E)`4`!I>B```"
+M("`A)`4`!C1"``(`0#`A$`#_U:>B```\`H`"C$)$;%!`_\&/OP`</`*``I1&
+M1'`D!0`'#`!BUS#&__\0`/^ZC[\`'">]__"OL0`$K[\`"*^P```0H``-`("(
+M(9##``$``"@A```P(0``."$\`H`##`!B7Z!#BKV/OP`(C[$`!(^P```#X``(
+M)[T`$#P"@`.01HJ])`4``PP`8M<D$``!`B`@(20%``$,`&+7)`8``0(`*"$"
+M("`A#`!;820&``$F`@`!,%``_RX"``,40/_Y`@`H(200``$"`"@A`B`@(0P`
+M6V$``#`A)@(``3!0`/\N`@`#%$#_^0(`*"$0`/_?C[\`"">]__"OL```K[\`
+M!`#`."$`@(`A$*``$0``0"&4PP``)`(#`#!E_P`0H@!5**(#`1!``#0D`@8`
+M)`(!`!"B`"HD`@(`$*(`"3P"@`("`"`A```H(0P`8Q(``#`AC[\`!(^P```#
+MX``()[T`$)!"1&DD`P!`.$(``@!B*`LE!``!``@8P#P"@`(`:!@C)$9%'#"(
+M`/\`9A@A``42`BT$``2@8@`7%(#_]:!E`!:4XP`$)`<`+@(`("$L8@`N`&(X
+M"P``*"$,`&)?``````(`("$``"@A```P(0P`8BX``#@A$`#_WX^_``24PP`$
+M)`<`$CP&@`(L8@`2`&(X"Q``__`DQD3\$*(`%R0"!P`4HO_0`@`@(3P"@`*0
+M0D1I)`4`0"0#`@`X0@`"`&(H"R4$``$`"!C`/`*``@!H&",D1D6$,(@`_P!F
+M&"$`!1("+00`!*!B`!<4@/_UH&4`%A``_]24XP`$E,,`!"0'``H\!H`"+&(`
+M"@!B.`L0`/_1),9%$#!C`/\L8@`$%$``"#P"@`(\!H`"D,-$?)3G``0DQD1\
+M`.,0*Q``_\8`8C@*)$(P```#&(``8A@AC&8``)3G``0``"@AD,,```#C$"L0
+M`/^]`&(X"B>]__```"@AK[\```P`8Q(``#`AC[\```/@``@GO0`0)[W_X`"@
+M$"&OL``0K[\`%`.@,"$D!0`$%$``!0"`@"&/OP`4C[``$`/@``@GO0`@#`!B
+MI0````"3HP`!/`*``B1&1\```"@A)`<``0(`("$,`&)?H$-'P`(`("$``"@A
+M```P(0P`8BX``#@A$`#_[8^_`!0GO?_@K[$`%*^P`!"OOP`8`,"((1"@`!L`
+M@(`AD,,``2QB``(00``=```H(11@`!\#H#`A)`4``0P`8J4#H#`AEZ(``"Q"
+M``(00``3`@`@(20%``0,`&+7```P(0(`("$D!0`!)`8``0P`8M<``````@`@
+M(0``*"$``#`A#`!B7P``."&/OP`8C[$`%(^P`!`#X``()[T`(```*"$,`&,2
+M```P(1``__B/OP`8#`!BI20%``22)@`!EZ(``%!&``@D!0`!`@`@(0P`8M<D
+M!0`$`@`@(20%``$0`/_C```P(0``,"$0`/_@`@`@(2>]_^"OL@`8K[$`%`"@
+MD"$`P(@A)`4``0.@,"&OL``0K[\`'`P`8J4`@(`AEZ(```(`("$``"@A%$``
+M%P``,"$60``'`````(^_`!R/L@`8C[$`%(^P`!`#X``()[T`()8G``22)@`'
+M/`*``B1"1'0`PC`A#`!B7P`'."L"`"`A```H(0``,"$,`&(N```X(1``_^Z/
+MOP`<#`!C$@`````0`/_JC[\`'">]__"OOP``$*``"0#`2"&0PP`#)`(``0``
+M*"$``#`A$&(`!@``."$,`&,2`````(^_```#X``()[T`$)$C``<\`H`")$)$
+M=`!B&"&1*``!D&(`````*"$02``#```P(9$B``&@8@``#`!B7P`````0`/_P
+MC[\``">]_^"OLP`,K[```*^_`!2OM``0K[(`"*^Q``0`P(`A$*``"`"`F"&0
+MT0`#)`(``@``*"$2(@`+```P(0P`8Q(`````C[\`%(^T`!"/LP`,C[(`"(^Q
+M``2/L````^``"">]`"`\`H`"D$-%'9("``<\$H`")E1'Q`!#$"LD!0`%%$``
+M!`*`,"$``"@A$`#_ZP``,"$,`&*E`````)8&``261$?$```H(2S"``(P@P#_
+M`,*("P`$(@(``QH``&08)0*`,"$"(#@A`F`@(0P`8E^F0T?$`F`@(0``*"$`
+M`#`A#`!B+@``."$0`/_7C[\`%">]_^"OLP`,K[(`"*^Q``2OL```K[\`$#P0
+M@`,`P)@AC@:*P`"`D"$`H(@A/`2``CP%@`(DA!&`#`!P="2E$9".`HK`)$(`
+M`1(@``>N`HK`EF,``"0"``$08@`A)`(``E!B``B69@`&C[\`$(^S``R/L@`(
+MC[$`!(^P```#X``()[T`(##%``\DH___,&+__RQ"``(00``$,&+__S#"`(`4
+M0``,,&+__RQ"``(00/_N,,(`@%1`_^V/OP`0`D`@(0``,"$,`%MA`````!``
+M_^>/OP`0`D`@(1``__HD!@`!)!```0(`*"$"0"`A#`!;820&``$F`@`!,%``
+M_RX"``,40/_Y`@`H(200``$"`"@A`D`@(0P`6V$``#`A)@(``3!0`/\N`@`#
+M5$#_^0(`*"$0`/_.C[\`$">]__"OL```K[\`!!"@``<`@(`AD,(``A!```@`
+M```````H(0P`8Q(``#`AC[\`!(^P```#X``()[T`$`P`7>X``````@`@(0``
+M*"$``#`A#`!B7P``."$0`/_UC[\`!#P"@`*00D7L$$```CP"@`*@2$1I`^``
+M"``````GO?_PK[```*^_``0\`H`"D$)%[```*"$40``%`("`(8^_``2/L```
+M`^``"">]`!`,`%LTC(0`$(X$`!`,`%LT)`4``0(`("$,`%I-)`4``A``__2/
+MOP`$)[W_\*^_```\`H`"D$)%[!1```0``"@AC[\```/@``@GO0`0#`!:30``
+M```0`/_[C[\```/@``@``````^``"``````GO?_@K[$`%*^P`!"OOP`8`*"(
+M(12@`($`@(`A/`*``B1&1[B0P@`#,$,`8"0"`"`08@`)*&(`(1!``'(D`@!`
+M4&``"I#&``*.!``0```H(0P`8Q(``#`AC[\`&(^Q`!2/L``0`^``"">]`"`L
+MP@`-$$#_]3P#@`(`!A"`)&,1G`!#$"&,0@```$``"`````".!``0/`:``@(@
+M*"$,`%MZ),9'N!``_^V/OP`8C@0`$#P&@`("("@A#`!;QR3&1[@0`/_FC[\`
+M&(X$`!`\!H`"`B`H(0P`7`LDQD>X$`#_WX^_`!B.!``0/`:``@(@*"$,`%QE
+M),9'N!``_]B/OP`8C@0`$#P&@`("("@A#`!<E23&1[@0`/_1C[\`&(X$`!`\
+M!H`"`B`H(0P`70HDQD>X$`#_RH^_`!B.!``0/`:``@(@*"$,`%T2),9'N!``
+M_\./OP`8C@0`$"0%``$,`&*E`Z`P(8X$`!`\!H`"`B`H(0P`72\DQD>XC@0`
+M$">F``(,`&*E)`4``9>B```00/^REZ(``E1`_[&/OP`8`@`@(0P`6DTD!0`#
+M$`#_K(^_`!B.!``0/`:``@(@*"$,`%UJ),9'N!``_Z6/OP`8C@0`$#P&@`("
+M("@A#`!=E"3&1[@0`/^>C[\`&(X$`!`\!H`"`B`H(0P`7;(DQD>X$`#_EX^_
+M`!@48O^1C@0`$`P`7CP"("@A$`#_D8^_`!B,A``0/`:``B3&1[@,`&(/```H
+M(1``_WL\`H`")[W_\*^_```\`H`"D$)%[#"C`/\PZ@#_$$``"`#`*"$!`#@A
+M`4`P(0$@0"$08``*+&(``Q1```0`8"@AC[\```/@``@GO0`0#`!:%0`````0
+M`/_[C[\```P`7H(`````$`#_]X^_```GO?_@K[$`!#"Q`/^OLP`,K[(`"`"`
+MF"$`$9#``B`@(:^_`!`,`&$SK[````)1$"$``A"``%$0(SP#@`,D8Z&```(0
+M@`!#$"$D0P`8E&0`!!"```H"41`A-`+__Q""``8`!"("D&(`!3P#@`(D8T3\
+MH&0`":!B``@"41`A``(0@`!1$",\`X`#)&.A@``"$(``0Q`A)$,`&)1E``8P
+MI/__4(``\B0#``,T`O__$((`[B2B``*D8@`&D&0`!SP#@`(D8T3\``(2`J!B
+M``N@9``*/`*``@`1&$`D0D?@`&*`(9(%``&2!@``/`2``@P`<'0DA!'0D@(`
+M`11``,X\!H`"`E$0(0`"$(``41`C/`.``R1CH8```A"``$,0(91$`"`0@``)
+M)$,`(#0"__\0@@`&``0B`I!B``$\`X`")&-$_*!D``V@8@`,`E$0(0`"$(``
+M41`C/`.``R1DH8```C"``,00(21#`""48@`$)$+__RQ"`$`00``B`E$0(3P%
+M@`(D@@`JD&,`!22D1(``PC`A)(0``@#$$"4D8P`",$(``Z"C1(`00`"6),,`
+M0`!@$"&(PP``F,,``XC%``28Q0`'B,<`")C'``N(R``,F,@`#ZB#``"X@P`#
+MJ(4`!+B%``>HAP`(N(<`"ZB(``RXB``/),8`$!3"_^XDA``0`E$0(0`"$(``
+M41`C/`.``R1HH8```CB``.@P(23#`""48@`&)$+__RQ"`"!00``IE,(`*)!C
+M``<\!8`")0(`:B1C``(`XA`A)*1$Q*"C1,2(20``F$D``XA*``282@`'B$,`
+M")A#``N(10`,F$4`#ZB)``*XB0`%J(H`!KB*``FH@P`*N(,`#:B%``ZXA0`1
+MB$D`$)A)`!.(2@`4F$H`%XA#`!B80P`;B$4`')A%`!^HB0`2N(D`%:B*`!:X
+MB@`9J(,`&KB#`!VHA0`>N(4`(93"`"@D0O__+$(`$!!``!@DPP`HD&(``3P%
+M@`(E`P"*)$(``@#C&"$DI$3HH*)$Z(AF``"89@`#B&<`!)AG``>(:``(F&@`
+M"XAI``R8:0`/J(8``KB&``6HAP`&N(<`":B(``JXB``-J(D`#KB)`!$F9@`0
+M`B`@(0)@*"$,`&&()`<``Q!```DD`___C[\`$(^S``R/L@`(C[$`!(^P````
+M8!`A`^``"">]`"`D`P`!/`*``J!#1>R.9``0```H(0P`6QXD$``!CF0`$`P`
+M6QXD!0`!CF0`$#(%__\,`%M()`8``28"``$``A8```*&`RH"``,40/_XCF0`
+M$"00``$R!?__#`!;2```,"$F`@`!``(6```"A@,J`@`#5$#_^(YD`!`,`&%,
+M`B`@(1``_]<``!@AC,D``(S*``2,P@`(C,4`#*R)``"LB@`$K((`"*R%``PD
+MQ@`0%,/_]B2$`!`0`/]T`E$0(23&11R0P@`'D@0``#!"`-\T0P`@`$08"CP$
+M@`(`8"@A)(01Z`P`<'2@PP`'$`#_*`)1$"$D`P`#/`*``A``_Q>@0T4&)[W_
+M\*^_``2OL````("`(0P`83.0A```/`*``J!`1>P,`&*2C@0`$`P`84R2!```
+MC[\`!(^P`````!`A`^``"">]`!`GO?_@`(`0(20$`#2OM0`4K[0`$*^S``RO
+ML@`(K[$`!*^P``"OOP`8`*"8(0#`H"$`X*@A`0"0(0P`>E<P40#_`$"`(1(`
+M``\D`@`"`@`@(0``*"$,`'"J)`8`-#P"@`(D0D?0`!$8@`!B&"&N4```KA,`
+M(*X4`"RN%0`PK'``````$"&/OP`8C[4`%(^T`!"/LP`,C[(`"(^Q``2/L```
+M`^``"">]`""0@@`H`*(H)0/@``B@A0`H)[W_\`"`$"&OL```K[\`!`"@("$0
+MH``(,%``_PP`>FH`````/`*``@`0&(`D0D?0`&(8(:Q@``"/OP`$C[``````
+M$"$#X``()[T`$#"$`/\`!!C``&08(0`#&(`\`H`"`&08(R1"1]``!""`)[W_
+M\`""("$\`H`#K[$`!*^_``BOL```)$*A@``#&(",D````&(8(9!D`!L`X(@A
+M/`B``CP'@`*N!0`@K@8`)"8)`!PDYX-@)0B#P```*"$"`#`A#`!Q"`(`4"&.
+M`@`<%$``!P!`("&N,```C[\`"(^Q``2/L````^``"">]`!`,`'$F`````!``
+M__BN,```)[W_\*^P``"OOP`$$*``!`"@@"&,H@`<%$``!0!`("&/OP`$C[``
+M``/@``@GO0`0#`!Q+0`````,`'$?C@0`'!``__>N```<)[W_\*^P````H(`A
+MK[\`"*^Q``0,`'%"`("((8X"`"``0/@)C@0`)`P`<5`"("`A#`!Q20(@("&2
+M!``HC[\`"*(``"B/L0`$C[```"0#``$D`@`"`&00"@/@``@GO0`0)[W_\*^_
+M``",P@`L`$#X"8S$`#"/OP```^``"">]`!`PA`#_%(``!``````\`H`#`^``
+M")!"H9L#X``(```0(3"$`/\4@``$`````#P"@`,#X``(C$*AE`/@``@``!`A
+M,(0`_Q2```4`````/`*``XQ"H90#X``()$(!``/@``@``!`A)[W_\#"$`/\4
+M@``%K[\``#P"@`*,0D?4$$``!`````"/OP```^``"">]`!`,`'"U``````P`
+M83,``"`A$`#_^8^_```GO?_P,(0`_Q2```6OOP``/`*``HQ"1]000``$````
+M`(^_```#X``()[T`$`P`<+H`````#`!A3```("$0`/_YC[\``">]__"OL```
+M,)``_Z^Q``2OOP`(#`!PM3P1@`,6```&DB**Q!!```L\`H`#DB**Q"1"``&B
+M(HK$#`!PN@````"/OP`(C[$`!(^P```#X``()[T`$`P`<4*,1*&8$`#_])(B
+MBL0GO?_PK[```*^_``0,`'"U,)``_Q8```8\!(`#D(**Q"1"__\P0P#_$&``
+M!Z""BL0,`'"Z`````(^_``2/L````^``"">]`!`\`H`##`!Q28Q$H9@0`/_V
+M`````">]__`PI0#_K[\```P`8QHPQ@#_C[\```/@``@GO0`0)[W_\*^Q``2O
+MOP`(K[```(R"`!@`@(@AC%````P`81&2!`"0C@(`'%1```^.`@`@KA$`'(XB
+M`!B.`P`HKA$`(*Q```"2!`"0)&,``0P`82*N`P`HC[\`"(^Q``2/L````^``
+M"">]`!",0@`8$`#_\:Q1```GO?_@K[0`$#"4`/\N@@`"K[8`&*^U`!2OL0`$
+MK[\`'*^S``ROL@`(K[````"@L"$`P*@A,/$`_Q1```PD`P`/C[\`'(^V`!B/
+MM0`4C[0`$(^S``R/L@`(C[$`!(^P````8!`A`^``"">]`"`,`'I7)`0`H`!`
+M@"$00/_Q)`,`"@``*"$D!@"@#`!PJ@!`("$"@"`A#`!A`*(4`)`"@"`A#`!@
+M^*X"``BB`@"1)`0'`"0"`/^B$0"3#`!Z5Z8"`(0`0(@A$$#_WB0#`*D`0"`A
+M```H(20&!P`,`'"JK@(`&`P`>E<D!`,`K@(`=!!`_]0D`P`!`$"0(:X``!RN
+M```@K@``*```F"$\`H`")$*%K*Y"``2N,@`8`B`@(0P`86NN4```)F(``3!3
+M`/\N8@!`)C$`'!1`__0F4@`,#`!Z5R0$`!P`0"`A)`8`'```*"$,`'"JK@(`
+M%`*`("$,`&-=`@`H(11`_[8D`P`OKK``````&"$0`/^RKA8`F">]__"OOP``
+MC(,`%#$I`/^@90``C(,`%*!G``&,@P`4H&@``HR%`!2D9@`0#`!G(*RI`!2/
+MOP```^``"">]`!`GO?_PK[\`#*^R``BOL0`$K[````"`D"&0A`"0,+``_PP`
+M81$PT0#_`@`H(0(@,"$,`&>%`D`@(9)$`)`,`&$B`$"`(0(`$"&/OP`,C[(`
+M"(^Q``2/L````^``"">]`!`GO?_PK[\```P`9OXPI0#_C[\```/@``@GO0`0
+M)[W_\*^_``ROL@`(K[$`!*^P````@)`AD(0`D#"P`/\,`&$1,-$`_P(`*"$"
+M(#`A#`!GDP)`("&21`"0#`!A(@!`@"$"`!`AC[\`#(^R``B/L0`$C[````/@
+M``@GO0`0)[W_X*^S``ROL@`(K[$`!*^P``"OOP`0`("((9"$`)``P)`A`."8
+M(0P`81$PL`#_CB(`*!!``!\"("`ACB,`'!!@``<`8"@AC&(`&(Q"```40``"
+MKB(`'*X@`"".(@`HK'(`!"1"__^N(@`H)`(``:!P``"L<P`(H&(``PP`95F@
+M8``!DB0`D`P`82(`0(`A)`(`H@`0$`J/OP`0C[,`#(^R``B/L0`$C[````/@
+M``@GO0`@#`!A(I(D`)`0`/_V)`(``R>]_^"OLP`,K[(`"*^Q``2OL```K[\`
+M$`"`B"&0A`"0`,"`(0#@F"$,`&$1,+(`_XXB`"@00``A`````(XF`!P0P``7
+M)`(`H8S"`!B,0@``%$```JXB`!RN(``@CB(`*"0#``&LT``$)$+__ZXB`"@`
+MP"@A`B`@(:#2``"LTP`(H,,``PP`95*@PP`!DB0`D`P`82(`0(`A)`(`H0`0
+M$`J/OP`0C[,`#(^R``B/L0`$C[````/@``@GO0`@#`!A(I(D`)`0`/_V)`(`
+M`R>]__"OL```K[\`!`P`:"0`@(`A#`!Z:HX$`!`,`'IJC@0`&`P`>FJ.!`!T
+M#`!Z:HX$`!0,`'IJ`@`@(8^_``2/L````^``"">]`!`GO?_PK[(`"*^Q``2O
+ML```K[\`#`"`B"&0A`"0,+``_PP`81$`P)`A)@/__RQB``800``;,@(`$``#
+M$(`\`X`")&,1^`!#$"&,0@```$``"`````"6(@"$ID(```P`82*2)`"0```0
+M(8^_``R/L@`(C[$`!(^P```#X``()[T`$!``__62(@"5$`#_\Y(B`)00`/_Q
+MEB(`B!``_^^6(@"&$$``!3(%``\,`&A<`B`@(1``_^JF0@``#`!A(I(D`)`0
+M`/_I)`(``B>]__"OL@`(K[$`!*^P``"OOP`,`("0(9"$`)`PL0#_#`!A$3#0
+M__\F(___+&(`!Q!``",R(@`0``,0@#P#@`(D8Q(0`$,0(8Q"````0``(````
+M`*90`(0,`&$BDD0`D```$"&/OP`,C[(`"(^Q``2/L````^``"">]`!`R!0#_
+MHE``E0P`9O@"0"`A$`#_\@`````0`/_PHE``E!``_^ZF4`"($`#_[*90`(8"
+M`"@A#`!H9@)`("$0`/_G`````!!```8R)0`/,@8`_PP`:(4"0"`A$`#_X```
+M```,`&$BDD0`D!``_]\D`@`")[W_\#"E`/^OOP``#`!H0##&`/^/OP```^``
+M"">]`!`GO?_@K[,`#*^R``BOL0`$K[\`%*^T`!"OL```C)0`"#"S`/\PQ@#_
+M`!,00(Z#`!@`1A`A``(1@`!BB"$2(``0`("0(3(B``\D0@!/)`/_\`!#*"0"
+M(Q@D`&40(0!#$"L40``'`&`@(;QQ```D8P`0`(40(0!#$"L00/_[`````(XE
+M`#PD`@`!$*(`"@``("&/OP`4C[0`$(^S``R/L@`(C[$`!(^P````@!`A`^``
+M"">]`"``!A$``%,0(0!%@`0"0"`A#`!D-P(`*"$40``(`!,0@`!4$"&N(```
+MC$,`@```("&L0P"`$`#_Z:X@`#P"0"`A#`!D*P(`*"$40/_D)`0`I1``__,`
+M$Q"`)[W_\#"$`/^OL```K[\`!`P`80@`H(`AC$,``#!C`/\`0Q@AK@,`"(Q"
+M`"0P0@`?+$,`!`!`*"$48``"H@(`DR0%``,PI`#_``0AP"2$"``,`'I7H@4`
+MDP!`&"&N`@`P$$``(B0$`*@``A`C,$('_P!B$"$D!`@@#`!Z5ZX"`"P`0!@A
+MK@(`-!!``!@D!`"J``(0(S!"`!\`8A`A)`0#``P`>E>N`@`XK@(`>!!```\D
+M!``!D@0`D#P%@`(F!P"<`@`P(0P`8)HDI9BD)`(`_Z8"`(0"`"`A#`!CG:8`
+M`(8\`H`"K%!'V```("&/OP`$C[````"`$"$#X``()[T`$">]_^"OL@`(K[$`
+M!*^_`!BOM0`4K[0`$*^S``ROL````("((9"$`)`,`&$(CC,`"`!`D"&.8@``
+M)`/__@!#$"2N8@``)`(``JYB``".8@``,$(``A1`__TD`@`&KF(`:)(B`)..
+M)``P```H(0`",<`DQ@@`#`!PJ@`"@$".)``T```H(20&"""N(``\#`!PJJX@
+M`$"2)@"3)B0`1```*"$,`'"J``8PP)(F`),``"@A)B0`7`P`<*H`!C#`KF``
+M;(XE`"P2```,``"@(0"@("$\`@!`-$*``":4``&L@@```I`8*R0"``&L@@`(
+MK(``/!1@__<DA`!`KF4`&(Y"``0P0@`04$``!(XP`#B.8@!$KF(`1(XP`#B.
+M,@!X``"@(8X#``0D`H#_)!4``0!B&"0\`H`")$*0.*Y"``2N$@`<K@,`!*X5
+M``"N40```@`@(0P`9`XFE``!+H(`0"80`"`40/_O)E(`##P"`$`T0@!`KF(`
+M@(YC`(`\`O_^-$+__@!B&"0D`@%'KF,`@*YB``@D`@#_IB(`A*8@`(:/OP`8
+MKG4``(^T`!"/M0`4C[,`#(^R``B/L0`$C[````/@``@GO0`@)[W_\*^Q``2O
+MOP`(K[```(R"`!P`@(@AC%````P`81&2!`"0C@(`/%1```^.`@!`KA$`/(XB
+M`!R6`P"*KA$`0*Q```"2!`"0)&,``0P`82*F`P"*C[\`"(^Q``2/L````^``
+M"">]`!",0@`<$`#_\:Q1``",A@`(```@(:S%`'2,PP!T+(($``!E&"008``#
+M)(0``11`__H``````^``"```$"&,A@`(```X(8S"```LZ`0`).<``31"0`"L
+MP@``C,0`>(S"`'",PP```$00)3!C0``48``#`$40)!4`__,`````C,,``"0$
+MO_\``A`K`&08)`/@``BLPP``)[W_\*^E``"OI@`$CZ4``(^B``2/HP``C(8`
+M"*RB``BL8``,C,(`````("$T0D``K,(``*S'`'",P@!X`$<0)!1```<L@P0`
+M$&``!22$``&,P@``,$)``!1`__<`````C,,``"R"!``D!+__`&08)*S#```#
+MX``()[T`$">]_^"OL0`4K[``$*^_`!B0Z0``C((`")#H``&OI0``KZ8`!(Q#
+M`!@`"8!``@B`(0`0$8``8A@AKZ,`"(^E``@`"$$`CZ8```$)0"$D!P`!`("(
+M(0$'.`0,`&1-`!"`@`(1&"&,8@!$5$``#(QC`%R/H@``K&(`1`(1&"&/I``$
+MC[\`&(^Q`!2/L``0```0(:QD`%P#X``()[T`((^B```0`/_UK&(``">]_^"O
+MOP`0D.@```#@8"&0YP`!C(D`"``($$``1U@AKZ4````+:("OI@`$KZ``"(TC
+M`!@!I!`A`(!0(8Q$`%P`!SD```L1@`!B&"$`Z#@A)`(``:^C``P`XG`$KZ0`
+M"```,"&-(@``+,@$``&J*"$T0D``K2(``(TB`'@`3C@D$.``!B3&``&/H@`(
+MCZ,``(^D``2L0P``K*0`7(TB```P0D``%$```P`````5`/_M`````(TB```D
+M`[__`$,0)!#@``6M(@``C[\`$```$"$#X``()[T`((^C``@`"Q"`CZ4``(^F
+M``0`2A`AK$,`7`%`("$,`&1L`8`X(1``__./OP`0)[W_T*^S`!ROL@`8K[$`
+M%*^_`""OL``0`*"0(8R#``B0I0```("((9)$``&,8P`8``400`!$$"$``A&`
+M`&(8(:^C``"/HP````0A``"%("$D`@`!`()@!```6"$``)@ACD@`"!!@`!,`
+M`%`ACZ0``(^E``"/H@``)`/_\`"#("0P0@`/)$(`3P!#$"0`@B`A`*,H)`"%
+M$"L40``&`````+RQ```DI0`0`(40*Q!`__P`````CZ(``(Q#`#PD`@`!$&(`
+M"20$`*&/OP`@C[,`'(^R`!B/L0`4C[``$`"`$"$#X``()[T`,(XP`#PM`D`!
+M)`E```$"2`L2```Z`0E`(XX&`!R,P@``%$```JXB`#RN(`!`EB,`B@`)%``T
+M18"`)&/__S1$`(`D`@`!K-$```(*F`JN`@``%0``**8C`(JN!0`$CD,`!(X$
+M``0D`H#_`&H8(0""("2LT@`()&=``"1B$``D92``)&8P`*X$``2N`@`,K@4`
+M$*X&`!2N!P`8K@,`"!%@``(!25`AK7```!4`_]4"`%@A`8`H(0P`9#<"("`A
+M%$``!P(@("$"8"@A`@`P(0P`9&P"0#@A$`#_P@``("$"8"@A`@`P(0P`9)8"
+M0#@A$`#_O```("$0`/_9K@0`!!``_[@D!`"F)[W_\*^_```,`&37`````(^_
+M```#X``()[T`$">]__"OOP``#`!DUP````"/OP```^``"">]`!`GO?^PK[,`
+M+*^_`$2OO@!`K[<`/*^V`#BOM0`TK[0`,*^R`"BOL0`DK[``((R"``BOH``(
+MKZ``#*^B``",50!L`("8(:^@`!`2H``2KZ``%)""`),00``/``"@(20"``$"
+M@A`$`J(0)#*%`/\D!@`!)I0``0``."$``$`A%$``I20)``B28@"3`H(0*Q1`
+M__0D`@`!CZ,``(QU`'RL=0!\$J``C(^_`$2OH``$CZ0`!))B`),``*`A$$``
+M?P`$N"L`%Q"``%,0(21"`$2OH@`8`N#P(1+@`(TD`@`!)H,`$`!B$`0"HA`D
+M4$``;))B`)./H@``CZ0`&(Q#`!@`'A&``&*P(1+``!",A0``,L(`#R1"`$\D
+M`__P`$,P)`+#&"0`9A`A`$,0*Q1```<`8"`AO'$``"1C`!``AA`A`$,0*Q!`
+M__L`````4*``5))B`),PH@`/)$(`+R0#__``0S`D`*,8)`!F$"$`0Q`K%$``
+M!P!@("&\<0``)&,`$`"&$"$`0Q`K$$#_^P````",H@`$,$(`@!!``!$`````
+M5H``/Y)B`).,H@`$)`,`0``"%`(P0@!_5$,`.9)B`).,H@`$,$*``%!``#62
+M8@"3C*(`!"0#_W\`0Q`DK*(`!(RB`!R,0@`($$``!@````",0P`$C$0`"*^B
+M`!"OHP`4KZ0`#(RB``",HP`$)`3_X#!C`&@48``[`$20)(RB``2/HP`(CZ0`
+M#``"%`(P0G__`&(8(0"#(".OHP`(KZ0`##*0`/\R\0#_`F`@(0(`*"$,`&B7
+M`B`P(5)```>.9`"8CD(`'(^C`!",0@`($$,`"0````".9`"8CZ@`%(^I``P"
+M`"@A`B`X(0P`7Q```#`AKZ``"!9`_Z\"0"@ADF(`DX^D`!@FE``!`H(0*R2$
+M``BOI``8%$#_B"?>``*/H@`$)$(``:^B``0L0@`"%$#_>8^D``2/OP!$C[X`
+M0(^W`#R/M@`XC[4`-(^T`#"/LP`LC[(`*(^Q`"2/L``@`^``"">]`%"NP``,
+M$`#_SC*0`/\0`/]U`H(0!`P`7Q".9`"8$`#_6I)B`),GO?_PK[$`!*^_``RO
+ML@`(K[```)""`)`\`X`")&-'U``"$(",D@`(`$,0(20#``$`@(@AK$,``(Y0
+M``2.0@`(`@(0)!!``"@R`@!`KE``!!1``"$`````,@(`!!1``!H`````,@(`
+M`A1``!,`````,@(``11```P`````,@(!`!!`_^T`````CD(`1#!"#``00/_I
+M``````P`9IH"("`A$`#_Y0`````,`&5@`B`@(1``__,R`@$`#`!FZ@(@("$0
+M`/_L,@(``0P`9JH"("`A$`#_Y3("``(,`&9O`B`@(1``_]XR`@`$DB,`D#P"
+M@`*/OP`,C[(`"(^Q``2/L```)$)'U``#&(``8A@AK&````/@``@GO0`0)[W_
+M\*^Q``2OOP`(K[```(R0``@`@(@AC(0`F```*"$``#`A```X(0P`7EL``$`A
+MC@,`%#P"`?\T0O__`&(8)*X#`!2.`@!LK@(`;(X"`'RN`@!\C@(`<!1`__XD
+M`O__K@(`=(X"`$0P0@$`$$``!"0"``&N(@``)`(``Z8B`(2.)`"8```H(0``
+M,"$``#@A#`!>6P``0"&/OP`(C[$`!(^P```#X``()[T`$">]__"OOP``E(,`
+MA`"`$"&,A`"8I$,`CB0#`("D0P"$```H(0``,"$``#@A#`!><0``0"&/OP``
+M`^``"">]`!`GO?_PK[```*^_``BOL0`$C((```"`@"$00``"C)$`"*R```".
+M(@!$,$(!`!1```T`````CB(`1#!"`@!00``#H@``DB0"``*B`@"2D@@`DHX$
+M`)@``"@A```P(0P`7E0``#@ACB(`1#!"`(!40``9E@(`A(XB`$0P0@"`%$``
+M!20"``*6`P"$)`(`@!!B``<D`@`"I@(`A(^_``B/L0`$C[````/@``@GO0`0
+ME@(`CHX$`)@``"@AI@(`A```,"$``#@A#`!>?@``0"$0`/_SC[\`"(X$`)@`
+M`"@AI@(`CB0"`("F`@"$```P(0``."$,`%Z```!`(1``_]X`````)[W_\*^P
+M````@(`A/`2``J^_``0,`'!T)(02+)8"`(R/OP`$)$(``:8"`(R/L````^``
+M"">]`!",@@`(``4N0*Q%`!0D`@`!`^``"*2"`(2,B0`(,*4`_P`%$<"-(P`8
+M`&(@(1"``!$D`@`!,((`#R1"`$\D`__P`$-`)`"#&"0`:!`A`$,0*Q1```<`
+M8#@AO'$``"1C`!``Z!`A`$,0*Q!`__L`````)`(``0"B$`2(@P`HF(,`*XB%
+M`"R8A0`OJ,,``+C#``.HQ0`$N,4`!P/@``BM(@!L)[W_X*^S``ROL0`$K[``
+M`*^_`!2OM``0K[(`"(R4``B0IP``D*8``8Z#`!@`!Q!``$80(0`"$8``0X@A
+M`*"`(1(@`!``@)@A,B(`#R1"`$\D`__P`$,H)`(C&"0`91`A`$,0*Q1```<`
+M8"`AO'$``"1C`!``A1`A`$,0*Q!`__L`````CB(`/``&&0``9Q@A)`0``0!D
+MD`000``*```8(8^_`!2/M``0C[,`#(^R``B/L0`$C[````!@$"$#X``()[T`
+M(`)@("$,`&0W`D`H(11``"H"8"`AD@,``B0"``$08@`BE@(`$!!@`!P`````
+MC@,`%!!@``,``B0`/`(@``""("6N)```D@(``)($``$D`P#```(0@`!4$"$\
+M!@#``&0P"HQ%`(`D0P"`$(``"9("``(``A2``,(0)0"B$"6L8@``)`(``:XB
+M`#P0`/_4```8(1``__@``A"```(4`#1"@``0`/_HKB(``#P#0````A0`$`#_
+M^P!#$"4,`&0K`D`H(11`_\8D`P"D$`#_TY(#``(PI0#_,,8`_P`%*$``IB@A
+M``4H@`"D*"&,HP!$$&``!```$"&,8@`<C$(`")!"``,#X``(`````">]_]"O
+MLP`<,-,`_Z^R`!@`$Q$`,+(`_Z^U`"2OM``@K[$`%*^_`"BOL``0`("((0!2
+M$"$`$AA`)`0``0!$(`0`<Q@ACB4`"*^@``BOH``,KZ,``*^D``2/H@``C*,`
+M&```J"$``A&``&(@(1"``!```*`A,((`#R1"`$\D`__P`$,P)`"#&"0`9A`A
+M`$,0*Q1```<`8"@AO'$``"1C`!``IA`A`$,0*Q!`__L`````C((`/!1``$,D
+M`P"CCZ(````"$(``41`AC$4`1!"@`#T``!@A,*(`#R1"`"\D`__P`$,P)`"C
+M&"0`9A`A`$,0*Q1```<`8"`AO'$``"1C`!``AA`A`$,0*Q!`__L`````C*(`
+M'(Q#``@08``%`````(QT``2,8@`(`&"H(:^B``R,H@``C*,`!"0$_^`P8P!H
+M%&``"P!$@"2,H@`$CZ,`"``"%`(P0G__`&(8(:^C``B/H@`,CZ,`"`!#$".O
+MH@`,`B`@(0)`*"$,`&B7`F`P(5(``!J.)`"8C@(`'(Q"``@050`)`````(XD
+M`)B/J0`,`D`H(0``,"$"8#@A#`!?$`*`0"&OH``(%@#_Q@(`*"$``!@AC[\`
+M*(^U`"2/M``@C[,`'(^R`!B/L0`4C[``$`!@$"$#X``()[T`,(^I``P"0"@A
+M```P(0)@."$,`%\0`H!`(1``_^P`````C((`""0%``&,0@!$,$,`P"0"`(!0
+M8@`$E((`A```*"$#X``(`*`0(51#__T``"@A$`#_^P`````GO?_PK[\`!*^P
+M````@(`AC(0`""0#_[B,@@`(`$,0)*R"``B,@@``)`/__@!#$"2L@@``)`(`
+M`JR"```,`'IJC@0`,`P`>FJ.!``T#`!Z:HX$`'B2!`"0#`!@QHX%`)R/OP`$
+MC[````/@``@GO0`0C(0`"#"E`/\PQP#_``400(R&`!@`1Q`A``(1@`!&$"&,
+M0@````48@`!D&"$\!@`!,$*``#3&``$00``%`&`H(8QB`(``1A`E`^``"*QB
+M`(",8P"`/`(``22E`(`4X``"`&(0)31B``$#X``(K*(``(R"``@PI0#_``4H
+M@`"B*"&,H@"`/`,``31C``$`0Q`D`^``"``"$"LGO?_PK[$`!*^_``BOL```
+MC)``"#P"`$`PL?__C@8`@```*"$D!P`U`,(0):X"`(`\!H`")`($`!(B``PD
+MQD7PC@8`1"0#_]4`$1(``,,P)`#"$"6N`@!$C[\`"(^Q``2/L````^``"">]
+M`!`,`&)?`````!``__..!@!$C(,`"#"E`/\\"``!/`?__@`%$(`PQ@#_-0@`
+M`33G__X0P``%`$,@(8R"`(``2!`E`^``"*R"`(",@@"``$<0)`/@``BL@@"`
+M)[W_X*^R``BOOP`0K[,`#*^Q``2OL```C((`"#"E`/\PQ@#_C$,`&``%*$``
+MIB@A``41@`"`D"$`8B`A$(``#S""``\D0@!/)`/_\`!#,"0`@Q@D`&80(0!#
+M$"L40``'`&`@(;QQ```D8P`0`(80(0!#$"L00/_[```````%F(`"<A`AC$0`
+M1!"``#$P@@`/)$(`+R0#__``0S`D`(,8)`!F$"$`0Q`K%$``!P!@*"&\<0``
+M)&,`$`"F$"$`0Q`K$$#_^P````",@P``)`+_X`!BB"02(``+)B(`(`!1$"L"
+M(!@A%$``!P(@*"&\<0``)&,`$"2B`"``0Q`K$$#_^P````",@P`<)`(``:R"
+M``"L<@``K(``!`P`9`Z,<``($B``$P)R$"$2```)K%$`1(XB`!R,0@`($%``
+M!H^_`!".`@`8`@`@(0P`86NL4@``C[\`$(^S``R/L@`(C[$`!(^P`````!`A
+M`^``"">]`""L0`!<$@#_]JQ``$00`/_QC@(`&">]__`T`K]H$*(`!*^_``"/
+MOP```^``"">]`!`D`@`!5(+__(^_```,`&VM`````!``__B/OP``)[W_\"0$
+M``&OOP``#`!H^#0%OVB/OP```^``"">]`!`GO?_PK[\```"`*"&,A`"(#`!T
+M[P`$((*/OP`````0(0/@``@GO0`0`^``"```$"$GO?_P/`*``J^P```D4$:<
+M/`*``B1"1H`"`A`K$$``!:^_``2/OP`$C[````/@``@GO0`0C@(```!`^`DF
+M$/_\/`*``B1"1H`"`A`K4$#_^HX"```0`/_TC[\`!``$$",`@B`D``04``!$
+M(",`!!&``((@(0`$$0``@B`A/`*``B1",!0`!":"`((@(0/@``B`@@``&(``
+M%"0(`!0H@R<1)`(G$`"#$`MP2#`"`((@(QC```M`!4@`0`)(`!"B__X`11@C
+M/`<``P!`*"$$8``(-.<-0`##,",<P/_W`````!R`_^\H@R<1`^``"``````0
+M`/_X`&<8(0/@``@``````^``"``````\`J#`-$(`H(Q"```#X``(,$(`#R>]
+M_^"OOP`0#`!I7``````00`!#C[\`$$"`X`````````````````!`@.@`````
+M````````````/`.``+QI```\`H``)&,`$#1"#_\`0Q`K$$#_^@````!``H``
+M````````````````/`/__S1C__@`0Q`D-$(``T""@`````````````````!`
+M@.``````````````````0(#H`````````````````#P#@`"\:```/`*``"1C
+M`!`T0@__`$,0*Q!`__H`````0`*``````````````````#P#__\T8__X`$,0
+M)#1"``-`@H``````````````````0`*``*^B``"/H@``CZ(``"0#__P`0Q`D
+MKZ(``(^B``!`@H``C[\`$`/@``@GO0`@/`2@P#2$`"",A0``)`+^_SP#H,``
+MHB@DK(4``(R%```D`OW_-&,`D`"B*"2LA0``C&4``#2E``$#X``(K&4``#P#
+MH)`T8T``C&4``"0"__P\!*"0`*(H)*QE```TA$`$C(4``#P#__PT8___`*,H
+M)#P"H)"LA0``-$*8<(Q%```TI0`/K$4``(R%```\`@`!`*,8)`!B*"4#X``(
+MK(4``#P#H,`T8P`@C&(``#1"`P`#X``(K&(``#P%H,`TI0!@C*8``#P#__X\
+M`@`!``0A@#1C__\`@B`D`,,8)`!D,"6LI@``C*8``#P"``(`PC`E`^``"*RF
+M```PA`#_``01@#P&H,`\!:#`,$<`0"0"``$TQ@!@$((`"C2E`&2,PP``)`+_
+MOS1C`#"LPP``C,,```!B$"0`1Q@E`^``"*S#``",HP``)`+__@!B&"00`/_S
+MK*,``">]__"OL```K[\`!`P`:5PPD`#_`$`P(3P#H,`D`@`!$@(`%S1C`&``
+M$!`G/`.@P``0(<`T8P!@``(1P#!%`(`PA`"`C&,``!#```HD`O]_`&(0)`!%
+M&"6/OP`$C[```#P"H,`T0@!@K$,```/@``@GO0`0`&(0)!``__<`1!@EC&,`
+M`%#```,T8P$`)`+^_P!B&"0\`J#`-$(`8*Q#```0`/_B`!`0)R>]__"OOP`$
+M#`!I7*^P````0(`A/`*``@P`:>F01$8J/`*``@P`:@"01$8I/`*@P#P#[_\T
+M0@!@-&/__XQ%```2```4/`(0``"C*"0\`J#`-$(`8#P#H,"L10``-&,`((QE
+M```D`N__/`2@P`"B*"0TA`"0K&4``(R%``"/OP`$C[```#2E``*LA0```^``
+M"">]`!`0`/_M`*(H)4`(8```````-0@``4"(8`````````````/@``@`````
+M/`.@`!"```XT8P0`**(`$!!```LD`O__)*7__Q"B``@`````D&(``"2E__\D
+M8P`!H((``"0"__\4HO_Z)(0``0/@``@`````)[W_X`.@("&OOP`0#`!J620%
+M``^3HP``C[\`$#P$@`(``Q!")(5'X#!"``$P8P`!H(-'X*"B``$#X``()[T`
+M(">]_^`\`Z#`K[\`$#1C`)",8@``/`6@P#2E`&"OH@``CZ(``#P$_O\TA/__
+M-$(`!*^B``"/H@``K&(``(RB``"OH@``CZ(```!$$"2OH@``CZ(```P`:QVL
+MH@``#`!IV0``("$,`&U)``````P`::L`````)`(#Z*^B``"/H@``)$+__Z^B
+M``"/HP``)`+__Q1B__H\!*#`-(0`8(R"```\`__O-&/__Z^B``"/H@```$,0
+M)*^B``"/H@``#`!INZR"```,`&HJ``````P`:T0`````#`!K<0`````,`&IK
+M`````#P"@`(,`&OU@$1&*`P`:E$`````C[\`$`/@``@GO0`@/`*@P#P%_^\T
+M0@!@-*7__XQ#``!0@``#`&48)#P"`!``8A@E/`*@P#1"`&`#X``(K$,``">]
+M__"OL```K[\`!`P`:5P`@(`A`$`P(3P#H,`D`@`5)`0`"0!0(`HT8P!H/`*@
+MP(QE```T0@!@K&0``(Q%```2```%/`*@P!#``",D`O[_-*4!`#P"H,`T0@!@
+MK$4``!(``!F,10``%,``%3P"$``\`N__-$+__P"B*"0\`J#`-$(`8*Q%``",
+M10``%@``!H^_``10P``$-*4!`"0"_O\`HB@DC[\`!(^P```\`J#`-$(`8*Q%
+M```#X``()[T`$!``_^X`HB@E4,#__3P"$``0`/_H/`+O_Q``_]X`HB@D/`:@
+MP#P"__TTQ@!@$(``!C1"__^,PP``/`(``@!B&"4#X``(K,,``(S#````8A@D
+M`^``"*S#```\!J#`/`+^_S3&`&`0@``&-$+__XS#```\`@$``&(8)0/@``BL
+MPP``C,,```!B&"0#X``(K,,``#P$H,`TA``@C(,``#P"__LT0O__`&(8)`/@
+M``BL@P``*((`!!!```L`````)`(``0"",`0`!A`G/`.@L8QC``!0H``"`&(8
+M)`!F&"4\`:"QK",```/@``@`````/`*@L31"``B,0P``)`(``0""$`0``C`G
+M)`(``1"@``8`@A`$`&88)#P"H+$T0@`(`^``"*Q#```0`/_[`&(8)3P$H,`T
+MA``@C(,``#P"__<T0O__`&(8)`/@``BL@P``/`*@P#1"`"`D`P`!K$,``!``
+M__P\`J#`)[W_X*^S``ROL@`(K[$`!*^P```\`H`#K[\`$(Q#H80`!!!``*"0
+M(0!B@"$`P)@A%*``"```B"&/OP`0C[,`#(^R``B/L0`$C[````/@``@GO0`@
+M`!$@0`)D*"$F,0`!#`!L1P($("$",A`K5$#_^@`1($`0`/_QC[\`$">]_^"O
+ML0`4K[``$*^_`!@,`&P^``````!`@"$\`H`#K%"A@"11H8`D`@`!$@(`40``
+M```6```"-`+P`*XB``0\$(`#)A"A@#P"H*"N`@`4)`(``JX"`!@F!@`<)`0`
+M`20%``$,`&M2K@``$"8&`!XD!`!`#`!K4B0%``$F!@`@)`0`00P`:U(D!0`!
+M)@8`(B0$`$(,`&M2)`4``28&`"0D!`!##`!K4B0%``&6`@`D)`4`("8&`"H`
+M`A!"+$,`(`!#*`L,`&M2)`0`1"8&`"8D!`!D#`!K4B0%``&6`@`F)`4`$"8&
+M`&H``A!"+$,`$`!#*`L,`&M2)`0`928&`"@D!`!U#`!K4B0%``&6`@`D)`4`
+M""8&`(H``A!"+$,`"`!#*`L,`&M2)`0`=B8&``PD!``=#`!K4B0%``$F!@`*
+M)`0`'B0%``$,`&M2)A``"`(`,"$D!``?#`!K4B0%``&/OP`8C[$`%(^P`!`#
+MX``()[T`(`P`:]D#H"`AEZ(````"&@(0</^M/`(``20"``)48O^L/!"``Q``
+M_Z@\`@`$)[W_\`"`*"&OOP``#`!L1R0$"'B/OP```^``"">]`!`\`H`"`^``
+M"*Q$1BP\`H`"`^``"(Q"1BP\`E'K-$*%'P""`!D\`H`"```@$``$(8(#X``(
+MK$1&,#P"@`(#X``(C$)&,#P"@`(#X``(C$)&-#P"@`(D0C!4``08@`!B&"$`
+M!!!`)[W_\#P(H,`P1P`.+((`"*^_``2OL```-0@`8!1```4`@#`AC[\`!(^P
+M```#X``()[T`$(T%```\`H`"K$9&-"0"__$`HA`D`$<H)8QD```TI0`!#`!K
+MX:T%```\`H``)$(#`(Q$`!0``"@A$(``!"0&)8",@@`4`$#X"8R$```,`&OD
+M``````P`:^<`0"`A0`A@```````!`(`A/`'__S0A__X!`4`D0(A@````````
+M``````````P`:^\R$``!/`.``JQB1]Q`@$@`````````````````0()8````
+M`````````````$`(8```````,A```0$00"5`B&``````````````````$`#_
+MQX^_``0\`J"S-$(`'(Q"```GO?_PKZ(``(^B```P0@`!`^``"">]`!`\`J$`
+M.(0``@""("&4@@```^``"*2B```#@#@A/!R``R><QK``!!!``$00(0`"&8``
+M0Q`A``(0@`!$$"$``A"``$00(3P#:-L``B&`-&.+K0"#`!@`!!?#```8$``#
+M&P,`8B`C/`(4^#1"M8D`@@`8``0?PP``$!```A-#`$,H(P`%$$``11`A``(9
+M@`!#$"$``A"``$40(0`"$(``11`A``(10`""*"-`!D@`0`-(``!F&",\`@`#
+M!&``"C1"#4``91`J%$#_^0``````@R`C7(#_Y3P"%/@`X.`A`^``"``````0
+M`/_V`&(8(2>]__"OOP```X`0(3P<@`,,`&M,)YS&L#P"O\``0``(`````">]
+M__"OOP`$K[````.`@"$\'(`##`!L@B><QK`"`.`AC[\`!(^P`````!`A`^``
+M"">]`!`#X``(```0(2>]_^"OL@`(K[```*^_`!"OLP`,K[$`!`"`@"$``"@A
+M)!(``0``&"$#@)@A/!R``R><QK`D`O_^$((`-RB"__\00``L)`+__R0"__U0
+M@@`"``"`(280``$D`P`!$&``&#P"@``D40,`CB0`&!"```<\`X`#C((`%(R$
+M````0/@))`4`!`!`*"$\`X`#`!`10"1CBL@`0Q`AKB(`&#P"@`*L4$8X$*``
+M#XXD`!B,@@`4C(0``"0%``4`0/@)``````)@X"$"0!`AC[\`$(^S``R/L@`(
+MC[$`!(^P```#X``()[T`((R"`!2,A```$`#_\B0%``14@O_8)A```3P"@`*,
+M0D8X'$#_U212__\D$O_]$`#_T@!"D`L\`H``)$(#`*Q``!@\`H`"$`#_S*Q$
+M1C@D!0`!```8(0.`,"$\'(`#)YS&L"0"__X0@@`>*(+__Q!``!,D`O__)`+_
+M_5""``(``"`A)(0``20#``$08``)``090#P"@`,D0HK(`&(8(3P"@``D0@,`
+MK$,`%#P"@`*L1$8\`,#@(0/@``@`H!`A5(+_\22$``$\`H`"C$)&/!Q`_^XD
+M1?__)`7__1``_^L`0B@+/`*``"1"`P"L0``4/`*``A``_^6L1$8\`X`0(3P<
+M@`,GG,:P`^``"`!`X"$#@!`A/!R``R><QK`#X``(`$#@(2>]__"OOP``/`6`
+M`I"B1D`00``$```@(8^_```#X``()[T`$#P"@``D0@,`C$(`-"0#``$`0/@)
+MH*-&0!``__>/OP``)[W_\#P"@`"OOP``)$(#`(Q#`!0`!"8```0F`Q!@`!(P
+MA0#_C&0``(QB``P`0/@)`````#P"@``D0P,`C&(`1!1```0``"`AC[\```/@
+M``@GO0`0K&``1`P`;:,`````$`#_^H^_``",0P`8$`#_[0`````GO?_PK[\`
+M!*^P`````#`A/`>````&$(`DY0,`),8``3P#@`(`11`A)&.R8"C$`$"L0P``
+M5(#_]SP'@``\`@`(-$(`%:SB`P`\`H`")$*R"*RB`$`\`H`")$*R+*RB`!`\
+M`H`")$*Q-*RB`$@\`H`")$*T1*RB`"`\`H`")$*T6*RB`!P``#`AK*``3*R@
+M`#@``"@A``88P`!E&"$\`H`#)$**R``#&(``8A@A)*4``3P"@`(D0K)@**0`
+M"*QB```4@/_U``88P"3&``$HP@`"%$#_\```*"$\$(``/`*``B80`P`D0K)H
+MK@(`,#P"@`(D0K.8)`3__@P`;)JN`@`T#`!LYB0$__X,`'RO``````P`;)H`
+M`"`A#`!LY@``("&N``!$C[\`!(^P```#X``()[T`$!"@``H``#`A)*7__P"%
+M$"&`0P``)`(``Q!B``0D!@`!5*#_^B2E__\``#`A`^``"`#`$"$```%-`^``
+M"``````GO?_PK[\```P`:1@`````C[\```/@``@GO0`0)[W_\*^_``2OL```
+M/`*``HQ"1D040``5/`*``B101K@\`H`")$)&N!("``XD`P`!C@(`#`!`^`D"
+M`"`A$$``#XX"`!@T0@`!K@(`&#P"@`(F$``@)$)&N%8"__:.`@`,)`,``3P"
+M@`*L0T9$C[\`!(^P```#X``()[T`$"0#__X0`/_Q`$,0)">]__"OOP``#`!M
+MV0`````,`&W;``````P`!H0`````#`!WP@`````#X``(``````/@``@`````
+M)[W_\``$)@"OL```)`(`"@`$A@.OOP`$$@(`!R0$``T,`&TL`@`@(8^_``2/
+ML````^``"">]`!`,`&TL`````!``__<```````0F`">]__"OOP``#`!MW0`$
+M)@./OP```^``"">]`!`GO?_PK[```*^_``0`@(`AD(0````$)@`4@``$C[\`
+M!(^P```#X``()[T`$``$)@,,`&W=)A```9($````!"8`5(#_^P`$)@,0`/_U
+MC[\`!">]__`D!0`0)`8`*P``."&OOP``#`!N;P``0"&/OP```^``"">]`!`G
+MO?^PK[4`-"0"`"`D%0`PK[X`0*^W`#ROM@`XK[0`,*^S`"ROL@`HK[\`1*^Q
+M`"2OL``@`$BH"@"`D"$`H)@A`,#P(0#@N"$!(+`A``"@(0.T&"$FE``!*H(`
+M(!1`__R@=0```E,0)11``"4``*`A)`(`,"04``&CH@```I80*@+"H`LD`@`M
+M$N(`%@*=$"$FE/__!H``"(^_`$0"G1`A@$0```P`;=TFE/__!H'__`*=$"&/
+MOP!$C[X`0(^W`#R/M@`XC[4`-(^T`#"/LP`LC[(`*(^Q`"2/L``@`^``"">]
+M`%"`0O__)H/__P!5$"8`8J`*`[00(1``_^:@5P``$$#_WP*6$"H``(`A`D`@
+M(0)@*"$"`#`A#``$XP/`."$\!(`")(02,`"#$"&00P```[00(0)`("$"8"@A
+M`@`P(0/`."$,``-$H$,```!`D"$`0Q`E`&"8(11`_^LFE``!$`#_QP*6$"H`
+MH%`A`,!8(0#@8"$`@!@A```0(2>]__`!`$@A`$`@(0!@*"$!0#`A`6`X(:^_
+M```,`&X5`8!`(8^_```#X``()[T`$"0'``$0@``9```0(9""`````AX`$&``
+M%`"`,"$`Q!`C*$((`0`".`H``QX#)`(`"A!B``<D`@`-$&(`!21B_^`L10!?
+M)`(`"%1B``$`!3@*$.``!23&``&0P@````(>`%1@_^\`Q!`C`.`0(0/@``@`
+M````)[W_@`"%$"6OO@!PK[<`;*^V`&BOM0!DK[0`8*^S`%ROL@!8K[\`=*^Q
+M`%2OL`!0`("0(0"@F"$`P*@A`."P(0$`\"$#H*`A%$``&@``N"$D`@`P)[0`
+M`:.B```2G0`(`N`0(2:4__^2@@``)O<``:*B```6G?_[)K4``0+@$"&BH```
+MC[\`=(^^`'"/MP!LC[8`:(^U`&2/M`!@C[,`7(^R`%B/L0!4C[``4`/@``@G
+MO0"`$$#_Z0``````%H?#`D`@(0)@*"$"`#`A#``$XP+`."$#PQ`AD$(```)`
+M("$"8"@AHH(```(`,"$,``-$`L`X(0!`D"$`0Q`E`&"8(11`_^XFE``!$`#_
+MU``````GO?]PK[X`@`"`\"$`P"`AK[<`?*^V`'BOM0!TK[0`<*^S`&ROL@!H
+MK[\`A*^Q`&2OL`!@`,"@(0"@N"$,`&Z``."H(0``D"$``)@AK[T`1*^@`%00
+M0`%D``"P(8*"```FE``!$$``#@!`B"$D`@`E$B(`&`(@("$"X"@A`\#X"0``
+M``"/H@!4)$(``:^B`%2"@@``)I0``11`__0`0(@ACZ(`5(^_`(2/O@"`C[<`
+M?(^V`'B/M0!TC[0`<(^S`&R/L@!HC[$`9(^P`&`#X``()[T`D(*1```D`@`M
+M)I0``0``*"&OH`!0$B(!.J^@`$@D`@`P4B(!,X*1``"OH`!,)B+_T"Q"``H0
+M0``.)`(`+H^C`$@``Q"``$,0(0`"$$``41`A@I$``"1"_]"OH@!()B+_T"Q"
+M``H40/_U)I0``20"`"X2(@$1CZ(`3"0"`&P2(@$'KZ``0"8B_[XP0P#_+&(`
+M-Q!``!HF(O_;``,0@#P#@`(D8Q*D`$,0(8Q"````0``(`````!"@`/(D`O_\
+M)J(`!R0#__@`0Z@DCK(``(ZS``0FM0`()`(`9!(B`.`D`@!$$B(`W@`````D
+M`@``)`/__P)"D"0"8Y@D)B+_VS!#`/\L8@!4$$``RP`#$(`\`X`")&,3@`!#
+M$"&,0@```$``"``````D!``P`\#X"0+@*"$D!`!X`\#X"0+@*"$D`@`!)`,`
+M"*^B`$ROHP!()B+_O#!$`/\L@@`U4$``$J^]`$0\`X`"``00@"1C%-``0Q`A
+MC$(```!```@`````/`B``B4($D0"0"`A`F`H(0.@,"$D!P`*#`!NG0``````
+M0+`AK[T`1(^B`$B/HP!``%:`(R8"__\`0X`+CZ(`3!!```,D$0`@%&``.B01
+M`#"/H@!0%$``#H^B`$`"`!`A&$``"B80__\"("`A`\#X"0+@*"&/HP!4`@`0
+M(280__\D8P`!'$#_^*^C`%2/H@!`%$``(@!`("$"P!`A&$``#B;6__^/H@!$
+M`N`H(8!1```D0@`!KZ(`1`/`^`D"("`ACZ,`5`+`$"$FUO__)&,``1Q`__2O
+MHP!4CZ(`4%!`_UF"@@```@`0(1A`_U4F$/__)`0`(`/`^`D"X"@ACZ,`5`(`
+M$"$F$/__)&,``1Q`__BOHP!4$`#_2X*"```#P/@)`N`H(8^C`%0D8P`!$`#_
+MVJ^C`%0`8"`A`\#X"0+@*"&/HP!4KZ``0"1C``$0`/_`KZ,`5#P(@`(E"!(P
+M`D`@(0)@*"$#H#`A$`#_JR0'`!`\"(`"$`#_^24($E`D!``E`\#X"0+@*"$0
+M`/^HCZ(`2(^V`$@6P``%)L;__R06`$`D`@`@`$6P"B;&__\8P/^=``"`(0`0
+M%H`$00`$``````(2*`<0```'`!(GPQ!```0"$R@&`!`0(P!2$`0`HB@E`A(@
+M!S"B``$#L!@A%$```B0$`#$D!``N)A```0(&$"H40/_LH&0``!``_X>OO0!$
+M)J(``R0#__P`0Z@D@K$``P+@*"$FM0`$$`#_``(@("$FH@`#)`/__`!#J"2.
+MH@``)K4`!!!``!FOH@!$#`!N@(^D`$100``-/`2``H^C`$2`8@``$$#_<```
+ML"&/HP!$)M8``0!V$"&`0@``5$#__2;6``$0`/]ICZ(`2`P`;?<DA!)D#`!N
+M"X^D`$0\`H`")$(2>!``_^VOH@!$/`*``A``__PD0A)\)`0`)0/`^`D"X"@A
+M`B`@(0/`^`D"X"@ACZ,`5"1C``(0`/]3KZ,`5`9!_R<F(O_;)`,`+0`3F",`
+M$I`C`!,0*P)"D",0`/\?KZ,`0":C``,`8J@DCJ(``":U``0`0)@A$`#_#P`"
+ME\."D0``%B+^^":4``&"D0``)`4``1``_O0FE``!@I$``"1"``&OH@!,)B+_
+MT"Q"``H00/[J)I0``8*1```F(O_0+$(`"A1`__PFE``!$`#^Y"0"`&PD`P`!
+M)I0``1``_LROHP!,)`(``8*1``"OH@!0$`#^PR:4``$\!(`"#`!M]R2$$H0,
+M`&X+`H`@(3P$@`(,`&WW)(02G"00``<,`&W=)`0`(":B``,D`__\`$.H)(ZS
+M```F$/__)K4`!`P`;@L"8"`A!@'_]3P$@`(,`&WW)(02H!``_I<``!`A)[W_
+MT*^_```\`H`"`(`8(8Q$1DBOI0`4KZ8`&*^G`!P`8#`A```H(2>G`!2OJ``@
+MKZD`)*^J`"@,`&[AKZL`+(^_```#X``()[T`,">]__`D`B=T$*(`!*^_``"/
+MOP```^``"">]`!`D`@`!5(+__(^_```,`&T;`````!``__B/OP``)[W_\"0$
+M``&OOP``#`!PAR0%)W2/OP```^``"">]`!`DQO__)`+__Q#"``@`@!@AD*(`
+M`"3&__\DI0`!H&(``"0"__\4PO_Z)&,``0/@``@`@!`A),;__R0"__\0P@`&
+M`(`8(23&__\D`O__H&4``!3"__PD8P`!`^``"`"`$"$\`X`"C&)&5"1"``$#
+MX``(K&)&5#P#@`*,8D94)[W_\!!```:OOP``C&)&5"1"__\00``%```@(:QB
+M1E2/OP```^``"">]`!`,`'>$`````!``__H`````)[W_\`"@$"$`P!@A`0!@
+M(0$@:"&OL0`$`6"((0#@6"&OL````(`H(0%`@"$"("`A`$`P(0!@."$!8$`A
+M`8!((:^_``@,`'(H`:!0(:X1``"/OP`(C[$`!(^P```#X``()[T`$">]__"O
+ML```K[\`!(R#`#0D`@`0$&(`!P"`@"$,`',.`@`@(8^_``2/L````^``"">]
+M`!`,`')E`````!``__<`````/`*``XQ$G#0GO?_PK[\```P`=Q\DA``8C[\`
+M``/@``@GO0`0/`*``P/@``B,0IPT)[W_\*^_```,`'/B`````(^_```#X``(
+M)[T`$">]__``H!`A`,`8(0$`6"&OL0`$`4"((0#@4"&OL````(`H(0$@@"$"
+M("`A`$`P(0!@."$!0$`AK[\`"`P`=1(!8$@AKA$``(^_``B/L0`$C[````/@
+M``@GO0`0)[W_\*^_```,`'4:`````(^_```#X``()[T`$">]__"OOP``#`!U
+MB`````"/OP```^``"">]`!`GO?_PK[\```P`=:$`````C[\```/@``@GO0`0
+M)[W_\*^_```,`'6W`````(^_```#X``()[T`$">]__"OOP``#`!USP````"/
+MOP```^``"">]`!`GO?_PK[\```P`=>,`````C[\```/@``@GO0`0)[W_\*^_
+M```,`'8,`````(^_```#X``()[T`$">]__"OOP``#`!V,P````"/OP```^``
+M"">]`!`#X``(K*0``#P"@`(#X``(C$)&=#P"@`*,0D9TC$,`#`/@``B,0@`(
+M)[W_\`"@$"$`P!@AK[$`!*^P```!`(@A`."`(0"`*"$`0#`A`&`X(:^_``@,
+M`'X3`0`@(:X1``"/OP`(C[$`!(^P```#X``()[T`$">]__"OOP``#`!^-P``
+M``"/OP```^``"">]`!`GO?_PK[\``(R"`"@40``$`(`H(8^_```#X``()[T`
+M$`P`?<2,A``($`#_^X^_```GO?_PK[\```P`>'$`````C[\```/@``@GO0`0
+M)[W_\*^_```,`'AT`````(^_```#X``()[T`$">]__"OOP``#`!XN@````"/
+MOP```^``"">]`!`GO?_PK[\```P`>1H`````C[\```/@``@GO0`0)[W_\*^_
+M```,`'DW`````(^_```#X``()[T`$">]__"OOP`$K[````P`>5L`H(`AK@(`
+M`(^_``2/L````^``"">]`!`GO?_PK[\```P`>5T`````C[\```/@``@GO0`0
+M)[W_\*^_```,`'EC`````(^_```#X``()[T`$">]__"OOP``#`!Y:@````"/
+MOP```^``"">]`!`GO?_PK[\```P`>=\`````C[\```/@``@GO0`0)[W_\*^_
+M```,`'H-`````(^_```#X``()[T`$"0#``4\`H`#K$.<,#P"@`,GO?_PK$"<
+M.#P"@`.OL```K[\`!`"`@"&L1)PT/`*``JQ`1E2.`@`0`$#X"8X$`!0,`'-Z
+M`````!``__N.`@`0)[W_\`$J$"&OL0`$`("((:XF`!`DA``8`*`P(:XG`!2N
+M(@`,KBD``*XJ``2N*0`(`B`H(:^_``ROL@`(K[````P`=]$!`)`A/`*``HQ%
+M1G0F,`!(/`:``@(`("$DQM$D#`!^!@(`."$\`X`"E&1&4"0"``2N$0`L)(4`
+M`:XB`#0D`@`!KB(`.*X@`#RN(`!XKB``?"8B`("D9490IB0`1"0#``4D8___
+MK$````1A__TD0@`$KC(`F`P`@40"("`A/`2``P(@*"$,`';M)(2</`(@("$,
+M`($H`B`H(8^_``R/L@`(C[$`!(^P```#X``()[T`$">]__`!*A`AK[$`!`"`
+MB"&N)@`0)(0`&`"@,"&N)P`4KB(`#*XI``"N*@`$KBD`"`(@*"&OOP`,K[(`
+M"*^P```,`'?1`0"0(3P"@`*,149T)C``2#P&@`("`"`A),;1)`P`?@8"`#@A
+M/`.``I1D1E`D`@`$KA$`+"2%``&N(@`T)`(``:XB`#BN(``\KB``>*X@`'PF
+M(@"`I&5&4*8D`$0D`P`%)&/__ZQ````$8?_])$(`!*XR`)@,`(%$`B`@(3P$
+M@`,"("@A#`!V[22$G#P"("`A#`"!*`(@*"&/OP`,C[(`"(^Q``2/L````^``
+M"">]`!`GO?_PK[```"2#`$BOOP`$C&(`*`"`@"$40``4`&`H(3P$@`,"`"@A
+M#`!V[R2$G#R.`@`P4$```HX%`"".!0`LC@@`F(X)``"."@`$C@8`$(X'`!0,
+M`'(H`@`@(8^_``2/L````^``"">]`!`,`'W$C&0`"!``_^L\!(`#)[W_\*^P
+M````@(`A/`2``R2$G#ROOP`$#`!V[P(`*"$\`X`"C&)&5"1"``&L8D94/`*`
+M`HQ$1DR,@P"<$'``'CP"@`*,0D9,%&+_^P!@("$\`X`"C&)&5"1"__\00``2
+M`````*QB1E0F!`!(#`!^(*8``$2.!``8)@,`&!"#``>/OP`$C&(`!*R"``2,
+M8@`$K&,`!*Q$``"N`P`8C[````/@``@GO0`0#`!WA```("$0`/_M`````#P%
+M@`*.`@"<C*-&3!1P_^*L@@"<C@(`G!``_]^LHD9,)[W_\*^_``BOL0`$K[``
+M`#P"@`.,4)PT/!&``HXB1E0D0@`!KB)&5(X"`#0\!(`#)(2</!!``!("`"@A
+MC@(`-#1"``&N`@`TCB)&5"1"__\00``'```@(:XB1E2/OP`(C[$`!(^P```#
+MX``()[T`$`P`=X0`````$`#_^``````,`':J`````!``_^V.`@`T)[W_\*^P
+M``"OOP`(K[$`!`"`@"$\`X`"C&)&5"1"``&L8D94C((`-"0#__P`0Q@D,$(`
+M`Q!```LDD0`8K(,`-(XB``P`@"@A%$``&0!`("&.`@`T/`2``P(`*"$00``0
+M)(2</#P#@`*,8D94)$+__Q!```<``"`AK&)&5(^_``B/L0`$C[````/@``@G
+MO0`0#`!WA``````0`/_X``````P`=GL`````$`#_[@`````,`'=F`````!``
+M_^6N(``,)[W_\*^_````@#`A/`*``HQ#1E0D8P`!K$-&5(R#`#@D`@`!4&(`
+M$8R"`#008``")&+__ZR"`#@\`X`"C&)&5"1"__\00``%```@(:QB1E2/OP``
+M`^``"">]`!`,`'>$`````!``__H`````)`/_^P"`*"&L@``X`$,0)#P$@`,D
+MA)P\%$#_[*S"`#0,`'9[`````!``_^@`````)[W_\*^_````@#`A/`*``HQ#
+M1E0D8P`!K$-&5(R"`#@00``))`/_^XR"`#0`@"@AK(``.`!#$"0\!(`#)(2<
+M/!!```ZLP@`T/`.``HQB1E0D0O__$$``!0``("&L8D94C[\```/@``@GO0`0
+M#`!WA``````0`/_Z``````P`=GL`````$`#_\``````GO?_PK[\``#P"@`*,
+M0T94)&,``:Q#1E2,@P!X+&(`"!!```H``Q"`/`.``B1C%?``0Q`AC$(```!`
+M``@`````)`(`!*R"`'RL@`!X#`!RW@`````\`X`"C&)&5"1"__\00``%````
+M`*QB1E2/OP```^``"">]`!`,`'>$```@(1``__H`````)[W_\*^_``BOL0`$
+MK[```#P#@`.,<)PT/!&``HXB1E0D0@`!KB)&5(QBG#0D0P!(C&(`*!1``!$`
+M8"@AC@(`-#P$@`,D`P`0`@`H(1!#``,DA)P\#`!VJJX#`#2.)$94#`!WA```
+M``"/OP`(C[$`!(^P```#X``()[T`$`P`?<2,9``($`#_[HX"`#0GO?_PK[``
+M`*^_``0\`H`#C$*<-!""`#L`@(`A/`*``HQ#1E0D8P`!K$-&5`P`<S4"`"`A
+M)@4`2(RB`"@40``M`````(X#`'PD`@`&$&(`$`````".`P!X+&(`"!!```P`
+M`Q"`/`.``B1C%A``0Q`AC$(```!```@`````C@(`-!!``!,\!(`#)`(`$*X"
+M`#0,`'+>`@`@(3P#@`*,8D94)$+__Q!```8`````K&)&5(^_``2/L````^``
+M"">]`!`,`'>$```@(1``__D`````)(2</`P`=JH"`"@A$`#_ZR0"`!`D`@`&
+MK@(`?!``_^BN``!X#`!]Q(RD``@0`/_2C@,`?`P`<WH`````$`#_PP`````G
+MO?_@K[(`"*^P``"OOP`0K[,`#*^Q``0`@(`A`*"0(3P#@`*,8D94)$(``:QB
+M1E2,@@`T$$``1```F"$P0@`!4$``"3P$@`,DD0`8CC,`#!)@``0"8"`A#`!W
+M9@(`*"&N(``,/`2``R2$G#P,`';O`@`H(8X"`#!00``&KA(`((X"`"`"0A`J
+M$$```JX2`"RN$@`@/`*``R11G#P"("`A#`!V[0(`*"&.`@`T$$``(@(@("$P
+M0@`!$$``!CP"@`,28``$`F`@(0P`=T0"`"@A/`*``XQ"G#02`@`4)`,``0P`
+M=M$"`"`A/`.``HQB1E0D0O__$$``"0````"L8D94C[\`$(^S``R/L@`(C[$`
+M!(^P```#X``()[T`(`P`=X0``"`A$`#_]@`````\`H`#$`#_[:Q#G#@,`'9[
+M`@`H(1``_^0\`H`#/`2``R2$G#P,`':J`@`H(1``_\,\!(`#)[W_\#P"@`.O
+MOP``C$.<-`"`$"$\!(`#$$,`!"2$G!B/OP```^``"">]`!`,`'3F`````!``
+M__N/OP``)[W_\*^_``",I``L/`.``HQB1E0D0@`!K&)&5(R#`'@L8@`($$``
+M"@`#$(`\`X`")&,6,`!#$"&,0@```$``"``````D`@`'K((`?*R``'@,`'+>
+M`````#P#@`*,8D94)$+__Q!```4`````K&)&5(^_```#X``()[T`$`P`=X0`
+M`"`A$`#_^@`````0`/_N)`(``R>]__"OOP``/`.``XQBBW`D0@`!`$`@(0P`
+M:5BL8HMP$`#_^CP#@`,\`H`#)$*+>`""$",GO?_P``(10Z^P`````H!``@*`
+M(0`0$0`"`H`A`!`2``("@"$`$!0``@*`(0`0@",\`H`#)$*,&``02P`\!H`"
+M/`B``@$B2"$E"!90```X(20*$``DQM&X)`4`'Z^_``BOL0`$#`!QZP"`B"$\
+M!(`#`B`H(0(`,"$,`';@)(2</(^_``B/L0`$C[````/@``@GO0`0)[W_X"0"
+M.IBOLP`,K[(`"*^_`!"OL0`$K[````"@F"$0H@`8`("0(20".I@28@`(````
+M`(^_`!"/LP`,C[(`"(^Q``2/L````^``"">]`"`60/_X/`*``R1"BW@00/_U
+M)%``H#P"@`,D0HMX$@+_\280_V`,`'*$`@`@(1``__H\`H`#)`(``12"_^@D
+M`CJ8/`*``R11BW@``(`A#`!T>`(@("$F$/__)`+__Q8"__LF,0"@$`#_W20"
+M.I@GO?_P)`0``:^_```,`'2@)`4ZF(^_```#X``()[T`$">]__```"`AK[\`
+M``P`=*`D!3J8C[\```/@``@GO0`0`^``"``````\`H`")$+3?*R"```#X``(
+MK(``!">]__"OOP``C((`!(R#````8/@)`$`@(8^_```#X``()[T`$">]__"O
+MOP``/`*``XQ"G#0`@!@A`*`P(0!`("$,`'0Z`&`H(8^_```#X``()[T`$">]
+M__`D`B[@$*(`!*^_``"/OP```^``"">]`!`D`@`!5(+__(^_```\!(`##`!T
+MX22$G!@0`/_WC[\``">]__`D!``!K[\```P`=/LD!2[@C[\```/@``@GO0`0
+MK(``%*R%``"LA@`$K(@`"*R)``RLAP`0`^``"*R``!@GO?_PK[\```P`=:$`
+M````C[\```/@``@GO0`0)[W_\*^P```\$(`#C@*<+!1```6OOP`$C[\`!(^P
+M```#X``()[T`$$`(8````````0`@(3P!__\T(?_^`0%`)$"(8```````````
+M```````PA``!C@.<+(QB`!BN`IPLC&4`%*Q@`!1`"&```````#"$``$!!$`E
+M0(A@`````````````````(QB``R,9@`0`$#X"8QD``".`IPL%$#_XH^_``00
+M`/_>C[```">]__"OOP``#`!U(0````"/OP```^``"">]`!!`"&````````$`
+M*"$\`?__-"'__@$!0"1`B&``````````````````,*4``8R"`!0\!H`#)$(`
+M`:R"`!2,@P`4)`(``1!B``H`````0`A@```````PI0`!`05`)4"(8```````
+M``````/@``@`````C,*<+*R"`!@0`/_TK,2<+">]__`PA``"$(``!:^_```0
+MH``#`*`@(0P`=5,`````/`.``HQB1E0D0O__$$``!0``("&L8D94C[\```/@
+M``@GO0`0#`!WA``````0`/_Z`````(R#```\`H`")$(Q>``#&(``8B@AC*(`
+M`#P"@`(D0C)H`&(X(3P"@`(D0C'P`(`P(8RD````8A@A/`*``B1"MIA0@@`#
+MC,(`"`/@``@`````K*(``(S"`!"L8@``$`#_^JSF``",@P``/`*``B1",7@`
+M`QB``&(X(3P"@`(D0C)HC(4`"(SD````8C`A/`*``B1",?`0A0`#`&(8(0/@
+M``@`````/`*``B1"MIBLX@``K&```!``__FLP```/`2``XR"G"`40``1````
+M`$`(8````````0`8(3P!__\T(?_^`0%`)$"(8``````````````````P8P`!
+M/`*``ZQ#G"@D`P`!/`*``ZQ#G"2,@IP@)$(``0/@``BL@IP@/`*``XQ#G"`D
+M8___K$.<((Q"G"`40``,/`*``ZQ`G"0\`H`#C$*<*$`(8```````,$(``0$"
+M0"5`B&```````````````````^``"`````!`"&````````$`,"$\`?__-"'_
+M_@$!0"1`B&``````````````````,,8``22"__HD`P`!/`6@P`!#&`0L@@`&
+M$$``$S2E`!1``V``)`($``""$`0`0!`G`&(8)$"#8`````````````````!`
+M"&```````##&``$!!D`E0(A@`````````````^``"`````",H@``,$(``0`#
+M$`L0`/_SK*(``$`(8````````0`P(3P!__\T(?_^`0%`)$"(8```````````
+M```````PQ@`!)(+_^B0#``$\!:#``$,8!"R"``800``2-*4`%$`#8``D`@0`
+M`((0!`!B&"5`@V``````````````````0`A@```````PQ@`!`09`)4"(8```
+M``````````/@``@`````C*(```!#$"40`/_TK*(``"R"``8D!0`$`((H"T`#
+M:``D`@0``*(0!`!`$"<`8A@D0(-H`````````````^``"``````D`B[@$*(`
+M`R0"``$#X``(`````!2"__T\`H`#K$"<)!``__H`````)[W_\"0$``&OOP``
+M#`!V0"0%+N"/OP```^``"">]`!`GO?_P```@(:^_```,`'9`)`4NX(^_```#
+MX``()[T`$"0#``$\`H`"K$-&5"0%`!\D@P`$)*7__R0"__^L8```%*+__"1C
+M``0D`P`%/`*``ZR```"L0YPP)`,``3P"@`,#X``(K$.<.">]__"OOP`$K[``
+M``"`@"$,`&DQC(0````"$(`"`H`AC@,`!(^_``2/L```)&+_Z``#$`H#X``(
+M)[T`$">]_^"OL@`(K[$`!*^P``"OOP`0K[,`#(RS`"",HP`D`("`(0`3$(``
+MH)`A`&`@(11@`!X"`H@ACB(`!"9#`!@``"`A`'(@"R0#``$40``$`F,8!(X"
+M````0Q`EK@(``(XC``148``+C&(`!*XD``0,`';1`D`@(8^_`!"/LP`,C[(`
+M"(^Q``2/L````^``"">]`""L@P``K((`!(QB``2L9``$$`#_\JQ$```,`'=F
+M`````!``_^&.(@`$C*<`("2C`!@`!1@*``<0@`"","&,P@`$`&`H(1!B`!(D
+MR``$C&(``(QC``2L0P`$C*,`!*RE``2L8@``K*4``(T"```40``&)`(``8R#
+M````XA`$``(0)P!B&"2L@P```^``"`````!08/_VC0(``(QC``!09?_RK,``
+M!(RB``2L8@`$C*(`!*RE``2L0P``K*4``!``_^JLPP`$/`6``XRCG#2,@@`@
+MC&,`(`!#$"H40``%)`,``8RBG#2,0@`T$$```P`````\`H`#K$.<.`/@``@`
+M````/`*``R1"G#0`!C"``,(P(2>]__``H"`AK,4``*^_```,`',.`````(^_
+M```#X``()[T`$`/@``@``````^``"``````\`X`#C&*<,">]__"OOP``)$+_
+M_Q!```2L8IPPC[\```/@``@GO0`0#`!V_P`````0`/_[C[\``#P%@`.,HYPP
+M/`*``Q1@`!:,1)PTC((`-!1``!,\`H`#C(,`("1"G#P``QB``&(8(8QB``10
+M0``$C&,`!(Q"``"L8@`$C&,`!"1B_^@``Q`*$$0``R0#``$\`H`#K$.<."0"
+M``6LHIPP`^``"`````"LA0`(K(0`!`/@``BLA```)[W_\*^_```\`X`"C&)&
+M5"1"``&L8D94)(3_Z(R"`#040``1/`*``XR#`"`D0IP\``,8@`!B&"&,8@`$
+M4$``!(QC``2,0@``K&(`!(QC``0D8O_H``,0"A!$``HD`P`!/`*``ZQ#G#@\
+M`H`"C$1&5`P`=X0DA/__C[\```/@``@GO0`0)`,`!3P"@`,0`/_VK$.<,(R&
+M```DH@`8```8(13```0`11@+K(,```/@``BLI``DC,(`!*QF``"L8@`$C,(`
+M!*S#``00`/_XK$,``(R#```08``,)&+_Z(QE``!0HP`)K(```(QB``2LH@`$
+MC&(`!*QC``2L10``K&,``*R%```D8O_H``,0"E1```&L0``D`^``"`````"L
+MH``DC(,``"2B`!@`!1`*$$,`"@!`*"&,0@``C*,`!*Q#``2,HP`$K*4`!*QB
+M``"LI0```^``"``````00/_]`````(Q#```08@`)`````(Q"``2L8@`$C*(`
+M!*RE``2L0P``K*4```/@``BL@P```^``"*R````GO?_PK[$`!*^_``ROL@`(
+MK[````"`B"$6(``%/!*``SP"@`.,0IPL%$``+P````".4)PTC@(`-!1```0\
+M`H`#C$*<.!!``!,`````/`2``PP`=FPDA)P\$@(`"0!`("$\`X`#C&*<P"2$
+M``PF!0`,)$(``0P``OZL8IS`KE"<-"0"``4\`X`#K&*<,#P"@`.L0)PX%B``
+M$``````\`X`"K&!&5#P"@`.,0IPL$$``!8^_``R,8D94)$(``1``_]:L8D94
+MC[(`"(^Q``2/L````^``"">]`!`\`H`"K%%&5!``__B/OP`,#`!U3#P2@`,0
+M`/_/`````">]__"OOP``#`!WQ@`````\!(`#)[W_\*^_```,`'9L)(2</#P#
+M@`.L8)PX)$0`##P#@`,,``,/K&*<-">]__"OL````,`H(:^_``0,`'<;`("`
+M(:X``!BN```,K@``$(^_``2/L````^``"">]`!`GO?_PK[$`!*^_``ROL@`(
+MK[```(R2``@`@(@A`+(0*A1```<DA/_HC[\`#(^R``B/L0`$C[````/@``@G
+MO0`0CC``&`P`<^*N(``84@```:XR`!0D`@`!$`#_\ZXB`!@GO?_PK[\``(S"
+M```40``$`*`P(8^_```#X``()[T`$`P`=]Z,I0`@$`#_^X^_```GO?_PK[\`
+M`(R"`!``@#`A%$``"B2$_^B,P@`8$$``"(^_``",PP`4C,(`"*S``!@`0Q`J
+M%$``!`!@*"&/OP```^``"">]`!`,`'/B`````!``__N/OP``)[W_\*^_````
+MH#`A#`!WWHRE`""/OP```^``"">]`!`GO?_PK[\```P`=_8`````C[\```/@
+M``@GO0`0)[W_\*^_```,`'@"`````(^_```#X``()[T`$">]__"OOP``#`!W
+MW@``,"&/OP```^``"">]`!`GO?_PK[\```P`>`(`````C[\```/@``@GO0`0
+M)[W_\"0"*OBOL0`$K[```*^_``@`H(@A$*(`%@"`@"$D`BKX$B(`!@````"/
+MOP`(C[$`!(^P```#X``()[T`$!8`__H\`H`#)%&</"0"__P2(O_V)C``A"8B
+M``02`O_S)A#__`P`@6H"`"`A$`#_^R8B``0D`@`!5(+_ZB0"*O@\!(`##`!V
+M6B2$G#P0`/_E)`(J^">]__`D!``!K[\```P`>#PD!2KXC[\```/@``@GO0`0
+M)[W_\```("&OOP``#`!X/"0%*OB/OP```^``"">]`!"LA0```^``"*R```0G
+MO?_PK[$`!*^P``"OOP`,K[(`"#P"@`,`@(`AC%*<-"01``$\`X`"C&)&5"1"
+M``&L8D94C((``!!``!<\!(`#$B``!`````".`@``)$+__ZX"```\`X`"C&)&
+M5"1"__\00``)`````*QB1E0"(!`AC[\`#(^R``B/L0`$C[````/@``@GO0`0
+M#`!WA```("$0`/_V`````(R#G#0D`@`!K&(`>(R"G#0,`'*ZK$``?`)`*"$,
+M`'=$)@0`!#P"@`(,`'>$C$1&5(Y#`'PH8@`$%$``!BAD``94@``$``"((20"
+M``808@`(`````(X"```40/_3`````!8@_^<\!(`#$`#_U``````,`'-Z````
+M`!``__>.`@``)[W_X*^Q``2OOP`0K[,`#*^R``BOL```/`6``P"`B"&,LIPT
+M/`.``HQB1E0D0@`!K&)&5(RCG#0D`@`#``!`(0``2"&L8@!XC**<-*Q``'R,
+MI)PT#`!^-R2$`$B.0@!\CB,``!1@``,L4``!%@``(CP#@`,\`H`#C$*<-"1%
+M`$B,H@`H%$``&``````2```$`````(XB```D0O__KB(``#P#@`*,8D94)$+_
+M_Q!```H`````K&)&5`(`$"&/OP`0C[,`#(^R``B/L0`$C[````/@``@GO0`@
+M#`!WA```("$0`/_U``````P`?<2,I``($`#_Y@````",8IPT)!,``ZQ3`'B,
+M8IPT#`!RNJQ``'PF)``$#`!W1`)`*"$\`H`"#`!WA(Q$1E2.0P!\*&(`!A!`
+M``TD`@`&*&(`!%!```,``(`A4',``0``@"&.(@``%$#_R3P"@`,6`/_G/`.`
+M`Q``_\4`````5&+_^8XB```,`'-Z`````!``__6.(@``)[W_\*^P``"OOP`$
+M)!```3P"@`*,0T94)&,``:Q#1E2,@@``&$``$21#__^L@P``/`.``HQB1E0D
+M0O__$$``!P``("&L8D94`@`0(8^_``2/L````^``"">]`!`,`'>$`````!``
+M__@`````$`#_\```@"$GO?_PK[\`!*^P````@!@A/!"``HX"1E0D0@`!K@)&
+M5(R"``",A0`$)(0`!"1"``$4H``.K&(``(X"1E0D0O__$$``!@``("&N`D94
+MC[\`!(^P```#X``()[T`$`P`=X0`````$`#_^0`````,`'=3`````"0#``>L
+M0`!XK$,`?`P`<MX`0"`A$`#_ZP`````#X``(C((``"0"``&L@@`,K(``"*"`
+M```#X``(K(``!">]__"OOP``#`"!:B2$``B/OP```^``"">]`!`GO?_@K[,`
+M#*^Q``2OOP`0K[(`"*^P```\`H`#`("((8Q2G#0D$P`!/`.``HQB1E0D0@`!
+MK&)&5(R"``Q00``&CB,`#"9#`!B,8@`0)$(``:QB`!".(P`,)`(``E!B`%F.
+M)0`0DB(``!1``"X\`X`#4F``%HXB``PD`@`!KC(`!*(B```\`X`"C&)&5"1"
+M__\00``*`````*QB1E0"8!`AC[\`$(^S``R/L@`(C[$`!(^P```#X``()[T`
+M(`P`=X0``"`A$`#_]0````!00``&CB,`#"9#`!B,8@`0)$+__ZQB`!".(P`,
+M)`(``1!B``D`````CB,`#"0"``(48O_A``````P`>#4F1``8$`#_W0`````,
+M`'@G)D0`&!``__:.(P`,C&*<-"00``&L4`!XC&*<-`P`<KJL0`!\`D`H(0P`
+M=T0F)``(CB(`#!!0`!@"0"@A/`*``@P`=X2,1$94CD,`?"AB``040``&*&0`
+M!E2```0``)@A)`(`!A!B``@`````DB(``!!`_[D`````%F#_Y#P#@`,0`/_,
+MCB(`#`P`<WH`````$`#_]@````".)``$#`!X&"2$`!@0`/_F/`*``@P`>"XF
+M1``8$`#_I0`````GO?_PK[```*^_``0`@"@A)!```3P"@`*,0T94)&,``:Q#
+M1E20@@``5$``$```@"$\`H`#C$*<-(R#``R@L```)$8`&`#`("$08``$K*(`
+M!(S"`!`D0@`!K,(`$(RC``PD`@`"$&(`$``````\`X`"C&)&5"1"__\00``'
+M```@(:QB1E0"`!`AC[\`!(^P```#X``()[T`$`P`=X0`````$`#_^``````,
+M`'@NC*4`$!``_^X`````)[W_\*^P``"OOP`,K[(`"*^Q``0`@(`A/`*``HQ#
+M1E0D8P`!K$-&5(R"``@40``K))(`"(X"``Q00``'C@,`#(X#``0D8P`8C&(`
+M$"1"__^L8@`0C@,`#"0"``%08@`;C@0`!(X#``PD`@`"4&(`$XX$``2N```$
+MH@```#P#@`*,8D94)$+__Q!```@`````K&)&5(^_``R/L@`(C[$`!(^P```#
+MX``()[T`$`P`=X0``"`A$`#_]P`````,`'@U)(0`&!``_^RN```$#`!X)R2$
+M`!@0`/_DC@,`#`P`=U,"0"`AC@,`#`!`B"$D`@`!4&(`"(X%``0D`@`'KB(`
+M?*X@`'@,`'+>`B`@(1``_\J.`@`,)B0`&`P`>"`"0#`A$`#_]B0"``<GO?_P
+MK[\`!*^P```\`H`"C$9&6`"`*"$\`X`"C&)&5"1"``&L8D94#`!_-`#`("$,
+M`(',`$"`(0(`$"&/OP`$C[````/@``@GO0`0)[W_\*^_`````#`A$(``!`"`
+M*"$\`H`"#`"!?XQ$1EB/OP```^``"">]`!`GO?_````H(20&`"ROL``PK[\`
+M-`P`<*H`@(`A)`+__Z.B`"BOH@``KZ(`!*^B``BOH@`,KZ(`$*^B`!2OH@`8
+MKZ(`(*^B`"0\`H`"C$1&6*.@`!P\`X`"C&)&5"1"``&L8D94`Z`P(0P`@/4D
+M!0!>#`"!S`````"/H@`$7$```:X"``"/H@`(7$```:X"``2/H@`,7$```:X"
+M`!R/H@`07$```:X"`""/H@`87$```:X"`"@"`!`AC[\`-(^P`#`#X``()[T`
+M0">]__`T`K>8K[$`!*^P``"OOP`(`*"((1"B``\`@(`A-`*WF!(B``6/OP`(
+MC[$`!(^P```#X``()[T`$%8`__N/OP`(/`2``PP`@>4DA)S$$`#_]H^_``@\
+M!8`#)*6B(#P&@`0\!(`#)`(``0#%,",DA)S$%@+_Z@``."$,`(';`````!``
+M_^<T`K>8)[W_\"0$``&OOP``#`!ZIS0%MYB/OP```^``"">]`!`GO?_P```@
+M(:^_```,`'JG-`6WF(^_```#X``()[T`$)""``PPI?__``4:`C1"`("@@@`,
+M,$(`?Z"#``2@A0```^``"*""``PGO?_P/`6@P#P&__ROOP`$K[```#2E`"`0
+M@``;-,;__XR#```D`@`#-&,``P!@@"&L@P``C*,```!F&"2LHP``H@``!`P`
+M:^2B`@`,/`,;3C1C@;4`0P`9`@`@(0``$!```A."#`!ZV@!`*"$D`@`'H@(`
+M"(^_``2B```$C[````/@``@GO0`0/`*``A``_^0D1$9@$(``$#"E`/^,A```
+M`X`8(3P<@`,GG,:PD((`%#!"`"`00/_]`````*"%``"0@@`4,$(`(!!`__T`
+M`````^``"`!@X"$\`H`"$`#_[R1$1F`0@``,/`*``HR$`````!@AD((`%#!"
+M``$00``$`````)""```D`P`!H*(```/@``@`8!`A$`#_]"1$1F`GO?_@K[``
+M$*^_`!BOL0`4`("`(0.`B"$\'(`#)YS&L!"```T\`H`"`@`@(0P`>QT#H"@A
+M$$#__0(`("$"(.`ADZ(``(^_`!B/L0`4C[``$`/@``@GO0`@$`#_\R101F`G
+MO?_@K[(`"*^Q``2OL```K[\`$*^S``P`@(@A`*"0(0#`@"$#@)@A/!R``R><
+MQK`0@``5/`*``@(`$"$40``))A#__P)@X"&/OP`0C[,`#(^R``B/L0`$C[``
+M``/@``@GO0`@DD4```(@("$,`'L))E(``0(`$"$40/_Z)A#__Q``__``````
+M$`#_ZR111F`GO?_@K[(`"*^Q``2OL```K[\`$*^S``P`@(@A`*"0(0#`@"$#
+M@)@A/!R``R><QK`0@``5/`*``@(`$"$40``))A#__P)@X"&/OP`0C[,`#(^R
+M``B/L0`$C[````/@``@GO0`@#`![+`(@("$"`!@AHD(``"80__\48/_Z)E(`
+M`1``__``````$`#_ZR111F`GO?_@K[,`#*^Q``2OOP`0K[(`"*^P````@(@A
+M`*"8(0.`D"$\'(`#)YS&L!"``!X\`H`"CB,`!``#$(``0Q`A``*`0`(@("$,
+M`'L=`F`H(0!`&"$D!`!D%$``"B80__\D`O__$@(`!SP"@``D0@,`C$(`2`!`
+M^`D`````$`#_\@(@("$"0.`AC[\`$(^S``R/L@`(C[$`!(^P````8!`A`^``
+M"">]`"`0`/_B)%%&8">]_\"OL@`(K[\`$*^S``ROL0`$K[```*^F`"BOIP`L
+MKZ@`,*^I`#2OJ@`XKZL`/```D"$#@)@A/!R``R><QK`0@`!D/`*``BRB``@0
+M0``:/`.``@`%$(`D8Q9<`$,0(8Q"````0``(`````(R#```\`H`")`4``:Q%
+M1FR08@`$-%```:!P``2,D0`(*B(`!A!``!(\!*#`0`-@`"0"!``"(A`$`&(8
+M)4"#8``````````````````"8.`A`D`0(8^_`!"/LP`,C[(`"(^Q``2/L```
+M`^``"">]`$`TA``4C(,``"8B__H`11`$`&(8)1``__&L@P``C[``*`P`:^2,
+MD0````(1`@!0`!M2```!```!S9(C``0"("`AHB``!#!P`/\``!`2,$+__PP`
+M>MH`0"@AHC``!!``_]\`````C(,``#P"@`*,4D9LK$!&;)!B``0P4`#^H'``
+M!(R1``@J(@`&$$``"SP$H,!``V``)`($``(B$`0`0!`G`&(8)$"#8```````
+M`````!``_\H`````-(0`%(R%```F(__Z)`(``0!B$`0PHP`!```H(0!B*`H0
+M`/_`K(4``!``_[Z,D@`(C)(`!(^B`"@0`/^ZK((`!!``_YPD1$9@)[W_X*^P
+M`!"OOP`8K[$`%`"`,"$`H(`A``!`(0.`B"$\'(`#)YS&L!"``"8D!P`$C,0`
+M""B"``8`XB`*0`-H`"0"!```@A`$`$`0)P!B&"1`@V@`````````````````
+MC,8```.@("$D!0`!D,(`"#!#``X09P`+K@```"0"``P08@`(``````(@X"&/
+MOP`8C[$`%(^P`!`!`!`A`^``"">]`""0P@``#`!MEJ.B```00/_U)`@``20"
+M``$0`/_RK@(``#P"@`(0`/_9)$9&8">]__`\`H``K[(`"*^_``ROL0`$K[``
+M`"1"`P",0@`T`$#X"20$__\`0)`A/`*``HQ$1F@D`@`!/`6@P"2#__H`8A@$
+M*((`!A!``#,TI0`40`-@`"0"!```@A`$`$`0)P!B&"1`@V``````````````
+M````/!"``B801F`\$8``)C$#``P`>N0"`"`ACB(`-`!`^`D``"`ACB,`%#P"
+M@`(D0NT0K'```*QB``0\`H`")$+MH*QB``@\`H`")$+L)*QB``P\`H`")$+L
+ML*QB`!`\`H`")$+NX*QB`!0\`H`")$+PO*QB`!@\`H`")$+N,*QB`!R.(@`T
+M`$#X"0)`("&/OP`,C[(`"(^Q``2/L````^``"">]`!",H@``,$(``0`#$`NL
+MH@``$`#_TSP0@`(\`X`"C&)&<">]__`00``$K[\``(^_```#X``()[T`$"0"
+M``$,`'QCK&)&<!``__J/OP`````0(0``&"&LA0`0K(```*R"``@#X``(K(,`
+M#(R"```00``1`````(R#``!08``,C((``(QE``!0HP`(K(```(QB``2LH@`$
+MC&(`!*QC``2L10``K&,``*R%``",@@``5$#_\HR#```#X``(`````">]_]"O
+ML@`8)`+__R2R__^OL0`4K[\`(*^S`!ROL``0$D(`:P"`B"$\`X`"C&)&5"1"
+M``&L8D94CB0`"(XE``R.(P`0```0(0""("$`HR@A`*,P*P"&("$GLP`(KB0`
+M"*XE``P"8"`A`B`H(:^@```,`((1KZ``"(^P``@2```B`B`@(5(```R.`P`8
+MC@,``%!P``BOH``(C@(`!*QB``2.`@`$KA``!*Q#``"N$```KZ,`"(X#`!B.
+M(@`(`$,0*U1``&./HP``CB(`"%!B`%F.`P`<C@(`((X#`"0`0Q`E%$``1@(@
+M("&N```HC@(`#(X%`!``0/@)`@`@(8^P``@6`/_@`B`@(0P`@A$#H"@A/`.`
+M`HQB1E0D0O__$$``,P````"L8D94CZ(`"!!``!*/H@``CF,``%!@``R.8@``
+MC&0``%"#``BN8```C&(`!*R"``2,8@`$K&,`!*Q$``"L8P``KF0``(YB``!4
+M0/_RCF,``(^B```00``1`Z`H(8RC``!08``,C*(``(QD``!0@P`(K*```(QB
+M``2L@@`$C&(`!*QC``2L1```K&,``*RD``",H@``5$#_\HRC```F4O__)`+_
+M_Q9"_Y<`````C[\`((^S`!R/L@`8C[$`%(^P`!`#X``()[T`,`P`=X0``"`A
+M$`#_S`````".`@`8C@,`'(X&`"".!P`D`&<8(0!G0"L`1A`A`$@0(:X"`!BN
+M`P`<#`!]=@(`*"$0`/^PC@(`#(XB``P`0Q`K%$``!(^C``".(@`,$`#_HXX"
+M`"!48``#C&(`!!``_ZBOL```K@,``*X"``2,8@`$K'``!!``_Z*L4```)[W_
+M\*^Q``2OL```K[\`"`"`B"$`H(`A/`.``HQB1E0D0@`!K&)&5"0"``&LH@`H
+MC*,`&(R"``@`0Q`K5$``+8XC``",@@`(4&(`-(RC`!R.`@`,C@4`$`!`^`D"
+M`"`AC@(`((X#`"0`0Q`E4$``!:X``"B.`@`H%$``$0````"N```H/`.``HQB
+M1E0D0O__$$``!P````"L8D94C[\`"(^Q``2/L````^``"">]`!`,`'>$```@
+M(1``__@`````C@(`&(X#`!R.!@`@C@<`)`!G&"$`9R@K`$80(0!%$"&N`@`8
+MK@,`'`P`?ED"`"`ACB,``%1@``.,8@`$$`#_X:XP``"N`P``K@(`!(QB``2L
+M<``$$`#_VZQ0``",@@`,`$,0*U1`__..(P``C((`#!``_\B.`@`,)[W_\*^_
+M```\`H`"C$-&5"1C``&L0T94C((``!"B`!8`````C*(``(RC``2L0P`$C*,`
+M!*RE``2L8@``K*4``*R@`"@\`X`"C&)&5"1"__\00``%```@(:QB1E2/OP``
+M`^``"">]`!`,`'>$`````!``__H`````4*#_\JR@`"B,HP``4&7_[JR```",
+MH@`$K&(`!(RB``2LI0`$K$,``*RE```0`/_FK(,``">]_^"OI0``)`4``:^_
+M`!2OL``0KZ8`!`P`?+P`@(`ACZ(``(^_`!2N`@`4CZ(`!*X"`!B/L``0`^``
+M"">]`"`GO?_PK[\```P`?,,`````C[\```/@``@GO0`0```0(0``&"&LA0`(
+MK(8`#*R'`!"L@``HK(0`!*R$``"L@@`8K(,`'*R"`"`#X``(K(,`)```$"$`
+M`!@AK(4`"*R&``RLAP`0K(``**R$``2LA```K((`&*R#`!RL@@`@`^``"*R#
+M`"0GO?_PK[```*^_``2,@@`H`("`(11```T`@"@AC@,``!!P``>/OP`$C@(`
+M!*QB``2.`@`$KA``!*Q#``"N$```C[````/@``@GO0`0#`!]Q(R$``@0`/_R
+MC@,``">]_^"OM0`0K[0`#*^S``BOL@`$K[```*^_`!2,@@`H`("`(0"`*"$`
+MP)`A`."8(0$`H"$40``0`2"H(8X$``BN$@`8KA,`'*X4`""N%0`D#`!]=@(`
+M*"&/OP`4C[4`$(^T``R/LP`(C[(`!(^P```#X``()[T`(`P`?<2,A``($`#_
+M[XX$``@GO?_@K[(`"*^_`!2OM0`0K[0`#*^Q``2OL```C((`((R*`"0`0%@A
+M`$H0)1!``!H`@)`AC((`"(R0`"",D0`DC)0`&(R5`!R,0P`,C$(`"`(`,"$`
+M<1@A`'$@*P!0$"$`1!`A`%1`(P!U("L!!$`C`'5((R4E__\LHO__)03__P""
+M("$!:!`K%$``#0(@."$1:``)`4D0*X^_`!2/M0`0C[0`#(^R``B/L0`$C[``
+M``/@``@GO0`@4$#_^(^_`!0,``-$``````(C`!D``"`0```H$@*E."$`````
+M`(``$W(B````Y1`K`.`H(7!P`````"`2`H0P(0#","$`P"`AKD0`&*Y%`!P0
+M`/_DC[\`%">]_^`\`H`"K[\`%*^P`!`D0T9XC&,`!(Q"1G@`@(`A`&`P(0!`
+M*"&OHP`$#`!][Z^B```\"(`"/`F``B8$`!PE"/LD)2G[="0%``4D!@`!#`!U
+M$@(`."$,`&OO`````#P#@`*L8D?<0(!(`````````````````$""6```````
+M```````````,`'6()@0`'`P`=@PD!``%/`*``JQ01G2/OP`4C[``$`/@``@G
+MO0`@)[W_\*^_```,`&OO`````#P#@`*L8D?<0(!(`````````````````$""
+M6``````````````````,`'8S)`0`!8^_```D`@`#`^``"">]`!`GO?_PK[\`
+M``P`?-@`P"`A/`2``PP`=O$DA)P\C[\```/@``@GO0`0)[W_\"0"-K"OL0`$
+MK[```*^_``@`H(@A$*(`$0"`@"$D`C:P$B(`!CP"@`./OP`(C[$`!(^P```#
+MX``()[T`$!8`__HD4:#8#`!U&B8D`!P,`'W_`B`@(1``__6/OP`()`(``52"
+M_^\D`C:P/`2``PP`?ITDA*#8$`#_ZB0"-K`GO?_P)`0``:^_```,`'[G)`4V
+ML(^_```#X``()[T`$">]__```"`AK[\```P`?N<D!3:PC[\```/@``@GO0`0
+MK(4``*R&``2L@``,K(``"```0"$`@#@A)0@``23B``@M`P"`K.(`$*SB`!04
+M8/_Z`$`X(3"C``=08``#```8(20"``@`0Q@C)&(`$`#"$"M00``#C((`!`/@
+M``BL@````*,8(:R#`!`T0@`!`^``"*QB``2,@@```(!@(1!``!T``%@A!*``
+M&P`````DI0`+**(`%U1```,D!0`0)`+_^`"B*"0LH@'X$$``\``%&D(`K!`A
+M)$D`"(TG``P0Z0`/``58PHSC``0D`O_^C.H`#`!B0"0`Z!@AC&(`!(SI``@D
+MZP`(-$(``:U)``BL8@`$K2H`#`/@``@!8!`A)$D`$(TG``Q4Z?_PC.,`!"5K
+M``*-AP`8)8X`$!#N`"XD`__^C.(`!`!#0"0!!3`C*,(`$%1```ZMC@`<`.5`
+M(32B``$!!A@A-,0``23K``BLX@`$K8@`&*QF``"M!``$K0X`"*V(`!P0`/_C
+MK0X`#`3```>MC@`8`.@8(8QB``0DZP`(-$(``1``_]NL8@`$+0("`!!``((`
+M"!I"``@@P@`$$,`!@A`A)$H`"(V#``R-20`(``0@@B0"``$`@A`$`&(8):V#
+M``RLZ@`,K.D`"*TG``RM1P`(*6,``"5B``,!8Q`*C88`#``"$(,D`P`!`$,@
+M!`#$$"M40``[C80`$`"&$"040``,``L0P``$($`D`O_\`6(0)`"&&"048``%
+M)$L`!``$($``AA`D$$#__25K``0`"Q#``8(0(21)``@!8&@A`2!0(8U'``Q0
+MZ@`.)6L``8SB``0D`__^`$-`)`$%,",HP@`04$``/XSI``@$PP`U`.@8(8SG
+M``Q4ZO_WC.(`!"5K``$Q8@`#%$#_[B5*``@QH@`#)2G_^!!``"4EK?__C2(`
+M"!!)__LQH@`#C8,`#``$($``9!`K5$``"HV$`!`0@``'`(,0)%1`_]H`"Q#`
+M``0@0`"#$"00`/_[)6L`!(V$`!`D`__^C((`!`!#$"0`11@K%&``!`!%,",H
+MP@`04$```P"`."$0`/]Z``!8(33#``$`A2`A-*(``:SB``2MA``0K(,`!!``
+M_W(DZP`(C8(`#``$&"<`0Q`D$`#_VZV"``R,8@`$C.H`#(SI``@T0@`!).L`
+M"*QB``00`/]DK4D`"(SJ``P`Y4`A-*(``0$&&"$TQ``!K4D`"*SB``2MB``8
+M).L`"*QF``"M!``$K0X`"!``_W*M*@`,$&``!@`((,(L8@`%$$``'BQB`!4`
+M"!&")$0`.``$$,`!@A`A)$H`"(U)``@1*@`1)(,``XTB``0D`__^`$,0)`$"
+M$"M00/]XC2H`#(TI``@1*@`&)`/__HTB``0`0Q`D`0(0*U1`__J-*0`($`#_
+M;HTJ``PH@@```&(@"XV#``P0`/]E``0@@Q1`_^0D9`!;+&(`51!```0L8@%5
+M``@3`A``_]XD1`!N$$``!"QB!54`"!/"$`#_V21$`'=00/_7)`0`?@`(%((0
+M`/_4)$0`?!!@``8`!5C"+&(`!1!``!TL8@`5``41@B1+`#@`"Q#``8(0(21*
+M``B-1P`,4.K_'25K``&,X@`$)`/__@!#0"0!!3`C*,(`$%!```8E:___!,,`
+M!@#H&"&,YP`,5.K_]XSB``00`/\/)6L``8QB``2,Z@`,C.D`"#1"``$0`/[_
+M).L`"!1`_^4D:P!;+&(`51!```0L8@%5``43`A``_]\D2P!N$$``!"QB!54`
+M!1/"$`#_VB1+`'=00/_8)`L`?@`%%((0`/_5)$L`?`"`6"$0H`!````8(22I
+M__B-)@`$)`+__HR$`!``PD`D`2A0(8U#``011`!U`&(8)#C"``$P0@`!K4,`
+M!!!```H``&`AC*7_^"5B`!`!)4@CC20`"!""`&@!!4`AC2<`#*SD``BLAP`,
+M`4,0(9!"``<X0@`!,$(``1!```PU`@`!%8``!0$#0"&-0P`()6(`$%!B`%0D
+M#``!C48`"(U'``RLY@`(K,<`##4"``$!*!@AK2(`!!6``!.L:```+0("`%!`
+M`!,`"!I"``@@P@`$$,`!8A`A)$<`"(UC``R,Y@`(``0@@B0"``$`@A`$`&(8
+M):UC``RM)P`,K28`"*S)``RLZ0`()`,``0/@``@`8!`A$&``!@`((,(L8@`%
+M$$``'RQB`!4`"!&")$0`.``$$,`!8A`A)$<`"(SF``@0QP`2)(,``XS"``0D
+M`__^`$,0)`$"$"M00/_GC,<`#(S&``A0Q__DC,<`#(S"``0D`__^`$,0)`$"
+M$"M40/_YC,8`"!``_]R,QP`,*((```!B(`N-8P`,$`#_TP`$((,40/_C)&0`
+M6RQB`%400``$+&(!50`($P(0`/_=)$0`;A!```0L8@55``@3PA``_]@D1`!W
+M4$#_UB0$`'X`"!2"$`#_TR1$`'RM:0`<K6D`&*TC``P0`/^MK2,`"!``_YLD
+M#``!.,(``3!"``$00``(`0-`(8RE__@!)4@CC2<`#(TF``@!!4`AK.8`"*S'
+M``PU`@`!)`,``:UI`!`0`/^SK2(`!#"E__\PH@!<4$``*(R"``",@@`0)(@`
+M$"0,`'Z,0P`$)`+__@!B2"0I(@`0.$L``0$@4"&-!P`,4.@`"R6,__^,X@`$
+M)`/__HSG``P`0Q`D`4(8*@!#4`L!(D@A%.C_^"5K``$EC/__!8'_\B4(``@P
+MH@`(4$``!20"__B,@@`$`$D0(ZS"``PD`O_X`4(8)`$B$"0D0O_L)&/_[*S"
+M`!"LRP`(K,,`&(R"``"LP@``K,(`((R#``0D`@`8H,(`**S#``0#X``(K,,`
+M)(R"``PD`__P/`H1$21)_\@!(T@D)2+_6`!#,"0``$`A`,`X(0%($"4E"``!
+M*0,`(*SB```48/_[).<`!#P#@`(D8\=<)`(``:S%`!"LR0!XK,,`D*S"`(RL
+MR0!TK,``A*S``("LPP!\`^``"*R&``PGO?_PK[\``#P#@`*,8D94)$(``:QB
+M1E0\`H`"C$)&3!1``!$`0!@AK(0`G#P"@`*L1$9,/`.``HQB1E0D0O__$$``
+M!0````"L8D94C[\```/@``@GO0`0#`!WA```("$0`/_Z`````!"#__`\`H`"
+MC$)&3(QC`)P48O_[`````!"#_^L\`H`"C&(`G*R"`)P0`/_FK&0`G(R"```0
+M0``1`````(R#``!08``,C((``(QE``!0HP`(K(```(QB``2LH@`$C&(`!*QC
+M``2L10``K&,``*R%``",@@``5$#_\HR#```#X``(`````">]_]"OL@`8K[\`
+M**^U`"2OM``@K[,`'*^Q`!2OL``0`("0(3P"@`*,0T94)&,``0P`@&6L0T94
+M`$"H(8Y"!!`00``:)E0$$*^@```,`'=3`H`@(8Q3`$`"0"`A`$"`(0P`?S2.
+M90```$"((0(`("$00``L`@`H(20"``>N`@!\#`!RWJX``'BN<0`$CD($$%1`
+M_^XF5`00CZ(``!1``!<`````#`"!:@.@("$\`X`"C&)&5"1"__\00``,````
+M`*QB1E0"H!`AC[\`*(^U`"2/M``@C[,`'(^R`!B/L0`4C[``$`/@``@GO0`P
+M#`!WA```("$0`/_S``````P`=U,#H"`A`$`H(0P`=T0"@"`ACZ(``!1`__D`
+M````$`#_X0`````,`'=$`Z`@(1``_]B.0@00)[W_\*^_```\`X`"C&)&5"1"
+M__\00``%```@(:QB1E2/OP```^``"">]`!`,`'>$`````!``__H`````)[W_
+M\*^P``"OOP`$#`!_%P"`@"&N``00C[\`!(^P```#X``()[T`$">]__"OL```
+MK[\`#*^R``BOL0`$`("`(3P"@`*,0T94)&,``:Q#1E2,@@00))($$!1``!,"
+M0(@A/`.``HQB1E0D0O__$$``"@````"L8D94#`"!:@)`("&/OP`,C[(`"(^Q
+M``2/L````^``"">]`!`,`'>$```@(1``__4`````#`!W4P(@("$D`P`%K$,`
+M?*Q``'@,`'+>`$`@(8X"!!`40/_W`````!``_^,`````C*<``!#@``8`@!@A
+MC(8``%3```6,X@`$K(<``*R@```#X``(`````(S$``2LP@`$C&,``*SD``2L
+M0P``$`#_]ZR'``!-96UO<GD@=7-E9#H@)60@1G)E93H@)60@"@H`6T)U9F9E
+M<B!S:7IE(%1X.B`E9"`@4G@Z("5D70H*``!405)'7W=D8U1X37-G1&ES<&%T
+M8VA,;V]P````@`!&?(``1JR``$;$@`!&K(``1JR``$:L@`!&K(``1O2``$:L
+M@`!&K(``1JR``$:L@`!&K(``1JR``$:L@`!&K(``1JR``$:L@`!&K(``1JR`
+M`$:L@`!&K(``1JR``$<4@`!')&%R0V]M<&QE=&5,;V]P``!405)'7W=D8T%S
+M>6YC179T1&ES<&%T8VA,;V]P`````%1A<F=E="!S=&%R=&5D"@"``%>0@`!8
+M*(``6%2``%AH@`!9%(``68R``%H@@`!:/(``6G"``%J$@`!:F(``6JR``%L(
+M@`!;6(``5^"``%N8@`!7X(``5^"``%?@@`!7X(``5^"``%NP@`!;V(``6_R`
+M`%PT@`!<E(``702``%TL@`!=/(``76"``%[$@`!7X(``7SR``%]@@`!?[(``
+M8""``&!,@`!@7(``8'2``&&D@`!B4(``5^"``&)@@`!BF(``8JB``%?@@`!B
+MS(``5^"``%?@@`!B](``8RR``&-D@`!CA(``5^"``&0\@`!D3(``9'"``&5(
+M@`!E^(``5^"``%?@@`!7X(``5^"``%?@@`!7X(``5^"``&8P5$%21U]W9&-#
+M=')L37-G1&ES<&%T8VA,;V]P`$%#22`D260Z("\O9&5P;W0O<W<O8G)A;F-H
+M97,O,2XU55-"1&5V+W-R8R]H86PO:&%L36ES8RYC(S$U("0```"``'=L@`!W
+M;(``=VR``'=L@`!W;(``=VR``'=L@`!W;(``=VR``'=L@`!W;(``=VR``'=L
+M@`!W;(``=VR``'=L@`!W?(``=Y"``'>D@`!X`"1)9#H@+R]D97!O="]S=R]B
+M<F%N8VAE<R\Q+C554T)$978O<W)C+VAA;"]A<C4R,3(O87(U,C$R071T86-H
+M+F,C,3<@)```````@````)@@55555:JJJJIF9F9FF9F9F21)9#H@+R]D97!O
+M="]S=R]B<F%N8VAE<R\Q+C554T)$978O<W)C+VAA;"]A<C4R,3(O87(U,C$R
+M2V5Y0V%C:&4N8R,W("0``(``L'"``*>L@`"G?(``L+B``*>L@`"GK(``IZR`
+M`*>L@`"GK(``IZR``*>L@`"GK(``IZR``*>L@`"GK(``IZR``+#<@`"P[(``
+MIZR``*>L@`"GK(``IZR``*>L@`"GK(``IZR``*>L@`"GK(``IZR``*>L@`"G
+MK(``IZR``*>L@`"P["1)9#H@+R]D97!O="]S=R]B<F%N8VAE<R\Q+C554T)$
+M978O<W)C+VAA;"]A<C4R,3(O87(U,C$R36ES8RYC(S(P("0`@`"Z-(``NC2`
+M`+M$@`"[;(``N\`N+B\N+B\N+B\N+B\N+B]H86PO87(U,C$R+V%R-3(Q,DUI
+M<V,N8P``(2`E+3,P<SH@)2TR,',Z)2TU9"!%0T]37TY/5$1/3D4*````87(U
+M,C$R27-(=T-I<&AE<E-U<'!O<G1E9````/___\G____"____\O____3____`
+M____NO___[+___^P````?P```#(```!_````*````'\```!-````?P```$``
+M```?````$````#\````P````"`````8`````````!`````@````"````!```
+M``8````(````"@````P````.````$(``Q8R``,:\@`#(K(``R0"``,EH)$ED
+M.B`O+V1E<&]T+W-W+V)R86YC:&5S+S$N-5530D1E=B]S<F,O:&%L+V%R-3(Q
+M,B]A<C4R,3)0;W=E<BYC(S4@)`"``-14@`#4[(``T]B``-5(@`#6#"1)9#H@
+M+R]D97!O="]S=R]B<F%N8VAE<R\Q+C554T)$978O<W)C+VAA;"]A<C4R,3(O
+M87(U,C$R4F5C96EV92YC(S@@)````(``V&2``-DT@`#9N(``V?R``-IP)$ED
+M.B`O+V1E<&]T+W-W+V)R86YC:&5S+S$N-5530D1E=B]S<F,O:&%L+V%R-3(Q
+M,B]A<C4R,3)297-E="YC(S$U("0`````(#9M8B!/1D1-````(#EM8B!/1D1-
+M````,3)M8B!/1D1-````,3AM8B!/1D1-````,C1M8B!/1D1-````,S9M8B!/
+M1D1-````-#AM8B!/1D1-````-31M8B!/1D1-````,4P@("!#0TL@````,DP@
+M("!#0TL@````,E,@("!#0TL@````-2XU3"!#0TL@````-2XU4R!#0TL@````
+M,3%,("!#0TL@````,3%3("!#0TL@````6%(@("`@("`@````@`(.O(`"#LB`
+M`@[4@`(.X(`"#NR``@[X@`(/!(`"#Q"``@\<@`(/*(`"#S2``@]`@`(/3(`"
+M#UB``@]D@`(/<(`!)_B``2@`@`$H"(`!*!"``2@0@`$H&(`!*""``4&@@`%!
+MS(`!0=2``4'<@`%!Y(`!0>R``4'T@`%!_(`!0@2``4(0@`%"&(`!0B2``4(P
+M@`%"/(`!0DB``4)4@`%"8(`!0FR``4)X@`%"A(`!0I"``4*<@`%"J(`!0K2`
+M`4+`@`%"X(`!0NR``4+X@`%#!(`!0Q"``4,<@`%#*(`!0S2``4-`@`%#3(`!
+M0UB``4-D@`%#<"XN+RXN+RXN+RXN+RXN+VAA;"]W9&,O=&%R9V5T+W-R8R]A
+M<D-O;FXN8P``)7,Z)60@4F5S971T:6YG(%)E=')Y(%%U975E(0H```"``5QL
+M@`%<I(`!7*R``5RX@`%<P(`!7'B``5QX@`%<R(`!7-"``5S8@`%<X(`!7'B`
+M`5SH@`%<\(`!7/B``5T`@`%<>(`!7'B``5T(@`%<>(`!71R``5V`@`%=B(`!
+M79"``5V8@`%=H(`!7:B``5VP@`%<>(`!7;B``5W$@`%=T(`!7=B``5WT@`%@
+MY(`!8B2``6'`@`%AS(`!8B2``6'4@`%AW(`!8>2``6'L@`%A](`!8?R``6(<
+M@`%B)(`!8BR``6)(55-".B5S(%LE9%T*`````'9E;F1O<E)E<V5T`(`!>IB`
+M`7JT@`%Z4(`!>M"``7I0@`%Z[(`!>PB``7LD@`%[0(`!>UR``7NX@`%[U(`!
+M>_!/=F5R:61E(#H@)60@96X@.B`E9`H```!#;VYF:6<@.B`E>`H`````@`&*
+MZ(`!BO"``8L4@`&+'(`!BR2``8LL@`&+L(`!B[2``8O8@`&+\(`!B_B``8P`
+M@`&,"$4*```P,3(S-#4V-S@Y04)#1$5&`````#`Q,C,T-38W.#D``#`Q,C,T
+M-38W.#EA8F-D968`````/$YO="!A('-T<FEN9SH@,'@````^````/&YU;&P^
+M```\0F%D(&9O<FUA="!S=')I;F<Z(``````@.@``/@H``(`!O0R``;U0@`&]
+M#(`!O5"``;U0@`&]4(`!O5"``;U0@`&]4(`!O5"``;U0@`&]4(`!O5"``;U0
+M@`&]4(`!O5"``;U0@`&]4(`!O5"``;T,@`&]4(`!O5"``;T,@`&]4(`!O5"`
+M`;U0@`&]4(`!O5"``;U0@`&]4(`!O5"``;U0@`&]#(`!O5"``;T,@`&]4(`!
+MO5"``;U0@`&]4(`!O5"``;U0@`&]4(`!O5"``;U0@`&]4(`!O5"``;T,@`&]
+M4(`!O5"``;U0@`&]4(`!O0R``;U0@`&]4(`!O0R``;]0@`'`C(`!P(R``<",
+M@`'`C(`!P(R``<",@`'`C(`!P(R``<",@`'`C(`!P(R``<",@`'`C(`!P(R`
+M`<",@`'`C(`!P(R``<",@`'`C(`!P(R``<",@`'`C(`!P(R``<",@`'`C(`!
+MP(R``<",@`'`C(`!OV2``;_D@`&]I(`!P(R``<",@`'`C(`!P(R``<",@`'`
+MC(`!P(R``<",@`'`C(`!P(R``<",@`'`C(`!P(R``<",@`'`!(`!P(R``;VD
+M@`'`C(`!P(R``;VD@`'`C(`!P(R``<",@`'`C(`!P(R``<",@`'`C(`!P(R`
+M`<",@`&_9(`!O^2``;VD@`'`C(`!P(R``<",@`'`C(`!P(R``<",@`'`C(`!
+MP(R``<",@`'`C(`!P(R``;U\@`'`C(`!P(R``<`$@`'`C(`!O:2``<",@`'`
+MC(`!O:2``;W4@`&]^(`!O?B``;WX@`&]^(`!O?B``;WX@`&]^(`!O?B``;WX
+M@`&]^(`!O?B``;WX@`&]^(`!O?B``;WX@`&]^(`!O=2``;WX@`&]^(`!ORB`
+M`;WX@`&]^(`!O?B``;WX@`&]^(`!O?B``;WX@`&]^(`!O?B``;WX@`&]^(`!
+MO=2``;WX@`&]^(`!O?B``;WX@`&]^(`!O?B``;WX@`&]^(`!O?B``;WX@`&]
+M^(`!OT2``;WX@`&]^(`!O?B``;WX@`&]U(`!O?B``;WX@`&_1"4P.%@Z(```
+M)3`R6"`````@````('P``"5C``!\"@``("`@`"4P.%@@````"@```"`@("`@
+M("`@(````"4P-%@@````("`@("````"``<VT@`'-H(`!S:"``<V@@`'-M(`!
+MS;2``<VT@`'-M(`!SO"``<]8@`'/6(`!SUB``<\,@`'/#(`!SPR``<\,@`'1
+M?(`!T7R``=%H@`'1L(`!T7R``=%\@`'1?(`!T7Q)9&QE(%1H<F5A9`"``>_8
+M@`'OF(`![YB``>^8@`'P((`![TR``?"<@`'PI``!`@(#`P,#!`0$!`0$!`0%
+M!04%!04%!04%!04%!04%!@8&!@8&!@8&!@8&!@8&!@8&!@8&!@8&!@8&!@8&
+M!@8'!P<'!P<'!P<'!P<'!P<'!P<'!P<'!P<'!P<'!P<'!P<'!P<'!P<'!P<'
+M!P<'!P<'!P<'!P<'!P<'!P<'!P<'"`@("`@("`@("`@("`@("`@("`@("`@(
+M"`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(
+M"`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@("`@(
+M"`@("`@("`@("`@("`@);`F/";0```D("6P)M```````!0`*`!0`'@`R`$8`
+M50!:`%\`9```````"@`4`!X`*``R`#P`1@!0`%H`9```````,```@!4``(`5
+M``"`%0``@!4``(`5```00``O_`\`+_P/`"_\'P`O_`\`+_P/```01``O_`\`
+M+_P/`"_\'P`O_`\`+_P/```02``O_`\`+_P/`"_\'P`O_`\`+_P/```03``O
+M_`\`+_P/`"_\'P`O_`\`+_P/```04``O_`\`+_P/`"_\'P`O_`\`+_P/```0
+M5``O_`\`+_P/`"_\'P`O_`\`+_P/```06``O_`\`+_P/`"_\'P`O_`\`+_P/
+M```07``O_`\`+_P/`"_\'P`O_`\`+_P/```08``O_`\`+_P/`"_\'P`O_`\`
+M+_P/```09``O_`\`+_P/`"_\'P`O_`\`+_P/```0,````C````'@````L```
+M`6````'@```0<````6@```'@```!N````8P```'@```0L```#F```!&````?
+M'```/C@``!&````0\```H.```4!H``!8@```L.```4!H``"`%`/H`^@&X`;@
+M!"`$(`A`"$`&X`;@``"`'!*-DZ<)B!//!.`3E1+@$ZL)B!//``"8!```````
+M```#```````````````#``"8(`("`@`"`@(``@$"``("`@`"`@(```"8)```
+M#@X```X.```'!P``#@X```X.``"8*`H"``$*`@`!!0(!``H"``$*`@`!``"8
+M-```#@X```X.```.#@``#@X```X.``"8.`````<````'````"P````L````+
+M``"81!-R%AP3<APE$W(7*!-R%J(3<APE``"82``8VFT`&-IM`!C*=0`8RG4`
+M&,IU``"84`WHM.`-Z+3@#>BTX`WHM.`-Z+3@``"86'Z`#2Y^@`TN?N@-+G[H
+M#2Y^@`TN``"87#$W9EXQ-V9>,3=F7C$W9EXQ-V9>``"88```G1```)T0``"=
+M&```G1@``)T0``"89``!S@```<X```'.```!S@```<X```"8:$":09!`FD&0
+M0)I!D$":09!`FD&0``"8;`4,L($%#+"!!0RP@04,L($%#+"!``"9%```!]``
+M``?0```$3```")@```?0``"9&````;@```&X````A````0@```&X``"9)!`%
+MB@40!8H%$`6*!1`%B@40!8H%``"91/>X$"#WN!`@][@-$/>X$!#WN!`0``"B
+M!```````````````"`````@````(``"B"-:^1XC6OD>(T#Y'B-`^1XC0/D>(
+M``"B#&0L`4!D+`%`9$+!8&1"P6!D0L%@``"B'!B#@`H8@X`*&&.`"AB#@`H8
+M@X`*``"B,````````````````````0@`````````#``````````T````!0``
+M`$``````````1`````@```!(````"````$P````0````4`````````!4````
+M'P``"``````````(!`````````@(````````"`P````````($`````````@4
+M````````"!@````````('`````````@@````````""0````````2,```````
+M`!)P````````$#@````````0>````````!"X````````$/@````````1.```
+M`````!%X````````$;@````````1^````````!(X````````$G@````````2
+MN````````!+X````````$S@````````3>````````!.X````````$_@`````
+M```4.````````!1X````````%+@````````4^````````!4X````````%7@`
+M```````5N````````!7X````````%C@````````6>````````!:X````````
+M%O@````````7.````````!=X````````%[@````````7^````````!`\````
+M````$'P````````0O````````!#\````````$3P````````1?````````!&\
+M````````$?P````````2/````````!)\````````$KP````````2_```````
+M`!,\````````$WP````````3O````````!/\````````%#P````````4?```
+M`````(`$````````@`@```````"`#````````(`8````````@"````````"`
+M)````````(`H````,```@"P`!___``"`,`'___\``(`T````,0``@#@`````
+M``"`/````````(!(````````@%0```````"`6````````(!<___'_P``@&``
+M```/``"`@````````("$````````@(@```````"`C````````("0````````
+M@)0```````"`F````````(#`*H(P&@``@,0%W`'@``"`R!]`)Q```(#,`?0`
+M````@-```!X<``"`U``"JJH``(#8`@!550``@-P```````"`X/____\``(#D
+M``#__P``@.@```````"`[````````(#P````````@/0```````"`^```````
+M`(#\````B```AP````````"'!````(P``(<(````Y```APP```+5``"'$```
+M`````(<4````````AQ@```"@``"''````<D``(<@````+```AR0````L``"'
+M*````#```(<L````/```AS`````L``"'-````"P``(<X````,```ASP````\
+M``"'0````````(=$````````AT@```````"'3````````(=0````````AU0`
+M``````"'6````````(=<````````AV````#5``"'9````-\``(=H```!`@``
+MAVP```$Z``"'<````'4``(=T````?P``AW@```"B``"'?````````($```$`
+M`@``@00````!``"!"````,```($,````````@1````%H``"!%````````(%`
+M@``"J```@40```````"'P`,"`0```(?$!P8%!```A\@+"@D(``"'S`\.#0P`
+M`(?0$Q(1$```A]07%A44``"'V!L:&1@``(?<'QX='```A^`#`@$```"'Y`<&
+M!00``(?H"PH)"```A^P/#@T,``"'\!,2$1```(?T%Q85%```A_@;&AD8``"'
+M_!\>'1P``)@(````````F`RMA(X9``"8$'THX````)@4G`J?:P``F!P`````
+M``"8+``"H`(``)@\``(!````F$`@:@%Z``"83!*$(SP``)A4```(60``F0``
+M``````"9!````````)D(````````F0P`@`````"9$`````$``)D<```,@```
+MF2`%$`````"9*`````$``)DL````!```F3```$B"``"9-!X?("(``)DX"@L,
+M#0``F3P````_``"90`````0``)E(DH"R$@``F51=4.&(``"96````/\``)E<
+M`$MJC@``F6@```/.``"9<!DOM14``)ET````````F7@````!``"9?```````
+M`)F`````````F80"@`````"9H````````)G@````````F>2JJJJJ``"9Z#Q&
+M9'@``)GL````J@``HA``@&,S``"B%``0;!```*(8`)Q`8```HB`!B##&``"B
+M)```!````*(H```)M0``HBP```````"B-"`@("```*(X("`@(```HCP3R(FO
+M``"B0#A)"B```*)$``![M@``HD@/_S_\``"B3````````*)0````````HE0`
+M``````";`````````)L$`````0``FP@````"``";#`````,``)L0````!```
+MFQ0````%``";&`````@``)L<````"0``FR`````*``";)`````L``)LH````
+M#```FRP````-``";,````!```)LT````$0``FS@````2``";/````!,``)M`
+M````%```FT0````5``";2````!@``)M,````&0``FU`````:``";5````!L`
+M`)M8````'```FUP````=``";8````"```)MD````(0``FV@````B``";;```
+M`",``)MP````)```FW0````E``";>````"@``)M\````*0``FX`````J``";
+MA````"L``)N(````+```FXP````M``";D````#```)N4````,0``FY@````R
+M``";G````#,``)N@````-```FZ0````U``";J````#4``)NL````-0``F[``
+M```U``";M````#4``)NX````-0``F[P````U``";P````#4``)O$````-0``
+MF\@````U``";S````#4``)O0````-0``F]0````U``";V````#4``)O<````
+M-0``F^`````U``";Y````#4``)OH````-0``F^P````U``";\````#4``)OT
+M````-0``F_@````0``";_````!H``)H`````!P````<``)H$````1P```$<`
+M`)H(````AP```(<``)H,```!H````:```)H0```!X````>```)H4````(```
+M`"```)H8````8````&```)H<```!H0```:$``)H@```!X0```>$``)HD````
+M(0```"$``)HH````80```&$``)HL```!8@```6(``)HP```!H@```:(``)HT
+M```!X@```>(``)HX````(@```"(``)H\````8@```&(``)I````!8P```6,`
+M`)I$```!HP```:,``)I(```!XP```>,``)I,````(P```",``)I0````8P``
+M`&,``)I4```!A````80``)I8```!Q````<0``)I<````!`````0``)I@```!
+MZ@````L``)ID````*@```$L``)IH````:@```(L``)IL````J@```:P``)IP
+M```!JP```>P``)IT```!ZP```"P``)IX````*P```!(``)I\````:P```%(`
+M`)J`````JP```)(``)J$```!K````9,``)J(```![````=,``)J,````+```
+M`!,``)J0````.@```%,``)J4````>@```),``)J8````N@```90``)J<```!
+MNP```=0``)J@```!^P```!0``)JD````.P```#H``)JH````>P```'H``)JL
+M````NP```+H``)JP```!O````;L``)JT```!_````?L``)JX````/````#L`
+M`)J\````?````'L``)K`````O````+L``)K$````_````;P``)K(````_```
+M`?P``)K,````_````#P``)K0````_````'P``)K4````_````+P``)K8````
+M_````/P``)K<````_````/P``)K@````_````/P``)KD````_````/P``)KH
+M````_````/P``)KL````_````/P``)KP````_````/P``)KT````_````/P`
+M`)KX````_````/P``)K\````_````/P``)C4````(```F-`#!@0(`P<$"`,&
+M!`@#!@0(`P<$"```F-P`H,#``*#`P`#@P,``X,#``.#`P```F)P*````"@``
+M``H````*````"@``````F)P`````````````````````````````F)P`@```
+M`(````"`````@````(``````F)P`*@```"H````J````*@```"H`````F)P`
+M`0````$````!`````0````$`````F)P`````````````````````````````
+MF)P`&````!@````8````&````!@`````F)P`8````&````!N````;@```&X`
+M````F)P`QP```,<```#'````QP```,<`````F)P`2P```$L```!+````2P``
+M`$L`````F)P$2```!$@```1(```$2```!$@`````F)P`3````$P```!,````
+M3````$P`````F)P`Y````.0```#D````Y````.0`````F)P`````````````
+M````````````````F)P`_````/P```#\````_````/P`````F)P`_P```/\`
+M``#_````_P```/\`````F)P$/P``!#\```0_```$/P``!#\`````F)P,#```
+M#`P```P,```,#```#`P`````F)P"&0```AD```(9```"&0```AD`````F)P`
+M)````"0````D````)````"0`````F)P`M````+0```"T````M````+0`````
+MF)P`F0```)D```"9````F0```)D`````F)P`4````%````!0````4````%``
+M````F)P`*@```"H````J````*@```"H`````F)P`$@```!(````2````$@``
+M`!(`````F)S`,@``P#(``,`R``#`,@``P#(`````F)P!=````70```%T```!
+M=````70`````F)P`$0```!$````1````$0```!$`````F)R&*```AB@``(8H
+M``"&*```AB@`````F)PQA```,80``#&$```QA```,80`````F)P`\@"``/(`
+M@`#R`(``\@"``/(`@```F)P`)P`9`"<`&0`G`!D`)P`9`"<`&0``F)P````#
+M`````P````,````#`````P``F)P`````````````````````````````F)P`
+M``"R````L@```+(```"R````L@``F)P`L"&$`+`AA`"P(80`L"&$`+`AA```
+MF)P`026D`$$EI`!!):0`026D`$$EI```F)P`$9(@`!&2(``1DB``$9(@`!&2
+M(```F)P`&D@``!I(```:2```&D@``!I(````F-@`"P(P``L",``+`C``"P(P
+M``L",```F)P```"4````E````)0```"4````E```F)P```"1````D0```)$`
+M``"1````D0``F)P````2````$@```!(````2````$@``F)P```"`````@```
+M`(````"`````@```F)P```#9````V0```-D```#9````V0``F)P```!@````
+M8````&````!@````8```F)P```#P````\````/````#P````\```F)P```"B
+M````H@```*(```"B````H@``F)P```!2````4@```%(```!2````4@``F)P`
+M``#4````U````-0```#4````U```F)P``!3,```4S```%,P``!3,```4S```
+MF)P```2,```$C```!(P```2,```$C```F,0````#`````P````,````#````
+M`X``\02``/5L@`$,<`````,`!@`)`#\```````D````$``0``0`!``$`````
+M``````````9&1S@```````````````````0````!``$```````````````1&
+M1S<```````````````````,``0`!``$```````````````-&1S8`````````
+M``````````0```````$```````````````%&1S4```````````````````0`
+M`0`!``````````````````!&1S0```````````````````0````!````````
+M`````/____Y&1S,```````````````````,``0`!`````````````/____U&
+M1S(```````````````````0``````````````````/____Q&1S$`````````
+M``````````(``0`!`````````````/____I&1S``````````````````````
+M````````````````````````````````````````````````"`````$``P``
+M````````````````````!D9'-P```````````````````@``````````````
+M`````````$9'-@```````````````````0``````````````````_____49'
+M-0``````````````````````````````````````____^D9'-```````````
+M```````````!``$`````````````____^$9',P`````````````````````!
+M``$````!``$`````____]D9',@`````````````````````!`````0`!``$`
+M````____\T9',0`````````````````````!`````0`!`````0``____\$9'
+M,```````````````````````````````````````````````````````````
+M```````````````````````````````````````````````````````````"
+M````!`````H````!`````P````H````"````!0````H````"````!`````H`
+M```"`````P````H``````````@````,```````````````"``D1X@`)$@(`"
+M1,2``D3H@`)$?/\``0P"!@`-`P`'``````X*!```"```&0``````%1L/'PL%
+M```````)```8```4&AX`````%P`3'0`6$AP1$``"8EH``/#<*``$```!;C8`
+M`<G#@`.3AP`')PX``+<;``````"```>`@``&=(``!G2```9T@``&=(``!G2`
+M``9T@``&=(``!G2```9T@``&=(``!G2```9T@``&=(``!G2```9T@``&=(``
+M!G2```9T@``&=(``!G2```9T@``&=(``!G2```9T@``&=(``!G2```9T@``&
+M=(``!G2```9T@``&=(``!G2```9T@``&=(``!G2```9T@``&=(``!G2```9T
+M@``&=(``!G2```9T@``&=(``!G2```9T@``&=(``!G2```9T@``&=(``!G2`
+M``9T@``&=(``!G2```9T@``&=(``!G2```9T@``&=(``!G2```9T@``&=(``
+M!G2```9T@`&VF(`!MIB``;:8@`&VF(`!MIB``;:8@`&VF(`!MIB``;:8@`&V
+MF(`!MIB``;:8@`&VF(`!MIB``;:8@`&VF(`!MIB``;:8@`&VF(`!MIB``;:8
+M@`&VF(`!MIB``;:8@`&VF(`!MIB``;:8@`&VF(`!MIB``;:8````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````@`*A$```````$P``@`!X2!$3``"``'A(`#```(``>$@`%```@`!X
+M2``5``"``'A(`!8``(``>$@`%P``@`!X2``8``"``'A(`!D``(``>$@`4``3
+M`%$`$P!3`!,`5@`3`%4`$P!5`!,`@``3`($`$P```,(```#$````Q0```-``
+M``#:````Y````,(```##````U````/(```$-```!*```````````````````
+M`!#_``````````````````````````````````````````````$`````%W`5
+M&`L`C``"`0`\`#P```````$`````(R@>>`\`$@`#`0`\`#P```````$`````
+M+N`G$`H`F`($`@`P`#````````$`````1E`V3`X`)`(&`@`P`#````````$`
+M````7<!#E`D`L`0*`P`L`"P```````$`````C*!9V`T`2`0.`P`L`"P`````
+M``$`````NX!K"`@`8`03`P`L`"P```````$`````TO!R=`P`;`07`P`L`"P`
+M``````$````!%W`I:`L`C`@"`0`B`"(```````$````!(R@\\`\`$@@#`0`B
+M`"(```````$````!+N!+R`H`F`H$`@`>`!X```````$````!1E!I%`X`)`H&
+M`@`>`!X```````$````!7<"!L`D`L`P*`P`:`!H```````$````!C*"J4`T`
+M2`P.`P`:`!H```````$````!NX#(9`@`8`P3`P`:`!H```````$````!TO#7
+M/`P`;`P7`P`:`!H`````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````````````````````&0````R
+M!0LR!P@```````````````````C_````````````````````````````````
+M``````````````$````!%W`5&`L`C``"`0`B`"(```````$````!(R@>>`\`
+M$@`$`0`B`"(```````$````!+N`G$`H`F`('`@`>`!X```````$````!1E`V
+M3`X`)`()`@`>`!X```````$````!7<!#E`D`L`0.`P`:`!H```````$````!
+MC*!9V`T`2`01`P`:`!H```````$````!NX!K"`@`8`06`P`:`!H```````$`
+M```!TO!R=`P`;`0:`P`:`!H`````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````&0````R````!P@``````````````````!/_````````
+M``````````````````````````````````````$````"`^@#A!L``@```0$Z
+M`3H```````$````"!]`';!H$!`$!`0$"`*(```````$````"%7P3)!D$"P("
+M`@#?`'\```````$````"*O@?I!@$%@,#`@#5`'4`````````````%W`5&`L`
+M#`0"`0`\`#P`````````````(R@>>`\`$@0#`0`\`#P```````$`````+N`G
+M=`H`&`8$`0`P`#````````$`````1E`W%`X`)`8&`@`P`#````````$`````
+M7<!%)`D`,`@*`P`L`"P```````$`````C*!<E`T`2`@.`P`L`"P```````$`
+M````NX!K"`@`8`@3`P`L`"P```````$`````TO!R=`P`;`@7`P`L`"P`````
+M``$````!%W`I:`L`C`P"`0`B`"(```````$````!+N!+R`H`&`T$`0`>`!X`
+M``````$````!1E!I%`X`)`T&`@`>`!X```````$````!7<"!L`D`L`\*`P`:
+M`!H```````$````!C*"J4`T`2`\.`P`:`!H```````$````!NX#(9`@`8`\3
+M`P`:`!H```````$````!TO#7/`P`;`\7`P`:`!H`````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````````````````````````````````````````&0````R"0XR"P<`````
+M``````````````3_````````````````````````````````````````````
+M``$````"`^@#A!L`@@```0$Z`3H```````$````"!]`'"!H$A`$!`0$"`*(`
+M``````$````"%7P0S!D$BP$"`@$"`*(```````$````"*O@;O!@$E@$$9`$"
+M`*(`````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M`````,@```!D`````P````````````````8``&P`V`&\`XP%5`JP````````
+M````````````````````````````````````````````````````````````
+M````````#?\``````````````````````````````````````````````0``
+M``,`^@#(`P`!`/<!`F0"9````````0````,!]`&0!P`!`?@$`<D!R0``````
+M`0````,#Z`.$`@`"`OP"`.0`Y````````0````,'T`<(!@`$`_X!`*``H```
+M`````0````,+N`J,`0`&!/\!`(P`C````````0`````7<!48"P",!0(!`#P`
+M/````````0`````C*!YX#P`2!0,!`#P`/````````0`````NX"<0"@"8!P0"
+M`#``,````````0````!&4#9,#@`D!P8"`#``,````````0````!=P$.4"0"P
+M"0H#`"P`+````````0````",H%G8#0!("0X#`"P`+````````0````"[@&L(
+M"`!@"1,#`"P`+````````0````#2\')T#`!L"1<#`"P`+```````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+M````````````````````````````````````````````````````````````
+MR````&0````,`````(`"0'P``````````(`!1^R``4A(@`%(I(`!21``````
+M````&0```#(```!+````4````%,```!5````5P```%@```!:```"````!R``
+M``(````'(````@````(````"`````@````(````"`````@````(`````````
+M``````````````0#"00$`R``-@-!`'0`:`!E`'(`;P!S`"``0P!O`&T`;0!U
+M`&X`:0!C`&$`=`!I`&\`;@!S`"``20!N`&,````````````````````.`T$`
+M4@`U`#4`,@`S```````````````````````````````(`S$`+@`P````````
+M`````````!(!``+_``!`\PP!``$``0(#`0``"@8``O\``$`!````"0(N``$!
+M`(#Z"00```3_````!P6!`D````<%`0)````'!8("0```!P4"`D````<%`P)`
+M```'!00"0```!P4%`D````<%!@)````'!0<"0```!P4(`D````<%"0)````'
+M!0H"0``````)!RX``0$`H/H)!```!/\````'!8$"0```!P4!`D````<%@@)`
+M```'!0("0```!P4#`D````<%!`)````'!04"0```!P4&`D````<%!P)````'
+M!0@"0```!P4)`D````<%"@)```````````````````````"JJJJJJJJJJN[N
+M[N[N[N[N_O______________?[_?[_?[_?Q^O]_O]_O]?@`````!`0`"8EH`
+M``8:@`````#____^_____@``````````@`&WO````````0```````8`"G,0`
+M````H+```````^@````(````````````````.YK*`````&2``:08@`'K*(`!
+MTSR``?P<@`'4*(`!V2B``>&$@`'"5(`!ZTB``=-<@`'\/(`!V4B``>&D````
+M`#P$@``DA````^`((3P%@``DI0``/!^``B?_1N``OR@B!!$``0``````OR@@
+M`"#X(0/@,"$#X`@A/!J``B=:1W@\'X`")_]'#`-?T"($$0`!``````-?T"``
+M(/@A`T#X"0``````P$`A`^`((3P)@`(E*4=D/!^``B?_1T`!/T@B!!$``0``
+M```!/T@@`"#X(0$H0"(\`H`")$)'7`!```@`````!!$``0`````#Z$`B`0#X
+M(0/@``@```````````"`0"$`H$@A/`N``B5K1W2-(@``K0(``"4I``0E"``$
+0%0O_^P`````#X``(````````
+`
+end
diff --git a/sys/contrib/pf/net/pf.c b/sys/contrib/pf/net/pf.c
index d69372b..71b7bda 100644
--- a/sys/contrib/pf/net/pf.c
+++ b/sys/contrib/pf/net/pf.c
@@ -6153,7 +6153,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if (r->rt == PF_FASTROUTE) {
in_rtalloc(ro, 0);
if (ro->ro_rt == 0) {
- V_ipstat.ips_noroute++;
+ IPSTAT_INC(ips_noroute);
goto bad;
}
@@ -6284,16 +6284,16 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
ifp->if_bridge == NULL) {
m0->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
- V_ipstat.ips_outhwcsum++;
+ IPSTAT_INC(ips_outhwcsum);
} else {
ip->ip_sum = 0;
ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
}
/* Update relevant hardware checksum stats for TCP/UDP */
if (m0->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT)
- V_tcpstat.tcps_outhwcsum++;
+ TCPSTAT_INC(tcpstat.tcps_outhwcsum);
else if (m0->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT)
- V_udpstat.udps_outhwcsum++;
+ UDPSTAT_INC(udps_outhwcsum);
error = (*ifp->if_output)(ifp, m0, sintosa(dst), NULL);
goto done;
}
@@ -6303,7 +6303,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
* Must be able to put at least 8 bytes per fragment.
*/
if (ip->ip_off & htons(IP_DF)) {
- V_ipstat.ips_cantfrag++;
+ IPSTAT_INC(ips_cantfrag);
if (r->rt != PF_DUPTO) {
#ifdef __FreeBSD__
/* icmp_error() expects host byte ordering */
@@ -6360,7 +6360,7 @@ pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
}
if (error == 0)
- V_ipstat.ips_fragmented++;
+ IPSTAT_INC(ips_fragmented);
done:
if (r->rt != PF_DUPTO)
@@ -6635,26 +6635,26 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t a
case IPPROTO_TCP:
{
INIT_VNET_INET(curvnet);
- V_tcpstat.tcps_rcvbadsum++;
+ TCPSTAT_INC(tcps_rcvbadsum);
break;
}
case IPPROTO_UDP:
{
INIT_VNET_INET(curvnet);
- V_udpstat.udps_badsum++;
+ UDPSTAT_INC(udps_badsum);
break;
}
case IPPROTO_ICMP:
{
INIT_VNET_INET(curvnet);
- V_icmpstat.icps_checksum++;
+ ICMPSTAT_INC(icps_checksum);
break;
}
#ifdef INET6
case IPPROTO_ICMPV6:
{
INIT_VNET_INET6(curvnet);
- V_icmp6stat.icp6s_checksum++;
+ ICMP6STAT_INC(icp6s_checksum);
break;
}
#endif /* INET6 */
@@ -6741,17 +6741,17 @@ pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
m->m_pkthdr.csum_flags |= flag_bad;
switch (p) {
case IPPROTO_TCP:
- V_tcpstat.tcps_rcvbadsum++;
+ TCPSTAT_INC(tcps_rcvbadsum);
break;
case IPPROTO_UDP:
- V_udpstat.udps_badsum++;
+ UDPSTAT_INC(udps_badsum);
break;
case IPPROTO_ICMP:
- V_icmpstat.icps_checksum++;
+ ICMPSTAT_INC(icps_checksum);
break;
#ifdef INET6
case IPPROTO_ICMPV6:
- V_icmp6stat.icp6s_checksum++;
+ ICMP6STAT_INC(icp6s_checksum);
break;
#endif /* INET6 */
}
diff --git a/sys/dev/acpi_support/acpi_asus.c b/sys/dev/acpi_support/acpi_asus.c
index 36cc4f9..28f9e7c 100644
--- a/sys/dev/acpi_support/acpi_asus.c
+++ b/sys/dev/acpi_support/acpi_asus.c
@@ -176,16 +176,39 @@ static struct acpi_asus_model acpi_asus_models[] = {
.disp_set = "SDSP"
},
{
+ .name = "A3E",
+ .mled_set = "MLED",
+ .wled_set = "WLED",
+ .lcd_get = "\\_SB.PCI0.SBRG.EC0.RPIN(0x67)",
+ .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
+ .brn_get = "GPLV",
+ .brn_set = "SPLV",
+ .disp_get = "\\_SB.PCI0.P0P2.VGA.GETD",
+ .disp_set = "SDSP"
+ },
+ {
+ .name = "A3F",
+ .mled_set = "MLED",
+ .wled_set = "WLED",
+ .bled_set = "BLED",
+ .lcd_get = "\\_SB.PCI0.SBRG.EC0.RPIN(0x11)",
+ .lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
+ .brn_get = "GPLV",
+ .brn_set = "SPLV",
+ .disp_get = "\\SSTE",
+ .disp_set = "SDSP"
+ },
+ {
.name = "A3N",
.mled_set = "MLED",
.bled_set = "BLED",
.wled_set = "WLED",
- .lcd_get = NULL,
+ .lcd_get = "\\BKLT",
.lcd_set = "\\_SB.PCI0.SBRG.EC0._Q10",
+ .brn_get = "GPLV",
.brn_set = "SPLV",
- .brn_get = "SDSP",
- .disp_set = "SDSP",
- .disp_get = "\\_SB.PCI0.P0P3.VGA.GETD"
+ .disp_get = "\\_SB.PCI0.P0P3.VGA.GETD",
+ .disp_set = "SDSP"
},
{
.name = "A4D",
@@ -577,7 +600,7 @@ acpi_asus_probe(device_t dev)
return (0);
}
- /* if EeePC */
+ /* EeePC */
if (strncmp("ASUS010", rstr, 7) == 0) {
sc->model = &acpi_eeepc_models[0];
device_set_desc(dev, "ASUS EeePC");
@@ -627,6 +650,9 @@ good:
else if (strncmp(model->name, "A2x", 3) == 0 &&
strncmp(Obj->String.Pointer, "A2", 2) == 0)
goto good;
+ else if (strncmp(model->name, "A3F", 3) == 0 &&
+ strncmp(Obj->String.Pointer, "A6F", 3) == 0)
+ goto good;
else if (strncmp(model->name, "D1x", 3) == 0 &&
strncmp(Obj->String.Pointer, "D1", 2) == 0)
goto good;
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 8271917..50b84a5 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -46,7 +46,11 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <sys/power.h>
#include <sys/sbuf.h>
+#ifdef SMP
+#include <sys/sched.h>
+#endif
#include <sys/smp.h>
+#include <sys/timetc.h>
#if defined(__i386__) || defined(__amd64__)
#include <machine/pci_cfgreg.h>
@@ -250,6 +254,12 @@ TUNABLE_INT("debug.acpi.do_powerstate", &acpi_do_powerstate);
SYSCTL_INT(_debug_acpi, OID_AUTO, do_powerstate, CTLFLAG_RW,
&acpi_do_powerstate, 1, "Turn off devices when suspending.");
+/* Reset system clock while resuming. XXX Remove once tested. */
+static int acpi_reset_clock = 1;
+TUNABLE_INT("debug.acpi.reset_clock", &acpi_reset_clock);
+SYSCTL_INT(_debug_acpi, OID_AUTO, reset_clock, CTLFLAG_RW,
+ &acpi_reset_clock, 1, "Reset system clock while resuming.");
+
/* Allow users to override quirks. */
TUNABLE_INT("debug.acpi.quirks", &acpi_quirks);
@@ -2274,6 +2284,7 @@ acpi_SetSleepState(struct acpi_softc *sc, int state)
return (acpi_EnterSleepState(sc, state));
}
+#if defined(__amd64__) || defined(__i386__)
static void
acpi_sleep_force(void *arg)
{
@@ -2284,6 +2295,7 @@ acpi_sleep_force(void *arg)
if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_sstate)))
printf("acpi: force sleep state S%d failed\n", sc->acpi_next_sstate);
}
+#endif
/*
* Request that the system enter the given suspend state. All /dev/apm
@@ -2294,7 +2306,9 @@ acpi_sleep_force(void *arg)
int
acpi_ReqSleepState(struct acpi_softc *sc, int state)
{
+#if defined(__i386__)
struct apm_clone_data *clone;
+#endif
if (state < ACPI_STATE_S1 || state > ACPI_STATE_S5)
return (EINVAL);
@@ -2307,11 +2321,7 @@ acpi_ReqSleepState(struct acpi_softc *sc, int state)
return (ENXIO);
}
-#if !defined(__i386__)
- /* This platform does not support acpi suspend/resume. */
- return (EOPNOTSUPP);
-#endif
-
+#if defined(__amd64__) || defined(__i386__)
/* If a suspend request is already in progress, just return. */
ACPI_LOCK(acpi);
if (sc->acpi_next_sstate != 0) {
@@ -2321,6 +2331,7 @@ acpi_ReqSleepState(struct acpi_softc *sc, int state)
/* Record the pending state and notify all apm devices. */
sc->acpi_next_sstate = state;
+#if defined(__i386__)
STAILQ_FOREACH(clone, &sc->apm_cdevs, entries) {
clone->notify_status = APM_EV_NONE;
if ((clone->flags & ACPI_EVF_DEVD) == 0) {
@@ -2328,9 +2339,10 @@ acpi_ReqSleepState(struct acpi_softc *sc, int state)
KNOTE_UNLOCKED(&clone->sel_read.si_note, 0);
}
}
+#endif
/* If devd(8) is not running, immediately enter the sleep state. */
- if (devctl_process_running() == FALSE) {
+ if (!devctl_process_running()) {
ACPI_UNLOCK(acpi);
if (ACPI_SUCCESS(acpi_EnterSleepState(sc, sc->acpi_next_sstate))) {
return (0);
@@ -2339,9 +2351,6 @@ acpi_ReqSleepState(struct acpi_softc *sc, int state)
}
}
- /* Now notify devd(8) also. */
- acpi_UserNotify("Suspend", ACPI_ROOT_OBJECT, state);
-
/*
* Set a timeout to fire if userland doesn't ack the suspend request
* in time. This way we still eventually go to sleep if we were
@@ -2351,7 +2360,15 @@ acpi_ReqSleepState(struct acpi_softc *sc, int state)
*/
callout_reset(&sc->susp_force_to, 10 * hz, acpi_sleep_force, sc);
ACPI_UNLOCK(acpi);
+
+ /* Now notify devd(8) also. */
+ acpi_UserNotify("Suspend", ACPI_ROOT_OBJECT, state);
+
return (0);
+#else
+ /* This platform does not support acpi suspend/resume. */
+ return (EOPNOTSUPP);
+#endif
}
/*
@@ -2364,14 +2381,10 @@ acpi_ReqSleepState(struct acpi_softc *sc, int state)
int
acpi_AckSleepState(struct apm_clone_data *clone, int error)
{
+#if defined(__amd64__) || defined(__i386__)
struct acpi_softc *sc;
int ret, sleeping;
-#if !defined(__i386__)
- /* This platform does not support acpi suspend/resume. */
- return (EOPNOTSUPP);
-#endif
-
/* If no pending sleep state, return an error. */
ACPI_LOCK(acpi);
sc = clone->acpi_sc;
@@ -2395,8 +2408,9 @@ acpi_AckSleepState(struct apm_clone_data *clone, int error)
* all devices, seeing if they agree yet. We only count devices that
* are writable since read-only devices couldn't ack the request.
*/
- clone->notify_status = APM_EV_ACKED;
sleeping = TRUE;
+#if defined(__i386__)
+ clone->notify_status = APM_EV_ACKED;
STAILQ_FOREACH(clone, &sc->apm_cdevs, entries) {
if ((clone->flags & ACPI_EVF_WRITE) != 0 &&
clone->notify_status != APM_EV_ACKED) {
@@ -2404,6 +2418,7 @@ acpi_AckSleepState(struct apm_clone_data *clone, int error)
break;
}
}
+#endif
/* If all devices have voted "yes", we will suspend now. */
if (sleeping)
@@ -2414,15 +2429,34 @@ acpi_AckSleepState(struct apm_clone_data *clone, int error)
if (ACPI_FAILURE(acpi_EnterSleepState(sc, sc->acpi_next_sstate)))
ret = ENODEV;
}
-
return (ret);
+#else
+ /* This platform does not support acpi suspend/resume. */
+ return (EOPNOTSUPP);
+#endif
}
static void
acpi_sleep_enable(void *arg)
{
+ struct acpi_softc *sc = (struct acpi_softc *)arg;
- ((struct acpi_softc *)arg)->acpi_sleep_disabled = 0;
+ ACPI_LOCK(acpi);
+ sc->acpi_sleep_disabled = 0;
+ ACPI_UNLOCK(acpi);
+}
+
+static ACPI_STATUS
+acpi_sleep_disable(struct acpi_softc *sc)
+{
+ ACPI_STATUS status;
+
+ ACPI_LOCK(acpi);
+ status = sc->acpi_sleep_disabled ? AE_ERROR : AE_OK;
+ sc->acpi_sleep_disabled = 1;
+ ACPI_UNLOCK(acpi);
+
+ return (status);
}
enum acpi_sleep_state {
@@ -2449,21 +2483,24 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
/* Re-entry once we're suspending is not allowed. */
- status = AE_OK;
- ACPI_LOCK(acpi);
- if (sc->acpi_sleep_disabled) {
- ACPI_UNLOCK(acpi);
+ status = acpi_sleep_disable(sc);
+ if (ACPI_FAILURE(status)) {
printf("acpi: suspend request ignored (not ready yet)\n");
- return (AE_ERROR);
+ return (status);
}
- sc->acpi_sleep_disabled = 1;
- ACPI_UNLOCK(acpi);
+
+#ifdef SMP
+ thread_lock(curthread);
+ sched_bind(curthread, 0);
+ thread_unlock(curthread);
+#endif
/*
* Be sure to hold Giant across DEVICE_SUSPEND/RESUME since non-MPSAFE
* drivers need this.
*/
mtx_lock(&Giant);
+
slp_state = ACPI_SS_NONE;
switch (state) {
case ACPI_STATE_S1:
@@ -2539,6 +2576,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
* shutdown handlers.
*/
shutdown_nice(RB_POWEROFF);
+ status = AE_OK;
break;
case ACPI_STATE_S0:
default:
@@ -2562,17 +2600,40 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
if (slp_state >= ACPI_SS_SLEPT)
acpi_enable_fixed_events(sc);
+ mtx_unlock(&Giant);
+
+#ifdef SMP
+ thread_lock(curthread);
+ sched_unbind(curthread);
+ thread_unlock(curthread);
+#endif
+
/* Allow another sleep request after a while. */
if (state != ACPI_STATE_S5)
timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME);
/* Run /etc/rc.resume after we are back. */
- acpi_UserNotify("Resume", ACPI_ROOT_OBJECT, state);
+ if (devctl_process_running())
+ acpi_UserNotify("Resume", ACPI_ROOT_OBJECT, state);
- mtx_unlock(&Giant);
return_ACPI_STATUS (status);
}
+void
+acpi_resync_clock(struct acpi_softc *sc)
+{
+
+ if (!acpi_reset_clock)
+ return;
+
+ /*
+ * Warm up timecounter again and reset system clock.
+ */
+ (void)timecounter->tc_get_timecount(timecounter);
+ (void)timecounter->tc_get_timecount(timecounter);
+ inittodr(time_second + sc->acpi_sleep_delay);
+}
+
/* Initialize a device's wake GPE. */
int
acpi_wake_init(device_t dev, int type)
diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c
index 2de059a..5044c4a 100644
--- a/sys/dev/acpica/acpi_cpu.c
+++ b/sys/dev/acpica/acpi_cpu.c
@@ -609,10 +609,6 @@ acpi_cpu_generic_cx_probe(struct acpi_cpu_softc *sc)
sc->cpu_cx_count++;
}
}
-
- /* Update the largest cx_count seen so far */
- if (sc->cpu_cx_count > cpu_cx_count)
- cpu_cx_count = sc->cpu_cx_count;
}
/*
@@ -752,6 +748,8 @@ acpi_cpu_startup(void *arg)
for (i = 0; i < cpu_ndevices; i++) {
sc = device_get_softc(cpu_devices[i]);
acpi_cpu_generic_cx_probe(sc);
+ if (sc->cpu_cx_count > cpu_cx_count)
+ cpu_cx_count = sc->cpu_cx_count;
}
/*
diff --git a/sys/dev/acpica/acpi_ec.c b/sys/dev/acpica/acpi_ec.c
index bb75223..696542c 100644
--- a/sys/dev/acpica/acpi_ec.c
+++ b/sys/dev/acpica/acpi_ec.c
@@ -747,7 +747,7 @@ EcSpaceHandler(UINT32 Function, ACPI_PHYSICAL_ADDRESS Address, UINT32 width,
* If booting, check if we need to run the query handler. If so, we
* we call it directly here since our thread taskq is not active yet.
*/
- if (cold || rebooting) {
+ if (cold || rebooting || sc->ec_suspending) {
if ((EC_GET_CSR(sc) & EC_EVENT_SCI)) {
CTR0(KTR_ACPI, "ec running gpe handler directly");
EcGpeQueryHandler(sc);
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index a5ac2de..ce6a242 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -330,6 +330,7 @@ ACPI_STATUS acpi_SetIntrModel(int model);
int acpi_ReqSleepState(struct acpi_softc *sc, int state);
int acpi_AckSleepState(struct apm_clone_data *clone, int error);
ACPI_STATUS acpi_SetSleepState(struct acpi_softc *sc, int state);
+void acpi_resync_clock(struct acpi_softc *sc);
int acpi_wake_init(device_t dev, int type);
int acpi_wake_set_enable(device_t dev, int enable);
int acpi_parse_prw(ACPI_HANDLE h, struct acpi_prw_data *prw);
diff --git a/sys/dev/age/if_age.c b/sys/dev/age/if_age.c
index f8d8a2e..74afa2e 100644
--- a/sys/dev/age/if_age.c
+++ b/sys/dev/age/if_age.c
@@ -106,8 +106,6 @@ static int age_miibus_writereg(device_t, int, int, int);
static void age_miibus_statchg(device_t);
static void age_mediastatus(struct ifnet *, struct ifmediareq *);
static int age_mediachange(struct ifnet *);
-static int age_read_vpd_word(struct age_softc *, uint32_t, uint32_t,
- uint32_t *);
static int age_probe(device_t);
static void age_get_macaddr(struct age_softc *);
static void age_phy_reset(struct age_softc *);
@@ -321,29 +319,6 @@ age_mediachange(struct ifnet *ifp)
}
static int
-age_read_vpd_word(struct age_softc *sc, uint32_t vpdc, uint32_t offset,
- uint32_t *word)
-{
- int i;
-
- pci_write_config(sc->age_dev, vpdc + PCIR_VPD_ADDR, offset, 2);
- for (i = AGE_TIMEOUT; i > 0; i--) {
- DELAY(10);
- if ((pci_read_config(sc->age_dev, vpdc + PCIR_VPD_ADDR, 2) &
- 0x8000) == 0x8000)
- break;
- }
- if (i == 0) {
- device_printf(sc->age_dev, "VPD read timeout!\n");
- *word = 0;
- return (ETIMEDOUT);
- }
-
- *word = pci_read_config(sc->age_dev, vpdc + PCIR_VPD_DATA, 4);
- return (0);
-}
-
-static int
age_probe(device_t dev)
{
struct age_dev *sp;
@@ -368,8 +343,8 @@ age_probe(device_t dev)
static void
age_get_macaddr(struct age_softc *sc)
{
- uint32_t ea[2], off, reg, word;
- int vpd_error, match, vpdc;
+ uint32_t ea[2], reg;
+ int i, vpdc;
reg = CSR_READ_4(sc, AGE_SPI_CTRL);
if ((reg & SPI_VPD_ENB) != 0) {
@@ -378,123 +353,114 @@ age_get_macaddr(struct age_softc *sc)
CSR_WRITE_4(sc, AGE_SPI_CTRL, reg);
}
- vpd_error = 0;
- ea[0] = ea[1] = 0;
- if ((vpd_error = pci_find_extcap(sc->age_dev, PCIY_VPD, &vpdc)) == 0) {
+ if (pci_find_extcap(sc->age_dev, PCIY_VPD, &vpdc) == 0) {
/*
- * PCI VPD capability exists, but it seems that it's
- * not in the standard form as stated in PCI VPD
- * specification such that driver could not use
- * pci_get_vpd_readonly(9) with keyword 'NA'.
- * Search VPD data starting at address 0x0100. The data
- * should be used as initializers to set AGE_PAR0,
- * AGE_PAR1 register including other PCI configuration
- * registers.
+ * PCI VPD capability found, let TWSI reload EEPROM.
+ * This will set ethernet address of controller.
*/
- word = 0;
- match = 0;
- reg = 0;
- for (off = AGE_VPD_REG_CONF_START; off < AGE_VPD_REG_CONF_END;
- off += sizeof(uint32_t)) {
- vpd_error = age_read_vpd_word(sc, vpdc, off, &word);
- if (vpd_error != 0)
- break;
- if (match != 0) {
- switch (reg) {
- case AGE_PAR0:
- ea[0] = word;
- break;
- case AGE_PAR1:
- ea[1] = word;
- break;
- default:
- break;
- }
- match = 0;
- } else if ((word & 0xFF) == AGE_VPD_REG_CONF_SIG) {
- match = 1;
- reg = word >> 16;
- } else
+ CSR_WRITE_4(sc, AGE_TWSI_CTRL, CSR_READ_4(sc, AGE_TWSI_CTRL) |
+ TWSI_CTRL_SW_LD_START);
+ for (i = 100; i > 0; i--) {
+ DELAY(1000);
+ reg = CSR_READ_4(sc, AGE_TWSI_CTRL);
+ if ((reg & TWSI_CTRL_SW_LD_START) == 0)
break;
}
- if (off >= AGE_VPD_REG_CONF_END)
- vpd_error = ENOENT;
- if (vpd_error == 0) {
- /*
- * Don't blindly trust ethernet address obtained
- * from VPD. Check whether ethernet address is
- * valid one. Otherwise fall-back to reading
- * PAR register.
- */
- ea[1] &= 0xFFFF;
- if ((ea[0] == 0 && ea[1] == 0) ||
- (ea[0] == 0xFFFFFFFF && ea[1] == 0xFFFF)) {
- if (bootverbose)
- device_printf(sc->age_dev,
- "invalid ethernet address "
- "returned from VPD.\n");
- vpd_error = EINVAL;
- }
- }
- if (vpd_error != 0 && (bootverbose))
- device_printf(sc->age_dev, "VPD access failure!\n");
+ if (i == 0)
+ device_printf(sc->age_dev,
+ "reloading EEPROM timeout!\n");
} else {
if (bootverbose)
device_printf(sc->age_dev,
"PCI VPD capability not found!\n");
}
- /*
- * It seems that L1 also provides a way to extract ethernet
- * address via SPI flash interface. Because SPI flash memory
- * device of different vendors vary in their instruction
- * codes for read ID instruction, it's very hard to get
- * instructions codes without detailed information for the
- * flash memory device used on ethernet controller. To simplify
- * code, just read AGE_PAR0/AGE_PAR1 register to get ethernet
- * address which is supposed to be set by hardware during
- * power on reset.
- */
- if (vpd_error != 0) {
- /*
- * VPD is mapped to SPI flash memory or BIOS set it.
- */
- ea[0] = CSR_READ_4(sc, AGE_PAR0);
- ea[1] = CSR_READ_4(sc, AGE_PAR1);
- }
-
- ea[1] &= 0xFFFF;
- if ((ea[0] == 0 && ea[1] == 0) ||
- (ea[0] == 0xFFFFFFFF && ea[1] == 0xFFFF)) {
- device_printf(sc->age_dev,
- "generating fake ethernet address.\n");
- ea[0] = arc4random();
- /* Set OUI to ASUSTek COMPUTER INC. */
- sc->age_eaddr[0] = 0x00;
- sc->age_eaddr[1] = 0x1B;
- sc->age_eaddr[2] = 0xFC;
- sc->age_eaddr[3] = (ea[0] >> 16) & 0xFF;
- sc->age_eaddr[4] = (ea[0] >> 8) & 0xFF;
- sc->age_eaddr[5] = (ea[0] >> 0) & 0xFF;
- } else {
- sc->age_eaddr[0] = (ea[1] >> 8) & 0xFF;
- sc->age_eaddr[1] = (ea[1] >> 0) & 0xFF;
- sc->age_eaddr[2] = (ea[0] >> 24) & 0xFF;
- sc->age_eaddr[3] = (ea[0] >> 16) & 0xFF;
- sc->age_eaddr[4] = (ea[0] >> 8) & 0xFF;
- sc->age_eaddr[5] = (ea[0] >> 0) & 0xFF;
- }
+ ea[0] = CSR_READ_4(sc, AGE_PAR0);
+ ea[1] = CSR_READ_4(sc, AGE_PAR1);
+ sc->age_eaddr[0] = (ea[1] >> 8) & 0xFF;
+ sc->age_eaddr[1] = (ea[1] >> 0) & 0xFF;
+ sc->age_eaddr[2] = (ea[0] >> 24) & 0xFF;
+ sc->age_eaddr[3] = (ea[0] >> 16) & 0xFF;
+ sc->age_eaddr[4] = (ea[0] >> 8) & 0xFF;
+ sc->age_eaddr[5] = (ea[0] >> 0) & 0xFF;
}
static void
age_phy_reset(struct age_softc *sc)
{
+ uint16_t reg, pn;
+ int i, linkup;
/* Reset PHY. */
CSR_WRITE_4(sc, AGE_GPHY_CTRL, GPHY_CTRL_RST);
- DELAY(1000);
+ DELAY(2000);
CSR_WRITE_4(sc, AGE_GPHY_CTRL, GPHY_CTRL_CLR);
- DELAY(1000);
+ DELAY(2000);
+
+#define ATPHY_DBG_ADDR 0x1D
+#define ATPHY_DBG_DATA 0x1E
+#define ATPHY_CDTC 0x16
+#define PHY_CDTC_ENB 0x0001
+#define PHY_CDTC_POFF 8
+#define ATPHY_CDTS 0x1C
+#define PHY_CDTS_STAT_OK 0x0000
+#define PHY_CDTS_STAT_SHORT 0x0100
+#define PHY_CDTS_STAT_OPEN 0x0200
+#define PHY_CDTS_STAT_INVAL 0x0300
+#define PHY_CDTS_STAT_MASK 0x0300
+
+ /* Check power saving mode. Magic from Linux. */
+ age_miibus_writereg(sc->age_dev, sc->age_phyaddr, MII_BMCR, BMCR_RESET);
+ for (linkup = 0, pn = 0; pn < 4; pn++) {
+ age_miibus_writereg(sc->age_dev, sc->age_phyaddr, ATPHY_CDTC,
+ (pn << PHY_CDTC_POFF) | PHY_CDTC_ENB);
+ for (i = 200; i > 0; i--) {
+ DELAY(1000);
+ reg = age_miibus_readreg(sc->age_dev, sc->age_phyaddr,
+ ATPHY_CDTC);
+ if ((reg & PHY_CDTC_ENB) == 0)
+ break;
+ }
+ DELAY(1000);
+ reg = age_miibus_readreg(sc->age_dev, sc->age_phyaddr,
+ ATPHY_CDTS);
+ if ((reg & PHY_CDTS_STAT_MASK) != PHY_CDTS_STAT_OPEN) {
+ linkup++;
+ break;
+ }
+ }
+ age_miibus_writereg(sc->age_dev, sc->age_phyaddr, MII_BMCR,
+ BMCR_RESET | BMCR_AUTOEN | BMCR_STARTNEG);
+ if (linkup == 0) {
+ age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
+ ATPHY_DBG_ADDR, 0);
+ age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
+ ATPHY_DBG_DATA, 0x124E);
+ age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
+ ATPHY_DBG_ADDR, 1);
+ reg = age_miibus_readreg(sc->age_dev, sc->age_phyaddr,
+ ATPHY_DBG_DATA);
+ age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
+ ATPHY_DBG_DATA, reg | 0x03);
+ /* XXX */
+ DELAY(1500 * 1000);
+ age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
+ ATPHY_DBG_ADDR, 0);
+ age_miibus_writereg(sc->age_dev, sc->age_phyaddr,
+ ATPHY_DBG_DATA, 0x024E);
+ }
+
+#undef ATPHY_DBG_ADDR
+#undef ATPHY_DBG_DATA
+#undef ATPHY_CDTC
+#undef PHY_CDTC_ENB
+#undef PHY_CDTC_POFF
+#undef ATPHY_CDTS
+#undef PHY_CDTS_STAT_OK
+#undef PHY_CDTS_STAT_SHORT
+#undef PHY_CDTS_STAT_OPEN
+#undef PHY_CDTS_STAT_INVAL
+#undef PHY_CDTS_STAT_MASK
}
static int
@@ -539,7 +505,8 @@ age_attach(device_t dev)
sc->age_chip_rev = CSR_READ_4(sc, AGE_MASTER_CFG) >>
MASTER_CHIP_REV_SHIFT;
if (bootverbose) {
- device_printf(dev, "PCI device revision : 0x%04x\n", sc->age_rev);
+ device_printf(dev, "PCI device revision : 0x%04x\n",
+ sc->age_rev);
device_printf(dev, "Chip id/revision : 0x%04x\n",
sc->age_chip_rev);
}
@@ -1369,7 +1336,7 @@ age_setwol(struct age_softc *sc)
AGE_LOCK_ASSERT(sc);
- if (pci_find_extcap(sc->age_dev, PCIY_PMG, &pmc) == 0) {
+ if (pci_find_extcap(sc->age_dev, PCIY_PMG, &pmc) != 0) {
CSR_WRITE_4(sc, AGE_WOL_CFG, 0);
/*
* No PME capability, PHY power down.
@@ -1524,6 +1491,9 @@ age_resume(device_t dev)
cmd &= ~0x0400;
pci_write_config(sc->age_dev, PCIR_COMMAND, cmd, 2);
}
+ AGE_UNLOCK(sc);
+ age_phy_reset(sc);
+ AGE_LOCK(sc);
ifp = sc->age_ifp;
if ((ifp->if_flags & IFF_UP) != 0)
age_init_locked(sc);
@@ -2544,14 +2514,8 @@ age_reset(struct age_softc *sc)
int i;
CSR_WRITE_4(sc, AGE_MASTER_CFG, MASTER_RESET);
- for (i = AGE_RESET_TIMEOUT; i > 0; i--) {
- DELAY(1);
- if ((CSR_READ_4(sc, AGE_MASTER_CFG) & MASTER_RESET) == 0)
- break;
- }
- if (i == 0)
- device_printf(sc->age_dev, "master reset timeout!\n");
-
+ CSR_READ_4(sc, AGE_MASTER_CFG);
+ DELAY(1000);
for (i = AGE_RESET_TIMEOUT; i > 0; i--) {
if ((reg = CSR_READ_4(sc, AGE_IDLE_STATUS)) == 0)
break;
diff --git a/sys/dev/age/if_agereg.h b/sys/dev/age/if_agereg.h
index 091eff1..284e5a4 100644
--- a/sys/dev/age/if_agereg.h
+++ b/sys/dev/age/if_agereg.h
@@ -91,6 +91,9 @@
#define AGE_SPI_OP_READ 0x217 /* 8bits */
#define AGE_TWSI_CTRL 0x218
+#define TWSI_CTRL_SW_LD_START 0x00000800
+#define TWSI_CTRL_HW_LD_START 0x00001000
+#define TWSI_CTRL_LD_EXIST 0x00400000
#define AGE_DEV_MISC_CTRL 0x21C
diff --git a/sys/dev/agp/agp.c b/sys/dev/agp/agp.c
index af34d14..560d3d8 100644
--- a/sys/dev/agp/agp.c
+++ b/sys/dev/agp/agp.c
@@ -532,7 +532,7 @@ agp_generic_bind_memory(device_t dev, struct agp_memory *mem,
int error;
/* Do some sanity checks first. */
- if (offset < 0 || (offset & (AGP_PAGE_SIZE - 1)) != 0 ||
+ if ((offset & (AGP_PAGE_SIZE - 1)) != 0 ||
offset + mem->am_size > AGP_GET_APERTURE(dev)) {
device_printf(dev, "binding memory at bad offset %#x\n",
(int)offset);
diff --git a/sys/dev/agp/agp_amd64.c b/sys/dev/agp/agp_amd64.c
index c68847a..e2bfa67 100644
--- a/sys/dev/agp/agp_amd64.c
+++ b/sys/dev/agp/agp_amd64.c
@@ -337,7 +337,7 @@ agp_amd64_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical)
{
struct agp_amd64_softc *sc = device_get_softc(dev);
- if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
return (EINVAL);
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] =
@@ -351,7 +351,7 @@ agp_amd64_unbind_page(device_t dev, vm_offset_t offset)
{
struct agp_amd64_softc *sc = device_get_softc(dev);
- if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
return (EINVAL);
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
diff --git a/sys/dev/agp/agp_i810.c b/sys/dev/agp/agp_i810.c
index 48cf171..891bfff 100644
--- a/sys/dev/agp/agp_i810.c
+++ b/sys/dev/agp/agp_i810.c
@@ -840,7 +840,7 @@ agp_i810_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical)
{
struct agp_i810_softc *sc = device_get_softc(dev);
- if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
+ if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT)) {
device_printf(dev, "failed: offset is 0x%08jx, shift is %d, entries is %d\n", (intmax_t)offset, AGP_PAGE_SHIFT, sc->gatt->ag_entries);
return EINVAL;
}
@@ -862,7 +862,7 @@ agp_i810_unbind_page(device_t dev, vm_offset_t offset)
{
struct agp_i810_softc *sc = device_get_softc(dev);
- if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
return EINVAL;
if ( sc->chiptype != CHIP_I810 ) {
@@ -1016,7 +1016,7 @@ agp_i810_bind_memory(device_t dev, struct agp_memory *mem,
vm_offset_t i;
/* Do some sanity checks first. */
- if (offset < 0 || (offset & (AGP_PAGE_SIZE - 1)) != 0 ||
+ if ((offset & (AGP_PAGE_SIZE - 1)) != 0 ||
offset + mem->am_size > AGP_GET_APERTURE(dev)) {
device_printf(dev, "binding memory at bad offset %#x\n",
(int)offset);
diff --git a/sys/dev/agp/agp_intel.c b/sys/dev/agp/agp_intel.c
index 3463d82..ac10c8e 100644
--- a/sys/dev/agp/agp_intel.c
+++ b/sys/dev/agp/agp_intel.c
@@ -371,7 +371,7 @@ agp_intel_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical)
sc = device_get_softc(dev);
- if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
return (EINVAL);
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical | 0x17;
@@ -385,7 +385,7 @@ agp_intel_unbind_page(device_t dev, vm_offset_t offset)
sc = device_get_softc(dev);
- if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
return (EINVAL);
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
diff --git a/sys/dev/agp/agp_via.c b/sys/dev/agp/agp_via.c
index 2873692..76ce382 100644
--- a/sys/dev/agp/agp_via.c
+++ b/sys/dev/agp/agp_via.c
@@ -362,7 +362,7 @@ agp_via_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical)
{
struct agp_via_softc *sc = device_get_softc(dev);
- if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
return EINVAL;
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical;
@@ -374,7 +374,7 @@ agp_via_unbind_page(device_t dev, vm_offset_t offset)
{
struct agp_via_softc *sc = device_get_softc(dev);
- if (offset < 0 || offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
+ if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
return EINVAL;
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
diff --git a/sys/dev/k8temp/k8temp.c b/sys/dev/amdtemp/amdtemp.c
index 35cca98..fdf0875 100644
--- a/sys/dev/k8temp/k8temp.c
+++ b/sys/dev/amdtemp/amdtemp.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2008 Rui Paulo <rpaulo@FreeBSD.org>
+ * Copyright (c) 2008, 2009 Rui Paulo <rpaulo@FreeBSD.org>
+ * Copyright (c) 2009 Norikatsu Shigemura <nork@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,8 +26,8 @@
*/
/*
- * Driver for the AMD K8 thermal sensors. Based on a Linux driver by the
- * same name.
+ * Driver for the AMD K8/K10/K11 thermal sensors. Initially based on the
+ * k8temp Linux driver.
*/
#include <sys/cdefs.h>
@@ -48,77 +49,92 @@ __FBSDID("$FreeBSD$");
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-struct k8temp_softc {
+typedef enum {
+ SENSOR0_CORE0,
+ SENSOR0_CORE1,
+ SENSOR1_CORE0,
+ SENSOR1_CORE1,
+ CORE0,
+ CORE1
+} amdsensor_t;
+
+struct amdtemp_softc {
device_t sc_dev;
int sc_temps[4];
int sc_ntemps;
struct sysctl_oid *sc_oid;
struct sysctl_oid *sc_sysctl_cpu[2];
struct intr_config_hook sc_ich;
+ int32_t (*sc_gettemp)(device_t, amdsensor_t);
};
#define VENDORID_AMD 0x1022
-#define DEVICEID_AMD_MISC 0x1103
-
-static struct k8temp_product {
- uint16_t k8temp_vendorid;
- uint16_t k8temp_deviceid;
-} k8temp_products[] = {
- { VENDORID_AMD, DEVICEID_AMD_MISC },
+#define DEVICEID_AMD_MISC0F 0x1103
+#define DEVICEID_AMD_MISC10 0x1203
+#define DEVICEID_AMD_MISC11 0x1303
+
+static struct amdtemp_product {
+ uint16_t amdtemp_vendorid;
+ uint16_t amdtemp_deviceid;
+} amdtemp_products[] = {
+ { VENDORID_AMD, DEVICEID_AMD_MISC0F },
+ { VENDORID_AMD, DEVICEID_AMD_MISC10 },
+ { VENDORID_AMD, DEVICEID_AMD_MISC11 },
{ 0, 0 }
};
/*
- * Register control
+ * Register control (K8 family)
*/
-#define K8TEMP_REG 0xe4
-#define K8TEMP_REG_SELSENSOR 0x40
-#define K8TEMP_REG_SELCORE 0x04
+#define AMDTEMP_REG0F 0xe4
+#define AMDTEMP_REG_SELSENSOR 0x40
+#define AMDTEMP_REG_SELCORE 0x04
-#define K8TEMP_MINTEMP 49 /* -49 C is the mininum temperature */
+/*
+ * Register control (K10 & K11) family
+ */
+#define AMDTEMP_REG 0xa4
-typedef enum {
- SENSOR0_CORE0,
- SENSOR0_CORE1,
- SENSOR1_CORE0,
- SENSOR1_CORE1,
- CORE0,
- CORE1
-} k8sensor_t;
+#define TZ_ZEROC 2732
+
+ /* -49 C is the mininum temperature */
+#define AMDTEMP_OFFSET0F (TZ_ZEROC-490)
+#define AMDTEMP_OFFSET (TZ_ZEROC)
/*
* Device methods.
*/
-static void k8temp_identify(driver_t *driver, device_t parent);
-static int k8temp_probe(device_t dev);
-static int k8temp_attach(device_t dev);
-static void k8temp_intrhook(void *arg);
-static int k8temp_detach(device_t dev);
-static int k8temp_match(device_t dev);
-static int32_t k8temp_gettemp(device_t dev, k8sensor_t sensor);
-static int k8temp_sysctl(SYSCTL_HANDLER_ARGS);
-
-static device_method_t k8temp_methods[] = {
+static void amdtemp_identify(driver_t *driver, device_t parent);
+static int amdtemp_probe(device_t dev);
+static int amdtemp_attach(device_t dev);
+static void amdtemp_intrhook(void *arg);
+static int amdtemp_detach(device_t dev);
+static int amdtemp_match(device_t dev);
+static int32_t amdtemp_gettemp0f(device_t dev, amdsensor_t sensor);
+static int32_t amdtemp_gettemp(device_t dev, amdsensor_t sensor);
+static int amdtemp_sysctl(SYSCTL_HANDLER_ARGS);
+
+static device_method_t amdtemp_methods[] = {
/* Device interface */
- DEVMETHOD(device_identify, k8temp_identify),
- DEVMETHOD(device_probe, k8temp_probe),
- DEVMETHOD(device_attach, k8temp_attach),
- DEVMETHOD(device_detach, k8temp_detach),
+ DEVMETHOD(device_identify, amdtemp_identify),
+ DEVMETHOD(device_probe, amdtemp_probe),
+ DEVMETHOD(device_attach, amdtemp_attach),
+ DEVMETHOD(device_detach, amdtemp_detach),
{0, 0}
};
-static driver_t k8temp_driver = {
- "k8temp",
- k8temp_methods,
- sizeof(struct k8temp_softc),
+static driver_t amdtemp_driver = {
+ "amdtemp",
+ amdtemp_methods,
+ sizeof(struct amdtemp_softc),
};
-static devclass_t k8temp_devclass;
-DRIVER_MODULE(k8temp, hostb, k8temp_driver, k8temp_devclass, NULL, NULL);
+static devclass_t amdtemp_devclass;
+DRIVER_MODULE(amdtemp, hostb, amdtemp_driver, amdtemp_devclass, NULL, NULL);
static int
-k8temp_match(device_t dev)
+amdtemp_match(device_t dev)
{
int i;
uint16_t vendor, devid;
@@ -126,9 +142,9 @@ k8temp_match(device_t dev)
vendor = pci_get_vendor(dev);
devid = pci_get_device(dev);
- for (i = 0; k8temp_products[i].k8temp_vendorid != 0; i++) {
- if (vendor == k8temp_products[i].k8temp_vendorid &&
- devid == k8temp_products[i].k8temp_deviceid)
+ for (i = 0; amdtemp_products[i].amdtemp_vendorid != 0; i++) {
+ if (vendor == amdtemp_products[i].amdtemp_vendorid &&
+ devid == amdtemp_products[i].amdtemp_deviceid)
return (1);
}
@@ -136,28 +152,28 @@ k8temp_match(device_t dev)
}
static void
-k8temp_identify(driver_t *driver, device_t parent)
+amdtemp_identify(driver_t *driver, device_t parent)
{
device_t child;
/* Make sure we're not being doubly invoked. */
- if (device_find_child(parent, "k8temp", -1) != NULL)
+ if (device_find_child(parent, "amdtemp", -1) != NULL)
return;
- if (k8temp_match(parent)) {
- child = device_add_child(parent, "k8temp", -1);
+ if (amdtemp_match(parent)) {
+ child = device_add_child(parent, "amdtemp", -1);
if (child == NULL)
- device_printf(parent, "add k8temp child failed\n");
+ device_printf(parent, "add amdtemp child failed\n");
}
}
static int
-k8temp_probe(device_t dev)
+amdtemp_probe(device_t dev)
{
uint32_t regs[4];
- if (resource_disabled("k8temp", 0))
+ if (resource_disabled("amdtemp", 0))
return (ENXIO);
do_cpuid(1, regs);
@@ -173,9 +189,9 @@ k8temp_probe(device_t dev)
}
static int
-k8temp_attach(device_t dev)
+amdtemp_attach(device_t dev)
{
- struct k8temp_softc *sc = device_get_softc(dev);
+ struct amdtemp_softc *sc = device_get_softc(dev);
struct sysctl_ctx_list *sysctlctx;
struct sysctl_oid *sysctlnode;
@@ -185,7 +201,7 @@ k8temp_attach(device_t dev)
* needed because the cpu driver may be loaded late on boot, after
* us.
*/
- sc->sc_ich.ich_func = k8temp_intrhook;
+ sc->sc_ich.ich_func = amdtemp_intrhook;
sc->sc_ich.ich_arg = dev;
if (config_intrhook_establish(&sc->sc_ich) != 0) {
device_printf(dev, "config_intrhook_establish "
@@ -193,8 +209,15 @@ k8temp_attach(device_t dev)
return (ENXIO);
}
+ if (pci_get_device(dev) == DEVICEID_AMD_MISC0F)
+ sc->sc_gettemp = amdtemp_gettemp0f;
+ else {
+ sc->sc_gettemp = amdtemp_gettemp;
+ return (0);
+ }
+
/*
- * dev.k8temp.N tree.
+ * dev.amdtemp.N tree.
*/
sysctlctx = device_get_sysctl_ctx(dev);
sysctlnode = SYSCTL_ADD_NODE(sysctlctx,
@@ -204,13 +227,13 @@ k8temp_attach(device_t dev)
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sysctlnode),
OID_AUTO, "core0", CTLTYPE_INT | CTLFLAG_RD,
- dev, SENSOR0_CORE0, k8temp_sysctl, "I",
+ dev, SENSOR0_CORE0, amdtemp_sysctl, "IK",
"Sensor 0 / Core 0 temperature");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sysctlnode),
OID_AUTO, "core1", CTLTYPE_INT | CTLFLAG_RD,
- dev, SENSOR0_CORE1, k8temp_sysctl, "I",
+ dev, SENSOR0_CORE1, amdtemp_sysctl, "IK",
"Sensor 0 / Core 1 temperature");
sysctlnode = SYSCTL_ADD_NODE(sysctlctx,
@@ -220,25 +243,25 @@ k8temp_attach(device_t dev)
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sysctlnode),
OID_AUTO, "core0", CTLTYPE_INT | CTLFLAG_RD,
- dev, SENSOR1_CORE0, k8temp_sysctl, "I",
+ dev, SENSOR1_CORE0, amdtemp_sysctl, "IK",
"Sensor 1 / Core 0 temperature");
SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(sysctlnode),
OID_AUTO, "core1", CTLTYPE_INT | CTLFLAG_RD,
- dev, SENSOR1_CORE1, k8temp_sysctl, "I",
+ dev, SENSOR1_CORE1, amdtemp_sysctl, "IK",
"Sensor 1 / Core 1 temperature");
return (0);
}
void
-k8temp_intrhook(void *arg)
+amdtemp_intrhook(void *arg)
{
int i;
device_t nexus, acpi, cpu;
device_t dev = (device_t) arg;
- struct k8temp_softc *sc;
+ struct amdtemp_softc *sc;
struct sysctl_ctx_list *sysctlctx;
sc = device_get_softc(dev);
@@ -258,7 +281,7 @@ k8temp_intrhook(void *arg)
sc->sc_sysctl_cpu[i] = SYSCTL_ADD_PROC(sysctlctx,
SYSCTL_CHILDREN(device_get_sysctl_tree(cpu)),
OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD,
- dev, CORE0, k8temp_sysctl, "I",
+ dev, CORE0, amdtemp_sysctl, "IK",
"Max of sensor 0 / 1");
}
}
@@ -266,41 +289,42 @@ k8temp_intrhook(void *arg)
}
int
-k8temp_detach(device_t dev)
+amdtemp_detach(device_t dev)
{
int i;
- struct k8temp_softc *sc = device_get_softc(dev);
+ struct amdtemp_softc *sc = device_get_softc(dev);
for (i = 0; i < 2; i++) {
if (sc->sc_sysctl_cpu[i])
sysctl_remove_oid(sc->sc_sysctl_cpu[i], 1, 0);
}
- /* NewBus removes the dev.k8temp.N tree by itself. */
+ /* NewBus removes the dev.amdtemp.N tree by itself. */
return (0);
}
static int
-k8temp_sysctl(SYSCTL_HANDLER_ARGS)
+amdtemp_sysctl(SYSCTL_HANDLER_ARGS)
{
device_t dev = (device_t) arg1;
+ struct amdtemp_softc *sc = device_get_softc(dev);
int error;
int32_t temp, auxtemp[2];
switch (arg2) {
case CORE0:
- auxtemp[0] = k8temp_gettemp(dev, SENSOR0_CORE0);
- auxtemp[1] = k8temp_gettemp(dev, SENSOR1_CORE0);
+ auxtemp[0] = sc->sc_gettemp(dev, SENSOR0_CORE0);
+ auxtemp[1] = sc->sc_gettemp(dev, SENSOR1_CORE0);
temp = imax(auxtemp[0], auxtemp[1]);
break;
case CORE1:
- auxtemp[0] = k8temp_gettemp(dev, SENSOR0_CORE1);
- auxtemp[1] = k8temp_gettemp(dev, SENSOR1_CORE1);
+ auxtemp[0] = sc->sc_gettemp(dev, SENSOR0_CORE1);
+ auxtemp[1] = sc->sc_gettemp(dev, SENSOR1_CORE1);
temp = imax(auxtemp[0], auxtemp[1]);
break;
default:
- temp = k8temp_gettemp(dev, arg2);
+ temp = sc->sc_gettemp(dev, arg2);
break;
}
error = sysctl_handle_int(oidp, &temp, 0, req);
@@ -309,34 +333,45 @@ k8temp_sysctl(SYSCTL_HANDLER_ARGS)
}
static int32_t
-k8temp_gettemp(device_t dev, k8sensor_t sensor)
+amdtemp_gettemp0f(device_t dev, amdsensor_t sensor)
{
uint8_t cfg;
uint32_t temp;
- cfg = pci_read_config(dev, K8TEMP_REG, 1);
+ cfg = pci_read_config(dev, AMDTEMP_REG0F, 1);
switch (sensor) {
case SENSOR0_CORE0:
- cfg &= ~(K8TEMP_REG_SELSENSOR | K8TEMP_REG_SELCORE);
+ cfg &= ~(AMDTEMP_REG_SELSENSOR | AMDTEMP_REG_SELCORE);
break;
case SENSOR0_CORE1:
- cfg &= ~K8TEMP_REG_SELSENSOR;
- cfg |= K8TEMP_REG_SELCORE;
+ cfg &= ~AMDTEMP_REG_SELSENSOR;
+ cfg |= AMDTEMP_REG_SELCORE;
break;
case SENSOR1_CORE0:
- cfg &= ~K8TEMP_REG_SELCORE;
- cfg |= K8TEMP_REG_SELSENSOR;
+ cfg &= ~AMDTEMP_REG_SELCORE;
+ cfg |= AMDTEMP_REG_SELSENSOR;
break;
case SENSOR1_CORE1:
- cfg |= (K8TEMP_REG_SELSENSOR | K8TEMP_REG_SELCORE);
+ cfg |= (AMDTEMP_REG_SELSENSOR | AMDTEMP_REG_SELCORE);
break;
default:
cfg = 0;
break;
}
- pci_write_config(dev, K8TEMP_REG, cfg, 1);
- temp = pci_read_config(dev, K8TEMP_REG, 4);
- temp = ((temp >> 16) & 0xff) - K8TEMP_MINTEMP;
+ pci_write_config(dev, AMDTEMP_REG0F, cfg, 1);
+ temp = pci_read_config(dev, AMDTEMP_REG0F, 4);
+ temp = ((temp >> 16) & 0xff) * 10 + AMDTEMP_OFFSET0F;
return (temp);
}
+
+static int32_t
+amdtemp_gettemp(device_t dev, amdsensor_t sensor)
+{
+ uint32_t temp;
+
+ temp = pci_read_config(dev, AMDTEMP_REG, 4);
+ temp = ((temp >> 21) & 0x3ff) * 10 / 8 + AMDTEMP_OFFSET;
+
+ return (temp);
+}
diff --git a/sys/dev/ata/ata-pci.c b/sys/dev/ata/ata-pci.c
index 97261d2..5fe26a8 100644
--- a/sys/dev/ata/ata-pci.c
+++ b/sys/dev/ata/ata-pci.c
@@ -584,22 +584,35 @@ ata_pcichannel_detach(device_t dev)
static int
ata_pcichannel_suspend(device_t dev)
{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
+ int error;
if (!ch->attached)
return (0);
- return ata_suspend(dev);
+ if ((error = ata_suspend(dev)))
+ return (error);
+
+ if (ctlr->ch_suspend != NULL && (error = ctlr->ch_suspend(dev)))
+ return (error);
+
+ return (0);
}
static int
ata_pcichannel_resume(device_t dev)
{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
+ int error;
if (!ch->attached)
return (0);
+ if (ctlr->ch_resume != NULL && (error = ctlr->ch_resume(dev)))
+ return (error);
+
return ata_resume(dev);
}
diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h
index 27a341e..9e31bc7 100644
--- a/sys/dev/ata/ata-pci.h
+++ b/sys/dev/ata/ata-pci.h
@@ -57,6 +57,8 @@ struct ata_pci_controller {
int (*resume)(device_t);
int (*ch_attach)(device_t);
int (*ch_detach)(device_t);
+ int (*ch_suspend)(device_t);
+ int (*ch_resume)(device_t);
int (*locking)(device_t, int);
void (*reset)(device_t);
void (*setmode)(device_t, int);
@@ -443,7 +445,9 @@ int ata_mode2idx(int mode);
/* global prototypes ata-sata.c */
void ata_sata_phy_check_events(device_t dev);
-int ata_sata_phy_reset(device_t dev);
+int ata_sata_scr_read(struct ata_channel *ch, int port, int reg, uint32_t *val);
+int ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val);
+int ata_sata_phy_reset(device_t dev, int port, int quick);
void ata_sata_setmode(device_t dev, int mode);
int ata_request2fis_h2d(struct ata_request *request, u_int8_t *fis);
void ata_pm_identify(device_t dev);
@@ -452,6 +456,8 @@ void ata_pm_identify(device_t dev);
int ata_ahci_chipinit(device_t);
int ata_ahci_ch_attach(device_t dev);
int ata_ahci_ch_detach(device_t dev);
+int ata_ahci_ch_suspend(device_t dev);
+int ata_ahci_ch_resume(device_t dev);
void ata_ahci_reset(device_t dev);
int ata_marvell_edma_chipinit(device_t);
int ata_sii_chipinit(device_t);
diff --git a/sys/dev/ata/ata-queue.c b/sys/dev/ata/ata-queue.c
index 707dfe9..4a4bb19 100644
--- a/sys/dev/ata/ata-queue.c
+++ b/sys/dev/ata/ata-queue.c
@@ -444,8 +444,7 @@ ata_completed(void *context, int dummy)
}
if (!request->result &&
- (request->u.atapi.sense.key & ATA_SENSE_KEY_MASK ?
- request->u.atapi.sense.key & ATA_SENSE_KEY_MASK :
+ (request->u.atapi.sense.key & ATA_SENSE_KEY_MASK ||
request->error))
request->result = EIO;
}
diff --git a/sys/dev/ata/ata-sata.c b/sys/dev/ata/ata-sata.c
index 642a94e..1151ca1 100644
--- a/sys/dev/ata/ata-sata.c
+++ b/sys/dev/ata/ata-sata.c
@@ -73,59 +73,141 @@ ata_sata_phy_check_events(device_t dev)
}
}
+int
+ata_sata_scr_read(struct ata_channel *ch, int port, int reg, uint32_t *val)
+{
+ int r;
+
+ if (port < 0) {
+ *val = ATA_IDX_INL(ch, reg);
+ return (0);
+ } else {
+ switch (reg) {
+ case ATA_SSTATUS:
+ r = 0;
+ break;
+ case ATA_SERROR:
+ r = 1;
+ break;
+ case ATA_SCONTROL:
+ r = 2;
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (ch->hw.pm_read(ch->dev, port, r, val));
+ }
+}
+
+int
+ata_sata_scr_write(struct ata_channel *ch, int port, int reg, uint32_t val)
+{
+ int r;
+
+ if (port < 0) {
+ ATA_IDX_OUTL(ch, reg, val);
+ return (0);
+ } else {
+ switch (reg) {
+ case ATA_SERROR:
+ r = 1;
+ break;
+ case ATA_SCONTROL:
+ r = 2;
+ break;
+ default:
+ return (EINVAL);
+ }
+ return (ch->hw.pm_write(ch->dev, port, r, val));
+ }
+}
+
static int
-ata_sata_connect(struct ata_channel *ch)
+ata_sata_connect(struct ata_channel *ch, int port)
{
u_int32_t status;
int timeout;
/* wait up to 1 second for "connect well" */
for (timeout = 0; timeout < 100 ; timeout++) {
- status = ATA_IDX_INL(ch, ATA_SSTATUS);
+ if (ata_sata_scr_read(ch, port, ATA_SSTATUS, &status))
+ return (0);
if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
(status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)
break;
ata_udelay(10000);
}
if (timeout >= 100) {
- if (bootverbose)
- device_printf(ch->dev, "SATA connect status=%08x\n", status);
+ if (bootverbose) {
+ if (port < 0) {
+ device_printf(ch->dev, "SATA connect timeout status=%08x\n",
+ status);
+ } else {
+ device_printf(ch->dev, "p%d: SATA connect timeout status=%08x\n",
+ port, status);
+ }
+ }
return 0;
}
- if (bootverbose)
- device_printf(ch->dev, "SATA connect time=%dms\n", timeout * 10);
+ if (bootverbose) {
+ if (port < 0) {
+ device_printf(ch->dev, "SATA connect time=%dms status=%08x\n",
+ timeout * 10, status);
+ } else {
+ device_printf(ch->dev, "p%d: SATA connect time=%dms status=%08x\n",
+ port, timeout * 10, status);
+ }
+ }
/* clear SATA error register */
- ATA_IDX_OUTL(ch, ATA_SERROR, ATA_IDX_INL(ch, ATA_SERROR));
+ ata_sata_scr_write(ch, port, ATA_SERROR, 0xffffffff);
return 1;
}
int
-ata_sata_phy_reset(device_t dev)
+ata_sata_phy_reset(device_t dev, int port, int quick)
{
struct ata_channel *ch = device_get_softc(dev);
int loop, retry;
+ uint32_t val;
- if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE)
- return ata_sata_connect(ch);
+ if (quick) {
+ if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
+ return (0);
+ if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_IDLE)
+ return ata_sata_connect(ch, port);
+ }
+ if (bootverbose) {
+ if (port < 0) {
+ device_printf(dev, "hardware reset ...\n");
+ } else {
+ device_printf(dev, "p%d: hardware reset ...\n", port);
+ }
+ }
for (retry = 0; retry < 10; retry++) {
for (loop = 0; loop < 10; loop++) {
- ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_RESET);
+ if (ata_sata_scr_write(ch, port, ATA_SCONTROL, ATA_SC_DET_RESET))
+ return (0);
ata_udelay(100);
- if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) ==
- ATA_SC_DET_RESET)
+ if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
+ return (0);
+ if ((val & ATA_SC_DET_MASK) == ATA_SC_DET_RESET)
break;
}
ata_udelay(5000);
for (loop = 0; loop < 10; loop++) {
- ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_IDLE |
- ATA_SC_IPM_DIS_PARTIAL |
- ATA_SC_IPM_DIS_SLUMBER);
+ if (ata_sata_scr_write(ch, port, ATA_SCONTROL,
+ ATA_SC_DET_IDLE |
+ ATA_SC_IPM_DIS_PARTIAL |
+ ATA_SC_IPM_DIS_SLUMBER))
+ return (0);
ata_udelay(100);
- if ((ATA_IDX_INL(ch, ATA_SCONTROL) & ATA_SC_DET_MASK) == 0)
- return ata_sata_connect(ch);
+ if (ata_sata_scr_read(ch, port, ATA_SCONTROL, &val))
+ return (0);
+ if ((val & ATA_SC_DET_MASK) == 0)
+ return ata_sata_connect(ch, port);
}
}
return 0;
@@ -237,14 +319,27 @@ ata_pm_identify(device_t dev)
/* chip specific quirks */
switch (pm_chipid) {
case 0x37261095:
- /* Some of these bogusly reports 6 ports */
+ /* This PM declares 6 ports, while only 5 of them are real.
+ * Port 5 is enclosure management bridge port, which has implementation
+ * problems, causing probe faults. Hide it for now. */
+ device_printf(dev, "SiI 3726 (rev=%x) Port Multiplier with %d (5) ports\n",
+ pm_revision, pm_ports);
pm_ports = 5;
- device_printf(dev, "SiI 3726 r%x Portmultiplier with %d ports\n",
+ break;
+
+ case 0x47261095:
+ /* This PM declares 7 ports, while only 5 of them are real.
+ * Port 5 is some fake "Config Disk" with 640 sectors size,
+ * port 6 is enclosure management bridge port.
+ * Both fake ports has implementation problems, causing
+ * probe faults. Hide them for now. */
+ device_printf(dev, "SiI 4726 (rev=%x) Port Multiplier with %d (5) ports\n",
pm_revision, pm_ports);
+ pm_ports = 5;
break;
default:
- device_printf(dev, "Portmultiplier (id=%08x rev=%x) with %d ports\n",
+ device_printf(dev, "Port Multiplier (id=%08x rev=%x) with %d ports\n",
pm_chipid, pm_revision, pm_ports);
}
@@ -253,41 +348,17 @@ ata_pm_identify(device_t dev)
/* reset all ports and register if anything connected */
for (port=0; port < pm_ports; port++) {
- u_int32_t signature, status;
- int timeout;
+ u_int32_t signature;
- if (ch->hw.pm_write(dev, port, 2, ATA_SC_DET_RESET)) {
- device_printf(dev, "p%d: writing ATA_SC_DET_RESET failed\n", port);
+ if (!ata_sata_phy_reset(dev, port, 1))
continue;
- }
-
- ata_udelay(5000);
-
- if (ch->hw.pm_write(dev, port, 2, ATA_SC_DET_IDLE)) {
- device_printf(dev, "p%d: writing ATA_SC_DET_idle failed\n", port);
- continue;
- }
-
- ata_udelay(5000);
-
- /* wait up to 1 second for "connect well" */
- for (timeout = 0; timeout < 100 ; timeout++) {
- ch->hw.pm_read(dev, port, 0, &status);
- if ((status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN1 ||
- (status & ATA_SS_CONWELL_MASK) == ATA_SS_CONWELL_GEN2)
- break;
- ata_udelay(10000);
- }
- if (timeout >= 100) {
- if (bootverbose)
- device_printf(dev, "p%d: connect status=%08x\n", port, status);
- continue;
- }
- if (bootverbose)
- device_printf(dev, "p%d: connect time %dms\n", port, timeout * 10);
- /* clear SERROR register */
- ch->hw.pm_write(dev, port, 1, 0xffffffff);
+ /*
+ * XXX: I have no idea how to properly wait for PMP port hardreset
+ * completion. Without this delay soft reset does not completes
+ * successfully.
+ */
+ DELAY(1000000);
signature = ch->hw.softreset(dev, port);
diff --git a/sys/dev/ata/chipsets/ata-ahci.c b/sys/dev/ata/chipsets/ata-ahci.c
index 991d2ad..9e78132 100644
--- a/sys/dev/ata/chipsets/ata-ahci.c
+++ b/sys/dev/ata/chipsets/ata-ahci.c
@@ -59,10 +59,16 @@ static int ata_ahci_begin_transaction(struct ata_request *request);
static int ata_ahci_end_transaction(struct ata_request *request);
static int ata_ahci_pm_read(device_t dev, int port, int reg, u_int32_t *result);
static int ata_ahci_pm_write(device_t dev, int port, int reg, u_int32_t result);
+static int ata_ahci_hardreset(device_t dev, int port, uint32_t *signature);
static u_int32_t ata_ahci_softreset(device_t dev, int port);
static void ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
static int ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *equest);
static void ata_ahci_dmainit(device_t dev);
+static void ata_ahci_start(device_t dev);
+static void ata_ahci_stop(device_t dev);
+static void ata_ahci_clo(device_t dev);
+static void ata_ahci_start_fr(device_t dev);
+static void ata_ahci_stop_fr(device_t dev);
/*
* AHCI v1.x compliant SATA chipset support functions
@@ -131,6 +137,8 @@ ata_ahci_chipinit(device_t dev)
ctlr->reset = ata_ahci_reset;
ctlr->ch_attach = ata_ahci_ch_attach;
ctlr->ch_detach = ata_ahci_ch_detach;
+ ctlr->ch_suspend = ata_ahci_ch_suspend;
+ ctlr->ch_resume = ata_ahci_ch_resume;
ctlr->setmode = ata_sata_setmode;
ctlr->suspend = ata_ahci_suspend;
ctlr->resume = ata_ahci_ctlr_reset;
@@ -192,7 +200,6 @@ ata_ahci_suspend(device_t dev)
return 0;
}
-
int
ata_ahci_ch_attach(device_t dev)
{
@@ -220,12 +227,22 @@ ata_ahci_ch_attach(device_t dev)
ch->hw.pm_read = ata_ahci_pm_read;
ch->hw.pm_write = ata_ahci_pm_write;
+ ata_ahci_ch_resume(dev);
return 0;
}
int
ata_ahci_ch_detach(device_t dev)
{
+
+ ata_ahci_ch_suspend(dev);
+ ata_dmafini(dev);
+ return (0);
+}
+
+int
+ata_ahci_ch_suspend(device_t dev)
+{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
int offset = ch->unit << 7;
@@ -233,6 +250,8 @@ ata_ahci_ch_detach(device_t dev)
/* Disable port interrupts. */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0);
/* Reset command register. */
+ ata_ahci_stop(dev);
+ ata_ahci_stop_fr(dev);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, 0);
/* Allow everything including partial and slumber modes. */
@@ -243,7 +262,35 @@ ata_ahci_ch_detach(device_t dev)
/* Disable PHY. */
ATA_IDX_OUTL(ch, ATA_SCONTROL, ATA_SC_DET_DISABLE);
- ata_dmafini(dev);
+ return (0);
+}
+
+int
+ata_ahci_ch_resume(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ uint64_t work;
+ int offset = ch->unit << 7;
+
+ /* Disable port interrupts */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0);
+
+ /* setup work areas */
+ work = ch->dma.work_bus + ATA_AHCI_CL_OFFSET;
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff);
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32);
+
+ work = ch->dma.work_bus + ATA_AHCI_FB_OFFSET;
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff);
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32);
+
+ /* activate the channel and power/spin up device */
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
+ (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD));
+ ata_ahci_start_fr(dev);
+ ata_ahci_start(dev);
+
return (0);
}
@@ -366,9 +413,6 @@ ata_ahci_begin_transaction(struct ata_request *request)
ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) &
~ATA_AHCI_P_CMD_ATAPI);
- /* set PM port to address */
- //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001);
-
/* issue command to controller */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, (1 << request->tag));
@@ -465,9 +509,6 @@ ata_ahci_issue_cmd(device_t dev, u_int16_t flags, int timeout)
clp->bytecount = 0;
clp->cmd_table_phys = htole64(ch->dma.work_bus + ATA_AHCI_CT_OFFSET);
- /* set PM port */
- //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, (port << 8) | 0x00000001);
-
/* issue command to controller */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CI + offset, 1);
@@ -480,7 +521,7 @@ ata_ahci_issue_cmd(device_t dev, u_int16_t flags, int timeout)
/* clear interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IS + offset,
- ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset));
+ ATA_INL(ctlr->r_res2, ATA_AHCI_P_IS + offset));
if (timeout && (count >= timeout)) {
if (bootverbose) {
@@ -559,7 +600,7 @@ ata_ahci_stop(device_t dev)
/* kill off all activity on this channel */
cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
- cmd & ~(ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST));
+ cmd & ~ATA_AHCI_P_CMD_ST);
/* XXX SOS this is not entirely wrong */
timeout = 0;
@@ -617,10 +658,47 @@ ata_ahci_start(device_t dev)
/* start operations on this channel */
cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
- cmd | (ATA_AHCI_P_CMD_FRE | ATA_AHCI_P_CMD_ST) |
+ cmd | ATA_AHCI_P_CMD_ST |
(ch->devices & ATA_PORTMULTIPLIER ? ATA_AHCI_P_CMD_PMA : 0));
}
+static void
+ata_ahci_stop_fr(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ u_int32_t cmd;
+ int offset = ch->unit << 7;
+ int timeout;
+
+ /* kill off all activity on this channel */
+ cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd & ~ATA_AHCI_P_CMD_FRE);
+
+ timeout = 0;
+ do {
+ DELAY(1000);
+ if (timeout++ > 1000) {
+ device_printf(dev, "stopping AHCI FR engine failed\n");
+ break;
+ }
+ }
+ while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset) & ATA_AHCI_P_CMD_FR);
+}
+
+static void
+ata_ahci_start_fr(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ u_int32_t cmd;
+ int offset = ch->unit << 7;
+
+ /* start FIS reception on this channel */
+ cmd = ATA_INL(ctlr->r_res2, ATA_AHCI_P_CMD + offset);
+ ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset, cmd | ATA_AHCI_P_CMD_FRE);
+}
+
static int
ata_ahci_wait_ready(device_t dev, int t)
{
@@ -628,13 +706,14 @@ ata_ahci_wait_ready(device_t dev, int t)
struct ata_channel *ch = device_get_softc(dev);
int offset = ch->unit << 7;
int timeout = 0;
+ uint32_t val;
- while (ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset) &
+ while ((val = ATA_INL(ctlr->r_res2, ATA_AHCI_P_TFD + offset)) &
(ATA_S_BUSY | ATA_S_DRQ)) {
DELAY(1000);
if (timeout++ > t) {
- device_printf(dev, "port is not ready (timeout %dms)\n", t);
- return (-1);
+ device_printf(dev, "port is not ready (timeout %dms) tfd = %08x\n", t, val);
+ return (EBUSY);
}
}
if (bootverbose)
@@ -642,6 +721,28 @@ ata_ahci_wait_ready(device_t dev, int t)
return (0);
}
+static int
+ata_ahci_hardreset(device_t dev, int port, uint32_t *signature)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ int offset = ch->unit << 7;
+
+ *signature = 0xffffffff;
+ ata_ahci_stop(dev);
+ /* Reset port */
+ if (!ata_sata_phy_reset(dev, port, 0))
+ return (ENOENT);
+ /* Wait for clearing busy status. */
+ if (ata_ahci_wait_ready(dev, 10000)) {
+ device_printf(dev, "hardware reset timeout\n");
+ return (EBUSY);
+ }
+ *signature = ATA_INL(ctlr->r_res2, ATA_AHCI_P_SIG + offset);
+ ata_ahci_start(dev);
+ return (0);
+}
+
static u_int32_t
ata_ahci_softreset(device_t dev, int port)
{
@@ -679,9 +780,9 @@ ata_ahci_softreset(device_t dev, int port)
ctp->cfis[1] = port & 0x0f;
//ctp->cfis[7] = ATA_D_LBA | ATA_D_IBM;
ctp->cfis[15] = ATA_A_4BIT;
- ata_ahci_issue_cmd(dev, 0, 1000);
+ ata_ahci_issue_cmd(dev, 0, 3000);
- if (ata_ahci_wait_ready(dev, 1000)) {
+ if (ata_ahci_wait_ready(dev, 0)) {
device_printf(dev, "software reset clear timeout\n");
return (-1);
}
@@ -694,7 +795,6 @@ ata_ahci_reset(device_t dev)
{
struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
struct ata_channel *ch = device_get_softc(dev);
- u_int64_t work;
u_int32_t signature;
int offset = ch->unit << 7;
@@ -704,25 +804,7 @@ ata_ahci_reset(device_t dev)
/* Disable port interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset, 0);
- /* setup work areas */
- work = ch->dma.work_bus + ATA_AHCI_CL_OFFSET;
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLB + offset, work & 0xffffffff);
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CLBU + offset, work >> 32);
-
- work = ch->dma.work_bus + ATA_AHCI_FB_OFFSET;
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FB + offset, work & 0xffffffff);
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBU + offset, work >> 32);
-
- /* activate the channel and power/spin up device */
- ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_CMD + offset,
- (ATA_AHCI_P_CMD_ACTIVE | ATA_AHCI_P_CMD_POD | ATA_AHCI_P_CMD_SUD));
-
- ata_ahci_stop(dev);
-
- /* enable FIS based switching */
- //ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_FBS + offset, 0x00000003);
-
- if (!ata_sata_phy_reset(dev)) {
+ if (ata_ahci_hardreset(dev, -1, &signature)) {
if (bootverbose)
device_printf(dev, "AHCI reset done: phy reset found no device\n");
ch->devices = 0;
@@ -733,8 +815,6 @@ ata_ahci_reset(device_t dev)
return;
}
- ata_ahci_start(dev);
-
/* enable wanted port interrupts */
ATA_OUTL(ctlr->r_res2, ATA_AHCI_P_IE + offset,
(ATA_AHCI_P_IX_CPD | ATA_AHCI_P_IX_TFE | ATA_AHCI_P_IX_HBF |
@@ -743,9 +823,6 @@ ata_ahci_reset(device_t dev)
ATA_AHCI_P_IX_UF | ATA_AHCI_P_IX_SDB | ATA_AHCI_P_IX_DS |
ATA_AHCI_P_IX_PS | ATA_AHCI_P_IX_DHR));
- /* Wait for initial TFD from device. */
- ata_ahci_wait_ready(dev, 10000);
-
/* only probe for PortMultiplier if HW has support */
if (ATA_INL(ctlr->r_res2, ATA_AHCI_CAP) & ATA_AHCI_CAP_SPM) {
signature = ata_ahci_softreset(dev, ATA_PM);
diff --git a/sys/dev/ata/chipsets/ata-intel.c b/sys/dev/ata/chipsets/ata-intel.c
index 8bd2f03..cae1778 100644
--- a/sys/dev/ata/chipsets/ata-intel.c
+++ b/sys/dev/ata/chipsets/ata-intel.c
@@ -517,7 +517,7 @@ ata_intel_31244_tf_write(struct ata_request *request)
static void
ata_intel_31244_reset(device_t dev)
{
- if (ata_sata_phy_reset(dev))
+ if (ata_sata_phy_reset(dev, -1, 1))
ata_generic_reset(dev);
}
diff --git a/sys/dev/ata/chipsets/ata-jmicron.c b/sys/dev/ata/chipsets/ata-jmicron.c
index 301b99b..b1e7aef 100644
--- a/sys/dev/ata/chipsets/ata-jmicron.c
+++ b/sys/dev/ata/chipsets/ata-jmicron.c
@@ -55,6 +55,8 @@ __FBSDID("$FreeBSD$");
static int ata_jmicron_chipinit(device_t dev);
static int ata_jmicron_ch_attach(device_t dev);
static int ata_jmicron_ch_detach(device_t dev);
+static int ata_jmicron_ch_suspend(device_t dev);
+static int ata_jmicron_ch_resume(device_t dev);
static void ata_jmicron_reset(device_t dev);
static void ata_jmicron_setmode(device_t dev, int mode);
@@ -127,6 +129,8 @@ ata_jmicron_chipinit(device_t dev)
ctlr->ch_attach = ata_jmicron_ch_attach;
ctlr->ch_detach = ata_jmicron_ch_detach;
+ ctlr->ch_suspend = ata_jmicron_ch_suspend;
+ ctlr->ch_resume = ata_jmicron_ch_resume;
ctlr->reset = ata_jmicron_reset;
ctlr->setmode = ata_jmicron_setmode;
@@ -173,6 +177,30 @@ ata_jmicron_ch_detach(device_t dev)
return (error);
}
+static int
+ata_jmicron_ch_suspend(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ int error = 0;
+
+ if (ch->unit < ctlr->chip->cfg1)
+ error = ata_ahci_ch_suspend(dev);
+ return error;
+}
+
+static int
+ata_jmicron_ch_resume(device_t dev)
+{
+ struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
+ struct ata_channel *ch = device_get_softc(dev);
+ int error = 0;
+
+ if (ch->unit < ctlr->chip->cfg1)
+ error = ata_ahci_ch_resume(dev);
+ return (error);
+}
+
static void
ata_jmicron_reset(device_t dev)
{
diff --git a/sys/dev/ata/chipsets/ata-marvell.c b/sys/dev/ata/chipsets/ata-marvell.c
index a0fa485..361bc5b 100644
--- a/sys/dev/ata/chipsets/ata-marvell.c
+++ b/sys/dev/ata/chipsets/ata-marvell.c
@@ -503,7 +503,7 @@ ata_marvell_edma_reset(device_t dev)
ATA_OUTL(ctlr->r_res1, 0x0200c + ATA_MV_EDMA_BASE(ch), ~0x0);
/* enable channel and test for devices */
- if (ata_sata_phy_reset(dev))
+ if (ata_sata_phy_reset(dev, -1, 1))
ata_generic_reset(dev);
/* enable EDMA machinery */
diff --git a/sys/dev/ata/chipsets/ata-nvidia.c b/sys/dev/ata/chipsets/ata-nvidia.c
index 7e03afa..9e1de81 100644
--- a/sys/dev/ata/chipsets/ata-nvidia.c
+++ b/sys/dev/ata/chipsets/ata-nvidia.c
@@ -249,7 +249,7 @@ ata_nvidia_status(device_t dev)
static void
ata_nvidia_reset(device_t dev)
{
- if (ata_sata_phy_reset(dev))
+ if (ata_sata_phy_reset(dev, -1, 1))
ata_generic_reset(dev);
}
diff --git a/sys/dev/ata/chipsets/ata-promise.c b/sys/dev/ata/chipsets/ata-promise.c
index 3856535..6b34596 100644
--- a/sys/dev/ata/chipsets/ata-promise.c
+++ b/sys/dev/ata/chipsets/ata-promise.c
@@ -769,7 +769,7 @@ ata_promise_mio_reset(device_t dev)
if ((ctlr->chip->cfg2 == PR_SATA) ||
((ctlr->chip->cfg2 == PR_CMBO) && (ch->unit < 2))) {
- if (ata_sata_phy_reset(dev))
+ if (ata_sata_phy_reset(dev, -1, 1))
ata_generic_reset(dev);
/* reset and enable plug/unplug intr */
@@ -805,7 +805,7 @@ ata_promise_mio_reset(device_t dev)
(ATA_INL(ctlr->r_res2, 0x414 + (ch->unit << 8)) &
~0x00000003) | 0x00000001);
- if (ata_sata_phy_reset(dev)) {
+ if (ata_sata_phy_reset(dev, -1, 1)) {
u_int32_t signature = ch->hw.softreset(dev, ATA_PM);
if (1 | bootverbose)
diff --git a/sys/dev/ata/chipsets/ata-serverworks.c b/sys/dev/ata/chipsets/ata-serverworks.c
index 366f9a1..c591d3d 100644
--- a/sys/dev/ata/chipsets/ata-serverworks.c
+++ b/sys/dev/ata/chipsets/ata-serverworks.c
@@ -58,6 +58,9 @@ static int ata_serverworks_ch_detach(device_t dev);
static void ata_serverworks_tf_read(struct ata_request *request);
static void ata_serverworks_tf_write(struct ata_request *request);
static void ata_serverworks_setmode(device_t dev, int mode);
+#ifdef __powerpc__
+static int ata_serverworks_status(device_t dev);
+#endif
/* misc defines */
#define SWKS_33 0
@@ -98,6 +101,23 @@ ata_serverworks_probe(device_t dev)
return 0;
}
+#ifdef __powerpc__
+static int
+ata_serverworks_status(device_t dev)
+{
+ struct ata_channel *ch = device_get_softc(dev);
+
+ /*
+ * We need to do a 4-byte read on the status reg before the values
+ * will report correctly
+ */
+
+ ATA_IDX_INL(ch,ATA_STATUS);
+
+ return ata_pci_status(dev);
+}
+#endif
+
static int
ata_serverworks_chipinit(device_t dev)
{
@@ -186,6 +206,9 @@ ata_serverworks_ch_attach(device_t dev)
ata_pci_hw(dev);
ch->hw.tf_read = ata_serverworks_tf_read;
ch->hw.tf_write = ata_serverworks_tf_write;
+#ifdef __powerpc__
+ ch->hw.status = ata_serverworks_status;
+#endif
/* chip does not reliably do 64K DMA transfers */
ch->dma.max_iosize = 64 * DEV_BSIZE;
diff --git a/sys/dev/ata/chipsets/ata-siliconimage.c b/sys/dev/ata/chipsets/ata-siliconimage.c
index f5093c7..b163276 100644
--- a/sys/dev/ata/chipsets/ata-siliconimage.c
+++ b/sys/dev/ata/chipsets/ata-siliconimage.c
@@ -380,7 +380,7 @@ ata_sii_status(device_t dev)
static void
ata_sii_reset(device_t dev)
{
- if (ata_sata_phy_reset(dev))
+ if (ata_sata_phy_reset(dev, -1, 1))
ata_generic_reset(dev);
}
@@ -832,7 +832,7 @@ ata_siiprb_reset(device_t dev)
}
/* reset phy */
- if (!ata_sata_phy_reset(dev)) {
+ if (!ata_sata_phy_reset(dev, -1, 1)) {
if (bootverbose)
device_printf(dev, "phy reset found no device\n");
ch->devices = 0;
diff --git a/sys/dev/ata/chipsets/ata-sis.c b/sys/dev/ata/chipsets/ata-sis.c
index 1d9dac7..8e02ee9 100644
--- a/sys/dev/ata/chipsets/ata-sis.c
+++ b/sys/dev/ata/chipsets/ata-sis.c
@@ -226,7 +226,7 @@ ata_sis_ch_attach(device_t dev)
static void
ata_sis_reset(device_t dev)
{
- if (ata_sata_phy_reset(dev))
+ if (ata_sata_phy_reset(dev, -1, 1))
ata_generic_reset(dev);
}
diff --git a/sys/dev/ata/chipsets/ata-via.c b/sys/dev/ata/chipsets/ata-via.c
index 4530adf..525ca2f 100644
--- a/sys/dev/ata/chipsets/ata-via.c
+++ b/sys/dev/ata/chipsets/ata-via.c
@@ -269,7 +269,7 @@ ata_via_reset(device_t dev)
if ((ctlr->chip->cfg2 & VIABAR) && (ch->unit > 1))
ata_generic_reset(dev);
else
- if (ata_sata_phy_reset(dev))
+ if (ata_sata_phy_reset(dev, -1, 1))
ata_generic_reset(dev);
}
diff --git a/sys/dev/ath/ah_osdep.c b/sys/dev/ath/ah_osdep.c
index c124772..b5880ee 100644
--- a/sys/dev/ath/ah_osdep.c
+++ b/sys/dev/ath/ah_osdep.c
@@ -71,12 +71,7 @@ extern void ath_hal_assert_failed(const char* filename,
int lineno, const char* msg);
#endif
#ifdef AH_DEBUG
-#if HAL_ABI_VERSION >= 0x08090101
extern void HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...);
-#else
-extern void HALDEBUG(struct ath_hal *ah, const char* fmt, ...);
-extern void HALDEBUGn(struct ath_hal *ah, u_int level, const char* fmt, ...);
-#endif
#endif /* AH_DEBUG */
/* NB: put this here instead of the driver to avoid circular references */
@@ -140,7 +135,6 @@ ath_hal_ether_sprintf(const u_int8_t *mac)
}
#ifdef AH_DEBUG
-#if HAL_ABI_VERSION >= 0x08090101
void
HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...)
{
@@ -151,29 +145,6 @@ HALDEBUG(struct ath_hal *ah, u_int mask, const char* fmt, ...)
va_end(ap);
}
}
-#else
-void
-HALDEBUG(struct ath_hal *ah, const char* fmt, ...)
-{
- if (ath_hal_debug) {
- __va_list ap;
- va_start(ap, fmt);
- ath_hal_vprintf(ah, fmt, ap);
- va_end(ap);
- }
-}
-
-void
-HALDEBUGn(struct ath_hal *ah, u_int level, const char* fmt, ...)
-{
- if (ath_hal_debug >= level) {
- __va_list ap;
- va_start(ap, fmt);
- ath_hal_vprintf(ah, fmt, ap);
- va_end(ap);
- }
-}
-#endif
#endif /* AH_DEBUG */
#ifdef AH_DEBUG_ALQ
diff --git a/sys/dev/ath/ath_hal/ah.h b/sys/dev/ath/ath_hal/ah.h
index da9060a..c1bff9c 100644
--- a/sys/dev/ath/ath_hal/ah.h
+++ b/sys/dev/ath/ath_hal/ah.h
@@ -598,8 +598,6 @@ struct ieee80211_channel;
*/
struct ath_hal {
uint32_t ah_magic; /* consistency check magic number */
- uint32_t ah_abi; /* HAL ABI version */
-#define HAL_ABI_VERSION 0x08112800 /* YYMMDDnn */
uint16_t ah_devid; /* PCI device ID */
uint16_t ah_subvendorid; /* PCI subvendor ID */
HAL_SOFTC ah_sc; /* back pointer to driver/os state */
diff --git a/sys/dev/ath/ath_hal/ah_internal.h b/sys/dev/ath/ath_hal/ah_internal.h
index 8b00e30..ef5aba5 100644
--- a/sys/dev/ath/ath_hal/ah_internal.h
+++ b/sys/dev/ath/ath_hal/ah_internal.h
@@ -333,8 +333,10 @@ struct ath_hal_private {
#define ath_hal_disablePCIE(_ah) \
(_ah)->ah_disablePCIE(_ah)
-#define ath_hal_eepromDetach(_ah) \
- AH_PRIVATE(_ah)->ah_eepromDetach(_ah)
+#define ath_hal_eepromDetach(_ah) do { \
+ if (AH_PRIVATE(_ah)->ah_eepromDetach != AH_NULL) \
+ AH_PRIVATE(_ah)->ah_eepromDetach(_ah); \
+} while (0)
#define ath_hal_eepromGet(_ah, _param, _val) \
AH_PRIVATE(_ah)->ah_eepromGet(_ah, _param, _val)
#define ath_hal_eepromSet(_ah, _param, _val) \
diff --git a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c
index 3df3924..13ad711 100644
--- a/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c
+++ b/sys/dev/ath/ath_hal/ar5210/ar5210_attach.c
@@ -38,7 +38,6 @@ static void ar5210DisablePCIE(struct ath_hal *ah);
static const struct ath_hal_private ar5210hal = {{
.ah_magic = AR5210_MAGIC,
- .ah_abi = HAL_ABI_VERSION,
.ah_getRateTable = ar5210GetRateTable,
.ah_detach = ar5210Detach,
diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c
index 81af95f..e55c67a 100644
--- a/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c
+++ b/sys/dev/ath/ath_hal/ar5211/ar5211_attach.c
@@ -38,7 +38,6 @@ static void ar5211DisablePCIE(struct ath_hal *ah);
static const struct ath_hal_private ar5211hal = {{
.ah_magic = AR5211_MAGIC,
- .ah_abi = HAL_ABI_VERSION,
.ah_getRateTable = ar5211GetRateTable,
.ah_detach = ar5211Detach,
diff --git a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
index 742523f..300c0a3 100644
--- a/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
+++ b/sys/dev/ath/ath_hal/ar5212/ar5212_attach.c
@@ -34,7 +34,6 @@ static void ar5212DisablePCIE(struct ath_hal *ah);
static const struct ath_hal_private ar5212hal = {{
.ah_magic = AR5212_MAGIC,
- .ah_abi = HAL_ABI_VERSION,
.ah_getRateTable = ar5212GetRateTable,
.ah_detach = ar5212Detach,
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416.h b/sys/dev/ath/ath_hal/ar5416/ar5416.h
index 27aa9e8..a02f732 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416.h
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416.h
@@ -45,6 +45,8 @@ typedef struct {
#define AR5416_CCA_MAX_HIGH_VALUE -62
#define AR5416_CCA_MIN_BAD_VALUE -140
+#define AR5416_SPUR_RSSI_THRESH 40
+
struct ath_hal_5416 {
struct ath_hal_5212 ah_5212;
@@ -59,6 +61,11 @@ struct ath_hal_5416 {
HAL_INI_ARRAY ah_ini_addac;
HAL_INI_ARRAY ah_ini_pcieserdes;
+ void (*ah_writeIni)(struct ath_hal *,
+ const struct ieee80211_channel *);
+ void (*ah_spurMitigate)(struct ath_hal *,
+ const struct ieee80211_channel *);
+
u_int ah_globaltxtimeout; /* global tx timeout */
u_int ah_gpioMask;
int ah_hangs; /* h/w hangs state */
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
index 8328a4e..1130529 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c
@@ -22,6 +22,8 @@
#include "ah_internal.h"
#include "ah_devid.h"
+#include "ah_eeprom_v14.h"
+
#include "ar5416/ar5416.h"
#include "ar5416/ar5416reg.h"
#include "ar5416/ar5416phy.h"
@@ -29,6 +31,10 @@
#include "ar5416/ar5416.ini"
static void ar5416ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore);
+static void ar5416WriteIni(struct ath_hal *ah,
+ const struct ieee80211_channel *chan);
+static void ar5416SpurMitigate(struct ath_hal *ah,
+ const struct ieee80211_channel *chan);
static void
ar5416AniSetup(struct ath_hal *ah)
@@ -152,6 +158,8 @@ ar5416InitState(struct ath_hal_5416 *ahp5416, uint16_t devid, HAL_SOFTC sc,
#endif
ahp->ah_priv.ah_getChipPowerLimits = ar5416GetChipPowerLimits;
+ AH5416(ah)->ah_writeIni = ar5416WriteIni;
+ AH5416(ah)->ah_spurMitigate = ar5416SpurMitigate;
/*
* Start by setting all Owl devices to 2x2
*/
@@ -393,6 +401,301 @@ ar5416ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore)
}
}
+static void
+ar5416WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan)
+{
+ u_int modesIndex, freqIndex;
+ int regWrites = 0;
+
+ /* Setup the indices for the next set of register array writes */
+ /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
+ if (IEEE80211_IS_CHAN_2GHZ(chan)) {
+ freqIndex = 2;
+ if (IEEE80211_IS_CHAN_HT40(chan))
+ modesIndex = 3;
+ else if (IEEE80211_IS_CHAN_108G(chan))
+ modesIndex = 5;
+ else
+ modesIndex = 4;
+ } else {
+ freqIndex = 1;
+ if (IEEE80211_IS_CHAN_HT40(chan) ||
+ IEEE80211_IS_CHAN_TURBO(chan))
+ modesIndex = 2;
+ else
+ modesIndex = 1;
+ }
+
+ /* Set correct Baseband to analog shift setting to access analog chips. */
+ OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+ /*
+ * Write addac shifts
+ */
+ OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
+#if 0
+ /* NB: only required for Sowl */
+ ar5416EepromSetAddac(ah, chan);
+#endif
+ regWrites = ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_addac, 1,
+ regWrites);
+ OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
+
+ regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes,
+ modesIndex, regWrites);
+ regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common,
+ 1, regWrites);
+
+ /* XXX updated regWrites? */
+ AH5212(ah)->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);
+}
+
+/*
+ * Convert to baseband spur frequency given input channel frequency
+ * and compute register settings below.
+ */
+
+static void
+ar5416SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan)
+{
+ uint16_t freq = ath_hal_gethwchannel(ah, chan);
+ static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
+ AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
+ static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
+ AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
+ static const int inc[4] = { 0, 100, 0, 0 };
+
+ int bb_spur = AR_NO_SPUR;
+ int bin, cur_bin;
+ int spur_freq_sd;
+ int spur_delta_phase;
+ int denominator;
+ int upper, lower, cur_vit_mask;
+ int tmp, new;
+ int i;
+
+ int8_t mask_m[123];
+ int8_t mask_p[123];
+ int8_t mask_amt;
+ int tmp_mask;
+ int cur_bb_spur;
+ HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan);
+
+ OS_MEMZERO(mask_m, sizeof(mask_m));
+ OS_MEMZERO(mask_p, sizeof(mask_p));
+
+ /*
+ * Need to verify range +/- 9.5 for static ht20, otherwise spur
+ * is out-of-band and can be ignored.
+ */
+ /* XXX ath9k changes */
+ for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+ cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
+ if (AR_NO_SPUR == cur_bb_spur)
+ break;
+ cur_bb_spur = cur_bb_spur - (freq * 10);
+ if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
+ bb_spur = cur_bb_spur;
+ break;
+ }
+ }
+ if (AR_NO_SPUR == bb_spur)
+ return;
+
+ bin = bb_spur * 32;
+
+ tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
+ new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+ AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+ AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+ AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+
+ OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), new);
+
+ new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+ AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+ AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+ AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+ SM(AR5416_SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+ OS_REG_WRITE(ah, AR_PHY_SPUR_REG, new);
+ /*
+ * Should offset bb_spur by +/- 10 MHz for dynamic 2040 MHz
+ * config, no offset for HT20.
+ * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
+ * /80 for dyn2040.
+ */
+ spur_delta_phase = ((bb_spur * 524288) / 100) &
+ AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+ /*
+ * in 11A mode the denominator of spur_freq_sd should be 40 and
+ * it should be 44 in 11G
+ */
+ denominator = IEEE80211_IS_CHAN_2GHZ(chan) ? 440 : 400;
+ spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
+
+ new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+ SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+ SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+ OS_REG_WRITE(ah, AR_PHY_TIMING11, new);
+
+
+ /*
+ * ============================================
+ * pilot mask 1 [31:0] = +6..-26, no 0 bin
+ * pilot mask 2 [19:0] = +26..+7
+ *
+ * channel mask 1 [31:0] = +6..-26, no 0 bin
+ * channel mask 2 [19:0] = +26..+7
+ */
+ //cur_bin = -26;
+ cur_bin = -6000;
+ upper = bin + 100;
+ lower = bin - 100;
+
+ for (i = 0; i < 4; i++) {
+ int pilot_mask = 0;
+ int chan_mask = 0;
+ int bp = 0;
+ for (bp = 0; bp < 30; bp++) {
+ if ((cur_bin > lower) && (cur_bin < upper)) {
+ pilot_mask = pilot_mask | 0x1 << bp;
+ chan_mask = chan_mask | 0x1 << bp;
+ }
+ cur_bin += 100;
+ }
+ cur_bin += inc[i];
+ OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+ OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+ }
+
+ /* =================================================
+ * viterbi mask 1 based on channel magnitude
+ * four levels 0-3
+ * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
+ * [1 2 2 1] for -9.6 or [1 2 1] for +16
+ * - enable_mask_ppm, all bins move with freq
+ *
+ * - mask_select, 8 bits for rates (reg 67,0x990c)
+ * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
+ * choose which mask to use mask or mask2
+ */
+
+ /*
+ * viterbi mask 2 2nd set for per data rate puncturing
+ * four levels 0-3
+ * - mask_select, 8 bits for rates (reg 67)
+ * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
+ * [1 2 2 1] for -9.6 or [1 2 1] for +16
+ */
+ cur_vit_mask = 6100;
+ upper = bin + 120;
+ lower = bin - 120;
+
+ for (i = 0; i < 123; i++) {
+ if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+ if ((abs(cur_vit_mask - bin)) < 75) {
+ mask_amt = 1;
+ } else {
+ mask_amt = 0;
+ }
+ if (cur_vit_mask < 0) {
+ mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+ } else {
+ mask_p[cur_vit_mask / 100] = mask_amt;
+ }
+ }
+ cur_vit_mask -= 100;
+ }
+
+ tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+ | (mask_m[48] << 26) | (mask_m[49] << 24)
+ | (mask_m[50] << 22) | (mask_m[51] << 20)
+ | (mask_m[52] << 18) | (mask_m[53] << 16)
+ | (mask_m[54] << 14) | (mask_m[55] << 12)
+ | (mask_m[56] << 10) | (mask_m[57] << 8)
+ | (mask_m[58] << 6) | (mask_m[59] << 4)
+ | (mask_m[60] << 2) | (mask_m[61] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+ tmp_mask = (mask_m[31] << 28)
+ | (mask_m[32] << 26) | (mask_m[33] << 24)
+ | (mask_m[34] << 22) | (mask_m[35] << 20)
+ | (mask_m[36] << 18) | (mask_m[37] << 16)
+ | (mask_m[48] << 14) | (mask_m[39] << 12)
+ | (mask_m[40] << 10) | (mask_m[41] << 8)
+ | (mask_m[42] << 6) | (mask_m[43] << 4)
+ | (mask_m[44] << 2) | (mask_m[45] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+ tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+ | (mask_m[18] << 26) | (mask_m[18] << 24)
+ | (mask_m[20] << 22) | (mask_m[20] << 20)
+ | (mask_m[22] << 18) | (mask_m[22] << 16)
+ | (mask_m[24] << 14) | (mask_m[24] << 12)
+ | (mask_m[25] << 10) | (mask_m[26] << 8)
+ | (mask_m[27] << 6) | (mask_m[28] << 4)
+ | (mask_m[29] << 2) | (mask_m[30] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+ tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
+ | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
+ | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
+ | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
+ | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
+ | (mask_m[10] << 10) | (mask_m[11] << 8)
+ | (mask_m[12] << 6) | (mask_m[13] << 4)
+ | (mask_m[14] << 2) | (mask_m[15] << 0);
+ OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+ tmp_mask = (mask_p[15] << 28)
+ | (mask_p[14] << 26) | (mask_p[13] << 24)
+ | (mask_p[12] << 22) | (mask_p[11] << 20)
+ | (mask_p[10] << 18) | (mask_p[ 9] << 16)
+ | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
+ | (mask_p[ 6] << 10) | (mask_p[ 5] << 8)
+ | (mask_p[ 4] << 6) | (mask_p[ 3] << 4)
+ | (mask_p[ 2] << 2) | (mask_p[ 1] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+ tmp_mask = (mask_p[30] << 28)
+ | (mask_p[29] << 26) | (mask_p[28] << 24)
+ | (mask_p[27] << 22) | (mask_p[26] << 20)
+ | (mask_p[25] << 18) | (mask_p[24] << 16)
+ | (mask_p[23] << 14) | (mask_p[22] << 12)
+ | (mask_p[21] << 10) | (mask_p[20] << 8)
+ | (mask_p[19] << 6) | (mask_p[18] << 4)
+ | (mask_p[17] << 2) | (mask_p[16] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+ tmp_mask = (mask_p[45] << 28)
+ | (mask_p[44] << 26) | (mask_p[43] << 24)
+ | (mask_p[42] << 22) | (mask_p[41] << 20)
+ | (mask_p[40] << 18) | (mask_p[39] << 16)
+ | (mask_p[38] << 14) | (mask_p[37] << 12)
+ | (mask_p[36] << 10) | (mask_p[35] << 8)
+ | (mask_p[34] << 6) | (mask_p[33] << 4)
+ | (mask_p[32] << 2) | (mask_p[31] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+ tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+ | (mask_p[59] << 26) | (mask_p[58] << 24)
+ | (mask_p[57] << 22) | (mask_p[56] << 20)
+ | (mask_p[55] << 18) | (mask_p[54] << 16)
+ | (mask_p[53] << 14) | (mask_p[52] << 12)
+ | (mask_p[51] << 10) | (mask_p[50] << 8)
+ | (mask_p[49] << 6) | (mask_p[48] << 4)
+ | (mask_p[47] << 2) | (mask_p[46] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+
/*
* Fill all software cached or static hardware state information.
* Return failure if capabilities are to come from EEPROM and
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
index 49b29c7..ac3d84a 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c
@@ -27,9 +27,6 @@
#include "ar5416/ar5416.h"
#include "ar5416/ar5416reg.h"
#include "ar5416/ar5416phy.h"
-#ifdef AH_SUPPORT_AR9280
-#include "ar5416/ar9280.h"
-#endif
/* Eeprom versioning macros. Returns true if the version is equal or newer than the ver specified */
#define EEP_MINOR(_ah) \
@@ -55,10 +52,6 @@ static HAL_BOOL ar5416SetTransmitPower(struct ath_hal *ah,
static HAL_BOOL ar5416ChannelChange(struct ath_hal *, const struct ieee80211_channel *);
#endif
static void ar5416SetDeltaSlope(struct ath_hal *, const struct ieee80211_channel *);
-static void ar5416SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan);
-#ifdef AH_SUPPORT_AR9280
-static void ar9280SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan);
-#endif
static HAL_BOOL ar5416SetResetPowerOn(struct ath_hal *ah);
static HAL_BOOL ar5416SetReset(struct ath_hal *ah, int type);
@@ -120,11 +113,10 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
uint32_t saveDefAntenna, saveLedState;
uint32_t macStaId1;
uint16_t rfXpdGain[2];
- u_int modesIndex, freqIndex;
HAL_STATUS ecode;
- int i, regWrites = 0;
uint32_t powerVal, rssiThrReg;
uint32_t ackTpcPow, ctsTpcPow, chirpTpcPow;
+ int i;
OS_MARK(ah, AH_MARK_RESET, bChannelChange);
@@ -181,12 +173,6 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
(AR_MAC_LED_ASSOC | AR_MAC_LED_MODE |
AR_MAC_LED_BLINK_THRESH_SEL | AR_MAC_LED_BLINK_SLOW);
- /*
- * Adjust gain parameters before reset if
- * there's an outstanding gain updated.
- */
- (void) ar5416GetRfgain(ah);
-
if (!ar5416ChipReset(ah, chan)) {
HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
FAIL(HAL_EIO);
@@ -195,67 +181,12 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
/* Restore bmiss rssi & count thresholds */
OS_REG_WRITE(ah, AR_RSSI_THR, rssiThrReg);
- /* Setup the indices for the next set of register array writes */
- /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
- if (IEEE80211_IS_CHAN_2GHZ(chan)) {
- freqIndex = 2;
- if (IEEE80211_IS_CHAN_HT40(chan))
- modesIndex = 3;
- else if (IEEE80211_IS_CHAN_108G(chan))
- modesIndex = 5;
- else
- modesIndex = 4;
- } else {
- freqIndex = 1;
- if (IEEE80211_IS_CHAN_HT40(chan) ||
- IEEE80211_IS_CHAN_TURBO(chan))
- modesIndex = 2;
- else
- modesIndex = 1;
- }
-
OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
- /* Set correct Baseband to analog shift setting to access analog chips. */
- OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+ AH5416(ah)->ah_writeIni(ah, chan);
- /*
- * Write addac shifts
- */
- OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
-#if 0
- /* NB: only required for Sowl */
- ar5416EepromSetAddac(ah, chan);
-#endif
- regWrites = ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_addac, 1,
- regWrites);
- OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
-
- /* XXX Merlin ini fixups */
- /* XXX Merlin 100us delay for shift registers */
- regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_modes, modesIndex,
- regWrites);
-#ifdef AH_SUPPORT_AR9280
- if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
- regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain,
- modesIndex, regWrites);
- regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain,
- modesIndex, regWrites);
- }
-#endif
- /* XXX Merlin 100us delay for shift registers */
- regWrites = ath_hal_ini_write(ah, &ahp->ah_ini_common, 1, regWrites);
/* Setup 11n MAC/Phy mode registers */
ar5416Set11nRegs(ah, chan);
- /* XXX updated regWrites? */
- ahp->ah_rfHal->writeRegs(ah, modesIndex, freqIndex, regWrites);
-#ifdef AH_SUPPORT_AR9280
- if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
- /* 5GHz channels w/ Fast Clock use different modal values */
- regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes,
- modesIndex, regWrites);
- }
-#endif
OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
@@ -300,7 +231,8 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
}
/* Write the analog registers */
- if (!ahp->ah_rfHal->setRfRegs(ah, chan, freqIndex, rfXpdGain)) {
+ if (!ahp->ah_rfHal->setRfRegs(ah, chan,
+ IEEE80211_IS_CHAN_2GHZ(chan) ? 2: 1, rfXpdGain)) {
HALDEBUG(ah, HAL_DEBUG_ANY,
"%s: ar5212SetRfRegs failed\n", __func__);
FAIL(HAL_EIO);
@@ -310,12 +242,7 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
if (IEEE80211_IS_CHAN_OFDM(chan)|| IEEE80211_IS_CHAN_HT(chan))
ar5416SetDeltaSlope(ah, chan);
-#ifdef AH_SUPPORT_AR9280
- if (AR_SREV_MERLIN_10_OR_LATER(ah))
- ar9280SpurMitigate(ah, chan);
- else
-#endif
- ar5416SpurMitigate(ah, chan);
+ AH5416(ah)->ah_spurMitigate(ah, chan);
/* Setup board specific options for EEPROM version 3 */
if (!ar5416SetBoardValues(ah, chan)) {
@@ -677,8 +604,6 @@ ar5416InitUserSettings(struct ath_hal *ah)
HAL_BOOL
ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
- uint32_t rfMode = 0;
-
OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0);
/*
* Warm reset is optimistic.
@@ -705,9 +630,11 @@ ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan)
* radio device.
*/
if (chan != AH_NULL) {
+ uint32_t rfMode;
+
/* treat channel B as channel G , no B mode suport in owl */
- rfMode |= IEEE80211_IS_CHAN_CCK(chan) ?
- AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
+ rfMode = IEEE80211_IS_CHAN_CCK(chan) ?
+ AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
/* phy mode bits for 5GHz channels require Fast Clock */
rfMode |= AR_PHY_MODE_DYNAMIC
@@ -804,558 +731,6 @@ ar5416SetDeltaSlope(struct ath_hal *ah, const struct ieee80211_channel *chan)
}
/*
- * Convert to baseband spur frequency given input channel frequency
- * and compute register settings below.
- */
-#define SPUR_RSSI_THRESH 40
-
-static void
-ar5416SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan)
-{
- uint16_t freq = ath_hal_gethwchannel(ah, chan);
- static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
- AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
- static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
- AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
- static const int inc[4] = { 0, 100, 0, 0 };
-
- int bb_spur = AR_NO_SPUR;
- int bin, cur_bin;
- int spur_freq_sd;
- int spur_delta_phase;
- int denominator;
- int upper, lower, cur_vit_mask;
- int tmp, new;
- int i;
-
- int8_t mask_m[123];
- int8_t mask_p[123];
- int8_t mask_amt;
- int tmp_mask;
- int cur_bb_spur;
- HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan);
-
- OS_MEMZERO(mask_m, sizeof(mask_m));
- OS_MEMZERO(mask_p, sizeof(mask_p));
-
- /*
- * Need to verify range +/- 9.5 for static ht20, otherwise spur
- * is out-of-band and can be ignored.
- */
- /* XXX ath9k changes */
- for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
- cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
- if (AR_NO_SPUR == cur_bb_spur)
- break;
- cur_bb_spur = cur_bb_spur - (freq * 10);
- if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) {
- bb_spur = cur_bb_spur;
- break;
- }
- }
- if (AR_NO_SPUR == bb_spur)
- return;
-
- bin = bb_spur * 32;
-
- tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
- new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
- AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
- AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
- AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
-
- OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), new);
-
- new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
- AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
- AR_PHY_SPUR_REG_MASK_RATE_SELECT |
- AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
- SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
- OS_REG_WRITE(ah, AR_PHY_SPUR_REG, new);
- /*
- * Should offset bb_spur by +/- 10 MHz for dynamic 2040 MHz
- * config, no offset for HT20.
- * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
- * /80 for dyn2040.
- */
- spur_delta_phase = ((bb_spur * 524288) / 100) &
- AR_PHY_TIMING11_SPUR_DELTA_PHASE;
- /*
- * in 11A mode the denominator of spur_freq_sd should be 40 and
- * it should be 44 in 11G
- */
- denominator = IEEE80211_IS_CHAN_2GHZ(chan) ? 440 : 400;
- spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff;
-
- new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
- SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
- SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
- OS_REG_WRITE(ah, AR_PHY_TIMING11, new);
-
-
- /*
- * ============================================
- * pilot mask 1 [31:0] = +6..-26, no 0 bin
- * pilot mask 2 [19:0] = +26..+7
- *
- * channel mask 1 [31:0] = +6..-26, no 0 bin
- * channel mask 2 [19:0] = +26..+7
- */
- //cur_bin = -26;
- cur_bin = -6000;
- upper = bin + 100;
- lower = bin - 100;
-
- for (i = 0; i < 4; i++) {
- int pilot_mask = 0;
- int chan_mask = 0;
- int bp = 0;
- for (bp = 0; bp < 30; bp++) {
- if ((cur_bin > lower) && (cur_bin < upper)) {
- pilot_mask = pilot_mask | 0x1 << bp;
- chan_mask = chan_mask | 0x1 << bp;
- }
- cur_bin += 100;
- }
- cur_bin += inc[i];
- OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
- OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
- }
-
- /* =================================================
- * viterbi mask 1 based on channel magnitude
- * four levels 0-3
- * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
- * [1 2 2 1] for -9.6 or [1 2 1] for +16
- * - enable_mask_ppm, all bins move with freq
- *
- * - mask_select, 8 bits for rates (reg 67,0x990c)
- * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
- * choose which mask to use mask or mask2
- */
-
- /*
- * viterbi mask 2 2nd set for per data rate puncturing
- * four levels 0-3
- * - mask_select, 8 bits for rates (reg 67)
- * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
- * [1 2 2 1] for -9.6 or [1 2 1] for +16
- */
- cur_vit_mask = 6100;
- upper = bin + 120;
- lower = bin - 120;
-
- for (i = 0; i < 123; i++) {
- if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
- if ((abs(cur_vit_mask - bin)) < 75) {
- mask_amt = 1;
- } else {
- mask_amt = 0;
- }
- if (cur_vit_mask < 0) {
- mask_m[abs(cur_vit_mask / 100)] = mask_amt;
- } else {
- mask_p[cur_vit_mask / 100] = mask_amt;
- }
- }
- cur_vit_mask -= 100;
- }
-
- tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
- | (mask_m[48] << 26) | (mask_m[49] << 24)
- | (mask_m[50] << 22) | (mask_m[51] << 20)
- | (mask_m[52] << 18) | (mask_m[53] << 16)
- | (mask_m[54] << 14) | (mask_m[55] << 12)
- | (mask_m[56] << 10) | (mask_m[57] << 8)
- | (mask_m[58] << 6) | (mask_m[59] << 4)
- | (mask_m[60] << 2) | (mask_m[61] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
-
- tmp_mask = (mask_m[31] << 28)
- | (mask_m[32] << 26) | (mask_m[33] << 24)
- | (mask_m[34] << 22) | (mask_m[35] << 20)
- | (mask_m[36] << 18) | (mask_m[37] << 16)
- | (mask_m[48] << 14) | (mask_m[39] << 12)
- | (mask_m[40] << 10) | (mask_m[41] << 8)
- | (mask_m[42] << 6) | (mask_m[43] << 4)
- | (mask_m[44] << 2) | (mask_m[45] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
-
- tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
- | (mask_m[18] << 26) | (mask_m[18] << 24)
- | (mask_m[20] << 22) | (mask_m[20] << 20)
- | (mask_m[22] << 18) | (mask_m[22] << 16)
- | (mask_m[24] << 14) | (mask_m[24] << 12)
- | (mask_m[25] << 10) | (mask_m[26] << 8)
- | (mask_m[27] << 6) | (mask_m[28] << 4)
- | (mask_m[29] << 2) | (mask_m[30] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
-
- tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
- | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
- | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
- | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
- | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
- | (mask_m[10] << 10) | (mask_m[11] << 8)
- | (mask_m[12] << 6) | (mask_m[13] << 4)
- | (mask_m[14] << 2) | (mask_m[15] << 0);
- OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
-
- tmp_mask = (mask_p[15] << 28)
- | (mask_p[14] << 26) | (mask_p[13] << 24)
- | (mask_p[12] << 22) | (mask_p[11] << 20)
- | (mask_p[10] << 18) | (mask_p[ 9] << 16)
- | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
- | (mask_p[ 6] << 10) | (mask_p[ 5] << 8)
- | (mask_p[ 4] << 6) | (mask_p[ 3] << 4)
- | (mask_p[ 2] << 2) | (mask_p[ 1] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
-
- tmp_mask = (mask_p[30] << 28)
- | (mask_p[29] << 26) | (mask_p[28] << 24)
- | (mask_p[27] << 22) | (mask_p[26] << 20)
- | (mask_p[25] << 18) | (mask_p[24] << 16)
- | (mask_p[23] << 14) | (mask_p[22] << 12)
- | (mask_p[21] << 10) | (mask_p[20] << 8)
- | (mask_p[19] << 6) | (mask_p[18] << 4)
- | (mask_p[17] << 2) | (mask_p[16] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
-
- tmp_mask = (mask_p[45] << 28)
- | (mask_p[44] << 26) | (mask_p[43] << 24)
- | (mask_p[42] << 22) | (mask_p[41] << 20)
- | (mask_p[40] << 18) | (mask_p[39] << 16)
- | (mask_p[38] << 14) | (mask_p[37] << 12)
- | (mask_p[36] << 10) | (mask_p[35] << 8)
- | (mask_p[34] << 6) | (mask_p[33] << 4)
- | (mask_p[32] << 2) | (mask_p[31] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
-
- tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
- | (mask_p[59] << 26) | (mask_p[58] << 24)
- | (mask_p[57] << 22) | (mask_p[56] << 20)
- | (mask_p[55] << 18) | (mask_p[54] << 16)
- | (mask_p[53] << 14) | (mask_p[52] << 12)
- | (mask_p[51] << 10) | (mask_p[50] << 8)
- | (mask_p[49] << 6) | (mask_p[48] << 4)
- | (mask_p[47] << 2) | (mask_p[46] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
-}
-
-#ifdef AH_SUPPORT_AR9280
-#define AR_BASE_FREQ_2GHZ 2300
-#define AR_BASE_FREQ_5GHZ 4900
-#define AR_SPUR_FEEQ_BOUND_HT40 19
-#define AR_SPUR_FEEQ_BOUND_HT20 10
-
-static void
-ar9280SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan)
-{
- static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
- AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
- static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
- AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
- static int inc[4] = { 0, 100, 0, 0 };
-
- int bb_spur = AR_NO_SPUR;
- int freq;
- int bin, cur_bin;
- int bb_spur_off, spur_subchannel_sd;
- int spur_freq_sd;
- int spur_delta_phase;
- int denominator;
- int upper, lower, cur_vit_mask;
- int tmp, newVal;
- int i;
- CHAN_CENTERS centers;
-
- int8_t mask_m[123];
- int8_t mask_p[123];
- int8_t mask_amt;
- int tmp_mask;
- int cur_bb_spur;
- HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan);
-
- OS_MEMZERO(&mask_m, sizeof(int8_t) * 123);
- OS_MEMZERO(&mask_p, sizeof(int8_t) * 123);
-
- ar5416GetChannelCenters(ah, chan, &centers);
- freq = centers.synth_center;
-
- /*
- * Need to verify range +/- 9.38 for static ht20 and +/- 18.75 for ht40,
- * otherwise spur is out-of-band and can be ignored.
- */
- for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
- cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
- /* Get actual spur freq in MHz from EEPROM read value */
- if (is2GHz) {
- cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
- } else {
- cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
- }
-
- if (AR_NO_SPUR == cur_bb_spur)
- break;
- cur_bb_spur = cur_bb_spur - freq;
-
- if (IEEE80211_IS_CHAN_HT40(chan)) {
- if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
- (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
- bb_spur = cur_bb_spur;
- break;
- }
- } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
- (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
- bb_spur = cur_bb_spur;
- break;
- }
- }
-
- if (AR_NO_SPUR == bb_spur) {
-#if 1
- /*
- * MRC CCK can interfere with beacon detection and cause deaf/mute.
- * Disable MRC CCK for now.
- */
- OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
-#else
- /* Enable MRC CCK if no spur is found in this channel. */
- OS_REG_SET_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
-#endif
- return;
- } else {
- /*
- * For Merlin, spur can break CCK MRC algorithm. Disable CCK MRC if spur
- * is found in this channel.
- */
- OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
- }
-
- bin = bb_spur * 320;
-
- tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
-
- newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
- AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
- AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
- AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
- OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), newVal);
-
- newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
- AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
- AR_PHY_SPUR_REG_MASK_RATE_SELECT |
- AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
- SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
- OS_REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
-
- /* Pick control or extn channel to cancel the spur */
- if (IEEE80211_IS_CHAN_HT40(chan)) {
- if (bb_spur < 0) {
- spur_subchannel_sd = 1;
- bb_spur_off = bb_spur + 10;
- } else {
- spur_subchannel_sd = 0;
- bb_spur_off = bb_spur - 10;
- }
- } else {
- spur_subchannel_sd = 0;
- bb_spur_off = bb_spur;
- }
-
- /*
- * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
- * /80 for dyn2040.
- */
- if (IEEE80211_IS_CHAN_HT40(chan))
- spur_delta_phase = ((bb_spur * 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
- else
- spur_delta_phase = ((bb_spur * 524288) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
-
- /*
- * in 11A mode the denominator of spur_freq_sd should be 40 and
- * it should be 44 in 11G
- */
- denominator = IEEE80211_IS_CHAN_2GHZ(chan) ? 44 : 40;
- spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
-
- newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
- SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
- SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
- OS_REG_WRITE(ah, AR_PHY_TIMING11, newVal);
-
- /* Choose to cancel between control and extension channels */
- newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
- OS_REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
-
- /*
- * ============================================
- * Set Pilot and Channel Masks
- *
- * pilot mask 1 [31:0] = +6..-26, no 0 bin
- * pilot mask 2 [19:0] = +26..+7
- *
- * channel mask 1 [31:0] = +6..-26, no 0 bin
- * channel mask 2 [19:0] = +26..+7
- */
- cur_bin = -6000;
- upper = bin + 100;
- lower = bin - 100;
-
- for (i = 0; i < 4; i++) {
- int pilot_mask = 0;
- int chan_mask = 0;
- int bp = 0;
- for (bp = 0; bp < 30; bp++) {
- if ((cur_bin > lower) && (cur_bin < upper)) {
- pilot_mask = pilot_mask | 0x1 << bp;
- chan_mask = chan_mask | 0x1 << bp;
- }
- cur_bin += 100;
- }
- cur_bin += inc[i];
- OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
- OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
- }
-
- /* =================================================
- * viterbi mask 1 based on channel magnitude
- * four levels 0-3
- * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
- * [1 2 2 1] for -9.6 or [1 2 1] for +16
- * - enable_mask_ppm, all bins move with freq
- *
- * - mask_select, 8 bits for rates (reg 67,0x990c)
- * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
- * choose which mask to use mask or mask2
- */
-
- /*
- * viterbi mask 2 2nd set for per data rate puncturing
- * four levels 0-3
- * - mask_select, 8 bits for rates (reg 67)
- * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
- * [1 2 2 1] for -9.6 or [1 2 1] for +16
- */
- cur_vit_mask = 6100;
- upper = bin + 120;
- lower = bin - 120;
-
- for (i = 0; i < 123; i++) {
- if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
- if ((abs(cur_vit_mask - bin)) < 75) {
- mask_amt = 1;
- } else {
- mask_amt = 0;
- }
- if (cur_vit_mask < 0) {
- mask_m[abs(cur_vit_mask / 100)] = mask_amt;
- } else {
- mask_p[cur_vit_mask / 100] = mask_amt;
- }
- }
- cur_vit_mask -= 100;
- }
-
- tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
- | (mask_m[48] << 26) | (mask_m[49] << 24)
- | (mask_m[50] << 22) | (mask_m[51] << 20)
- | (mask_m[52] << 18) | (mask_m[53] << 16)
- | (mask_m[54] << 14) | (mask_m[55] << 12)
- | (mask_m[56] << 10) | (mask_m[57] << 8)
- | (mask_m[58] << 6) | (mask_m[59] << 4)
- | (mask_m[60] << 2) | (mask_m[61] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
-
- tmp_mask = (mask_m[31] << 28)
- | (mask_m[32] << 26) | (mask_m[33] << 24)
- | (mask_m[34] << 22) | (mask_m[35] << 20)
- | (mask_m[36] << 18) | (mask_m[37] << 16)
- | (mask_m[48] << 14) | (mask_m[39] << 12)
- | (mask_m[40] << 10) | (mask_m[41] << 8)
- | (mask_m[42] << 6) | (mask_m[43] << 4)
- | (mask_m[44] << 2) | (mask_m[45] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
-
- tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
- | (mask_m[18] << 26) | (mask_m[18] << 24)
- | (mask_m[20] << 22) | (mask_m[20] << 20)
- | (mask_m[22] << 18) | (mask_m[22] << 16)
- | (mask_m[24] << 14) | (mask_m[24] << 12)
- | (mask_m[25] << 10) | (mask_m[26] << 8)
- | (mask_m[27] << 6) | (mask_m[28] << 4)
- | (mask_m[29] << 2) | (mask_m[30] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
-
- tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
- | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
- | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
- | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
- | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
- | (mask_m[10] << 10) | (mask_m[11] << 8)
- | (mask_m[12] << 6) | (mask_m[13] << 4)
- | (mask_m[14] << 2) | (mask_m[15] << 0);
- OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
-
- tmp_mask = (mask_p[15] << 28)
- | (mask_p[14] << 26) | (mask_p[13] << 24)
- | (mask_p[12] << 22) | (mask_p[11] << 20)
- | (mask_p[10] << 18) | (mask_p[ 9] << 16)
- | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
- | (mask_p[ 6] << 10) | (mask_p[ 5] << 8)
- | (mask_p[ 4] << 6) | (mask_p[ 3] << 4)
- | (mask_p[ 2] << 2) | (mask_p[ 1] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
-
- tmp_mask = (mask_p[30] << 28)
- | (mask_p[29] << 26) | (mask_p[28] << 24)
- | (mask_p[27] << 22) | (mask_p[26] << 20)
- | (mask_p[25] << 18) | (mask_p[24] << 16)
- | (mask_p[23] << 14) | (mask_p[22] << 12)
- | (mask_p[21] << 10) | (mask_p[20] << 8)
- | (mask_p[19] << 6) | (mask_p[18] << 4)
- | (mask_p[17] << 2) | (mask_p[16] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
-
- tmp_mask = (mask_p[45] << 28)
- | (mask_p[44] << 26) | (mask_p[43] << 24)
- | (mask_p[42] << 22) | (mask_p[41] << 20)
- | (mask_p[40] << 18) | (mask_p[39] << 16)
- | (mask_p[38] << 14) | (mask_p[37] << 12)
- | (mask_p[36] << 10) | (mask_p[35] << 8)
- | (mask_p[34] << 6) | (mask_p[33] << 4)
- | (mask_p[32] << 2) | (mask_p[31] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
-
- tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
- | (mask_p[59] << 26) | (mask_p[58] << 24)
- | (mask_p[57] << 22) | (mask_p[56] << 20)
- | (mask_p[55] << 18) | (mask_p[54] << 16)
- | (mask_p[53] << 14) | (mask_p[52] << 12)
- | (mask_p[51] << 10) | (mask_p[50] << 8)
- | (mask_p[49] << 6) | (mask_p[48] << 4)
- | (mask_p[47] << 2) | (mask_p[46] << 0);
- OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
- OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
-}
-#endif /* AH_SUPPORT_AR9280 */
-
-/*
* Set a limit on the overall output power. Used for dynamic
* transmit power control and the like.
*
@@ -1620,21 +995,14 @@ ar5416PhyDisable(struct ath_hal *ah)
HAL_BOOL
ar5416SetResetReg(struct ath_hal *ah, uint32_t type)
{
- /*
- * Set force wake
- */
- OS_REG_WRITE(ah, AR_RTC_FORCE_WAKE,
- AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
-
switch (type) {
case HAL_RESET_POWER_ON:
return ar5416SetResetPowerOn(ah);
- break;
case HAL_RESET_WARM:
case HAL_RESET_COLD:
return ar5416SetReset(ah, type);
- break;
default:
+ HALASSERT(AH_FALSE);
return AH_FALSE;
}
}
@@ -1703,11 +1071,11 @@ ar5416SetReset(struct ath_hal *ah, int type)
case HAL_RESET_WARM:
OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM);
break;
- case HAL_RESET_COLD:
+ case HAL_RESET_COLD:
OS_REG_WRITE(ah, AR_RTC_RC, AR_RTC_RC_MAC_WARM|AR_RTC_RC_MAC_COLD);
break;
- default:
- HALASSERT(0);
+ default:
+ HALASSERT(AH_FALSE);
break;
}
@@ -1755,7 +1123,8 @@ ar5416InitPLL(struct ath_hal *ah, const struct ieee80211_channel *chan)
{
uint32_t pll;
- if (AR_SREV_MERLIN_20(ah) && chan != AH_NULL) {
+ if (AR_SREV_MERLIN_20(ah) &&
+ chan != AH_NULL && IEEE80211_IS_CHAN_5GHZ(chan)) {
/*
* PLL WAR for Merlin 2.0/2.1
* When doing fast clock, set PLL to 0x142c
diff --git a/sys/dev/ath/ath_hal/ar5416/ar9280.c b/sys/dev/ath/ath_hal/ar5416/ar9280.c
new file mode 100644
index 0000000..72720f7
--- /dev/null
+++ b/sys/dev/ath/ath_hal/ar5416/ar9280.c
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting
+ * Copyright (c) 2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND 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.
+ *
+ * $FreeBSD$
+ */
+#include "opt_ah.h"
+
+/*
+ * NB: Merlin and later have a simpler RF backend.
+ */
+#include "ah.h"
+#include "ah_internal.h"
+
+#include "ah_eeprom_v14.h"
+
+#include "ar5416/ar9280.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#define N(a) (sizeof(a)/sizeof(a[0]))
+
+struct ar9280State {
+ RF_HAL_FUNCS base; /* public state, must be first */
+ uint16_t pcdacTable[1]; /* XXX */
+};
+#define AR9280(ah) ((struct ar9280State *) AH5212(ah)->ah_rfHal)
+
+static HAL_BOOL ar9280GetChannelMaxMinPower(struct ath_hal *,
+ const struct ieee80211_channel *, int16_t *maxPow,int16_t *minPow);
+int16_t ar9280GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c);
+
+static void
+ar9280WriteRegs(struct ath_hal *ah, u_int modesIndex, u_int freqIndex,
+ int writes)
+{
+ (void) ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_bb_rfgain,
+ freqIndex, writes);
+}
+
+/*
+ * Take the MHz channel value and set the Channel value
+ *
+ * ASSUMES: Writes enabled to analog bus
+ *
+ * Actual Expression,
+ *
+ * For 2GHz channel,
+ * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
+ * (freq_ref = 40MHz)
+ *
+ * For 5GHz channel,
+ * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
+ * (freq_ref = 40MHz/(24>>amodeRefSel))
+ *
+ * For 5GHz channels which are 5MHz spaced,
+ * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
+ * (freq_ref = 40MHz)
+ */
+static HAL_BOOL
+ar9280SetChannel(struct ath_hal *ah, const struct ieee80211_channel *chan)
+{
+ uint16_t bMode, fracMode, aModeRefSel = 0;
+ uint32_t freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
+ CHAN_CENTERS centers;
+ uint32_t refDivA = 24;
+
+ OS_MARK(ah, AH_MARK_SETCHANNEL, chan->ic_freq);
+
+ ar5416GetChannelCenters(ah, chan, &centers);
+ freq = centers.synth_center;
+
+ reg32 = OS_REG_READ(ah, AR_PHY_SYNTH_CONTROL);
+ reg32 &= 0xc0000000;
+
+ if (freq < 4800) { /* 2 GHz, fractional mode */
+ uint32_t txctl;
+
+ bMode = 1;
+ fracMode = 1;
+ aModeRefSel = 0;
+ channelSel = (freq * 0x10000)/15;
+
+ txctl = OS_REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+ if (freq == 2484) {
+ /* Enable channel spreading for channel 14 */
+ OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+ } else {
+ OS_REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl &~ AR_PHY_CCK_TX_CTRL_JAPAN);
+ }
+ } else {
+ bMode = 0;
+ fracMode = 0;
+
+ if ((freq % 20) == 0) {
+ aModeRefSel = 3;
+ } else if ((freq % 10) == 0) {
+ aModeRefSel = 2;
+ } else {
+ aModeRefSel = 0;
+ /* Enable 2G (fractional) mode for channels which are 5MHz spaced */
+ fracMode = 1;
+ refDivA = 1;
+ channelSel = (freq * 0x8000)/15;
+
+ /* RefDivA setting */
+ OS_REG_RMW_FIELD(ah, AR_AN_SYNTH9,
+ AR_AN_SYNTH9_REFDIVA, refDivA);
+ }
+ if (!fracMode) {
+ ndiv = (freq * (refDivA >> aModeRefSel))/60;
+ channelSel = ndiv & 0x1ff;
+ channelFrac = (ndiv & 0xfffffe00) * 2;
+ channelSel = (channelSel << 17) | channelFrac;
+ }
+ }
+
+ reg32 = reg32 | (bMode << 29) | (fracMode << 28) |
+ (aModeRefSel << 26) | (channelSel);
+
+ OS_REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32);
+
+ AH_PRIVATE(ah)->ah_curchan = chan;
+
+ return AH_TRUE;
+}
+
+/*
+ * Return a reference to the requested RF Bank.
+ */
+static uint32_t *
+ar9280GetRfBank(struct ath_hal *ah, int bank)
+{
+ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: unknown RF Bank %d requested\n",
+ __func__, bank);
+ return AH_NULL;
+}
+
+/*
+ * Reads EEPROM header info from device structure and programs
+ * all rf registers
+ */
+static HAL_BOOL
+ar9280SetRfRegs(struct ath_hal *ah, const struct ieee80211_channel *chan,
+ uint16_t modesIndex, uint16_t *rfXpdGain)
+{
+ return AH_TRUE; /* nothing to do */
+}
+
+/*
+ * Read the transmit power levels from the structures taken from EEPROM
+ * Interpolate read transmit power values for this channel
+ * Organize the transmit power values into a table for writing into the hardware
+ */
+
+static HAL_BOOL
+ar9280SetPowerTable(struct ath_hal *ah, int16_t *pPowerMin, int16_t *pPowerMax,
+ const struct ieee80211_channel *chan, uint16_t *rfXpdGain)
+{
+ return AH_TRUE;
+}
+
+#if 0
+static int16_t
+ar9280GetMinPower(struct ath_hal *ah, EXPN_DATA_PER_CHANNEL_5112 *data)
+{
+ int i, minIndex;
+ int16_t minGain,minPwr,minPcdac,retVal;
+
+ /* Assume NUM_POINTS_XPD0 > 0 */
+ minGain = data->pDataPerXPD[0].xpd_gain;
+ for (minIndex=0,i=1; i<NUM_XPD_PER_CHANNEL; i++) {
+ if (data->pDataPerXPD[i].xpd_gain < minGain) {
+ minIndex = i;
+ minGain = data->pDataPerXPD[i].xpd_gain;
+ }
+ }
+ minPwr = data->pDataPerXPD[minIndex].pwr_t4[0];
+ minPcdac = data->pDataPerXPD[minIndex].pcdac[0];
+ for (i=1; i<NUM_POINTS_XPD0; i++) {
+ if (data->pDataPerXPD[minIndex].pwr_t4[i] < minPwr) {
+ minPwr = data->pDataPerXPD[minIndex].pwr_t4[i];
+ minPcdac = data->pDataPerXPD[minIndex].pcdac[i];
+ }
+ }
+ retVal = minPwr - (minPcdac*2);
+ return(retVal);
+}
+#endif
+
+static HAL_BOOL
+ar9280GetChannelMaxMinPower(struct ath_hal *ah,
+ const struct ieee80211_channel *chan,
+ int16_t *maxPow, int16_t *minPow)
+{
+#if 0
+ struct ath_hal_5212 *ahp = AH5212(ah);
+ int numChannels=0,i,last;
+ int totalD, totalF,totalMin;
+ EXPN_DATA_PER_CHANNEL_5112 *data=AH_NULL;
+ EEPROM_POWER_EXPN_5112 *powerArray=AH_NULL;
+
+ *maxPow = 0;
+ if (IS_CHAN_A(chan)) {
+ powerArray = ahp->ah_modePowerArray5112;
+ data = powerArray[headerInfo11A].pDataPerChannel;
+ numChannels = powerArray[headerInfo11A].numChannels;
+ } else if (IS_CHAN_G(chan) || IS_CHAN_108G(chan)) {
+ /* XXX - is this correct? Should we also use the same power for turbo G? */
+ powerArray = ahp->ah_modePowerArray5112;
+ data = powerArray[headerInfo11G].pDataPerChannel;
+ numChannels = powerArray[headerInfo11G].numChannels;
+ } else if (IS_CHAN_B(chan)) {
+ powerArray = ahp->ah_modePowerArray5112;
+ data = powerArray[headerInfo11B].pDataPerChannel;
+ numChannels = powerArray[headerInfo11B].numChannels;
+ } else {
+ return (AH_TRUE);
+ }
+ /* Make sure the channel is in the range of the TP values
+ * (freq piers)
+ */
+ if ((numChannels < 1) ||
+ (chan->channel < data[0].channelValue) ||
+ (chan->channel > data[numChannels-1].channelValue))
+ return(AH_FALSE);
+
+ /* Linearly interpolate the power value now */
+ for (last=0,i=0;
+ (i<numChannels) && (chan->channel > data[i].channelValue);
+ last=i++);
+ totalD = data[i].channelValue - data[last].channelValue;
+ if (totalD > 0) {
+ totalF = data[i].maxPower_t4 - data[last].maxPower_t4;
+ *maxPow = (int8_t) ((totalF*(chan->channel-data[last].channelValue) + data[last].maxPower_t4*totalD)/totalD);
+
+ totalMin = ar9280GetMinPower(ah,&data[i]) - ar9280GetMinPower(ah, &data[last]);
+ *minPow = (int8_t) ((totalMin*(chan->channel-data[last].channelValue) + ar9280GetMinPower(ah, &data[last])*totalD)/totalD);
+ return (AH_TRUE);
+ } else {
+ if (chan->channel == data[i].channelValue) {
+ *maxPow = data[i].maxPower_t4;
+ *minPow = ar9280GetMinPower(ah, &data[i]);
+ return(AH_TRUE);
+ } else
+ return(AH_FALSE);
+ }
+#else
+ *maxPow = *minPow = 0;
+ return AH_FALSE;
+#endif
+}
+
+static void
+ar9280GetNoiseFloor(struct ath_hal *ah, int16_t nfarray[])
+{
+ int16_t nf;
+
+ nf = MS(OS_REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ HALDEBUG(ah, HAL_DEBUG_NFCAL,
+ "NF calibrated [ctl] [chain 0] is %d\n", nf);
+ nfarray[0] = nf;
+
+ nf = MS(OS_REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ HALDEBUG(ah, HAL_DEBUG_NFCAL,
+ "NF calibrated [ctl] [chain 1] is %d\n", nf);
+ nfarray[1] = nf;
+
+ nf = MS(OS_REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ HALDEBUG(ah, HAL_DEBUG_NFCAL,
+ "NF calibrated [ext] [chain 0] is %d\n", nf);
+ nfarray[3] = nf;
+
+ nf = MS(OS_REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ HALDEBUG(ah, HAL_DEBUG_NFCAL,
+ "NF calibrated [ext] [chain 1] is %d\n", nf);
+ nfarray[4] = nf;
+}
+
+/*
+ * Adjust NF based on statistical values for 5GHz frequencies.
+ * Stubbed:Not used by Fowl
+ */
+int16_t
+ar9280GetNfAdjust(struct ath_hal *ah, const HAL_CHANNEL_INTERNAL *c)
+{
+ return 0;
+}
+
+/*
+ * Free memory for analog bank scratch buffers
+ */
+static void
+ar9280RfDetach(struct ath_hal *ah)
+{
+ struct ath_hal_5212 *ahp = AH5212(ah);
+
+ HALASSERT(ahp->ah_rfHal != AH_NULL);
+ ath_hal_free(ahp->ah_rfHal);
+ ahp->ah_rfHal = AH_NULL;
+}
+
+HAL_BOOL
+ar9280RfAttach(struct ath_hal *ah, HAL_STATUS *status)
+{
+ struct ath_hal_5212 *ahp = AH5212(ah);
+ struct ar9280State *priv;
+
+ HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: attach AR9280 radio\n", __func__);
+
+ HALASSERT(ahp->ah_rfHal == AH_NULL);
+ priv = ath_hal_malloc(sizeof(struct ar9280State));
+ if (priv == AH_NULL) {
+ HALDEBUG(ah, HAL_DEBUG_ANY,
+ "%s: cannot allocate private state\n", __func__);
+ *status = HAL_ENOMEM; /* XXX */
+ return AH_FALSE;
+ }
+ priv->base.rfDetach = ar9280RfDetach;
+ priv->base.writeRegs = ar9280WriteRegs;
+ priv->base.getRfBank = ar9280GetRfBank;
+ priv->base.setChannel = ar9280SetChannel;
+ priv->base.setRfRegs = ar9280SetRfRegs;
+ priv->base.setPowerTable = ar9280SetPowerTable;
+ priv->base.getChannelMaxMinPower = ar9280GetChannelMaxMinPower;
+ priv->base.getNfAdjust = ar9280GetNfAdjust;
+
+ ahp->ah_pcdacTable = priv->pcdacTable;
+ ahp->ah_pcdacTableSize = sizeof(priv->pcdacTable);
+ ahp->ah_rfHal = &priv->base;
+ /*
+ * Set noise floor adjust method; we arrange a
+ * direct call instead of thunking.
+ */
+ AH_PRIVATE(ah)->ah_getNfAdjust = priv->base.getNfAdjust;
+ AH_PRIVATE(ah)->ah_getNoiseFloor = ar9280GetNoiseFloor;
+
+ return AH_TRUE;
+}
diff --git a/sys/dev/ath/ath_hal/ar5416/ar9280.h b/sys/dev/ath/ath_hal/ar5416/ar9280.h
new file mode 100644
index 0000000..f2e97d96
--- /dev/null
+++ b/sys/dev/ath/ath_hal/ar5416/ar9280.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND 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.
+ *
+ * $FreeBSD$
+ */
+#ifndef _ATH_AR9280_H_
+#define _ATH_AR9280_H_
+
+#include "ar5416/ar5416.h"
+
+struct ath_hal_9280 {
+ struct ath_hal_5416 ah_5416;
+
+ HAL_INI_ARRAY ah_ini_xmodes;
+ HAL_INI_ARRAY ah_ini_rxgain;
+ HAL_INI_ARRAY ah_ini_txgain;
+};
+#define AH9280(_ah) ((struct ath_hal_9280 *)(_ah))
+
+#define AR9280_DEFAULT_RXCHAINMASK 3
+#define AR9280_DEFAULT_TXCHAINMASK 1
+
+HAL_BOOL ar9280RfAttach(struct ath_hal *, HAL_STATUS *);
+
+struct ath_hal;
+
+HAL_BOOL ar9280SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING);
+#endif /* _ATH_AR9280_H_ */
diff --git a/sys/dev/ath/ath_hal/ar5416/ar9280_attach.c b/sys/dev/ath/ath_hal/ar5416/ar9280_attach.c
new file mode 100644
index 0000000..d998af0
--- /dev/null
+++ b/sys/dev/ath/ath_hal/ar5416/ar9280_attach.c
@@ -0,0 +1,738 @@
+/*
+ * Copyright (c) 2008-2009 Sam Leffler, Errno Consulting
+ * Copyright (c) 2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND 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.
+ *
+ * $FreeBSD$
+ */
+#include "opt_ah.h"
+
+#include "ah.h"
+#include "ah_internal.h"
+#include "ah_devid.h"
+
+#include "ah_eeprom_v14.h" /* XXX for tx/rx gain */
+
+#include "ar5416/ar9280.h"
+#include "ar5416/ar5416reg.h"
+#include "ar5416/ar5416phy.h"
+
+#include "ar5416/ar9280v1.ini"
+#include "ar5416/ar9280v2.ini"
+
+static const HAL_PERCAL_DATA ar9280_iq_cal = { /* single sample */
+ .calName = "IQ", .calType = IQ_MISMATCH_CAL,
+ .calNumSamples = MIN_CAL_SAMPLES,
+ .calCountMax = PER_MAX_LOG_COUNT,
+ .calCollect = ar5416IQCalCollect,
+ .calPostProc = ar5416IQCalibration
+};
+static const HAL_PERCAL_DATA ar9280_adc_gain_cal = { /* single sample */
+ .calName = "ADC Gain", .calType = ADC_GAIN_CAL,
+ .calNumSamples = MIN_CAL_SAMPLES,
+ .calCountMax = PER_MIN_LOG_COUNT,
+ .calCollect = ar5416AdcGainCalCollect,
+ .calPostProc = ar5416AdcGainCalibration
+};
+static const HAL_PERCAL_DATA ar9280_adc_dc_cal = { /* single sample */
+ .calName = "ADC DC", .calType = ADC_DC_CAL,
+ .calNumSamples = MIN_CAL_SAMPLES,
+ .calCountMax = PER_MIN_LOG_COUNT,
+ .calCollect = ar5416AdcDcCalCollect,
+ .calPostProc = ar5416AdcDcCalibration
+};
+static const HAL_PERCAL_DATA ar9280_adc_init_dc_cal = {
+ .calName = "ADC Init DC", .calType = ADC_DC_INIT_CAL,
+ .calNumSamples = MIN_CAL_SAMPLES,
+ .calCountMax = INIT_LOG_COUNT,
+ .calCollect = ar5416AdcDcCalCollect,
+ .calPostProc = ar5416AdcDcCalibration
+};
+
+static void ar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore);
+static HAL_BOOL ar9280FillCapabilityInfo(struct ath_hal *ah);
+static void ar9280WriteIni(struct ath_hal *ah,
+ const struct ieee80211_channel *chan);
+static void ar9280SpurMitigate(struct ath_hal *ah,
+ const struct ieee80211_channel *chan);
+
+static void
+ar9280AniSetup(struct ath_hal *ah)
+{
+ /* NB: disable ANI for reliable RIFS rx */
+ ar5212AniAttach(ah, AH_NULL, AH_NULL, AH_FALSE);
+}
+
+/*
+ * Attach for an AR9280 part.
+ */
+static struct ath_hal *
+ar9280Attach(uint16_t devid, HAL_SOFTC sc,
+ HAL_BUS_TAG st, HAL_BUS_HANDLE sh, HAL_STATUS *status)
+{
+ struct ath_hal_9280 *ahp9280;
+ struct ath_hal_5212 *ahp;
+ struct ath_hal *ah;
+ uint32_t val;
+ HAL_STATUS ecode;
+ HAL_BOOL rfStatus;
+
+ HALDEBUG(AH_NULL, HAL_DEBUG_ATTACH, "%s: sc %p st %p sh %p\n",
+ __func__, sc, (void*) st, (void*) sh);
+
+ /* NB: memory is returned zero'd */
+ ahp9280 = ath_hal_malloc(sizeof (struct ath_hal_9280));
+ if (ahp9280 == AH_NULL) {
+ HALDEBUG(AH_NULL, HAL_DEBUG_ANY,
+ "%s: cannot allocate memory for state block\n", __func__);
+ *status = HAL_ENOMEM;
+ return AH_NULL;
+ }
+ ahp = AH5212(ahp9280);
+ ah = &ahp->ah_priv.h;
+
+ ar5416InitState(AH5416(ah), devid, sc, st, sh, status);
+
+ /* XXX override with 9280 specific state */
+ /* override 5416 methods for our needs */
+ ah->ah_setAntennaSwitch = ar9280SetAntennaSwitch;
+ ah->ah_configPCIE = ar9280ConfigPCIE;
+
+ AH5416(ah)->ah_cal.iqCalData.calData = &ar9280_iq_cal;
+ AH5416(ah)->ah_cal.adcGainCalData.calData = &ar9280_adc_gain_cal;
+ AH5416(ah)->ah_cal.adcDcCalData.calData = &ar9280_adc_dc_cal;
+ AH5416(ah)->ah_cal.adcDcCalInitData.calData = &ar9280_adc_init_dc_cal;
+ AH5416(ah)->ah_cal.suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
+
+ AH5416(ah)->ah_spurMitigate = ar9280SpurMitigate;
+ AH5416(ah)->ah_writeIni = ar9280WriteIni;
+ AH5416(ah)->ah_rx_chainmask = AR9280_DEFAULT_RXCHAINMASK;
+ AH5416(ah)->ah_tx_chainmask = AR9280_DEFAULT_TXCHAINMASK;
+
+ if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) {
+ /* reset chip */
+ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't reset chip\n",
+ __func__);
+ ecode = HAL_EIO;
+ goto bad;
+ }
+
+ if (!ar5416SetPowerMode(ah, HAL_PM_AWAKE, AH_TRUE)) {
+ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: couldn't wakeup chip\n",
+ __func__);
+ ecode = HAL_EIO;
+ goto bad;
+ }
+ /* Read Revisions from Chips before taking out of reset */
+ val = OS_REG_READ(ah, AR_SREV);
+ HALDEBUG(ah, HAL_DEBUG_ATTACH,
+ "%s: ID 0x%x VERSION 0x%x TYPE 0x%x REVISION 0x%x\n",
+ __func__, MS(val, AR_XSREV_ID), MS(val, AR_XSREV_VERSION),
+ MS(val, AR_XSREV_TYPE), MS(val, AR_XSREV_REVISION));
+ /* NB: include chip type to differentiate from pre-Sowl versions */
+ AH_PRIVATE(ah)->ah_macVersion =
+ (val & AR_XSREV_VERSION) >> AR_XSREV_TYPE_S;
+ AH_PRIVATE(ah)->ah_macRev = MS(val, AR_XSREV_REVISION);
+ AH_PRIVATE(ah)->ah_ispcie = (val & AR_XSREV_TYPE_HOST_MODE) == 0;
+
+ /* setup common ini data; rf backends handle remainder */
+ if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
+ HAL_INI_INIT(&ahp->ah_ini_modes, ar9280Modes_v2, 6);
+ HAL_INI_INIT(&ahp->ah_ini_common, ar9280Common_v2, 2);
+ HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
+ ar9280PciePhy_clkreq_always_on_L1_v2, 2);
+ HAL_INI_INIT(&ahp9280->ah_ini_xmodes,
+ ar9280Modes_fast_clock_v2, 3);
+ } else {
+ HAL_INI_INIT(&ahp->ah_ini_modes, ar9280Modes_v1, 6);
+ HAL_INI_INIT(&ahp->ah_ini_common, ar9280Common_v1, 2);
+ HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes,
+ ar9280PciePhy_v1, 2);
+ }
+ ar5416AttachPCIE(ah);
+
+ ecode = ath_hal_v14EepromAttach(ah);
+ if (ecode != HAL_OK)
+ goto bad;
+
+ if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */
+ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__);
+ ecode = HAL_EIO;
+ goto bad;
+ }
+
+ AH_PRIVATE(ah)->ah_phyRev = OS_REG_READ(ah, AR_PHY_CHIP_ID);
+
+ if (!ar5212ChipTest(ah)) {
+ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: hardware self-test failed\n",
+ __func__);
+ ecode = HAL_ESELFTEST;
+ goto bad;
+ }
+
+ /*
+ * Set correct Baseband to analog shift
+ * setting to access analog chips.
+ */
+ OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+
+ /* Read Radio Chip Rev Extract */
+ AH_PRIVATE(ah)->ah_analog5GhzRev = ar5416GetRadioRev(ah);
+ switch (AH_PRIVATE(ah)->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR) {
+ case AR_RAD2133_SREV_MAJOR: /* Sowl: 2G/3x3 */
+ case AR_RAD5133_SREV_MAJOR: /* Sowl: 2+5G/3x3 */
+ break;
+ default:
+ if (AH_PRIVATE(ah)->ah_analog5GhzRev == 0) {
+ AH_PRIVATE(ah)->ah_analog5GhzRev =
+ AR_RAD5133_SREV_MAJOR;
+ break;
+ }
+#ifdef AH_DEBUG
+ HALDEBUG(ah, HAL_DEBUG_ANY,
+ "%s: 5G Radio Chip Rev 0x%02X is not supported by "
+ "this driver\n", __func__,
+ AH_PRIVATE(ah)->ah_analog5GhzRev);
+ ecode = HAL_ENOTSUPP;
+ goto bad;
+#endif
+ }
+ rfStatus = ar9280RfAttach(ah, &ecode);
+ if (!rfStatus) {
+ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: RF setup failed, status %u\n",
+ __func__, ecode);
+ goto bad;
+ }
+
+ if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
+ /* setup rxgain table */
+ switch (ath_hal_eepromGet(ah, AR_EEP_RXGAIN_TYPE, AH_NULL)) {
+ case AR5416_EEP_RXGAIN_13dB_BACKOFF:
+ HAL_INI_INIT(&ahp9280->ah_ini_rxgain,
+ ar9280Modes_backoff_13db_rxgain_v2, 6);
+ break;
+ case AR5416_EEP_RXGAIN_23dB_BACKOFF:
+ HAL_INI_INIT(&ahp9280->ah_ini_rxgain,
+ ar9280Modes_backoff_23db_rxgain_v2, 6);
+ break;
+ case AR5416_EEP_RXGAIN_ORIG:
+ HAL_INI_INIT(&ahp9280->ah_ini_rxgain,
+ ar9280Modes_original_rxgain_v2, 6);
+ break;
+ default:
+ HALASSERT(AH_FALSE);
+ goto bad; /* XXX ? try to continue */
+ }
+ }
+ if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
+ /* setp txgain table */
+ switch (ath_hal_eepromGet(ah, AR_EEP_TXGAIN_TYPE, AH_NULL)) {
+ case AR5416_EEP_TXGAIN_HIGH_POWER:
+ HAL_INI_INIT(&ahp9280->ah_ini_txgain,
+ ar9280Modes_high_power_tx_gain_v2, 6);
+ break;
+ case AR5416_EEP_TXGAIN_ORIG:
+ HAL_INI_INIT(&ahp9280->ah_ini_txgain,
+ ar9280Modes_original_tx_gain_v2, 6);
+ break;
+ default:
+ HALASSERT(AH_FALSE);
+ goto bad; /* XXX ? try to continue */
+ }
+ }
+
+ /*
+ * Got everything we need now to setup the capabilities.
+ */
+ if (!ar9280FillCapabilityInfo(ah)) {
+ ecode = HAL_EEREAD;
+ goto bad;
+ }
+
+ ecode = ath_hal_eepromGet(ah, AR_EEP_MACADDR, ahp->ah_macaddr);
+ if (ecode != HAL_OK) {
+ HALDEBUG(ah, HAL_DEBUG_ANY,
+ "%s: error getting mac address from EEPROM\n", __func__);
+ goto bad;
+ }
+ /* XXX How about the serial number ? */
+ /* Read Reg Domain */
+ AH_PRIVATE(ah)->ah_currentRD =
+ ath_hal_eepromGet(ah, AR_EEP_REGDMN_0, AH_NULL);
+
+ /*
+ * ah_miscMode is populated by ar5416FillCapabilityInfo()
+ * starting from griffin. Set here to make sure that
+ * AR_MISC_MODE_MIC_NEW_LOC_ENABLE is set before a GTK is
+ * placed into hardware.
+ */
+ if (ahp->ah_miscMode != 0)
+ OS_REG_WRITE(ah, AR_MISC_MODE, ahp->ah_miscMode);
+
+ ar9280AniSetup(ah); /* Anti Noise Immunity */
+ ar5416InitNfHistBuff(AH5416(ah)->ah_cal.nfCalHist);
+
+ HALDEBUG(ah, HAL_DEBUG_ATTACH, "%s: return\n", __func__);
+
+ return ah;
+bad:
+ if (ah != AH_NULL)
+ ah->ah_detach(ah);
+ if (status)
+ *status = ecode;
+ return AH_NULL;
+}
+
+static void
+ar9280ConfigPCIE(struct ath_hal *ah, HAL_BOOL restore)
+{
+ if (AH_PRIVATE(ah)->ah_ispcie && !restore) {
+ ath_hal_ini_write(ah, &AH5416(ah)->ah_ini_pcieserdes, 1, 0);
+ OS_DELAY(1000);
+ OS_REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+ OS_REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT);
+ }
+}
+
+static void
+ar9280WriteIni(struct ath_hal *ah, const struct ieee80211_channel *chan)
+{
+ u_int modesIndex, freqIndex;
+ int regWrites = 0;
+
+ /* Setup the indices for the next set of register array writes */
+ /* XXX Ignore 11n dynamic mode on the AR5416 for the moment */
+ if (IEEE80211_IS_CHAN_2GHZ(chan)) {
+ freqIndex = 2;
+ if (IEEE80211_IS_CHAN_HT40(chan))
+ modesIndex = 3;
+ else if (IEEE80211_IS_CHAN_108G(chan))
+ modesIndex = 5;
+ else
+ modesIndex = 4;
+ } else {
+ freqIndex = 1;
+ if (IEEE80211_IS_CHAN_HT40(chan) ||
+ IEEE80211_IS_CHAN_TURBO(chan))
+ modesIndex = 2;
+ else
+ modesIndex = 1;
+ }
+
+ /* Set correct Baseband to analog shift setting to access analog chips. */
+ OS_REG_WRITE(ah, AR_PHY(0), 0x00000007);
+ OS_REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
+
+ /* XXX Merlin ini fixups */
+ /* XXX Merlin 100us delay for shift registers */
+ regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_modes,
+ modesIndex, regWrites);
+ if (AR_SREV_MERLIN_20_OR_LATER(ah)) {
+ regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_rxgain,
+ modesIndex, regWrites);
+ regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_txgain,
+ modesIndex, regWrites);
+ }
+ /* XXX Merlin 100us delay for shift registers */
+ regWrites = ath_hal_ini_write(ah, &AH5212(ah)->ah_ini_common,
+ 1, regWrites);
+
+ if (AR_SREV_MERLIN_20(ah) && IS_5GHZ_FAST_CLOCK_EN(ah, chan)) {
+ /* 5GHz channels w/ Fast Clock use different modal values */
+ regWrites = ath_hal_ini_write(ah, &AH9280(ah)->ah_ini_xmodes,
+ modesIndex, regWrites);
+ }
+}
+
+#define AR_BASE_FREQ_2GHZ 2300
+#define AR_BASE_FREQ_5GHZ 4900
+#define AR_SPUR_FEEQ_BOUND_HT40 19
+#define AR_SPUR_FEEQ_BOUND_HT20 10
+
+static void
+ar9280SpurMitigate(struct ath_hal *ah, const struct ieee80211_channel *chan)
+{
+ static const int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8,
+ AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 };
+ static const int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10,
+ AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 };
+ static int inc[4] = { 0, 100, 0, 0 };
+
+ int bb_spur = AR_NO_SPUR;
+ int freq;
+ int bin, cur_bin;
+ int bb_spur_off, spur_subchannel_sd;
+ int spur_freq_sd;
+ int spur_delta_phase;
+ int denominator;
+ int upper, lower, cur_vit_mask;
+ int tmp, newVal;
+ int i;
+ CHAN_CENTERS centers;
+
+ int8_t mask_m[123];
+ int8_t mask_p[123];
+ int8_t mask_amt;
+ int tmp_mask;
+ int cur_bb_spur;
+ HAL_BOOL is2GHz = IEEE80211_IS_CHAN_2GHZ(chan);
+
+ OS_MEMZERO(&mask_m, sizeof(int8_t) * 123);
+ OS_MEMZERO(&mask_p, sizeof(int8_t) * 123);
+
+ ar5416GetChannelCenters(ah, chan, &centers);
+ freq = centers.synth_center;
+
+ /*
+ * Need to verify range +/- 9.38 for static ht20 and +/- 18.75 for ht40,
+ * otherwise spur is out-of-band and can be ignored.
+ */
+ for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+ cur_bb_spur = ath_hal_getSpurChan(ah, i, is2GHz);
+ /* Get actual spur freq in MHz from EEPROM read value */
+ if (is2GHz) {
+ cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ;
+ } else {
+ cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ;
+ }
+
+ if (AR_NO_SPUR == cur_bb_spur)
+ break;
+ cur_bb_spur = cur_bb_spur - freq;
+
+ if (IEEE80211_IS_CHAN_HT40(chan)) {
+ if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) &&
+ (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) {
+ bb_spur = cur_bb_spur;
+ break;
+ }
+ } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) &&
+ (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) {
+ bb_spur = cur_bb_spur;
+ break;
+ }
+ }
+
+ if (AR_NO_SPUR == bb_spur) {
+#if 1
+ /*
+ * MRC CCK can interfere with beacon detection and cause deaf/mute.
+ * Disable MRC CCK for now.
+ */
+ OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+#else
+ /* Enable MRC CCK if no spur is found in this channel. */
+ OS_REG_SET_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+#endif
+ return;
+ } else {
+ /*
+ * For Merlin, spur can break CCK MRC algorithm. Disable CCK MRC if spur
+ * is found in this channel.
+ */
+ OS_REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, AR_PHY_FORCE_CLKEN_CCK_MRC_MUX);
+ }
+
+ bin = bb_spur * 320;
+
+ tmp = OS_REG_READ(ah, AR_PHY_TIMING_CTRL4_CHAIN(0));
+
+ newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI |
+ AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER |
+ AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK |
+ AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK);
+ OS_REG_WRITE(ah, AR_PHY_TIMING_CTRL4_CHAIN(0), newVal);
+
+ newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL |
+ AR_PHY_SPUR_REG_ENABLE_MASK_PPM |
+ AR_PHY_SPUR_REG_MASK_RATE_SELECT |
+ AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI |
+ SM(AR5416_SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH));
+ OS_REG_WRITE(ah, AR_PHY_SPUR_REG, newVal);
+
+ /* Pick control or extn channel to cancel the spur */
+ if (IEEE80211_IS_CHAN_HT40(chan)) {
+ if (bb_spur < 0) {
+ spur_subchannel_sd = 1;
+ bb_spur_off = bb_spur + 10;
+ } else {
+ spur_subchannel_sd = 0;
+ bb_spur_off = bb_spur - 10;
+ }
+ } else {
+ spur_subchannel_sd = 0;
+ bb_spur_off = bb_spur;
+ }
+
+ /*
+ * spur_delta_phase = bb_spur/40 * 2**21 for static ht20,
+ * /80 for dyn2040.
+ */
+ if (IEEE80211_IS_CHAN_HT40(chan))
+ spur_delta_phase = ((bb_spur * 262144) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+ else
+ spur_delta_phase = ((bb_spur * 524288) / 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE;
+
+ /*
+ * in 11A mode the denominator of spur_freq_sd should be 40 and
+ * it should be 44 in 11G
+ */
+ denominator = IEEE80211_IS_CHAN_2GHZ(chan) ? 44 : 40;
+ spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff;
+
+ newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC |
+ SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) |
+ SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE));
+ OS_REG_WRITE(ah, AR_PHY_TIMING11, newVal);
+
+ /* Choose to cancel between control and extension channels */
+ newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S;
+ OS_REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal);
+
+ /*
+ * ============================================
+ * Set Pilot and Channel Masks
+ *
+ * pilot mask 1 [31:0] = +6..-26, no 0 bin
+ * pilot mask 2 [19:0] = +26..+7
+ *
+ * channel mask 1 [31:0] = +6..-26, no 0 bin
+ * channel mask 2 [19:0] = +26..+7
+ */
+ cur_bin = -6000;
+ upper = bin + 100;
+ lower = bin - 100;
+
+ for (i = 0; i < 4; i++) {
+ int pilot_mask = 0;
+ int chan_mask = 0;
+ int bp = 0;
+ for (bp = 0; bp < 30; bp++) {
+ if ((cur_bin > lower) && (cur_bin < upper)) {
+ pilot_mask = pilot_mask | 0x1 << bp;
+ chan_mask = chan_mask | 0x1 << bp;
+ }
+ cur_bin += 100;
+ }
+ cur_bin += inc[i];
+ OS_REG_WRITE(ah, pilot_mask_reg[i], pilot_mask);
+ OS_REG_WRITE(ah, chan_mask_reg[i], chan_mask);
+ }
+
+ /* =================================================
+ * viterbi mask 1 based on channel magnitude
+ * four levels 0-3
+ * - mask (-27 to 27) (reg 64,0x9900 to 67,0x990c)
+ * [1 2 2 1] for -9.6 or [1 2 1] for +16
+ * - enable_mask_ppm, all bins move with freq
+ *
+ * - mask_select, 8 bits for rates (reg 67,0x990c)
+ * - mask_rate_cntl, 8 bits for rates (reg 67,0x990c)
+ * choose which mask to use mask or mask2
+ */
+
+ /*
+ * viterbi mask 2 2nd set for per data rate puncturing
+ * four levels 0-3
+ * - mask_select, 8 bits for rates (reg 67)
+ * - mask (-27 to 27) (reg 98,0x9988 to 101,0x9994)
+ * [1 2 2 1] for -9.6 or [1 2 1] for +16
+ */
+ cur_vit_mask = 6100;
+ upper = bin + 120;
+ lower = bin - 120;
+
+ for (i = 0; i < 123; i++) {
+ if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) {
+ if ((abs(cur_vit_mask - bin)) < 75) {
+ mask_amt = 1;
+ } else {
+ mask_amt = 0;
+ }
+ if (cur_vit_mask < 0) {
+ mask_m[abs(cur_vit_mask / 100)] = mask_amt;
+ } else {
+ mask_p[cur_vit_mask / 100] = mask_amt;
+ }
+ }
+ cur_vit_mask -= 100;
+ }
+
+ tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28)
+ | (mask_m[48] << 26) | (mask_m[49] << 24)
+ | (mask_m[50] << 22) | (mask_m[51] << 20)
+ | (mask_m[52] << 18) | (mask_m[53] << 16)
+ | (mask_m[54] << 14) | (mask_m[55] << 12)
+ | (mask_m[56] << 10) | (mask_m[57] << 8)
+ | (mask_m[58] << 6) | (mask_m[59] << 4)
+ | (mask_m[60] << 2) | (mask_m[61] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask);
+
+ tmp_mask = (mask_m[31] << 28)
+ | (mask_m[32] << 26) | (mask_m[33] << 24)
+ | (mask_m[34] << 22) | (mask_m[35] << 20)
+ | (mask_m[36] << 18) | (mask_m[37] << 16)
+ | (mask_m[48] << 14) | (mask_m[39] << 12)
+ | (mask_m[40] << 10) | (mask_m[41] << 8)
+ | (mask_m[42] << 6) | (mask_m[43] << 4)
+ | (mask_m[44] << 2) | (mask_m[45] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask);
+
+ tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28)
+ | (mask_m[18] << 26) | (mask_m[18] << 24)
+ | (mask_m[20] << 22) | (mask_m[20] << 20)
+ | (mask_m[22] << 18) | (mask_m[22] << 16)
+ | (mask_m[24] << 14) | (mask_m[24] << 12)
+ | (mask_m[25] << 10) | (mask_m[26] << 8)
+ | (mask_m[27] << 6) | (mask_m[28] << 4)
+ | (mask_m[29] << 2) | (mask_m[30] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask);
+
+ tmp_mask = (mask_m[ 0] << 30) | (mask_m[ 1] << 28)
+ | (mask_m[ 2] << 26) | (mask_m[ 3] << 24)
+ | (mask_m[ 4] << 22) | (mask_m[ 5] << 20)
+ | (mask_m[ 6] << 18) | (mask_m[ 7] << 16)
+ | (mask_m[ 8] << 14) | (mask_m[ 9] << 12)
+ | (mask_m[10] << 10) | (mask_m[11] << 8)
+ | (mask_m[12] << 6) | (mask_m[13] << 4)
+ | (mask_m[14] << 2) | (mask_m[15] << 0);
+ OS_REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask);
+
+ tmp_mask = (mask_p[15] << 28)
+ | (mask_p[14] << 26) | (mask_p[13] << 24)
+ | (mask_p[12] << 22) | (mask_p[11] << 20)
+ | (mask_p[10] << 18) | (mask_p[ 9] << 16)
+ | (mask_p[ 8] << 14) | (mask_p[ 7] << 12)
+ | (mask_p[ 6] << 10) | (mask_p[ 5] << 8)
+ | (mask_p[ 4] << 6) | (mask_p[ 3] << 4)
+ | (mask_p[ 2] << 2) | (mask_p[ 1] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask);
+
+ tmp_mask = (mask_p[30] << 28)
+ | (mask_p[29] << 26) | (mask_p[28] << 24)
+ | (mask_p[27] << 22) | (mask_p[26] << 20)
+ | (mask_p[25] << 18) | (mask_p[24] << 16)
+ | (mask_p[23] << 14) | (mask_p[22] << 12)
+ | (mask_p[21] << 10) | (mask_p[20] << 8)
+ | (mask_p[19] << 6) | (mask_p[18] << 4)
+ | (mask_p[17] << 2) | (mask_p[16] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask);
+
+ tmp_mask = (mask_p[45] << 28)
+ | (mask_p[44] << 26) | (mask_p[43] << 24)
+ | (mask_p[42] << 22) | (mask_p[41] << 20)
+ | (mask_p[40] << 18) | (mask_p[39] << 16)
+ | (mask_p[38] << 14) | (mask_p[37] << 12)
+ | (mask_p[36] << 10) | (mask_p[35] << 8)
+ | (mask_p[34] << 6) | (mask_p[33] << 4)
+ | (mask_p[32] << 2) | (mask_p[31] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask);
+
+ tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28)
+ | (mask_p[59] << 26) | (mask_p[58] << 24)
+ | (mask_p[57] << 22) | (mask_p[56] << 20)
+ | (mask_p[55] << 18) | (mask_p[54] << 16)
+ | (mask_p[53] << 14) | (mask_p[52] << 12)
+ | (mask_p[51] << 10) | (mask_p[50] << 8)
+ | (mask_p[49] << 6) | (mask_p[48] << 4)
+ | (mask_p[47] << 2) | (mask_p[46] << 0);
+ OS_REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask);
+ OS_REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
+}
+
+/*
+ * Fill all software cached or static hardware state information.
+ * Return failure if capabilities are to come from EEPROM and
+ * cannot be read.
+ */
+static HAL_BOOL
+ar9280FillCapabilityInfo(struct ath_hal *ah)
+{
+ HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
+
+ if (!ar5416FillCapabilityInfo(ah))
+ return AH_FALSE;
+ pCap->halNumGpioPins = 10;
+ pCap->halWowSupport = AH_TRUE;
+ pCap->halWowMatchPatternExact = AH_TRUE;
+#if 0
+ pCap->halWowMatchPatternDword = AH_TRUE;
+#endif
+ pCap->halCSTSupport = AH_TRUE;
+ pCap->halRifsRxSupport = AH_TRUE;
+ pCap->halRifsTxSupport = AH_TRUE;
+ pCap->halRtsAggrLimit = 64*1024; /* 802.11n max */
+ pCap->halExtChanDfsSupport = AH_TRUE;
+#if 0
+ /* XXX bluetooth */
+ pCap->halBtCoexSupport = AH_TRUE;
+#endif
+ pCap->halAutoSleepSupport = AH_FALSE; /* XXX? */
+#if 0
+ pCap->hal4kbSplitTransSupport = AH_FALSE;
+#endif
+ pCap->halRxStbcSupport = 1;
+ pCap->halTxStbcSupport = 1;
+
+ return AH_TRUE;
+}
+
+HAL_BOOL
+ar9280SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings)
+{
+#define ANTENNA0_CHAINMASK 0x1
+#define ANTENNA1_CHAINMASK 0x2
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ /* Antenna selection is done by setting the tx/rx chainmasks approp. */
+ switch (settings) {
+ case HAL_ANT_FIXED_A:
+ /* Enable first antenna only */
+ ahp->ah_tx_chainmask = ANTENNA0_CHAINMASK;
+ ahp->ah_rx_chainmask = ANTENNA0_CHAINMASK;
+ break;
+ case HAL_ANT_FIXED_B:
+ /* Enable second antenna only, after checking capability */
+ if (AH_PRIVATE(ah)->ah_caps.halTxChainMask > ANTENNA1_CHAINMASK)
+ ahp->ah_tx_chainmask = ANTENNA1_CHAINMASK;
+ ahp->ah_rx_chainmask = ANTENNA1_CHAINMASK;
+ break;
+ case HAL_ANT_VARIABLE:
+ /* Restore original chainmask settings */
+ /* XXX */
+ ahp->ah_tx_chainmask = AR5416_DEFAULT_TXCHAINMASK;
+ ahp->ah_rx_chainmask = AR5416_DEFAULT_RXCHAINMASK;
+ break;
+ }
+ return AH_TRUE;
+#undef ANTENNA0_CHAINMASK
+#undef ANTENNA1_CHAINMASK
+}
+
+static const char*
+ar9280Probe(uint16_t vendorid, uint16_t devid)
+{
+ if (vendorid == ATHEROS_VENDOR_ID &&
+ (devid == AR9280_DEVID_PCI || devid == AR9280_DEVID_PCIE))
+ return "Atheros 9280";
+ return AH_NULL;
+}
+AH_CHIP(AR9280, ar9280Probe, ar9280Attach);
diff --git a/sys/dev/ath/ath_hal/ar5416/ar9280v1.ini b/sys/dev/ath/ath_hal/ar5416/ar9280v1.ini
new file mode 100644
index 0000000..96e0f44
--- /dev/null
+++ b/sys/dev/ath/ath_hal/ar5416/ar9280v1.ini
@@ -0,0 +1,582 @@
+/*
+ * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND 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.
+ *
+ * $FreeBSD$
+ */
+/* Auto Generated PCI Register Writes. Created: 10/12/07 */
+
+static const uint32_t ar9280Modes_v1[][6] = {
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+ { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 },
+ { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+ { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 },
+ { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 },
+ { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 },
+ { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
+ { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
+ { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
+ { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18 },
+ { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+ { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190 },
+ { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
+ { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
+ { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+ { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
+ { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 },
+ { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
+ { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
+ { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 },
+ { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a },
+ { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
+ { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+ { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214 },
+ { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218 },
+ { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224 },
+ { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228 },
+ { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c },
+ { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230 },
+ { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4 },
+ { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8 },
+ { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac },
+ { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0 },
+ { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4 },
+ { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8 },
+ { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390 },
+ { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394 },
+ { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398 },
+ { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334 },
+ { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338 },
+ { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac },
+ { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0 },
+ { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4 },
+ { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8 },
+ { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5 },
+ { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9 },
+ { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad },
+ { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
+ { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
+ { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
+ { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
+ { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
+ { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
+ { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
+ { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
+ { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
+ { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
+ { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
+ { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
+ { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
+ { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
+ { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
+ { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
+ { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
+ { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
+ { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
+ { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
+ { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
+ { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
+ { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
+ { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
+ { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
+ { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
+ { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
+ { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
+ { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
+ { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
+ { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
+ { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
+ { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
+ { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
+ { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c },
+ { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 },
+ { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 },
+ { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 },
+ { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 },
+ { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 },
+ { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 },
+ { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 },
+ { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 },
+ { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 },
+ { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 },
+ { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 },
+ { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 },
+ { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c },
+ { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 },
+ { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 },
+ { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 },
+ { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 },
+ { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 },
+ { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 },
+ { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 },
+ { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 },
+ { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad },
+ { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 },
+ { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 },
+ { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 },
+ { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 },
+ { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 },
+ { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 },
+ { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 },
+ { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 },
+ { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 },
+ { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca },
+ { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce },
+ { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 },
+ { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 },
+ { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 },
+ { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 },
+ { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb },
+ { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf },
+ { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 },
+ { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 },
+ { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 },
+ { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 },
+ { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+ { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
+ { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
+ { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b },
+ { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 },
+ { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 },
+ { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a },
+ { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 },
+ { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
+ { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b },
+ { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 },
+ { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 },
+ { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a },
+ { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 },
+ { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b },
+ { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 },
+ { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 },
+ { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a },
+ { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 },
+ { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a },
+ { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 },
+ { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
+ { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c },
+ { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828 },
+ { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000 },
+ { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000 },
+};
+
+static const uint32_t ar9280Common_v1[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020015 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00004024, 0x0000001f },
+ { 0x00007010, 0x00000033 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x40000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x00008070, 0x00000000 },
+ { 0x000080c0, 0x2a82301a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04800 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0x00000000 },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c4, 0x00000000 },
+ { 0x000081d0, 0x00003210 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x00008300, 0x00000000 },
+ { 0x00008304, 0x00000000 },
+ { 0x00008308, 0x00000000 },
+ { 0x0000830c, 0x00000000 },
+ { 0x00008310, 0x00000000 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008318, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000007 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00000000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x000107ff },
+ { 0x00008344, 0x00000000 },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xaf268e30 },
+ { 0x00009810, 0xfd14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x00009840, 0x206a01ae },
+ { 0x0000984c, 0x0040233c },
+ { 0x0000a84c, 0x0040233c },
+ { 0x00009854, 0x00000044 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x04900000 },
+ { 0x0000a920, 0x04900000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009948, 0x9280c00a },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0xe250a51e },
+ { 0x00009958, 0x3388ffff },
+ { 0x00009940, 0x00781204 },
+ { 0x0000c95c, 0x004b6a8e },
+ { 0x0000c968, 0x000003ce },
+ { 0x00009970, 0x190fb514 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x006f00c4 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099b4, 0x00000820 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000000 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099fc, 0x00001042 },
+ { 0x0000a210, 0x4080a333 },
+ { 0x0000a214, 0x40206c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x01834061 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x000003b5 },
+ { 0x0000a22c, 0x23277200 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a23c, 0x13c889af },
+ { 0x0000a240, 0x38490a20 },
+ { 0x0000a244, 0x00007bb6 },
+ { 0x0000a248, 0x0fff3ffc },
+ { 0x0000a24c, 0x00000001 },
+ { 0x0000a250, 0x001da000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0cdbd380 },
+ { 0x0000a25c, 0x0f0f0f01 },
+ { 0x0000a260, 0xdfa91f01 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0ebae9c6 },
+ { 0x0000b26c, 0x0ebae9c6 },
+ { 0x0000d270, 0x00820820 },
+ { 0x0000a278, 0x1ce739ce },
+ { 0x0000a27c, 0x050701ce },
+ { 0x0000a358, 0x7999aa0f },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x1ce739ce },
+ { 0x0000a398, 0x000001ce },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3c8, 0x00000246 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x1ce739ce },
+ { 0x0000a3e0, 0x000001ce },
+ { 0x0000a3e4, 0x00000000 },
+ { 0x0000a3e8, 0x18c43433 },
+ { 0x0000a3ec, 0x00f38081 },
+ { 0x00007800, 0x00040000 },
+ { 0x00007804, 0xdb005012 },
+ { 0x00007808, 0x04924914 },
+ { 0x0000780c, 0x21084210 },
+ { 0x00007810, 0x6d801300 },
+ { 0x00007814, 0x0019beff },
+ { 0x00007818, 0x07e40000 },
+ { 0x0000781c, 0x00492000 },
+ { 0x00007820, 0x92492480 },
+ { 0x00007824, 0x00040000 },
+ { 0x00007828, 0xdb005012 },
+ { 0x0000782c, 0x04924914 },
+ { 0x00007830, 0x21084210 },
+ { 0x00007834, 0x6d801300 },
+ { 0x00007838, 0x0019beff },
+ { 0x0000783c, 0x07e40000 },
+ { 0x00007840, 0x00492000 },
+ { 0x00007844, 0x92492480 },
+ { 0x00007848, 0x00120000 },
+ { 0x00007850, 0x54214514 },
+ { 0x00007858, 0x92592692 },
+ { 0x00007860, 0x52802000 },
+ { 0x00007864, 0x0a8e370e },
+ { 0x00007868, 0xc0102850 },
+ { 0x0000786c, 0x812d4000 },
+ { 0x00007874, 0x001b6db0 },
+ { 0x00007878, 0x00376b63 },
+ { 0x0000787c, 0x06db6db6 },
+ { 0x00007880, 0x006d8000 },
+ { 0x00007884, 0xffeffffe },
+ { 0x00007888, 0xffeffffe },
+ { 0x00007890, 0x00060aeb },
+ { 0x00007894, 0x5a108000 },
+ { 0x00007898, 0x2a850160 },
+};
+
+/* hand-crafted from code that does explicit register writes */
+static const uint32_t ar9280PciePhy_v1[][2] = {
+ { AR_PCIE_SERDES, 0x9248fd00 },
+ { AR_PCIE_SERDES, 0x24924924 },
+ { AR_PCIE_SERDES, 0xa8000019 },
+ { AR_PCIE_SERDES, 0x13160820 },
+ { AR_PCIE_SERDES, 0xe5980560 },
+ { AR_PCIE_SERDES, 0x401deffd },
+ { AR_PCIE_SERDES, 0x1aaabe40 },
+ { AR_PCIE_SERDES, 0xbe105554 },
+ { AR_PCIE_SERDES, 0x00043007 },
+ { AR_PCIE_SERDES2, 0x00000000 },
+};
diff --git a/sys/dev/ath/ath_hal/ar5416/ar9280v2.ini b/sys/dev/ath/ath_hal/ar5416/ar9280v2.ini
new file mode 100644
index 0000000..aa8e524
--- /dev/null
+++ b/sys/dev/ath/ath_hal/ar5416/ar9280v2.ini
@@ -0,0 +1,941 @@
+/*
+ * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
+ * Copyright (c) 2002-2008 Atheros Communications, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND 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.
+ *
+ * $FreeBSD$
+ */
+/* Auto Generated PCI Register Writes. Created: 10/15/08 */
+
+static const uint32_t ar9280Modes_v2[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+ { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+ { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
+ { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+ { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e },
+ { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
+ { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 },
+ { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
+ { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e },
+ { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
+ { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+ { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
+ { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
+ { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+ { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
+ { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 },
+ { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
+ { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
+ { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 },
+ { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c },
+ { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 },
+ { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+ { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 },
+ { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
+ { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+ { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 },
+ { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
+ { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
+ { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 },
+};
+
+static const uint32_t ar9280Common_v2[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020015 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00004024, 0x0000001f },
+ { 0x00004060, 0x00000000 },
+ { 0x00004064, 0x00000000 },
+ { 0x00007010, 0x00000033 },
+ { 0x00007034, 0x00000002 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x40000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x00008070, 0x00000000 },
+ { 0x000080c0, 0x2a80001a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04800 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0xffffffff },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c0, 0x00000000 },
+ { 0x000081d0, 0x00003210 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008264, 0xa8a00010 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x0000829c, 0x00000000 },
+ { 0x00008300, 0x00000040 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000007 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00ff0000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x000107ff },
+ { 0x00008344, 0x00581043 },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xafa68e30 },
+ { 0x00009810, 0xfd14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x0000984c, 0x0040233c },
+ { 0x0000a84c, 0x0040233c },
+ { 0x00009854, 0x00000044 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x00009910, 0x01002310 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x04900000 },
+ { 0x0000a920, 0x04900000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009948, 0x9280c00a },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0x5f3ca3de },
+ { 0x00009958, 0x2108ecff },
+ { 0x00009940, 0x14750604 },
+ { 0x0000c95c, 0x004b6a8e },
+ { 0x00009968, 0x000003ce },
+ { 0x00009970, 0x190fb515 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x006f0000 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099b4, 0x00000820 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000000 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099f0, 0x00000000 },
+ { 0x000099fc, 0x00001042 },
+ { 0x0000a208, 0x803e4788 },
+ { 0x0000a210, 0x4080a333 },
+ { 0x0000a214, 0x40206c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x01834061 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x000003b5 },
+ { 0x0000a22c, 0x233f7180 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a23c, 0x13c88000 },
+ { 0x0000a240, 0x38490a20 },
+ { 0x0000a244, 0x00007bb6 },
+ { 0x0000a248, 0x0fff3ffc },
+ { 0x0000a24c, 0x00000000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0cdbd380 },
+ { 0x0000a25c, 0x0f0f0f01 },
+ { 0x0000a260, 0xdfa91f01 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0ebae9c6 },
+ { 0x0000b26c, 0x0ebae9c6 },
+ { 0x0000d270, 0x00820820 },
+ { 0x0000a278, 0x1ce739ce },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x1ce739ce },
+ { 0x0000a398, 0x000001ce },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3c8, 0x00000246 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x1ce739ce },
+ { 0x0000a3e0, 0x000001ce },
+ { 0x0000a3e4, 0x00000000 },
+ { 0x0000a3e8, 0x18c43433 },
+ { 0x0000a3ec, 0x00f70081 },
+ { 0x00007800, 0x00040000 },
+ { 0x00007804, 0xdb005012 },
+ { 0x00007808, 0x04924914 },
+ { 0x0000780c, 0x21084210 },
+ { 0x00007810, 0x6d801300 },
+ { 0x00007818, 0x07e41000 },
+ { 0x0000781c, 0x00392000 },
+ { 0x00007820, 0x92592480 },
+ { 0x00007824, 0x00040000 },
+ { 0x00007828, 0xdb005012 },
+ { 0x0000782c, 0x04924914 },
+ { 0x00007830, 0x21084210 },
+ { 0x00007834, 0x6d801300 },
+ { 0x0000783c, 0x07e40000 },
+ { 0x00007840, 0x00392000 },
+ { 0x00007844, 0x92592480 },
+ { 0x00007848, 0x00100000 },
+ { 0x0000784c, 0x773f0567 },
+ { 0x00007850, 0x54214514 },
+ { 0x00007854, 0x12035828 },
+ { 0x00007858, 0x9259269a },
+ { 0x00007860, 0x52802000 },
+ { 0x00007864, 0x0a8e370e },
+ { 0x00007868, 0xc0102850 },
+ { 0x0000786c, 0x812d4000 },
+ { 0x00007870, 0x807ec400 },
+ { 0x00007874, 0x001b6db0 },
+ { 0x00007878, 0x00376b63 },
+ { 0x0000787c, 0x06db6db6 },
+ { 0x00007880, 0x006d8000 },
+ { 0x00007884, 0xffeffffe },
+ { 0x00007888, 0xffeffffe },
+ { 0x0000788c, 0x00010000 },
+ { 0x00007890, 0x02060aeb },
+ { 0x00007898, 0x2a850160 },
+};
+
+static const uint32_t ar9280Modes_fast_clock_v2[][3] = {
+ /* Address 5G-HT20 5G-HT40 */
+ { 0x00001030, 0x00000268, 0x000004d0 },
+ { 0x00001070, 0x0000018c, 0x00000318 },
+ { 0x000010b0, 0x00000fd0, 0x00001fa0 },
+ { 0x00008014, 0x044c044c, 0x08980898 },
+ { 0x0000801c, 0x148ec02b, 0x148ec057 },
+ { 0x00008318, 0x000044c0, 0x00008980 },
+ { 0x00009820, 0x02020200, 0x02020200 },
+ { 0x00009824, 0x00000f0f, 0x00000f0f },
+ { 0x00009828, 0x0b020001, 0x0b020001 },
+ { 0x00009834, 0x00000f0f, 0x00000f0f },
+ { 0x00009844, 0x03721821, 0x03721821 },
+ { 0x00009914, 0x00000898, 0x00001130 },
+ { 0x00009918, 0x0000000b, 0x00000016 },
+ { 0x00009944, 0xdfbc1210, 0xdfbc1210 },
+};
+
+static const uint32_t ar9280Modes_backoff_23db_rxgain_v2[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
+ { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
+ { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
+ { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
+ { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
+ { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
+ { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
+ { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
+ { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
+ { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
+ { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
+ { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
+ { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
+ { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
+ { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
+ { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
+ { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
+ { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
+ { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
+ { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
+ { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
+ { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
+ { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
+ { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
+ { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
+ { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
+ { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
+ { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
+ { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
+ { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
+ { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
+ { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
+ { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
+ { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
+ { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
+ { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
+ { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
+ { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
+ { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
+ { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
+ { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
+ { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
+ { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
+ { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
+ { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
+ { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
+ { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
+ { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
+ { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 },
+ { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 },
+ { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 },
+ { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 },
+ { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 },
+ { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d },
+ { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 },
+ { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 },
+ { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 },
+ { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 },
+ { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a },
+ { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e },
+ { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 },
+ { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 },
+ { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 },
+ { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 },
+ { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b },
+ { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f },
+ { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 },
+ { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 },
+ { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 },
+ { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 },
+ { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b },
+ { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f },
+ { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 },
+ { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 },
+ { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 },
+ { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 },
+ { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b },
+ { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f },
+ { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 },
+ { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 },
+ { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
+ { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
+};
+
+static const uint32_t ar9280Modes_original_rxgain_v2[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
+ { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
+ { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
+ { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
+ { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
+ { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
+ { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
+ { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
+ { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
+ { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
+ { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
+ { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
+ { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
+ { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
+ { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
+ { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
+ { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
+ { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
+ { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
+ { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
+ { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
+ { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
+ { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
+ { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
+ { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
+ { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
+ { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
+ { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
+ { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
+ { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
+ { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
+ { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
+ { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
+ { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
+ { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
+ { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
+ { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
+ { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
+ { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
+ { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
+ { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
+ { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
+ { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
+ { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
+ { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
+ { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
+ { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
+ { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
+ { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
+ { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
+ { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
+ { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
+ { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
+ { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
+ { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
+ { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
+ { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
+ { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
+ { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c },
+ { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 },
+ { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 },
+ { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 },
+ { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 },
+ { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 },
+ { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 },
+ { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 },
+ { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 },
+ { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 },
+ { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 },
+ { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 },
+ { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 },
+ { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c },
+ { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 },
+ { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 },
+ { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 },
+ { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 },
+ { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 },
+ { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 },
+ { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 },
+ { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 },
+ { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad },
+ { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 },
+ { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 },
+ { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 },
+ { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 },
+ { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 },
+ { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 },
+ { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 },
+ { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 },
+ { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 },
+ { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca },
+ { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce },
+ { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 },
+ { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 },
+ { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 },
+ { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 },
+ { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb },
+ { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf },
+ { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 },
+ { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
+ { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
+ { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
+};
+
+static const uint32_t ar9280Modes_backoff_13db_rxgain_v2[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
+ { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
+ { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
+ { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
+ { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
+ { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
+ { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
+ { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
+ { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
+ { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
+ { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
+ { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
+ { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
+ { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
+ { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
+ { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
+ { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
+ { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
+ { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
+ { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
+ { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
+ { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
+ { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
+ { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
+ { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
+ { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
+ { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
+ { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
+ { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
+ { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
+ { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
+ { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
+ { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
+ { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
+ { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
+ { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
+ { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
+ { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
+ { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
+ { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
+ { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
+ { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
+ { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
+ { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
+ { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
+ { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
+ { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
+ { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
+ { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
+ { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
+ { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
+ { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
+ { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
+ { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
+ { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
+ { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
+ { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
+ { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
+ { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 },
+ { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 },
+ { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 },
+ { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 },
+ { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 },
+ { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c },
+ { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 },
+ { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 },
+ { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 },
+ { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 },
+ { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 },
+ { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d },
+ { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 },
+ { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 },
+ { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 },
+ { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 },
+ { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a },
+ { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e },
+ { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 },
+ { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 },
+ { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 },
+ { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 },
+ { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b },
+ { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f },
+ { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 },
+ { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 },
+ { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 },
+ { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 },
+ { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b },
+ { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f },
+ { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 },
+ { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 },
+ { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
+ { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
+};
+
+static const uint32_t ar9280Modes_high_power_tx_gain_v2[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 },
+ { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 },
+ { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 },
+ { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 },
+ { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 },
+ { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a },
+ { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 },
+ { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
+ { 0x0000a324, 0x00020092, 0x00020092, 0x00022411, 0x00022411, 0x00022411 },
+ { 0x0000a328, 0x0002410a, 0x0002410a, 0x00025413, 0x00025413, 0x00025413 },
+ { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00029811, 0x00029811, 0x00029811 },
+ { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002c813, 0x0002c813, 0x0002c813 },
+ { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030a14, 0x00030a14, 0x00030a14 },
+ { 0x0000a338, 0x000321ec, 0x000321ec, 0x00035a50, 0x00035a50, 0x00035a50 },
+ { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00039c4c, 0x00039c4c, 0x00039c4c },
+ { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003de8a, 0x0003de8a, 0x0003de8a },
+ { 0x0000a344, 0x000321ec, 0x000321ec, 0x00042e92, 0x00042e92, 0x00042e92 },
+ { 0x0000a348, 0x000321ec, 0x000321ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 },
+ { 0x0000a34c, 0x000321ec, 0x000321ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 },
+ { 0x0000a350, 0x000321ec, 0x000321ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 },
+ { 0x0000a354, 0x000321ec, 0x000321ec, 0x00053fd5, 0x00053fd5, 0x00053fd5 },
+ { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
+ { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
+ { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce },
+};
+
+static const uint32_t ar9280Modes_original_tx_gain_v2[][6] = {
+ /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
+ { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
+ { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b },
+ { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 },
+ { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 },
+ { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a },
+ { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 },
+ { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
+ { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b },
+ { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 },
+ { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 },
+ { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a },
+ { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 },
+ { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b },
+ { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 },
+ { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 },
+ { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a },
+ { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 },
+ { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a },
+ { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 },
+ { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
+ { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
+ { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
+ { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
+};
+
+/* Auto generated PCI-E PHY config for Merlin with CLKREQ de-asserted in L1 mode. */
+/* In L1 mode, deassert CLKREQ, power consumption will be lower than leaving CLKREQ asserted. */
+static const uint32_t ar9280PciePhy_clkreq_off_L1_v2[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffc },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+/* Auto generated PCI-E PHY config for Merlin with CLKREQ always asserted in L1 mode */
+/* In L1 mode leave CLKREQ asserted, power consumption will be little high. */
+static const uint32_t ar9280PciePhy_clkreq_always_on_L1_v2[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffd },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+/* Auto generated PCI-E PHY config for Merlin with WOW */
+static const uint32_t ar9280PciePhy_AWOW_merlin[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01ddffd },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 3a401fe..32fbbe8 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_ath.h"
+#include "opt_wlan.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -70,7 +71,10 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
+#ifdef IEEE80211_SUPPORT_TDMA
#include <net80211/ieee80211_tdma.h>
#endif
@@ -89,11 +93,6 @@ __FBSDID("$FreeBSD$");
#endif
/*
- * We require a HAL w/ the changes for split tx/rx MIC.
- */
-CTASSERT(HAL_ABI_VERSION > 0x06052200);
-
-/*
* ATH_BCBUF determines the number of vap's that can transmit
* beacons and also (currently) the number of vap's that can
* have unique mac addresses/bssid. When staggering beacons
@@ -218,14 +217,14 @@ static int ath_raw_xmit(struct ieee80211_node *,
static void ath_bpfattach(struct ath_softc *);
static void ath_announce(struct ath_softc *);
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
static void ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt,
u_int32_t bintval);
static void ath_tdma_bintvalsetup(struct ath_softc *sc,
const struct ieee80211_tdma_state *tdma);
static void ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap);
static void ath_tdma_update(struct ieee80211_node *ni,
- const struct ieee80211_tdma_param *tdma);
+ const struct ieee80211_tdma_param *tdma, int);
static void ath_tdma_beacon_send(struct ath_softc *sc,
struct ieee80211vap *vap);
@@ -260,7 +259,7 @@ ath_hal_getcca(struct ath_hal *ah)
#define TDMA_EP_RND(x,mul) \
((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
#define TDMA_AVG(x) TDMA_EP_RND(x, TDMA_EP_MULTIPLIER)
-#endif /* ATH_SUPPORT_TDMA */
+#endif /* IEEE80211_SUPPORT_TDMA */
SYSCTL_DECL(_hw_ath);
@@ -358,6 +357,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
HAL_STATUS status;
int error = 0, i;
u_int wmodes;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid);
@@ -380,13 +380,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
error = ENXIO;
goto bad;
}
- if (ah->ah_abi != HAL_ABI_VERSION) {
- if_printf(ifp, "HAL ABI mismatch detected "
- "(HAL:0x%x != driver:0x%x)\n",
- ah->ah_abi, HAL_ABI_VERSION);
- error = ENXIO;
- goto bad;
- }
sc->sc_ah = ah;
sc->sc_invalid = 0; /* ready to go, enable interrupt handling */
#ifdef ATH_DEBUG
@@ -669,7 +662,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
wmodes = ath_hal_getwirelessmodes(ah);
if (wmodes & (HAL_MODE_108G|HAL_MODE_TURBO))
ic->ic_caps |= IEEE80211_C_TURBOP;
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
if (ath_hal_macversion(ah) > 0x78) {
ic->ic_caps |= IEEE80211_C_TDMA; /* capable of TDMA */
ic->ic_tdma_update = ath_tdma_update;
@@ -693,14 +686,14 @@ ath_attach(u_int16_t devid, struct ath_softc *sc)
sc->sc_hasveol = ath_hal_hasveol(ah);
/* get mac address from hardware */
- ath_hal_getmac(ah, ic->ic_myaddr);
+ ath_hal_getmac(ah, macaddr);
if (sc->sc_hasbmask)
ath_hal_getbssidmask(ah, sc->sc_hwbssidmask);
/* NB: used to size node table key mapping array */
ic->ic_max_keyix = sc->sc_keymax;
/* call MI attach routine. */
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, macaddr);
ic->ic_setregdomain = ath_setregdomain;
ic->ic_getradiocaps = ath_getradiocaps;
sc->sc_opmode = HAL_M_STA;
@@ -898,7 +891,7 @@ ath_vap_create(struct ieee80211com *ic,
needbeacon = 1;
break;
case IEEE80211_M_AHDEMO:
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
if (flags & IEEE80211_CLONE_TDMA) {
needbeacon = 1;
flags |= IEEE80211_CLONE_NOBEACONS;
@@ -1023,7 +1016,7 @@ ath_vap_create(struct ieee80211com *ic,
sc->sc_opmode = HAL_M_STA;
break;
case IEEE80211_M_AHDEMO:
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
if (vap->iv_caps & IEEE80211_C_TDMA) {
sc->sc_tdma = 1;
/* NB: disable tsf adjust */
@@ -1129,7 +1122,7 @@ ath_vap_delete(struct ieee80211vap *vap)
}
if (vap->iv_opmode != IEEE80211_M_WDS)
sc->sc_nvaps--;
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
/* TDMA operation ceases when the last vap is destroyed */
if (sc->sc_tdma && sc->sc_nvaps == 0) {
sc->sc_tdma = 0;
@@ -1290,7 +1283,7 @@ ath_intr(void *arg)
* this is too slow to meet timing constraints
* under load.
*/
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
if (sc->sc_tdma) {
if (sc->sc_tdmaswba == 0) {
struct ieee80211com *ic = ifp->if_l2com;
@@ -1303,7 +1296,17 @@ ath_intr(void *arg)
sc->sc_tdmaswba--;
} else
#endif
+ {
ath_beacon_proc(sc, 0);
+#ifdef IEEE80211_SUPPORT_SUPERG
+ /*
+ * Schedule the rx taskq in case there's no
+ * traffic so any frames held on the staging
+ * queue are aged and potentially flushed.
+ */
+ taskqueue_enqueue(sc->sc_tq, &sc->sc_rxtask);
+#endif
+ }
}
if (status & HAL_INT_RXEOL) {
/*
@@ -1637,7 +1640,7 @@ ath_reset(struct ifnet *ifp)
*/
ath_chan_change(sc, ic->ic_curchan);
if (sc->sc_beacons) {
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
if (sc->sc_tdma)
ath_tdma_config(sc, NULL);
else
@@ -1672,320 +1675,6 @@ ath_reset_vap(struct ieee80211vap *vap, u_long cmd)
return ath_reset(ifp);
}
-static int
-ath_ff_always(struct ath_txq *txq, struct ath_buf *bf)
-{
- return 0;
-}
-
-#if 0
-static int
-ath_ff_ageflushtestdone(struct ath_txq *txq, struct ath_buf *bf)
-{
- return (txq->axq_curage - bf->bf_age) < ATH_FF_STAGEMAX;
-}
-#endif
-
-/*
- * Flush FF staging queue.
- */
-static void
-ath_ff_stageq_flush(struct ath_softc *sc, struct ath_txq *txq,
- int (*ath_ff_flushdonetest)(struct ath_txq *txq, struct ath_buf *bf))
-{
- struct ath_buf *bf;
- struct ieee80211_node *ni;
- int pktlen, pri;
-
- for (;;) {
- ATH_TXQ_LOCK(txq);
- /*
- * Go from the back (oldest) to front so we can
- * stop early based on the age of the entry.
- */
- bf = TAILQ_LAST(&txq->axq_stageq, axq_headtype);
- if (bf == NULL || ath_ff_flushdonetest(txq, bf)) {
- ATH_TXQ_UNLOCK(txq);
- break;
- }
-
- ni = bf->bf_node;
- pri = M_WME_GETAC(bf->bf_m);
- KASSERT(ATH_NODE(ni)->an_ff_buf[pri],
- ("no bf on staging queue %p", bf));
- ATH_NODE(ni)->an_ff_buf[pri] = NULL;
- TAILQ_REMOVE(&txq->axq_stageq, bf, bf_stagelist);
-
- ATH_TXQ_UNLOCK(txq);
-
- DPRINTF(sc, ATH_DEBUG_FF, "%s: flush frame, age %u\n",
- __func__, bf->bf_age);
-
- sc->sc_stats.ast_ff_flush++;
-
- /* encap and xmit */
- bf->bf_m = ieee80211_encap(ni, bf->bf_m);
- if (bf->bf_m == NULL) {
- DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF,
- "%s: discard, encapsulation failure\n",
- __func__);
- sc->sc_stats.ast_tx_encap++;
- goto bad;
- }
- pktlen = bf->bf_m->m_pkthdr.len; /* NB: don't reference below */
- if (ath_tx_start(sc, ni, bf, bf->bf_m) == 0) {
-#if 0 /*XXX*/
- ifp->if_opackets++;
-#endif
- continue;
- }
- bad:
- if (ni != NULL)
- ieee80211_free_node(ni);
- bf->bf_node = NULL;
- if (bf->bf_m != NULL) {
- m_freem(bf->bf_m);
- bf->bf_m = NULL;
- }
-
- ATH_TXBUF_LOCK(sc);
- STAILQ_INSERT_HEAD(&sc->sc_txbuf, bf, bf_list);
- ATH_TXBUF_UNLOCK(sc);
- }
-}
-
-static __inline u_int32_t
-ath_ff_approx_txtime(struct ath_softc *sc, struct ath_node *an, struct mbuf *m)
-{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
- u_int32_t framelen;
- struct ath_buf *bf;
-
- /*
- * Approximate the frame length to be transmitted. A swag to add
- * the following maximal values to the skb payload:
- * - 32: 802.11 encap + CRC
- * - 24: encryption overhead (if wep bit)
- * - 4 + 6: fast-frame header and padding
- * - 16: 2 LLC FF tunnel headers
- * - 14: 1 802.3 FF tunnel header (skb already accounts for 2nd)
- */
- framelen = m->m_pkthdr.len + 32 + 4 + 6 + 16 + 14;
- if (ic->ic_flags & IEEE80211_F_PRIVACY)
- framelen += 24;
- bf = an->an_ff_buf[M_WME_GETAC(m)];
- if (bf != NULL)
- framelen += bf->bf_m->m_pkthdr.len;
- return ath_hal_computetxtime(sc->sc_ah, sc->sc_currates, framelen,
- sc->sc_lastdatarix, AH_FALSE);
-}
-
-/*
- * Determine if a data frame may be aggregated via ff tunnelling.
- * Note the caller is responsible for checking if the destination
- * supports fast frames.
- *
- * NB: allowing EAPOL frames to be aggregated with other unicast traffic.
- * Do 802.1x EAPOL frames proceed in the clear? Then they couldn't
- * be aggregated with other types of frames when encryption is on?
- *
- * NB: assumes lock on an_ff_buf effectively held by txq lock mechanism.
- */
-static __inline int
-ath_ff_can_aggregate(struct ath_softc *sc,
- struct ath_node *an, struct mbuf *m, int *flushq)
-{
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
- struct ath_txq *txq;
- u_int32_t txoplimit;
- u_int pri;
-
- *flushq = 0;
-
- /*
- * If there is no frame to combine with and the txq has
- * fewer frames than the minimum required; then do not
- * attempt to aggregate this frame.
- */
- pri = M_WME_GETAC(m);
- txq = sc->sc_ac2q[pri];
- if (an->an_ff_buf[pri] == NULL && txq->axq_depth < sc->sc_fftxqmin)
- return 0;
- /*
- * When not in station mode never aggregate a multicast
- * frame; this insures, for example, that a combined frame
- * does not require multiple encryption keys when using
- * 802.1x/WPA.
- */
- if (ic->ic_opmode != IEEE80211_M_STA &&
- ETHER_IS_MULTICAST(mtod(m, struct ether_header *)->ether_dhost))
- return 0;
- /*
- * Consult the max bursting interval to insure a combined
- * frame fits within the TxOp window.
- */
- txoplimit = IEEE80211_TXOP_TO_US(
- ic->ic_wme.wme_chanParams.cap_wmeParams[pri].wmep_txopLimit);
- if (txoplimit != 0 && ath_ff_approx_txtime(sc, an, m) > txoplimit) {
- DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF,
- "%s: FF TxOp violation\n", __func__);
- if (an->an_ff_buf[pri] != NULL)
- *flushq = 1;
- return 0;
- }
- return 1; /* try to aggregate */
-}
-
-/*
- * Check if the supplied frame can be partnered with an existing
- * or pending frame. Return a reference to any frame that should be
- * sent on return; otherwise return NULL.
- */
-static struct mbuf *
-ath_ff_check(struct ath_softc *sc, struct ath_txq *txq,
- struct ath_buf *bf, struct mbuf *m, struct ieee80211_node *ni)
-{
- struct ath_node *an = ATH_NODE(ni);
- struct ath_buf *bfstaged;
- int ff_flush, pri;
-
- /*
- * Check if the supplied frame can be aggregated.
- *
- * NB: we use the txq lock to protect references to
- * an->an_ff_txbuf in ath_ff_can_aggregate().
- */
- ATH_TXQ_LOCK(txq);
- pri = M_WME_GETAC(m);
- if (ath_ff_can_aggregate(sc, an, m, &ff_flush)) {
- struct ath_buf *bfstaged = an->an_ff_buf[pri];
- if (bfstaged != NULL) {
- /*
- * A frame is available for partnering; remove
- * it, chain it to this one, and encapsulate.
- */
- an->an_ff_buf[pri] = NULL;
- TAILQ_REMOVE(&txq->axq_stageq, bfstaged, bf_stagelist);
- ATH_TXQ_UNLOCK(txq);
-
- /*
- * Chain mbufs and add FF magic.
- */
- DPRINTF(sc, ATH_DEBUG_FF,
- "[%s] aggregate fast-frame, age %u\n",
- ether_sprintf(ni->ni_macaddr), txq->axq_curage);
- m->m_nextpkt = NULL;
- bfstaged->bf_m->m_nextpkt = m;
- m = bfstaged->bf_m;
- bfstaged->bf_m = NULL;
- m->m_flags |= M_FF;
- /*
- * Release the node reference held while
- * the packet sat on an_ff_buf[]
- */
- bfstaged->bf_node = NULL;
- ieee80211_free_node(ni);
-
- /*
- * Return bfstaged to the free list.
- */
- ATH_TXBUF_LOCK(sc);
- STAILQ_INSERT_HEAD(&sc->sc_txbuf, bfstaged, bf_list);
- ATH_TXBUF_UNLOCK(sc);
-
- return m; /* ready to go */
- } else {
- /*
- * No frame available, queue this frame to wait
- * for a partner. Note that we hold the buffer
- * and a reference to the node; we need the
- * buffer in particular so we're certain we
- * can flush the frame at a later time.
- */
- DPRINTF(sc, ATH_DEBUG_FF,
- "[%s] stage fast-frame, age %u\n",
- ether_sprintf(ni->ni_macaddr), txq->axq_curage);
-
- bf->bf_m = m;
- bf->bf_node = ni; /* NB: held reference */
- bf->bf_age = txq->axq_curage;
- an->an_ff_buf[pri] = bf;
- TAILQ_INSERT_HEAD(&txq->axq_stageq, bf, bf_stagelist);
- ATH_TXQ_UNLOCK(txq);
-
- return NULL; /* consumed */
- }
- }
- /*
- * Frame could not be aggregated, it needs to be returned
- * to the caller for immediate transmission. In addition
- * we check if we should first flush a frame from the
- * staging queue before sending this one.
- *
- * NB: ath_ff_can_aggregate only marks ff_flush if a frame
- * is present to flush.
- */
- if (ff_flush) {
- int pktlen;
-
- bfstaged = an->an_ff_buf[pri];
- an->an_ff_buf[pri] = NULL;
- TAILQ_REMOVE(&txq->axq_stageq, bfstaged, bf_stagelist);
- ATH_TXQ_UNLOCK(txq);
-
- DPRINTF(sc, ATH_DEBUG_FF, "[%s] flush staged frame\n",
- ether_sprintf(an->an_node.ni_macaddr));
-
- /* encap and xmit */
- bfstaged->bf_m = ieee80211_encap(ni, bfstaged->bf_m);
- if (bfstaged->bf_m == NULL) {
- DPRINTF(sc, ATH_DEBUG_XMIT | ATH_DEBUG_FF,
- "%s: discard, encap failure\n", __func__);
- sc->sc_stats.ast_tx_encap++;
- goto ff_flushbad;
- }
- pktlen = bfstaged->bf_m->m_pkthdr.len;
- if (ath_tx_start(sc, ni, bfstaged, bfstaged->bf_m)) {
- DPRINTF(sc, ATH_DEBUG_XMIT,
- "%s: discard, xmit failure\n", __func__);
- ff_flushbad:
- /*
- * Unable to transmit frame that was on the staging
- * queue. Reclaim the node reference and other
- * resources.
- */
- if (ni != NULL)
- ieee80211_free_node(ni);
- bfstaged->bf_node = NULL;
- if (bfstaged->bf_m != NULL) {
- m_freem(bfstaged->bf_m);
- bfstaged->bf_m = NULL;
- }
-
- ATH_TXBUF_LOCK(sc);
- STAILQ_INSERT_HEAD(&sc->sc_txbuf, bfstaged, bf_list);
- ATH_TXBUF_UNLOCK(sc);
- } else {
-#if 0
- ifp->if_opackets++;
-#endif
- }
- } else {
- if (an->an_ff_buf[pri] != NULL) {
- /*
- * XXX: out-of-order condition only occurs for AP
- * mode and multicast. There may be no valid way
- * to get this condition.
- */
- DPRINTF(sc, ATH_DEBUG_FF, "[%s] out-of-order frame\n",
- ether_sprintf(an->an_node.ni_macaddr));
- /* XXX stat */
- }
- ATH_TXQ_UNLOCK(txq);
- }
- return m;
-}
-
static struct ath_buf *
_ath_getbuf_locked(struct ath_softc *sc)
{
@@ -2080,9 +1769,7 @@ ath_start(struct ifnet *ifp)
struct ieee80211_node *ni;
struct ath_buf *bf;
struct mbuf *m, *next;
- struct ath_txq *txq;
ath_bufhead frags;
- int pri;
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 || sc->sc_invalid)
return;
@@ -2101,47 +1788,14 @@ ath_start(struct ifnet *ifp)
ATH_TXBUF_UNLOCK(sc);
break;
}
- STAILQ_INIT(&frags);
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- pri = M_WME_GETAC(m);
- txq = sc->sc_ac2q[pri];
- if (IEEE80211_ATH_CAP(ni->ni_vap, ni, IEEE80211_NODE_FF)) {
- /*
- * Check queue length; if too deep drop this
- * frame (tail drop considered good).
- */
- if (txq->axq_depth >= sc->sc_fftxqmax) {
- DPRINTF(sc, ATH_DEBUG_FF,
- "[%s] tail drop on q %u depth %u\n",
- ether_sprintf(ni->ni_macaddr),
- txq->axq_qnum, txq->axq_depth);
- sc->sc_stats.ast_tx_qfull++;
- m_freem(m);
- goto reclaim;
- }
- m = ath_ff_check(sc, txq, bf, m, ni);
- if (m == NULL) {
- /* NB: ni ref & bf held on stageq */
- continue;
- }
- }
- ifp->if_opackets++;
- /*
- * Encapsulate the packet in prep for transmission.
- */
- m = ieee80211_encap(ni, m);
- if (m == NULL) {
- DPRINTF(sc, ATH_DEBUG_XMIT,
- "%s: encapsulation failure\n", __func__);
- sc->sc_stats.ast_tx_encap++;
- goto bad;
- }
/*
* Check for fragmentation. If this frame
* has been broken up verify we have enough
* buffers to send all the fragments so all
* go out or none...
*/
+ STAILQ_INIT(&frags);
if ((m->m_flags & M_FRAG) &&
!ath_txfrag_setup(sc, &frags, m, ni)) {
DPRINTF(sc, ATH_DEBUG_XMIT,
@@ -2150,6 +1804,7 @@ ath_start(struct ifnet *ifp)
ath_freetx(m);
goto bad;
}
+ ifp->if_opackets++;
nextfrag:
/*
* Pass the frame to the h/w for transmission.
@@ -2199,13 +1854,6 @@ ath_start(struct ifnet *ifp)
}
sc->sc_wd_timer = 5;
-#if 0
- /*
- * Flush stale frames from the fast-frame staging queue.
- */
- if (ic->ic_opmode != IEEE80211_M_STA)
- ath_ff_stageq_flush(sc, txq, ath_ff_ageflushtestdone);
-#endif
}
}
@@ -2689,17 +2337,8 @@ ath_calcrxfilter(struct ath_softc *sc)
u_int32_t rfilt;
rfilt = HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST;
-#if HAL_ABI_VERSION < 0x08011600
- rfilt |= (ath_hal_getrxfilter(sc->sc_ah) &
- (HAL_RX_FILTER_PHYRADAR | HAL_RX_FILTER_PHYERR));
-#elif HAL_ABI_VERSION < 0x08060100
- if (ic->ic_opmode == IEEE80211_M_STA &&
- !sc->sc_needmib && !sc->sc_scanning)
- rfilt |= HAL_RX_FILTER_PHYERR;
-#else
if (!sc->sc_needmib && !sc->sc_scanning)
rfilt |= HAL_RX_FILTER_PHYERR;
-#endif
if (ic->ic_opmode != IEEE80211_M_STA)
rfilt |= HAL_RX_FILTER_PROBEREQ;
if (ic->ic_opmode == IEEE80211_M_MONITOR || (ifp->if_flags & IFF_PROMISC))
@@ -2776,7 +2415,6 @@ static void
ath_mode_init(struct ath_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
struct ath_hal *ah = sc->sc_ah;
u_int32_t rfilt;
@@ -2787,16 +2425,8 @@ ath_mode_init(struct ath_softc *sc)
/* configure operational mode */
ath_hal_setopmode(ah);
- /*
- * Handle any link-level address change. Note that we only
- * need to force ic_myaddr; any other addresses are handled
- * as a byproduct of the ifnet code marking the interface
- * down then up.
- *
- * XXX should get from lladdr instead of arpcom but that's more work
- */
- IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
- ath_hal_setmac(ah, ic->ic_myaddr);
+ /* handle any link-level address change */
+ ath_hal_setmac(ah, IF_LLADDR(ifp));
/* calculate and install multicast filter */
ath_update_mcast(ifp);
@@ -4305,7 +3935,7 @@ rx_accept:
/*
* Sending station is known, dispatch directly.
*/
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
sc->sc_tdmars = rs;
#endif
type = ieee80211_input(ni, m,
@@ -4363,10 +3993,18 @@ rx_next:
if (ngood)
sc->sc_lastrx = tsf;
- if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0 &&
- !IFQ_IS_EMPTY(&ifp->if_snd))
- ath_start(ifp);
-
+ if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
+#ifdef IEEE80211_SUPPORT_SUPERG
+ if (ic->ic_stageqdepth) {
+ ieee80211_age_stageq(ic, WME_AC_VO, 100);
+ ieee80211_age_stageq(ic, WME_AC_VI, 100);
+ ieee80211_age_stageq(ic, WME_AC_BE, 100);
+ ieee80211_age_stageq(ic, WME_AC_BK, 100);
+ }
+#endif
+ if (!IFQ_IS_EMPTY(&ifp->if_snd))
+ ath_start(ifp);
+ }
#undef PA2DESC
}
@@ -4374,13 +4012,12 @@ static void
ath_txq_init(struct ath_softc *sc, struct ath_txq *txq, int qnum)
{
txq->axq_qnum = qnum;
+ txq->axq_ac = 0;
txq->axq_depth = 0;
txq->axq_intrcnt = 0;
txq->axq_link = NULL;
STAILQ_INIT(&txq->axq_q);
ATH_TXQ_LOCK_INIT(sc, txq);
- TAILQ_INIT(&txq->axq_stageq);
- txq->axq_curage = 0;
}
/*
@@ -4457,6 +4094,7 @@ ath_tx_setup(struct ath_softc *sc, int ac, int haltype)
}
txq = ath_txq_setup(sc, HAL_TX_QUEUE_DATA, haltype);
if (txq != NULL) {
+ txq->axq_ac = ac;
sc->sc_ac2q[ac] = txq;
return 1;
} else
@@ -4480,7 +4118,7 @@ ath_txq_update(struct ath_softc *sc, int ac)
HAL_TXQ_INFO qi;
ath_hal_gettxqueueprops(ah, txq->axq_qnum, &qi);
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
if (sc->sc_tdma) {
/*
* AIFS is zero so there's no pre-transmit wait. The
@@ -4514,7 +4152,7 @@ ath_txq_update(struct ath_softc *sc, int ac)
qi.tqi_cwmax = ATH_EXPONENT_TO_VALUE(wmep->wmep_logcwmax);
qi.tqi_readyTime = 0;
qi.tqi_burstTime = ATH_TXOP_TO_US(wmep->wmep_txopLimit);
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
}
#endif
@@ -4704,7 +4342,7 @@ ath_tx_handoff(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf)
KASSERT((bf->bf_flags & ATH_BUF_BUSY) == 0,
("busy status 0x%x", bf->bf_flags));
if (txq->axq_qnum != ATH_TXQ_SWQ) {
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
int qbusy;
ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
@@ -4774,7 +4412,7 @@ ath_tx_handoff(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf)
txq->axq_qnum, txq->axq_link,
(caddr_t)bf->bf_daddr, bf->bf_desc, txq->axq_depth);
}
-#endif /* ATH_SUPPORT_TDMA */
+#endif /* IEEE80211_SUPPORT_TDMA */
txq->axq_link = &bf->bf_desc[bf->bf_nseg - 1].ds_link;
ath_hal_txstart(ah, txq->axq_qnum);
} else {
@@ -5009,7 +4647,7 @@ ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf
}
if (flags & HAL_TXDESC_NOACK) /* NB: avoid double counting */
sc->sc_stats.ast_tx_noack++;
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
if (sc->sc_tdma && (flags & HAL_TXDESC_NOACK) == 0) {
DPRINTF(sc, ATH_DEBUG_TDMA,
"%s: discard frame, ACK required w/ TDMA\n", __func__);
@@ -5251,7 +4889,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
break;
}
ATH_TXQ_REMOVE_HEAD(txq, bf_list);
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
if (txq->axq_depth > 0) {
/*
* More frames follow. Mark the buffer busy
@@ -5320,13 +4958,6 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
ieee80211_process_callback(ni, bf->bf_m,
(bf->bf_txflags & HAL_TXDESC_NOACK) == 0 ?
ts->ts_status : HAL_TXERR_XRETRY);
- /*
- * Reclaim reference to node.
- *
- * NB: the node may be reclaimed here if, for example
- * this is a DEAUTH message that was sent and the
- * node was timed out due to inactivity.
- */
ieee80211_free_node(ni);
}
bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
@@ -5344,11 +4975,13 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
ATH_TXBUF_UNLOCK(sc);
}
+#ifdef IEEE80211_SUPPORT_SUPERG
/*
* Flush fast-frame staging queue when traffic slows.
*/
if (txq->axq_depth <= 1)
- ath_ff_stageq_flush(sc, txq, ath_ff_always);
+ ieee80211_flush_stageq(ic, txq->axq_ac);
+#endif
return nacked;
}
@@ -5962,7 +5595,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ni->ni_capinfo, ieee80211_chan2ieee(ic, ic->ic_curchan));
switch (vap->iv_opmode) {
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
case IEEE80211_M_AHDEMO:
if ((vap->iv_caps & IEEE80211_C_TDMA) == 0)
break;
@@ -5996,7 +5629,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ni->ni_tstamp.tsf != 0) {
sc->sc_syncbeacon = 1;
} else if (!sc->sc_beacons) {
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
if (vap->iv_caps & IEEE80211_C_TDMA)
ath_tdma_config(sc, vap);
else
@@ -6064,7 +5697,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
taskqueue_block(sc->sc_tq);
sc->sc_beacons = 0;
}
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
ath_hal_setcca(ah, AH_TRUE);
#endif
}
@@ -6273,10 +5906,6 @@ ath_rate_setup(struct ath_softc *sc, u_int mode)
break;
case IEEE80211_MODE_TURBO_A:
rt = ath_hal_getratetable(ah, HAL_MODE_108A);
-#if HAL_ABI_VERSION < 0x07013100
- if (rt == NULL) /* XXX bandaid for old hal's */
- rt = ath_hal_getratetable(ah, HAL_MODE_TURBO);
-#endif
break;
case IEEE80211_MODE_TURBO_G:
rt = ath_hal_getratetable(ah, HAL_MODE_108G);
@@ -6576,7 +6205,7 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
sc->sc_stats.ast_rx_packets = ifp->if_ipackets;
sc->sc_stats.ast_tx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgtxrssi);
sc->sc_stats.ast_rx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgrssi);
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
sc->sc_stats.ast_tdma_tsfadjp = TDMA_AVG(sc->sc_avgtsfdeltap);
sc->sc_stats.ast_tdma_tsfadjm = TDMA_AVG(sc->sc_avgtsfdeltam);
#endif
@@ -6866,7 +6495,7 @@ ath_sysctl_intmit(SYSCTL_HANDLER_ARGS)
return !ath_hal_setintmit(sc->sc_ah, intmit) ? EINVAL : 0;
}
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
static int
ath_sysctl_setcca(SYSCTL_HANDLER_ARGS)
{
@@ -6880,7 +6509,7 @@ ath_sysctl_setcca(SYSCTL_HANDLER_ARGS)
sc->sc_setcca = (setcca != 0);
return 0;
}
-#endif /* ATH_SUPPORT_TDMA */
+#endif /* IEEE80211_SUPPORT_TDMA */
static void
ath_sysctlattach(struct ath_softc *sc)
@@ -6952,16 +6581,6 @@ ath_sysctlattach(struct ath_softc *sc)
"tpcts", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
ath_sysctl_tpcts, "I", "tx power for cts frames");
}
- if (ath_hal_hasfastframes(sc->sc_ah)) {
- sc->sc_fftxqmin = ATH_FF_TXQMIN;
- SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
- "fftxqmin", CTLFLAG_RW, &sc->sc_fftxqmin, 0,
- "min frames before fast-frame staging");
- sc->sc_fftxqmax = ATH_FF_TXQMAX;
- SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
- "fftxqmax", CTLFLAG_RW, &sc->sc_fftxqmax, 0,
- "max queued frames before tail drop");
- }
if (ath_hal_hasrfsilent(ah)) {
SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"rfsilent", CTLTYPE_INT | CTLFLAG_RW, sc, 0,
@@ -6979,7 +6598,7 @@ ath_sysctlattach(struct ath_softc *sc)
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
"monpass", CTLFLAG_RW, &sc->sc_monpass, 0,
"mask of error frames to pass when monitoring");
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
if (ath_hal_macversion(ah) > 0x78) {
sc->sc_tdmadbaprep = 2;
SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
@@ -7318,7 +6937,7 @@ ath_announce(struct ath_softc *sc)
if_printf(ifp, "using %u tx buffers\n", ath_txbuf);
}
-#ifdef ATH_SUPPORT_TDMA
+#ifdef IEEE80211_SUPPORT_TDMA
static __inline uint32_t
ath_hal_getnexttbtt(struct ath_hal *ah)
{
@@ -7477,7 +7096,7 @@ ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap)
*/
static void
ath_tdma_update(struct ieee80211_node *ni,
- const struct ieee80211_tdma_param *tdma)
+ const struct ieee80211_tdma_param *tdma, int changed)
{
#define TSF_TO_TU(_h,_l) \
((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10))
@@ -7498,7 +7117,7 @@ ath_tdma_update(struct ieee80211_node *ni,
/*
* Check for and adopt configuration changes.
*/
- if (isset(ATH_VAP(vap)->av_boff.bo_flags, IEEE80211_BEACON_TDMA)) {
+ if (changed != 0) {
const struct ieee80211_tdma_state *ts = vap->iv_tdma;
ath_tdma_bintvalsetup(sc, ts);
@@ -7678,4 +7297,4 @@ ath_tdma_beacon_send(struct ath_softc *sc, struct ieee80211vap *vap)
vap->iv_bss->ni_tstamp.tsf = ath_hal_gettsf64(ah);
}
}
-#endif /* ATH_SUPPORT_TDMA */
+#endif /* IEEE80211_SUPPORT_TDMA */
diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h
index 540b76a..8f88b59 100644
--- a/sys/dev/ath/if_athvar.h
+++ b/sys/dev/ath/if_athvar.h
@@ -71,10 +71,6 @@
#define ATH_KEYMAX 128 /* max key cache size we handle */
#define ATH_KEYBYTES (ATH_KEYMAX/NBBY) /* storage space in bytes */
-#define ATH_FF_TXQMIN 2 /* min txq depth for staging */
-#define ATH_FF_TXQMAX 50 /* maximum # of queued frames allowed */
-#define ATH_FF_STAGEMAX 5 /* max waiting period for staged frame*/
-
struct taskqueue;
struct kthread;
struct ath_buf;
@@ -106,8 +102,6 @@ struct ath_node {
struct ath_buf {
STAILQ_ENTRY(ath_buf) bf_list;
- TAILQ_ENTRY(ath_buf) bf_stagelist; /* stage queue list */
- u_int32_t bf_age; /* age when placed on stageq */
int bf_nseg;
uint16_t bf_txflags; /* tx descriptor flags */
uint16_t bf_flags; /* status flags (below) */
@@ -151,6 +145,7 @@ struct ath_descdma {
struct ath_txq {
u_int axq_qnum; /* hardware q number */
#define ATH_TXQ_SWQ (HAL_NUM_TX_QUEUES+1) /* qnum for s/w only queue */
+ u_int axq_ac; /* WME AC */
u_int axq_flags;
#define ATH_TXQ_PUTPENDING 0x0001 /* ath_hal_puttxbuf pending */
u_int axq_depth; /* queue depth (stat only) */
@@ -159,13 +154,6 @@ struct ath_txq {
STAILQ_HEAD(, ath_buf) axq_q; /* transmit queue */
struct mtx axq_lock; /* lock on q and link */
char axq_name[12]; /* e.g. "ath0_txq4" */
- /*
- * Fast-frame state. The staging queue holds awaiting
- * a fast-frame pairing. Buffers on this queue are
- * assigned an ``age'' and flushed when they wait too long.
- */
- TAILQ_HEAD(axq_headtype, ath_buf) axq_stageq;
- u_int32_t axq_curage; /* queue age */
};
#define ATH_TXQ_LOCK_INIT(_sc, _tq) do { \
@@ -181,7 +169,6 @@ struct ath_txq {
#define ATH_TXQ_INSERT_TAIL(_tq, _elm, _field) do { \
STAILQ_INSERT_TAIL(&(_tq)->axq_q, (_elm), _field); \
(_tq)->axq_depth++; \
- (_tq)->axq_curage++; \
} while (0)
#define ATH_TXQ_REMOVE_HEAD(_tq, _field) do { \
STAILQ_REMOVE_HEAD(&(_tq)->axq_q, _field); \
@@ -345,18 +332,15 @@ struct ath_softc {
int sc_lastlongcal; /* last long cal completed */
int sc_lastcalreset;/* last cal reset done */
HAL_NODE_STATS sc_halstats; /* station-mode rssi stats */
-#ifdef ATH_SUPPORT_TDMA
u_int sc_tdmadbaprep; /* TDMA DBA prep time */
u_int sc_tdmaswbaprep;/* TDMA SWBA prep time */
u_int sc_tdmaswba; /* TDMA SWBA counter */
u_int32_t sc_tdmabintval; /* TDMA beacon interval (TU) */
u_int32_t sc_tdmaguard; /* TDMA guard time (usec) */
u_int sc_tdmaslotlen; /* TDMA slot length (usec) */
- u_int sc_tdmabintcnt; /* TDMA beacon intvl (slots) */
struct ath_rx_status *sc_tdmars; /* TDMA status of last rx */
u_int32_t sc_avgtsfdeltap;/* TDMA slot adjust (+) */
u_int32_t sc_avgtsfdeltam;/* TDMA slot adjust (-) */
-#endif
};
#define ATH_LOCK_INIT(_sc) \
@@ -462,16 +446,10 @@ void ath_intr(void *);
((*(_ah)->ah_setChannel)((_ah), (_chan)))
#define ath_hal_calibrate(_ah, _chan, _iqcal) \
((*(_ah)->ah_perCalibration)((_ah), (_chan), (_iqcal)))
-#if HAL_ABI_VERSION >= 0x08111000
#define ath_hal_calibrateN(_ah, _chan, _lcal, _isdone) \
((*(_ah)->ah_perCalibrationN)((_ah), (_chan), 0x1, (_lcal), (_isdone)))
#define ath_hal_calreset(_ah, _chan) \
((*(_ah)->ah_resetCalValid)((_ah), (_chan)))
-#else
-#define ath_hal_calibrateN(_ah, _chan, _lcal, _isdone) \
- ath_hal_calibrate(_ah, _chan, _isdone)
-#define ath_hal_calreset(_ah, _chan) (0)
-#endif
#define ath_hal_setledstate(_ah, _state) \
((*(_ah)->ah_setLedState)((_ah), (_state)))
#define ath_hal_beaconinit(_ah, _nextb, _bperiod) \
@@ -545,19 +523,8 @@ void ath_intr(void *);
(ath_hal_getcapability(_ah, HAL_CAP_CIPHER, _cipher, NULL) == HAL_OK)
#define ath_hal_getregdomain(_ah, _prd) \
(ath_hal_getcapability(_ah, HAL_CAP_REG_DMN, 0, (_prd)) == HAL_OK)
-#if HAL_ABI_VERSION < 0x08090100
-/* XXX wrong for anything but amd64 and i386 */
-#if defined(__LP64__)
-#define ath_hal_setregdomain(_ah, _rd) \
- (*(uint16_t *)(((uint8_t *)&(_ah)[1]) + 176) = (_rd))
-#else
-#define ath_hal_setregdomain(_ah, _rd) \
- (*(uint16_t *)(((uint8_t *)&(_ah)[1]) + 128) = (_rd))
-#endif
-#else
#define ath_hal_setregdomain(_ah, _rd) \
ath_hal_setcapability(_ah, HAL_CAP_REG_DMN, 0, _rd, NULL)
-#endif
#define ath_hal_getcountrycode(_ah, _pcc) \
(*(_pcc) = (_ah)->ah_countryCode)
#define ath_hal_gettkipmic(_ah) \
@@ -656,31 +623,6 @@ void ath_intr(void *);
ath_hal_setcapability(_ah, HAL_CAP_INTMIT, 1, _v, NULL)
#define ath_hal_getchannoise(_ah, _c) \
((*(_ah)->ah_getChanNoise)((_ah), (_c)))
-#if HAL_ABI_VERSION < 0x05122200
-#define HAL_TXQ_TXOKINT_ENABLE TXQ_FLAG_TXOKINT_ENABLE
-#define HAL_TXQ_TXERRINT_ENABLE TXQ_FLAG_TXERRINT_ENABLE
-#define HAL_TXQ_TXDESCINT_ENABLE TXQ_FLAG_TXDESCINT_ENABLE
-#define HAL_TXQ_TXEOLINT_ENABLE TXQ_FLAG_TXEOLINT_ENABLE
-#define HAL_TXQ_TXURNINT_ENABLE TXQ_FLAG_TXURNINT_ENABLE
-#endif
-#if HAL_ABI_VERSION < 0x06102501
-#define ath_hal_ispublicsafetysku(ah) \
- (((ah)->ah_regdomain == 0 && (ah)->ah_countryCode == 842) || \
- (ah)->ah_regdomain == 0x12)
-#endif
-#if HAL_ABI_VERSION < 0x06122400
-/* XXX yech, can't get to regdomain so just hack a compat shim */
-#define ath_hal_isgsmsku(ah) \
- ((ah)->ah_countryCode == 843)
-#endif
-#if HAL_ABI_VERSION < 0x07050400
-/* compat shims so code compilers--it won't work though */
-#define CHANNEL_HT20 0x10000
-#define CHANNEL_HT40PLUS 0x20000
-#define CHANNEL_HT40MINUS 0x40000
-#define HAL_MODE_11NG_HT20 0x008000
-#define HAL_MODE_11NA_HT20 0x010000
-#endif
#define ath_hal_setuprxdesc(_ah, _ds, _size, _intreq) \
((*(_ah)->ah_setupRxDesc)((_ah), (_ds), (_size), (_intreq)))
diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c
index 338d8f2..93c9acb 100644
--- a/sys/dev/atkbdc/psm.c
+++ b/sys/dev/atkbdc/psm.c
@@ -70,7 +70,10 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/conf.h>
+#include <sys/filio.h>
#include <sys/poll.h>
+#include <sys/sigio.h>
+#include <sys/signalvar.h>
#include <sys/syslog.h>
#include <machine/bus.h>
#include <sys/rman.h>
@@ -299,6 +302,7 @@ struct psm_softc { /* Driver status information */
struct cdev *bdev;
int lasterr;
int cmdcount;
+ struct sigio *async; /* Processes waiting for SIGIO */
};
static devclass_t psm_devclass;
#define PSM_SOFTC(unit) \
@@ -1490,6 +1494,7 @@ psmopen(struct cdev *dev, int flag, int fmt, struct thread *td)
sc->mode.level = sc->dflt_mode.level;
sc->mode.protocol = sc->dflt_mode.protocol;
sc->watchdog = FALSE;
+ sc->async = NULL;
/* flush the event queue */
sc->queue.count = 0;
@@ -1629,6 +1634,12 @@ psmclose(struct cdev *dev, int flag, int fmt, struct thread *td)
/* remove anything left in the output buffer */
empty_aux_buffer(sc->kbdc, 10);
+ /* clean up and sigio requests */
+ if (sc->async != NULL) {
+ funsetown(&sc->async);
+ sc->async = NULL;
+ }
+
/* close is almost always successful */
sc->state &= ~PSM_OPEN;
kbdc_lock(sc->kbdc, FALSE);
@@ -2190,6 +2201,15 @@ psmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
break;
#endif /* MOUSE_GETHWID */
+ case FIONBIO:
+ case FIOASYNC:
+ break;
+ case FIOSETOWN:
+ error = fsetown(*(int *)addr, &sc->async);
+ break;
+ case FIOGETOWN:
+ *(int *) addr = fgetown(&sc->async);
+ break;
default:
return (ENOTTY);
}
@@ -3454,6 +3474,9 @@ next:
wakeup(sc);
}
selwakeuppri(&sc->rsel, PZERO);
+ if (sc->async != NULL) {
+ pgsigio(&sc->async, SIGIO, 0);
+ }
sc->state &= ~PSM_SOFTARMED;
splx(s);
}
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index e9e5b93..1bfd509 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -384,6 +384,7 @@ static uint32_t bge_readreg_ind(struct bge_softc *, int);
#endif
static void bge_writemem_direct(struct bge_softc *, int, int);
static void bge_writereg_ind(struct bge_softc *, int, int);
+static void bge_set_max_readrq(struct bge_softc *, int);
static int bge_miibus_readreg(device_t, int, int);
static int bge_miibus_writereg(device_t, int, int, int);
@@ -523,6 +524,34 @@ bge_writemem_ind(struct bge_softc *sc, int off, int val)
pci_write_config(dev, BGE_PCI_MEMWIN_BASEADDR, 0, 4);
}
+/*
+ * PCI Express only
+ */
+static void
+bge_set_max_readrq(struct bge_softc *sc, int expr_ptr)
+{
+ device_t dev;
+ uint16_t val;
+
+ KASSERT((sc->bge_flags & BGE_FLAG_PCIE) && expr_ptr != 0,
+ ("%s: not applicable", __func__));
+
+ dev = sc->bge_dev;
+
+ val = pci_read_config(dev, expr_ptr + BGE_PCIE_DEVCTL, 2);
+ if ((val & BGE_PCIE_DEVCTL_MAX_READRQ_MASK) !=
+ BGE_PCIE_DEVCTL_MAX_READRQ_4096) {
+ if (bootverbose)
+ device_printf(dev, "adjust device control 0x%04x ",
+ val);
+ val &= ~BGE_PCIE_DEVCTL_MAX_READRQ_MASK;
+ val |= BGE_PCIE_DEVCTL_MAX_READRQ_4096;
+ pci_write_config(dev, expr_ptr + BGE_PCIE_DEVCTL, val, 2);
+ if (bootverbose)
+ printf("-> 0x%04x\n", val);
+ }
+}
+
#ifdef notdef
static uint32_t
bge_readreg_ind(struct bge_softc *sc, int off)
@@ -1266,8 +1295,7 @@ bge_stop_fw(sc)
}
/*
- * Do endian, PCI and DMA initialization. Also check the on-board ROM
- * self-test results.
+ * Do endian, PCI and DMA initialization.
*/
static int
bge_chipinit(struct bge_softc *sc)
@@ -1278,18 +1306,6 @@ bge_chipinit(struct bge_softc *sc)
/* Set endianness before we access any non-PCI registers. */
pci_write_config(sc->bge_dev, BGE_PCI_MISC_CTL, BGE_INIT, 4);
- /*
- * Check the 'ROM failed' bit on the RX CPU to see if
- * self-tests passed. Skip this check when there's no
- * chip containing the Ethernet address fitted, since
- * in that case it will always fail.
- */
- if ((sc->bge_flags & BGE_FLAG_EADDR) &&
- CSR_READ_4(sc, BGE_RXCPU_MODE) & BGE_RXCPUMODE_ROMFAIL) {
- device_printf(sc->bge_dev, "RX CPU self-diagnostics failed!\n");
- return (ENODEV);
- }
-
/* Clear the MAC control register */
CSR_WRITE_4(sc, BGE_MAC_MODE, 0);
@@ -1387,9 +1403,11 @@ bge_chipinit(struct bge_softc *sc)
/*
* Disable memory write invalidate. Apparently it is not supported
- * properly by these devices.
+ * properly by these devices. Also ensure that INTx isn't disabled,
+ * as these chips need it even when using MSI.
*/
- PCI_CLRBIT(sc->bge_dev, BGE_PCI_CMD, PCIM_CMD_MWIEN, 4);
+ PCI_CLRBIT(sc->bge_dev, BGE_PCI_CMD,
+ PCIM_CMD_INTxDIS | PCIM_CMD_MWIEN, 4);
/* Set the timer prescaler (always 66Mhz) */
CSR_WRITE_4(sc, BGE_MISC_CFG, BGE_32BITTIME_66MHZ);
@@ -1742,14 +1760,18 @@ bge_blockinit(struct bge_softc *sc)
/* Enable host coalescing bug fix. */
if (sc->bge_asicrev == BGE_ASICREV_BCM5755 ||
sc->bge_asicrev == BGE_ASICREV_BCM5787)
- val |= 1 << 29;
+ val |= 1 << 29;
/* Turn on write DMA state machine */
CSR_WRITE_4(sc, BGE_WDMA_MODE, val);
+ DELAY(40);
/* Turn on read DMA state machine */
- CSR_WRITE_4(sc, BGE_RDMA_MODE,
- BGE_RDMAMODE_ENABLE | BGE_RDMAMODE_ALL_ATTNS);
+ val = BGE_RDMAMODE_ENABLE | BGE_RDMAMODE_ALL_ATTNS;
+ if (sc->bge_flags & BGE_FLAG_PCIE)
+ val |= BGE_RDMAMODE_FIFO_LONG_BURST;
+ CSR_WRITE_4(sc, BGE_RDMA_MODE, val);
+ DELAY(40);
/* Turn on RX data completion state machine */
CSR_WRITE_4(sc, BGE_RDC_MODE, BGE_RDCMODE_ENABLE);
@@ -2387,7 +2409,7 @@ bge_attach(device_t dev)
goto fail;
}
- /* Save ASIC rev. */
+ /* Save various chip information. */
sc->bge_chipid =
pci_read_config(dev, BGE_PCI_MISC_CTL, 4) &
BGE_PCIMISCCTL_ASICREV;
@@ -2470,14 +2492,17 @@ bge_attach(device_t dev)
* Found a PCI Express capabilities register, this
* must be a PCI Express device.
*/
- if (reg != 0)
+ if (reg != 0) {
sc->bge_flags |= BGE_FLAG_PCIE;
#else
if (BGE_IS_5705_PLUS(sc)) {
reg = pci_read_config(dev, BGE_PCIE_CAPID_REG, 4);
- if ((reg & 0xFF) == BGE_PCIE_CAPID)
+ if ((reg & 0xFF) == BGE_PCIE_CAPID) {
sc->bge_flags |= BGE_FLAG_PCIE;
+ reg = BGE_PCIE_CAPID;
#endif
+ bge_set_max_readrq(sc, reg);
+ }
} else {
/*
* Check if the device is in PCI-X Mode.
@@ -2522,6 +2547,13 @@ bge_attach(device_t dev)
goto fail;
}
+ if (bootverbose)
+ device_printf(dev,
+ "CHIP ID 0x%08x; ASIC REV 0x%02x; CHIP REV 0x%02x; %s\n",
+ sc->bge_chipid, sc->bge_asicrev, sc->bge_chiprev,
+ (sc->bge_flags & BGE_FLAG_PCIX) ? "PCI-X" :
+ ((sc->bge_flags & BGE_FLAG_PCIE) ? "PCI-E" : "PCI"));
+
BGE_LOCK_INIT(sc, device_get_nameunit(dev));
/* Try to reset the chip. */
@@ -3882,6 +3914,7 @@ bge_ifmedia_upd_locked(struct ifnet *ifp)
{
struct bge_softc *sc = ifp->if_softc;
struct mii_data *mii;
+ struct mii_softc *miisc;
struct ifmedia *ifm;
BGE_LOCK_ASSERT(sc);
@@ -3932,12 +3965,9 @@ bge_ifmedia_upd_locked(struct ifnet *ifp)
sc->bge_link_evt++;
mii = device_get_softc(sc->bge_miibus);
- if (mii->mii_instance) {
- struct mii_softc *miisc;
- for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
- miisc = LIST_NEXT(miisc, mii_list))
+ if (mii->mii_instance)
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
mii_phy_reset(miisc);
- }
mii_mediachg(mii);
/*
diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h
index b10da2e..66e36b5 100644
--- a/sys/dev/bge/if_bgereg.h
+++ b/sys/dev/bge/if_bgereg.h
@@ -176,6 +176,22 @@
#define BGE_PCI_MSI_ADDR_LO 0x60
#define BGE_PCI_MSI_DATA 0x64
+/*
+ * PCI Express definitions
+ * According to
+ * PCI Express base specification, REV. 1.0a
+ */
+
+/* PCI Express device control, 16bits */
+#define BGE_PCIE_DEVCTL 0x08
+#define BGE_PCIE_DEVCTL_MAX_READRQ_MASK 0x7000
+#define BGE_PCIE_DEVCTL_MAX_READRQ_128 0x0000
+#define BGE_PCIE_DEVCTL_MAX_READRQ_256 0x1000
+#define BGE_PCIE_DEVCTL_MAX_READRQ_512 0x2000
+#define BGE_PCIE_DEVCTL_MAX_READRQ_1024 0x3000
+#define BGE_PCIE_DEVCTL_MAX_READRQ_2048 0x4000
+#define BGE_PCIE_DEVCTL_MAX_READRQ_4096 0x5000
+
/* PCI MSI. ??? */
#define BGE_PCIE_CAPID_REG 0xD0
#define BGE_PCIE_CAPID 0x10
@@ -388,6 +404,9 @@
#ifndef PCIM_CMD_MWIEN
#define PCIM_CMD_MWIEN 0x0010
#endif
+#ifndef PCIM_CMD_INTxDIS
+#define PCIM_CMD_INTxDIS 0x0400
+#endif
/*
* High priority mailbox registers
@@ -1359,6 +1378,8 @@
#define BGE_RDMAMODE_PCI_FIFOOREAD_ATTN 0x00000100
#define BGE_RDMAMODE_LOCWRITE_TOOBIG 0x00000200
#define BGE_RDMAMODE_ALL_ATTNS 0x000003FC
+#define BGE_RDMAMODE_FIFO_SIZE_128 0x00020000
+#define BGE_RDMAMODE_FIFO_LONG_BURST 0x00030000
/* Read DMA status register */
#define BGE_RDMASTAT_PCI_TGT_ABRT_ATTN 0x00000004
diff --git a/sys/dev/cardbus/cardbus_cis.c b/sys/dev/cardbus/cardbus_cis.c
index 2f68003..7e58949 100644
--- a/sys/dev/cardbus/cardbus_cis.c
+++ b/sys/dev/cardbus/cardbus_cis.c
@@ -451,8 +451,7 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
space = *start & PCIM_CIS_ASI_MASK;
switch (space) {
case PCIM_CIS_ASI_CONFIG:
- if (cardbus_cis_debug)
- device_printf(cbdev, "CIS in PCI config space\n");
+ DEVPRINTF((cbdev, "CIS in PCI config space\n"));
/* CIS in PCI config space need no initialization */
return (CIS_CONFIG_SPACE);
case PCIM_CIS_ASI_BAR0:
@@ -462,13 +461,11 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
case PCIM_CIS_ASI_BAR4:
case PCIM_CIS_ASI_BAR5:
*rid = PCIR_BAR(space - PCIM_CIS_ASI_BAR0);
- if (cardbus_cis_debug)
- device_printf(cbdev, "CIS in BAR %#x\n", *rid);
+ DEVPRINTF((cbdev, "CIS in BAR %#x\n", *rid));
break;
case PCIM_CIS_ASI_ROM:
*rid = PCIR_BIOS;
- if (cardbus_cis_debug)
- device_printf(cbdev, "CIS in option rom\n");
+ DEVPRINTF((cbdev, "CIS in option rom\n"));
break;
default:
device_printf(cbdev, "Unable to read CIS: Unknown space: %d\n",
@@ -484,6 +481,7 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
"to read CIS.\n");
return (NULL);
}
+ DEVPRINTF((cbdev, "CIS Mapped to %#lx\n", rman_get_start(res)));
if (*rid == PCIR_BIOS)
pci_write_config(child, *rid,
rman_get_start(res) | PCIM_BIOS_ENABLE, 4);
@@ -558,8 +556,7 @@ cardbus_read_tuple_init(device_t cbdev, device_t child, uint32_t *start,
} else {
*start = *start & PCIM_CIS_ADDR_MASK;
}
- if (cardbus_cis_debug)
- device_printf(cbdev, "CIS offset is %#x\n", *start);
+ DEVPRINTF((cbdev, "CIS offset is %#x\n", *start));
return (res);
}
@@ -598,13 +595,10 @@ cardbus_parse_cis(device_t cbdev, device_t child,
bzero(tupledata, MAXTUPLESIZE);
expect_linktarget = TRUE;
if ((start = pci_read_config(child, PCIR_CIS, 4)) == 0) {
- if (cardbus_cis_debug)
- device_printf(cbdev,
- "Warning: CIS pointer 0 (no CIS present)\n");
+ DEVPRINTF((cbdev, "Warning: CIS pointer is 0: (no CIS)\n"));
return (ENXIO);
}
- if (cardbus_cis_debug)
- device_printf(cbdev, "CIS pointer is %#x\n", start);
+ DEVPRINTF((cbdev, "CIS pointer is %#x\n", start));
off = 0;
res = cardbus_read_tuple_init(cbdev, child, &start, &rid);
if (res == NULL) {
diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c
index 593a8d6..cc09aa0 100644
--- a/sys/dev/cxgb/cxgb_main.c
+++ b/sys/dev/cxgb/cxgb_main.c
@@ -365,8 +365,8 @@ cxgb_controller_probe(device_t dev)
}
#define FW_FNAME "cxgb_t3fw"
-#define TPEEPROM_NAME "t3%c_tp_eeprom"
-#define TPSRAM_NAME "t3%c_protocol_sram"
+#define TPEEPROM_NAME "cxgb_t3%c_tp_eeprom"
+#define TPSRAM_NAME "cxgb_t3%c_protocol_sram"
static int
upgrade_fw(adapter_t *sc)
@@ -1292,10 +1292,8 @@ void t3_os_link_fault_handler(struct adapter *sc, int port_id)
{
struct port_info *pi = &sc->port[port_id];
- ADAPTER_LOCK(sc);
pi->link_fault = 1;
taskqueue_enqueue(sc->tq, &pi->link_fault_task);
- ADAPTER_UNLOCK(sc);
}
void
@@ -1595,8 +1593,9 @@ update_tpeeprom(struct adapter *adap)
tpeeprom = firmware_get(name);
if (tpeeprom == NULL) {
- device_printf(adap->dev, "could not load TP EEPROM: unable to load %s\n",
- TPEEPROM_NAME);
+ device_printf(adap->dev,
+ "could not load TP EEPROM: unable to load %s\n",
+ name);
return;
}
@@ -1607,7 +1606,9 @@ update_tpeeprom(struct adapter *adap)
goto release_tpeeprom;
if (len != TP_SRAM_LEN) {
- device_printf(adap->dev, "%s length is wrong len=%d expected=%d\n", TPEEPROM_NAME, len, TP_SRAM_LEN);
+ device_printf(adap->dev,
+ "%s length is wrong len=%d expected=%d\n", name,
+ len, TP_SRAM_LEN);
return;
}
@@ -1619,7 +1620,8 @@ update_tpeeprom(struct adapter *adap)
"Protocol SRAM image updated in EEPROM to %d.%d.%d\n",
TP_VERSION_MAJOR, TP_VERSION_MINOR, TP_VERSION_MICRO);
} else
- device_printf(adap->dev, "Protocol SRAM image update in EEPROM failed\n");
+ device_printf(adap->dev,
+ "Protocol SRAM image update in EEPROM failed\n");
release_tpeeprom:
firmware_put(tpeeprom, FIRMWARE_UNLOAD);
@@ -1912,6 +1914,7 @@ cxgb_init_locked(struct port_info *p)
device_printf(sc->dev, "enabling interrupts on port=%d\n", p->port_id);
t3_port_intr_enable(sc, p->port_id);
+ callout_reset(&sc->cxgb_tick_ch, CXGB_TICKS(sc), cxgb_tick, sc);
t3_sge_reset_adapter(sc);
ifp->if_drv_flags |= IFF_DRV_RUNNING;
@@ -2570,7 +2573,7 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
mmd = mid->phy_id >> 8;
if (!mmd)
mmd = MDIO_DEV_PCS;
- else if (mmd > MDIO_DEV_XGXS)
+ else if (mmd > MDIO_DEV_VEND2)
return (EINVAL);
error = phy->mdio_read(sc, mid->phy_id & 0x1f, mmd,
@@ -2592,7 +2595,7 @@ cxgb_extension_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data,
mmd = mid->phy_id >> 8;
if (!mmd)
mmd = MDIO_DEV_PCS;
- else if (mmd > MDIO_DEV_XGXS)
+ else if (mmd > MDIO_DEV_VEND2)
return (EINVAL);
error = phy->mdio_write(sc, mid->phy_id & 0x1f,
diff --git a/sys/dev/cxgb/cxgb_offload.c b/sys/dev/cxgb/cxgb_offload.c
index b1b9d55..2ae83bd 100644
--- a/sys/dev/cxgb/cxgb_offload.c
+++ b/sys/dev/cxgb/cxgb_offload.c
@@ -94,6 +94,9 @@ register_tdev(struct t3cdev *tdev)
static inline void
unregister_tdev(struct t3cdev *tdev)
{
+ if (!inited)
+ return;
+
mtx_lock(&cxgb_db_lock);
TAILQ_REMOVE(&ofld_dev_list, tdev, entry);
mtx_unlock(&cxgb_db_lock);
diff --git a/sys/dev/cxgb/cxgb_sge.c b/sys/dev/cxgb/cxgb_sge.c
index 6c5a17e..47f36fd 100644
--- a/sys/dev/cxgb/cxgb_sge.c
+++ b/sys/dev/cxgb/cxgb_sge.c
@@ -2879,6 +2879,7 @@ process_responses(adapter_t *adap, struct sge_qset *qs, int budget)
eop = get_packet(adap, drop_thresh, qs, &rspq->rspq_mbuf, r);
#endif
#ifdef IFNET_MULTIQUEUE
+ rspq->rspq_mh.mh_head->m_flags |= M_FLOWID;
rspq->rspq_mh.mh_head->m_pkthdr.flowid = rss_hash;
#endif
ethpad = 2;
diff --git a/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c b/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
index f11aaf0..6582b97 100644
--- a/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
+++ b/sys/dev/cxgb/ulp/tom/cxgb_cpl_io.c
@@ -3829,7 +3829,7 @@ socket_act_establish(struct socket *so, struct mbuf *m)
#endif
toep->tp_state = tp->t_state;
- V_tcpstat.tcps_connects++;
+ TCPSTAT_INC(tcps_connects);
}
diff --git a/sys/dev/dc/dcphy.c b/sys/dev/dc/dcphy.c
index 2033577..a4df704 100644
--- a/sys/dev/dc/dcphy.c
+++ b/sys/dev/dc/dcphy.c
@@ -154,13 +154,12 @@ dcphy_attach(device_t dev)
sc->mii_service = dcphy_service;
sc->mii_pdata = mii;
- sc->mii_flags |= MIIF_NOISOLATE;
- mii->mii_instance++;
-
-#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
+ /*
+ * Apparently, we can neither isolate nor do loopback.
+ */
+ sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
- BMCR_ISO);
+ mii->mii_instance++;
/*dcphy_reset(sc);*/
dc_sc = mii->mii_ifp->if_softc;
@@ -186,9 +185,8 @@ dcphy_attach(device_t dev)
sc->mii_capabilities &= ma->mii_capmask;
device_printf(dev, " ");
- mii_add_media(sc);
+ mii_phy_add_media(sc);
printf("\n");
-#undef ADD
MIIBUS_MEDIAINIT(sc->mii_dev);
return (0);
diff --git a/sys/dev/dc/pnphy.c b/sys/dev/dc/pnphy.c
index e78ccf3..d1282a7 100644
--- a/sys/dev/dc/pnphy.c
+++ b/sys/dev/dc/pnphy.c
@@ -137,24 +137,19 @@ pnphy_attach(device_t dev)
sc->mii_service = pnphy_service;
sc->mii_pdata = mii;
- sc->mii_flags |= MIIF_NOISOLATE;
- mii->mii_instance++;
+ /*
+ * Apparently, we can neither isolate nor do loopback.
+ */
+ sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
-#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
+ mii->mii_instance++;
sc->mii_capabilities =
BMSR_100TXFDX | BMSR_100TXHDX | BMSR_10TFDX | BMSR_10THDX;
sc->mii_capabilities &= ma->mii_capmask;
device_printf(dev, " ");
- mii_add_media(sc);
+ mii_phy_add_media(sc);
printf("\n");
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_NONE, 0, sc->mii_inst),
- BMCR_ISO);
-
- ADD(IFM_MAKEWORD(IFM_ETHER, IFM_100_TX, IFM_LOOP, sc->mii_inst),
- BMCR_LOOP|BMCR_S100);
-
-#undef ADD
MIIBUS_MEDIAINIT(sc->mii_dev);
return (0);
diff --git a/sys/dev/dcons/dcons_os.c b/sys/dev/dcons/dcons_os.c
index f4d4181..49967eb 100644
--- a/sys/dev/dcons/dcons_os.c
+++ b/sys/dev/dcons/dcons_os.c
@@ -72,7 +72,7 @@
#ifndef DCONS_POLL_HZ
-#define DCONS_POLL_HZ 100
+#define DCONS_POLL_HZ 25
#endif
#ifndef DCONS_BUF_SIZE
@@ -360,6 +360,7 @@ dcons_attach_port(int port, char *name, int flags)
tp = tty_alloc(&dcons_ttydevsw, dc, NULL);
dc->flags = flags;
dc->tty = tp;
+ tty_init_console(tp, 0);
tty_makedev(tp, NULL, "%s", name);
return(0);
}
@@ -402,8 +403,9 @@ dcons_modevent(module_t mode, int type, void *data)
switch (type) {
case MOD_LOAD:
ret = dcons_drv_init(1);
- if (ret == 0) {
+ if (ret != -1)
dcons_attach();
+ if (ret == 0) {
dcons_cnprobe(&dcons_consdev);
dcons_cninit(&dcons_consdev);
cnadd(&dcons_consdev);
diff --git a/sys/dev/drm/ati_pcigart.c b/sys/dev/drm/ati_pcigart.c
index 3073cb1..e3fecd1 100644
--- a/sys/dev/drm/ati_pcigart.c
+++ b/sys/dev/drm/ati_pcigart.c
@@ -75,14 +75,14 @@ drm_ati_alloc_pcigart_table(struct drm_device *dev,
NULL, NULL, /* filtfunc, filtfuncargs */
gart_info->table_size, 1, /* maxsize, nsegs */
gart_info->table_size, /* maxsegsize */
- BUS_DMA_ALLOCNOW, NULL, NULL, /* flags, lockfunc, lockfuncargs */
+ 0, NULL, NULL, /* flags, lockfunc, lockfuncargs */
&dmah->tag);
if (ret != 0) {
free(dmah, DRM_MEM_DMA);
return ENOMEM;
}
- flags = BUS_DMA_NOWAIT | BUS_DMA_ZERO;
+ flags = BUS_DMA_WAITOK | BUS_DMA_ZERO;
if (gart_info->gart_reg_if == DRM_ATI_GART_IGP)
flags |= BUS_DMA_NOCACHE;
@@ -95,7 +95,8 @@ drm_ati_alloc_pcigart_table(struct drm_device *dev,
DRM_LOCK();
ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr,
- gart_info->table_size, drm_ati_alloc_pcigart_table_cb, dmah, 0);
+ gart_info->table_size, drm_ati_alloc_pcigart_table_cb, dmah,
+ BUS_DMA_NOWAIT);
if (ret != 0) {
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
bus_dma_tag_destroy(dmah->tag);
@@ -103,7 +104,7 @@ drm_ati_alloc_pcigart_table(struct drm_device *dev,
return ENOMEM;
}
- dev->sg->dmah = dmah;
+ gart_info->dmah = dmah;
return 0;
}
@@ -112,12 +113,12 @@ static void
drm_ati_free_pcigart_table(struct drm_device *dev,
struct drm_ati_pcigart_info *gart_info)
{
- struct drm_dma_handle *dmah = dev->sg->dmah;
+ struct drm_dma_handle *dmah = gart_info->dmah;
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
bus_dma_tag_destroy(dmah->tag);
free(dmah, DRM_MEM_DMA);
- dev->sg->dmah = NULL;
+ gart_info->dmah = NULL;
}
int
@@ -133,7 +134,7 @@ drm_ati_pcigart_cleanup(struct drm_device *dev,
if (gart_info->bus_addr) {
if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) {
gart_info->bus_addr = 0;
- if (dev->sg->dmah)
+ if (gart_info->dmah)
drm_ati_free_pcigart_table(dev, gart_info);
}
}
@@ -168,8 +169,8 @@ drm_ati_pcigart_init(struct drm_device *dev,
goto done;
}
- address = (void *)dev->sg->dmah->vaddr;
- bus_address = dev->sg->dmah->busaddr;
+ address = (void *)gart_info->dmah->vaddr;
+ bus_address = gart_info->dmah->busaddr;
} else {
address = gart_info->addr;
bus_address = gart_info->bus_addr;
diff --git a/sys/dev/drm/drmP.h b/sys/dev/drm/drmP.h
index 0b6ba60..602d906 100644
--- a/sys/dev/drm/drmP.h
+++ b/sys/dev/drm/drmP.h
@@ -240,17 +240,23 @@ typedef u_int8_t u8;
#endif
#define DRM_READ8(map, offset) \
- *(volatile u_int8_t *) (((unsigned long)(map)->handle) + (offset))
+ *(volatile u_int8_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset))
#define DRM_READ16(map, offset) \
- *(volatile u_int16_t *) (((unsigned long)(map)->handle) + (offset))
+ *(volatile u_int16_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset))
#define DRM_READ32(map, offset) \
- *(volatile u_int32_t *)(((unsigned long)(map)->handle) + (offset))
+ *(volatile u_int32_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset))
#define DRM_WRITE8(map, offset, val) \
- *(volatile u_int8_t *) (((unsigned long)(map)->handle) + (offset)) = val
+ *(volatile u_int8_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset)) = val
#define DRM_WRITE16(map, offset, val) \
- *(volatile u_int16_t *) (((unsigned long)(map)->handle) + (offset)) = val
+ *(volatile u_int16_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset)) = val
#define DRM_WRITE32(map, offset, val) \
- *(volatile u_int32_t *)(((unsigned long)(map)->handle) + (offset)) = val
+ *(volatile u_int32_t *)(((vm_offset_t)(map)->handle) + \
+ (vm_offset_t)(offset)) = val
#define DRM_VERIFYAREA_READ( uaddr, size ) \
(!useracc(__DECONST(caddr_t, uaddr), size, VM_PROT_READ))
@@ -474,9 +480,7 @@ typedef struct drm_sg_mem {
void *virtual;
int pages;
dma_addr_t *busaddr;
- struct drm_dma_handle *sg_dmah; /* Handle for sg_pages */
struct drm_dma_handle *dmah; /* Handle to PCI memory */
- /* for ATI PCIGART table */
} drm_sg_mem_t;
typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t;
@@ -537,6 +541,7 @@ struct drm_ati_pcigart_info {
struct drm_dma_handle *table_handle;
drm_local_map_t mapping;
int table_size;
+ struct drm_dma_handle *dmah; /* handle for ATI PCIGART table */
};
#ifndef DMA_BIT_MASK
@@ -607,7 +612,7 @@ struct drm_driver_info {
};
/* Length for the array of resource pointers for drm_get_resource_*. */
-#define DRM_MAX_PCI_RESOURCE 3
+#define DRM_MAX_PCI_RESOURCE 6
/**
* DRM device functions structure
diff --git a/sys/dev/drm/drm_bufs.c b/sys/dev/drm/drm_bufs.c
index c7d0288..6016c98 100644
--- a/sys/dev/drm/drm_bufs.c
+++ b/sys/dev/drm/drm_bufs.c
@@ -216,7 +216,7 @@ int drm_addmap(struct drm_device * dev, unsigned long offset,
DRM_LOCK();
return EINVAL;
}
- map->offset = map->offset + dev->sg->handle;
+ map->offset += dev->sg->handle;
break;
case _DRM_CONSISTENT:
/* Unfortunately, we don't get any alignment specification from
@@ -1106,7 +1106,7 @@ int drm_order(unsigned long size)
if (size == 0)
return 0;
- order = ffsl(size) - 1;
+ order = flsl(size) - 1;
if (size & ~(1ul << order))
++order;
diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c
index 79e81d2..1612120 100644
--- a/sys/dev/drm/drm_drv.c
+++ b/sys/dev/drm/drm_drv.c
@@ -182,7 +182,10 @@ int drm_probe(device_t kdev, drm_pci_id_list_t *idlist)
id_entry = drm_find_description(vendor, device, idlist);
if (id_entry != NULL) {
- device_set_desc(kdev, id_entry->name);
+ if (!device_get_desc(kdev)) {
+ DRM_DEBUG("desc : %s\n", device_get_desc(kdev));
+ device_set_desc(kdev, id_entry->name);
+ }
return 0;
}
@@ -290,7 +293,8 @@ drm_pci_id_list_t *drm_find_description(int vendor, int device,
for (i = 0; idlist[i].vendor != 0; i++) {
if ((idlist[i].vendor == vendor) &&
- (idlist[i].device == device)) {
+ ((idlist[i].device == device) ||
+ (idlist[i].device == 0))) {
return &idlist[i];
}
}
@@ -666,7 +670,7 @@ void drm_close(void *data)
}
/* Contention */
retcode = mtx_sleep((void *)&dev->lock.lock_queue,
- &dev->dev_lock, PZERO | PCATCH, "drmlk2", 0);
+ &dev->dev_lock, PCATCH, "drmlk2", 0);
if (retcode)
break;
}
diff --git a/sys/dev/drm/drm_irq.c b/sys/dev/drm/drm_irq.c
index 00e1c9d..a13192c 100644
--- a/sys/dev/drm/drm_irq.c
+++ b/sys/dev/drm/drm_irq.c
@@ -80,13 +80,14 @@ static void vblank_disable_fn(void *arg)
}
callout_deactivate(&dev->vblank_disable_timer);
- DRM_DEBUG("vblank_disable_allowed=%d\n", dev->vblank_disable_allowed);
+ DRM_DEBUG("vblank_disable: %s\n", dev->vblank_disable_allowed ?
+ "allowed" : "denied");
if (!dev->vblank_disable_allowed)
return;
for (i = 0; i < dev->num_crtcs; i++) {
if (atomic_read(&dev->vblank[i].refcount) == 0 &&
- dev->vblank[i].enabled) {
+ dev->vblank[i].enabled && !dev->vblank[i].inmodeset) {
DRM_DEBUG("disabling vblank on crtc %d\n", i);
dev->vblank[i].last =
dev->driver->get_vblank_counter(dev, i);
@@ -98,15 +99,13 @@ static void vblank_disable_fn(void *arg)
void drm_vblank_cleanup(struct drm_device *dev)
{
- unsigned long irqflags;
-
/* Bail if the driver didn't call drm_vblank_init() */
if (dev->num_crtcs == 0)
return;
- DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
+ DRM_SPINLOCK(&dev->vbl_lock);
callout_stop(&dev->vblank_disable_timer);
- DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
+ DRM_SPINUNLOCK(&dev->vbl_lock);
callout_drain(&dev->vblank_disable_timer);
@@ -151,7 +150,7 @@ err:
int drm_irq_install(struct drm_device *dev)
{
- int retcode;
+ int crtc, retcode;
if (dev->irq == 0 || dev->dev_private == NULL)
return EINVAL;
@@ -188,6 +187,17 @@ int drm_irq_install(struct drm_device *dev)
DRM_LOCK();
dev->driver->irq_postinstall(dev);
DRM_UNLOCK();
+ if (dev->driver->enable_vblank) {
+ DRM_SPINLOCK(&dev->vbl_lock);
+ for( crtc = 0 ; crtc < dev->num_crtcs ; crtc++) {
+ if (dev->driver->enable_vblank(dev, crtc) == 0) {
+ dev->vblank[crtc].enabled = 1;
+ }
+ }
+ callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ,
+ (timeout_t *)vblank_disable_fn, (void *)dev);
+ DRM_SPINUNLOCK(&dev->vbl_lock);
+ }
return 0;
err:
@@ -200,11 +210,27 @@ err:
int drm_irq_uninstall(struct drm_device *dev)
{
+ int crtc;
+
if (!dev->irq_enabled)
return EINVAL;
dev->irq_enabled = 0;
+ /*
+ * Wake up any waiters so they don't hang.
+ */
+ DRM_SPINLOCK(&dev->vbl_lock);
+ for (crtc = 0; crtc < dev->num_crtcs; crtc++) {
+ if (dev->vblank[crtc].enabled) {
+ DRM_WAKEUP(&dev->vblank[crtc].queue);
+ dev->vblank[crtc].last =
+ dev->driver->get_vblank_counter(dev, crtc);
+ dev->vblank[crtc].enabled = 0;
+ }
+ }
+ DRM_SPINUNLOCK(&dev->vbl_lock);
+
DRM_DEBUG("irq=%d\n", dev->irq);
dev->driver->irq_uninstall(dev);
@@ -277,16 +303,15 @@ static void drm_update_vblank_count(struct drm_device *dev, int crtc)
int drm_vblank_get(struct drm_device *dev, int crtc)
{
- unsigned long irqflags;
int ret = 0;
- DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
+ DRM_SPINLOCK(&dev->vbl_lock);
/* Going from 0->1 means we have to enable interrupts again */
atomic_add_acq_int(&dev->vblank[crtc].refcount, 1);
- DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount);
if (dev->vblank[crtc].refcount == 1 &&
!dev->vblank[crtc].enabled) {
ret = dev->driver->enable_vblank(dev, crtc);
+ DRM_DEBUG("enabling vblank on crtc %d, ret: %d\n", crtc, ret);
if (ret)
atomic_dec(&dev->vblank[crtc].refcount);
else {
@@ -294,30 +319,30 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
drm_update_vblank_count(dev, crtc);
}
}
- DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
+ DRM_SPINUNLOCK(&dev->vbl_lock);
return ret;
}
void drm_vblank_put(struct drm_device *dev, int crtc)
{
- unsigned long irqflags;
+ KASSERT(atomic_read(&dev->vblank[crtc].refcount) > 0,
+ ("invalid refcount"));
- DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
/* Last user schedules interrupt disable */
atomic_subtract_acq_int(&dev->vblank[crtc].refcount, 1);
- DRM_DEBUG("vblank refcount = %d\n", dev->vblank[crtc].refcount);
+
+ DRM_SPINLOCK(&dev->vbl_lock);
if (dev->vblank[crtc].refcount == 0)
callout_reset(&dev->vblank_disable_timer, 5 * DRM_HZ,
(timeout_t *)vblank_disable_fn, (void *)dev);
- DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
+ DRM_SPINUNLOCK(&dev->vbl_lock);
}
int drm_modeset_ctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_modeset_ctl *modeset = data;
- unsigned long irqflags;
int crtc, ret = 0;
DRM_DEBUG("num_crtcs=%d\n", dev->num_crtcs);
@@ -343,18 +368,22 @@ int drm_modeset_ctl(struct drm_device *dev, void *data,
case _DRM_PRE_MODESET:
DRM_DEBUG("pre-modeset\n");
if (!dev->vblank[crtc].inmodeset) {
- dev->vblank[crtc].inmodeset = 1;
- drm_vblank_get(dev, crtc);
+ dev->vblank[crtc].inmodeset = 0x1;
+ if (drm_vblank_get(dev, crtc) == 0)
+ dev->vblank[crtc].inmodeset |= 0x2;
}
break;
case _DRM_POST_MODESET:
DRM_DEBUG("post-modeset\n");
if (dev->vblank[crtc].inmodeset) {
- DRM_SPINLOCK_IRQSAVE(&dev->vbl_lock, irqflags);
+ DRM_SPINLOCK(&dev->vbl_lock);
dev->vblank_disable_allowed = 1;
+ DRM_SPINUNLOCK(&dev->vbl_lock);
+
+ if (dev->vblank[crtc].inmodeset & 0x2)
+ drm_vblank_put(dev, crtc);
+
dev->vblank[crtc].inmodeset = 0;
- DRM_SPINUNLOCK_IRQRESTORE(&dev->vbl_lock, irqflags);
- drm_vblank_put(dev, crtc);
}
break;
default:
@@ -434,27 +463,29 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr
} else {
DRM_DEBUG("waiting on vblank count %d, crtc %d\n",
vblwait->request.sequence, crtc);
- for ( ret = 0 ; !ret && !((drm_vblank_count(dev, crtc) -
- vblwait->request.sequence) <= (1 << 23)) ; ) {
+ dev->vblank[crtc].last = vblwait->request.sequence;
+ for ( ret = 0 ; !ret && !(((drm_vblank_count(dev, crtc) -
+ vblwait->request.sequence) <= (1 << 23)) ||
+ !dev->irq_enabled) ; ) {
mtx_lock(&dev->irq_lock);
- if (!((drm_vblank_count(dev, crtc) -
- vblwait->request.sequence) <= (1 << 23)))
+ if (!(((drm_vblank_count(dev, crtc) -
+ vblwait->request.sequence) <= (1 << 23)) ||
+ !dev->irq_enabled))
ret = mtx_sleep(&dev->vblank[crtc].queue,
&dev->irq_lock, PCATCH, "vblwtq",
3 * DRM_HZ);
mtx_unlock(&dev->irq_lock);
}
- DRM_DEBUG("return = %d\n", ret);
- if (ret != EINTR) {
+ if (ret != EINTR && ret != ERESTART) {
struct timeval now;
microtime(&now);
vblwait->reply.tval_sec = now.tv_sec;
vblwait->reply.tval_usec = now.tv_usec;
vblwait->reply.sequence = drm_vblank_count(dev, crtc);
- DRM_DEBUG("returning %d to client\n",
- vblwait->reply.sequence);
+ DRM_DEBUG("returning %d to client, irq_enabled %d\n",
+ vblwait->reply.sequence, dev->irq_enabled);
} else {
DRM_DEBUG("vblank wait interrupted by signal\n");
}
diff --git a/sys/dev/drm/drm_linux_list.h b/sys/dev/drm/drm_linux_list.h
index d2142a4..809d8ed 100644
--- a/sys/dev/drm/drm_linux_list.h
+++ b/sys/dev/drm/drm_linux_list.h
@@ -67,6 +67,10 @@ list_del(struct list_head *entry) {
#define list_for_each(entry, head) \
for (entry = (head)->next; entry != head; entry = (entry)->next)
+#define list_for_each_prev(entry, head) \
+ for (entry = (head)->prev; entry != (head); \
+ entry = entry->prev)
+
#define list_for_each_safe(entry, temp, head) \
for (entry = (head)->next, temp = (entry)->next; \
entry != head; \
diff --git a/sys/dev/drm/drm_lock.c b/sys/dev/drm/drm_lock.c
index bb8a834..28573c8 100644
--- a/sys/dev/drm/drm_lock.c
+++ b/sys/dev/drm/drm_lock.c
@@ -82,12 +82,17 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
/* Contention */
ret = mtx_sleep((void *)&dev->lock.lock_queue, &dev->dev_lock,
- PZERO | PCATCH, "drmlk2", 0);
+ PCATCH, "drmlk2", 0);
if (ret != 0)
break;
}
DRM_UNLOCK();
- DRM_DEBUG("%d %s\n", lock->context, ret ? "interrupted" : "has lock");
+
+ if (ret == ERESTART)
+ DRM_DEBUG("restarting syscall\n");
+ else
+ DRM_DEBUG("%d %s\n", lock->context,
+ ret ? "interrupted" : "has lock");
if (ret != 0)
return ret;
diff --git a/sys/dev/drm/drm_pci.c b/sys/dev/drm/drm_pci.c
index 6d46c5d..afd6604 100644
--- a/sys/dev/drm/drm_pci.c
+++ b/sys/dev/drm/drm_pci.c
@@ -91,7 +91,7 @@ drm_pci_alloc(struct drm_device *dev, size_t size,
}
ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr,
- BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmah->map);
+ BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_NOCACHE, &dmah->map);
if (ret != 0) {
bus_dma_tag_destroy(dmah->tag);
free(dmah, DRM_MEM_DMA);
diff --git a/sys/dev/drm/drm_pciids.h b/sys/dev/drm/drm_pciids.h
index b7e7ecc..fddf70a 100644
--- a/sys/dev/drm/drm_pciids.h
+++ b/sys/dev/drm/drm_pciids.h
@@ -320,6 +320,8 @@
{0x1002, 0x9612, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Radeon HD 3200 Graphics"}, \
{0x1002, 0x9613, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Radeon 3100 Graphics"}, \
{0x1002, 0x9614, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Radeon 3300 Graphics"}, \
+ {0x1002, 0x9615, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Radeon 3200 Graphics"}, \
+ {0x1002, 0x9616, CHIP_RS780|RADEON_NEW_MEMMAP|RADEON_IS_IGP, "ATI Radeon 3000 Graphics"}, \
{0x1002, 0x9440, CHIP_RV770|RADEON_NEW_MEMMAP, "ATI Radeon 4800 Series"}, \
{0x1002, 0x9441, CHIP_RV770|RADEON_NEW_MEMMAP, "ATI Radeon 4870 X2"}, \
{0x1002, 0x9442, CHIP_RV770|RADEON_NEW_MEMMAP, "ATI Radeon 4800 Series"}, \
@@ -334,6 +336,8 @@
{0x1002, 0x944B, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI Mobility Radeon HD 4850 X2"}, \
{0x1002, 0x945A, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI Mobility Radeon HD 4870"}, \
{0x1002, 0x945B, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI Mobility Radeon M98"}, \
+ {0x1002, 0x9460, CHIP_RV770|RADEON_NEW_MEMMAP, "ATI Radeon 4800 Series"}, \
+ {0x1002, 0x9462, CHIP_RV770|RADEON_NEW_MEMMAP, "ATI Radeon 4800 Series"}, \
{0x1002, 0x946A, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI FirePro M7750"}, \
{0x1002, 0x946B, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI M98"}, \
{0x1002, 0x947A, CHIP_RV770|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP, "ATI M98"}, \
diff --git a/sys/dev/drm/drm_scatter.c b/sys/dev/drm/drm_scatter.c
index c884df1..5f8b29b 100644
--- a/sys/dev/drm/drm_scatter.c
+++ b/sys/dev/drm/drm_scatter.c
@@ -92,7 +92,7 @@ drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather *request)
}
ret = bus_dmamem_alloc(dmah->tag, &dmah->vaddr,
- BUS_DMA_WAITOK | BUS_DMA_ZERO, &dmah->map);
+ BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_NOCACHE, &dmah->map);
if (ret != 0) {
bus_dma_tag_destroy(dmah->tag);
free(dmah, DRM_MEM_DMA);
@@ -102,8 +102,7 @@ drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather *request)
}
ret = bus_dmamap_load(dmah->tag, dmah->map, dmah->vaddr,
- request->size, drm_sg_alloc_cb, entry,
- BUS_DMA_NOWAIT | BUS_DMA_NOCACHE);
+ request->size, drm_sg_alloc_cb, entry, BUS_DMA_NOWAIT);
if (ret != 0) {
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
bus_dma_tag_destroy(dmah->tag);
@@ -113,7 +112,7 @@ drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather *request)
return ENOMEM;
}
- entry->sg_dmah = dmah;
+ entry->dmah = dmah;
entry->handle = (unsigned long)dmah->vaddr;
DRM_DEBUG("sg alloc handle = %08lx\n", entry->handle);
@@ -161,7 +160,7 @@ drm_sg_alloc_ioctl(struct drm_device *dev, void *data,
void
drm_sg_cleanup(struct drm_sg_mem *entry)
{
- struct drm_dma_handle *dmah = entry->sg_dmah;
+ struct drm_dma_handle *dmah = entry->dmah;
bus_dmamap_unload(dmah->tag, dmah->map);
bus_dmamem_free(dmah->tag, dmah->vaddr, dmah->map);
diff --git a/sys/dev/drm/drm_vm.c b/sys/dev/drm/drm_vm.c
index e00684b..7d5cd8d 100644
--- a/sys/dev/drm/drm_vm.c
+++ b/sys/dev/drm/drm_vm.c
@@ -54,7 +54,7 @@ int drm_mmap(struct cdev *kdev, vm_offset_t offset, vm_paddr_t *paddr,
if (file_priv && !file_priv->authenticated)
return EACCES;
- if (dev->dma && offset >= 0 && offset < ptoa(dev->dma->page_count)) {
+ if (dev->dma && offset < ptoa(dev->dma->page_count)) {
drm_device_dma_t *dma = dev->dma;
DRM_SPINLOCK(&dev->dma_lock);
@@ -86,8 +86,14 @@ int drm_mmap(struct cdev *kdev, vm_offset_t offset, vm_paddr_t *paddr,
}
if (map == NULL) {
+ DRM_DEBUG("Can't find map, requested offset = %016lx\n",
+ (unsigned long)offset);
+ TAILQ_FOREACH(map, &dev->maplist, link) {
+ DRM_DEBUG("map offset = %016lx, handle = %016lx\n",
+ (unsigned long)map->offset,
+ (unsigned long)map->handle);
+ }
DRM_UNLOCK();
- DRM_DEBUG("can't find map\n");
return -1;
}
if (((map->flags&_DRM_RESTRICTED) && !DRM_SUSER(DRM_CURPROC))) {
diff --git a/sys/dev/drm/i915_dma.c b/sys/dev/drm/i915_dma.c
index 1996831..a701a5e 100644
--- a/sys/dev/drm/i915_dma.c
+++ b/sys/dev/drm/i915_dma.c
@@ -193,7 +193,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
dev_priv->ring.map.flags = 0;
dev_priv->ring.map.mtrr = 0;
- drm_core_ioremap(&dev_priv->ring.map, dev);
+ drm_core_ioremap_wc(&dev_priv->ring.map, dev);
if (dev_priv->ring.map.handle == NULL) {
i915_dma_cleanup(dev);
@@ -209,7 +209,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
dev_priv->back_offset = init->back_offset;
dev_priv->front_offset = init->front_offset;
dev_priv->current_page = 0;
- dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
+ dev_priv->sarea_priv->pf_current_page = 0;
/* Allow hardware batchbuffers unless told otherwise.
*/
@@ -439,8 +439,7 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
drm_i915_private_t *dev_priv = dev->dev_private;
RING_LOCALS;
- dev_priv->counter++;
- if (dev_priv->counter > 0x7FFFFFFFUL)
+ if (++dev_priv->counter > 0x7FFFFFFFUL)
dev_priv->counter = 0;
if (dev_priv->sarea_priv)
dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
@@ -574,7 +573,10 @@ static int i915_dispatch_flip(struct drm_device * dev)
OUT_RING(0);
ADVANCE_LP_RING();
- dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
+ if (++dev_priv->counter > 0x7FFFFFFFUL)
+ dev_priv->counter = 0;
+ if (dev_priv->sarea_priv)
+ dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
BEGIN_LP_RING(4);
OUT_RING(MI_STORE_DWORD_INDEX);
@@ -721,7 +723,7 @@ static int i915_flip_bufs(struct drm_device *dev, void *data,
DRM_DEBUG("%s\n", __func__);
- LOCK_TEST_WITH_RETURN(dev, file_priv);
+ RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
ret = i915_dispatch_flip(dev);
@@ -758,7 +760,7 @@ static int i915_getparam(struct drm_device *dev, void *data,
value = 0;
break;
default:
- DRM_ERROR("Unknown parameter %d\n", param->param);
+ DRM_DEBUG("Unknown parameter %d\n", param->param);
return -EINVAL;
}
@@ -791,7 +793,7 @@ static int i915_setparam(struct drm_device *dev, void *data,
dev_priv->allow_batchbuffer = param->value;
break;
default:
- DRM_ERROR("unknown parameter %d\n", param->param);
+ DRM_DEBUG("unknown parameter %d\n", param->param);
return -EINVAL;
}
@@ -822,7 +824,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data,
dev_priv->hws_map.flags = 0;
dev_priv->hws_map.mtrr = 0;
- drm_core_ioremap(&dev_priv->hws_map, dev);
+ drm_core_ioremap_wc(&dev_priv->hws_map, dev);
if (dev_priv->hws_map.handle == NULL) {
i915_dma_cleanup(dev);
dev_priv->status_gfx_addr = 0;
@@ -880,8 +882,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
/* Init HWS */
if (!I915_NEED_GFX_HWS(dev)) {
ret = i915_init_phys_hws(dev);
- if (ret != 0)
+ if (ret != 0) {
+ drm_rmmap(dev, dev_priv->mmio_map);
+ drm_free(dev_priv, sizeof(struct drm_i915_private),
+ DRM_MEM_DRIVER);
return ret;
+ }
}
#ifdef __linux__
/* On the 945G/GM, the chipset reports the MSI capability on the
@@ -901,6 +907,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
intel_opregion_init(dev);
#endif
DRM_SPININIT(&dev_priv->user_irq_lock, "userirq");
+ dev_priv->user_irq_refcount = 0;
ret = drm_vblank_init(dev, I915_NUM_PIPE);
diff --git a/sys/dev/drm/i915_drv.c b/sys/dev/drm/i915_drv.c
index 9715814..39db236 100644
--- a/sys/dev/drm/i915_drv.c
+++ b/sys/dev/drm/i915_drv.c
@@ -46,11 +46,8 @@ static drm_pci_id_list_t i915_pciidlist[] = {
static int i915_suspend(device_t kdev)
{
struct drm_device *dev = device_get_softc(kdev);
- struct drm_i915_private *dev_priv = dev->dev_private;
- if (!dev || !dev_priv) {
- DRM_ERROR("dev: 0x%lx, dev_priv: 0x%lx\n",
- (unsigned long) dev, (unsigned long) dev_priv);
+ if (!dev || !dev->dev_private) {
DRM_ERROR("DRM not initialized, aborting suspend.\n");
return -ENODEV;
}
diff --git a/sys/dev/drm/i915_drv.h b/sys/dev/drm/i915_drv.h
index 0935a70..92c8f74 100644
--- a/sys/dev/drm/i915_drv.h
+++ b/sys/dev/drm/i915_drv.h
@@ -151,6 +151,8 @@ typedef struct drm_i915_private {
u32 saveDSPACNTR;
u32 saveDSPBCNTR;
u32 saveDSPARB;
+ u32 saveRENDERSTANDBY;
+ u32 saveHWS;
u32 savePIPEACONF;
u32 savePIPEBCONF;
u32 savePIPEASRC;
@@ -232,8 +234,8 @@ typedef struct drm_i915_private {
u8 saveAR_INDEX;
u8 saveAR[21];
u8 saveDACMASK;
- u8 saveDACDATA[256*3]; /* 256 3-byte colors */
u8 saveCR[37];
+
struct {
#ifdef __linux__
struct drm_mm gtt_space;
@@ -651,7 +653,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
(dev)->pci_device == 0x2E12 || \
- (dev)->pci_device == 0x2E22)
+ (dev)->pci_device == 0x2E22 || \
+ IS_GM45(dev))
#define IS_G33(dev) ((dev)->pci_device == 0x29C2 || \
(dev)->pci_device == 0x29B2 || \
diff --git a/sys/dev/drm/i915_irq.c b/sys/dev/drm/i915_irq.c
index 1117f62..7583031 100644
--- a/sys/dev/drm/i915_irq.c
+++ b/sys/dev/drm/i915_irq.c
@@ -43,21 +43,28 @@ __FBSDID("$FreeBSD$");
* we leave them always unmasked in IMR and then control enabling them through
* PIPESTAT alone.
*/
-#define I915_INTERRUPT_ENABLE_FIX (I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
- I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
+#define I915_INTERRUPT_ENABLE_FIX (I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | \
+ I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
/** Interrupts that we mask and unmask at runtime. */
-#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
+#define I915_INTERRUPT_ENABLE_VAR (I915_USER_INTERRUPT)
/** These are all of the interrupts used by the driver */
-#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \
- I915_INTERRUPT_ENABLE_VAR)
+#define I915_INTERRUPT_ENABLE_MASK (I915_INTERRUPT_ENABLE_FIX | \
+ I915_INTERRUPT_ENABLE_VAR)
+
+#define I915_PIPE_VBLANK_STATUS (PIPE_START_VBLANK_INTERRUPT_STATUS |\
+ PIPE_VBLANK_INTERRUPT_STATUS)
+
+#define I915_PIPE_VBLANK_ENABLE (PIPE_START_VBLANK_INTERRUPT_ENABLE |\
+ PIPE_VBLANK_INTERRUPT_ENABLE)
+
+#define DRM_I915_VBLANK_PIPE_ALL (DRM_I915_VBLANK_PIPE_A | \
+ DRM_I915_VBLANK_PIPE_B)
static inline void
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
{
- DRM_DEBUG("irq_enable_reg = 0x%08x, mask = 0x%08x\n",
- dev_priv->irq_mask_reg, mask);
mask &= I915_INTERRUPT_ENABLE_VAR;
if ((dev_priv->irq_mask_reg & mask) != 0) {
dev_priv->irq_mask_reg &= ~mask;
@@ -189,59 +196,84 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 iir, new_iir;
u32 pipea_stats, pipeb_stats;
+ u32 vblank_status;
+ u32 vblank_enable;
+ int irq_received;
atomic_inc(&dev_priv->irq_received);
- for (iir = I915_READ(IIR) ; iir != 0 ; iir = new_iir) {
+ iir = I915_READ(IIR);
- pipea_stats = pipeb_stats = 0;
+ if (IS_I965G(dev)) {
+ vblank_status = I915_START_VBLANK_INTERRUPT_STATUS;
+ vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE;
+ } else {
+ vblank_status = I915_VBLANK_INTERRUPT_STATUS;
+ vblank_enable = I915_VBLANK_INTERRUPT_ENABLE;
+ }
+
+ for (;;) {
+ irq_received = iir != 0;
+
+ /* Can't rely on pipestat interrupt bit in iir as it might
+ * have been cleared after the pipestat interrupt was received.
+ * It doesn't set the bit in iir again, but it still produces
+ * interrupts (for non-MSI).
+ */
+ DRM_SPINLOCK(&dev_priv->user_irq_lock);
+ pipea_stats = I915_READ(PIPEASTAT);
+ pipeb_stats = I915_READ(PIPEBSTAT);
/*
* Clear the PIPE(A|B)STAT regs before the IIR
*/
- if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
- DRM_SPINLOCK(&dev_priv->user_irq_lock);
- pipea_stats = I915_READ(PIPEASTAT);
+ if (pipea_stats & 0x8000ffff) {
I915_WRITE(PIPEASTAT, pipea_stats);
- DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
+ irq_received = 1;
}
- if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
- DRM_SPINLOCK(&dev_priv->user_irq_lock);
- pipeb_stats = I915_READ(PIPEBSTAT);
+ if (pipeb_stats & 0x8000ffff) {
I915_WRITE(PIPEBSTAT, pipeb_stats);
- DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
+ irq_received = 1;
}
+ DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
- I915_WRITE(IIR, iir);
- new_iir = I915_READ(IIR);
+ if (!irq_received)
+ break;
- DRM_DEBUG("iir = 0x%08x, pipestats a = 0x%08x, b = 0x%08x\n",
- iir, pipea_stats, pipeb_stats);
+ I915_WRITE(IIR, iir);
+ new_iir = I915_READ(IIR); /* Flush posted writes */
if (dev_priv->sarea_priv)
dev_priv->sarea_priv->last_dispatch =
READ_BREADCRUMB(dev_priv);
if (iir & I915_USER_INTERRUPT) {
-#ifdef I915_HAVE_GEM
- dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
-#endif
DRM_WAKEUP(&dev_priv->irq_queue);
}
- if (pipea_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS |
- PIPE_VBLANK_INTERRUPT_STATUS))
+ if (pipea_stats & vblank_status)
drm_handle_vblank(dev, 0);
- if (pipeb_stats & (PIPE_START_VBLANK_INTERRUPT_STATUS |
- PIPE_VBLANK_INTERRUPT_STATUS))
+ if (pipeb_stats & vblank_status)
drm_handle_vblank(dev, 1);
-#ifdef __linux__
- if ((pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
- (iir & I915_ASLE_INTERRUPT))
- opregion_asle_intr(dev);
-#endif
+
+ /* With MSI, interrupts are only generated when iir
+ * transitions from zero to nonzero. If another bit got
+ * set while we were handling the existing iir bits, then
+ * we would never get another interrupt.
+ *
+ * This is fine on non-MSI as well, as if we hit this path
+ * we avoid exiting the interrupt handler only to generate
+ * another one.
+ *
+ * Note that for MSI this could cause a stray interrupt report
+ * if an interrupt landed in the time between writing IIR and
+ * the posting read. This should be rare enough to never
+ * trigger the 99% of 100,000 interrupts test for disabling
+ * stray interrupts.
+ */
+ iir = new_iir;
}
}
@@ -252,14 +284,13 @@ static int i915_emit_irq(struct drm_device * dev)
i915_kernel_lost_context(dev);
- DRM_DEBUG("\n");
-
- dev_priv->counter++;
- if (dev_priv->counter > 0x7FFFFFFFUL)
- dev_priv->counter = 1;
+ if (++dev_priv->counter > 0x7FFFFFFFUL)
+ dev_priv->counter = 0;
if (dev_priv->sarea_priv)
dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
+ DRM_DEBUG("emitting: %d\n", dev_priv->counter);
+
BEGIN_LP_RING(4);
OUT_RING(MI_STORE_DWORD_INDEX);
OUT_RING(I915_BREADCRUMB_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
@@ -273,27 +304,25 @@ static int i915_emit_irq(struct drm_device * dev)
void i915_user_irq_get(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- unsigned long irqflags;
DRM_DEBUG("\n");
- DRM_SPINLOCK_IRQSAVE(&dev_priv->user_irq_lock, irqflags);
+ DRM_SPINLOCK(&dev_priv->user_irq_lock);
if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
- DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->user_irq_lock, irqflags);
+ DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
}
void i915_user_irq_put(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- unsigned long irqflags;
-
- DRM_SPINLOCK_IRQSAVE(&dev_priv->user_irq_lock, irqflags);
-#ifdef __linux__
- BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
-#endif
- if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0))
- i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
- DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->user_irq_lock, irqflags);
+
+ DRM_SPINLOCK(&dev_priv->user_irq_lock);
+ if (dev->irq_enabled) {
+ KASSERT(dev_priv->user_irq_refcount > 0, ("invalid refcount"));
+ if (--dev_priv->user_irq_refcount == 0)
+ i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
+ }
+ DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
}
static int i915_wait_irq(struct drm_device * dev, int irq_nr)
@@ -301,9 +330,6 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int ret = 0;
- DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
- READ_BREADCRUMB(dev_priv));
-
if (READ_BREADCRUMB(dev_priv) >= irq_nr) {
if (dev_priv->sarea_priv) {
dev_priv->sarea_priv->last_dispatch =
@@ -315,20 +341,22 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
if (dev_priv->sarea_priv)
dev_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
+ DRM_DEBUG("irq_nr=%d breadcrumb=%d\n", irq_nr,
+ READ_BREADCRUMB(dev_priv));
+
i915_user_irq_get(dev);
DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ,
READ_BREADCRUMB(dev_priv) >= irq_nr);
i915_user_irq_put(dev);
+ if (ret == -ERESTART)
+ DRM_DEBUG("restarting syscall\n");
+
if (ret == -EBUSY) {
DRM_ERROR("EBUSY -- rec: %d emitted: %d\n",
READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
}
- if (dev_priv->sarea_priv)
- dev_priv->sarea_priv->last_dispatch =
- READ_BREADCRUMB(dev_priv);
-
return ret;
}
@@ -341,13 +369,13 @@ int i915_irq_emit(struct drm_device *dev, void *data,
drm_i915_irq_emit_t *emit = data;
int result;
- RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-
if (!dev_priv) {
DRM_ERROR("called with no initialization\n");
return -EINVAL;
}
+ RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
+
result = i915_emit_irq(dev);
if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) {
@@ -380,21 +408,21 @@ int i915_irq_wait(struct drm_device *dev, void *data,
int i915_enable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- unsigned long irqflags;
- u32 pipestat;
+ int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
+ u32 pipeconf;
- /*
- * Older chips didn't have the start vblank interrupt,
- * but
- */
- if (IS_I965G (dev))
- pipestat = PIPE_START_VBLANK_INTERRUPT_ENABLE;
- else
- pipestat = PIPE_VBLANK_INTERRUPT_ENABLE;
+ pipeconf = I915_READ(pipeconf_reg);
+ if (!(pipeconf & PIPEACONF_ENABLE))
+ return -EINVAL;
- DRM_SPINLOCK_IRQSAVE(&dev_priv->user_irq_lock, irqflags);
- i915_enable_pipestat(dev_priv, pipe, pipestat);
- DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->user_irq_lock, irqflags);
+ DRM_SPINLOCK(&dev_priv->user_irq_lock);
+ if (IS_I965G(dev))
+ i915_enable_pipestat(dev_priv, pipe,
+ PIPE_START_VBLANK_INTERRUPT_ENABLE);
+ else
+ i915_enable_pipestat(dev_priv, pipe,
+ PIPE_VBLANK_INTERRUPT_ENABLE);
+ DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
return 0;
}
@@ -404,12 +432,12 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
void i915_disable_vblank(struct drm_device *dev, int pipe)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
- unsigned long irqflags;
- DRM_SPINLOCK_IRQSAVE(&dev_priv->user_irq_lock, irqflags);
+ DRM_SPINLOCK(&dev_priv->user_irq_lock);
i915_disable_pipestat(dev_priv, pipe,
- PIPE_START_VBLANK_INTERRUPT_ENABLE | PIPE_VBLANK_INTERRUPT_ENABLE);
- DRM_SPINUNLOCK_IRQRESTORE(&dev_priv->user_irq_lock, irqflags);
+ PIPE_VBLANK_INTERRUPT_ENABLE |
+ PIPE_START_VBLANK_INTERRUPT_ENABLE);
+ DRM_SPINUNLOCK(&dev_priv->user_irq_lock);
}
/* Set the vblank monitor pipe
@@ -463,7 +491,6 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
* Context switching to userland and back is plenty fast enough for
* meeting the requirements of vblank swapping.
*/
-
return -EINVAL;
}
@@ -473,6 +500,8 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+ atomic_set_int(&dev_priv->irq_received, 0);
+
I915_WRITE(HWSTAM, 0xeffe);
I915_WRITE(PIPEASTAT, 0);
I915_WRITE(PIPEBSTAT, 0);
@@ -505,13 +534,6 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
I915_WRITE(IER, I915_INTERRUPT_ENABLE_MASK);
I915_WRITE(IMR, dev_priv->irq_mask_reg);
(void) I915_READ(IER);
-#ifdef __linux__
- opregion_enable_asle(dev);
-#endif
- DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
-
- i915_enable_vblank(dev, 0);
- i915_enable_vblank(dev, 1);
return 0;
}
diff --git a/sys/dev/drm/i915_reg.h b/sys/dev/drm/i915_reg.h
index a9142d0..1a32c5f 100644
--- a/sys/dev/drm/i915_reg.h
+++ b/sys/dev/drm/i915_reg.h
@@ -38,7 +38,7 @@ __FBSDID("$FreeBSD$");
#define INTEL_GMCH_MEM_64M 0x1
#define INTEL_GMCH_MEM_128M 0
-#define INTEL_855_GMCH_GMS_MASK (0x7 << 4)
+#define INTEL_GMCH_GMS_MASK (0xf << 4)
#define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4)
#define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4)
#define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4)
@@ -48,6 +48,12 @@ __FBSDID("$FreeBSD$");
#define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
#define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
+#define INTEL_GMCH_GMS_STOLEN_128M (0x8 << 4)
+#define INTEL_GMCH_GMS_STOLEN_256M (0x9 << 4)
+#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4)
+#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4)
+#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4)
+#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4)
/* PCI config space */
@@ -178,9 +184,27 @@ __FBSDID("$FreeBSD$");
#define DISPLAY_PLANE_B (1<<20)
/*
- * Instruction and interrupt control regs
+ * Fence registers
*/
+#define FENCE_REG_830_0 0x2000
+#define FENCE_REG_945_8 0x3000
+#define I830_FENCE_START_MASK 0x07f80000
+#define I830_FENCE_TILING_Y_SHIFT 12
+#define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8)
+#define I830_FENCE_PITCH_SHIFT 4
+#define I830_FENCE_REG_VALID (1<<0)
+
+#define I915_FENCE_START_MASK 0x0ff00000
+#define I915_FENCE_SIZE_BITS(size) ((ffs((size) >> 20) - 1) << 8)
+
+#define FENCE_REG_965_0 0x03000
+#define I965_FENCE_PITCH_SHIFT 2
+#define I965_FENCE_TILING_Y_SHIFT 1
+#define I965_FENCE_REG_VALID (1<<0)
+/*
+ * Instruction and interrupt control regs
+ */
#define PRB0_TAIL 0x02030
#define PRB0_HEAD 0x02034
#define PRB0_START 0x02038
@@ -248,6 +272,7 @@ __FBSDID("$FreeBSD$");
#define CM0_RC_OP_FLUSH_DISABLE (1<<0)
#define GFX_FLSH_CNTL 0x02170 /* 915+ only */
+
/*
* Framebuffer compression (915+ only)
*/
@@ -525,11 +550,17 @@ __FBSDID("$FreeBSD$");
#define DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED (2 << 0)
#define DCC_ADDRESSING_MODE_MASK (3 << 0)
#define DCC_CHANNEL_XOR_DISABLE (1 << 10)
+#define DCC_CHANNEL_XOR_BIT_17 (1 << 9)
/** 965 MCH register controlling DRAM channel configuration */
#define C0DRB3 0x10206
#define C1DRB3 0x10606
+/** GM965 GM45 render standby register */
+#define MCHBAR_RENDER_STANDBY 0x111B8
+
+#define PEG_BAND_GAP_DATA 0x14d68
+
/*
* Overlay regs
*/
@@ -593,6 +624,9 @@ __FBSDID("$FreeBSD$");
/* Hotplug control (945+ only) */
#define PORT_HOTPLUG_EN 0x61110
+#define HDMIB_HOTPLUG_INT_EN (1 << 29)
+#define HDMIC_HOTPLUG_INT_EN (1 << 28)
+#define HDMID_HOTPLUG_INT_EN (1 << 27)
#define SDVOB_HOTPLUG_INT_EN (1 << 26)
#define SDVOC_HOTPLUG_INT_EN (1 << 25)
#define TV_HOTPLUG_INT_EN (1 << 18)
@@ -600,6 +634,9 @@ __FBSDID("$FreeBSD$");
#define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
#define PORT_HOTPLUG_STAT 0x61114
+#define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
+#define HDMIC_HOTPLUG_INT_STATUS (1 << 28)
+#define HDMID_HOTPLUG_INT_STATUS (1 << 27)
#define CRT_HOTPLUG_INT_STATUS (1 << 11)
#define TV_HOTPLUG_INT_STATUS (1 << 10)
#define CRT_HOTPLUG_MONITOR_MASK (3 << 8)
@@ -629,7 +666,16 @@ __FBSDID("$FreeBSD$");
#define SDVO_PHASE_SELECT_DEFAULT (6 << 19)
#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18)
#define SDVOC_GANG_MODE (1 << 16)
+#define SDVO_ENCODING_SDVO (0x0 << 10)
+#define SDVO_ENCODING_HDMI (0x2 << 10)
+/** Requird for HDMI operation */
+#define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9)
#define SDVO_BORDER_ENABLE (1 << 7)
+#define SDVO_AUDIO_ENABLE (1 << 6)
+/** New with 965, default is to be set */
+#define SDVO_VSYNC_ACTIVE_HIGH (1 << 4)
+/** New with 965, default is to be set */
+#define SDVO_HSYNC_ACTIVE_HIGH (1 << 3)
#define SDVOB_PCIE_CONCURRENCY (1 << 3)
#define SDVO_DETECTED (1 << 2)
/* Bits to be preserved when writing */
@@ -1403,6 +1449,7 @@ __FBSDID("$FreeBSD$");
#define PIPEB_FRMCOUNT_GM45 0x71040
#define PIPEB_FLIPCOUNT_GM45 0x71044
+
/* Display B control */
#define DSPBCNTR 0x71180
#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15)
diff --git a/sys/dev/drm/i915_suspend.c b/sys/dev/drm/i915_suspend.c
index 9f8fad6..0692f52 100644
--- a/sys/dev/drm/i915_suspend.c
+++ b/sys/dev/drm/i915_suspend.c
@@ -125,11 +125,6 @@ static void i915_save_vga(struct drm_device *dev)
/* VGA color palette registers */
dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
- /* DACCRX automatically increments during read */
- I915_WRITE8(VGA_DACRX, 0);
- /* Read 3 bytes of color data from each index */
- for (i = 0; i < 256 * 3; i++)
- dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA);
/* MSR bits */
dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
@@ -231,12 +226,6 @@ static void i915_restore_vga(struct drm_device *dev)
/* VGA color palette registers */
I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
- /* DACCRX automatically increments during read */
- I915_WRITE8(VGA_DACWX, 0);
- /* Read 3 bytes of color data from each index */
- for (i = 0; i < 256 * 3; i++)
- I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]);
-
}
int i915_save_state(struct drm_device *dev)
@@ -250,6 +239,13 @@ int i915_save_state(struct drm_device *dev)
pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
#endif
+ /* Render Standby */
+ if (IS_I965G(dev) && IS_MOBILE(dev))
+ dev_priv->saveRENDERSTANDBY = I915_READ(MCHBAR_RENDER_STANDBY);
+
+ /* Hardware status page */
+ dev_priv->saveHWS = I915_READ(HWS_PGA);
+
/* Display arbitration control */
dev_priv->saveDSPARB = I915_READ(DSPARB);
@@ -379,6 +375,14 @@ int i915_restore_state(struct drm_device *dev)
pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
#endif
+ /* Render Standby */
+ if (IS_I965G(dev) && IS_MOBILE(dev))
+ I915_WRITE(MCHBAR_RENDER_STANDBY, dev_priv->saveRENDERSTANDBY);
+
+ /* Hardware status page */
+ I915_WRITE(HWS_PGA, dev_priv->saveHWS);
+
+ /* Display arbitration */
I915_WRITE(DSPARB, dev_priv->saveDSPARB);
/* Pipe & plane A info */
@@ -511,7 +515,7 @@ int i915_restore_state(struct drm_device *dev)
for (i = 0; i < 16; i++) {
I915_WRITE(SWF00 + (i << 2), dev_priv->saveSWF0[i]);
- I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i+7]);
+ I915_WRITE(SWF10 + (i << 2), dev_priv->saveSWF1[i]);
}
for (i = 0; i < 3; i++)
I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]);
diff --git a/sys/dev/drm/mga_irq.c b/sys/dev/drm/mga_irq.c
index 005d43d..8e28987 100644
--- a/sys/dev/drm/mga_irq.c
+++ b/sys/dev/drm/mga_irq.c
@@ -139,6 +139,9 @@ int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
(((cur_fence = atomic_read(&dev_priv->last_fence_retired))
- *sequence) <= (1 << 23)));
+ if (ret == -ERESTART)
+ DRM_DEBUG("restarting syscall\n");
+
*sequence = cur_fence;
return ret;
diff --git a/sys/dev/drm/r300_cmdbuf.c b/sys/dev/drm/r300_cmdbuf.c
index b9e9f0f..8251562 100644
--- a/sys/dev/drm/r300_cmdbuf.c
+++ b/sys/dev/drm/r300_cmdbuf.c
@@ -208,6 +208,10 @@ void r300_init_reg_flags(struct drm_device *dev)
ADD_RANGE(0x42C0, 2);
ADD_RANGE(R300_RS_CNTL_0, 2);
+ ADD_RANGE(R300_SU_REG_DEST, 1);
+ if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530)
+ ADD_RANGE(RV530_FG_ZBREG_DEST, 1);
+
ADD_RANGE(R300_SC_HYPERZ, 2);
ADD_RANGE(0x43E8, 1);
@@ -232,7 +236,11 @@ void r300_init_reg_flags(struct drm_device *dev)
ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */
ADD_RANGE(R300_ZB_DEPTHPITCH, 1);
ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1);
- ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13);
+ ADD_RANGE(R300_ZB_ZMASK_OFFSET, 5);
+ ADD_RANGE(R300_ZB_HIZ_OFFSET, 5);
+ ADD_RANGE(R300_ZB_ZPASS_DATA, 1);
+ ADD_RANGE_MARK(R300_ZB_ZPASS_ADDR, 1, MARK_CHECK_OFFSET); /* check offset */
+ ADD_RANGE(R300_ZB_DEPTHXY_OFFSET, 1)
ADD_RANGE(R300_TX_FILTER_0, 16);
ADD_RANGE(R300_TX_FILTER1_0, 16);
diff --git a/sys/dev/drm/r300_reg.h b/sys/dev/drm/r300_reg.h
index c92779e..928440f 100644
--- a/sys/dev/drm/r300_reg.h
+++ b/sys/dev/drm/r300_reg.h
@@ -1776,6 +1776,11 @@ __FBSDID("$FreeBSD$");
#define R500_RB3D_COLOR_CLEAR_VALUE_AR 0x46c0
#define R500_RB3D_CONSTANT_COLOR_AR 0x4ef8
+#define R300_SU_REG_DEST 0x42c8
+#define RV530_FG_ZBREG_DEST 0x4be8
+#define R300_ZB_ZPASS_DATA 0x4f58
+#define R300_ZB_ZPASS_ADDR 0x4f5c
+
#endif /* _R300_REG_H */
/* *INDENT-ON* */
diff --git a/sys/dev/drm/r600_cp.c b/sys/dev/drm/r600_cp.c
index 9cf4f31..f9b16af 100644
--- a/sys/dev/drm/r600_cp.c
+++ b/sys/dev/drm/r600_cp.c
@@ -174,7 +174,6 @@ int r600_page_table_init(struct drm_device *dev)
if (entry->busaddr[i] == 0) {
DRM_ERROR("unable to map PCIGART pages!\n");
r600_page_table_cleanup(dev, gart_info);
- ret = -EINVAL;
goto done;
}
#endif
@@ -193,6 +192,7 @@ int r600_page_table_init(struct drm_device *dev)
entry_addr += ATI_PCIGART_PAGE_SIZE;
}
}
+ ret = 1;
#ifdef __linux__
done:
#endif
@@ -282,8 +282,50 @@ static void r600_vm_init(struct drm_device *dev)
/* load r600 microcode */
static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
{
+ const u32 (*cp)[3];
+ const u32 *pfp;
int i;
+ switch (dev_priv->flags & RADEON_FAMILY_MASK) {
+ case CHIP_R600:
+ DRM_INFO("Loading R600 Microcode\n");
+ cp = R600_cp_microcode;
+ pfp = R600_pfp_microcode;
+ break;
+ case CHIP_RV610:
+ DRM_INFO("Loading RV610 Microcode\n");
+ cp = RV610_cp_microcode;
+ pfp = RV610_pfp_microcode;
+ break;
+ case CHIP_RV630:
+ DRM_INFO("Loading RV630 Microcode\n");
+ cp = RV630_cp_microcode;
+ pfp = RV630_pfp_microcode;
+ break;
+ case CHIP_RV620:
+ DRM_INFO("Loading RV620 Microcode\n");
+ cp = RV620_cp_microcode;
+ pfp = RV620_pfp_microcode;
+ break;
+ case CHIP_RV635:
+ DRM_INFO("Loading RV635 Microcode\n");
+ cp = RV635_cp_microcode;
+ pfp = RV635_pfp_microcode;
+ break;
+ case CHIP_RV670:
+ DRM_INFO("Loading RV670 Microcode\n");
+ cp = RV670_cp_microcode;
+ pfp = RV670_pfp_microcode;
+ break;
+ case CHIP_RS780:
+ DRM_INFO("Loading RS780 Microcode\n");
+ cp = RS780_cp_microcode;
+ pfp = RS780_pfp_microcode;
+ break;
+ default:
+ return;
+ }
+
r600_do_cp_stop(dev_priv);
RADEON_WRITE(R600_CP_RB_CNTL,
@@ -298,116 +340,19 @@ static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
- if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600)) {
- DRM_INFO("Loading R600 CP Microcode\n");
- for (i = 0; i < PM4_UCODE_SIZE; i++) {
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- R600_cp_microcode[i][0]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- R600_cp_microcode[i][1]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- R600_cp_microcode[i][2]);
- }
-
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
- DRM_INFO("Loading R600 PFP Microcode\n");
- for (i = 0; i < PFP_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_PFP_UCODE_DATA, R600_pfp_microcode[i]);
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610)) {
- DRM_INFO("Loading RV610 CP Microcode\n");
- for (i = 0; i < PM4_UCODE_SIZE; i++) {
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV610_cp_microcode[i][0]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV610_cp_microcode[i][1]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV610_cp_microcode[i][2]);
- }
-
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
- DRM_INFO("Loading RV610 PFP Microcode\n");
- for (i = 0; i < PFP_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV610_pfp_microcode[i]);
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630)) {
- DRM_INFO("Loading RV630 CP Microcode\n");
- for (i = 0; i < PM4_UCODE_SIZE; i++) {
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV630_cp_microcode[i][0]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV630_cp_microcode[i][1]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV630_cp_microcode[i][2]);
- }
-
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
- DRM_INFO("Loading RV630 PFP Microcode\n");
- for (i = 0; i < PFP_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV630_pfp_microcode[i]);
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620)) {
- DRM_INFO("Loading RV620 CP Microcode\n");
- for (i = 0; i < PM4_UCODE_SIZE; i++) {
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV620_cp_microcode[i][0]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV620_cp_microcode[i][1]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV620_cp_microcode[i][2]);
- }
-
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
- DRM_INFO("Loading RV620 PFP Microcode\n");
- for (i = 0; i < PFP_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV620_pfp_microcode[i]);
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV635)) {
- DRM_INFO("Loading RV635 CP Microcode\n");
- for (i = 0; i < PM4_UCODE_SIZE; i++) {
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV635_cp_microcode[i][0]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV635_cp_microcode[i][1]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV635_cp_microcode[i][2]);
- }
-
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
- DRM_INFO("Loading RV635 PFP Microcode\n");
- for (i = 0; i < PFP_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV635_pfp_microcode[i]);
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670)) {
- DRM_INFO("Loading RV670 CP Microcode\n");
- for (i = 0; i < PM4_UCODE_SIZE; i++) {
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV670_cp_microcode[i][0]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV670_cp_microcode[i][1]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV670_cp_microcode[i][2]);
- }
+ for (i = 0; i < PM4_UCODE_SIZE; i++) {
+ RADEON_WRITE(R600_CP_ME_RAM_DATA, cp[i][0]);
+ RADEON_WRITE(R600_CP_ME_RAM_DATA, cp[i][1]);
+ RADEON_WRITE(R600_CP_ME_RAM_DATA, cp[i][2]);
+ }
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
- DRM_INFO("Loading RV670 PFP Microcode\n");
- for (i = 0; i < PFP_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV670_pfp_microcode[i]);
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
- DRM_INFO("Loading RS780 CP Microcode\n");
- for (i = 0; i < PM4_UCODE_SIZE; i++) {
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV670_cp_microcode[i][0]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV670_cp_microcode[i][1]);
- RADEON_WRITE(R600_CP_ME_RAM_DATA,
- RV670_cp_microcode[i][2]);
- }
+ RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
+ for (i = 0; i < PFP_UCODE_SIZE; i++)
+ RADEON_WRITE(R600_CP_PFP_UCODE_DATA, pfp[i]);
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
- DRM_INFO("Loading RS780 PFP Microcode\n");
- for (i = 0; i < PFP_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV670_pfp_microcode[i]);
- }
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
-
}
static void r700_vm_init(struct drm_device *dev)
@@ -465,8 +410,30 @@ static void r700_vm_init(struct drm_device *dev)
/* load r600 microcode */
static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
{
+ const u32 *pfp;
+ const u32 *cp;
int i;
+ switch (dev_priv->flags & RADEON_FAMILY_MASK) {
+ case CHIP_RV770:
+ DRM_INFO("Loading RV770/RV790 Microcode\n");
+ pfp = RV770_pfp_microcode;
+ cp = RV770_cp_microcode;
+ break;
+ case CHIP_RV730:
+ DRM_INFO("Loading RV730 Microcode\n");
+ pfp = RV730_pfp_microcode;
+ cp = RV730_cp_microcode;
+ break;
+ case CHIP_RV710:
+ DRM_INFO("Loading RV710 Microcode\n");
+ pfp = RV710_pfp_microcode;
+ cp = RV710_cp_microcode;
+ break;
+ default:
+ return;
+ }
+
r600_do_cp_stop(dev_priv);
RADEON_WRITE(R600_CP_RB_CNTL,
@@ -479,51 +446,19 @@ static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
DRM_UDELAY(15000);
RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
+ RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
+ for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
+ RADEON_WRITE(R600_CP_PFP_UCODE_DATA, pfp[i]);
+ RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
- if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)) {
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
- DRM_INFO("Loading RV770 PFP Microcode\n");
- for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV770_pfp_microcode[i]);
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-
- RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
- DRM_INFO("Loading RV770 CP Microcode\n");
- for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_ME_RAM_DATA, RV770_cp_microcode[i]);
- RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV730)) {
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
- DRM_INFO("Loading RV730 PFP Microcode\n");
- for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV730_pfp_microcode[i]);
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-
- RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
- DRM_INFO("Loading RV730 CP Microcode\n");
- for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_ME_RAM_DATA, RV730_cp_microcode[i]);
- RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
-
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)) {
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
- DRM_INFO("Loading RV710 PFP Microcode\n");
- for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV710_pfp_microcode[i]);
- RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
-
- RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
- DRM_INFO("Loading RV710 CP Microcode\n");
- for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
- RADEON_WRITE(R600_CP_ME_RAM_DATA, RV710_cp_microcode[i]);
- RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
+ RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
+ for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
+ RADEON_WRITE(R600_CP_ME_RAM_DATA, cp[i]);
+ RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
- }
RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
-
}
static void r600_test_writeback(drm_radeon_private_t *dev_priv)
@@ -1740,9 +1675,6 @@ static void r600_cp_init_ring_buffer(struct drm_device *dev,
RADEON_WRITE(R600_CP_DEBUG, (1 << 27) | (1 << 28));
- /* Start with assuming that writeback doesn't work */
- dev_priv->writeback_works = 0;
-
/* Initialize the scratch register pointer. This will cause
* the scratch register values to be written out to memory
* whenever they are updated.
@@ -2103,7 +2035,7 @@ int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
dev_priv->gart_info.addr,
dev_priv->pcigart_offset);
- if (r600_page_table_init(dev)) {
+ if (!r600_page_table_init(dev)) {
DRM_ERROR("Failed to init GART table\n");
r600_do_cleanup_cp(dev);
return -EINVAL;
diff --git a/sys/dev/drm/radeon_cp.c b/sys/dev/drm/radeon_cp.c
index 972751c..8f723ce 100644
--- a/sys/dev/drm/radeon_cp.c
+++ b/sys/dev/drm/radeon_cp.c
@@ -436,7 +436,7 @@ static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) {
RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4));
- RADEON_WRITE(R500_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1));
+ RADEON_WRITE(R300_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1));
}
RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config);
radeon_do_wait_for_idle(dev_priv);
@@ -455,88 +455,71 @@ static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
/* Load the microcode for the CP */
static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
{
+ const u32 (*cp)[2];
int i;
- DRM_DEBUG("\n");
- radeon_do_wait_for_idle(dev_priv);
+ DRM_DEBUG("\n");
- RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
- if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) {
+ switch (dev_priv->flags & RADEON_FAMILY_MASK) {
+ case CHIP_R100:
+ case CHIP_RV100:
+ case CHIP_RV200:
+ case CHIP_RS100:
+ case CHIP_RS200:
DRM_INFO("Loading R100 Microcode\n");
- for (i = 0; i < 256; i++) {
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
- R100_cp_microcode[i][1]);
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
- R100_cp_microcode[i][0]);
- }
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) {
+ cp = R100_cp_microcode;
+ break;
+ case CHIP_R200:
+ case CHIP_RV250:
+ case CHIP_RV280:
+ case CHIP_RS300:
DRM_INFO("Loading R200 Microcode\n");
- for (i = 0; i < 256; i++) {
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
- R200_cp_microcode[i][1]);
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
- R200_cp_microcode[i][0]);
- }
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
+ cp = R200_cp_microcode;
+ break;
+ case CHIP_R300:
+ case CHIP_R350:
+ case CHIP_RV350:
+ case CHIP_RV380:
+ case CHIP_RS400:
+ case CHIP_RS480:
DRM_INFO("Loading R300 Microcode\n");
- for (i = 0; i < 256; i++) {
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
- R300_cp_microcode[i][1]);
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
- R300_cp_microcode[i][0]);
- }
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
+ cp = R300_cp_microcode;
+ break;
+ case CHIP_R420:
+ case CHIP_R423:
+ case CHIP_RV410:
DRM_INFO("Loading R400 Microcode\n");
- for (i = 0; i < 256; i++) {
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
- R420_cp_microcode[i][1]);
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
- R420_cp_microcode[i][0]);
- }
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) {
+ cp = R420_cp_microcode;
+ break;
+ case CHIP_RS690:
+ case CHIP_RS740:
DRM_INFO("Loading RS690/RS740 Microcode\n");
- for (i = 0; i < 256; i++) {
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
- RS690_cp_microcode[i][1]);
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
- RS690_cp_microcode[i][0]);
- }
- } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) {
+ cp = RS690_cp_microcode;
+ break;
+ case CHIP_RS600:
DRM_INFO("Loading RS600 Microcode\n");
- for (i = 0; i < 256; i++) {
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
- RS600_cp_microcode[i][1]);
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
- RS600_cp_microcode[i][0]);
- }
- } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) ||
- ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) {
+ cp = RS600_cp_microcode;
+ break;
+ case CHIP_RV515:
+ case CHIP_R520:
+ case CHIP_RV530:
+ case CHIP_R580:
+ case CHIP_RV560:
+ case CHIP_RV570:
DRM_INFO("Loading R500 Microcode\n");
- for (i = 0; i < 256; i++) {
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
- R520_cp_microcode[i][1]);
- RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
- R520_cp_microcode[i][0]);
- }
+ cp = R520_cp_microcode;
+ break;
+ default:
+ return;
+ }
+
+ radeon_do_wait_for_idle(dev_priv);
+
+ RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
+
+ for (i = 0; i != 256; i++) {
+ RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, cp[i][1]);
+ RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, cp[i][0]);
}
}
@@ -1708,26 +1691,14 @@ void radeon_do_release(struct drm_device * dev)
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
while ((ret = r600_do_cp_idle(dev_priv)) != 0) {
DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
-#ifdef __linux__
- schedule();
-#elsif defined(__FreeBSD__)
mtx_sleep(&ret, &dev->dev_lock, 0,
"rdnrel", 1);
-#else
- tsleep(&ret, PZERO, "rdnrel", 1);
-#endif
}
} else {
while ((ret = radeon_do_cp_idle(dev_priv)) != 0) {
DRM_DEBUG("radeon_do_cp_idle %d\n", ret);
-#ifdef __linux__
- schedule();
-#elsif defined(__FreeBSD__)
mtx_sleep(&ret, &dev->dev_lock, 0,
"rdnrel", 1);
-#else
- tsleep(&ret, PZERO, "rdnrel", 1);
-#endif
}
}
if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) {
diff --git a/sys/dev/drm/radeon_drv.h b/sys/dev/drm/radeon_drv.h
index 138a1e2..57f57a9 100644
--- a/sys/dev/drm/radeon_drv.h
+++ b/sys/dev/drm/radeon_drv.h
@@ -684,7 +684,6 @@ extern void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pciga
/* pipe config regs */
#define R400_GB_PIPE_SELECT 0x402c
#define R500_DYN_SCLK_PWMEM_PIPE 0x000d /* PLL */
-#define R500_SU_REG_DEST 0x42c8
#define R300_GB_TILE_CONFIG 0x4018
# define R300_ENABLE_TILING (1 << 0)
# define R300_PIPE_COUNT_RV350 (0 << 1)
diff --git a/sys/dev/drm/radeon_irq.c b/sys/dev/drm/radeon_irq.c
index 58b957d..ce301eb 100644
--- a/sys/dev/drm/radeon_irq.c
+++ b/sys/dev/drm/radeon_irq.c
@@ -229,6 +229,7 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
RADEON_WRITE(RADEON_AIC_CNTL,
tmp | RS400_MSI_REARM);
break;
+ case CHIP_RS600:
case CHIP_RS690:
case CHIP_RS740:
tmp = RADEON_READ(RADEON_BUS_CNTL) &
@@ -281,6 +282,9 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ,
RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr);
+ if (ret == -ERESTART)
+ DRM_DEBUG("restarting syscall");
+
return ret;
}
diff --git a/sys/dev/e1000/e1000_80003es2lan.c b/sys/dev/e1000/e1000_80003es2lan.c
index fa7272e..5c06086 100644
--- a/sys/dev/e1000/e1000_80003es2lan.c
+++ b/sys/dev/e1000/e1000_80003es2lan.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -43,9 +43,7 @@ static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw);
static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw);
static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw);
static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw);
-static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw);
static void e1000_release_phy_80003es2lan(struct e1000_hw *hw);
-static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw);
static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw);
static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw);
static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
@@ -276,6 +274,8 @@ static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw)
mac->ops.mta_set = e1000_mta_set_generic;
/* read mac address */
mac->ops.read_mac_addr = e1000_read_mac_addr_80003es2lan;
+ /* ID LED init */
+ mac->ops.id_led_init = e1000_id_led_init_generic;
/* blink LED */
mac->ops.blink_led = e1000_blink_led_generic;
/* setup LED */
@@ -802,17 +802,16 @@ static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
index = phy_data & GG82563_DSPD_CABLE_LENGTH;
- if (index < GG82563_CABLE_LENGTH_TABLE_SIZE + 5) {
- phy->min_cable_length = e1000_gg82563_cable_length_table[index];
- phy->max_cable_length =
- e1000_gg82563_cable_length_table[index+5];
-
- phy->cable_length = (phy->min_cable_length +
- phy->max_cable_length) / 2;
- } else {
+ if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE + 5) {
ret_val = E1000_ERR_PHY;
+ goto out;
}
+ phy->min_cable_length = e1000_gg82563_cable_length_table[index];
+ phy->max_cable_length = e1000_gg82563_cable_length_table[index+5];
+
+ phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
+
out:
return ret_val;
}
@@ -892,7 +891,7 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
icr = E1000_READ_REG(hw, E1000_ICR);
- e1000_check_alt_mac_addr_generic(hw);
+ ret_val = e1000_check_alt_mac_addr_generic(hw);
out:
return ret_val;
@@ -916,7 +915,7 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
e1000_initialize_hw_bits_80003es2lan(hw);
/* Initialize identification LED */
- ret_val = e1000_id_led_init_generic(hw);
+ ret_val = mac->ops.id_led_init(hw);
if (ret_val) {
DEBUGOUT("Error initializing identification LED\n");
/* This is not fatal and we should not stop init due to this */
@@ -1104,9 +1103,9 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
/* Bypass Rx and Tx FIFO's */
ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
- E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
- E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
- E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
+ E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
+ E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
+ E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
if (ret_val)
goto out;
@@ -1147,22 +1146,19 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
if (!(hw->mac.ops.check_mng_mode(hw))) {
/* Enable Electrical Idle on the PHY */
data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
- ret_val = hw->phy.ops.write_reg(hw,
- GG82563_PHY_PWR_MGMT_CTRL,
+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
data);
if (ret_val)
goto out;
- ret_val = hw->phy.ops.read_reg(hw,
- GG82563_PHY_KMRN_MODE_CTRL,
- &data);
- if (ret_val)
- goto out;
+
+ ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+ &data);
+ if (ret_val)
+ goto out;
data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
- ret_val = hw->phy.ops.write_reg(hw,
- GG82563_PHY_KMRN_MODE_CTRL,
+ ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
data);
-
if (ret_val)
goto out;
}
@@ -1261,7 +1257,6 @@ static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
DEBUGFUNC("e1000_configure_on_link_up");
if (hw->phy.media_type == e1000_media_type_copper) {
-
ret_val = e1000_get_speed_and_duplex_copper_generic(hw,
&speed,
&duplex);
@@ -1393,7 +1388,8 @@ out:
* using the kumeran interface. The information retrieved is stored in data.
* Release the semaphore before exiting.
**/
-s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
+ u16 *data)
{
u32 kmrnctrlsta;
s32 ret_val = E1000_SUCCESS;
@@ -1429,7 +1425,8 @@ out:
* at the offset using the kumeran interface. Release semaphore
* before exiting.
**/
-s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, u16 data)
+static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
+ u16 data)
{
u32 kmrnctrlsta;
s32 ret_val = E1000_SUCCESS;
@@ -1461,9 +1458,19 @@ static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw)
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_read_mac_addr_80003es2lan");
- if (e1000_check_alt_mac_addr_generic(hw))
- ret_val = e1000_read_mac_addr_generic(hw);
+ /*
+ * If there's an alternate MAC address place it in RAR0
+ * so that it will override the Si installed default perm
+ * address.
+ */
+ ret_val = e1000_check_alt_mac_addr_generic(hw);
+ if (ret_val)
+ goto out;
+
+ ret_val = e1000_read_mac_addr_generic(hw);
+
+out:
return ret_val;
}
diff --git a/sys/dev/e1000/e1000_82540.c b/sys/dev/e1000/e1000_82540.c
index 6967261..2cd1057 100644
--- a/sys/dev/e1000/e1000_82540.c
+++ b/sys/dev/e1000/e1000_82540.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -229,6 +229,8 @@ static s32 e1000_init_mac_params_82540(struct e1000_hw *hw)
mac->ops.clear_vfta = e1000_clear_vfta_generic;
/* setting MTA */
mac->ops.mta_set = e1000_mta_set_generic;
+ /* ID LED init */
+ mac->ops.id_led_init = e1000_id_led_init_generic;
/* setup LED */
mac->ops.setup_led = e1000_setup_led_generic;
/* cleanup LED */
@@ -332,7 +334,7 @@ static s32 e1000_init_hw_82540(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_hw_82540");
/* Initialize identification LED */
- ret_val = e1000_id_led_init_generic(hw);
+ ret_val = mac->ops.id_led_init(hw);
if (ret_val) {
DEBUGOUT("Error initializing identification LED\n");
/* This is not fatal and we should not stop init due to this */
diff --git a/sys/dev/e1000/e1000_82541.c b/sys/dev/e1000/e1000_82541.c
index 03d1103..a7f896e 100644
--- a/sys/dev/e1000/e1000_82541.c
+++ b/sys/dev/e1000/e1000_82541.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -261,6 +261,8 @@ static s32 e1000_init_mac_params_82541(struct e1000_hw *hw)
mac->ops.clear_vfta = e1000_clear_vfta_generic;
/* setting MTA */
mac->ops.mta_set = e1000_mta_set_generic;
+ /* ID LED init */
+ mac->ops.id_led_init = e1000_id_led_init_generic;
/* setup LED */
mac->ops.setup_led = e1000_setup_led_82541;
/* cleanup LED */
@@ -381,7 +383,7 @@ static s32 e1000_init_hw_82541(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_hw_82541");
/* Initialize identification LED */
- ret_val = e1000_id_led_init_generic(hw);
+ ret_val = mac->ops.id_led_init(hw);
if (ret_val) {
DEBUGOUT("Error initializing identification LED\n");
/* This is not fatal and we should not stop init due to this */
diff --git a/sys/dev/e1000/e1000_82571.c b/sys/dev/e1000/e1000_82571.c
index db7852a..5d16136 100644
--- a/sys/dev/e1000/e1000_82571.c
+++ b/sys/dev/e1000/e1000_82571.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -46,6 +46,7 @@
* 82573E Gigabit Ethernet Controller (Copper)
* 82573L Gigabit Ethernet Controller
* 82574L Gigabit Network Connection
+ * 82574L Gigabit Network Connection
*/
#include "e1000_api.h"
@@ -67,11 +68,9 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw);
static void e1000_clear_vfta_82571(struct e1000_hw *hw);
static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
static s32 e1000_led_on_82574(struct e1000_hw *hw);
-static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count,
- u32 rar_used_count, u32 rar_count);
static s32 e1000_setup_link_82571(struct e1000_hw *hw);
static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw);
+static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw);
static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw);
static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data);
static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
@@ -330,7 +329,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
mac->ops.check_for_link = e1000_check_for_fiber_link_generic;
break;
case e1000_media_type_internal_serdes:
- mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
+ mac->ops.check_for_link = e1000_check_for_serdes_link_82571;
break;
default:
ret_val = -E1000_ERR_CONFIG;
@@ -347,7 +346,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
break;
}
/* multicast address update */
- mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_82571;
+ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
/* writing VFTA */
mac->ops.write_vfta = e1000_write_vfta_generic;
/* clearing VFTA */
@@ -356,6 +355,8 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
mac->ops.mta_set = e1000_mta_set_generic;
/* read mac address */
mac->ops.read_mac_addr = e1000_read_mac_addr_82571;
+ /* ID LED init */
+ mac->ops.id_led_init = e1000_id_led_init_generic;
/* blink LED */
mac->ops.blink_led = e1000_blink_led_generic;
/* setup LED */
@@ -528,8 +529,14 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
if (ret_val)
goto out;
- if (hw->mac.type != e1000_82573 && hw->mac.type != e1000_82574)
+ switch (hw->mac.type) {
+ case e1000_82574:
+ case e1000_82573:
+ break;
+ default:
ret_val = e1000_acquire_nvm_generic(hw);
+ break;
+ }
if (ret_val)
e1000_put_hw_semaphore_82571(hw);
@@ -876,7 +883,9 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
* Must acquire the MDIO ownership before MAC reset.
* Ownership defaults to firmware after a reset.
*/
- if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
+ switch (hw->mac.type) {
+ case e1000_82574:
+ case e1000_82573:
extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;
@@ -892,6 +901,9 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
msec_delay(2);
i++;
} while (i < MDIO_OWNERSHIP_TIMEOUT);
+ break;
+ default:
+ break;
}
ctrl = E1000_READ_REG(hw, E1000_CTRL);
@@ -917,15 +929,30 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
* Need to wait for Phy configuration completion before accessing
* NVM and Phy.
*/
- if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574)
+
+ switch (hw->mac.type) {
+ case e1000_82574:
+ case e1000_82573:
msec_delay(25);
+ break;
+ default:
+ break;
+ }
/* Clear any pending interrupt events. */
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
icr = E1000_READ_REG(hw, E1000_ICR);
- if (!(e1000_check_alt_mac_addr_generic(hw)))
- e1000_set_laa_state_82571(hw, TRUE);
+ /* Install any alternate MAC address into RAR0 */
+ ret_val = e1000_check_alt_mac_addr_generic(hw);
+ if (ret_val)
+ goto out;
+
+ e1000_set_laa_state_82571(hw, TRUE);
+
+ /* Reinitialize the 82571 serdes link state machine */
+ if (hw->phy.media_type == e1000_media_type_internal_serdes)
+ hw->mac.serdes_link_state = e1000_serdes_link_down;
out:
return ret_val;
@@ -949,7 +976,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
e1000_initialize_hw_bits_82571(hw);
/* Initialize identification LED */
- ret_val = e1000_id_led_init_generic(hw);
+ ret_val = mac->ops.id_led_init(hw);
if (ret_val) {
DEBUGOUT("Error initializing identification LED\n");
/* This is not fatal and we should not stop init due to this */
@@ -985,17 +1012,21 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
/* ...for both queues. */
- if (mac->type != e1000_82573 && mac->type != e1000_82574) {
- reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
- reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
- E1000_TXDCTL_FULL_TX_DESC_WB |
- E1000_TXDCTL_COUNT_DESC;
- E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
- } else {
+ switch (mac->type) {
+ case e1000_82574:
+ case e1000_82573:
e1000_enable_tx_pkt_filtering_generic(hw);
reg_data = E1000_READ_REG(hw, E1000_GCR);
reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX;
E1000_WRITE_REG(hw, E1000_GCR, reg_data);
+ break;
+ default:
+ reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
+ reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
+ E1000_TXDCTL_FULL_TX_DESC_WB |
+ E1000_TXDCTL_COUNT_DESC;
+ E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
+ break;
}
/*
@@ -1062,25 +1093,70 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
}
/* Device Control */
- if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
+
+ switch (hw->mac.type) {
+ case e1000_82574:
+ case e1000_82573:
reg = E1000_READ_REG(hw, E1000_CTRL);
reg &= ~(1 << 29);
E1000_WRITE_REG(hw, E1000_CTRL, reg);
+ break;
+ default:
+ break;
}
/* Extended Device Control */
- if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
+ switch (hw->mac.type) {
+ case e1000_82574:
+ case e1000_82573:
reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
reg &= ~(1 << 23);
reg |= (1 << 22);
E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
+ break;
+ default:
+ break;
}
- /* PCI-Ex Control Register */
- if (hw->mac.type == e1000_82574) {
+
+ if (hw->mac.type == e1000_82571) {
+ reg = E1000_READ_REG(hw, E1000_PBA_ECC);
+ reg |= E1000_PBA_ECC_CORR_EN;
+ E1000_WRITE_REG(hw, E1000_PBA_ECC, reg);
+ }
+
+ /*
+ * Workaround for hardware errata.
+ * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572
+ */
+
+ if ((hw->mac.type == e1000_82571) ||
+ (hw->mac.type == e1000_82572)) {
+ reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
+ reg &= ~E1000_CTRL_EXT_DMA_DYN_CLK_EN;
+ E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
+ }
+
+ /* PCI-Ex Control Registers */
+
+ switch (hw->mac.type) {
+ case e1000_82574:
reg = E1000_READ_REG(hw, E1000_GCR);
reg |= (1 << 22);
E1000_WRITE_REG(hw, E1000_GCR, reg);
+ /*
+ * Workaround for hardware errata.
+ * apply workaround for hardware errata documented in errata
+ * docs Fixes issue where some error prone or unreliable PCIe
+ * completions are occurring, particularly with ASPM enabled.
+ * Without fix, issue can cause tx timeouts.
+ */
+ reg = E1000_READ_REG(hw, E1000_GCR2);
+ reg |= 1;
+ E1000_WRITE_REG(hw, E1000_GCR2, reg);
+ break;
+ default:
+ break;
}
return;
@@ -1102,31 +1178,38 @@ static void e1000_clear_vfta_82571(struct e1000_hw *hw)
DEBUGFUNC("e1000_clear_vfta_82571");
- if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
+ switch (hw->mac.type) {
+ case e1000_82574:
+ case e1000_82573:
if (hw->mng_cookie.vlan_id != 0) {
/*
- * The VFTA is a 4096b bit-field, each identifying
- * a single VLAN ID. The following operations
- * determine which 32b entry (i.e. offset) into the
- * array we want to set the VLAN ID (i.e. bit) of
- * the manageability unit.
- */
+ *The VFTA is a 4096b bit-field, each identifying
+ *a single VLAN ID. The following operations
+ *determine which 32b entry (i.e. offset) into the
+ *array we want to set the VLAN ID (i.e. bit) of
+ *the manageability unit.
+ */
vfta_offset = (hw->mng_cookie.vlan_id >>
- E1000_VFTA_ENTRY_SHIFT) &
- E1000_VFTA_ENTRY_MASK;
+ E1000_VFTA_ENTRY_SHIFT) & E1000_VFTA_ENTRY_MASK;
vfta_bit_in_reg = 1 << (hw->mng_cookie.vlan_id &
- E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
+ E1000_VFTA_ENTRY_BIT_SHIFT_MASK);
}
- }
- for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
- /*
- * If the offset we want to clear is the same offset of the
- * manageability VLAN ID, then clear all bits except that of
- * the manageability unit.
- */
- vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0;
- E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, vfta_value);
- E1000_WRITE_FLUSH(hw);
+
+ for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
+ /*
+ *If the offset we want to clear is the same offset of
+ *the manageability VLAN ID, then clear all bits except
+ *that of the manageability unit
+ */
+ vfta_value = (offset == vfta_offset) ?
+ vfta_bit_in_reg : 0;
+ E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset,
+ vfta_value);
+ E1000_WRITE_FLUSH(hw);
+ }
+ break;
+ default:
+ break;
}
}
@@ -1176,31 +1259,6 @@ static s32 e1000_led_on_82574(struct e1000_hw *hw)
return E1000_SUCCESS;
}
-/**
- * e1000_update_mc_addr_list_82571 - Update Multicast addresses
- * @hw: pointer to the HW structure
- * @mc_addr_list: array of multicast addresses to program
- * @mc_addr_count: number of multicast addresses to program
- * @rar_used_count: the first RAR register free to program
- * @rar_count: total number of supported Receive Address Registers
- *
- * Updates the Receive Address Registers and Multicast Table Array.
- * The caller must have a packed mc_addr_list of multicast addresses.
- * The parameter rar_count will usually be hw->mac.rar_entry_count
- * unless there are workarounds that change this.
- **/
-static void e1000_update_mc_addr_list_82571(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count,
- u32 rar_used_count, u32 rar_count)
-{
- DEBUGFUNC("e1000_update_mc_addr_list_82571");
-
- if (e1000_get_laa_state_82571(hw))
- rar_count--;
-
- e1000_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count,
- rar_used_count, rar_count);
-}
/**
* e1000_setup_link_82571 - Setup flow control and link settings
@@ -1221,10 +1279,15 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
* the default flow control setting, so we explicitly
* set it to full.
*/
- if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
- hw->fc.requested_mode == e1000_fc_default)
- hw->fc.requested_mode = e1000_fc_full;
-
+ switch (hw->mac.type) {
+ case e1000_82574:
+ case e1000_82573:
+ if (hw->fc.requested_mode == e1000_fc_default)
+ hw->fc.requested_mode = e1000_fc_full;
+ break;
+ default:
+ break;
+ }
return e1000_setup_link_generic(hw);
}
@@ -1306,6 +1369,133 @@ static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw)
}
/**
+ * e1000_check_for_serdes_link_82571 - Check for link (Serdes)
+ * @hw: pointer to the HW structure
+ *
+ * Checks for link up on the hardware. If link is not up and we have
+ * a signal, then we need to force link up.
+ **/
+s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
+{
+ struct e1000_mac_info *mac = &hw->mac;
+ u32 rxcw;
+ u32 ctrl;
+ u32 status;
+ s32 ret_val = E1000_SUCCESS;
+
+ DEBUGFUNC("e1000_check_for_serdes_link_82571");
+
+ ctrl = E1000_READ_REG(hw, E1000_CTRL);
+ status = E1000_READ_REG(hw, E1000_STATUS);
+ rxcw = E1000_READ_REG(hw, E1000_RXCW);
+
+ if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) {
+
+ /* Receiver is synchronized with no invalid bits. */
+ switch (mac->serdes_link_state) {
+ case e1000_serdes_link_autoneg_complete:
+ if (!(status & E1000_STATUS_LU)) {
+ /*
+ * We have lost link, retry autoneg before
+ * reporting link failure
+ */
+ mac->serdes_link_state =
+ e1000_serdes_link_autoneg_progress;
+ DEBUGOUT("AN_UP -> AN_PROG\n");
+ }
+ break;
+
+ case e1000_serdes_link_forced_up:
+ /*
+ * If we are receiving /C/ ordered sets, re-enable
+ * auto-negotiation in the TXCW register and disable
+ * forced link in the Device Control register in an
+ * attempt to auto-negotiate with our link partner.
+ */
+ if (rxcw & E1000_RXCW_C) {
+ /* Enable autoneg, and unforce link up */
+ E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
+ E1000_WRITE_REG(hw, E1000_CTRL,
+ (ctrl & ~E1000_CTRL_SLU));
+ mac->serdes_link_state =
+ e1000_serdes_link_autoneg_progress;
+ DEBUGOUT("FORCED_UP -> AN_PROG\n");
+ }
+ break;
+
+ case e1000_serdes_link_autoneg_progress:
+ /*
+ * If the LU bit is set in the STATUS register,
+ * autoneg has completed sucessfully. If not,
+ * try foring the link because the far end may be
+ * available but not capable of autonegotiation.
+ */
+ if (status & E1000_STATUS_LU) {
+ mac->serdes_link_state =
+ e1000_serdes_link_autoneg_complete;
+ DEBUGOUT("AN_PROG -> AN_UP\n");
+ } else {
+ /*
+ * Disable autoneg, force link up and
+ * full duplex, and change state to forced
+ */
+ E1000_WRITE_REG(hw, E1000_TXCW,
+ (mac->txcw & ~E1000_TXCW_ANE));
+ ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD);
+ E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+
+ /* Configure Flow Control after link up. */
+ ret_val =
+ e1000_config_fc_after_link_up_generic(hw);
+ if (ret_val) {
+ DEBUGOUT("Error config flow control\n");
+ break;
+ }
+ mac->serdes_link_state =
+ e1000_serdes_link_forced_up;
+ DEBUGOUT("AN_PROG -> FORCED_UP\n");
+ }
+ mac->serdes_has_link = TRUE;
+ break;
+
+ case e1000_serdes_link_down:
+ default:
+ /* The link was down but the receiver has now gained
+ * valid sync, so lets see if we can bring the link
+ * up. */
+ E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
+ E1000_WRITE_REG(hw, E1000_CTRL,
+ (ctrl & ~E1000_CTRL_SLU));
+ mac->serdes_link_state =
+ e1000_serdes_link_autoneg_progress;
+ DEBUGOUT("DOWN -> AN_PROG\n");
+ break;
+ }
+ } else {
+ if (!(rxcw & E1000_RXCW_SYNCH)) {
+ mac->serdes_has_link = FALSE;
+ mac->serdes_link_state = e1000_serdes_link_down;
+ DEBUGOUT("ANYSTATE -> DOWN\n");
+ } else {
+ /*
+ * We have sync, and can tolerate one
+ * invalid (IV) codeword before declaring
+ * link down, so reread to look again
+ */
+ usec_delay(10);
+ rxcw = E1000_READ_REG(hw, E1000_RXCW);
+ if (rxcw & E1000_RXCW_IV) {
+ mac->serdes_link_state = e1000_serdes_link_down;
+ mac->serdes_has_link = FALSE;
+ DEBUGOUT("ANYSTATE -> DOWN\n");
+ }
+ }
+ }
+
+ return ret_val;
+}
+
+/**
* e1000_valid_led_default_82571 - Verify a valid default LED config
* @hw: pointer to the HW structure
* @data: pointer to the NVM (EEPROM)
@@ -1325,11 +1515,19 @@ static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data)
goto out;
}
- if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
- *data == ID_LED_RESERVED_F746)
- *data = ID_LED_DEFAULT_82573;
- else if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
- *data = ID_LED_DEFAULT;
+ switch (hw->mac.type) {
+ case e1000_82574:
+ case e1000_82573:
+ if(*data == ID_LED_RESERVED_F746)
+ *data = ID_LED_DEFAULT_82573;
+ break;
+ default:
+ if (*data == ID_LED_RESERVED_0000 ||
+ *data == ID_LED_RESERVED_FFFF)
+ *data = ID_LED_DEFAULT;
+ break;
+ }
+
out:
return ret_val;
}
@@ -1435,6 +1633,7 @@ out:
return ret_val;
}
+
/**
* e1000_read_mac_addr_82571 - Read device MAC address
* @hw: pointer to the HW structure
@@ -1444,9 +1643,19 @@ static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw)
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_read_mac_addr_82571");
- if (e1000_check_alt_mac_addr_generic(hw))
- ret_val = e1000_read_mac_addr_generic(hw);
+ /*
+ * If there's an alternate MAC address place it in RAR0
+ * so that it will override the Si installed default perm
+ * address.
+ */
+ ret_val = e1000_check_alt_mac_addr_generic(hw);
+ if (ret_val)
+ goto out;
+
+ ret_val = e1000_read_mac_addr_generic(hw);
+
+out:
return ret_val;
}
diff --git a/sys/dev/e1000/e1000_82575.c b/sys/dev/e1000/e1000_82575.c
index 3d16447..d7ed6c8 100644
--- a/sys/dev/e1000/e1000_82575.c
+++ b/sys/dev/e1000/e1000_82575.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,7 @@
* 82575EB Gigabit Network Connection
* 82575EB Gigabit Backplane Connection
* 82575GB Gigabit Network Connection
+ * 82575GB Gigabit Network Connection
* 82576 Gigabit Network Connection
*/
@@ -75,11 +76,6 @@ static bool e1000_sgmii_active_82575(struct e1000_hw *hw);
static s32 e1000_reset_init_script_82575(struct e1000_hw *hw);
static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw);
static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw);
-
-static void e1000_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count);
-static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count,
- u32 rar_used_count, u32 rar_count);
void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw);
/**
@@ -281,13 +277,15 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
/* read mac address */
mac->ops.read_mac_addr = e1000_read_mac_addr_82575;
/* multicast address update */
- mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_82575;
+ mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
/* writing VFTA */
mac->ops.write_vfta = e1000_write_vfta_generic;
/* clearing VFTA */
mac->ops.clear_vfta = e1000_clear_vfta_generic;
/* setting MTA */
mac->ops.mta_set = e1000_mta_set_generic;
+ /* ID LED init */
+ mac->ops.id_led_init = e1000_id_led_init_generic;
/* blink LED */
mac->ops.blink_led = e1000_blink_led_generic;
/* setup LED */
@@ -854,11 +852,18 @@ static s32 e1000_check_for_link_82575(struct e1000_hw *hw)
/* SGMII link check is done through the PCS register. */
if ((hw->phy.media_type != e1000_media_type_copper) ||
- (e1000_sgmii_active_82575(hw)))
+ (e1000_sgmii_active_82575(hw))) {
ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed,
&duplex);
- else
+ /*
+ * Use this flag to determine if link needs to be checked or
+ * not. If we have link clear the flag so that we do not
+ * continue to check for link.
+ */
+ hw->mac.get_link_status = !hw->mac.serdes_has_link;
+ } else {
ret_val = e1000_check_for_copper_link_generic(hw);
+ }
return ret_val;
}
@@ -921,101 +926,6 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
}
/**
- * e1000_init_rx_addrs_82575 - Initialize receive address's
- * @hw: pointer to the HW structure
- * @rar_count: receive address registers
- *
- * Setups the receive address registers by setting the base receive address
- * register to the devices MAC address and clearing all the other receive
- * address registers to 0.
- **/
-static void e1000_init_rx_addrs_82575(struct e1000_hw *hw, u16 rar_count)
-{
- u32 i;
- u8 addr[6] = {0,0,0,0,0,0};
- /*
- * This function is essentially the same as that of
- * e1000_init_rx_addrs_generic. However it also takes care
- * of the special case where the register offset of the
- * second set of RARs begins elsewhere. This is implicitly taken care by
- * function e1000_rar_set_generic.
- */
-
- DEBUGFUNC("e1000_init_rx_addrs_82575");
-
- /* Setup the receive address */
- DEBUGOUT("Programming MAC Address into RAR[0]\n");
- hw->mac.ops.rar_set(hw, hw->mac.addr, 0);
-
- /* Zero out the other (rar_entry_count - 1) receive addresses */
- DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1);
- for (i = 1; i < rar_count; i++) {
- hw->mac.ops.rar_set(hw, addr, i);
- }
-}
-
-/**
- * e1000_update_mc_addr_list_82575 - Update Multicast addresses
- * @hw: pointer to the HW structure
- * @mc_addr_list: array of multicast addresses to program
- * @mc_addr_count: number of multicast addresses to program
- * @rar_used_count: the first RAR register free to program
- * @rar_count: total number of supported Receive Address Registers
- *
- * Updates the Receive Address Registers and Multicast Table Array.
- * The caller must have a packed mc_addr_list of multicast addresses.
- * The parameter rar_count will usually be hw->mac.rar_entry_count
- * unless there are workarounds that change this.
- **/
-static void e1000_update_mc_addr_list_82575(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count,
- u32 rar_used_count, u32 rar_count)
-{
- u32 hash_value;
- u32 i;
- u8 addr[6] = {0,0,0,0,0,0};
- /*
- * This function is essentially the same as that of
- * e1000_update_mc_addr_list_generic. However it also takes care
- * of the special case where the register offset of the
- * second set of RARs begins elsewhere. This is implicitly taken care by
- * function e1000_rar_set_generic.
- */
-
- DEBUGFUNC("e1000_update_mc_addr_list_82575");
-
- /*
- * Load the first set of multicast addresses into the exact
- * filters (RAR). If there are not enough to fill the RAR
- * array, clear the filters.
- */
- for (i = rar_used_count; i < rar_count; i++) {
- if (mc_addr_count) {
- e1000_rar_set_generic(hw, mc_addr_list, i);
- mc_addr_count--;
- mc_addr_list += ETH_ADDR_LEN;
- } else {
- e1000_rar_set_generic(hw, addr, i);
- }
- }
-
- /* Clear the old settings from the MTA */
- DEBUGOUT("Clearing MTA\n");
- for (i = 0; i < hw->mac.mta_reg_count; i++) {
- E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
- E1000_WRITE_FLUSH(hw);
- }
-
- /* Load any remaining multicast addresses into the hash table. */
- for (; mc_addr_count > 0; mc_addr_count--) {
- hash_value = e1000_hash_mc_addr(hw, mc_addr_list);
- DEBUGOUT1("Hash value = 0x%03X\n", hash_value);
- hw->mac.ops.mta_set(hw, hash_value);
- mc_addr_list += ETH_ADDR_LEN;
- }
-}
-
-/**
* e1000_shutdown_fiber_serdes_link_82575 - Remove link during power down
* @hw: pointer to the HW structure
*
@@ -1060,6 +970,253 @@ void e1000_shutdown_fiber_serdes_link_82575(struct e1000_hw *hw)
}
/**
+ * e1000_vmdq_loopback_enable_pf- Enables VM to VM queue loopback replication
+ * @hw: pointer to the HW structure
+ **/
+void e1000_vmdq_loopback_enable_pf(struct e1000_hw *hw)
+{
+ u32 reg;
+
+ reg = E1000_READ_REG(hw, E1000_DTXSWC);
+ reg |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
+ E1000_WRITE_REG(hw, E1000_DTXSWC, reg);
+}
+
+/**
+ * e1000_vmdq_loopback_disable_pf - Disable VM to VM queue loopbk replication
+ * @hw: pointer to the HW structure
+ **/
+void e1000_vmdq_loopback_disable_pf(struct e1000_hw *hw)
+{
+ u32 reg;
+
+ reg = E1000_READ_REG(hw, E1000_DTXSWC);
+ reg &= ~(E1000_DTXSWC_VMDQ_LOOPBACK_EN);
+ E1000_WRITE_REG(hw, E1000_DTXSWC, reg);
+}
+
+/**
+ * e1000_vmdq_replication_enable_pf - Enable replication of brdcst & multicst
+ * @hw: pointer to the HW structure
+ *
+ * Enables replication of broadcast and multicast packets from the network
+ * to VM's which have their respective broadcast and multicast accept
+ * bits set in the VM Offload Register. This gives the PF driver per
+ * VM granularity control over which VM's get replicated broadcast traffic.
+ **/
+void e1000_vmdq_replication_enable_pf(struct e1000_hw *hw, u32 enables)
+{
+ u32 reg;
+ u32 i;
+
+ for (i = 0; i < MAX_NUM_VFS; i++) {
+ if (enables & (1 << i)) {
+ reg = E1000_READ_REG(hw, E1000_VMOLR(i));
+ reg |= (E1000_VMOLR_AUPE |
+ E1000_VMOLR_BAM |
+ E1000_VMOLR_MPME);
+ E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
+ }
+ }
+
+ reg = E1000_READ_REG(hw, E1000_VT_CTL);
+ reg |= E1000_VT_CTL_VM_REPL_EN;
+ E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
+}
+
+/**
+ * e1000_vmdq_replication_disable_pf - Disable replication of brdcst & multicst
+ * @hw: pointer to the HW structure
+ *
+ * Disables replication of broadcast and multicast packets to the VM's.
+ **/
+void e1000_vmdq_replication_disable_pf(struct e1000_hw *hw)
+{
+ u32 reg;
+
+ reg = E1000_READ_REG(hw, E1000_VT_CTL);
+ reg &= ~(E1000_VT_CTL_VM_REPL_EN);
+ E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
+}
+
+/**
+ * e1000_vmdq_enable_replication_mode_pf - Enables replication mode in the device
+ * @hw: pointer to the HW structure
+ **/
+void e1000_vmdq_enable_replication_mode_pf(struct e1000_hw *hw)
+{
+ u32 reg;
+
+ reg = E1000_READ_REG(hw, E1000_VT_CTL);
+ reg |= E1000_VT_CTL_VM_REPL_EN;
+ E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
+}
+
+/**
+ * e1000_vmdq_broadcast_replication_enable_pf - Enable replication of brdcst
+ * @hw: pointer to the HW structure
+ * @enables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
+ *
+ * Enables replication of broadcast packets from the network
+ * to VM's which have their respective broadcast accept
+ * bits set in the VM Offload Register. This gives the PF driver per
+ * VM granularity control over which VM's get replicated broadcast traffic.
+ **/
+void e1000_vmdq_broadcast_replication_enable_pf(struct e1000_hw *hw,
+ u32 enables)
+{
+ u32 reg;
+ u32 i;
+
+ for (i = 0; i < MAX_NUM_VFS; i++) {
+ if ((enables == ALL_QUEUES) || (enables & (1 << i))) {
+ reg = E1000_READ_REG(hw, E1000_VMOLR(i));
+ reg |= E1000_VMOLR_BAM;
+ E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
+ }
+ }
+}
+
+/**
+ * e1000_vmdq_broadcast_replication_disable_pf - Disable replication
+ * of broadcast packets
+ * @hw: pointer to the HW structure
+ * @disables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
+ *
+ * Disables replication of broadcast packets for specific pools.
+ * If bam/mpe is disabled on all pools then replication mode is
+ * turned off.
+ **/
+void e1000_vmdq_broadcast_replication_disable_pf(struct e1000_hw *hw,
+ u32 disables)
+{
+ u32 reg;
+ u32 i;
+ u32 oneenabled = 0;
+
+ for (i = 0; i < MAX_NUM_VFS; i++) {
+ reg = E1000_READ_REG(hw, E1000_VMOLR(i));
+ if ((disables == ALL_QUEUES) || (disables & (1 << i))) {
+ reg &= ~(E1000_VMOLR_BAM);
+ E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
+ }
+ if (!oneenabled && (reg & (E1000_VMOLR_AUPE |
+ E1000_VMOLR_BAM |
+ E1000_VMOLR_MPME)))
+ oneenabled = 1;
+ }
+ if (!oneenabled) {
+ reg = E1000_READ_REG(hw, E1000_VT_CTL);
+ reg &= ~(E1000_VT_CTL_VM_REPL_EN);
+ E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
+ }
+}
+
+/**
+ * e1000_vmdq_multicast_promiscuous_enable_pf - Enable promiscuous reception
+ * @hw: pointer to the HW structure
+ * @enables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
+ *
+ * Enables promiscuous reception of multicast packets from the network
+ * to VM's which have their respective multicast promiscuous mode enable
+ * bits set in the VM Offload Register. This gives the PF driver per
+ * VM granularity control over which VM's get all multicast traffic.
+ **/
+void e1000_vmdq_multicast_promiscuous_enable_pf(struct e1000_hw *hw,
+ u32 enables)
+{
+ u32 reg;
+ u32 i;
+
+ for (i = 0; i < MAX_NUM_VFS; i++) {
+ if ((enables == ALL_QUEUES) || (enables & (1 << i))) {
+ reg = E1000_READ_REG(hw, E1000_VMOLR(i));
+ reg |= E1000_VMOLR_MPME;
+ E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
+ }
+ }
+}
+
+/**
+ * e1000_vmdq_multicast_promiscuous_disable_pf - Disable promiscuous
+ * reception of multicast packets
+ * @hw: pointer to the HW structure
+ * @disables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
+ *
+ * Disables promiscuous reception of multicast packets for specific pools.
+ * If bam/mpe is disabled on all pools then replication mode is
+ * turned off.
+ **/
+void e1000_vmdq_multicast_promiscuous_disable_pf(struct e1000_hw *hw,
+ u32 disables)
+{
+ u32 reg;
+ u32 i;
+ u32 oneenabled = 0;
+
+ for (i = 0; i < MAX_NUM_VFS; i++) {
+ reg = E1000_READ_REG(hw, E1000_VMOLR(i));
+ if ((disables == ALL_QUEUES) || (disables & (1 << i))) {
+ reg &= ~(E1000_VMOLR_MPME);
+ E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
+ }
+ if (!oneenabled && (reg & (E1000_VMOLR_AUPE |
+ E1000_VMOLR_BAM |
+ E1000_VMOLR_MPME)))
+ oneenabled = 1;
+ }
+ if (!oneenabled) {
+ reg = E1000_READ_REG(hw, E1000_VT_CTL);
+ reg &= ~(E1000_VT_CTL_VM_REPL_EN);
+ E1000_WRITE_REG(hw, E1000_VT_CTL, reg);
+ }
+}
+
+/**
+ * e1000_vmdq_aupe_enable_pf - Enable acceptance of untagged packets
+ * @hw: pointer to the HW structure
+ * @enables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
+ *
+ * Enables acceptance of packets from the network which do not have
+ * a VLAN tag but match the exact MAC filter of a given VM.
+ **/
+void e1000_vmdq_aupe_enable_pf(struct e1000_hw *hw, u32 enables)
+{
+ u32 reg;
+ u32 i;
+
+ for (i = 0; i < MAX_NUM_VFS; i++) {
+ if ((enables == ALL_QUEUES) || (enables & (1 << i))) {
+ reg = E1000_READ_REG(hw, E1000_VMOLR(i));
+ reg |= E1000_VMOLR_AUPE;
+ E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
+ }
+ }
+}
+
+/**
+ * e1000_vmdq_aupe_disable_pf - Disable acceptance of untagged packets
+ * @hw: pointer to the HW structure
+ * @disables: PoolSet Bit - if set to ALL_QUEUES, apply to all pools.
+ *
+ * Disables acceptance of packets from the network which do not have
+ * a VLAN tag but match the exact MAC filter of a given VM.
+ **/
+void e1000_vmdq_aupe_disable_pf(struct e1000_hw *hw, u32 disables)
+{
+ u32 reg;
+ u32 i;
+
+ for (i = 0; i < MAX_NUM_VFS; i++) {
+ if ((disables == ALL_QUEUES) || (disables & (1 << i))) {
+ reg = E1000_READ_REG(hw, E1000_VMOLR(i));
+ reg &= ~E1000_VMOLR_AUPE;
+ E1000_WRITE_REG(hw, E1000_VMOLR(i), reg);
+ }
+ }
+}
+
+/**
* e1000_reset_hw_82575 - Reset hardware
* @hw: pointer to the HW structure
*
@@ -1113,7 +1270,8 @@ static s32 e1000_reset_hw_82575(struct e1000_hw *hw)
E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
icr = E1000_READ_REG(hw, E1000_ICR);
- e1000_check_alt_mac_addr_generic(hw);
+ /* Install any alternate MAC address into RAR0 */
+ ret_val = e1000_check_alt_mac_addr_generic(hw);
return ret_val;
}
@@ -1133,7 +1291,7 @@ static s32 e1000_init_hw_82575(struct e1000_hw *hw)
DEBUGFUNC("e1000_init_hw_82575");
/* Initialize identification LED */
- ret_val = e1000_id_led_init_generic(hw);
+ ret_val = mac->ops.id_led_init(hw);
if (ret_val) {
DEBUGOUT("Error initializing identification LED\n");
/* This is not fatal and we should not stop init due to this */
@@ -1144,7 +1302,8 @@ static s32 e1000_init_hw_82575(struct e1000_hw *hw)
mac->ops.clear_vfta(hw);
/* Setup the receive address */
- e1000_init_rx_addrs_82575(hw, rar_count);
+ e1000_init_rx_addrs_generic(hw, rar_count);
+
/* Zero out the Multicast HASH table */
DEBUGOUT("Zeroing the MTA\n");
for (i = 0; i < mac->mta_reg_count; i++)
@@ -1502,9 +1661,19 @@ static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw)
s32 ret_val = E1000_SUCCESS;
DEBUGFUNC("e1000_read_mac_addr_82575");
- if (e1000_check_alt_mac_addr_generic(hw))
- ret_val = e1000_read_mac_addr_generic(hw);
+ /*
+ * If there's an alternate MAC address place it in RAR0
+ * so that it will override the Si installed default perm
+ * address.
+ */
+ ret_val = e1000_check_alt_mac_addr_generic(hw);
+ if (ret_val)
+ goto out;
+
+ ret_val = e1000_read_mac_addr_generic(hw);
+
+out:
return ret_val;
}
diff --git a/sys/dev/e1000/e1000_82575.h b/sys/dev/e1000/e1000_82575.h
index 56321e4..1b7ce89 100644
--- a/sys/dev/e1000/e1000_82575.h
+++ b/sys/dev/e1000/e1000_82575.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -128,6 +128,7 @@ struct e1000_adv_context_desc {
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION 0x06000000
#define E1000_SRRCTL_DESCTYPE_HDR_REPLICATION_LARGE_PKT 0x08000000
#define E1000_SRRCTL_DESCTYPE_MASK 0x0E000000
+#define E1000_SRRCTL_DROP_EN 0x80000000
#define E1000_SRRCTL_BSIZEPKT_MASK 0x0000007F
#define E1000_SRRCTL_BSIZEHDR_MASK 0x00003F00
@@ -137,6 +138,7 @@ struct e1000_adv_context_desc {
#define E1000_MRQC_ENABLE_RSS_4Q 0x00000002
#define E1000_MRQC_ENABLE_VMDQ 0x00000003
+#define E1000_MRQC_ENABLE_VMDQ_RSS_2Q 0x00000005
#define E1000_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
#define E1000_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
#define E1000_MRQC_RSS_FIELD_IPV6_UDP_EX 0x01000000
@@ -313,6 +315,7 @@ struct e1000_adv_tx_context_desc {
#define E1000_ADVTXD_TUCMD_IPV6 0x00000000 /* IP Packet Type: 0=IPv6 */
#define E1000_ADVTXD_TUCMD_L4T_UDP 0x00000000 /* L4 Packet TYPE of UDP */
#define E1000_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
+#define E1000_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */
#define E1000_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */
/* IPSec Encrypt Enable for ESP */
#define E1000_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000
@@ -381,6 +384,8 @@ struct e1000_adv_tx_context_desc {
#define E1000_DTXSWC_MAC_SPOOF_MASK 0x000000FF /* Per VF MAC spoof control */
#define E1000_DTXSWC_VLAN_SPOOF_MASK 0x0000FF00 /* Per VF VLAN spoof control */
#define E1000_DTXSWC_LLE_MASK 0x00FF0000 /* Per VF Local LB enables */
+#define E1000_DTXSWC_VLAN_SPOOF_SHIFT 8
+#define E1000_DTXSWC_LLE_SHIFT 16
#define E1000_DTXSWC_VMDQ_LOOPBACK_EN (1 << 31) /* global VF LB enable */
/* Easy defines for setting default pool, would normally be left a zero */
@@ -393,82 +398,44 @@ struct e1000_adv_tx_context_desc {
#define E1000_VT_CTL_VM_REPL_EN (1 << 30)
/* Per VM Offload register setup */
+#define E1000_VMOLR_RLPML_MASK 0x00003FFF /* Long Packet Maximum Length mask */
#define E1000_VMOLR_LPE 0x00010000 /* Accept Long packet */
+#define E1000_VMOLR_RSSE 0x00020000 /* Enable RSS */
#define E1000_VMOLR_AUPE 0x01000000 /* Accept untagged packets */
+#define E1000_VMOLR_ROMPE 0x02000000 /* Accept overflow multicast */
+#define E1000_VMOLR_ROPE 0x04000000 /* Accept overflow unicast */
#define E1000_VMOLR_BAM 0x08000000 /* Accept Broadcast packets */
#define E1000_VMOLR_MPME 0x10000000 /* Multicast promiscuous mode */
#define E1000_VMOLR_STRVLAN 0x40000000 /* Vlan stripping enable */
+#define E1000_VMOLR_STRCRC 0x80000000 /* CRC stripping enable */
-#define E1000_V2PMAILBOX_REQ 0x00000001 /* Request for PF Ready bit */
-#define E1000_V2PMAILBOX_ACK 0x00000002 /* Ack PF message received */
-#define E1000_V2PMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
-#define E1000_V2PMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
-#define E1000_V2PMAILBOX_PFSTS 0x00000010 /* PF wrote a message in the MB */
-#define E1000_V2PMAILBOX_PFACK 0x00000020 /* PF ack the previous VF msg */
-#define E1000_V2PMAILBOX_RSTI 0x00000040 /* PF has reset indication */
-
-#define E1000_P2VMAILBOX_STS 0x00000001 /* Initiate message send to VF */
-#define E1000_P2VMAILBOX_ACK 0x00000002 /* Ack message recv'd from VF */
-#define E1000_P2VMAILBOX_VFU 0x00000004 /* VF owns the mailbox buffer */
-#define E1000_P2VMAILBOX_PFU 0x00000008 /* PF owns the mailbox buffer */
-#define E1000_P2VMAILBOX_RVFU 0x00000010 /* Reset VFU - used when VF stuck */
-
-#define E1000_VFMAILBOX_SIZE 16 /* 16 32 bit words - 64 bytes */
-
-/* If it's a E1000_VF_* msg then it originates in the VF and is sent to the
- * PF. The reverse is TRUE if it is E1000_PF_*.
- * Message ACK's are the value or'd with 0xF0000000
- */
-#define E1000_VT_MSGTYPE_ACK 0xF0000000 /* Messages below or'd with
- * this are the ACK */
-#define E1000_VT_MSGTYPE_NACK 0xFF000000 /* Messages below or'd with
- * this are the NACK */
-#define E1000_VT_MSGINFO_SHIFT 16
-/* bits 23:16 are used for exra info for certain messages */
-#define E1000_VT_MSGINFO_MASK (0xFF << E1000_VT_MSGINFO_SHIFT)
-
-#define E1000_VF_MSGTYPE_REQ_MAC 1 /* VF needs to know its MAC */
-#define E1000_VF_MSGTYPE_VFLR 2 /* VF notifies VFLR to PF */
-#define E1000_VF_SET_MULTICAST 3 /* VF requests PF to set MC addr */
-#define E1000_VF_SET_VLAN 4 /* VF requests PF to set VLAN */
-
-/* Add 100h to all PF msgs, leaves room for up to 255 discrete message types
- * from VF to PF - way more than we'll ever need */
-#define E1000_PF_MSGTYPE_RESET (1 + 0x100) /* PF notifies global reset
- * imminent to VF */
-#define E1000_PF_MSGTYPE_LSC (2 + 0x100) /* PF notifies VF of LSC... VF
- * will see extra msg info for
- * status */
-
-#define E1000_PF_MSG_LSCDOWN (1 << E1000_VT_MSGINFO_SHIFT)
-#define E1000_PF_MSG_LSCUP (2 << E1000_VT_MSGINFO_SHIFT)
+#define E1000_VLVF_ARRAY_SIZE 32
+#define E1000_VLVF_VLANID_MASK 0x00000FFF
+#define E1000_VLVF_POOLSEL_SHIFT 12
+#define E1000_VLVF_POOLSEL_MASK (0xFF << E1000_VLVF_POOLSEL_SHIFT)
+#define E1000_VLVF_LVLAN 0x00100000
+#define E1000_VLVF_VLANID_ENABLE 0x80000000
+
+#define E1000_VF_INIT_TIMEOUT 200 /* Number of retries to clear RSTI */
+
+#define E1000_IOVCTL 0x05BBC
+#define E1000_IOVCTL_REUSE_VFQ 0x00000001
#define ALL_QUEUES 0xFFFF
-s32 e1000_send_mail_to_pf_vf(struct e1000_hw *hw, u32 *msg,
- s16 size);
-s32 e1000_receive_mail_from_pf_vf(struct e1000_hw *hw,
- u32 *msg, s16 size);
-s32 e1000_send_mail_to_vf(struct e1000_hw *hw, u32 *msg,
- u32 vf_number, s16 size);
-s32 e1000_receive_mail_from_vf(struct e1000_hw *hw, u32 *msg,
- u32 vf_number, s16 size);
-void e1000_vmdq_loopback_enable_vf(struct e1000_hw *hw);
-void e1000_vmdq_loopback_disable_vf(struct e1000_hw *hw);
-void e1000_vmdq_replication_enable_vf(struct e1000_hw *hw, u32 enables);
-void e1000_vmdq_replication_disable_vf(struct e1000_hw *hw);
-void e1000_vmdq_enable_replication_mode_vf(struct e1000_hw *hw);
-void e1000_vmdq_broadcast_replication_enable_vf(struct e1000_hw *hw,
+void e1000_vmdq_loopback_enable_pf(struct e1000_hw *hw);
+void e1000_vmdq_loopback_disable_pf(struct e1000_hw *hw);
+void e1000_vmdq_replication_enable_pf(struct e1000_hw *hw, u32 enables);
+void e1000_vmdq_replication_disable_pf(struct e1000_hw *hw);
+void e1000_vmdq_enable_replication_mode_pf(struct e1000_hw *hw);
+void e1000_vmdq_broadcast_replication_enable_pf(struct e1000_hw *hw,
u32 enables);
-void e1000_vmdq_multicast_replication_enable_vf(struct e1000_hw *hw,
+void e1000_vmdq_multicast_promiscuous_enable_pf(struct e1000_hw *hw,
u32 enables);
-void e1000_vmdq_broadcast_replication_disable_vf(struct e1000_hw *hw,
+void e1000_vmdq_broadcast_replication_disable_pf(struct e1000_hw *hw,
u32 disables);
-void e1000_vmdq_multicast_replication_disable_vf(struct e1000_hw *hw,
+void e1000_vmdq_multicast_promiscuous_disable_pf(struct e1000_hw *hw,
u32 disables);
-bool e1000_check_for_pf_ack_vf(struct e1000_hw *hw);
-
-bool e1000_check_for_pf_mail_vf(struct e1000_hw *hw, u32*);
-
-
-#endif
+void e1000_vmdq_aupe_enable_pf(struct e1000_hw *hw, u32 enables);
+void e1000_vmdq_aupe_disable_pf(struct e1000_hw *hw, u32 disables);
+#endif /* _E1000_82575_H_ */
diff --git a/sys/dev/e1000/e1000_api.c b/sys/dev/e1000/e1000_api.c
index 47bffb5..1f47d34 100644
--- a/sys/dev/e1000/e1000_api.c
+++ b/sys/dev/e1000/e1000_api.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -112,6 +112,7 @@ out:
return ret_val;
}
+
/**
* e1000_set_mac_type - Sets MAC type
* @hw: pointer to the HW structure
@@ -250,12 +251,14 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
case E1000_DEV_ID_82575EB_COPPER:
case E1000_DEV_ID_82575EB_FIBER_SERDES:
case E1000_DEV_ID_82575GB_QUAD_COPPER:
+ case E1000_DEV_ID_82575GB_QUAD_COPPER_PM:
mac->type = e1000_82575;
break;
case E1000_DEV_ID_82576:
case E1000_DEV_ID_82576_FIBER:
case E1000_DEV_ID_82576_SERDES:
case E1000_DEV_ID_82576_QUAD_COPPER:
+ case E1000_DEV_ID_82576_NS:
mac->type = e1000_82576;
break;
default:
@@ -370,7 +373,6 @@ s32 e1000_setup_init_funcs(struct e1000_hw *hw, bool init_device)
ret_val = e1000_init_phy_params(hw);
if (ret_val)
goto out;
-
}
out:
@@ -426,26 +428,16 @@ void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value)
* @hw: pointer to the HW structure
* @mc_addr_list: array of multicast addresses to program
* @mc_addr_count: number of multicast addresses to program
- * @rar_used_count: the first RAR register free to program
- * @rar_count: total number of supported Receive Address Registers
*
- * Updates the Receive Address Registers and Multicast Table Array.
+ * Updates the Multicast Table Array.
* The caller must have a packed mc_addr_list of multicast addresses.
- * The parameter rar_count will usually be hw->mac.rar_entry_count
- * unless there are workarounds that change this. Currently no func pointer
- * exists and all implementations are handled in the generic version of this
- * function.
**/
void e1000_update_mc_addr_list(struct e1000_hw *hw, u8 *mc_addr_list,
- u32 mc_addr_count, u32 rar_used_count,
- u32 rar_count)
+ u32 mc_addr_count)
{
if (hw->mac.ops.update_mc_addr_list)
- hw->mac.ops.update_mc_addr_list(hw,
- mc_addr_list,
- mc_addr_count,
- rar_used_count,
- rar_count);
+ hw->mac.ops.update_mc_addr_list(hw, mc_addr_list,
+ mc_addr_count);
}
/**
@@ -617,6 +609,21 @@ s32 e1000_blink_led(struct e1000_hw *hw)
}
/**
+ * e1000_id_led_init - store LED configurations in SW
+ * @hw: pointer to the HW structure
+ *
+ * Initializes the LED config in SW. This is a function pointer entry point
+ * called by drivers.
+ **/
+s32 e1000_id_led_init(struct e1000_hw *hw)
+{
+ if (hw->mac.ops.id_led_init)
+ return hw->mac.ops.id_led_init(hw);
+
+ return E1000_SUCCESS;
+}
+
+/**
* e1000_led_on - Turn on SW controllable LED
* @hw: pointer to the HW structure
*
diff --git a/sys/dev/e1000/e1000_api.h b/sys/dev/e1000/e1000_api.h
index 4629ff0..b492e57 100644
--- a/sys/dev/e1000/e1000_api.h
+++ b/sys/dev/e1000/e1000_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -70,14 +70,14 @@ void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index);
void e1000_mta_set(struct e1000_hw *hw, u32 hash_value);
u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr);
void e1000_update_mc_addr_list(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count,
- u32 rar_used_count, u32 rar_count);
+ u8 *mc_addr_list, u32 mc_addr_count);
s32 e1000_setup_led(struct e1000_hw *hw);
s32 e1000_cleanup_led(struct e1000_hw *hw);
s32 e1000_check_reset_block(struct e1000_hw *hw);
s32 e1000_blink_led(struct e1000_hw *hw);
s32 e1000_led_on(struct e1000_hw *hw);
s32 e1000_led_off(struct e1000_hw *hw);
+s32 e1000_id_led_init(struct e1000_hw *hw);
void e1000_reset_adaptive(struct e1000_hw *hw);
void e1000_update_adaptive(struct e1000_hw *hw);
s32 e1000_get_cable_length(struct e1000_hw *hw);
diff --git a/sys/dev/e1000/e1000_defines.h b/sys/dev/e1000/e1000_defines.h
index 81259a1..1f6c198 100644
--- a/sys/dev/e1000/e1000_defines.h
+++ b/sys/dev/e1000/e1000_defines.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -144,6 +144,7 @@
#define E1000_CTRL_EXT_PFRSTD 0x00004000
#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
+#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000
@@ -162,8 +163,6 @@
#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */
/* IAME enable bit (27) was removed in >= 82575 */
#define E1000_CTRL_EXT_IAME 0x08000000 /* Int acknowledge Auto-mask */
-#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers
- * after IMS clear */
#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error
* detection enabled */
#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity
@@ -402,6 +401,7 @@
#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */
#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */
#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */
+#define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */
#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */
#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */
#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */
@@ -692,14 +692,19 @@
/* PBA constants */
#define E1000_PBA_6K 0x0006 /* 6KB */
#define E1000_PBA_8K 0x0008 /* 8KB */
+#define E1000_PBA_10K 0x000A /* 10KB */
#define E1000_PBA_12K 0x000C /* 12KB */
+#define E1000_PBA_14K 0x000E /* 14KB */
#define E1000_PBA_16K 0x0010 /* 16KB */
+#define E1000_PBA_18K 0x0012
#define E1000_PBA_20K 0x0014
#define E1000_PBA_22K 0x0016
#define E1000_PBA_24K 0x0018
+#define E1000_PBA_26K 0x001A
#define E1000_PBA_30K 0x001E
#define E1000_PBA_32K 0x0020
#define E1000_PBA_34K 0x0022
+#define E1000_PBA_35K 0x0023
#define E1000_PBA_38K 0x0026
#define E1000_PBA_40K 0x0028
#define E1000_PBA_48K 0x0030 /* 48KB */
@@ -761,6 +766,13 @@
#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */
#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */
+/* PBA ECC Register */
+#define E1000_PBA_ECC_COUNTER_MASK 0xFFF00000 /* ECC counter mask */
+#define E1000_PBA_ECC_COUNTER_SHIFT 20 /* ECC counter shift value */
+#define E1000_PBA_ECC_CORR_EN 0x00000001 /* Enable ECC error correction */
+#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */
+#define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 on ECC error */
+
/* Extended Interrupt Cause Read */
#define E1000_EICR_RX_QUEUE0 0x00000001 /* Rx Queue 0 Interrupt */
#define E1000_EICR_RX_QUEUE1 0x00000002 /* Rx Queue 1 Interrupt */
@@ -906,6 +918,8 @@
#define E1000_EICS_TCP_TIMER E1000_EICR_TCP_TIMER /* TCP Timer */
#define E1000_EICS_OTHER E1000_EICR_OTHER /* Interrupt Cause Active */
+#define E1000_EITR_ITR_INT_MASK 0x0000FFFF
+
/* Transmit Descriptor Control */
#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
@@ -936,6 +950,10 @@
*/
#define E1000_RAR_ENTRIES 15
#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */
+#define E1000_RAL_MAC_ADDR_LEN 4
+#define E1000_RAH_MAC_ADDR_LEN 2
+#define E1000_RAH_POOL_MASK 0x03FC0000
+#define E1000_RAH_POOL_1 0x00040000
/* Error Codes */
#define E1000_SUCCESS 0
@@ -951,6 +969,7 @@
#define E1000_BLK_PHY_RESET 12
#define E1000_ERR_SWFW_SYNC 13
#define E1000_NOT_IMPLEMENTED 14
+#define E1000_ERR_MBX 15
/* Loop limit on how long we wait for auto-negotiation to complete */
#define FIBER_LINK_UP_LIMIT 50
@@ -1145,6 +1164,7 @@
#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */
#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
#define E1000_EECD_SECVAL_SHIFT 22
+#define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES)
#define E1000_NVM_SWDPIN0 0x0001 /* SWDPIN 0 NVM Value */
#define E1000_NVM_LED_LOGIC 0x0020 /* Led Logic Word */
diff --git a/sys/dev/e1000/e1000_hw.h b/sys/dev/e1000/e1000_hw.h
index 277d8d1..d92ea40 100644
--- a/sys/dev/e1000/e1000_hw.h
+++ b/sys/dev/e1000/e1000_hw.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -94,6 +94,7 @@ struct e1000_hw;
#define E1000_DEV_ID_82573E_IAMT 0x108C
#define E1000_DEV_ID_82573L 0x109A
#define E1000_DEV_ID_82574L 0x10D3
+#define E1000_DEV_ID_82574LA 0x10F6
#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096
#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098
#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA
@@ -123,10 +124,11 @@ struct e1000_hw;
#define E1000_DEV_ID_82576_FIBER 0x10E6
#define E1000_DEV_ID_82576_SERDES 0x10E7
#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8
-#define E1000_DEV_ID_82576_VF 0x10CA
+#define E1000_DEV_ID_82576_NS 0x150A
#define E1000_DEV_ID_82575EB_COPPER 0x10A7
#define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9
#define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6
+#define E1000_DEV_ID_82575GB_QUAD_COPPER_PM 0x10E2
#define E1000_REVISION_0 0
#define E1000_REVISION_1 1
#define E1000_REVISION_2 2
@@ -136,6 +138,9 @@ struct e1000_hw;
#define E1000_FUNC_0 0
#define E1000_FUNC_1 1
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0
+#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3
+
enum e1000_mac_type {
e1000_undefined = 0,
e1000_82542,
@@ -160,7 +165,6 @@ enum e1000_mac_type {
e1000_ich10lan,
e1000_82575,
e1000_82576,
- e1000_vfadapt,
e1000_num_macs /* List is 1-based, so subtract 1 for TRUE count. */
};
@@ -279,6 +283,13 @@ enum e1000_smart_speed {
e1000_smart_speed_off
};
+enum e1000_serdes_link_state {
+ e1000_serdes_link_down = 0,
+ e1000_serdes_link_autoneg_progress,
+ e1000_serdes_link_autoneg_complete,
+ e1000_serdes_link_forced_up
+};
+
/* Receive Descriptor */
struct e1000_rx_desc {
__le64 buffer_addr; /* Address of the descriptor's data buffer */
@@ -496,37 +507,6 @@ struct e1000_hw_stats {
u64 doosync;
};
-struct e1000_vf_stats {
- u64 base_gprc;
- u64 base_gptc;
- u64 base_gorc;
- u64 base_gotc;
- u64 base_mprc;
- u64 base_gotlbc;
- u64 base_gptlbc;
- u64 base_gorlbc;
- u64 base_gprlbc;
-
- u32 last_gprc;
- u32 last_gptc;
- u32 last_gorc;
- u32 last_gotc;
- u32 last_mprc;
- u32 last_gotlbc;
- u32 last_gptlbc;
- u32 last_gorlbc;
- u32 last_gprlbc;
-
- u64 gprc;
- u64 gptc;
- u64 gorc;
- u64 gotc;
- u64 mprc;
- u64 gotlbc;
- u64 gptlbc;
- u64 gorlbc;
- u64 gprlbc;
-};
struct e1000_phy_stats {
u32 idle_errors;
@@ -581,6 +561,7 @@ struct e1000_host_mng_command_info {
struct e1000_mac_operations {
/* Function pointers for the MAC. */
s32 (*init_params)(struct e1000_hw *);
+ s32 (*id_led_init)(struct e1000_hw *);
s32 (*blink_led)(struct e1000_hw *);
s32 (*check_for_link)(struct e1000_hw *);
bool (*check_mng_mode)(struct e1000_hw *hw);
@@ -592,7 +573,7 @@ struct e1000_mac_operations {
s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *);
s32 (*led_on)(struct e1000_hw *);
s32 (*led_off)(struct e1000_hw *);
- void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32, u32, u32);
+ void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32);
s32 (*reset_hw)(struct e1000_hw *);
s32 (*init_hw)(struct e1000_hw *);
void (*shutdown_serdes)(struct e1000_hw *);
@@ -666,6 +647,10 @@ struct e1000_mac_info {
u16 ifs_ratio;
u16 ifs_step_size;
u16 mta_reg_count;
+#define MAX_MTA_REG 128 /* this must be the maximum size of the MTA register
+ * table in all supported adapters
+ */
+ u32 mta_shadow[MAX_MTA_REG];
u16 rar_entry_count;
u8 forced_speed_duplex;
@@ -678,6 +663,7 @@ struct e1000_mac_info {
bool get_link_status;
bool in_ifs_mode;
bool report_tx_early;
+ enum e1000_serdes_link_state serdes_link_state;
bool serdes_has_link;
bool tx_pkt_filtering;
};
@@ -785,12 +771,15 @@ struct e1000_dev_spec_ich8lan {
struct e1000_dev_spec_82575 {
bool sgmii_active;
+ bool global_device_reset;
};
struct e1000_dev_spec_vf {
u32 vf_number;
+ u32 v2p_mailbox;
};
+
struct e1000_hw {
void *back;
diff --git a/sys/dev/e1000/e1000_ich8lan.c b/sys/dev/e1000/e1000_ich8lan.c
index f368998..1225e55 100644
--- a/sys/dev/e1000/e1000_ich8lan.c
+++ b/sys/dev/e1000/e1000_ich8lan.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -197,7 +197,7 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
phy->ops.read_reg = e1000_read_phy_reg_bm;
ret_val = e1000_determine_phy_address(hw);
if (ret_val) {
- DEBUGOUT("Cannot determine PHY address. Erroring out\n");
+ DEBUGOUT("Cannot determine PHY addr. Erroring out\n");
goto out;
}
}
@@ -319,6 +319,9 @@ out:
static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
{
struct e1000_mac_info *mac = &hw->mac;
+#if defined(NAHUM4) && !defined(NO_PCH_A_SUPPORT)
+ u16 pci_cfg;
+#endif
DEBUGFUNC("e1000_init_mac_params_ich8lan");
@@ -360,18 +363,30 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
/* setting MTA */
mac->ops.mta_set = e1000_mta_set_generic;
- /* blink LED */
- mac->ops.blink_led = e1000_blink_led_generic;
- /* setup LED */
- mac->ops.setup_led = e1000_setup_led_generic;
- /* cleanup LED */
- mac->ops.cleanup_led = e1000_cleanup_led_ich8lan;
- /* turn on/off LED */
- mac->ops.led_on = e1000_led_on_ich8lan;
- mac->ops.led_off = e1000_led_off_ich8lan;
/* clear hardware counters */
mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan;
+ /* LED operations */
+ switch (mac->type) {
+ case e1000_ich8lan:
+ case e1000_ich9lan:
+ case e1000_ich10lan:
+ /* ID LED init */
+ mac->ops.id_led_init = e1000_id_led_init_generic;
+ /* blink LED */
+ mac->ops.blink_led = e1000_blink_led_generic;
+ /* setup LED */
+ mac->ops.setup_led = e1000_setup_led_generic;
+ /* cleanup LED */
+ mac->ops.cleanup_led = e1000_cleanup_led_ich8lan;
+ /* turn on/off LED */
+ mac->ops.led_on = e1000_led_on_ich8lan;
+ mac->ops.led_off = e1000_led_off_ich8lan;
+ break;
+ default:
+ break;
+ }
+
/* Enable PCS Lock-loss workaround for ICH8 */
if (mac->type == e1000_ich8lan)
e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, TRUE);
@@ -993,48 +1008,65 @@ out:
* @bank: pointer to the variable that returns the active bank
*
* Reads signature byte from the NVM using the flash access registers.
+ * Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank.
**/
static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
{
- s32 ret_val = E1000_SUCCESS;
+ u32 eecd;
struct e1000_nvm_info *nvm = &hw->nvm;
- /* flash bank size is in words */
u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
- u8 bank_high_byte = 0;
+ u8 sig_byte = 0;
+ s32 ret_val = E1000_SUCCESS;
- if (hw->mac.type != e1000_ich10lan) {
- if (E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_SEC1VAL)
- *bank = 1;
- else
- *bank = 0;
- } else {
- /*
- * Make sure the signature for bank 0 is valid,
- * if not check for bank1
- */
- e1000_read_flash_byte_ich8lan(hw, act_offset, &bank_high_byte);
- if ((bank_high_byte & 0xC0) == 0x80) {
+ switch (hw->mac.type) {
+ case e1000_ich8lan:
+ case e1000_ich9lan:
+ eecd = E1000_READ_REG(hw, E1000_EECD);
+ if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) ==
+ E1000_EECD_SEC1VAL_VALID_MASK) {
+ if (eecd & E1000_EECD_SEC1VAL)
+ *bank = 1;
+ else
+ *bank = 0;
+
+ goto out;
+ }
+ DEBUGOUT("Unable to determine valid NVM bank via EEC - "
+ "reading flash signature\n");
+ /* fall-thru */
+ default:
+ /* set bank to 0 in case flash read fails */
+ *bank = 0;
+
+ /* Check bank 0 */
+ ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset,
+ &sig_byte);
+ if (ret_val)
+ goto out;
+ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+ E1000_ICH_NVM_SIG_VALUE) {
*bank = 0;
- } else {
- /*
- * find if segment 1 is valid by verifying
- * bit 15:14 = 10b in word 0x13
- */
- e1000_read_flash_byte_ich8lan(hw,
- act_offset + bank1_offset,
- &bank_high_byte);
+ goto out;
+ }
- /* bank1 has a valid signature equivalent to SEC1V */
- if ((bank_high_byte & 0xC0) == 0x80) {
- *bank = 1;
- } else {
- DEBUGOUT("ERROR: EEPROM not present\n");
- ret_val = -E1000_ERR_NVM;
- }
+ /* Check bank 1 */
+ ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset +
+ bank1_offset,
+ &sig_byte);
+ if (ret_val)
+ goto out;
+ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+ E1000_ICH_NVM_SIG_VALUE) {
+ *bank = 1;
+ goto out;
}
- }
+ DEBUGOUT("ERROR: No valid NVM bank present\n");
+ ret_val = -E1000_ERR_NVM;
+ break;
+ }
+out:
return ret_val;
}
@@ -1072,7 +1104,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
if (ret_val != E1000_SUCCESS)
- goto out;
+ goto release;
act_offset = (bank) ? nvm->flash_bank_size : 0;
act_offset += offset;
@@ -1091,9 +1123,13 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
}
}
+release:
nvm->ops.release(hw);
out:
+ if (ret_val)
+ DEBUGOUT1("NVM read error: %d\n", ret_val);
+
return ret_val;
}
@@ -1426,17 +1462,27 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
* is going to be written
*/
ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
- if (ret_val != E1000_SUCCESS)
+ if (ret_val != E1000_SUCCESS) {
+ nvm->ops.release(hw);
goto out;
+ }
if (bank == 0) {
new_bank_offset = nvm->flash_bank_size;
old_bank_offset = 0;
- e1000_erase_flash_bank_ich8lan(hw, 1);
+ ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
+ if (ret_val) {
+ nvm->ops.release(hw);
+ goto out;
+ }
} else {
old_bank_offset = nvm->flash_bank_size;
new_bank_offset = 0;
- e1000_erase_flash_bank_ich8lan(hw, 0);
+ ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
+ if (ret_val) {
+ nvm->ops.release(hw);
+ goto out;
+ }
}
for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
@@ -1448,9 +1494,11 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
if (dev_spec->shadow_ram[i].modified) {
data = dev_spec->shadow_ram[i].value;
} else {
- e1000_read_flash_word_ich8lan(hw,
- i + old_bank_offset,
- &data);
+ ret_val = e1000_read_flash_word_ich8lan(hw, i +
+ old_bank_offset,
+ &data);
+ if (ret_val)
+ break;
}
/*
@@ -1500,7 +1548,11 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
* and we need to change bit 14 to 0b
*/
act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
- e1000_read_flash_word_ich8lan(hw, act_offset, &data);
+ ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data);
+ if (ret_val) {
+ nvm->ops.release(hw);
+ goto out;
+ }
data &= 0xBFFF;
ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
act_offset * 2 + 1,
@@ -1539,6 +1591,9 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
msec_delay(10);
out:
+ if (ret_val)
+ DEBUGOUT1("NVM update error: %d\n", ret_val);
+
return ret_val;
}
@@ -1997,11 +2052,10 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
e1000_initialize_hw_bits_ich8lan(hw);
/* Initialize identification LED */
- ret_val = e1000_id_led_init_generic(hw);
- if (ret_val) {
- DEBUGOUT("Error initializing identification LED\n");
+ ret_val = mac->ops.id_led_init(hw);
+ if (ret_val)
/* This is not fatal and we should not stop init due to this */
- }
+ DEBUGOUT("Error initializing identification LED\n");
/* Setup the receive address. */
e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
@@ -2140,7 +2194,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
hw->fc.current_mode = hw->fc.requested_mode;
DEBUGOUT1("After fix-ups FlowControl is now = %x\n",
- hw->fc.current_mode);
+ hw->fc.current_mode);
/* Continue to configure the copper link. */
ret_val = hw->mac.ops.setup_physical_interface(hw);
@@ -2195,17 +2249,18 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
if (ret_val)
goto out;
- if (hw->phy.type == e1000_phy_igp_3) {
+ switch (hw->phy.type) {
+ case e1000_phy_igp_3:
ret_val = e1000_copper_link_setup_igp(hw);
if (ret_val)
goto out;
- } else if (hw->phy.type == e1000_phy_bm) {
+ break;
+ case e1000_phy_bm:
ret_val = e1000_copper_link_setup_m88(hw);
if (ret_val)
goto out;
- }
-
- if (hw->phy.type == e1000_phy_ife) {
+ break;
+ case e1000_phy_ife:
ret_val = hw->phy.ops.read_reg(hw, IFE_PHY_MDIX_CONTROL,
&reg_data);
if (ret_val)
@@ -2229,6 +2284,9 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
reg_data);
if (ret_val)
goto out;
+ break;
+ default:
+ break;
}
ret_val = e1000_setup_copper_link_generic(hw);
@@ -2476,18 +2534,21 @@ out:
* 'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
* to a lower speed.
*
- * Should only be called for ICH9 and ICH10 devices.
+ * Should only be called for applicable parts.
**/
void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw)
{
u32 phy_ctrl;
- if ((hw->mac.type == e1000_ich10lan) ||
- (hw->mac.type == e1000_ich9lan)) {
+ switch (hw->mac.type) {
+ case e1000_ich9lan:
+ case e1000_ich10lan:
phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU |
E1000_PHY_CTRL_GBE_DISABLE;
E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
+ default:
+ break;
}
return;
diff --git a/sys/dev/e1000/e1000_ich8lan.h b/sys/dev/e1000/e1000_ich8lan.h
index 79dffcd..6316021 100644
--- a/sys/dev/e1000/e1000_ich8lan.h
+++ b/sys/dev/e1000/e1000_ich8lan.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -41,9 +41,10 @@
#define ICH_FLASH_FADDR 0x0008
#define ICH_FLASH_FDATA0 0x0010
-#define ICH_FLASH_READ_COMMAND_TIMEOUT 500
-#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500
-#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 3000000
+/* Requires up to 10 seconds when MNG might be accessing part. */
+#define ICH_FLASH_READ_COMMAND_TIMEOUT 10000000
+#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 10000000
+#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 10000000
#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF
#define ICH_FLASH_CYCLE_REPEAT_COUNT 10
@@ -70,12 +71,14 @@
#define E1000_ICH_MNG_IAMT_MODE 0x2
#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \
- (ID_LED_DEF1_OFF2 << 8) | \
- (ID_LED_DEF1_ON2 << 4) | \
+ (ID_LED_OFF1_OFF2 << 8) | \
+ (ID_LED_OFF1_ON2 << 4) | \
(ID_LED_DEF1_DEF2))
#define E1000_ICH_NVM_SIG_WORD 0x13
#define E1000_ICH_NVM_SIG_MASK 0xC000
+#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0
+#define E1000_ICH_NVM_SIG_VALUE 0x80
#define E1000_ICH8_LAN_INIT_TIMEOUT 1500
@@ -99,6 +102,25 @@
#define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200
#define IGP3_PM_CTRL_FORCE_PWR_DOWN 0x0020
+/* PHY Wakeup Registers and defines */
+#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0)
+#define BM_WUC PHY_REG(BM_WUC_PAGE, 1)
+#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2)
+#define BM_WUS PHY_REG(BM_WUC_PAGE, 3)
+#define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2)))
+#define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2)))
+#define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2)))
+#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2)))
+#define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1)))
+
+#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */
+#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */
+#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */
+#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */
+#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */
+#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */
+#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */
+
/*
* Additional interrupts need to be handled for ICH family:
* DSW = The FW changed the status of the DISSW bit in FWSM
@@ -128,5 +150,8 @@ void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw);
+#if defined(HANKSVILLE_HW) && !defined(NO_PCH_A_SUPPORT)
+s32 e1000_hv_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
+#endif
#endif
diff --git a/sys/dev/e1000/e1000_mac.c b/sys/dev/e1000/e1000_mac.c
index fcec342..435d14e 100644
--- a/sys/dev/e1000/e1000_mac.c
+++ b/sys/dev/e1000/e1000_mac.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,7 @@
#include "e1000_api.h"
static s32 e1000_validate_mdi_setting_generic(struct e1000_hw *hw);
+static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
/**
* e1000_init_mac_ops_generic - Initialize MAC function pointers
@@ -126,7 +127,7 @@ bool e1000_null_mng_mode(struct e1000_hw *hw)
* e1000_null_update_mc - No-op function, return void
* @hw: pointer to the HW structure
**/
-void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a, u32 b, u32 c)
+void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a)
{
DEBUGFUNC("e1000_null_update_mc");
return;
@@ -261,18 +262,17 @@ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw)
* Determines the LAN function id by reading memory-mapped registers
* and swaps the port value if requested.
**/
-void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw)
+static void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw)
{
struct e1000_bus_info *bus = &hw->bus;
u32 reg;
+ /*
+ * The status register reports the correct function number
+ * for the device regardless of function swap state.
+ */
reg = E1000_READ_REG(hw, E1000_STATUS);
bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT;
-
- /* check for a port swap */
- reg = E1000_READ_REG(hw, E1000_FACTPS);
- if (reg & E1000_FACTPS_LFS)
- bus->func ^= 0x1;
}
/**
@@ -358,6 +358,7 @@ void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value)
void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count)
{
u32 i;
+ u8 mac_addr[ETH_ADDR_LEN] = {0};
DEBUGFUNC("e1000_init_rx_addrs_generic");
@@ -368,12 +369,8 @@ void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count)
/* Zero out the other (rar_entry_count - 1) receive addresses */
DEBUGOUT1("Clearing RAR[1-%u]\n", rar_count-1);
- for (i = 1; i < rar_count; i++) {
- E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1), 0);
- E1000_WRITE_FLUSH(hw);
- E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((i << 1) + 1), 0);
- E1000_WRITE_FLUSH(hw);
- }
+ for (i = 1; i < rar_count; i++)
+ hw->mac.ops.rar_set(hw, mac_addr, i);
}
/**
@@ -382,10 +379,11 @@ void e1000_init_rx_addrs_generic(struct e1000_hw *hw, u16 rar_count)
*
* Checks the nvm for an alternate MAC address. An alternate MAC address
* can be setup by pre-boot software and must be treated like a permanent
- * address and must override the actual permanent MAC address. If an
- * alternate MAC address is found it is saved in the hw struct and
- * programmed into RAR0 and the function returns success, otherwise the
- * function returns an error.
+ * address and must override the actual permanent MAC address. If an
+ * alternate MAC address is found it is programmed into RAR0, replacing
+ * the permanent address that was installed into RAR0 by the Si on reset.
+ * This function will return SUCCESS unless it encounters an error while
+ * reading the EEPROM.
**/
s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
{
@@ -404,13 +402,12 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
}
if (nvm_alt_mac_addr_offset == 0xFFFF) {
- ret_val = -(E1000_NOT_IMPLEMENTED);
+ /* There is no Alternate MAC Address */
goto out;
}
if (hw->bus.func == E1000_FUNC_1)
- nvm_alt_mac_addr_offset += ETH_ADDR_LEN/sizeof(u16);
-
+ nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1;
for (i = 0; i < ETH_ADDR_LEN; i += 2) {
offset = nvm_alt_mac_addr_offset + (i >> 1);
ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
@@ -425,14 +422,16 @@ s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw)
/* if multicast bit is set, the alternate address will not be used */
if (alt_mac_addr[0] & 0x01) {
- ret_val = -(E1000_NOT_IMPLEMENTED);
+ DEBUGOUT("Ignoring Alternate Mac Address with MC bit set\n");
goto out;
}
- for (i = 0; i < ETH_ADDR_LEN; i++)
- hw->mac.addr[i] = hw->mac.perm_addr[i] = alt_mac_addr[i];
-
- hw->mac.ops.rar_set(hw, hw->mac.perm_addr, 0);
+ /*
+ * We have a valid alternate MAC address, and we want to treat it the
+ * same as the normal permanent MAC address stored by the HW into the
+ * RAR. Do this by mapping this address into RAR0.
+ */
+ hw->mac.ops.rar_set(hw, alt_mac_addr, 0);
out:
return ret_val;
@@ -467,8 +466,15 @@ void e1000_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index)
if (rar_low || rar_high)
rar_high |= E1000_RAH_AV;
+ /*
+ * Some bridges will combine consecutive 32-bit writes into
+ * a single burst write, which will malfunction on some parts.
+ * The flushes avoid this.
+ */
E1000_WRITE_REG(hw, E1000_RAL(index), rar_low);
+ E1000_WRITE_FLUSH(hw);
E1000_WRITE_REG(hw, E1000_RAH(index), rar_high);
+ E1000_WRITE_FLUSH(hw);
}
/**
@@ -512,55 +518,36 @@ void e1000_mta_set_generic(struct e1000_hw *hw, u32 hash_value)
* @hw: pointer to the HW structure
* @mc_addr_list: array of multicast addresses to program
* @mc_addr_count: number of multicast addresses to program
- * @rar_used_count: the first RAR register free to program
- * @rar_count: total number of supported Receive Address Registers
*
- * Updates the Receive Address Registers and Multicast Table Array.
+ * Updates entire Multicast Table Array.
* The caller must have a packed mc_addr_list of multicast addresses.
- * The parameter rar_count will usually be hw->mac.rar_entry_count
- * unless there are workarounds that change this.
**/
void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count,
- u32 rar_used_count, u32 rar_count)
+ u8 *mc_addr_list, u32 mc_addr_count)
{
- u32 hash_value;
- u32 i;
+ u32 hash_value, hash_bit, hash_reg;
+ int i;
DEBUGFUNC("e1000_update_mc_addr_list_generic");
- /*
- * Load the first set of multicast addresses into the exact
- * filters (RAR). If there are not enough to fill the RAR
- * array, clear the filters.
- */
- for (i = rar_used_count; i < rar_count; i++) {
- if (mc_addr_count) {
- hw->mac.ops.rar_set(hw, mc_addr_list, i);
- mc_addr_count--;
- mc_addr_list += ETH_ADDR_LEN;
- } else {
- E1000_WRITE_REG_ARRAY(hw, E1000_RA, i << 1, 0);
- E1000_WRITE_FLUSH(hw);
- E1000_WRITE_REG_ARRAY(hw, E1000_RA, (i << 1) + 1, 0);
- E1000_WRITE_FLUSH(hw);
- }
- }
+ /* clear mta_shadow */
+ memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
- /* Clear the old settings from the MTA */
- DEBUGOUT("Clearing MTA\n");
- for (i = 0; i < hw->mac.mta_reg_count; i++) {
- E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
- E1000_WRITE_FLUSH(hw);
- }
-
- /* Load any remaining multicast addresses into the hash table. */
- for (; mc_addr_count > 0; mc_addr_count--) {
+ /* update mta_shadow from mc_addr_list */
+ for (i = 0; (u32) i < mc_addr_count; i++) {
hash_value = e1000_hash_mc_addr_generic(hw, mc_addr_list);
- DEBUGOUT1("Hash value = 0x%03X\n", hash_value);
- hw->mac.ops.mta_set(hw, hash_value);
- mc_addr_list += ETH_ADDR_LEN;
+
+ hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1);
+ hash_bit = hash_value & 0x1F;
+
+ hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit);
+ mc_addr_list += (ETH_ADDR_LEN);
}
+
+ /* replace the entire MTA table */
+ for (i = hw->mac.mta_reg_count - 1; i >= 0; i--)
+ E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]);
+ E1000_WRITE_FLUSH(hw);
}
/**
@@ -1022,7 +1009,7 @@ s32 e1000_setup_link_generic(struct e1000_hw *hw)
hw->fc.current_mode = hw->fc.requested_mode;
DEBUGOUT1("After fix-ups FlowControl is now = %x\n",
- hw->fc.current_mode);
+ hw->fc.current_mode);
/* Call the necessary media_type subroutine to configure the link. */
ret_val = hw->mac.ops.setup_physical_interface(hw);
diff --git a/sys/dev/e1000/e1000_mac.h b/sys/dev/e1000/e1000_mac.h
index 7f9baa9..b7a5b2c 100644
--- a/sys/dev/e1000/e1000_mac.h
+++ b/sys/dev/e1000/e1000_mac.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,7 @@ void e1000_null_mac_generic(struct e1000_hw *hw);
s32 e1000_null_ops_generic(struct e1000_hw *hw);
s32 e1000_null_link_info(struct e1000_hw *hw, u16 *s, u16 *d);
bool e1000_null_mng_mode(struct e1000_hw *hw);
-void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a, u32 b, u32 c);
+void e1000_null_update_mc(struct e1000_hw *hw, u8 *h, u32 a);
void e1000_null_write_vfta(struct e1000_hw *hw, u32 a, u32 b);
void e1000_null_mta_set(struct e1000_hw *hw, u32 a);
void e1000_null_rar_set(struct e1000_hw *hw, u8 *h, u32 a);
@@ -63,7 +63,6 @@ s32 e1000_get_bus_info_pci_generic(struct e1000_hw *hw);
s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw);
void e1000_set_lan_id_single_port(struct e1000_hw *hw);
void e1000_set_lan_id_multi_port_pci(struct e1000_hw *hw);
-void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw);
s32 e1000_get_hw_semaphore_generic(struct e1000_hw *hw);
s32 e1000_get_speed_and_duplex_copper_generic(struct e1000_hw *hw, u16 *speed,
u16 *duplex);
@@ -73,8 +72,7 @@ s32 e1000_id_led_init_generic(struct e1000_hw *hw);
s32 e1000_led_on_generic(struct e1000_hw *hw);
s32 e1000_led_off_generic(struct e1000_hw *hw);
void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
- u8 *mc_addr_list, u32 mc_addr_count,
- u32 rar_used_count, u32 rar_count);
+ u8 *mc_addr_list, u32 mc_addr_count);
s32 e1000_set_default_fc_generic(struct e1000_hw *hw);
s32 e1000_set_fc_watermarks_generic(struct e1000_hw *hw);
s32 e1000_setup_fiber_serdes_link_generic(struct e1000_hw *hw);
diff --git a/sys/dev/e1000/e1000_nvm.c b/sys/dev/e1000/e1000_nvm.c
index 8492d80..83557ef 100644
--- a/sys/dev/e1000/e1000_nvm.c
+++ b/sys/dev/e1000/e1000_nvm.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -34,6 +34,8 @@
#include "e1000_api.h"
+static void e1000_reload_nvm_generic(struct e1000_hw *hw);
+
/**
* e1000_init_nvm_ops_generic - Initialize NVM function pointers
* @hw: pointer to the HW structure
@@ -815,31 +817,23 @@ out:
**/
s32 e1000_read_mac_addr_generic(struct e1000_hw *hw)
{
- s32 ret_val = E1000_SUCCESS;
- u16 offset, nvm_data, i;
+ u32 rar_high;
+ u32 rar_low;
+ u16 i;
- DEBUGFUNC("e1000_read_mac_addr");
+ rar_high = E1000_READ_REG(hw, E1000_RAH(0));
+ rar_low = E1000_READ_REG(hw, E1000_RAL(0));
- for (i = 0; i < ETH_ADDR_LEN; i += 2) {
- offset = i >> 1;
- ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
- if (ret_val) {
- DEBUGOUT("NVM Read Error\n");
- goto out;
- }
- hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
- hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
- }
+ for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++)
+ hw->mac.perm_addr[i] = (u8)(rar_low >> (i*8));
- /* Flip last bit of mac address if we're on second port */
- if (hw->bus.func == E1000_FUNC_1)
- hw->mac.perm_addr[5] ^= 1;
+ for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++)
+ hw->mac.perm_addr[i+4] = (u8)(rar_high >> (i*8));
for (i = 0; i < ETH_ADDR_LEN; i++)
hw->mac.addr[i] = hw->mac.perm_addr[i];
-out:
- return ret_val;
+ return E1000_SUCCESS;
}
/**
@@ -916,7 +910,7 @@ out:
* Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
* extended control register.
**/
-void e1000_reload_nvm_generic(struct e1000_hw *hw)
+static void e1000_reload_nvm_generic(struct e1000_hw *hw)
{
u32 ctrl_ext;
diff --git a/sys/dev/e1000/e1000_nvm.h b/sys/dev/e1000/e1000_nvm.h
index d0ab33c..974c407 100644
--- a/sys/dev/e1000/e1000_nvm.h
+++ b/sys/dev/e1000/e1000_nvm.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -61,7 +61,6 @@ s32 e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words,
s32 e1000_update_nvm_checksum_generic(struct e1000_hw *hw);
void e1000_stop_nvm(struct e1000_hw *hw);
void e1000_release_nvm_generic(struct e1000_hw *hw);
-void e1000_reload_nvm_generic(struct e1000_hw *hw);
#define E1000_STM_OPCODE 0xDB00
diff --git a/sys/dev/e1000/e1000_phy.c b/sys/dev/e1000/e1000_phy.c
index 2e4d046..751edbb 100644
--- a/sys/dev/e1000/e1000_phy.c
+++ b/sys/dev/e1000/e1000_phy.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -237,6 +237,12 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
E1000_WRITE_REG(hw, E1000_MDIC, mdic);
+#if defined(HANKSVILLE_HW) && !defined(NO_PCH_A_SUPPORT)
+ /* Workaround for Si errata */
+ if ((hw->phy.type == e1000_phy_lsi) && (hw->revision_id <= 2 ))
+ msec_delay(10);
+
+#endif /* HANKSVILLE_HW && !NO_PCH_A_SUPPORT */
/*
* Poll the ready bit to see if the MDI read completed
* Increasing the time out as testing showed failures with
@@ -292,6 +298,12 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
E1000_WRITE_REG(hw, E1000_MDIC, mdic);
+#if defined(HANKSVILLE_HW) && !defined(NO_PCH_A_SUPPORT)
+ /* Workaround for Si errata */
+ if ((hw->phy.type == e1000_phy_lsi) && (hw->revision_id <= 2))
+ msec_delay(10);
+
+#endif /* HANKSVILLE_HW && !NO_PCH_A_SUPPORT */
/*
* Poll the ready bit to see if the MDI read completed
* Increasing the time out as testing showed failures with
@@ -563,8 +575,8 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
if (ret_val)
goto out;
- /* For newer PHYs this bit is downshift enable */
- if (phy->type == e1000_phy_m88)
+ /* For BM PHY this bit is downshift enable */
+ if (phy->type != e1000_phy_bm)
phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
/*
@@ -1670,16 +1682,16 @@ s32 e1000_get_cable_length_m88(struct e1000_hw *hw)
index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
M88E1000_PSSR_CABLE_LENGTH_SHIFT;
- if (index < M88E1000_CABLE_LENGTH_TABLE_SIZE + 1) {
- phy->min_cable_length = e1000_m88_cable_length_table[index];
- phy->max_cable_length = e1000_m88_cable_length_table[index+1];
-
- phy->cable_length = (phy->min_cable_length +
- phy->max_cable_length) / 2;
- } else {
+ if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE + 1) {
ret_val = E1000_ERR_PHY;
+ goto out;
}
+ phy->min_cable_length = e1000_m88_cable_length_table[index];
+ phy->max_cable_length = e1000_m88_cable_length_table[index+1];
+
+ phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
+
out:
return ret_val;
}
@@ -2140,6 +2152,8 @@ s32 e1000_determine_phy_address(struct e1000_hw *hw)
u32 i;
enum e1000_phy_type phy_type = e1000_phy_unknown;
+ hw->phy.id = phy_type;
+
for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) {
hw->phy.addr = phy_addr;
i = 0;
@@ -2427,11 +2441,11 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
u16 *data, bool read)
{
s32 ret_val;
- u16 reg = ((u16)offset);
+ u16 reg = BM_PHY_REG_NUM(offset);
u16 phy_reg = 0;
u8 phy_acquired = 1;
- DEBUGFUNC("e1000_read_phy_wakeup_reg_bm");
+ DEBUGFUNC("e1000_access_phy_wakeup_reg_bm");
ret_val = hw->phy.ops.acquire(hw);
if (ret_val) {
@@ -2484,15 +2498,15 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
if (read) {
/* Read the page 800 value using opcode 0x12 */
ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
- data);
+ data);
} else {
- /* Read the page 800 value using opcode 0x12 */
+ /* Write the page 800 value using opcode 0x12 */
ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
- *data);
+ *data);
}
if (ret_val) {
- DEBUGOUT("Could not read data value from page 800\n");
+ DEBUGOUT("Could not access data value from page 800\n");
goto out;
}
diff --git a/sys/dev/e1000/e1000_phy.h b/sys/dev/e1000/e1000_phy.h
index 06bcaf0..3e52368 100644
--- a/sys/dev/e1000/e1000_phy.h
+++ b/sys/dev/e1000/e1000_phy.h
@@ -1,6 +1,6 @@
-/*****************************************************************************
+/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -99,14 +99,29 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
#define IGP_PAGE_SHIFT 5
#define PHY_REG_MASK 0x1F
+/* BM/HV Specific Registers */
+#define BM_PORT_CTRL_PAGE 769
+#define BM_PCIE_PAGE 770
#define BM_WUC_PAGE 800
#define BM_WUC_ADDRESS_OPCODE 0x11
#define BM_WUC_DATA_OPCODE 0x12
-#define BM_WUC_ENABLE_PAGE 769
+#define BM_WUC_ENABLE_PAGE BM_PORT_CTRL_PAGE
#define BM_WUC_ENABLE_REG 17
#define BM_WUC_ENABLE_BIT (1 << 2)
#define BM_WUC_HOST_WU_BIT (1 << 4)
+#define PHY_UPPER_SHIFT 21
+#define BM_PHY_REG(page, reg) \
+ (((reg) & MAX_PHY_REG_ADDRESS) |\
+ (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\
+ (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)))
+#define BM_PHY_REG_PAGE(offset) \
+ ((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF))
+#define BM_PHY_REG_NUM(offset) \
+ ((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\
+ (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\
+ ~MAX_PHY_REG_ADDRESS)))
+
/* BM PHY Copper Specific Control 1 */
#define BM_CS_CTRL1 16
#define BM_CS_CTRL1_ENERGY_DETECT 0x0300 /* Enable Energy Detect */
diff --git a/sys/dev/e1000/e1000_regs.h b/sys/dev/e1000/e1000_regs.h
index 1dbd56b..ac673a7 100644
--- a/sys/dev/e1000/e1000_regs.h
+++ b/sys/dev/e1000/e1000_regs.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -62,6 +62,7 @@
#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */
#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */
#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */
+#define E1000_PBA_ECC 0x01100 /* PBA ECC Register */
#define E1000_EICR 0x01580 /* Ext. Interrupt Cause Read - R/clr */
#define E1000_EITR(_n) (0x01680 + (0x4 * (_n)))
#define E1000_EICS 0x01520 /* Ext. Interrupt Cause Set - W0 */
@@ -269,15 +270,6 @@
#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */
#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */
-#define E1000_VFGPRC 0x00F10
-#define E1000_VFGORC 0x00F18
-#define E1000_VFMPRC 0x00F3C
-#define E1000_VFGPTC 0x00F14
-#define E1000_VFGOTC 0x00F34
-#define E1000_VFGOTLBC 0x00F50
-#define E1000_VFGPTLBC 0x00F44
-#define E1000_VFGORLBC 0x00F48
-#define E1000_VFGPRLBC 0x00F40
#define E1000_LSECTXUT 0x04300 /* LinkSec Tx Untagged Packet Count - OutPktsUntagged */
#define E1000_LSECTXPKTE 0x04304 /* LinkSec Encrypted Tx Packets Count - OutPktsEncrypted */
#define E1000_LSECTXPKTP 0x04308 /* LinkSec Protected Tx Packet Count - OutPktsProtected */
@@ -387,6 +379,7 @@
#define E1000_GIOCTL 0x05B44 /* GIO Analog Control Register */
#define E1000_SCCTL 0x05B4C /* PCIc PLL Configuration Register */
#define E1000_GCR 0x05B00 /* PCI-Ex Control */
+#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */
#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */
#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */
#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */
@@ -429,7 +422,6 @@
#define E1000_VFTE 0x00C90 /* VF Transmit Enables */
#define E1000_QDE 0x02408 /* Queue Drop Enable - RW */
#define E1000_DTXSWC 0x03500 /* DMA Tx Switch Control - RW */
-#define E1000_VLVF 0x05D00 /* VLAN Virtual Machine Filter - RW */
#define E1000_RPLOLR 0x05AF0 /* Replication Offload - RW */
#define E1000_UTA 0x0A000 /* Unicast Table Array - RW */
#define E1000_IOVTCL 0x05BBC /* IOV Control Register */
@@ -440,6 +432,8 @@
#define E1000_VMBMEM(_n) (0x00800 + (64 * (_n)))
#define E1000_VFVMBMEM(_n) (0x00800 + (_n))
#define E1000_VMOLR(_n) (0x05AD0 + (4 * (_n)))
+#define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN Virtual Machine
+ * Filter - RW */
/* Time Sync */
#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */
#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index f0cd60f..df54a53 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -93,7 +93,7 @@ int em_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char em_driver_version[] = "6.9.6";
+char em_driver_version[] = "6.9.9";
/*********************************************************************
@@ -278,10 +278,8 @@ static void em_set_multi(struct adapter *);
static void em_print_hw_stats(struct adapter *);
static void em_update_link_status(struct adapter *);
static int em_get_buf(struct adapter *, int);
-
static void em_register_vlan(void *, struct ifnet *, u16);
static void em_unregister_vlan(void *, struct ifnet *, u16);
-
static int em_xmit(struct adapter *, struct mbuf **);
static void em_smartspeed(struct adapter *);
static int em_82547_fifo_workaround(struct adapter *, int);
@@ -322,17 +320,19 @@ static void em_irq_fast(void *);
#else
static int em_irq_fast(void *);
#endif
+
/* MSIX handlers */
static void em_msix_tx(void *);
static void em_msix_rx(void *);
static void em_msix_link(void *);
-static void em_add_rx_process_limit(struct adapter *, const char *,
- const char *, int *, int);
-static void em_handle_rxtx(void *context, int pending);
static void em_handle_rx(void *context, int pending);
static void em_handle_tx(void *context, int pending);
+
+static void em_handle_rxtx(void *context, int pending);
static void em_handle_link(void *context, int pending);
-#endif /* EM_LEGACY_IRQ */
+static void em_add_rx_process_limit(struct adapter *, const char *,
+ const char *, int *, int);
+#endif /* ~EM_LEGACY_IRQ */
#ifdef DEVICE_POLLING
static poll_handler_t em_poll;
@@ -514,8 +514,8 @@ em_attach(device_t dev)
** identified
*/
if ((adapter->hw.mac.type == e1000_ich8lan) ||
- (adapter->hw.mac.type == e1000_ich10lan) ||
- (adapter->hw.mac.type == e1000_ich9lan)) {
+ (adapter->hw.mac.type == e1000_ich9lan) ||
+ (adapter->hw.mac.type == e1000_ich10lan)) {
int rid = EM_BAR_TYPE_FLASH;
adapter->flash = bus_alloc_resource_any(dev,
SYS_RES_MEMORY, &rid, RF_ACTIVE);
@@ -644,6 +644,13 @@ em_attach(device_t dev)
adapter->rx_desc_base =
(struct e1000_rx_desc *)adapter->rxdma.dma_vaddr;
+ /*
+ ** Start from a known state, this is
+ ** important in reading the nvm and
+ ** mac from that.
+ */
+ e1000_reset_hw(&adapter->hw);
+
/* Make sure we have a good EEPROM before we read from it */
if (e1000_validate_nvm_checksum(&adapter->hw) < 0) {
/*
@@ -659,13 +666,6 @@ em_attach(device_t dev)
}
}
- /* Initialize the hardware */
- if (em_hardware_init(adapter)) {
- device_printf(dev, "Unable to initialize the hardware\n");
- error = EIO;
- goto err_hw_init;
- }
-
/* Copy the permanent MAC address out of the EEPROM */
if (e1000_read_mac_addr(&adapter->hw) < 0) {
device_printf(dev, "EEPROM read error while reading MAC"
@@ -680,6 +680,13 @@ em_attach(device_t dev)
goto err_hw_init;
}
+ /* Initialize the hardware */
+ if (em_hardware_init(adapter)) {
+ device_printf(dev, "Unable to initialize the hardware\n");
+ error = EIO;
+ goto err_hw_init;
+ }
+
/* Allocate transmit descriptors and buffers */
if (em_allocate_transmit_structures(adapter)) {
device_printf(dev, "Could not setup transmit structures\n");
@@ -1463,8 +1470,6 @@ em_init_locked(struct adapter *adapter)
/* Setup VLAN support, basic and offload if available */
E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
- /* New register interface replaces this but
- waiting on kernel support to be added */
if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) &&
((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)) {
u32 ctrl;
@@ -1473,6 +1478,7 @@ em_init_locked(struct adapter *adapter)
E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
}
+
/* Set hardware offload abilities */
ifp->if_hwassist = 0;
if (adapter->hw.mac.type >= e1000_82543) {
@@ -1622,49 +1628,35 @@ em_intr(void *arg)
return;
EM_CORE_LOCK(adapter);
- for (;;) {
- reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
-
- if (adapter->hw.mac.type >= e1000_82571 &&
- (reg_icr & E1000_ICR_INT_ASSERTED) == 0)
- break;
- else if (reg_icr == 0)
- break;
-
- /*
- * XXX: some laptops trigger several spurious interrupts
- * on em(4) when in the resume cycle. The ICR register
- * reports all-ones value in this case. Processing such
- * interrupts would lead to a freeze. I don't know why.
- */
- if (reg_icr == 0xffffffff)
- break;
+ reg_icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
+ if ((reg_icr == 0xffffffff) || (reg_icr == 0)||
+ (adapter->hw.mac.type >= e1000_82571 &&
+ (reg_icr & E1000_ICR_INT_ASSERTED) == 0))
+ goto out;
- EM_CORE_UNLOCK(adapter);
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- em_rxeof(adapter, -1);
- EM_TX_LOCK(adapter);
- em_txeof(adapter);
- EM_TX_UNLOCK(adapter);
- }
- EM_CORE_LOCK(adapter);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+ goto out;
- /* Link status change */
- if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
- callout_stop(&adapter->timer);
- adapter->hw.mac.get_link_status = 1;
- em_update_link_status(adapter);
- /* Deal with TX cruft when link lost */
- em_tx_purge(adapter);
- callout_reset(&adapter->timer, hz,
- em_local_timer, adapter);
- }
+ EM_TX_LOCK(adapter);
+ em_txeof(adapter);
+ em_rxeof(adapter, -1);
+ em_txeof(adapter);
+ EM_TX_UNLOCK(adapter);
- if (reg_icr & E1000_ICR_RXO)
- adapter->rx_overruns++;
+ if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
+ callout_stop(&adapter->timer);
+ adapter->hw.mac.get_link_status = 1;
+ em_update_link_status(adapter);
+ /* Deal with TX cruft when link lost */
+ em_tx_purge(adapter);
+ callout_reset(&adapter->timer, hz,
+ em_local_timer, adapter);
}
- EM_CORE_UNLOCK(adapter);
+ if (reg_icr & E1000_ICR_RXO)
+ adapter->rx_overruns++;
+out:
+ EM_CORE_UNLOCK(adapter);
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
em_start(ifp);
@@ -1713,33 +1705,6 @@ em_handle_rxtx(void *context, int pending)
em_enable_intr(adapter);
}
-static void
-em_handle_rx(void *context, int pending)
-{
- struct adapter *adapter = context;
- struct ifnet *ifp = adapter->ifp;
-
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) &&
- (em_rxeof(adapter, adapter->rx_process_limit) != 0))
- taskqueue_enqueue(adapter->tq, &adapter->rx_task);
-
-}
-
-static void
-em_handle_tx(void *context, int pending)
-{
- struct adapter *adapter = context;
- struct ifnet *ifp = adapter->ifp;
-
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- EM_TX_LOCK(adapter);
- em_txeof(adapter);
- if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
- em_start_locked(ifp);
- EM_TX_UNLOCK(adapter);
- }
-}
-
/*********************************************************************
*
* Fast Legacy/MSI Combined Interrupt Service routine
@@ -1868,6 +1833,33 @@ em_msix_link(void *arg)
EM_MSIX_LINK | E1000_IMS_LSC);
return;
}
+
+static void
+em_handle_rx(void *context, int pending)
+{
+ struct adapter *adapter = context;
+ struct ifnet *ifp = adapter->ifp;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) &&
+ (em_rxeof(adapter, adapter->rx_process_limit) != 0))
+ taskqueue_enqueue(adapter->tq, &adapter->rx_task);
+
+}
+
+static void
+em_handle_tx(void *context, int pending)
+{
+ struct adapter *adapter = context;
+ struct ifnet *ifp = adapter->ifp;
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ EM_TX_LOCK(adapter);
+ em_txeof(adapter);
+ if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
+ em_start_locked(ifp);
+ EM_TX_UNLOCK(adapter);
+ }
+}
#endif /* EM_FAST_IRQ */
/*********************************************************************
@@ -2468,7 +2460,7 @@ em_set_multi(struct adapter *adapter)
struct ifnet *ifp = adapter->ifp;
struct ifmultiaddr *ifma;
u32 reg_rctl = 0;
- u8 mta[512]; /* Largest MTS is 4096 bits */
+ u8 *mta; /* Multicast array memory */
int mcnt = 0;
IOCTL_DEBUGOUT("em_set_multi: begin");
@@ -2483,6 +2475,13 @@ em_set_multi(struct adapter *adapter)
msec_delay(5);
}
+ /* Allocate temporary memory to setup array */
+ mta = malloc(sizeof(u8) *
+ (ETH_ADDR_LEN * MAX_NUM_MULTICAST_ADDRESSES),
+ M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (mta == NULL)
+ panic("em_set_multi memory failure\n");
+
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
@@ -2502,8 +2501,7 @@ em_set_multi(struct adapter *adapter)
reg_rctl |= E1000_RCTL_MPE;
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
} else
- e1000_update_mc_addr_list(&adapter->hw, mta,
- mcnt, 1, adapter->hw.mac.rar_entry_count);
+ e1000_update_mc_addr_list(&adapter->hw, mta, mcnt);
if (adapter->hw.mac.type == e1000_82542 &&
adapter->hw.revision_id == E1000_REVISION_2) {
@@ -2514,6 +2512,7 @@ em_set_multi(struct adapter *adapter)
if (adapter->hw.bus.pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
e1000_pci_set_mwi(&adapter->hw);
}
+ free(mta, M_DEVBUF);
}
@@ -2925,6 +2924,7 @@ em_allocate_msix(struct adapter *adapter)
return (0);
}
+
static void
em_free_pci_resources(struct adapter *adapter)
{
@@ -2973,7 +2973,7 @@ em_free_pci_resources(struct adapter *adapter)
}
/*
- * Setup MSI/X
+ * Setup MSI or MSI/X
*/
static int
em_setup_msix(struct adapter *adapter)
diff --git a/sys/dev/e1000/if_igb.c b/sys/dev/e1000/if_igb.c
index 0f7dd7c..919cab1 100644
--- a/sys/dev/e1000/if_igb.c
+++ b/sys/dev/e1000/if_igb.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -34,7 +34,6 @@
#ifdef HAVE_KERNEL_OPTION_HEADERS
#include "opt_device_polling.h"
-#include "opt_inet.h"
#endif
#include <sys/param.h>
@@ -95,7 +94,7 @@ int igb_display_debug_stats = 0;
/*********************************************************************
* Driver version:
*********************************************************************/
-char igb_driver_version[] = "version - 1.4.1";
+char igb_driver_version[] = "version - 1.5.2";
/*********************************************************************
@@ -116,8 +115,11 @@ static igb_vendor_info_t igb_vendor_info_array[] =
{ 0x8086, E1000_DEV_ID_82575GB_QUAD_COPPER,
PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82576, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82576_NS, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82576_FIBER, PCI_ANY_ID, PCI_ANY_ID, 0},
{ 0x8086, E1000_DEV_ID_82576_SERDES, PCI_ANY_ID, PCI_ANY_ID, 0},
+ { 0x8086, E1000_DEV_ID_82576_QUAD_COPPER,
+ PCI_ANY_ID, PCI_ANY_ID, 0},
/* required last entry */
{ 0, 0, 0, 0, 0}
};
@@ -152,7 +154,9 @@ static void igb_identify_hardware(struct adapter *);
static int igb_allocate_pci_resources(struct adapter *);
static int igb_allocate_msix(struct adapter *);
static int igb_allocate_legacy(struct adapter *);
+#if __FreeBSD_version >= 602105
static int igb_setup_msix(struct adapter *);
+#endif
static void igb_free_pci_resources(struct adapter *);
static void igb_local_timer(void *);
static int igb_hardware_init(struct adapter *);
@@ -179,10 +183,7 @@ static void igb_disable_intr(struct adapter *);
static void igb_update_stats_counters(struct adapter *);
static bool igb_txeof(struct tx_ring *);
static bool igb_rxeof(struct rx_ring *, int);
-#ifndef __NO_STRICT_ALIGNMENT
-static int igb_fixup_rx(struct rx_ring *);
-#endif
-static void igb_rx_checksum(u32, struct mbuf *);
+static void igb_rx_checksum(u32, struct mbuf *, bool);
static int igb_tx_ctx_setup(struct tx_ring *, struct mbuf *);
static bool igb_tso_setup(struct tx_ring *, struct mbuf *, u32 *);
static void igb_set_promisc(struct adapter *);
@@ -190,11 +191,9 @@ static void igb_disable_promisc(struct adapter *);
static void igb_set_multi(struct adapter *);
static void igb_print_hw_stats(struct adapter *);
static void igb_update_link_status(struct adapter *);
-static int igb_get_buf(struct rx_ring *, int);
-
+static int igb_get_buf(struct rx_ring *, int, u8);
static void igb_register_vlan(void *, struct ifnet *, u16);
static void igb_unregister_vlan(void *, struct ifnet *, u16);
-
static int igb_xmit(struct tx_ring *, struct mbuf **);
static int igb_dma_malloc(struct adapter *, bus_size_t,
struct igb_dma_alloc *, int);
@@ -217,18 +216,24 @@ static int igb_tsync_init(struct adapter *);
static void igb_tsync_disable(struct adapter *);
#endif
+#if __FreeBSD_version > 700000
static int igb_irq_fast(void *);
+#else
+static void igb_irq_fast(void *);
+#endif
+
static void igb_add_rx_process_limit(struct adapter *, const char *,
const char *, int *, int);
static void igb_handle_rxtx(void *context, int pending);
static void igb_handle_tx(void *context, int pending);
static void igb_handle_rx(void *context, int pending);
-static void igb_handle_link(void *context, int pending);
+#if __FreeBSD_version >= 602105
/* These are MSIX only irq handlers */
static void igb_msix_rx(void *);
static void igb_msix_tx(void *);
static void igb_msix_link(void *);
+#endif
/* Adaptive Interrupt Moderation */
static void igb_update_aim(struct rx_ring *);
@@ -271,8 +276,12 @@ TUNABLE_INT("hw.igb.txd", &igb_txd);
** These parameters are used in Adaptive
** Interrupt Moderation. The value is set
** into EITR and controls the interrupt
-** frequency. They can be modified but
-** be careful in tuning them.
+** frequency. A variable static scheme can
+** be created by changing the assigned value
+** of igb_ave_latency to the desired value,
+** and then set igb_enable_aim to FALSE.
+** This will result in all EITR registers
+** getting set to that value statically.
*/
static int igb_enable_aim = TRUE;
TUNABLE_INT("hw.igb.enable_aim", &igb_enable_aim);
@@ -289,7 +298,7 @@ TUNABLE_INT("hw.igb.bulk_latency", &igb_bulk_latency);
** 0, it will then be based on number of cpus.
*/
static int igb_tx_queues = 1;
-static int igb_rx_queues = 4;
+static int igb_rx_queues = 1;
TUNABLE_INT("hw.igb.tx_queues", &igb_tx_queues);
TUNABLE_INT("hw.igb.rx_queues", &igb_rx_queues);
@@ -297,8 +306,8 @@ TUNABLE_INT("hw.igb.rx_queues", &igb_rx_queues);
static int igb_rx_process_limit = 100;
TUNABLE_INT("hw.igb.rx_process_limit", &igb_rx_process_limit);
-/* Flow control setting - default to none */
-static int igb_fc_setting = 0;
+/* Flow control setting - default to FULL */
+static int igb_fc_setting = e1000_fc_full;
TUNABLE_INT("hw.igb.fc_setting", &igb_fc_setting);
/*
@@ -310,6 +319,12 @@ TUNABLE_INT("hw.igb.fc_setting", &igb_fc_setting);
static int igb_enable_lro = 1;
TUNABLE_INT("hw.igb.enable_lro", &igb_enable_lro);
+/*
+ * Enable RX Header Split
+ */
+static int igb_rx_hdr_split = 1;
+TUNABLE_INT("hw.igb.rx_hdr_split", &igb_rx_hdr_split);
+
extern int mp_ncpus;
/*********************************************************************
* Device identification routine
@@ -426,6 +441,11 @@ igb_attach(device_t dev)
OID_AUTO, "bulk_latency", CTLTYPE_INT|CTLFLAG_RW,
&igb_bulk_latency, 1, "Bulk Latency");
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
+ OID_AUTO, "hdr_split", CTLTYPE_INT|CTLFLAG_RW,
+ &igb_rx_hdr_split, 0, "RX Header Split");
+
callout_init_mtx(&adapter->timer, &adapter->core_mtx, 0);
/* Determine hardware and mac info */
@@ -475,7 +495,6 @@ igb_attach(device_t dev)
adapter->hw.mac.autoneg = DO_AUTO_NEG;
adapter->hw.phy.autoneg_wait_to_complete = FALSE;
adapter->hw.phy.autoneg_advertised = AUTONEG_ADV_DEFAULT;
- adapter->rx_buffer_len = 2048;
/* Copper options */
if (adapter->hw.phy.media_type == e1000_media_type_copper) {
@@ -499,6 +518,13 @@ igb_attach(device_t dev)
goto err_pci;
}
+ /*
+ ** Start from a known state, this is
+ ** important in reading the nvm and
+ ** mac from that.
+ */
+ e1000_reset_hw(&adapter->hw);
+
/* Make sure we have a good EEPROM before we read from it */
if (e1000_validate_nvm_checksum(&adapter->hw) < 0) {
/*
@@ -514,27 +540,29 @@ igb_attach(device_t dev)
}
}
- /* Initialize the hardware */
- if (igb_hardware_init(adapter)) {
- device_printf(dev, "Unable to initialize the hardware\n");
- error = EIO;
- goto err_late;
- }
-
- /* Copy the permanent MAC address out of the EEPROM */
+ /*
+ ** Copy the permanent MAC address out of the EEPROM
+ */
if (e1000_read_mac_addr(&adapter->hw) < 0) {
device_printf(dev, "EEPROM read error while reading MAC"
" address\n");
error = EIO;
goto err_late;
}
-
+ /* Check its sanity */
if (!igb_is_valid_ether_addr(adapter->hw.mac.addr)) {
device_printf(dev, "Invalid MAC address\n");
error = EIO;
goto err_late;
}
+ /* Now Initialize the hardware */
+ if (igb_hardware_init(adapter)) {
+ device_printf(dev, "Unable to initialize the hardware\n");
+ error = EIO;
+ goto err_late;
+ }
+
/*
** Configure Interrupts
*/
@@ -613,7 +641,11 @@ igb_detach(device_t dev)
INIT_DEBUGOUT("igb_detach: begin");
/* Make sure VLANS are not using driver */
+#if __FreeBSD_version >= 700000
if (adapter->ifp->if_vlantrunk != NULL) {
+#else
+ if (adapter->ifp->if_nvlans != 0) {
+#endif
device_printf(dev,"Vlan in use, detach first\n");
return (EBUSY);
}
@@ -919,13 +951,11 @@ igb_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
reinit = 1;
}
- if (mask & IFCAP_VLAN_HWFILTER) {
- ifp->if_capenable ^= IFCAP_VLAN_HWFILTER;
- reinit = 1;
- }
if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING))
igb_init(adapter);
+#if __FreeBSD_version >= 700000
VLAN_CAPABILITIES(ifp);
+#endif
break;
}
@@ -1124,7 +1154,6 @@ igb_init_locked(struct adapter *adapter)
E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
- /* Vlan's enabled but HW Filtering off */
if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) &&
((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)) {
u32 ctrl;
@@ -1135,8 +1164,14 @@ igb_init_locked(struct adapter *adapter)
/* Set hardware offload abilities */
ifp->if_hwassist = 0;
- if (ifp->if_capenable & IFCAP_TXCSUM)
+ if (ifp->if_capenable & IFCAP_TXCSUM) {
ifp->if_hwassist |= (CSUM_TCP | CSUM_UDP);
+#if __FreeBSD_version >= 800000
+ if (adapter->hw.mac.type == e1000_82576)
+ ifp->if_hwassist |= CSUM_SCTP;
+#endif
+ }
+
if (ifp->if_capenable & IFCAP_TSO4)
ifp->if_hwassist |= CSUM_TSO;
@@ -1150,6 +1185,15 @@ igb_init_locked(struct adapter *adapter)
/* Setup Multicast table */
igb_set_multi(adapter);
+ /*
+ ** Figure out the desired mbuf pool
+ ** for doing jumbo/packetsplit
+ */
+ if (ifp->if_mtu > ETHERMTU)
+ adapter->rx_mbuf_sz = MJUMPAGESIZE;
+ else
+ adapter->rx_mbuf_sz = MCLBYTES;
+
/* Prepare receive descriptors and buffers */
if (igb_setup_receive_structures(adapter)) {
device_printf(dev, "Could not setup receive structures\n");
@@ -1211,24 +1255,6 @@ igb_init(void *arg)
static void
-igb_handle_link(void *context, int pending)
-{
- struct adapter *adapter = context;
- struct ifnet *ifp;
-
- ifp = adapter->ifp;
-
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
- return;
-
- IGB_CORE_LOCK(adapter);
- callout_stop(&adapter->timer);
- igb_update_link_status(adapter);
- callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
- IGB_CORE_UNLOCK(adapter);
-}
-
-static void
igb_handle_rxtx(void *context, int pending)
{
struct adapter *adapter = context;
@@ -1239,7 +1265,7 @@ igb_handle_rxtx(void *context, int pending)
ifp = adapter->ifp;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if (igb_rxeof(rxr, adapter->rx_process_limit) != 0)
+ if (igb_rxeof(rxr, adapter->rx_process_limit))
taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
IGB_TX_LOCK(txr);
igb_txeof(txr);
@@ -1255,23 +1281,23 @@ igb_handle_rxtx(void *context, int pending)
static void
igb_handle_rx(void *context, int pending)
{
- struct rx_ring *rxr = context;
- struct adapter *adapter = rxr->adapter;
- struct ifnet *ifp = adapter->ifp;
-
+ struct rx_ring *rxr = context;
+ struct adapter *adapter = rxr->adapter;
+ struct ifnet *ifp = adapter->ifp;
+
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
if (igb_rxeof(rxr, adapter->rx_process_limit) != 0)
/* More to clean, schedule another task */
taskqueue_enqueue(adapter->tq, &rxr->rx_task);
-
+
}
static void
igb_handle_tx(void *context, int pending)
{
- struct tx_ring *txr = context;
- struct adapter *adapter = txr->adapter;
- struct ifnet *ifp = adapter->ifp;
+ struct tx_ring *txr = context;
+ struct adapter *adapter = txr->adapter;
+ struct ifnet *ifp = adapter->ifp;
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
IGB_TX_LOCK(txr);
@@ -1289,7 +1315,11 @@ igb_handle_tx(void *context, int pending)
* Interrupt Service routine
*
*********************************************************************/
+#if __FreeBSD_version < 700000
+static void
+#else
static int
+#endif
igb_irq_fast(void *arg)
{
struct adapter *adapter = arg;
@@ -1320,7 +1350,7 @@ igb_irq_fast(void *arg)
/* Link status change */
if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) {
adapter->hw.mac.get_link_status = 1;
- taskqueue_enqueue(adapter->tq, &adapter->link_task);
+ igb_update_link_status(adapter);
}
if (reg_icr & E1000_ICR_RXO)
@@ -1329,26 +1359,32 @@ igb_irq_fast(void *arg)
}
+#if __FreeBSD_version >= 602105
/*********************************************************************
*
* MSIX TX Interrupt Service routine
*
**********************************************************************/
-
static void
igb_msix_tx(void *arg)
{
struct tx_ring *txr = arg;
struct adapter *adapter = txr->adapter;
- struct ifnet *ifp = adapter->ifp;
+ u32 loop = IGB_MAX_LOOP;
+ bool more;
++txr->tx_irq;
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IGB_TX_LOCK(txr);
- igb_txeof(txr);
- IGB_TX_UNLOCK(txr);
- taskqueue_enqueue(adapter->tq, &txr->tx_task);
- }
+ IGB_TX_LOCK(txr);
+
+ do {
+ more = igb_txeof(txr);
+ } while (loop-- && more);
+
+ IGB_TX_UNLOCK(txr);
+
+ /* Schedule a clean task */
+ taskqueue_enqueue(adapter->tq, &txr->tx_task);
+
/* Reenable this interrupt */
E1000_WRITE_REG(&adapter->hw, E1000_EIMS, txr->eims);
return;
@@ -1365,25 +1401,55 @@ igb_msix_rx(void *arg)
{
struct rx_ring *rxr = arg;
struct adapter *adapter = rxr->adapter;
- u32 more, loop = 5;
+ u32 loop = IGB_MAX_LOOP;
+ bool more;
++rxr->rx_irq;
do {
more = igb_rxeof(rxr, adapter->rx_process_limit);
- } while (loop-- || more != 0);
-
- taskqueue_enqueue(adapter->tq, &rxr->rx_task);
+ } while (loop-- && more);
/* Update interrupt rate */
if (igb_enable_aim == TRUE)
igb_update_aim(rxr);
+ /* Schedule another clean */
+ taskqueue_enqueue(adapter->tq, &rxr->rx_task);
+
/* Reenable this interrupt */
E1000_WRITE_REG(&adapter->hw, E1000_EIMS, rxr->eims);
return;
}
+/*********************************************************************
+ *
+ * MSIX Link Interrupt Service routine
+ *
+ **********************************************************************/
+
+static void
+igb_msix_link(void *arg)
+{
+ struct adapter *adapter = arg;
+ u32 icr;
+
+ ++adapter->link_irq;
+ icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
+ if (!(icr & E1000_ICR_LSC))
+ goto spurious;
+ adapter->hw.mac.get_link_status = 1;
+ igb_update_link_status(adapter);
+
+spurious:
+ /* Rearm */
+ E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC);
+ E1000_WRITE_REG(&adapter->hw, E1000_EIMS, adapter->link_mask);
+ return;
+}
+#endif
+
+
/*
** Routine to adjust the RX EITR value based on traffic,
** its a simple three state model, but seems to help.
@@ -1436,33 +1502,6 @@ igb_update_aim(struct rx_ring *rxr)
/*********************************************************************
*
- * MSIX Link Interrupt Service routine
- *
- **********************************************************************/
-
-static void
-igb_msix_link(void *arg)
-{
- struct adapter *adapter = arg;
- u32 icr;
-
- ++adapter->link_irq;
- icr = E1000_READ_REG(&adapter->hw, E1000_ICR);
- if (!(icr & E1000_ICR_LSC))
- goto spurious;
- adapter->hw.mac.get_link_status = 1;
- taskqueue_enqueue(adapter->tq, &adapter->link_task);
-
-spurious:
- /* Rearm */
- E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC);
- E1000_WRITE_REG(&adapter->hw, E1000_EIMS, adapter->link_mask);
- return;
-}
-
-
-/*********************************************************************
- *
* Media Ioctl callback
*
* This routine is called whenever the user queries the status of
@@ -1589,7 +1628,7 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
struct adapter *adapter = txr->adapter;
bus_dma_segment_t segs[IGB_MAX_SCATTER];
bus_dmamap_t map;
- struct igb_buffer *tx_buffer, *tx_buffer_mapped;
+ struct igb_tx_buffer *tx_buffer, *tx_buffer_mapped;
union e1000_adv_tx_desc *txd = NULL;
struct mbuf *m_head;
u32 olinfo_status = 0, cmd_type_len = 0;
@@ -1639,7 +1678,7 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
m = m_defrag(*m_headp, M_DONTWAIT);
if (m == NULL) {
- adapter->mbuf_alloc_failed++;
+ adapter->mbuf_defrag_failed++;
m_freem(*m_headp);
*m_headp = NULL;
return (ENOBUFS);
@@ -1692,7 +1731,7 @@ igb_xmit(struct tx_ring *txr, struct mbuf **m_headp)
return (ENXIO);
} else
/* Do all other context descriptor setup */
- offload = igb_tx_ctx_setup(txr, m_head);
+ offload = igb_tx_ctx_setup(txr, m_head);
if (offload == TRUE)
olinfo_status |= E1000_TXD_POPTS_TXSM << 8;
#ifdef IGB_TIMESYNC
@@ -1829,8 +1868,7 @@ igb_set_multi(struct adapter *adapter)
reg_rctl |= E1000_RCTL_MPE;
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, reg_rctl);
} else
- e1000_update_mc_addr_list(&adapter->hw, mta,
- mcnt, 1, adapter->hw.mac.rar_entry_count);
+ e1000_update_mc_addr_list(&adapter->hw, mta, mcnt);
}
@@ -1861,6 +1899,9 @@ igb_local_timer(void *arg)
*/
igb_watchdog(adapter);
+ /* Trigger an RX interrupt on all queues */
+ E1000_WRITE_REG(&adapter->hw, E1000_EICS, adapter->rx_mask);
+
callout_reset(&adapter->timer, hz, igb_local_timer, adapter);
}
@@ -2027,9 +2068,10 @@ igb_allocate_pci_resources(struct adapter *adapter)
adapter->num_tx_queues = 1; /* Defaults for Legacy or MSI */
adapter->num_rx_queues = 1;
+#if __FreeBSD_version >= 602105
/* This will setup either MSI/X or MSI */
adapter->msix = igb_setup_msix(adapter);
-
+#endif
adapter->hw.back = &adapter->osdep;
return (error);
@@ -2067,14 +2109,16 @@ igb_allocate_legacy(struct adapter *adapter)
* processing contexts.
*/
TASK_INIT(&adapter->rxtx_task, 0, igb_handle_rxtx, adapter);
- TASK_INIT(&adapter->link_task, 0, igb_handle_link, adapter);
adapter->tq = taskqueue_create_fast("igb_taskq", M_NOWAIT,
taskqueue_thread_enqueue, &adapter->tq);
taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq",
device_get_nameunit(adapter->dev));
if ((error = bus_setup_intr(dev, adapter->res[0],
- INTR_TYPE_NET | INTR_MPSAFE, igb_irq_fast, NULL, adapter,
- &adapter->tag[0])) != 0) {
+ INTR_TYPE_NET | INTR_MPSAFE, igb_irq_fast,
+#if __FreeBSD_version >= 700000
+ NULL,
+#endif
+ adapter, &adapter->tag[0])) != 0) {
device_printf(dev, "Failed to register fast interrupt "
"handler: %d\n", error);
taskqueue_free(adapter->tq);
@@ -2086,6 +2130,7 @@ igb_allocate_legacy(struct adapter *adapter)
}
+#if __FreeBSD_version >= 602105
/*********************************************************************
*
* Setup the MSIX Interrupt handlers:
@@ -2115,8 +2160,11 @@ igb_allocate_msix(struct adapter *adapter)
return (ENXIO);
}
error = bus_setup_intr(dev, adapter->res[vector],
- INTR_TYPE_NET | INTR_MPSAFE, NULL, igb_msix_tx,
- txr, &adapter->tag[vector]);
+ INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version >= 700000
+ NULL,
+#endif
+ igb_msix_tx, txr, &adapter->tag[vector]);
if (error) {
adapter->res[vector] = NULL;
device_printf(dev, "Failed to register TX handler");
@@ -2146,13 +2194,17 @@ igb_allocate_msix(struct adapter *adapter)
return (ENXIO);
}
error = bus_setup_intr(dev, adapter->res[vector],
- INTR_TYPE_NET | INTR_MPSAFE, NULL, igb_msix_rx,
- rxr, &adapter->tag[vector]);
+ INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version >= 700000
+ NULL,
+#endif
+ igb_msix_rx, rxr, &adapter->tag[vector]);
if (error) {
adapter->res[vector] = NULL;
device_printf(dev, "Failed to register RX handler");
return (error);
}
+ /* Make tasklet for deferred handling - one per queue */
TASK_INIT(&rxr->rx_task, 0, igb_handle_rx, rxr);
if (adapter->hw.mac.type == e1000_82575) {
rxr->eims = E1000_EICR_RX_QUEUE0 << i;
@@ -2161,6 +2213,8 @@ igb_allocate_msix(struct adapter *adapter)
rxr->eims = 1 << vector;
rxr->msix = vector;
}
+ /* Get a mask for local timer */
+ adapter->rx_mask |= rxr->eims;
}
/* And Link */
@@ -2174,8 +2228,11 @@ igb_allocate_msix(struct adapter *adapter)
return (ENXIO);
}
if ((error = bus_setup_intr(dev, adapter->res[vector],
- INTR_TYPE_NET | INTR_MPSAFE, NULL, igb_msix_link,
- adapter, &adapter->tag[vector])) != 0) {
+ INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version >= 700000
+ NULL,
+#endif
+ igb_msix_link, adapter, &adapter->tag[vector])) != 0) {
device_printf(dev, "Failed to register Link handler");
return (error);
}
@@ -2184,9 +2241,6 @@ igb_allocate_msix(struct adapter *adapter)
else
adapter->linkvec = vector;
- /* Make tasklet for deferred link interrupt handling */
- TASK_INIT(&adapter->link_task, 0, igb_handle_link, adapter);
-
adapter->tq = taskqueue_create_fast("igb_taskq", M_NOWAIT,
taskqueue_thread_enqueue, &adapter->tq);
taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq",
@@ -2194,6 +2248,14 @@ igb_allocate_msix(struct adapter *adapter)
return (0);
}
+#else /* FreeBSD 6.1/2 */
+static int
+igb_allocate_msix(struct adapter *adapter)
+{
+ return (1);
+}
+#endif
+
static void
igb_configure_queues(struct adapter *adapter)
@@ -2316,12 +2378,14 @@ igb_free_pci_resources(struct adapter *adapter)
}
}
+#if __FreeBSD_version >= 602105
if (adapter->msix)
pci_release_msi(dev);
if (adapter->msix_mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
PCIR_BAR(IGB_MSIX_BAR), adapter->msix_mem);
+#endif
if (adapter->pci_mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
@@ -2329,6 +2393,7 @@ igb_free_pci_resources(struct adapter *adapter)
}
+#if __FreeBSD_version >= 602105
/*
* Setup Either MSI/X or MSI
*/
@@ -2391,6 +2456,7 @@ msi:
device_printf(adapter->dev,"Using MSI interrupt\n");
return (msgs);
}
+#endif /* __FreeBSD_version >= 602105 */
/*********************************************************************
*
@@ -2487,11 +2553,12 @@ igb_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_capabilities = ifp->if_capenable = 0;
ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
- ifp->if_capabilities |= IFCAP_TSO4;
+ ifp->if_capabilities |= IFCAP_TSO4 | IFCAP_VLAN_MTU;
+ ifp->if_capabilities |= IFCAP_JUMBO_MTU;
ifp->if_capenable = ifp->if_capabilities;
/*
- * Tell the upper layer(s) what we support.
+ * Tell the upper layer(s) we support long frames.
*/
ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header);
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_HWFILTER;
@@ -2750,7 +2817,7 @@ igb_allocate_transmit_buffers(struct tx_ring *txr)
{
struct adapter *adapter = txr->adapter;
device_t dev = adapter->dev;
- struct igb_buffer *txbuf;
+ struct igb_tx_buffer *txbuf;
int error, i;
/*
@@ -2773,7 +2840,7 @@ igb_allocate_transmit_buffers(struct tx_ring *txr)
}
if (!(txr->tx_buffers =
- (struct igb_buffer *) malloc(sizeof(struct igb_buffer) *
+ (struct igb_tx_buffer *) malloc(sizeof(struct igb_tx_buffer) *
adapter->num_tx_desc, M_DEVBUF, M_NOWAIT | M_ZERO))) {
device_printf(dev, "Unable to allocate tx_buffer memory\n");
error = ENOMEM;
@@ -2806,7 +2873,7 @@ static void
igb_setup_transmit_ring(struct tx_ring *txr)
{
struct adapter *adapter = txr->adapter;
- struct igb_buffer *txbuf;
+ struct igb_tx_buffer *txbuf;
int i;
/* Clear the old ring contents */
@@ -2936,7 +3003,7 @@ static void
igb_free_transmit_buffers(struct tx_ring *txr)
{
struct adapter *adapter = txr->adapter;
- struct igb_buffer *tx_buffer;
+ struct igb_tx_buffer *tx_buffer;
int i;
INIT_DEBUGOUT("free_transmit_ring: begin");
@@ -2978,6 +3045,7 @@ igb_free_transmit_buffers(struct tx_ring *txr)
return;
}
+#if __FreeBSD_version >= 700000
/**********************************************************************
*
* Setup work for hardware segmentation offload (TSO) on
@@ -2989,7 +3057,7 @@ igb_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *hdrlen)
{
struct adapter *adapter = txr->adapter;
struct e1000_adv_tx_context_desc *TXD;
- struct igb_buffer *tx_buffer;
+ struct igb_tx_buffer *tx_buffer;
u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
u32 mss_l4len_idx = 0;
u16 vtag = 0;
@@ -3065,7 +3133,13 @@ igb_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *hdrlen)
txr->next_avail_desc = ctxd;
return TRUE;
}
-
+#else /* fake out for 6.2 */
+static boolean_t
+igb_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *hdrlen)
+{
+ return (FALSE);
+}
+#endif
/*********************************************************************
*
@@ -3078,7 +3152,7 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
{
struct adapter *adapter = txr->adapter;
struct e1000_adv_tx_context_desc *TXD;
- struct igb_buffer *tx_buffer;
+ struct igb_tx_buffer *tx_buffer;
uint32_t vlan_macip_lens = 0, type_tucmd_mlhl = 0;
struct ether_vlan_header *eh;
struct ip *ip = NULL;
@@ -3086,24 +3160,38 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
int ehdrlen, ip_hlen = 0;
u16 etype;
u8 ipproto = 0;
- bool offload = TRUE;
+ bool offload = FALSE;
+#if __FreeBSD_version >= 700000
u16 vtag = 0;
+#else
+ struct m_tag *mtag;
+#endif
int ctxd = txr->next_avail_desc;
tx_buffer = &txr->tx_buffers[ctxd];
TXD = (struct e1000_adv_tx_context_desc *) &txr->tx_base[ctxd];
- if ((mp->m_pkthdr.csum_flags & CSUM_OFFLOAD) == 0)
- offload = FALSE; /* Only here to handle VLANs */
+ if (mp->m_pkthdr.csum_flags & CSUM_OFFLOAD)
+ offload = TRUE;
+
/*
** In advanced descriptors the vlan tag must
** be placed into the descriptor itself.
*/
+#if __FreeBSD_version < 700000
+ mtag = VLAN_OUTPUT_TAG(ifp, mp);
+ if (mtag != NULL) {
+ vlan_macip_lens |=
+ htole16(VLAN_TAG_VALUE(mtag)) << E1000_ADVTXD_VLAN_SHIFT;
+ offload = TRUE;
+ }
+#else
if (mp->m_flags & M_VLANTAG) {
vtag = htole16(mp->m_pkthdr.ether_vtag);
vlan_macip_lens |= (vtag << E1000_ADVTXD_VLAN_SHIFT);
- } else if (offload == FALSE)
- return FALSE;
+ offload = TRUE;
+ }
+#endif
/*
* Determine where frame payload starts.
* Jump over vlan headers if already present,
@@ -3125,10 +3213,8 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
case ETHERTYPE_IP:
ip = (struct ip *)(mp->m_data + ehdrlen);
ip_hlen = ip->ip_hl << 2;
- if (mp->m_len < ehdrlen + ip_hlen) {
- offload = FALSE;
- break;
- }
+ if (mp->m_len < ehdrlen + ip_hlen)
+ return FALSE;
ipproto = ip->ip_p;
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_IPV4;
break;
@@ -3142,12 +3228,10 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
break;
#ifdef IGB_TIMESYNC
case ETHERTYPE_IEEE1588:
- offload = IGB_TIMESTAMP;
- break;
+ return (IGB_TIMESTAMP);
#endif
default:
- offload = FALSE;
- break;
+ return (FALSE);
}
vlan_macip_lens |= ip_hlen;
@@ -3155,8 +3239,10 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
switch (ipproto) {
case IPPROTO_TCP:
- if (mp->m_pkthdr.csum_flags & CSUM_TCP)
+ if (mp->m_pkthdr.csum_flags & CSUM_TCP) {
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_TCP;
+ offload = TRUE;
+ }
break;
case IPPROTO_UDP:
{
@@ -3165,17 +3251,31 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
struct udphdr *uh = (struct udphdr *)hdr;
if (uh->uh_dport == htons(TSYNC_PORT))
- offload = IGB_TIMESTAMP;
+ return (IGB_TIMESTAMP);
#endif
- if (mp->m_pkthdr.csum_flags & CSUM_UDP)
+ if (mp->m_pkthdr.csum_flags & CSUM_UDP) {
type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_UDP;
+ offload = TRUE;
+ }
break;
}
- default:
- offload = FALSE;
+#if __FreeBSD_version >= 800000
+ case IPPROTO_SCTP:
+ {
+ if (mp->m_pkthdr.csum_flags & CSUM_SCTP) {
+ type_tucmd_mlhl |= E1000_ADVTXD_TUCMD_L4T_SCTP;
+ offload = TRUE;
+ }
break;
+ }
+#endif
+ default:
+ return (FALSE);
}
+ if (offload != TRUE)
+ return (FALSE);
+
/* Now copy bits into descriptor */
TXD->vlan_macip_lens |= htole32(vlan_macip_lens);
TXD->type_tucmd_mlhl |= htole32(type_tucmd_mlhl);
@@ -3191,7 +3291,7 @@ igb_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
txr->next_avail_desc = ctxd;
--txr->tx_avail;
- return (offload);
+ return (TRUE);
}
@@ -3208,7 +3308,7 @@ igb_txeof(struct tx_ring *txr)
{
struct adapter *adapter = txr->adapter;
int first, last, done, num_avail;
- struct igb_buffer *tx_buffer;
+ struct igb_tx_buffer *tx_buffer;
struct e1000_tx_desc *tx_desc, *eop_desc;
struct ifnet *ifp = adapter->ifp;
@@ -3304,55 +3404,113 @@ igb_txeof(struct tx_ring *txr)
/*********************************************************************
*
- * Get a buffer from system mbuf buffer pool.
+ * Setup descriptor buffer(s) from system mbuf buffer pools.
+ * i - designates the ring index
+ * clean - tells the function whether to update
+ * the header, the packet buffer, or both.
*
**********************************************************************/
static int
-igb_get_buf(struct rx_ring *rxr, int i)
+igb_get_buf(struct rx_ring *rxr, int i, u8 clean)
{
struct adapter *adapter = rxr->adapter;
- struct mbuf *m;
- bus_dma_segment_t segs[1];
+ struct mbuf *mh, *mp;
+ bus_dma_segment_t seg[2];
bus_dmamap_t map;
- struct igb_buffer *rx_buffer;
+ struct igb_rx_buffer *rx_buffer;
int error, nsegs;
+ int merr = 0;
- m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
- if (m == NULL) {
- adapter->mbuf_cluster_failed++;
- return (ENOBUFS);
- }
- m->m_len = m->m_pkthdr.len = MCLBYTES;
- if (adapter->max_frame_size <= (MCLBYTES - ETHER_ALIGN))
- m_adj(m, ETHER_ALIGN);
+ rx_buffer = &rxr->rx_buffers[i];
+ /* First get our header and payload mbuf */
+ if (clean & IGB_CLEAN_HEADER) {
+ mh = m_gethdr(M_DONTWAIT, MT_DATA);
+ if (mh == NULL)
+ goto remap;
+ } else /* reuse */
+ mh = rxr->rx_buffers[i].m_head;
+
+ mh->m_len = MHLEN;
+ mh->m_flags |= M_PKTHDR;
+
+ if (clean & IGB_CLEAN_PAYLOAD) {
+ mp = m_getjcl(M_DONTWAIT, MT_DATA,
+ M_PKTHDR, adapter->rx_mbuf_sz);
+ if (mp == NULL)
+ goto remap;
+ mp->m_len = adapter->rx_mbuf_sz;
+ mp->m_flags &= ~M_PKTHDR;
+ } else { /* reusing */
+ mp = rxr->rx_buffers[i].m_pack;
+ mp->m_len = adapter->rx_mbuf_sz;
+ mp->m_flags &= ~M_PKTHDR;
+ }
/*
- * Using memory from the mbuf cluster pool, invoke the
- * bus_dma machinery to arrange the memory mapping.
- */
+ ** Need to create a chain for the following
+ ** dmamap call at this point.
+ */
+ mh->m_next = mp;
+ mh->m_pkthdr.len = mh->m_len + mp->m_len;
+
+ /* Get the memory mapping */
error = bus_dmamap_load_mbuf_sg(rxr->rxtag,
- rxr->rx_spare_map, m, segs, &nsegs, BUS_DMA_NOWAIT);
+ rxr->rx_spare_map, mh, seg, &nsegs, BUS_DMA_NOWAIT);
if (error != 0) {
- m_free(m);
+ printf("GET BUF: dmamap load failure - %d\n", error);
+ m_free(mh);
return (error);
}
- /* If nsegs is wrong then the stack is corrupt. */
- KASSERT(nsegs == 1, ("Too many segments returned!"));
-
- rx_buffer = &rxr->rx_buffers[i];
+ /* Unload old mapping and update buffer struct */
if (rx_buffer->m_head != NULL)
- bus_dmamap_unload(rxr->rxtag, rx_buffer->map);
-
+ bus_dmamap_unload(rxr->rxtag, rx_buffer->map);
map = rx_buffer->map;
rx_buffer->map = rxr->rx_spare_map;
rxr->rx_spare_map = map;
- bus_dmamap_sync(rxr->rxtag, rx_buffer->map, BUS_DMASYNC_PREREAD);
- rx_buffer->m_head = m;
+ rx_buffer->m_head = mh;
+ rx_buffer->m_pack = mp;
+ bus_dmamap_sync(rxr->rxtag,
+ rx_buffer->map, BUS_DMASYNC_PREREAD);
+
+ /* Update descriptor */
+ rxr->rx_base[i].read.hdr_addr = htole64(seg[0].ds_addr);
+ rxr->rx_base[i].read.pkt_addr = htole64(seg[1].ds_addr);
- rxr->rx_base[i].read.pkt_addr = htole64(segs[0].ds_addr);
return (0);
+
+ /*
+ ** If we get here, we have an mbuf resource
+ ** issue, so we discard the incoming packet
+ ** and attempt to reuse existing mbufs next
+ ** pass thru the ring, but to do so we must
+ ** fix up the descriptor which had the address
+ ** clobbered with writeback info.
+ */
+remap:
+ adapter->mbuf_header_failed++;
+ merr = ENOBUFS;
+ /* Is there a reusable buffer? */
+ mh = rxr->rx_buffers[i].m_head;
+ if (mh == NULL) /* Nope, init error */
+ return (merr);
+ mp = rxr->rx_buffers[i].m_pack;
+ if (mp == NULL) /* Nope, init error */
+ return (merr);
+ /* Get our old mapping */
+ rx_buffer = &rxr->rx_buffers[i];
+ error = bus_dmamap_load_mbuf_sg(rxr->rxtag,
+ rx_buffer->map, mh, seg, &nsegs, BUS_DMA_NOWAIT);
+ if (error != 0) {
+ /* We really have a problem */
+ m_free(mh);
+ return (error);
+ }
+ /* Now fix the descriptor as needed */
+ rxr->rx_base[i].read.hdr_addr = htole64(seg[0].ds_addr);
+ rxr->rx_base[i].read.pkt_addr = htole64(seg[1].ds_addr);
+ return (merr);
}
@@ -3369,31 +3527,36 @@ igb_allocate_receive_buffers(struct rx_ring *rxr)
{
struct adapter *adapter = rxr->adapter;
device_t dev = adapter->dev;
- struct igb_buffer *rxbuf;
+ struct igb_rx_buffer *rxbuf;
int i, bsize, error;
- bsize = sizeof(struct igb_buffer) * adapter->num_rx_desc;
+ bsize = sizeof(struct igb_rx_buffer) * adapter->num_rx_desc;
if (!(rxr->rx_buffers =
- (struct igb_buffer *) malloc(bsize,
+ (struct igb_rx_buffer *) malloc(bsize,
M_DEVBUF, M_NOWAIT | M_ZERO))) {
device_printf(dev, "Unable to allocate rx_buffer memory\n");
error = ENOMEM;
goto fail;
}
+ /*
+ ** The tag is made to accomodate the largest buffer size
+ ** with packet split (hence the two segments, even though
+ ** it may not always use this.
+ */
if ((error = bus_dma_tag_create(NULL, /* parent */
PAGE_SIZE, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
- MCLBYTES, /* maxsize */
- 1, /* nsegments */
- MCLBYTES, /* maxsegsize */
+ MJUM16BYTES, /* maxsize */
+ 2, /* nsegments */
+ MJUMPAGESIZE, /* maxsegsize */
0, /* flags */
NULL, /* lockfunc */
NULL, /* lockfuncarg */
&rxr->rxtag))) {
- device_printf(dev, "Unable to create RX Small DMA tag\n");
+ device_printf(dev, "Unable to create RX DMA tag\n");
goto fail;
}
@@ -3401,7 +3564,8 @@ igb_allocate_receive_buffers(struct rx_ring *rxr)
error = bus_dmamap_create(rxr->rxtag, BUS_DMA_NOWAIT,
&rxr->rx_spare_map);
if (error) {
- device_printf(dev, "%s: bus_dmamap_create failed: %d\n",
+ device_printf(dev,
+ "%s: bus_dmamap_create header spare failed: %d\n",
__func__, error);
goto fail;
}
@@ -3411,7 +3575,7 @@ igb_allocate_receive_buffers(struct rx_ring *rxr)
error = bus_dmamap_create(rxr->rxtag,
BUS_DMA_NOWAIT, &rxbuf->map);
if (error) {
- device_printf(dev, "Unable to create Small RX DMA map\n");
+ device_printf(dev, "Unable to create RX DMA maps\n");
goto fail;
}
}
@@ -3434,36 +3598,40 @@ igb_setup_receive_ring(struct rx_ring *rxr)
{
struct adapter *adapter;
device_t dev;
- struct igb_buffer *rxbuf;
+ struct igb_rx_buffer *rxbuf;
struct lro_ctrl *lro = &rxr->lro;
- int j, rsize;
+ int j, rsize;
adapter = rxr->adapter;
dev = adapter->dev;
- rsize = roundup2(adapter->num_rx_desc *
- sizeof(union e1000_adv_rx_desc), 4096);
+
/* Clear the ring contents */
+ rsize = roundup2(adapter->num_rx_desc *
+ sizeof(union e1000_adv_rx_desc), IGB_DBA_ALIGN);
bzero((void *)rxr->rx_base, rsize);
/*
- ** Free current RX buffers: the size buffer
- ** that is loaded is indicated by the buffer
- ** bigbuf value.
+ ** Free current RX buffer structures and their mbufs
*/
for (int i = 0; i < adapter->num_rx_desc; i++) {
rxbuf = &rxr->rx_buffers[i];
- if (rxbuf->m_head != NULL) {
- bus_dmamap_sync(rxr->rxtag, rxbuf->map,
- BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(rxr->rxtag, rxbuf->map);
+ bus_dmamap_sync(rxr->rxtag, rxbuf->map,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(rxr->rxtag, rxbuf->map);
+ if (rxbuf->m_head) {
+ rxbuf->m_head->m_next = rxbuf->m_pack;
m_freem(rxbuf->m_head);
- rxbuf->m_head = NULL;
}
+ rxbuf->m_head = NULL;
+ rxbuf->m_pack = NULL;
}
+ /* Next replenish the ring */
for (j = 0; j < adapter->num_rx_desc; j++) {
- if (igb_get_buf(rxr, j) == ENOBUFS) {
+ if (igb_get_buf(rxr, j, IGB_CLEAN_BOTH) == ENOBUFS) {
rxr->rx_buffers[j].m_head = NULL;
+ rxr->rx_buffers[j].m_pack = NULL;
+ rxr->rx_base[j].read.hdr_addr = 0;
rxr->rx_base[j].read.pkt_addr = 0;
goto fail;
}
@@ -3515,9 +3683,9 @@ static int
igb_setup_receive_structures(struct adapter *adapter)
{
struct rx_ring *rxr = adapter->rx_rings;
- int j;
+ int i, j;
- for (j = 0; j < adapter->num_rx_queues; j++, rxr++)
+ for (i = 0; i < adapter->num_rx_queues; i++, rxr++)
if (igb_setup_receive_ring(rxr))
goto fail;
@@ -3526,13 +3694,14 @@ fail:
/*
* Free RX buffers allocated so far, we will only handle
* the rings that completed, the failing case will have
- * cleaned up for itself. Clean up til 'j', the failure.
+ * cleaned up for itself. The value of 'i' will be the
+ * failed ring so we must pre-decrement it.
*/
- for (int i = 0; i < j; i++) {
- rxr = &adapter->rx_rings[i];
- for (int n = 0; n < adapter->num_rx_desc; n++) {
- struct igb_buffer *rxbuf;
- rxbuf = &rxr->rx_buffers[n];
+ rxr = adapter->rx_rings;
+ for (--i; i > 0; i--, rxr++) {
+ for (j = 0; j < adapter->num_rx_desc; j++) {
+ struct igb_rx_buffer *rxbuf;
+ rxbuf = &rxr->rx_buffers[j];
if (rxbuf->m_head != NULL) {
bus_dmamap_sync(rxr->rxtag, rxbuf->map,
BUS_DMASYNC_POSTREAD);
@@ -3556,7 +3725,7 @@ igb_initialize_receive_units(struct adapter *adapter)
{
struct rx_ring *rxr = adapter->rx_rings;
struct ifnet *ifp = adapter->ifp;
- u32 rctl, rxcsum, psize;
+ u32 rctl, rxcsum, psize, srrctl = 0;
INIT_DEBUGOUT("igb_initialize_receive_unit: begin");
@@ -3567,10 +3736,44 @@ igb_initialize_receive_units(struct adapter *adapter)
rctl = E1000_READ_REG(&adapter->hw, E1000_RCTL);
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl & ~E1000_RCTL_EN);
+ /*
+ ** Set up for header split
+ */
+ if (igb_rx_hdr_split) {
+ /* Use a standard mbuf for the header */
+ srrctl |= IGB_HDR_BUF << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
+ srrctl |= E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
+ } else
+ srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
+
+ /*
+ ** Set up for jumbo frames
+ */
+ if (ifp->if_mtu > ETHERMTU) {
+ rctl |= E1000_RCTL_LPE;
+ srrctl |= 4096 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+ rctl |= E1000_RCTL_SZ_4096 | E1000_RCTL_BSEX;
+
+ /* Set maximum packet len */
+ psize = adapter->max_frame_size;
+ /* are we on a vlan? */
+#if __FreeBSD_version >= 700000
+ if (adapter->ifp->if_vlantrunk != NULL)
+#else
+ if (adapter->ifp->if_nvlans != 0)
+#endif
+ psize += VLAN_TAG_SIZE;
+ E1000_WRITE_REG(&adapter->hw, E1000_RLPML, psize);
+ } else {
+ rctl &= ~E1000_RCTL_LPE;
+ srrctl |= 2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+ rctl |= E1000_RCTL_SZ_2048;
+ }
+
/* Setup the Base and Length of the Rx Descriptor Rings */
for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) {
u64 bus_addr = rxr->rxdma.dma_paddr;
- u32 rxdctl, srrctl;
+ u32 rxdctl;
E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(i),
adapter->num_rx_desc * sizeof(struct e1000_rx_desc));
@@ -3578,9 +3781,6 @@ igb_initialize_receive_units(struct adapter *adapter)
(uint32_t)(bus_addr >> 32));
E1000_WRITE_REG(&adapter->hw, E1000_RDBAL(i),
(uint32_t)bus_addr);
- /* Use Advanced Descriptor type */
- srrctl = E1000_READ_REG(&adapter->hw, E1000_SRRCTL(i));
- srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
E1000_WRITE_REG(&adapter->hw, E1000_SRRCTL(i), srrctl);
/* Enable this Queue */
rxdctl = E1000_READ_REG(&adapter->hw, E1000_RXDCTL(i));
@@ -3595,6 +3795,7 @@ igb_initialize_receive_units(struct adapter *adapter)
/*
** Setup for RX MultiQueue
*/
+ rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM);
if (adapter->num_rx_queues >1) {
u32 random[10], mrqc, shift = 0;
union igb_reta {
@@ -3611,7 +3812,7 @@ igb_initialize_receive_units(struct adapter *adapter)
(i % adapter->num_rx_queues) << shift;
if ((i & 3) == 3)
E1000_WRITE_REG(&adapter->hw,
- E1000_RETA(i & ~3), reta.dword);
+ E1000_RETA(i >> 2), reta.dword);
}
/* Now fill in hash table */
mrqc = E1000_MRQC_ENABLE_RSS_4Q;
@@ -3636,14 +3837,25 @@ igb_initialize_receive_units(struct adapter *adapter)
** this is not the same as TCP/IP checksums which
** still work.
*/
- rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM);
rxcsum |= E1000_RXCSUM_PCSD;
- E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum);
- } else if (ifp->if_capenable & IFCAP_RXCSUM) {
- rxcsum = E1000_READ_REG(&adapter->hw, E1000_RXCSUM);
- rxcsum |= (E1000_RXCSUM_IPOFL | E1000_RXCSUM_TUOFL);
- E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum);
+#if __FreeBSD_version >= 800000
+ /* For SCTP Offload */
+ if ((adapter->hw.mac.type == e1000_82576)
+ && (ifp->if_capenable & IFCAP_RXCSUM))
+ rxcsum |= E1000_RXCSUM_CRCOFL;
+#endif
+ } else {
+ /* Non RSS setup */
+ if (ifp->if_capenable & IFCAP_RXCSUM) {
+ rxcsum |= E1000_RXCSUM_IPPCSE;
+#if __FreeBSD_version >= 800000
+ if (adapter->hw.mac.type == e1000_82576)
+ rxcsum |= E1000_RXCSUM_CRCOFL;
+#endif
+ } else
+ rxcsum &= ~E1000_RXCSUM_TUOFL;
}
+ E1000_WRITE_REG(&adapter->hw, E1000_RXCSUM, rxcsum);
/* Setup the Receive Control Register */
rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
@@ -3653,39 +3865,9 @@ igb_initialize_receive_units(struct adapter *adapter)
/* Make sure VLAN Filters are off */
rctl &= ~E1000_RCTL_VFE;
-
+ /* Don't store bad packets */
rctl &= ~E1000_RCTL_SBP;
- switch (adapter->rx_buffer_len) {
- default:
- case 2048:
- rctl |= E1000_RCTL_SZ_2048;
- break;
- case 4096:
- rctl |= E1000_RCTL_SZ_4096 |
- E1000_RCTL_BSEX | E1000_RCTL_LPE;
- break;
- case 8192:
- rctl |= E1000_RCTL_SZ_8192 |
- E1000_RCTL_BSEX | E1000_RCTL_LPE;
- break;
- case 16384:
- rctl |= E1000_RCTL_SZ_16384 |
- E1000_RCTL_BSEX | E1000_RCTL_LPE;
- break;
- }
-
- if (ifp->if_mtu > ETHERMTU) {
- /* Set maximum packet len */
- psize = adapter->max_frame_size;
- /* are we on a vlan? */
- if (adapter->ifp->if_vlantrunk != NULL)
- psize += VLAN_TAG_SIZE;
- E1000_WRITE_REG(&adapter->hw, E1000_RLPML, psize);
- rctl |= E1000_RCTL_LPE;
- } else
- rctl &= ~E1000_RCTL_LPE;
-
/* Enable Receives */
E1000_WRITE_REG(&adapter->hw, E1000_RCTL, rctl);
@@ -3730,7 +3912,7 @@ static void
igb_free_receive_buffers(struct rx_ring *rxr)
{
struct adapter *adapter = rxr->adapter;
- struct igb_buffer *rx_buffer;
+ struct igb_rx_buffer *rx_buffer;
INIT_DEBUGOUT("free_receive_structures: begin");
@@ -3780,7 +3962,7 @@ igb_free_receive_buffers(struct rx_ring *rxr)
* We loop at most count times if count is > 0, or until done if
* count < 0.
*
- * Return TRUE if all clean, FALSE otherwise
+ * Return TRUE if more to clean, FALSE otherwise
*********************************************************************/
static bool
igb_rxeof(struct rx_ring *rxr, int count)
@@ -3789,120 +3971,172 @@ igb_rxeof(struct rx_ring *rxr, int count)
struct ifnet *ifp;
struct lro_ctrl *lro = &rxr->lro;
struct lro_entry *queued;
- struct mbuf *mp;
- uint8_t accept_frame = 0;
- uint8_t eop = 0;
- uint16_t len, desc_len, prev_len_adj;
int i;
u32 staterr;
union e1000_adv_rx_desc *cur;
+
IGB_RX_LOCK(rxr);
ifp = adapter->ifp;
i = rxr->next_to_check;
cur = &rxr->rx_base[i];
staterr = cur->wb.upper.status_error;
- bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
- BUS_DMASYNC_POSTREAD);
-
if (!(staterr & E1000_RXD_STAT_DD)) {
IGB_RX_UNLOCK(rxr);
return FALSE;
}
+ /* Sync the ring */
+ bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
+ BUS_DMASYNC_POSTREAD);
+
+ /* Main clean loop */
while ((staterr & E1000_RXD_STAT_DD) &&
(count != 0) &&
(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- struct mbuf *m = NULL;
+ struct mbuf *sendmp, *mh, *mp;
+ u16 hlen, plen, hdr, ptype, len_adj;
+ u8 dopayload, accept_frame, eop;
+
+ accept_frame = 1;
+ hlen = plen = len_adj = 0;
+ sendmp = mh = mp = NULL;
+ ptype = (u16)cur->wb.lower.lo_dword.data;
- mp = rxr->rx_buffers[i].m_head;
- /*
- * Can't defer bus_dmamap_sync(9) because TBI_ACCEPT
- * needs to access the last received byte in the mbuf.
- */
+ /* Sync the buffers */
bus_dmamap_sync(rxr->rxtag, rxr->rx_buffers[i].map,
- BUS_DMASYNC_POSTREAD);
+ BUS_DMASYNC_POSTREAD);
+
+ /*
+ ** The way the hardware is configured to
+ ** split, it will ONLY use the header buffer
+ ** when header split is enabled, otherwise we
+ ** get normal behavior, ie, both header and
+ ** payload are DMA'd into the payload buffer.
+ **
+ ** The fmp test is to catch the case where a
+ ** packet spans multiple descriptors, in that
+ ** case only the first header is valid.
+ */
+ if ((igb_rx_hdr_split) && (rxr->fmp == NULL)){
+ hdr = le16toh(cur->
+ wb.lower.lo_dword.hs_rss.hdr_info);
+ hlen = (hdr & E1000_RXDADV_HDRBUFLEN_MASK) >>
+ E1000_RXDADV_HDRBUFLEN_SHIFT;
+ if (hlen > IGB_HDR_BUF)
+ hlen = IGB_HDR_BUF;
+ plen = le16toh(cur->wb.upper.length);
+ /* Handle the header mbuf */
+ mh = rxr->rx_buffers[i].m_head;
+ mh->m_len = hlen;
+ dopayload = IGB_CLEAN_HEADER;
+ /*
+ ** Get the payload length, this
+ ** could be zero if its a small
+ ** packet.
+ */
+ if (plen) {
+ mp = rxr->rx_buffers[i].m_pack;
+ mp->m_len = plen;
+ mp->m_next = NULL;
+ mp->m_flags &= ~M_PKTHDR;
+ mh->m_next = mp;
+ mh->m_flags |= M_PKTHDR;
+ dopayload = IGB_CLEAN_BOTH;
+ rxr->rx_split_packets++;
+ } else { /* small packets */
+ mh->m_flags &= ~M_PKTHDR;
+ mh->m_next = NULL;
+ }
+ } else {
+ /*
+ ** Either no header split, or a
+ ** secondary piece of a fragmented
+ ** split packet.
+ */
+ mh = rxr->rx_buffers[i].m_pack;
+ mh->m_flags |= M_PKTHDR;
+ mh->m_len = le16toh(cur->wb.upper.length);
+ dopayload = IGB_CLEAN_PAYLOAD;
+ }
- accept_frame = 1;
- prev_len_adj = 0;
- desc_len = le16toh(cur->wb.upper.length);
if (staterr & E1000_RXD_STAT_EOP) {
count--;
eop = 1;
- if (desc_len < ETHER_CRC_LEN) {
- len = 0;
- prev_len_adj = ETHER_CRC_LEN - desc_len;
- } else
- len = desc_len - ETHER_CRC_LEN;
- } else {
+ /*
+ ** Strip CRC and account for frag
+ */
+ if (mp) {
+ if (mp->m_len < ETHER_CRC_LEN) {
+ /* a frag, how much is left? */
+ len_adj = ETHER_CRC_LEN - mp->m_len;
+ mp->m_len = 0;
+ } else
+ mp->m_len -= ETHER_CRC_LEN;
+ } else { /* not split */
+ if (mh->m_len < ETHER_CRC_LEN) {
+ len_adj = ETHER_CRC_LEN - mh->m_len;
+ mh->m_len = 0;
+ } else
+ mh->m_len -= ETHER_CRC_LEN;
+ }
+ } else
eop = 0;
- len = desc_len;
- }
-
- if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) {
- u32 pkt_len = desc_len;
-
- if (rxr->fmp != NULL)
- pkt_len += rxr->fmp->m_pkthdr.len;
+ if (staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK)
accept_frame = 0;
- }
if (accept_frame) {
- if (igb_get_buf(rxr, i) != 0) {
+ if (igb_get_buf(rxr, i, dopayload) != 0) {
ifp->if_iqdrops++;
goto discard;
}
-
- /* Assign correct length to the current fragment */
- mp->m_len = len;
-
+ /* Initial frame - setup */
if (rxr->fmp == NULL) {
- mp->m_pkthdr.len = len;
- rxr->fmp = mp; /* Store the first mbuf */
- rxr->lmp = mp;
+ mh->m_flags |= M_PKTHDR;
+ mh->m_pkthdr.len = mh->m_len;
+ rxr->fmp = mh; /* Store the first mbuf */
+ rxr->lmp = mh;
+ if (mp) { /* Add payload if split */
+ mh->m_pkthdr.len += mp->m_len;
+ rxr->lmp = mh->m_next;
+ }
} else {
/* Chain mbuf's together */
- mp->m_flags &= ~M_PKTHDR;
- /*
- * Adjust length of previous mbuf in chain if
- * we received less than 4 bytes in the last
- * descriptor.
- */
- if (prev_len_adj > 0) {
- rxr->lmp->m_len -= prev_len_adj;
- rxr->fmp->m_pkthdr.len -=
- prev_len_adj;
- }
- rxr->lmp->m_next = mp;
+ mh->m_flags &= ~M_PKTHDR;
+ rxr->lmp->m_next = mh;
rxr->lmp = rxr->lmp->m_next;
- rxr->fmp->m_pkthdr.len += len;
+ rxr->fmp->m_pkthdr.len += mh->m_len;
+ /* Adjust for CRC frag */
+ if (len_adj) {
+ rxr->lmp->m_len -= len_adj;
+ rxr->fmp->m_pkthdr.len -= len_adj;
+ }
}
if (eop) {
+ bool sctp = ((ptype & 0x40) != 0);
rxr->fmp->m_pkthdr.rcvif = ifp;
ifp->if_ipackets++;
rxr->rx_packets++;
+ /* capture data for AIM */
rxr->bytes += rxr->fmp->m_pkthdr.len;
- rxr->rx_bytes += rxr->bytes;
-
- igb_rx_checksum(staterr, rxr->fmp);
-#ifndef __NO_STRICT_ALIGNMENT
- if (adapter->max_frame_size >
- (MCLBYTES - ETHER_ALIGN) &&
- igb_fixup_rx(rxr) != 0)
- goto skip;
-#endif
+ rxr->rx_bytes += rxr->fmp->m_pkthdr.len;
+
+ igb_rx_checksum(staterr, rxr->fmp, sctp);
if (staterr & E1000_RXD_STAT_VP) {
+#if __FreeBSD_version >= 700000
rxr->fmp->m_pkthdr.ether_vtag =
le16toh(cur->wb.upper.vlan);
rxr->fmp->m_flags |= M_VLANTAG;
- }
-#ifndef __NO_STRICT_ALIGNMENT
-skip:
+#else
+ VLAN_INPUT_TAG_NEW(ifp, rxr->fmp,
+ (le16toh(cur->wb.upper.vlan) &
+ E1000_RXD_SPC_VLAN_MASK));
#endif
- m = rxr->fmp;
+ }
+ sendmp = rxr->fmp;
rxr->fmp = NULL;
rxr->lmp = NULL;
}
@@ -3910,23 +4144,27 @@ skip:
ifp->if_ierrors++;
discard:
/* Reuse loaded DMA map and just update mbuf chain */
- mp = rxr->rx_buffers[i].m_head;
- mp->m_len = mp->m_pkthdr.len = MCLBYTES;
+ if (hlen) {
+ mh = rxr->rx_buffers[i].m_head;
+ mh->m_len = MHLEN;
+ mh->m_next = NULL;
+ }
+ mp = rxr->rx_buffers[i].m_pack;
+ mp->m_len = mp->m_pkthdr.len = adapter->rx_mbuf_sz;
mp->m_data = mp->m_ext.ext_buf;
mp->m_next = NULL;
if (adapter->max_frame_size <=
(MCLBYTES - ETHER_ALIGN))
m_adj(mp, ETHER_ALIGN);
if (rxr->fmp != NULL) {
+ /* handles the whole chain */
m_freem(rxr->fmp);
rxr->fmp = NULL;
rxr->lmp = NULL;
}
- m = NULL;
+ sendmp = NULL;
}
- /* Zero out the receive descriptors status. */
- cur->wb.upper.status_error = 0;
bus_dmamap_sync(rxr->rxdma.dma_tag, rxr->rxdma.dma_map,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -3935,16 +4173,19 @@ discard:
/* Advance our pointers to the next descriptor. */
if (++i == adapter->num_rx_desc)
i = 0;
-
- if (m != NULL) {
- rxr->next_to_check = i;
+
+ /*
+ ** Note that we hold the RX lock thru
+ ** the following call so this ring's
+ ** next_to_check is not gonna change.
+ */
+ if (sendmp != NULL) {
/* Use LRO if possible */
- if ((!lro->lro_cnt) || (tcp_lro_rx(lro, m, 0))) {
+ if ((!lro->lro_cnt) || (tcp_lro_rx(lro, sendmp, 0)))
/* Pass up to the stack */
- (*ifp->if_input)(ifp, m);
- i = rxr->next_to_check;
- }
+ (*ifp->if_input)(ifp, sendmp);
}
+
/* Get the next descriptor */
cur = &rxr->rx_base[i];
staterr = cur->wb.upper.status_error;
@@ -3965,60 +4206,18 @@ discard:
IGB_RX_UNLOCK(rxr);
- if (!((staterr) & E1000_RXD_STAT_DD))
- return FALSE;
-
- return TRUE;
-}
-
-#ifndef __NO_STRICT_ALIGNMENT
-/*
- * When jumbo frames are enabled we should realign entire payload on
- * architecures with strict alignment. This is serious design mistake of 8254x
- * as it nullifies DMA operations. 8254x just allows RX buffer size to be
- * 2048/4096/8192/16384. What we really want is 2048 - ETHER_ALIGN to align its
- * payload. On architecures without strict alignment restrictions 8254x still
- * performs unaligned memory access which would reduce the performance too.
- * To avoid copying over an entire frame to align, we allocate a new mbuf and
- * copy ethernet header to the new mbuf. The new mbuf is prepended into the
- * existing mbuf chain.
- *
- * Be aware, best performance of the 8254x is achived only when jumbo frame is
- * not used at all on architectures with strict alignment.
- */
-static int
-igb_fixup_rx(struct rx_ring *rxr)
-{
- struct adapter *adapter = rxr->adapter;
- struct mbuf *m, *n;
- int error;
-
- error = 0;
- m = rxr->fmp;
- if (m->m_len <= (MCLBYTES - ETHER_HDR_LEN)) {
- bcopy(m->m_data, m->m_data + ETHER_HDR_LEN, m->m_len);
- m->m_data += ETHER_HDR_LEN;
- } else {
- MGETHDR(n, M_DONTWAIT, MT_DATA);
- if (n != NULL) {
- bcopy(m->m_data, n->m_data, ETHER_HDR_LEN);
- m->m_data += ETHER_HDR_LEN;
- m->m_len -= ETHER_HDR_LEN;
- n->m_len = ETHER_HDR_LEN;
- M_MOVE_PKTHDR(n, m);
- n->m_next = m;
- rxr->fmp = n;
- } else {
- adapter->dropped_pkts++;
- m_freem(rxr->fmp);
- rxr->fmp = NULL;
- error = ENOMEM;
- }
+ /*
+ ** We still have cleaning to do?
+ ** Schedule another interrupt if so.
+ */
+ if (staterr & E1000_RXD_STAT_DD) {
+ E1000_WRITE_REG(&adapter->hw, E1000_EICS, rxr->eims);
+ return TRUE;
}
- return (error);
+ return FALSE;
}
-#endif
+
/*********************************************************************
*
@@ -4028,7 +4227,7 @@ igb_fixup_rx(struct rx_ring *rxr)
*
*********************************************************************/
static void
-igb_rx_checksum(u32 staterr, struct mbuf *mp)
+igb_rx_checksum(u32 staterr, struct mbuf *mp, bool sctp)
{
u16 status = (u16)staterr;
u8 errors = (u8) (staterr >> 24);
@@ -4045,17 +4244,21 @@ igb_rx_checksum(u32 staterr, struct mbuf *mp)
/* IP Checksum Good */
mp->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
mp->m_pkthdr.csum_flags |= CSUM_IP_VALID;
-
} else
mp->m_pkthdr.csum_flags = 0;
}
- if (status & E1000_RXD_STAT_TCPCS) {
+ if (status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS)) {
+ u16 type = (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
+#if __FreeBSD_version >= 800000
+ if (sctp) /* reassign */
+ type = CSUM_SCTP_VALID;
+#endif
/* Did it pass? */
if (!(errors & E1000_RXD_ERR_TCPE)) {
- mp->m_pkthdr.csum_flags |=
- (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
- mp->m_pkthdr.csum_data = htons(0xffff);
+ mp->m_pkthdr.csum_flags = type;
+ if (!sctp)
+ mp->m_pkthdr.csum_data = htons(0xffff);
}
}
return;
@@ -4071,10 +4274,6 @@ igb_register_vlan(void *unused, struct ifnet *ifp, u16 vtag)
struct adapter *adapter = ifp->if_softc;
u32 ctrl, rctl, index, vfta;
- /* Shouldn't happen */
- if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)
- return;
-
ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
ctrl |= E1000_CTRL_VME;
E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
@@ -4107,10 +4306,6 @@ igb_unregister_vlan(void *unused, struct ifnet *ifp, u16 vtag)
struct adapter *adapter = ifp->if_softc;
u32 index, vfta;
- /* Shouldn't happen */
- if ((ifp->if_capenable & IFCAP_VLAN_HWFILTER) == 0)
- return;
-
/* Remove entry in the hardware filter table */
index = ((vtag >> 5) & 0x7F);
vfta = E1000_READ_REG_ARRAY(&adapter->hw, E1000_VFTA, index);
@@ -4172,8 +4367,6 @@ igb_disable_intr(struct adapter *adapter)
static void
igb_init_manageability(struct adapter *adapter)
{
- /* A shared code workaround */
-#define E1000_82542_MANC2H E1000_MANC2H
if (adapter->has_manage) {
int manc2h = E1000_READ_REG(&adapter->hw, E1000_MANC2H);
int manc = E1000_READ_REG(&adapter->hw, E1000_MANC);
@@ -4183,12 +4376,9 @@ igb_init_manageability(struct adapter *adapter)
/* enable receiving management packets to the host */
manc |= E1000_MANC_EN_MNG2HOST;
-#define E1000_MNG2HOST_PORT_623 (1 << 5)
-#define E1000_MNG2HOST_PORT_664 (1 << 6)
- manc2h |= E1000_MNG2HOST_PORT_623;
- manc2h |= E1000_MNG2HOST_PORT_664;
+ manc2h |= 1 << 5; /* Mng Port 623 */
+ manc2h |= 1 << 6; /* Mng Port 664 */
E1000_WRITE_REG(&adapter->hw, E1000_MANC2H, manc2h);
-
E1000_WRITE_REG(&adapter->hw, E1000_MANC, manc);
}
}
@@ -4430,6 +4620,8 @@ igb_print_debug_info(struct adapter *adapter)
E1000_READ_REG(&adapter->hw, E1000_RDT(i)));
device_printf(dev, "RX(%d) Packets received = %lld\n", rxr->me,
(long long)rxr->rx_packets);
+ device_printf(dev, "RX(%d) Split Packets = %lld\n", rxr->me,
+ (long long)rxr->rx_split_packets);
device_printf(dev, "RX(%d) Byte count = %lld\n", rxr->me,
(long long)rxr->rx_bytes);
device_printf(dev, "RX(%d) MSIX IRQ Handled = %lld\n", rxr->me,
@@ -4442,10 +4634,12 @@ igb_print_debug_info(struct adapter *adapter)
device_printf(dev, "LINK MSIX IRQ Handled = %u\n", adapter->link_irq);
- device_printf(dev, "Std mbuf failed = %ld\n",
- adapter->mbuf_alloc_failed);
- device_printf(dev, "Std mbuf cluster failed = %ld\n",
- adapter->mbuf_cluster_failed);
+ device_printf(dev, "Mbuf defrag failed = %ld\n",
+ adapter->mbuf_defrag_failed);
+ device_printf(dev, "Std mbuf header failed = %ld\n",
+ adapter->mbuf_header_failed);
+ device_printf(dev, "Std mbuf packet failed = %ld\n",
+ adapter->mbuf_packet_failed);
device_printf(dev, "Driver dropped packets = %ld\n",
adapter->dropped_pkts);
device_printf(dev, "Driver tx dma failure in xmit = %ld\n",
diff --git a/sys/dev/e1000/if_igb.h b/sys/dev/e1000/if_igb.h
index c0e5aaa..025a03c 100644
--- a/sys/dev/e1000/if_igb.h
+++ b/sys/dev/e1000/if_igb.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -172,7 +172,7 @@
#define IGB_DEFAULT_PBA 0x00000030
#define IGB_SMARTSPEED_DOWNSHIFT 3
#define IGB_SMARTSPEED_MAX 15
-#define IGB_MAX_INTR 10
+#define IGB_MAX_LOOP 10
#define IGB_RX_PTHRESH 16
#define IGB_RX_HTHRESH 8
#define IGB_RX_WTHRESH 1
@@ -184,14 +184,18 @@
#define IGB_FC_PAUSE_TIME 0x0680
#define IGB_EEPROM_APME 0x400;
-#define MAX_INTS_PER_SEC 8000
-#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256)
-
/* Code compatilbility between 6 and 7 */
#ifndef ETHER_BPF_MTAP
#define ETHER_BPF_MTAP BPF_MTAP
#endif
+#if __FreeBSD_version < 700000
+#define CSUM_TSO 0
+#define IFCAP_TSO4 0
+#define FILTER_STRAY
+#define FILTER_HANDLED
+#endif
+
/*
* TDBA/RDBA should be aligned on 16 byte boundary. But TDLEN/RDLEN should be
* multiple of 128 bytes. So we align TDBA/RDBA on 128 byte boundary. This will
@@ -230,9 +234,21 @@
#define IGB_MAX_SCATTER 64
#define IGB_TSO_SIZE (65535 + sizeof(struct ether_vlan_header))
#define IGB_TSO_SEG_SIZE 4096 /* Max dma segment size */
+#define IGB_HDR_BUF 128
#define ETH_ZLEN 60
#define ETH_ADDR_LEN 6
-#define CSUM_OFFLOAD 7 /* Offload bits in mbuf flag */
+
+/* Offload bits in mbuf flag */
+#if __FreeBSD_version >= 800000
+#define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP|CSUM_SCTP)
+#else
+#define CSUM_OFFLOAD (CSUM_IP|CSUM_TCP|CSUM_UDP)
+#endif
+
+/* Header split codes for get_buf */
+#define IGB_CLEAN_HEADER 1
+#define IGB_CLEAN_PAYLOAD 2
+#define IGB_CLEAN_BOTH 3
/*
* Interrupt Moderation parameters
@@ -305,7 +321,7 @@ struct tx_ring {
u32 next_avail_desc;
u32 next_to_clean;
volatile u16 tx_avail;
- struct igb_buffer *tx_buffers;
+ struct igb_tx_buffer *tx_buffers;
bus_dma_tag_t txtag; /* dma tag for tx */
u32 watchdog_timer;
u64 no_desc_avail;
@@ -329,7 +345,7 @@ struct rx_ring {
char mtx_name[16];
u32 last_cleaned;
u32 next_to_check;
- struct igb_buffer *rx_buffers;
+ struct igb_rx_buffer *rx_buffers;
bus_dma_tag_t rxtag; /* dma tag for tx */
bus_dmamap_t rx_spare_map;
/*
@@ -344,6 +360,7 @@ struct rx_ring {
/* Soft stats */
u64 rx_irq;
+ u64 rx_split_packets;
u64 rx_packets;
u64 rx_bytes;
};
@@ -380,6 +397,7 @@ struct adapter {
struct taskqueue *tq; /* private task queue */
eventhandler_tag vlan_attach;
eventhandler_tag vlan_detach;
+
/* Management and WOL features */
int wol;
int has_manage;
@@ -402,15 +420,18 @@ struct adapter {
* Receive rings
*/
struct rx_ring *rx_rings;
+ bool rx_hdr_split;
u16 num_rx_desc;
u16 num_rx_queues;
int rx_process_limit;
- u32 rx_buffer_len;
+ u32 rx_mbuf_sz;
+ u32 rx_mask;
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
- unsigned long mbuf_alloc_failed;
- unsigned long mbuf_cluster_failed;
+ unsigned long mbuf_defrag_failed;
+ unsigned long mbuf_header_failed;
+ unsigned long mbuf_packet_failed;
unsigned long no_tx_map_avail;
unsigned long no_tx_dma_setup;
unsigned long watchdog_events;
@@ -443,12 +464,18 @@ typedef struct _igb_vendor_info_t {
} igb_vendor_info_t;
-struct igb_buffer {
+struct igb_tx_buffer {
int next_eop; /* Index of the desc to watch */
struct mbuf *m_head;
bus_dmamap_t map; /* bus_dma map for packet */
};
+struct igb_rx_buffer {
+ struct mbuf *m_head;
+ struct mbuf *m_pack;
+ bus_dmamap_t map; /* bus_dma map for packet */
+};
+
#define IGB_CORE_LOCK_INIT(_sc, _name) \
mtx_init(&(_sc)->core_mtx, _name, "IGB Core Lock", MTX_DEF)
#define IGB_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx)
diff --git a/sys/dev/ed/ax88x90reg.h b/sys/dev/ed/ax88x90reg.h
index 9d2eeed..d28d5aa 100644
--- a/sys/dev/ed/ax88x90reg.h
+++ b/sys/dev/ed/ax88x90reg.h
@@ -30,7 +30,7 @@
/* AX88x90 based miibus defines */
#define ED_AX88X90_MIIBUS 0x04 /* MII bus register on ASIC */
#define ED_AX88X90_MII_CLK 0x01
-#define ED_AX88X90_MII_DIROUT 0x02
+#define ED_AX88X90_MII_DIRIN 0x02
#define ED_AX88X90_MII_DATAIN 0x04
#define ED_AX88X90_MII_DATAOUT 0x08
#define ED_AX88X90_TEST 0x05 /* "test" register on asic */
diff --git a/sys/dev/ed/dl100xxreg.h b/sys/dev/ed/dl100xxreg.h
index a4659b0..3b9f1c9 100644
--- a/sys/dev/ed/dl100xxreg.h
+++ b/sys/dev/ed/dl100xxreg.h
@@ -29,14 +29,15 @@
/* Dlink chipset used on some Netgear and Dlink PCMCIA cards */
#define ED_DL100XX_MIIBUS 0x0c /* MII bus register on ASIC */
-#define ED_DL100XX_DIAG 0x0d
-#define ED_DL100XX_COLLISON_DIS 4 /* Disable collision detection */
+#define ED_DL10022_DIAG 0x0d
+#define ED_DL10022_COLLISON_DIS 4 /* Disable collision detection */
-#define ED_DL100XX_MII_RESET1 0x04
-#define ED_DL100XX_MII_RESET2 0x08
+#define ED_DL10022_MII_RESET1 0x04
+#define ED_DL10022_MII_RESET2 0x08
#define ED_DL100XX_MII_DATAIN 0x10
-#define ED_DL100XX_MII_DIROUT_22 0x20
-#define ED_DL100XX_MII_DIROUT_19 0x10
+#define ED_DL10022_MII_DIROUT 0x20
+#define ED_DL10019_MII_DIROUT 0x10
+#define ED_DL100XX_MII_DIROUT (ED_DL10022_MII_DIROUT | ED_DL10019_MII_DIROUT)
#define ED_DL100XX_MII_DATAOUT 0x40
#define ED_DL100XX_MII_CLK 0x80
diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c
index a11beda..f9a32bf 100644
--- a/sys/dev/ed/if_ed.c
+++ b/sys/dev/ed/if_ed.c
@@ -389,8 +389,11 @@ ed_detach(device_t dev)
callout_drain(&sc->tick_ch);
ether_ifdetach(ifp);
}
- bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
+ if (sc->irq_res != NULL && sc->irq_handle)
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
ed_release_resources(dev);
+ if (sc->miibus)
+ device_delete_child(dev, sc->miibus);
ED_LOCK_DESTROY(sc);
bus_generic_detach(dev);
return (0);
@@ -426,10 +429,19 @@ ed_stop_hw(struct ed_softc *sc)
* Wait for interface to enter stopped state, but limit # of checks to
* 'n' (about 5ms). It shouldn't even take 5us on modern DS8390's, but
* just in case it's an old one.
+ *
+ * The AX88x90 chips don't seem to implement this behavor. The
+ * datasheets say it is only turned on when the chip enters a RESET
+ * state and is silent about behavior for the stopped state we just
+ * entered.
*/
- if (sc->chip_type != ED_CHIP_TYPE_AX88190)
- while (((ed_nic_inb(sc, ED_P0_ISR) & ED_ISR_RST) == 0) && --n)
- continue;
+ if (sc->chip_type == ED_CHIP_TYPE_AX88190 ||
+ sc->chip_type == ED_CHIP_TYPE_AX88790)
+ return;
+ while (((ed_nic_inb(sc, ED_P0_ISR) & ED_ISR_RST) == 0) && --n)
+ continue;
+ if (n <= 0)
+ device_printf(sc->dev, "ed_stop_hw RST never set\n");
}
/*
@@ -806,14 +818,15 @@ ed_rint(struct ed_softc *sc)
/*
* Length is a wild value. There's a good chance that
* this was caused by the NIC being old and buggy.
- * The bug is that the length low byte is duplicated in
- * the high byte. Try to recalculate the length based on
- * the pointer to the next packet.
- */
- /*
- * NOTE: sc->next_packet is pointing at the current packet.
+ * The bug is that the length low byte is duplicated
+ * in the high byte. Try to recalculate the length
+ * based on the pointer to the next packet. Also,
+ * need ot preserve offset into page.
+ *
+ * NOTE: sc->next_packet is pointing at the current
+ * packet.
*/
- len &= ED_PAGE_SIZE - 1; /* preserve offset into page */
+ len &= ED_PAGE_SIZE - 1;
if (packet_hdr.next_packet >= sc->next_packet)
len += (packet_hdr.next_packet -
sc->next_packet) * ED_PAGE_SIZE;
@@ -834,14 +847,14 @@ ed_rint(struct ed_softc *sc)
}
/*
- * Be fairly liberal about what we allow as a "reasonable" length
- * so that a [crufty] packet will make it to BPF (and can thus
- * be analyzed). Note that all that is really important is that
- * we have a length that will fit into one mbuf cluster or less;
- * the upper layer protocols can then figure out the length from
- * their own length field(s).
- * But make sure that we have at least a full ethernet header
- * or we would be unable to call ether_input() later.
+ * Be fairly liberal about what we allow as a "reasonable"
+ * length so that a [crufty] packet will make it to BPF (and
+ * can thus be analyzed). Note that all that is really
+ * important is that we have a length that will fit into one
+ * mbuf cluster or less; the upper layer protocols can then
+ * figure out the length from their own length field(s). But
+ * make sure that we have at least a full ethernet header or
+ * we would be unable to call ether_input() later.
*/
if ((len >= sizeof(struct ed_ring) + ETHER_HDR_LEN) &&
(len <= MCLBYTES) &&
@@ -914,10 +927,10 @@ edintr(void *arg)
ed_nic_outb(sc, ED_P0_CR, sc->cr_proto | ED_CR_STA);
/*
- * loop until there are no more new interrupts. When the card
- * goes away, the hardware will read back 0xff. Looking at
- * the interrupts, it would appear that 0xff is impossible,
- * or at least extremely unlikely.
+ * loop until there are no more new interrupts. When the card goes
+ * away, the hardware will read back 0xff. Looking at the interrupts,
+ * it would appear that 0xff is impossible, or at least extremely
+ * unlikely.
*/
while ((isr = ed_nic_inb(sc, ED_P0_ISR)) != 0 && isr != 0xff) {
@@ -928,12 +941,14 @@ edintr(void *arg)
*/
ed_nic_outb(sc, ED_P0_ISR, isr);
- /*
- * XXX workaround for AX88190
+ /*
+ * The AX88190 and AX88190A has problems acking an interrupt
+ * and having them clear. This interferes with top-level loop
+ * here. Wait for all the bits to clear.
+ *
* We limit this to 5000 iterations. At 1us per inb/outb,
- * this translates to about 15ms, which should be plenty
- * of time, and also gives protection in the card eject
- * case.
+ * this translates to about 15ms, which should be plenty of
+ * time, and also gives protection in the card eject case.
*/
if (sc->chip_type == ED_CHIP_TYPE_AX88190) {
count = 5000; /* 15ms */
@@ -1309,7 +1324,7 @@ ed_shmem_readmem16(struct ed_softc *sc, bus_size_t src, uint8_t *dst,
uint16_t amount)
{
bus_space_read_region_2(sc->mem_bst, sc->mem_bsh, src, (uint16_t *)dst,
- amount + 1 / 2);
+ (amount + 1) / 2);
}
/*
@@ -1528,7 +1543,8 @@ ed_setrcr(struct ed_softc *sc)
ED_ASSERT_LOCKED(sc);
/* Bit 6 in AX88190 RCR register must be set. */
- if (sc->chip_type == ED_CHIP_TYPE_AX88190)
+ if (sc->chip_type == ED_CHIP_TYPE_AX88190 ||
+ sc->chip_type == ED_CHIP_TYPE_AX88790)
reg1 = ED_RCR_INTT;
else
reg1 = 0x00;
@@ -1723,3 +1739,38 @@ ed_shmem_write_mbufs(struct ed_softc *sc, struct mbuf *m, bus_size_t dst)
}
return (len);
}
+
+/*
+ * Generic ifmedia support. By default, the DP8390-based cards don't know
+ * what their network attachment really is, or even if it is valid (except
+ * upon successful transmission of a packet). To play nicer with dhclient, as
+ * well as to fit in with a framework where some cards can provde more
+ * detailed information, make sure that we use this as a fallback.
+ */
+static int
+ed_gen_ifmedia_ioctl(struct ed_softc *sc, struct ifreq *ifr, u_long command)
+{
+ return (ifmedia_ioctl(sc->ifp, ifr, &sc->ifmedia, command));
+}
+
+static int
+ed_gen_ifmedia_upd(struct ifnet *ifp)
+{
+ return 0;
+}
+
+static void
+ed_gen_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ ifmr->ifm_active = IFM_ETHER | IFM_AUTO;
+ ifmr->ifm_status = IFM_AVALID | IFM_ACTIVE;
+}
+
+void
+ed_gen_ifmedia_init(struct ed_softc *sc)
+{
+ sc->sc_media_ioctl = &ed_gen_ifmedia_ioctl;
+ ifmedia_init(&sc->ifmedia, 0, ed_gen_ifmedia_upd, ed_gen_ifmedia_sts);
+ ifmedia_add(&sc->ifmedia, IFM_ETHER | IFM_AUTO, 0, 0);
+ ifmedia_set(&sc->ifmedia, IFM_ETHER | IFM_AUTO);
+}
diff --git a/sys/dev/ed/if_ed_cbus.c b/sys/dev/ed/if_ed_cbus.c
index dc4fabb..bcc0d85 100644
--- a/sys/dev/ed/if_ed_cbus.c
+++ b/sys/dev/ed/if_ed_cbus.c
@@ -248,7 +248,8 @@ ed_cbus_attach(dev)
ed_release_resources(dev);
return (error);
}
-
+ if (sc->sc_media_ioctl == NULL)
+ ed_gen_ifmedia_init(sc);
return ed_attach(dev);
}
diff --git a/sys/dev/ed/if_ed_isa.c b/sys/dev/ed/if_ed_isa.c
index 7d30614..1beac27 100644
--- a/sys/dev/ed/if_ed_isa.c
+++ b/sys/dev/ed/if_ed_isa.c
@@ -175,7 +175,8 @@ ed_isa_attach(device_t dev)
ed_release_resources(dev);
return (error);
}
-
+ if (sc->sc_media_ioctl == NULL)
+ ed_gen_ifmedia_init(sc);
return ed_attach(dev);
}
diff --git a/sys/dev/ed/if_ed_pccard.c b/sys/dev/ed/if_ed_pccard.c
index 28ccfc2..fa8a86d 100644
--- a/sys/dev/ed/if_ed_pccard.c
+++ b/sys/dev/ed/if_ed_pccard.c
@@ -45,6 +45,7 @@
* 2 loopback
* 1 gdlink (tpi mode only) 1 tp good, 0 tp bad
* 0 0-no mam, 1 mam connected
+ *
* NS83926 appears to be a NS pcmcia glue chip used on the IBM Ethernet II
* and the NEC PC9801N-J12 ccr base 0x2000!
*
@@ -64,8 +65,6 @@
* 0-1 PHY01 00 auto, 01 res, 10 10B5, 11 TPI
* 2 GDLINK 1 disable checking of link
* 6 LINK 0 bad link, 1 good link
- * TMI tc5299 10/100 chip, has a different MII interaction than
- * dl100xx and ax88x90.
*
* EN5017A, EN5020 no data, but very popular
* Other chips?
@@ -114,9 +113,12 @@
* memory somewhere that isn't in the CIS. Some new chipsets have it
* in special registers in the ASIC part of the chip.
*
- * For those cards that have the MAC adress stored in attribute memory,
- * nearly all of them have it at a fixed offset (0xff0). We use that
- * offset as a source of last resource if other offsets have failed.
+ * For those cards that have the MAC adress stored in attribute memory
+ * outside of a FUNCE entry in the CIS, nearly all of them have it at
+ * a fixed offset (0xff0). We use that offset as a source of last
+ * resource if other offsets have failed. This is the address of the
+ * National Semiconductor DP83903A, which is the only chip's datasheet
+ * I've found.
*/
#define ED_DEFAULT_MAC_OFFSET 0xff0
@@ -126,6 +128,7 @@ static const struct ed_product {
#define NE2000DVF_DL100XX 0x0001 /* chip is D-Link DL10019/22 */
#define NE2000DVF_AX88X90 0x0002 /* chip is ASIX AX88[17]90 */
#define NE2000DVF_TC5299J 0x0004 /* chip is Tamarack TC5299J */
+#define NE2000DVF_TOSHIBA 0x0008 /* Toshiba DP83902A */
#define NE2000DVF_ENADDR 0x0100 /* Get MAC from attr mem */
#define NE2000DVF_ANYFUNC 0x0200 /* Allow any function type */
#define NE2000DVF_MODEM 0x0400 /* Has a modem/serial */
@@ -138,6 +141,7 @@ static const struct ed_product {
{ PCMCIA_CARD(BILLIONTON, CFLT10N), 0},
{ PCMCIA_CARD(BILLIONTON, LNA100B), NE2000DVF_AX88X90},
{ PCMCIA_CARD(BILLIONTON, LNT10TN), 0},
+ { PCMCIA_CARD(BROMAX, AXNET), NE2000DVF_AX88X90},
{ PCMCIA_CARD(BROMAX, IPORT), 0},
{ PCMCIA_CARD(BROMAX, IPORT2), 0},
{ PCMCIA_CARD(BUFFALO, LPC2_CLT), 0},
@@ -161,23 +165,24 @@ static const struct ed_product {
{ PCMCIA_CARD(COREGA, LAPCCTXD), 0},
{ PCMCIA_CARD(DAYNA, COMMUNICARD_E_1), 0},
{ PCMCIA_CARD(DAYNA, COMMUNICARD_E_2), 0},
- { PCMCIA_CARD(DLINK, DE650), 0 },
+ { PCMCIA_CARD(DLINK, DE650), NE2000DVF_ANYFUNC },
{ PCMCIA_CARD(DLINK, DE660), 0 },
{ PCMCIA_CARD(DLINK, DE660PLUS), 0},
{ PCMCIA_CARD(DYNALINK, L10C), 0},
{ PCMCIA_CARD(EDIMAX, EP4000A), 0},
- { PCMCIA_CARD(EPSON, EEN10B), NE2000DVF_ENADDR, 0xff0},
+ { PCMCIA_CARD(EPSON, EEN10B), 0},
{ PCMCIA_CARD(EXP, THINLANCOMBO), 0},
{ PCMCIA_CARD(GLOBALVILLAGE, LANMODEM), 0},
{ PCMCIA_CARD(GREY_CELL, TDK3000), 0},
{ PCMCIA_CARD(GREY_CELL, DMF650TX),
NE2000DVF_ANYFUNC | NE2000DVF_DL100XX | NE2000DVF_MODEM},
{ PCMCIA_CARD(IBM, HOME_AND_AWAY), 0},
- { PCMCIA_CARD(IBM, INFOMOVER), NE2000DVF_ENADDR, 0xff0},
+ { PCMCIA_CARD(IBM, INFOMOVER), 0},
{ PCMCIA_CARD(IODATA3, PCLAT), 0},
{ PCMCIA_CARD(KINGSTON, CIO10T), 0},
{ PCMCIA_CARD(KINGSTON, KNE2), 0},
{ PCMCIA_CARD(LANTECH, FASTNETTX), NE2000DVF_AX88X90},
+ /* Same ID for many different cards, including generic NE2000 */
{ PCMCIA_CARD(LINKSYS, COMBO_ECARD),
NE2000DVF_DL100XX | NE2000DVF_AX88X90},
{ PCMCIA_CARD(LINKSYS, ECARD_1), 0},
@@ -188,6 +193,7 @@ static const struct ed_product {
{ PCMCIA_CARD(MAGICRAM, ETHER), 0},
{ PCMCIA_CARD(MELCO, LPC3_CLX), NE2000DVF_AX88X90},
{ PCMCIA_CARD(MELCO, LPC3_TX), NE2000DVF_AX88X90},
+ { PCMCIA_CARD(MITSUBISHI, B8895), NE2000DVF_ANYFUNC}, /* NG */
{ PCMCIA_CARD(MICRORESEARCH, MR10TPC), 0},
{ PCMCIA_CARD(NDC, ND5100_E), 0},
{ PCMCIA_CARD(NETGEAR, FA410TXC), NE2000DVF_DL100XX},
@@ -206,6 +212,7 @@ static const struct ed_product {
{ PCMCIA_CARD(RACORE, FASTENET), NE2000DVF_AX88X90},
{ PCMCIA_CARD(RACORE, 8041TX), NE2000DVF_AX88X90 | NE2000DVF_TC5299J},
{ PCMCIA_CARD(RELIA, COMBO), 0},
+ { PCMCIA_CARD(RIOS, PCCARD3), 0},
{ PCMCIA_CARD(RPTI, EP400), 0},
{ PCMCIA_CARD(RPTI, EP401), 0},
{ PCMCIA_CARD(SMC, EZCARD), 0},
@@ -223,6 +230,7 @@ static const struct ed_product {
{ PCMCIA_CARD(TELECOMDEVICE, LM5LT), 0 },
{ PCMCIA_CARD(TELECOMDEVICE, TCD_HPC100), NE2000DVF_AX88X90},
{ PCMCIA_CARD(TJ, PTJ_LAN_T), 0 },
+ { PCMCIA_CARD(TOSHIBA2, LANCT00A), NE2000DVF_ANYFUNC | NE2000DVF_TOSHIBA},
{ PCMCIA_CARD(ZONET, ZEN), 0},
{ { NULL } }
};
@@ -232,6 +240,7 @@ static const struct ed_product {
*/
static int ed_pccard_probe(device_t);
static int ed_pccard_attach(device_t);
+static void ed_pccard_tick(void *);
static int ed_pccard_dl100xx(device_t dev, const struct ed_product *);
static void ed_pccard_dl100xx_mii_reset(struct ed_softc *sc);
@@ -240,7 +249,6 @@ static void ed_pccard_dl100xx_mii_writebits(struct ed_softc *sc, u_int val,
int nbits);
static int ed_pccard_ax88x90(device_t dev, const struct ed_product *);
-static void ed_pccard_ax88x90_mii_reset(struct ed_softc *sc);
static u_int ed_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits);
static void ed_pccard_ax88x90_mii_writebits(struct ed_softc *sc, u_int val,
int nbits);
@@ -250,7 +258,6 @@ static int ed_ifmedia_upd(struct ifnet *);
static void ed_ifmedia_sts(struct ifnet *, struct ifmediareq *);
static int ed_pccard_tc5299j(device_t dev, const struct ed_product *);
-static void ed_pccard_tc5299j_mii_reset(struct ed_softc *sc);
static u_int ed_pccard_tc5299j_mii_readbits(struct ed_softc *sc, int nbits);
static void ed_pccard_tc5299j_mii_writebits(struct ed_softc *sc, u_int val,
int nbits);
@@ -359,7 +366,7 @@ ed_pccard_rom_mac(device_t dev, uint8_t *enaddr)
*/
ed_pio_readmem(sc, 0, romdata, 32);
if (bootverbose)
- printf("ROM DATA: %32D\n", romdata, " ");
+ device_printf(dev, "ROM DATA: %32D\n", romdata, " ");
if (romdata[28] != 0x57 || romdata[30] != 0x57)
return (0);
for (i = 0; i < ETHER_ADDR_LEN; i++)
@@ -378,6 +385,26 @@ ed_pccard_add_modem(device_t dev)
}
static int
+ed_pccard_kick_phy(struct ed_softc *sc)
+{
+ struct mii_softc *miisc;
+ struct mii_data *mii;
+
+ /*
+ * Many of the PHYs that wind up on PC Cards are weird in
+ * this way. Generally, we don't need to worry so much about
+ * the Isolation protocol since there's only one PHY in
+ * these designs, so this workaround is reasonable.
+ */
+ mii = device_get_softc(sc->miibus);
+ LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
+ miisc->mii_flags |= MIIF_FORCEANEG;
+ mii_phy_reset(miisc);
+ }
+ return (mii_mediachg(mii));
+}
+
+static int
ed_pccard_media_ioctl(struct ed_softc *sc, struct ifreq *ifr, u_long command)
{
struct mii_data *mii;
@@ -400,40 +427,18 @@ ed_pccard_mediachg(struct ed_softc *sc)
mii_mediachg(mii);
}
-static void
-ed_pccard_tick(void *arg)
-{
- struct ed_softc *sc = arg;
- struct mii_data *mii;
- int media = 0;
-
- ED_ASSERT_LOCKED(sc);
- if (sc->miibus != NULL) {
- mii = device_get_softc(sc->miibus);
- media = mii->mii_media_status;
- mii_tick(mii);
- if (mii->mii_media_status & IFM_ACTIVE &&
- media != mii->mii_media_status && 0 &&
- sc->chip_type == ED_CHIP_TYPE_DL10022) {
- ed_asic_outb(sc, ED_DL100XX_DIAG,
- (mii->mii_media_active & IFM_FDX) ?
- ED_DL100XX_COLLISON_DIS : 0);
- }
-
- }
- callout_reset(&sc->tick_ch, hz, ed_pccard_tick, sc);
-}
-
static int
ed_pccard_attach(device_t dev)
{
u_char sum;
u_char enaddr[ETHER_ADDR_LEN];
const struct ed_product *pp;
- int error, i;
+ int error, i, flags;
struct ed_softc *sc = device_get_softc(dev);
u_long size;
+ static uint16_t *intr_vals[] = {NULL, NULL};
+ sc->dev = dev;
if ((pp = (const struct ed_product *) pccard_product_lookup(dev,
(const struct pccard_product *) ed_pccard_products,
sizeof(ed_pccard_products[0]), NULL)) == NULL)
@@ -464,12 +469,14 @@ ed_pccard_attach(device_t dev)
goto bad;
/*
- * Determine which chipset we are. All the PC Card chipsets have the
- * ASIC and NIC offsets in the same place.
+ * Determine which chipset we are. Almost all the PC Card chipsets
+ * have the Novel ASIC and NIC offsets. There's 2 known cards that
+ * follow the WD80x3 conventions, which are handled as a special case.
*/
sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
sc->nic_offset = ED_NOVELL_NIC_OFFSET;
error = ENXIO;
+ flags = device_get_flags(dev);
if (error != 0)
error = ed_pccard_dl100xx(dev, pp);
if (error != 0)
@@ -477,7 +484,14 @@ ed_pccard_attach(device_t dev)
if (error != 0)
error = ed_pccard_tc5299j(dev, pp);
if (error != 0)
- error = ed_probe_Novell_generic(dev, device_get_flags(dev));
+ error = ed_probe_Novell_generic(dev, flags);
+ if (error != 0 && (pp->flags & NE2000DVF_TOSHIBA)) {
+ flags |= ED_FLAGS_TOSH_ETHER;
+ flags |= ED_FLAGS_PCCARD;
+ sc->asic_offset = ED_WD_ASIC_OFFSET;
+ sc->nic_offset = ED_WD_NIC_OFFSET;
+ error = ed_probe_WD80x3_generic(dev, flags, intr_vals);
+ }
if (error)
goto bad;
@@ -489,16 +503,18 @@ ed_pccard_attach(device_t dev)
}
/*
- * For the older cards, we have to get the MAC address from
- * the card in some way. Let's try the standard PCMCIA way
- * first. If that fails, then check to see if we have valid
- * data from the standard NE-2000 data roms. If that fails,
- * check to see if the card has a hint about where to look in
- * its CIS. If that fails, maybe we should look at some
- * default value. In all fails, we should fail the attach,
- * but don't right now.
+ * There are several ways to get the MAC address for the card.
+ * Some of the above probe routines can fill in the enaddr. If
+ * not, we run through a number of 'well known' locations:
+ * (1) From the PC Card FUNCE
+ * (2) From offset 0 in the shared memory
+ * (3) From a hinted offset in attribute memory
+ * (4) From 0xff0 in attribute memory
+ * If we can't get a non-zero MAC address from this list, we fail.
*/
- if (sc->chip_type == ED_CHIP_TYPE_DP8390) {
+ for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++)
+ sum |= sc->enaddr[i];
+ if (sum == 0) {
pccard_get_ether(dev, enaddr);
if (bootverbose)
device_printf(dev, "CIS MAC %6D\n", enaddr, ":");
@@ -547,16 +563,15 @@ ed_pccard_attach(device_t dev)
ed_pccard_dl100xx_mii_reset(sc);
(void)mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd,
ed_ifmedia_sts);
- } else if (sc->chip_type == ED_CHIP_TYPE_AX88190) {
- ed_pccard_ax88x90_mii_reset(sc);
+ } else if (sc->chip_type == ED_CHIP_TYPE_AX88190 ||
+ sc->chip_type == ED_CHIP_TYPE_AX88790) {
if ((error = mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd,
ed_ifmedia_sts)) != 0) {
- device_printf(dev, "Missing mii!\n");
+ device_printf(dev, "Missing mii %d!\n", error);
goto bad;
}
} else if (sc->chip_type == ED_CHIP_TYPE_TC5299J) {
- ed_pccard_tc5299j_mii_reset(sc);
if ((error = mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd,
ed_ifmedia_sts)) != 0) {
device_printf(dev, "Missing mii!\n");
@@ -568,6 +583,10 @@ ed_pccard_attach(device_t dev)
sc->sc_tick = ed_pccard_tick;
sc->sc_mediachg = ed_pccard_mediachg;
sc->sc_media_ioctl = ed_pccard_media_ioctl;
+ ed_pccard_kick_phy(sc);
+ } else {
+ printf("Generic ifmedia\n");
+ ed_gen_ifmedia_init(sc);
}
if (sc->modem_rid != -1)
ed_pccard_add_modem(dev);
@@ -580,10 +599,6 @@ bad:
/*
* Probe the Ethernet MAC addrees for PCMCIA Linksys EtherFast 10/100
* and compatible cards (DL10019C Ethernet controller).
- *
- * Note: The PAO patches try to use more memory for the card, but that
- * seems to fail for my card. A future optimization would add this back
- * conditionally.
*/
static int
ed_pccard_dl100xx(device_t dev, const struct ed_product *pp)
@@ -591,6 +606,7 @@ ed_pccard_dl100xx(device_t dev, const struct ed_product *pp)
struct ed_softc *sc = device_get_softc(dev);
u_char sum;
uint8_t id;
+ u_int memsize;
int i, error;
if (!(pp->flags & NE2000DVF_DL100XX))
@@ -624,8 +640,26 @@ ed_pccard_dl100xx(device_t dev, const struct ed_product *pp)
ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
id = ed_asic_inb(sc, 0xf);
sc->isa16bit = 1;
- sc->vendor = ED_VENDOR_NOVELL;
+ /*
+ * Hard code values based on the datasheet. We're NE-2000 compatible
+ * NIC with 24kb of packet memory starting at 24k offset. These
+ * cards also work with 16k at 16k, but don't work with 24k at 16k
+ * or 32k at 16k.
+ */
sc->type = ED_TYPE_NE2000;
+ sc->mem_start = 24 * 1024;
+ memsize = sc->mem_size = 24 * 1024;
+ sc->mem_end = sc->mem_start + memsize;
+ sc->tx_page_start = memsize / ED_PAGE_SIZE;
+ sc->txb_cnt = 3;
+ sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
+ sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE;
+
+ sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
+
+ ed_nic_outb(sc, ED_P0_PSTART, sc->mem_start / ED_PAGE_SIZE);
+ ed_nic_outb(sc, ED_P0_PSTOP, sc->mem_end / ED_PAGE_SIZE);
+ sc->vendor = ED_VENDOR_NOVELL;
sc->chip_type = (id & 0x90) == 0x90 ?
ED_CHIP_TYPE_DL10022 : ED_CHIP_TYPE_DL10019;
sc->type_str = ((id & 0x90) == 0x90) ? "DL10022" : "DL10019";
@@ -646,15 +680,15 @@ ed_pccard_dl100xx_mii_reset(struct ed_softc *sc)
if (sc->chip_type != ED_CHIP_TYPE_DL10022)
return;
- ed_asic_outb(sc, ED_DL100XX_MIIBUS, ED_DL100XX_MII_RESET2);
+ ed_asic_outb(sc, ED_DL100XX_MIIBUS, ED_DL10022_MII_RESET2);
DELAY(10);
ed_asic_outb(sc, ED_DL100XX_MIIBUS,
- ED_DL100XX_MII_RESET2 | ED_DL100XX_MII_RESET1);
+ ED_DL10022_MII_RESET2 | ED_DL10022_MII_RESET1);
DELAY(10);
- ed_asic_outb(sc, ED_DL100XX_MIIBUS, ED_DL100XX_MII_RESET2);
+ ed_asic_outb(sc, ED_DL100XX_MIIBUS, ED_DL10022_MII_RESET2);
DELAY(10);
ed_asic_outb(sc, ED_DL100XX_MIIBUS,
- ED_DL100XX_MII_RESET2 | ED_DL100XX_MII_RESET1);
+ ED_DL10022_MII_RESET2 | ED_DL10022_MII_RESET1);
DELAY(10);
ed_asic_outb(sc, ED_DL100XX_MIIBUS, 0);
}
@@ -664,21 +698,14 @@ ed_pccard_dl100xx_mii_writebits(struct ed_softc *sc, u_int val, int nbits)
{
int i;
- if (sc->chip_type == ED_CHIP_TYPE_DL10022)
- DL100XX_MIISET(sc, ED_DL100XX_MII_DIROUT_22);
- else
- DL100XX_MIISET(sc, ED_DL100XX_MII_DIROUT_19);
-
+ DL100XX_MIISET(sc, ED_DL100XX_MII_DIROUT);
for (i = nbits - 1; i >= 0; i--) {
if ((val >> i) & 1)
DL100XX_MIISET(sc, ED_DL100XX_MII_DATAOUT);
else
DL100XX_MIICLR(sc, ED_DL100XX_MII_DATAOUT);
- DELAY(10);
DL100XX_MIISET(sc, ED_DL100XX_MII_CLK);
- DELAY(10);
DL100XX_MIICLR(sc, ED_DL100XX_MII_CLK);
- DELAY(10);
}
}
@@ -688,66 +715,157 @@ ed_pccard_dl100xx_mii_readbits(struct ed_softc *sc, int nbits)
int i;
u_int val = 0;
- if (sc->chip_type == ED_CHIP_TYPE_DL10022)
- DL100XX_MIICLR(sc, ED_DL100XX_MII_DIROUT_22);
- else
- DL100XX_MIICLR(sc, ED_DL100XX_MII_DIROUT_19);
-
+ DL100XX_MIICLR(sc, ED_DL100XX_MII_DIROUT);
for (i = nbits - 1; i >= 0; i--) {
DL100XX_MIISET(sc, ED_DL100XX_MII_CLK);
- DELAY(10);
val <<= 1;
if (ed_asic_inb(sc, ED_DL100XX_MIIBUS) & ED_DL100XX_MII_DATAIN)
val++;
DL100XX_MIICLR(sc, ED_DL100XX_MII_CLK);
- DELAY(10);
}
return val;
}
-static int
-ed_pccard_ax88x90_geteprom(struct ed_softc *sc)
+static void
+ed_pccard_ax88x90_reset(struct ed_softc *sc)
{
- int prom[16],i;
- u_char tmp;
- struct {
- unsigned char offset, value;
- } pg_seq[] = {
- /* Select Page0 */
- {ED_P0_CR, ED_CR_RD2 | ED_CR_STP | ED_CR_PAGE_0},
- {ED_P0_DCR, 0x01},
- {ED_P0_RBCR0, 0x00}, /* Clear the count regs. */
- {ED_P0_RBCR1, 0x00},
- {ED_P0_IMR, 0x00}, /* Mask completion irq. */
- {ED_P0_ISR, 0xff},
- {ED_P0_RCR, ED_RCR_MON | ED_RCR_INTT}, /* Set To Monitor */
- {ED_P0_TCR, ED_TCR_LB0}, /* loopback mode. */
- {ED_P0_RBCR0, 32},
- {ED_P0_RBCR1, 0x00},
- {ED_P0_RSAR0, 0x00},
- {ED_P0_RSAR1, 0x04},
- {ED_P0_CR, ED_CR_RD0 | ED_CR_STA | ED_CR_PAGE_0},
- };
+ int i;
/* Reset Card */
- tmp = ed_asic_inb(sc, ED_NOVELL_RESET);
- ed_asic_outb(sc, ED_NOVELL_RESET, tmp);
- DELAY(5000);
ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP | ED_CR_PAGE_0);
- DELAY(5000);
-
- /* Card Settings */
- for (i = 0; i < sizeof(pg_seq) / sizeof(pg_seq[0]); i++)
- ed_nic_outb(sc, pg_seq[i].offset, pg_seq[i].value);
-
- /* Get Data */
- for (i = 0; i < ETHER_ADDR_LEN / 2; i++)
- prom[i] = ed_asic_inw(sc, 0);
- for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
- sc->enaddr[i] = prom[i / 2] & 0xff;
- sc->enaddr[i + 1] = (prom[i / 2] >> 8) & 0xff;
+ ed_asic_outb(sc, ED_NOVELL_RESET, ed_asic_inb(sc, ED_NOVELL_RESET));
+
+ /* Wait for the RST bit to assert, but cap it at 10ms */
+ for (i = 10000; !(ed_nic_inb(sc, ED_P0_ISR) & ED_ISR_RST) && i > 0;
+ i--)
+ continue;
+ ed_nic_outb(sc, ED_P0_ISR, ED_ISR_RST); /* ACK INTR */
+ if (i == 0)
+ device_printf(sc->dev, "Reset didn't finish\n");
+}
+
+/*
+ * Probe and vendor-specific initialization routine for ax88x90 boards
+ */
+static int
+ed_probe_ax88x90_generic(device_t dev, int flags)
+{
+ struct ed_softc *sc = device_get_softc(dev);
+ u_int memsize;
+ static char test_pattern[32] = "THIS is A memory TEST pattern";
+ char test_buffer[32];
+
+ ed_pccard_ax88x90_reset(sc);
+ DELAY(10*1000);
+
+ /* Make sure that we really have an 8390 based board */
+ if (!ed_probe_generic8390(sc))
+ return (ENXIO);
+
+ sc->vendor = ED_VENDOR_NOVELL;
+ sc->mem_shared = 0;
+ sc->cr_proto = ED_CR_RD2;
+
+ /*
+ * This prevents packets from being stored in the NIC memory when the
+ * readmem routine turns on the start bit in the CR. We write some
+ * bytes in word mode and verify we can read them back. If we can't
+ * then we don't have an AX88x90 chip here.
+ */
+ sc->isa16bit = 1;
+ ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON);
+ ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
+ ed_pio_writemem(sc, test_pattern, 16384, sizeof(test_pattern));
+ ed_pio_readmem(sc, 16384, test_buffer, sizeof(test_pattern));
+ if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) != 0)
+ return (ENXIO);
+
+ /*
+ * Hard code values based on the datasheet. We're NE-2000 compatible
+ * NIC with 16kb of packet memory starting at 16k offset.
+ */
+ sc->type = ED_TYPE_NE2000;
+ memsize = sc->mem_size = 16*1024;
+ sc->mem_start = 16 * 1024;
+ if (ed_asic_inb(sc, ED_AX88X90_TEST) != 0)
+ sc->chip_type = ED_CHIP_TYPE_AX88790;
+ else {
+ sc->chip_type = ED_CHIP_TYPE_AX88190;
+ /*
+ * The AX88190 (not A) has external 64k SRAM. Probe for this
+ * here. Most of the cards I have either use the AX88190A
+ * part, or have only 32k SRAM for some reason, so I don't
+ * know if this works or not.
+ */
+ ed_pio_writemem(sc, test_pattern, 32768, sizeof(test_pattern));
+ ed_pio_readmem(sc, 32768, test_buffer, sizeof(test_pattern));
+ if (bcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) {
+ sc->mem_start = 2*1024;
+ memsize = sc->mem_size = 62 * 1024;
+ }
+ }
+ sc->mem_end = sc->mem_start + memsize;
+ sc->tx_page_start = memsize / ED_PAGE_SIZE;
+ if (sc->mem_size > 16 * 1024)
+ sc->txb_cnt = 3;
+ else
+ sc->txb_cnt = 2;
+ sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
+ sc->rec_page_stop = sc->tx_page_start + memsize / ED_PAGE_SIZE;
+
+ sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
+
+ ed_nic_outb(sc, ED_P0_PSTART, sc->mem_start / ED_PAGE_SIZE);
+ ed_nic_outb(sc, ED_P0_PSTOP, sc->mem_end / ED_PAGE_SIZE);
+
+ /* Get the mac before we go -- It's just at 0x400 in "SRAM" */
+ ed_pio_readmem(sc, 0x400, sc->enaddr, ETHER_ADDR_LEN);
+
+ /* clear any pending interrupts that might have occurred above */
+ ed_nic_outb(sc, ED_P0_ISR, 0xff);
+ sc->sc_write_mbufs = ed_pio_write_mbufs;
+ return (0);
+}
+
+static int
+ed_pccard_ax88x90_check_mii(device_t dev, struct ed_softc *sc)
+{
+ int i, id;
+
+ /*
+ * All AX88x90 devices have MII and a PHY, so we use this to weed out
+ * chips that would otherwise make it through the tests we have after
+ * this point.
+ */
+ for (i = 0; i < 32; i++) {
+ id = ed_miibus_readreg(dev, i, MII_BMSR);
+ if (id != 0 && id != 0xffff)
+ break;
+ }
+ /*
+ * Found one, we're good.
+ */
+ if (i != 32)
+ return (0);
+ /*
+ * Didn't find anything, so try to power up and try again. The PHY
+ * may be not responding because we're in power down mode.
+ */
+ if (sc->chip_type == ED_CHIP_TYPE_AX88190)
+ return (ENXIO);
+ pccard_ccr_write_1(dev, PCCARD_CCR_STATUS, PCCARD_CCR_STATUS_PWRDWN);
+ for (i = 0; i < 32; i++) {
+ id = ed_miibus_readreg(dev, i, MII_BMSR);
+ if (id != 0 && id != 0xffff)
+ break;
}
+ /*
+ * Still no joy? We're AFU, punt.
+ */
+ if (i == 32)
+ return (ENXIO);
return (0);
+
}
/*
@@ -756,8 +874,8 @@ ed_pccard_ax88x90_geteprom(struct ed_softc *sc)
static int
ed_pccard_ax88x90(device_t dev, const struct ed_product *pp)
{
- int error, iobase, i, id;
- char *ts;
+ int error;
+ int iobase;
struct ed_softc *sc = device_get_softc(dev);
if (!(pp->flags & NE2000DVF_AX88X90))
@@ -769,93 +887,48 @@ ed_pccard_ax88x90(device_t dev, const struct ed_product *pp)
/*
* Set the IOBASE Register. The AX88x90 cards are potentially
* multifunction cards, and thus requires a slight workaround.
- * We write the address the card is at.
+ * We write the address the card is at, on the off chance that this
+ * card is not MFC.
+ * XXX I'm not sure that this is still needed...
*/
iobase = rman_get_start(sc->port_res);
pccard_ccr_write_1(dev, PCCARD_CCR_IOBASE0, iobase & 0xff);
pccard_ccr_write_1(dev, PCCARD_CCR_IOBASE1, (iobase >> 8) & 0xff);
- ts = "AX88190";
- if (ed_asic_inb(sc, ED_AX88X90_TEST) != 0) {
- /*
- * AX88790 (and I think AX88190A) chips need to be
- * powered down. There's an erratum that says we should
- * power down the PHY for 2.5s, but this seems to power
- * down the whole card. I'm unsure why this was done, but
- * appears to be required for proper operation.
- */
- pccard_ccr_write_1(dev, PCCARD_CCR_STATUS,
- PCCARD_CCR_STATUS_PWRDWN);
- /*
- * Linux axnet driver selects the internal phy for the ax88790
- */
- ed_asic_outb(sc, ED_AX88X90_GPIO, ED_AX88X90_GPIO_INT_PHY);
- ts = "AX88790";
- }
-
- /*
- * Check to see if we have a MII PHY ID at any of the first 17
- * locations. All AX88x90 devices have MII and a PHY, so we use
- * this to weed out chips that would otherwise make it through
- * the tests we have after this point.
- */
sc->mii_readbits = ed_pccard_ax88x90_mii_readbits;
sc->mii_writebits = ed_pccard_ax88x90_mii_writebits;
- for (i = 0; i < 17; i++) {
- id = ed_miibus_readreg(dev, i, MII_PHYIDR1);
- if (id != 0 && id != 0xffff)
- break;
- }
- if (i == 17) {
- sc->mii_readbits = 0;
- sc->mii_writebits = 0;
- return (ENXIO);
+ error = ed_probe_ax88x90_generic(dev, device_get_flags(dev));
+ if (error) {
+ if (bootverbose)
+ device_printf(dev, "probe ax88x90 failed %d\n",
+ error);
+ goto fail;
}
-
- sc->chip_type = ED_CHIP_TYPE_AX88190;
- error = ed_pccard_ax88x90_geteprom(sc);
+ error = ed_pccard_ax88x90_check_mii(dev, sc);
if (error)
- return (error);
- error = ed_probe_Novell_generic(dev, device_get_flags(dev));
- if (bootverbose)
- device_printf(dev, "probe novel returns %d\n", error);
- if (error == 0) {
- sc->vendor = ED_VENDOR_NOVELL;
- sc->type = ED_TYPE_NE2000;
- sc->chip_type = ED_CHIP_TYPE_AX88190;
- sc->type_str = ts;
- }
+ goto fail;
+ sc->vendor = ED_VENDOR_NOVELL;
+ sc->type = ED_TYPE_NE2000;
+ if (sc->chip_type == ED_CHIP_TYPE_AX88190)
+ sc->type_str = "AX88190";
+ else
+ sc->type_str = "AX88790";
+ return (0);
+fail:;
+ sc->mii_readbits = 0;
+ sc->mii_writebits = 0;
return (error);
}
-/* MII bit-twiddling routines for cards using AX88x90 chipset */
-#define AX88X90_MIISET(sc, x) ed_asic_outb(sc, ED_AX88X90_MIIBUS, \
- ed_asic_inb(sc, ED_AX88X90_MIIBUS) | (x))
-#define AX88X90_MIICLR(sc, x) ed_asic_outb(sc, ED_AX88X90_MIIBUS, \
- ed_asic_inb(sc, ED_AX88X90_MIIBUS) & ~(x))
-
-static void
-ed_pccard_ax88x90_mii_reset(struct ed_softc *sc)
-{
- /* Do nothing! */
-}
-
static void
ed_pccard_ax88x90_mii_writebits(struct ed_softc *sc, u_int val, int nbits)
{
- int i;
+ int i, data;
- AX88X90_MIICLR(sc, ED_AX88X90_MII_DIROUT);
for (i = nbits - 1; i >= 0; i--) {
- if ((val >> i) & 1)
- AX88X90_MIISET(sc, ED_AX88X90_MII_DATAOUT);
- else
- AX88X90_MIICLR(sc, ED_AX88X90_MII_DATAOUT);
- DELAY(10);
- AX88X90_MIISET(sc, ED_AX88X90_MII_CLK);
- DELAY(10);
- AX88X90_MIICLR(sc, ED_AX88X90_MII_CLK);
- DELAY(10);
+ data = (val >> i) & 1 ? ED_AX88X90_MII_DATAOUT : 0;
+ ed_asic_outb(sc, ED_AX88X90_MIIBUS, data);
+ ed_asic_outb(sc, ED_AX88X90_MIIBUS, data | ED_AX88X90_MII_CLK);
}
}
@@ -864,16 +937,15 @@ ed_pccard_ax88x90_mii_readbits(struct ed_softc *sc, int nbits)
{
int i;
u_int val = 0;
+ uint8_t mdio;
- AX88X90_MIISET(sc, ED_AX88X90_MII_DIROUT);
+ mdio = ED_AX88X90_MII_DIRIN;
for (i = nbits - 1; i >= 0; i--) {
- AX88X90_MIISET(sc, ED_AX88X90_MII_CLK);
- DELAY(10);
+ ed_asic_outb(sc, ED_AX88X90_MIIBUS, mdio);
val <<= 1;
if (ed_asic_inb(sc, ED_AX88X90_MIIBUS) & ED_AX88X90_MII_DATAIN)
val++;
- AX88X90_MIICLR(sc, ED_AX88X90_MII_CLK);
- DELAY(10);
+ ed_asic_outb(sc, ED_AX88X90_MIIBUS, mdio | ED_AX88X90_MII_CLK);
}
return val;
}
@@ -934,36 +1006,24 @@ ed_pccard_tc5299j(device_t dev, const struct ed_product *pp)
return (0);
}
-/* MII bit-twiddling routines for cards using TC5299J chipset */
-#define TC5299J_MIISET(sc, x) ed_nic_outb(sc, ED_TC5299J_MIIBUS, \
- ed_nic_inb(sc, ED_TC5299J_MIIBUS) | (x))
-#define TC5299J_MIICLR(sc, x) ed_nic_outb(sc, ED_TC5299J_MIIBUS, \
- ed_nic_inb(sc, ED_TC5299J_MIIBUS) & ~(x))
-
-static void
-ed_pccard_tc5299j_mii_reset(struct ed_softc *sc)
-{
- /* Do nothing! */
-}
-
static void
ed_pccard_tc5299j_mii_writebits(struct ed_softc *sc, u_int val, int nbits)
{
int i;
- uint8_t cr;
+ uint8_t cr, data;
+ /* Select page 3 */
cr = ed_nic_inb(sc, ED_P0_CR);
ed_nic_outb(sc, ED_P0_CR, cr | ED_CR_PAGE_3);
- TC5299J_MIICLR(sc, ED_TC5299J_MII_DIROUT);
for (i = nbits - 1; i >= 0; i--) {
- if ((val >> i) & 1)
- TC5299J_MIISET(sc, ED_TC5299J_MII_DATAOUT);
- else
- TC5299J_MIICLR(sc, ED_TC5299J_MII_DATAOUT);
- TC5299J_MIISET(sc, ED_TC5299J_MII_CLK);
- TC5299J_MIICLR(sc, ED_TC5299J_MII_CLK);
+ data = (val >> i) & 1 ? ED_TC5299J_MII_DATAOUT : 0;
+ ed_nic_outb(sc, ED_TC5299J_MIIBUS, data);
+ ed_nic_outb(sc, ED_TC5299J_MIIBUS, data | ED_TC5299J_MII_CLK);
}
+ ed_nic_outb(sc, ED_TC5299J_MIIBUS, 0);
+
+ /* Restore prior page */
ed_nic_outb(sc, ED_P0_CR, cr);
}
@@ -974,17 +1034,21 @@ ed_pccard_tc5299j_mii_readbits(struct ed_softc *sc, int nbits)
u_int val = 0;
uint8_t cr;
+ /* Select page 3 */
cr = ed_nic_inb(sc, ED_P0_CR);
ed_nic_outb(sc, ED_P0_CR, cr | ED_CR_PAGE_3);
- TC5299J_MIISET(sc, ED_TC5299J_MII_DIROUT);
+ ed_asic_outb(sc, ED_TC5299J_MIIBUS, ED_TC5299J_MII_DIROUT);
for (i = nbits - 1; i >= 0; i--) {
- TC5299J_MIISET(sc, ED_TC5299J_MII_CLK);
+ ed_nic_outb(sc, ED_TC5299J_MIIBUS,
+ ED_TC5299J_MII_CLK | ED_TC5299J_MII_DIROUT);
val <<= 1;
if (ed_nic_inb(sc, ED_TC5299J_MIIBUS) & ED_TC5299J_MII_DATAIN)
val++;
- TC5299J_MIICLR(sc, ED_TC5299J_MII_CLK);
+ ed_nic_outb(sc, ED_TC5299J_MIIBUS, ED_TC5299J_MII_DIROUT);
}
+
+ /* Restore prior page */
ed_nic_outb(sc, ED_P0_CR, cr);
return val;
}
@@ -998,23 +1062,45 @@ ed_miibus_readreg(device_t dev, int phy, int reg)
struct ed_softc *sc;
int failed, val;
+ sc = device_get_softc(dev);
/*
- * The AX88790 seem to have phy 0..f external, and 0x10 internal.
- * but they also seem to have a bogus one that shows up at phy
- * 0x11 through 0x1f.
+ * The AX88790 has an interesting quirk. It has an internal phy that
+ * needs a special bit set to access, but can also have additional
+ * external PHYs set for things like HomeNET media. When accessing
+ * the internal PHY, a bit has to be set, when accessing the external
+ * PHYs, it must be clear. See Errata 1, page 51, in the AX88790
+ * datasheet for more details.
+ *
+ * Also, PHYs above 16 appear to be phantoms on some cards, but not
+ * others. Registers read for this are often the same as prior values
+ * read. Filter all register requests to 17-31.
+ *
+ * I can't explain it, since I don't have the DL100xx data sheets, but
+ * the DL100xx chips do 13-bits before the 'ACK' but, but the AX88x90
+ * chips have 14. The linux pcnet and axnet drivers confirm this.
*/
- if (phy >= 0x11)
- return (0);
+ if (sc->chip_type == ED_CHIP_TYPE_AX88790) {
+ if (phy > 0x10)
+ return (0);
+ if (phy == 0x10)
+ ed_asic_outb(sc, ED_AX88X90_GPIO,
+ ED_AX88X90_GPIO_INT_PHY);
+ else
+ ed_asic_outb(sc, ED_AX88X90_GPIO, 0);
+ }
- sc = device_get_softc(dev);
(*sc->mii_writebits)(sc, 0xffffffff, 32);
(*sc->mii_writebits)(sc, ED_MII_STARTDELIM, ED_MII_STARTDELIM_BITS);
(*sc->mii_writebits)(sc, ED_MII_READOP, ED_MII_OP_BITS);
(*sc->mii_writebits)(sc, phy, ED_MII_PHY_BITS);
(*sc->mii_writebits)(sc, reg, ED_MII_REG_BITS);
+ if (sc->chip_type == ED_CHIP_TYPE_AX88790 ||
+ sc->chip_type == ED_CHIP_TYPE_AX88190)
+ (*sc->mii_readbits)(sc, ED_MII_ACK_BITS);
failed = (*sc->mii_readbits)(sc, ED_MII_ACK_BITS);
val = (*sc->mii_readbits)(sc, ED_MII_DATA_BITS);
(*sc->mii_writebits)(sc, ED_MII_IDLE, ED_MII_IDLE_BITS);
+/* printf("Reading phy %d reg %#x returning %#x (valid %d)\n", phy, reg, val, !failed); */
return (failed ? 0 : val);
}
@@ -1023,15 +1109,18 @@ ed_miibus_writereg(device_t dev, int phy, int reg, int data)
{
struct ed_softc *sc;
- /*
- * The AX88790 seem to have phy 0..f external, and 0x10 internal.
- * but they also seem to have a bogus one that shows up at phy
- * 0x11 through 0x1f.
- */
- if (phy >= 0x11)
- return (0);
-
+/* printf("Writing phy %d reg %#x data %#x\n", phy, reg, data); */
sc = device_get_softc(dev);
+ /* See ed_miibus_readreg for details */
+ if (sc->chip_type == ED_CHIP_TYPE_AX88790) {
+ if (phy > 0x10)
+ return (0);
+ if (phy == 0x10)
+ ed_asic_outb(sc, ED_AX88X90_GPIO,
+ ED_AX88X90_GPIO_INT_PHY);
+ else
+ ed_asic_outb(sc, ED_AX88X90_GPIO, 0);
+ }
(*sc->mii_writebits)(sc, 0xffffffff, 32);
(*sc->mii_writebits)(sc, ED_MII_STARTDELIM, ED_MII_STARTDELIM_BITS);
(*sc->mii_writebits)(sc, ED_MII_WRITEOP, ED_MII_OP_BITS);
@@ -1047,14 +1136,15 @@ static int
ed_ifmedia_upd(struct ifnet *ifp)
{
struct ed_softc *sc;
- struct mii_data *mii;
+ int error;
sc = ifp->if_softc;
if (sc->miibus == NULL)
return (ENXIO);
-
- mii = device_get_softc(sc->miibus);
- return mii_mediachg(mii);
+ ED_LOCK(sc);
+ error = ed_pccard_kick_phy(sc);
+ ED_UNLOCK(sc);
+ return (error);
}
static void
@@ -1083,6 +1173,37 @@ ed_child_detached(device_t dev, device_t child)
sc->miibus = NULL;
}
+static void
+ed_pccard_tick(void *arg)
+{
+ struct ed_softc *sc = arg;
+ struct mii_data *mii;
+ int media = 0;
+
+ ED_ASSERT_LOCKED(sc);
+ if (sc->miibus != NULL) {
+ mii = device_get_softc(sc->miibus);
+ media = mii->mii_media_status;
+ mii_tick(mii);
+ if (mii->mii_media_status & IFM_ACTIVE &&
+ media != mii->mii_media_status) {
+ if (sc->chip_type == ED_CHIP_TYPE_DL10022) {
+ ed_asic_outb(sc, ED_DL10022_DIAG,
+ (mii->mii_media_active & IFM_FDX) ?
+ ED_DL10022_COLLISON_DIS : 0);
+#ifdef notyet
+ } else if (sc->chip_type == ED_CHIP_TYPE_DL10019) {
+ write_asic(sc, ED_DL10019_MAGIC,
+ (mii->mii_media_active & IFM_FDX) ?
+ DL19FDUPLX : 0);
+#endif
+ }
+ }
+
+ }
+ callout_reset(&sc->tick_ch, hz, ed_pccard_tick, sc);
+}
+
static device_method_t ed_pccard_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ed_pccard_probe),
diff --git a/sys/dev/ed/if_ed_pci.c b/sys/dev/ed/if_ed_pci.c
index a2831b8..1b2e17d 100644
--- a/sys/dev/ed/if_ed_pci.c
+++ b/sys/dev/ed/if_ed_pci.c
@@ -91,11 +91,9 @@ ed_pci_attach(device_t dev)
int error = ENXIO;
/*
- * If this card claims to be a RTL8029, probe it as such.
- * However, allow that probe to fail. Some versions of qemu
- * claim to be a 8029 in the PCI register, but it doesn't
- * implement the 8029 specific registers. In that case, fall
- * back to a normal NE2000.
+ * Probe RTL8029 cards, but allow failure and try as a generic
+ * ne-2000. QEMU 0.9 and earlier use the RTL8029 PCI ID, but
+ * are areally just generic ne-2000 cards.
*/
if (pci_get_devid(dev) == ED_RTL8029_PCI_ID)
error = ed_probe_RTL80x9(dev, PCIR_BAR(0), flags);
@@ -118,7 +116,8 @@ ed_pci_attach(device_t dev)
ed_release_resources(dev);
return (error);
}
-
+ if (sc->sc_media_ioctl == NULL)
+ ed_gen_ifmedia_init(sc);
error = ed_attach(dev);
if (error)
ed_release_resources(dev);
diff --git a/sys/dev/ed/if_ed_wd80x3.c b/sys/dev/ed/if_ed_wd80x3.c
index b3cb439..4ff2286 100644
--- a/sys/dev/ed/if_ed_wd80x3.c
+++ b/sys/dev/ed/if_ed_wd80x3.c
@@ -119,7 +119,6 @@ ed_probe_WD80x3_generic(device_t dev, int flags, uint16_t *intr_vals[])
sum += ed_asic_inb(sc, ED_WD_PROM + i);
if (sum != totalsum) {
-
/*
* Checksum is invalid. This often happens with cheap WD8003E
* clones. In this case, the checksum byte (the eighth byte)
@@ -268,9 +267,11 @@ ed_probe_WD80x3_generic(device_t dev, int flags, uint16_t *intr_vals[])
printf("%x -> %x\n", i, ed_asic_inb(sc, i));
#endif
pmem = rman_get_start(sc->mem_res);
- error = ed_isa_mem_ok(dev, pmem, memsize);
- if (error)
- return (error);
+ if (!(flags & ED_FLAGS_PCCARD)) {
+ error = ed_isa_mem_ok(dev, pmem, memsize);
+ if (error)
+ return (error);
+ }
/*
* (note that if the user specifies both of the following flags that
diff --git a/sys/dev/ed/if_edreg.h b/sys/dev/ed/if_edreg.h
index 3f2b719..9820dfd 100644
--- a/sys/dev/ed/if_edreg.h
+++ b/sys/dev/ed/if_edreg.h
@@ -1066,19 +1066,23 @@ struct ed_ring {
/*
* Chip types.
*/
-
-#define ED_CHIP_TYPE_DP8390 0
-#define ED_CHIP_TYPE_WD790 1
-#define ED_CHIP_TYPE_AX88190 2
-#define ED_CHIP_TYPE_DL10019 3
-#define ED_CHIP_TYPE_DL10022 4
-#define ED_CHIP_TYPE_TC5299J 5
-#define ED_CHIP_TYPE_RTL8019 6
-#define ED_CHIP_TYPE_RTL8029 7
+#define ED_CHIP_TYPE_AX88190 0
+#define ED_CHIP_TYPE_AX88790 1
+#define ED_CHIP_TYPE_DL10019 2
+#define ED_CHIP_TYPE_DL10022 3
+#define ED_CHIP_TYPE_DP8390 4
+#define ED_CHIP_TYPE_NS83903 5
+#define ED_CHIP_TYPE_NS83926 6
+#define ED_CHIP_TYPE_RTL8019 7
+#define ED_CHIP_TYPE_RTL8029 8
+#define ED_CHIP_TYPE_TC3299 9
+#define ED_CHIP_TYPE_TC5299J 10
+#define ED_CHIP_TYPE_W89C926 11
+#define ED_CHIP_TYPE_WD790 12
/*
* MII bus definitions. These are common to both DL100xx and AX88x90
- * MII definitions, most likely because they are standards based.
+ * MII definitions, because they are standards based.
*/
#define ED_MII_STARTDELIM 0x01
#define ED_MII_WRITEOP 0x01
@@ -1091,6 +1095,6 @@ struct ed_ring {
#define ED_MII_PHY_BITS 5
#define ED_MII_REG_BITS 5
#define ED_MII_TURNAROUND_BITS 2
-#define ED_MII_DATA_BITS 16
#define ED_MII_ACK_BITS 1
+#define ED_MII_DATA_BITS 16
#define ED_MII_IDLE_BITS 1
diff --git a/sys/dev/ed/if_edvar.h b/sys/dev/ed/if_edvar.h
index 170558e..27dd669 100644
--- a/sys/dev/ed/if_edvar.h
+++ b/sys/dev/ed/if_edvar.h
@@ -226,6 +226,8 @@ u_short ed_pio_write_mbufs(struct ed_softc *, struct mbuf *, bus_size_t);
void ed_disable_16bit_access(struct ed_softc *);
void ed_enable_16bit_access(struct ed_softc *);
+void ed_gen_ifmedia_init(struct ed_softc *);
+
driver_intr_t edintr;
extern devclass_t ed_devclass;
@@ -267,12 +269,15 @@ extern devclass_t ed_devclass;
#define ED_FLAGS_FORCE_PIO 0x0010
/*
+ * This forces a PC Card, and disables ISA memory range checks
+ */
+#define ED_FLAGS_PCCARD 0x0020
+
+/*
* These are flags describing the chip type.
*/
#define ED_FLAGS_TOSH_ETHER 0x10000
#define ED_FLAGS_GWETHER 0x20000
-#define ED_FLAGS_AX88190 0x30000
-#define ED_FLAGS_LINKSYS 0x80000
#define ED_FLAGS_GETTYPE(flg) ((flg) & 0xff0000)
diff --git a/sys/dev/ep/if_ep.c b/sys/dev/ep/if_ep.c
index 3b91369..c56639d 100644
--- a/sys/dev/ep/if_ep.c
+++ b/sys/dev/ep/if_ep.c
@@ -435,6 +435,8 @@ epinit_locked(struct ep_softc *sc)
if (!sc->epb.mii_trans)
ep_ifmedia_upd(ifp);
+ if (sc->stat & F_HAS_TX_PLL)
+ CSR_WRITE_2(sc, EP_COMMAND, TX_PLL_ENABLE);
CSR_WRITE_2(sc, EP_COMMAND, RX_ENABLE);
CSR_WRITE_2(sc, EP_COMMAND, TX_ENABLE);
@@ -473,7 +475,7 @@ epstart_locked(struct ifnet *ifp)
struct ep_softc *sc;
u_int len;
struct mbuf *m, *m0;
- int pad;
+ int pad, started;
sc = ifp->if_softc;
if (sc->gone)
@@ -482,11 +484,15 @@ epstart_locked(struct ifnet *ifp)
EP_BUSY_WAIT(sc);
if (ifp->if_drv_flags & IFF_DRV_OACTIVE)
return;
+ started = 0;
startagain:
/* Sneak a peek at the next packet */
IFQ_DRV_DEQUEUE(&ifp->if_snd, m0);
if (m0 == NULL)
return;
+ if (!started && (sc->stat & F_HAS_TX_PLL))
+ CSR_WRITE_2(sc, EP_COMMAND, TX_PLL_ENABLE);
+ started++;
for (len = 0, m = m0; m != NULL; m = m->m_next)
len += m->m_len;
@@ -895,8 +901,24 @@ static void
ep_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
{
struct ep_softc *sc = ifp->if_softc;
+ uint16_t ms;
- ifmr->ifm_active = sc->ifmedia.ifm_media;
+ switch (IFM_SUBTYPE(sc->ifmedia.ifm_media)) {
+ case IFM_10_T:
+ GO_WINDOW(sc, 4);
+ ms = CSR_READ_2(sc, EP_W4_MEDIA_TYPE);
+ GO_WINDOW(sc, 0);
+ ifmr->ifm_status = IFM_AVALID;
+ if (ms & MT_LB) {
+ ifmr->ifm_status |= IFM_ACTIVE;
+ ifmr->ifm_active = IFM_ETHER | IFM_10_T;
+ } else {
+ ifmr->ifm_active = IFM_ETHER | IFM_NONE;
+ }
+ default:
+ ifmr->ifm_active = sc->ifmedia.ifm_media;
+ break;
+ }
}
static int
diff --git a/sys/dev/ep/if_ep_pccard.c b/sys/dev/ep/if_ep_pccard.c
index 4309358..98ebaf4 100644
--- a/sys/dev/ep/if_ep_pccard.c
+++ b/sys/dev/ep/if_ep_pccard.c
@@ -68,9 +68,10 @@ struct ep_pccard_product
#define EP_CHIP_589 1 /* Classic 3c5x9 chipset */
#define EP_CHIP_574 2 /* Roadrunner */
+#define EP_CHIP_C1 3 /* 3c1 */
static const struct ep_pccard_product ep_pccard_products[] = {
- { PCMCIA_CARD(3COM, 3C1), EP_CHIP_589 },
+ { PCMCIA_CARD(3COM, 3C1), EP_CHIP_C1 },
{ PCMCIA_CARD(3COM, 3C562), EP_CHIP_589 },
{ PCMCIA_CARD(3COM, 3C589), EP_CHIP_589 },
{ PCMCIA_CARD(3COM, 3CXEM556), EP_CHIP_589 },
@@ -144,19 +145,21 @@ ep_pccard_attach(device_t dev)
if ((pp = ep_pccard_lookup(dev)) == NULL)
panic("ep_pccard_attach: can't find product in attach.");
- if (pp->chipset == EP_CHIP_589) {
- sc->epb.mii_trans = 0;
- sc->epb.cmd_off = 0;
- } else {
+ if (pp->chipset == EP_CHIP_574) {
sc->epb.mii_trans = 1;
sc->epb.cmd_off = 2;
+ } else {
+ sc->epb.mii_trans = 0;
+ sc->epb.cmd_off = 0;
}
-
if ((error = ep_alloc(dev))) {
device_printf(dev, "ep_alloc() failed! (%d)\n", error);
goto bad;
}
+ if (pp->chipset == EP_CHIP_C1)
+ sc->stat |= F_HAS_TX_PLL;
+
/* ROM size = 0, ROM base = 0 */
/* For now, ignore AUTO SELECT feature of 3C589B and later. */
error = ep_get_e(sc, EEPROM_ADDR_CFG, &result);
diff --git a/sys/dev/ep/if_epreg.h b/sys/dev/ep/if_epreg.h
index 25ab182..f3c269f 100644
--- a/sys/dev/ep/if_epreg.h
+++ b/sys/dev/ep/if_epreg.h
@@ -156,6 +156,7 @@
* Window 2 registers. Station Address Setup/Read
*/
/* Read/Write */
+#define EP_W2_PHY_MGMT 0x0c
#define EP_W2_ALT_EEPROM 0x0a
#define EP_W2_ADDR_5 0x05
#define EP_W2_ADDR_4 0x04
@@ -406,6 +407,17 @@
#define LINKBEAT_ENABLE 0x80
#define ENABLE_UTP (JABBER_GUARD_ENABLE | LINKBEAT_ENABLE)
#define DISABLE_UTP 0x0
+#define MT_CSD 0x0004 /* CRC Strip disable */
+#define MT_SQE 0x0008 /* SQE Enable */
+#define MT_C0 0x0010 /* Collison */
+#define MT_CS 0x0020 /* Carrier Sense */
+#define MT_J 0x0200 /* Jabber detected */
+#define MT_PL 0x0400 /* Plarity Inverted */
+#define MT_LB 0x0800 /* Link Beat detected */
+#define MT_SQ 0x1000 /* SQE Present */
+#define MT_IN 0x2000 /* Reserved */
+#define MT_CE 0x4000 /* Coax */
+#define MT_TPE 0x8000
/*
* Misc defines for various things.
diff --git a/sys/dev/ep/if_epvar.h b/sys/dev/ep/if_epvar.h
index 704fe02..922a264 100644
--- a/sys/dev/ep/if_epvar.h
+++ b/sys/dev/ep/if_epvar.h
@@ -57,6 +57,7 @@ struct ep_softc {
#define F_ENADDR_SKIP 0x002
#define F_PROMISC 0x008
#define F_ACCESS_32_BITS 0x100
+#define F_HAS_TX_PLL 0x200
int gone; /* adapter is not present (for PCCARD) */
struct ep_board epb;
diff --git a/sys/dev/fe/if_fe_pccard.c b/sys/dev/fe/if_fe_pccard.c
index 40c10ee..e1cb10d 100644
--- a/sys/dev/fe/if_fe_pccard.c
+++ b/sys/dev/fe/if_fe_pccard.c
@@ -62,9 +62,10 @@ static int fe_pccard_detach(device_t);
static const struct fe_pccard_product {
struct pccard_product mpp_product;
int mpp_flags;
+ int mpp_cfe;
#define MPP_MBH10302 1
#define MPP_ANYFUNC 2
-#define MPP_SKIP_TO_CFE_10 4
+#define MPP_SKIP_TO_CFE 4
} fe_pccard_products[] = {
/* These need to be first */
{ PCMCIA_CARD(FUJITSU2, FMV_J181), MPP_MBH10302 },
@@ -72,16 +73,17 @@ static const struct fe_pccard_product {
{ PCMCIA_CARD(FUJITSU2, FMV_J182A), 0 },
{ PCMCIA_CARD(FUJITSU2, ITCFJ182A), 0 },
/* These need to be second */
+ { PCMCIA_CARD(TDK, LAK_CD011), 0 },
{ PCMCIA_CARD(TDK, LAK_CD021BX), 0 },
{ PCMCIA_CARD(TDK, LAK_CF010), 0 },
#if 0 /* XXX 86960-based? */
{ PCMCIA_CARD(TDK, LAK_DFL9610), 0 },
#endif
- { PCMCIA_CARD(CONTEC, CNETPC), 0 },
+ { PCMCIA_CARD(CONTEC, CNETPC), MPP_SKIP_TO_CFE, 2 },
{ PCMCIA_CARD(FUJITSU, LA501), 0 },
{ PCMCIA_CARD(FUJITSU, LA10S), 0 },
{ PCMCIA_CARD(FUJITSU, NE200T), MPP_MBH10302 },/* Sold by Eagle */
- { PCMCIA_CARD(HITACHI, HT_4840), MPP_MBH10302 | MPP_SKIP_TO_CFE_10},
+ { PCMCIA_CARD(HITACHI, HT_4840), MPP_MBH10302 | MPP_SKIP_TO_CFE, 10 },
{ PCMCIA_CARD(RATOC, REX_R280), 0 },
{ PCMCIA_CARD(XIRCOM, CE), MPP_ANYFUNC },
{ { NULL } }
@@ -108,13 +110,13 @@ fe_pccard_probe(device_t dev)
return (error);
if (fcn != PCCARD_FUNCTION_NETWORK)
return (ENXIO);
- if (pp->mpp_flags & MPP_SKIP_TO_CFE_10) {
- for (i = 10; i < 27; i++) {
+ if (pp->mpp_flags & MPP_SKIP_TO_CFE) {
+ for (i = pp->mpp_cfe; i < 32; i++) {
if (pccard_select_cfe(dev, i) == 0)
goto good;
}
device_printf(dev,
- "Hitachi HT-4840-11 workaround failed\n");
+ "Failed to map CFE %d or higher\n", pp->mpp_cfe);
return ENXIO;
}
good:;
diff --git a/sys/dev/firewire/firewire.c b/sys/dev/firewire/firewire.c
index 05cf834..c2484ae 100644
--- a/sys/dev/firewire/firewire.c
+++ b/sys/dev/firewire/firewire.c
@@ -685,7 +685,8 @@ fw_init_crom(struct firewire_comm *fc)
src->businfo.cyc_clk_acc = 100;
src->businfo.max_rec = fc->maxrec;
src->businfo.max_rom = MAXROM_4;
- src->businfo.generation = 0;
+#define FW_GENERATION_CHANGEABLE 2
+ src->businfo.generation = FW_GENERATION_CHANGEABLE;
src->businfo.link_spd = fc->speed;
src->businfo.eui64.hi = fc->eui.hi;
@@ -734,6 +735,7 @@ fw_busreset(struct firewire_comm *fc, uint32_t new_status)
struct firewire_dev_comm *fdc;
struct crom_src *src;
device_t *devlistp;
+ uint32_t *newrom;
int i, devcnt;
FW_GLOCK_ASSERT(fc);
@@ -759,18 +761,31 @@ fw_busreset(struct firewire_comm *fc, uint32_t new_status)
}
src = &fc->crom_src_buf->src;
- /*
- * If the old config rom needs to be overwritten,
- * bump the businfo.generation indicator to
- * indicate that we need to be reprobed
- */
- if (bcmp(src, fc->config_rom, CROMSIZE) != 0) {
- /* generation is a 2 bit field */
- /* valid values are only from 0 - 3 */
- src->businfo.generation = 1;
- bcopy(src, (void *)fc->config_rom, CROMSIZE);
- } else
- src->businfo.generation = 0;
+ /*
+ * If the old config rom needs to be overwritten,
+ * bump the businfo.generation indicator to
+ * indicate that we need to be reprobed
+ * See 1394a-2000 8.3.2.5.4 for more details.
+ * generation starts at 2 and rolls over at 0xF
+ * back to 2.
+ *
+ * A generation of 0 indicates a device
+ * that is not 1394a-2000 compliant.
+ * A generation of 1 indicates a device that
+ * does not change it's Bus Info Block or
+ * Configuration ROM.
+ */
+#define FW_MAX_GENERATION 0xF
+ newrom = malloc(CROMSIZE, M_FW, M_NOWAIT | M_ZERO);
+ src = &fc->crom_src_buf->src;
+ crom_load(src, newrom, CROMSIZE);
+ if (bcmp(newrom, fc->config_rom, CROMSIZE) != 0) {
+ if ( src->businfo.generation++ > FW_MAX_GENERATION )
+ src->businfo.generation = FW_GENERATION_CHANGEABLE;
+ bcopy(newrom, (void *)fc->config_rom, CROMSIZE);
+ }
+ free(newrom, M_FW);
+
}
/* Call once after reboot */
@@ -1590,6 +1605,10 @@ fw_explore_node(struct fw_device *dfwdev)
}
fwdev->fc = fc;
fwdev->eui = binfo->eui64;
+ fwdev->dst = dfwdev->dst;
+ fwdev->maxrec = dfwdev->maxrec;
+ fwdev->status = dfwdev->status;
+
/*
* Pre-1394a-2000 didn't have link_spd in
* the Bus Info block, so try and use the
@@ -1599,7 +1618,7 @@ fw_explore_node(struct fw_device *dfwdev)
* ignore the speed map alltogether. SWB
*/
if ( binfo->link_spd == FWSPD_S100 /* 0 */) {
- device_printf(fc->bdev, "%s"
+ device_printf(fc->bdev, "%s: "
"Pre 1394a-2000 detected\n",
__func__);
fwdev->speed = fc->speed_map->speed[fc->nodeid][node];
@@ -1609,22 +1628,24 @@ fw_explore_node(struct fw_device *dfwdev)
* Test this speed with a read to the CSRROM.
* If it fails, slow down the speed and retry.
*/
- while (fwdev->speed > 0) {
+ while (fwdev->speed > FWSPD_S100 /* 0 */) {
err = fw_explore_read_quads(fwdev, CSRROMOFF,
&speed_test, 1);
- if (err)
+ if (err) {
+ device_printf(fc->bdev, "%s: fwdev->speed(%s)"
+ " decremented due to negotiation\n",
+ __func__,
+ linkspeed[fwdev->speed]);
fwdev->speed--;
- else
+ } else
break;
}
- if (fwdev->speed != binfo->link_spd)
- device_printf(fc->bdev, "%s: fwdev->speed(%s)"
- " set lower than binfo->link_spd(%s)\n",
- __func__,
- linkspeed[fwdev->speed],
- linkspeed[binfo->link_spd]);
- /* inesrt into sorted fwdev list */
+
+ /*
+ * If the fwdev is not found in the
+ * fc->devices TAILQ, then we will add it.
+ */
pfwdev = NULL;
STAILQ_FOREACH(tfwdev, &fc->devices, link) {
if (tfwdev->eui.hi > fwdev->eui.hi ||
@@ -1641,15 +1662,15 @@ fw_explore_node(struct fw_device *dfwdev)
device_printf(fc->bdev, "New %s device ID:%08x%08x\n",
linkspeed[fwdev->speed],
fwdev->eui.hi, fwdev->eui.lo);
- }
- fwdev->dst = node;
- fwdev->status = FWDEVINIT;
-
- /* unchanged ? */
- if (bcmp(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5) == 0) {
- if (firewire_debug)
- device_printf(fc->dev, "node%d: crom unchanged\n", node);
- return (0);
+ } else {
+ fwdev->dst = node;
+ fwdev->status = FWDEVINIT;
+ /* unchanged ? */
+ if (bcmp(&csr[0], &fwdev->csrrom[0], sizeof(uint32_t) * 5) == 0) {
+ if (firewire_debug)
+ device_printf(fc->dev, "node%d: crom unchanged\n", node);
+ return (0);
+ }
}
bzero(&fwdev->csrrom[0], CROMSIZE);
@@ -1661,6 +1682,9 @@ fw_explore_node(struct fw_device *dfwdev)
err = fw_explore_csrblock(fwdev, 0x14, 1); /* root directory */
if (err) {
+ if (firewire_debug)
+ device_printf(fc->dev, "%s: explore csrblock failed err(%d)\n",
+ __func__, err);
fwdev->status = FWDEVINVAL;
fwdev->csrrom[0] = 0;
}
diff --git a/sys/dev/firewire/sbp.h b/sys/dev/firewire/sbp.h
index 9f85fab..fcfa514 100644
--- a/sys/dev/firewire/sbp.h
+++ b/sys/dev/firewire/sbp.h
@@ -121,7 +121,7 @@ struct sbp_status{
/* 3: Page size not supported */
/* 4: Access denied */
#define STATUS_ACCESS_DENY 4
-/* 5: Logical unit not supported */
+#define STATUS_LUR 5
/* 6: Maximum payload too small */
/* 7: Reserved for future standardization */
/* 8: Resource unavailabe */
diff --git a/sys/dev/hptiop/hptiop.h b/sys/dev/hptiop/hptiop.h
index 0f74592..eb48676 100644
--- a/sys/dev/hptiop/hptiop.h
+++ b/sys/dev/hptiop/hptiop.h
@@ -260,7 +260,7 @@ struct hpt_iop_ioctl_param {
unsigned long lpOutBuffer; /* output data buffer */
u_int32_t nOutBufferSize; /* size of output data buffer */
unsigned long lpBytesReturned; /* count of HPT_U8s returned */
-};
+} __packed;
#define HPT_IOCTL_FLAG_OPEN 1
#define HPT_CTL_CODE_BSD_TO_IOP(x) ((x)-0xff00)
diff --git a/sys/dev/hptmv/access601.h b/sys/dev/hptmv/access601.h
index 26eaab2..51f1ca3 100644
--- a/sys/dev/hptmv/access601.h
+++ b/sys/dev/hptmv/access601.h
@@ -28,6 +28,8 @@
#ifndef _ACCESS601_H_
#define _ACCESS601_H_
+#ifndef FOR_DEMO
+
void HPTLIBAPI BeepOn(MV_BUS_ADDR_T BaseAddr);
void HPTLIBAPI BeepOff(MV_BUS_ADDR_T BaseAddr);
UCHAR HPTLIBAPI check_protect_circuit(MV_BUS_ADDR_T BaseAddr);
@@ -40,4 +42,21 @@ void HPTLIBAPI set_fail_leds(MV_SATA_ADAPTER *pAdapter, UCHAR mask);
#define set_fail_leds(pAdapter, mask)
#endif
+int HPTLIBAPI sx508x_ioctl(MV_SATA_ADAPTER *pSataAdapter, UCHAR *indata, ULONG inlen,
+ UCHAR *outdata, ULONG maxoutlen, ULONG *poutlen);
+
+MV_BOOLEAN HPTLIBAPI sx508x_flash_access(MV_SATA_ADAPTER *pSataAdapter,
+ MV_U32 offset, void *value, int size, int reading);
+#else
+
+#define BeepOn(addr)
+#define BeepOff(addr)
+#define check_protect_circuit(addr) 1
+#define set_fail_led(pAdapter, channel, state)
+#define set_fail_leds(pAdapter, mask)
+#define sx508x_ioctl(pSataAdapter, indata, inlen, outdata, maxoutlen, poutlen) 0
+#define sx508x_flash_access(pSataAdapter, offset, value, size, reading) 0
+
+#endif
+
#endif
diff --git a/sys/dev/hptmv/amd64-elf.raid.o.uu b/sys/dev/hptmv/amd64-elf.raid.o.uu
index 5b439c9..333a8f6 100644
--- a/sys/dev/hptmv/amd64-elf.raid.o.uu
+++ b/sys/dev/hptmv/amd64-elf.raid.o.uu
@@ -26,1881 +26,1909 @@
* $FreeBSD$
*/
begin 644 hptmvraid.o
-M?T5,1@(!`0D```````````$`/@`!`````````````````````````"#=````
-M`````````$```````$``#@`+`$B)7"302(EL)-A,B60DX$R);"3H3(ET)/!,
-MB7PD^$B![$@"``!(B?M,BV\02(UOD$R-9"00N`(```"`?P$`=0N`?P(!&<"#
-MX`+_P(A%`$C'10@`````@$T!!$B+0Q!(B440BU,8B5482`^V10!(BP3%````
-M`$B)16"`?0`#=2:-0O:)11B+<QB#[@I,B>&Z(````$B)W^@`````08$\)/,6
-M>%IT&D@/MD4`2(L$Q0````!(B45H@$T!!.FE!```OI````!,B>?H`````(3`
-M==5!]D0D"0)T'<9#"`%!#[9$)`J(0PLZ0PES"P^V\$B)W^@`````O@`"``!,
-MB>?H`````(3`=!=)C;PDD````+IP`0``O@````#H`````$$/MI0DDP```+X!
-M````(=8/MD,$@^#\B=&#X0()\`G(O@0````AUH/@\XG1@^$("?`)R+X0````
-M(=:#X,^)T8/A(`GP"<B)T8/A0(/@/X/B@`G("="(0P1!#[94)`F#X@$/MD4!
-M@^#^"="(10%!@'PD$`,/A`____]!@'PD$`!U%,9%``!(BP4`````2(E%:.FR
-M`P``08-\)`0`#X3G_O__N@````!!#[9$)`N)P8/X`'XQ2,?&`````$ACPDC!
-MX`1,`>"`>!`(#X>Z_O__2`^V0!!(@SS&``^$JO[____".=%_UD&+1"08B40D
-M#+H`````2&/"2&G`,`$``$J-G"BH1```2(-["`!U#HM#=$$[1"0$#X04`0``
-M_\*#^@]^TDF+G:!$``!(A=MT(4B+0Q!)B86@1```NC`!``"^`````$B)W^@`
-M````3(EK$$&+1"0$B4-T#[93?H/*`8A3?F9!#[9$)!2#X`$!P(/B_0G"B%-^
-M00^W1"069HF#@````(M4)`R)DX0```!!#[9$)!"(`T$/MD0D$XA#<@^VR+@!
-M````T^!FB4-\2,=#"`````!!BT0D#(E#&$$/MD0D$8A#<$@/M@-(BP3%````
-M`$B)0V!)C70D+$B-N\@```"Z$````.@`````28UT)#Q(C;O8````N@0```#H
-M`````$F-M"2`````2(V['`$``+H0````Z`````!)C70D0$B-N]P```"Z0```
-M`.@`````BT0D##F#A````'8&B8.$````0?9$)`D!=`2`2P$!10^V?"0208!\
-M)`L!#X:V`0``1(GZ#[;"3(NTPX@```!!BT0D*(E$)`Q-A?8/A3D!``!-B[6@
-M1```387V="%)BT8028F%H$0``+HP`0``O@````!,B??H`````$V);A!!BT0D
-M!$&)1G1!#[96?H/*`4&(5GYF00^V1"0D@^`!`<"#XOT)PD&(5GY!#[=$)"9F
-M08F&@````(M4)`Q!B9:$````00^V1"0A08A&<$$/MD0D($&(!DF)7@A!BT0D
-M'$&)1AA!#[9$)"-!B$9R#[;(N`$```#3X&9!B49\20^V!DB+!,4`````28E&
-M8$@/M@-(BP3%`````$F)1FA%B'X#1(GZ#[;"3(FTPX@```#^0W%)C70D+$F-
-MOL@```"Z$````.@`````28UT)#Q)C;[8````N@0```#H`````$F-M"2`````
-M28V^'`$``+H0````Z`````!)C70D0$F-OMP```"Z0````.@`````0?9$)`D!
-M=`5!@$X!`4D/MD0D(DF#O,:(`````'5S28FLQH@```!!#[9$)"*(10-!_D9Q
-M3(EU"$D/M@9(BP3%`````$B)16B+1"0,03F&A````'8]08F&A````.LT1(GZ
-M#[;"2(.\PX@`````=2-(B:S#B````$B)70C^0W%$B'T#2`^V`TB+!,4`````
-M2(E%:$B+G"08`@``2(NL)"`"``!,BZ0D*`(``$R+K"0P`@``3(NT)#@"``!,
-MB[PD0`(``$B!Q$@"``##9F9FD%532(/L"$B)\[T`````#[9&<(G"@_@`#X[(
-M````9F:02&/%2(.\PX@`````=`O_Q3GJ?^SIK````+@!````B>G3X&8)@X``
-M``!(B=[H`````$B)PDB%P`^$B````,8``T"(:`-(B5@(@#L(#Y3`P>`##[9*
-M`8/A]PG!B$H!2(L%`````$B)0F!(#[8#2(L$Q0````!(B4)H]D,!$'01B<B#
-MR!"(0@&+@H@```")0AA(8\5(B93#B`````^V0WZ#X/Z#R`J(0W['@X0`````
-M````_D-Q2(G6OP<```#H`````(!+?@1(@\0(6UW#9F9FD$B)7"3@2(EL).A,
-MB60D\$R);"3X2(/L*$F)_4B)\P^V!H/X!@^$EP```(/X!G\1@_@$#XR8`0``
-MZQMF9I!F9I"#^`@/A.<```!F9F:09F:0Z7L!```/MD9Q.D9P9F9FD`^%:@$`
-M`(!.`02`9G[^0;P`````@'YP``^$4@$``&:026/$2(NLPX@```!(A>UT((!]
-M``-V&DB)[DR)[^@`````]D5^!'0)@$M^!&9FD&:00?_$#[9#<$0YX'_$Z0\!
-M``"`3@$$@'YQ`G4*@&9^_I#I^P```(!F?OU(@[Z(`````'4=2(N&D````,9`
-M`P!(B8:(````2,>&D`````````!(BX.(````@#@#=0M(B=Y,B>_H`````(!+
-M?@3'@X0`````````Z:8```!F9I!F9I`/MD9Q.D9P=2"`3@$$#[9&?H/@_HA&
-M?F:#OH``````=&^#R`*(1G[K9P^V1G'_P`^V5G`YT'599H.^@`````!T++D`
-M````#[>&@````(G"J`%U"O_!B=#3^*@!=/9(8\%(@[S#B`````!U&^L&]D9^
-M`G43@$L!!(!+?@1(B=Y,B>_H`````,>#A``````````/MT-\]]@A@X0```!F
-M9F:02(-["`!U&?9#?@1T$^@`````B4-T2(G?Z`````!F9I!(BUPD"$B+;"00
-M3(MD)!A,BVPD($B#Q"C#9F9FD&9FD$%455-)B?R]`````&9F9I!(8\5(:<`P
-M`0``2HV<(*A$``"#>W0`="!(@WL(`'492(G>3(GGZ`````#V0P$$=`A(QT-H
-M`````/_%@_T/?L%;74%<PV9F9I!F9F:09F9FD$%7059!54%455-(@>P(`@``
-M28G]2(GU08G628GG2(GWZ`````"`?0`(=0M(B>Y,B>_H`````$&\`````(!]
-M<``/AL<```!)8\1(@[S%B``````/A*@```!(B[3%B````(`^`W8100^VUDR)
-M[^@`````Z8H```!)8\1(BYS%B````,9#`P!(QT,(`````,>#C`````````"`
-M8P'^2,=#:`````!%A/9U#8!]``9U!TB#?0@`="JZ``(``+X`````3(G_Z```
-M``!(C7MP3(GYNC````"^`````.@`````ZQ,/ME4!@^(!#[9#`8/@_@G0B$,!
-M2(G?Z`````!F9I!F9I!!_\1$.&5P#X<Y____NC`!``"^`````$B)[^@`````
-M28N%H$0``$B)11!)B:V@1```QT5T`````$B!Q`@"``!;74%<05U!7D%?PV9F
-MD&9FD$%6055!5%532('L``(``$B)TTB+!DR+:`A,BW8X28MN($0/MF`#2(GB
-M2(7M=`UF00^V1AB#X`$YR'4A2(G528-^*`!T#4R)]D'_5BB%P&:0=0JX````
-M`.F(````00^W3DC!X0E!#[9V1&9F9I!F9I!,BT4`OP```0!F@WT(`'0$#[=]
-M"#GYB?H/1M%$.>9U$6:)4PAFQT,*``!,B0-(@\,0*=>)T$D!P"G1=1O_QD$/
-MMD5P.<:X``````]$\$$/MT5\B<'!X0F%_W6Y9H%]"@"`=`9(@\40ZY=FQT/Z
-M`("X`0```$B!Q``"``!;74%<05U!7L-F9F:09F9FD&9F9I!,BT\(1(M&0`^V
-M3P,/MWY,.$Y$=0L/MT9*00'`ZP]FD#A.1'8(00^W07Q!`<`X3D1U!&8#?D@X
-M3D5U!68#?D:0@'Y0`'0..$Y$<QTX3D5FD'<1ZQ0X3D1S!69!`WE\.$Y%=@5F
-M00-Y?&:)>@Q$B4((PV9F9I!F9F:09F9FD&9FD%-)B?E)B?"+?@A$#[=6#$&[
-M`````$$/MDERB?[3[F9!QT!,``!!QD!0`4$/ME%PB?")T;H`````]_%!#[9)
-M<M/@08E`0$$/ME%PB?")T;H`````]_%!B%!$B=%!#[=!?/_((?AF08E`2D$/
-MMU%\9BG"9D0YTG(-9D6)4$A!N@````#K7&9!B5!(9D$ITD&[`0```+H!````
-MB=#3X&9!"4!._\%!.$EP=2>Y`````$&`>%``=`M!QD!0`.L49F9FD$$/MT!,
-M9D$#07QF08E`3)!F13E1?',)9D4K47SKNF:0N`$```#3X&9!"4!.08A(169%
-MB5!&00^WPUO#9F:09I!54TB#[`A(B?U(BUXX2(L&#[9(`[C^____T\!F(4-.
-M@'X9`70'#[9&&8A#&4B)[^@`````9H-[3@!U&8![&0!U!,9#&0%(BW,P2(G:
-M2(GOZ`````!(@\0(6UW#9F:09I!(B5PDT$B);"383(ED).!,B6PDZ$R)="3P
-M3(E\)/A(@^PX28G_2(GU3(LV0?9&`01U%<9&&0)(BW8P2(GJZ`````#IR@``
-M`$R)]^A1_O__9H-]3@!U&L9%&0)(BW4P2(GJ3(G_Z`````#IHP```&:00;T`
-M````08!^<``/A)`````/MT5.1(GIT_BH`71R3(G_Z`````!(B<-)8\5-BZ3&
-MB````$R)(TB):S@/ME48@^("#[9#&(/@_0G0B$,8#[95&(/B!(/@^PG0B$,8
-M#[9%#HA##DB)VDB)[DR)Y^@^_?__2,=#,`````!(QT,H`````$B)WDR)_T'_
-M5"1@9F:00?_%00^V1G!$.>@/CW#___](BUPD"$B+;"003(MD)!A,BVPD($R+
-M="0H3(M\)#!(@\0XPV9F9I!F9F:09F9FD$B#[`A(BTX(#[91`8!F`?N`80'[
-M_DEQ@$E^`4B#>6@`#Y7`]L($#Y7"#[;`A<)T!DB)SO]1:$B#Q`C#9F:09I!(
-M@^P(3(M&.$F+<"!(A?9T#69!#[9`&(/@`3G(=2))@W@H`'003(G&0?]0*+H!
-M````A<!U,+H`````ZREF9F:02(L&2(D"2(M&"$B)0@A(@\(02(U&"DB#QA!F
-M@S@`>>"Z`0```(G02(/$",-F9F:055-(B?L/M@>#Z`2#^`%W4+T`````@']P
-M`'0W9F:09I!(8\5(@[S#B`````!T$4B+O,.(````Z,7___^%P'4'N`````#K
-M)/_%#[9#<#GH9I!_SK@!````ZQ%F9F:09F:0#[9'`<#H`H/@`5M=PV9FD$B)
-M7"382(EL).!,B60DZ$R);"3P3(ET)/A(@^PH28G^2(GU2(M>.$R+(TR++H!^
-M&0$/A-D```#V0Q@"#X1_````@'L:``^%Q0```$'V1"1^`@^%N0```,9#&@%!
-M@'T#`4@9P(/@"$Z+K""(````387M=$),B>_H%?___X7`=#9(C7U`ND@```"^
-M`````.@`````00^V30.X`0```-/@9HE#3DR);0!(B>Y,B?=!_U5@Z<````!,
-MBVT`ZU5F9I!FD/9#&`1T2DR)[^C"_O__A<!T(DB-?4"Z2````+X`````Z```
-M``!(B>Y,B?=!_U5@Z8$```"`>QD!=!T/MU-.00^V30.X`0```-/@.<)U"6:0
-M#[9%&8A#&4B)[DR)]^@`````00^V30.X_O___]/`9B%#3F:#>TX`=3R`>QD`
-M=03&0QD!2(MS,$B)VDR)]^@`````9D'_3"0B9D&#?"0B`'4428M$)#!(A<!T
-M"DF+="0X3(GW_]!(BQPD2(ML)`A,BV0D$$R+;"083(MT)"!(@\0HPV9F9I!F
-M9F:09F:09F:02(/L"$B+1CB%R70:2(M`$$B)`@^W1@S!X`EFB4((9L=""@"`
-MZU%(@W@@`'0S]D`8`70M2(M(($B+`4B)`DB+00A(B4((2(/"$$B-00I(@\$0
-M9H,X`'G@ZQYF9F:09F:0O@````!(@W@H`'002(G&D/]0*(G&ZP6^`0```(GP
-M2(/$",-F9F:09F:09F:09F:02(E<).A(B6PD\$R)9"3X2(/L&$F)_$B)\TB+
-M;CA(BP8/MD@#N/[____3P&8A14Z`?AD!=`</MD89B$492(G>3(GGZ`````!F
-M@WU.`'55@'T9`'4?QD49`4B+30"+D80````[4PAU#`^W0PP!T(F!A````$B+
-M=3!(B>I,B>?H`````$B+10!FQT`@``!(BU4`2(/"*$C'Q@````!,B>?H````
-M`$B+'"1(BVPD"$R+9"002(/$&,-F9F:09F:09F:02(E<).A(B6PD\$R)9"3X
-M2(/L&$F)_$B)\TB+;CB`?AD!=`T/MD89B$49ZW1F9F:0@'X.('5*QD89`$B+
-M10!(BX"0````2(D&2(U^0+I(````O@````#H`````,9#&@#&0PXP#[9#&(/@
-M_8/(!(A#&$B+`TB)WDR)Y_]08.M=9I#&11D!2(M-`(N1A````#M6"'4-#[=&
-M#`'0B8&$````D$B)WDR)Y^@`````2(MU,$B)ZDR)Y^@`````2(M%`&;'0"``
-M`$B+50!(@\(H2,?&`````$R)Y^@`````2(L<)$B+;"0(3(MD)!!(@\08PV:0
-M05154TF)]$B)U4B+1CB%R71&2(M0$$B)50`/MT8,P>`)9HE%"&;'10H`@$B+
-M!H!X`P`/A`T!``!(C8(```$`9H-]"`!T"4@/MT4(2(T$`DB)10#I[0````^W
-M7@S!XPE(@W@@`'0L]D`8`70F2(M(($B+`4B)`DB+00A(B4((2(/"$$B-00I(
-M@\$09H,X`'G@ZS2Z`````$B#>"@`#X2H````2(GJ2(G&_U`HN@````"%P`^$
-MD@```.L,9HE9"&;'00H`@.M&2(GI9F9FD&9FD+H```$`9H-Y"`!T!`^W40A)
-MBP0D@'@#`'06.=IV%HG82`$!B=!F*=AFB4$(ZPYFD#G:<[9(@\$0*=-UQ$F+
-M!"2`>`,`#Y7`2#G-#Y7"#[;`A<)T(4B+`4B)10!(BT$(2(E%"$B#Q1!(C4$*
-M2(/!$&:#.`!YW[H!````B=!;74%<PV9F9I!F9F:09F9FD&9FD$B)7"3H2(EL
-M)/!,B60D^$B#[!A)B?Q(B?-(BVXX@'X9`70-#[9&&8A%&>F!````D$B+!H!X
-M`P!U-\9&&0!(BT4`2(N`D````$B)!DB-?D"Z2````+X`````Z`````#&0QH`
-M2(L#2(G>3(GG_U!@ZWL/MU8,P>()B=9(BWT02`'^Z`````"%P'0'QD49#.LA
-MD,9%&0%(BTT`BY&$````.U,(=0T/MT,,`=")@80```"02(G>3(GGZ`````!(
-MBW4P2(GJ3(GGZ`````!(BT4`9L=`(```2(M5`$B#PBA(Q\8`````3(GGZ```
-M``!(BQPD2(ML)`A,BV0D$$B#Q!C#9I!(B5PDX$B);"3H3(ED)/!,B6PD^$B#
-M["A)B?Q(B?-(BRY(QT4P`````/9%?@$/A54!```/MD8.@_@"#X3V````@_@"
-M?Q"#^`$/A)8```!FD.DS`0``@_@##X4J`0``BT8(B44<#[=&#&:)12`/MU8,
-MP>()2(M^$+X`````Z`````!FQT-.`P!!O0````!,B>?H`````$B)QL9`#C"+
-M0PB)1@@/MT,,9HE&#(!.&`1(B5XX2,=&,`````!(QT8H`````$ECQ4B+A,6(
-M````2(D&3(GG_U!@0?_%08/]`7ZNZ;<```"+1@B)11P/MT8,9HE%(.@`````
-M2(G&QD`.((M#"(E&"`^W0PQFB48,@$X8`DB)7CA(QT8P`````$C'1B@`````
-M2(N%B````$B)!DR)Y_]08.MEBT8(B44<#[=&#&:)12#H`````$B)QL9`#B"+
-M0PB)1@@/MT,,9HE&#(!.&`)(B5XX2,=&,`````!(QT8H`````$B+A8@```!(
-MB09,B>?_4&#K$\9#&09(BW,P2(G:3(GGZ`````!(C54H2,?&`````$R)Y^@`
-M````2(M<)`A(BVPD$$R+9"083(ML)"!(@\0HPV9FD&9FD&9FD$B)7"302(EL
-M)-A,B60DX$R);"3H3(ET)/!,B7PD^$B#[#A)B?])B?1(BR[V10$$=17&1AD"
-M2(MV,$R)XN@`````Z=H!``#V1A@@="1(QT4P`````$B)=3AF@WTB``^%O0$`
-M`.C(_?__Z;,!``!F9I!(@WTP`'4I9H-](`!F9F:0=#X/MT4@`T4<.T8(=C(/
-MMT8,`T8(.44<<R9F9I!F9I!)QT0D2`````!(C7TH3(GFZ`````#I9@$``&9F
-MD&9FD&;_12+V17X##X6B````0?9$)!@"#X26````2(N5B````$B+M9````"`
-M.@-U9(`^`W5?08M$)`B)P2N*D````$&)P$0KAI````"+NI0```"+MI0```")
-MR)DQT2G11(G`F4$QT$$IT$0YP7T3A?8/E$0D!X/_!0^7P"!$)`?K-X7_#Y5$
-M)`>#_@4/EL`(1"0'ZR2`O8(`````#Y1$)`</MDPD!XB-@@```.L+9F:09F:0
-MQD0D!P!F0<=$)$X``$&^`````$2)\$0/MNA*@[SMB`````!T>TJ+A.V(````
-M]D`!!'1M00^V5"08P.H"1#AT)`</E,`)T*@!=%9,B?_H`````$B)P[I`````
-M3(GF2(G'Z`````"X`0```$2)\=/@9D$)1"1.3(EC.$C'0S``````2,=#*```
-M``!*BX3MB````$B)`TB)WDR)__]08&9FD$'_QD&`_@$/AF;___]F9I!(BUPD
-M"$B+;"003(MD)!A,BVPD($R+="0H3(M\)#!(@\0XPV9F9I!F9I!F9I!F9I!5
-M4TB#[`A(B?5(BUX(#[96`X!F`?N`2WX!QX.$`````````/Y+<8![<0!U!H!C
-M`?OK%@^V0WZH`G0.@^#5B$-^A=)U!(!C`?OV0P$$=1=(@WMH``^$[P```$B)
-MWO]3:)#IXP```(72=21(BY.(````QD(#`4B+@Y````#&0`,`2(F#B````$B)
-MDY````!(@WL(`'0.2(M#"/9``00/A'X```!(BX.(````@#@#=7)(B=[H````
-M`$B)PDB%P'1BQ@`#QD`#`4B)6`A(BP4`````2(E"8$B+!0````!(B4)H]D,!
-M$'0-@$H!$(N"B````(E"&$C'10@`````2(F3D`````^V0WZ#X/Z#R`J(0W[^
-M0W%(B=:_!P```.@`````9I!(@WL(`'0+2(M;"$B#>P@`=?6+0W2)0WCH````
-M`(E#=$B)W^@`````2(/$"%M=PY!(B5PDV$B);"3@3(ED).A,B6PD\$R)="3X
-M2('L*`(``$F)U$R+-DB+;CA(BUT@0;T1````2(GB2(7;=`QF#[9%&(/@`3G(
-M=2A(B=-(@WTH`'0.2(GN_U4HA<!U%&9F9I"X`````.GE````9F:09F:0@'U%
-M_P^$O@````^W34C!X0FZ```!`&:#>P@`=`0/MU,(.=%V.T$/MD8#.D5$=11(
-MBP-)B00D2(M#"$F)1"0(28/$$"G12(/#$+H```$`9H-["`!T!`^W4PA!_\TY
-MT7?%00^V1@,Z141U'$B+`TF)!"1F08E,)`AF0<=$)`H`@+@!````ZUDYT7,W
-MB<A(`P-)B00DB=!F*<AF08E$)`AF@7L*`(!U#V9!QT0D"@"`N`$```#K*F9!
-MQT0D"@``28/$$$B#PQ!!_\U$B>I(P>($2(G>3(GGZ`````"X`0```$B+G"0`
-M`@``2(NL)`@"``!,BZ0D$`(``$R+K"08`@``3(NT)"`"``!(@<0H`@``PY`/
-MMD<#.D9$=0\/MT9(9HE"#(M&0(E"",,/MT9&9HE"#,=""`````##9F9FD&9F
-M9I!$BT8(1`^W3@Q!NP````"Y`````(!_<``/A((```!%#[?1B<A(BY3'B```
-M`$0Y0AAV7T2)1D"(3D2X`0```-/@#[=^3@G'9HE^3D.-!`([0AAV,T&[`0``
-M`(U!`8A&1?_!1(G8T^")P8GX"<AFB49.BT(89D0IP&:)1DAF02G!9D2)3D;K
-M&L9&1?]F1(E.2.L/1"M"&/_!#[9'<#G(=X.01(G8PV9F9I!F9F:09F9FD%53
-M2(/L"$B)_4B+7CA(BP8/MD@#N/[____3P&8A0TZ`?AD!=`</MD89B$,92(GO
-MZ`````!F@WM.`'49@'L9`'4$QD,9`4B+<S!(B=I(B>_H`````$B#Q`A;7<-F
-M9I!FD$B)7"302(EL)-A,B60DX$R);"3H3(ET)/!,B7PD^$B#[#A)B?](B?5,
-MBS9!]D8!!'45QD89`DB+=C!(B>KH`````.G*````3(GWZ*'^__]F@WU.`'4:
-MQD49`DB+=3!(B>I,B?_H`````.FC````9I!!O0````!!@'YP``^$D`````^W
-M14Y$B>G3^*@!='),B?_H`````$B)PTECQ4V+I,:(````3(DC2(EK.`^V51B#
-MX@(/MD,8@^#]"="(0Q@/ME48@^($@^#["="(0Q@/MD4.B$,.2(G:2(GN3(GG
-MZ-[]__](QT,P`````$C'0R@`````2(G>3(G_0?]4)&!F9I!!_\5!#[9&<$0Y
-MZ`^/</___TB+7"0(2(ML)!!,BV0D&$R+;"0@3(MT)"A,BWPD,$B#Q#C#9F9F
-MD&9F9I!F9F:02(/L"$B+1@B`9@'[@&`!^_Y(<8!(?@%(@WAH`'0&2(G&_U!H
-M2(/$",-F9F:09F:02&/.2(N4S^!7``!(A=)T"TB+`DB)A,_@5P``2(G0PY!(
-M8])(BX37X%<``$B)!DB)M-?@5P``PV9FD&9FD&9FD$%7059!54%455-(@^P(
-M28G_O0"```"!_@!```!W:&:]`$"!_@`@``!W7&:]`""!_@`0``!W4&:]`!"!
-M_@`(``!W1&:]``B!_@`$``!W.&:]``2!_@`"``!W+&:]``*!_@`!``!W(&:]
-M``&!_H````!W%&:]@`"#_D!W"X/^(1GM@^7@@\5`B=`/K\5$C;#_#P``0<'N
-M#,=$)`0`````N`````"!_0`0```/A]L```!!_\Y!@_[_#X3*````0;T`$```
-M3(G_Z`````!(B</_1"0$0;P`````1(GHN@````#W]8/X``^&CP```&9FD&9F
-MD+H*````@?T`0```=U:R"8']`"```'=,L@B!_0`0``!W0K('@?T`"```=SBR
-M!H']``0``'<NL@6!_0`"``!W)+($@?T``0``=QJR`X']@````'<0L@*#_4!W
-M"8/](`^7P`^VT$B)WDR)_^B"_O__B>A(`<-!_\1$B>BZ`````/?U1#G@#X=W
-M____0?_.08/^_P^%//___XM$)`1(@\0(6UU!7$%=05Y!7\-F9F:09F:055-(
-MB?V)\[@`````.;<X6```<E.^`P```.@"_O__2(G&2(7`=#Z)&/_+@_O_=#60
-MB=FZ`````$B#O3!8````=!=(BY4P6```2(L"2(F%,%@``/^-.%@``$B)5,X(
-M_\N#^_]US$B)\%M=PV9FD&9FD(L._\F#^?]T+69F9I!F9I!(8\%(BU3&"$B+
-MAS!8``!(B0)(B9<P6```_X<X6```_\F#^?]UVKH#````Z)#]___SPV9F9I!F
-M9F:09F:09F:055-(@^P(2(G]BQ__RX/[_W0>2&/#2(M\Q0BZ`!```+X`````
-MZ`````#_RX/[_W7B2(/$"%M=PV9FD&9FD&9FD(L/_\F#^?]T+DACP4B+1,<(
-MN@````!(@S@`=`:X`````,/_PDB#P`B!^O\!``!VYO_)@_G_==*X`0```,-F
-M9I!(@^P(NA````"^`````.@`````2(/$",-F9F:09F9FD$B#?A``=`Q(BU80
-M2(M&"$B)0@A(BU8(2(M&$$B)`DC'1@@`````N@````#HL/S___/#9F9FD&9F
-M9I!F9I!F9I!(C4]82(M'6$B)1A!(A<!T#$B+5UA(C4802(E""$B)3@A(B3'#
-M9F9FD&9F9I!F9I!(B5PDX$B);"3H3(ED)/!,B6PD^$B#["!)B?5!B=2)S4B+
-M7EA(A=MT(F9F9I!F9I`Y*W,.1#EC!'8(N`````"0ZRI(BUL02(7;=>6^````
-M`.C[^___2(G#1(D@B6@$2(G&3(GOZ&?___](B=A(BQPD2(ML)`A,BV0D$$R+
-M;"082(/$(,-F9F:09F9FD&9F9I`/MD=)#[;02(T4DDB-5-=0_\"(1TE(B3K&
-M0@D`QD(*`,9""P!(B=##9F9FD&9F9I!!5%5328G\2(GSO0`````/ME9&C4+]
-MT?@!PH/Z`'XED$ACQ4B+M,.@"@``3(GGZ*W]____Q0^V4T:-0OW1^`'".>I_
-MW+H'````2(G>3(GGZ%S[__];74%<PV9F9I!F9I!!5T%6055!5%532(/L"$F)
-M_8E4)`2)\T&)SHNW.%@``,'F`P^WR0^VTXU"_='X`<(/K\HYS@^#UP```$0/
-MMOM$B3PD08G,28V%L%<``$DYA;!7```/A-@```!)BZVP5P``2(M5"$B+10!(
-MB5`(2(D"2(EM`$B);0A(@WT@`'0F2(-]*`!T#$B+52A(BT4@2(E"($B+52!(
-MBT4H2(D"2,=%(`````!F1#EU1'5(.%U&=4-(B6T`2(EM"(M$)`2)14!!O```
-M``!!@_\`?B"+'"2026/\2,'G!$B-O"]P"P``Z&S]__]!_\1$.>-_Y$B)Z.DF
-M`0``2(GN3(GOZ*'^__]!BX4X6```P>`#1#G@#X(T____O@<```!,B>_H$?K_
-M_TB)Q;@`````2(7M#X3J````ZPZX`````.G>````9F9FD$B);0!(B6T(BT0D
-M!(E%0&9$B75$B%U&2,=%,`````!!O``````/MM.-0OW1^`'"@_H`#XZ?````
-M18GW9D'![P,/MM.-0OW1^$2--`)F9F:026/<00^W]TR)[^AQ^___2(F$W:`*
-M``!(A<!U/$'_S$&#_/]T'$ECQ$B+M,6@"@``3(GOZ+C[__]!_\Q!@_S_=>2Z
-M!P```$B)[DR)[^AO^?__N`````#K,DECQ$C!X`1(C1PH2(V[\`H``.A1_/__
-M2(V[<`L``.A%_/__0?_$13GF#X]Y____2(GH2(/$"%M=05Q!74%>05_#9F9F
-MD&9FD$%455-(B?6)TXG.#[9-<HG0T^@E_P$``$B+55!,C23"38L$)$V%P'0P
-M9F9FD&9FD$$Y6$!U&DF+4`A)BP!(B5`(2(D"38D`38E`"$R)P.MM38M`*$V%
-MP'77#[?.#[9U<(G:Z&G]__])B<!(A<!T2TB):#A)BP0D28E`*$B%P'0,28L4
-M)$F-0"A(B4(@38E@($V)!"0/MG5P08AP1@^V37*)V-/H#[95<(G1N@````#W
-M\4`HUO_.08AP1TR)P%M=05S#9F9FD&9F9I!F9I!F9I!!5T%6055!5%532('L
-M:`$``$B)?"1(2(ET)$!(B50D.`^V5AB)T-#H@_`!B<&#X0&)3"0T2(-^(`!T
-M!?;"`70<3(U\)%"Y`0```$R)^DB+="1`2(M\)$C_5BCK"4B+7"1`3(M[(,=$
-M)`P```$`9D&#?P@`=`E!#[='"(E$)`Q!O0````#'1"0P`````$B+5"1`@'IX
-M``^$=0$``$AC1"0P2(M,)$!(BT3!4$B)1"0@#[:88`P``(A<)"\XF&$,```/
-M@C,!```/MD0D+TB+5"0@.$)'#X0&`0``#[;`2(G1#[>4@D`,```/MX2!0@P`
-M`&:)1"00B=!FP>@##[?`B40D"$&)UD&#Y@=!#[?&B<;!Y@FX"````&9$*?!!
-MB<9F1#MT)!"+7"001`]'\T$/M\:)Q<'E"4@/MD0D+TB+5"0@2(N,PJ`*``"+
-M5"0(B?!)B<1,`V31"$0[;"0,=21)@\<0QT0D#````0!F08-_"`!T"4$/MT\(
-MB4PD#$&]`````)"+7"0,1"GK.>L/1]V#?"0T`'021(GN20,WB=I,B>?H````
-M`.L01(GO20,_B=I,B>;H`````$$!W2G==`>)V$D!Q.N29D0I="00=!3_1"0(
-MO@````!!O@@```#I/O____Y$)"\/MEPD+TB+1"0@.)AA#```#X/-_O___T0D
-M,$B+5"1`#[9">#M$)#`/CXO^__^Z`````$B+="1`2(M\)$C_5"0X2('$:`$`
-M`%M=05Q!74%>05_#9F9FD&9F9I!F9I!54TB#[`A(B?V%TG0$QD89"T&[````
-M`(!^>``/A,$```!(C9W`5P``2(V]L%<``)!)8\-,BT3&4$G'@#`,````````
-M38G"N0````!!@'A&`'9(#[;!2,'@!$P!T$B-D/`*``!!N0````"#N/`*````
-M=1*#>@0`=0R#>@@`=0:#>@P`=`9!N0$```!%A<EF9I!U)?_!03A*1G>XN```
-M``"%P'0=2(M#"$R)0PA)B1A)B4`(3(D`ZQNX`0```.OA9I!(BT<(3(E'"$F)
-M.$F)0`A,B0!!_\,/MD9X1#G8#X].____2(GOZ`8X``!(@\0(6UW#9F9FD&9F
-M9I!F9F:09F:02(E<)-!(B6PDV$R)9"3@3(EL).A,B70D\$R)?"3X2(/L2$F)
-M_4B)\TB+KC`,``#_CSQ8``!(C4802(M("$B+5A!(B4H(2(D12(E&$$B)0`A(
-MA>T/A(<"``#V11@@#X0=`0``3(ME``^W1D1!B<9$`W9`1`^W?D1(QX8P#```
-M`````$B-A[!7``!(BU`(2(EP"$B)!DB)5@A(B3*`OF(,```!=56`?0X"=49(
-M#[9&1TB+O,:@"@``Z!3W__^%P'4PQH-B#```#$&`3"1^"D$/MT0D?/?8(T-`
-M03F$)(0```!V#D&)A"2$````9F:09F:0@+MB#````70:#[:#8@P``(A%&4B)
-M[DR)[^CB-@``Z6T#``!!#[=$)'R+50C_P@^OPD0Y\'8M00^WST2)\DR)YDR)
-M[^BX^O__2(FH,`P``$B)15!(B<9,B>_H`A```.DM`P``00^W1"1\00.$)(0`
-M``!$.?!U"$6)M"2$````2(GN3(GOZ'<V``#I`@,``&:0#[9%>?_`B$5Y.D5X
-M#X6.`@``]D48!`^$T@```$&^`````(!]>``/AK(```!(C8>P5P``2(E$)!!(
-MC9?`5P``2(E4)`A$B?(/ML)(BUS%4$C'@S`,````````@+MB#````75-28G?
-M0;P`````@'M&`'8@1(G@#[;X2,'G!$J-O#_P"@``Z`?V__]!_\1%.&=&=^!(
-MBU0D$$B+0@A(B5H(2(D32(E#"$B)&.LF9F:09I`/MH-B#```B$492(M4)`A(
-MBT((2(E:"$B)$TB)0PA(B1A!_\9$.'5X#X=F____2(GN3(GOZ(<U``#IL@$`
-M`$&^`````(!]>`!V+69FD&9FD$2)\@^VPDB+7,50@+MB#````70*#[:#8@P`
-M`(A%&4'_QD0X=7AWV8!]&0!U%TC'P@````!(B>Y,B>_H`?K__^E<`0``N@``
-M``!(B>Y,B>_H+/S__^E'`0``9F9FD&9FD("^8@P```$/A8,```!)B?2]````
-M`(!^1@!V)&9FD&:0B>@/MOA(P><$2HV\)_`*``#H^O3____%03AL)$9WX4B#
-MNS@,````="E(BX,X#```2(F#,`P``$C'@S@,````````2(G>3(GOZ`,.``#I
-MS@```$F-A;!7``!(BU`(2(E8"$B)`TB)4PA(B1KK6F9FD$B-A\!7``!(BU`(
-M2(EP"$B)!DB)5@A(B3)(@[XX#````'0T2(N&.`P```^VEF(,``"(4!E(BY8X
-M#```2,?&`````.@`````2,>#.`P```````#IN0```$B+<S!,B>_H7?3__TC'
-M0S``````2(M#.$B#>"@`=!5(C5`H2,?&`````$R)[^@`````ZR5)@[U(6```
-M`'0;28V52%@``$C'Q@````!,B>_H`````&9FD&:008.]0%@```!T5H"[8@P`
-M``%U34B+>SA(@W]``'0PZ-TQ``"%P'4G2(M#.$B+4$A(BW!`3(GOZ`````!(
-MBT,X2,=`0`````!!_XU`6```08.]0%@```!T"$R)[^@`````2(M<)!A(BVPD
-M($R+9"0H3(ML)#!,BW0D.$R+?"1`2(/$2,-F9F:09F:09F:09F:02(/L"$B+
-M%H!Z2@!T$\9"2@!(Q\8`````Z`````!F9I!(@\0(PV9F9I!F9F:09F:005=!
-M5D%505154TB#[`A)B=1!B<](BT8X2(L02`^V0!%,B[3"H`H``(M&""M"0,'@
-M"0^W;@S!Y0F)P8'A_P\``$&)Q4'![0R[`!```"G+.>L/1]U%A?]T#$ECU8G(
-M20-$U@CK#TECQ8G/20-\Q@CH`````$F)!"1F08E<)`@YZW089D''1"0*``!)
-M@\000?_%*=VY`````.NN9D''1"0*`("X`0```$B#Q`A;74%<05U!7D%?PV9F
-M9I!F9F:09F:0#[9'$@)'$XA'$DB-5Q2^`0```.L/@'\2`'D&N`````##_D<2
-M#[9/$H/Y'W<3B?#3X(5'%`^5P`^VP.M49F9FD(/Y/W<2@^D@B?#3X(5"!`^5
-MP`^VP.LY@_E?=Q2#Z4")\-/@A4((#Y7`#[;`ZR)FD+@`````@_E_=Q:#Z6")
-M\-/@A4(,#Y7`#[;`9F:09F:0A<!T@<9'$P%,C4<4#[97$KX!````ZP/^1Q,/
-MMD<3C0P"@_D?=P^)\-/@A4<4#Y7`#[;`ZTZ#^3]W%H/I((GPT^!!A4`$#Y7`
-M#[;`ZS9F9I"#^5]W$X/I0(GPT^!!A4`(#Y7`#[;`ZQNX`````(/Y?W<1@^E@
-MB?#3X$&%0`P/E<`/ML"%P'60L`'#9F:09F:02(E<).A(B6PD\$R)9"3X2(/L
-M&$B)_4B+7CA,BR,/MD89B$,*Z`````"`>PH!=7%(B=_HJ?[__X7`=!7&0PH`
-M2(G>2(GOZ,8```#K8V9F9I"`>P@!=4H/MD,003A$)$>0=#XX0Q%U.0^V\$B)
-M\$C!X`1*C;0@<`L``$B-2Q2+!@M#%(D&BT8$"T$$B48$BT8("T$(B48(BT8,
-M"T$,B48,D,9#"0)(B=Y(B>_H0?W__TB+'"1(BVPD"$R+9"002(/$&,-F9F:0
-M9F9FD&9FD&9FD$B)7"3P3(ED)/A(@^P828G\2(GSQD83`,9&$@!(B??H[/W_
-M_TB)WDR)Y^@1````2(M<)`A,BV0D$$B#Q!C#9I!(B5PDX$B);"3H3(ED)/!,
-MB6PD^$B#["A)B?U(B?-(BRY(BU4X2`^V1A!,BZ3"B````.@`````2(G&3(D@
-M@'L(`74-@$@8`L9`#B#K"V9FD(!(&`3&0`XP#[9#$@-%0(E&"&8/MD,39HE&
-M#$C'1B@`````2(E>.$C'1C``````3(GO0?]4)&!(BUPD"$B+;"003(MD)!A,
-MBVPD($B#Q"C#05154T&Y`````$&[`````$B)_4&\`0```.L808/[?W8/1(G(
-MZ5X!``!F9F:09F:00?_#1(G:08/['W<21(G@1(G9T^"%!P^5P`^VP.M208/[
-M/W<3C4K@1(GCT^.%700/E<`/ML#K.4&#^U]W$XU*P$2)X-/@A44(#Y7`#[;`
-MZR"X`````$&#^W]W%8U*H$2)X]/CA5T,#Y7`#[;`9F9FD(7`#X1S____0;@!
-M````2(GZ0;H!````ZPIF9F:09F:00?_`0XT,`X/Y'W<41(G0T^"%`@^5P`^V
-MP.M59F:09I"#^3]W$X/I($2)T-/@A4($#Y7`#[;`ZSB#^5]W$X/I0$2)T]/C
-MA5H(#Y7`#[;`ZR"X`````(/Y?W<6@^E@1(G0T^"%0@P/E<`/ML!F9I!FD(7`
-M=8Q$B=E%`<-!N@@```!$B<J)R,'H`X@$EHG(@^`'B$26`42)TRC#B%R6`@^V
-MPT0YP',*02G``<%!_\'KT42)R$2(1(8"0?_!08/[?P^&K_[__T2)R%M=05S#
-M9F9FD$B)7"302(EL)-A,B60DX$R);"3H3(ET)/!,B7PD^$B![%@!``!(B7PD
-M"$F)]4B++DB+7A"`>QD`#X3C````2(-[$`!U"TB)<Q#I9`$``&:0QD,9`$B-
-M="0@2(G?Z`_^__]!B<9(#[9#&$R+I,6@"@``2(M#$$@/MD`83(N\Q:`*``!)
-M#[9%&$B+K,6@"@``NP````!$.?,/C0,!``!F9I!(8],/MD24(8G!P>$)#[9$
-ME")!B<!!P>`)1`^V3)0@1(G(#[;0B<A(B<=)`WS7"$B)?"002(G&2`-TU0A(
-MB70D&$D#1-0(2#G'=0I$B<+H`````.L@2(M4)!A(BW0D$$2)R$0/MLB)STL#
-M?,P(1(G!Z`````#_PT0Y\WR$Z7\```!(C70D($B)W^A"_?__08G&2`^V0QA,
-MBZ3%H`H``$D/MD483(N\Q:`*``"[`````$0Y\WU+2&/3#[9$E"&)P<'A"0^V
-M1)0B08G`0<'@"4@/MD24((G.2(GW20-\Q`A(B7PD$$D#=,<(2(ET)!A$B<+H
-M`````/_#1#GS?+EF9F:0N@````!,B>Y(BWPD".A^`@``2(N<)"@!``!(BZPD
-M,`$``$R+I"0X`0``3(NL)$`!``!,B[0D2`$``$R+O"10`0``2('$6`$``,-F
-M9I!F9I!(B5PDT$B);"383(ED).!,B6PDZ$R)="3P3(E\)/A(@>Q(`0``28G_
-M2(GU2(L>2(UT)!!(C7T0Z$3\__]!B<1(#[9%($R+M,.@"@``2`^V12%,BZS#
-MH`H``+L`````1#GC?3U(8\,/MG2$$<'F"0^V5(02P>()2`^V1(00B?9(B?=)
-M`WS&"$B)/"1)`W3%"$B)="0(Z`````#_PT0YXWS#N@````!(B>Y,B?_HD`$`
-M`$B+G"08`0``2(NL)"`!``!,BZ0D*`$``$R+K"0P`0``3(NT)#@!``!,B[PD
-M0`$``$B!Q$@!``##9F9FD&9F9I!!5T%6055!5%532('LB`$``$F)_TB)]4R+
-M)DB+7A!(C;0D@````$B)W^AB^___08G&2`^V0QA-BZS$H`H``+L`````@'T@
-M`'8C#[9-(&9FD`^VPT@/ME0H&$F+E-2@"@``2(E4Q$#_PSC9=^1!O`````!%
-M.?0/C:T```!F9I!FD$ECQ`^VE(2!````08G20<'B"0^VE(2"````08G30<'C
-M"0^VC(2`````NP````"`?2``=BA$#[;)18G0#[9U()`/ML-(BU3$0$J+?,H(
-M28T4.$B)%,3_PT`XWG?D#[;11(G02(G'20-\U0A(.3PD=1!(BW0D"$2)VN@`
-M````ZQV02(M4)`A(BS0D#[;!1(G720-\Q0A$B=GH`````$'_Q$4Y]`^,6/__
-M_[H`````2(GN3(G_Z!@```!(@<2(`0``6UU!7$%=05Y!7\-F9I!F9I!(B5PD
-MZ$B);"3P3(ED)/A(@^P828G\2(GSB=7&1@D"@_H!&<"#X/6#P`R(1@KH3O;_
-M_X!["`-U+TB+0Q!(BW`02(7V=")(QT`0`````,9&"0*#_0$9P(/@]8/`#(A&
-M"DR)Y^@9]O__2(L<)$B+;"0(3(MD)!!(@\08PV9FD&9FD`^V5@N%TG1&B=!(
-M#[:$1[`)``!(C02`2(U$QU"`>`D"=`:X`````,.`>`H!=!+&1@D"#[9`"HA&
-M"K@`````PY")T`^VE$>Q"0``A=)UNK@!````PV9F9I!F9F:09F9FD$%7059!
-M54%455-(@^P(28G^2(GUQD9*`("^8PP````/A(L```!!O`````!(C5U0@'U)
-M`'1.@'L)`74X@'L(`W4I2(M#$(!X&0!T'TB#>!``=!A(QT`0`````,9#"0(/
-MMH5B#```B$,*ZPG&14H!Z;<!``!!_\1(@\,H#[9%240YX'^R2(GN3(GWZ&+P
-M___IEP$```^V0PJ(A6(,``#&A6,,```!Z7S___]F9F:09F:00;\`````0;T!
-M````0;P`````2(U=4(!]20`/A#0!``"`>PD`=7I(B=Y(B>_HO_[__X7`=%O&
-M0PD!3(GW2(G>#[9#"(/X!G=(B<#_),4`````Z'KW___K.&9F9I!F9F:0Z-OY
-M___K*>C$^___9F9FD.L>Z*G\___K%\9%2P'&1@D"QD8*`>AF]/__9F:09F:0
-M@'L)`G400?_'9F9FD&9FD(!["0)T"T&]`````.F/````@'L*`0^$A0```(!]
-M2P"0#X0=____2(M%.$@/ME,02(N$T(@```#V0`$$=%]!O0````#&0PD!QD,*
-M`$R)]TB)W@^V0PB#^`9W1HG`_R3%`````.C(]O__ZS9F9I!F9I#H*_G__^LI
-MZ!3[__]F9F:0ZQ[H^?O__^L7QD5+`<9&"0+&1@H!Z+;S___K!,9#"@%!_\1(
-M@\,H#[9%240YX`^/S/[__T6%_P^%H_[__T6%[704QH5B#````4B)[DR)]^C,
-M[O__ZP3&14H!2(/$"%M=05Q!74%>05_#9F9FD&9FD$%7059!54%455-(@>QX
-M`0``2(E\)$A(B?5(BUXX3(NF,`P``$&]`````$V%Y'4E#[=.1(M60`'12(G>
-MZ!#G__](B44PN/____](@WTP``^$L2(``$B+1"1(_X`\6```2(U%$$B+5"1(
-M2('"T%<``$B+2@A(B4((2(E5$$B)2`A(B0%F@[N``````'1$]D-^`74+BX.$
-M````.T5`=R=!O@`````/MX.`````B<*H`74.0?_&B=!$B?'3^*@!=/)$B'5(
-MZS#&14@(ZRIF9I!F9I#V0WX"=!J+@X0````[14!W#P^V14>(14CK"F9FD&9F
-MD,9%2`C&14D`QH6P"0```,9%2P#&A6(,````QH5C#````$C'A3@,````````
-M387D#X1@#P``0?9$)!@@#X2/!P``00^V1"0.@_@"#X1N!```@_@"?Q"#^`$/
-MA`4!``!FD.F>(0``@_@##X65(0``2(U<)&!(B=_H5>7__TF)VK\`````#[=U
-M1+L`````0;D@````0;L!````@_\?=S\/ML-)C12"1(G)*?DY\0]'SH/Y('4(
-MQP+_____ZPU$B=C3X/_(B?G3X`D"1(G(*?@Y\',5C70^X+\`````ZP.#[R#_
-MPX#[`W:R2(N]H`H``.A>Y/__0;\`````@'U&``^&`2$``$2)^P^VPTC!X`1(
-MC1PH2(V[\`H``.BTY/__2(V[<`L``.BHY/__2(GOZ,#E___&0`@"1(AX$,9`
-M$0!(BU0D8$B)4!1(BU0D:$B)4!Q!_\=$.'U&=ZOIIR```+@!````ZU5(B>^Y
-M`````(!]1@"0=D$/ML%(P>`$2`'X2(V0\`H``+X`````@[CP"@```'42@WH$
-M`'4,@WH(`'4&@WH,`'0%O@$```"%]G6P_\$X3T9WO[@`````A<!T%TR)I3@,
-M``!(QX4P#````````.G"#0``2(U<)&!(B=_H\./__TF)VK\`````#[=U1+L`
-M````0;D@````0;L!````@_\?=S\/ML-)C12"1(G)*?DY\0]'SH/Y('4(QP+_
-M____ZPU$B=C3X/_(B?G3X`D"1(G(*?@Y\',5C70^X+\`````ZP.#[R#_PX#[
-M`W:R@'U("'4'#[9%1XA%2`^V74B(G0@,``#&A0D,```!2(M$)&!(B87P"P``
-M2(M$)&A(B87X"P``2,>%``P```````!(B>_H7.3__\9`"`*(6!"(6!%(BU0D
-M8$B)4!1(BU0D:$B)4!Q)B<2`?48"#X<``0``2(V=\`L``$B)[^@DY/__QD`(
-M!4B)6!#&0"``28G%28L,)/Z!L`D```^VL;`)``")]T@IR$B#Z%!(P?@#2+K-
-MS,S,S,S,S$@/K\*(A'FP"0``00^V1"0+B(1YL0D``$&(="0+0;\`````@'U&
-M``^&TQX``$B)TT0X?4AT<DB)[^BOX___QD`(`42(>!!$B'@12(M4)&!(B5`4
-M2(M4)&A(B5`<00^V52`/MLI&B'PI&/_"08A5($F+50#^@K`)```/MK*P"0``
-MB?%(*=!(@^A02,'X`T@/K\.(A$JP"0``00^V10N(A$JQ"0``08AU"T'_QT0X
-M?48/AWO____I1AX``$&_`````(!]1@`/AC8>``!(C9WP"P``2;[-S,S,S,S,
-MS$0X?4@/A+T```!(B>_H`./__\9`"`%$B'@01(AX$4B+5"1@2(E0%$B+5"1H
-M2(E0'$B)1"1`2(GOZ-7B___&0`@#2(E8$$2(>!A)B<5(BQ#^@K`)```/MK*P
-M"0``B?%(BT0D0$@IT$B#Z%!(P?@#20^OQHB$2K`)``!!#[9%"XB$2K$)``!!
-MB'4+28L4)/Z"L`D```^VLK`)``")\4R)Z$@IT$B#Z%!(P?@#20^OQHB$2K`)
-M``!!#[9$)`N(A$JQ"0``08AT)`M!_\=$.'U&#X<L____Z4P=``"X`0```.M9
-M2(GON0````"`?48`=D9F9F:0#[;!2,'@!$@!^$B-D/`*``"^`````(.X\`H`
-M``!U$X-Z!`!U#8-Z"`!U!X-Z#`"0=`6^`0```(7V=:S_P3A/1G>^N`````"%
-MP'073(FE.`P``$C'A3`,````````Z6,*``!(C5PD8$B)W^B1X/__28G:OP``
-M```/MW5$NP````!!N2````!!NP$```!F9F:0@_\?=S\/ML-)C12"1(G)*?DY
-M\0]'SH/Y('4(QP+_____ZPU$B=C3X/_(B?G3X`D"1(G(*?@Y\',5C70^X+\`
-M````ZP.#[R#_PX#[`W:R#[9%1XB%"`P``,:%"0P```!(BT0D8$B)A?`+``!(
-MBT0D:$B)A?@+``!(QX4`#````````(!]1@(/A[@```!(C9WP"P``2(GOZ/7@
-M___&0`@%2(E8$,9`(`!)B<5!OP````"`?48`#X;I&P``2+O-S,S,S,S,S$B)
-M[^C$X/__QD`(`42(>!!$B'@12(M4)&!(B5`42(M4)&A(B5`<00^V52`/MLI&
-MB'PI&/_"08A5($F+50#^@K`)```/MK*P"0``B?%(*=!(@^A02,'X`T@/K\.(
-MA$JP"0``00^V10N(A$JQ"0``08AU"T'_QT0X?49WA>E?&P``#[9=1TB)[^A`
-MX/__QD`(`8A8$(A8$4B+5"1@2(E0%$B+5"1H2(E0'$B)1"0X0;\`````@'U&
-M``^&(AL``$B-G?`+``!)O,W,S,S,S,S,1#A]1P^$O0```$B)[^CLW___QD`(
-M`42(>!!$B'@12(M4)&!(B5`42(M4)&A(B5`<2(E$)$!(B>_HP=___\9`"`-(
-MB5@01(AX&$F)Q4B+$/Z"L`D```^VLK`)``")\4B+1"1`2"G02(/H4$C!^`-)
-M#Z_$B(1*L`D``$$/MD4+B(1*L0D``$&(=0M)BU4`_H*P"0``#[:RL`D``(GQ
-M2(M$)#A(*=!(@^A02,'X`TD/K\2(A$JP"0``00^V10N(A$JQ"0``08AU"T'_
-MQT0X?48/ARS____I.!H``&9FD&:0387D#X2\!P``0?9$)!@"D`^$KP<``$0/
-MMKU@#```1#B]80P```^"50$``&9FD&:01#A]1P^$-@$``$2)^`^VV$B)V$C!
-MX`1,C:0$\````$R)Y^BIW?__#[>4G4`,```/M[R=0@P``+L`````0;D@````
-M0;H!````@_H?=T0/ML-)C32$1(G)*=$Y^0]'SX/Y('4-QP;_____ZQ)F9I!F
-MD$2)T-/@_\B)T=/@"09$B<@IT#GX<Q6-?!?@N@````#K`X/J(/_#@/L#=JU$
-MB?L/ML-(B<=(P><$2(T$+TB-D'`+``"+B'`+``#WT8E,)&"+0@3WT(E$)&2+
-M0@CWT(E$)&B+0@SWT(E$)&Q(C70\<$B-E#SP````(PJ)#HM"!"-$)&2)1@2+
-M0@@C1"1HB48(BT(,(T0D;(E&#$0X?4AU,;H`````@SX`=1*#?@0`=0R#?@@`
-M=0:#?@P`=`6Z`0```(72N`$```!$#T7H9F:09I!!_\=$.+UA#```#X.P_O__
-M183M#X2:!0``2(U\)&#H;=S__T&_`````(!]1@!V69!$.'U(=$E$.'U'=$-$
-MB?@/MM!(P>($2`'J2(V*\`H``(M$)&`+@O`*``")1"1@BT0D9`M!!(E$)&2+
-M1"1H"T$(B40D:(M$)&P+00R)1"1L0?_'1#A]1G>H3`^V14A)P>`$2HUT!'"+
-M?"1@(SZ)?"10BTPD9"-.!(E,)%2+5"1H(U8(B50D6(M$)&PC1@R)1"1<]]>)
-M?"1@]]&)3"1D]]*)5"1H]]")1"1L(SZ)?"1@(TX$B4PD9"-6"(E4)&@C1@R)
-M1"1L2(GOZ+3<___&0`@`2(E$)"BX`````(-\)&``=16#?"1D`'4.@WPD:`!U
-M!X-\)&P`=`6X`0```(7`#X2F`0``#[9%2(B%"`P``$B+1"1@2(F%\`L``$B+
-M1"1H2(F%^`L``,:%"0P```%(QX4`#````````$&_`````(!]1@`/A@,"``!,
-MC:7P"P``1#A]2`^$/P$``$0XO6`,``!W#T0XO6$,``!R!D0X?4=U+4B)[^@(
-MW/__QD`(`42(>!!$B'@12(M4)&!(B5`42(M4)&A(B5`<2(E$)$#K4D2)^@^V
-MPDC!X`1(C5P$<(M$)&`)`XM$)&0)0P2+1"1H"4,(BT0D;`E##$B)[^BQV___
-MQD`(`42(>!!$B'@12(L32(E0%$B+4PA(B5`<2(E$)$!(B>_HB=O__\9`"`-,
-MB6`01(AX&$F)Q4B+$/Z"L`D```^VLK`)``")\4B+1"1`2"G02(/H4$C!^`-(
-MO\W,S,S,S,S,2`^OQXB$2K`)``!!#[9%"XB$2K$)``!!B'4+1#A]1W5$2(M,
-M)"A(BQ'^@K`)```/MK*P"0``B?%,B>A(*=!(@^A02,'X`T@/K\>(A$JP"0``
-M2(M<)"@/MD,+B(1*L0D``$"(<PM!_\=$.'U&#X>J_O__Z:$```!!OP````"`
-M?48`#X:1````1#B]8`P``'=[1#B]80P``')R1#A]1W1L1#A]2'1F1(GZ#[;"
-M2,'@!$B-1`1PN@````"#.`!U$H-X!`!U#(-X"`!U!H-X#`!T!;H!````A=)T
-M,D2)^0^VP4C!X`1(C5P$<$B)[^A>VO__QD`(`42(>!!$B'@12(L32(E0%$B+
-M4PA(B5`<0?_'1#A]1@^';____[@`````@WPD4`!U%8-\)%0`=0Z#?"18`'4'
-M@WPD7`!T!;@!````A<`/A!L5``!$#[9E2$2(I2@,``!(BT0D4$B)A1`,``!(
-MBT0D6$B)A1@,``#&A2D,````2,>%(`P````````/MEU'2(GOZ,;9___&0`@!
-MB%@01(A@$4B+5"102(E0%$B+5"182(E0'$B)1"0X2,=$)#``````0;\`````
-M@'U&``^&GA0``$R-I1`,``!)OLW,S,S,S,S,1#A]2`^$80$``$0X?4</A%<!
-M```/MEU'2(GOZ%K9___&0`@!1(AX$(A8$4B+5"102(E0%$B+5"182(E0'$B)
-M1"1`2(L0_H*P"0``#[:RL`D``(GQ2(M$)"A(*=!(@^A02,'X`TB_S<S,S,S,
-MS,Q(#Z_'B(1*L`D``$B+7"1`#[9#"XB$2K$)``!`B',+2(-\)#``=#Q(BQ/^
-M@K`)```/MK*P"0``B?%(BT0D,$@IT$B#Z%!(P?@#2`^OQXB$2K`)```/MD,+
-MB(1*L0D``$"(<PL/MEU'2(GOZ)W8___&0`@#3(E@$(A8&$F)Q4B)1"0P2(L0
-M_H*P"0``#[:RL`D``(GQ2(M$)$!(*=!(@^A02,'X`TD/K\:(A$JP"0``00^V
-M10N(A$JQ"0``08AU"TF+50#^@K`)```/MK*P"0``B?%(BT0D.$@IT$B#Z%!(
-MP?@#20^OQHB$2K`)``!!#[9%"XB$2K$)``!!B'4+0?_'1#A]1@^'B/[__^D0
-M$P``1`^VO6`,``!$.+UA#```#X+[$@``1#A]1W1R1(GZ#[;"2,'@!$B-1`1P
-MN@````"#.`!U&8-X!`!U$X-X"`!U#8-X#`!T#&9F9I!F9I"Z`0```(72=#=$
-MB?D/ML%(P>`$2(U<!'!(B>_HD-?__\9`"`%$B'@01(AX$4B+$TB)4!1(BU,(
-M2(E0'&9FD&:00?_'1#B]80P```^#>/___^EN$@``@'U(!P^&TPD``$B-?"1@
-MZ"?6___&1"0G`$&_`````(!]1@`/AJ$```!FD$0X?4</A(@```!$B?L/ML-(
-MP>`$2`'H2(V0\`H``+D`````@[CP"@```'46@WH$`'40@WH(`'4*@WH,`&9F
-M9I!T!;D!````A<ET1T2)^`^VT$C!X@1(`>I(C8KP"@``BT0D8`N"\`H``(E$
-M)&"+1"1D"T$$B40D9(M$)&@+00B)1"1HBT0D;`M!#(E$)&S^1"0G0?_'1#A]
-M1@^'8?___P^V5"0G#[9%1H/H`]'X.<(/CE0%```/MEU'B)T(#```2(M$)&!(
-MB87P"P``2(M$)&A(B87X"P``QH4)#````4C'A0`,````````2(GOZ#_6___&
-M0`@"B%@0B%@12(M4)&!(B5`42(M4)&A(B5`<28G$2(GOZ!C6___&0`@&2(E$
-M)"A)BQ0D_H*P"0``#[:RL`D``(GQ2(M$)"A(*=!(@^A02,'X`TF^S<S,S,S,
-MS,Q)#Z_&B(1*L`D``$$/MD0D"XB$2K$)``!!B'0D"X!]1@(/ATD"``!(C9WP
-M"P``2(GOZ*S5___&0`@%2(E8$,9`(`!)B<5(BTPD*$B+$?Z"L`D```^VLK`)
-M``")\4@IT$B#Z%!(P?@#20^OQHB$2K`)``!(BUPD*`^V0PN(A$JQ"0``0(AS
-M"T&_`````(!]1@`/AE\0``!$.'U'#X2^`0``00^V12`/MM!&B'PJ&/_`08A%
-M($2)^`^V\$C!Y@1(C00N2(V(<`L``(N0<`L``/?2B50D4(M!!/?0B40D5(M!
-M"/?0B40D6(M!#/?0B40D7$B-3#1P(U0D8(D1BT0D9"-$)%2)002+1"1H(T0D
-M6(E!"(M$)&PC1"1<B4$,N`````"#.0!U$H-Y!`!U#(-Y"`!U!H-Y#`!T!;@!
-M````A<!T:T2)^@^VPDC!X`1(C5P$<$B)[^B+U/__QD`(`42(>!!$B'@12(L3
-M2(E0%$B+4PA(B5`<28M5`/Z"L`D```^VLK`)``")\4@IT$B#Z%!(P?@#20^O
-MQHB$2K`)``!!#[9%"XB$2K$)``!!B'4+1(GY#[;!2,'@!$B-A"CP"@``N@``
-M``"#.`!U$H-X!`!U#(-X"`!U!H-X#`!T!;H!````A=)FD'1Z1(GX#[;82(G8
-M2,'@!$B-G"CP"@``2(GOZ.'3___&0`@"1(AX$$2(>!%(BQ-(B5`42(M3"$B)
-M4!Q)B<1(BQ#^@K`)```/MK*P"0``B?%(BT0D*$@IT$B#Z%!(P?@#20^OQHB$
-M2K`)``!!#[9$)`N(A$JQ"0``08AT)`M!_\=$.'U&#X<K_O__Z84.``!!OP``
-M``"`?48`#X9U#@``2(V5\`L``$B)5"082;[-S,S,S,S,S$0X?4</A`D"``!$
-MB?D/MO%(P>8$2(T$+DB-B'`+``"+D'`+``#WTHE4)%"+003WT(E$)%2+00CW
-MT(E$)%B+00SWT(E$)%Q(C5PT<"-4)&")$XM$)&0C1"14B4,$BT0D:"-$)%B)
-M0PB+1"1L(T0D7(E##$B)[^C2TO__QD`(`TB+?"082(EX$$2(>!A)B<5(BT0D
-M*$B+$/Z"L`D```^VLK`)``")\4R)Z$@IT$B#Z%!(P?@#20^OQHB$2K`)``!(
-MBWPD*`^V1PN(A$JQ"0``0(AW"[@`````@SL`=1*#>P0`=0R#>P@`=0:#>PP`
-M=`6X`0```(7`=&M$B?H/ML)(P>`$2(U<!'!(B>_H/M+__\9`"`%$B'@01(AX
-M$4B+$TB)4!1(BU,(2(E0'$F+50#^@K`)```/MK*P"0``B?%(*=!(@^A02,'X
-M`TD/K\:(A$JP"0``00^V10N(A$JQ"0``08AU"T2)^0^VP4C!X`1(C80H\`H`
-M`+H`````@S@`=1*#>`0`=0R#>`@`=0:#>`P`=`6Z`0```(72='I$B?@/MMA(
-MB=A(P>`$2(V<*/`*``!(B>_HEM'__\9`"`)$B'@01(AX$4B+$TB)4!1(BU,(
-M2(E0'$F)Q$B+$/Z"L`D```^VLK`)``")\4B+1"0H2"G02(/H4$C!^`-)#Z_&
-MB(1*L`D``$$/MD0D"XB$2K$)``!!B'0D"T'_QT0X?48/A^#]___I.@P```^V
-M74=(B>_H&]'__\9`"`&(6!"(6!%(BU0D8$B)4!1(BU0D:$B)4!Q(B40D.`^V
-M74=(B>_H[M#__\9`"`*(6!"(6!%(BU0D8$B)4!1(BU0D:$B)4!Q)B<1(B>_H
-MQ]#__\9`"`9(B40D*$F+#"3^@;`)```/MKFP"0``B?Y(BT0D*$@IR$B#Z%!(
-MP?@#2+K-S,S,S,S,S$@/K\*(A'&P"0``00^V1"0+B(1QL0D``$&(?"0+0;\`
-M````@'U&``^&=PL``&9F9I!$.'U'#X3&`@``1(GZ#[;"2,'@!$@!Z$B-D/`*
-M``"Y`````(.X\`H```!U%H-Z!`!U$(-Z"`!U"H-Z#`!F9F:0=`6Y`0```(7)
-M#X2!`@``_DPD)P^V3"0G`DU&08G.1(G[1`^VXTG!Y`1)`>Q)C;PD\`H``$B)
-M?"002(GOZ-_/___&0`@!1(AX$$2(<!%)BY0D\`H``$B)4!1(BTPD$$B+40A(
-MB5`<2(E$)$`/MEU'2(GOZ*G/___&0`@$B%@@1(AP(4F+E"3P"@``2(E0$$B+
-M7"002(M3"$B)4!A)B<5(BQ#^@K`)```/MK*P"0``B?%(BT0D.$@IT$B#Z%!(
-MP?@#2+_-S,S,S,S,S$@/K\>(A$JP"0``00^V10N(A$JQ"0``08AU"TF+50#^
-M@K`)```/MK*P"0``B?%(BT0D0$@IT$B#Z%!(P?@#2`^OQXB$2K`)``!!#[9%
-M"XB$2K$)``!!B'4+2(M$)"A(BQ#^@K`)```/MK*P"0``B?%,B>A(*=!(@^A0
-M2,'X`T@/K\>(A$JP"0``2(M<)"@/MD,+B(1*L0D``$"(<PL/MEU'2(GOZ*W.
-M___&0`@$B%@@1(AX(4F+E"3P"@``2(E0$$B+?"002(M7"$B)4!A)B<5(BQ#^
-M@K`)```/MK*P"0``B?%(BT0D.$@IT$B#Z%!(P?@#2+O-S,S,S,S,S$@/K\.(
-MA$JP"0``00^V10N(A$JQ"0``08AU"TB+?"0H2(L7_H*P"0``#[:RL`D``(GQ
-M3(GH2"G02(/H4$C!^`-(#Z_#B(1*L`D```^V1PN(A$JQ"0``0(AW"TB)[^CX
-MS?__QD`(`D2(>!!$B'@128N4)/`*``!(B5`42(M,)!!(BU$(2(E0'$F)Q$B+
-M$/Z"L`D```^VLK`)``")\4B+1"0H2"G02(/H4$C!^`-(#Z_#B(1*L`D``$$/
-MMD0D"XB$2K$)``!!B'0D"Y!!_\=$.'U&#X<C_?__Z9$(```/MD5(.D5'#X6H
-M````0;\`````@'U&``^&=`@``)!$.'U'=']$B?L/ML-(P>`$2`'H2(V0\`H`
-M`+D`````@[CP"@```'48@WH$`'42@WH(`'4,@WH,`'0+9F:09F:0N0$```"%
-MR70\1(GX#[;82,'C!$@!ZTR-H_`*``!(B>_H^\S__\9`"`)$B'@01(AX$4B+
-MD_`*``!(B5`428M4)`A(B5`<0?_'1#A]1@^';O___^G<!P``2(U\)&#HG\O_
-M_TB)[^BWS/__QD`(!DB)1"0H0;\`````@'U&``^&&P$``$0X?4</A`0!``!$
-MB?H/ML)(P>`$2`'H2(V0\`H``+D`````@[CP"@```'44@WH$`'4.@WH(`'4(
-M@WH,`&:0=`6Y`0```(7)#X3!````1(GY#[;!2,'@!$R-)"A)C9PD\`H``(M$
-M)&!!"X0D\`H``(E$)&"+1"1D"T,$B40D9(M$)&@+0PB)1"1HBT0D;`M##(E$
-M)&Q$.'U(='1(B>_H_,O__\9`"`)$B'@01(AX$4F+E"3P"@``2(E0%$B+4PA(
-MB5`<28G$2(L(_H&P"0``#[:YL`D``(G^2(M$)"A(*<A(@^A02,'X`TBZS<S,
-MS,S,S,Q(#Z_"B(1QL`D``$$/MD0D"XB$<;$)``!!B'PD"T'_QT0X?48/A^7^
-M__\/MEU'2(GOZ'?+___&0`@"B%@0B%@12(M4)&!(B5`42(M4)&A(B5`<28G$
-M2(L(_H&P"0``#[:YL`D``(G^2(M$)"A(*<A(@^A02,'X`TBZS<S,S,S,S,Q(
-M#Z_"B(1QL`D``$$/MD0D"XB$<;$)``!!B'PD"T@/MG5(2(GW2(GP2,'@!$B-
-MM"AP"P``BP;WT(E$)%"+5@3WTHE4)%2+3@CWT8E,)%B+=@SWUD2+3"1@1"'(
-MB40D4$2+1"1D1"'"B50D5(M4)&@AT8E,)%B+1"1L(<:)="1<2,'G!$B-O"]P
-M"P``1",/1(E,)&!$(T<$1(E$)&0C5PB)5"1H(T<,B40D;+@`````187)=1!%
-MA<!U"X72=0>#?"1L`'0%N`$```"%P)`/A`\"```/MD5'B(4(#```2(M$)&!(
-MB87P"P``2(M$)&A(B87X"P``QH4)#````4C'A0`,````````0;\`````@'U&
-M``^&RP$``$R-M?`+``!)O,W,S,S,S,S,9F:09I!$.'U(=5I(B>_H\LG__\9`
-M"`-,B7`01(AX&$B+7"0H2(L3_H*P"0``#[:RL`D``(GQ2"G02(/H4$C!^`-)
-M#Z_$B(1*L`D```^V0PN(A$JQ"0``0(AS"^E-`0``9F:09I!$.'U'#X0^`0``
-M1(GZ#[;"2,'@!$B-7`1P2`'H2(VX<`L``(NP<`L``/?6B3.+3P3WT8E+!(M7
-M"/?2B5,(BT<,]]")0PPC="1@B3,C3"1DB4L$(U0D:(E3""-$)&R)0PQ(B>_H
-M.,G__\9`"`-,B7`01(AX&$F)Q4B+3"0H2(L1_H*P"0``#[:RL`D``(GQ2"G0
-M2(/H4$C!^`-)#Z_$B(1*L`D``$B+?"0H#[9'"XB$2K$)``!`B'<+N`````"#
+M?T5,1@(!`0D```````````$`/@`!`````````````````````````"CA````
+M`````````$```````$``#@`+`$B![$@"``!(B9PD&`(``$B)K"0@`@``3(FD
+M)"@"``!,B:PD,`(``$R)M"0X`@``3(F\)$`"``!(B?M,BV\02(UOB$R-9"00
+MN`(```"`?P$`=0N`?P(!&<"#X`+_P(A%`$C'10@`````@$T!!$B+0Q!(B440
+MBU,82(E5&$@/MD4`2(L$Q0````!(B45H@'T``W4N2(U"]DB)11B+<QB#[@I,
+MB>&Z(````$B)W^@`````08$\)/,6>%IT(&9FD&9FD$@/MD4`2(L$Q0````!(
+MB45P@$T!!.E:!0``OI````!,B>?H`````(3`==5!]D0D"0)T'<9#"`%!#[9$
+M)`J(0PLZ0PES"P^V\$B)W^@`````O@`"``!,B>?H`````(3`=!=)C;PDD```
+M`+IP`0``O@````#H`````$$/MI0DDP```+X!````(=8/MD,$@^#\B=&#X0()
+M\`G(O@0````AUH/@\XG1@^$("?`)R+X0````(=:#X,^)T8/A(`GP"<B)T8/A
+M0(/@/X/B@`G("="(0P2H`704T.B)QH/F`;H`````2(G?Z``````/MD,$J`1T
+M%<#H`XG&@^8!N@````!(B=_H``````^V0P2H$'00P.@%B<:#Y@%(B=_H````
+M``^V0P2H0'0.P.@'#[;P2(G?Z`````!!#[94)`F#X@$/MD4!@^#^"="(10%!
+M@'PD$`,/A*S^__]!@'PD$`!U%,9%``!(BP4`````2(E%<.D$!```08-\)`0`
+M#X2$_O__N@````!!#[9$)`N)P8/X`'XQ2,?&`````$ACPDC!X`1,`>"`>!`(
+M#X=7_O__2`^V0!!(@SS&``^$1_[____".=%_UD6+?"0808N$))@```!(P>`@
+M20G'N@````!(8\)(:<!(`0``2HV<*,A$``!(@WL(`'4.BT-\03M$)`0/A#$!
+M``#_PH/Z#W[228N=P$0``$B%VW0A2(M#$$F)A<!$``"Z2`$``+X`````2(G?
+MZ`````!,B6L008M$)`2)0WP/MI.2````@\H!B).2````9D$/MD0D%(/@`0'`
+M@^+]"<*(DY(```!!#[=$)!9FB8.4````3(F[F````$$/MD0D$(@#00^V1"03
+MB$-Z#[;(N`$```#3X&:)@Y````!(QT,(`````$&+5"0,2(E3&$&+A"24````
+M2,'@($@)T$B)0QA!#[9$)!&(0WA(#[8#2(L$Q0````!(B4-H28UT)"Q(C;O@
+M````NA````#H`````$F-="0\2(V[\````+H$````Z`````!)C;0D@````$B-
+MNS0!``"Z$````.@`````28UT)$!(C;OT````ND````#H`````$PYNY@```!V
+M!TR)NY@```!!]D0D"0%T!(!+`0%!#[9$)!*(1"0/08!\)`L!#X;:`0``#[;`
+M3(NTPZ````!%BWPD*$&+A"2@````2,'@($D)QTV%]@^%60$``$V+M<!$``!-
+MA?9T(4F+1A!)B87`1```ND@!``"^`````$R)]^@`````38EN$$&+1"0$08E&
+M?$$/MI:2````@\H!08B6D@```&9!#[9$)"2#X`$!P(/B_0G"08B6D@```$$/
+MMT0D)F9!B8:4````38F^F````$$/MD0D(4&(1GA!#[9$)"!!B`9)B5X(08M4
+M)!Q)B58808N$))P```!(P>`@2`G028E&&$$/MD0D(T&(1GH/MLBX`0```-/@
+M9D&)AI````!)#[8&2(L$Q0````!)B49H2`^V`TB+!,4`````28E&<`^V1"0/
+M08A&`T@/MD0D#TR)M,.@````_D-Y28UT)"Q)C;[@````NA````#H`````$F-
+M="0\28V^\````+H$````Z`````!)C;0D@````$F-OC0!``"Z$````.@`````
+M28UT)$!)C;[T````ND````#H`````$'V1"0)`70%08!.`0%)#[9$)"))@[S&
+MH`````!U<TF)K,:@````00^V1"0BB$4#0?Y&>4R)=0A)#[8&2(L$Q0````!(
+MB45P33F^F````'9!38F^F````.LX2`^V1"0/2(.\PZ``````=2=(B:S#H```
+M`$B)70C^0WD/MD0D#XA%`T@/M@-(BP3%`````$B)17!(BYPD&`(``$B+K"0@
+M`@``3(ND)"@"``!,BZPD,`(``$R+M"0X`@``3(N\)$`"``!(@<1(`@``PV9F
+M9I!54TB#[`A(B?.]``````^V1GB)PH/X``^.TP```&9FD$ACQ4B#O,.@````
+M`'0+_\4YZG_LZ;<```"X`0```(GIT^!F"8.4````2(G>Z`````!(B<)(A<`/
+MA),```#&``-`B&@#2(E8"(`["`^4P,'@`P^V2@&#X?<)P8A*`4B+!0````!(
+MB4)H2`^V`TB+!,4`````2(E"</9#`1!T$HG(@\@0B$(!BX*0````2(E"&$AC
+MQ4B)E,.@````#[:#D@```(/@_H/("HB#D@```$C'@Y@`````````_D-Y2(G6
+MOP<```#H`````("+D@````1(@\0(6UW#9F:09F:09F:02(/L*$B)7"0(2(EL
+M)!!,B60D&$R);"0@28G]2(GS#[8&@_@&#X29````@_@&?Q&#^`0/C+H!``#K
+M&V9FD&9FD(/X"`^$]P```&9F9I!F9I#IG0$```^V1GDZ1GAF9F:0#X6,`0``
+M@$X!!("FD@```/Y!O`````"`?G@`#X1Q`0``26/$2(NLPZ````!(A>UT(8!]
+M``-V&TB)[DR)[^@`````]H62````!'0'@(N2````!$'_Q`^V0WA$.>!_P^DO
+M`0``@$X!!(!^>0)U$X"FD@```/[I&0$``&9F9I!F9I"`II(```#]2(.^H```
+M``!U'4B+AJ@```#&0`,`2(F&H````$C'AJ@`````````2(N#H````(`X`W4+
+M2(G>3(GOZ`````"`BY(````$2,>#F`````````#IM@```&9F9I`/MD9Y.D9X
+M=2F`3@$$#[:&D@```(/@_HB&D@```&:#OI0`````='F#R`*(AI(```#K;@^V
+M1GG_P`^V5G@YT'5@9H.^E`````!T++D`````#[>&E````(G"J`%U"O_!B=#3
+M^*@!=/9(8\%(@[S#H`````!U(>L)]H:2`````G46@$L!!("+D@````1(B=Y,
+MB>_H`````$C'@Y@`````````2`^W@Y````!(]]A((8.8````2(-["`!U&?:#
+MD@````1T$.@`````B4-\2(G?Z`````!(BUPD"$B+;"003(MD)!A,BVPD($B#
+MQ"C#9F:09I!!5%5328G\O0````!F9F:02&/%2&G`2`$``$J-G"#(1```@WM\
+M`'0@2(-["`!U&4B)WDR)Y^@`````]D,!!'0(2,=#<`````#_Q8/]#W[!6UU!
+M7,-F9F:09F9FD&9F9I!!5T%6055!5%532('L"`(``$F)_4B)]4&)UDF)YTB)
+M]^@`````@'T`"'4+2(GN3(GOZ`````!!O`````"`?7@`#X;'````26/$2(.\
+MQ:``````#X2H````2(NTQ:````"`/@-V$4$/MM9,B>_H`````.F*````26/$
+M2(N<Q:````#&0P,`2,=#"`````#'@Y0`````````@&,!_DC'0W``````183V
+M=0V`?0`&=0=(@WT(`'0JN@`"``"^`````$R)_^@`````2(U[>$R)^;HP````
+MO@````#H`````.L3#[95`8/B`0^V0P&#X/X)T(A#`4B)W^@`````9F:09F:0
+M0?_$1#AE>`^'.?___[I(`0``O@````!(B>_H`````$F+A<!$``!(B44028FM
+MP$0``,=%?`````!(@<0(`@``6UU!7$%=05Y!7\-F9I!F9I!!5D%505154TB!
+M[``"``!(B=-(BP9,BV@(3(MV0$F+;BA$#[9@`TB)XDB%[70-9D$/MD8@@^`!
+M.<AU(4B)U4F#?C``=`U,B?9!_U8PA<!FD'4*N`````#IBP```$$/MTY4P>$)
+M00^V=E!F9F:09F:03(M%`+\```$`9H-]"`!T!`^W?0@Y^8GZ#T;11#GF=1%F
+MB5,(9L=#"@``3(D#2(/#$"G7B=!)`<`IT74>_\9!#[9%>#G&N``````/1/!!
+M#[>%D````(G!P>$)A?]UMF:!?0H`@'0&2(/%$.N49L=#^@"`N`$```!(@<0`
+M`@``6UU!7$%=05[#9F:09F:09F:03(M/"$R+1D@/MD\##[=^6#A.4'4+2`^W
+M1E9)`<#K$9`X3E!V"TD/MX&0````20'`.$Y0=0MF`WY49F9FD&9FD#A.474+
+M9@-^4F9F9I!F9I"`?EP`=`XX3E!S)3A.46:0=Q3K'#A.4',(9D$#N9`````X
+M3E%V"F9!`[F0````9I!FB7H03(E"",-F9F:09F:04TF)^4F)\$B+?@A$#[=6
+M$$&[`````$$/MDEZ2(G^2-/N9D''0%@``$'&0%P!20^V47A(B?!(B=&Z````
+M`$CW\4$/MDEZ2-/@28E`2$D/ME%X2(GP2(G1N@````!(]_%!B%!0B=%!#[>!
+MD````/_((?AF08E`5D$/MY&0````9BG"9D0YTG(-9D6)4%1!N@````#K8F9!
+MB5!49D$ITD&[`0```+H!````B=#3X&9!"4!:_\%!.$EX=2FY`````$&`>%P`
+M=`M!QD!<`.L69F9FD$$/MT!89D$#@9````!F08E`6&9%.9&0````<PIF12N1
+MD````.NRN`$```#3X&9!"4!:08A(469%B5!200^WPUO#9F9FD&9F9I!F9F:0
+M9F:055-(@^P(2(G]2(M>0$B+!@^V2`.X_O___]/`9B%#6H!^(0%T!P^V1B&(
+M0R%(B>_H`````&:#>UH`=1F`>R$`=03&0R$!2(MS.$B)VDB)[^@`````2(/$
+M"%M=PV9FD&:02(/L.$B)7"0(2(EL)!!,B60D&$R);"0@3(ET)"A,B7PD,$F)
+M_TB)]4R+-D'V1@$$=17&1B$"2(MV.$B)ZN@`````Z<H```!,B??H,?[__V:#
+M?5H`=1K&12$"2(MU.$B)ZDR)_^@`````Z:,```!FD$&]`````$&`?G@`#X20
+M````#[=%6D2)Z=/XJ`%T<DR)_^@`````2(G#26/%38NDQJ````!,B2-(B6M`
+M#[95((/B`@^V0R"#X/T)T(A#(`^V52"#X@2#X/L)T(A#(`^V11*(0Q)(B=I(
+MB>Y,B>?H#OW__TC'0S@`````2,=#,`````!(B=Y,B?]!_U0D:&9FD$'_Q4$/
+MMD9X1#GH#X]P____2(M<)`A(BVPD$$R+9"083(ML)"!,BW0D*$R+?"0P2(/$
+M.,-F9F:09F9FD&9F9I!(@^P(2(M."`^V40&`9@'[@&$!^_Y)>8")D@````%(
+M@WEP``^5P/;"!`^5P@^VP(7"=`U(B<[_47!F9F:09F:02(/$",-F9F:09F9F
+MD&9FD$B#[`A,BT9`28MP*$B%]G0-9D$/MD`@@^`!.<AU(DF#>#``=!!,B<9!
+M_U`PN@$```"%P'4PN@````#K*69F9I!(BP9(B0)(BT8(2(E""$B#PA!(C48*
+M2(/&$&:#.`!YX+H!````B=!(@\0(PV9F9I!54TB)^P^V!X/H!(/X`7=0O0``
+M``"`?W@`=#=F9I!FD$ACQ4B#O,.@`````'012(N\PZ````#HQ?___X7`=0>X
+M`````.LD_\4/MD-X.>AFD'_.N`$```#K$69F9I!F9I`/MD<!P.@"@^`!6UW#
+M9F:02(/L*$B)'"1(B6PD"$R)9"003(EL)!A,B70D($F)_DB)]4B+7D!,BR-,
+MBRZ`?B$!#X3:````]D,@`@^$@````(![(@`/A<8```!!]H0DD@````(/A;<`
+M``#&0R(!08!]`P%(&<"#X`A.BZP@H````$V%[71"3(GOZ!/___^%P'0V2(U]
+M2+I8````O@````#H`````$$/MDT#N`$```#3X&:)0UI,B6T`2(GN3(GW0?]5
+M:.F^````3(MM`.M39F:0]D,@!'1*3(GOZ,+^__^%P'0B2(U]2+I8````O@``
+M``#H`````$B)[DR)]T'_56CI@0```(![(0%T'0^W4UI!#[9-`[@!````T^`Y
+MPG4)9I`/MD4AB$,A2(GN3(GWZ`````!!#[9-`[C^____T\!F(4-:9H-[6@!U
+M/(![(0!U!,9#(0%(BW,X2(G:3(GWZ`````!F0?],)"IF08-\)"H`=11)BT0D
+M.$B%P'0*28MT)$!,B??_T$B+'"1(BVPD"$R+9"003(ML)!A,BW0D($B#Q"C#
+M9F9FD&9F9I!F9I!F9I!(@^P(2(M&0(7)=!I(BT`82(D"#[=&$,'@"6:)0@AF
+MQT(*`(#K44B#>"@`=#/V0"`!="U(BT@H2(L!2(D"2(M!"$B)0@A(@\(02(U!
+M"DB#P1!F@S@`>>#K'F9F9I!F9I"^`````$B#>#``=!!(B<:0_U`PB<;K!;X!
+M````B?!(@\0(PV9F9I!F9I!F9I!F9I!(@^P82(D<)$B);"0(3(ED)!!)B?Q(
+MB?-(BVY`2(L&#[9(`[C^____T\!F(45:@'XA`70'#[9&(8A%(4B)WDR)Y^@`
+M````9H-]6@!U6H!](0!U),9%(0%(BTT`2(N1F````$@[4PAU#T@/MT,02`'0
+M2(F!F````$B+=3A(B>I,B>?H`````$B+10!FQT`H``!(BU4`2(/",$C'Q@``
+M``!,B>?H`````$B+'"1(BVPD"$R+9"002(/$&,-F9I!F9I!(@^P82(D<)$B)
+M;"0(3(ED)!!)B?Q(B?-(BVY`@'XA`70.#[9&(8A%(>MY9F:09I"`?A(@=4K&
+M1B$`2(M%`$B+@*@```!(B09(C7Y(NE@```"^`````.@`````QD,B`,9#$C`/
+MMD,@@^#]@\@$B$,@2(L#2(G>3(GG_U!HZV%FD,9%(0%(BTT`2(N1F````$@[
+M5@AU#T@/MT802`'02(F!F````$B)WDR)Y^@`````2(MU.$B)ZDR)Y^@`````
+M2(M%`&;'0"@``$B+50!(@\(P2,?&`````$R)Y^@`````2(L<)$B+;"0(3(MD
+M)!!(@\08PV9F9I!F9F:09F:09F:005154TF)]$B)U4B+1D"%R71&2(M0&$B)
+M50`/MT80P>`)9HE%"&;'10H`@$B+!H!X`P`/A`T!``!(C8(```$`9H-]"`!T
+M"4@/MT4(2(T$`DB)10#I[0````^W7A#!XPE(@W@H`'0L]D`@`70F2(M(*$B+
+M`4B)`DB+00A(B4((2(/"$$B-00I(@\$09H,X`'G@ZS2Z`````$B#>#``#X2H
+M````2(GJ2(G&_U`PN@````"%P`^$D@```.L,9HE9"&;'00H`@.M&2(GI9F9F
+MD&9FD+H```$`9H-Y"`!T!`^W40A)BP0D@'@#`'06.=IV%HG82`$!B=!F*=AF
+MB4$(ZPYFD#G:<[9(@\$0*=-UQ$F+!"2`>`,`#Y7`2#G-#Y7"#[;`A<)T(4B+
+M`4B)10!(BT$(2(E%"$B#Q1!(C4$*2(/!$&:#.`!YW[H!````B=!;74%<PV9F
+M9I!F9F:09F9FD&9FD$B#[!A(B1PD2(EL)`A,B60D$$F)_$B)\TB+;D"`?B$!
+M=`X/MD8AB$4AZ88```!FD$B+!H!X`P!U-\9&(0!(BT4`2(N`J````$B)!DB-
+M?DBZ6````+X`````Z`````#&0R(`2(L#2(G>3(GG_U!HZW\/MU80P>()B=9(
+MBWT82`'^Z`````"%P'0'QD4A#.LED,9%(0%(BTT`2(N1F````$@[4PAU#T@/
+MMT,02`'02(F!F````$B)WDR)Y^@`````2(MU.$B)ZDR)Y^@`````2(M%`&;'
+M0"@``$B+50!(@\(P2,?&`````$R)Y^@`````2(L<)$B+;"0(3(MD)!!(@\08
+MPV9F9I!F9F:09F:09F:02(/L*$B)7"0(2(EL)!!,B60D&$R);"0@28G\2(GS
+M2(LN2,=%.`````#VA9(````!#X5J`0``#[9&$H/X`@^$`P$``(/X`G\.@_@!
+M#X2?````Z4H!``"#^`-F9F:09F:0#X4Z`0``2(M&"$B)12`/MT809HE%*`^W
+M5A#!X@E(BWX8O@````#H`````&;'0UH#`$&]`````$R)Y^@`````2(G&QD`2
+M,$B+0PA(B48(#[=#$&:)1A"`3B`$2(E>0$C'1C@`````2,=&,`````!)8\5(
+MBX3%H````$B)!DR)Y_]0:$'_Q4&#_0%^K.G#````2(M&"$B)12`/MT809HE%
+M*.@`````2(G&QD`2($B+0PA(B48(#[=#$&:)1A"`3B`"2(E>0$C'1C@`````
+M2,=&,`````!(BX6@````2(D&3(GG_U!HZVU(BT8(2(E%(`^W1A!FB44HZ```
+M``!(B<;&0!(@2(M#"$B)1@@/MT,09HE&$(!.(`)(B5Y`2,=&.`````!(QT8P
+M`````$B+A:````!(B09,B>?_4&CK%V9F9I#&0R$&2(MS.$B)VDR)Y^@`````
+M2(U5,$C'Q@````!,B>?H`````$B+7"0(2(ML)!!,BV0D&$R+;"0@2(/$*,.0
+M2(/L.$B)7"0(2(EL)!!,B60D&$R);"0@3(ET)"A,B7PD,$F)_TF)]$B++O9%
+M`01U%<9&(0)(BW8X3(GBZ`````#IV@$``/9&("!T)$C'13@`````2(EU0&:#
+M?2H`#X6]`0``Z+C]___ILP$``&9FD$B#?3@`=2EF@WTH`&9F9I!T/D@/MT4H
+M2`-%($@[1@AV+T@/MT802`-&"$@Y12!S($G'1"10`````$B-?3!,B>;H````
+M`.EF`0``9F:09F:09O]%*O:%D@````,/A9\```!!]D0D(`(/A),```!(BY6@
+M````2(NUJ````(`Z`W5D@#X#=5])BT0D"(G!*XJ8````08G`1"N&F````(NZ
+MG````(NVG````(G(F3'1*=%$B<"903'002G01#G!?1.%]@^41"0'@_\%#Y?`
+M($0D!^LTA?\/E40D!X/^!0^6P`A$)`?K(8"]E@`````/E$0D!P^V3"0'B(V6
+M````ZPAF9I#&1"0'`&9!QT0D6@``0;X`````1(GP1`^VZ$J#O.V@`````'1[
+M2HN$[:````#V0`$$=&U!#[94)"#`Z@)$.'0D!P^4P`G0J`%T5DR)_^@`````
+M2(G#ND@```!,B>9(B<?H`````+@!````1(GQT^!F00E$)%I,B6-`2,=#.```
+M``!(QT,P`````$J+A.V@````2(D#2(G>3(G__U!H9F:00?_&08#^`0^&9O__
+M_V9FD$B+7"0(2(ML)!!,BV0D&$R+;"0@3(MT)"A,BWPD,$B#Q#C#9F9FD&9F
+MD&9FD&9FD%532(/L"$B)]4B+7@@/ME8#@&8!^X"+D@````%(QX.8````````
+M`/Y+>8![>0!U!H!C`?OK'`^V@Y(```"H`G01@^#7B(.2````A=)U!(!C`?OV
+M0P$$=1U(@WMP``^$+`$``$B)WO]3<&9F9I!F9I#I&@$``(72=21(BY.@````
+MQD(#`4B+@Z@```#&0`,`2(F#H````$B)DZ@```!(@WL(`'0.2(M#"/9``00/
+MA(,```!(BX.@````@#@#=7=(B=[H`````$B)PDB%P'1GQ@`#QD`#`4B)6`A(
+MBP4`````2(E":$B+!0````!(B4)P]D,!$'0.@$H!$(N"D````$B)0AA(QT4(
+M`````$B)DZ@````/MH.2````@^#^@\@*B(.2````_D-Y2(G6OP<```#H````
+M`$B#>P@`=`]F9F:02(M;"$B#>P@`=?6+@X@```")@XP```"+@X0```")@X@`
+M``"+@X````")@X0```"+0WR)@X````#H`````(E#?,:#EP````%(B=_H````
+M`$B#Q`A;7<-F9F:09F:09F:02('L*`(``$B)G"0``@``2(FL)`@"``!,B:0D
+M$`(``$R)K"08`@``3(FT)"`"``!)B=1,BS9(BVY`2(M=*$&]$0```$B)XDB%
+MVW0,9@^V12"#X`$YR'4I2(G32(-],`!T#TB)[O]5,(7`=15F9I!FD+@`````
+MZ>4```!F9I!F9I"`?5'_#X2^````#[=-5,'A";H```$`9H-["`!T!`^W4P@Y
+MT78[00^V1@,Z15!U%$B+`TF)!"1(BT,(28E$)`A)@\00*=%(@\,0N@```0!F
+M@WL(`'0$#[=3"$'_S3G1=\5!#[9&`SI%4'4<2(L#28D$)&9!B4PD"&9!QT0D
+M"@"`N`$```#K63G1<S>)R$@#`TF)!"2)T&8IR&9!B40D"&:!>PH`@'4/9D''
+M1"0*`("X`0```.LJ9D''1"0*``!)@\002(/#$$'_S42)ZDC!X@1(B=Y,B>?H
+M`````+@!````2(N<)``"``!(BZPD"`(``$R+I"00`@``3(NL)!@"``!,B[0D
+M(`(``$B!Q"@"``##D`^V1P,Z1E!U%P^W1E1FB4(02(M&2$B)0@C#9F:09F:0
+M#[=&4F:)0A!(QT((`````,-F9F:09F9FD&9F9I!F9I!,BT8(1`^W3A!!NP``
+M``"Y`````(!_>``/A(,```!%#[?1B<A(BY3'H````$PY0AAV84R)1DB(3E"X
+M`0```-/@#[=^6@G'9HE^6DN-!`)(.T(8=C1!NP$```"-00&(1E'_P42)V-/@
+MB<&)^`G(9HE&6DB+0AAF1"G`9HE&5&9!*<%F1(E.4NL9QD91_V9$B4Y4ZPY,
+M*T(8_\$/MD=X.<AW@42)V,-F9F:09F9FD&9FD%532(/L"$B)_4B+7D!(BP8/
+MMD@#N/[____3P&8A0UJ`?B$!=`</MD8AB$,A2(GOZ`````!F@WM:`'49@'LA
+M`'4$QD,A`4B+<SA(B=I(B>_H`````$B#Q`A;7<-F9I!FD$B#[#A(B5PD"$B)
+M;"003(ED)!A,B6PD($R)="0H3(E\)#!)B?](B?5,BS9!]D8!!'45QD8A`DB+
+M=CA(B>KH`````.G*````3(GWZ*'^__]F@WU:`'4:QD4A`DB+=3A(B>I,B?_H
+M`````.FC````9I!!O0````!!@'YX``^$D`````^W15I$B>G3^*@!='),B?_H
+M`````$B)PTECQ4V+I,:@````3(DC2(EK0`^V52"#X@(/MD,@@^#]"="(0R`/
+MME4@@^($@^#["="(0R`/MD42B$,22(G:2(GN3(GGZ,[]__](QT,X`````$C'
+M0S``````2(G>3(G_0?]4)&AF9I!!_\5!#[9&>$0YZ`^/</___TB+7"0(2(ML
+M)!!,BV0D&$R+;"0@3(MT)"A,BWPD,$B#Q#C#9F9FD&9F9I!F9F:02(/L"$B+
+M1@B`9@'[@&`!^_Y(>8"(D@````%(@WAP`'0&2(G&_U!P2(/$",-F9F:02&/.
+M2(N4SX!9``!(A=)T"TB+`DB)A,^`60``2(G0PY!(8])(BX37@%D``$B)!DB)
+MM->`60``PV9FD&9FD&9FD$%7059!54%455-(@^P(28G_O0"```"!_@!```!W
+M:&:]`$"!_@`@``!W7&:]`""!_@`0``!W4&:]`!"!_@`(``!W1&:]``B!_@`$
+M``!W.&:]``2!_@`"``!W+&:]``*!_@`!``!W(&:]``&!_H````!W%&:]@`"#
+M_D!W"X/^(1GM@^7@@\5`B=`/K\5$C;#_#P``0<'N#,=$)`0`````N`````"!
+M_0`0```/A]L```!!_\Y!@_[_#X3*````0;T`$```3(G_Z`````!(B</_1"0$
+M0;P`````1(GHN@````#W]8/X``^&CP```&9FD&9FD+H*````@?T`0```=U:R
+M"8']`"```'=,L@B!_0`0``!W0K('@?T`"```=SBR!H']``0``'<NL@6!_0`"
+M``!W)+($@?T``0``=QJR`X']@````'<0L@*#_4!W"8/](`^7P`^VT$B)WDR)
+M_^B"_O__B>A(`<-!_\1$B>BZ`````/?U1#G@#X=W____0?_.08/^_P^%//__
+M_XM$)`1(@\0(6UU!7$%=05Y!7\-F9F:09F:055-(B?V)\[@`````.;?860``
+M<E.^`P```.@"_O__2(G&2(7`=#Z)&/_+@_O_=#60B=FZ`````$B#O=!9````
+M=!=(BY7060``2(L"2(F%T%D``/^-V%D``$B)5,X(_\N#^_]US$B)\%M=PV9F
+MD&9FD(L._\F#^?]T+69F9I!F9I!(8\%(BU3&"$B+A]!9``!(B0)(B9?060``
+M_X?860``_\F#^?]UVKH#````Z)#]___SPV9F9I!F9F:09F:09F:055-(@^P(
+M2(G]BQ__RX/[_W0>2&/#2(M\Q0BZ`!```+X`````Z`````#_RX/[_W7B2(/$
+M"%M=PV9FD&9FD&9FD(L/_\F#^?]T+DACP4B+1,<(N@````!(@S@`=`:X````
+M`,/_PDB#P`B!^O\!``!VYO_)@_G_==*X`0```,-F9I!(@^P(NA````"^````
+M`.@`````2(/$",-F9F:09F9FD$B#?A@`=`Q(BU882(M&$$B)0A!(BU802(M&
+M&$B)`DC'1A``````N@````#HL/S___/#9F9FD&9F9I!F9I!F9I!(C4]@2(M'
+M8$B)1AA(A<!T#$B+5V!(C4882(E"$$B)3A!(B3'#9F9FD&9F9I!F9I!(@^P@
+M2(D<)$B);"0(3(ED)!!,B6PD&$F)]4F)U$B)S4B+7F!(A=MT(F9F9I!F9I!(
+M.2MS#4PY8PAV![@`````ZRM(BUL82(7;=>6^`````.C[^___2(G#3(D@2(EH
+M"$B)QDR)[^AF____2(G82(L<)$B+;"0(3(MD)!!,BVPD&$B#Q"##9F9FD&9F
+M9I!F9I`/MD=-#[;02(T4DDB-5-=0_\"(1TU(B3K&0@D`QD(*`,9""P!(B=##
+M9F9FD&9F9I!!5%5328G\2(GSO0`````/ME9*C4+]T?@!PH/Z`'XED$ACQ4B+
+MM,.@"@``3(GGZ*W]____Q0^V4TJ-0OW1^`'".>I_W+H'````2(G>3(GGZ%S[
+M__];74%<PV9F9I!F9I!!5T%6055!5%532(/L&$F)_4B)5"00B?-!B<Z+M]A9
+M``#!Y@,/M\D/MM.-0OW1^`'"#Z_*.<X/@]H```!$#[;[1(E\)`Q!B<Q)C850
+M60``23F%4%D```^$V@```$F+K5!9``!(BU4(2(M%`$B)4`A(B0)(B6T`2(EM
+M"$B#?2``="9(@WTH`'0,2(M5*$B+12!(B4(@2(M5($B+12A(B0)(QT4@````
+M`&9$.75(=4HX74IU14B);0!(B6T(2(M$)!!(B45`0;P`````08/_`'X@BUPD
+M#$EC_$C!YP1(C;PO<`L``.AH_?__0?_$1#GC?^1(B>CI(@$``$B)[DR)[^B=
+M_O__08N%V%D``,'@`T0YX`^",O___[X'````3(GOZ`WZ__](B<6X`````$B%
+M[0^$Y@```.L*N`````#IV@```$B);0!(B6T(2(M$)!!(B45`9D2)=4B(74I(
+MQT4P`````$&\``````^VTXU"_='X`<*#^@`/CIT```!%B?=F0<'O`P^VTXU"
+M_='X1(TT`F:026/<00^W]TR)[^AQ^___2(F$W:`*``!(A<!U/$'_S$&#_/]T
+M'$ECQ$B+M,6@"@``3(GOZ+C[__]!_\Q!@_S_=>2Z!P```$B)[DR)[^AO^?__
+MN`````#K,DECQ$C!X`1(C1PH2(V[\`H``.A1_/__2(V[<`L``.A%_/__0?_$
+M13GF#X]Y____2(GH2(/$&%M=05Q!74%>05_#9F9FD&9FD$%455-(B?5(B=.)
+MS@^V37J)T-/H)?\!``!(BU583(TDPDV+!"1-A<!T+V9FD&9FD$DY6$!U&DF+
+M4`A)BP!(B5`(2(D"38D`38E`"$R)P.MS38M`*$V%P'77#[?.#[9U>$B)VNAH
+M_?__28G`2(7`=%!(B6@X28L$)$F)0"A(A<!T#$F+%"1)C4`H2(E"($V)8"!-
+MB00D#[9U>$&(<$H/MDUZ2(G82-/H2`^V57A(B=&Z`````$CW\4`HUO_.08AP
+M2TR)P%M=05S#9F9FD&9F9I!!5T%6055!5%532('L:`$``$B)?"1(2(ET)$!(
+MB50D.`^V5B")T-#H@_`!B<&#X0&)3"0T2(-^*`!T!?;"`70<3(U\)%"Y`0``
+M`$R)^DB+="1`2(M\)$C_5C#K"4B+7"1`3(M[*,=$)`P```$`9D&#?P@`=`E!
+M#[='"(E$)`Q!O0````#'1"0P`````$B+5"1`@+J```````^$=P$``$AC1"0P
+M2(M,)$!(BT3!6$B)1"0@#[:88`P``(A<)"\XF&$,```/@C(!```/MD0D+TB+
+M5"0@.$)+#X0%`0``#[;`2(G1#[>4@D`,```/MX2!0@P``&:)1"00B=!FP>@#
+M#[?`B40D"$&)UD&#Y@=!#[?&B<;!Y@FX"````&9$*?!!B<9F1#MT)!"+7"00
+M1`]'\T$/M\:)Q<'E"4@/MD0D+TB+5"0@2(N,PJ`*``"+5"0(B?!)B<1,`V31
+M"$0[;"0,=2-)@\<0QT0D#````0!F08-_"`!T"4$/MT\(B4PD#$&]`````(M<
+M)`Q$*>LYZP]'W8-\)#0`=!)$B>Y)`S>)VDR)Y^@`````ZQ!$B>])`S^)VDR)
+MYN@`````00'=*=UT!XG820'$ZY-F1"ET)!!T%/]$)`B^`````$&^"````.D_
+M_____D0D+P^V7"0O2(M$)"`XF&$,```/@\[^____1"0P2(M4)$`/MH*`````
+M.T0D,`^/B?[__[H`````2(MT)$!(BWPD2/]4)#A(@<1H`0``6UU!7$%=05Y!
+M7\-F9I!F9I!54TB#[`A(B?V%TG0$QD8A"T&[`````("^@``````/A,$```!(
+MC9U@60``2(V]4%D``$ECPTR+1,982<>`,`P```````!-B<*Y`````$&`>$H`
+M=D8/ML%(P>`$3`'02(V0\`H``$&Y`````(.X\`H```!U$H-Z!`!U#(-Z"`!U
+M!H-Z#`!T!D&Y`0```$6%R9!U)?_!03A*2G>ZN`````"%P'0=2(M#"$R)0PA)
+MB1A)B4`(3(D`ZQNX`0```.OA9I!(BT<(3(E'"$F).$F)0`A,B0!!_\,/MH:`
+M````1#G8#X]-____2(GOZ%,X``!(@\0(6UW#9F9FD&9F9I!F9F:02(/L2$B)
+M7"082(EL)"!,B60D*$R);"0P3(ET)#A,B7PD0$F)_4B)\TB+KC`,``#_C]Q9
+M``!(C4802(M("$B+5A!(B4H(2(D12(E&$$B)0`A(A>T/A*<"``#V12`@#X0M
+M`0``3(ME`$@/MT9(28G&3`-V0$0/MWY(2,>&,`P```````!(C8=060``2(M0
+M"$B)<`A(B09(B58(2(DR@+YB#````758@'T2`G5)2`^V1DM(B[S&H`H``.@3
+M]___A<!U,\:#8@P```Q!@(PDD@````I!#[>$))````#WV$B82"-#0$DYA"28
+M````=@A)B80DF````("[8@P```%T&@^V@V(,``"(12%(B>Y,B>_H+C<``.F)
+M`P``20^WA"20````2(M5"$C_PD@/K\),.?!V+4$/M\],B?),B>9,B>_HKOK_
+M_TB)J#`,``!(B4582(G&3(GOZ$@0``#I0P,``$D/MX0DD````$D#A"28````
+M3#GP=0A-B;0DF````$B)[DR)[^BZ-@``Z14#``!F9I!FD`^VA8$```#_P(B%
+M@0```#J%@`````^%E0(``/9%(`0/A-P```!!O@````"`O8``````#X:Y````
+M2(V'4%D``$B)1"002(V78%D``$B)5"0(1(GR#[;"2(M<Q5A(QX,P#```````
+M`("[8@P```%U44F)WT&\`````(![2@!V(F:01(G@#[;X2,'G!$J-O#_P"@``
+MZ.GU__]!_\1%.&=*=^!(BU0D$$B+0@A(B5H(2(D32(E#"$B)&.LH9F9FD&9F
+MD`^V@V(,``"(12%(BU0D"$B+0@A(B5H(2(D32(E#"$B)&$'_QD0XM8`````/
+MAU____](B>Y,B>_HM#4``.FO`0``0;X`````@+V``````'8J1(GR#[;"2(M<
+MQ5B`NV(,```!=`H/MH-B#```B$4A0?_&1#BU@````'?6@'TA`'472,?"````
+M`$B)[DR)[^C>^?__Z5D!``"Z`````$B)[DR)[^@)_/__Z40!``!F9F:0@+YB
+M#````0^%@P```$F)]+T`````@'Y*`'8D9F:09I")Z`^V^$C!YP1*C;PG\`H`
+M`.C:]/___\5!.&PD2G?A2(.[.`P```!T*4B+@S@,``!(B8,P#```2,>#.`P`
+M``````!(B=Y,B>_H,PX``.G.````28V%4%D``$B+4`A(B5@(2(D#2(E3"$B)
+M&NM:9F:02(V'8%D``$B+4`A(B7`(2(D&2(E6"$B),DB#OC@,````=#1(BX8X
+M#```#[:68@P``(A0(4B+EC@,``!(Q\8`````Z`````!(QX,X#````````.FY
+M````2(MS,$R)[^@]]/__2,=#,`````!(BT,X2(-X,`!T%4B-4#!(Q\8`````
+M3(GOZ`````#K)4F#O>A9````=!M)C97H60``2,?&`````$R)[^@`````9F:0
+M9I!!@[W@60```'16@+MB#````75-2(M[.$B#?T@`=##H#3(``(7`=2=(BT,X
+M2(M04$B+<$A,B>_H`````$B+0SA(QT!(`````$'_C>!9``!!@[W@60```'0(
+M3(GOZ`````!(BUPD&$B+;"0@3(MD)"A,BVPD,$R+="0X3(M\)$!(@\1(PV9F
+M9I!F9I!F9I!F9I!(@^P(2(L6@'I.`'03QD).`$C'Q@````#H`````&9FD$B#
+MQ`C#9F9FD&9F9I!F9I!!5T%6055!5%532(/L"$F)U$&)STB+1D!(BQ!(#[9`
+M$4R+M,*@"@``BT8(*T)`P>`)#[=N$,'E"8G!@>'_#P``08G%0<'M#+L`$```
+M*<LYZP]'W46%_W0,26/5B<A)`T36".L/26/%B<])`WS&".@`````28D$)&9!
+MB5PD"#GK=!AF0<=$)`H``$F#Q!!!_\4IW;D`````ZZYF0<=$)`H`@+@!````
+M2(/$"%M=05Q!74%>05_#9F9FD&9F9I!F9I`/MD<2`D<3B$<22(U7%+X!````
+MZP^`?Q(`>0:X`````,/^1Q(/MD\2@_D?=Q.)\-/@A4<4#Y7`#[;`ZU1F9F:0
+M@_D_=Q*#Z2")\-/@A4($#Y7`#[;`ZSF#^5]W%(/I0(GPT^"%0@@/E<`/ML#K
+M(F:0N`````"#^7]W%H/I8(GPT^"%0@P/E<`/ML!F9I!F9I"%P'2!QD<3`4R-
+M1Q0/ME<2O@$```#K`_Y'$P^V1Q.-#`*#^1]W#XGPT^"%1Q0/E<`/ML#K3H/Y
+M/W<6@^D@B?#3X$&%0`0/E<`/ML#K-F9FD(/Y7W<3@^E`B?#3X$&%0`@/E<`/
+MML#K&[@`````@_E_=Q&#Z6")\-/@085`#`^5P`^VP(7`=9"P`<-F9I!F9I!(
+M@^P82(D<)$B);"0(3(ED)!!(B?U(BUY`3(LC#[9&(8A#"N@`````@'L*`75R
+M2(G?Z*K^__^%P'06QD,*`$B)WDB)[^C'````ZV1F9I!FD(!["`%U2@^V0Q!!
+M.$0D2Y!T/CA#$74Y#[;P2(GP2,'@!$J-M"!P"P``2(U+%(L&"T,4B0:+1@0+
+M002)1@2+1@@+00B)1@B+1@P+00R)1@R0QD,)`DB)WDB)[^A!_?__2(L<)$B+
+M;"0(3(MD)!!(@\08PV9F9I!F9F:09F:09F:02(/L&$B)7"0(3(ED)!!)B?Q(
+MB?/&1A,`QD82`$B)]^CL_?__2(G>3(GGZ!$```!(BUPD"$R+9"002(/$&,-F
+MD$B#["A(B5PD"$B);"003(ED)!A,B6PD($F)_4B)\TB++DB+53A(#[9&$$R+
+MI,*@````Z`````!(B<9,B2"`>P@!=0V`2"`"QD`2(.L+9F:0@$@@!,9`$C!(
+M#[9#$D@#14!(B48(9@^V0Q-FB4802,=&,`````!(B5Y`2,=&.`````!,B>]!
+M_U0D:$B+7"0(2(ML)!!,BV0D&$R+;"0@2(/$*,-F9F:09F:09F:09F:00515
+M4T&Y`````$&[`````$B)_4&\`0```.L808/[?W8/1(G(Z5X!``!F9F:09F:0
+M0?_#1(G:08/['W<21(G@1(G9T^"%!P^5P`^VP.M208/[/W<3C4K@1(GCT^.%
+M700/E<`/ML#K.4&#^U]W$XU*P$2)X-/@A44(#Y7`#[;`ZR"X`````$&#^W]W
+M%8U*H$2)X]/CA5T,#Y7`#[;`9F9FD(7`#X1S____0;@!````2(GZ0;H!````
+MZPIF9F:09F:00?_`0XT,`X/Y'W<41(G0T^"%`@^5P`^VP.M59F:09I"#^3]W
+M$X/I($2)T-/@A4($#Y7`#[;`ZSB#^5]W$X/I0$2)T]/CA5H(#Y7`#[;`ZR"X
+M`````(/Y?W<6@^E@1(G0T^"%0@P/E<`/ML!F9I!FD(7`=8Q$B=E%`<-!N@@`
+M``!$B<J)R,'H`X@$EHG(@^`'B$26`42)TRC#B%R6`@^VPT0YP',*02G``<%!
+M_\'KT42)R$2(1(8"0?_!08/[?P^&K_[__T2)R%M=05S#9F9FD$B![%@!``!(
+MB9PD*`$``$B)K"0P`0``3(FD)#@!``!,B:PD0`$``$R)M"1(`0``3(F\)%`!
+M``!(B7PD"$F)]4B++DB+7A"`>QD`#X3A````2(-[$`!U"4B)<Q#I8@$``,9#
+M&0!(C70D($B)W^C__?__08G&2`^V0QA,BZ3%H`H``$B+0Q!(#[9`&$R+O,6@
+M"@``20^V11A(BZS%H`H``+L`````1#GS#XT#`0``9F:02&/3#[9$E"&)P<'A
+M"0^V1)0B08G`0<'@"40/MDR4($2)R`^VT(G(2(G'20-\UPA(B7PD$$B)QD@#
+M=-4(2(ET)!A)`T34"$@YQW4*1(G"Z`````#K($B+5"082(MT)!!$B<A$#[;(
+MB<]+`WS,"$2)P>@`````_\-$.?-\A.E_````2(UT)"!(B=_H,OW__T&)QD@/
+MMD,83(NDQ:`*``!)#[9%&$R+O,6@"@``NP````!$.?-]2TACTP^V1)0AB<'!
+MX0D/MD24(D&)P$'!X`E(#[9$E"")SDB)]TD#?,0(2(E\)!!)`W3'"$B)="08
+M1(G"Z`````#_PT0Y\WRY9F9FD+H`````3(GN2(M\)`CHC@(``$B+G"0H`0``
+M2(NL)#`!``!,BZ0D.`$``$R+K"1``0``3(NT)$@!``!,B[PD4`$``$B!Q%@!
+M``##9F:09F:02('L2`$``$B)G"08`0``2(FL)"`!``!,B:0D*`$``$R)K"0P
+M`0``3(FT)#@!``!,B;PD0`$``$F)_TB)]4B+'DB-="002(U]$.@B_/__08G$
+M2`^V12!,B[3#H`H``$@/MD4A3(NLPZ`*``"[`````$0YXWT]2&/##[9TA!'!
+MY@D/ME2$$L'B"4@/MD2$$(GV2(GW20-\Q@A(B3PD20-TQ0A(B70D".@`````
+M_\-$.>-\P[H`````2(GN3(G_Z(X!``!(BYPD&`$``$B+K"0@`0``3(ND)"@!
+M``!,BZPD,`$``$R+M"0X`0``3(N\)$`!``!(@<1(`0``PV9FD&9FD$%7059!
+M54%455-(@>R(`0``28G_2(GU3(LF2(M>$$B-M"2`````2(G?Z$+[__]!B<9(
+M#[9#&$V+K,2@"@``NP````"`?2``=B,/MDT@9F:0#[;#2`^V5"@828N4U*`*
+M``!(B53$0/_#.-EWY$&\`````$4Y]`^-K0```&9FD&:026/$#[:4A($```!!
+MB=)!P>()#[:4A((```!!B=-!P>,)#[:,A(````"[`````(!](`!V*$0/MLE%
+MB=`/MG4@D`^VPTB+5,1`2HM\R@A)C10X2(D4Q/_#0#C>=^0/MM%$B=!(B<=)
+M`WS5"$@Y/"1U$$B+="0(1(G:Z`````#K'9!(BU0D"$B+-"0/ML%$B==)`WS%
+M"$2)V>@`````0?_$13GT#XQ8____N@````!(B>Y,B?_H&````$B!Q(@!``!;
+M74%<05U!7D%?PV9FD&9FD$B#[!A(B1PD2(EL)`A,B60D$$F)_$B)\XG5QD8)
+M`H/Z`1G`@^#U@\`,B$8*Z!_V__^`>P@#=2](BT,02(MP$$B%]G0B2,=`$```
+M``#&1@D"@_T!&<"#X/6#P`R(1@I,B>?HZO7__TB+'"1(BVPD"$R+9"002(/$
+M&,-F9F:09F:0#[96"X72=$:)T$@/MH1'L`D``$B-!(!(C43'4(!X"0)T!K@`
+M````PX!X"@%T$L9&"0(/MD`*B$8*N`````##D(G0#[:41[$)``"%TG6ZN`$`
+M``##9F9FD&9F9I!F9F:005=!5D%505154TB#[`A)B?Y(B?7&1DX`@+YC#```
+M``^$BP```$&\`````$B-75"`?4T`=$Z`>PD!=3B`>P@#=2E(BT,0@'@9`'0?
+M2(-X$`!T&$C'0!``````QD,)`@^VA6(,``"(0PKK"<9%3@'IMP$``$'_Q$B#
+MPR@/MD5-1#G@?[)(B>Y,B??H$O#__^F7`0``#[9#"HB%8@P``,:%8PP```'I
+M?/___V9F9I!F9I!!OP````!!O0$```!!O`````!(C5U0@'U-``^$-`$``(![
+M"0!U>DB)WDB)[^B__O__A<!T6\9#"0%,B?=(B=X/MD,(@_@&=TB)P/\DQ0``
+M``#H2O?__^LX9F9FD&9F9I#HN_G__^LIZ+3[__]F9F:0ZQ[HJ?S__^L7QD5/
+M`<9&"0+&1@H!Z#;T__]F9I!F9I"`>PD"=1!!_\=F9F:09F:0@'L)`G0+0;T`
+M````Z8\```"`>PH!#X2%````@'U/`)`/A!W___](BT4X2`^V4Q!(BX30H```
+M`/9``01T7T&]`````,9#"0'&0PH`3(GW2(G>#[9#"(/X!G=&B<#_),4`````
+MZ)CV___K-F9FD&9FD.@+^?__ZRGH!/O__V9F9I#K'NCY^___ZQ?&14\!QD8)
+M`L9&"@'HAO/__^L$QD,*`4'_Q$B#PR@/MD5-1#G@#X_,_O__187_#X6C_O__
+M187M=!3&A6(,```!2(GN3(GWZ'SN___K!,9%3@%(@\0(6UU!7$%=05Y!7\-F
+M9F:09F:005=!5D%505154TB!['@!``!(B7PD2$B)]4B+7CA,BZ8P#```0;T`
+M````387D=2A(#[=.2$B+5D!(`=%(B=[HO>;__TB)13"X_____TB#?3``#X2N
+M(@``2(M$)$C_@-Q9``!(C4402(M4)$A(@<)P60``2(M*"$B)0@A(B5402(E(
+M"$B)`6:#NY0`````=$/V@Y(````!=0U(BU5`2#F3F````'<G0;X`````#[>#
+ME````(G"J`%U#D'_QHG01(GQT_BH`73R1(AU3.LIQD5,".LC]H.2`````G06
+M2(M]0$@YNY@```!W"0^V14N(14SK!,9%3`C&14T`QH6P"0```,9%3P#&A6(,
+M````QH5C#````$C'A3@,````````387D#X1?#P``0?9$)"`@#X2.!P``00^V
+M1"02@_@"#X1M!```@_@"?P^#^`$/A`0!``"0Z9XA``"#^`,/A94A``!(C5PD
+M8$B)W^@%Y?__28G:OP`````/MW5(NP````!!N2````!!NP$```"#_Q]W/P^V
+MPTF-%()$B<DI^3GQ#T?.@_D@=0C'`O_____K#42)V-/@_\B)^=/@"0)$B<@I
+M^#GP<Q6-=#[@OP````#K`X/O(/_#@/L#=K)(B[V@"@``Z`[D__]!OP````"`
+M?4H`#X8!(0``1(G[#[;#2,'@!$B-'"A(C;OP"@``Z&3D__](C;MP"P``Z%CD
+M__](B>_H<.7__\9`"`)$B'@0QD`1`$B+5"1@2(E0%$B+5"1H2(E0'$'_QT0X
+M?4IWJ^FG(```N`$```#K54B)[[D`````@'U*`)!V00^VP4C!X`1(`?A(C9#P
+M"@``O@````"#N/`*````=1*#>@0`=0R#>@@`=0:#>@P`=`6^`0```(7V=;#_
+MP3A/2G>_N`````"%P'073(FE.`P``$C'A3`,````````Z<(-``!(C5PD8$B)
+MW^B@X___28G:OP`````/MW5(NP````!!N2````!!NP$```"#_Q]W/P^VPTF-
+M%()$B<DI^3GQ#T?.@_D@=0C'`O_____K#42)V-/@_\B)^=/@"0)$B<@I^#GP
+M<Q6-=#[@OP````#K`X/O(/_#@/L#=K*`?4P(=0</MD5+B$5,#[9=3(B="`P`
+M`,:%"0P```%(BT0D8$B)A?`+``!(BT0D:$B)A?@+``!(QX4`#````````$B)
+M[^@,Y/__QD`(`HA8$(A8$4B+5"1@2(E0%$B+5"1H2(E0'$F)Q(!]2@(/AP`!
+M``!(C9WP"P``2(GOZ-3C___&0`@%2(E8$,9`(`!)B<5)BPPD_H&P"0``#[:Q
+ML`D``(GW2"G(2(/H4$C!^`-(NLW,S,S,S,S,2`^OPHB$>;`)``!!#[9$)`N(
+MA'FQ"0``08AT)`M!OP````"`?4H`#X;3'@``2(G31#A]3'1R2(GOZ%_C___&
+M0`@!1(AX$$2(>!%(BU0D8$B)4!1(BU0D:$B)4!Q!#[95(`^VRD:(?"D8_\)!
+MB%4@28M5`/Z"L`D```^VLK`)``")\4@IT$B#Z%!(P?@#2`^OPXB$2K`)``!!
+M#[9%"XB$2K$)``!!B'4+0?_'1#A]2@^'>____^E&'@``0;\`````@'U*``^&
+M-AX``$B-G?`+``!)OLW,S,S,S,S,1#A]3`^$O0```$B)[^BPXO__QD`(`42(
+M>!!$B'@12(M4)&!(B5`42(M4)&A(B5`<2(E$)$!(B>_HA>+__\9`"`-(B5@0
+M1(AX&$F)Q4B+$/Z"L`D```^VLK`)``")\4B+1"1`2"G02(/H4$C!^`-)#Z_&
+MB(1*L`D``$$/MD4+B(1*L0D``$&(=0M)BQ0D_H*P"0``#[:RL`D``(GQ3(GH
+M2"G02(/H4$C!^`-)#Z_&B(1*L`D``$$/MD0D"XB$2K$)``!!B'0D"T'_QT0X
+M?4H/ARS____I3!T``+@!````ZUE(B>^Y`````(!]2@!V1F9F9I`/ML%(P>`$
+M2`'X2(V0\`H``+X`````@[CP"@```'43@WH$`'4-@WH(`'4'@WH,`)!T!;X!
+M````A?9UK/_!.$]*=[ZX`````(7`=!=,B:4X#```2,>%,`P```````#I8PH`
+M`$B-7"1@2(G?Z$'@__])B=J_``````^W=4B[`````$&Y(````$&[`0```&9F
+M9I"#_Q]W/P^VPTF-%()$B<DI^3GQ#T?.@_D@=0C'`O_____K#42)V-/@_\B)
+M^=/@"0)$B<@I^#GP<Q6-=#[@OP````#K`X/O(/_#@/L#=K(/MD5+B(4(#```
+MQH4)#````$B+1"1@2(F%\`L``$B+1"1H2(F%^`L``$C'A0`,````````@'U*
+M`@^'N````$B-G?`+``!(B>_HI>#__\9`"`5(B5@0QD`@`$F)Q4&_`````(!]
+M2@`/AND;``!(N\W,S,S,S,S,2(GOZ'3@___&0`@!1(AX$$2(>!%(BU0D8$B)
+M4!1(BU0D:$B)4!Q!#[95(`^VRD:(?"D8_\)!B%4@28M5`/Z"L`D```^VLK`)
+M``")\4@IT$B#Z%!(P?@#2`^OPXB$2K`)``!!#[9%"XB$2K$)``!!B'4+0?_'
+M1#A]2G>%Z5\;```/MEU+2(GOZ/#?___&0`@!B%@0B%@12(M4)&!(B5`42(M4
+M)&A(B5`<2(E$)#A!OP````"`?4H`#X8B&P``2(V=\`L``$F\S<S,S,S,S,Q$
+M.'U+#X2]````2(GOZ)S?___&0`@!1(AX$$2(>!%(BU0D8$B)4!1(BU0D:$B)
+M4!Q(B40D0$B)[^AQW___QD`(`TB)6!!$B'@828G%2(L0_H*P"0``#[:RL`D`
+M`(GQ2(M$)$!(*=!(@^A02,'X`TD/K\2(A$JP"0``00^V10N(A$JQ"0``08AU
+M"TF+50#^@K`)```/MK*P"0``B?%(BT0D.$@IT$B#Z%!(P?@#20^OQ(B$2K`)
+M``!!#[9%"XB$2K$)``!!B'4+0?_'1#A]2@^'+/___^DX&@``9F:09I!-A>0/
+MA+P'``!!]D0D(`*0#X2O!P``1`^VO6`,``!$.+UA#```#X)5`0``9F:09I!$
+M.'U+#X0V`0``1(GX#[;82(G82,'@!$R-I`3P````3(GGZ%G=__\/MY2=0`P`
+M``^WO)U"#```NP````!!N2````!!N@$```"#^A]W1`^VPTF--(1$B<DIT3GY
+M#T?/@_D@=0W'!O_____K$F9FD&:01(G0T^#_R(G1T^`)!D2)R"G0.?AS%8U\
+M%^"Z`````.L#@^H@_\.`^P-VK42)^P^VPTB)QTC!YP1(C00O2(V0<`L``(N(
+M<`L``/?1B4PD8(M"!/?0B40D9(M""/?0B40D:(M"#/?0B40D;$B-=#QP2(V4
+M//`````C"HD.BT($(T0D9(E&!(M"""-$)&B)1@B+0@PC1"1LB48,1#A]3'4Q
+MN@````"#/@!U$H-^!`!U#(-^"`!U!H-^#`!T!;H!````A=*X`0```$0/1>AF
+M9I!FD$'_QT0XO6$,```/@[#^__]%A.T/A)H%``!(C7PD8.@=W/__0;\`````
+M@'U*`'99D$0X?4QT240X?4MT0T2)^`^VT$C!X@1(`>I(C8KP"@``BT0D8`N"
+M\`H``(E$)&"+1"1D"T$$B40D9(M$)&@+00B)1"1HBT0D;`M!#(E$)&Q!_\=$
+M.'U*=ZA,#[9%3$G!X`1*C70$<(M\)&`C/HE\)%"+3"1D(TX$B4PD5(M4)&@C
+M5@B)5"18BT0D;"-&#(E$)%SWUXE\)&#WT8E,)&3WTHE4)&CWT(E$)&PC/HE\
+M)&`C3@2)3"1D(U8(B50D:"-&#(E$)&Q(B>_H9-S__\9`"`!(B40D*+@`````
+M@WPD8`!U%8-\)&0`=0Z#?"1H`'4'@WPD;`!T!;@!````A<`/A*8!```/MD5,
+MB(4(#```2(M$)&!(B87P"P``2(M$)&A(B87X"P``QH4)#````4C'A0`,````
+M````0;\`````@'U*``^&`P(``$R-I?`+``!$.'U,#X0_`0``1#B]8`P``'</
+M1#B]80P``'(&1#A]2W4M2(GOZ+C;___&0`@!1(AX$$2(>!%(BU0D8$B)4!1(
+MBU0D:$B)4!Q(B40D0.M21(GZ#[;"2,'@!$B-7`1PBT0D8`D#BT0D9`E#!(M$
+M)&@)0PB+1"1L"4,,2(GOZ&';___&0`@!1(AX$$2(>!%(BQ-(B5`42(M3"$B)
+M4!Q(B40D0$B)[^@YV___QD`(`TR)8!!$B'@828G%2(L0_H*P"0``#[:RL`D`
+M`(GQ2(M$)$!(*=!(@^A02,'X`TB_S<S,S,S,S,Q(#Z_'B(1*L`D``$$/MD4+
+MB(1*L0D``$&(=0M$.'U+=41(BTPD*$B+$?Z"L`D```^VLK`)``")\4R)Z$@I
+MT$B#Z%!(P?@#2`^OQXB$2K`)``!(BUPD*`^V0PN(A$JQ"0``0(AS"T'_QT0X
+M?4H/AZK^___IH0```$&_`````(!]2@`/AI$```!$.+U@#```=WM$.+UA#```
+M<G)$.'U+=&Q$.'U,=&9$B?H/ML)(P>`$2(U$!'"Z`````(,X`'42@W@$`'4,
+M@W@(`'4&@W@,`'0%N@$```"%TG0R1(GY#[;!2,'@!$B-7`1P2(GOZ`[:___&
+M0`@!1(AX$$2(>!%(BQ-(B5`42(M3"$B)4!Q!_\=$.'U*#X=O____N`````"#
+M?"10`'45@WPD5`!U#H-\)%@`=0>#?"1<`'0%N`$```"%P`^$&Q4``$0/MF5,
+M1(BE*`P``$B+1"102(F%$`P``$B+1"182(F%&`P``,:%*0P```!(QX4@#```
+M``````^V74M(B>_H=MG__\9`"`&(6!!$B&`12(M4)%!(B5`42(M4)%A(B5`<
+M2(E$)#A(QT0D,`````!!OP````"`?4H`#X:>%```3(VE$`P``$F^S<S,S,S,
+MS,Q$.'U,#X1A`0``1#A]2P^$5P$```^V74M(B>_H"MG__\9`"`%$B'@0B%@1
+M2(M4)%!(B5`42(M4)%A(B5`<2(E$)$!(BQ#^@K`)```/MK*P"0``B?%(BT0D
+M*$@IT$B#Z%!(P?@#2+_-S,S,S,S,S$@/K\>(A$JP"0``2(M<)$`/MD,+B(1*
+ML0D``$"(<PM(@WPD,`!T/$B+$_Z"L`D```^VLK`)``")\4B+1"0P2"G02(/H
+M4$C!^`-(#Z_'B(1*L`D```^V0PN(A$JQ"0``0(AS"P^V74M(B>_H3=C__\9`
+M"`-,B6`0B%@828G%2(E$)#!(BQ#^@K`)```/MK*P"0``B?%(BT0D0$@IT$B#
+MZ%!(P?@#20^OQHB$2K`)``!!#[9%"XB$2K$)``!!B'4+28M5`/Z"L`D```^V
+MLK`)``")\4B+1"0X2"G02(/H4$C!^`-)#Z_&B(1*L`D``$$/MD4+B(1*L0D`
+M`$&(=0M!_\=$.'U*#X>(_O__Z1`3``!$#[:]8`P``$0XO6$,```/@OL2``!$
+M.'U+=')$B?H/ML)(P>`$2(U$!'"Z`````(,X`'49@W@$`'43@W@(`'4-@W@,
+M`'0,9F9FD&9FD+H!````A=)T-T2)^0^VP4C!X`1(C5P$<$B)[^A`U___QD`(
+M`42(>!!$B'@12(L32(E0%$B+4PA(B5`<9F:09I!!_\=$.+UA#```#X-X____
+MZ6X2``"`?4P'#X;3"0``2(U\)&#HU]7__\9$)"<`0;\`````@'U*``^&H0``
+M`&:01#A]2P^$B````$2)^P^VPTC!X`1(`>A(C9#P"@``N0````"#N/`*````
+M=1:#>@0`=1"#>@@`=0J#>@P`9F9FD'0%N0$```"%R71'1(GX#[;02,'B!$@!
+MZDB-BO`*``"+1"1@"X+P"@``B40D8(M$)&0+002)1"1DBT0D:`M!"(E$)&B+
+M1"1L"T$,B40D;/Y$)"=!_\=$.'U*#X=A____#[94)"</MD5*@^@#T?@YP@^.
+M5`4```^V74N(G0@,``!(BT0D8$B)A?`+``!(BT0D:$B)A?@+``#&A0D,```!
+M2,>%``P```````!(B>_H[]7__\9`"`*(6!"(6!%(BU0D8$B)4!1(BU0D:$B)
+M4!Q)B<1(B>_HR-7__\9`"`9(B40D*$F+%"3^@K`)```/MK*P"0``B?%(BT0D
+M*$@IT$B#Z%!(P?@#2;[-S,S,S,S,S$D/K\:(A$JP"0``00^V1"0+B(1*L0D`
+M`$&(="0+@'U*`@^'20(``$B-G?`+``!(B>_H7-7__\9`"`5(B5@0QD`@`$F)
+MQ4B+3"0H2(L1_H*P"0``#[:RL`D``(GQ2"G02(/H4$C!^`-)#Z_&B(1*L`D`
+M`$B+7"0H#[9#"XB$2K$)``!`B',+0;\`````@'U*``^&7Q```$0X?4L/A+X!
+M``!!#[9%(`^VT$:(?"H8_\!!B$4@1(GX#[;P2,'F!$B-!"Y(C8AP"P``BY!P
+M"P``]]*)5"10BT$$]]")1"14BT$(]]")1"18BT$,]]")1"1<2(U,-'`C5"1@
+MB1&+1"1D(T0D5(E!!(M$)&@C1"18B4$(BT0D;"-$)%R)00RX`````(,Y`'42
+M@WD$`'4,@WD(`'4&@WD,`'0%N`$```"%P'1K1(GZ#[;"2,'@!$B-7`1P2(GO
+MZ#O4___&0`@!1(AX$$2(>!%(BQ-(B5`42(M3"$B)4!Q)BU4`_H*P"0``#[:R
+ML`D``(GQ2"G02(/H4$C!^`-)#Z_&B(1*L`D``$$/MD4+B(1*L0D``$&(=0M$
+MB?D/ML%(P>`$2(V$*/`*``"Z`````(,X`'42@W@$`'4,@W@(`'4&@W@,`'0%
+MN@$```"%TF:0='I$B?@/MMA(B=A(P>`$2(V<*/`*``!(B>_HD=/__\9`"`)$
+MB'@01(AX$4B+$TB)4!1(BU,(2(E0'$F)Q$B+$/Z"L`D```^VLK`)``")\4B+
+M1"0H2"G02(/H4$C!^`-)#Z_&B(1*L`D``$$/MD0D"XB$2K$)``!!B'0D"T'_
+MQT0X?4H/ARO^___IA0X``$&_`````(!]2@`/AG4.``!(C97P"P``2(E4)!A)
+MOLW,S,S,S,S,1#A]2P^$"0(``$2)^0^V\4C!Y@1(C00N2(V(<`L``(N0<`L`
+M`/?2B50D4(M!!/?0B40D5(M!"/?0B40D6(M!#/?0B40D7$B-7#1P(U0D8(D3
+MBT0D9"-$)%2)0P2+1"1H(T0D6(E#"(M$)&PC1"1<B4,,2(GOZ(+2___&0`@#
+M2(M\)!A(B7@01(AX&$F)Q4B+1"0H2(L0_H*P"0``#[:RL`D``(GQ3(GH2"G0
+M2(/H4$C!^`-)#Z_&B(1*L`D``$B+?"0H#[9'"XB$2K$)``!`B'<+N`````"#
M.P!U$H-[!`!U#(-["`!U!H-[#`!T!;@!````A<!T:T2)^@^VPDC!X`1(C5P$
-M<$B)[^BLR/__QD`(`42(>!!$B'@12(L32(E0%$B+4PA(B5`<28M5`/Z"L`D`
-M``^VLK`)``")\4@IT$B#Z%!(P?@#20^OQ(B$2K`)``!!#[9%"XB$2K$)``!!
-MB'4+0?_'1#A]1@^'2_[__[@`````@WPD4`!U%8-\)%0`=0Z#?"18`'4'@WPD
-M7`!T!;@!````A<`/A#`#```/MEU'2(GOZ!'(___&0`@!B%@0B%@12(M4)%!(
-MB5`42(M4)%A(B5`<2(E$)#A(QT0D,`````!!OP````"`?48`#X;J`@``9F9F
-MD&9FD$0X?4@/A,P"``!$.'U'#X3"`@``1(GY#[;!2,'@!$B-=`1P2`'H2(V(
-M\`H``(M4)%`CD/`*``")%HM$)%0C002)1@2+1"18(T$(B48(BT0D7"-!#(E&
-M#+@`````@SX`=1*#?@0`=0R#?@@`=0:#?@P`=`6X`0```(7`#X16`@``1`^V
-M94A$B?L/ML-(P>`$2(U<!'!(B>_H-,?__\9`"`%$B'@01(A@$4B+$TB)4!1(
-MBU,(2(E0'$B)1"1`2(-\)#``=$M(BQ#^@K`)```/MK*P"0``B?%(BT0D,$@I
-MT$B#Z%!(P?@#2+_-S,S,S,S,S$@/K\>(A$JP"0``2(M<)$`/MD,+B(1*L0D`
-M`$"(<PM$#[9E1P^V?4A`B'PD#T2)^$0/MO!)P>8$2HU<-'!(B>_HF\;__\9`
-M"`1$B&`@#[94)`^(4"%(BQ-(B5`02(M3"$B)4!A)B<5(B40D,$B+$/Z"L`D`
-M``^VLK`)``")\4B+1"0X2"G02(/H4$C!^`-(N\W,S,S,S,S,2`^OPXB$2K`)
-M``!!#[9%"XB$2K$)``!!B'4+28M5`/Z"L`D```^VLK`)``")\4B+1"1`2"G0
-M2(/H4$C!^`-(#Z_#B(1*L`D``$$/MD4+B(1*L0D``$&(=0M(BWPD*$B+%_Z"
-ML`D```^VLK`)``")\4R)Z$@IT$B#Z%!(P?@#2`^OPXB$2K`)```/MD<+B(1*
-ML0D``$"(=PL/MEU'3HUD-'!(B>_HG\7__\9`"`2(6"!$B'@A28L4)$B)4!!)
-MBU0D"$B)4!A)B<5(BQ#^@K`)```/MK*P"0``B?%(BT0D.$@IT$B#Z%!(P?@#
-M2+O-S,S,S,S,S$@/K\.(A$JP"0``00^V10N(A$JQ"0``08AU"TB+?"0H2(L7
-M_H*P"0``#[:RL`D``(GQ3(GH2"G02(/H4$C!^`-(#Z_#B(1*L`D```^V1PN(
-MA$JQ"0``0(AW"T'_QT0X?48/AQW]__](B>Y(BWPD2.C`VO__N`````!(@<1X
-M`0``6UU!7$%=05Y!7\-F9I!F9I!F9I!!5T%6055!5%532(/L&$F)_8._/%@`
-M``,/AQ(!``!(C8?`5P``2#F'P%<```^$_@```$F)QTR+M\!7``!(C8>P5P``
-M2(E$)!!,B7PD"&9FD$R)\TV+-DB+4PA)B58(3(DR2(D;2(E;"$B+0SCV0`$$
-M=7Y)B=R]`````(![1@!V'XGH#[;X2,'G!$J-O"?P"@``Z`K#____Q4$X;"1&
-M=^%)BX6P5P``2(E8"$B)`TB+1"002(E#"$F)G;!7``!(BT,X2(-X0`!T6$B+
-M4$A(BW!`3(GOZ`````!(BT,X2,=`0`````!!_XU`6```ZS-F9I!(B=Y,B>_H
-MY=O__X7`=#%)BX7`5P``2(E8"$B)`TB+1"0(2(E#"$F)G<!7``!F9I!-.?X/
-MA2?___]F9F:09F:02(/$&%M=05Q!74%>05_#D%532(/L"$B+7Q"#NSQ8````
-M=1!(C8/`5P``2#F#P%<``'0W2(VKP%<``&9FD&9FD$B)W^@`````2(G?Z```
-M``!(B=_H`````(.[/%@```!UWT@YJ\!7``!UUK@`````2(/$"%M=PV9F9I!F
-M9I!F9I!33(M/$$F+B<!7``!)C8'`5P``2#G(#X1^````28G"D$@Y>3AU;$F)
-MR+L`````@'E&`'9"#[;#2,'@!$P!P$B-D/`*``"^`````(.X\`H```!U$H-Z
-M!`!U#(-Z"`!U!H-Z#`!T!;X!````A?9U&__#03A81G>^N`````"%P'03N`$`
-M``#IN````+@!````9I#KZ4B+"4DYRG6&28N)T%<``$F-@=!7``!(.<@/A(L`
-M``!)B<%(C4'P2#EX.'5R2(G&NP````"`>$8`=DAF9F:0#[;#2,'@!$@!\$B-
-MD/`*``!!N`````"#N/`*````=1*#>@0`=0R#>@@`=0:#>@P`=`9!N`$```!%
-MA<!U%__#.%Y&=[RX`````(7`=!.X`0```.L=N`$```#K[F9FD&:02(L)23G)
-M#X5X____N`````!;PV9F9I!F9I!F9I!F9I!(B5PDX$B);"3H3(ED)/!,B6PD
-M^$B#["A(B?M)B?5)B=1(BV\02(-_0`!U">A__O__A<!U#4R)YDB)[T'_U6:0
-MZQ9,B6M`3(EC2/^%0%@``$B)[^@`````2(M<)`A(BVPD$$R+9"083(ML)"!(
-M@\0HPV9F9I!F9F:09F9FD&9FD%532(/L"$B)_4B)\X!^&0!U!,9&&0$/MD,9
-M/`$/E<(\!@^5P`^VTH70=!6`>QD#=`_V0Q@@=0G&0QD+9F:09I!(BW-(2(GO
-MZ/2___](BW,P2(G:2(GOZ`````!(BP-(@W@H`'0;2(U0*$C'Q@````!(B>_H
-M`````.M<9F:09F:02(.]2%@```!T*$B-A;!7``!(.86P5P``=!A(C95(6```
-M2,?&`````$B)[^@`````ZR2!O3A8``#_````=QA(C86P5P``2#F%L%<``'4(
-M2(GOZ`````!(@\0(6UW#9F:005=!5D%505154TB![$@!``!(B70D*$F)U(E,
-M)"1,BT8X28L`2(D$)`^V4'#_RHE4)!1!#[=`#&:)1"0B08N0@````(E4)!Q%
-M#[9P?D$/MD!_B40D$$4/M[B&````00^WF(0```!)@W@@`'0-9D$/MD`8@^`!
-M.<AU,KH`````28-X*``/A!0"``!,C6PD,(M,)"1,B>I,B<9!_U`HN@````"%
-MP`^$]`$``.L$38MH(+T`````2(M4)"A(BP(/MD`#B40D#+D`````9F9FD&9F
-MD`^WPP-$)!R)1"081#MT)`P/A04!``"%R711*<B)P\'C"71(@WPD)`!T"4B+
-M!0````#K#$B+/0````#H`````$F)!"1F0<=$)`H``('[`!````^&L0```&9!
-MQT0D"``028/$$('K`!```'6X00^WQXG#P>,)00^W50B%TK@```$`#T30B=`I
-MZ#G8<BV)Z$D#10!)B00D9D&)7"0(9D''1"0*``!)@\00`=TYU74]O0````!)
-M@\40ZS*)Z$D#10!)B00DB=!F*>AF08E$)`AF0<=$)`H``$F#Q!")T"GH*<-)
-M@\40O0````#KBD$/M\\#3"082(M4)"@/MT(,`T((.<@/A+H```#K2&9!B5PD
-M"$F#Q!#I5/___P'=ZS5!#[??P>,)00^W50B%TK@```$`#T30B=`IZ#G8=]Z)
-MT"GH*<-)@\40O0````#KV&9FD&9FD&9$*7PD(G1HNP````!!_\9$.W0D$`^4
-MP`^VP$$!QDB+%"0/MD)P1#GP=26+1"00_\B#?"00``]$1"04B40D$(7`#Y3`
-M1`^V\`^W0GP!1"0<2(L$)$0/MWA\9D0[?"0B#X9+_O__1`^W?"0BZ4#^__]F
-M0<=$)/H`@+H!````B=!(@<1(`0``6UU!7$%=05Y!7\-F9F:09F9FD&9F9I!F
-M9I!(B5PD\$B);"3X2(/L&$B)_4B+7CB`?AD!=`</MD89B$,92(GOZ``````/
-MMD-]_\"(0WTZ0WQU.(![&0!U!,9#&0$/MD,9/`$/E<(\!@^5P`^VTH70=`J`
-M>QD#=`3&0QD+2(G>2(GO_U,P9F:09F:02(M<)`A(BVPD$$B#Q!C#D$%7059!
-M54%455-(@^P82(E\)!!)B?5(BP9(B40D"/9&&`0/A-4!``!!O@````"`?G@`
-M#X18`0``26/&38M$Q5!!#[:H8`P``$$XJ&$,```/@BH!``!!.&A'#X01`0``
-MB>H/ML)(B<)(P>($3HV4`O`*``!!#[>4@$`,``!!#[>\@$(,``"[`````$&[
-M(````$&\`0```(/Z'W=&#[;#28TT@D2)V2G1.?D/1\^#^2!U#\<&_____^L4
-M9F9FD&9FD$2)X-/@_\B)T=/@"09$B=@IT#GX<Q6-?!?@N@````#K`X/J(/_#
-M@/L#=JN)ZP^VPTB)PDC!X@1.C90"<`L``$$/MY2`0`P``$$/M[R`0@P``+L`
-M````0;L@````0;P!````@_H?=S\/ML-)C32"1(G9*=$Y^0]'SX/Y('4(QP;_
-M____ZPU$B>#3X/_(B='3X`D&1(G8*=`Y^',5C7P7X+H`````ZP.#ZB#_PX#[
-M`W:R_\5!.*AA#```#X/6_O__0?_&00^V17A$.?`/CZC^__](BUPD$(.[J%<`
-M```/A&(#``!!O@````!!@'UX`'0\2(G:2('"P%<``$ECQDV+1,502<>`,`P`
-M``````!(BT((3(E""$F)$$F)0`A,B0!!_\9!#[9%>$0Y\'_.3(GN2(M\)!#H
-MZ/G__^DS`P``]D88`@^$_0(``$B+1"002`506```2(D$)$R+?"0028''<%@`
-M`$B+5"0(]D)^`P^%TP(``+H0````O@````!,B?_H`````$&^`````$&`?7@`
-M#X3_````26/&38M$Q5!,B<>Y`````$&`>$8`=DP/ML%(P>`$2`'X2(V0\`H`
-M`+X`````@[CP"@```'42@WH$`'4,@WH(`'4&@WH,`'0%O@$```"%]G0+N`$`
-M``#K$&9F9I#_P3A/1G>TN`````"%P&:0#X4^`@``00^VJ&`,``!!.*AA#```
-M<FM!.&A'=%J)Z0^VT69!@SQ7`'4D00^WA)!`#```00-`0$B+'"2)!)-!#[>$
-MD$(,``!F08D$5^LIB>@/MM!!#[>$D$`,``!F00-`0&9!`X200@P``$B+#"1F
-M*P219D&)!%?_Q4$XJ&$,``!SE4'_QD$/MD5X1#GP#X\!____28MU2$B+?"00
-MZ+^X__]!O@````!!@'UX``^$X````$B+3"002('!L%<``$ECQDV+1,50187V
-M=5Y!BT!`08F%@````$$/MH!@#```08A%?D$/MD!'08A%?TD/MH!@#```00^W
-MA(!`#```9D&)A80```!)#[:`8`P``$$/MX2`0@P``&9!B86&````0<9%?`!!
-MQD5]`.M&08M00$$[E8````!V.4B+7"0(#[=#?/?8(<)!(X6`````.<)U(4D/
-MMI!@#```00^WA88```!F00.$D$(,``!F08F%A@```$B+00A,B4$(28D(28E`
-M"$R)`$'_QD$/MD5X1#GP#X\L____2(M$)!!(@[A(6````'092(G"2('"2%@`
-M`$C'Q@````!(B<?H`````+T`````2(M4)`B`>G``#X:B````B>E$#[;A9D.#
-M/&<`=%E(BT0D"$J+G."(````2(M\)!#H`````$B)QD'^17S&0`X@0P^W!&=F
-MB48,2(L4)$*+!**)1@B`3A@"2,=&*`````!(QT8P`````$B)'DR);CA(BWPD
-M$/]38/_%2(M,)`A`.&EP=XSK+$&^`````$&`?7@`=!])8\9)BW3%4$B+?"00
-MZ!W0__]!_\9!#[9%>$0Y\'_A2(/$&%M=05Q!74%>05_#D$%7059!54%455-(
-M@^Q82(E\)$A)B?=(B50D0$B+!DB)1"0XO@`````/MU!\9H'Z@0"X@`````]#
-MT&:)5"0@0?9'&"!T0`^WRDB+7"1`BU,(2(MT)#CH1KK__TB)QKC_____2(7V
-M#X1K`P``0<9'>`%)B7=03(F^,`P``+@`````Z5$#``!(BT0D0`^V4!)(B<&+
-M`(G3N@````#W\T&)UDB+1"0X#[90<(M!!(G1N@````#W\4B+7"1`#[9#$BC0
-MB$0D'T$XQD&`WO](BT0D.`^W4'R-0O\/MTL,(<%!B=1F02G,9D0Y8Q!S!40/
-MMV,00<9'>`!!QD=Y`,=$)!@!````#[=$)"#WV(E$)!0/M\%!B<5(BU0D0$0#
-M:@A(BTPD2$B!P<!7``!(B4PD"$B+7"1(2('#L%<``$B)'"1F9F:0BT0D(/_(
-M1"'HBUPD(&8IPV9$.>-!#T?<BVPD%$0A[8-\)!@`#X1>`0``QT0D&`````"+
-M5"0@2(M$)#AF.5!\=BBZ`````$$/MD=XB<&#^`!^%TACPDF+=,=0.6Y`#X0E
-M`0``_\(YT7_I#[=,)"")ZDB+="0X2(M\)$CHX;C__TB)QDB%P`^%U0```$'^
-M3WA!@']X_P^$M0```$R+5"0(3(L,)$D/MD=X28MTQU!(QX8P#````````$F)
-M\+D`````@'Y&`'9$#[;!2,'@!$P!P$B-D/`*``"_`````(.X\`H```!U$H-Z
-M!`!U#(-Z"`!U!H-Z#`!T!;\!````A?]FD'4E_\%!.$A&=[RX`````(7`=!M)
-MBT((28ER"$R)%DB)1@A(B3#K&;@!````Z^%)BT$(28EQ"$R)#DB)1@A(B3!!
-M_D]X08!_>/\/A53___^X_____^D]`0``9F9FD&9FD$$/MD=X#[;028ETUU#_
-MP$&(1WA,B;XP#```QH9@#```",:&80P```!$B?$/MM%$B>AF*>AFB8260`P`
-M`&:)G)9"#```1#BV8`P``'8'1(BV8`P``$0XMF$,``!S!T2(MF$,``!(BT0D
-M0&8I6!!F02G<=!,/M\-!`<7'1"08`0```.D:_O__2(M4)$!F@WH0``^$FP``
-M`+D`````0?_&1#IT)!\/E,!!`<9(BUPD.$0X<W!U/H!\)!\`=`;^3"0?ZPU(
-MBT0D0`^V0!*(1"0?@'PD'P!!#Y3&2(M4)#@/MT)\2(M<)$`!0PC'1"08`0``
-M`.L;BU0D($B+1"0X9CE0?+@!````#T9$)!B)1"082(M<)$!$#[=C$$B+1"0X
-M9D0[8'P/AD7]__]$#[=@?.D[_?__N`````!(@\186UU!7$%=05Y!7\-F9F:0
-M9F9FD&9FD$B#[`B%TG08QD89"TB)\DC'Q@````#H`````.L(9F:0Z*OV__](
-M@\0(PV9FD&9FD$%455-(@^P@28G\2(GU2(L>]D,!!'49QD89`DB+=C!(B>KH
-M`````.DT`@``9F9FD$B#>U``=2F^!P```&9F9I#H.Z___TB)QTB)0U"Z`!``
-M`+X`````Z`````!F9I!FD`^V11BH(`^%N````*@&=1C&11D!2(MU,$B)ZDR)
-MY^@`````Z=@!``#V11@$="=(@WM``'0@2(M32$B+<T!,B>?H`````$C'0T``
-M````0?^,)$!8``"+?0B)?"0,#[=%#&:)1"00#[9#</_(B$0D$@^V2W*)^-/H
-MB00D#[9T)!*Z`````/?VB40D!`^V2W+3X(E$)`@/MTM\#Z_.#[=$)!"-/#@/
-MKW0D""GWC7P/_XGXN@````#W\8G!#[=#?(G/#Z_XZRSV0WX!=!C&11D&2(MU
-M,$B)ZDR)Y^@`````Z1X!```/MWM\B?@/KT4(B40D"(M4)`B-#!=(B=Y,B>?H
-MSK'__TB)14A(A<!U&4C'14@`````2(U[*$B)[N@`````Z=P```!(B>)(B>Y,
-MB>?H3OK__X7`#X2&````2(MU2$R)Y^@:L?__08N,))A$``!!.8PDG$0``'1&
-M2&/!2,'@!$J!O""((@```````'1M_\%(8\%(:<#APW_P2,'H((T$`8G&P?X)
-MB<B9B?`IT&G`(0(``"G!03F,))Q$``!UNDC'14@`````28V\)$A8``!(B>[H
-M`````$R)Y^@`````ZT#V11@$="E(Q\(`````2(GN3(GGZ!BU___K)L9%&05(
-MBW4P2(GJ3(GGZ`````#K$4B)[DR)Y^A&]/__9F:09F:02(/$(%M=05S#9F9F
-MD&9FD%532(/L"$B)_4B)\TB#?E``=%%(B??H`````+D`````2&/12(M#4$B+
-M!-!(A<!T$4C'0"``````2(M`*$B%P'7O_\&!^?\!``!VU4B+<U"Z!P```$B)
-M[^C4K/__2,=#4`````!(@\0(6UW#9F:09I!!5%532(G[QX>H5P```````$B-
-MA[!7``!(B8>P5P``2(F'N%<``$B-A\!7``!(B8?`5P``2(F'R%<``$B-A]!7
-M``!(B8?05P``2(F'V%<``(L%`````,'@#(G"N*NJJJI(#Z_"2,'H($&)Q$'!
-M[`]$B>*^:`P``.ADK/__B<5!C50D(+X8````2(G?Z%"L__\!Q8L5`````,'B
-M#,'J#KZ(````2(G?Z#6L__\!Q;H(````O@`0``!(B=_H(:S__P'%2(G?Z```
-M``!(B04`````_\4[+0````!S-V9FD&9FD$B)W^@`````2(G"2(7`="%(BX,P
-M6```2(D"2(F3,%@``/^#.%@``/_%.RT`````<L];74%<PV9F9I!F9I!F9I!5
-M4TB#[`A(B?5(BUX(#[9.`[@!````B<+3XH!F`?O'@X0`````````]D-^`G02
-M9H.[@`````!T&^L09F:09F:09H.[@`````!T-F:%DX````!U+68)DX````"`
-M8P'[2(-[:`!T"TB)WO]3:&9FD&:0@&-^'^G'````9F9FD&9FD`^V0WYFB9.`
-M````_DMQQX.$`````````(/(!8A#?H3`>0Z#X'^(0W[IDP```&9FD(!C?I](
-MB=[H`````$B)PDB%P'1:Q@`##[9%`XA"`TB)6@B`2@$(2(L%`````$B)0F!(
-MBP4`````2(E":$C'10@`````2`^V0@-(B93#B`````^V0WZ#X/Z#R`J(0W[^
-M0W%(B=:_!P```.@`````2(-["`!T"TB+6PA(@WL(`'7UZ`````")0W1(B=_H
-M`````$B#Q`A;7<-F9I!F9I!F9I"Z`````/_.@_[_=!-F9F:0#[8'`<)(_\?_
-MSH/^_W7Q#[;"PV9F9I!F9I!F9I!F9I!54TB#[`A(B?N`/P-V6+T`````@']P
-M`'1'9F9FD&9FD$AC]4B#O/.(`````'0H2(N,\X@````/ME,!@^(!#[9!`8/@
-M_@G0B$$!2(N\\X@```#H`````/_%#[9#<#GH?\"`8W[[ZPKH%0```&9FD&:0
-M2(/$"%M=PV9FD&9FD&9FD$%505154TB![`@"``!)B?Q!O0````!(B>.`?W``
-M#X1)`@``2(MO"$B%[70.2(-]"`!T!TF)[4B+;0BZ``(``+X`````2(G?Z```
-M``#'`_,6>%JX`````$B%[70#BT5TB4,$08!\)'@`=`V`2PD"00^V1"1[B$,*
-M00^V5"1TO@$````AU@^V@Y,```"#X/R)T8/A`@GP"<B^!````"'6@^#SB=&#
-MX0@)\`G(OA`````AUH/@SXG1@^$@"?`)R(G1@^%`@^`_@^*`"<@)T(B#DP``
-M`$'V1"0!`70$@$L)`;@`````2(7M=`E)@_T!&<"#P`*(0PM(A>T/A+P```"+
-M11B)0PS'@Y0`````````#[9%`(A#$`^V17"(0Q%-A>UT!T$/MD4#ZPE!#[9$
-M)`-F9I"(0Q(/MD5RB$,3]D5^`G0$@$L4`0^WA8````!FB4,6BX6$````B4,8
-MQX.8`````````$B-M<@```!(C7LLNA````#H`````$B-M=@```!(C7L\N@0`
-M``#H`````$B-M1P!``!(C;N`````NA````#H`````$B-M=P```!(C7M`ND``
-M``#H`````$V%[71=08M%&(E#',>#G`````````!!#[9%`(A#($$/MD5PB$,A
-M00^V1"0#B$,B00^V17*(0R-!]D5^`G0$@$LD`4$/MX6`````9HE#)D&+A80`
-M``")0RC'@Z``````````2(7M=0A!#[8$)(A#$+Z0````2(G?Z`````#WV(A#
-M"+X``@``2(G?Z`````#WV(B#D````$&+M"2(````@^X*28U\)'!(B=FZ,```
-M`.@`````2('$"`(``%M=05Q!7<-F9I!F9I!(B?B`/P-V.+H`````@']P`'08
-M#[9/<$ACPDB#O,>(`````'4,_\(YT7_LN`````##2(N\QX@```#H`````&:0
-M\\-F9F:09F9FD&9FD&9FD%532(G[@#\#=C:]`````(!_<`!T+TACQ4B#O,.(
-M`````'0-2(N\PX@```#H`````/_%#[9#<#GH?]OK"&9F9I"`9P'^6UW#9F:0
-M9F:09F:02(M/$+H`````9F9FD&9FD(G02#D\P74)2,<$P0````##_\*#^@=V
-MZ//#9F:09F:02(GW@&8!^^@`````\\-FD$%505154TB![`@$``!)B?Q(C9PD
-M``(``$B)_0^V1P&H!`^$+P$``(`_`@^&)@$``(/@_8A'`;H``@``O@````!(
-MB=_H`````$&`/"0##X2+````2(G@2(NMB````$&`/"0(=7!(A>UT#&9!@[PD
-M@`````%U7TB)Q4&]`0```$$/MD0D<(/X`7YK26/%28N\Q(@```!(@\=P2(GI
-MNB````"^`````.@`````N0````"02&/1BP23,T25`(D$D__!@_E_?NQ!_\5!
-M#[9$)'!$.>A_M^L@@'T``P^%>/___TB-?7!(B=FZ(````+X`````Z`````!F
-M@;O^`0``5:IU5X.[R@$```!T'8%[!DQ)3$]T#(&[=@$``$=254)U"$&`3"0!
-M`NLQ0;T`````26/%2,'@!$@!V("XO@$``(!U#X.XR@$```!T!D&`3"0!`D'_
-MQ4&#_0-^U4B!Q`@$``!;74%<05W#9F9FD&9F9I!F9F:01(N'A"(``$6-2`%)
-M8\%(:<#APW_P2,'H($&-!`'!^`E$B<G!^1\IR&G`(0(``$$IP4UCP$G!X`1)
-MB70X<$ACAX0B``!(P>`$2(E4.'A$B8^$(@``PV9F9I!F9F:09F:04TB#[!!(
-MB?N+AX`B```[AX0B``!T8HN+@"(``$ACP4C!X`1(`=A,BT!P3(D$)$B+<'A(
-MB70D"/_!2&/!2&G`X<-_\$C!Z""-!`&)Q\'_"8G(F8GX*=!IP"$"```IP8F+
-M@"(``$B)WT'_T(N#@"(``#N#A"(``'6>2(/$$%O#9I!$BX><1```18U(`4EC
-MP4AIP.'#?_!(P>@@08T$`<'X"42)R<'Y'RG(:<`A`@``02G!36/`2<'@!$F)
-MM#B((@``2&.'G$0``$C!X`1(B90XD"(``$2)CYQ$``##9F:09I!32(/L$$B)
-M^XN'F$0``#N'G$0```^$@P```&9FD&9FD(N+F$0``$ACP4C!X`1(C808@"(`
-M`$B+4`A(B10D2(M`$$B)1"0(_\%(8\%(:<#APW_P2,'H((T$`8G&P?X)B<B9
-MB?`IT&G`(0(``"G!B8N81```@[L\6````'0(2(G?Z`````!(BW0D"$B)W_\4
-M)(N#F$0``#N#G$0``'6#2(/$$%O#9F9FD&9FD&9FD&9FD%.X`````$B#?V@`
-M="!(BU]H2(L#2(E':+J(````O@````!(B=_H`````$B)V%O#D$B+1VA(B09(
-MB7=HPV9F9I!(@S\`=!I(BP=(BT!`2(E&0$B+!TB)<$#K"F9FD&9FD$B)=D!(
-MB3?#9F9FD&9F9I!(B5PDX$B);"3H3(ED)/!,B6PD^$B#["A)B?U(B?5(@SX`
-M=#U,BR9(BT4`2(M80$@YV'4,2,=%``````#K#F:02(M5`$B+0T!(B4)`2(G>
-M3(GO_U-(3#GC=`=(@WT``'7&2(M<)`A(BVPD$$R+9"083(ML)"!(@\0HPV9F
-MD&9FD$B#[`B`/PAU!^@`````9I!(@\0(PV9F9I!F9F:09F:02(/L"$B)\4B+
-M1Q"`/PAU!^@`````ZPM(B=9(B<=F9I#_T4B#Q`C#9F:09F:09F:02(E<)-!(
-MB6PDV$R)9"3@3(EL).A,B70D\$R)?"3X2(/L:$&)]$F)ST&)U4B+;S!$#[8W
-M00^VWHG>2(GOZ`````"Z`````(G>2(GOZ`````#'!"0`````0;D`````0;@`
-M````N0````"Z`P```(G>2(GOZ`````"Z`````(7`#X2U````0??$````\`^5
-MP`^VR$&`_3`/E,!$#[;00?_"00^V]D$/ML6%R70108#](+HT````N"0````/
-M1<*)1"0PN$````"%R74)1(G@P>@8@\A`B40D*$2)Y\'O$$`/ML>)1"0@3(GB
-M#[;&B40D&$$/MM0/M\*%R70)B?@E`/\```G0B40D$,=$)`@!````QP0D````
-M`$&Y``$``$V)^$2)TDB)[^@`````B<-!#[;V2(GOZ`````")VHG02(M<)#A(
-MBVPD0$R+9"1(3(ML)%!,BW0D6$R+?"1@2(/$:,-FD(GX@^`#P>`-!0`@``!`
-M]L<$=`T%```#`,-F9F:09F:0!0```@##9F9FD&9FD&9FD$%455-)B?R)];\@
-MH0<`Z`````"[(*$'`$`/MOWHK____XVH'`$``$F+?"00B>[H`````(3`>`FX
-M`0```.L?9I"_$"<``.@`````@<,0)P``@?L_2TP`=L^X`````%M=05S#9F9F
-MD&9F9I!F9I!F9I!(B5PD\$R)9"3X2(/L&$F)_$`/MO[H1O___XG#C7,(28M\
-M)!"Z`````.@`````C7,,28M\)!"Z&`$``.@`````2(M<)`A,BV0D$$B#Q!C#
-MD%-(B?M`#[;^Z`/___^-<`Q(BWL0N@````#H`````%O#B?!FA<EU#O?"````
-M\'4&9JD`_W0+N`$```##9F:09I!FA?8/E,"#_P$/E,(/ML"%P@^5P`^VP,-F
-M9F:09F9FD$F)T;H`````3(U'"HM!$(D'BT$4B4<$@SD`N`$````/1-!!#[9!
-M!`'`"<)FB5<(BX9$`@``A<`/E,*#^`(/E,`)T*@!#X1F`0``@WD$`0^%W```
-M`&8/MD$/@,P19D&)`$F#P`)F#[9!#H#,$69!B0!)@\`"00^V003!X`-F)?@`
-M@,P29D&)`$F#P`)F#[9!"X#,$V9!B0!)@\`"9@^V00B`S!-F08D`28/``F8/
-MMD$,@,P49D&)`$F#P`)F#[9!"8#,%&9!B0!)@\`"9@^V00V`S!5F08D`28/`
-M`F8/MD$*@,P59D&)`$F#P`)F0<<`0!9)@\`"@SD`=1F#OD0"```"NB8```"X
-M8`````]%PNF@`0``@[Y$`@```KHV````N&$````/1<+IAP$``&9F9I!F#[9!
-M#H#,$69!B0!)@\`"00^V003!X`-F)?@`@,P29D&)`$F#P`)F#[9!"(#,$V9!
-MB0!)@\`"9@^V00F`S!1F08D`28/``F8/MD$*@,P59D&)`$F#P`*+00@E````
-M#\'H&&8-0!9F08D`28/``H,Y`1G`@^#[@^@TZ04!``!FD(-Y!`$/A9<```!F
-M#[9!#X#,$F9!B0!)@\`"9@^V00Z`S!)F08D`28/``F8/MD$+@,P39D&)`$F#
-MP`)F#[9!"(#,$V9!B0!)@\`"9@^V00R`S!1F08D`28/``F8/MD$)@,P49D&)
-M`$F#P`)F#[9!#8#,%69!B0!)@\`"9@^V00J`S!5F08D`28/``F9!QP!`%DF#
-MP`*#.0$9P(/@\(/`->MB9@^V00Z`S!)F08D`28/``F8/MD$(@,P39D&)`$F#
-MP`)F#[9!"8#,%&9!B0!)@\`"9@^V00J`S!5F08D`28/``HM!""4````/P>@8
-M9@U`%F9!B0!)@\`"@SD!&<"#X/Z#Z#9F#[;`9@T`EV9!B0##2(E<)-!(B6PD
-MV$R)9"3@3(EL).A,B70D\$R)?"3X2(/L2(GPB50D%$B)S4R+;Q`/ML!(BT3'
-M,$2+<#Q!C;8$`0``3(GOZ`````"(10!!C88(`0``B40D$(G&3(GOZ`````!F
-M#[;`9HE%`D&-G@P!``")WDR)[^@`````9@^VP&:)101%C:80`0``1(GF3(GO
-MZ`````!F#[;`9HE%!D6-OA0!``!$B?Y,B>_H`````&8/ML!FB44(@WPD%`$/
-MA88```!!C88@`0``B40D"(G&3(GOZ`````"(1"0/B<*#RH`/MM*+="0(3(GO
-MZ`````"+="003(GOZ`````#!X`AF"44"B=Y,B>_H`````,'@"&8)101$B>9,
-MB>_H`````,'@"&8)109$B?Y,B>_H`````,'@"&8)10@/ME0D#XMT)`A,B>_H
-M`````$&-MA@!``!,B>_H`````(A%"D&-MAP!``!,B>_H`````(A%"TB+7"08
-M2(ML)"!,BV0D*$R+;"0P3(MT)#A,BWPD0$B#Q$C#D$B)7"302(EL)-A,B60D
-MX$R);"3H3(ET)/!,B7PD^$B#[&A)B?^)\V:)5"0>#[;#3(MTQS!!BW8\@\8P
-M2(M_$.@`````2(G%@^4?2(U$K0!(P>`$2HVL,%`"``"#?0`!=%U(C44@2(E$
-M)!!,C60D((M0!$0/MNM,B>%$B>Y,B?_H[/W__T'^CF4,``!(BUPD$$B+2R!)
-MBWXP3(DD)$&Y`````$0/MT0D'KH!````1(GN_U,82(GN3(GWZ!(3``!(BUPD
-M.$B+;"1`3(MD)$A,BVPD4$R+="183(M\)&!(@\1HPV9F9I!F9F:09F9FD&9F
-MD$B)7"302(EL)-A,B60DX$R);"3H3(ET)/!,B7PD^$B#[&A)B?]!B?7'1"04
-M`````(GQ#[;!2(MLQS!!O@`````/MP)FB40D&$B-3"08#[="`F:)00*+0@2)
-M000/MT0D&$B)PX/C'TB-!)M(P>`$2(V<*%`"```/MT$"A,!T*L=$)!0!````
-M#[=!`D0/MO!F08'.``''A6`,````````QX5``@```````$R-8R!(C40D&`^W
-M0`*H!'072(U,)"!!BU0D!$$/MO5,B?_HL?S__Y"#.P$/A)<```#^C64,``!(
-MC40D&$2+2`1)BTPD($4/MNU(BWTP2(U$)"!(B00D10^WQHM4)!1$B>Y!_U0D
-M&$B)WDB)[^C'$0``@[U@#````'1.2(.]4`P```!T1$B+A5`,``"#>!@!=3=$
-MB>Y,B?_HW!,``$B+M5`,``!(B>_H#14``(7`=1E(B[50#```N@````!(B>_H
-M]08``&9FD&:02(M<)#A(BVPD0$R+9"1(3(ML)%!,BW0D6$R+?"1@2(/$:,-F
-M9F:09F:09F:09F:02(E<).!(B6PDZ$R)9"3P3(EL)/A(@^PH2(G[B?5!B=5(
-MBW\0OBP-``#H`````$&)Q(G"@\H!2(M[$+XL#0``Z`````!(BWL0OBP-``#H
-M`````$B+>Q"^\`0!`.@`````B>KWTB'01`GH2(M[$(G"OO`$`0#H`````$B+
-M>Q"^\`0!`.@`````2(M[$$2)XKXL#0``Z`````!(BUPD"$B+;"003(MD)!A,
-MBVPD($B#Q"C#9F9FD&9F9I!F9F:09F:02(E<)-!(B6PDV$R)9"3@3(EL).A,
-MB70D\$R)?"3X2(/L2$F)_D&)S$2)3"042(M'$$B)1"0(QT0D!`````!$C3RU
-M`````$$)UT2)^@^VPDR+;,<P187`=')-A>T/A-<```!!BYWP#```0HT4Y0``
-M``!!"U4L08MU/(/&)$B+?"0(Z`````!$.>-T(T$/MN^0B=I)BT482(T4T(GN
-M3(GWZ/S\____PX/C'T0YXW7B08.]8`P```"X`0````]%1"0$B40D!$&)G?`,
-M``"#?"04``^5PH-\)`0`#Y7`"="H`0^$^P$``$$/MO_H(O;__T2-8`A$B>9(
-MBWPD".@`````B<4/M]B)VO?21(GF2(M\)`CH`````/;#"`^$(0$``$V%[706
-M0<>%8`P```````!!QX5``@```````$&#OI`````!=`I!@[Z4`````744O@`!
-M``!$B?G3YHGR3(GWZ-_]__]!@[Z,`````70408.^D`````%T"D&#OI0````!
-M=0Y!#[;W3(GWZ*4)``#K?T&#OH@````!=`I!@[Z,`````75K00^VWXG?Z&3U
-M__]$C6`HN@0```!$B>9(BWPD".@`````1(GF2(M\)`CH`````+\9````Z```
-M``"Z`````$2)YDB+?"0(Z`````!$B>9(BWPD".@`````O]`'``#H`````(G>
-M3(GWZ.0'``!!#[;?B=_H^?3__XVP'`$``$B+?"0(Z`````")V;H`````O@$`
-M``!,B?=!_U8HZ:$```!`]L40=%)!#[;W3(GW9F9FD.B;!P``08.^D`````%T
-M"D&#OI0````!=1>^``$``$2)^=/FN@````!,B??HP/S__T$/ML^Z`0```+X!
-M````3(GW0?]6*.M)#[?5]L8!=$%!@[U``@```74B0<>%8`P```````!!QX5`
-M`@```````$$/MO=,B??HY?G__X,]``````%U#$R)[^C4$```9F9FD$B+7"08
-M2(ML)"!,BV0D*$R+;"0P3(MT)#A,BWPD0$B#Q$C#9F9FD&9FD&9FD&9FD$B#
-M[`A)B?B-#+4`````"=$/ML%(BWS',$B%_W43#[;Q3(G'Z'@.``#K2V9FD&9F
-MD$B+MU`,``!(A?9U%`^V\4R)Q^A9#@``ZRQF9F:09F:0@SX!=`V#?A@!9F9F
-MD&9FD'0.#[;Q3(G'Z#,.``#K!I#H"P```$B#Q`C#9F:09F:02(E<)-!(B6PD
-MV$R)9"3@3(EL).A,B70D\$R)?"3X2(/L.$F)_DF)]TB+1S!,BV`0BV\\0;T#
-M````1"(O#[8?@^,$P>L"C;4@`0``3(GGZ`````"-M1P!``!,B>?H`````(G%
-MN@`!``!$B>G3XO?2@/L!&?9FO@``@<84``,`3(GGZ`````!`A.T/B/$```!`
-M]L4!=!NZ`0```$R)_DR)]^C+`0``Z=8```!F9I!F9I!!BT<@@_@!="R#^`%F
-M9F:0<@Z#^`)T<NFT````9F9FD+H`````3(G^3(GWZ)`!``#IFP```$#VQ4!T
-M/$F-=R!,B??HN0```(/X`74908-_,`!U?;H`````3(G^3(GWZ%T!``#K:[H!
-M````3(G^3(GWZ$L!``#K6;H!````3(G^3(GWZ#D!``#K1T`/ML6H0'0_J"!U
-M.T&#?S``=1*Z`````$R)_DR)]^@4`0``ZR))C7<@3(GWZ$8```"%P'42N@$`
-M``!,B?Y,B??H\@```&:02(M<)`A(BVPD$$R+9"083(ML)"!,BW0D*$R+?"0P
-M2(/$.,-F9F:09F:09F:09F:005154TF)_$B)\[@`````@7X0_P````^&GP``
-M`(L6@_H!=%BX`````(/Z`0^"B@```(/Z`@^%?````+T`````D$B+0P@/MQ!(
-M@\`"2(E#"$&+="0\@<8``0``28M$)#!(BW@0Z`````#_Q8']_P```';.@6L0
-M``$``.L[O0````!!BW0D/('&``$``$F+1"0P2(MX$.@`````2(M3"&:)`DB#
-M0P@"_\6!_?\```!VT8%K$``!``"X`0```%M=05S#2(E<)-A(B6PDX$R)9"3H
-M3(EL)/!,B70D^$B#[$A(B?U)B?1!B=5!O@````!(C5X@2(U,)!"+4P0/MC=(
-MBW\PZ-ST__]!@_T!=0U!M@''A6`,````````2(M+*`^V=0!(BWTP2(U$)!!(
-MB00D0;D`````0;@`````1(GR_U,@3(GF2(GOZ/<)``!!@_T!=1&#/0`````!
-M=0A(B>_H$`T``$B#O5`,````#X2C````2(NU4`P``(-^&`%U)DB)[^@]#0``
-MA<`/A88```!(B[50#```N@````!(B>_H(?___^MP@[U$`@```'4J#[9U`$B+
-M?3#HN0H``(MU/(/&*$B+13!(BW@0Z`````"_`0```.@`````#[9U`$B+?3#H
-MOPH``$B+G5`,``!(A=MT)(-[&`!U'DB-4R!(B=Y(B>_H_@L``$B+6PA(A=MT
-M!H-[&`!TXDB+7"0@2(ML)"A,BV0D,$R+;"0X3(MT)$!(@\1(PY!!54%455-(
-M@^P(2(G[2(M',$R+8!!$BV\\08UM*(GN3(GGZ`````"H!'0QN@(```")[DR)
-MY^@`````B>Y,B>?H`````+_0!P``Z``````/MC-(BWLPZ"8"``#K$4&-=2BZ
-M`@```$R)Y^@`````QH-(`@```,:#9`P```#&@V4,````QX/L#````````,>#
-M\`P```````#'@T`"````````QX/H#```(````+H`````D$ACPHF4@V@,``#_
-MPH/Z'W[ON@````!(8\)(C02`2,'@!,>$&%`"```!````_\*#^A]^XTC'@U`,
-M````````2,>#6`P```````#'@V`,````````08UU"+H`````3(GGZ`````!!
-MC74,NA@!``!,B>?H`````(M3($&-=1!,B>?H`````(M3)('B`/S__T&-=11,
-MB>?H`````$&-=1BZ`````$R)Y^@`````BU,H08UU'$R)Y^@`````08UU(+H`
-M````3(GGZ`````"+4RRR`$&-=21,B>?H`````+@!````2(/$"%M=05Q!7<-F
-M9I!FD$%7059!54%455-(@^PX2(G[B50D'$&)SX7V#X6B````O0````!,C70D
-M(&9FD&9FD$ACQ4B-!(!(P>`$2`'8@[A0`@```'5P2(V08`(``(-Z"`%U$XM2
-M%$R+H)@"``!,BZB0`@``ZR)(8\5(C02`2,'@!$@!V(N0=`(``$R+H)`"``!,
-MBZB(`@``#[8S2(M[,$R)\>AX\?__#[8S2(M[,$R)-"1!N0````!%#[?'3(GA
-MBU0D'$'_U?_%@_T?#XYN____2(/$.%M=05Q!74%>05_#9F9FD&9F9I!F9F:0
-M9F:02(E<).!(B6PDZ$R)9"3P3(EL)/A(@^PH2(G[B?6)Z(/@!$&)Q4'![0)!
-MO`,```!!(>R#OX@````!=`F#OXP````!=5I!#[;TP>8(@<8,`0``C88```,`
-M@<8```(`183M#T7P2(M[$.@`````B<&#X?R#R0%!#[;TP>8(@<8,`0``C88`
-M``,`@<8```(`183M#T7P2(M[$(G*Z`````!!#[;TP>8(@<9T`0``C88```,`
-M@<8```(`183M#T7P2(M[$.@`````B<&`X1^)Z`^VT`^VA!JF````P>`%)>``
-M```)P8#EYP^VA!JN````P>`+)0`8```)P4$/MO3!Y@B!QG0!``"-A@```P"!
-MQ@```@!%A.T/1?!(BWL0B<KH`````$B+7"0(2(ML)!!,BV0D&$R+;"0@2(/$
-M*,-F9I!F9I!(B5PDZ$R)9"3P3(EL)/A(@^P82(G[1`^V[D2)[^B^Z___1(U@
-M*$2)[DB)W^B?[/__2(M[$+H$````1(GFZ`````!(BWL01(GFZ`````"_&0``
-M`.@`````2(M[$+H`````1(GFZ`````!(BWL01(GFZ`````!$B>Y(B=_H0/[_
-M_T2)[DB)W^CUZ___2(L<)$R+9"0(3(ML)!!(@\08PV:005=!5D%505154TB#
-M[`A(B?W&1"0'`$&^``````^V1"0'1(T\A0````!F9F:09F:00XT$/D0/MNA$
-MB>_H`.O__T&)Q$&-7"0H2(M]$+H"````B=[H`````$B+?1")WN@`````1(GN
-M2(GOZ/+^__](BWT0N@````")WN@`````2(M]$+H?`0``1(GFZ`````!!C70D
-M!$B+?1"Z`````.@`````08UT)`A(BWT0N@````#H`````$&-="0,2(M]$+H`
-M````Z`````!!C70D$$B+?1"Z`````.@`````08UT)!1(BWT0N@````#H````
-M`$&-="082(M]$+H`````Z`````!!C70D'$B+?1"Z`````.@`````08UT)"1(
-MBWT0N@````#H`````$&-="0@2(M]$+H`````Z`````!!C70D+$B+?1"Z````
-M`.@`````08UT)#1(BWT0NKP```#H`````$'_QD&`_@,/AL/^__^`?"0'`1G;
-M9KL``('#```#`(US#$B+?1"Z`````.@`````C7,02(M]$+H`````Z`````"-
-M<Q1(BWT0N@````#H`````(US&$B+?1"Z`````.@`````@\,@2(M]$(G>Z```
-M```E'!P<'`T#`P,#2(M]$(G"B=[H`````/Y$)`>`?"0'`0^&(/[__TB#Q`A;
-M74%<05U!7D%?PV9F9I!F9F:09F:02(/L"$B+?Q"Z___/#[YL!`$`Z`````!(
-M@\0(PV9F9I!32(G[BT<$L``]``"`4'0A2(M_$+XL#0``Z`````"#R`%(BWL0
-MB<*^+`T``.@`````2(M[$+X`#0``Z``````E__\`_TB+>Q")PKX`#0``Z```
-M``!(BWL0N@````"^!`T``.@`````2(M[$+H`````OC@,``#H`````$B+>Q"Z
-M_P`!`+X$'0``Z`````!(BWL0N@````"^9!T``.@`````2(M[$+H`````OB@,
-M``#H`````$B+>Q"Z`````+Y8'0``Z`````!(BWL0N@````"^7!T``.@`````
-M2(M[$+H`````OD`=``#H`````$B+>Q"Z`````+Y$'0``Z`````!(BWL0N@``
-M``"^2!T``.@`````2(M[$+H`````OE`=``#H`````%O#9F:09F:09F:02,=&
-M"`````!(BX=8#```2(E&$$B#OU@,````=`M(BX=8#```2(EP"$B)MU@,``!(
-M@[]0#````'4'2(FW4`P``//#9F9FD&9F9I!F9I!F9I!(@WX(`'4:2(M&$$B)
-MAU@,``!(A<!T%DC'0`@`````ZPQ(BU8(2(M&$$B)0A!(@WX0`'4<2(M&"$B)
-MAU`,``!(A<!T&$C'0!``````ZPYFD$B+5A!(BT8(2(E""$C'1@@`````2,=&
-M$`````##9F:02(E<).A(B6PD\$R)9"3X2(/L&$F)_$B)]4B)TX,Z`'442(UR
-M"$B-?2"Z*````.@`````ZQI(C7((2(U](+HP````Z`````!!_H0D9`P``(L#
-MB4482(GN3(GGZ.'^___'10``````0?Z$)$@"``!(BQPD2(ML)`A,BV0D$$B#
-MQ!C#9F9FD&9F9I!F9F:09F:02(E<)/!(B6PD^$B#[!!(B?M(B?6#?A@`=`;^
-MCV0,``!(B>Y(B=_HU?[__XN#Z`P``(G!#[95!(F4BV@,``#_P(F#Z`P``,=%
-M``$```#^BT@"``!(BQPD2(ML)`A(@\00PV9F9I!F9F:09F9FD&9FD$"`_P-V
-M$4`/ML^-3`D"N`$```!(T^##0`^VSXU,"0&X`0```$C3X,-F9F:09F9FD%53
-M2(/L"$B)^T`/MNZ)[^B\____"8.`````B>_HS^7__XVP'`$``$B+>Q#H````
-M`(GI@^$#N@`!``#3XO?2B>B#X`3!^`*#^`$9]F:^``"!QA0``P!(BWL0Z```
-M``"+DX````!(BWL0OF0=``#H`````$B+>Q"^9!T``.@`````2(/$"%M=PV9F
-MD&9FD&9FD%-(B?M`#[;^Z#/____WT(G"(Y.`````B9.`````2(M[$+YD'0``
-MZ`````!;PV9FD$B)7"382(EL).!,B60DZ$R);"3P3(ET)/A(@^PH28G^B?-,
-MBV\0#[;#3(MDQS!!BVPD/$''A"1``@```0```(G8@^`$P>@"B=F#X0.Z`0$`
-M`-/B]](\`1GV9KX``('&%``#`$R)[^@`````08MT)#R#Q@BZ`````$R)[^@`
-M````#[;S3(GWZ$7___^-M1P!``!,B>_H`````$''A"1,`@```0```(UU*+H!
-M````3(GOZ`````!(BQPD2(ML)`A,BV0D$$R+;"083(MT)"!(@\0HPV9F9I!F
-M9F:09F:09F:02(E<).!(B6PDZ$R)9"3P3(EL)/A(@^PH2(G[08GU3(MG$(GR
-M#[;"2(M$QS"+4#S'@$`"````````C6HHN@(```")[DR)Y^@`````B>Y,B>?H
-M`````$$/MO5(B=_H__W__TB+7"0(2(ML)!!,BV0D&$R+;"0@2(/$*,-F9I!F
-M9I!!5%-(@^P(2(G[2(G12(M',$R+8!"+O^P,``!(P><%2`-[$$B)\DB)WNCR
-MY/__BX/L#```_\"#X!^)@^P,``#^@V4,``"+4R2!X@#\___!X`4)PHMS/(/&
-M%$R)Y^@`````2(/$"%M!7,-F9F:09F:04TB)^[D`````N@(```"^`````.A(
-M]?__2(G?Z*#S__](B=_H`````(/X`746QX-@#````0````^V,TB+>S#H+?W_
-M_UO#9F9FD&9F9I!F9I!(B5PDX$B);"3H3(ED)/!,B6PD^$B#["A,C68@2(M'
-M,$B+:!"+7SR-LQP!``!(B>_H`````"7!````N@````"#^$`/A<@!``!!@WPD
-M!`%U9D$/ME0D%8VS!`$``$B)[^@`````00^V5"07C;,(`0``2(GOZ`````!!
-M#[94)!F-LPP!``!(B>_H`````$$/ME0D&XVS$`$``$B)[^@`````00^V5"0=
-MC;,4`0``2(GOZ`````#K-[@`____9D&%1"04=2!F085$)!9U&&9!A40D&'40
-M9D&%1"0:=0AF085$)!QT"KH`````Z2,!``!!#[94)!2-LP0!``!(B>_H````
-M`$$/ME0D%HVS"`$``$B)[^@`````00^V5"08C;,,`0``2(GOZ`````!!#[94
-M)!J-LQ`!``!(B>_H`````$$/ME0D'(VS%`$``$B)[^@`````00^V5"0>C;,8
-M`0``2(GOZ`````!!#[94)!^-LQP!``!(B>_H`````$&#/"0"#X6$````C;,@
-M`0``2(GOZ`````"Y9````+H*````B=Y(B>_H`````+H`````A<!T88VS'`$`
-M`$B)[^@`````)8D```"Z`````(/X"'5$0;T`````@<,``0``28M$)`@/MQ!(
-M@\`"28E$)`B)WDB)[^@`````0?_%08']_P```';908%L)!```0``N@$```!F
-M9I")T$B+7"0(2(ML)!!,BV0D&$R+;"0@2(/$*,-F9I!FD$B)7"382(EL).!,
-MB60DZ$R);"3P3(ET)/A(@^PH2(G[QX>``````````$B+?Q"Z`````+YD'0``
-MZ`````#'@X@`````````QX.,`````````,>#D`````````#'@Y0`````````
-MQX.8`````````,>#G`````````#'@Z``````````QH.D`````;@`````2(-[
-M*``/A*8"``"X`````&:!>P:!4`^%E0(```^V4P6#^@$/A(@"``"#^@%_!X72
-MD'00ZRJ#^@)T&69F9I!F9I#K',>#C`````$```!F9F:0ZQ;'@Y`````!````
-MZPK'@Y0````!````O0````!F9I!`#[;5B="#X`/!X`@%=`$``/;"!'0*C;``
-M``,`ZPAFD(VP```"`$B+>Q#H`````(GJ#[;*B<!(B<*!XN````!(P>H%B)09
-MI@```"4`&```2,'H"XB$&:X```#_Q4"`_0=VGDB)W^@V]/__2(G?Z#[V__](
-MB=_H5O;__TB+>Q"Z`````+[P!`$`Z`````!(BWL0OBP-``#H`````$&)Q$&#
-MY/Y(BWL01(GBOBP-``#H`````$B+>Q"^``T``.@`````J#!T18M#<*G@`P"`
-M=`@E'_S_?XE#<(.[B`````%T&X.[C`````%T$H.[D`````%T"8.[E`````%U
-M$XM#<*@0=`R#X.^)0W#K!(-C<,^]`````$`/MO5(B=_HH?'____%0(#]!W;L
-MBU-P2(M[$+X`#```Z`````"+4W1(BWL0OB@,``#H`````(M3>$B+>Q"^7!T`
-M`.@`````O0````")Z0^VP8M4@QA`@/T!&?9FO@``@<8,``,`2(M[$.@`````
-MB>H/ML*+5(,@0(#]`1GV9KX``('&$``#`$B+>Q#H`````/_%0(#]`7:TQX.`
-M````5:L&`+T`````9F:09F:00`^V]4B)W^BTWO___\5`@/T'=NR_4,,``.@`
-M````@[N0`````70)@[N4`````75'0;P`````O0````!!O@`!``!$#[;M1(GN
-M2(G?Z`````"%P'4+1(GP1(GIT^!!"<3_Q4"`_0=VVD2)XKX`_P``2(G?Z-GE
-M__^X`0```&9F9I!(BQPD2(ML)`A,BV0D$$R+;"083(MT)"!(@\0HPV9FD$B#
-M[`A(BW\0N@````"^9!T``.@`````N`$```!(@\0(PV9F9I!F9F:09F9FD&9F
-MD,<%``````$```##9F:09I#'!0``````````PV9FD&:02(E<)/!(B6PD^$B#
-M[!A(B?V)\@^VPDB+7,<PN`````!(A=MT+$`/MO[H`MW__XE#/$B):S#'@V`,
-M````````QX-``@```````$B)W^@_[?__2(M<)`A(BVPD$$B#Q!C#B?`/ML!(
-MBU3',+@`````2(72=`V#NF`,```!#Y7`#[;`\\-F9F:09F:09F:09F:055-(
-M@^P(2(G]B?"#X`/!X`@%``$``$#VQ@1T"(V8```#`.L&C9@```(`2(M]$(G>
-MZ`````"#X`^#^`%T$X/X`7(^@_@#=#'K-V9F9I!F9I!(BWT0B=[H`````+]`
-M#0,`Z`````!(BWT0B=[H`````(/@#X/X`W4(N`$```#K!I"X`````$B#Q`A;
-M7<-F9F:005=!5D%505154TB#[#A(B?U!B?:)\(/@`XA$)#-$B?"#X`1!B<5!
-MP>T"B?(/ML)(BU3',$R+?Q"X`````$B%T@^$W@$``(M"/(E$)#2X`````(.Z
-M8`P```$/A,4!``!$#[;F1(GFZ)7<__^+7"0T@\,HN@0```")WDR)_^@`````
-MB=Y,B?_H`````+\9````Z`````"Z`````(G>3(G_Z`````")WDR)_^@`````
-M1(GF2(GOZ#?N__]!O``````/MD0D,\'@"`4(`0``B<)(B50D*$B)5"0@2(E4
-M)!A(B50D$(G`2(E$)`A!#[;&B40D!$B+5"0HC8(```,`C;(```(`183M#T7P
-M2(M]$.@`````B<.#X_"#RP%(BW0D((V&```#`(VV```"`$6$[0]%\$B+?1")
-MVN@`````2(MT)!B-A@```P"-M@```@!%A.T/1?!(BWT0Z`````"_&0```.@`
-M````@^/P2(MT)!"-A@```P"-M@```@!%A.T/1?!(BWT0B=KH`````$B+="0(
-MC88```,`C;8```(`183M#T7P2(M]$.@`````O]`'``#H`````(M<)`2)WDB)
-M[^@`````A<!U'D'_Q$&#_`,/A1[___^)WDB)[^C3VO__N`````#K0(MT)#2!
-MQAP!``!,B?_H`````"7`````@_A`=!-!#[;V2(GOZ*3:__^X`````.L100^V
-M]DB)[^B1VO__N`$```!(@\0X6UU!7$%=05Y!7\-F9F:09F:09F:09F:02(E<
-M)-A(B6PDX$R)9"3H3(EL)/!,B70D^$B#["B)\(G508G-#[;`2(M<QS"Z````
-M`$B%VP^$BP```$R+=Q!$BV,\N@````"#NV`,```!='5$B>9,B??H`````(G&
-MA>UU+T&-1?^Z`````#P?=U?'@T0"````````@^;`00^VQ?_("<:!S@`"``#K
-M%69FD&:0QX-$`@```0```('FP/W__XGR@,X!B?"`Y/Z#>PP!B=8/1?")\D2)
-MYDR)]^@`````N@$```")T$B+'"1(BVPD"$R+9"003(ML)!A,BW0D($B#Q"C#
-M9F9FD&9F9I!F9F:02(/L"(GQ#[;!2(M4QS"X`````$B%TG0FN`````"#NF`,
-M```!=!C'@F`,```!````0`^V]NAW\___N`$```!(@\0(PV9F9I!F9I!F9I!F
-M9I!(@^P(B?(/ML*Y`````$B#?,<P`'0@#[;"2(M$QS#'@&`,````````0`^V
-M]N@/]/__N0$```")R$B#Q`C#9F:04XGPB=8/ML!(BUS',+@`````2(7;="VX
-M`````(.[8`P```%T'[D`````N@(```!(B=_H&>K__TB)W^AQZ/__N`$```!;
-MPV9F9I!F9I!F9I")\`^VP$B+5,<PN/\```!(A=)T!P^V@D@"``#SPV9FD$B)
-M7"3H2(EL)/!,B60D^$B#[!B)\$&)U$B+;Q`/ML!(BU3',+D`````2(72=%*+
-M6CR-<RQ(B>_H`````$&#_`%U'KD`````J`)U-8US++H"````2(GOZ`````#K
-M'&9FD+D`````J`)T%XUS++H`````2(GOZ`````"Y`0```&:0B<A(BQPD2(ML
-M)`A,BV0D$$B#Q!C#9F9FD&9F9I!F9I!(B5PDV$B);"3@3(ED).A,B6PD\$R)
-M="3X2(/L*$F)_8GSB=5!B<R)\H/B`XG8@^`$B<'!Z0)`]L7X=09!]L3\=`ZX
-M`````.MZ9F9FD&9FD`^VPL'@"(V0=`$``(V"```#`('"```"`(3)08G&1`]$
-M\DB+?Q!$B?;H`````"0?B>K!X@6!XN`````)T(#DYT2)XL'B"X'B`!@```G0
-M28M]$(G"1(GVZ``````/ML-&B*0HK@```$*(K"BF````N`$```!(BQPD2(ML
-M)`A,BV0D$$R+;"083(MT)"!(@\0HPTB)7"3H2(EL)/!,B60D^$B#[!A(B?N)
-M\$&\`P```$$AQ(/@!(G%P>T"0(#]`1GV9KX``('&&``#`$B+?Q#H`````$$/
-MMM2-2ABZ`0```$C3X@G00(#]`1GV9KX``('&&``#`$B+>Q")PN@`````0(#]
-M`1GV9KX``('&&``#`$B+>Q#H`````+@!````2(L<)$B+;"0(3(MD)!!(@\08
-MPY!!54%455-(@^P(28G\08GUO0,```!$(>U`#[;VB?.#XP3!ZP+H=^C__X#[
-M`1GV9KX``('&&``#`$F+?"00Z`````!`#[;-@\$82,?"_O___TC3PB'0@/L!
-M&?9FO@``@<88``,`28M\)!")PN@`````@/L!&?9FO@``@<88``,`28M\)!#H
-M`````$`/MO7!Y@B!Q@@!``"-A@```P"!Q@```@"$VP]%\$F+?"00Z`````"#
-MX/"#R`%`#[;5P>((C8H(`0``C9$```,`@<$```(`A-N)U@]$\4F+?"00B<+H
-M`````$$/MO5,B>?HL>?__[@!````2(/$"%M=05Q!7<.005=!5D%505154TB#
-M[`A)B?Q(B=-!B?5,BW\0B?(/ML)(BVS',$`/MM:)T(/@`\'@"`5T`0``]L($
-M=`B-L````P#K!HVP```"`$F+?"00Z`````")0UA(A>UU$,<#`````+@!````
-MZ=,```!$BW4\00^V]4R)Y^@`````B0.X`0```(,[``^$LP```(N%8`P``(E#
-M+(N%1`(``(E#,`^VA4@"``"(0S2Y`````&9F9I")R@^V1"IVB$0:!/_!@_DG
-M=NY$B?9,B?_H`````(E#.$&-=A!,B?_H`````(E#/$&-=A1,B?_H`````(E#
-M0$&-=AA,B?_H`````(E#1$&-=AQ,B?_H`````(E#2$&-=B!,B?_H`````(E#
-M3$&-=B1,B?_H`````(E#4$&-=BA,B?_H`````(E#5+@!````2(/$"%M=05Q!
-M74%>05_#9F:02(/L2$B-1"0(QP0D`````(D0B4@(9D2)0`QF1(E(#HM4)%")
-M4!"+5"18B5`42(M4)&!(B5`82(M4)&A(B5`@2(GB0`^V]N@`````2(/$2,-(
-MB5PDT$B);"383(ED).!,B6PDZ$R)="3P3(E\)/A(@^PX2(D\)$F)UD&)]XGR
-M#[;"2(MLQS"X!````$B%[0^$80$``+@!````@[U@#`````^$3P$``+@"````
-M@+U(`@``'P^$/0$``/^-Z`P``(N%Z`P``$2+K(5H#```18GL2XT$I$C!X`1,
-MC:0H4`(``$6(;"0$08,^``^%M````$F-7@B#O40"```"=0G'0P0!````ZT,/
-MMTL,#[=S#HM3"(M]".AIT___B4,$@_@!=2B#?0@`=2*+A>@,``")PD2)K)5H
-M#```_\")A>@,``"X`P```.FN````@+UD#````'5"@[U``@```'4:00^VWXG>
-M2(L\).BH[/__B=Y(BSPDZ,WL__],B?),B>9(B>_HS^K__TF-5@A,B>9(B>_H
-M$.[__^M>3(GR3(GF2(GOZ+#J___K3DR)\DR)YDB)[^B@ZO__@+U(`@```74W
-M@[U``@```74-00^V]TB+/"3H4>W__TR)YDB)[^B&[O__A<!U$DR)YDB)[^CW
-MZO__N`$```#K!;@`````2(M<)`A(BVPD$$R+9"083(ML)"!,BW0D*$R+?"0P
-M2(/$.,-F9F:09F9FD$B)7"302(EL)-A,B60DX$R);"3H3(ET)/!,B7PD^$B#
-M[%A(B7PD($R+?Q"^8!T``$R)_^@`````B<5(BT0D((N`@````(E$)!RX````
-M`(5L)!P/A&$!``#WQ0``!`!T-+Y8'0``3(G_Z`````")PXG"]]*^6!T``$R)
-M_^@`````N0````")VKX`````2(M\)"#_5RC&1"0;`/?%_P$```^$^P```(!\
-M)!L!&=MFNP``@<,4``,`NN____^)WDR)_^@`````B=Y,B?_H`````$&)QHG"
-M]]*#RA")WDR)_^@`````@'PD&P$9]F:^``"!Q@@``P!,B?_H`````$&)Q$&]
-M``````^V3"0;B4PD%(E,)!!!#[;5N``!``")T=/@B<-$(?.X`0```-/@1"'P
-M08GI08/A`8G!1`G)=!M$B>&#X1]$B30D08G`BW0D%$B+?"0@Z.G8__^%VW0L
-MBUPD$(T$G0````!$">@/MOCHO^G__X5$)!QT$$$/MM6)WDB+?"0@Z,G;___!
-M[0)!P>P(0?_%08#]`P^&=____^L&9F:0P>T(T>W^1"0;@'PD&P$/AN7^__^X
-M`0```$B+7"0H2(ML)#!,BV0D.$R+;"1`3(MT)$A,BWPD4$B#Q%C#9F9FD$B#
-M[`A(BW\0N@````"^9!T``.@`````N`$```!(@\0(PV9F9I!F9F:09F9FD&9F
-MD$B#[`B+EX````!(BW\0OF0=``#H`````+@!````2(/$",-F9F:09F9FD&9F
-MD&9FD$B)7"382(EL).!,B60DZ$R);"3P3(ET)/A(@^PH28G^08G408G-NP``
-M```YTW,PC:X<`0``B>Y,B??H`````(3`>`VH`0^4P`^VP.L79F:01(GOZ```
-M``#_PT0YXW+6N`````!(BQPD2(ML)`A,BV0D$$R+;"083(MT)"!(@\0HPV9F
-M9I!F9F:09F9FD&9FD%-(B?N+=SR!QB`!``!(BT<P2(MX$+H`````Z`````"+
-M<SR!QB`!``!(BT,P2(MX$.@`````6\-F9I!F9I!F9I!32(G[BW<\@<8@`0``
-M2(M',$B+>!"Z`@```.@`````BW,\@<8<`0``2(M#,$B+>!#H`````%O#9F:0
-M9F:09F:0055!5%532(/L"$B)^TB+1S!,BV@01(MG/+T`````N`````"#OT`"
-M```!#X25````08VT)"`!``!,B>_H`````*B!=`R_,@```.@`````9I!!C;0D
-M(`$``$R)[^@`````J(%T+HGH_\5F/;<+=QP/MC-(BWLPZ`````"%P'1'O^@#
-M``#H`````.O&N`````"0ZS.Y9````+H*````1(GF3(GOZ`````!!C;0D'`$`
-M`$R)[^@`````)<$```"#^$`/E,`/ML!(@\0(6UU!7$%=PTB)7"3H2(EL)/!,
-MB60D^$B#[!B)\`^VP$B+7,<PN`````!(A=MT:4B+0S!,BV`0BVL\N`````"#
-MNV`,```!=%!(B=_H`````(VU'`$``+KA````3(GGZ`````"Y9````+H0)P``
-MB>Y,B>?H`````(7`=0](B=_H`````+@`````ZPY(B=_H`````+@!````D$B+
-M'"1(BVPD"$R+9"002(/$&,-F9F:09F:09F:09F:04TB#[$")\@^VPDB+1,<P
-MO@````!(A<`/A*$```!(C5A`#[;RQT0D,.P```#'1"0H`````,=$)"``````
-MQT0D&`````#'1"00`````,=$)`@`````QP0D`````$&Y``$``$F)V+D`````
-MN@$```#H`````+X`````A<!T0O:#H````.!T-+D`````28G8O@$```"`N_X!
-M``"E=2.Z``````^WPD("#`#_PF:!^O\!=O"^`````(3)=06^`0```(GP2(/$
-M0%O#9F9FD&9FD&9FD$B#[`B)\`^VP$B+?,<PN`````!(A?]T$[@`````@[]@
-M#````70%Z`````!(@\0(PTB#[#A`#[;VQT0D,.\```#'1"0H``````^V1"1`
-MB40D($4/MLE$B4PD&$4/ML!$B40D$`^VR8E,)`@/MM*)%"1!N0````!!N```
-M``"Y`````+H`````Z`````!(@\0XPTB)7"302(EL)-A,B60DX$R);"3H3(ET
-M)/!,B7PD^$B#[&A(B?M!B==!B<Y-B<5%B<R)\HML)'!$BTPD>$2+A"2`````
-MB[PDB````(N,))````!$#[:<))@```!$#[:4)*`````/ML*^`````$B#?,,P
-M`'1-#[;R00^VPHE$)#!!#[;#B40D*`^WP8E$)"`/M\>)1"0800^WP(E$)!!!
-M#[?!B40D"`^WQ8D$)$6)X4V)Z$2)\42)^DB)W^@`````B<:)\$B+7"0X2(ML
-M)$!,BV0D2$R+;"103(MT)%A,BWPD8$B#Q&C#9F9FD&9FD&9FD$B)7"302(EL
-M)-A,B60DX$R);"3H3(ET)/!,B7PD^$B![)@```")\(E4)%R)S4R)1"101(E,
-M)$Q$B[0DH````$2+O"2H````BY0DL````&:)5"0PBXPDN````&:)3"0@BY0D
-MP````&:)5"00#[:,),@```"(3"0/#[:4)-````"(5"0.#[;`2(M<QS!,BV<0
-M1(MK/$B)W^B5^___N@````"%P`^$B`(``$B)W^@`````@_T!=6Y,B?$/MM5!
-MC;4$`0``3(GGZ`````!,B?@/MM1!C;4(`0``3(GGZ`````"+3"0P#[;508VU
-M#`$``$R)Y^@`````BT0D(`^VU$&-M1`!``!,B>?H`````(M,)!`/MM5!C;44
-M`0``3(GGZ`````#K-[@`____9D2%\'4B9D2%^'4<9H5$)#!U%6:%1"0@=0YF
-MA40D$'019F9FD&9FD+H`````Z=8!``!!#[;608VU!`$``$R)Y^@`````00^V
-MUT&-M0@!``!,B>?H``````^V5"0P08VU#`$``$R)Y^@`````#[94)"!!C;40
-M`0``3(GGZ``````/ME0D$$&-M10!``!,B>?H``````^V5"0/08VU&`$``$R)
-MY^@`````#[94)`Y!C;4<`0``3(GGZ`````"#?"1<`'4]N60```"Z\+H$`$2)
-M[DR)Y^@`````A<!U$DB)W^@`````N@````#I&@$``$B)W^@`````N@$```#I
-M"`$``+ED````NO"Z!`!$B>Y,B>?H`````(7`=11(B=_H`````+H`````9I#I
-MVP```$&-M1P!``!,B>?H`````*@(=1)(B=_H`````+H`````Z;8```"]````
-M`#ML)$QS8D6-M0`!``!`A.UU&;ED````NE##``!$B>Y,B>?H`````(7`=&6#
-M?"1<`7481(GV3(GGZ`````")ZDB+3"109HD$4>L6B>A(BTPD4`^W%$%$B?9,
-MB>?H`````/_%.VPD3'*EN60```"Z4,,``$2)[DR)Y^@`````A<!U'DB)W^@`
-M````N@````#K(4B)W^@`````N@````#K$DB)W^@`````N@$```!F9I!FD(G0
-M2(M<)&A(BVPD<$R+9"1X3(NL)(````!,B[0DB````$R+O"20````2('$F```
-M`,-F9F:09F9FD&9F9I!F9I!!5%532(G[2(M',$B+:!!$BV<\08VT)"`!``"Z
-M!@```$B)[^@`````BW,\@<8@`0``2(GOZ`````"_"@```.@`````2(G?Z```
-M``"_]`$``.@`````O_0!``#H`````+_T`0``Z`````"_]`$``.@`````NP``
-M``!!@<0<`0``D$2)YDB)[^@`````A,!X![@!````ZQZ_]`$``&9FD&:0Z```
-M``#_PX'[#R<``';1N`````!;74%<PV9F9I!F9I!32(G[Z#?___^Z`0```(/X
-M`704O_0!``#H`````$B)W^@;____B<*)T%O#9F:09I!54TB#[`A(B?U(BP4`
-M````BW`8@<8```0`NJ````#H`````+L`````2(L%`````(MP$('&```$`$B)
-M[^@`````_\.#^P1^X;L`````9F9FD$B+!0````"+<!2!Q@``!`!(B>_H````
-M`/_#@_L%?N&[`````$B+!0````"+<!"!Q@``!`!(B>_H`````/_#@_L$?N%(
-M@\0(6UW#9F:09F:04TB)^TB+!0````"+<`R!Q@``!`"Z@````.@`````2(L%
-M`````(MP&('&```$`+JP````2(G?Z`````!;PV9FD$B)7"3P3(ED)/A(@^P8
-M28G\Z`K___](BP4`````BW`(@<8```0`N@````!,B>?H`````$B+!0````"+
-M,('&```$`$R)Y^@`````B<-,B>?H;/___P^VVXG82(M<)`A,BV0D$$B#Q!C#
-M9F9FD&9F9I!!5%532(G[OBP-``#H`````$&)Q(G"@\H!OBP-``!(B=_H````
-M`+[P!`$`2(G?Z`````")Q8/@8H/X8G05B>J#RF(/MM*^\`0!`$B)W^@`````
-MO@``!`!(B=_H`````$B)W^A)_O__2(L%`````(MP"('&```$`+H'````2(G?
-MZ`````!(BP4`````BS"!Q@``!`"Z$0```$B)W^@`````2(L%`````(MP"('&
-M```$`+H%````2(G?Z`````!(BP4`````BS"!Q@``!`"Z$0```$B)W^@`````
-M2(G?Z&_^__^)ZK[P!`$`2(G?Z`````"^\`0!`$B)W^@`````1(GBOBP-``!(
-MB=_H`````%M=05S#9F9FD&9F9I!F9I!F9I!!5%532(G[OBP-``#H`````$&)
-MQ(G"@\H!OBP-``!(B=_H`````+[P!`$`2(G?Z`````")Q8/@8H/X8G05B>J#
-MRF(/MM*^\`0!`$B)W^@`````O@``!`!(B=_H`````$B)W^@I_?__2(L%````
-M`(MP"('&```$`+H'````2(G?Z`````!(BP4`````BS"!Q@``!`"Z`````$B)
-MW^@`````2(L%`````(MP"('&```$`+H%````2(G?Z`````!(BP4`````BS"!
-MQ@``!`"Z`````$B)W^@`````2(G?Z$_]__^)ZK[P!`$`2(G?Z`````"^\`0!
-M`$B)W^@`````1(GBOBP-``!(B=_H`````%M=05S#9F9FD&9F9I!F9I!F9I!3
-M2(G[Z&?\__](BP4`````BW`(@<8```0`N@H```!(B=_H`````$B+!0````"+
-M,('&```$`+H`````2(G?Z`````!(B=_HQOS__[X!``0`2(G?Z`````"Z____
-M_Z@"=4U(B=_H"/S__TB+!0````"+,('&```$`+H!````2(G?Z`````!(B=_H
-MA/S__[]D````Z`````"^`0`$`$B)W^@`````T>B#X`&#^`$9THG06\-F9F:0
-M9F9FD&9F9I!F9I!(B5PDV$B);"3@3(ED).A,B6PD\$R)="3X2(/L*$F)_$&)
-M]DB+7Q"^+`T``$B)W^@`````08G%B<*#R@&^+`T``$B)W^@`````OO`$`0!(
-MB=_H`````(G%@^!B@_AB=!6)ZH/*8@^VTK[P!`$`2(G?Z`````"^```$`$B)
-MW^@`````18BT)*4```!!#[;6O@#@!0!(B=_H`````(GJOO`$`0!(B=_H````
-M`+[P!`$`2(G?Z`````!$B>J^+`T``$B)W^@`````2(L<)$B+;"0(3(MD)!!,
-MBVPD&$R+="0@2(/$*,-F9F:09F9FD&9F9I!(@^P(B?&$TG06N`$```#3X`B'
-MI0```.L49F9FD&9FD+C^____T\`@AZ4````/MK>E````Z`````!(@\0(PV:0
-M05=!5D%505154TB#[`A(B?U!OP````"^+`T``.@`````08G&B<*#R@&^+`T`
-M`$B)[^@`````OO`$`0!(B>_H`````$&)Q8/@8H/X8G061(GJ@\IB#[;2OO`$
-M`0!(B>_H`````+X```0`2(GOZ`````"^```$`$B)[^@`````9CU5J@^%[P``
-M`$&\`````&:0NP````!$.>-_*F9FD&9FD$B+!0````"+<!B!Q@``!`"ZH```
-M`$B)[^@`````_\-$.>-^W$&!_,@```!^"K\!````Z`````"^```$`$B)[^@`
-M````B<-(BP4`````BW`8@<8```0`NK````!(B>_H`````&:!^U6J=1A!_\1!
-M@?S'````#XYV____9H'[5:J0=%5(BP4`````BW`8@<8```0`NK````!(B>_H
-M`````+X```0`2(GOZ`````!F/56J=25!OP$```!(B>_H`/K__SP^=1-(B>_H
-MI/S__X7`N`(```!$#T3X2(L%`````(MP&('&```$`+JP````2(GOZ`````!$
-MB>J^\`0!`$B)[^@`````OO`$`0!(B>_H`````$2)\KXL#0``2(GOZ`````!!
-M#[;'2(/$"%M=05Q!74%>05_#9F9FD&9F9I!F9F:055-(@^P(2(G]NP````!F
-MD$C'!0``````````2(GOZ/W]__^$P'4A2,<%``````````!(B>_HYOW__X3`
-M=0K_PX'[YP,``'[(#[;`2(/$"%M=PP````````````````````0`````````
+M<$B)[^CNT?__QD`(`42(>!!$B'@12(L32(E0%$B+4PA(B5`<28M5`/Z"L`D`
+M``^VLK`)``")\4@IT$B#Z%!(P?@#20^OQHB$2K`)``!!#[9%"XB$2K$)``!!
+MB'4+1(GY#[;!2,'@!$B-A"CP"@``N@````"#.`!U$H-X!`!U#(-X"`!U!H-X
+M#`!T!;H!````A=)T>D2)^`^VV$B)V$C!X`1(C9PH\`H``$B)[^A&T?__QD`(
+M`D2(>!!$B'@12(L32(E0%$B+4PA(B5`<28G$2(L0_H*P"0``#[:RL`D``(GQ
+M2(M$)"A(*=!(@^A02,'X`TD/K\:(A$JP"0``00^V1"0+B(1*L0D``$&(="0+
+M0?_'1#A]2@^'X/W__^DZ#```#[9=2TB)[^C+T/__QD`(`8A8$(A8$4B+5"1@
+M2(E0%$B+5"1H2(E0'$B)1"0X#[9=2TB)[^B>T/__QD`(`HA8$(A8$4B+5"1@
+M2(E0%$B+5"1H2(E0'$F)Q$B)[^AWT/__QD`(!DB)1"0H28L,)/Z!L`D```^V
+MN;`)``")_DB+1"0H2"G(2(/H4$C!^`-(NLW,S,S,S,S,2`^OPHB$<;`)``!!
+M#[9$)`N(A'&Q"0``08A\)`M!OP````"`?4H`#X9W"P``9F9FD$0X?4L/A,8"
+M``!$B?H/ML)(P>`$2`'H2(V0\`H``+D`````@[CP"@```'46@WH$`'40@WH(
+M`'4*@WH,`&9F9I!T!;D!````A<D/A($"``#^3"0G#[9,)"<"34I!B<Y$B?M$
+M#[;C2<'D!$D![$F-O"3P"@``2(E\)!!(B>_HC\___\9`"`%$B'@01(AP$4F+
+ME"3P"@``2(E0%$B+3"002(M1"$B)4!Q(B40D0`^V74M(B>_H6<___\9`"`2(
+M6"!$B'`A28N4)/`*``!(B5`02(M<)!!(BU,(2(E0&$F)Q4B+$/Z"L`D```^V
+MLK`)``")\4B+1"0X2"G02(/H4$C!^`-(O\W,S,S,S,S,2`^OQXB$2K`)``!!
+M#[9%"XB$2K$)``!!B'4+28M5`/Z"L`D```^VLK`)``")\4B+1"1`2"G02(/H
+M4$C!^`-(#Z_'B(1*L`D``$$/MD4+B(1*L0D``$&(=0M(BT0D*$B+$/Z"L`D`
+M``^VLK`)``")\4R)Z$@IT$B#Z%!(P?@#2`^OQXB$2K`)``!(BUPD*`^V0PN(
+MA$JQ"0``0(AS"P^V74M(B>_H7<[__\9`"`2(6"!$B'@A28N4)/`*``!(B5`0
+M2(M\)!!(BU<(2(E0&$F)Q4B+$/Z"L`D```^VLK`)``")\4B+1"0X2"G02(/H
+M4$C!^`-(N\W,S,S,S,S,2`^OPXB$2K`)``!!#[9%"XB$2K$)``!!B'4+2(M\
+M)"A(BQ?^@K`)```/MK*P"0``B?%,B>A(*=!(@^A02,'X`T@/K\.(A$JP"0``
+M#[9'"XB$2K$)``!`B'<+2(GOZ*C-___&0`@"1(AX$$2(>!%)BY0D\`H``$B)
+M4!1(BTPD$$B+40A(B5`<28G$2(L0_H*P"0``#[:RL`D``(GQ2(M$)"A(*=!(
+M@^A02,'X`T@/K\.(A$JP"0``00^V1"0+B(1*L0D``$&(="0+D$'_QT0X?4H/
+MAR/]___ID0@```^V14PZ14L/A:@```!!OP````"`?4H`#X9T"```D$0X?4MT
+M?T2)^P^VPTC!X`1(`>A(C9#P"@``N0````"#N/`*````=1B#>@0`=1*#>@@`
+M=0R#>@P`=`MF9I!F9I"Y`0```(7)=#Q$B?@/MMA(P>,$2`'K3(VC\`H``$B)
+M[^BKS/__QD`(`D2(>!!$B'@12(N3\`H``$B)4!1)BU0D"$B)4!Q!_\=$.'U*
+M#X=N____Z=P'``!(C7PD8.A/R___2(GOZ&?,___&0`@&2(E$)"A!OP````"`
+M?4H`#X8;`0``1#A]2P^$!`$``$2)^@^VPDC!X`1(`>A(C9#P"@``N0````"#
+MN/`*````=12#>@0`=0Z#>@@`=0B#>@P`9I!T!;D!````A<D/A,$```!$B?D/
+MML%(P>`$3(TD*$F-G"3P"@``BT0D8$$+A"3P"@``B40D8(M$)&0+0P2)1"1D
+MBT0D:`M#"(E$)&B+1"1L"T,,B40D;$0X?4QT=$B)[^BLR___QD`(`D2(>!!$
+MB'@128N4)/`*``!(B5`42(M3"$B)4!Q)B<1(BPC^@;`)```/MKFP"0``B?Y(
+MBT0D*$@IR$B#Z%!(P?@#2+K-S,S,S,S,S$@/K\*(A'&P"0``00^V1"0+B(1Q
+ML0D``$&(?"0+0?_'1#A]2@^'Y?[__P^V74M(B>_H)\O__\9`"`*(6!"(6!%(
+MBU0D8$B)4!1(BU0D:$B)4!Q)B<1(BPC^@;`)```/MKFP"0``B?Y(BT0D*$@I
+MR$B#Z%!(P?@#2+K-S,S,S,S,S$@/K\*(A'&P"0``00^V1"0+B(1QL0D``$&(
+M?"0+2`^V=4Q(B?=(B?!(P>`$2(VT*'`+``"+!O?0B40D4(M6!/?2B50D5(M.
+M"/?1B4PD6(MV#/?61(M,)&!$(<B)1"101(M$)&1$(<*)5"14BU0D:"'1B4PD
+M6(M$)&PAQHET)%Q(P><$2(V\+W`+``!$(P]$B4PD8$0C1P1$B40D9"-7"(E4
+M)&@C1PR)1"1LN`````!%A<EU$$6%P'4+A=)U!X-\)&P`=`6X`0```(7`D`^$
+M#P(```^V14N(A0@,``!(BT0D8$B)A?`+``!(BT0D:$B)A?@+``#&A0D,```!
+M2,>%``P```````!!OP````"`?4H`#X;+`0``3(VU\`L``$F\S<S,S,S,S,QF
+M9I!FD$0X?4QU6DB)[^BBR?__QD`(`TR)<!!$B'@82(M<)"A(BQ/^@K`)```/
+MMK*P"0``B?%(*=!(@^A02,'X`TD/K\2(A$JP"0``#[9#"XB$2K$)``!`B',+
+MZ4T!``!F9I!FD$0X?4L/A#X!``!$B?H/ML)(P>`$2(U<!'!(`>A(C;AP"P``
+MB[!P"P``]]:),XM/!/?1B4L$BU<(]]*)4PB+1PSWT(E##"-T)&"),R-,)&2)
+M2P0C5"1HB5,((T0D;(E##$B)[^CHR/__QD`(`TR)<!!$B'@828G%2(M,)"A(
+MBQ'^@K`)```/MK*P"0``B?%(*=!(@^A02,'X`TD/K\2(A$JP"0``2(M\)"@/
+MMD<+B(1*L0D``$"(=PNX`````(,[`'42@WL$`'4,@WL(`'4&@WL,`'0%N`$`
+M``"%P'1K1(GZ#[;"2,'@!$B-7`1P2(GOZ%S(___&0`@!1(AX$$2(>!%(BQ-(
+MB5`42(M3"$B)4!Q)BU4`_H*P"0``#[:RL`D``(GQ2"G02(/H4$C!^`-)#Z_$
+MB(1*L`D``$$/MD4+B(1*L0D``$&(=0M!_\=$.'U*#X=+_O__N`````"#?"10
+M`'45@WPD5`!U#H-\)%@`=0>#?"1<`'0%N`$```"%P`^$,`,```^V74M(B>_H
+MP<?__\9`"`&(6!"(6!%(BU0D4$B)4!1(BU0D6$B)4!Q(B40D.$C'1"0P````
+M`$&_`````(!]2@`/ANH"``!F9F:09F:01#A]3`^$S`(``$0X?4L/A,("``!$
+MB?D/ML%(P>`$2(UT!'!(`>A(C8CP"@``BU0D4".0\`H``(D6BT0D5"-!!(E&
+M!(M$)%@C00B)1@B+1"1<(T$,B48,N`````"#/@!U$H-^!`!U#(-^"`!U!H-^
+M#`!T!;@!````A<`/A%8"``!$#[9E3$2)^P^VPTC!X`1(C5P$<$B)[^CDQO__
+MQD`(`42(>!!$B&`12(L32(E0%$B+4PA(B5`<2(E$)$!(@WPD,`!T2TB+$/Z"
+ML`D```^VLK`)``")\4B+1"0P2"G02(/H4$C!^`-(O\W,S,S,S,S,2`^OQXB$
+M2K`)``!(BUPD0`^V0PN(A$JQ"0``0(AS"T0/MF5+#[9]3$"(?"0/1(GX1`^V
+M\$G!Y@1*C5PT<$B)[^A+QO__QD`(!$2(8"`/ME0D#XA0(4B+$TB)4!!(BU,(
+M2(E0&$F)Q4B)1"0P2(L0_H*P"0``#[:RL`D``(GQ2(M$)#A(*=!(@^A02,'X
+M`TB[S<S,S,S,S,Q(#Z_#B(1*L`D``$$/MD4+B(1*L0D``$&(=0M)BU4`_H*P
+M"0``#[:RL`D``(GQ2(M$)$!(*=!(@^A02,'X`T@/K\.(A$JP"0``00^V10N(
+MA$JQ"0``08AU"TB+?"0H2(L7_H*P"0``#[:RL`D``(GQ3(GH2"G02(/H4$C!
+M^`-(#Z_#B(1*L`D```^V1PN(A$JQ"0``0(AW"P^V74M.C60T<$B)[^A/Q?__
+MQD`(!(A8($2(>"%)BQ0D2(E0$$F+5"0(2(E0&$F)Q4B+$/Z"L`D```^VLK`)
+M``")\4B+1"0X2"G02(/H4$C!^`-(N\W,S,S,S,S,2`^OPXB$2K`)``!!#[9%
+M"XB$2K$)``!!B'4+2(M\)"A(BQ?^@K`)```/MK*P"0``B?%,B>A(*=!(@^A0
+M2,'X`T@/K\.(A$JP"0``#[9'"XB$2K$)``!`B'<+0?_'1#A]2@^''?W__TB)
+M[DB+?"1(Z,#:__^X`````$B!Q'@!``!;74%<05U!7D%?PV9FD&9FD&9FD$%7
+M059!54%455-(@^P828G]@[_<60```P^'$@$``$B-AV!9``!(.8=@60``#X3^
+M````28G'3(NW8%D``$B-AU!9``!(B40D$$R)?"0(9F:03(GS38LV2(M3"$F)
+M5@A,B3)(B1M(B5L(2(M#./9``01U?DF)W+T`````@'M*`'8?B>@/MOA(P><$
+M2HV\)_`*``#HNL+____%03AL)$IWX4F+A5!9``!(B5@(2(D#2(M$)!!(B4,(
+M28F=4%D``$B+0SA(@WA(`'182(M04$B+<$A,B>_H`````$B+0SA(QT!(````
+M`$'_C>!9``#K,V9FD$B)WDR)[^CEV___A<!T,4F+A6!9``!(B5@(2(D#2(M$
+M)`A(B4,(28F=8%D``&9FD$TY_@^%)____V9F9I!F9I!(@\086UU!7$%=05Y!
+M7\.055-(@^P(2(M?$(.[W%D```!U$$B-@V!9``!(.8-@60``=#=(C:M@60``
+M9F:09F:02(G?Z`````!(B=_H`````$B)W^@`````@[O<60```'7?2#FK8%D`
+M`'76N`````!(@\0(6UW#9F9FD&9FD&9FD%-,BT\028N)8%D``$F-@6!9``!(
+M.<@/A'X```!)B<*02#EY.'5L28G(NP````"`>4H`=D(/ML-(P>`$3`'`2(V0
+M\`H``+X`````@[CP"@```'42@WH$`'4,@WH(`'4&@WH,`'0%O@$```"%]G4;
+M_\-!.%A*=[ZX`````(7`=!.X`0```.FX````N`$```!FD.OI2(L)23G*=89)
+MBXEP60``28V!<%D``$@YR`^$BP```$F)P4B-0?!(.7@X=7)(B<:[`````(!X
+M2@!V2&9F9I`/ML-(P>`$2`'P2(V0\`H``$&X`````(.X\`H```!U$H-Z!`!U
+M#(-Z"`!U!H-Z#`!T!D&X`0```$6%P'47_\,X7DIWO+@`````A<!T$[@!````
+MZQVX`0```.ON9F:09I!(BPE).<D/A7C___^X`````%O#9F9FD&9FD&9FD&9F
+MD$B#["A(B5PD"$B);"003(ED)!A,B6PD($B)^TF)]4F)U$B+;Q!(@W](`'4)
+MZ'_^__^%P'4-3(GF2(GO0?_59I#K%DR):TA,B6-0_X7@60``2(GOZ`````!(
+MBUPD"$B+;"003(MD)!A,BVPD($B#Q"C#9F9FD&9F9I!F9F:09F:055-(@^P(
+M2(G]2(GS@'XA`'4$QD8A`0^V0R$\`0^5PCP&#Y7`#[;2A=!T%8![(0-T#_9#
+M("!U"<9#(0MF9I!FD$B+<U!(B>_HI+___TB+<SA(B=I(B>_H`````$B+`TB#
+M>#``=!M(C5`P2,?&`````$B)[^@`````ZUQF9I!F9I!(@[WH60```'0H2(V%
+M4%D``$@YA5!9``!T&$B-E>A9``!(Q\8`````2(GOZ`````#K)(&]V%D``/\`
+M``!W&$B-A5!9``!(.85060``=0A(B>_H`````$B#Q`A;7<-F9I!!5T%6055!
+M5%532('L6`$``$B)="0X28G4B4PD-$R+1D!)BP!(B40D"`^V4'C_RHE4)!Q!
+M#[=`$&:)1"0R28N0D````$B)5"0H10^VL(H```!!#[:`BP```(E$)!A%#[>X
+MF@```$$/MYB8````28-X*`!T#69!#[9`((/@`3G(=3*Z`````$F#>#``#X0F
+M`@``3(UL)$"+3"0T3(GJ3(G&0?]0,+H`````A<`/A`8"``#K!$V+:"B]````
+M`$B+5"0X2(L"#[9``XE$)!2Y``````^WPT@#1"0H2(E$)"!$.W0D%`^%$@$`
+M`$B%R715BT0D("G(B</!XPET2(-\)#0`=`E(BP4`````ZPQ(BST`````Z```
+M``!)B00D9D''1"0*``"!^P`0```/AKD```!F0<=$)`@`$$F#Q!"!ZP`0``!U
+MN$$/M\>)P\'C"69F9I!!#[=5"(72N````0`/1-")T"GH.=AR+8GH20-%`$F)
+M!"1F08E<)`AF0<=$)`H``$F#Q!`!W3G5=3V]`````$F#Q1#K,HGH20-%`$F)
+M!"2)T&8IZ&9!B40D"&9!QT0D"@``28/$$(G0*>@IPTF#Q1"]`````.N*00^W
+MST@#3"0@2(M4)#A(#[="$$@#0@A(.<@/A,0```#K2&9!B5PD"$F#Q!#I3/__
+M_P'=ZS5!#[??P>,)00^W50B%TK@```$`#T30B=`IZ#G8=]Z)T"GH*<-)@\40
+MO0````#KV&9FD&9FD&9$*7PD,G1RNP````!!_\9$.W0D&`^4P`^VP$$!QDB+
+M5"0(#[9">$0Y\'4JBT0D&/_(@WPD&``/1$0D'(E$)!B%P`^4P$0/MO!(#[>"
+MD````$@!1"0H2(M$)`A$#[>XD````&9$.WPD,@^&,O[__T0/MWPD,NDG_O__
+M9D''1"3Z`("Z`0```(G02('$6`$``%M=05Q!74%>05_#9F:09I!(@^P82(E<
+M)`A(B6PD$$B)_4B+7D"`?B$!=`</MD8AB$,A2(GOZ``````/MH.)````_\"(
+M@XD````Z@X@```!U,H![(0!U!,9#(0$/MD,A/`$/E<(\!@^5P`^VTH70=`J`
+M>R$#=`3&0R$+2(G>2(GO_U,X2(M<)`A(BVPD$$B#Q!C#9F9FD&9F9I!F9I!F
+M9I!!5T%6055!5%532(/L&$B)?"0028GU2(L&2(E$)`CV1B`$#X3H`0``0;X`
+M````@+Z```````^$8@$``$ECQDV+1,5800^VJ&`,``!!.*AA#```#X(Q`0``
+M03AH2P^$&`$``(GJ#[;"2(G"2,'B!$Z-E`+P"@``00^WE(!`#```00^WO(!"
+M#```NP````!!NR````!!O`$```!F9F:09F:0@_H?=S\/ML-)C32"1(G9*=$Y
+M^0]'SX/Y('4(QP;_____ZPU$B>#3X/_(B='3X`D&1(G8*=`Y^',5C7P7X+H`
+M````ZP.#ZB#_PX#[`W:RB>L/ML-(B<)(P>($3HV4`G`+``!!#[>4@$`,``!!
+M#[>\@$(,``"[`````$&[(````$&\`0```(/Z'W=&#[;#28TT@D2)V2G1.?D/
+M1\^#^2!U",<&_____^L-1(G@T^#_R(G1T^`)!D2)V"G0.?AS'(U\%^"Z````
+M`.L*9F9FD&9FD(/J(/_#@/L#=JO_Q4$XJ&$,```/@\_^__]!_\9!#[:%@```
+M`$0Y\`^/GO[__TB+7"00@[M(60````^$B0,``$&^`````$&`O8``````=#](
+MB=I(@<)@60``26/&38M$Q5A)QX`P#````````$B+0@A,B4((28D028E`"$R)
+M`$'_QD$/MH6`````1#GP?\M,B>Y(BWPD$.BU^?__Z5H#``#V1B`"#X0>`P``
+M2(M$)!!(!?!9``!(B00D3(M\)!!)@<<P6@``2(M4)`CV@I(````##X7Q`@``
+MNA````"^`````$R)_^@`````0;X`````08"]@``````/A/T```!)8\9-BT3%
+M6$R)Q[D`````08!X2@!V2`^VP4C!X`1(`?A(C9#P"@``O@````"#N/`*````
+M=1*#>@0`=0R#>@@`=0:#>@P`=`6^`0```(7V=`>X`0```.L,_\$X3TIWN+@`
+M````A<`/A5\"``!!#[:H8`P``$$XJ&$,``!R;$$X:$MT6XGI#[;19D&#/%<`
+M=25)#[>$D$`,``!)`T!`2(L<)$B)!--!#[>$D$(,``!F08D$5^LIB>@/MM!!
+M#[>$D$`,``!F00-`0&9!`X200@P``$B+#"1F*P319D&)!%?_Q4$XJ&$,``!S
+ME$'_QD$/MH6`````1#GP#X\#____28MU4$B+?"00Z#BX__]!O@````!!@+V`
+M``````^$]@```$B+3"002('!4%D``$ECQDV+1,58187V=6I)BT!`28F%D```
+M`$$/MH!@#```08B%B@```$$/MD!+08B%BP```$D/MH!@#```00^WA(!`#```
+M9D&)A9@```!)#[:`8`P``$$/MX2`0@P``&9!B86:````0<:%B`````!!QH6)
+M`````.M-28M00$D[E9````!V0$B+7"0(#[>#D````/?82)A((<))(X60````
+M2#G"=2%)#[:08`P``$$/MX6:````9D$#A)!"#```9D&)A9H```!(BT$(3(E!
+M"$F)"$F)0`A,B0!!_\9!#[:%@````$0Y\`^/%O___TB+1"002(.XZ%D```!T
+M&4B)PDB!PNA9``!(Q\8`````2(G'Z`````"]`````$B+5"0(@'IX``^&K```
+M`(GI1`^VX69#@SQG`'1=2(M$)`A*BYS@H````$B+?"00Z`````!(B<9!_H6(
+M````QD`2($,/MP1G9HE&$$B+%"1*BP3B2(E&"(!.(`)(QT8P`````$C'1C@`
+M````2(D>3(EN0$B+?"00_U-H_\5(BTPD"$`X:7AWB.LR0;X`````08"]@```
+M``!T(DECQDF+=,582(M\)!#HQL___T'_QD$/MH6`````1#GP?]Y(@\086UU!
+M7$%=05Y!7\-F9F:09F:005=!5D%505154TB#[%A(B7PD2$F)]TB)5"1`2(L&
+M2(E$)#B^``````^WD)````!F@?J!`+B`````#T/09HE4)"!!]D<@('1$#[?*
+M2(M<)$!(BU,02(MT)#CHDKG__TB)QKC_____2(7V#X2C`P``0<:'@`````%)
+MB7=83(F^,`P``+@`````Z88#``!(BT0D0$@/ME`B2(G!2(L`2(G3N@````!(
+M]_-!B=9(BT0D.$@/ME!X2(M!"$B)T;H`````2/?Q2(M<)$`/MD,B*-"(1"0?
+M03C&08#>_TB+1"0X#[>0D````(U"_P^W2Q@AP4&)U&9!*<QF1#EC(',%1`^W
+M8R!!QH>``````$'&AX$`````QT0D&`$````/MT0D(/?82)A(B40D$`^WP4F)
+MQ4B+5"1`3`-J$$B+3"1(2('!8%D``$B)3"0(2(M<)$A(@<-060``2(D<)(M$
+M)"#_R$0AZ(M<)"!F*<-F1#GC00]'W$B+;"003"'M@WPD&``/A'0!``#'1"08
+M`````(M4)"!(BT0D.&8YD)````!V++H`````00^VAX````")P8/X`'X82&/"
+M28MTQUA(.6Y`#X0T`0``_\(YT7_H#[=,)"!(B>I(BW0D.$B+?"1(Z!&X__](
+MB<9(A<`/A=T```!!_H^`````08"_@````/\/A+X```!,BU0D"$R+#"1)#[:'
+M@````$F+=,=82,>&,`P```````!)B?"Y`````(!^2@!V1)`/ML%(P>`$3`'`
+M2(V0\`H``+\`````@[CP"@```'43@WH$`'4-@WH(`'4'@WH,`)!T!;\!````
+MA?]U)?_!03A(2G>]N`````"%P'0;28M""$F)<@A,B19(B48(2(DPZQFX`0``
+M`.OA28M!"$F)<0A,B0Y(B48(2(DP0?Z/@````$&`OX````#_#X5+____N/__
+M___I2@$``$$/MH>`````#[;028ETUUC_P$&(AX````!,B;XP#```QH9@#```
+M",:&80P```!$B?$/MM%$B>AF*>AFB8260`P``&:)G)9"#```1#BV8`P``'8'
+M1(BV8`P``$0XMF$,``!S!T2(MF$,``!(BT0D0&8I6"!F02G<=!,/M\-)`<7'
+M1"08`0```.D#_O__2(M4)$!F@WH@``^$J0```+D`````0?_&1#IT)!\/E,!!
+M`<9(BUPD.$0X<WAU0X!\)!\`=`;^3"0?ZPU(BT0D0`^V0"*(1"0?@'PD'P!!
+M#Y3&2(M4)#A(#[>"D````$B+7"1`2`%#$,=$)!@!````ZQZ+5"0@2(M$)#AF
+M.9"0````N`$````/1D0D&(E$)!A(BUPD0$0/MV,@2(M$)#AF1#N@D`````^&
+M)_W__T0/MZ"0````Z1K]__^X`````$B#Q%A;74%<05U!7D%?PV9F9I!F9F:0
+M9F9FD&9FD$B#[`B%TG08QD8A"TB)\DC'Q@````#H`````.L(9F:0Z"OV__](
+M@\0(PV9FD&9FD$%455-(@^PP28G\2(GU2(L>]D,!!'49QD8A`DB+=CA(B>KH
+M`````.ED`@``9F9FD$B#>U@`=2F^!P```&9F9I#H2Z[__TB)QTB)0UBZ`!``
+M`+X`````Z`````!F9I!FD`^V12"H(`^%U````*@&=1C&12$!2(MU.$B)ZDR)
+MY^@`````Z0@"``#V12`$="=(@WM(`'0@2(M34$B+<TA,B>?H`````$C'0T@`
+M````0?^,).!9``!(BWT(2(E\)!@/MT409HE$)"`/MD-X_\B(1"0B#[9+>DB)
+M^$C3Z$B)!"1(#[9T)"*Z`````$CW]DB)1"0(#[9+>DC3X$B)1"00#[>3D```
+M``^V3"0B2`^W1"0@2`'X2`^O="002"GP#Z_12(U$$/](B=&Z`````$CW\4@/
+MMY.0````#Z_0ZSAF9F:0]H.2`````708QD4A!DB+=3A(B>I,B>?H`````.DO
+M`0``#[>3D````(G02`^O10A(B40D$(G12(M4)!!(`=%(B=Y,B>?HM[#__TB)
+M15!(A<!U'DC'15``````2(U[,$B)[N@`````Z>4```!F9I!FD$B)XDB)[DR)
+MY^CB^?__A<`/A(H```!(BW503(GGZ/ZO__]!BXPDN$0``$$YC"2\1```=$9(
+M8\%(P>`$2H&\()@B````````=''_P4ACP4AIP/$`#_!(P>@@C00!B<;!_@F)
+MR)F)\"G0:<`B`@``*<%!.8PDO$0``'6Z2,=%4`````!)C;PDZ%D``$B)[N@`
+M````3(GGZ`````#K1&9F9I#V12`$="E(Q\(`````2(GN3(GGZ/BS___K)L9%
+M(05(BW4X2(GJ3(GGZ`````#K$4B)[DR)Y^B6\___9F:09F:02(/$,%M=05S#
+M9F9FD&9FD%532(/L"$B)_4B)\TB#?E@`=%%(B??H`````+D`````2&/12(M#
+M6$B+!-!(A<!T$4C'0"``````2(M`*$B%P'7O_\&!^?\!``!VU4B+<UBZ!P``
+M`$B)[^BTJ___2,=#6`````!(@\0(6UW#9F:09I!!5%532(G[QX=(60``````
+M`$B-AU!9``!(B8=060``2(F'6%D``$B-AV!9``!(B8=@60``2(F':%D``$B-
+MAW!9``!(B8=P60``2(F'>%D``(L%`````,'@#(G"N*NJJJI(#Z_"2,'H($&)
+MQ$'![`]$B>*^:`P``.A$J___B<5!C50D(+X@````2(G?Z#"K__\!Q8L5````
+M`,'B#,'J#KZ(````2(G?Z!6K__\!Q;H(````O@`0``!(B=_H`:O__P'%2(G?
+MZ`````!(B04`````_\4[+0````!S-V9FD&9FD$B)W^@`````2(G"2(7`="%(
+MBX/060``2(D"2(F3T%D``/^#V%D``/_%.RT`````<L];74%<PV9F9I!F9I!F
+M9I!54TB#[`A(B?5(BUX(#[9.`[@!````B<+3XH!F`?M(QX.8`````````$BX
+M```"`/__``!((X.0````2#T```(`=!-F@[N4`````'0T9H63E````'4K9@F3
+ME````(!C`?M(@WMP`'0)2(G>_U-P9F:0@*.2````'^G4````9F9FD`^V@Y(`
+M``!FB9.4````_DMY2,>#F`````````"#R`6(@Y(```"$P'D.@^!_B(.2````
+MZ9D```"`HY(```"?2(G>Z`````!(B<)(A<!T8,8``P^V10.(0@-(B5H(@$H!
+M"$B+!0````!(B4)H2(L%`````$B)0G!(QT4(`````$@/MD(#2(F4PZ`````/
+MMH.2````@^#^@\@*B(.2````_D-Y2(G6OP<```#H`````$B#>P@`=`M(BUL(
+M2(-["`!U]>@`````B4-\2(G?Z`````!(@\0(6UW#9F:09F:09F:0N@````#_
+MSH/^_W039F9FD`^V!P'"2/_'_\Z#_O]U\0^VPL-F9F:09F:09F:09F:055-(
+M@^P(2(G[@#\#=EN]`````(!_>`!T1V9F9I!F9I!(8_5(@[SSH`````!T*$B+
+MC/.@````#[93`8/B`0^V00&#X/X)T(A!`4B+O/.@````Z`````#_Q0^V0W@Y
+MZ'_`@*.2````^^L'Z!(```!FD$B#Q`A;7<-F9I!F9I!F9I!!54%455-(@>P(
+M`@``28G\0;T`````2(GE@']X``^$6`(``$B+7PA(A=MT#DB#>P@`=`=)B=U(
+MBUL(N@`"``"^`````$B)[^@`````QT4`\Q9X6K@`````2(7;=`.+0WR)101!
+M@+PD@`````!T$(!-"0)!#[:$)(,```"(10I!#[94)'R^`0```"'6#[:%DP``
+M`(/@_(G1@^$""?`)R+X$````(=:#X/.)T8/A"`GP"<B^$````"'6@^#/B=&#
+MX2`)\`G(B=&#X4"#X#^#XH`)R`G0B(63````0?9$)`$!=`2`30D!N`````!(
+MA=MT"4F#_0$9P(/``HA%"TB%VP^$O@```$B+0QB)10R+0QR)A90````/M@.(
+M11`/MD-XB$41387M=`=!#[9%`^L&00^V1"0#B$42#[9#>HA%$_:#D@````)T
+M!(!-%`$/MX.4````9HE%%DB+@Y@```")11B+@YP```")A9@```!(C;/@````
+M2(U]++H0````Z`````!(C;/P````2(U]/+H$````Z`````!(C;,T`0``2(V]
+M@````+H0````Z`````!(C;/T````2(U]0+I`````Z`````!-A>UT8TF+11B)
+M11Q!BT4<B86<````00^V10"(12!!#[9%>(A%(4$/MD0D`XA%(D$/MD5ZB$4C
+M0?:%D@````)T!(!-)`%!#[>%E````&:)129)BX68````B44H08N%G````(F%
+MH````$B%VW4(00^V!"2(11"^D````$B)[^@`````]]B(10B^``(``$B)[^@`
+M````]]B(A9````!!B[0DD````(/N"DF-?"1X2(GINC````#H`````$B!Q`@"
+M``!;74%<05W#9F9FD&9FD$B)^(`_`W8XN@````"`?W@`=!@/MD]X2&/"2(.\
+MQZ``````=0S_PCG1?^RX`````,-(B[S'H````.@`````9I#SPV9F9I!F9F:0
+M9F:09F:055-(B?N`/P-V-KT`````@']X`'0O2&/%2(.\PZ``````=`U(B[S#
+MH````.@`````_\4/MD-X.>A_V^L(9F9FD(!G`?Y;7<-F9I!F9I!F9I!(BT\0
+MN@````!F9F:09F:0B=!(.3S!=0E(QP3!`````,/_PH/Z!W;H\\-F9I!F9I!(
+MB?>`9@'[Z`````#SPV:0055!5%532('L"`0``$F)_$B-G"0``@``2(G]#[9'
+M`:@$#X0O`0``@#\"#X8F`0``@^#]B$<!N@`"``"^`````$B)W^@`````08`\
+M)`,/A(L```!(B>!(BZV@````08`\)`AU<$B%[70,9D&#O"24`````75?2(G%
+M0;T!````00^V1"1X@_@!?FM)8\5)B[S$H````$B#QWA(B>FZ(````+X`````
+MZ`````"Y`````)!(8]&+!),S1)4`B023_\&#^7]^[$'_Q4$/MD0D>$0YZ'^W
+MZR"`?0`##X5X____2(U]>$B)V;H@````O@````#H`````&:!N_X!``!5JG57
+M@[O*`0```'0=@7L&3$E,3W0,@;MV`0``1U)50G4(08!,)`$"ZS%!O0````!)
+M8\5(P>`$2`'8@+B^`0``@'4/@[C*`0```'0&08!,)`$"0?_%08/]`W[52('$
+M"`0``%M=05Q!7<-F9F:09F9FD&9F9I!$BX>4(@``18U(`4ECP4AIP/$`#_!(
+MP>@@08T$`<'X"42)R<'Y'RG(:<`B`@``02G!36/`2<'@!$F)=#AP2&.'E"(`
+M`$C!X`1(B50X>$2)CY0B``##9F9FD&9F9I!F9I!32(/L$$B)^XN'D"(``#N'
+ME"(``'1BBXN0(@``2&/!2,'@!$@!V$R+0'!,B00D2(MP>$B)="0(_\%(8\%(
+M:<#Q``_P2,'H((T$`8G'P?\)B<B9B?@IT&G`(@(``"G!B8N0(@``2(G?0?_0
+MBX.0(@``.X.4(@``=9Y(@\006\-FD$2+A[Q$``!%C4@!26/!2&G`\0`/\$C!
+MZ"!!C00!P?@)1(G)P?D?*<AIP"("``!!*<%-8\!)P>`$28FT.)@B``!(8X>\
+M1```2,'@!$B)E#B@(@``1(F/O$0``,-F9I!FD%-(@^P02(G[BX>X1```.X>\
+M1```#X2#````9F:09F:0BXNX1```2&/!2,'@!$B-A!B0(@``2(M0"$B)%"1(
+MBT`02(E$)`C_P4ACP4AIP/$`#_!(P>@@C00!B<;!_@F)R)F)\"G0:<`B`@``
+M*<&)B[A$``"#N]Q9````=`A(B=_H`````$B+="0(2(G?_Q0DBX.X1```.X.\
+M1```=8-(@\006\-F9F:09F:09F:09F:04[@`````2(-_:`!T($B+7VA(BP-(
+MB4=HNJ````"^`````$B)W^@`````2(G86\.02(M':$B)!DB)=VC#9F9FD$B#
+M/P!T&DB+!TB+0$A(B49(2(L'2(EP2.L*9F:09F:02(EV2$B)-\-F9F:09F9F
+MD$B#["A(B5PD"$B);"003(ED)!A,B6PD($F)_4B)]4B#/@!T/4R+)DB+10!(
+MBUA(2#G8=0Q(QT4``````.L.9I!(BU4`2(M#2$B)0DA(B=Y,B>__4U!,.>-T
+M!TB#?0``=<9(BUPD"$B+;"003(MD)!A,BVPD($B#Q"C#9F:09F:02(/L"(`_
+M"'4'Z`````!FD$B#Q`C#9F9FD&9F9I!F9I!(@^P(2(GQ2(M'$(`_"'4'Z```
+M``#K"TB)UDB)QV9FD/_12(/$",-F9I!F9I!F9I!(@^QH2(E<)#A(B6PD0$R)
+M9"1(3(EL)%!,B70D6$R)?"1@28GT28G/08G52(MO,$0/MC=!#[;>B=Y(B>_H
+M`````+H`````B=Y(B>_H`````,<$)`````!!N0````!!N`````"Y`````+H#
+M````B=Y(B>_H`````+H`````A<`/A+T```!!]\0```#P#Y7`#[;(08#],`^4
+MP$0/MM!!_\)!#[;V00^VQ87)=!%!@/T@NC0```"X)`````]%PHE$)#"X0```
+M`(7)=0E$B>#!Z!B#R$")1"0H3(G@2,'H$`^W^$`/ML>)1"0@3(G@2,'H"`^V
+MP(E$)!A!#[;4#[?"A<ET"8GX)0#_```)T(E$)!#'1"0(`0```,<$)`````!!
+MN0`!``!-B?A$B=)(B>_H`````(G#00^V]DB)[^@`````B=J)T$B+7"0X2(ML
+M)$!,BV0D2$R+;"103(MT)%A,BWPD8$B#Q&C#9F9FD&9FD&9FD(GX@^`#P>`-
+M!0`@``!`]L<$=`T%```#`,-F9F:09F:0!0```@##9F9FD&9FD&9FD$%455-)
+MB?R)];\@H0<`Z`````"[(*$'`$`/MOWHK____XVH'`$``$F+?"00B>[H````
+M`(3`>`FX`0```.L?9I"_$"<``.@`````@<,0)P``@?L_2TP`=L^X`````%M=
+M05S#9F9FD&9F9I!F9I!F9I!(@^P82(E<)`A,B60D$$F)_$`/MO[H1O___XG#
+MC7,(28M\)!"Z`````.@`````C7,,28M\)!"Z&`$``.@`````2(M<)`A,BV0D
+M$$B#Q!C#D%-(B?M`#[;^Z`/___^-<`Q(BWL0N@````#H`````%O#28G1N@``
+M``!,C4<*BT$0B0>+012)1P2#.0"X`0````]$T$$/MD$$`<`)PF:)5PB+AD0"
+M``"%P`^4PH/X`@^4P`G0J`$/A&8!``"#>00!#X7<````9@^V00^`S!%F08D`
+M28/``F8/MD$.@,P19D&)`$F#P`)!#[9!!,'@`V8E^`"`S!)F08D`28/``F8/
+MMD$+@,P39D&)`$F#P`)F#[9!"(#,$V9!B0!)@\`"9@^V00R`S!1F08D`28/`
+M`F8/MD$)@,P49D&)`$F#P`)F#[9!#8#,%69!B0!)@\`"9@^V00J`S!5F08D`
+M28/``F9!QP!`%DF#P`*#.0!U&8.^1`(```*Z)@```+A@````#T7"Z:`!``"#
+MOD0"```"NC8```"X80````]%PNF'`0``9F9FD&8/MD$.@,P19D&)`$F#P`)!
+M#[9!!,'@`V8E^`"`S!)F08D`28/``F8/MD$(@,P39D&)`$F#P`)F#[9!"8#,
+M%&9!B0!)@\`"9@^V00J`S!5F08D`28/``HM!""4````/P>@89@U`%F9!B0!)
+M@\`"@SD!&<"#X/N#Z#3I!0$``&:0@WD$`0^%EP```&8/MD$/@,P29D&)`$F#
+MP`)F#[9!#H#,$F9!B0!)@\`"9@^V00N`S!-F08D`28/``F8/MD$(@,P39D&)
+M`$F#P`)F#[9!#(#,%&9!B0!)@\`"9@^V00F`S!1F08D`28/``F8/MD$-@,P5
+M9D&)`$F#P`)F#[9!"H#,%69!B0!)@\`"9D''`$`628/``H,Y`1G`@^#P@\`U
+MZV)F#[9!#H#,$F9!B0!)@\`"9@^V00B`S!-F08D`28/``F8/MD$)@,P49D&)
+M`$F#P`)F#[9!"H#,%69!B0!)@\`"BT$()0````_!Z!AF#4`69D&)`$F#P`*#
+M.0$9P(/@_H/H-F8/ML!F#0"79D&)`,-(@^Q(2(E<)!A(B6PD($R)9"0H3(EL
+M)#!,B70D.$R)?"1`B?")5"042(G-3(MG$`^VP$B+1,<P1(MH/$&-A2`!``")
+M1"00N@````")QDR)Y^@`````08VU!`$``$R)Y^@`````B$4`08V%"`$``(E$
+M)`R)QDR)Y^@`````9@^VP&:)10)!C9T,`0``B=Y,B>?H`````&8/ML!FB44$
+M18V]$`$``$2)_DR)Y^@`````9@^VP&:)109%C;44`0``1(GV3(GGZ`````!F
+M#[;`9HE%"(-\)!0!=6JZ@````(MT)!!,B>?H`````(MT)`Q,B>?H`````,'@
+M"&8)10*)WDR)Y^@`````P>`(9@E%!$2)_DR)Y^@`````P>`(9@E%!D2)]DR)
+MY^@`````P>`(9@E%"+H`````BW0D$$R)Y^@`````08VU&`$``$R)Y^@`````
+MB$4*08VU'`$``$R)Y^@`````B$4+2(M<)!A(BVPD($R+9"0H3(ML)#!,BW0D
+M.$R+?"1`2(/$2,-F9F:09F:02(/L:$B)7"0X2(EL)$!,B60D2$R);"103(ET
+M)%A,B7PD8$F)_XGS9HE4)!X/ML-,BW3',$&+=CR#QC!(BW\0Z`````!(B<6#
+MY1](C42M`$C!X`1*C:PP4`(``(-]``%T74B-12!(B40D$$R-9"0@BU`$1`^V
+MZTR)X42)[DR)_^CL_?__0?Z.90P``$B+7"002(M+($F+?C!,B20D0;D`````
+M1`^W1"0>N@$```!$B>[_4QA(B>Y,B??H(A,``$B+7"0X2(ML)$!,BV0D2$R+
+M;"103(MT)%A,BWPD8$B#Q&C#9F9FD&9F9I!F9F:09F:02(/L:$B)7"0X2(EL
+M)$!,B60D2$R);"103(ET)%A,B7PD8$F)_T&)]<=$)!0`````B?$/ML%(BVS'
+M,$&^``````^W`F:)1"082(U,)!@/MT("9HE!`HM"!(E!!`^W1"082(G#@^,?
+M2(T$FTC!X`1(C9PH4`(```^W00*$P'0JQT0D%`$````/MT$"1`^V\&9!@<X`
+M`<>%8`P```````#'A4`"````````3(UC($B-1"08#[=``J@$=!=(C4PD($&+
+M5"0$00^V]4R)_^BQ_/__D(,[`0^$EP```/Z-90P``$B-1"081(M(!$F+3"0@
+M10^V[4B+?3!(C40D($B)!"1%#[?&BU0D%$2)[D'_5"082(G>2(GOZ-<1``"#
+MO6`,````=$Y(@[U0#````'1$2(N%4`P``(-X&`%U-T2)[DR)_^@L%```2(NU
+M4`P``$B)[^A]%0``A<!U&4B+M5`,``"Z`0```$B)[^CU!@``9F:09I!(BUPD
+M.$B+;"1`3(MD)$A,BVPD4$R+="183(M\)&!(@\1HPV9F9I!F9I!F9I!F9I!(
+M@^PH2(E<)`A(B6PD$$R)9"083(EL)"!(B?N)]4&)U4B+?Q"^+`T``.@`````
+M08G$B<*#R@%(BWL0OBP-``#H`````$B+>Q"^+`T``.@`````2(M[$+[P!`$`
+MZ`````")ZO?2(=!$">A(BWL0B<*^\`0!`.@`````2(M[$+[P!`$`Z`````!(
+MBWL01(GBOBP-``#H`````$B+7"0(2(ML)!!,BV0D&$R+;"0@2(/$*,-F9F:0
+M9F9FD&9F9I!F9I!(@^Q(2(E<)!A(B6PD($R)9"0H3(EL)#!,B70D.$R)?"1`
+M28G^08G,1(E,)!1(BT<02(E$)`C'1"0$`````$2-/+4`````00G71(GZ#[;"
+M3(MLQS!%A<!T<DV%[0^$UP```$&+G?`,``!"C13E`````$$+52Q!BW4\@\8D
+M2(M\)`CH`````$0YXW0C00^V[Y")VDF+11A(C130B>Y,B??H_/S____#@^,?
+M1#GC=>)!@[U@#````+@!````#T5$)`2)1"0$08F=\`P``(-\)!0`#Y7"@WPD
+M!``/E<`)T*@!#X3P`0``00^V_^AB]O__1(U@"$2)YDB+?"0(Z`````")Q0^W
+MV(G:]])$B>9(BWPD".@`````]L,(#X0<`0``387M=!9!QX5@#````````$''
+MA4`"````````08.^D`````%T"D&#OI0````!=12^``$``$2)^=/FB?),B??H
+MW_W__T&#OHP````!=!1!@[Z0`````70*08.^E`````%U#D$/MO=,B??HQ0D`
+M`.M_08.^B`````%T"D&#OHP````!=6M!#[;?B=_HI/7__T2-8"BZ!````$2)
+MYDB+?"0(Z`````!$B>9(BWPD".@`````OQD```#H`````+H`````1(GF2(M\
+M)`CH`````$2)YDB+?"0(Z`````"_T`<``.@`````B=Y,B??H!`@``$$/MM^)
+MWDR)]^@`````A<`/A;,```")V;H`````O@$```!,B?=!_U8HZ9L```!`]L40
+M=$Y!#[;W3(GWZ,0'``!!@[Z0`````70*08.^E`````%U%[X``0``1(GYT^:Z
+M`````$R)]^C)_/__00^VS[H!````O@$```!,B?=!_U8HZT</M]7VQ@%T/T&#
+MO4`"```!9I!U(D''A6`,````````0<>%0`(```````!!#[;W3(GWZ.SY__^#
+M/0`````!=0A,B>_H2Q$``$B+7"082(ML)"!,BV0D*$R+;"0P3(MT)#A,BWPD
+M0$B#Q$C#9F9FD&9F9I!(@^P(28GXC0RU``````G1#[;!2(M\QS!(A?]U$P^V
+M\4R)Q^BH#@``ZTMF9I!F9I!(B[=0#```2(7V=10/MO%,B<?HB0X``.LL9F9F
+MD&9FD(,^`70-@WX8`69F9I!F9I!T#@^V\4R)Q^AC#@``ZP:0Z`L```!(@\0(
+MPV9FD&9FD$B#[#A(B5PD"$B);"003(ED)!A,B6PD($R)="0H3(E\)#!)B?Y)
+MB?=(BT<P3(M@$(MO/$&]`P```$0B+P^V'X/C!,'K`HVU(`$``$R)Y^@`````
+MC;4<`0``3(GGZ`````")Q;H``0``1(GIT^+WTH#[`1GV9KX``('&%``#`$R)
+MY^@`````0(3M#X@'`0``0/;%`70;N@$```!,B?Y,B??HVP$``.GL````9F:0
+M9F:008M'((/X`70L@_@!9F9FD'(.@_@"=';IR@```&9F9I"Z`````$R)_DR)
+M]^B@`0``Z;$```!`]L5`=$!)C7<@3(GWZ,D```"#^`%U'4&#?S``#X6/````
+MN@````!,B?Y,B??H:0$``.M]N@$```!,B?Y,B??H5P$``.MKN@$```!,B?Y,
+MB??H10$``.M90`^VQ:A`=$&H('4]08-_,`!FD'42N@````!,B?Y,B??H'@$`
+M`.LR28UW($R)]^A0````A<!U(KH!````3(G^3(GWZ/P```#K$+H!````3(G^
+M3(GWZ.H```!(BUPD"$B+;"003(MD)!A,BVPD($R+="0H3(M\)#!(@\0XPV9F
+M9I!F9I!!5%5328G\2(GSN`````"!?A#_````#X:?````BQ:#^@%T6+@`````
+M@_H!#X**````@_H"#X5\````O0````"02(M#"`^W$$B#P`)(B4,(08MT)#R!
+MQ@`!``!)BT0D,$B+>!#H`````/_%@?W_````=LZ!:Q```0``ZSN]`````$&+
+M="0\@<8``0``28M$)#!(BW@0Z`````!(BU,(9HD"2(-#"`+_Q8']_P```';1
+M@6L0``$``+@!````6UU!7,-(@^Q(2(E<)"!(B6PD*$R)9"0P3(EL)#A,B70D
+M0$B)_4F)]$&)U4&^`````$B-7B!(C4PD$(M3!`^V-TB+?S#HW/3__T&#_0%U
+M#4&V`<>%8`P```````!(BTLH#[9U`$B+?3!(C40D$$B)!"1!N0````!!N```
+M``!$B?+_4R!,B>9(B>_H!PH``$&#_0%U$8,]``````%U"$B)[^B`#0``2(.]
+M4`P````/A*,```!(B[50#```@WX8`74F2(GOZ*T-``"%P`^%A@```$B+M5`,
+M``"Z`0```$B)[^@A____ZW"#O40"````=2H/MG4`2(M],.C9"@``BW4\@\8H
+M2(M%,$B+>!#H`````+\!````Z``````/MG4`2(M],.@/"P``2(N=4`P``$B%
+MVW0D@WL8`'4>2(U3($B)WDB)[^AN#```2(M;"$B%VW0&@WL8`'3B2(M<)"!(
+MBVPD*$R+9"0P3(ML)#A,BW0D0$B#Q$C#D$%505154TB#[`A(B?M(BT<P3(M@
+M$$2+;SQ!C6THB>Y,B>?H`````*@$=#&Z`@```(GN3(GGZ`````")[DR)Y^@`
+M````O]`'``#H``````^V,TB+>S#H1@(``.L108UU*+H"````3(GGZ`````#&
+M@T@"````QH-D#````,:#90P```#'@^P,````````QX/P#````````,>#0`(`
+M``````#'@^@,```@````N@````"02&/"B92#:`P``/_"@_H??N^Z`````$AC
+MPDB-!(!(P>`$QX084`(```$```#_PH/Z'W[C2,>#4`P```````!(QX-8#```
+M`````,>#8`P```````!!C74(N@````!,B>?H`````$&-=0RZ&`$``$R)Y^@`
+M````BU,@08UU$$R)Y^@`````BU,D@>(`_/__08UU%$R)Y^@`````2(M#,+H`
+M````@[BD`````'0#BU,D08UU&$R)Y^@`````BU,H08UU'$R)Y^@`````2(M#
+M,+H`````@[BD`````'0#BU,D08UU($R)Y^@`````BU,LL@!!C74D3(GGZ```
+M``"X`0```$B#Q`A;74%<05W#9F:09I!!5T%6055!5%532(/L.$B)^XE4)!Q!
+MB<^%]@^%H@```+T`````3(UT)"!F9I!F9I!(8\5(C02`2,'@!$@!V(.X4`(`
+M``!U<$B-D&`"``"#>@@!=1.+4A1,BZ"8`@``3(NHD`(``.LB2&/%2(T$@$C!
+MX`1(`=B+D'0"``!,BZ"0`@``3(NHB`(```^V,TB+>S!,B?'H6/'__P^V,TB+
+M>S!,B30D0;D`````10^WQTR)X8M4)!Q!_]7_Q8/]'P^.;O___TB#Q#A;74%<
+M05U!7D%?PV9F9I!F9F:09F9FD&9FD$B#["A(B5PD"$B);"003(ED)!A,B6PD
+M($B)^XGUB>B#X`1!B<5!P>T"0;P#````02'L@[^(`````70)@[^,`````75:
+M00^V],'F"('&#`$``(V&```#`('&```"`$6$[0]%\$B+>Q#H`````(G!@^'\
+M@\D!00^V],'F"('&#`$``(V&```#`('&```"`$6$[0]%\$B+>Q")RN@`````
+M00^V],'F"('&=`$``(V&```#`('&```"`$6$[0]%\$B+>Q#H`````(G!@.$?
+MB>@/MM`/MH0:M0```,'@!27@````"<&`Y></MH0:O0```,'@"R4`&```"<%!
+M#[;TP>8(@<9T`0``C88```,`@<8```(`183M#T7P2(M[$(G*Z`````!(BUPD
+M"$B+;"003(MD)!A,BVPD($B#Q"C#9F:09F:02(/L&$B)'"1,B60D"$R);"00
+M2(G[1`^V[D2)[^C?Z___1(U@*$2)[DB)W^C`[/__2(M[$+H$````1(GFZ```
+M``!(BWL01(GFZ`````"_&0```.@`````2(M[$+H`````1(GFZ`````!(BWL0
+M1(GFZ`````!$B>Y(B=_H0?[__T2)[DB)W^@6[/__2(L<)$R+9"0(3(ML)!!(
+M@\08PV9FD$%7059!54%455-(@^P(2(G]QD0D!P!!O@`````/MD0D!T2-/(4`
+M````9F9FD&9FD$.-!#Y$#[;H1(GOZ"#K__]!B<1!C5PD*$B+?1"Z`@```(G>
+MZ`````!(BWT0B=[H`````$2)[DB)[^CR_O__2(M]$+H`````B=[H`````$B+
+M?1"Z'P$``$2)YN@`````08UT)`1(BWT0N@````#H`````$&-="0(2(M]$+H`
+M````Z`````!!C70D#$B+?1"Z`````.@`````08UT)!!(BWT0N@````#H````
+M`$&-="042(M]$+H`````Z`````!!C70D&$B+?1"Z`````.@`````08UT)!Q(
+MBWT0N@````#H`````$&-="0D2(M]$+H`````Z`````!!C70D($B+?1"Z````
+M`.@`````08UT)"Q(BWT0N@````#H`````$&-="0T2(M]$+J\````Z`````!!
+M_\9!@/X##X;#_O__@'PD!P$9VV:[``"!PP```P"-<PQ(BWT0N@````#H````
+M`(US$$B+?1"Z`````.@`````C7,42(M]$+H`````Z`````"-<QA(BWT0N@``
+M``#H`````(/#($B+?1")WN@`````)1P<'!P-`P,#`TB+?1")PHG>Z`````#^
+M1"0'@'PD!P$/AB#^__](@\0(6UU!7$%=05Y!7\-F9F:09F9FD&9FD$B#[`A(
+MBW\0NO__SP^^;`0!`.@`````2(/$",-F9F:04TB)^XM'!+``/0``@%!T(4B+
+M?Q"^+`T``.@`````@\@!2(M[$(G"OBP-``#H`````$B+>Q"^``T``.@`````
+M)?__`/](BWL0B<*^``T``.@`````2(M[$+H`````O@0-``#H`````$B+>Q"Z
+M`````+XX#```Z`````!(BWL0NO\``0"^!!T``.@`````2(M[$+H`````OF0=
+M``#H`````$B+>Q"Z`````+XH#```Z`````!(BWL0N@````"^6!T``.@`````
+M2(M[$+H`````OEP=``#H`````$B+>Q"Z`````+Y`'0``Z`````!(BWL0N@``
+M``"^1!T``.@`````2(M[$+H`````OD@=``#H`````$B+>Q"Z`````+Y0'0``
+MZ`````!;PV9FD&9FD&9FD$C'1@@`````2(N'6`P``$B)1A!(@[]8#````'0+
+M2(N'6`P``$B)<`A(B;=8#```2(._4`P```!U!TB)MU`,``#SPV9F9I!F9F:0
+M9F:09F:02(-^"`!U&DB+1A!(B8=8#```2(7`=!9(QT`(`````.L,2(M6"$B+
+M1A!(B4(02(-^$`!U'$B+1@A(B8=0#```2(7`=!A(QT`0`````.L.9I!(BU80
+M2(M&"$B)0@A(QT8(`````$C'1A``````PV9FD$B#[!A(B1PD2(EL)`A,B60D
+M$$F)_$B)]4B)TX,Z`'442(UR"$B-?2"Z*````.@`````ZQI(C7((2(U](+HP
+M````Z`````!!_H0D9`P``(L#B4482(GN3(GGZ.+^___'10``````0?Z$)$@"
+M``!(BQPD2(ML)`A,BV0D$$B#Q!C#2(/L$$B)'"1(B6PD"$B)^TB)]8-^&`!T
+M!OZ/9`P``$B)[DB)W^CF_O__BX/H#```B<$/ME4$B92+:`P``/_`B8/H#```
+MQT4``0```/Z+2`(``$B+'"1(BVPD"$B#Q!##0(#_`W810`^VSXU,"0*X`0``
+M`$C3X,-`#[;/C4P)`;@!````2-/@PV9F9I!F9F:005154TF)_(N?@````$`/
+MMNZ)[^BX____"=A!B80D@````(GOZ`?F__^-L!P!``!)BWPD$.@`````B>F#
+MX0.Z``$``-/B]]*)Z(/@!,'X`H/X`1GV9KX``('&%``#`$F+?"00Z`````!)
+MBWPD$+YD'0``Z``````YV'4F08N4)(````!)BWPD$+YD'0``Z`````!)BWPD
+M$+YD'0``Z`````!;74%<PV9F9I!F9I!F9I!(@^P82(E<)`A(B6PD$$B)_8N?
+M@````$`/MO[H`/____?0(=B)A8````!(BWT0OF0=``#H`````#G8=12+E8``
+M``!(BWT0OF0=``#H`````$B+7"0(2(ML)!!(@\08PY!(@^PH2(D<)$B);"0(
+M3(ED)!!,B6PD&$R)="0@28G^B?-,BV\0#[;#3(MDQS!!BVPD/$''A"1``@``
+M`0```(G8@^`$P>@"B=F#X0.Z`0$``-/B]](\`1GV9KX``('&%``#`$R)[^@`
+M````08MT)#R#Q@BZ`````$R)[^@`````#[;S3(GWZ!;___^-M1P!``!,B>_H
+M`````$''A"1,`@```0```(UU*+H!````3(GOZ`````!(BQPD2(ML)`A,BV0D
+M$$R+;"083(MT)"!(@\0HPV9F9I!F9F:09F9FD&9FD$%6055!5%5328G]08GV
+MO0````!,BV<0B?(/ML)(BT3',(M8/,>`0`(```````"-<RBZ`@```$R)Y^@`
+M````@\,HB=Y,B>?H`````*@!=!:_Z`,``.@`````_\6!_><#``!VWNL-@?WG
+M`P``9F:09I!V#$$/MO9,B>_HPO?__T$/MO9,B>_HAOW__UM=05Q!74%>PV9F
+M9I!F9I!F9I!F9I!!5%-(@^P(2(G[2(G12(M',$R+8!"+O^P,``!(P><%2`-[
+M$$B)\DB)WNB"Y/__BX/L#```_\"#X!^)@^P,``#^@V4,``"+4R2!X@#\___!
+MX`4)PHMS/(/&%$R)Y^@`````2(/$"%M!7,-F9F:09F:04TB)^[D`````N@(`
+M``"^`````.CX]/__2(G?Z##S__](B=_H`````(/X`746QX-@#````0````^V
+M,TB+>S#HO?S__UO#9F9FD&9F9I!F9I!(@^PH2(E<)`A(B6PD$$R)9"083(EL
+M)"!)B?U,C68@2(M',$B+:!"+7SR-LQP!``!(B>_H`````"7!````N@````"#
+M^$`/A=H!``!!@WPD!`%U;4$/ME0D%8VS!`$``$B)[^@`````00^V5"07C;,(
+M`0``2(GOZ`````!!#[94)!F-LPP!``!(B>_H`````$$/ME0D&XVS$`$``$B)
+M[^@`````00^V5"0=C;,4`0``2(GOZ`````#K0V9F9I!F9I"X`/___V9!A40D
+M%'4E9D&%1"06=1UF085$)!AU%69!A40D&G4-9D&%1"0<9F:09I!T"KH`````
+MZ2D!``!!#[94)!2-LP0!``!(B>_H`````$$/ME0D%HVS"`$``$B)[^@`````
+M00^V5"08C;,,`0``2(GOZ`````!!#[94)!J-LQ`!``!(B>_H`````$$/ME0D
+M'(VS%`$``$B)[^@`````00^V5"0>C;,8`0``2(GOZ`````!!#[94)!^-LQP!
+M``!(B>_H`````$&#/"0"#X6-````C;,@`0``2(GOZ`````!!N,@```"Y$"<`
+M`+H!````O@````!,B>_H`````+H`````A<!T7HVS'`$``$B)[^@`````)8D`
+M``"Z`````(/X"'5!0;T`````@<,``0``28M$)`@/MQ!(@\`"28E$)`B)WDB)
+M[^@`````0?_%08']_P```';908%L)!```0``N@$```")T$B+7"0(2(ML)!!,
+MBV0D&$R+;"0@2(/$*,-(@^PH2(D<)$B);"0(3(ED)!!,B6PD&$R)="0@2(G[
+MQX>``````````$B+?Q"Z`````+YD'0``Z`````!(BWL0Z`````"(0P2X````
+M`(![!``/A`P#``#'@X@`````````QX.,`````````,>#D`````````#'@Y0`
+M````````QX.8`````````,>#G`````````#'@Z``````````QH.L`````;@`
+M````2(-[*``/A*\"``"X`````&:!>P:!4`^%G@(```^V4P6#^@$/A)$"``"#
+M^@%_"X72=!=F9I!FD.LL@_H"=!MF9I!F9I!F9I#K',>#C`````$```!F9F:0
+MZQ;'@Y`````!````ZPK'@Y0````!````O0````!F9I!`#[;5B="#X`/!X`@%
+M=`$``/;"!'0*C;````,`ZPAFD(VP```"`$B+>Q#H`````(GJ#[;*B<!(B<*!
+MXN````!(P>H%B)09M0```"4`&```2,'H"XB$&;T```#_Q4"`_0=VGDB)W^BV
+M\___2(G?Z+[U__](B=_HUO7__TB+>Q"Z`````+[P!`$`Z`````!(BWL0OBP-
+M``#H`````$&)Q4&#Y?Y(BWL01(GJOBP-``#H`````(.[L`````!U6TB+>Q"^
+M``T``.@`````J#!T18M#<*G@`P"`=`@E'_S_?XE#<(.[B`````%T&X.[C```
+M``%T$H.[D`````%T"8.[E`````%U$XM#<*@0=`R#X.^)0W#K!(-C<,^]````
+M`&9F9I!`#[;U2(G?Z!3Q____Q4"`_0=V[(M3<$B+>Q"^``P``.@`````BU-T
+M2(M[$+XH#```Z`````"+4WA(BWL0OEP=``#H`````+T`````B>D/ML&+5(,8
+M0(#]`1GV9KX``('&#``#`$B+>Q#H`````(GJ#[;"BU2#($"`_0$9]F:^``"!
+MQA```P!(BWL0Z`````#_Q4"`_0%VM,>#@````%6K!@"]`````$`/MO5(B=_H
+M3=[____%0(#]!W;LOU##``#H`````(.[D`````%T"8.[E`````%U1T&]````
+M`+T`````0;X``0``1`^VY42)YDB)W^@`````A<!U"T2)\$2)X=/@00G%_\5`
+M@/T'=MI$B>J^`/\``$B)W^@RY?__N`$```!(BQPD2(ML)`A,BV0D$$R+;"08
+M3(MT)"!(@\0HPTB#[`A(BW\0N@````"^9!T``.@`````N`$```!(@\0(PV9F
+M9I!F9F:09F9FD&9FD,<%``````$```##9F:09I#'!0``````````PV9FD&:0
+M2(/L&$B)7"0(2(EL)!!(B?V)\@^VPDB+7,<PN`````!(A=MT+$`/MO[HHMS_
+M_XE#/$B):S#'@V`,````````QX-``@```````$B)W^B?[/__2(M<)`A(BVPD
+M$$B#Q!C#B?`/ML!(BU3',+@`````2(72=`V#NF`,```!#Y7`#[;`\\-F9F:0
+M9F:09F:09F:055-(@^P(2(G]B?"#X`/!X`@%``$``$#VQ@1T"(V8```#`.L&
+MC9@```(`2(M]$(G>Z`````"#X`^#^`%T$X/X`7(^@_@#=#'K-V9F9I!F9I!(
+MBWT0B=[H`````+]`#0,`Z`````!(BWT0B=[H`````(/@#X/X`W4(N`$```#K
+M!I"X`````$B#Q`A;7<-F9F:005=!5D%505154TB#[#A(B?U!B?>)\@^VPDB+
+M5,<P2(M'$$B)1"0PN`````!(A=(/A,L!``"+0CR)1"0LN`````"#NF`,```!
+M#X2R`0``QT0D*`````#_1"0H@WPD*`IV#[@`````Z94!``!F9I!FD$$/MM^)
+MWDB)[^@R[___B=Y(B>_H&-S__X/C!$&)W$'![`)!O0````!$B?B#X`/!X`@%
+M"`$``$&)QHG"2(E4)"!(B50D&$B)5"00B<!(B40D"$$/ML>)1"0$08V&```#
+M`$&-M@```@!%A.0/1?!(BWT0Z`````")PX/C\(/+`4B+="0@C88```,`C;8`
+M``(`183D#T7P2(M]$(G:Z`````!(BW0D&(V&```#`(VV```"`$6$Y`]%\$B+
+M?1#H`````+\9````Z`````"#X_!(BW0D$(V&```#`(VV```"`$6$Y`]%\$B+
+M?1")VN@`````2(MT)`B-A@```P"-M@```@!%A.0/1?!(BWT0Z`````"_T`<`
+M`.@`````BUPD!(G>2(GOZ`````"%P'4<0?_%08/]`@^&(?___XG>2(GOZ)[:
+M___IG_[__XMT)"R!QAP!``!(BWPD,.@`````)<````"#^$!T$T$/MO=(B>_H
+M;]K__[@`````ZQA!#[;W2(GOZ%S:__^X`0```&9F9I!F9I!(@\0X6UU!7$%=
+M05Y!7\.02(/L*$B)'"1(B6PD"$R)9"003(EL)!A,B70D((GPB=5!B<X/ML!(
+MBUS',+D`````2(7;='%,BV\01(MC/+D`````@[M@#````71;1(GF3(GOZ```
+M``")PH7M=2=!C4;_N0`````\'W<]QX-$`@```````(/BP$$/ML;_R`G"@,X"
+MZQ#'@T0"```!````@>+`_?__@,X!1(GF3(GOZ`````"Y`0```(G(2(L<)$B+
+M;"0(3(MD)!!,BVPD&$R+="0@2(/$*,-F9F:09F9FD&9FD$B#[`B)\0^VP4B+
+M5,<PN`````!(A=)T)K@`````@[I@#````708QX)@#````0```$`/MO;H=_/_
+M_[@!````2(/$",-F9F:09F:09F:09F:02(/L"(GR#[;"N0````!(@WS',`!T
+M(`^VPDB+1,<PQX!@#````````$`/MO;H#_3__[D!````B<A(@\0(PV9FD%.)
+M\(G6#[;`2(M<QS"X`````$B%VW0MN`````"#NV`,```!=!^Y`````+H"````
+M2(G?Z.GI__](B=_H(>C__[@!````6\-F9F:09F:09F:0B?`/ML!(BU3',+C_
+M````2(72=`</MH)(`@``\\-F9I!(@^PH2(D<)$B);"0(3(ED)!!,B6PD&$R)
+M="0@28G]B?.)U4&)S(GR@^(#B=B#X`2)P<'I`D#VQ?AU!D'VQ/QT![@`````
+MZW@/ML+!X`B-D'0!``"-@@```P"!P@```@"$R4&)QD0/1/)(BW\01(GVZ```
+M```D'XGJP>(%@>+@````"="`Y.=$B>+!X@N!X@`8```)T$F+?1")PD2)]N@`
+M````#[;#1HBD*+T```!"B*PHM0```+@!````9F:09I!(BQPD2(ML)`A,BV0D
+M$$R+;"083(MT)"!(@\0HPV9FD$B#[!A(B1PD2(EL)`A,B60D$$B)^XGP0;P#
+M````02'$@^`$B<7![0)`@/T!&?9FO@``@<88``,`2(M_$.@`````00^VU(U*
+M&+H!````2-/B"=!`@/T!&?9FO@``@<88``,`2(M[$(G"Z`````!`@/T!&?9F
+MO@``@<88``,`2(M[$.@`````N`$```!(BQPD2(ML)`A,BV0D$$B#Q!C#9I!!
+M54%455-(@^P(28G\08GUO0,```!$(>U`#[;VB?.#XP3!ZP+HY^C__X#[`1GV
+M9KX``('&&``#`$F+?"00Z`````!`#[;-@\$82,?"_O___TC3PB'0@/L!&?9F
+MO@``@<88``,`28M\)!")PN@`````@/L!&?9FO@``@<88``,`28M\)!#H````
+M`$`/MO7!Y@B!Q@@!``"-A@```P"!Q@```@"$VP]%\$F+?"00Z`````"#X/"#
+MR`%`#[;5P>((C8H(`0``C9$```,`@<$```(`A-N)U@]$\4F+?"00B<+H````
+M`$$/MO5,B>?H(>C__[@!````2(/$"%M=05Q!7<.005=!5D%505154TB#[`A)
+MB?Q(B=-!B?5,BW\0B?(/ML)(BVS',$`/MM:)T(/@`\'@"`5T`0``]L($=`B-
+ML````P#K!HVP```"`$F+?"00Z`````")0UA(A>UU$,<#`````+@!````Z=,`
+M``!$BW4\00^V]4R)Y^@`````B0.X`0```(,[``^$LP```(N%8`P``(E#+(N%
+M1`(``(E#,`^VA4@"``"(0S2Y`````&9F9I")R@^V1"IVB$0:!/_!@_DG=NY$
+MB?9,B?_H`````(E#.$&-=A!,B?_H`````(E#/$&-=A1,B?_H`````(E#0$&-
+M=AA,B?_H`````(E#1$&-=AQ,B?_H`````(E#2$&-=B!,B?_H`````(E#3$&-
+M=B1,B?_H`````(E#4$&-=BA,B?_H`````(E#5+@!````2(/$"%M=05Q!74%>
+M05_#9F:02(/L*$B)'"1(B6PD"$R)9"003(EL)!A,B70D($F)_DF)U8GS#[;#
+M2(MLQS"X`0```(.]8`P````/A$<!``"X`@```("]2`(``!\/A#4!``#_C>@,
+M``"+A>@,``"+C(5H#```08G,2XT$I$C!X`1,C:0H4`(``$&(3"0$@SH`#X6N
+M````2(U""(.]1`(```)U#\=`!`$```#K-F9FD&9FD(-X!`%U*H-]"`!U)(N%
+MZ`P``(G"B8R5:`P``/_`B87H#```N`,```#IN````&9FD("]9`P```!U1X.]
+M0`(```!U'@^VVXG>3(GWZ)'M__^)WDR)]^CG[?__9F9FD&9FD$R)ZDR)YDB)
+M[^BRZ___28U5"$R)YDB)[^A#[___ZV&03(GJ3(GF2(GOZ)+K__]FD.M.3(GF
+M2(GOZ(/K__^`O4@"```!=3J#O4`"```!=0L/MO-,B??H9N[__TR)YDB)[^B[
+M[___A<!U%TR)YDB)[^C,Z___N`$```#K"F9FD&:0N`````!(BQPD2(ML)`A,
+MBV0D$$R+;"083(MT)"!(@\0HPV9F9I!F9F:09F:09F:02(/L6$B)7"0H2(EL
+M)#!,B60D.$R);"1`3(ET)$A,B7PD4$F)_TB+1Q!(B40D&+Y@'0``2(G'Z```
+M``")Q4&+CX````")3"0DN`````"%S0^$BP$``/?%```$`'1908._L`````$9
+M]H'F6`0``('&`!D``$B+?"08Z`````")PXG"]])!@[^P`````1GV@>98!```
+M@<8`&0``2(M\)!CH`````+D`````B=J^`````$R)_T'_5RC&1"0C`/?%_P$`
+M``^$``$``(!\)",!&=MFNP``@<,4``,`NN____^)WDB+?"08Z`````")WDB+
+M?"08Z`````!!B<:)PO?2@\H0B=Y(BWPD&.@`````@'PD(P$9]F:^``"!Q@@`
+M`P!(BWPD&.@`````08G$0;T`````#[9$)".)1"04B40D$&9F9I!!#[;5N``!
+M``")T=/@B<-$(?.X`0```-/@1"'P08GI08/A`8G!1`G)=!E$B>&#X1]$B30D
+M08G`BW0D%$R)_^A]V?__A=MT*HM<)!"-!)T`````1`GH#[;XZ%/J__^%1"0D
+M=`Y!#[;5B=Y,B?_H3]S__\'M`D'![`A!_\5!@/T##X9[____ZP/![0C1[?Y$
+M)".`?"0C`0^&X/[__[@!````2(M<)"A(BVPD,$R+9"0X3(ML)$!,BW0D2$R+
+M?"102(/$6,-F9F:09F:09F:09F:02(/L"$B+?Q"Z`````+YD'0``Z`````"X
+M`0```$B#Q`C#9F9FD&9F9I!F9F:09F:02(/L"(N7@````$B+?Q"^9!T``.@`
+M````N`$```!(@\0(PV9F9I!F9F:09F:09F:02(/L.$B)7"0(2(EL)!!,B60D
+M&$R);"0@3(ET)"A,B7PD,$B)^T&)S$6)Q4&)]HG0O0`````YS7-.1`GP08G'
+MD(MS/('&'`$``$B+0S!(BW@0Z`````"$P'@.1"'X1#CP#Y3`#[;`ZR1$B>_H
+M``````^V,TB+>S#H`````(7`=`S_Q40YY7*YN`````!(BUPD"$B+;"003(MD
+M)!A,BVPD($R+="0H3(M\)#!(@\0XPY!32(G[BW<\@<8@`0``2(M',$B+>!"Z
+M`````.@`````BW,\@<8@`0``2(M#,$B+>!#H`````%O#9F:09F:09F:04TB)
+M^XMW/('&(`$``$B+1S!(BW@0N@(```#H`````(MS/('&'`$``$B+0S!(BW@0
+MZ`````!;PV9FD&9FD&9FD$B#[!A(B1PD2(EL)`A,B60D$(GP#[;`2(M<QS"X
+M`````$B%VW1M3(MG$(MK/+@`````@[M@#````7182(G?Z`````"-M1P!``"Z
+MX0```$R)Y^@`````0;AD````N1`G``"Z`0```+X`````2(G?Z`````"%P'4/
+M2(G?Z`````"X`````.L-2(G?Z`````"X`0```$B+'"1(BVPD"$R+9"002(/$
+M&,-F9F:09F:09F:0055!5%532(/L.$F)_(GUB?(/ML),BVS',+@`````387M
+M#X3M````28U=0&9FD&:00`^V]<=$)##L````QT0D*`````#'1"0@`````,=$
+M)!@`````QT0D$`````#'1"0(`````,<$)`````!!N0`!``!-C45`N0````"Z
+M`0```$R)Y^@`````A<`/A(4```#V`P1T/V:!>P3(-W4W0`^V]<<$)`````!!
+MN0````!!N`````"Y`````+H'````3(GGZ`````"%P'1+9L<#``#I7?____:#
+MH````.!T,[D`````2(G>N`$```"`N_X!``"E=2*Z``````^WP@(,,/_"9H'Z
+M_P%V\;@`````A,EU!;@!````2(/$.%M=05Q!7<.02(/L"(GP#[;`2(M\QS"X
+M`````$B%_W03N`````"#OV`,```!=`7H`````$B#Q`C#2(/L.$`/MO;'1"0P
+M[P```,=$)"@`````#[9$)$")1"0@10^VR42)3"0810^VP$2)1"00#[;)B4PD
+M"`^VTHD4)$&Y`````$&X`````+D`````N@````#H`````$B#Q#C#2(/L:$B)
+M7"0X2(EL)$!,B60D2$R);"103(ET)%A,B7PD8$B)^T&)UT&)SDV)Q46)S(GR
+MBVPD<$2+3"1X1(N$)(````"+O"2(````BXPDD````$0/MIPDF````$0/MI0D
+MH`````^VPKX`````2(-\PS``=$T/MO)!#[;"B40D,$$/ML.)1"0H#[?!B40D
+M(`^WQXE$)!A!#[?`B40D$$$/M\&)1"0(#[?%B00D18GA38GH1(GQ1(GZ2(G?
+MZ#$```")QHGP2(M<)#A(BVPD0$R+9"1(3(ML)%!,BW0D6$R+?"1@2(/$:,-F
+M9F:09F:09F:02('LF````$B)7"1H2(EL)'!,B60D>$R)K"2`````3(FT)(@`
+M``!,B;PDD````(GPB50D7(G-3(E$)%!$B4PD3$2+K"2@````1(N\)*@```"+
+ME"2P````9HE4)#"+C"2X````9HE,)""+E"3`````9HE4)!`/MHPDR````(A,
+M)`\/MI0DT````(A4)`X/ML!(BUS',$R+9Q!$BW,\@[M``@```70)@[M@#```
+M`74*N@````#IV`(``$&XZ`,``+FX"P``N@````"^0````$B)W^@`````N@``
+M``"%P`^$K@(``$B)W^@`````@_T!=6Y,B>D/MM5!C;8$`0``3(GGZ`````!,
+MB?@/MM1!C;8(`0``3(GGZ`````"+3"0P#[;508VV#`$``$R)Y^@`````BT0D
+M(`^VU$&-MA`!``!,B>?H`````(M,)!`/MM5!C;84`0``3(GGZ`````#K/K@`
+M____9D2%Z'4A9D2%^&9F9I!U%V:%1"0P=1!FA40D(&:0=0=FA40D$'022(G?
+MZ`````"Z`````.GU`0``00^VU4&-M@0!``!,B>?H`````$$/MM=!C;8(`0``
+M3(GGZ``````/ME0D,$&-M@P!``!,B>?H``````^V5"0@08VV$`$``$R)Y^@`
+M````#[94)!!!C;84`0``3(GGZ``````/ME0D#T&-MA@!``!,B>?H``````^V
+M5"0.08VV'`$``$R)Y^@`````@WPD7`!U14&X$"<``+D<#```N@$```"^````
+M`$B)W^@`````A<!U$DB)W^@`````N@````#I,0$``$B)W^@`````N@$```#I
+M'P$``$&X$"<``+D<#```N@$```"^`````$B)W^@`````A<!U$TB)W^@`````
+MN@````"0Z>L```!!C;8<`0``3(GGZ`````"H"'422(G?Z`````"Z`````.G&
+M````O0`````[;"1,<VI%C:X``0``0(3M=2%!N&0```"Y4,,``+H!````O@``
+M``!(B=_H`````(7`=&V#?"1<`7481(GN3(GGZ`````")ZDB+3"109HD$4>L6
+MB>A(BTPD4`^W%$%$B>Y,B>?H`````/_%.VPD3'*=0;AD````N5##``"Z`0``
+M`+X`````2(G?Z`````"%P'4>2(G?Z`````"Z`````.LA2(G?Z`````"Z````
+M`.L22(G?Z`````"Z`0```&9FD&:0B=!(BUPD:$B+;"1P3(MD)'A,BZPD@```
+M`$R+M"2(````3(N\))````!(@<28````PV9F9I!F9F:09F9FD&9FD$%455-(
+MB?M(BT<P2(MH$$2+9SQ!C;0D(`$``+H&````2(GOZ`````"+<SR!QB`!``!(
+MB>_H`````+\*````Z`````!(B=_H`````+_T`0``Z`````"_]`$``.@`````
+MO_0!``#H`````+_T`0``Z`````"[`````$&!Q!P!``"01(GF2(GOZ`````"$
+MP'@'N`$```#K'K_T`0``9F:09I#H`````/_#@?L/)P``=M&X`````%M=05S#
+M9F9FD&9FD%-(B?OH-____[H!````@_@!=!2_]`$``.@`````2(G?Z!O___^)
+MPHG06\-F9I!FD%532(/L"$B)_4B+!0````"+<!B!Q@``!`"ZH````.@`````
+MNP````!(BP4`````BW`0@<8```0`2(GOZ`````#_PX/[!'[ANP````!F9F:0
+M2(L%`````(MP%('&```$`$B)[^@`````_\.#^P5^X;L`````2(L%`````(MP
+M$('&```$`$B)[^@`````_\.#^P1^X4B#Q`A;7<-F9I!F9I!32(G[2(L%````
+M`(MP#('&```$`+J`````Z`````!(BP4`````BW`8@<8```0`NK````!(B=_H
+M`````%O#9F:02(/L&$B)7"0(3(ED)!!)B?SH"O___TB+!0````"+<`B!Q@``
+M!`"Z`````$R)Y^@`````2(L%`````(LP@<8```0`3(GGZ`````")PTR)Y^AL
+M____#[;;B=A(BUPD"$R+9"002(/$&,-F9F:09F9FD$B#[!A(B1PD2(EL)`A,
+MB60D$$B)^X,]```````/A08!``"^+`T``.@`````08G$B<*#R@&^+`T``$B)
+MW^@`````OO`$`0!(B=_H`````(G%@^!B@_AB=!6)ZH/*8@^VTK[P!`$`2(G?
+MZ`````"^```$`$B)W^@`````2(G?Z"[^__](BP4`````BW`(@<8```0`N@<`
+M``!(B=_H`````$B+!0````"+,('&```$`+H1````2(G?Z`````!(BP4`````
+MBW`(@<8```0`N@4```!(B=_H`````$B+!0````"+,('&```$`+H1````2(G?
+MZ`````!(B=_H5/[__XGJOO`$`0!(B=_H`````+[P!`$`2(G?Z`````!$B>*^
+M+`T``$B)W^@`````2(L<)$B+;"0(3(MD)!!(@\08PV9FD&:005154TB)^[XL
+M#0``Z`````!!B<2)PH/*`;XL#0``2(G?Z`````"^\`0!`$B)W^@`````B<6#
+MX&*#^&)T%8GJ@\IB#[;2OO`$`0!(B=_H`````+X```0`2(G?Z`````!(B=_H
+M"?W__TB+!0````"+<`B!Q@``!`"Z!P```$B)W^@`````2(L%`````(LP@<8`
+M``0`N@````!(B=_H`````$B+!0````"+<`B!Q@``!`"Z!0```$B)W^@`````
+M2(L%`````(LP@<8```0`N@````!(B=_H`````$B)W^@O_?__B>J^\`0!`$B)
+MW^@`````OO`$`0!(B=_H`````$2)XKXL#0``2(G?Z`````!;74%<PV9F9I!F
+M9F:09F:09F:04TB)^^A'_/__2(L%`````(MP"('&```$`+H*````2(G?Z```
+M``!(BP4`````BS"!Q@``!`"Z`````$B)W^@`````2(G?Z*;\__^^`0`$`$B)
+MW^@`````NO____^H`G5-2(G?Z.C[__](BP4`````BS"!Q@``!`"Z`0```$B)
+MW^@`````2(G?Z&3\__^_9````.@`````O@$`!`!(B=_H`````-'H@^`!@_@!
+M&=*)T%O#9F9FD&9F9I!F9F:09F:02(/L*$B)'"1(B6PD"$R)9"003(EL)!A,
+MB70D($F)_$&)]DB+7Q"^+`T``$B)W^@`````08G%B<*#R@&^+`T``$B)W^@`
+M````OO`$`0!(B=_H`````(G%@^!B@_AB=!6)ZH/*8@^VTK[P!`$`2(G?Z```
+M``"^```$`$B)W^@`````18BT)+0```!!#[;62(L%`````(MP'('&```$`$B)
+MW^@`````B>J^\`0!`$B)W^@`````OO`$`0!(B=_H`````$2)ZKXL#0``2(G?
+MZ`````!(BQPD2(ML)`A,BV0D$$R+;"083(MT)"!(@\0HPV:02(/L"(GQA-)T
+M%K@!````T^`(A[0```#K%&9F9I!F9I"X_O___]/`((>T````#[:WM````.@`
+M````2(/$",-FD$%7059!54%455-(@^P(2(G]0;\`````OBP-``#H`````$&)
+MQHG"@\H!OBP-``!(B>_H`````+[P!`$`2(GOZ`````!!B<6#X&*#^&)T%D2)
+MZH/*8@^VTK[P!`$`2(GOZ`````"^```$`$B)[^@`````O@``!`!(B>_H````
+M`&8]5:H/A>\```!!O`````!FD+L`````1#GC?RIF9I!F9I!(BP4`````BW`8
+M@<8```0`NJ````!(B>_H`````/_#1#GC?MQ!@?S(````?@J_`0```.@`````
+MO@``!`!(B>_H`````(G#2(L%`````(MP&('&```$`+JP````2(GOZ`````!F
+M@?M5JG480?_$08'\QP````^.=O___V:!^U6JD'152(L%`````(MP&('&```$
+M`+JP````2(GOZ`````"^```$`$B)[^@`````9CU5JG4E0;\!````2(GOZ.#Y
+M__\\/G432(GOZ*3\__^%P+@"````1`]$^$B+!0````"+<!B!Q@``!`"ZL```
+M`$B)[^@`````1(GJOO`$`0!(B>_H`````+[P!`$`2(GOZ`````!$B?*^+`T`
+M`$B)[^@`````00^VQTB#Q`A;74%<05U!7D%?PV9F9I!F9F:09F9FD%532(/L
+M"$B)_;L`````9I!(QP4``````````$B)[^C]_?__A,!U(4C'!0``````````
+M2(GOZ.;]__^$P'4*_\.!^^<#``!^R`^VP$B#Q`A;7<-F9F:09F9FD&9FD&9F
+MD(!^`0)U&H!^`@%U%`^V1@.)!0````"X`````,-F9F:0N/_____#9F9FD&9F
+MD&9FD$B#[#A(B5PD"$B);"003(ED)!A,B6PD($R)="0H3(E\)#!!B?=!B<U$
+MB<-(BV\028G4OBP-``!(B>_H`````(E$)`2)PH/*`;XL#0``2(GOZ`````"^
+M\`0!`$B)[^@`````08G&@^!B@_AB=!9$B?*#RF(/MM*^\`0!`$B)[^@`````
+MO@``!`!(B>_H`````(7;="R[`````$0YZWU29I!!C;0?```$`$B)[^@`````
+M08@$)/_#2?_$1#GK?.+K,+L`````1#GK?29F9I!F9I!!#[84)$&-M!\```0`
+M2(GOZ`````#_PTG_Q$0YZWSAD$2)\K[P!`$`2(GOZ`````"^\`0!`$B)[^@`
+M````BU0D!+XL#0``2(GOZ`````"X`0```$B+7"0(2(ML)!!,BV0D&$R+;"0@
+M3(MT)"A,BWPD,$B#Q#C#```````````````$````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
-M```````````````!`````````````0`!``$``@`!``,``0`$``$`!0`!``8`
-M`0`````````!```@`0``0`$``&`!``"``0``H`$``,`!````````````````
+M`0`````````````````````````````````!``$``0`"``$``P`!``0``0`%
+M``$`!@`!``<``0````$``"`!``!``0``8`$``(`!``"@`0``P`$``.`!````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
-M````````````````````%``````````!``%X$`P'")`!````````)````!P`
-M`````````````)P%````````90[0!(\"C@.-!(P%A@:#!R0```!$````````
-M``````#L`````````$$.$$$.&$0.((,#A@(````D````;```````````````
-M"0(```````!8#C"-`HP#A@2#!0``````)````)0``````````````%0`````
-M````0@X000X800X@@P2&`XP"`#P```"\``````````````!*`0```````$(.
-M$$(.&$(.($(.*$$.,$$..$<.P`2#!X8&C`6-!(X#CP(````````T````_```
-M````````````]`````````!"#A!"#AA"#B!!#BA!#C!'#K`$@P:&!8P$C0..
-M`@```!0````T`0````````````!Q`````````!P```!,`0````````````#[
-M`````````$$.$(,"````)````&P!`````````````%L`````````00X000X8
-M1`X@@P.&`@```"0```"4`0`````````````T`0```````&(.0(\"C@.-!(P%
-MA@:#!P`<````O`$`````````````.P````````!$#A```````!P```#<`0``
-M``````````!L`````````$0.$```````)````/P!`````````````&T`````
-M````00X000X8@P.&`@```````"0````D`@````````````"2`0```````%T.
-M,(X"C0.,!(8%@P8````<````3`(`````````````@P````````!$#A``````
-M`"0```!L`@````````````"V`````````%,.((P"A@.#!``````````D````
-ME`(`````````````[@````````!3#B",`H8#@P0`````````)````+P"````
-M`````````%$!````````0@X000X800X@@P2&`XP"`"0```#D`@``````````
-M``#^`````````%,.((P"A@.#!``````````D````#`,`````````````QP$`
-M``````!8#C"-`HP#A@2#!0``````)````#0#`````````````$,"````````
-M8@Y`CP*.`XT$C`6&!H,'`"0```!<`P````````````!/`0```````$$.$$$.
-M&$0.((,#A@(````D````A`,`````````````?P$```````!@#K`$C@*-`XP$
-MA@6#!@``%````*P#`````````````"@`````````%````,0#````````````
-M`*0`````````)````-P#`````````````%L`````````00X000X81`X@@P.&
-M`@```"0````$!``````````````T`0```````&(.0(\"C@.-!(P%A@:#!P`<
-M````+`0`````````````*0````````!$#A```````!0```!,!```````````
-M```?`````````!0```!D!``````````````7`````````#P```!\!```````
-M``````"9`0```````$(.$$(.&$(.($(.*$$.,$$..$0.0(,'A@:,!8T$C@./
-M`@`````````D````O`0`````````````:@````````!!#A!!#AB#`X8"````
-M````%````.0$`````````````$(`````````)````/P$`````````````#<`
-M````````00X000X81`X@@P.&`@```!0````D!0`````````````]````````
-M`!P````\!0`````````````8`````````$0.$```````%````%P%````````
-M`````#(`````````%````'0%`````````````"4`````````)````(P%````
-M`````````(0`````````6`XHC0*,`X8$@P4``````!0```"T!0``````````
-M```H`````````"0```#,!0````````````!9`````````$(.$$$.&$$.((,$
-MA@.,`@`\````]`4`````````````*0(```````!"#A!"#AA"#B!"#BA!#C!!
-M#CA$#D"#!X8&C`6-!(X#CP(`````````)````#0&`````````````,(`````
-M````0@X000X800X@@P2&`XP"`#P```!<!@`````````````U`@```````$(.
-M$$(.&$(.($(.*$$.,$$..$<.H`.#!X8&C`6-!(X#CP(````````D````G`8`
-M````````````\0````````!!#A!!#AA$#B"#`X8"````)````,0&````````
-M`````*,$````````8@Y0CP*.`XT$C`6&!H,'`!P```#L!@`````````````E
-M`````````$0.$```````/`````P'`````````````+4`````````0@X00@X8
-M0@X@0@XH00XP00XX1`Y`@P>&!HP%C02.`X\"`````````!0```!,!P``````
-M```````:`0```````"0```!D!P````````````#"`````````%,.((P"A@.#
-M!``````````<````C`<`````````````/@````````!.#B",`H,#`"0```"L
-M!P````````````"@`````````%@.,(T"C`.&!(,%```````D````U`<`````
-M````````C`$```````!"#A!!#AA!#B"#!(8#C`(`)````/P'````````````
-M`.H!````````90[@`H\"C@.-!(P%A@:#!R0````D"`````````````#H````
-M`````&4.T`*/`HX#C02,!88&@P<\````3`@`````````````2@$```````!"
-M#A!"#AA"#B!"#BA!#C!!#CA'#L`#@P>&!HP%C02.`X\"````````)````(P(
-M`````````````'H`````````4PX@C`*&`X,$`````````!0```"T"```````
-M``````!4`````````#P```#,"``````````````Y`@```````$(.$$(.&$(.
-M($(.*$$.,$$..$0.0(,'A@:,!8T$C@./`@`````````\````#`D`````````
-M````%R,```````!"#A!"#AA"#B!"#BA!#C!!#CA'#K`#@P>&!HP%C02.`X\"
-M````````/````$P)`````````````#\!````````0@X00@X80@X@0@XH00XP
-M00XX1`Y0@P>&!HP%C02.`X\"`````````"0```","0````````````!F````
-M`````$$.$$$.&$0.((,#A@(````<````M`D`````````````0P$```````!!
-M#A"#`@```"0```#4"0````````````!Q`````````%@.,(T"C`.&!(,%````
-M```D````_`D`````````````W0````````!!#A!!#AA$#B"#`X8"````/```
-M`"0*`````````````+$"````````0@X00@X80@X@0@XH00XP00XX1PZ``X,'
-MA@:,!8T$C@./`@```````!P```!D"@````````````!_`````````$X.((8"
-M@P,`/````(0*`````````````#\%````````0@X00@X80@X@0@XH00XP00XX
-M1`Y0@P>&!HP%C02.`X\"`````````#P```#$"@````````````#E`P``````
-M`$(.$$(.&$(.($(.*$$.,$$..$0.D`&#!X8&C`6-!(X#CP(````````<````
-M!`L`````````````*@````````!$#A```````"P````D"P````````````!I
-M`@```````$(.$$$.&$$.($0.0(,$A@.,`@```````"0```!4"P``````````
-M``!K`````````$$.$$$.&$0.((,#A@(````D````?`L`````````````%@$`
-M``````!"#A!!#AA!#B"#!(8#C`(`)````*0+`````````````$<!````````
-M00X000X81`X@@P.&`@```!0```#,"P`````````````C`````````"0```#D
-M"P````````````!W`````````$$.$$$.&$0.((,#A@(````L````#`P`````
-M````````>@(```````!"#A!"#AA!#B!!#BA'#K`$@P6&!(P#C0(4````/`P`
-M````````````0@`````````D````5`P`````````````1P````````!!#A!!
-M#AB#`X8"````````%````'P,`````````````"H`````````%````)0,````
-M``````````X`````````+````*P,`````````````&0!````````0@X00@X8
-M00X@00XH1PZP"(,%A@2,`XT"%````-P,`````````````%4`````````'```
-M`/0,`````````````'X`````````00X01`X@@P(4````%`T`````````````
-M6P`````````<````+`T`````````````HP````````!!#A!$#B"#`AP```!,
-M#0`````````````O`````````$$.$(,"````%````&P-``````````````P`
-M````````%````(0-`````````````"@`````````)````)P-````````````
-M`'H`````````6`XPC0*,`X8$@P4``````!P```#$#0`````````````5````
-M`````$0.$```````'````.0-`````````````"<`````````1`X0```````D
-M````!`X`````````````7@$```````!B#G"/`HX#C02,!88&@P<`%````"P.
-M`````````````"8`````````)````$0.`````````````&(`````````0@X0
-M00X800X@@P2&`XP"`!P```!L#@````````````!/`````````$X.((P"@P,`
-M'````(P.`````````````"``````````00X0@P(````4````K`X`````````
-M````.``````````4````Q`X`````````````P`(````````D````W`X`````
-M````````CP$```````!B#E"/`HX#C02,!88&@P<`)`````0/````````````
-M`.$`````````8@YPCP*.`XT$C`6&!H,'`"0````L#P````````````"3`0``
-M`````&(.<(\"C@.-!(P%A@:#!P`D````5`\`````````````L0````````!8
-M#C"-`HP#A@2#!0``````)````'P/``````````````,#````````8@Y0CP*.
-M`XT$C`6&!H,'`!P```"D#P````````````!Z`````````$0.$```````)```
-M`,0/`````````````*,!````````8@Y`CP*.`XT$C`6&!H,'`"0```#L#P``
-M``````````#``````````$(.$$$.&$$.((,$A@.,`@`D````%!``````````
-M````;P$```````!=#E".`HT#C`2&!8,&````+````#P0`````````````)L!
-M````````0@X00@X800X@00XH1`XP@P6&!(P#C0(`/````&P0````````````
-M`-$`````````0@X00@X80@X@0@XH00XP00XX1`YP@P>&!HP%C02.`X\"````
-M`````"0```"L$``````````````Z`0```````%@.,(T"C`.&!(,%```````D
-M````U!``````````````G@````````!3#B"-`HP#@P0`````````/````/P0
-M``````````````4"````````0@X00@X80@X@0@XH00XP00XX1`Y`@P>&!HP%
-MC02.`X\"`````````!P````\$0`````````````<`````````$0.$```````
-M'````%P1`````````````"<!````````00X0@P(````4````?!$`````````
-M````0@`````````4````E!$`````````````;0`````````D````K!$`````
-M````````@0````````!3#B",`H8#@P0`````````'````-01````````````
-M`&$`````````3@X8A@*#`P`4````]!$`````````````*``````````D````
-M#!(`````````````AP````````!!#A!!#AA$#B"#`X8"````'````#02````
-M`````````"T`````````00X0@P(````D````5!(`````````````T@``````
-M``!=#C".`HT#C`2&!8,&````)````'P2`````````````'H`````````6`XP
-MC0*,`X8$@P4``````"0```"D$@````````````!I`````````$(.$$$.&$0.
-M((,#C`(````<````S!(`````````````10````````!!#A"#`@```"0```#L
-M$@`````````````K`@```````%@.,(T"C`.&!(,%```````D````%!,`````
-M````````70,```````!=#C".`HT#C`2&!8,&````'````#P3````````````
-M`"$`````````1`X0```````4````7!,`````````````"P`````````4````
-M=!,`````````````"P`````````<````C!,`````````````8`````````!.
-M#B"&`H,#`!0```"L$P`````````````C`````````"0```#$$P``````````
-M``",`````````$$.$$$.&$0.((,#A@(````\````[!,`````````````,P(`
-M``````!"#A!"#AA"#B!"#BA!#C!!#CA$#G"#!X8&C`6-!(X#CP(`````````
-M)````"P4`````````````.0`````````70XPC@*-`XP$A@6#!@```!P```!4
-M%`````````````!#`````````$0.$```````'````'04`````````````#T`
-M````````1`X0```````<````E!0`````````````1@````````!!#A"#`@``
-M`!0```"T%``````````````=`````````"0```#,%`````````````"5````
-M`````%,.((P"A@.#!``````````D````]!0`````````````X`````````!=
-M#C".`HT#C`2&!8,&````)````!P5`````````````)\`````````4PX@C`*&
-M`X,$`````````"P```!$%0````````````#_`````````$(.$$(.&$$.($$.
-M*$0.,(,%A@2,`XT"`#P```!T%0````````````!-`0```````$(.$$(.&$(.
-M($(.*$$.,$$..$0.0(,'A@:,!8T$C@./`@`````````<````M!4`````````
-M````4`````````!$#E```````"0```#4%0````````````#(`0```````&(.
-M0(\"C@.-!(P%A@:#!P`D````_!4`````````````W`$```````!B#F"/`HX#
-MC02,!88&@P<`'````"06`````````````"$`````````1`X0```````<````
-M1!8`````````````(@````````!$#A```````"0```!D%@````````````"!
-M`````````%T.,(X"C0.,!(8%@P8````<````C!8`````````````-P``````
-M``!!#A"#`@```!P```"L%@`````````````W`````````$$.$(,"````+```
-M`,P6`````````````-``````````0@X00@X800X@00XH1`XP@P6&!(P#C0(`
-M)````/P6`````````````*,`````````4PX@C`*&`X,$`````````!P````D
-M%P````````````#&`````````$$.$$0.4(,"'````$07`````````````#``
-M````````1`X0```````<````9!<`````````````8`````````!$#D``````
-M`"0```"$%P````````````#F`````````&(.<(\"C@.-!(P%A@:#!P`D````
-MK!<`````````````80,```````!E#J`!CP*.`XT$C`6&!H,')````-07````
-M`````````+D`````````0@X000X800X@@P2&`XP"`!P```#\%P``````````
-M```K`````````$$.$(,"````)````!P8`````````````)H`````````00X0
-M00X81`X@@P.&`@```!P```!$&``````````````]`````````$$.$(,"````
-M'````&08`````````````&@`````````3@X@C`*#`P`D````A!@`````````
-M````$@$```````!"#A!!#AA!#B"#!(8#C`(`)````*P8`````````````!(!
-M````````0@X000X800X@@P2&`XP"`!P```#4&`````````````"Q````````
-M`$$.$(,"````)````/08`````````````.0`````````70XPC@*-`XP$A@6#
-M!@```!P````<&0`````````````^`````````$0.$```````/````#P9````
-M`````````-0!````````0@X00@X80@X@0@XH00XP00XX1`Y`@P>&!HP%C02.
-M`X\"`````````"0```!\&0````````````!2`````````$$.$$$.&$0.((,#
-MA@(`````1T-#.B`H1TY5*2`S+C0N,B!;1G)E94)31%T@,C`P-#`W,C@``"YS
-M>6UT86(`+G-T<G1A8@`N<VAS=')T86(`+G)E;&$N=&5X=``N<F5L82YD871A
-M`"YB<W,`+G)E;&$N<F]D871A`"YR96QA+F5H7V9R86UE`"YC;VUM96YT````
+M`````````````````````````````````````!0``````````0`!>!`,!PB0
+M`0```````"P````<``````````````!L!@```````$<.T`1PCP*.`XT$C`6&
+M!H,'`````````"0```!,``````````````#W`````````$$.$$$.&$0.((,#
+MA@(````D````=```````````````*P(```````!$#C!4C0*,`X8$@P4`````
+M)````)P``````````````%0`````````0@X000X800X@@P2&`XP"`#P```#$
+M``````````````!*`0```````$(.$$(.&$(.($(.*$$.,$$..$<.P`2#!X8&
+MC`6-!(X#CP(````````T````!`$`````````````]P````````!"#A!"#AA"
+M#B!!#BA!#C!'#K`$@P:&!8P$C0..`@```!0````\`0````````````")````
+M`````!P```!4`0`````````````1`0```````$$.$(,"````)````'0!````
+M`````````%L`````````00X000X81`X@@P.&`@```"0```"<`0``````````
+M```T`0```````$0.0%Z/`HX#C02,!88&@P<<````Q`$`````````````10``
+M``````!$#A```````!P```#D`0````````````!L`````````$0.$```````
+M)`````0"`````````````&T`````````00X000X8@P.&`@```````"0````L
+M`@````````````"2`0```````$0.,%B.`HT#C`2&!8,&```<````5`(`````
+M````````@P````````!$#A```````"0```!T`@````````````"Z````````
+M`$0.($Z,`H8#@P0````````D````G`(`````````````\@````````!$#B!.
+MC`*&`X,$````````)````,0"`````````````%$!````````0@X000X800X@
+M@P2&`XP"`"0```#L`@`````````````"`0```````$0.($Z,`H8#@P0`````
+M```D````%`,`````````````WP$```````!$#C!4C0*,`X8$@P4`````)```
+M`#P#`````````````$,"````````1`Y`7H\"C@.-!(P%A@:#!R0```!D`P``
+M``````````"6`0```````$$.$$$.&$0.((,#A@(````D````C`,`````````
+M````CP$```````!'#K`$:(X"C0.,!(8%@P8`%````+0#`````````````#$`
+M````````%````,P#`````````````*4`````````)````.0#````````````
+M`%L`````````00X000X81`X@@P.&`@```"0````,!``````````````T`0``
+M`````$0.0%Z/`HX#C02,!88&@P<<````-`0`````````````+`````````!$
+M#A```````!0```!4!``````````````?`````````!0```!L!```````````
+M```7`````````#P```"$!`````````````"9`0```````$(.$$(.&$(.($(.
+M*$$.,$$..$0.0(,'A@:,!8T$C@./`@`````````D````Q`0`````````````
+M:@````````!!#A!!#AB#`X8"````````%````.P$`````````````$(`````
+M````)`````0%`````````````#<`````````00X000X81`X@@P.&`@```!0`
+M```L!0`````````````]`````````!P```!$!0`````````````8````````
+M`$0.$```````%````&0%`````````````#(`````````%````'P%````````
+M`````"4`````````)````)0%`````````````(4`````````1`XH4XT"C`.&
+M!(,%`````!0```"\!0`````````````H`````````"0```#4!0``````````
+M``!9`````````$(.$$$.&$$.((,$A@.,`@`\````_`4`````````````*0(`
+M``````!"#A!"#AA"#B!"#BA!#C!!#CA$#E"#!X8&C`6-!(X#CP(`````````
+M)````#P&`````````````,@`````````0@X000X800X@@P2&`XP"`#P```!D
+M!@`````````````Z`@```````$(.$$(.&$(.($(.*$$.,$$..$<.H`.#!X8&
+MC`6-!(X#CP(````````D````I`8`````````````]`````````!!#A!!#AA$
+M#B"#`X8"````)````,P&`````````````,,$````````1`Y07H\"C@.-!(P%
+MA@:#!QP```#T!@`````````````E`````````$0.$```````/````!0'````
+M`````````+4`````````0@X00@X80@X@0@XH00XP00XX1`Y`@P>&!HP%C02.
+M`X\"`````````!0```!4!P`````````````:`0```````"0```!L!P``````
+M``````#"`````````$0.($Z,`H8#@P0````````<````E`<`````````````
+M/@````````!$#B!*C`*#`R0```"T!P````````````"C`````````$0.,%2-
+M`HP#A@2#!0`````D````W`<`````````````C`$```````!"#A!!#AA!#B"#
+M!(8#C`(`+`````0(`````````````/H!````````1P[@`G"/`HX#C02,!88&
+M@P<`````````+````#0(`````````````/H`````````1P[0`G"/`HX#C02,
+M!88&@P<`````````/````&0(`````````````$H!````````0@X00@X80@X@
+M0@XH00XP00XX1P[``X,'A@:,!8T$C@./`@```````"0```"D"```````````
+M``!Y`````````$0.($Z,`H8#@P0````````4````S`@`````````````5```
+M```````\````Y`@`````````````.0(```````!"#A!"#AA"#B!"#BA!#C!!
+M#CA$#D"#!X8&C`6-!(X#CP(`````````/````"0)`````````````!<C````
+M````0@X00@X80@X@0@XH00XP00XX1PZP`X,'A@:,!8T$C@./`@```````#P`
+M``!D"0`````````````_`0```````$(.$$(.&$(.($(.*$$.,$$..$0.4(,'
+MA@:,!8T$C@./`@`````````D````I`D`````````````9@````````!!#A!!
+M#AA$#B"#`X8"````'````,P)`````````````$,!````````00X0@P(````D
+M````[`D`````````````<0````````!$#C!4C0*,`X8$@P4`````)````!0*
+M`````````````-T`````````00X000X81`X@@P.&`@```#P````\"@``````
+M``````#+`@```````$(.$$(.&$(.($(.*$$.,$$..$<.D`.#!X8&C`6-!(X#
+MCP(````````<````?`H`````````````@@````````!$#B!*A@*#`SP```"<
+M"@````````````!Y!0```````$(.$$(.&$(.($(.*$$.,$$..$0.4(,'A@:,
+M!8T$C@./`@`````````\````W`H`````````````(00```````!"#A!"#AA"
+M#B!"#BA!#C!!#CA$#I`!@P>&!HP%C02.`X\"````````'````!P+````````
+M`````"H`````````1`X0```````L````/`L`````````````F0(```````!"
+M#A!!#AA!#B!$#E"#!(8#C`(````````D````;`L`````````````:P``````
+M``!!#A!!#AA$#B"#`X8"````)````)0+`````````````!8!````````0@X0
+M00X800X@@P2&`XP"`"0```"\"P````````````!7`0```````$$.$$$.&$0.
+M((,#A@(````4````Y`L`````````````(P`````````D````_`L`````````
+M````=P````````!!#A!!#AA$#B"#`X8"````+````"0,`````````````(D"
+M````````0@X00@X800X@00XH1PZP!(,%A@2,`XT"%````%0,````````````
+M`$(`````````)````&P,`````````````$<`````````00X000X8@P.&`@``
+M`````!0```"4#``````````````J`````````!0```"L#``````````````.
+M`````````"P```#$#`````````````!D`0```````$(.$$(.&$$.($$.*$<.
+ML`B#!88$C`.-`A0```#T#`````````````!5`````````!P````,#0``````
+M``````!^`````````$$.$$0.((,"%````"P-`````````````%L`````````
+M'````$0-`````````````*,`````````00X01`X@@P(<````9`T`````````
+M````+P````````!!#A"#`@```!0```"$#0`````````````,`````````!0`
+M``"<#0`````````````H`````````"0```"T#0````````````!Z````````
+M`$0.,%2-`HP#A@2#!0`````<````W`T`````````````%0````````!$#A``
+M`````!P```#\#0`````````````G`````````$0.$```````)````!P.````
+M`````````&8!````````1`YP7H\"C@.-!(P%A@:#!Q0```!$#@``````````
+M```F`````````"0```!<#@````````````!B`````````$(.$$$.&$$.((,$
+MA@.,`@`<````A`X`````````````3P````````!$#B!*C`*#`QP```"D#@``
+M```````````@`````````$$.$(,"````%````,0.`````````````,`"````
+M````)````-P.`````````````(D!````````1`Y07H\"C@.-!(P%A@:#!R0`
+M```$#P````````````#A`````````$0.<%Z/`HX#C02,!88&@P<D````+`\`
+M````````````DP$```````!$#G!>CP*.`XT$C`6&!H,')````%0/````````
+M`````+$`````````1`XP5(T"C`.&!(,%`````"0```!\#P````````````#X
+M`@```````$0.4%Z/`HX#C02,!88&@P<<````I`\`````````````>@``````
+M``!$#A```````"0```#$#P````````````"Y`0```````$0.0%Z/`HX#C02,
+M!88&@P<D````[`\`````````````P`````````!"#A!!#AA!#B"#!(8#C`(`
+M)````!00`````````````&\!````````1`Y068X"C0.,!(8%@P8``"P````\
+M$`````````````"[`0```````$(.$$(.&$$.($$.*$0.,(,%A@2,`XT"`#P`
+M``!L$`````````````#1`````````$(.$$(.&$(.($(.*$$.,$$..$0.<(,'
+MA@:,!8T$C@./`@`````````D````K!``````````````.@$```````!$#C!4
+MC0*,`X8$@P4`````)````-00`````````````)T`````````1`X@3HT"C`.#
+M!````````#P```#\$``````````````%`@```````$(.$$(.&$(.($(.*$$.
+M,$$..$0.0(,'A@:,!8T$C@./`@`````````<````/!$`````````````'```
+M``````!$#A```````!P```!<$0`````````````G`0```````$$.$(,"````
+M%````'P1`````````````$(`````````%````)01`````````````&T`````
+M````)````*P1`````````````(``````````1`X@3HP"A@.#!````````!P`
+M``#4$0````````````!@`````````$0.&$F&`H,#%````/01````````````
+M`"@`````````)`````P2`````````````*8`````````0@X000X800X@@P2&
+M`XP"`!P````T$@````````````!?`````````$0.($J&`H,#)````%02````
+M`````````-$`````````1`XP6(X"C0.,!(8%@P8``#0```!\$@``````````
+M``"3`````````$(.$$(.&$(.($$.*$$.,(,&A@6,!(T#C@(`````````)```
+M`+02`````````````&D`````````0@X000X81`X@@P.,`@```!P```#<$@``
+M``````````!%`````````$$.$(,"````)````/P2`````````````$`"````
+M````1`XP5(T"C`.&!(,%`````"0````D$P````````````"``P```````$0.
+M,%B.`HT#C`2&!8,&```<````3!,`````````````(0````````!$#A``````
+M`!0```!L$P`````````````+`````````!0```"$$P`````````````+````
+M`````!P```"<$P````````````!@`````````$0.($J&`H,#%````+P3````
+M`````````",`````````)````-03`````````````(P`````````00X000X8
+M1`X@@P.&`@```#P```#\$P`````````````/`@```````$(.$$(.&$(.($(.
+M*$$.,$$..$0.<(,'A@:,!8T$C@./`@`````````D````/!0`````````````
+MQ0````````!$#C!8C@*-`XP$A@6#!@``'````&04`````````````$,`````
+M````1`X0```````<````A!0`````````````/0````````!$#A```````!P`
+M``"D%`````````````!&`````````$$.$(,"````%````,04````````````
+M`!T`````````)````-P4`````````````-T`````````1`XP6(X"C0.,!(8%
+M@P8``"0````$%0````````````">`````````$0.($Z,`H8#@P0````````L
+M````+!4`````````````_P````````!"#A!"#AA!#B!!#BA$#C"#!88$C`.-
+M`@`\````7!4`````````````30$```````!"#A!"#AA"#B!"#BA!#C!!#CA$
+M#D"#!X8&C`6-!(X#CP(`````````)````)P5`````````````*(!````````
+M1`XP6(X"C0.,!(8%@P8``"0```#$%0`````````````#`@```````$0.8%Z/
+M`HX#C02,!88&@P<<````[!4`````````````(0````````!$#A```````!P`
+M```,%@`````````````B`````````$0.$```````)````"P6````````````
+M`*\`````````1`Y`7H\"C@.-!(P%A@:#!QP```!4%@`````````````W````
+M`````$$.$(,"````'````'06`````````````#<`````````00X0@P(````D
+M````E!8`````````````I@````````!$#B!.C`*&`X,$````````+````+P6
+M`````````````!\!````````0@X00@X800X@00XH1`Y@@P6&!(P#C0(`'```
+M`.P6`````````````#``````````1`X0```````<````#!<`````````````
+M8`````````!$#D```````"0````L%P````````````#F`````````$0.<%Z/
+M`HX#C02,!88&@P<L````5!<`````````````P0,```````!'#J`!9X\"C@.-
+M!(P%A@:#!P`````````D````A!<`````````````N0````````!"#A!!#AA!
+M#B"#!(8#C`(`'````*P7`````````````"L`````````00X0@P(````D````
+MS!<`````````````F@````````!!#A!!#AA$#B"#`X8"````'````/07````
+M`````````#T`````````00X0@P(````<````%!@`````````````:```````
+M``!$#B!*C`*#`R0````T&``````````````[`0```````$0.($Z,`H8#@P0`
+M```````D````7!@`````````````$@$```````!"#A!!#AA!#B"#!(8#C`(`
+M'````(08`````````````+$`````````00X0@P(````D````I!@`````````
+M````[@````````!$#C!8C@*-`XP$A@6#!@``'````,P8`````````````#X`
+M````````1`X0```````\````[!@`````````````U`$```````!"#A!"#AA"
+M#B!"#BA!#C!!#CA$#D"#!X8&C`6-!(X#CP(`````````)````"P9````````
+M`````%(`````````00X000X81`X@@P.&`@```!0```!4&0`````````````F
+M`````````"0```!L&0````````````!&`0```````$0.0%Z/`HX#C02,!88&
+M@P<`1T-#.B`H1TY5*2`S+C0N,B!;1G)E94)31%T@,C`P-#`W,C@``"YS>6UT
+M86(`+G-T<G1A8@`N<VAS=')T86(`+G)E;&$N=&5X=``N<F5L82YD871A`"YB
+M<W,`+G)E;&$N<F]D871A`"YR96QA+F5H7V9R86UE`"YC;VUM96YT````````
M````````````````````````````````````````````````````````````
-M```````````````````````@`````0````8```````````````````!`````
-M`````#+!```````````````````0````````````````````&P````0`````
-M````````````````````T`$!``````#X-`````````P````!````"```````
-M```8`````````"L````!`````P```````````````````(#!````````#`$`
-M`````````````````"`````````````````````F````!```````````````
-M``````````#(-@$``````(`!````````#`````,````(`````````!@`````
-M````,0````@````#````````````````````D,(````````0````````````
-M````````"````````````````````#L````!`````@``````````````````
-M`)#"````````<`````````````````````@````````````````````V````
-M!`````````````````````````!(.`$``````%`!````````#`````8````(
-M`````````!@`````````2`````$````"`````````````````````,,`````
-M``"@&0``````````````````"````````````````````$,````$````````
-M`````````````````)@Y`0``````(!`````````,````"`````@`````````
-M&`````````!2`````0````````````````````````"@W````````"4`````
-M```````````````!````````````````````$0````,`````````````````
-M````````Q=P```````!;`````````````````````0``````````````````
-M``$````"`````````````````````````*#@````````L!,````````-````
-M8@````@`````````&``````````)`````P````````````````````````!0
-M]````````'P-```````````````````!````````````````````````````
-M`````````````````````````0````0`\?\`````````````````````````
-M``,``0````````````````````````````,``P``````````````````````
-M``````,`!0``````````````````````"`````(``0!0"P```````'$`````
-M````&0````(``0#0"P```````/L`````````+`````(``0`@#P```````&T`
-M````````.0````(``0#0%0```````,<!````````1@````(``0#`'```````
-M`"@`````````50````(``0#P'````````*0`````````9@````(``0!P'P``
-M`````!\`````````<@````(``0"0'P```````!<`````````?0````$`!0``
-M``````````@`````````B@````(``0"P'P```````)D!````````F@````(`
-M`0!0(0```````&H`````````HP````(``0#`(0```````$(`````````JP``
-M``(``0`0(@```````#<`````````LP````(``0!0(@```````#T`````````
-MO@````(``0"0(@```````!@`````````Q@````(``0"P(@```````#(`````
-M````V`````(``0#P(@```````"4`````````YP````(``0`@(P```````(0`
-M````````\@````(``0"P(P```````"@`````````_P````(``0#@(P``````
-M`%D`````````"P$```(``0!`)````````"D"````````&`$```(``0!P)@``
-M`````,(`````````)0$```(``0!`)P```````#4"````````+P$```(``0"`
-M*0```````/$`````````/@$```(``0!P8@```````-T`````````20$```(`
-M`0"`*@```````*,$````````50$```(``0#0.P```````!<C````````8P$`
-M``(``0"@8````````$,!````````;P$```(``0`P+P```````"4`````````
-M>0$```(``0"0.0```````#D"````````BP$```(``0!@+P```````+4`````
-M````G`$```(``0`@,````````!H!````````J0$```(``0!`,0```````,(`
-M````````M@$```(``0!0,@```````*``````````PP$```(``0`0,@``````
-M`#X`````````S@$```(``0#P,@```````(P!````````V0$```(``0"`-```
-M`````.H!````````Y0$```(``0"P.````````'H`````````\P$```(``0!P
-M-@```````.@```````````(```(``0!@-P```````$H!````````#0(```(`
-M`0`P.0```````%0```````````````,`!@``````````````````````'@(`
-M``(``0!08P```````+$"````````+@(```(``0`09@```````'\`````````
-M10(```(``0"09@```````#\%````````4`(```(``0#0:P```````.4#````
-M````7`(```(``0#`;P```````"H`````````;`(```(``0#P=0```````'H"
-M````````>0(```(``0!0?P```````"8`````````B@(```(``0#P?P``````
-M`$\`````````GP(```(``0!`@````````"``````````L@(```(``0!@@```
-M`````#@`````````OP(```(``0"@@````````,`"````````U0(```(``0!@
-M@P```````(\!````````[`(```(``0#PA````````.$`````````!`,```(`
-M`0#`F````````&$`````````$@,```(``0#@A0```````),!````````)0,`
-M``(``0``FP```````'H`````````-`,```(``0!`G````````"L"````````
-M2`,```(``0!`C@```````&\!````````6P,```(``0"`AP```````+$`````
-M````:@,```(``0!`B`````````,#````````?@,```(``0!PDP```````)X`
-M````````D`,```(``0`PD@```````#H!````````G@,```(``0#PFP``````
-M`$4`````````JP,```(``0!0BP```````'H`````````P0,```(``0#PF0``
-M`````"T`````````V`,```(``0#0BP```````*,!````````ZP,```(``0"`
-MC0```````,``````````^P,```(``0`@F@```````-(`````````"`0```(`
-M`0"`FP```````&D`````````&P0```(``0"PCP```````)L!````````+`0`
-M``(``0!0D0```````-$`````````.@0```(``0`0E`````````4"````````
-M2P0```(``0`@E@```````!P`````````9`0```(``0!`E@```````"<!````
-M````>P0```(``0!PEP```````$(`````````D`0```(``0#`EP```````&T`
-M````````I`0```(``0`PF````````($`````````KP0```(``0`PF0``````
-M`"@`````````P00```(``0!@F0```````(<`````````UP0```(``0!0L0``
-M`````-``````````[P0```(``0"0N````````+D`````````_`0```$``P#0
-M`````````!P`````````!@4```$``P#P`````````!P`````````$`4```(`
-M`0"`N0```````)H`````````&04```$`!0`(``````````@`````````(04`
-M``(``0`@N@```````#T`````````*04```(``0!@N@```````&@`````````
-M-`4```(``0`0O0```````+$`````````/`4```(``0``OP```````-0!````
-M``````````,`"`````````````````````````````,`"@``````````````
-M````````5`4``!(``0```````````)P%````````8`4``!$``P`@````````
-M`$@`````````;P4``!``````````````````````````?`4``!$``P"`````
-M`````$@`````````C`4``!(``0!`=0```````",`````````E04``!``````
-M````````````````````HP4``!``````````````````````````K04``!``
-M````````````````````````MP4``!(``0"@!0```````.P`````````P04`
-M`!``````````````````````````S@4``!``````````````````````````
-MX`4``!(``0"0!@````````D"````````\`4``!``````````````````````
-M````^04``!(``0!P=0```````'<`````````!P8``!(``0"@"````````%0`
-M````````&@8``!(``0!`>0````````X`````````*`8``!(``0``"0``````
-M`$H!````````-08``!(``0`0>0```````"H`````````1P8``!(``0!@<@``
-M`````&L`````````4@8``!(``0!0"@```````/0`````````908``!(``0#0
-M#````````%L`````````=@8``!(``0#@?`````````P`````````@@8``!(`
-M`0#`>@```````%4`````````D@8``!(``0`P#0```````#0!````````I`8`
-M`!(``0"P?````````"\`````````M`8``!(``0!P#@```````#L`````````
-MQP8``!(``0"P#@```````&P`````````V08``!(``0"0#P```````)(!````
-M````[P8``!(``0`P$0```````(,`````````#`<``!(``0#`$0```````+8`
-M````````(`<``!(``0`@?0```````'H`````````+@<``!(``0"`$@``````
-M`.X`````````10<``!(``0!P$P```````%$!````````70<``!(``0#0%```
-M`````/X`````````<P<``!``````````````````````````?0<``!(``0"@
-M%P```````$,"````````CP<``!(``0#P?````````"@`````````H`<``!(`
-M`0#P&0```````$\!````````LP<``!(``0!`&P```````'\!````````Q`<`
-M`!(``0"@'0```````%L`````````U`<``!(``0``'@```````#0!````````
-MY0<``!(``0!`'P```````"D`````````]P<``!$``P````````````0`````
-M````!P@``!``````````````````````````%0@``!(``0#P7@```````#\!
-M````````*`@``!``````````````````````````.P@``!``````````````
-M````````````0@@``!``````````````````````````20@``!(``0`P8```
-M`````&8`````````50@``!``````````````````````````=P@``!(``0``
-M?````````*,`````````A0@``!(``0#P80```````'$`````````EP@``!(`
-M`0#P;P```````&D"````````J0@``!(``0#P<P```````$<!````````O`@`
-M`!(``0#0<@```````!8!````````S@@``!``````````````````````````
-MX`@``!``````````````````````````\P@``!(``0!P>````````$(`````
-M`````@D``!(``0#`>````````$<`````````$0D``!(``0!0>0```````&0!
-M````````(`D``!(``0`@>P```````'X`````````,0D``!(``0"@>P``````
-M`%L`````````/@D``!(``0"@?0```````!4`````````20D``!(``0#`?0``
-M`````"<`````````60D``!(``0#P?0```````%X!````````90D``!(``0#`
-MI@```````#T`````````?0D``!(``0``IP```````$8`````````D0D``!(`
-M`0#0LP```````&``````````K`D``!(``0`PM````````.8`````````T0D`
-M`!(``0!PI@```````$,`````````Z`D``!(``0"`?P```````&(`````````
-M_PD``!``````````````````````````$PH``!``````````````````````
-M````)`H``!``````````````````````````-PH``!$``P#(``````````0`
-M````````2@H``!``````````````````````````7`H``!``````````````
-M````````````;@H``!``````````````````````````@`H``!``````````
-M````````````````D0H``!(``0!0N0```````"L`````````H`H``!(``0!`
-ML````````($`````````N@H``!(``0!PG@```````%T#````````S`H``!(`
-M`0"PH@```````(P`````````ZPH``!(``0#0H0```````"$``````````0L`
-M`!(``0``H@````````L`````````$PL``!(``0`0H@````````L`````````
-M)@L``!(``0`@H@```````&``````````/0L``!(``0"`H@```````",`````
-M````40L``!(``0!`HP```````#,"````````:`L``!(``0"`I0```````.0`
-M````````?0L``!(``0!0IP```````!T`````````E`L``!(``0!PIP``````
-M`)4`````````M0L``!(``0`0J````````.``````````SPL``!(``0#PJ```
-M`````)\`````````Z`L``!(``0"0J0```````/\```````````P``!(``0"0
-MJ@```````$T!````````%PP``!(``0#@JP```````%``````````+@P``!(`
-M`0`PK````````,@!````````00P``!(``0``K@```````-P!````````7PP`
-M`!(``0#@KP```````"$`````````>@P``!(``0`0L````````"(`````````
-MEPP``!(``0#0L````````#<`````````L0P``!(``0`0L0```````#<`````
-M````S`P``!(``0`@L@```````*,`````````Z0P``!(``0#0L@```````,8`
-M````````!PT``!(``0"@LP```````#``````````)@T``!(``0`@M0``````
-M`&$#````````/`T``!(``0#0N@```````!(!````````0PT``!(``0#PNP``
-M`````!(!````````2PT``!(``0#0O0```````.0`````````60T``!(``0#`
-MO@```````#X`````````9@T``!(``0#@P````````%(``````````')A:60N
-M8P!3=')I<&5'971#;VUM86YD`%-T<FEP95-P;&ET0V]M;6%N9`!)<U9$979/
-M;FQI;F4`1&]#;VYT<F]L0VUD`$I"3T1'971#;VUM86YD`$I"3T13<&QI=$-O
-M;6UA;F0`7U]H<'1?86QL;V,`7U]H<'1?9G)E90!G87)B86=E7V%D9'(`:6YI
-M=%]H96%P7V)L;V-K`&-B7V%L;&]C`&-B7V9R964`8V)?>F5R;P!C8E]I<U]Z
-M97)O`&-F7VEN:70`<F5M;W9E7W)A;F=E7VQO8VL`861D7W)A;F=E7VQO8VL`
-M;&]C:U]R86YG90!?7V%L;&]C7W1A<VL`9G)E95]S=')I<&4`86QL;V-?<W1R
-M:7!E`%]?9V5T7W-T<FEP90!D871A7WAF97(`<F5A9%]X9F5R7V1O;F4`<F%I
-M9#5?9&]N90!S=')I<&5?9&]N90!H86YD;&5?<W1R:7!E`')A:60U7V1I<G1Y
-M`'1A<VM?9&]N90!S=')I<&5?8VAE8VM?=&%S:P!R=U]T87-K7V)U:6QD<V=L
-M`')W7V=E=%]R86YG90!R=U]T87-K7V1O;F4`7U]D;U]R=U]T87-K`&1O7W)W
-M7W1A<VL`9V5T7W-L:6-E<P!D;U]X;W)?=&%S:P!X;W)?=&%S:U]D;VYE`&1O
-M7WAO<C)?=&%S:P!D;U]X;W)N7W1A<VL`8VAE8VM?9&5P96YD96YC>0!D:7)E
-M8W1?<F5A9%]S9VP`9&ER96-T7W)E861?8V]M<&QE=&EO;@!H86YD;&5?8VUD
-M`&=E=%]S=')I<&5S`'=R:71E7WAF97)?9&]N90!3>6YC1&ES:TEN9F\`9V5T
-M161M85)E9T]F9G-E=`!U;FUA<VM%9&UA26YT97)R=7!T<P!M87-K161M84EN
-M=&5R<G5P=',`:7-%>'1#;VUM86YD`'=R:71E161M85)E<75E<W1%;G1R>0!D
-M=6UP071A1&5V:6-E4F5G:7-T97)S`&AA;F1L945D;6%&86EL961#;VUM86YD
-M`')E;6]V94-O;6UA;F0`:&%N9&QE161M85)E<W!O;G-E`&1E86-T:79A=&5%
-M9&UA`'-E;F1.;VYE561M84-O;6UA;F0`8V]M<&QE=&5024]#;VUM86YD`%-E
-M=$=024]#=')L4F5G`&AA;F1L945D;6%);G1E<G)U<'0`7V-H86YN96Q(87)D
-M4F5S970`7V9I>%!H>5!A<F%M<P!?9&]!=71O1FQU<V@`:&%N9&QE1&5V:6-E
-M26YT97)R=7!T`&1I<V%B;&53841E=DEN=&5R<G5T<',`:&%N9&QE4$E/26YT
-M97)R=7!T`'1R86YS9F5R4$E/1&%T80!A8W1I=F%T945D;6$`161M85)E<5%U
-M975E26YS97)T`')E<V5T161M84-H86YN96P`9FQU<VA$;6%1=65U90!R979E
-M<G13871A2$-296=S`')E=F5R=$9L87-H26YT97)F86-E4F5G<P!R979E<G10
-M0TE);G1E<F9A8V5296=S`&-O;6UA;F1S475E=65!9&1486EL`&-O;6UA;F1S
-M475E=65296UO=F4`861D0V]M;6%N9`!3841E=DEN=&5R<G5T<$)I=`!E;F%B
-M;&53841E=DEN=&5R<G5T<',`:7-3=&]R86=E1&5V4F5A9'E&;W)024\`7V1O
-M4V]F=%)E<V5T`%]A9&1R36%P,0!?861D<DUA<#(`16YT97(V,#$`861D<DUA
-M<`!%>&ET-C`Q`&=E=%\V,#%?:60`<V5T7V-T;`!?7V-H96-K7W!R;W1E8W1?
-M8VER8W5I=`!F0VAE8VM!<G)A>0!P9FY396YD0V]M;6%N9`!F1&5296%D5W)I
-M=&4`<&9N1&5V:6-E1F%I;&5D`$-H96-K4W5M`&9$95-E;&5C=$UO9&4`;W-?
-M;65M<V5T`&]S7VUE;6-P>0!F061D4W!A<F4`1V5T4W!A<F5$:7-K`&EO8W1L
-M7U)E<&]R=$5V96YT`$9I>'5P07)R87E3=&%T90!'9713=&%M<`!3>6YC07)R
-M87E);F9O`$-H96-K07)R87E#<FET:6-A;`!F3W-$:7-K1F%I;&5D`&9$96QE
-M=&5!<G)A>0!5;G)E9VES=&5R5D1E=FEC90!R86ED-5]F<F5E`%-T<FEP94)U
-M:6QD4V=486)L90!F4D%)1#!-96UB97)$;VYE`$9R965#;VUM86YD`$-A;&Q!
-M9G1E<E)E='5R;@!F4D%)1#!396YD0V]M;6%N9`!!;&QO8V%T94-O;6UA;F0`
-M9E)!240P365M8F5R1F%I;&5D`%)!240Q0G5I;&139U1A8FQE`%)!240Q365M
-M8F5R0V]M<&QE=&EO;@!204E$,4EN:71296)U:6QD0G5I;&139U1A8FQE`%)!
-M240Q26YI=$-O;7!L971I;VX`1&]786ET:6YG3&ES=`!204E$,5)E8G5I;&1#
-M;VUP;&5T:6]N`%)!240Q5F5R:69Y0G5I;&139U1A8FQE`%)!240Q5F5R:69Y
-M0V]M<&QE=&EO;@!O<U]M96UC;7``9E)!240Q4V5N9$-O;6UA;F0`061D5&]7
-M86ET:6YG3&ES=`!F4D%)1#%-96UB97)&86EL960`2D)/1$)U:6QD4V=486)L
-M90!F2D)/1$UE;6)E<D1O;F4`9DI"3T1396YD0V]M;6%N9`!F2D)/1$UE;6)E
-M<D9A:6QE9`!N=6U?<F%I9#5?<&%G97,`;W-?86QL;V-?<&%G90!F;'5S:%]S
-M=')I<&5?8V%C:&4`9D]S4&AY<VEC86Q!9&1R97-S`$1O6&]R,@!$;UAO<C$`
-M9FQU<VA?<F%I9#4`9D-O;7!L971E06QL0V]M;6%N9'-3>6YC:')O;F]U<VQY
-M`$-H96-K261L94-A;&P`9FQU<VA?<F%I9#5?87-Y;F,`9E)!240U4V5N9$-O
-M;6UA;F0`9E)!240U365M8F5R1F%I;&5D`&EN:71?<F%I9#5?;65M;W)Y`&]S
-M7V%L;&]C7V1M85]P86=E`&9$979I8V5396YD0V]M;6%N9`!F1V5T1FER<W1#
-M:&EL9`!F4F5S971";V]T36%R:P!F0VAE8VM";V]T86)L90!#:&5C:U!E;F1I
-M;F=#86QL`$-A;&Q7:&5N261L90!F1FQU<VA61&5V`&9&;'5S:%9$979!<WEN
-M8P!M=E)E8617<FET90!M=E-A=&%$:7-A8FQE0VAA;FYE;$1M80!M=E-A=&%&
-M;'5S:$1M85%U975E`&UV4W1O<F%G941E=D%405-E=$9E871U<F5S`&UV4W1O
-M<F%G941E=D%4045X96-U=&5.;VY51$U!0V]M;6%N9`!M=E-A=&%%;F%B;&5#
-M:&%N;F5L1&UA`'=A:71&;W)"=7-Y069T97)(4F5S970`;79-:6-R;U-E8V]N
-M9'-$96QA>0!-5E]214=?4D5!1%]"651%`$U67U)%1U]74DE415]$5T]21`!M
-M=D%U=&]&;'5S:$]N17)R;W(`359?4D5'7U=2251%7T)95$4`359?4D5'7U)%
-M041?1%=/4D0`359?4D5'7U=2251%7U=/4D0`359?4D5'7U)%041?5T]21`!?
-M9&]-=E-O9G1297-E=`!W86ET5VAI;&53=&]R86=E1&5V27-"=7-Y`&UV4V%T
-M84EN:71!9&%P=&5R`&UV4V%T84ES4W1O<F%G941E=FEC94-O;FYE8W1E9`!M
-M=E-A=&%3:'5T9&]W;D%D87!T97(`;79%;F%B;&5!=71O1FQU<V@`;79$:7-A
-M8FQE075T;T9L=7-H`&UV4V%T84-O;F9I9W5R94-H86YN96P`;793871A4F5M
-M;W9E0VAA;FYE;`!M=E-A=&%#:&%N;F5L2&%R9%)E<V5T`&UV4V%T84-O;F9I
-M9T5D;6%-;V1E`&UV4V%T84YU;4]F1&UA0V]M;6%N9',`;793871A0VAA;FYE
-M;%-E=$5D;6%,;V]P0F%C:TUO9&4`;793871A4V5T0VAA;FYE;%!H>5!A<F%M
-M<P!M=E-A=&%#:&%N;F5L4&AY4VAU=&1O=VX`;793871A0VAA;FYE;%!H>5!O
-M=V5R3VX`;793871A1V5T0VAA;FYE;%-T871U<P!M=E-A=&%1=65U955$;6%#
-M;VUM86YD`&UV4V%T85%U975E0V]M;6%N9`!M=E-A=&%);G1E<G)U<'1397)V
-M:6-E4F]U=&EN90!M=E-A=&%-87-K061A<'1E<DEN=&5R<G5P=`!M=E-A=&%5
-M;FUA<VM!9&%P=&5R26YT97)R=7!T`&5N86)L95-T;W)A9V5$979);G1E<G)U
-M<'0`9&ES86)L95-T;W)A9V5$979);G1E<G)U<'0`;793=&]R86=E1&5V051!
-M261L94EM;65D:6%T90!M=E-T;W)A9V5$979!5$%)9&5N=&EF>41E=FEC90!M
-M=E-T;W)A9V5$979!5$%3;V9T4F5S971$979I8V4`97AE8W5T94YO;E5$34%#
-M;VUM86YD`$)E97!/;@!"965P3V9F`'-E=%]F86EL7VQE9',`<V5T7V9A:6Q?
-M;&5D`&-H96-K7W!R;W1E8W1?8VER8W5I=```````<0`````````+````8P``
-M````````````EP`````````"````9````/S_________K@`````````+````
-M90``````````````R``````````"````9@```/S_________\0`````````"
-M````9P```/S__________@`````````"````9@```/S_________&0$`````
-M```"````:````/S_________I0$````````"````90```/S_________TP$`
-M```````+````8P``````````````8@(````````"````:````/S_________
-MYP(````````+````8P```````````````0,````````"````:0```/S_____
-M____%P,````````"````:0```/S_________,`,````````"````:0```/S_
-M________1@,````````"````:0```/S_________OP,````````"````:```
-M`/S_________2P0````````+````8P``````````````6P0````````+````
-M90``````````````B@0````````"````:0```/S_________H`0````````"
-M````:0```/S_________N00````````"````:0```/S_________SP0`````
-M```"````:0```/S_________$@4````````+````90``````````````7`4`
-M```````+````90``````````````[04````````"````:P```/S_________
-M(`8````````"````8P```!0`````````,`8````````+````90``````````
-M````?08````````"````;````/S_________+0<````````"````;0```/S_
-M________HP<````````"````:@```/S_________0@@````````"````:@``
-M`/S_________;@@````````"````;@```/S_________>0@````````"````
-M;P```/S_________U@@````````"````;0```/S_________Y`@````````+
-M````<0``````````````(0D````````"````<P```/S_________,@D`````
-M```"````=````/S_________;0D````````"````<@```/S_________GPD`
-M```````+````<0``````````````PPD````````"````:````/S_________
-MV0D````````"````9````/S_________]@D````````"````;P```/S_____
-M____&PH````````"````:````/S_________``T````````"````=P```/S_
-M________(`T````````"````>````/S_________;@T````````"````>```
-M`/S_________E0T````````"````>````/S_________P@T````````"````
-M>@```/S_________%@X````````+````=@``````````````'@X````````+
-M````=0``````````````'A`````````"````:````/S_________<1``````
-M```"````:````/S_________KA`````````"````=P```/S_________WA``
-M```````"````>````/S_________`Q(````````"````=P```/S_________
-M/A(````````"````>````/S_________5Q(````````+````@```````````
-M````7Q(````````"````>````/S_________UQ(````````"````:````/S_
-M________)Q,````````"````=P```/S_________-A,````````"````>```
-M`/S_________3Q,````````+````@```````````````5Q,````````"````
-M>````/S_________*A4````````"````:````/S_________414````````"
-M````A````/S_________AQ4````````"````=P```/S_________EA4`````
-M```"````>````/S_________KQ4````````+````@```````````````MQ4`
-M```````"````>````/S_________318````````"````:````/S_________
-M818````````"````>@```/S_________AA8````````+````?P``````````
-M````CA8````````+````?@``````````````PQ8````````"````>@```/S_
-M________Z!8````````+````@0``````````````\!8````````+````?@``
-M````````````%1<````````"````>@```/S_________.A<````````+````
-M@P``````````````0A<````````+````@@``````````````9Q<````````"
-M````>````/S_________<A<````````+````@```````````````>A<`````
-M```"````>````/S_________W1<````````"````>````/S_________\!<`
-M```````+`````@```-`5````````11@````````+````A0``````````````
-M41@````````"````A@```/S_________7AD````````"````>@```/S_____
-M____<1D````````"````:0```/S_________C1D````````+````?0``````
-M````````E1D````````+````?```````````````HAH````````"````:P``
-M`/S_________O!H````````"````8P```!0`````````QQH````````"````
-M90```"P`````````"AL````````"````;````/S_________*1L````````"
-M````;@```/S_________-!L````````"````;P```/S_________AAP`````
-M```"````:0```/S_________T!T````````"````=P```/S_________\!T`
-M```````"````>````/S_________/AX````````"````>````/S_________
-M91X````````"````>````/S_________DAX````````"````>@```/S_____
-M____YAX````````+````B0``````````````[AX````````+````B```````
-M````````=B`````````"````C0```/S_________-2(````````"````:```
-M`/S_________GR(````````"````:````/S_________WR@````````"````
-M:0```/S_________\2@````````"````:0```/S_________,"T````````+
-M`````@```(`I````````+BX````````+`````@```'!B````````,RX`````
-M```"````>````/S_________;2X````````+````@```````````````=2X`
-M```````"````>````/S_________CRX````````+````@```````````````
-MERX````````"````>````/S_________URX````````"````>````/S_____
-M_____"X````````"````C@```/S_________1"\````````+`````@```)`Y
-M````````22\````````"````>````/S_________SR\````````"````CP``
-M`/S_________93$````````"````=P```/S_________@S(````````"````
-M>@```/S_________OS(````````+`````@```&`O````````RS(````````+
-M`````@```$`Q````````;S4````````"````D````/S_________D34`````
-M```"````D0```/S_________$38````````"````D````/S_________!3<`
-M```````"````D````/S_________63@````````"````D````/S_________
-M>#@````````"````D0```/S_________C3H````````+````+@``````````
-M````/SL````````+````+@```#@`````````Q%\````````"````>````/S_
-M________9&`````````"````C@```/S_________;&`````````"````DP``
-M`/S_________=&`````````"````E````/S_________1&(````````"````
-MC@```/S_________QV(````````"````>````/S_________W&(````````+
-M````@```````````````Y&(````````"````>````/S_________%&,`````
-M```+````@```````````````'&,````````"````>````/S_________0F,`
-M```````"````C@```/S_________360````````"````!````/S_________
-M5F0````````"````!````/S_________6V0````````"````CP```/S_____
-M____-F8````````"````=P```/S_________SV@````````"````:````/S_
-M_________FH````````+````@```````````````!FL````````"````>```
-M`/S_________/VL````````"````>@```/S_________:FL````````+````
-M`@```%!C````````<FL````````+`````@```!!F````````TF\````````+
-M`````@```'!B````````UV\````````"````>````/S_________$W``````
-M```"````>````/S_________1W`````````"````:````/S_________;W``
-M```````"````>````/S_________D7`````````"````>````/S_________
-M*7$````````"````>````/S_________7W$````````+````E@``````````
-M````:W$````````"````A@```/S_________MW$````````+````EP``````
-M````````\G$````````+````E@```````````````G(````````"````A@``
-M`/S_________"G(````````"````C@```/S_________&7(````````+````
-M`@```,!O````````.7(````````"````>````/S_________=W(````````"
-M````D@```/S_________(G,````````"````C````/S_________9',`````
-M```"````C````/S_________E7,````````"````F0```/S_________G',`
-M```````"````!````/S_________I',````````"````C````/S_________
-MM',````````"````F0```/S_________VW,````````"````C````/S_____
-M____J'0````````"````:P```/S_________R70````````"````8P```!0`
-M````````U'0````````"````90```#P`````````"G4````````"````;```
-M`/S_________(74````````"````;@```/S_________+'4````````"````
-M;P```/S_________PG4````````"````;P```/S_________.'8````````"
-M````:````/S_________8W<````````"````:0```/S_________>'<`````
-M```"````:0```/S_________D'<````````"````:0```/S_________I7<`
-M```````"````:0```/S_________(7@````````"````9@```/S_________
-M,W@````````"````9@```/S_________6'@````````"````9````/S_____
-M____JG@````````"````FP```/S_________['@````````"````G````/S_
-M________2'D````````"````<P```/S_________E'D````````"````:```
-M`/S_________]GD````````"````9````/S_________0'H````````"````
-M9````/S_________@'P````````"````DP```/S_________UGP````````"
-M````:````/S_________JGT````````"````D@```/S_________T7T`````
-M```"````E0```/S_________+7X````````"````HP```/S_________/'X`
-M```````"````I````/S_________8WX````````"````I0```/S_________
-M%7\````````"````I@```/S_________(W\````````"````IP```/S_____
-M____CW\````````"````J0```/S_________KW\````````"````J@```/S_
-M________QG\````````"````J0```/S_________&H`````````"````JP``
-M`/S_________+(`````````"````JP```/S_________6H`````````"````
-MJP```/S_________IH,````````"````J@```/S_________OH,````````"
-M````J@```/S_________UX,````````"````J@```/S_________\8,`````
-M```"````J@```/S_________"X0````````"````J@```/S_________,X0`
-M```````"````J@```/S_________2X0````````"````K0```/S_________
-M5X0````````"````J@```/S_________:(0````````"````J@```/S_____
-M____>H0````````"````J@```/S_________C(0````````"````J@```/S_
-M________I(0````````"````K0```/S_________LX0````````"````J@``
-M`/S_________Q80````````"````J@```/S_________,(4````````"````
-MK@```/S_________JH<````````"````K@```/S_________P(<````````"
-M````JP```/S_________SH<````````"````K@```/S_________W(<`````
-M```"````K@```/S_________]8<````````"````JP```/S_________`X@`
-M```````"````K@```/S_________%(@````````"````JP```/S_________
-MPH@````````"````JP```/S_________.XD````````"````K@```/S_____
-M____48D````````"````JP```/S__________HD````````"````JP```/S_
-M________"XH````````"````K@```/S_________%8H````````"````J0``
-M`/S_________)XH````````"````JP```/S_________-(H````````"````
-MK@```/S_________/HH````````"````J0```/S_________8XH````````"
-M````J@```/S_________#8L````````"````K````/O_________'XP`````
-M```"````J@```/S_________+8P````````"````J@```/S_________4HP`
-M```````"````JP```/S_________Y(T````````"````KP```/S_________
-M%8X````````"````L````/S_________T8X````````"````K````/O_____
-M____1H\````````"````K@```/S_________4(\````````"````J0```/S_
-M________TX\````````"````K@```/S_________YH\````````"````JP``
-M`/S_________\(\````````"````K@```/S_________^H\````````"````
-MJ0```/S_________&9`````````"````JP```/S_________P)`````````"
-M````JP```/S_________T9`````````"````JP```/S_________X)``````
-M```"````JP```/S_________]9`````````"````JP```/S_________!I$`
-M```````"````JP```/S_________%9$````````"````JP```/S_________
-M)I$````````"````JP```/S_________-Y$````````"````JP```/S_____
-M____F)(````````"````K@```/S_________RI(````````"````JP```/S_
-M________\I(````````"````K@```/S_________39,````````"````JP``
-M`/S_________KI,````````"````JP```/S_________NI,````````"````
-MK@```/S_________Q),````````"````J0```/S_________U9,````````"
-M````JP```/S_________X9,````````"````K@```/S_________9)0`````
-M```"````JP```/S_________;Y0````````"````K@```/S_________BI0`
-M```````"````JP```/S_________FY0````````"````JP```/S_________
-MKI0````````"````JP```/S_________P90````````"````JP```/S_____
-M____U)0````````"````JP```/S_________YY0````````"````JP```/S_
-M________^I0````````"````JP```/S_________#94````````"````JP``
-M`/S_________()4````````"````JP```/S_________,Y4````````"````
-MJP```/S_________1I4````````"````JP```/S_________694````````"
-M````JP```/S_________;)4````````"````JP```/S_________FY4`````
-M```"````JP```/S_________K)4````````"````JP```/S_________O94`
-M```````"````JP```/S_________SI4````````"````JP```/S_________
-MW)4````````"````K@```/S_________\Y4````````"````JP```/S_____
-M____,Y8````````"````JP```/S_________6I8````````"````K@```/S_
-M________;98````````"````JP```/S_________>Y8````````"````K@``
-M`/S_________D)8````````"````JP```/S_________HY8````````"````
-MJP```/S_________MI8````````"````JP```/S_________R98````````"
-M````JP```/S_________W)8````````"````JP```/S_________[Y8`````
-M```"````JP```/S_________`I<````````"````JP```/S_________%9<`
-M```````"````JP```/S_________*)<````````"````JP```/S_________
-M.Y<````````"````JP```/S_________3I<````````"````JP```/S_____
-M____89<````````"````JP```/S_________7Y@````````"````:0```/S_
-M________<Y@````````"````:0```/S_________C)D````````"````J@``
-M`/S_________NID````````"````JP```/S_________SID````````"````
-MJP```/S_________W)D````````"````K@```/S_________%YH````````"
-M````JP```/S_________AYH````````"````JP```/S_________G)H`````
-M```"````JP```/S_________M9H````````"````J@```/S_________T9H`
-M```````"````JP```/S_________1YL````````"````JP```/S_________
-M49L````````"````K@```/S_________W9L````````"````JP```/S_____
-M____%)P````````"````L0```/S_________<9P````````"````J@```/S_
-M________H)P````````"````K0```/S_________M)P````````"````K0``
-M`/S_________R)P````````"````K0```/S_________W)P````````"````
-MK0```/S_________\)P````````"````K0```/S_________/9T````````"
-M````K0```/S_________49T````````"````K0```/S_________99T`````
-M```"````K0```/S_________>9T````````"````K0```/S_________C9T`
-M```````"````K0```/S_________H9T````````"````K0```/S_________
-MM9T````````"````K0```/S_________SIT````````"````J@```/S_____
-M____XIT````````"````L@```/S_________^9T````````"````J@```/S_
-M________+YX````````"````KP```/S_________J9X````````"````JP``
-M`/S_________FY\````````"````K@```/S_________^9\````````"````
-MJP```/S_________!Z`````````"````K@```/S_________'Z`````````"
-M````JP```/S_________+:`````````"````K@```/S_________I*``````
-M```"````JP```/S_________M:`````````"````JP```/S_________QJ``
-M```````"````JP```/S_________[:`````````"````JP```/S_________
-M#Z$````````"````JP```/S_________2J$````````"````J0```/S_____
-M____?*$````````"````M````/S_________XZ$````````"````JP```/S_
-M________`J(````````"````K````/C_________$J(````````"````K```
-M`/C_________X:(````````"````K@```/S_________!Z,````````"````
-MK@```/S_________$:,````````"````J0```/S_________'*,````````"
-M````K@```/S_________O:,````````"````JP```/S_________QZ,`````
-M```"````K@```/S_________T:,````````"````J0```/S_________X*,`
-M```````"````JP```/S_________ZJ,````````"````K@```/S_________
-M3:0````````"````K@```/S_________=Z0````````"````JP```/S_____
-M____EZ0````````"````K@```/S_________H:0````````"````J0```/S_
-M________QJ0````````"````JP```/S_________YJ0````````"````K@``
-M`/S_________\*0````````"````J0```/S__________J0````````"````
-MJ````/S_________,J4````````"````J@```/S_________UZ4````````"
-M````K@```/S_________/*8````````"````JP```/S_________J*<`````
-M```"````K@```/S_________QZ<````````"````JP```/S_________Y:<`
-M```````"````JP```/S_________B:@````````"````K@```/S_________
-MMZ@````````"````JP```/S_________+JD````````"````K@```/S_____
-M____6JD````````"````JP```/S_________<ZD````````"````K@```/S_
-M________SJD````````"````K@```/S__________*D````````"````JP``
-M`/S_________%:H````````"````K@```/S_________/:H````````"````
-MK@```/S_________;ZH````````"````JP```/S_________WZH````````"
-M````K@```/S_________!ZL````````"````M````/S_________6:L`````
-M```"````K@```/S_________:*L````````"````K@```/S_________=ZL`
-M```````"````K@```/S_________AJL````````"````K@```/S_________
-ME:L````````"````K@```/S_________I*L````````"````K@```/S_____
-M____LZL````````"````K@```/S_________PJL````````"````K@```/S_
-M________)ZP````````"````PP```/S_________-*X````````"````K@``
-M`/S_________::X````````"````K@```/S_________?*X````````"````
-MJP```/S_________P:X````````"````JP```/S_________RZX````````"
-M````K@```/S_________WZX````````"````JP```/S_________^*X`````
-M```"````K@```/S_________\Z\````````"````JP```/S_________)+``
-M```````"````JP```/S_________>[`````````"````J@```/S_________
-ME+`````````"````J0```/S_________Z[`````````"````K0```/S_____
-M____`;$````````"````J@```/S_________*[$````````"````K0```/S_
-M________0;$````````"````J@```/S_________C+$````````"````J@``
-M`/S_________FK$````````"````J0```/S_________K+$````````"````
-MJ@```/S_________QK$````````"````M````/S_________U+$````````"
-M````J0```/S_________\[$````````"````L@```/S_________`[(`````
-M```"````J@```/S_________9+(````````"````R````/S_________=[(`
-M```````"````K0```/S_________B[(````````"````L@```/S_________
-ME[(````````"````QP```/S_________IK(````````"````QP```/S_____
-M____/[,````````"````I@```/S_________Q[,````````"````L0```/S_
-M________)[0````````"````I@```/S_________Z[0````````"````S```
-M`/S_________S+4````````"````R````/S_________YK4````````"````
-MK0```/S_________^[4````````"````K0```/S_________$;8````````"
-M````K0```/S_________)[8````````"````K0```/S_________/;8`````
-M```"````K0```/S_________B;8````````"````K0```/S_________G+8`
-M```````"````K0```/S_________L+8````````"````K0```/S_________
-MQ+8````````"````K0```/S_________V+8````````"````K0```/S_____
-M____[+8````````"````K0```/S_________`+<````````"````K0```/S_
-M________'+<````````"````L@```/S_________*+<````````"````QP``
-M`/S_________.K<````````"````QP```/S_________6;<````````"````
-ML@```/S_________9;<````````"````QP```/S_________@+<````````"
-M````J@```/S_________C+<````````"````QP```/S_________PK<`````
-M```"````L@```/S_________V+<````````"````L````/S_________^[<`
-M```````"````KP```/S_________&+@````````"````L@```/S_________
-M)+@````````"````QP```/S_________,[@````````"````QP```/S_____
-M____0K@````````"````QP```/S_________M+@````````"````K0```/S_
-M________Q;@````````"````J@```/S_________S[@````````"````J0``
-M`/S_________U[@````````"````QP```/S_________X;@````````"````
-MJ0```/S_________Z[@````````"````J0```/S_________];@````````"
-M````J0```/S__________[@````````"````J0```/S_________%[D`````
-M```"````J@```/S_________,;D````````"````J0```/S_________:;D`
-M```````"````J0```/S_________C+D````````"````!`````0`````````
-MG[D````````"````K0```/S_________J[D````````"````!`````0`````
-M````O+D````````"````J@```/S_________T[D````````"````!`````0`
-M````````Y+D````````"````J@```/S_________][D````````"````!```
-M``0`````````"+H````````"````J@```/S_________)[H````````"````
-M!`````0`````````.KH````````"````K0```/S_________0;H````````"
-M````!`````0`````````5[H````````"````K0```/S_________>;H`````
-M```"````!`````0`````````C[H````````"````K0```/S_________EKH`
-M```````"````!`````0`````````IKH````````"````J@```/S_________
-MW;H````````"````K@```/S_________\KH````````"````JP```/S_____
-M_____[H````````"````K@```/S_________'KL````````"````KP```/S_
-M________*[L````````"````K@```/S_________.KL````````"````!```
-M``0`````````4+L````````"````K0```/S_________5[L````````"````
-M!`````0`````````;+L````````"````K0```/S_________<[L````````"
-M````!`````0`````````B;L````````"````K0```/S_________D+L`````
-M```"````!`````0`````````I;L````````"````K0```/S_________O+L`
-M```````"````JP```/S_________R;L````````"````K@```/S_________
-MV;L````````"````JP```/S__________;L````````"````K@```/S_____
-M____$KP````````"````JP```/S_________'[P````````"````K@```/S_
-M________/KP````````"````KP```/S_________2[P````````"````K@``
-M`/S_________6KP````````"````!`````0`````````<+P````````"````
-MK0```/S_________=[P````````"````!`````0`````````C+P````````"
-M````K0```/S_________D[P````````"````!`````0`````````J;P`````
-M```"````K0```/S_________L+P````````"````!`````0`````````Q;P`
-M```````"````K0```/S_________W+P````````"````JP```/S_________
-MZ;P````````"````K@```/S_________^;P````````"````JP```/S_____
-M____'+T````````"````!`````0`````````,KT````````"````K0```/S_
-M________.;T````````"````!`````0`````````3KT````````"````K0``
-M`/S_________8[T````````"````J@```/S_________>[T````````"````
-M!`````0`````````D+T````````"````K0```/S_________HKT````````"
-M````J0```/S_________K[T````````"````J@```/S_________`+X`````
-M```"````K@```/S_________%;X````````"````JP```/S_________(KX`
-M```````"````K@```/S_________0;X````````"````KP```/S_________
-M3KX````````"````K@```/S_________9[X````````"````K0```/S_____
-M____=KX````````"````JP```/S_________@[X````````"````K@```/S_
-M________D[X````````"````JP```/S_________];X````````"````SP``
-M`/S_________';\````````"````K@```/S_________,K\````````"````
-MJP```/S_________/[\````````"````K@```/S_________8+\````````"
-M````KP```/S_________;;\````````"````K@```/S_________>K\`````
-M```"````L````/S_________H[\````````"````!`````0`````````N;\`
-M```````"````K0```/S_________T[\````````"````J0```/S_________
-MX+\````````"````L````/S_________Z;\````````"````!`````0`````
-M````_[\````````"````K0```/S_________)<`````````"````!`````0`
-M````````.\`````````"````K0```/S_________2,`````````"````L```
-M`/S_________>L`````````"````!`````0`````````D,`````````"````
-MK0```/S_________H,`````````"````JP```/S_________K<`````````"
-M````K@```/S_________O<`````````"````JP```/S_________\\``````
-M```"````!```````````````]\`````````+`````P```-``````````"L$`
-M```````"````!```````````````#L$````````+`````P```/``````````
-M(``````````!````F@``````````````*``````````!````F@``````````
-M````,``````````!````F@``````````````.``````````!````F@``````
-M````````0``````````!````B@``````````````2``````````!````>0``
-M````````````4``````````!````A0``````````````8``````````!````
-ME@``````````````@``````````!````<0``````````````B``````````!
-M````<0``````````````D``````````!````<0``````````````F```````
-M```!````<0``````````````H``````````!````BP``````````````J```
-M```````!````>P``````````````L``````````!````AP``````````````
-MP``````````!````EP`````````````````````````!`````@```+TZ````
-M````"``````````!`````@```)$Z````````$``````````!`````@```)$Z
-M````````&``````````!`````@```)@Z````````(``````````!`````@``
-M`*<Z````````*``````````!`````@```+(Z````````,``````````!````
-M`@```+DZ````````.``````````!`````@```&T[````````0``````````!
-M`````@```$,[````````2``````````!`````@```$,[````````4```````
-M```!`````@```$H[````````6``````````!`````@```%<[````````8```
-M```````!`````@```&([````````:``````````!`````@```&D[````````
-M(``````````!`````@``````````````2``````````!`````@```*`%````
-M````<``````````!`````@```)`&````````F``````````!`````@```*`(
-M````````P``````````!`````@`````)``````````$````````!`````@``
-M`%`*````````.`$````````!`````@```%`+````````4`$````````!````
-M`@```-`+````````<`$````````!`````@```-`,````````F`$````````!
-M`````@```#`-````````P`$````````!`````@```'`.````````X`$`````
-M```!`````@```+`.``````````(````````!`````@```"`/````````*`(`
-M```````!`````@```)`/````````4`(````````!`````@```#`1````````
-M<`(````````!`````@```,`1````````F`(````````!`````@```(`2````
-M````P`(````````!`````@```'`3````````Z`(````````!`````@```-`4
-M````````$`,````````!`````@```-`5````````.`,````````!`````@``
-M`*`7````````8`,````````!`````@```/`9````````B`,````````!````
-M`@```$`;````````L`,````````!`````@```,`<````````R`,````````!
-M`````@```/`<````````X`,````````!`````@```*`=````````"`0`````
-M```!`````@`````>````````,`0````````!`````@```$`?````````4`0`
-M```````!`````@```'`?````````:`0````````!`````@```)`?````````
-M@`0````````!`````@```+`?````````P`0````````!`````@```%`A````
-M````Z`0````````!`````@```,`A``````````4````````!`````@```!`B
-M````````*`4````````!`````@```%`B````````0`4````````!`````@``
-M`)`B````````8`4````````!`````@```+`B````````>`4````````!````
-M`@```/`B````````D`4````````!`````@```"`C````````N`4````````!
-M`````@```+`C````````T`4````````!`````@```.`C````````^`4`````
-M```!`````@```$`D````````.`8````````!`````@```'`F````````8`8`
-M```````!`````@```$`G````````H`8````````!`````@```(`I````````
-MR`8````````!`````@```(`J````````\`8````````!`````@```#`O````
-M````$`<````````!`````@```&`O````````4`<````````!`````@```"`P
-M````````:`<````````!`````@```$`Q````````D`<````````!`````@``
-M`!`R````````L`<````````!`````@```%`R````````V`<````````!````
-M`@```/`R``````````@````````!`````@```(`T````````*`@````````!
-M`````@```'`V````````4`@````````!`````@```&`W````````D`@`````
-M```!`````@```+`X````````N`@````````!`````@```#`Y````````T`@`
-M```````!`````@```)`Y````````$`D````````!`````@```-`[````````
-M4`D````````!`````@```/!>````````D`D````````!`````@```#!@````
-M````N`D````````!`````@```*!@````````V`D````````!`````@```/!A
-M``````````H````````!`````@```'!B````````*`H````````!`````@``
-M`%!C````````:`H````````!`````@```!!F````````B`H````````!````
-M`@```)!F````````R`H````````!`````@```-!K````````"`L````````!
-M`````@```,!O````````*`L````````!`````@```/!O````````6`L`````
-M```!`````@```&!R````````@`L````````!`````@```-!R````````J`L`
-M```````!`````@```/!S````````T`L````````!`````@```$!U````````
-MZ`L````````!`````@```'!U````````$`P````````!`````@```/!U````
-M````0`P````````!`````@```'!X````````6`P````````!`````@```,!X
-M````````@`P````````!`````@```!!Y````````F`P````````!`````@``
-M`$!Y````````L`P````````!`````@```%!Y````````X`P````````!````
-M`@```,!Z````````^`P````````!`````@```"![````````&`T````````!
-M`````@```*![````````,`T````````!`````@````!\````````4`T`````
-M```!`````@```+!\````````<`T````````!`````@```.!\````````B`T`
-M```````!`````@```/!\````````H`T````````!`````@```"!]````````
-MR`T````````!`````@```*!]````````Z`T````````!`````@```,!]````
-M````"`X````````!`````@```/!]````````,`X````````!`````@```%!_
-M````````2`X````````!`````@```(!_````````<`X````````!`````@``
-M`/!_````````D`X````````!`````@```$"`````````L`X````````!````
-M`@```&"`````````R`X````````!`````@```*"`````````X`X````````!
-M`````@```&"#````````"`\````````!`````@```/"$````````,`\`````
-M```!`````@```."%````````6`\````````!`````@```("'````````@`\`
-M```````!`````@```$"(````````J`\````````!`````@```%"+````````
-MR`\````````!`````@```-"+````````\`\````````!`````@```("-````
-M````&!`````````!`````@```$".````````0!`````````!`````@```+"/
-M````````<!`````````!`````@```%"1````````L!`````````!`````@``
-M`#"2````````V!`````````!`````@```'"3`````````!$````````!````
-M`@```!"4````````0!$````````!`````@```""6````````8!$````````!
-M`````@```$"6````````@!$````````!`````@```'"7````````F!$`````
-M```!`````@```,"7````````L!$````````!`````@```#"8````````V!$`
-M```````!`````@```,"8````````^!$````````!`````@```#"9````````
-M$!(````````!`````@```&"9````````.!(````````!`````@```/"9````
-M````6!(````````!`````@```"":````````@!(````````!`````@````";
-M````````J!(````````!`````@```(";````````T!(````````!`````@``
-M`/";````````\!(````````!`````@```$"<````````&!,````````!````
-M`@```'">````````0!,````````!`````@```-"A````````8!,````````!
-M`````@````"B````````>!,````````!`````@```!"B````````D!,`````
-M```!`````@```""B````````L!,````````!`````@```("B````````R!,`
-M```````!`````@```+"B````````\!,````````!`````@```$"C````````
-M,!0````````!`````@```("E````````6!0````````!`````@```'"F````
-M````>!0````````!`````@```,"F````````F!0````````!`````@````"G
-M````````N!0````````!`````@```%"G````````T!0````````!`````@``
-M`'"G````````^!0````````!`````@```!"H````````(!4````````!````
-M`@```/"H````````2!4````````!`````@```)"I````````>!4````````!
-M`````@```)"J````````N!4````````!`````@```."K````````V!4`````
-M```!`````@```#"L`````````!8````````!`````@````"N````````*!8`
-M```````!`````@```."O````````2!8````````!`````@```!"P````````
-M:!8````````!`````@```$"P````````D!8````````!`````@```-"P````
-M````L!8````````!`````@```!"Q````````T!8````````!`````@```%"Q
-M`````````!<````````!`````@```""R````````*!<````````!`````@``
-M`-"R````````2!<````````!`````@```*"S````````:!<````````!````
-M`@```-"S````````B!<````````!`````@```#"T````````L!<````````!
-M`````@```""U````````V!<````````!`````@```)"X`````````!@`````
-M```!`````@```%"Y````````(!@````````!`````@```("Y````````2!@`
-M```````!`````@```""Z````````:!@````````!`````@```&"Z````````
-MB!@````````!`````@```-"Z````````L!@````````!`````@```/"[````
-M````V!@````````!`````@```!"]````````^!@````````!`````@```-"]
-M````````(!D````````!`````@```,"^````````0!D````````!`````@``
-A``"_````````@!D````````!`````@```.#`````````
+M```````````````````@`````0````8```````````````````!`````````
+M`#;%```````````````````0````````````````````&P````0`````````
+M````````````````(`8!``````"X-0````````P````!````"``````````8
+M`````````"L````!`````P```````````````````(#%````````*`$`````
+M`````````````"`````````````````````F````!```````````````````
+M``````#8.P$``````)@!````````#`````,````(`````````!@`````````
+M,0````@````#````````````````````J,8````````,````````````````
+M````"````````````````````#L````!`````@```````````````````*C&
+M````````<`````````````````````@````````````````````V````!```
+M``````````````````````!P/0$``````%`!````````#`````8````(````
+M`````!@`````````2`````$````"````````````````````&,<```````"0
+M&0``````````````````"````````````````````$,````$````````````
+M`````````````,`^`0``````\`\````````,````"`````@`````````&```
+M``````!2`````0````````````````````````"HX````````"4`````````
+M```````````!````````````````````$0````,`````````````````````
+M````S>````````!;`````````````````````0````````````````````$`
+M```"`````````````````````````*CD````````^!,````````-````8@``
+M``@`````````&``````````)`````P````````````````````````"@^```
+M`````'\-```````````````````!````````````````````````````````
+M`````````````````````0````0`\?\```````````````````````````,`
+M`0````````````````````````````,``P``````````````````````````
+M``,`!0``````````````````````"`````(``0!0#````````(D`````````
+M&0````(``0#@#````````!$!````````+`````(``0!@$````````&T`````
+M````.0````(``0`P%P```````-\!````````1@````(``0"0'@```````#$`
+M````````50````(``0#0'@```````*4`````````9@````(``0!0(0``````
+M`!\`````````<@````(``0!P(0```````!<`````````?0````$`!0``````
+M``````@`````````B@````(``0"0(0```````)D!````````F@````(``0`P
+M(P```````&H`````````HP````(``0"@(P```````$(`````````JP````(`
+M`0#P(P```````#<`````````LP````(``0`P)````````#T`````````O@``
+M``(``0!P)````````!@`````````Q@````(``0"0)````````#(`````````
+MV`````(``0#0)````````"4`````````YP````(``0``)0```````(4`````
+M````\@````(``0"0)0```````"@`````````_P````(``0#`)0```````%D`
+M````````"P$```(``0`@)@```````"D"````````&`$```(``0!0*```````
+M`,@`````````)0$```(``0`@*0```````#H"````````+P$```(``0!@*P``
+M`````/0`````````/@$```(``0"@9````````-T`````````20$```(``0!@
+M+````````,,$````````50$```(``0``/@```````!<C````````8P$```(`
+M`0#08@```````$,!````````;P$```(``0`P,0```````"4`````````>0$`
+M``(``0#`.P```````#D"````````BP$```(``0!@,0```````+4`````````
+MG`$```(``0`@,@```````!H!````````J0$```(``0!`,P```````,(`````
+M````M@$```(``0!0-````````*,`````````PP$```(``0`0-````````#X`
+M````````S@$```(``0``-0```````(P!````````V0$```(``0"0-@``````
+M`/H!````````Y0$```(``0#@.@```````'D`````````\P$```(``0"0.```
+M`````/H```````````(```(``0"0.0```````$H!````````#0(```(``0!@
+M.P```````%0```````````````,`!@``````````````````````'@(```(`
+M`0"`90```````,L"````````+@(```(``0!0:````````((`````````10(`
+M``(``0#@:````````'D%````````4`(```(``0!@;@```````"$$````````
+M7`(```(``0"0<@```````"H`````````;`(```(``0``>0```````(D"````
+M````>0(```(``0"`@@```````"8`````````B@(```(``0`@@P```````$\`
+M````````GP(```(``0!P@P```````"``````````L@(```(``0"0@P``````
+M`,`"````````R`(```(``0!0A@```````(D!````````WP(```(``0#@AP``
+M`````.$`````````]P(```(``0#`FP```````&``````````!0,```(``0#0
+MB````````),!````````&`,```(``0!`G@```````),`````````)P,```(`
+M`0"@GP```````$`"````````.P,```(``0`PD0```````&\!````````3@,`
+M``(``0!PB@```````+$`````````70,```(``0`PBP```````/@"````````
+M<0,```(``0"`E@```````)T`````````@P,```(``0!`E0```````#H!````
+M````D0,```(``0!0GP```````$4`````````G@,```(``0`PC@```````'H`
+M````````M`,```(``0``G0```````%\`````````RP,```(``0"PC@``````
+M`+D!````````W@,```(``0!PD````````,``````````[@,```(``0!@G0``
+M`````-$`````````^P,```(``0#@G@```````&D`````````#@0```(``0"@
+MD@```````+L!````````'P0```(``0!@E````````-$`````````+00```(`
+M`0`@EP````````4"````````/@0```(``0`PF0```````!P`````````5P0`
+M``(``0!0F0```````"<!````````;@0```(``0"`F@```````$(`````````
+M@P0```(``0#0F@```````&T`````````EP0```(``0!`FP```````(``````
+M````H@0```(``0`@G````````"@`````````M`0```(``0!0G````````*8`
+M````````R@0```(``0`@MP```````,$#````````X`0```(``0#PN@``````
+M`+D`````````[00```$``P#@`````````"``````````]P0```$``P```0``
+M`````"```````````04```$``P`@`0````````@`````````"04```$`!0`(
+M``````````0`````````&`4```(``0#@NP```````)H`````````(04```(`
+M`0"`O````````#T`````````*04```(``0#`O````````&@`````````-`4`
+M``(``0"0OP```````+$`````````/`4```(``0"`P0```````-0!````````
+M``````,`"`````````````````````````````,`"@``````````````````
+M````5`4``!(``0```````````&P&````````8`4``!$``P`@`````````$@`
+M````````;P4``!``````````````````````````?`4``!$``P"`````````
+M`$@`````````C`4``!(``0!0>````````",`````````E04``!``````````
+M````````````````HP4``!``````````````````````````K04``!``````
+M````````````````````MP4``!``````````````````````````P04``!``
+M````````````````````````T@4``!``````````````````````````X@4`
+M`!``````````````````````````[`4``!(``0!P!@```````/<`````````
+M]@4``!```````````````````````````P8``!``````````````````````
+M````%08``!(``0!P!P```````"L"````````)08``!``````````````````
+M````````+@8``!(``0"`>````````'<`````````/`8``!(``0"@"0``````
+M`%0`````````3P8``!(``0!@?`````````X`````````708``!(``0``"@``
+M`````$H!````````:@8``!(``0`P?````````"H`````````?`8``!(``0!@
+M=0```````&L`````````AP8``!(``0!0"P```````/<`````````F@8``!(`
+M`0``#@```````%L`````````JP8``!(``0``@`````````P`````````MP8`
+M`!(``0#@?0```````%4`````````QP8``!(``0!@#@```````#0!````````
+MV08``!(``0#0?P```````"\`````````Z08``!(``0"@#P```````$4`````
+M````_`8``!(``0#P#P```````&P`````````#@<``!(``0#0$````````)(!
+M````````)`<``!(``0!P$@```````(,`````````00<``!(``0``$P``````
+M`+H`````````50<``!(``0!`@````````'H`````````8P<``!(``0#`$P``
+M`````/(`````````>@<``!(``0#`%````````%$!````````D@<``!(``0`@
+M%@````````(!````````J`<``!``````````````````````````L@<``!(`
+M`0`0&0```````$,"````````Q`<``!(``0`0@````````"@`````````U0<`
+M`!(``0!@&P```````)8!````````Z`<``!(``0``'0```````(\!````````
+M^0<``!(``0"`'P```````%L`````````"0@``!(``0#@'P```````#0!````
+M````&@@``!(``0`@(0```````"P`````````+`@``!$``P````````````0`
+M````````/`@``!``````````````````````````2@@``!(``0`@80``````
+M`#\!````````70@``!``````````````````````````<`@``!``````````
+M````````````````=P@``!``````````````````````````?@@``!(``0!@
+M8@```````&8`````````B@@``!``````````````````````````K`@``!(`
+M`0`@?P```````*,`````````N@@``!(``0`@9````````'$`````````S`@`
+M`!(``0#`<@```````)D"````````W@@``!(``0#P=@```````%<!````````
+M\0@``!(``0#0=0```````!8!`````````PD``!``````````````````````
+M````%0D``!``````````````````````````*`D``!(``0"0>P```````$(`
+M````````-PD``!(``0#@>P```````$<`````````1@D``!(``0!P?```````
+M`&0!````````50D``!(``0!`?@```````'X`````````9@D``!(``0#`?@``
+M`````%L`````````<PD``!(``0#`@````````!4`````````?@D``!(``0#@
+M@````````"<`````````C@D``!(``0`0@0```````&8!````````F@D``!(`
+M`0``J@```````#T`````````L@D``!(``0!`J@```````$8`````````Q@D`
+M`!(``0#0M0```````&``````````X0D``!(``0`PM@```````.8`````````
+M!@H``!(``0"PJ0```````$,`````````'0H``!(``0"P@@```````&(`````
+M````-`H``!``````````````````````````2`H``!``````````````````
+M````````60H``!``````````````````````````;`H``!$``P#(````````
+M``0`````````?PH``!``````````````````````````D0H``!``````````
+M````````````````HPH``!(``0!`I@```````(P`````````P@H``!``````
+M````````````````````U`H``!``````````````````````````Y0H``!(`
+M`0"PNP```````"L`````````]`H``!(``0"@L@```````*\`````````"0L`
+M`!(``0#@H0```````(`#````````&PL``!(``0!@PP```````%(`````````
+M,0L``!(``0!@I0```````"$`````````1PL``!(``0"0I0````````L`````
+M````60L``!(``0"@I0````````L`````````;`L``!(``0"PI0```````&``
+M````````@PL``!(``0`0I@```````",`````````EPL``!(``0#0I@``````
+M``\"````````K@L``!(``0#@J````````,4`````````PPL``!(``0"0J@``
+M`````!T`````````V@L``!(``0"PJ@```````-T`````````]`L``!(``0"0
+MJP```````)X`````````#0P``!(``0`PK````````/\`````````)0P``!(`
+M`0`PK0```````$T!````````/`P``!(``0"`K@```````*(!````````3PP`
+M`!(``0`PL`````````,"````````;0P``!(``0!`L@```````"$`````````
+MB`P``!(``0!PL@```````"(`````````I0P``!(``0!0LP```````#<`````
+M````OPP``!(``0"0LP```````#<`````````V@P``!(``0#0LP```````*8`
+M````````]PP``!(``0"`M````````!\!````````%0T``!(``0"@M0``````
+M`#``````````-`T``!(``0`PO0```````#L!````````.PT``!(``0!PO@``
+M`````!(!````````0PT``!(``0!0P````````.X`````````40T``!(``0!`
+MP0```````#X`````````7@T``!(``0#`PP```````"8`````````:PT``!(`
+M`0#PPP```````$8!`````````')A:60N8P!3=')I<&5'971#;VUM86YD`%-T
+M<FEP95-P;&ET0V]M;6%N9`!)<U9$979/;FQI;F4`1&]#;VYT<F]L0VUD`$I"
+M3T1'971#;VUM86YD`$I"3T13<&QI=$-O;6UA;F0`7U]H<'1?86QL;V,`7U]H
+M<'1?9G)E90!G87)B86=E7V%D9'(`:6YI=%]H96%P7V)L;V-K`&-B7V%L;&]C
+M`&-B7V9R964`8V)?>F5R;P!C8E]I<U]Z97)O`&-F7VEN:70`<F5M;W9E7W)A
+M;F=E7VQO8VL`861D7W)A;F=E7VQO8VL`;&]C:U]R86YG90!?7V%L;&]C7W1A
+M<VL`9G)E95]S=')I<&4`86QL;V-?<W1R:7!E`%]?9V5T7W-T<FEP90!D871A
+M7WAF97(`<F5A9%]X9F5R7V1O;F4`<F%I9#5?9&]N90!S=')I<&5?9&]N90!H
+M86YD;&5?<W1R:7!E`')A:60U7V1I<G1Y`'1A<VM?9&]N90!S=')I<&5?8VAE
+M8VM?=&%S:P!R=U]T87-K7V)U:6QD<V=L`')W7V=E=%]R86YG90!R=U]T87-K
+M7V1O;F4`7U]D;U]R=U]T87-K`&1O7W)W7W1A<VL`9V5T7W-L:6-E<P!D;U]X
+M;W)?=&%S:P!X;W)?=&%S:U]D;VYE`&1O7WAO<C)?=&%S:P!D;U]X;W)N7W1A
+M<VL`8VAE8VM?9&5P96YD96YC>0!D:7)E8W1?<F5A9%]S9VP`9&ER96-T7W)E
+M861?8V]M<&QE=&EO;@!H86YD;&5?8VUD`&=E=%]S=')I<&5S`'=R:71E7WAF
+M97)?9&]N90!3>6YC1&ES:TEN9F\`9V5T161M85)E9T]F9G-E=`!U;FUA<VM%
+M9&UA26YT97)R=7!T<P!M87-K161M84EN=&5R<G5P=',`=W)I=&5%9&UA4F5Q
+M=65S=$5N=')Y`&1U;7!!=&%$979I8V5296=I<W1E<G,`:&%N9&QE161M849A
+M:6QE9$-O;6UA;F0`<F5M;W9E0V]M;6%N9`!H86YD;&5%9&UA4F5S<&]N<V4`
+M9&5A8W1I=F%T945D;6$`<V5N9$YO;F559&UA0V]M;6%N9`!C;VUP;&5T95!)
+M3T-O;6UA;F0`4V5T1U!)3T-T<FQ296<`:&%N9&QE161M84EN=&5R<G5P=`!?
+M8VAA;FYE;$AA<F1297-E=`!?9FEX4&AY4&%R86US`%]D;T%U=&]&;'5S:`!H
+M86YD;&5$979I8V5);G1E<G)U<'0`9&ES86)L95-A1&5V26YT97)R=71P<P!H
+M86YD;&5024]);G1E<G)U<'0`=')A;G-F97)024]$871A`&%C=&EV871E161M
+M80!%9&UA4F5Q475E=65);G-E<G0`<F5S971%9&UA0VAA;FYE;`!F;'5S:$1M
+M85%U975E`')E=F5R=%-A=&%(0U)E9W,`<F5V97)T1FQA<VA);G1E<F9A8V52
+M96=S`')E=F5R=%!#24EN=&5R9F%C95)E9W,`8V]M;6%N9'-1=65U94%D9%1A
+M:6P`8V]M;6%N9'-1=65U95)E;6]V90!A9&1#;VUM86YD`%-A1&5V26YT97)R
+M=71P0FET`&5N86)L95-A1&5V26YT97)R=71P<P!E>&5C=71E3F]N541-04-O
+M;6UA;F0`7V1O4V]F=%)E<V5T`%]A9&1R36%P,0!?861D<DUA<#(`861D<DUA
+M<`!D:7-A8FQE7V)E97!E<@!%;G1E<C8P,0!%>&ET-C`Q`&=E=%\V,#%?:60`
+M<V5T7V-T;`!?7V-H96-K7W!R;W1E8W1?8VER8W5I=`!F0VAE8VM!<G)A>0!P
+M9FY396YD0V]M;6%N9`!F1&5296%D5W)I=&4`<&9N1&5V:6-E1F%I;&5D`$-H
+M96-K4W5M`&9$95-E;&5C=$UO9&4`;W-?;65M<V5T`&9$95-E=%1#40!F1&53
+M971.0U$`9D1E4V5T5W)I=&5#86-H90!F1&53971296%D06AE860`;W-?;65M
+M8W!Y`&9!9&13<&%R90!'9713<&%R941I<VL`:6]C=&Q?4F5P;W)T179E;G0`
+M1FEX=7!!<G)A>5-T871E`$=E=%-T86UP`%-Y;F-!<G)A>4EN9F\`0VAE8VM!
+M<G)A>4-R:71I8V%L`&9/<T1I<VM&86EL960`9D1E;&5T94%R<F%Y`%5N<F5G
+M:7-T97)61&5V:6-E`')A:60U7V9R964`4W1R:7!E0G5I;&139U1A8FQE`&92
+M04E$,$UE;6)E<D1O;F4`1G)E94-O;6UA;F0`0V%L;$%F=&5R4F5T=7)N`&92
+M04E$,%-E;F1#;VUM86YD`$%L;&]C871E0V]M;6%N9`!F4D%)1#!-96UB97)&
+M86EL960`4D%)1#%"=6EL9%-G5&%B;&4`4D%)1#%-96UB97)#;VUP;&5T:6]N
+M`%)!240Q26YI=%)E8G5I;&1"=6EL9%-G5&%B;&4`4D%)1#%);FET0V]M<&QE
+M=&EO;@!$;U=A:71I;F=,:7-T`%)!240Q4F5B=6EL9$-O;7!L971I;VX`4D%)
+M1#%697)I9GE"=6EL9%-G5&%B;&4`4D%)1#%697)I9GE#;VUP;&5T:6]N`&]S
+M7VUE;6-M<`!F4D%)1#%396YD0V]M;6%N9`!!9&14;U=A:71I;F=,:7-T`&92
+M04E$,4UE;6)E<D9A:6QE9`!*0D]$0G5I;&139U1A8FQE`&9*0D]$365M8F5R
+M1&]N90!F2D)/1%-E;F1#;VUM86YD`&9*0D]$365M8F5R1F%I;&5D`&YU;5]R
+M86ED-5]P86=E<P!O<U]A;&QO8U]P86=E`&9L=7-H7W-T<FEP95]C86-H90!F
+M3W-0:'ES:6-A;$%D9')E<W,`1&]8;W(R`$1O6&]R,0!F;'5S:%]R86ED-0!F
+M0V]M<&QE=&5!;&Q#;VUM86YD<U-Y;F-H<F]N;W5S;'D`0VAE8VM)9&QE0V%L
+M;`!F;'5S:%]R86ED-5]A<WEN8P!F4D%)1#5396YD0V]M;6%N9`!F4D%)1#5-
+M96UB97)&86EL960`:6YI=%]R86ED-5]M96UO<GD`;W-?86QL;V-?9&UA7W!A
+M9V4`9D1E=FEC95-E;F1#;VUM86YD`&9'971&:7)S=$-H:6QD`&9297-E=$)O
+M;W1-87)K`&9#:&5C:T)O;W1A8FQE`$-H96-K4&5N9&EN9T-A;&P`0V%L;%=H
+M96Y)9&QE`&9&;'5S:%9$978`9D9L=7-H5D1E=D%S>6YC`&UV4F5A9%=R:71E
+M`&UV4V%T841I<V%B;&5#:&%N;F5L1&UA`&UV4V%T849L=7-H1&UA475E=64`
+M;793=&]R86=E1&5V051!4V5T1F5A='5R97,`;793=&]R86=E1&5V051!17AE
+M8W5T94YO;E5$34%#;VUM86YD`&UV4V%T845N86)L94-H86YN96Q$;6$`=V%I
+M=$9O<D)U<WE!9G1E<DA297-E=`!M=DUI8W)O4V5C;VYD<T1E;&%Y`$U67U)%
+M1U]214%$7T)95$4`359?4D5'7U=2251%7T173U)$`&UV075T;T9L=7-H3VY%
+M<G)O<@!-5E]214=?5U))5$5?0EE410!-5E]214=?4D5!1%]$5T]21`!M=E-A
+M=&%)<U-T;W)A9V5$979I8V5#;VYN96-T960`359?4D5'7U=2251%7U=/4D0`
+M359?4D5'7U)%041?5T]21`!?9&]-=E-O9G1297-E=`!M=E-T;W)A9V5$9797
+M86ET4W1A=`!M=E-A=&%);FET061A<'1E<@!C:&5C:U]P<F]T96-T7V-I<F-U
+M:70`;793871A4VAU=&1O=VY!9&%P=&5R`&UV16YA8FQE075T;T9L=7-H`&UV
+M1&ES86)L94%U=&]&;'5S:`!M=E-A=&%#;VYF:6=U<F5#:&%N;F5L`&UV4V%T
+M85)E;6]V94-H86YN96P`;793871A0VAA;FYE;$AA<F1297-E=`!M=E-A=&%#
+M;VYF:6=%9&UA36]D90!M=E-A=&%.=6U/9D1M84-O;6UA;F1S`&UV4V%T85-E
+M=$-H86YN96Q0:'E087)A;7,`;793871A0VAA;FYE;%!H>5-H=71D;W=N`&UV
+M4V%T84-H86YN96Q0:'E0;W=E<D]N`&UV4V%T84=E=$-H86YN96Q3=&%T=7,`
+M;793871A475E=65#;VUM86YD`&UV4V%T84EN=&5R<G5P=%-E<G9I8V52;W5T
+M:6YE`&UV4V%T84UA<VM!9&%P=&5R26YT97)R=7!T`&UV4V%T855N;6%S:T%D
+M87!T97));G1E<G)U<'0`96YA8FQE4W1O<F%G941E=DEN=&5R<G5P=`!D:7-A
+M8FQE4W1O<F%G941E=DEN=&5R<G5P=`!M=E-T;W)A9V5$979!5$%)9&QE26UM
+M961I871E`&UV4W1O<F%G941E=D%404ED96YT:69Y1&5V:6-E`&UV4W1O<F%G
+M941E=D%405-O9G1297-E=$1E=FEC90!"965P3VX`0F5E<$]F9@!S971?9F%I
+M;%]L961S`'-E=%]F86EL7VQE9`!S>#4P.'A?:6]C=&P`<W@U,#AX7V9L87-H
+M7V%C8V5S<P``A``````````+````8P``````````````K``````````"````
+M9````/S_________R0`````````+````90``````````````XP`````````"
+M````9@```/S_________#`$````````"````9P```/S_________&0$`````
+M```"````9@```/S_________-`$````````"````:````/S_________I`$`
+M```````"````:0```/S_________P0$````````"````:@```/S_________
+MV0$````````"````:P```/S_________[P$````````"````;````/S_____
+M____(P(````````"````90```/S_________40(````````+````8P``````
+M````````ZP(````````"````:````/S_________C0,````````+````8P``
+M````````````IP,````````"````;0```/S_________O0,````````"````
+M;0```/S_________U@,````````"````;0```/S_________[`,````````"
+M````;0```/S_________;P0````````"````:````/S_________%@4`````
+M```+````8P``````````````)@4````````+````90``````````````6@4`
+M```````"````;0```/S_________<`4````````"````;0```/S_________
+MB04````````"````;0```/S_________GP4````````"````;0```/S_____
+M____X@4````````+````90``````````````+`8````````+````90``````
+M````````O08````````"````;P```/S_________\`8````````"````8P``
+M`!0```````````<````````+````90``````````````50<````````"````
+M<````/S_________#@@````````"````<0```/S_________D0@````````"
+M````;@```/S_________00D````````"````;@```/S_________<PD`````
+M```"````<@```/S_________?@D````````"````<P```/S_________U@D`
+M```````"````<0```/S_________Y`D````````+````=0``````````````
+M(0H````````"````=P```/S_________,@H````````"````>````/S_____
+M____;0H````````"````=@```/S_________GPH````````+````=0``````
+M````````PPH````````"````:````/S_________V0H````````"````9```
+M`/S_________]@H````````"````<P```/S_________&PL````````"````
+M:````/S_________,`X````````"````>P```/S_________4`X````````"
+M````?````/S_________G@X````````"````?````/S_________Q0X`````
+M```"````?````/S_________\@X````````"````?@```/S_________1@\`
+M```````+````>@``````````````3@\````````+````>0``````````````
+M8!$````````"````:````/S_________L1$````````"````:````/S_____
+M____[A$````````"````>P```/S_________'A(````````"````?````/S_
+M________0A,````````"````>P```/S_________@A,````````"````?```
+M`/S_________FQ,````````+````A```````````````HQ,````````"````
+M?````/S_________%Q0````````"````:````/S_________:Q0````````"
+M````>P```/S_________>A0````````"````?````/S_________DQ0`````
+M```+````A```````````````FQ0````````"````?````/S_________>A8`
+M```````"````:````/S_________H18````````"````B````/S_________
+MVQ8````````"````>P```/S_________ZA8````````"````?````/S_____
+M____`Q<````````+````A```````````````"Q<````````"````?````/S_
+M________MQ<````````"````:````/S_________RQ<````````"````?@``
+M`/S_________\A<````````+````@P``````````````^A<````````+````
+M@@``````````````,1@````````"````?@```/S_________6!@````````+
+M````A0``````````````8!@````````+````@@``````````````AQ@`````
+M```"````?@```/S_________KA@````````+````AP``````````````MA@`
+M```````+````A@``````````````WQ@````````"````?````/S_________
+MZA@````````+````A```````````````\A@````````"````?````/S_____
+M____31D````````"````?````/S_________8!D````````+`````@```#`7
+M````````M1D````````+````B0``````````````P1D````````"````B@``
+M`/S_________SAH````````"````?@```/S_________X1H````````"````
+M;0```/S__________1H````````+````@0``````````````!1L````````+
+M````@```````````````(AP````````"````;P```/S_________/!P`````
+M```"````8P```!0`````````1QP````````"````90```"P`````````D1P`
+M```````"````<````/S_________V1P````````"````<@```/S_________
+MZQP````````"````<P```/S_________5AX````````"````;0```/S_____
+M____L!\````````"````>P```/S_________T!\````````"````?````/S_
+M________'B`````````"````?````/S_________12`````````"````?```
+M`/S_________<B`````````"````?@```/S_________QB`````````+````
+MC0``````````````SB`````````+````C```````````````5B(````````"
+M````D0```/S_________%20````````"````:````/S_________?R0`````
+M```"````:````/S_________P2H````````"````;0```/S_________TRH`
+M```````"````;0```/S_________,R\````````+`````@```&`K````````
+M+C`````````+`````@```*!D````````,S`````````"````?````/S_____
+M____;3`````````+````A```````````````=3`````````"````?````/S_
+M________CS`````````+````A```````````````ES`````````"````?```
+M`/S_________US`````````"````?````/S__________#`````````"````
+MD@```/S_________1#$````````+`````@```,`[````````23$````````"
+M````?````/S_________SS$````````"````DP```/S_________9#,`````
+M```"````>P```/S_________@S0````````"````?@```/S_________PC0`
+M```````+`````@```&`Q````````SC0````````+`````@```$`S````````
+MCS<````````"````E````/S_________L3<````````"````E0```/S_____
+M____,3@````````"````E````/S_________-SD````````"````E````/S_
+M________B3H````````"````E````/S_________J#H````````"````E0``
+M`/S_________O3P````````+````+@``````````````;ST````````+````
+M+@```#@`````````]&$````````"````?````/S_________E&(````````"
+M````D@```/S_________G&(````````"````EP```/S_________I&(`````
+M```"````F````/S_________=&0````````"````D@```/S_________]V0`
+M```````"````?````/S_________#&4````````+````A```````````````
+M%&4````````"````?````/S_________1&4````````+````A```````````
+M````3&4````````"````?````/S_________<F4````````"````D@```/S_
+M________A68````````"````!````/S_________CF8````````"````!```
+M`/S_________DV8````````"````DP```/S_________=F@````````"````
+M>P```/S_________-6L````````"````:````/S_________?FT````````+
+M````A```````````````AFT````````"````?````/S_________OVT`````
+M```"````?@```/S_________[FT````````+`````@```(!E````````]FT`
+M```````+`````@```%!H````````HG(````````+`````@```*!D````````
+MIW(````````"````?````/S_________XW(````````"````?````/S_____
+M____%W,````````"````:````/S_________/W,````````"````?````/S_
+M________87,````````"````?````/S_________&'0````````"````?```
+M`/S_________5G0````````+````F@``````````````8G0````````"````
+MB@```/S_________LW0````````+````FP``````````````[G0````````+
+M````F@``````````````_G0````````"````B@```/S_________!G4`````
+M```"````D@```/S_________&74````````+`````@```)!R````````.74`
+M```````"````?````/S_________=W4````````"````E@```/S_________
+M(G8````````"````D````/S_________9'8````````"````D````/S_____
+M____E78````````"````G0```/S_________G'8````````"````!````/S_
+M________I'8````````"````D````/S_________M'8````````"````G0``
+M`/S_________VW8````````"````D````/S_________LG<````````"````
+M;P```/S_________TW<````````"````8P```!0`````````WG<````````"
+M````90```#P`````````&G@````````"````<````/S_________,7@`````
+M```"````<@```/S_________/'@````````"````<P```/S_________TG@`
+M```````"````<P```/S_________2'D````````"````:````/S_________
+M?'H````````"````;0```/S_________D7H````````"````;0```/S_____
+M____J7H````````"````;0```/S_________OGH````````"````;0```/S_
+M________0'L````````"````9@```/S_________4GL````````"````9@``
+M`/S_________=WL````````"````9````/S_________RGL````````"````
+MGP```/S_________#'P````````"````H````/S_________:'P````````"
+M````=P```/S_________M'P````````"````:````/S_________%GT`````
+M```"````9````/S_________8'T````````"````9````/S_________H'\`
+M```````"````EP```/S_________]G\````````"````:````/S_________
+MRH`````````"````E@```/S_________\8`````````"````F0```/S_____
+M____38$````````"````IP```/S_________7($````````"````J````/S_
+M________@X$````````"````J0```/S_________/8(````````"````J@``
+M`/S_________2X(````````"````JP```/S_________OX(````````"````
+MK0```/S_________WX(````````"````K@```/S_________]H(````````"
+M````K0```/S_________2H,````````"````KP```/S_________7(,`````
+M```"````KP```/S_________BH,````````"````KP```/S_________H88`
+M```````"````L0```/S_________L(8````````"````K@```/S_________
+MR(8````````"````K@```/S_________X88````````"````K@```/S_____
+M____^X8````````"````K@```/S_________%8<````````"````K@```/S_
+M________-8<````````"````L0```/S_________08<````````"````K@``
+M`/S_________4H<````````"````K@```/S_________9(<````````"````
+MK@```/S_________=H<````````"````K@```/S_________CH<````````"
+M````L0```/S_________G8<````````"````K@```/S_________KX<`````
+M```"````K@```/S_________((@````````"````L@```/S_________FHH`
+M```````"````L@```/S_________L(H````````"````KP```/S_________
+MOHH````````"````L@```/S_________S(H````````"````L@```/S_____
+M____Y8H````````"````KP```/S_________\XH````````"````L@```/S_
+M________!(L````````"````KP```/S_________LHL````````"````KP``
+M`/S_________*XP````````"````L@```/S_________08P````````"````
+MKP```/S_________[HP````````"````KP```/S_________^XP````````"
+M````L@```/S_________!8T````````"````K0```/S_________%XT`````
+M```"````KP```/S_________)(T````````"````L@```/S_________+HT`
+M```````"````K0```/S_________1HT````````"````LP```/S_________
+M]HT````````"````L````/O__________XX````````"````K@```/S_____
+M____#8\````````"````K@```/S_________,H\````````"````KP```/S_
+M________U)`````````"````M````/S_________!9$````````"````M0``
+M`/S_________P9$````````"````L````/O_________-I(````````"````
+ML@```/S_________0)(````````"````K0```/S_________PY(````````"
+M````L@```/S_________UI(````````"````KP```/S_________X)(`````
+M```"````L@```/S_________ZI(````````"````K0```/S_________"9,`
+M```````"````KP```/S_________L),````````"````KP```/S_________
+MP9,````````"````KP```/S_________T),````````"````KP```/S_____
+M____Y9,````````"````KP```/S_________!I0````````"````KP```/S_
+M________%90````````"````KP```/S_________-I0````````"````KP``
+M`/S_________1Y0````````"````KP```/S_________J)4````````"````
+ML@```/S_________VI4````````"````KP```/S_________`I8````````"
+M````L@```/S_________798````````"````KP```/S_________O98`````
+M```"````KP```/S_________R98````````"````L@```/S_________TY8`
+M```````"````K0```/S_________Y)8````````"````KP```/S_________
+M\)8````````"````L@```/S_________=)<````````"````KP```/S_____
+M____?Y<````````"````L@```/S_________FI<````````"````KP```/S_
+M________JY<````````"````KP```/S_________OI<````````"````KP``
+M`/S_________T9<````````"````KP```/S_________Y)<````````"````
+MKP```/S_________]Y<````````"````KP```/S_________"I@````````"
+M````KP```/S_________'9@````````"````KP```/S_________,)@`````
+M```"````KP```/S_________0Y@````````"````KP```/S_________5I@`
+M```````"````KP```/S_________:9@````````"````KP```/S_________
+M?)@````````"````KP```/S_________JY@````````"````KP```/S_____
+M____O)@````````"````KP```/S_________S9@````````"````KP```/S_
+M________WI@````````"````KP```/S_________[)@````````"````L@``
+M`/S_________`YD````````"````KP```/S_________0YD````````"````
+MKP```/S_________:ID````````"````L@```/S_________?9D````````"
+M````KP```/S_________BYD````````"````L@```/S_________H)D`````
+M```"````KP```/S_________LYD````````"````KP```/S_________QID`
+M```````"````KP```/S_________V9D````````"````KP```/S_________
+M[)D````````"````KP```/S__________YD````````"````KP```/S_____
+M____$IH````````"````KP```/S_________)9H````````"````KP```/S_
+M________.)H````````"````KP```/S_________2YH````````"````KP``
+M`/S_________7IH````````"````KP```/S_________<9H````````"````
+MKP```/S_________;IL````````"````;0```/S_________@IL````````"
+M````;0```/S_________A9P````````"````K@```/S_________M)P`````
+M```"````KP```/S_________PYP````````"````L@```/S_________WIP`
+M```````"````KP```/S_________[9P````````"````L@```/S_________
+M-)T````````"````L@```/S_________3)T````````"````KP```/S_____
+M____QIT````````"````KP```/S_________VYT````````"````KP```/S_
+M________])T````````"````K@```/S_________$)X````````"````KP``
+M`/S_________>IX````````"````KP```/S_________AYX````````"````
+ML@```/S_________E9X````````"````K0```/S_________/9\````````"
+M````KP```/S_________=)\````````"````M@```/S_________U)\`````
+M```"````K@```/S_________`Z`````````"````L0```/S_________%Z``
+M```````"````L0```/S_________*Z`````````"````L0```/S_________
+M/Z`````````"````L0```/S_________4Z`````````"````L0```/S_____
+M____K*`````````"````L0```/S_________P*`````````"````L0```/S_
+M________U*`````````"````L0```/S_________Z*`````````"````L0``
+M`/S__________*`````````"````L0```/S_________$*$````````"````
+ML0```/S_________)*$````````"````L0```/S_________/:$````````"
+M````K@```/S_________6J$````````"````MP```/S_________<:$`````
+M```"````K@```/S_________IZ$````````"````M````/S_________&*(`
+M```````"````KP```/S_________(:(````````"````N0```/S_________
+M*Z,````````"````L@```/S_________B:,````````"````KP```/S_____
+M____EZ,````````"````L@```/S_________KZ,````````"````KP```/S_
+M________QJ,````````"````L@```/S_________0:0````````"````KP``
+M`/S_________4J0````````"````KP```/S_________8Z0````````"````
+MKP```/S_________BJ0````````"````KP```/S_________K*0````````"
+M````KP```/S_________X:0````````"````K0```/S_________$Z4`````
+M```"````LP```/S_________<Z4````````"````KP```/S_________DJ4`
+M```````"````L````/C_________HJ4````````"````L````/C_________
+M<:8````````"````L@```/S_________EZ8````````"````L@```/S_____
+M____H:8````````"````K0```/S_________K*8````````"````L@```/S_
+M________LJ<````````"````L@```/S_________W*<````````"````KP``
+M`/S__________*<````````"````L@```/S_________!J@````````"````
+MK0```/S_________*Z@````````"````KP```/S_________2Z@````````"
+M````L@```/S_________5:@````````"````K0```/S_________8Z@`````
+M```"````K````/S_________EZ@````````"````K@```/S_________,JD`
+M```````"````L@```/S_________?:D````````"````KP```/S_________
+M(:L````````"````L@```/S_________3ZL````````"````KP```/S_____
+M____S:L````````"````L@```/S_________^:L````````"````KP```/S_
+M________$JP````````"````L@```/S_________;JP````````"````L@``
+M`/S_________G*P````````"````KP```/S_________M:P````````"````
+ML@```/S_________W:P````````"````L@```/S_________#ZT````````"
+M````KP```/S_________?ZT````````"````L@```/S_________IZT`````
+M```"````LP```/S_________^:T````````"````L@```/S_________"*X`
+M```````"````L@```/S_________%ZX````````"````L@```/S_________
+M)JX````````"````L@```/S_________-:X````````"````L@```/S_____
+M____1*X````````"````L@```/S_________4ZX````````"````L@```/S_
+M________8JX````````"````L@```/S_________9[`````````"````L@``
+M`/S_________J;`````````"````L@```/S_________S[`````````"````
+MKP```/S_________%;$````````"````KP```/S_________(;$````````"
+M````L@```/S_________-[$````````"````KP```/S_________4K$`````
+M```"````L@```/S_________4[(````````"````KP```/S_________A+(`
+M```````"````KP```/S_________\K(````````"````K@```/S_________
+M#+,````````"````K0```/S_________&+,````````"````LP```/S_____
+M____:[,````````"````L0```/S_________@;,````````"````K@```/S_
+M________J[,````````"````L0```/S_________P;,````````"````K@``
+M`/S_________#[0````````"````RP```/S_________(K0````````"````
+ML0```/S_________/[0````````"````MP```/S_________2[0````````"
+M````R@```/S_________6K0````````"````R@```/S_________`[4`````
+M```"````J@```/S_________0;4````````"````J0```/S_________Q[4`
+M```````"````M@```/S_________)[8````````"````J@```/S_________
+M\;<````````"````MP```/S_________!K@````````"````RP```/S_____
+M____(+@````````"````L0```/S_________-;@````````"````L0```/S_
+M________2[@````````"````L0```/S_________8;@````````"````L0``
+M`/S_________=[@````````"````L0```/S_________K;@````````"````
+MR@```/S_________RK@````````"````L0```/S_________W;@````````"
+M````L0```/S_________\;@````````"````L0```/S_________!;D`````
+M```"````L0```/S_________&;D````````"````L0```/S_________+;D`
+M```````"````L0```/S_________0;D````````"````L0```/S_________
+M9;D````````"````MP```/S_________<;D````````"````R@```/S_____
+M____@[D````````"````R@```/S_________JKD````````"````MP```/S_
+M________MKD````````"````R@```/S_________T+D````````"````K@``
+M`/S_________W+D````````"````R@```/S_________&KH````````"````
+MMP```/S_________,+H````````"````M0```/S_________4[H````````"
+M````M````/S_________>+H````````"````MP```/S_________A+H`````
+M```"````R@```/S_________D[H````````"````R@```/S_________HKH`
+M```````"````R@```/S_________%+L````````"````L0```/S_________
+M);L````````"````K@```/S_________+[L````````"````K0```/S_____
+M____-[L````````"````R@```/S_________0;L````````"````K0```/S_
+M________2[L````````"````K0```/S_________5;L````````"````K0``
+M`/S_________7[L````````"````K0```/S_________=[L````````"````
+MK@```/S_________D;L````````"````K0```/S_________R;L````````"
+M````K0```/S_________[+L````````"`````P```!P!````````_[L`````
+M```"````L0```/S_________"[P````````"`````P```!P!````````'+P`
+M```````"````K@```/S_________,[P````````"`````P```!P!````````
+M1+P````````"````K@```/S_________5[P````````"`````P```!P!````
+M````:+P````````"````K@```/S_________A[P````````"`````P```!P!
+M````````FKP````````"````L0```/S_________H;P````````"`````P``
+M`!P!````````M[P````````"````L0```/S_________V;P````````"````
+M`P```!P!````````[[P````````"````L0```/S_________]KP````````"
+M`````P```!P!````````!KT````````"````K@```/S_________1[T`````
+M```"````!`````,`````````6+T````````"````L@```/S_________;;T`
+M```````"````KP```/S_________>KT````````"````L@```/S_________
+MF;T````````"````M````/S_________IKT````````"````L@```/S_____
+M____M;T````````"`````P```!P!````````R[T````````"````L0```/S_
+M________TKT````````"`````P```!P!````````Y[T````````"````L0``
+M`/S_________[KT````````"`````P```!P!````````!+X````````"````
+ML0```/S_________"[X````````"`````P```!P!````````(+X````````"
+M````L0```/S_________-[X````````"````KP```/S_________1+X`````
+M```"````L@```/S_________5+X````````"````KP```/S_________?;X`
+M```````"````L@```/S_________DKX````````"````KP```/S_________
+MG[X````````"````L@```/S_________OKX````````"````M````/S_____
+M____R[X````````"````L@```/S_________VKX````````"`````P```!P!
+M````````\+X````````"````L0```/S_________][X````````"`````P``
+M`!P!````````#+\````````"````L0```/S_________$[\````````"````
+M`P```!P!````````*;\````````"````L0```/S_________,+\````````"
+M`````P```!P!````````1;\````````"````L0```/S_________7+\`````
+M```"````KP```/S_________:;\````````"````L@```/S_________>;\`
+M```````"````KP```/S_________G+\````````"`````P```!P!````````
+MLK\````````"````L0```/S_________N;\````````"`````P```!P!````
+M````SK\````````"````L0```/S_________X[\````````"````K@```/S_
+M________^[\````````"`````P```!P!````````$,`````````"````L0``
+M`/S_________(L`````````"````K0```/S_________+\`````````"````
+MK@```/S_________?\`````````"````L@```/S_________E,`````````"
+M````KP```/S_________H<`````````"````L@```/S_________P,``````
+M```"````M````/S_________S<`````````"````L@```/S_________X,``
+M```````"`````P```!P!````````\<`````````"````L0```/S_________
+M`,$````````"````KP```/S_________#<$````````"````L@```/S_____
+M____'<$````````"````KP```/S_________=<$````````"````T0```/S_
+M________G<$````````"````L@```/S_________LL$````````"````KP``
+M`/S_________O\$````````"````L@```/S_________X,$````````"````
+MM````/S_________[<$````````"````L@```/S_________^L$````````"
+M````M0```/S_________(\(````````"`````P```!P!````````.<(`````
+M```"````L0```/S_________4\(````````"````K0```/S_________8,(`
+M```````"````M0```/S_________:<(````````"`````P```!P!````````
+M?\(````````"````L0```/S_________I<(````````"`````P```!P!````
+M````N\(````````"````L0```/S_________R,(````````"````M0```/S_
+M________^L(````````"`````P```!P!````````$,,````````"````L0``
+M`/S_________(,,````````"````KP```/S_________+<,````````"````
+ML@```/S_________/<,````````"````KP```/S_________<\,````````"
+M`````P```!@!````````=\,````````+`````P```.``````````BL,`````
+M```"`````P```!@!````````CL,````````+`````P`````!````````TL,`
+M```````"````!`````0`````````*\0````````"````L@```/S_________
+M0<0````````"````KP```/S_________3L0````````"````L@```/S_____
+M____;\0````````"````M````/S_________?,0````````"````L@```/S_
+M________G,0````````"````K@```/S_________T<0````````"````L0``
+M`/S_________[,0````````"````KP```/S_________^<0````````"````
+ML@```/S_________"L4````````"````KP```/S_________(``````````!
+M````G@``````````````*``````````!````G@``````````````,```````
+M```!````G@``````````````.``````````!````G@``````````````0```
+M```````!````C@``````````````2``````````!````?0``````````````
+M4``````````!````B0``````````````8``````````!````F@``````````
+M````@``````````!````=0``````````````B``````````!````=0``````
+M````````D``````````!````=0``````````````F``````````!````=0``
+M````````````H``````````!````CP``````````````J``````````!````
+M?P``````````````L``````````!````BP``````````````P``````````!
+M````FP``````````````(`$````````!`````P`````!````````````````
+M```!`````@```.T\````````"``````````!`````@```,$\````````$```
+M```````!`````@```,$\````````&``````````!`````@```,@\````````
+M(``````````!`````@```-<\````````*``````````!`````@```.(\````
+M````,``````````!`````@```.D\````````.``````````!`````@```)T]
+M````````0``````````!`````@```',]````````2``````````!`````@``
+M`',]````````4``````````!`````@```'H]````````6``````````!````
+M`@```(<]````````8``````````!`````@```)(]````````:``````````!
+M`````@```)D]````````(``````````!`````@``````````````4```````
+M```!`````@```'`&````````>``````````!`````@```'`'````````H```
+M```````!`````@```*`)````````R``````````!`````@`````*````````
+M"`$````````!`````@```%`+````````0`$````````!`````@```%`,````
+M````6`$````````!`````@```.`,````````>`$````````!`````@`````.
+M````````H`$````````!`````@```&`.````````R`$````````!`````@``
+M`*`/````````Z`$````````!`````@```/`/````````"`(````````!````
+M`@```&`0````````,`(````````!`````@```-`0````````6`(````````!
+M`````@```'`2````````>`(````````!`````@`````3````````H`(`````
+M```!`````@```,`3````````R`(````````!`````@```,`4````````\`(`
+M```````!`````@```"`6````````&`,````````!`````@```#`7````````
+M0`,````````!`````@```!`9````````:`,````````!`````@```&`;````
+M````D`,````````!`````@`````=````````N`,````````!`````@```)`>
+M````````T`,````````!`````@```-`>````````Z`,````````!`````@``
+M`(`?````````$`0````````!`````@```.`?````````.`0````````!````
+M`@```"`A````````6`0````````!`````@```%`A````````<`0````````!
+M`````@```'`A````````B`0````````!`````@```)`A````````R`0`````
+M```!`````@```#`C````````\`0````````!`````@```*`C````````"`4`
+M```````!`````@```/`C````````,`4````````!`````@```#`D````````
+M2`4````````!`````@```'`D````````:`4````````!`````@```)`D````
+M````@`4````````!`````@```-`D````````F`4````````!`````@`````E
+M````````P`4````````!`````@```)`E````````V`4````````!`````@``
+M`,`E``````````8````````!`````@```"`F````````0`8````````!````
+M`@```%`H````````:`8````````!`````@```"`I````````J`8````````!
+M`````@```&`K````````T`8````````!`````@```&`L````````^`8`````
+M```!`````@```#`Q````````&`<````````!`````@```&`Q````````6`<`
+M```````!`````@```"`R````````<`<````````!`````@```$`S````````
+MF`<````````!`````@```!`T````````N`<````````!`````@```%`T````
+M````X`<````````!`````@`````U````````"`@````````!`````@```)`V
+M````````.`@````````!`````@```)`X````````:`@````````!`````@``
+M`)`Y````````J`@````````!`````@```.`Z````````T`@````````!````
+M`@```&`[````````Z`@````````!`````@```,`[````````*`D````````!
+M`````@`````^````````:`D````````!`````@```"!A````````J`D`````
+M```!`````@```&!B````````T`D````````!`````@```-!B````````\`D`
+M```````!`````@```"!D````````&`H````````!`````@```*!D````````
+M0`H````````!`````@```(!E````````@`H````````!`````@```%!H````
+M````H`H````````!`````@```.!H````````X`H````````!`````@```&!N
+M````````(`L````````!`````@```)!R````````0`L````````!`````@``
+M`,!R````````<`L````````!`````@```&!U````````F`L````````!````
+M`@```-!U````````P`L````````!`````@```/!V````````Z`L````````!
+M`````@```%!X``````````P````````!`````@```(!X````````*`P`````
+M```!`````@````!Y````````6`P````````!`````@```)![````````<`P`
+M```````!`````@```.![````````F`P````````!`````@```#!\````````
+ML`P````````!`````@```&!\````````R`P````````!`````@```'!\````
+M````^`P````````!`````@```.!]````````$`T````````!`````@```$!^
+M````````,`T````````!`````@```,!^````````2`T````````!`````@``
+M`"!_````````:`T````````!`````@```-!_````````B`T````````!````
+M`@````"`````````H`T````````!`````@```!"`````````N`T````````!
+M`````@```$"`````````X`T````````!`````@```,"```````````X`````
+M```!`````@```."`````````(`X````````!`````@```!"!````````2`X`
+M```````!`````@```(""````````8`X````````!`````@```+""````````
+MB`X````````!`````@```""#````````J`X````````!`````@```'"#````
+M````R`X````````!`````@```)"#````````X`X````````!`````@```%"&
+M````````"`\````````!`````@```."'````````,`\````````!`````@``
+M`-"(````````6`\````````!`````@```'"*````````@`\````````!````
+M`@```#"+````````J`\````````!`````@```#".````````R`\````````!
+M`````@```+".````````\`\````````!`````@```'"0````````&!``````
+M```!`````@```#"1````````0!`````````!`````@```*"2````````<!``
+M```````!`````@```&"4````````L!`````````!`````@```$"5````````
+MV!`````````!`````@```("6`````````!$````````!`````@```""7````
+M````0!$````````!`````@```#"9````````8!$````````!`````@```%"9
+M````````@!$````````!`````@```(":````````F!$````````!`````@``
+M`-":````````L!$````````!`````@```$";````````V!$````````!````
+M`@```,";````````^!$````````!`````@```""<````````$!(````````!
+M`````@```%"<````````.!(````````!`````@````"=````````6!(`````
+M```!`````@```&"=````````@!(````````!`````@```$">````````N!(`
+M```````!`````@```.">````````X!(````````!`````@```%"?````````
+M`!,````````!`````@```*"?````````*!,````````!`````@```."A````
+M````4!,````````!`````@```&"E````````<!,````````!`````@```)"E
+M````````B!,````````!`````@```*"E````````H!,````````!`````@``
+M`+"E````````P!,````````!`````@```!"F````````V!,````````!````
+M`@```$"F`````````!0````````!`````@```-"F````````0!0````````!
+M`````@```."H````````:!0````````!`````@```+"I````````B!0`````
+M```!`````@````"J````````J!0````````!`````@```$"J````````R!0`
+M```````!`````@```)"J````````X!0````````!`````@```+"J````````
+M"!4````````!`````@```)"K````````,!4````````!`````@```#"L````
+M````8!4````````!`````@```#"M````````H!4````````!`````@```("N
+M````````R!4````````!`````@```#"P````````\!4````````!`````@``
+M`$"R````````$!8````````!`````@```'"R````````,!8````````!````
+M`@```*"R````````6!8````````!`````@```%"S````````>!8````````!
+M`````@```)"S````````F!8````````!`````@```-"S````````P!8`````
+M```!`````@```("T````````\!8````````!`````@```*"U````````$!<`
+M```````!`````@```-"U````````,!<````````!`````@```#"V````````
+M6!<````````!`````@```""W````````B!<````````!`````@```/"Z````
+M````L!<````````!`````@```+"[````````T!<````````!`````@```."[
+M````````^!<````````!`````@```("\````````&!@````````!`````@``
+M`,"\````````.!@````````!`````@```#"]````````8!@````````!````
+M`@```'"^````````B!@````````!`````@```)"_````````J!@````````!
+M`````@```%#`````````T!@````````!`````@```$#!````````\!@`````
+M```!`````@```(#!````````,!D````````!`````@```&##````````6!D`
+M```````!`````@```,##````````<!D````````!`````@```/##````````
`
end
diff --git a/sys/dev/hptmv/array.h b/sys/dev/hptmv/array.h
index 14d627a..7b50774 100644
--- a/sys/dev/hptmv/array.h
+++ b/sys/dev/hptmv/array.h
@@ -62,7 +62,7 @@ typedef struct _RaidArray
UCHAR reserve1;
ULONG dArStamp; /* array ID. all disks in a array has same ID */
- ULONG failedStamp; /* stamp for failed member */
+ ULONG failedStamps[4]; /* stamp for failed members */
USHORT bStripeWitch; /* = (1 << BlockSizeShift) */
USHORT rf_broken: 1;
@@ -84,7 +84,7 @@ typedef struct _RaidArray
USHORT CriticalMembers; /* tell which member is critial */
UCHAR last_read; /* for RAID 1 load banlancing */
- UCHAR PrivateFlag1;
+ UCHAR alreadyBroken;
LBA_T RebuildSectors; /* how many sectors is OK (LBA on member disk) */
@@ -152,8 +152,8 @@ typedef struct _ArrayDescript
#define ArrayDescript_3_1_size 512
UCHAR bCheckSum31; /* new check sum */
- UCHAR PrivateFlag1; /* private */
- UCHAR reserve1;
+ UCHAR PrivateFlag1; /* private */
+ UCHAR alreadyBroken; /* last stamp has been saved to failedStamps */
#ifdef __BIG_ENDIAN_BITFIELD
UCHAR df_read_ahead: 1; /* enable read ahead */
@@ -181,7 +181,7 @@ typedef struct _ArrayDescript
}
levelex[2];
- ULONG failedStamp; /* array stamp for failed memebr */
+ ULONG failedStamps[4]; /* failed memebrs's stamps */
} ArrayDescript;
diff --git a/sys/dev/hptmv/command.h b/sys/dev/hptmv/command.h
index 12eb694..3b6a53b 100644
--- a/sys/dev/hptmv/command.h
+++ b/sys/dev/hptmv/command.h
@@ -42,9 +42,9 @@ typedef struct _AtaCommand
typedef struct _PassthroughCmd {
BYTE bFeaturesReg; /* feature register */
BYTE bSectorCountReg; /* IDE sector count register. */
- BYTE bSectorNumberReg; /* IDE sector number register. */
- BYTE bCylLowReg; /* IDE low order cylinder value. */
- BYTE bCylHighReg; /* IDE high order cylinder value. */
+ BYTE bLbaLowReg; /* IDE sector number register. */
+ BYTE bLbaMidReg; /* IDE low order cylinder value. */
+ BYTE bLbaHighReg; /* IDE high order cylinder value. */
BYTE bDriveHeadReg; /* IDE drive/head register. */
BYTE bCommandReg; /* Actual IDE command. Checked for validity by driver. */
BYTE nSectors; /* data transfer */
@@ -247,7 +247,7 @@ DPC_ROUTINE;
* IdleRoutines[] size:
* Each command may invoke CallWhenIdle once.
*/
-#define MAX_COMMAND_BLOCKS_FOR_EACH_VBUS (MAX_QUEUE_COMM * (1+MAX_MEMBERS*2))
+#define MAX_COMMAND_BLOCKS_FOR_EACH_VBUS (MAX_QUEUE_COMM * (1+MAX_MEMBERS*2) + 1)
#define MAX_PENDING_ROUTINES (MAX_COMMAND_BLOCKS_FOR_EACH_VBUS+1)
#define MAX_IDLE_ROUTINES (MAX_COMMAND_BLOCKS_FOR_EACH_VBUS+1)
diff --git a/sys/dev/hptmv/entry.c b/sys/dev/hptmv/entry.c
index 33c3066..843281a 100644
--- a/sys/dev/hptmv/entry.c
+++ b/sys/dev/hptmv/entry.c
@@ -93,7 +93,7 @@ static device_method_t driver_methods[] = {
DEVMETHOD(device_attach, hpt_attach),
DEVMETHOD(device_detach, hpt_detach),
-/* DEVMETHOD(device_shutdown, hpt_shutdown), */
+ DEVMETHOD(device_shutdown, hpt_shutdown),
{ 0, 0 }
};
@@ -158,7 +158,7 @@ static ST_HPT_DPC DpcQueue[MAX_DPC];
static int DpcQueue_First=0;
static int DpcQueue_Last = 0;
-char DRIVER_VERSION[] = "v1.12";
+char DRIVER_VERSION[] = "v1.16";
#if (__FreeBSD_version >= 500000)
static struct mtx driver_lock;
@@ -204,7 +204,7 @@ void unlock_driver(intrmask_t spl)
*
* Description: free allocated queues for the given channel
*
- * Parameters: pMvSataAdapter - pointer to the RR182x controler this
+ * Parameters: pMvSataAdapter - pointer to the RR18xx controler this
* channel connected to.
* channelNum - channel number.
*
@@ -238,7 +238,6 @@ static void failDevice(PVDevice pVDev)
}
int MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel);
-/*void fDeviceSendCommand(_VBUS_ARG PCommand pCmd); */
static void
handleEdmaError(_VBUS_ARG PCommand pCmd)
@@ -292,7 +291,7 @@ hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
if (channelNum >= MV_SATA_CHANNELS_NUM)
{
- MV_ERROR("RR182x[%d]: Bad channelNum=%d",
+ MV_ERROR("RR18xx[%d]: Bad channelNum=%d",
pAdapter->mvSataAdapter.adapterId, channelNum);
return -1;
}
@@ -313,14 +312,14 @@ hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
/* check the 1K alignment of the request queue*/
if (req_dma_addr & 0x3ff)
{
- MV_ERROR("RR182x[%d]: request queue allocated isn't 1 K aligned,"
+ MV_ERROR("RR18xx[%d]: request queue allocated isn't 1 K aligned,"
" dma_addr=%llx channel=%d\n", pAdapter->mvSataAdapter.adapterId,
(HPT_U64)(ULONG_PTR)req_dma_addr, channelNum);
return -1;
}
pMvSataChannel->requestQueuePciLowAddress = req_dma_addr;
pMvSataChannel->requestQueuePciHiAddress = 0;
- KdPrint(("RR182x[%d,%d]: request queue allocated: 0x%p",
+ KdPrint(("RR18xx[%d,%d]: request queue allocated: 0x%p",
pAdapter->mvSataAdapter.adapterId, channelNum,
pMvSataChannel->requestQueue));
pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *)
@@ -330,14 +329,14 @@ hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
/* check the 256 alignment of the response queue*/
if (rsp_dma_addr & 0xff)
{
- MV_ERROR("RR182x[%d,%d]: response queue allocated isn't 256 byte "
+ MV_ERROR("RR18xx[%d,%d]: response queue allocated isn't 256 byte "
"aligned, dma_addr=%llx\n",
pAdapter->mvSataAdapter.adapterId, channelNum, (HPT_U64)(ULONG_PTR)rsp_dma_addr);
return -1;
}
pMvSataChannel->responseQueuePciLowAddress = rsp_dma_addr;
pMvSataChannel->responseQueuePciHiAddress = 0;
- KdPrint(("RR182x[%d,%d]: response queue allocated: 0x%p",
+ KdPrint(("RR18xx[%d,%d]: response queue allocated: 0x%p",
pAdapter->mvSataAdapter.adapterId, channelNum,
pMvSataChannel->responseQueue));
@@ -349,7 +348,7 @@ hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
* Name: hptmv_parse_identify_results
*
* Description: this functions parses the identify command results, checks
- * that the connected deives can be accesed by RR182x EDMA,
+ * that the connected deives can be accesed by RR18xx EDMA,
* and updates the channel stucture accordingly.
*
* Parameters: pMvSataChannel, pointer to the channel data structure.
@@ -507,14 +506,14 @@ start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
MV_CHANNEL *pChannelInfo = &(pAdapter->mvChannel[channelNum]);
MV_U32 udmaMode,pioMode;
- KdPrint(("RR182x [%d]: start channel (%d)", pMvSataAdapter->adapterId,
+ KdPrint(("RR18xx [%d]: start channel (%d)", pMvSataAdapter->adapterId,
channelNum));
/* Software reset channel */
if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE)
{
- MV_ERROR("RR182x [%d,%d]: failed to perform Software reset\n",
+ MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n",
pMvSataAdapter->adapterId, channelNum);
return -1;
}
@@ -527,7 +526,7 @@ start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
StallExec(5000000); /* wait 5 sec before trying again */
if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE)
{
- MV_ERROR("RR182x [%d,%d]: failed to perform Hard reset\n",
+ MV_ERROR("RR18xx [%d,%d]: failed to perform Hard reset\n",
pMvSataAdapter->adapterId, channelNum);
return -1;
}
@@ -536,13 +535,13 @@ start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
/* identify device*/
if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == MV_FALSE)
{
- MV_ERROR("RR182x [%d,%d]: failed to perform ATA Identify command\n"
+ MV_ERROR("RR18xx [%d,%d]: failed to perform ATA Identify command\n"
, pMvSataAdapter->adapterId, channelNum);
return -1;
}
if (hptmv_parse_identify_results(pMvSataChannel))
{
- MV_ERROR("RR182x [%d,%d]: Error in parsing ATA Identify message\n"
+ MV_ERROR("RR18xx [%d,%d]: Error in parsing ATA Identify message\n"
, pMvSataAdapter->adapterId, channelNum);
return -1;
}
@@ -551,13 +550,13 @@ start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
/* Disable 8 bit PIO in case CFA enabled */
if (pMvSataChannel->identifyDevice[86] & 4)
{
- KdPrint(("RR182x [%d]: Disable 8 bit PIO (CFA enabled) \n",
+ KdPrint(("RR18xx [%d]: Disable 8 bit PIO (CFA enabled) \n",
pMvSataAdapter->adapterId));
if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0,
0, 0, 0) == MV_FALSE)
{
- MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures"
+ MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures"
" failed\n", pMvSataAdapter->adapterId, channelNum);
return -1;
}
@@ -572,48 +571,48 @@ start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0,
0, 0, 0) == MV_FALSE)
{
- MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
+ MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
pMvSataAdapter->adapterId, channelNum);
return -1;
}
}
- KdPrint(("RR182x [%d]: channel %d, write cache enabled\n",
+ KdPrint(("RR18xx [%d]: channel %d, write cache enabled\n",
pMvSataAdapter->adapterId, channelNum));
}
else
{
- KdPrint(("RR182x [%d]: channel %d, write cache not supported\n",
+ KdPrint(("RR18xx [%d]: channel %d, write cache not supported\n",
pMvSataAdapter->adapterId, channelNum));
}
#else /* disable write cache */
{
if (pMvSataChannel->identifyDevice[85] & 0x20)
{
- KdPrint(("RR182x [%d]: channel =%d, disable write cache\n",
+ KdPrint(("RR18xx [%d]: channel =%d, disable write cache\n",
pMvSataAdapter->adapterId, channelNum));
if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0,
0, 0, 0) == MV_FALSE)
{
- MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
+ MV_ERROR("RR18xx [%d]: channel %d: mvStorageDevATASetFeatures failed\n",
pMvSataAdapter->adapterId, channelNum);
return -1;
}
}
- KdPrint(("RR182x [%d]: channel=%d, write cache disabled\n",
+ KdPrint(("RR18xx [%d]: channel=%d, write cache disabled\n",
pMvSataAdapter->adapterId, channelNum));
}
#endif
/* Set transfer mode */
- KdPrint(("RR182x [%d] Set transfer mode XFER_PIO_SLOW\n",
+ KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_SLOW\n",
pMvSataAdapter->adapterId));
if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
MV_ATA_SET_FEATURES_TRANSFER,
MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) ==
MV_FALSE)
{
- MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
+ MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
pMvSataAdapter->adapterId, channelNum);
return -1;
}
@@ -632,14 +631,14 @@ start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
pioMode = MV_ATA_TRANSFER_PIO_SLOW;
}
- KdPrint(("RR182x [%d] Set transfer mode XFER_PIO_4\n",
+ KdPrint(("RR18xx [%d] Set transfer mode XFER_PIO_4\n",
pMvSataAdapter->adapterId));
pAdapter->mvChannel[channelNum].maxPioModeSupported = pioMode;
if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
MV_ATA_SET_FEATURES_TRANSFER,
pioMode, 0, 0, 0) == MV_FALSE)
{
- MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
+ MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
pMvSataAdapter->adapterId, channelNum);
return -1;
}
@@ -666,7 +665,7 @@ start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
udmaMode = MV_ATA_TRANSFER_UDMA_2;
}
- KdPrint(("RR182x [%d] Set transfer mode XFER_UDMA_%d\n",
+ KdPrint(("RR18xx [%d] Set transfer mode XFER_UDMA_%d\n",
pMvSataAdapter->adapterId, udmaMode & 0xf));
pChannelInfo->maxUltraDmaModeSupported = udmaMode;
@@ -674,7 +673,7 @@ start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
MV_ATA_SET_FEATURES_TRANSFER, udmaMode,
0, 0, 0) == MV_FALSE)
{
- MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
+ MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
pMvSataAdapter->adapterId, channelNum);
return -1;
}*/
@@ -721,48 +720,48 @@ start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0,
0, 0) == MV_FALSE)
{
- MV_ERROR("RR182x [%d] channel %d: Set Features failed\n",
+ MV_ERROR("RR18xx [%d] channel %d: Set Features failed\n",
pMvSataAdapter->adapterId, channelNum);
return -1;
}
}
- KdPrint(("RR182x [%d]: channel=%d, read look ahead enabled\n",
+ KdPrint(("RR18xx [%d]: channel=%d, read look ahead enabled\n",
pMvSataAdapter->adapterId, channelNum));
}
else
{
- KdPrint(("RR182x [%d]: channel %d, Read Look Ahead not supported\n",
+ KdPrint(("RR18xx [%d]: channel %d, Read Look Ahead not supported\n",
pMvSataAdapter->adapterId, channelNum));
}
#else
{
if (pMvSataChannel->identifyDevice[86] & 0x20)
{
- KdPrint(("RR182x [%d]:channel %d, disable read look ahead\n",
+ KdPrint(("RR18xx [%d]:channel %d, disable read look ahead\n",
pMvSataAdapter->adapterId, channelNum));
if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum,
MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0,
0, 0) == MV_FALSE)
{
- MV_ERROR("RR182x [%d]:channel %d: ATA Set Features failed\n",
+ MV_ERROR("RR18xx [%d]:channel %d: ATA Set Features failed\n",
pMvSataAdapter->adapterId, channelNum);
return -1;
}
}
- KdPrint(("RR182x [%d]:channel %d, read look ahead disabled\n",
+ KdPrint(("RR18xx [%d]:channel %d, read look ahead disabled\n",
pMvSataAdapter->adapterId, channelNum));
}
#endif
{
- KdPrint(("RR182x [%d]: channel %d config EDMA, Non Queued Mode\n",
+ KdPrint(("RR18xx [%d]: channel %d config EDMA, Non Queued Mode\n",
pMvSataAdapter->adapterId,
channelNum));
if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum,
MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE)
{
- MV_ERROR("RR182x [%d] channel %d Error: mvSataConfigEdmaMode failed\n",
+ MV_ERROR("RR18xx [%d] channel %d Error: mvSataConfigEdmaMode failed\n",
pMvSataAdapter->adapterId, channelNum);
return -1;
}
@@ -770,11 +769,11 @@ start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum)
/* Enable EDMA */
if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE)
{
- MV_ERROR("RR182x [%d] Failed to enable DMA, channel=%d\n",
+ MV_ERROR("RR18xx [%d] Failed to enable DMA, channel=%d\n",
pMvSataAdapter->adapterId, channelNum);
return -1;
}
- MV_ERROR("RR182x [%d,%d]: channel started successfully\n",
+ MV_ERROR("RR18xx [%d,%d]: channel started successfully\n",
pMvSataAdapter->adapterId, channelNum);
#ifndef FOR_DEMO
@@ -799,12 +798,12 @@ hptmv_handle_event(void * data, int flag)
/* Handle only connects */
if (flag == 1)
break;
- KdPrint(("RR182x [%d,%d]: new device connected\n",
+ KdPrint(("RR18xx [%d,%d]: new device connected\n",
pMvSataAdapter->adapterId, channelIndex));
hptmv_init_channel(pAdapter, channelIndex);
if (mvSataConfigureChannel( pMvSataAdapter, channelIndex) == MV_FALSE)
{
- MV_ERROR("RR182x [%d,%d] Failed to configure\n",
+ MV_ERROR("RR18xx [%d,%d] Failed to configure\n",
pMvSataAdapter->adapterId, channelIndex);
hptmv_free_channel(pAdapter, channelIndex);
}
@@ -813,7 +812,7 @@ hptmv_handle_event(void * data, int flag)
/*mvSataChannelHardReset(pMvSataAdapter, channel);*/
if (start_channel( pAdapter, channelIndex))
{
- MV_ERROR("RR182x [%d,%d]Failed to start channel\n",
+ MV_ERROR("RR18xx [%d,%d]Failed to start channel\n",
pMvSataAdapter->adapterId, channelIndex);
hptmv_free_channel(pAdapter, channelIndex);
}
@@ -829,7 +828,7 @@ hptmv_handle_event(void * data, int flag)
/* Handle only disconnects */
if (flag == 0)
break;
- KdPrint(("RR182x [%d,%d]: device disconnected\n",
+ KdPrint(("RR18xx [%d,%d]: device disconnected\n",
pMvSataAdapter->adapterId, channelIndex));
/* Flush pending commands */
if(pMvSataAdapter->sataChannel[channelIndex])
@@ -841,14 +840,14 @@ hptmv_handle_event(void * data, int flag)
mvSataRemoveChannel(pMvSataAdapter,channelIndex);
hptmv_free_channel(pAdapter, channelIndex);
pMvSataAdapter->sataChannel[channelIndex] = NULL;
- KdPrint(("RR182x [%d,%d]: channel removed\n",
+ KdPrint(("RR18xx [%d,%d]: channel removed\n",
pMvSataAdapter->adapterId, channelIndex));
if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0)
Check_Idle_Call(pAdapter);
}
else
{
- KdPrint(("RR182x [%d,%d]: channel already removed!!\n",
+ KdPrint(("RR18xx [%d,%d]: channel already removed!!\n",
pMvSataAdapter->adapterId, channelIndex));
}
pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE;
@@ -894,7 +893,7 @@ hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType,
if (param1 == EVENT_CONNECT)
{
pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_CONNECTED;
- KdPrint(("RR182x [%d,%d]: device connected event received\n",
+ KdPrint(("RR18xx [%d,%d]: device connected event received\n",
pMvSataAdapter->adapterId, channel));
/* Delete previous timers (if multiple drives connected in the same time */
pAdapter->event_timer_connect = timeout(hptmv_handle_event_connect, pAdapter, 10*hz);
@@ -902,7 +901,7 @@ hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType,
else if (param1 == EVENT_DISCONNECT)
{
pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_DISCONNECTED;
- KdPrint(("RR182x [%d,%d]: device disconnected event received \n",
+ KdPrint(("RR18xx [%d,%d]: device disconnected event received \n",
pMvSataAdapter->adapterId, channel));
device_change(pAdapter, channel, FALSE);
/* Delete previous timers (if multiple drives disconnected in the same time */
@@ -913,7 +912,7 @@ hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType,
else
{
- MV_ERROR("RR182x: illigal value for param1(%d) at "
+ MV_ERROR("RR18xx: illigal value for param1(%d) at "
"connect/disconect event, host=%d\n", param1,
pMvSataAdapter->adapterId );
@@ -921,11 +920,11 @@ hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType,
}
break;
case MV_EVENT_TYPE_ADAPTER_ERROR:
- KdPrint(("RR182x: DEVICE error event received, pci cause "
+ KdPrint(("RR18xx: DEVICE error event received, pci cause "
"reg=%x, don't how to handle this\n", param1));
return MV_TRUE;
default:
- MV_ERROR("RR182x[%d]: unknown event type (%d)\n",
+ MV_ERROR("RR18xx[%d]: unknown event type (%d)\n",
pMvSataAdapter->adapterId, eventType);
return MV_FALSE;
}
@@ -939,7 +938,7 @@ hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter)
M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
if (pAdapter->requestsArrayBaseAddr == NULL)
{
- MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA request"
+ MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA request"
" queues\n", pAdapter->mvSataAdapter.adapterId);
return -1;
}
@@ -955,7 +954,7 @@ hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter)
if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) !=
(pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr))
{
- MV_ERROR("RR182x[%d]: Error in Request Quueues Alignment\n",
+ MV_ERROR("RR18xx[%d]: Error in Request Quueues Alignment\n",
pAdapter->mvSataAdapter.adapterId);
contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
return -1;
@@ -965,7 +964,7 @@ hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter)
M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul);
if (pAdapter->responsesArrayBaseAddr == NULL)
{
- MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA response"
+ MV_ERROR("RR18xx[%d]: Failed to allocate memory for EDMA response"
" queues\n", pAdapter->mvSataAdapter.adapterId);
contigfree(pAdapter->requestsArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
return -1;
@@ -982,7 +981,7 @@ hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter)
if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) !=
(pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr))
{
- MV_ERROR("RR182x[%d]: Error in Response Quueues Alignment\n",
+ MV_ERROR("RR18xx[%d]: Error in Response Quueues Alignment\n",
pAdapter->mvSataAdapter.adapterId);
contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF);
contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF);
@@ -1065,8 +1064,8 @@ PVDevice
GetSpareDisk(_VBUS_ARG PVDevice pArray)
{
IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt;
- ULONG capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1);
- ULONG thiscap, maxcap = MAX_LBA_T;
+ LBA_T capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1);
+ LBA_T thiscap, maxcap = MAX_LBA_T;
PVDevice pVDevice, pFind = NULL;
int i;
@@ -1131,6 +1130,127 @@ void HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode)
KdPrint(("Failed to enable DMA, channel=%d", channelIndex));
}
+int HPTLIBAPI fDeSetTCQ(PDevice pDev, int enable, int depth)
+{
+ MV_SATA_CHANNEL *pSataChannel = pDev->mv;
+ MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
+ MV_U8 channelIndex = pSataChannel->channelNumber;
+ IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData;
+ MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]);
+ int dmaActive = pSataChannel->queueCommandsEnabled;
+ int ret = 0;
+
+ if (dmaActive) {
+ mvSataDisableChannelDma(pSataAdapter, channelIndex);
+ mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK);
+ }
+
+ if (enable) {
+ if (pSataChannel->queuedDMA == MV_EDMA_MODE_NOT_QUEUED &&
+ (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))) {
+ UCHAR depth = ((pSataChannel->identifyDevice[IDEN_QUEUE_DEPTH]) & 0x1f) + 1;
+ channelInfo->queueDepth = (depth==32)? 31 : depth;
+ mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_QUEUED, depth);
+ ret = 1;
+ }
+ }
+ else
+ {
+ if (pSataChannel->queuedDMA != MV_EDMA_MODE_NOT_QUEUED) {
+ channelInfo->queueDepth = 2;
+ mvSataConfigEdmaMode(pSataAdapter, channelIndex, MV_EDMA_MODE_NOT_QUEUED, 0);
+ ret = 1;
+ }
+ }
+
+ if (dmaActive)
+ mvSataEnableChannelDma(pSataAdapter,channelIndex);
+ return ret;
+}
+
+int HPTLIBAPI fDeSetNCQ(PDevice pDev, int enable, int depth)
+{
+ return 0;
+}
+
+int HPTLIBAPI fDeSetWriteCache(PDevice pDev, int enable)
+{
+ MV_SATA_CHANNEL *pSataChannel = pDev->mv;
+ MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
+ MV_U8 channelIndex = pSataChannel->channelNumber;
+ IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData;
+ MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]);
+ int dmaActive = pSataChannel->queueCommandsEnabled;
+ int ret = 0;
+
+ if (dmaActive) {
+ mvSataDisableChannelDma(pSataAdapter, channelIndex);
+ mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK);
+ }
+
+ if ((pSataChannel->identifyDevice[82] & (0x20))) {
+ if (enable) {
+ if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
+ MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, 0, 0, 0))
+ {
+ channelInfo->writeCacheEnabled = MV_TRUE;
+ ret = 1;
+ }
+ }
+ else {
+ if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
+ MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 0, 0, 0))
+ {
+ channelInfo->writeCacheEnabled = MV_FALSE;
+ ret = 1;
+ }
+ }
+ }
+
+ if (dmaActive)
+ mvSataEnableChannelDma(pSataAdapter,channelIndex);
+ return ret;
+}
+
+int HPTLIBAPI fDeSetReadAhead(PDevice pDev, int enable)
+{
+ MV_SATA_CHANNEL *pSataChannel = pDev->mv;
+ MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter;
+ MV_U8 channelIndex = pSataChannel->channelNumber;
+ IAL_ADAPTER_T *pAdapter = pSataAdapter->IALData;
+ MV_CHANNEL *channelInfo = &(pAdapter->mvChannel[channelIndex]);
+ int dmaActive = pSataChannel->queueCommandsEnabled;
+ int ret = 0;
+
+ if (dmaActive) {
+ mvSataDisableChannelDma(pSataAdapter, channelIndex);
+ mvSataFlushDmaQueue(pSataAdapter,channelIndex,MV_FLUSH_TYPE_CALLBACK);
+ }
+
+ if ((pSataChannel->identifyDevice[82] & (0x40))) {
+ if (enable) {
+ if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
+ MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, 0, 0))
+ {
+ channelInfo->readAheadEnabled = MV_TRUE;
+ ret = 1;
+ }
+ }
+ else {
+ if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex,
+ MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 0, 0))
+ {
+ channelInfo->readAheadEnabled = MV_FALSE;
+ ret = 1;
+ }
+ }
+ }
+
+ if (dmaActive)
+ mvSataEnableChannelDma(pSataAdapter,channelIndex);
+ return ret;
+}
+
#ifdef SUPPORT_ARRAY
#define IdeRegisterVDevice fCheckArray
#else
@@ -1166,9 +1286,12 @@ dmamap_put(PBUS_DMAMAP p)
/*Since mtx not provide the initialize when declare, so we Final init here to initialize the global mtx*/
#if __FreeBSD_version >= 500000
+#define override_kernel_driver()
+
static void hpt_init(void *dummy)
{
- mtx_init(&driver_lock, "hptlock", NULL, MTX_DEF);
+ override_kernel_driver();
+ mtx_init(&driver_lock, "hptsleeplock", NULL, MTX_DEF);
}
SYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL);
#endif
@@ -1183,6 +1306,8 @@ init_adapter(IAL_ADAPTER_T *pAdapter)
PVDevice pVDev;
+ intrmask_t oldspl = lock_driver();
+
pAdapter->next = 0;
if(gIal_Adapter == 0){
@@ -1222,7 +1347,8 @@ init_adapter(IAL_ADAPTER_T *pAdapter)
if (hptmv_allocate_edma_queues(pAdapter))
{
- MV_ERROR("RR182x: Failed to allocate memory for EDMA queues\n");
+ MV_ERROR("RR18xx: Failed to allocate memory for EDMA queues\n");
+ unlock_driver(oldspl);
return ENOMEM;
}
@@ -1233,13 +1359,14 @@ init_adapter(IAL_ADAPTER_T *pAdapter)
||
!(pMvSataAdapter->adapterIoBaseAddress = rman_get_virtual(pAdapter->mem_res)))
{
- MV_ERROR("RR182x: Failed to remap memory space\n");
+ MV_ERROR("RR18xx: Failed to remap memory space\n");
hptmv_free_edma_queues(pAdapter);
+ unlock_driver(oldspl);
return ENXIO;
}
else
{
- KdPrint(("RR182x: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress));
+ KdPrint(("RR18xx: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress));
}
pMvSataAdapter->adapterId = num_adapters++;
@@ -1247,7 +1374,7 @@ init_adapter(IAL_ADAPTER_T *pAdapter)
pMvSataAdapter->pciConfigRevisionId = pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1);
pMvSataAdapter->pciConfigDeviceId = pci_get_device(pAdapter->hpt_dev);
- /* init RR182x */
+ /* init RR18xx */
pMvSataAdapter->intCoalThre[0]= 1;
pMvSataAdapter->intCoalThre[1]= 1;
pMvSataAdapter->intTimeThre[0] = 1;
@@ -1259,11 +1386,12 @@ init_adapter(IAL_ADAPTER_T *pAdapter)
if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE)
{
- MV_ERROR("RR182x[%d]: core failed to initialize the adapter\n",
+ MV_ERROR("RR18xx[%d]: core failed to initialize the adapter\n",
pMvSataAdapter->adapterId);
unregister:
bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, pAdapter->mem_res);
hptmv_free_edma_queues(pAdapter);
+ unlock_driver(oldspl);
return ENXIO;
}
pAdapter->ver_601 = pMvSataAdapter->pcbVersion;
@@ -1341,14 +1469,14 @@ unregister:
if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel)
== MV_TRUE)
{
- KdPrint(("RR182x[%d]: channel %d is connected\n",
+ KdPrint(("RR18xx[%d]: channel %d is connected\n",
pMvSataAdapter->adapterId, channel));
if (hptmv_init_channel(pAdapter, channel) == 0)
{
if (mvSataConfigureChannel(pMvSataAdapter, channel) == MV_FALSE)
{
- MV_ERROR("RR182x[%d]: Failed to configure channel"
+ MV_ERROR("RR18xx[%d]: Failed to configure channel"
" %d\n",pMvSataAdapter->adapterId, channel);
hptmv_free_channel(pAdapter, channel);
}
@@ -1356,7 +1484,7 @@ unregister:
{
if (start_channel(pAdapter, channel))
{
- MV_ERROR("RR182x[%d]: Failed to start channel,"
+ MV_ERROR("RR18xx[%d]: Failed to start channel,"
" channel=%d\n",pMvSataAdapter->adapterId,
channel);
hptmv_free_channel(pAdapter, channel);
@@ -1402,10 +1530,11 @@ unregister:
#if defined(SUPPORT_ARRAY) && defined(_RAID5N_)
init_raid5_memory(_VBUS_P0);
_vbus_(r5).enable_write_back = 1;
- printf("RR182x: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled");
+ printf("RR18xx: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled");
#endif
mvSataUnmaskAdapterInterrupt(pMvSataAdapter);
+ unlock_driver(oldspl);
return 0;
}
@@ -1421,7 +1550,7 @@ MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel)
/* Software reset channel */
if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == MV_FALSE)
{
- MV_ERROR("RR182x [%d,%d]: failed to perform Software reset\n",
+ MV_ERROR("RR18xx [%d,%d]: failed to perform Software reset\n",
pMvSataAdapter->adapterId, channel);
hptmv_free_channel(pAdapter, channel);
return -1;
@@ -1430,7 +1559,7 @@ MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel)
/* Hardware reset channel */
if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE)
{
- MV_ERROR("RR182x [%d,%d] Failed to Hard reser the SATA channel\n",
+ MV_ERROR("RR18xx [%d,%d] Failed to Hard reser the SATA channel\n",
pMvSataAdapter->adapterId, channel);
hptmv_free_channel(pAdapter, channel);
return -1;
@@ -1438,7 +1567,7 @@ MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel)
if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == MV_FALSE)
{
- MV_ERROR("RR182x [%d,%d] Failed to Connect Device\n",
+ MV_ERROR("RR18xx [%d,%d] Failed to Connect Device\n",
pMvSataAdapter->adapterId, channel);
hptmv_free_channel(pAdapter, channel);
return -1;
@@ -1632,7 +1761,7 @@ fDeviceSendCommand(_VBUS_ARG PCommand pCmd)
MV_SATA_CHANNEL *pMvSataChannel;
PVDevice pVDevice = pCmd->pVDevice;
PDevice pDevice = &pVDevice->u.disk;
- ULONG Lba = pCmd->uCmd.Ide.Lba;
+ LBA_T Lba = pCmd->uCmd.Ide.Lba;
USHORT nSector = pCmd->uCmd.Ide.nSectors;
MV_QUEUE_COMMAND_RESULT result;
@@ -1640,7 +1769,7 @@ fDeviceSendCommand(_VBUS_ARG PCommand pCmd)
MV_UDMA_COMMAND_PARAMS *pUdmaParams = &commandInfo.commandParams.udmaCommand;
MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand;
- MV_BOOLEAN is48bit = MV_FALSE;
+ MV_BOOLEAN is48bit;
MV_U8 channel;
int i=0;
@@ -1667,9 +1796,12 @@ fDeviceSendCommand(_VBUS_ARG PCommand pCmd)
return;
}
- if(Lba & 0xF0000000){
- is48bit = MV_TRUE;
- }
+ /*
+ * always use 48bit LBA if drive supports it.
+ * Some Seagate drives report error if you use a 28-bit command
+ * to access sector 0xfffffff.
+ */
+ is48bit = pMvSataChannel->lba48Address;
switch (pCmd->uCmd.Ide.Command)
{
@@ -1929,7 +2061,13 @@ hpt_attach(device_t dev)
return(ENXIO);
}
- if(bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM, NULL, hpt_intr, pAdapter, &pAdapter->hpt_intr))
+#if __FreeBSD_version <700000
+ if (bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM,
+ hpt_intr, pAdapter, &pAdapter->hpt_intr))
+#else
+ if (bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM,
+ NULL, hpt_intr, pAdapter, &pAdapter->hpt_intr))
+#endif
{
hpt_printk(("can't set up interrupt\n"));
free(pAdapter, M_DEVBUF);
@@ -1959,14 +2097,23 @@ hpt_attach(device_t dev)
/*
* Construct our SIM entry
*/
- if ((hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME),
- pAdapter, device_get_unit(pAdapter->hpt_dev),
- &Giant, /*untagged*/1, /*tagged*/8, devq)) == NULL) {
+#if __FreeBSD_version <700000
+ hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME),
+ pAdapter, device_get_unit(pAdapter->hpt_dev), 1, 8, devq);
+#else
+ hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME),
+ pAdapter, device_get_unit(pAdapter->hpt_dev), &Giant, 1, 8, devq);
+#endif
+ if (hpt_vsim == NULL) {
cam_simq_free(devq);
return ENOMEM;
}
- if(xpt_bus_register(hpt_vsim, dev, 0) != CAM_SUCCESS)
+#if __FreeBSD_version <700000
+ if (xpt_bus_register(hpt_vsim, 0) != CAM_SUCCESS)
+#else
+ if (xpt_bus_register(hpt_vsim, dev, 0) != CAM_SUCCESS)
+#endif
{
cam_sim_free(hpt_vsim, /*free devq*/ TRUE);
hpt_vsim = NULL;
@@ -1991,14 +2138,9 @@ hpt_attach(device_t dev)
xpt_action((union ccb *)ccb);
free(ccb, M_DEVBUF);
- /* Register shutdown handler, and start the work thread. */
if (device_get_unit(dev) == 0) {
- pAdapter->eh = EVENTHANDLER_REGISTER(shutdown_final,
- hpt_shutdown, dev, SHUTDOWN_PRI_DEFAULT);
- if (pAdapter->eh)
- launch_worker_thread();
- else
- hpt_printk(("shutdown event registration failed\n"));
+ /* Start the work thread. XXX */
+ launch_worker_thread();
}
return 0;
@@ -2358,7 +2500,11 @@ static void hpt_worker_thread(void)
#if (__FreeBSD_version < 500000)
YIELD_THREAD;
#else
+#if (__FreeBSD_version > 700033)
pause("sched", 1);
+#else
+ tsleep((caddr_t)hpt_worker_thread, PPAUSE, "sched", 1);
+#endif
#endif
if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) {
/* abort rebuilding process. */
@@ -2392,15 +2538,25 @@ static void hpt_worker_thread(void)
/*
#ifdef DEBUG
if (SIGISMEMBER(curproc->p_siglist, SIGSTOP))
+#if (__FreeBSD_version > 700033)
pause("hptrdy", 2*hz);
+#else
+ tsleep((caddr_t)hpt_worker_thread, PPAUSE, "hptrdy", 2*hz);
+#endif
#endif
*/
- #if (__FreeBSD_version >= 500043)
+ #if (__FreeBSD_version >= 800002)
kproc_suspend_check(curproc);
+ #elif (__FreeBSD_version >= 500043)
+ kthread_suspend_check(curproc);
#else
kproc_suspend_loop(curproc);
#endif
+#if (__FreeBSD_version > 700033)
pause("hptrdy", 2*hz); /* wait for something to do */
+#else
+ tsleep((caddr_t)hpt_worker_thread, PPAUSE, "hptrdy", 2*hz); /* wait for something to do */
+#endif
}
}
@@ -2537,7 +2693,7 @@ SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev)
}
break;
default:
- memcpy(&inquiryData->VendorId, "RR182x ", 8);
+ memcpy(&inquiryData->VendorId, "RR18xx ", 8);
#ifdef SUPPORT_ARRAY
switch(pVDev->VDeviceType){
case VD_RAID_0:
@@ -2659,20 +2815,57 @@ OsSendCommand(_VBUS_ARG union ccb *ccb)
case READ_CAPACITY:
{
- UCHAR swip[4];
+ UCHAR *rbuf=csio->data_ptr;
+ unsigned int cap;
+
+ if (pVDev->VDeviceCapacity > 0xfffffffful) {
+ cap = 0xfffffffful;
+ } else {
+ cap = pVDev->VDeviceCapacity - 1;
+ }
+
+ rbuf[0] = (UCHAR)(cap>>24);
+ rbuf[1] = (UCHAR)(cap>>16);
+ rbuf[2] = (UCHAR)(cap>>8);
+ rbuf[3] = (UCHAR)cap;
/* Claim 512 byte blocks (big-endian). */
- ((PREAD_CAPACITY_DATA)csio->data_ptr)->BytesPerBlock = 0x20000;
- *(ULONG*)swip = pVDev->VDeviceCapacity - 1;
- ((PREAD_CAPACITY_DATA)csio->data_ptr)->LogicalBlockAddress =
- (swip[0] << 24) | (swip[1] << 16) | (swip[2] << 8) | swip[3];
+ rbuf[4] = 0;
+ rbuf[5] = 0;
+ rbuf[6] = 2;
+ rbuf[7] = 0;
+
ccb_h->status = CAM_REQ_CMP;
break;
}
+ case 0x9e: /*SERVICE_ACTION_IN*/
+ {
+ UCHAR *rbuf = csio->data_ptr;
+ LBA_T cap = pVDev->VDeviceCapacity - 1;
+
+ rbuf[0] = (UCHAR)(cap>>56);
+ rbuf[1] = (UCHAR)(cap>>48);
+ rbuf[2] = (UCHAR)(cap>>40);
+ rbuf[3] = (UCHAR)(cap>>32);
+ rbuf[4] = (UCHAR)(cap>>24);
+ rbuf[5] = (UCHAR)(cap>>16);
+ rbuf[6] = (UCHAR)(cap>>8);
+ rbuf[7] = (UCHAR)cap;
+ rbuf[8] = 0;
+ rbuf[9] = 0;
+ rbuf[10] = 2;
+ rbuf[11] = 0;
+
+ ccb_h->status = CAM_REQ_CMP;
+ break;
+ }
+
case READ_6:
case WRITE_6:
case READ_10:
case WRITE_10:
+ case 0x88: /* READ_16 */
+ case 0x8a: /* WRITE_16 */
case 0x13:
case 0x2f:
{
@@ -2716,6 +2909,20 @@ OsSendCommand(_VBUS_ARG union ccb *ccb)
pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4];
break;
+ case 0x88: /* READ_16 */
+ case 0x8a: /* WRITE_16 */
+ pCmd->uCmd.Ide.Lba =
+ (HPT_U64)Cdb[2] << 56 |
+ (HPT_U64)Cdb[3] << 48 |
+ (HPT_U64)Cdb[4] << 40 |
+ (HPT_U64)Cdb[5] << 32 |
+ (HPT_U64)Cdb[6] << 24 |
+ (HPT_U64)Cdb[7] << 16 |
+ (HPT_U64)Cdb[8] << 8 |
+ (HPT_U64)Cdb[9];
+ pCmd->uCmd.Ide.nSectors = (USHORT)Cdb[12] << 8 | (USHORT)Cdb[13];
+ break;
+
default:
pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | ((ULONG)Cdb[2] << 24);
pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | ((USHORT)Cdb[7]<<8);
@@ -2726,12 +2933,14 @@ OsSendCommand(_VBUS_ARG union ccb *ccb)
{
case READ_6:
case READ_10:
+ case 0x88: /* READ_16 */
pCmd->uCmd.Ide.Command = IDE_COMMAND_READ;
pCmd->cf_data_in = 1;
break;
case WRITE_6:
case WRITE_10:
+ case 0x8a: /* WRITE_16 */
pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE;
pCmd->cf_data_out = 1;
break;
diff --git a/sys/dev/hptmv/global.h b/sys/dev/hptmv/global.h
index 4e6a0d0..c6f6982 100644
--- a/sys/dev/hptmv/global.h
+++ b/sys/dev/hptmv/global.h
@@ -33,12 +33,12 @@
#include <dev/hptmv/mvStorageDev.h>
#define COMPANY "HighPoint Technologies, Inc."
-#define COPYRIGHT "(c) 2000-2004. HighPoint Technologies, Inc."
-#define DRIVER_NAME "RocketRAID 182x SATA Controller driver"
-#define CONTROLLER_NAME "RocketRAID 182x SATA Controller"
+#define COPYRIGHT "(c) 2000-2007. HighPoint Technologies, Inc."
+#define DRIVER_NAME "RocketRAID 18xx SATA Controller driver"
+#define CONTROLLER_NAME "RocketRAID 18xx SATA Controller"
#define PROC_DIR_NAME hptmv
-#define HPT_INTERFACE_VERSION 0x01000003
+#define HPT_INTERFACE_VERSION 0x01010000
#define SUPPORT_48BIT_LBA
#define SUPPORT_ARRAY
#define SUPPORT_RAID5 1
@@ -193,6 +193,10 @@ extern void HPTLIBAPI ioctl_ReportEvent(UCHAR event, PVOID param);
int HPTLIBAPI fDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer);
void HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode);
+int HPTLIBAPI fDeSetTCQ(PDevice pDev, int enable, int depth);
+int HPTLIBAPI fDeSetNCQ(PDevice pDev, int enable, int depth);
+int HPTLIBAPI fDeSetWriteCache(PDevice pDev, int enable);
+int HPTLIBAPI fDeSetReadAhead(PDevice pDev, int enable);
#include <dev/hptmv/atapi.h>
#include <dev/hptmv/command.h>
diff --git a/sys/dev/hptmv/gui_lib.c b/sys/dev/hptmv/gui_lib.c
index 13def6b..a9feb4a 100644
--- a/sys/dev/hptmv/gui_lib.c
+++ b/sys/dev/hptmv/gui_lib.c
@@ -57,11 +57,14 @@ static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo);
static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo);
static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount);
static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo);
+static int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo);
static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam);
+static DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam);
static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk);
static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk);
static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo);
static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo);
+static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo);
int
check_VDevice_valid(PVDevice p)
@@ -97,82 +100,65 @@ check_VDevice_valid(PVDevice p)
}
#ifdef SUPPORT_ARRAY
-static void get_array_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo)
-{
- int i;
-
- pInfo->Type = LDT_ARRAY;
- pInfo->Capacity = pVDevice->VDeviceCapacity;
- pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
- memcpy(pInfo->u.array.Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME);
-
- switch( pVDevice->VDeviceType )
+static UCHAR get_vdev_type(PVDevice pVDevice)
{
- case VD_RAID_0:
- pInfo->u.array.ArrayType = AT_RAID0;
- break;
- case VD_RAID_1:
- pInfo->u.array.ArrayType = AT_RAID1;
- break;
- case VD_JBOD:
- pInfo->u.array.ArrayType = AT_JBOD;
- break;
- case VD_RAID_5:
- pInfo->u.array.ArrayType = AT_RAID5;
- break;
- default:
- pInfo->u.array.ArrayType = AT_UNKNOWN;
+ switch (pVDevice->VDeviceType) {
+ case VD_RAID_0: return AT_RAID0;
+ case VD_RAID_1: return AT_RAID1;
+ case VD_JBOD: return AT_JBOD;
+ case VD_RAID_5: return AT_RAID5;
+ default: return AT_UNKNOWN;
+ }
}
- pInfo->u.array.BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
-
- pInfo->u.array.RebuiltSectors = pVDevice->u.array.RebuildSectors;
+static DWORD get_array_flag(PVDevice pVDevice)
+{
+ int i;
+ DWORD f = 0;
/* The array is disabled */
if(!pVDevice->vf_online) {
- pInfo->u.array.Flags |= ARRAY_FLAG_DISABLED;
- goto ignore_info;
+ f |= ARRAY_FLAG_DISABLED;
+ /* Ignore other info */
+ return f;
}
/* array need synchronizing */
if(pVDevice->u.array.rf_need_rebuild && !pVDevice->u.array.rf_duplicate_and_create)
- pInfo->u.array.Flags |= ARRAY_FLAG_NEEDBUILDING;
-
- pInfo->u.array.RebuildingProgress = ((pVDevice->u.array.RebuildSectors>>11)*1000 /
- (pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10;
+ f |= ARRAY_FLAG_NEEDBUILDING;
/* array is in rebuilding process */
if(pVDevice->u.array.rf_rebuilding)
- pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING;
+ f |= ARRAY_FLAG_REBUILDING;
/* array is being verified */
if(pVDevice->u.array.rf_verifying)
- pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING;
+ f |= ARRAY_FLAG_VERIFYING;
/* array is being initialized */
if(pVDevice->u.array.rf_initializing)
- pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING;
+ f |= ARRAY_FLAG_INITIALIZING;
/* broken but may still working */
if(pVDevice->u.array.rf_broken)
- pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN;
+ f |= ARRAY_FLAG_BROKEN;
/* array has a active partition */
if(pVDevice->vf_bootable)
- pInfo->u.array.Flags |= ARRAY_FLAG_BOOTDISK;
+ f |= ARRAY_FLAG_BOOTDISK;
/* a newly created array */
if(pVDevice->u.array.rf_newly_created)
- pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED;
+ f |= ARRAY_FLAG_NEWLY_CREATED;
/* array has boot mark set */
if(pVDevice->vf_bootmark)
- pInfo->u.array.Flags |= ARRAY_FLAG_BOOTMARK;
+ f |= ARRAY_FLAG_BOOTMARK;
/* auto-rebuild should start */
if(pVDevice->u.array.rf_auto_rebuild)
- pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD;
+ f |= ARRAY_FLAG_NEED_AUTOREBUILD;
for(i = 0; i < pVDevice->u.array.bArnMember; i++)
{
@@ -183,94 +169,128 @@ static void get_array_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo)
/* array need synchronizing */
if(pMember->u.array.rf_need_rebuild &&
!pMember->u.array.rf_duplicate_and_create)
- pInfo->u.array.Flags |= ARRAY_FLAG_NEEDBUILDING;
+ f |= ARRAY_FLAG_NEEDBUILDING;
/* array is in rebuilding process */
if(pMember->u.array.rf_rebuilding)
- pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING;
+ f |= ARRAY_FLAG_REBUILDING;
/* array is being verified */
if(pMember->u.array.rf_verifying)
- pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING;
+ f |= ARRAY_FLAG_VERIFYING;
/* array is being initialized */
if(pMember->u.array.rf_initializing)
- pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING;
+ f |= ARRAY_FLAG_INITIALIZING;
/* broken but may still working */
if(pMember->u.array.rf_broken)
- pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN;
+ f |= ARRAY_FLAG_BROKEN;
/* a newly created array */
if(pMember->u.array.rf_newly_created)
- pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED;
+ f |= ARRAY_FLAG_NEWLY_CREATED;
/* auto-rebuild should start */
if(pMember->u.array.rf_auto_rebuild)
- pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD;
+ f |= ARRAY_FLAG_NEED_AUTOREBUILD;
+ }
+
+ return f;
+}
+
+static DWORD calc_rebuild_progress(PVDevice pVDevice)
+{
+ int i;
+ DWORD result = ((ULONG)(pVDevice->u.array.RebuildSectors>>11)*1000 /
+ (ULONG)(pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10;
+
+ for(i = 0; i < pVDevice->u.array.bArnMember; i++)
+ {
+ PVDevice pMember = pVDevice->u.array.pMember[i];
+ if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK))
+ continue;
/* for RAID1/0 case */
if (pMember->u.array.rf_rebuilding ||
pMember->u.array.rf_verifying ||
pMember->u.array.rf_initializing)
{
- DWORD percent = ((pMember->u.array.RebuildSectors>>11)*1000 /
- (pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10;
- if (pInfo->u.array.RebuildingProgress==0 ||
- pInfo->u.array.RebuildingProgress>percent)
- pInfo->u.array.RebuildingProgress = percent;
+ DWORD percent = ((ULONG)(pMember->u.array.RebuildSectors>>11)*1000 /
+ (ULONG)(pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10;
+ if (result==0 || result>percent)
+ result = percent;
}
+ }
+
+ if (result>10000) result = 10000;
+ return result;
}
- if (pInfo->u.array.RebuildingProgress>10000)
- pInfo->u.array.RebuildingProgress = 10000;
+static void get_array_info(PVDevice pVDevice, PHPT_ARRAY_INFO pArrayInfo)
+{
+ int i;
-ignore_info:
+ memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME);
+ pArrayInfo->ArrayType = get_vdev_type(pVDevice);
+ pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
+ pArrayInfo->RebuiltSectors = pVDevice->u.array.RebuildSectors;
+ pArrayInfo->Flags = get_array_flag(pVDevice);
+ pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice);
- pInfo->u.array.nDisk = 0;
- for(i=0; i<MAX_ARRAY_MEMBERS; i++)
- pInfo->u.array.Members[i] = INVALID_DEVICEID;
+ pArrayInfo->nDisk = 0;
for(i = 0; i < pVDevice->u.array.bArnMember; i++)
- {
- if(pVDevice->u.array.pMember[i] != 0)
- {
- pInfo->u.array.Members[pInfo->u.array.nDisk] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
- pInfo->u.array.nDisk++;
- }
+ if(pVDevice->u.array.pMember[i] != NULL)
+ pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
+
+ for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS; i++)
+ pArrayInfo->Members[i] = INVALID_DEVICEID;
}
+
+static void get_array_info_v2(PVDevice pVDevice, PHPT_ARRAY_INFO_V2 pArrayInfo)
+{
+ int i;
+
+ memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAYNAME_LEN);
+ pArrayInfo->ArrayType = get_vdev_type(pVDevice);
+ pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
+ pArrayInfo->RebuiltSectors.lo32 = pVDevice->u.array.RebuildSectors;
+ pArrayInfo->RebuiltSectors.hi32 = sizeof(LBA_T)>4? (pVDevice->u.array.RebuildSectors>>32) : 0;
+ pArrayInfo->Flags = get_array_flag(pVDevice);
+ pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice);
+
+ pArrayInfo->nDisk = 0;
+
+ for(i = 0; i < pVDevice->u.array.bArnMember; i++)
+ if(pVDevice->u.array.pMember[i] != NULL)
+ pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
+
+ for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS_V2; i++)
+ pArrayInfo->Members[i] = INVALID_DEVICEID;
}
#endif
-static int get_disk_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo)
+static int get_disk_info(PVDevice pVDevice, PDEVICE_INFO pDiskInfo)
{
MV_SATA_ADAPTER *pSataAdapter;
MV_SATA_CHANNEL *pSataChannel;
IAL_ADAPTER_T *pAdapter;
+ MV_CHANNEL *channelInfo;
char *p;
int i;
- pInfo->Type = LDT_DEVICE;
-
- if (pVDevice->pParent)
- pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
- else
- pInfo->ParentArray = INVALID_DEVICEID;
-
- /* report real capacity to be compatible with old arrays */
- pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity;
-
/* device location */
pSataChannel = pVDevice->u.disk.mv;
if(pSataChannel == NULL) return -1;
- pInfo->u.device.TargetId = 0;
+ pDiskInfo->TargetId = 0;
pSataAdapter = pSataChannel->mvSataAdapter;
if(pSataAdapter == NULL) return -1;
pAdapter = pSataAdapter->IALData;
- pInfo->u.device.PathId = pSataChannel->channelNumber;
- pInfo->u.device.ControllerId = (UCHAR)pSataAdapter->adapterId;
+ pDiskInfo->PathId = pSataChannel->channelNumber;
+ pDiskInfo->ControllerId = (UCHAR)pSataAdapter->adapterId;
/*GUI uses DeviceModeSetting to display to users
(1) if users select a mode, GUI/BIOS should display that mode.
@@ -278,48 +298,58 @@ static int get_disk_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo)
(3) display real mode if case (1)&&(2) not satisfied.
*/
if (pVDevice->u.disk.df_user_mode_set)
- pInfo->u.device.DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode;
- else if ((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability & 3)==2)
- pInfo->u.device.DeviceModeSetting = 15;
+ pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode;
+ else if (((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability) & 3)==2)
+ pDiskInfo->DeviceModeSetting = 15;
else {
p = (char *)&((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->ModelNumber;
- if (*(WORD*)p==0x5354 /*'ST'*/ &&
- (*(WORD*)(p+8)==0x4153/*'AS'*/ || (p[8]=='A' && p[11]=='S')))
- pInfo->u.device.DeviceModeSetting = 15;
+ if (*(WORD*)p==(0x5354) /*'ST'*/ &&
+ (*(WORD*)(p+8)==(0x4153)/*'AS'*/ || (p[8]=='A' && p[11]=='S')))
+ pDiskInfo->DeviceModeSetting = 15;
else
- pInfo->u.device.DeviceModeSetting = pVDevice->u.disk.bDeModeSetting;
+ pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeModeSetting;
}
- pInfo->u.device.UsableMode = pVDevice->u.disk.bDeUsable_Mode;
+ pDiskInfo->UsableMode = pVDevice->u.disk.bDeUsable_Mode;
- pInfo->u.device.DeviceType = PDT_HARDDISK;
+ pDiskInfo->DeviceType = PDT_HARDDISK;
- pInfo->u.device.Flags = 0x0;
+ pDiskInfo->Flags = 0x0;
/* device is disabled */
if(!pVDevice->u.disk.df_on_line)
- pInfo->u.device.Flags |= DEVICE_FLAG_DISABLED;
+ pDiskInfo->Flags |= DEVICE_FLAG_DISABLED;
/* disk has a active partition */
if(pVDevice->vf_bootable)
- pInfo->u.device.Flags |= DEVICE_FLAG_BOOTDISK;
+ pDiskInfo->Flags |= DEVICE_FLAG_BOOTDISK;
/* disk has boot mark set */
if(pVDevice->vf_bootmark)
- pInfo->u.device.Flags |= DEVICE_FLAG_BOOTMARK;
+ pDiskInfo->Flags |= DEVICE_FLAG_BOOTMARK;
- pInfo->u.device.Flags |= DEVICE_FLAG_SATA;
+ pDiskInfo->Flags |= DEVICE_FLAG_SATA;
/* is a spare disk */
if(pVDevice->VDeviceType == VD_SPARE)
- pInfo->u.device.Flags |= DEVICE_FLAG_IS_SPARE;
+ pDiskInfo->Flags |= DEVICE_FLAG_IS_SPARE;
- memcpy(&(pInfo->u.device.IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2));
- p = (char *)&pInfo->u.device.IdentifyData.ModelNumber;
+ memcpy(&(pDiskInfo->IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2));
+ p = (char *)&pDiskInfo->IdentifyData.ModelNumber;
for (i = 0; i < 20; i++)
((WORD*)p)[i] = shortswap(pSataChannel->identifyDevice[IDEN_MODEL_OFFSET+i]);
p[39] = '\0';
+ channelInfo = &pAdapter->mvChannel[pSataChannel->channelNumber];
+ pDiskInfo->ReadAheadSupported = channelInfo->readAheadSupported;
+ pDiskInfo->ReadAheadEnabled = channelInfo->readAheadEnabled;
+ pDiskInfo->WriteCacheSupported = channelInfo->writeCacheSupported;
+ pDiskInfo->WriteCacheEnabled = channelInfo->writeCacheEnabled;
+ pDiskInfo->TCQSupported = (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))!=0;
+ pDiskInfo->TCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_QUEUED;
+ pDiskInfo->NCQSupported = MV_SATA_GEN_2(pSataAdapter) &&
+ (pSataChannel->identifyDevice[IDEN_SATA_CAPABILITIES] & (0x0100));
+ pDiskInfo->NCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_NATIVE_QUEUING;
return 0;
}
@@ -403,7 +433,7 @@ int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo)
#else
#define _set_product_id(x) strcpy(pInfo->szProductID, x)
#endif
- _set_product_id("RocketRAID 182x SATA Controller");
+ _set_product_id("RocketRAID 18xx SATA Controller");
pInfo->NumBuses = 8;
pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150;
return 0;
@@ -487,24 +517,60 @@ int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo)
return -1;
#ifdef SUPPORT_ARRAY
- if (mIsArray(pVDevice))
- get_array_info(pVDevice, pInfo);
- else
+ if (mIsArray(pVDevice)) {
+ pInfo->Type = LDT_ARRAY;
+ pInfo->Capacity = pVDevice->VDeviceCapacity;
+ pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
+ get_array_info(pVDevice, &pInfo->u.array);
+ return 0;
+ }
#endif
- return get_disk_info(pVDevice, pInfo);
+ pInfo->Type = LDT_DEVICE;
+ pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID;
+ /* report real capacity to be compatible with old arrays */
+ pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity;
+ return get_disk_info(pVDevice, &pInfo->u.device);
+}
+
+int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo)
+{
+ PVDevice pVDevice = ID_TO_VDEV(id);
+
+ if((id == 0) || check_VDevice_valid(pVDevice))
+ return -1;
+
+#ifdef SUPPORT_ARRAY
+ if (mIsArray(pVDevice)) {
+ pInfo->Type = LDT_ARRAY;
+ pInfo->Capacity.lo32 = pVDevice->VDeviceCapacity;
+ pInfo->Capacity.hi32 = sizeof(LBA_T)>4? (pVDevice->VDeviceCapacity>>32) : 0;
+ pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
+ get_array_info_v2(pVDevice, &pInfo->u.array);
return 0;
}
+#endif
+
+ pInfo->Type = LDT_DEVICE;
+ pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID;
+ /* report real capacity to be compatible with old arrays */
+ pInfo->Capacity.lo32 = pVDevice->u.disk.dDeRealCapacity;
+ pInfo->Capacity.hi32 = 0;
+ return get_disk_info(pVDevice, &pInfo->u.device);
+}
#ifdef SUPPORT_ARRAY
-DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam)
+DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam)
{
ULONG Stamp = GetStamp();
int i,j;
- ULONG capacity = MAX_LBA_T;
+ LBA_T capacity = MAX_LBA_T;
PVDevice pArray,pChild;
int Loca = -1;
+ if (pParam->nDisk > MAX_MEMBERS)
+ return INVALID_DEVICEID;
+/* check in verify_vd
for(i = 0; i < pParam->nDisk; i++)
{
PVDevice pVDev = ID_TO_VDEV(pParam->Members[i]);
@@ -516,6 +582,8 @@ DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam)
else if (_vbus_p != pVDev->u.disk.pVBus)
return INVALID_DEVICEID;
}
+*/
+ _vbus_p = (ID_TO_VDEV(pParam->Members[0]))->u.disk.pVBus;
if (!_vbus_p) return INVALID_DEVICEID;
mArGetArrayTable(pArray);
@@ -742,6 +810,22 @@ error:
return INVALID_DEVICEID;
}
+DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam)
+{
+ CREATE_ARRAY_PARAMS_V2 param2;
+ param2.ArrayType = pParam->ArrayType;
+ param2.nDisk = pParam->nDisk;
+ param2.BlockSizeShift = pParam->BlockSizeShift;
+ param2.CreateFlags = pParam->CreateFlags;
+ param2.CreateTime = pParam->CreateTime;
+ memcpy(param2.ArrayName, pParam->ArrayName, sizeof(param2.ArrayName));
+ memcpy(param2.Description, pParam->Description, sizeof(param2.Description));
+ memcpy(param2.CreateManager, pParam->CreateManager, sizeof(param2.CreateManager));
+ param2.Capacity.lo32 = param2.Capacity.hi32 = 0;
+ memcpy(param2.Members, pParam->Members, sizeof(pParam->Members));
+ return hpt_create_array_v2(_VBUS_P &param2);
+}
+
#ifdef SUPPORT_OLD_ARRAY
/* this is only for old RAID 0/1 */
int old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
@@ -822,7 +906,7 @@ int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
{
int i;
- ULONG Capacity;
+ LBA_T Capacity;
PVDevice pArray = ID_TO_VDEV(idArray);
PVDevice pDisk = ID_TO_VDEV(idDisk);
@@ -859,7 +943,7 @@ int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
for(i = 0; i < pArray->u.array.bArnMember; i++)
- if((pArray->u.array.pMember[i] == NULL) || !pArray->u.array.pMember[i]->vf_online)
+ if((pArray->u.array.pMember[i] == 0) || !pArray->u.array.pMember[i]->vf_online)
{
if(pArray->u.array.pMember[i] != NULL)
pArray->u.array.pMember[i]->pParent = NULL;
@@ -961,124 +1045,76 @@ int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo)
return 0;
}
-int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo)
+static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo)
{
PVDevice pVDevice = ID_TO_VDEV(idDisk);
- /* stop buzzer. */
- if(idDisk == 0) {
-#ifndef FOR_DEMO
- IAL_ADAPTER_T *pAdapter;
- for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
- if (pAdapter->beeping) {
- pAdapter->beeping = 0;
- BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
- }
- }
-#endif
+ if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1;
+ if (mIsArray(pVDevice))
+ return -1;
+
+ if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
+
+ /* TODO */
return 0;
}
- if (check_VDevice_valid(pVDevice)) return -1;
+static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo)
+{
+ PVDevice pVDevice = ID_TO_VDEV(idDisk);
+ int sync = 0;
+
+ if(idDisk==0 || check_VDevice_valid(pVDevice)) return -1;
if (mIsArray(pVDevice))
return -1;
if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
-/* if (pInfo->ValidFields & ADIF_MODE) {
+ if (pInfo->ValidFields & ADIF_MODE) {
pVDevice->u.disk.bDeModeSetting = pInfo->DeviceModeSetting;
pVDevice->u.disk.bDeUserSelectMode = pInfo->DeviceModeSetting;
pVDevice->u.disk.df_user_mode_set = 1;
fDeSelectMode((PDevice)&(pVDevice->u.disk), (UCHAR)pInfo->DeviceModeSetting);
- SyncArrayInfo(pVDevice);
- }*/
- return 0;
+ sync = 1;
}
-#endif
-
-#ifdef SUPPORT_HPT601
-int hpt_get_601_info(DEVICEID idDisk, PHPT601_INFO pInfo)
-{
- PVDevice pVDevice = ID_TO_VDEV(idDisk);
- PChannel pChan = pVDevice->u.disk.pChannel;
- PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1;
-
- if(!pVDevice->u.disk.df_with_601) return -1;
-
- mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId);
- pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1);
-
- BeginAccess601(IoPort);
-
- mSetBlockCount(IoPort, 0);
- pInfo->DeviceId = InWord(&IoPort->Data);
-
- mSetBlockCount(IoPort, 0x14);
- pInfo->Temperature = InWord(&IoPort->Data);
-
- mSetBlockCount(IoPort, 0xA);
- pInfo->FanStatus = InWord(&IoPort->Data);
- mSetBlockCount(IoPort, 7);
- pInfo->BeeperControl = InWord(&IoPort->Data);
-
- mSetBlockCount(IoPort, 3);
- pInfo->LED1Control = InWord(&IoPort->Data);
-
- mSetBlockCount(IoPort, 5);
- pInfo->LED2Control = InWord(&IoPort->Data);
-
- mSetBlockCount(IoPort, 0x18);
- pInfo->PowerStatus = InWord(&IoPort->Data);
-
- EndAccess601(IoPort);
- pInfo->ValidFields = 0x7F;
- /*DEVICEID|TEMPERATURE|FANSTATUS|BEEPERCONTROL|LED1CONTROL|LED2CONTROL|POWERSTATUS*/
- return 0;
+ if (pInfo->ValidFields & ADIF_TCQ) {
+ if (fDeSetTCQ(&pVDevice->u.disk, pInfo->TCQEnabled, 0)) {
+ pVDevice->u.disk.df_tcq_set = 1;
+ pVDevice->u.disk.df_tcq = pInfo->TCQEnabled!=0;
+ sync = 1;
}
-
-int hpt_set_601_info(DEVICEID idDisk, PHPT601_INFO pInfo)
-{
- PVDevice pVDevice = ID_TO_VDEV(idDisk);
- PChannel pChan = pVDevice->u.disk.pChannel;
- PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1;
-
- if(!pVDevice->u.disk.df_with_601) return -1;
-
- mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId);
- pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1);
-
- BeginAccess601(IoPort);
-
- if (pInfo->ValidFields & HPT601_INFO_TEMPERATURE) {
- mSetBlockCount(IoPort, 1);
- OutWord(&IoPort->Data, pInfo->Temperature);
}
- if (pInfo->ValidFields & HPT601_INFO_FANSTATUS) {
- mSetBlockCount(IoPort, 0xA);
- OutWord(&IoPort->Data, pInfo->FanStatus);
+ if (pInfo->ValidFields & ADIF_NCQ) {
+ if (fDeSetNCQ(&pVDevice->u.disk, pInfo->NCQEnabled, 0)) {
+ pVDevice->u.disk.df_ncq_set = 1;
+ pVDevice->u.disk.df_ncq = pInfo->NCQEnabled!=0;
+ sync = 1;
}
-
- if (pInfo->ValidFields & HPT601_INFO_BEEPERCONTROL) {
- mSetBlockCount(IoPort, 7);
- OutWord(&IoPort->Data, pInfo->BeeperControl);
}
- if (pInfo->ValidFields & HPT601_INFO_LED1CONTROL) {
- mSetBlockCount(IoPort, 3);
- OutWord(&IoPort->Data, pInfo->LED1Control);
+ if (pInfo->ValidFields & ADIF_WRITE_CACHE) {
+ if (fDeSetWriteCache(&pVDevice->u.disk, pInfo->WriteCacheEnabled)) {
+ pVDevice->u.disk.df_write_cache_set = 1;
+ pVDevice->u.disk.df_write_cache = pInfo->WriteCacheEnabled!=0;
+ sync = 1;
}
-
- if (pInfo->ValidFields & HPT601_INFO_LED2CONTROL) {
- mSetBlockCount(IoPort, 5);
- OutWord(&IoPort->Data, pInfo->LED2Control);
}
- EndAccess601(IoPort);
+ if (pInfo->ValidFields & ADIF_READ_AHEAD) {
+ if (fDeSetReadAhead(&pVDevice->u.disk, pInfo->ReadAheadEnabled)) {
+ pVDevice->u.disk.df_read_ahead_set = 1;
+ pVDevice->u.disk.df_read_ahead = pInfo->ReadAheadEnabled!=0;
+ sync = 1;
+ }
+ }
+ if (sync)
+ SyncArrayInfo(pVDevice);
return 0;
}
+
#endif
/* hpt_default_ioctl()
@@ -1175,21 +1211,46 @@ int hpt_default_ioctl(_VBUS_ARG
}
break;
-#ifdef SUPPORT_ARRAY
- case HPT_IOCTL_CREATE_ARRAY:
+ case HPT_IOCTL_GET_DEVICE_INFO_V2:
{
- CREATE_ARRAY_PARAMS *pParam;
DEVICEID id;
+ PLOGICAL_DEVICE_INFO_V2 pInfo;
+
+ if (nInBufferSize!=sizeof(DEVICEID)) return -1;
+ if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO_V2)) return -1;
+ id = *(DWORD *)lpInBuffer;
+ if (id == INVALID_DEVICEID) return -1;
+
+ pInfo = (PLOGICAL_DEVICE_INFO_V2)lpOutBuffer;
+ memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO_V2));
+
+ if (hpt_get_device_info_v2(id, pInfo)!=0)
+ return -1;
+ }
+ break;
+
+#ifdef SUPPORT_ARRAY
+ case HPT_IOCTL_CREATE_ARRAY:
+ {
if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1;
if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
- pParam = (PCREATE_ARRAY_PARAMS)lpInBuffer;
+ *(DEVICEID *)lpOutBuffer = hpt_create_array(_VBUS_P (PCREATE_ARRAY_PARAMS)lpInBuffer);
- id = hpt_create_array(_VBUS_P pParam);
- *(DEVICEID *)lpOutBuffer = id;
+ if(*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID)
+ return -1;
+ }
+ break;
+
+ case HPT_IOCTL_CREATE_ARRAY_V2:
+ {
+ if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS_V2)) return -1;
+ if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
+
+ *(DEVICEID *)lpOutBuffer = hpt_create_array_v2(_VBUS_P (PCREATE_ARRAY_PARAMS_V2)lpInBuffer);
- if(id == (DEVICEID)INVALID_DEVICEID)
+ if (*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID)
return -1;
}
break;
@@ -1225,6 +1286,21 @@ int hpt_default_ioctl(_VBUS_ARG
}
break;
+ case HPT_IOCTL_SET_DEVICE_INFO_V2:
+ {
+ DEVICEID idDisk;
+ PALTERABLE_DEVICE_INFO_V2 pInfo;
+
+ if (nInBufferSize < sizeof(HPT_SET_DEVICE_INFO_V2)) return -1;
+ if (nOutBufferSize!=0) return -1;
+
+ idDisk = ((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk;
+ pInfo = &((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->Info;
+ if(hpt_set_device_info_v2(_VBUS_P idDisk, pInfo) != 0)
+ return -1;
+ }
+ break;
+
case HPT_IOCTL_SET_BOOT_MARK:
{
DEVICEID id;
@@ -1238,7 +1314,7 @@ int hpt_default_ioctl(_VBUS_ARG
while(pAdapter != 0)
{
pVBus = &pAdapter->VBus;
- for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
+ for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
{
if(!(pTop = pVBus->pVDevice[i])) continue;
if (pTop->pVBus!=_vbus_p) return -1;
@@ -1256,16 +1332,7 @@ int hpt_default_ioctl(_VBUS_ARG
}
}
break;
-#endif
- case HPT_IOCTL_RESCAN_DEVICES:
- {
- if (nInBufferSize!=0) return -1;
- if (nOutBufferSize!=0) return -1;
- fRescanAllDevice(_VBUS_P0);
- }
- break;
-#ifdef SUPPORT_ARRAY
case HPT_IOCTL_ADD_SPARE_DISK:
{
DEVICEID id;
@@ -1319,41 +1386,57 @@ int hpt_default_ioctl(_VBUS_ARG
}
break;
-#ifdef SUPPORT_HPT601
- case HPT_IOCTL_GET_601_INFO:
+ case HPT_IOCTL_GET_CONTROLLER_VENID:
{
- DEVICEID id;
- PHPT601_INFO pInfo;
-
- if (nInBufferSize!=sizeof(DEVICEID)) return -1;
- if (nOutBufferSize!=sizeof(HPT601_INFO)) return -1;
+ DWORD id = ((DWORD*)lpInBuffer)[0];
+ IAL_ADAPTER_T *pAdapTemp;
+ int iControllerCount = 0;
- id = *(DWORD *)lpInBuffer;
- if (id == INVALID_DEVICEID) return -1;
-
- pInfo = (PHPT601_INFO)lpOutBuffer;
- memset(pInfo, 0, sizeof(HPT601_INFO));
-
- if (hpt_get_601_info(id, pInfo)!=0)
+ for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next)
+ if (iControllerCount++==id)
+ break;
+
+ if (!pAdapTemp)
return -1;
+
+ if (nOutBufferSize < 4)
+ return -1;
+
+ *(DWORD*)lpOutBuffer = ((DWORD)pAdapTemp->mvSataAdapter.pciConfigDeviceId << 16) | 0x11AB;
+ return 0;
}
- break;
- case HPT_IOCTL_SET_601_INFO:
+ case HPT_IOCTL_EPROM_IO:
{
- DEVICEID id;
- PHPT601_INFO pInfo;
+ DWORD id = ((DWORD*)lpInBuffer)[0];
+ DWORD offset = ((DWORD*)lpInBuffer)[1];
+ DWORD direction = ((DWORD*)lpInBuffer)[2];
+ DWORD length = ((DWORD*)lpInBuffer)[3];
+ IAL_ADAPTER_T *pAdapTemp;
+ int iControllerCount = 0;
+
+ for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next)
+ if (iControllerCount++==id)
+ break;
+
+ if (!pAdapTemp)
+ return -1;
+
+ if (nInBufferSize < sizeof(DWORD) * 4 + (direction? length : 0) ||
+ nOutBufferSize < (direction? 0 : length))
+ return -1;
- if (nInBufferSize!=sizeof(HPT_SET_601_INFO)) return -1;
- if (nOutBufferSize!=0) return -1;
+ if (direction == 0) /* read */
+ sx508x_flash_access(&pAdapTemp->mvSataAdapter,
+ offset, lpOutBuffer, length, 1);
+ else
+ sx508x_flash_access(&pAdapTemp->mvSataAdapter,
+ offset, (char *)lpInBuffer + 16, length, 0);
- id = ((PHPT_SET_601_INFO)lpInBuffer)->idDisk;
- pInfo = &((PHPT_SET_601_INFO)lpInBuffer)->Info;
- if(hpt_set_601_info(id, pInfo) != 0)
- return -1;
+ return 0;
}
break;
-#endif
+
default:
return -1;
}
diff --git a/sys/dev/hptmv/hptintf.h b/sys/dev/hptmv/hptintf.h
index 34477a2..09d638f 100644
--- a/sys/dev/hptmv/hptintf.h
+++ b/sys/dev/hptmv/hptintf.h
@@ -162,7 +162,7 @@ typedef DWORD DEVICEID;
* It would be better if ioctl code are the same on different platforms,
* but we must not conflict with system defined ioctl code.
************************************************************************/
-#if defined(LINUX) || defined(__FreeBSD_version) || defined(_MACOSX_)
+#if defined(LINUX) || defined(__FreeBSD_version)
#define HPT_CTL_CODE(x) (x+0xFF00)
#elif defined(_MS_WIN32_) || defined(WIN32)
@@ -221,6 +221,11 @@ typedef DWORD DEVICEID;
#define HPT_IOCTL_DEVICE_IO_V2 HPT_CTL_CODE(39)
#define HPT_IOCTL_DEVICE_IO_EX_V2 HPT_CTL_CODE(40)
+#define HPT_IOCTL_I2C_TRANSACTION HPT_CTL_CODE(48)
+#define HPT_IOCTL_GET_PARAMETER_LIST HPT_CTL_CODE(49)
+#define HPT_IOCTL_GET_PARAMETER HPT_CTL_CODE(50)
+#define HPT_IOCTL_SET_PARAMETER HPT_CTL_CODE(51)
+
/* Windows only */
#define HPT_IOCTL_GET_CONTROLLER_IDS HPT_CTL_CODE(100)
#define HPT_IOCTL_GET_DCB HPT_CTL_CODE(101)
@@ -368,8 +373,13 @@ typedef struct _HPT_ARRAY_INFO {
#if HPT_INTERFACE_VERSION>=0x01010000
typedef struct _LBA64 {
+#ifdef __BIG_ENDIAN_BITFIELD
+ DWORD hi32;
+ DWORD lo32;
+#else
DWORD lo32;
DWORD hi32;
+#endif
}
LBA64;
typedef struct _HPT_ARRAY_INFO_V2 {
@@ -687,16 +697,15 @@ typedef struct _IDE_PASS_THROUGH_HEADER {
DEVICEID idDisk; /* disk ID */
BYTE bFeaturesReg; /* feature register */
BYTE bSectorCountReg; /* IDE sector count register. */
- BYTE bSectorNumberReg; /* IDE sector number register. */
- BYTE bCylLowReg; /* IDE low order cylinder value. */
- BYTE bCylHighReg; /* IDE high order cylinder value. */
+ BYTE bLbaLowReg; /* IDE sector number register. */
+ BYTE bLbaMidReg; /* IDE low order cylinder value. */
+ BYTE bLbaHighReg; /* IDE high order cylinder value. */
BYTE bDriveHeadReg; /* IDE drive/head register. */
BYTE bCommandReg; /* Actual IDE command. Checked for validity by driver. */
- BYTE reserve1;
- DWORD DataSize; /* data size in bytes, if the command has data transfer */
-#ifdef _MSC_VER
- BYTE DataBuffer[0]; /* data buffer */
-#endif
+ BYTE nSectors; /* data sze in sectors, if the command has data transfer */
+ BYTE protocol; /* IO_COMMAND_(READ,WRITE) or zero for non-DATA */
+ BYTE reserve[3];
+#define IDE_PASS_THROUGH_buffer(p) ((unsigned char *)(p) + sizeof(IDE_PASS_THROUGH_HEADER))
}
IDE_PASS_THROUGH_HEADER, *PIDE_PASS_THROUGH_HEADER;
@@ -729,7 +738,8 @@ DEVICE_IO_EX_PARAMS, *PDEVICE_IO_EX_PARAMS;
/*
* ioctl structure
*/
-#define HPT_IOCTL_MAGIC 0x1A2B3C4D
+#define HPT_IOCTL_MAGIC32 0x1A2B3C4D
+#define HPT_IOCTL_MAGIC 0xA1B2C3D4
typedef struct _HPT_IOCTL_PARAM {
DWORD Magic; /* used to check if it's a valid ioctl packet */
@@ -742,7 +752,7 @@ typedef struct _HPT_IOCTL_PARAM {
}
HPT_IOCTL_PARAM, *PHPT_IOCTL_PARAM;
-/* for 64-bit system */
+/* for 32-bit app running on 64-bit system */
typedef struct _HPT_IOCTL_PARAM32 {
DWORD Magic;
DWORD dwIoControlCode;
@@ -1206,6 +1216,18 @@ int hpt_query_remove(DWORD ndev, DEVICEID *pIds);
int hpt_remove_devices(DWORD ndev, DEVICEID *pIds);
/*-------------------------------------------------------------------------- */
+/* hpt_ide_pass_through
+ * directly access controller's command and control registers.
+ * Can only call it on physical devices.
+ * Version compatibility: v1.0.0.3 or later
+ * Parameters:
+ * p - IDE_PASS_THROUGH header pointer
+ * Returns:
+ * 0 Success
+ */
+int hpt_ide_pass_through(PIDE_PASS_THROUGH_HEADER p);
+/*-------------------------------------------------------------------------- */
+
#endif
#pragma pack()
diff --git a/sys/dev/hptmv/hptproc.c b/sys/dev/hptmv/hptproc.c
index b38ef38..b93ab22 100644
--- a/sys/dev/hptmv/hptproc.c
+++ b/sys/dev/hptmv/hptproc.c
@@ -278,7 +278,8 @@ hpt_set_info(int length)
}
#ifdef SUPPORT_IOCTL
piop = (PHPT_IOCTL_PARAM)buffer;
- if (piop->Magic == HPT_IOCTL_MAGIC) {
+ if (piop->Magic == HPT_IOCTL_MAGIC ||
+ piop->Magic == HPT_IOCTL_MAGIC32) {
KdPrintE(("ioctl=%d in=%p len=%d out=%p len=%d\n",
piop->dwIoControlCode,
piop->lpInBuffer,
@@ -450,14 +451,14 @@ hpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray)
if (pTmpArray->u.array.rf_rebuilding) {
#ifdef DEBUG
- sprintf(buf, "Rebuilding %dMB", (pTmpArray->u.array.RebuildSectors>>11));
+ sprintf(buf, "Rebuilding %lldMB", (pTmpArray->u.array.RebuildSectors>>11));
#else
- sprintf(buf, "Rebuilding %d%%", (pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11));
+ sprintf(buf, "Rebuilding %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)));
#endif
sStatus = buf;
}
else if (pTmpArray->u.array.rf_verifying) {
- sprintf(buf, "Verifying %d%%", (pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11));
+ sprintf(buf, "Verifying %d%%", (UINT)((pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)));
sStatus = buf;
}
else if (pTmpArray->u.array.rf_need_rebuild)
@@ -472,7 +473,7 @@ hpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray)
}
out:
if (!sStatus) sStatus = "Normal";
- hpt_copy_info(pinfo, "%2d %11s %-20s %5dMB %-16s", nld, sType, pArray->u.array.ArrayName, pArray->VDeviceCapacity>>11, sStatus);
+ hpt_copy_info(pinfo, "%2d %11s %-20s %5lldMB %-16s", nld, sType, pArray->u.array.ArrayName, pArray->VDeviceCapacity>>11, sStatus);
}
#endif
diff --git a/sys/dev/hptmv/i386-elf.raid.o.uu b/sys/dev/hptmv/i386-elf.raid.o.uu
index a7462b8..6e1b8ca 100644
--- a/sys/dev/hptmv/i386-elf.raid.o.uu
+++ b/sys/dev/hptmv/i386-elf.raid.o.uu
@@ -26,1358 +26,1415 @@
* $FreeBSD$
*/
begin 644 hptmvraid.o
-M?T5,1@$!`0D```````````$``P`!``````````````#(O@```````#0`````
-M`"@`#``)`%6)Y5=64X'L'`(``(M]"(M'#(F%Y/W__XUWQ+`"@'\!`'4*@'\"
-M`1G`@^`"0(@&QT8$`````(!.`02+1PR)1@B+5Q")5@P/M@:+!(4`````B48T
-M@#X#=2R-0O:)1@R-E>C]__]2:B"+1Q"#Z`I05^C\____@\00@;WH_?__\Q9X
-M6G07D`^V!HL$A0````")1CB`3@$$Z;8$``"#[`AHD````(V-Z/W__U'H_/__
-M_X/$$(3`=<_VA?']__\"="+&1P@!BH7R_?__B$<+.D<)<Q"#[`@/ML!05^C\
-M____@\00@^P(:``"``"-A>C]__]0Z/S___^#Q!"$P'0>@^P$:'`!``!J`(V%
-MZ/W__P60````4.C\____@\00BI5[_O__B-.#XP&*1P2#X/R(T8/A`@G8"<B(
-MTX/C!(/@\XC1@^$("=@)R(C3@^,0@^#/B-&#X2`)V`G(B-&#X4"#X#^#XH`)
-MR`G0B$<$BI7Q_?__@^(!BD8!@^#^"="(1@&`O?C]__\##X3\_O__@+WX_?__
-M`'40Q@8`H0````")1CCIKP,``(.][/W__P`/A-;^__^Z``````^VA?/]__^)
-MP8/X`'XONP````")T,'@!(V]Z/W__P'X@'@0"`^'I_[__P^V0!"#/(,`#X29
-M_O__0CG1?]:+A0#^__^)A=S]__^Z`````(T$4HT$P(N-Y/W__XV<P6`B``"#
-M>P0`=0^+0T`[A>S]__\/A"$!``!"@_H/?M*+O>3]__^+GUPB``"%VW0?BT,(
-MB8=<(@``@^P$:-@```!J`%/H_/___XE["(/$$(N%[/W__XE#0(I32H/*`8A3
-M2F8/MH7\_?__@^`!T>"#XOT)PHA32F:+A?[]__]FB4-,BX7<_?__B4-0BH7X
-M_?__B`.*A?O]__^(0SX/MLBX`0```-/@9HE#2,=#!`````"+A?3]__^)0PR*
-MA?G]__^(0SP/M@.+!(4`````B4,T@^P$:A"-A>C]__^#P"Q0C4-T4.C\____
-M@\0,:@2-A>C]__^#P#Q0C8.$````4.C\____@\0,:A"-A>C]__^#Z(!0C8/(
-M````4.C\____@\0,:D"-A>C]__^#P$!0C8.(````4.C\____@\00BY7<_?__
-M.5-0=@.)4U#VA?']__\!=`2`2P$!BHWZ_?__B(WC_?__@+WS_?__`0^&HP$`
-M``^VP8M\@U2+A1#^__^)A=S]__^%_P^%/0$``(N5Y/W__XNZ7"(``(7_="6+
-M1PB)@EPB``"#[`1HV````&H`5^C\____BXWD_?__B4\(@\00BX7L_?__B4=`
-MBE=*@\H!B%=*9@^VA0S^__^#X`'1X(/B_0G"B%=*9HN%#O[__V:)1TR+A=S]
-M__^)1U"*A0G^__^(1SR*A0C^__^(!XE?!(N%!/[__XE'#(J%"_[__XA'/@^V
-MR+@!````T^!FB4=(#[8'BP2%`````(E'-`^V`XL$A0````")1SB*E>/]__^(
-M5P,/ML*)?(-4_D,]@^P$:A"-A>C]__^#P"Q0C4=T4.C\____@\0,:@2-A>C]
-M__^#P#Q0C8>$````4.C\____@\0,:A"-A>C]__^#Z(!0C8?(````4.C\____
-M@\0,:D"-A>C]__^#P$!0C8>(````4.C\____@\00]H7Q_?__`70$@$\!`0^V
-MA0K^__^#?(=4`'5?B72'5(J%"O[__XA&`_Y'/8E^!`^V!XL$A0````")1CB+
-MC=S]__\Y3U!V-(E/4.LO#[:%X_W__X-\@U0`=2&)=(-4B5X$_D,]BH7C_?__
-MB$8##[8#BP2%`````(E&.)"-9?1;7E_)PU6)Y593BW4,NP`````/MD8\B<*#
-M^``/CJ@```"#?)Y4`'0*0SG:?_3IEP```+@!````B-G3X&8)1DR#[`A6_W4(
-MZ/S___^)PH/$$(7`='7&``.(6`.)<`2`/@@/E,#!X`.*2@&#X?<)P8A*`:$,
-M````B4(T#[8&BP2%`````(E"./9&`1!T#HC(@\@0B$(!BT),B4(,B52>5(I&
-M2H/@_H/("HA&2L=&4`````#^1CV#[`A2:@?H_/___X!.2@2#Q!"-=@"-9?A;
-M7LG#D%6)Y5=64X/L#(MU#`^V!H/X!G1\@_@&?PN#^`0/C%(!``#K$(/X"`^$
-MNP```.E"`0``B?:*1CTZ1CP/A30!``"`3@$$@&9*_K\`````@'X\``^$'0$`
-M`)"+7+Y4A=MT((`[`W8;@^P(4_]U".C\____@\00]D-*!'0&@$Y*!(GV1P^V
-M1CPY^'_/Z>8```")]H!.`02`?CT"=0J`9DK^Z=$```"0@&9*_8-^5`!U$8M&
-M6,9``P")1E3'1E@`````BT94@#@#=1&#[`A6_W4(Z/S___^#Q!")]H!.2@3'
-M1E``````Z8P```"*1CTZ1CQU'(!.`02*1DJ#X/Z(1DIF@WY,`'1D@\@"B$9*
-MZUP/MD8]0`^V5CPYT'5/9H-^3`!T(;D`````#[=&3(G"J`%U"4&)T-/XJ`%T
-M]X-\CE0`=1_K!O9&2@)U%X!.`02`3DH$@^P(5O]U".C\____@\00QT90````
-M`(UV``^W1DCWV"%&4(UV`(-^!`!U&O9&2@1T%.C\____B49`@^P,5NC\____
-M@\00C67T6UY?R<-5B>575E.#[`R+?0B^`````(UV`(T$=HT$P(V<QV`B``"#
-M>T``="&#>P0`=1N#[`A35^C\____@\00]D,!!'0(QT,X`````)!&@_X/?L:-
-M9?1;7E_)PXGV58GE5U93@>PH`@``BWT,BD40B(7G_?__5^C\____@\00@#\(
-M=1*#[`A7_W4(Z/S___^#Q!"-=@"^`````(!_/``/AL4```"0@WRW5``/A*T`
-M``"+1+=4@#@#=B"#[`0/MH7G_?__4/]TMU3_=0CH_/___X/$$.F%````D(M<
-MMU3&0P,`QT,$`````,=#4`````"`8P'^QT,X`````("]Y_W__P!U#H`_!G4)
-M@W\$`'0RC78`@^P$:``"``!J`(V5Z/W__U+H_/___XV%Z/W__U!J,&H`C4,\
-M4.C\____@\0@ZQ&*5P&#X@&*0P&#X/X)T(A#`8/L#%/H_/___X/$$$:)\CA7
-M/`^'//___X/L!&C8````:@!7Z/S___^+50B+@EPB``")1PB)NEPB``#'1T``
-M````@\00C67T6UY?R<-5B>575E.![!P"``"+50R+?1"+312+`HM8!(F=Y/W_
-M_XM:((M3%(F5X/W__P^V0`.)A=S]__^-E>C]__^#O>#]__\`=`QF#[9#$(/@
-M`3G(=2:)E>#]__^#>Q@`=!!14E/_=0C_4QB#Q!"%P'4*N`````#IE@````^W
-M0RS!X`D/MG,HB?:+E>#]__^+&KD```$`9H-Z!`!T!`^W2@2)PCG(=@*)RCNU
-MW/W__W409HE7!&;'1P8``(D?@\<(D"G1`=,IT'4A1HN5Y/W__P^V0CPYQG4%
-MO@````"+E>3]__\/MT)(P>`)A<EULXN=X/W__V:!>P8`@'0+@\,(B9W@_?__
-MZX)FQT?^`("X`0```(UE]%M>7\G#C78`58GE5U93BT4(BTT,BW@$BW$DBE`#
-M9HM9,#A1*'4*#[=!+@'&ZPV)]CA1*'8&#[='2`'&.%$H=01F`UDL.%$I=0=F
-M`UDJC78`@'DT`'0..%$H<QTX42EW$NL6B?8X42AS!&8#7T@X42EV!F8#7TB)
-M]HM%$&:)6`B)<`1;7E_)PY!5B>575E.#[`B+?0QFBW<(9L=%\@``BT4(#[9(
-M/HM?!-/K9L=',```QD<T`0^V2#R)V+H`````]_&)1>R+50@/MDH^T^")1R0/
-MMDH\B=BZ`````/?QB%<HB-&+50AFBT)(2&8C1P1FB4<NBUT(9HM32&8IPF8Y
-M\G(+9HEW++X`````ZU1FB5<L9BG69L=%\@$`N@$```")]HG0T^!F"4<R08M%
-M"#A(/'4?L0"`?S0`=`?&1S0`ZQ&09HM',(M="&8#0TAFB4<PD(M%"&8Y<$AS
-M!V8K<$CKP9"X`0```-/@9@E',HA/*6:)=RH/MT7R@\0(6UY?R<.)]E6)Y593
-MBW4(BU4,BUH@BP(/MD@#N/[____3P&8A0S*`>A$!=`:*0A&(0Q&#[`A25NC\
-M____@\009H-[,@!U&H![$0!U!,9#$0&#[`13_W,<5NC\____@\00C67X6U[)
-MPU6)Y5=64X/L#(M]#(L'B47P]D`!!'49QD<1`H/L!%?_=QS_=0CH_/___^G)
-M````D%?_=?#H;_[__X/$"&:#?S(`=1G&1Q$"@^P$5_]W'/]U".C\____Z9T`
-M``"0O@````"+5?"`>CP`#X2*````B?8/MT<RB?'3^*@!=&R#[`S_=0CH_/__
-M_XG#BT7PBT2P5(E%[(D#B7L@BE<0@^("BD,0@^#]"="(0Q"*5Q"#X@2#X/L)
-MT(A#$(I'"HA#"E-7_W7LZ&']___'0QP`````QT,8`````(/$%%/_=0B+5>S_
-M4C2#Q!"-=@!&BTWP#[9!/#GP#X]X____C67T6UY?R<-5B>6#[`B+50R+2@2*
-M00'`Z`*#\`&#X`&`8@'[@&$!^_Y)/8!)2@&#>3@`=!.%P'4/@^P(4?]U"/]1
-M.(/$$(GVR<.)]E6)Y593BUT0BW44BT4,BU`@BTH4A<ET#&8/MD(0@^`!.?!U
-M)(-Z&`!T%5934O]U"/]2&(/$$+H!````A<!U)[H`````ZR")]HL!BU$$B0.)
-M4P2#PPB-00:#P0AF@S@`>>>Z`0```(G0C67X6U[)PY!5B>564XMU"`^V!H/H
-M!(/X`7=!NP````"`?CP`="^)]H-\GE0`=!.#[`S_=)Y4Z,W___^#Q!"%P'4*
-MN`````#K'(UV`$,/MD8\.=A_T[@!````ZPF*1@'`Z`*#X`&-9?A;7LG#58GE
-M5U93@^P,BW4,BUX@BSN+!HE%\(!^$0$/A-````#V0Q`"=':`>Q(`#X7`````
-M]D=*`@^%M@```,9#$@&`>`,!&<"#X`2+1#A4B47PA<!T0U#H1/___X/$!(7`
-M=#:#[`1J,&H`C48D4.C\____BT7P#[9(`[@!````T^!FB4,RBT7PB0:#Q`A6
-M_W4(_U`TZ<<```"+!HE%\.M4]D,0!'1._W7PZ/+^__^#Q`2%P'0B@^P$:C!J
-M`(U&)%#H_/___X/$"%;_=0B+1?#_4#3IB0```(![$0%T'0^W4S*+1?`/MD@#
-MN`$```#3X#G"=0>0BD81B$,1@^P(5O]U".C\____BT7P#[9(`[C^____T\!F
-M(4,R@\009H-[,@!U/H![$0!U!,9#$0&#[`13_W,<_W4(Z/S___]F_T\6@\00
-M9H-_%@!U%XM''(7`=!"#[`C_=R#_=0C_T(/$$(GVC67T6UY?R<-5B>53@^P$
-MBU4,BUT0BTT4BT(@A<ET&8M`#(D#9HM"",'@"6:)0P1FQT,&`(#K19"#>!0`
-M=";V0!`!=""+2!20BP&+402)`XE3!(/#"(U!!H/!"&:#.`!YY^L9D+H`````
-M@W@8`'0245-0_W4(_U`8B<+K!;H!````B="+7?S)PU6)Y5=64X/L#(M]"(MU
-M#(M>((L&#[9(`[C^____T\!F(4,R@'X1`70&BD81B$,1@^P(5E?H_/___X/$
-M$&:#>S(`=4F`>Q$`=1?&0Q$!BPN+45`[5@1U"0^W1@@!T(E!4(/L!%/_<QQ7
-MZ/S___^+`V;'0!0``(/$#(L#@\`84&@`````5^C\____@\00C67T6UY?R<-5
-MB>575E.#[`R+?0B+=0R+7B"`?A$!=`B*1A&(0Q'K7(!^"B!U/L9&$0"+`XM`
-M6(D&@^P$:C!J`(U&)%#H_/___\9&$@#&1@HPBD80@^#]@\@$B$80@\0(BP96
-M5_]0-.M.C78`QD,1`8L+BU%0.U8$=0H/MT8(`=")05"0@^P(5E?H_/___X/$
-M#%/_<QQ7Z/S___^+`V;'0!0``(/$#(L#@\`84&@`````5^C\____C67T6UY?
-MR<.058GE5U93@^P,BWT0BTT4BU4,BT(@A<ET0XM0#(D7BTT,9HM!",'@"6:)
-M1P1FQT<&`("+`8!X`P`/A/(```"-@@```0!F@W\$`'0'#[='!(T$`HD'Z=<`
-M``"-=@")^XM5#`^W<@C!Y@F#>!0`=";V0!`!=""+2!20BP&+402)`XE3!(/#
-M"(U!!H/!"&:#.`!YY^LUD+H`````@W@8``^$D@```%%74/]U"/]0&(/$$+H`
-M````A<!T?>L.9HEQ!&;'008`@.L]B?:)^8GVN@```0!F@WD$`'0$#[=1!(M=
-M#(L#@'@#`'01.?)V$0$QB=!F*?!FB4$$ZPLY\G.^@\$(*=9UR8M5#(L"@'@#
-M`'0B.<]T'HGVBP&+402)!XE7!(/'"(U!!H/!"&:#.`!YYXUV`+H!````B="-
-M9?1;7E_)PY!5B>575E.#[`R+?0B+=0R+7B"`?A$!=`B*1A&(0Q'K<(L&@'@#
-M`'4LQD81`(L#BT!8B0:#[`1J,&H`C48D4.C\____QD82`(/$"(L&5E?_4#3K
-M<)"#[`0/MT8(P>`)4`-##%#_<PSH_/___X/$$(7`=`;&0Q$,ZQC&0Q$!BPN+
-M45`[5@1U"@^W1@@!T(E!4)"#[`A65^C\____@\0,4_]S'%?H_/___XL#9L=`
-M%```@\0,BP.#P!A0:`````!7Z/S___^-9?1;7E_)PY!5B>575E.#[`R+?0B+
-M70R+,\=&'`````#V1DH!#X5:`0``#[9#"H/X`@^$^0```(/X`G\0@_@!#X27
-M````Z3H!``")]H/X`P^%+P$``(M#!(E&$&:+0PAFB484@^P$#[=#",'@"5!J
-M`/]S#.C\____9L=#,@,`QT7P`````(/$$(/L#%?H_/___XG"QD`*,(M#!(E"
-M!&:+0PAFB4((@$H0!(E:(,="'`````#'0A@`````BTWPBT2.5(D"@\0(4E?_
-M4#2#Q!#_1?"#??`!?K'IO````(M#!(E&$&:+0PAFB484@^P,5^C\____B<+&
-M0`H@BT,$B4($9HM#"&:)0@B`2A`"B5H@QT(<`````,="&`````"+1E2)`H/$
-M"%)7_U`T@\00ZVJ)]HM#!(E&$&:+0PAFB484@^P,5^C\____B<+&0`H@BT,$
-MB4($9HM#"&:)0@B`2A`"B5H@QT(<`````,="&`````"+1E2)`H/$"%)7_U`T
-M@\00ZQ:)]L9#$0:#[`13_W,<5^C\____@\00@^P$C4884&@`````5^C\____
-MC67T6UY?R<.)]E6)Y5=64X/L'(M]#(LW]D8!!'48QD<1`H/L!%?_=QS_=0CH
-M_/___^E\`0``]D<0('0JQT8<G!,``(E^(&:#?A8`#X5A`0``@^P(5_]U".@!
-M_O__@\00Z4T!``"0@WX<`'4B9H-^%`!T-P^W1A0#1A`[1P1V*P^W1P@#1P0Y
-M1A!S'XUV`,='*`````"#[`A7C4884.C\____Z0L!``"-=@!F_T86]D9*`W5Z
-M]D<0`G1TBU94BTY8@#H#=5F`.0-U5(M'!(G#*UE4B5WDBUI8B5WHBTE8*T)4
-M>0+WV(-]Y`!Y`_==Y#M%Y'T4QD7S`(7)=3>#?>@%=C'&1?,!ZRO&1?,`@WWH
-M`'4%@_D%=QS&1?,!ZQ:)]H!^3@`/E$7SBD7SB$9.ZP3&1?,`9L=',@``LP`/
-MML.#?(94`'1FBT2&5/9``01T7/9'$`1U!3A=\W51@^P,_W4(Z/S___^)1>R#
-MQ`QJ)%=0Z/S___\/MLNX`0```-/@9@E',HM5[(EZ(,="'`````#'0A@`````
-MBT2.5(D"@\0(4O]U"/]0-(/$$(GV0X#[`7:*B?:-9?1;7E_)PU6)Y593BTT(
-MBW4,BUX$#[96`X!F`?N`2TH!QT-0`````/Y+/8![/0!U!H!C`?OK&(I#2J@"
-M=!&#X-6(0TJ%TG4'@&,!^XUV`/9#`01U&H-[.``/A,P```"#[`A34?]3.(/$
-M$.F\````A=)U%(M35,9"`P&+0UC&0`,`B4-4B5-8@WL$`'0)BT,$]D`!!'1M
-MBT-4@#@#=66#[`A34>C\____B<*#Q!"%P'12Q@`#QD`#`8E8!*$,````B4(T
-MH1@```")0CCV0P$0=`J`2@$0BT),B4(,QT8$`````(E36(I#2H/@_H/("HA#
-M2OY#/8/L"%)J!^C\____@\00D(-[!`!T"XGVBUL$@WL$`'7WBT-`B4-$Z/S_
-M__^)0T"#[`Q3Z/S___^-9?A;7LG#D%6)Y5=64X'L+`(``(M%#(M-%(L0B97D
-M_?__BT`@B874_?__BU@4QX7@_?__$0```(V5Z/W__X7;=`QF#[9`$(/@`3G(
-M=2J)TXNUU/W__X-^&`!T$%%25O]U"/]6&(/$$(7`=0RX`````.D``0``B?:+
-MO=3]__^`?RG_#X33````#[=/+,'A";X```$`9H-[!`!T!`^W<P0Y\79(D(N5
-MY/W__XI"`XN]U/W__SI'*'44BP.+4P2+?1")!XE7!(/'"(E]$)`I\8/#"+X`
-M``$`9H-[!`!T!`^W<P3_C>#]__\Y\7>YBY7D_?__BD(#B[W4_?__.D<H=1F+
-M`XM5$(D"9HE*!&;'0@8`@+@!````ZU^0.?%S-HG(`P.+?1")!XGP9BG(9HE'
-M!&:!>P8`@'4-9L='!@"`N`$```#K,XM%$&;'0`8``(/`"(E%$(/#"/^-X/W_
-M_X/L!(N%X/W__\'@`U!3_W40Z/S___^X`0```(UE]%M>7\G#B?95B>6+50R+
-M31"+10B*0`,Z0BAU$&:+0BQFB4$(BT(DB4$$ZP]FBT(J9HE!",=!!`````#)
-MPXUV`%6)Y5=64X/L"(M]"(MU#(M>!&:+1@AFB47RQT7L`````+D`````@'\\
-M`'1\BU2/5#E:#'9GB5XDB$XHN`$```#3X&:+?C()QV:)?C(/MT7R`=@[0@QV
-M-<=%[`$```"-00&(1BE!BT7LT^")P8GX"<AFB48RBT(,9BG89HE&+&:+5?)F
-M*<)FB58JZQV0QD8I_V:+1?)FB48LZPZ)]BM:#$$/MD<\.<AWA(M%[(/$"%M>
-M7\G#D%6)Y593BW4(BU4,BUH@BP(/MD@#N/[____3P&8A0S*`>A$!=`:*0A&(
-M0Q&#[`A25NC\____@\009H-[,@!U&H![$0!U!,9#$0&#[`13_W,<5NC\____
-M@\00C67X6U[)PU6)Y5=64X/L#(M]#(L'B47P]D`!!'49QD<1`H/L!%?_=QS_
-M=0CH_/___^G)````D%?_=?#HL_[__X/$"&:#?S(`=1G&1Q$"@^P$5_]W'/]U
-M".C\____Z9T```"0O@````"+5?"`>CP`#X2*````B?8/MT<RB?'3^*@!=&R#
-M[`S_=0CH_/___XG#BT7PBT2P5(E%[(D#B7L@BE<0@^("BD,0@^#]"="(0Q"*
-M5Q"#X@2#X/L)T(A#$(I'"HA#"E-7_W7LZ.W]___'0QP`````QT,8`````(/$
-M%%/_=0B+5>S_4C2#Q!"-=@!&BTWP#[9!/#GP#X]X____C67T6UY?R<-5B>6#
-M[`B+10R+4`2`8`'[@&(!^_Y*/8!*2@&#>C@`=`^#[`A2_W4(_U(X@\00B?;)
-MPXGV58GE4XM="(M-#(N4B_PO``"%TG0)BP*)A(O\+P``B=!;R<.058GE4XM=
-M"(M-#(M5$(N$D_PO``")`8F,D_PO``!;R<-5B>575E.#[`R+10R[`(```#T`
-M0```=V%FNP!`/0`@``!W5F:[`"`]`!```'=+9KL`$#T`"```=T!FNP`(/0`$
-M``!W-6:[``0]``(``'<J9KL``CT``0``=Q]FNP`!/8````!W%&:[@`"#^$!W
-M"X/X(1G;@^/@@\-`BT40#Z_#!?\/``#!Z`R)1?#'1>P`````N`````"!^P`0
-M```/A]8```#_3?"#??#_#X3&````D(/L#/]U".C\____B<;_1>R_`````(/$
-M$+@`$```N@````#W\X/X``^&BP```(UV`+@*````@?L`0```=U>P"8'[`"``
-M`'=-L`B!^P`0``!W0[`'@?L`"```=SFP!H'[``0``'<OL`6!^P`"``!W);`$
-M@?L``0``=QNP`X'[@````'<1L`*#^T!W"H/[(`^7P`^VP)!05O]U".B2_O__
-M`=Z#Q`Q'N``0``"Z`````/?S.?@/AWC_____3?"#??#_#X4[____BT7LC67T
-M6UY?R<-5B>564XMU"(M=#+@`````.9XH,```<DIJ`E;H'/[__XG!@\0(A<!T
-M-XD82X/[_W0OC78`N@````"#OB0P````=!2+EB0P``"+`HF&)#```/^.*#``
-M`(E4F01+@_O_==2)R(UE^%M>R<.-=@!5B>564XM="(MU#(L.28/Y_W0?D(M4
-MC@2+@R0P``")`HF3)#```/^#*#```$F#^?]UXFH"5E/HN?W__XUE^%M>R<.)
-M]E6)Y593BW4(BQY+@_O_=!R#[`1H`!```&H`_W2>!.C\____@\002X/[_W7D
-MC67X6U[)PY!5B>53BUT(BPM)@_G_=">+1(L$N@````"#.`!T![@`````ZQ="
-M@\`$@?K_`P``=NA)@_G_==FX`0```%O)PXGV58GE@^P,:A!J`/]U".C\____
-MR<-5B>6+30R#>0P`=`F+40R+00B)0@B+40B+00R)`L=!"`````!J`%'_=0CH
-M^?S__\G#C78`58GE4XM5"(M-#(U:,(M",(E!#(7`=`F+4C"-00R)0@B)60B)
-M"UO)PU6)Y5=64XM]$(MU%(M%#(M8,(7;=!F)]CDS<PPY>P1V![@`````ZR.+
-M6PR%VW7I:@#_=0CH;_S__XG#B3B)<`10_W4,Z(____^)V(UE]%M>7\G#D%6)
-MY5.+30B*42D/MMJ-!-T`````*=B-7($L0HA1*8D+QD,%`,9#!@#&0P<`B=A;
-MR<.-=@!5B>575E.+?0B+=0R[``````^V5B:-0OW1^`'"@_H`?B.-=@#_M)ZL
-M!P``5^@?_O__@\0(0P^V5B:-0OW1^`'".=I_X&H'5E?H]_O__XUE]%M>7\G#
-MC78`58GE5U93@^P<BWT0BD4,B$7SBU449HE5\(M%"(N8*#```,'C`P^WR@^V
-M5?.-0OW1^`'"#Z_*.<L/@]H````/ME7SB57DB=")5>`/MU7PC4#]T?@#1>2)
-MTP^OV)"+10@%Y"\``(M5"#F"Y"\```^$PP```(NRY"\``(M6!(L&B5`$B0*)
-M-HEV!(-^$`!T'H-^%`!T"8M6%(M&$(E"$(M6$(M&%(D"QT80`````(M%\&8Y
-M1B1U0XI5\SA6)G4[B3:)=@2)?B"_`````(-]Y`!^(8M=X)"#[`R)^,'@!(V$
-M,%0(``!0Z,?]__^#Q!!'.?M_XXGPZ1,!``!6_W4(Z*?^__^#Q`B+50B+@B@P
-M``#!X`,YV`^"1/___VH'_W4(Z*;Z__^)QH/$"+@`````A?8/A-<```#K"K@`
-M````Z<L```")-HEV!(E^((M%\&:)1B2*5?.(5B;'1A@`````OP`````/ME7S
-MC4+]T?@!PH/Z``^.E````(M%\&;!Z`,/M\")1>@/ME7SC4+]T?@!PHE5[/]U
-MZ/]U".CQ^___B82^K`<``(/$"(7`=3-/@___=!F0_[2^K`<``/]U".@Y_/__
-M@\0(3X/__W7H:@=6_W4(Z!GZ__^X`````.LQB?:#[`R)^\'C!`'SC8/4!P``
-M4.B^_/__@<-4"```B1PDZ+#\__^#Q!!'.7WL?X>)\(UE]%M>7\G#D%6)Y5=6
-M4X/L#(M]$(M%%&:)1?*+50P/MDH^B?C3Z"7_`P``BU(LC1R"BS.%]G0@D#E^
-M('43BU8$BP:)4`2)`HDVB78$B?#K:XMV%(7V=>$/MT7R4%>+50P/MD(\4/]U
-M".B'_?__B<:#Q!"%P'1#BTT,B4@<BP.)1A2%P'0(BQ.-1A2)0A")7A"),XM%
-M#(I8/(A>)@^V2#Z)^-/HBTT,#[91/(G1N@````#W\2C32XA>)XGPC67T6UY?
-MR<.058GE5U93@>S,````BT4,BE`0B-#0Z(/P`8G!@^$!B8U4____BT4,@W@4
-M`'0%]L(!=""-E5C___^)E5#___]J`5+_=0S_=0B+30S_41B#Q!#K#(M%#(M`
-M%(F%4/___\>%./___P```0"+E5#___]F@WH$`'0*#[=*!(F-./___\>%0/__
-M_P````#'A4S___\`````BT4,@'A$``^$W`$``(N53/___XM-#(M4D3")E43_
-M__^*BBP)``"(C4O___\XBBT)```/@I@!``"*A4O___^+E43___\X0B</A&4!
-M```/ML")T6:+E((,"0``9HN$@0X)``!FB84^____B=!FP>@##[?`B84T____
-M@^('9HF5//___P^WPHG"P>()N`@```!F*X4\____9HF%//___V:+A3[___]F
-M.84\____=@=FB84\____#[>%//___XG&P>8)#[:%2____XN-1/___XN$@:P'
-M``")UXN--/___P-\B`20BX4X____.85`____=3*#A5#___\(QX4X____```!
-M`(N54/___V:#>@0`=`H/MTH$B8TX____QX5`____`````(N=./___RN=0/__
-M_SGS=@*)\X.]5/___P!T(8/L!%.+A4#___^+E5#___\#`E!7Z/S___^#Q!#K
-M'XUV`(/L!%-7BX5`____BXU0____`P%0Z/S___^#Q!`!G4#___\IWG0'`=_I
-M5____XN%//___V8IA3[___]T&?^%-/___[H`````9L>%//___P@`Z>O^___^
-MA4O___^*E4O___^+C43___\XD2T)```/@VC^____A4S___^+50P/MD)$.X5,
-M____#X\D_O__@^P$:@#_=0S_=0C_51"-9?1;7E_)PXGV58GE5U93@^P,@WT0
-M`'0'BT4,QD`1"\=%\`````"+50R`>D0`#X3!````BT4(!>PO``")1>R+50B!
-MPN0O``")5>B-=@"+1?"+50R+7((PQX,$"0```````(G?L0"`>R8`=D&)]@^V
-MP<'@!`'XC9#4!P``O@````"#N-0'````=12#>@0`=0Z#>@@`=0B#>@P`=`>)
-M]KX!````A?9U(4$X3R9WP;@`````A<!T'(M5[(M"!(E:!(D3B4,$B1CK&K@!
-M````Z^.-=@"+5>B+0@2)6@2)$XE#!(D8_T7PBU4,#[9"1#M%\`^/6?___X/L
-M"/]U#/]U".AC/P``C67T6UY?R<.-=@!5B>575E.#[!R+70R+LP0)``"+10C_
-MB"PP``"-0PB+2`2+4PB)2@2)$8E#"(E`!(7V#X11`@``]D80(`^$^P```(L^
-M#[=#)`-#((E%[&:+4R1FB57JQX,$"0```````(M%"`7D+P``BU`$B5@$B0.)
-M4P2)&H"[+@D```%U1(!^"@)U-0^V0R?_M(.L!P``Z'7W__^#Q`2%P'4>QH,N
-M"0``#(!/2@H/MT=(]]@C0R`Y1U!V!8E'4(GV@+LN"0```70:BH,N"0``B$81
-M@^P(5O]U".B"/@``Z5D#```/MT=(BU8$0@^OPCM%['8K#[=%ZE#_=>Q7_W4(
-MZ+#Z__^)L`0)``")1C"#Q`A0_W4(Z*L/``#I'@,```^W1T@#1U`[1>QU!HM%
-M[(E'4(/L"%;_=0CH)#X``.G[`@``C78`BD9%0(A&13I&1`^%=`(``/9&$`0/
-MA,H```#&1?,`@'Y$``^&J````(M5"('"Y"\``(E5X(M%"`7L+P``B47<D`^V
-M1?.+7(8PQX,$"0```````("[+@D```%U38E=Y+\`````@'LF`'8LC78`@^P,
-MB?H/ML+!X`2+5>2-A!#4!P``4.B%]O__@\001XGXBU7D.$(F=]>+5>"+0@2)
-M6@2)$XE#!(D8ZQJ0BH,N"0``B$81BU7<BT($B5H$B1.)0P2)&/Y%\XI%\SA&
-M1`^'</___X/L"%;_=0CH0#T``(/$$.F@`0``QD7S`(!^1`!V)XGV#[9%\XM<
-MAC"`NRX)```!=`F*@RX)``"(1A'^1?.*5?,X5D1WVX!^$0!U&8/L!&BX)0``
-M5O]U".@`^O__@\00Z5`!``"#[`1J`%;_=0CH?OS__X/$$.DZ`0``B?:`NRX)
-M```!=7^)W[X`````@'LF`'8EB?:#[`R)\@^VPL'@!(V$.-0'``!0Z)#U__^#
-MQ!!&B?`X1R9WW8.["`D```!T*HN#"`D``(F#!`D``,>#"`D```````"#[`A3
-M_W4(Z,X-``"#Q!#IR@```(M%"`7D+P``BU`$B5@$B0.)4P2)&NM7C78`BT4(
-M!>PO``"+4`2)6`2)`XE3!(D:@[L("0```'0VBY,("0``BH,N"0``B$(1@^P$
-M_[,("0``:!1F``#_=0CH_/___\>#"`D```````#IT@```(GV_W,8_W4(Z.WT
-M___'0Q@`````BT,<@\0(@W@8`'09@^P$@\`84&@`````_W4(Z/S___^#Q!#K
-M)8M5"(.Z-#````!T&8/L!(G0!30P``!0:`````!2Z/S___^#Q!"+10B#N#`P
-M````=&B`NRX)```!=5^+0QR#>"0`=#V#[`Q0Z-TY``"#Q!"%P'4M@^P$BT,<
-M_W`HBT,<_W`D_W4(Z/S___^+0QS'0"0`````BU4(_XHP,```@\00BT4(@[@P
-M,````'0-@^P,4.C\____@\00D(UE]%M>7\G#58GE@^P(BT4,BP"`>"H`=!O&
-M0"H`@^P$4&@4-0``_W4(Z/S___^#Q!"-=@#)PXGV58GE5U93@^P,BU4,BWT0
-MBT(@BP@/MD`)BX2!K`<``(E%\(M"!"M!(,'@"0^W<@C!Y@F)PH'B_P\``,'H
-M#(E%[+@`$```B<,ITSGS=@*)\X-]%`!T#XM%[(M-\`-4@03K&XUV`(/L#(M%
-M[(M-\`-4@012Z/S___^#Q!")PHD79HE?!#GS=!5FQT<&``"#QPC_1>PIWKH`
-M````ZZ5FQT<&`("X`0```(UE]%M>7\G#B?95B>575E.+50B*0@H"0@N(0@J-
-M6@R^`0```.L3@'H*`'D*N`````#I\@```/Y""@^V2@J#^1]W$(GPT^"%0@P/
-ME<`/ML#K39"#^3]W$X/I((GPT^"%0P0/E<`/ML#K-9"#^5]W$X/I0(GPT^"%
-M0P@/E<`/ML#K'9"X`````(/Y?W<2@^E@B?#3X(5##`^5P`^VP(GVA<!TA,9"
-M"P&->@P/MEH*O@$```#K!8GV_D(+#[9""XT,`X/Y'W<1B?#3X(5"#`^5P`^V
-MP.M.B?:#^3]W$X/I((GPT^"%1P0/E<`/ML#K-9"#^5]W$H/I0(GPT^"%1P@/
-ME<`/ML#K';@`````@_E_=Q.#Z6")\-/@A4<,#Y7`#[;`C78`A<!UD+`!6UY?
-MR<.058GE5U93@^P4BWT(BU4,BUH@BS.*0A&(0P925^C\____@\00@'L&`75F
-M4^BL_O__@\0$A<!T$<9#!@"#[`A35^B/````ZU>0@'L$`75"BD,(.$8G=#HX
-M0PEU-0^VR(G(P>`$C8PP5`@``(US#(L!"T,,B0&+000+1@2)002+00@+1@B)
-M00B+00P+1@R)00R0QD,%`H/L"%-7Z%[]__^-9?1;7E_)PXGV58GE4X/L!(M=
-M#,9#"P#&0PH`4^@<_O__@^P$4_]U".@(````BUW\R<.-=@!5B>575E.#[!B+
-M70R+,XM6'`^V0PB+?()4_W4(Z/S___^)PHDX@\00@'L$`74*@$@0`L9`"B#K
-M"(!($`3&0`HP#[9#"@-&((E"!&8/MD,+9HE"",="&"@K``")6B#'0AS\+```
-M@^P(4O]U"/]7-(UE]%M>7\G#B?95B>575E.#[`B+?0R^`````,=%\`````"+
-M10B)1>SK$X-]\']V"HGPZ4<!``"-=@#_1?"+5?"#^A]W%[@!````BDWPT^"+
-M50B%`@^5P`^VP.M:@_H_=QB-2N"X`0```-/@BU7LA4($#Y7`#[;`ZSV#^E]W
-M&(U*P+@!````T^"+5>R%0@@/E<`/ML#K(+@`````@_I_=Q:-2J"P`=/@BU7L
-MA4(,#Y7`#[;`C78`A<`/A&S___^[`0```(M5".L#B?9#BTWP`=F#^1]W$;@!
-M````T^"%`@^5P`^VP.M4@_D_=Q>#Z2"X`0```-/@A4($#Y7`#[;`ZSJ)]H/Y
-M7W<7@^E`N`$```#3X(5""`^5P`^VP.L>B?:X`````(/Y?W<2@^E@L`'3X(5"
-M#`^5P`^VP(GVA<!UC(M5\`%=\(GVB=#!Z`.(!+>(T(/@!XA$MP&Q""C!B$RW
-M`@^VP3G8<P<IPP'"1NO9B%RW`D:#??!_#X;!_O__B?"#Q`A;7E_)PU6)Y5=6
-M4X'L3`$``(M%#(LPBU@(@'L5``^$.@$``(-[$`!U"(E#$.GF`0``QD,5`(V%
-MZ/[__U!3Z$?^__^)A<S^__\/MD,4BX2&K`<``(F%W/[__XM#$`^V0`R+A(:L
-M!P``B878_O__BU4,#[9"#(N$AJP'``")A=3^__^[`````(/$"#N=S/[__P^-
-M<@$```^VA)WI_O__B<'!X0D/MH2=ZO[__XG&P>8)BH2=Z/[__XB%T_[__P^V
-MT(G(B[W8_O__`T27!(F%X/[__XN%U/[__XM\D`0!SXF]M/[__XF]Y/[__XN%
-MW/[__XM\D`0!SSF]X/[__W4D@^P$5O^UM/[__XG(B[7<_O__`T26!%#H_/__
-M_X/$$.LJC78`5O^UY/[___^UX/[__P^VA=/^__^+O=S^__\#3(<$4>C\____
-M@\000SN=S/[__P^,0/___^FM````C78`C87H_O__4%/H'_W__XF%S/[__P^V
-M0Q2+A(:L!P``B87<_O__BU4,#[9"#(N$AJP'``")A=C^__^[`````(/$"#N=
-MS/[__WUB#[:$G>G^__^)P<'A"0^VA)WJ_O__B<;!Y@D/MI2=Z/[__XG(B[W<
-M_O__`T27!(F%X/[__XG(B[W8_O__`T27!(F%Y/[__X/L!%90_[7@_O__Z/S_
-M__^#Q!!#.YW,_O__?)Z#[`1J`/]U#/]U".AJ`@``C67T6UY?R<.)]E6)Y5=6
-M4X'L+`$``(M%#(L8C87H_O__4(M%#(/`"%#H1/S__XF%V/[__XM5#`^V0AB+
-MA(.L!P``B87<_O__#[9"&8N$@ZP'``")A=3^__^^`````(/$"#NUV/[__WU=
-MD`^VA+7I_O__P>`)#[:,M>K^___!X0D/MIRUZ/[__XG"B[W<_O__`U2?!(F5
-MX/[__XN5U/[__P-$F@2)A>3^__^#[`114/^UX/[__^C\____@\001CNUV/[_
-M_WRD@^P$:@#_=0S_=0CHE`$``(UE]%M>7\G#58GE5U93@>Q\`0``BT4,BS"+
-M6`B-A>C^__]04^AS^___B864_O__#[9#%(N$AJP'``")A:3^__^Q`(/$"(M5
-M#(!Z%`!V)(I:%(UV``^VP8M]#`^V5`<,BY26K`<``(F4A<C^__]!.,MWXL>%
-MF/[__P````"+A93^__\YA9C^__\/C>X```")]HN5F/[__P^VA)7I_O__B<?!
-MYPD/MH25ZO[__\'@"8F%H/[__XJ,E>C^__^(C9_^__^Q`(M=#(![%`!V,0^V
-MM9_^__^*0Q2(A8?^__\/ML&+E(7(_O__BURR!(T4'XF4A:C^__]!.(V'_O__
-M=]\/MI6?_O__B?B+C:3^__\#1)$$.86H_O__=2"#[`3_M:#^____M:S^__^)
-M^`-$D010Z/S___^#Q!#K+/^UH/[___^UK/[___^UJ/[__P^VA9_^__^+G:3^
-M__\#?(,$5^C\____@\00_X68_O__B[V4_O__.;V8_O__#XP4____@^P$:@#_
-M=0S_=0CH"````(UE]%M>7\G#58GE5U93@^P4BWT(BUT,BW40QD,%`H/^`1G`
-M@^#U@\`,B$,&4U?HC?;__X/$$(![!`-U,(M#"(M0$(72=";'0!``````QD(%
-M`H/^`1G`@^#U@\`,B$(&@^P(4E?H5_;__X/$$(UE]%M>7\G#58GE5E.+70B+
-M=0P/MDX'A<ET29`/MI1+O`8``(T$U0`````IT(U$@RR`>`4"=`FX`````.LK
-MB?:`>`8!=!+&1@4"BD`&B$8&N`````#K$I`/MHQ+O08``(7)=;BX`0```%M>
-MR<.-=@!5B>575E.#[!R+?0S&1RH`@+\O"0```'1[O@````"-7RR`?RD`=$F0
-M@'L%`74V@'L$`W4EBT,(@'@5`'0<@W@0`'06QT`0`````,9#!0**ARX)``"(
-M0P;K"\9'*@'I]P$``(GV1H/#'`^V1RDY\'^X@^P(5_]U".@L\?__Z=@!``"*
-M0P:(ARX)``#&AR\)```!ZX:0QT7P`````,=%[`$```"^`````(U?+(!_*0`/
-MA'P!``"`>P4`#X66````4U?HT_[__X/$"(7`='S&0P4!BT4(B47HB=H/MD,$
-M@_@&=V?_)(4`````@^P(4_]UZ.B<]___@\00ZT^#[`A3_W7HZ*OY__^#Q!#K
-M/H/L"%/_=>CHMOO__X/$$.LM@^P(4_]UZ.AY_/__@\00ZQS&1RL!QD(%`L9"
-M!@&#[`A2_W7HZ*#T__^#Q!"0@'L%`G4,_T7PC78`@'L%`G0.QT7L`````.FZ
-M````B?:`>P8!#X2N````@'\K``^$!?___XM''`^V4PB+1)!4]D`!!`^$B```
-M`,=%[`````#&0P4!QD,&`(M%"(E%Y(G:#[9#!(/X!G=O_R2%'````(/L"%/_
-M=>3HS/;__X/$$.M7@^P(4_]UY.C;^/__@\00ZT:#[`A3_W7DZ.;Z__^#Q!#K
-M-8/L"%/_=>3HJ?O__X/$$.LDQD<K`<9"!0+&0@8!@^P(4O]UY.C0\___@\00
-MZP?&0P8!C78`1H/#'`^V1RDY\`^/A/[__X-]\``/A5K^__^#?>P`=!7&ARX)
-M```!@^P(5_]U".A5[___ZP3&1RH!C67T6UY?R<.-=@!5B>575E.![&P!``"+
-M10R+6!R+N`0)``#&A;'^__\`A?]U,0^W0"2+30R+42`!T%!24_]U".C"Y___
-MBW4,B488@\00N/____^#?A@`#X09*P``B?:+10C_@"PP``"+10R#P`B+50B!
-MPO0O``"+2@2)0@2+=0R)5@B)2`2)`6:#>TP`=$#V0TH!=0B+0U`[1B!W)[X`
-M````#[=#3(G"J`%U#HUV`$:)T(GQT_BH`73UB?.+10R(6"CK+HM5#,9"*`CK
-M)8GV]D-*`G06BT-0BTT,.T$@=PN*02>(02CK"HUV`(M=#,9#*`B+=0S&1BD`
-MQH:\!@```,9&*P#&ABX)````QH8O"0```,>&"`D```````"%_P^$7Q,``/9'
-M$"`/A&D)```/MD<*@_@"#X2&!0``@_@"?PZ#^`$/A$0!``#I%2H``(/X`P^%
-M#"H``(/L#(V=V/[__U/H,>;__X/$$+\`````BT4,#[=P)+,`@_\?=U(/ML.-
-ME(78_O__B;VL_O__N2`````I^3GQ=@*)\8/Y('4(QP+_____ZQ*X`0```-/@
-M2(J-K/[__]/@"0*X(````"GX.?!S%(UT/N"_`````.L#@^\@0X#[`W:@@^P,
-MBUT,_[.L!P``Z#OE___&A;/^__\`@\00@'LF``^&9RD``(/L#`^VG;/^___!
-MXP0#70R-@]0'``!0Z'_E__^!PU0(``")'"3H<>7__X/$$/]U#.@JYO__@\0$
-MQD`$`HJ5L_[__XA0",9`"0"+E=C^__^)4`R+E=S^__^)4!"+E>#^__^)4!2+
-ME>3^__^)4!C^A;/^__^*C;/^__^+70PX2R8/AWO____IW2@``+@!````ZTV+
-M=0RQ`(!^)@!V/0^VP<'@!`'PC9#4!P``NP````"#N-0'````=1*#>@0`=0R#
-M>@@`=0:#>@P`=`6[`0```(7;=;=!.$XF=\.X`````(7`=!B+=0R)O@@)``#'
-MA@0)````````Z8T1``"#[`R-G=C^__]3Z)+D__^#Q!"_`````(M%#`^W<"2S
-M`(/_'W=2#[;#C92%V/[__XF]J/[__[D@````*?DY\78"B?&#^2!U",<"____
-M_^L2N`$```#3X$B*C:C^___3X`D"N"`````I^#GP<Q2-=#[@OP````#K`X/O
-M($.`^P-VH(M=#(![*`AU!HI#)XA#*(MU#(I>*(B>Z`@``,:&Z0@```&+A=C^
-M__^)AM0(``"+A=S^__^)AM@(``"+A>#^__^)AMP(``"+A>3^__^)AN`(``#'
-MAN0(````````5NB#Y/__@\0$QD`$`HA8"(A8"8N5V/[__XE0#(N5W/[__XE0
-M$(N5X/[__XE0%(N5Y/[__XE0&(G'@'XF`@^'5`$``(GS@</4"```5N@XY/__
-M@\0$QD`$!8E8",9`%`")A<#^__^+'_Z#O`8```^VL[P&``")PBG:@^HLP?H"
-MC032C03"C03"C03"B<'!X0\!R(T$PO?8B(1SO`8``(I'!XB$<[T&``")\(A'
-M!\:%L_[__P"+50R`>B8`#X;1)@``BHVS_O__BUT,.$LH#X2H````4^BQX___
-M@\0$QD`$`8J5L_[__XA0"(A0"8N5V/[__XE0#(N5W/[__XE0$(N5X/[__XE0
-M%(N5Y/[__XE0&(N-P/[__XI1%`^VRHJ=L_[__XNUP/[__XA<#@Q"B%84BQ[^
-M@[P&```/MK.\!@``*=B#Z"S!^`*-%,"-%-"-%-"-%-")T<'A#P'*C130]]J(
-ME'.\!@``B[W`_O__BD<'B(1SO08``(GPB$<'_H6S_O__BI6S_O__BTT,.%$F
-M#X<N____Z?HE``#&A;/^__\`BUT,@'LF``^&YB4``('#U`@``(F=I/[__XJ%
-ML_[__XM5##A"*`^$`@$``%+HNN+__X/$!,9`!`&*C;/^__^(2`B(2`F+E=C^
-M__^)4`R+E=S^__^)4!"+E>#^__^)4!2+E>3^__^)4!B)A<3^____=0SH=>+_
-M_X/$!,9`!`.+G:3^__^)6`B*E;/^__^(4`R)A<#^__^+&/Z#O`8```^VL[P&
-M``"+E<3^__\IVH/J+,'Z`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<[P&
-M``"+C<#^__^*00>(A'.]!@``B?.(60>+'_Z#O`8```^VL[P&``")RBG:@^HL
-MP?H"C032C03"C03"C03"B<'!X0\!R(T$PO?8B(1SO`8``(I'!XB$<[T&``")
-M\(A'!_Z%L_[__XJ5L_[__XM-##A1)@^'U/[__^FI)```N`$```#K4HMU#+$`
-M@'XF`'9"C78`#[;!P>`$`?"-D-0'``"[`````(.XU`<```!U%(-Z!`!U#H-Z
-M"`!U"(-Z#`!T!XGVNP$```"%VW6R03A.)G?!N`````"%P'08BUT,B;L("0``
-MQX,$"0```````.E4#0``@^P,C9W8_O__4^A9X/__@\00OP````"+10P/MW`D
-MLP"#_Q]W4@^VPXV4A=C^__^)O:#^__^Y(````"GY.?%V`HGQ@_D@=0C'`O__
-M___K$K@!````T^!(BHV@_O__T^`)`K@@````*?@Y\',4C70^X+\`````ZP.#
-M[R!#@/L#=J"+70R*0R>(@^@(``#&@^D(````BX78_O__B8/4"```BX7<_O__
-MB8/8"```BX7@_O__B8/<"```BX7D_O__B8/@"```QX/D"````````(![)@(/
-MAP`!``"+70R!P]0(``#_=0SH1.#__X/$!,9`!`6)6`C&0!0`B87`_O__QH6S
-M_O__`(MU#(!^)@`/AB0C``#_=0SH%.#__X/$!,9`!`&*E;/^__^(4`B(4`F+
-ME=C^__^)4`R+E=S^__^)4!"+E>#^__^)4!2+E>3^__^)4!B+C<#^__^*410/
-MMLJ*G;/^__^+M<#^__^(7`X,0HA6%(L>_H.\!@``#[:SO`8``"G8@^@LP?@"
-MC13`C130C130C130B='!X0\!RHT4T/?:B)1SO`8``(N]P/[__XI'!XB$<[T&
-M``")\(A'!_Z%L_[__XJ5L_[__XM-##A1)@^'/O___^E=(@``BW4,BEXG5NA)
-MW___@\0$QD`$`8A8"(A8"8N5V/[__XE0#(N5W/[__XE0$(N5X/[__XE0%(N5
-MY/[__XE0&(F%O/[__\:%L_[__P"`?B8`#X8)(@``B?>!Q]0(``"*A;/^__^+
-M50PX0B</A`8!``!2Z.'>__^#Q`3&0`0!BHVS_O__B$@(B$@)BY78_O__B5`,
-MBY7<_O__B5`0BY7@_O__B5`4BY7D_O__B5`8B87$_O___W4,Z)S>__^#Q`3&
-M0`0#B7@(BIVS_O__B%@,B87`_O__BQC^@[P&```/MK.\!@``BY7$_O__*=J#
-MZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``BY7`_O__BD('
-MB(1SO08``(GQB$H'BQK^@[P&```/MK.\!@``BY6\_O__*=J#ZBS!^@*-!-*-
-M!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``BY7`_O__BD('B(1SO08``(GQ
-MB$H'_H6S_O__BIVS_O__BW4,.%XF#X?0_O__Z<P@``"%_P^$Y`D``/9'$`(/
-MA-H)``"+10R*@"P)``"(A;/^__^+50PX@BT)```/@H<!``"*C;/^__^+70PX
-M2R</A%H!``"#[`P/MMF)V,'@!(VT!6C___]6Z*;<__^#Q!")M9S^__^+=0P/
-MMY2>#`D```^WO)X."0``O@````"0@_H?=U>)\0^VP8N-G/[__XT<@8F5F/[_
-M_[D@````*=$Y^78"B?F#^2!U"<<#_____^L3D+@!````T^!(BHV8_O__T^`)
-M`[@@````*=`Y^',6C7P7X+H`````ZP.#ZB!&B?.`^P-VF0^VG;/^__^)VHG8
-MP>`$BW4,C9PP5`@``(L+]]&)C=C^__^+0P3WT(F%W/[__XM#"/?0B87@_O__
-MBT,,]]")A>3^__^)UL'F!(V<->C^__^-E#5H____(PJ)"XM"!".%W/[__XE#
-M!(M""".%X/[__XE#"(M"#".%Y/[__XE##(J%L_[__XM5##A"*'4MN@````"#
-M.P!U$H-[!`!U#(-["`!U!H-[#`!T!;H!````A=)T",:%L?[__P&0_H6S_O__
-MBHVS_O__BUT,.(LM"0``#X-Y_O__@+VQ_O__``^$9`<``(/L#(V%V/[__U#H
-M+=O__\:%L_[__P"#Q!"+=0R`?B8`=G>)]HJ%L_[__XM5##A"*'13.$(G=$X/
-MMM#!X@0#50R-BM0'``"+A=C^__\+@M0'``")A=C^__^+A=S^__\+002)A=S^
-M__^+A>#^__\+00B)A>#^__^+A>3^__\+00R)A>3^___^A;/^__^*C;/^__^+
-M70PX2R9WBXMU#`^V?BC!YP2-G#WH_O__B[78_O__(S.)M<C^__^+C=S^__\C
-M2P2)C<S^__^+E>#^__\C4PB)E=#^__^+A>3^__\C0PR)A=3^___WUHFUV/[_
-M__?1B8W<_O__]]*)E>#^___WT(F%Y/[__R,SB;78_O__(TL$B8W<_O__(U,(
-MB97@_O__(T,,B87D_O___W4,Z-#:__^#Q`3&0`0`B86T_O__N`````"#O=C^
-M__\`=1N#O=S^__\`=1*#O>#^__\`=0F#O>3^__\`=`6X`0```(7`#X0\`@``
-MBWT,BD<HB(?H"```BX78_O__B8?4"```BX7<_O__B8?8"```BX7@_O__B8?<
-M"```BX7D_O__B8?@"```QH?I"````<>'Y`@```````#&A;/^__\`@'\F``^&
-MI@(``(J%L_[__XM5##A"*`^$KP$``#B"+`D``'<-.((M"0``<@4X0B=U1_]U
-M#.@`VO__@\0$QD`$`8J-L_[__XA("(A("8N5V/[__XE0#(N5W/[__XE0$(N5
-MX/[__XE0%(N5Y/[__XE0&(F%Q/[__^MW#[:-L_[__\'A!(V<#>C^__^+A=C^
-M__\+`XD#BX7<_O__"T,$B4,$BX7@_O__"T,(B4,(BX7D_O__"T,,B4,,_W4,
-MZ'K9__^#Q`3&0`0!BI6S_O__B%`(B%`)BQ.)4`R+4P2)4!"+4PB)4!2+4PR)
-M4!B)A<3^__^+70R!P]0(``#_=0SH.=G__X/$!,9`!`.)6`B*C;/^__^(2`R)
-MA<#^__^+&/Z#O`8```^VL[P&``"+E<3^__\IVH/J+,'Z`HT$THT$PHT$PHT$
-MPHG!P>$/`<B-!,+WV(B$<[P&``"+O<#^__^*1P>(A'.]!@``B?"(1P>*E;/^
-M__^+30PX42=U4XNUM/[__XL>_H.\!@``#[:SO`8``(GZ*=J#ZBS!^@*-!-*-
-M!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``B[VT_O__BD<'B(1SO08``(GP
-MB$<'_H6S_O__BI6S_O__BTT,.%$F#X<G_O__Z<@```#&A;/^__\`BUT,@'LF
-M``^&M````(J%L_[__XM5##B"+`D```^'AP```#B"+0D``')_.$(G='HX0BAT
-M=0^VP,'@!(V$!>C^__^Z`````(,X`'42@W@$`'4,@W@(`'4&@W@,`'0%N@$`
-M``"%TG1##[:%L_[__\'@!(V<!>C^____=0SHR]?__X/$!,9`!`&*C;/^__^(
-M2`B(2`F+$XE0#(M3!(E0$(M3"(E0%(M3#(E0&/Z%L_[__XJ=L_[__XMU##A>
-M)@^'3/___[@`````@[W(_O__`'4;@[W,_O__`'42@[W0_O__`'4)@[W4_O__
-M`'0%N`$```"%P`^$6QH``(M%#(I`*(B%E_[__XM5#(B"``D``(N%R/[__XF"
-M[`@``(N%S/[__XF"\`@``(N%T/[__XF"]`@``(N%U/[__XF"^`@``,:"`0D`
-M``#'@OP(````````BEHG4NCTUO__@\0$QD`$`8A8"(J-E_[__XA("8N5R/[_
-M_XE0#(N5S/[__XE0$(N5T/[__XE0%(N5U/[__XE0&(F%O/[__\>%N/[__P``
-M``#&A;/^__\`BUT,@'LF``^&H1D``(J%L_[__XM5##A"*`^$S`$``#A")P^$
-MPP$``(I:)U+H==;__X/$!,9`!`&*C;/^__^(2`B(6`F+E<C^__^)4`R+E<S^
-M__^)4!"+E=#^__^)4!2+E=3^__^)4!B)A<3^__^+&/Z#O`8```^VL[P&``"+
-ME;3^__\IVH/J+,'Z`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<[P&``"+
-MO<3^__^*1P>(A'.]!@``B?"(1P>#O;C^__\`=$N+'_Z#O`8```^VL[P&``"+
-ME;C^__\IVH/J+,'Z`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<[P&``"*
-M1P>(A'.]!@``B?*(5P>+70R!P^P(``"+30R*22>(C9;^____=0SH=M7__X/$
-M!,9`!`.)6`B*G9;^__^(6`R)A<#^__^)A;C^__^+&/Z#O`8```^VL[P&``"+
-ME<3^__\IVH/J+,'Z`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<[P&``"+
-MO<#^__^*1P>(A'.]!@``B?"(1P>+'_Z#O`8```^VL[P&``"+E;S^__\IVH/J
-M+,'Z`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<[P&``"*1P>(A'.]!@``
-MB?*(5P?^A;/^__^*C;/^__^+70PX2R8/APK^___IIA<``(GVBT4,BH`L"0``
-MB(6S_O__BU4,.((M"0``#X*&%P``B?:*C;/^__^+70PX2R=T=@^VP<'@!(V$
-M!>C^__^Z`````(,X`'43@W@$`'4-@W@(`'4'@W@,`'0&D+H!````A=)T0P^V
-MA;/^___!X`2-G`7H_O___W4,Z"+4__^#Q`3&0`0!BI6S_O__B%`(B%`)BQ.)
-M4`R+4P2)4!"+4PB)4!2+4PR)4!C^A;/^__^*C;/^__^+70PXBRT)```/@V'_
-M___IX!8``(MU#(!^*`</AA\,``"#[`R-A=C^__]0Z/C2___&A;+^__\`QH6S
-M_O__`(/$$(!^)@`/AKD```"0BH6S_O__BU4,.$(G#X2.````#[;`P>`$`="-
-MD-0'``"Y`````(.XU`<```!U$H-Z!`!U#(-Z"`!U!H-Z#`!T!;D!````A<ET
-M5P^VE;/^__^)T,'@!(M-#(V4"-0'``"+A=C^__\+`HF%V/[__XN%W/[__PM"
-M!(F%W/[__XN%X/[__PM""(F%X/[__XN%Y/[__PM"#(F%Y/[___Z%LO[___Z%
-ML_[__XJ=L_[__XMU##A>)@^'2/___P^VE;+^__^+?0P/MD<F@^@#T?@YP@^.
-ME@8``(I?)XB?Z`@``(N%V/[__XF'U`@``(N%W/[__XF'V`@``(N%X/[__XF'
-MW`@``(N%Y/[__XF'X`@``,:'Z0@```''A^0(````````5^A]TO__@\0$QD`$
-M`HA8"(A8"8N5V/[__XE0#(N5W/[__XE0$(N5X/[__XE0%(N5Y/[__XE0&(G'
-M_W4,Z$+2__^#Q`3&0`0&B86T_O__BQ_^@[P&```/MK.\!@``B<(IVH/J+,'Z
-M`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<[P&``"*1P>(A'.]!@``B?"(
-M1P>+50R`>B8"#X?6`@``B=.!P]0(``!2Z-/1__^#Q`3&0`0%B5@(QD`4`(F%
-MP/[__XN-M/[__XL9_H.\!@``#[:SO`8``(G"*=J#ZBS!^@*-!-*-!,*-!,*-
-M!,*)P<'A#P'(C03"]]B(A'.\!@``B[VT_O__BD<'B(1SO08``(GPB$<'QH6S
-M_O__`(M5#(!Z)@`/AF`4``"*C;/^__^+70PX2R</A!X"``"+M<#^__^*1A0/
-MMM"(3!8,0(A&%`^VV<'C!(M]#(T$.XV(5`@``(N05`@``/?2B97(_O__BT$$
-M]]")A<S^__^+00CWT(F%T/[__XM!#/?0B874_O__C8P=Z/[__R.5V/[__XD1
-MBX7<_O__(X7,_O__B4$$BX7@_O__(X70_O__B4$(BX7D_O__(X74_O__B4$,
-MN@````"#.0!U$H-Y!`!U#(-Y"`!U!H-Y#`!T!;H!````A=(/A)0````/MH6S
-M_O__P>`$C9P%Z/[___]U#.AST/__@\0$QD`$`8J5L_[__XA0"(A0"8L3B5`,
-MBU,$B5`0BU,(B5`4BU,,B5`8BXW`_O__BQG^@[P&```/MK.\!@``*=B#Z"S!
-M^`*-%,"-%-"-%-"-%-")T<'A#P'*C130]]J(E'.\!@``B[W`_O__BD<'B(1S
-MO08``(GPB$<'#[:%L_[__\'@!(M5#(V$$-0'``"Z`````(,X`'42@W@$`'4,
-M@W@(`'4&@W@,`'0%N@$```"%T@^$DP````^VG;/^__^)V,'@!(M-#(V<"-0'
-M``!1Z)_/__^#Q`3&0`0"BI6S_O__B%`(B%`)BQ.)4`R+4P2)4!"+4PB)4!2+
-M4PR)4!B)QXL8_H.\!@``#[:SO`8``(N5M/[__RG:@^HLP?H"C032C03"C03"
-MC03"B<'!X0\!R(T$PO?8B(1SO`8``(I'!XB$<[T&``")\8A/!_Z%L_[__XJ=
-ML_[__XMU##A>)@^'N/W__^D3$@``QH6S_O__`(M]#(!_)@`/AO\1``"-=@"*
-MA;/^__^+50PX0B</A(X"```/MOC!YP2-!!>-B%0(``"+D%0(``#WTHF5R/[_
-M_XM!!/?0B87,_O__BT$(]]")A=#^__^+00SWT(F%U/[__XV,/>C^__\CE=C^
-M__^)$8N%W/[__R.%S/[__XE!!(N%X/[__R.%T/[__XE!"(N%Y/[__R.%U/[_
-M_XE!#(M=#('#U`@``/]U#.A7SO__@\0$QD`$`XE8"(J-L_[__XA(#(F%P/[_
-M_XNUM/[__XL>_H.\!@``#[:SO`8``(G"*=J#ZBS!^@*-!-*-!,*-!,*-!,*)
-MP<'A#P'(C03"]]B(A'.\!@``BY6T_O__BD('B(1SO08``(GQB$H'C80]Z/[_
-M_[H`````@S@`=1*#>`0`=0R#>`@`=0:#>`P`=`6Z`0```(72#X24````#[:%
-ML_[__\'@!(V<!>C^____=0SHHLW__X/$!,9`!`&*E;/^__^(4`B(4`F+$XE0
-M#(M3!(E0$(M3"(E0%(M3#(E0&(N-P/[__XL9_H.\!@``#[:SO`8``"G8@^@L
-MP?@"C13`C130C130C130B='!X0\!RHT4T/?:B)1SO`8``(N]P/[__XI'!XB$
-M<[T&``")\(A'!P^VA;/^___!X`2+50R-A!#4!P``N@````"#.`!U$H-X!`!U
-M#(-X"`!U!H-X#`!T!;H!````A=(/A)8````/MIVS_O__B=C!X`2+30R-G`C4
-M!P``4>C.S/__@\0$QD`$`HJ5L_[__XA0"(A0"8L3B5`,BU,$B5`0BU,(B5`4
-MBU,,B5`8B<>+&/Z#O`8```^VL[P&``"+E;3^__\IVH/J+,'Z`HT$THT$PHT$
-MPHT$PHG!P>$/`<B-!,+WV(B$<[P&``"*1P>(A'.]!@``B?&(3P>-=@#^A;/^
-M__^*G;/^__^+=0PX7B8/ATC]___I/P\``(M]#(I?)U?H*\S__\9`!`&(6`B(
-M6`F+E=C^__^)4`R+E=S^__^)4!"+E>#^__^)4!2+E>3^__^)4!B)A;S^__^*
-M7R>)/"3H[,O__X/$!,9`!`*(6`B(6`F+E=C^__^)4`R+E=S^__^)4!"+E>#^
-M__^)4!2+E>3^__^)4!B)Q_]U#.BQR___@\0$QD`$!HF%M/[__XL?_H.\!@``
-M#[:SO`8``(G"*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\
-M!@``BD<'B(1SO08``(GPB$<'QH6S_O__`(M5#(!Z)@`/AE$.``"0BHVS_O__
-MBUT,.$LG#X1J`P``#[;!P>`$`=B-D-0'``"Y`````(.XU`<```!U$H-Z!`!U
-M#(-Z"`!U!H-Z#`!T!;D!````A<D/A"\#``#^C;+^__^*A;+^__^+50R*4B:-
-M-!`/MIVS_O__B=^)V,'@!(M-#(V<"-0'``!1Z,C*___&0`0!BI6S_O__B%`(
-MB?&(2`F+$XE0#(M3!(E0$(M3"(E0%(M3#(E0&(F%Q/[__XM=#(I;)XB=E?[_
-M_\'G!(M%#(V<!]0'``")!"3H>,K__\9`!`2*E97^__^(4!B)\8A(&8L3B5`(
-MBU,$B5`,BU,(B5`0BU,,B5`4B87`_O__BQC^@[P&```/MK.\!@``BY6\_O__
-M*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``BY7`_O__
-MBD('B(1SO08``(GQB$H'BQK^@[P&```/MK.\!@``BY7$_O__*=J#ZBS!^@*-
-M!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``BY7`_O__BD('B(1SO08`
-M`(GQB$H'B[6T_O__BQ[^@[P&```/MK.\!@``BY7`_O__*=J#ZBS!^@*-!-*-
-M!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``BY6T_O__BD('B(1SO08``(GQ
-MB$H'BUT,BELGB)V4_O__BW4,C9PWU`<``(DT).@RR?__QD`$!(J5E/[__XA0
-M&(J-L_[__XA(&8L3B5`(BU,$B5`,BU,(B5`0BU,,B5`4B87`_O__BQC^@[P&
-M```/MK.\!@``BY6\_O__*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"
-M]]B(A'.\!@``BY7`_O__BD('B(1SO08``(GQB$H'B[6T_O__BQ[^@[P&```/
-MMK.\!@``BY7`_O__*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(
-MA'.\!@``BY6T_O__BD('B(1SO08``(GQB$H'BUT,C;P?U`<``(D<).A%R/__
-M@\0$QD`$`HJ5L_[__XA0"(A0"8L7B5`,BU<$B5`0BU<(B5`4BU<,B5`8B<>+
-M&/Z#O`8```^VL[P&``"+E;3^__\IVH/J+,'Z`HT$THT$PHT$PHT$PHG!P>$/
-M`<B-!,+WV(B$<[P&``"*1P>(A'.]!@``B?&(3P>)]OZ%L_[__XJ=L_[__XMU
-M##A>)@^';/S__^FW"@``C78`BWT,BD<H.D<G#X6Z````QH6S_O__`(!_)@`/
-MAI0*``"*A;/^__^+50PX0B=T?@^VP,'@!`'0C9#4!P``N0````"#N-0'````
-M=1*#>@0`=0R#>@@`=0:#>@P`=`6Y`0```(7)=$</MIVS_O__B=C!X`2+30R-
-MG`C4!P``4>@KQ___@\0$QD`$`HJ5L_[__XA0"(A0"8L3B5`,BU,$B5`0BU,(
-MB5`4BU,,B5`8D/Z%L_[__XJ-L_[__XM=##A+)@^'7/___^GK"0``@^P,C878
-M_O__4.@0QO__@\00_W4,Z,G&__^#Q`3&0`0&B86T_O__QH6S_O__`(MU#(!^
-M)@`/AE0!``"*A;/^__^+50PX0B</A"H!```/ML#!X`0!T(V0U`<``+D`````
-M@[C4!P```'42@WH$`'4,@WH(`'4&@WH,`'0%N0$```"%R0^$[P````^VE;/^
-M__^)T8G0P>`$BUT,C908U`<``(N%V/[__PL"B878_O__BX7<_O__"T($B87<
-M_O__BX7@_O__"T((B87@_O__BX7D_O__"T(,B87D_O__BH6S_O__.$,H#X2-
-M````B<O!XP2+50R-G!/4!P``4NCDQ?__@\0$QD`$`HJ-L_[__XA("(A("8L3
-MB5`,BU,$B5`0BU,(B5`4BU,,B5`8B<>+&/Z#O`8```^VL[P&``"+E;3^__\I
-MVH/J+,'Z`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<[P&``"*1P>(A'.]
-M!@``B?.(7P>0_H6S_O__BH6S_O__BU4,.$(F#X>L_O__BTT,BEDG4>A(Q?__
-M@\0$QD`$`HA8"(A8"8N5V/[__XE0#(N5W/[__XE0$(N5X/[__XE0%(N5Y/[_
-M_XE0&(G'BQC^@[P&```/MK.\!@``BY6T_O__*=J#ZBS!^@*-!-*-!,*-!,*-
-M!,*)P<'A#P'(C03"]]B(A'.\!@``BD<'B(1SO08``(GSB%\'BW4,#[9>*(G>
-MB=C!X`2+?0R-G#A4"```BP/WT(F%R/[__XM3!/?2B97,_O__BTL(]]&)C=#^
-M__^+6PSWTR.%V/[__XF%R/[__XN]W/[__R'ZB97,_O__BY7@_O__(=&)C=#^
-M__^+A>3^__\APXF=U/[__\'F!(M-#(VT#E0(``"+C=C^__\C#HF-V/[__R-^
-M!(F]W/[__R-6"(F5X/[__R-&#(F%Y/[__[@`````A<EU$87_=0V%TG4)@[WD
-M_O__`'0%N`$```"%P`^$N@(``(M=#(I#)XB#Z`@``(N%V/[__XF#U`@``(N%
-MW/[__XF#V`@``(N%X/[__XF#W`@``(N%Y/[__XF#X`@``,:#Z0@```''@^0(
-M````````QH6S_O__`(![)@`/AEP"``"!P]0(``")G9#^__^*A;/^__^+50PX
-M0BAU=E+H?,/__X/$!,9`!`.+C9#^__^)2`B*G;/^__^(6`R+M;3^__^+'OZ#
-MO`8```^VL[P&```IV(/H+,'X`HT4P(T4T(T4T(T4T(G1P>$/`<J-%-#WVHB4
-M<[P&``"+O;3^__^*1P>(A'.]!@``B?"(1P?IM0$``)"*E;/^__^+30PX42</
-MA*(!```/MOK!YP2-C#WH_O__BUT,C90?5`@``(L"]]")`8M"!/?0B4$$BT((
-M]]")00B+0@SWT(E!#(L!(X78_O__B0&+000CA=S^__^)002+00@CA>#^__^)
-M00B+00PCA>3^__^)00Q3Z)'"__^#Q`3&0`0#B[60_O__B7`(BI6S_O__B%`,
-MB87`_O__BXVT_O__BQG^@[P&```/MK.\!@``B<(IVH/J+,'Z`HT$THT$PHT$
-MPHT$PHG!P>$/`<B-!,+WV(B$<[P&``"+E;3^__^*0@>(A'.]!@``B?&(2@>-
-MA#WH_O__N@````"#.`!U$H-X!`!U#(-X"`!U!H-X#`!T!;H!````A=(/A)<`
-M```/MH6S_O__P>`$C9P%Z/[___]U#.C6P?__@\0$QD`$`8J5L_[__XA0"(A0
-M"8L3B5`,BU,$B5`0BU,(B5`4BU,,B5`8BXW`_O__BQG^@[P&```/MK.\!@``
-M*=B#Z"S!^`*-%,"-%-"-%-"-%-")T<'A#P'*C130]]J(E'.\!@``B[W`_O__
-MBD<'B(1SO08``(GPB$<'C78`_H6S_O__BI6S_O__BTT,.%$F#X>P_?__N```
-M``"#O<C^__\`=1N#O<S^__\`=1*#O=#^__\`=0F#O=3^__\`=`6X`0```(7`
-M#X02!```BW4,BEXG5NC^P/__@\0$QD`$`8A8"(A8"8N5R/[__XE0#(N5S/[_
-M_XE0$(N5T/[__XE0%(N5U/[__XE0&(F%O/[__\>%N/[__P````#&A;/^__\`
-M@'XF``^&M`,``(J%L_[__XM5##A"*`^$B@,``#A")P^$@0,```^VP,'@!(V<
-M!>C^__\!T(V(U`<``(N5R/[__R.0U`<``(D3BX7,_O__(T$$B4,$BX70_O__
-M(T$(B4,(BX74_O__(T$,B4,,N`````"#.P!U$H-[!`!U#(-["`!U!H-[#`!T
-M!;@!````A<`/A!$#``"+30R*22B(C8_^__\/MH6S_O__P>`$C9P%Z/[___]U
-M#.C\O___@\0$QD`$`8J5L_[__XA0"(J-C_[__XA("8L3B5`,BU,$B5`0BU,(
-MB5`4BU,,B5`8B87$_O__@[VX_O__`'11BQC^@[P&```/MK.\!@``BY6X_O__
-M*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``B[W$_O__
-MBD<'B(1SO08``(GPB$<'BU4,BE(GB)6._O__BTT,BDDHB(V-_O__#[:]L_[_
-M_\'G!(V</>C^____=0SH.[___X/$!,9`!`2*E8[^__^(4!B*C8W^__^(2!F+
-M$XE0"(M3!(E0#(M3"(E0$(M3#(E0%(F%P/[__XF%N/[__XL8_H.\!@``#[:S
-MO`8``(N5O/[__RG:@^HLP?H"C032C03"C03"C03"B<'!X0\!R(T$PO?8B(1S
-MO`8``(N5P/[__XI"!XB$<[T&``")\8A*!XL:_H.\!@``#[:SO`8``(N5Q/[_
-M_RG:@^HLP?H"C032C03"C03"C03"B<'!X0\!R(T$PO?8B(1SO`8``(N5P/[_
-M_XI"!XB$<[T&``")\8A*!XNUM/[__XL>_H.\!@``#[:SO`8``(N5P/[__RG:
-M@^HLP?H"C032C03"C03"C03"B<'!X0\!R(T$PO?8B(1SO`8``(N5M/[__XI"
-M!XB$<[T&``")\8A*!XM=#(I;)XB=C/[__XV</>C^____=0SHZ[W__X/$!,9`
-M!`2*E8S^__^(4!B*C;/^__^(2!F+$XE0"(M3!(E0#(M3"(E0$(M3#(E0%(F%
-MP/[__XL8_H.\!@``#[:SO`8``(N5O/[__RG:@^HLP?H"C032C03"C03"C03"
-MB<'!X0\!R(T$PO?8B(1SO`8``(N]P/[__XI'!XB$<[T&``")\(A'!XN5M/[_
-M_XL:_H.\!@``#[:SO`8``(GZ*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(
-MC03"]]B(A'.\!@``BXVT_O__BD$'B(1SO08``(GSB%D'D/Z%L_[__XJ%L_[_
-M_XM5##A")@^'3/S__X/L"/]U#/]U".@VTO__N`````"-9?1;7E_)PY!5B>57
-M5E.#[`R+10B#N"PP```##X</`0``!>PO``"+50@Y@NPO```/A/L```")1>R+
-MBNPO``")3?"-=@"+7?"+`XE%\(M3!(L#B5`$B0*)&XE;!(M#'/9``00/A8@`
-M``")W[X`````@'LF`'8FC78`@^P,B?(/ML+!X`2-A#C4!P``4.B0N___@\00
-M1HGQ.$\F=]V+50B!PN0O``"+30B+@>0O``")6`2)`XE3!(F9Y"\``(M#'(-X
-M)`!T8(/L!/]P*(M#'/]P)%'H_/___XM#',=`)`````"+10C_B#`P``"#Q!#K
-M-HGV@^P(4_]U".B8T___@\00A<!T+8M5"('"["\``(M-"(N!["\``(E8!(D#
-MB5,$B9GL+P``D(M%[#E%\`^%%/___XUE]%M>7\G#58GE4X/L!(M%"(M8"(.[
-M+#````!U#HV#["\``#F#["\``'0S@^P,4^C\____B1PDZ/S___^)'"3H_/__
-M_X/$$(.[+#````!UVXV#["\``#F#["\``'7-N`````"+7?S)PXUV`%6)Y5=6
-M4X/L!(M%"(M`"(E%\(N(["\```7L+P``.<@/A($```"-=@"+50@Y41QU:(G/
-MLP"`>28`=D&)]@^VP\'@!`'XC9#4!P``O@````"#N-0'````=12#>@0`=0Z#
-M>@@`=0B#>@P`=`>)]KX!````A?9U&4,X7R9WP;@`````A<!T%+@!````Z:T`
-M``"X`0```.OKC78`BPF+1?`%["\``#G(=8*+1?"+B/0O```%]"\``#G(='Z-
-M0?B+50@Y4!QU98G#O@````"`>"8`=D&)\@^VPL'@!`'8C9#4!P``OP````"#
-MN-0'````=1*#>@0`=0R#>@@`=0:#>@P`=`6_`0```(7_=1A&B?`X0R9WO[@`
-M````A<!T#K@!````ZQJX`0```.ONBPF+1?`%]"\``#G(=8*X`````(/$!%M>
-M7\G#D%6)Y5=64X/L#(M="(M]$(MS"(-[)`!U#5/HGO[__X/$!(7`=0N#[`A7
-M5O]5#.L9D(M%#(E#)(E[*/^&,#```(/L#%;H_/___XUE]%M>7\G#58GE5E.+
-M=0B+70R`>Q$`=03&0Q$!@'L1`709@'L1!G03@'L1`W0-]D,0('4'QD,1"XUV
-M`/]S+%;HQ[C__XD<)/]S'%;H_/___XL#@\00@W@8`'08@^P$@\`84&@`````
-M5NC\____@\00ZUV0@[XT,````'0KC8;D+P``.8;D+P``=!V#[`2-AC0P``!0
-M:`````!6Z/S___^#Q!#K*XUV`(&^*#```/\```!W'(V&Y"\``#F&Y"\``'4.
-M@^P,5NC\____@\00B?:-9?A;7LG#D%6)Y5=64X'LS````(M]$(M%#(M0((L*
-MB8TT____#[9!/$B)A4C___]FBTH(9HF-5O___XM"3(F%4/___P^V2DJ)C43_
-M__\/MD)+B85`____9HM*4F:)C53___]FBUI0@WH4`'0-9@^V0A"#X`$[111U
-M.+D`````@WH8``^$?P(``(V%6/___XF%./____]U%%!2_W4(_U(8@\00N0``
-M``"%P`^$6`(``.L)BU(4B94X____O@````"+50R+`@^V0`.)A3S___^Y````
-M``^WPP.%4/___XF%3/___XN%//___SF%1/___P^%%P$``(7)=%*+A4S___\I
-MR(G#P>,)=$.#?10`=`>A`````.L1@^P,_S4`````Z/S___^#Q!")!V;'1P8`
-M`('[`!````^&OP```&;'1P0`$(/'"('K`!```'6]#[>=5/___\'C"8UV`(N-
-M./___P^W402%TG4%N@```0")T"GP.=AR,8GPBXTX____`P&)!V:)7P1FQT<&
-M``"#QP@!WCG6=4:^`````(/!"(F-./___^LVB?:)\(N-./___P,!B0>)T&8I
-M\&:)1P1FQT<&``"#QPB)T"GP*<.#P0B)C3C___^^`````.N`#[>-5/___P.-
-M3/___XM5#`^W0@@#0@0YR`^$!@$``.M/9HE?!(/'".E&____C78``=[K/`^W
-MG53____!XPF)]HN%./___P^W4`2%TG4%N@```0")T"GP.=AWU8G0*?`IPX.%
-M./___PB^`````.O1D(N55/___V8IE5;___\/A*(```"[`````/^%1/___XN%
-M0/___SF%1/___W4(_X5$____B?:+E33___\/MD(\.X5$____=4*#O4#___\`
-M=`C_C4#____K#(N%2/___XF%0/___X.]0/___P`/E,`/ML")A43___^+E33_
-M__\/MT)(`850____B?:+A33___]FBT!(9HF%5/___V:+E5;___]F.=`/AN/]
-M__]FB954____Z=?]__]FQT?^`("Y`0```(G(C67T6UY?R<.)]E6)Y593BW4(
-MBU4,BUH@@'H1`70&BD(1B$,1@^P(4E;H_/___XI#24"(0TF#Q!`Z0TAU+8![
-M$0!U!,9#$0&`>Q$!=!"`>Q$&=`J`>Q$#=`3&0Q$+@^P(4U;_4QR#Q!")]HUE
-M^%M>R<.058GE5U93@^PLBT4,BP")1>R+50SV0A`$#X3T`0``QT7P`````(!Z
-M1``/A'L!``"+3?"+70R+3(LPB4WHBIDL"0``B%WG.)DM"0``#X)&`0``C78`
-MBD7GBU7H.$(G#X0?`0``#[;`B<+!X@2+3>B-E`K4!P``B57@#[>4@0P)```/
-MM[2!#@D``+\`````C78`@_H?=U.)^P^VPXM-X(T<@8E5W+D@````*=$Y\78"
-MB?&#^2!U"\<#_____^L2C78`N`$```#3X$B*3=S3X`D#N"`````IT#GP<QF-
-M=!;@N@````#K!HUV`(/J($>)^X#[`W:=#[9%YXG"P>`$BTWHC80(5`@``(E%
-MV`^WG)$,"0``#[>TD0X)``"_`````(GV@_L?=U.)^@^VPHM-V(T4@8E=U+D@
-M````*=DY\78"B?&#^2!U"\<"_____^L2C78`N`$```#3X$B*3=33X`D"N"``
-M```IV#GP<QB-=![@NP````#K!HUV`(/K($>)^#P#=I[^1>>*5>>+3>@XD2T)
-M```/@[W^____1?"+70P/MD-$.T7P#X^%_O__BT4(@[C@+P````^$/@,``,=%
-M\`````"+50R`>D0`=#6)PH'"["\``(M-\(M=#(M,BS#'@00)````````BT($
-MB4H$B1&)002)"/]%\`^V0T0[1?!_TX/L"/]U#/]U".BO^?__Z1T#``"+70SV
-M0Q`"#X39`@``BT4(!3@P``")1="+?0B!QU@P``"+5>SV0DH##X6X`@``@^P$
-M:A!J`%?H_/___\=%\`````"#Q!"`>T0`#X3_````BTWPBUT,BTR+,(E-Z(G.
-ML0"`?B8`=D8/ML'!X`0!\(V0U`<``+L`````@[C4!P```'42@WH$`'4,@WH(
-M`'4&@WH,`'0%NP$```"%VW0)N`$```#K#8GV03A.)G>ZN`````"%P`^%+0(`
-M`(M%Z(J`+`D``(A%YXM5Z#B"+0D``')KBDWGBUWH.$LG=$\/MM%F@SQ7`'4?
-M#[>$DPP)```#0R"+3=")!)%FBX23#@D``&:)!%?K)@^V5>>+7>AFBX23#`D`
-M`&8#0R!F`X23#@D``(M-T&8K!)%FB017_D7GBEWGBT7H.)@M"0``<Y7_1?"+
-M50P/MD)$.T7P#X\!____BTT,_W$L_W4(Z%*Q___'1?``````@\0(BUT,@'M$
-M``^$S````(M-"('!Y"\``(M%\(M5#(M$@C")1>B#??``=4J)PHM`((M=#(E#
-M3(J"+`D``(A#2HI")XA#2P^V@BP)``!FBX2"#`D``&:)0U`/MH(L"0``9HN$
-M@@X)``!FB4-2QD-(`,9#20#K0XM%Z(M0((M=##M33'8UBUWL#[=#2/?8(<*+
-M70PC0TPYPG4@BT7H#[:0+`D``&:+0U*+7>AF`X23#@D``(M5#&:)0E*+002+
-M7>B)602)"XE#!(D8_T7PBU4,#[9"1#M%\`^//?___XM-"(.Y-#````!T&8/L
-M!(G(!30P``!0:`````!1Z/S___^#Q!#&1><`BUWL@'L\``^&J`````^V=>=F
-M@SQW`'14BT7LBURP5(/L#/]U".C\____BU4,_D)(QD`*(&:+%'=FB5`(BTW0
-MBQ2QB5`$@$@0`L=`&.1F``#'0!SP:0``B1B+50R)4""#Q`A0_W4(_U,T@\00
-M_D7GBDWGBUWL.$L\=Y/K.8GVQT7P`````(M%#(!X1`!T)X/L"(M5\(M-#/]T
-MD3#_=0CH`\C__X/$$/]%\(M=#`^V0T0[1?!_V8UE]%M>7\G#D%6)Y5=64X/L
-M/(M%#(L`B47PQT7D`````&:+4$AFB57J9H'Z@`!V!F;'1>J``(M-#/9!$"!T
-M2`^W1>I0BUT0_W,(_W7P_W4(Z(RR__^)1>2#Q!"X_____X-]Y``/A#,#``"+
-M10S&0$0!BU7DB5`PB8($"0``N`````#I%@,``(M-$`^V41*+`8G3N@````#W
-M\XA5XXM%\`^V4#R+002)T;H`````]_&+71"*0Q(HT(A%XCA%XX!=X_^+1?!F
-MBU!(C4+_9HM+#"'!B==F*<]F.7L0<P1FBWL0BU4,QD)$`,9"10#'1=P!````
-M#[==ZHE=V/?;B5W4#[?!BU40`T((B47LBTT(@<'L+P``B4W,BUT(@</D+P``
-MB5W(C78`9HM%ZD@C1>QFBUWJ9BG#9CG[=@*)^XMUU"-U[(-]W``/A%X!``#'
-M1=P`````9HM5ZHM%\&8Y4$AV+KH`````BTT,#[9!1(G!@_@`?AN-=@"+10R+
-M1)`PB47D.7`@#X0A`0``0CG1?^C_==A6_W7P_W4(Z$6Q__^)1>2#Q!"%P`^%
-MRP```(M5#/Y*1(!Z1/\/A*\```"+3<R)3="+?<B+70P/MD-$BT2#,(E%Y,>`
-M!`D```````")QK$`@'@F`'8_#[;!P>`$`?"-D-0'``"[`````(.XU`<```!U
-M%(-Z!`!U#H-Z"`!U"(-Z#`!T!XGVNP$```"%VW4D03A.)G?!N`````"%P'0<
-MBU70BT($BTWDB4H$B1&)002)".L7N`$```#KX(M'!(M=Y(E?!(D[B4,$B1B+
-M10S^2$2`>$3_#X5:____N/_____I*@$``(GVBU4,BE)$B%7##[;*BU7DBT4,
-MB52(,(I%PT"+30R(042)B@0)``#&@BP)```(QH(M"0````^V5>.+1>QF*?"+
-M3>1FB821#`D``&:)G)$."0``BD7C.($L"0``=@:(@2P)``"*5>.+3>0XD2T)
-M``!S!HB1+0D``(M%$&8I6!!F*=]T$@^WPP%%[,=%W`$```#I'/[__XM5$&:#
-M>A``#X2!````N0````#^1>.*7>(X7>-U`_Y%XXI%XXM5\#A"/'4R@'WB`'0%
-M_DWBZPF+71"*6Q*(7>*`?>(`#Y1%XXM5\`^W0DB+71`!0PC'1=P!````ZQ1F
-MBU7JBT7P9CE02'8'QT7<`0```(M=$&:+>Q"+1?!F.WA(#X9O_?__9HMX2.EF
-M_?__N`````"-9?1;7E_)PU6)Y8/L"(M5"(M%#(-]$`!T&L9`$0N#[`10:!1F
-M``!2Z/S___^#Q!#K#XGV@^P(4%+H]O;__X/$$,G#D%6)Y5=64X/L3(MU#(L^
-M]D<!!'48QD81`H/L!%;_=AS_=0CH_/___^D0`@``@W\L`'4B:@?_=0CH>*C_
-M_XE'+,<$)``0``!J`%#H_/___X/$$(UV`(I&$*@@#X6U````J`9U&<9&$0&#
-M[`16_W8<_W4(Z/S____IP0$``)#V1A`$="J#?R0`="2#[`3_=RC_=R3_=0CH
-M_/___\=')`````"+10C_B#`P``"#Q!"+5@2)5=1FBT8(9HE%V(I'/$B(1=H/
-MMD\^B=#3Z(E%R`^V7=JZ`````/?SB47,#[9//M/@B470#[='2`^OPXE%M`^W
-M3=@#3@0/KUW0*=F-3`'_B<BZ`````/=UM(G!#[='2`^OR.LND/9'2@%T&L9&
-M$0:#[`16_W8<_W4(Z/S____I"@$``(GV#[=/2(G(#Z]&!(E%T(M%T(T4`5)0
-M5_]U".BZJO__B48L@\00A<!U',=&*`````"#[`A6C4<84.C\____Z<<```"-
-M=@"#[`2-1<A05O]U".B@^O__@\00A<!T;?]V+/]U".@6JO__BT4(BY!4(@``
-M@\0(.9!8(@``=">Y(0(``)"+10B!O-!,$0```````'140HG0F??YBT4(.9!8
-M(@``==_'1B@`````@^P(5HM%"`4T,```4.C\____@\0$_W4(Z/S____K09#V
-M1A`$="N#[`1H+',``%;_=0CHJ:W__X/$$.LDQD81!8/L!%;_=AS_=0CH_/__
-M_^L/@^P(5O]U".BW]/__@\00C67T6UY?R<-5B>53@^P$BUT,@WLL`'1.@^P,
-M4^C\____N@````"#Q!"-=@"+0RR+!)"%P'00B?;'0!``````BT`4A<!U\D*!
-M^O\#``!VW6H'_W,L_W4(Z$"F___'0RP`````@\0,BUW\R<.058GE5U93@^P0
-MBWT(QX?@+P```````(V'Y"\``(F'Y"\``(F'Z"\``(V'["\``(F'["\``(F'
-M\"\``(V']"\``(F']"\``(F'^"\``*$`````P>`,NJNJJJKWXHG3P>L/4V@P
-M"0``5^CDI?__B<:#Q`R#PR!3:A!7Z-.E__\!QH/$#*$`````P>`,P>@.4&I$
-M5^BZI?__`<:#Q`QJ"&@`$```5^BHI?__`<:)/"3H_/___Z,`````@\001CLU
-M`````',QD(/L#%?H_/___XG"@\00A<!T'HN')#```(D"B9<D,```_X<H,```
-M1CLU`````'+1D(UE]%M>7\G#58GE5U93@^P,BWT(BW4,BUX$#[9.`[@!````
-MB<+3XH!F`?O'0U``````]D-*`G0,9H-[3`!T$NL*C78`9H-[3`!T+6:%4TQU
-M)V8)4TR`8P'[@WLX`'0-@^P(4U?_4SB#Q!")]H!C2A_ILP```(UV`(I#2F:)
-M4TS^2SW'0U``````@\@%B$-*A,!Y#8/@?XA#2NF*````B?:`8TJ?@^P(4U?H
-M_/___XG"@\00A<!T3,8``XI&`XA"`XE:!(!*`0BA#````(E"-*$@````B4(X
-MQT8$``````^V0@.)5(-4BD-*@^#^@\@*B$-*_D,]@^P(4FH'Z/S___^#Q!"#
-M>P0`=`R-=@"+6P2#>P0`=??H_/___XE#0(/L#%/H_/___XGVC67T6UY?R<-5
-MB>53BTT(NP````"+50Q*@_K_=`^-=@`/M@$!PT%*@_K_=?0/ML-;R<.)]E6)
-MY593BW4(@#X#=D:[`````(!^/`!T-8-\GE0`="6+3)Y4BE8!@^(!BD$!@^#^
-M"="(00&#[`S_=)Y4Z/S___^#Q!"00P^V1CPYV'_+@&9*^^L)@^P,5N@(````
-MC67X6U[)PY!5B>575E.![!P"``#'A>3]__\`````C;7H_?__BT4(@'@\``^$
-M.@(``(MX!(7_=`^#?P0`=`F)O>3]__^+?P2#[`1H``(``&H`5NC\____QP;S
-M%GA:@\00N`````"%_W0#BT=`B48$BU4(@'I$`'0*@$X)`HI"1XA&"HM%"(I0
-M0(C3@^,!BH:3````@^#\B-&#X0()V`G(B-.#XP2#X/.(T8/A"`G8"<B(TX/C
-M$(/@SXC1@^$@"=@)R(C1@^%`@^`_@^*`"<@)T(B&DP```(M5"/9"`0%T!(!.
-M"0&P`(7_=`R#O>3]__\!&<"#P`*(1@N%_P^$N@```(M'#(E&#,>&E```````
-M``"*!XA&$(I'/(A&$8.]Y/W__P!T"XN5Y/W__XI"`^L)BU4(BD(#C78`B$82
-MBD<^B$83]D=*`G0$@$X4`6:+1TQFB486BT=0B488QX:8`````````(/L!&H0
-MC4=T4(U&+%#H_/___X/$#&H$C8>$````4(U&/%#H_/___X/$#&H0C8?(````
-M4(V&@````%#H_/___X/$#&I`C8>(````4(U&0%#H_/___X/$$(.]Y/W__P!T
-M7HN5Y/W__XM"#(E&',>&G`````````"*`HA&((I"/(A&(8M5"(I"`XA&(HN5
-MY/W__XI"/HA&(_9"2@)T!(!.)`&+E>3]__]FBT),9HE&)HM"4(E&*,>&H```
-M``````"%_W4+BU4(B@*(1A"-=@!HD````%;H_/____?8B$8(:``"``!6Z/S_
-M___WV(B&D````%9J,(M5"(M"3(/H"E")T(/`/%#H_/___XUE]%M>7\G#D%6)
-MY8M-"(G(@#D#=B^X`````(!Y/`!T$`^V43R#?(%4`'4,0#G"?_2X`````.L-
-M@^P,_W2!5.C\____D,G#B?95B>564XMU"(`^`W8ONP````"`?CP`="B#?)Y4
-M`'01@^P,_W2>5.C\____@\00B?9##[9&/#G8?]_K!9"`9@'^C67X6U[)PY!5
-MB>6+30B+40BX`````(GV.0R"=0O'!((`````ZPB)]D"#^`=VZLG#58GEBT4,
-M@&`!^U#H_/___\G#B?95B>575E.![!P$``"+?0B-M>C]__^)^XI'`:@$#X09
-M`0``@#\"#X80`0``@^#]B$<!@^P$:``"``!J`%;H_/___X/$$(`_`W1XC87H
-M^___D(M;5(`_"'5DA=MT!V:#?TP!=5F)P\>%Y/O__P$````/MD<\@_@!?EI3
-M:B!J`(N5Y/O__XM$EU2#P#Q0Z/S___^Z`````(/$$(L$EC,$DXD$ED*#^G]^
-M\?^%Y/O__P^V1SP[A>3[__]_O^L7D(`[`W6/5FH@:@"-0SQ0Z/S___^#Q!!F
-M@;[^`0``5:IU7H.^R@$```!T&X%^!DQ)3$]T#(&^=@$``$=254)U!H!/`0+K
-M.L>%Y/O__P````"+A>3[___!X`0!\("XO@$``(!U#8.XR@$```!T!(!/`0+_
-MA>3[__^#O>3[__\#?M"-9?1;7E_)PY!5B>564XM-"(N92!$``(U#`;XA`@``
-MF??^B=:+10R)1-D\BY%($0``BT40B4310(FQ2!$``%M>R<.-=@!5B>575E.#
-M[`R+=0B+AD01```[AD@1``!T-K\A`@``D(N&1!$``(M,QCR+7,9`0)GW_XF6
-M1!$``(/L"%-6_]&#Q!"+AD01```[AD@1``!UT(UE]%M>7\G#58GE5E.+30B+
-MF5@B``"-0P&^(0(``)GW_HG6BT4,B8393!$``(N16"(``(M%$(F$T5`1``")
-ML5@B``!;7LG#D%6)Y5=64X/L#(M="(N#5"(``#N#6"(``'16B?:+@U0B``"+
-MM,-,$0``B[S#4!$``$"Z(0(``(G1F??YB9-4(@``@[LL,````'0.@^P,4^C\
-M____@\00B?:#[`A74__6@\00BX-4(@``.X-8(@``=:R-9?1;7E_)PU6)Y5.#
-M[`2+50BX`````(-Z.`!T%XM:.(L#B4(X@^P$:E1J`%/H_/___XG8BUW\R<.-
-M=@!5B>6+30B+50R+03B)`HE1.,G#D%6)Y8M-"(M5#(,Y`'02BP&+0"2)0B2+
-M`8E0).L&C78`B5(DB1')PY!5B>575E.#[`R+=0R#/@!T-8L^D(L&BU@D.=AU
-M"\<&`````.L+C78`BQ:+0R2)0B2#[`A3_W4(_U,H@\00.?MT!8,^`'7.C67T
-M6UY?R<.)]E6)Y8/L"(M%"(`X"'4.@^P,4.C\____@\00B?;)PXGV58GE4X/L
-M!(M%"(M=#(M-$(M0"(`X"'40@^P$45-0Z/S____K"HUV`(/L"%%2_].+7?S)
-MPU6)Y5=64X/L%(M%"(I5$(A5\XMX*(H`B$7R#[;84U?H_/___X/$#&H`4U?H
-M_/___X/$#&H`:@!J`&H`:@-35^C\____@\0@N@````"%P`^$F````/=%#```
-M`/`/E<`/MLB#[`R%R704N"0```"`??,@=`VX-````.L&B?8/MD7S4+A`````
-MA<EU"8M%#,'H&(/(0%"+70S!ZQ`/ML-0BU4,#[;&4`^V50P/M\*%R70)B=@E
-M`/\```G04&H!:@!H``$``/]U%%&`??,P#Y3`#[;`0%`/MEWR4U?H_/___XG&
-M@\0X4U?H_/___XGRB="-9?1;7E_)PXGV58GEBD4(B<*#X@.)T<'A#8V1`"``
-M`*@$=`J-@0`@`P#K"(GVC8(```(`R<-5B>564X/L'(MU"(I%#(A%]V@@H0<`
-MZ/S___^[(*$'`(/$$)"#[`@/MD7W4.BC____!1P!``")!"3_=@SH_/___X/$
-M$(3`>`BX`0```.LDD(/L#&@0)P``Z/S___^#Q!"!PQ`G``"!^S]+3`!VMK@`
-M````C67X6U[)PXGV58GE5E.+70B#[`1J``^V10Q0Z$'___^)QHU`"(D$)/]S
-M#.C\____@\0,:!@!``"-1@Q0_W,,Z/S___^#Q!"-9?A;7LG#C78`58GE@^P,
-M:@`/MD4,4.C^_O__@\`,B00DBT4(_W`,Z/S____)PXUV`%6)Y8M%#&:#?10`
-M=1/W11````#P=0JI`/\``'0+C78`N`$```#K&9!FA<!U"[@!````@WT(`70(
-MN`````"-=@#)PXGV58GE5U93BUT(BWT0BW44N0````"-4PJ+1A")`XM&%(E#
-M!(,^`'4"L0$/MD<$T>`)P6:)2PB+10R#N#@"````=`^#N#@"```"#X5&`0``
-MB?:#?@0!#X7&````9@^V1@^`S!%FB0*#P@)F#[9&#H#,$6:)`H/"`@^V1P3!
-MX`,E^````(#,$F:)`H/"`F8/MD8+@,P39HD"@\("9@^V1@B`S!-FB0*#P@)F
-M#[9&#(#,%&:)`H/"`F8/MD8)@,P49HD"@\("9@^V1@V`S!5FB0*#P@)F#[9&
-M"H#,%6:)`H/"`F;'`D`6@\("@SX`=1FP8(M-#(.Y.`(```(/A((!``"P)NE[
-M`0``L&&+30R#N3@"```"#X1I`0``L#;I8@$``(GV9@^V1@Z`S!%FB0*#P@(/
-MMD<$P>`#)?@```"`S!)FB0*#P@)F#[9&"(#,$V:)`H/"`F8/MD8)@,P49HD"
-M@\("9@^V1@J`S!5FB0*#P@*+1@@E````#\'H&`U`%@``9HD"@\("@SX!&<"#
-MX/N#Z#3I[0```)"#?@0!#X6&````9@^V1@^`S!)FB0*#P@)F#[9&#H#,$F:)
-M`H/"`F8/MD8+@,P39HD"@\("9@^V1@B`S!-FB0*#P@)F#[9&#(#,%&:)`H/"
-M`F8/MD8)@,P49HD"@\("9@^V1@V`S!5FB0*#P@)F#[9&"H#,%6:)`H/"`F;'
-M`D`6@\("@SX!&<"#X/"#P#7K79!F#[9&#H#,$F:)`H/"`F8/MD8(@,P39HD"
-M@\("9@^V1@F`S!1FB0*#P@)F#[9&"H#,%6:)`H/"`HM&""4````/P>@8#4`6
-M``!FB0*#P@*#/@$9P(/@_H/H-HUV`&8/ML`-`)?__V:)`EM>7\G#C78`58GE
-M5U93@^PDBU4(BUT4BW(,#[9%#(M$@B2+>#"-AP0!``!05NC\____B`.#Q`B-
-MAP@!``")1?!05NC\____9@^VP&:)0P*#Q`B-APP!``")1>Q05NC\____9@^V
-MP&:)0P2#Q`B-AQ`!``")1>A05NC\____9@^VP&:)0P:#Q`B-AQ0!``")1>10
-M5NC\____9@^VP&:)0PB#Q!"#?1`!#X6+````@^P(C8<@`0``B47<4%;H_/__
-M_XA%XX/$#(/(@`^VP%#_==Q6Z/S___^#Q`C_=?!6Z/S____!X`AF"4,"@\0(
-M_W7L5NC\____P>`(9@E#!(/$"/]UZ%;H_/___\'@"&8)0P:#Q`C_=>16Z/S_
-M___!X`AF"4,(@\0,#[9%XU#_==Q6Z/S___^#Q!")]H/L"(V'&`$``%!6Z/S_
-M__^(0PJ#Q`B-AQP!``!05NC\____B$,+C67T6UY?R<.)]E6)Y5=64X/L-(M%
-M$&:)1=8/ME4,B570BT4(BWR0)(M',(/`,%"+50C_<@SH_/___X/@'XT4Q0``
-M```IPHVTUT0"``"#Q!"#/@%T08U>%(U%V%#_<P3_==#_=0CH0/[___Z/40D`
-M`(/$#(U5V%)J``^W1=90_W,<:@'_==#_=RC_4QB#Q!A65^B,$0``C67T6UY?
-MR<-5B>575E.#[#R+51"*10R(1<_'1<@`````#[;`BTT(BW2!)&;'1<8``&:+
-M`F:)1="-3=!FBT("9HE!`HM"!(E!!&:+1=")PX/C'XT$W0`````IV(V<QD0"
-M``!FBT$"A,!T+L=%R`$```!FBT$")?\```!FB47&9H%-Q@`!QX9,"0``````
-M`,>&-`(```````"->Q2-1=!FBT`"J`1T&HU%V%#_=P0/MD7/4/]U".A:_?__
-M@\00C78`@SL!#X23````_HY1"0``@^P$C4784(U%T(M`!%`/MT7&4/]W'/]U
-MR`^V1<^)1<!0_W8H_U<8@\084U;HC!```(/$$(.^3`D```!T4(.^1`D```!T
-M1XN&1`D``(-X$`%U.X/L"/]UP/]U".A!$@``@\0(_[9$"0``5N@Z$P``@\00
-MA<!U%X/L!&H`_[9$"0``5N@R!@``@\00C78`C67T6UY?R<-5B>564XM="(/L
-M"&@L#0``_W,,Z/S___^)QH/$#(/(`5!H+`T``/]S#.C\____@\0(:"P-``#_
-M<PSH_/___X/$"&CP!`$`_W,,Z/S___^+50SWTB'0"T40@\0,4&CP!`$`_W,,
-MZ/S___^#Q`AH\`0!`/]S#.C\____@\0,5F@L#0``_W,,Z/S___^-9?A;7LG#
-MC78`58GE5U93@^P<BT4(BT`,B47LQT7H``````^V10R-#(4`````B$WSBD40
-M"$7S#[9%\XM5"(MT@B2#?1@`=&N%]@^$S0```(N>W`D``(/L!(M%%,'@`PM&
-M)%"+1C"#P"10_W7LZ/S___^#Q!`[711T(P^V??.#[`2+1A2-!-A05_]U".B)
-M_?__0X/C'X/$$#M=%'7A@[Y,"0```'4'QT7H`0```(F>W`D``(-]'`!U"H-]
-MZ``/A`,"``"#[`@/MD7S4.AF]___@\`(B47DB00D_W7LZ/S___^)QX/$#`^W
-MV(G8]]!0_W7D_W7LZ/S___^#Q!#VPP@/A!@!``"%]G04QX9,"0```````,>&
-M-`(```````"+30B#>60!=`:#>6@!=1J#[`2X``$``(I-\]/@4%#_=0CH,_[_
-M_X/$$(M%"(-X8`%T#(-X9`%T!H-X:`%U%8/L"`^V1?-0_W4(Z#,)``"#Q!#K
-M>HM5"(-Z7`%T!H-Z8`%U:X/L!&H$#[9=\U/HJ/;__XUP*(DT)/]U[.C\____
-M@\0(5O]U[.C\____QP0D&0```.C\____@\0,:@!6_W7LZ/S___^#Q`A6_W7L
-MZ/S____'!"30!P``Z/S___^#Q`A3_W4(Z(`'``"#Q!"0@^P(#[9=\U/H/_;_
-M_P4<`0``B00D_W7LZ/S___^#Q!!3:@!J`?]U"(M-"/]1(.FI````]\<0````
-M=%&#[`@/MD7S4/]U".@Q!P``@\00BT4(@WAD`70&@WAH`74;@^P$:@"X``$`
-M`(I-\]/@4/]U".@7_?__@\00#[9%\U!J`6H!_W4(BU4(_U(@ZU`/M\?VQ`%T
-M2(.^-`(```%U*,>&3`D```````#'AC0"````````@^P$4`^V1?-0_W4(Z-KZ
-M__^#Q!"#/0`````!=0Z#[`Q6Z'4/``"#Q!")]HUE]%M>7\G#58GE4X/L!(M=
-M"`^V10S!X`(+11`/MM"+3),DA<EU#8/L"%)3Z*<-``#K19"+D40)``"%TG42
-M@^P(#[;`4%/HC0T``.LKC78`@SH!=`:#>A`!=!&#[`@/ML!04^AP#0``ZPZ)
-M]H/L"%)1Z`H```")]HM=_,G#C78`58GE5U93@^PDBU4(BT(HBW`,BUHPB@J#
-MX0.)SP^V`H/@!,'H`HA%V(V#(`$``%!6Z/S___^#Q`B!PQP!``!35NC\____
-MB,.#Q`RX``$``(GYT^#WT%"`?=@!&<`E``#__P44``,`4%;H_/___X/$$(3;
-M#X@0`0``]L,!=!>#[`1J`?]U#/]U".C'`0``Z?8```")]HM5#(M"%(/X`70M
-M@_@!<A"#^`(/A(4```#IU@```(GV@^P$:@#_=0S_=0CHD`$``(/$$.F\````
-M]L-`=$^#[`B+10R#P!10_W4(Z*T```"#Q!"#^`%U((M-#(-Y(``/A9````"#
-M[`1J`%'_=0CH3@$``(/$$.M]@^P$:@'_=0S_=0CH.0$``(/$$.MH@^P$:@'_
-M=0S_=0CH)`$``.M6#[;#J$!T3Z@@=4N+10R#>"``=1.#[`1J`%#_=0CH``$`
-M`(/$$.LO@^P(BT4,@\`44/]U".@E````@\00A<!U%H/L!&H!_W4,_W4(Z-(`
-M``"#Q!"-=@"-9?1;7E_)PU6)Y5=64X/L#(M]"(MU#+@`````@7X,_P````^&
-MF````(L6@_H!=%&X`````(/Z`0^"@P```(/Z`G5YNP````"#[`2+1@@/MQ!2
-M@\`"B48(BT<P!0`!``!0BT<H_W`,Z/S___^#Q!!#@?O_````=M"!;@P``0``
-MZSN[`````(GV@^P(BT<P!0`!``!0BT<H_W`,Z/S___^+5@AFB0*#1@@"@\00
-M0X'[_P```';3@6X,``$``+@!````C67T6UY?R<.-=@!5B>575E.#[!R+=0B_
-M`````(M=#(/#%(U%V%#_<P0/M@90_W8HZ&+V__^#Q!"#?1`!=1%FOP$`QX9,
-M"0```````(UV`(/L!(U%V%!J`&H`_W,@5P^V!E#_=BC_4QR#Q!C_=0Q6Z)L)
-M``"#Q!"#?1`!=1:#/0`````!=0V#[`Q6Z!@,``"#Q!"0@[Y$"0````^$NP``
-M`(N&1`D``(-X$`%U+X/L"%!6Z$4,``"#Q!"%P`^%F@```(/L!&H`_[9$"0``
-M5N@Y____@\00Z8$```"0@[XX`@```'4S@^P(#[8&4/]V*.@<"@``@\0(BT8P
-M@\`H4(M&*/]P#.C\____QP0D`0```.C\____@\00@^P(#[8&4/]V*.@9"@``
-MBYY$"0``@\00A=MT*(-[$`!U(HGV@^P$C4,44%-6Z/H*``"+6PB#Q!"%VW0(
-M@WL0`'3BB?:-9?1;7E_)PU6)Y5=64X/L%(M="(M#*(MX#(M#,(E%\(G&@\8H
-M5E?H_/___X/$$*@$=#:#[`1J`E97Z/S___^#Q`A65^C\____QP0DT`<``.C\
-M____@\0(#[8#4/]S*.@8`@``@\00ZQ6#[`1J`HM%\(/`*%!7Z/S___^#Q!#&
-M@SP"````QH-0"0```,:#40D```#'@]@)````````QX/<"0```````,>#-`(`
-M``````#'@]0)```@````N@````")E)-4"0``0H/Z'W[SN@````")]HT$U0``
-M```IT,>$PT0"```!````0H/Z'W[FQX-$"0```````,>#2`D```````#'@TP)
-M````````@^P$:@"+1?"#P`A05^C\____@\0,:!@!``"+1?"#P`Q05^C\____
-M@\0,_W,8BT7P@\`04%?H_/___X/$#(M#'"4`_/__4(M%\(/`%%!7Z/S___^#
-MQ`QJ`(M%\(/`&%!7Z/S___^#Q`S_<R"+1?"#P!Q05^C\____@\0,:@"+1?"#
-MP"!05^C\____@\0,BT,DL`!0BT7P@\`D4%?H_/___[@!````C67T6UY?R<.-
-M=@!5B>575E.#["R+=0B+111FB476@WT,``^%F@```+L`````B?:-!-T`````
-M*=B-!,:#N$0"````=72#N%0"```!=1J+D%P"``"+N'@"``"+@'0"``")1=#K
-M)(UV`(T$W0`````IV(T$QHN07`(``(NX=`(``(N`<`(``(E%T(U%V%!2#[8&
-M4/]V*.CR\O__@\0,C4784&H`#[=%UE!7_W40#[8&4/]V*/]5T(/$($.#^Q\/
-MCFW___^-9?1;7E_)PY!5B>575E.#[!R+70@/MG4,B?"#X`3!Z`*(1=B_`P``
-M`"'W@WM<`70&@WM@`75K@^P(B?H/ML*)PL'B"(V"#`$``(!]V`!T"8V"#`$#
-M`.L&D`4```(`4/]S#.C\____B<&#X?R#R0&#Q`Q1B?H/ML*)PL'B"(V"#`$`
-M`(!]V`!T"(V"#`$#`.L%!0```@!0_W,,Z/S___^#Q!"#[`B)^@^VPHG"P>((
-MC8)T`0``@'W8`'0*C8)T`0,`ZP>)]@4```(`4/]S#.C\____B<&`X1^)\@^V
-MP@^V5!AZP>(%@>+@````"=&`Y></MH08@@```,'@"R4`&```"<&#Q`Q1B?H/
-MML*)PL'B"(V"=`$``(!]V`!T"8V"=`$#`.L&D`4```(`4/]S#.C\____@\00
-MC67T6UY?R<.-=@!5B>575E.#[`R+70@/MG4,5NB"[?__@^P$C7@H5E/H9>[_
-M_X/$#&H$5_]S#.C\____@\0(5_]S#.C\____QP0D&0```.C\____@\0,:@!7
-M_W,,Z/S___^#Q`A7_W,,Z/S___^#Q`A64^A;_O__@\0(5E/HR>W__XUE]%M>
-M7\G#D%6)Y5=64X/L#,9%\@#&1?,`C78`BD7RBE7SC1R"#[;;4^CR[/__B<=J
-M`HUP*%:+10C_<`SH_/___X/$"%:+50C_<@SH_/___X/$"%/_=0CH+/___X/$
-M#&H`5HM%"/]P#.C\____@\0,:!\!``!7BU4(_W(,Z/S___^#Q`QJ`(U'!%"+
-M10C_<`SH_/___X/$#&H`C4<(4(M5"/]R#.C\____@\0,:@"-1PQ0BT4(_W`,
-MZ/S___^#Q`QJ`(U'$%"+50C_<@SH_/___X/$#&H`C4<44(M%"/]P#.C\____
-M@\0,:@"-1QA0BU4(_W(,Z/S___^#Q`QJ`(U''%"+10C_<`SH_/___X/$#&H`
-MC4<D4(M5"/]R#.C\____@\0,:@"-1R!0BT4(_W`,Z/S___^#Q`QJ`(U'+%"+
-M50C_<@SH_/___X/$#&B\````C4<T4(M%"/]P#.C\____@\00_D7S@'WS`P^&
-MK/[__X!]\@$9VX'C``#__X'#```#`(/L!&H`C4,,4(M5"/]R#.C\____@\0,
-M:@"-0Q!0BT4(_W`,Z/S___^#Q`QJ`(U#%%"+50C_<@SH_/___X/$#&H`C4,8
-M4(M%"/]P#.C\____@\0(@\,@4XM5"/]R#.C\____)1P<'!P-`P,#`X/$#%!3
-MBT4(_W`,Z/S___^#Q!#^1?*`??(!#X8'_O__C67T6UY?R<.)]E6)Y8/L#&C_
-M_\\/:&P$`0"+10C_<`SH_/___\G#C78`58GE4X/L!(M="(M#!+``/0``@%!T
-M)X/L"&@L#0``_W,,Z/S___^#R`&#Q`Q0:"P-``#_<PSH_/___X/$$(/L"&@`
-M#0``_W,,Z/S___\E__\`_X/$#%!H``T``/]S#.C\____@\0,:@!H!`T``/]S
-M#.C\____@\0,:@!H.`P``/]S#.C\____@\0,:/\``0!H!!T``/]S#.C\____
-M@\0,:@!H9!T``/]S#.C\____@\0,:@!H*`P``/]S#.C\____@\0,:@!H6!T`
-M`/]S#.C\____@\0,:@!H7!T``/]S#.C\____@\0,:@!H0!T``/]S#.C\____
-M@\0,:@!H1!T``/]S#.C\____@\0,:@!H2!T``/]S#.C\____@\0,:@!H4!T`
-M`/]S#.C\____BUW\R<.-=@!5B>6+50B+30S'00@`````BX)("0``B4$,@[I(
-M"0```'0)BX)("0``B4@(B8I("0``@[I$"0```'4&B8I$"0``R<.)]E6)Y5.+
-M70B+30R#>0@`=1B+00R)@T@)``"%P'04QT`(`````.L+B?:+40B+00R)0@R#
-M>0P`=1F+00B)@T0)``"%P'05QT`,`````.L,C78`BU$,BT$(B4((QT$(````
-M`,=!#`````!;R<.)]E6)Y5=64X/L#(M]"(MU#(M=$(,[`'49@^P$:B"-0P10
-MC4844.C\____@\00ZQV)]H/L!&HDC4,$4(U&%%#H_/____Z'4`D``(/$$(L#
-MB4805E?H^?[__\<&`````/Z'/`(``(UE]%M>7\G#D%6)Y593BUT(BW4,@WX0
-M`'0&_HM0"0``5E/H"O___XN#U`D```^V5@2)E(-4"0``0(F#U`D``,<&`0``
-M`/Z+/`(``(UE^%M>R<.-=@!5B>6*10@\`W82#[;(C4P)`K@!````T^#K$(GV
-M#[;(C4P)`;@!````T^#)PU6)Y593BW4(#[9=#%/HPO___X/L!`E&5%/H`NC_
-M_P4<`0``B00D_W8,Z/S___^#Q`R)V8/A`[@``0``T^#WT%"#XP3!^P*#^P$9
-MP"4``/__!10``P!0_W8,Z/S___^#Q`S_=E1H9!T``/]V#.C\____@\0(:&0=
-M``#_=@SH_/___XUE^%M>R<-5B>53@^P$BUT(#[9%#%#H./____?0(T-4B4-4
-M4&AD'0``_W,,Z/S___^+7?S)PY!5B>575E.#[!"*70R+10B+0`R)1?`/MM.+
-M10B+=)`DBWXPQX8T`@```0```(/B!,'J`HG9@^$#N`$!``#3X/?04(#Z`1G`
-M)0``__\%%``#`%#_=?#H_/___X/$#&H`BT8P@\`(4/]U\.C\____@\0(#[;;
-M4_]U".A4____@\0(C8<<`0``4/]U\.C\____QX9``@```0```(/$#&H!@\<H
-M5_]U\.C\____C67T6UY?R<.-=@!5B>575E.#[!"+10B+>`P/MG4,BT2P)(M8
-M,,>`-`(```````!J`H/#*%-7Z/S___^#Q`A35^C\____@\0(5O]U".A._O__
-MC67T6UY?R<.)]E6)Y593BUT(BT,HBW`,_W40_W4,4XN#V`D``,'@!0-#$%#H
-MF>?__XN3V`D``$*#XA^)D]@)``#^@U$)``"#Q`R+0QPE`/S__\'B!0G04(M#
-M,(/`%%!6Z/S___^-9?A;7LG#B?95B>53@^P$BUT(:@!J`FH`4^A:]O__B1PD
-MZ)[T__^)'"3H_/___X/$$(/X`74>QX-,"0```0```(/L"`^V`U#_<RCHF?W_
-M_X/$$(GVBUW\R<.-=@!5B>575E.#[!2+50B+?0R#QQ2+0BB+<`R+6C"-@QP!
-M``!05NC\____)<$```"#Q!"Z`````(/X0`^%T@$``(-_!`%U<(/L!`^V1Q%0
-MC8,$`0``4%;H_/___X/$#`^V1Q-0C8,(`0``4%;H_/___X/$#`^V1Q50C8,,
-M`0``4%;H_/___X/$#`^V1Q=0C8,0`0``4%;H_/___X/$#`^V1QE0C8,4`0``
-M4%;H_/___X/$$.LTB?9F]T<0`/]U(&;W1Q(`_W489O='%`#_=1!F]T<6`/]U
-M"&;W1Q@`_W0*N@````#I*@$``(/L!`^V1Q!0C8,$`0``4%;H_/___X/$#`^V
-M1Q)0C8,(`0``4%;H_/___X/$#`^V1Q10C8,,`0``4%;H_/___X/$#`^V1Q90
-MC8,0`0``4%;H_/___X/$#`^V1QA0C8,4`0``4%;H_/___X/$#`^V1QI0C8,8
-M`0``4%;H_/___X/$#`^V1QM0C8,<`0``4%;H_/___X/$$(,_`@^%A````(/L
-M"(V#(`$``%!6Z/S___]J9&H*4U;H_/___X/$(+H`````A<!T9(/L"(V#'`$`
-M`%!6Z/S___\EB0```(/$$+H`````@_@(=4+'1?``````@<,``0``D(/L!(M'
-M"`^W$%*#P`*)1PA35NC\____@\00_T7P@7WP_P```';:@6\,``$``+H!````
-MB?:)T(UE]%M>7\G#B?95B>575E.#[!"+=0C'1E0`````:@!H9!T``/]V#.C\
-M____QT9<`````,=&8`````#'1F0`````QT9H`````,=&;`````#'1G``````
-MQT9T`````,9&>`&#Q!"X`````(-^(``/A',"``"X`````&:!?@:!4`^%8@(`
-M``^V5@6#^@$/A%4"``"#^@%_!H72=`GK&8/Z`G0+ZQ+'1F`!````ZQ#'1F0!
-M````ZP?'1F@!````LP"#[`@/MM.)T(/@`\'@"(V(=`$``/;"!'0'!70!`P#K
-M!HV!```"`%#_=@SH_/___P^VRXG"@>+@````P>H%B%0Q>B4`&```P>@+B(0Q
-M@@```(/$$$.`^P=VIX/L#%;H8O7__XDT).AJ]___B30DZ(+W__^#Q`QJ`&CP
-M!`$`_W8,Z/S___^#Q`AH+`T``/]V#.C\____B<>#Y_Z#Q`Q7:"P-``#_=@SH
-M_/___X/$"&@`#0``_W8,Z/S___^#Q!"H,'0YBT9$J>`#`(!T""4?_/]_B49$
-M@WY<`702@WY@`70,@WYD`70&@WYH`743BT9$J!!T#(/@[XE&1.L$@V9$S[,`
-M@^P(#[;#4%;H__+__X/$$$.`^P=VZH/L!/]V1&@`#```_W8,Z/S___^#Q`S_
-M=DAH*`P``/]V#.C\____@\0,_W9,:%P=``#_=@SH_/___[,`@\00@^P$#[;#
-M_W2&$(#[`1G`)0``__\%#``#`%#_=@SH_/___X/$#`^VP_]TAAB`^P$9P"4`
-M`/__!1```P!0_W8,Z/S___^#Q!!#@/L!=K/'1E15JP8`LP")]H/L"`^VPU!6
-MZ,OA__^#Q!!#@/L'=NJ#[`QH4,,``.C\____@\00@WYD`70&@WYH`75$OP``
-M``"S`(UV`(/L"`^VPXE%\%!6Z/S___^#Q!"%P'4+9K@``8I-\-/@"<=#@/L'
-M=MB#[`17:`#_``!6Z/WG__^#Q!"X`0```)"-9?1;7E_)PU6)Y8/L#&H`:&0=
-M``"+10C_<`SH_/___[@!````R<.058GEQP4``````0```,G#D%6)Y<<%````
-M``````#)PY!5B>564XMU"(I5#`^VPHM<AB2X`````(7;="P/ML)0Z$C@__^#
-M[`B)0S")<RC'@TP)````````QX,T`@```````%/HX>[__XUE^%M>R<.)]E6)
-MY0^V50R+10B+5)`DN`````"%TG0-@[I,"0```0^5P`^VP,G#B?95B>564XMU
-M"(I%#(G"@^(#B='!X0B-D0`!``"H!'0)C9D``0,`ZP>0C9H```(`@^P(4_]V
-M#.C\____@^`/@\00@_@!=`^#^`%R0H/X`W0UZSN-=@"#[`A3_W8,Z/S____'
-M!"1`#0,`Z/S___^#Q`A3_W8,Z/S___^#X`^#Q!"#^`-U"9"X`0```.L&D+@`
-M````C67X6U[)PU6)Y5=64X/L+(M]"(I%#(A%\X/@`XA%YP^V5?.)T(/@!(G&
-MP>X"BU27)(M/#(E-[+@`````A=(/A!\"``"+0C")1>BX`````(.Z3`D```$/
-MA`<"``"#[`@/ME7SB57<4E?HYM___X/$#&H$BUWH@\,H4_]U[.C\____@\0(
-M4_]U[.C\____QP0D&0```.C\____@\0,:@!3_W7LZ/S___^#Q`A3_W7LZ/S_
-M__^#Q`C_==Q7Z-3O___'1>``````@\00#[9%YXG!P>$(B4W4@<$(`0``B4W8
-MP>`(B470@^P(BU74C8((`0,`B?&$R74)BU78C8(```(`4/]W#.C\____B<.#
-MX_"#RP&#Q`Q3BT70C9`(`0``C8`(`0,`B?&$R74&C8(```(`4/]W#.C\____
-M@\0(#[9%YXG"P>((C8((`0``B?&$R70+C8((`0,`ZPB-=@`%```"`%#_=PSH
-M_/___\<$)!D```#H_/___X/C\(/$#%,/MD7GB<+!X@B-@@@!``")\83)=`J-
-M@@@!`P#K!XGV!0```@!0_W<,Z/S___^#Q`@/MD7GB<+!X@B-@@@!``")\83)
-M=`J-@@@!`P#K!XGV!0```@!0_W<,Z/S____'!"30!P``Z/S___^#Q`@/MEWS
-M4U?H_/___X/$$(7`=1[_1>"#?>`##X7=_O__@^P(4U?H^MW__[@`````ZTN#
-M[`B+1>@%'`$``%#_=>SH_/___R7`````@\00@_A`=!6#[`@/MD7S4%?HQ-W_
-M_[@`````ZQ6#[`@/MD7S4%?HK]W__[@!````B?:-9?1;7E_)PU6)Y5=64X/L
-M#(M5"`^V=10/MD4,BUR")+D`````A=L/A(L```"+4@R)5?"+>S"Y`````(.[
-M3`D```%T=(/L"%?_=?#H_/___XG"@\00@WT0`'4IC4;_N0`````\'W=1QX,X
-M`@```````(/BP(GQ#[;!2`G"@,X"ZQ.-=@#'@S@"```!````@>+`_?__@WL,
-M`74&@,X!ZP20@.;^@^P$4E?_=?#H_/___[D!````C78`B<B-9?1;7E_)PXGV
-M58GE4X/L!(M="(I-#`^VP8M4@R2X`````(72="JX`````(.Z3`D```%T',>"
-M3`D```$```"#[`@/ML%04^B2]/__N`$```"+7?S)PU6)Y5.#[`2+70B*50P/
-MML*Y`````(-\@R0`="`/MM*+1),DQX!,"0```````(/L"%)3Z`7U__^Y`0``
-M`(G(BUW\R<.058GE4X/L!`^V50R+10B+7)`DN`````"%VW0HN`````"#NTP)
-M```!=!IJ`&H"_W404^CFZ___B1PDZ"KJ__^X`0```(M=_,G#58GE#[95#(M%
-M"(M4D"2X_P```(72=`</MH(\`@``R<-5B>564XM5"(MR#`^V10R+1((DN@``
-M``"%P'18BU@P@^P(C4,L4%;H_/___X/$$(-]$`%U'[H`````J`)U-H/L!&H"
-MC4,L4%;H_/___X/$$.L=B?:Z`````*@"=!>#[`1J`(U#+%!6Z/S___^#Q!"Z
-M`0```(G0C67X6U[)PXUV`%6)Y5=64X/L#(I=#`^V=1`/MGT4B-J#X@.)V(/@
-M!,'H`O?&^````'4(]\?\````=`NX`````.F)````D`^VTHG1P>$(C9%T`0``
-MA,!T#H'!=`$#`(E-\.L,C78`@<(```(`B57P@^P(_W7PBT4(_W`,Z/S___\D
-M'XGRP>(%@>+@````"="`Y.>)^L'B"X'B`!@```G0@\0,4/]U\(M5"/]R#.C\
-M____#[;#B?F+50B(C!""````B?&(3!!Z@\00N`$```"-9?1;7E_)PU6)Y5=6
-M4X/L%(MU"(I=#+\#````(=^#XP3!ZP*`^P$9P"4``/__!1@``P!0_W8,Z/S_
-M__^)^0^VT8U*&+H!````T^()T(/$#%"`^P$9P"4``/__!1@``P!0_W8,Z/S_
-M__^#Q`B`^P$9P"4``/__!1@``P!0_W8,Z/S___^#Q!"X`0```(UE]%M>7\G#
-M58GE5U93@^P4BW4(#[9]#(GX@^`#B$7SB?@/MM")T(/@!(G#P>L"4E;H;NK_
-M_X/$"(#[`1G`)0``__\%&``#`%#_=@SH_/___P^V3?.#P1BZ_O___]/"(="#
-MQ`Q0@/L!&<`E``#__P48``,`4/]V#.C\____@\0(@/L!&<`E``#__P48``,`
-M4/]V#.C\____@\0(#[9%\XG"P>((C8((`0``A-MT"HV""`$#`.L'B?8%```"
-M`%#_=@SH_/___X/@\(/(`8/$#%`/MD7SB<+!X@B-@@@!``"$VW0)C8((`0,`
-MZP:0!0```@!0_W8,Z/S___^#Q`B)^@^VPE!6Z)OI__^#Q!"X`0```(UE]%M>
-M7\G#C78`58GE5U93@^P4BWT(BW40BD4,B$7SBT<,B47L#[9%\XM<AR2)PH/B
-M`XG1P>$(C9%T`0``J`1T"(V!=`$#`.L&C8(```(`4/]W#.C\____B498@\00
-MA=MU$,<&`````+@!````Z?\```"+0S")1>B#[`@/MD7S4%?H_/___XD&@\00
-MN`$```"#/@`/A-@```"+@TP)``")1BR+@S@"``")1C"*@SP"``"(1C2Z````
-M`)"*1!-JB$06!$*#^B=V\H/L"/]UZ/]U[.C\____B48X@\0(BT7H@\`04/]U
-M[.C\____B48\@\0(BT7H@\`44/]U[.C\____B49`@\0(BT7H@\`84/]U[.C\
-M____B49$@\0(BT7H@\`<4/]U[.C\____B49(@\0(BT7H@\`@4/]U[.C\____
-MB49,@\0(BT7H@\`D4/]U[.C\____B490@\0(BT7H@\`H4/]U[.C\____B494
-MN`$```"-9?1;7E_)PY!5B>6#[#S'1<@`````BT40B47,BT44B474BT489HE%
-MV(M%'&:)1=J+12")1=R+122)1>"+12B)1>2+12R)1>B-1<A0#[9%#%#_=0CH
-M_/___\G#B?95B>575E.#[`R*10R(1?,/ML"+50B+=((DN`0```"%]@^$BP$`
-M`+@!````@[Y,"0````^$>0$``+@"````@+X\`@``'P^$9P$``(N&U`D``$B)
-MAM0)``"+O(94"0``C03]`````"GXC83&1`(``(E%[(GZB%`$BT40@S@`#X7.
-M````B<.#PP2#OC@"```"=0S'0P0!````ZT>-=@`/MT,,#[=3#E#_<PA2_W8(
-MZ/O6__^#Q!")0P2#^`%U)(-^"`!U'HN&U`D``(F\AE0)``!`B8;4"0``N`,`
-M``#IT0```("^4`D```!U4X.^-`(```!U(H/L"`^V7?-3_W4(Z/KM__^#Q`A3
-M_W4(Z![N__^#Q!"-=@"#[`3_=1#_=>Q6Z&WL__^#Q`R+11"#P`10_W7L5NCZ
-M[O__@\00ZW&0@^P$_W40_W7L5NA%[/__@\00ZUR#[`3_=1#_=>Q6Z#'L__^#
-MQ!"`OCP"```!=4&#OC0"```!=1.#[`@/MD7S4/]U".A<[O__@\00@^P(_W7L
-M5NA5[___@\00A<!U$O]U[%;H6>S__[@!````ZP>)]K@`````C67T6UY?R<.-
-M=@!5B>575E.#["2+10B+0`R)1>1H8!T``%#H_/___XG&BU4(BU)4B57P@\00
-MN`````"%U@^$9P$``/?&```$`'0X@^P(:%@=``#_=>3H_/___XG#@\0,]]!0
-M:%@=``#_=>3H_/___VH`4VH`_W4(BU4(_U(@@\0@B?;&1>L`]\;_`0``#X0`
-M`0``@'WK`1G;@>,``/__@<,4``,`@^P$:N]3_W7DZ/S___^#Q`A3_W7DZ/S_
-M__^)QX/$#/?0@\@04%/_=>3H_/___X/$"(!]ZP$9P"4``/__!0@``P!0_W7D
-MZ/S___^)1>"S`(/$$`^V1>N)1=B0#[;+N``!``#3X"'XB47LN`$```#3X(GR
-M@^(!(?AU!(72="&#[`174E"+1>"#X!]0#[;#4`^V1>M0_W4(Z'?;__^#Q""#
-M?>P`=#:+5=B)5=R)T,'@`@G8#[;`4.@XZ___@\0$A47P=!B#[`0/ML-0_W7<
-M_W4(Z`+>__^#Q!"-=@#![@+!;>`(0X#[`P^&;____^L$D,'N"-'N_D7K@'WK
-M`0^&XO[__[@!````C67T6UY?R<.058GE@^P,:@!H9!T``(M%"/]P#.C\____
-MN`$```#)PY!5B>6#[`R+10C_<%1H9!T``/]P#.C\____N`$```#)PU6)Y5=6
-M4X/L#(MU$(M]%+L`````.?-S.8/L"(M%#`4<`0``4/]U".C\____@\00A,!X
-M#:@!#Y3`#[;`ZQF-=@"#[`Q7Z/S___^#Q!!#.?-RQ[@`````C67T6UY?R<.)
-M]E6)Y5.#[`B+70AJ`(M#,`4@`0``4(M#*/]P#.C\____@\0(BT,P!2`!``!0
-MBT,H_W`,Z/S___^+7?S)PU6)Y5.#[`B+70AJ`HM#,`4@`0``4(M#*/]P#.C\
-M____@\0(BT,P!1P!``!0BT,H_W`,Z/S___^+7?S)PU6)Y5=64X/L#(MU"(M&
-M*(M`#(E%\(M^,+L`````N`````"#OC0"```!#X2M````@^P(C8<@`0``4/]U
-M\.C\____@\00J(%T$(/L#&HRZ/S___^#Q!"-=@"#[`B-AR`!``!0_W7PZ/S_
-M__^#Q!"H@70XB=A#9CVW"W<H@^P(#[8&4/]V*.C\____@\00A<!T3(/L#&CH
-M`P``Z/S___^#Q!#KMK@`````ZS-J9&H*5_]U\.C\____@\0(C8<<`0``4/]U
-M\.C\____)<$```"#Q!"#^$`/E,`/ML"-=@"-9?1;7E_)PU6)Y5=64X/L#`^V
-M50R+10B+7)`DN`````"%VW1KBT,HBW@,BW,PN`````"#NTP)```!=%2#[`Q3
-MZ/S___^#Q`QHX0```(V&'`$``%!7Z/S___]J9&@0)P``5E?H_/___X/$((7`
-M=1&#[`Q3Z/S___^X`````.L1D(/L#%/H_/___[@!````B?:-9?1;7E_)PU6)
-MY593BTT(BE4,#[;"BT2!)+X`````A<!T<8U8-(/L#&CL````:@!J`&H`:@!J
-M`&H`:``!``!3:@!J`0^VPE!1Z/S___^#Q$"^`````(7`=#KV@Z````#@="RQ
-M`+X!````@+O^`0``I74AN@`````/M\("#!A"9H'Z_P%V\KX`````A,EU!;X!
-M````B?"-9?A;7LG#C78`58GE@^P(#[95#(M%"(M4D"2X`````(72=!>X````
-M`(.Z3`D```%T"8/L#%+H_/___\G#D%6)Y8/L%&CO````:@`/MD4@4`^V11Q0
-M#[9%&%`/MD444`^V11!0:@!J`&H`:@`/MD4,4/]U".C\____R<.-=@!5B>57
-M5E.#[`R*10R(1?.+32!FB4WPBT4D9HE%[HM-*&:)3>R+?2R+=3"*732*13B(
-M1>L/MD7SN@````"+30B#?($D`'0^@^P,#[9%ZU`/ML-0#[?&4`^WQU`/MT7L
-M4`^W1>Y0#[=%\%#_=1S_=1C_=13_=1`/MD7S4/]U".C\____B<*)T(UE]%M>
-M7\G#B?95B>575E.#['B+10B+52!FB578BTTD9HE-R(M5*&:)5;B+32QFB4VH
-MBU4P9HE5F(I--(A-EXI5.(A5E@^V50R+7)`DBW`,BWLP4^BA_/__@\00N@``
-M``"%P`^$K0(``(/L#%/H_/___X/$$(-]%`%U>X/L!(M-V`^VQ5"-AP0!``!0
-M5NC\____@\0,BU7(#[;&4(V'"`$``%!6Z/S___^#Q`R+3;@/ML50C8<,`0``
-M4%;H_/___X/$#(M5J`^VQE"-AQ`!``!05NC\____@\0,BTV8#[;%4(V'%`$`
-M`%!6Z/S___^#Q!#K/8UV`/=%V`#_``!U)_=%R`#_``!U'O=%N`#_``!U%?=%
-MJ`#_``!U#/=%F`#_``!T#8UV`+H`````Z>8!``"#[`0/MD784(V'!`$``%!6
-MZ/S___^#Q`P/MD7(4(V'"`$``%!6Z/S___^#Q`P/MD6X4(V'#`$``%!6Z/S_
-M__^#Q`P/MD6H4(V'$`$``%!6Z/S___^#Q`P/MD684(V'%`$``%!6Z/S___^#
-MQ`P/MD674(V'&`$``%!6Z/S___^#Q`P/MD664(V''`$``%!6Z/S___^#Q!"#
-M?1``=3MJ9&CPN@0`5U;H_/___X/$$(7`=1.#[`Q3Z/S___^Z`````.DB`0``
-M@^P,4^C\____N@$```#I#P$``&ID:/"Z!`!75NC\____@\00A<!U$X/L#%/H
-M_/___[H`````Z><```"#[`B-AQP!``!05NC\____@\00J`AU$X/L#%/H_/__
-M_[H`````Z;T```#'19``````BT4<.460<VJ-EP`!``")58R`?9``=15J9&A0
-MPP``5U;H_/___X/$$(7`=&N#?1`!=1N#[`C_=8Q6Z/S___^+39"+51AFB01*
-M@\00ZQJ#[`2+39"+51@/MP1*4/]UC%;H_/___X/$$/]%D(M-'#E-D'*?:F1H
-M4,,``%=6Z/S___^#Q!"%P'4@@^P,4^C\____N@````#K'X/L#%/H_/___[H`
-M````ZP^#[`Q3Z/S___^Z`0```)")T(UE]%M>7\G#B?95B>575E.#[!"+70B+
-M0RB+<`R+>S!J!HV'(`$``%!6Z/S___^#Q`B+0S`%(`$``%!6Z/S____'!"0*
-M````Z/S___^)'"3H_/___\<$)/0!``#H_/___\<$)/0!``#H_/___\<$)/0!
-M``#H_/___\<$)/0!``#H_/___[L`````@\00B?:#[`B-AQP!``!05NC\____
-M@\00A,!X";@!````ZR")]H/L#&CT`0``Z/S___^#Q!!#@?L/)P``=L>X````
-M`(UE]%M>7\G#B?95B>53@^P0BUT(4^@D____@\00N@$```"#^`%T%X/L#&CT
-M`0``Z/S___^)'"3H`O___XG"B="+7?S)PY!5B>564XMU"(/L!&B@````H00`
-M``"+0!@%```$`%!6Z/S___^[`````(/$$(/L"*$$````BT`0!0``!`!05NC\
-M____@\000X/[!'[@NP````"-=@"#[`BA!````(M`%`4```0`4%;H_/___X/$
-M$$.#^P5^X+L`````C78`@^P(H00```"+0!`%```$`%!6Z/S___^#Q!!#@_L$
-M?N"-9?A;7LG#D%6)Y5.#[`B+70AH@````*$$````BT`,!0``!`!04^C\____
-M@\0,:+````"A!````(M`&`4```0`4%/H_/___XM=_,G#58GE5E.+=0B#[`Q6
-MZ`?___^#Q`QJ`*$$````BT`(!0``!`!05NC\____@\0(H00```"+``4```0`
-M4%;H_/___XC#B30DZ'+___\/MMN)V(UE^%M>R<.)]E6)Y5=64X/L%(M="&@L
-M#0``4^C\____B<>#Q`R#R`%0:"P-``!3Z/S___^#Q`AH\`0!`%/H_/___XG&
-M@^!B@\00@_AB=!J#[`2)\(/(8@^VP%!H\`0!`%/H_/___X/$$(/L"&@```0`
-M4^C\____B1PDZ$K^__^#Q`QJ!Z$$````BT`(!0``!`!04^C\____@\0,:A&A
-M!````(L`!0``!`!04^C\____@\0,:@6A!````(M`"`4```0`4%/H_/___X/$
-M#&H1H00```"+``4```0`4%/H_/___XD<).B$_O__@\0,5FCP!`$`4^C\____
-M@\0(:/`$`0!3Z/S___^#Q`Q7:"P-``!3Z/S___^#Q!"-9?1;7E_)PY!5B>57
-M5E.#[!2+70AH+`T``%/H_/___XG'@\0,@\@!4&@L#0``4^C\____@\0(:/`$
-M`0!3Z/S___^)QH/@8H/$$(/X8G0:@^P$B?"#R&(/ML!0:/`$`0!3Z/S___^#
-MQ!"#[`AH```$`%/H_/___XD<).@R_?__@\0,:@>A!````(M`"`4```0`4%/H
-M_/___X/$#&H`H00```"+``4```0`4%/H_/___X/$#&H%H00```"+0`@%```$
-M`%!3Z/S___^#Q`QJ`*$$````BP`%```$`%!3Z/S___^)'"3H;/W__X/$#%9H
-M\`0!`%/H_/___X/$"&CP!`$`4^C\____@\0,5V@L#0``4^C\____@\00C67T
-M6UY?R<.058GE4X/L$(M="%/H@/S__X/$#&H*H00```"+0`@%```$`%!3Z/S_
-M__^#Q`QJ`*$$````BP`%```$`%!3Z/S___^)'"3HZ_S__X/$"&@!``0`4^C\
-M____@\00NO____^H`G50@^P,4^@D_/__@\0,:@&A!````(L`!0``!`!04^C\
-M____B1PDZ*C\___'!"1D````Z/S___^#Q`AH`0`$`%/H_/___]'H@^`!@\00
-M@_@!&=*)T(M=_,G#B?95B>575E.#[!2+?0B*10R(1?.+7PQH+`T``%/H_/__
-M_XE%[(/$#(/(`5!H+`T``%/H_/___X/$"&CP!`$`4^C\____B<:#X&*#Q!"#
-M^&)T&H/L!(GP@\AB#[;`4&CP!`$`4^C\____@\00@^P(:```!`!3Z/S___^#
-MQ`R*1?.(1WD/ML!0:`#@!0!3Z/S___^#Q`Q6:/`$`0!3Z/S___^#Q`AH\`0!
-M`%/H_/___X/$#/]U[&@L#0``4^C\____@\00C67T6UY?R<.-=@!5B>6#[`B+
-M50B*30R`?1``=`ZX`0```-/@"$)YZPR)]KC^____T\`@0GF#[`@/MD)Y4%+H
-M_/___\G#B?95B>575E.#[!2+?0C&1?,`:"P-``!7Z/S___^)1>B#Q`R#R`%0
-M:"P-``!7Z/S___^#Q`AH\`0!`%?H_/___XE%[(/@8H/$$(/X8G0;@^P$BD7L
-M@\AB#[;`4&CP!`$`5^C\____@\00@^P(:```!`!7Z/S___^#Q`AH```$`%?H
-M_/___X/$$&8]5:H/A?4```"^`````(UV`+L`````.?-_)XUV`(/L!&B@````
-MH00```"+0!@%```$`%!7Z/S___^#Q!!#.?-^W('^R````'X0@^P,:@'H_/__
-M_X/$$(UV`(/L"&@```0`5^C\____B<.#Q`QHL````*$$````BT`8!0``!`!0
-M5^C\____@\009H'[5:IU%$:!_L<````/CG7___]F@?M5JG1;@^P$:+````"A
-M!````(M`&`4```0`4%?H_/___X/$"&@```0`5^C\____@\009CU5JG4HQD7S
-M`8/L#%?H2OK__X/$$#P^=12#[`Q7Z,+\__^#Q!"%P'4$QD7S`H/L!&BP````
-MH00```"+0!@%```$`%!7Z/S___^#Q`S_=>QH\`0!`%?H_/___X/$"&CP!`$`
-M5^C\____@\0,_W7H:"P-``!7Z/S___^#Q!`/MD7SC67T6UY?R<-5B>564XMU
-M"+L`````C78`QP4$````B````(/L#%;H_?W__X/$$(3`=2/'!00```"D````
-M@^P,5NCC_?__@\00A,!U"4.!^^<#``!^PP^VP(UE^%M>R<,`````````````
-M``````````````````````0`````````````````````````````````````
+M?T5,1@$!`0D```````````$``P`!``````````````#LQP```````#0`````
+M`"@`#``)`%6)Y5=64X'L+`(``(M]"(M'#(F%Y/W__XUWO+`"@'\!`'4*@'\"
+M`1G`@^`"0(@&QT8$`````(!.`02+1PR)1@B+5Q"Y`````(E6#(E.$`^V!HL$
+MA0````")1CR`/@-U.(G0B<J#P/:#TO^)1@R)5A"-E>C]__]2:B"+1Q"#Z`I0
+M5^C\____@\00@;WH_?__\Q9X6G09C78`#[8&BP2%`````(E&0(!.`03I>@8`
+M`(/L"&B0````C8WH_?__4>C\____@\00A,!US_:%\?W__P)T(L9'"`&*A?+]
+M__^(1PLZ1PES$(/L"`^VP%!7Z/S___^#Q!"#[`AH``(``(V%Z/W__U#H_/__
+M_X/$$(3`=!Z#[`1H<`$``&H`C87H_?__!9````!0Z/S___^#Q!"*E7O^__^(
+MTX/C`8I'!(/@_(C1@^$""=@)R(C3@^,$@^#SB-&#X0@)V`G(B-.#XQ"#X,^(
+MT8/A(`G8"<B(T8/A0(/@/X/B@`G("="(1P2H`704@^P$:@#0Z(/@`5!7Z/S_
+M__^#Q!"*1P2H!'05@^P$:@#`Z`.#X`%05^C\____@\00BD<$J!!T$X/L",#H
+M!8/@`5!7Z/S___^#Q!"*1P2H0'03@^P(P.@'#[;`4%?H_/___X/$$(J5\?W_
+M_X/B`8I&`8/@_@G0B$8!@+WX_?__`P^$E/[__X"]^/W__P!U$,8&`*$`````
+MB49`Z0L%``"#O>S]__\`#X1N_O__N@`````/MH7S_?__B<&#^`!^+[L`````
+MB=#!X`2-O>C]__\!^(!X$`@/AS_^__\/MD`0@SR#``^$,?[__T(YT7_6BX4`
+M_O__N@````")A=C]__^)E=S]__^+C8#^__^)R[D`````BX78_?__"<B+E=S]
+M__\)VHF%V/W__XF5W/W__[H`````C012C02`P>`$BXWD_?__C;P(<"(``(-_
+M!`!U#XM'2#N%[/W__P^$60$``$*#^@]^SXN%Y/W__XNX;"(``(7_="N+1PB+
+ME>3]__^)@FPB``"#[`1H\````&H`5^C\____BXWD_?__B4\(@\00BX7L_?__
+MB4=(BE=>@\H!B%=>9@^VA?S]__^#X`'1X(/B_0G"B%=>9HN%_OW__V:)1V"+
+MA=C]__^+E=S]__^)1V2)5VB*A?C]__^(!XJ%^_W__XA'1@^VR+@!````T^!F
+MB4=<QT<$`````(N5]/W__XE7#,='$`````"+A7S^__^)PK@`````"T<,"U<0
+MB4<,B5<0BH7Y_?__B$=$#[8'BP2%`````(E'/(/L!&H0C87H_?__@\`L4(V'
+MC````%#H_/___X/$#&H$C87H_?__@\`\4(V'G````%#H_/___X/$#&H0C87H
+M_?__@^B`4(V'X````%#H_/___X/$#&I`C87H_?__@\!`4(V'H````%#H_/__
+M_X/$$(N-W/W__SE/:'(?=PN+E=C]__\Y5V1V$HN%V/W__XN5W/W__XE'9(E7
+M:/:%\?W__P%T!(!/`0&*E?K]__^(E>/]__^`O?/]__\!#X9U`@``#[;"BT2'
+M;(F%U/W__XN%$/[__[H`````B878_?__B97<_?__BXV(_O__B<NY`````(N%
+MV/W__PG(BY7<_?__"=J)A=C]__^)E=S]__^#O=3]__\`#X6>`0``BY7D_?__
+MBY)L(@``B974_?__A=)T,8M""(N-Y/W__XF!;"(``(/L!&CP````:@!2Z/S_
+M__^+E>3]__^+A=3]__^)4`B#Q!"+A>S]__^+C=3]__^)04B*45Z#R@&(45YF
+M#[:%#/[__X/@`='@@^+]"<*(45YFBX4._O__9HE!8(N%V/W__XN5W/W__XN-
+MU/W__XE!9(E1:(J%"?[__XA!1(J%"/[__X@!B7D$BX4$_O__B4$,QT$0````
+M`(N%A/[__XG"N``````+00P+41")00R)41"*A0O^__^(04:+E=3]__\/MDI&
+MN`$```#3X&:)0EP/M@*+!(4`````B4(\#[8'BP2%`````(E"0(J-X_W__XA*
+M`P^VP8E4AVS^1T6#[`1J$(V%Z/W__X/`+%")T`6,````4.C\____@\0,:@2-
+MA>C]__^#P#Q0BX74_?__!9P```!0Z/S___^#Q`QJ$(V%Z/W__X/H@%"+A=3]
+M__\%X````%#H_/___X/$#&I`C87H_?__@\!`4(N%U/W__P6@````4.C\____
+M@\00]H7Q_?__`70*B[W4_?__@$\!`0^VA0K^__^+E=3]__^#?()L``^%@```
+M`(ET@FR*A0K^__^(1@/^0D6)5@0/M@*+!(4`````B49`BXW<_?__.4IH<E5W
+M"XN%V/W__SE"9'9(BY78_?__BXW<_?__B[W4_?__B5=DB4]HZRX/MH7C_?__
+M@WR';`!U((ETAVR)?@3^1T6*A>/]__^(1@,/M@>+!(4`````B49`C67T6UY?
+MR<-5B>564XMU#+L`````#[9&1(G"@_@`#XZX````@WR>;`!T"D,YVG_TZ:<`
+M``"X`0```(C9T^!F"49@@^P(5O]U".C\____B<*#Q!"%P`^$@0```,8``XA8
+M`XEP!(`^"`^4P,'@`XI*`8/A]PG!B$H!H0P```")0CP/M@:+!(4`````B4)`
+M]D8!$'05B,B#R!"(0@&+0E2)0@S'0A``````B52>;(I&7H/@_H/("HA&7L=&
+M9`````#'1F@`````_D9%@^P(4FH'Z/S___^`3EX$@\00D(UE^%M>R<.058GE
+M5U93@^P,BW4,#[8&@_@&='R#^`9_"X/X!`^,<@$``.L0@_@(#X3#````Z6(!
+M``")]HI&13I&1`^%5`$``(!.`02`9E[^OP````"`?D0`#X0]`0``D(M<OFR%
+MVW0@@#L#=AN#[`A3_W4(Z/S___^#Q!#V0UX$=`:`3EX$B?9'#[9&1#GX?\_I
+M!@$``(GV@$X!!(!^10)U"H!F7O[I\0```)"`9E[]@WYL`'41BT9PQD`#`(E&
+M;,=&<`````"+1FR`.`-U$8/L"%;_=0CH_/___X/$$(GV@$Y>!,=&9`````#'
+M1F@`````Z:4```"0BD9%.D9$=1R`3@$$BD9>@^#^B$9>9H-^8`!T:(/(`HA&
+M7NM@#[9&14`/ME9$.=!U4V:#?F``="&Y``````^W1F")PJ@!=0E!B=#3^*@!
+M=/>#?(YL`'4?ZP;V1EX"=1>`3@$$@$Y>!(/L"%;_=0CH_/___X/$$,=&9```
+M``#'1F@`````#[=&7+H`````@\#_@]+_]]#WTB-&9"-6:(E&9(E6:)"#?@0`
+M=1KV1EX$=!3H_/___XE&2(/L#%;H_/___X/$$(UE]%M>7\G#58GE5U93@^P,
+MBWT(O@````"-=@"-!':-!(#!X`2-G#AP(@``@WM(`'0B@WL$`'4<@^P(4U?H
+M_/___X/$$/9#`01T"<=#0`````")]D:#_@]^PHUE]%M>7\G#B?95B>575E.!
+M["@"``"+?0R*11"(A>?]__]7Z/S___^#Q!"`/PAU$H/L"%?_=0CH_/___X/$
+M$(UV`+X`````@']$``^&Q0```)"#?+=L``^$K0```(M$MVR`.`-V((/L!`^V
+MA>?]__]0_W2W;/]U".C\____@\00Z84```"0BURW;,9#`P#'0P0`````QT-8
+M`````(!C`?['0T``````@+WG_?__`'4.@#\&=0F#?P0`=#*-=@"#[`1H``(`
+M`&H`C97H_?__4NC\____C87H_?__4&HP:@"-0T10Z/S___^#Q"#K$8I7`8/B
+M`8I#`8/@_@G0B$,!@^P,4^C\____@\001HGR.%=$#X<\____@^P$:/````!J
+M`%?H_/___XM5"(N";"(``(E'"(FZ;"(``,='2`````"#Q!"-9?1;7E_)PU6)
+MY5=64X'L'`(``(M5#(M]$(M-%(L"BU@$B9WD_?__BUHDBU,8B97@_?__#[9`
+M`XF%W/W__XV5Z/W__X.]X/W__P!T#&8/MD,4@^`!.<AU)HF5X/W__X-['`!T
+M$%%24_]U"/]3'(/$$(7`=0JX`````.F6````#[=#-,'@"0^V<S")]HN5X/W_
+M_XL:N0```0!F@WH$`'0$#[=*!(G".<AV`HG*.[7<_?__=1!FB5<$9L='!@``
+MB1^#QPB0*=$!TRG0=2%&BY7D_?__#[9"1#G&=06^`````(N5Y/W__P^W0ES!
+MX`F%R76SBYW@_?__9H%[!@"`=`N#PPB)G>#]___K@F;'1_X`@+@!````C67T
+M6UY?R<.-=@!5B>575E.#[`R+10B+70R+>`2+4RB+2RR)5>B)3>R*2`-FBW,X
+M.$LP=1(/MT,VN@`````!1>@15>SK%9`X2S!V#P^W1URZ``````%%Z!%5[#A+
+M,'4'9@-S-(UV`#A+,74'9@-S,HUV`(![/`!T#CA+,',=.$LQ=Q+K%HGV.$LP
+M<P1F`W=<.$LQ=@9F`W=<B?:+31!FB7$,BT7HBU7LBTT0B4$$B5$(@\0,6UY?
+MR<.)]E6)Y5=64X/L'(M="(MU#&:+?@QFQT7F```/MDM&BT8$BU8(#ZW0T^KV
+MP2!T!XG0N@````")1>B)5>QFQT8X``#&1CP!#[9#1+H`````4E#_=>S_=>CH
+M_/___X/$$`^V2T8/I<+3X/;!('0'B<*X`````(E&*(E6+`^V0T2Z`````%)0
+M_W7L_W7HZ/S___^#Q!"(1C"(P6:+0UQ(9B-&!&:)1C9FBU-<9BG"9CGZ<@MF
+MB7XTOP````#K1F:)5C1F*==FQT7F`0"Z`0```(G0T^!F"48Z03A+1'4:L0"`
+M?CP`=`;&1CP`ZPQFBT8X9@-#7&:)1CAF.7M<<P9F*WM<Z\RX`0```-/@9@E&
+M.HA.,6:)?C(/MT7FC67T6UY?R<.)]E6)Y593BW4(BU4,BUHDBP(/MD@#N/[_
+M___3P&8A0SJ`>A4!=`:*0A6(0Q6#[`A25NC\____@\009H-[.@!U&H![%0!U
+M!,9#%0&#[`13_W,@5NC\____@\00C67X6U[)PU6)Y5=64X/L#(M]#(L'B47P
+M]D`!!'49QD<5`H/L!%?_=R#_=0CH_/___^G-````D(/L"%?_=?#H1/[__X/$
+M$&:#?SH`=1K&1Q4"@^P$5_]W(/]U".C\____Z9X```")]KX`````BU7P@'I$
+M``^$B@```(GV#[='.HGQT_BH`71L@^P,_W4(Z/S___^)PXM%\(M$L&R)1>R)
+M`XE[)(I7%(/B`HI#%(/@_0G0B$,4BE<4@^($@^#["="(0Q2*1PZ(0PY35_]U
+M[.@%_?__QT,@`````,=#'`````"#Q!13_W4(BU7L_U(\@\00C78`1HM-\`^V
+M040Y\`^/>/___XUE]%M>7\G#58GE@^P(BU4,BTH$BD$!P.@"@_`!@^`!@&(!
+M^X!A`?O^246`25X!@WE``'03A<!U#X/L"%'_=0C_44"#Q!")]LG#B?95B>56
+M4XM=$(MU%(M%#(M0)(M*&(7)=`QF#[9"%(/@`3GP=22#>AP`=!564U+_=0C_
+M4AR#Q!"Z`0```(7`=2>Z`````.L@B?:+`8M1!(D#B5,$@\,(C4$&@\$(9H,X
+M`'GGN@$```")T(UE^%M>R<.058GE5E.+=0@/M@:#Z`2#^`%W0;L`````@'Y$
+M`'0OB?:#?)YL`'03@^P,_W2>;.C-____@\00A<!U"K@`````ZQR-=@!##[9&
+M1#G8?].X`0```.L)BD8!P.@"@^`!C67X6U[)PU6)Y5=64X/L#(MU#(M>)(L[
+MBP:)1?"`?A4!#X30````]D,4`G1V@'L6``^%P````/9'7@(/A;8```#&0Q8!
+M@'@#`1G`@^`$BT0X;(E%\(7`=$-0Z$3___^#Q`2%P'0V@^P$:C1J`(U&*%#H
+M_/___XM%\`^V2`.X`0```-/@9HE#.HM%\(D&@\0(5O]U"/]0/.G'````BP:)
+M1?#K5/9#%`1T3O]U\.CR_O__@\0$A<!T(H/L!&HT:@"-1BA0Z/S___^#Q`A6
+M_W4(BT7P_U`\Z8D```"`>Q4!=!T/MU,ZBT7P#[9(`[@!````T^`YPG4'D(I&
+M%8A#%8/L"%;_=0CH_/___XM%\`^V2`.X_O___]/`9B%#.H/$$&:#>SH`=3Z`
+M>Q4`=03&0Q4!@^P$4_]S(/]U".C\____9O]/'H/$$&:#?QX`=1>+1R2%P'00
+M@^P(_W<H_W4(_]"#Q!")]HUE]%M>7\G#58GE4X/L!(M5#(M=$(M-%(M")(7)
+M=!F+0!")`V:+0@S!X`EFB4,$9L=#!@"`ZT60@W@8`'0F]D`4`70@BT@8D(L!
+MBU$$B0.)4P2#PPB-00:#P0AF@S@`>>?K&9"Z`````(-X'`!T$E%34/]U"/]0
+M'(G"ZP6Z`0```(G0BUW\R<-5B>575E.#[`R+10R+6"2)PHL`#[9(`[C^____
+MT\!F(4,Z@'H5`70&BD(5B$,5@^P(_W4,_W4(Z/S___^#Q!!F@WLZ`'5N@'L5
+M`'4XQD,5`8L+B4WPBW%DBWEHBTT,BU$(,?J+000Q\`G"=1@/MT$,N@`````!
+M\!'ZBTWPB4%DB5%HB?:#[`13_W,@_W4(Z/S___^+`V;'0!P``(/$#(L#@\`@
+M4&@`````_W4(Z/S___^#Q!"-9?1;7E_)PU6)Y5=64X/L#(M]#(MW)(!_%0%T
+M"XI'%8A&%>M[C78`@'\.('4^QD<5`(L&BT!PB0>#[`1J-&H`C4<H4.C\____
+MQD<6`,9'#C"*1Q2#X/V#R`2(1Q2#Q`B+!U?_=0C_4#SK;I#&1A4!BP:)1?"+
+M2&2+6&B+5P@QVHM'!#'("<)U%P^W1PRZ``````'($=J+3?")062)46B0@^P(
+M5_]U".C\____@\0,5O]V(/]U".C\____BP9FQT`<``"#Q`R+!H/`(%!H````
+M`/]U".C\____C67T6UY?R<.-=@!5B>575E.#[`R+?1"+312+50R+0B2%R71#
+MBU`0B1>+30QFBT$,P>`)9HE'!&;'1P8`@(L!@'@#``^$\@```(V"```!`&:#
+M?P0`=`</MT<$C00"B0?IUP```(UV`(G[BU4,#[=R#,'F"8-X&`!T)O9`%`%T
+M((M(&)"+`8M1!(D#B5,$@\,(C4$&@\$(9H,X`'GGZS60N@````"#>!P`#X22
+M````45=0_W4(_U`<@\00N@````"%P'1]ZPYFB7$$9L=!!@"`ZSV)]HGYB?:Z
+M```!`&:#>00`=`0/MU$$BUT,BP.`>`,`=!$Y\G81`3&)T&8I\&:)003K"SGR
+M<[Z#P0@IUG7)BU4,BP*`>`,`="(YSW0>B?:+`8M1!(D'B5<$@\<(C4$&@\$(
+M9H,X`'GGC78`N@$```")T(UE]%M>7\G#D%6)Y5=64X/L#(M]"(MU#(M>)(!^
+M%0%T#(I&%8A#%>F5````D(L&@'@#`'4PQD85`(L#BT!PB0:#[`1J-&H`C48H
+M4.C\____QD86`(/$"(L&5E?_4#SID0```(GV@^P$#[=&#,'@"5`#0Q!0_W,0
+MZ/S___^#Q!"%P'0&QD,5#.LXQD,5`8L+BT%DBU%HB47HB57LBU7L,U8(BT7H
+M,T8$"<)U%@^W1@RZ``````-%Z!-5[(E!9(E1:)"#[`A65^C\____@\0,4_]S
+M(%?H_/___XL#9L=`'```@\0,BP.#P"!0:`````!7Z/S___^-9?1;7E_)PY!5
+MB>575E.#[`R+?0B+70R+,\=&)`````#V1EX!#X5^`0``#[9##H/X`@^$$0$`
+M`(/X`G\0@_@!#X2C````Z5X!``")]H/X`P^%4P$``(M#!(M3"(E&%(E6&&:+
+M0PQFB48<@^P$#[=##,'@"5!J`/]S$.C\____9L=#.@,`QT7P`````(/$$(/L
+M#%?H_/___XG!QD`.,(M#!(M3"(E!!(E1"&:+0PQFB4$,@$D4!(E9),=!(```
+M``#'01P`````BU7PBT26;(D!@\0(45?_4#R#Q!#_1?"#??`!?JOIU````(M#
+M!(M3"(E&%(E6&&:+0PQFB48<@^P,5^C\____B<'&0`X@BT,$BU,(B4$$B5$(
+M9HM##&:)00R`210"B5DDQT$@`````,=!'`````"+1FR)`8/$"%%7_U`\@\00
+MZW:)]HM#!(M3"(E&%(E6&&:+0PQFB48<@^P,5^C\____B<'&0`X@BT,$BU,(
+MB4$$B5$(9HM##&:)00R`210"B5DDQT$@`````,=!'`````"+1FR)`8/$"%%7
+M_U`\@\00ZQ:)]L9#%0:#[`13_W,@5^C\____@\00@^P$C48@4&@`````5^C\
+M____C67T6UY?R<.)]E6)Y5=64X/L'(M]#(LW]D8!!'48QD<5`H/L!%?_=R#_
+M=0CH_/___^F8`0``]D<4('0JQT8D>!8``(E^*&:#?AX`#X5]`0``@^P(5_]U
+M".C=_?__@\00Z6D!``"0@WXD`'4^9H-^'`!T4P^W1ARZ``````-&%!-6&#M7
+M"'(_=P4[1P1V.`^W1PRZ``````-'!!-7"#E6&'((=R(Y1A1S'9#'1RP`````
+M@^P(5XU&(%#H_/___^D+`0``C78`9O]&'O9&7@-U>O9'%`)T=(M&;(M6<(`X
+M`W59@#H#=52+7P2)7>2+2EPI3>2+2&")3>B+4F`K6%QY`O?;@WWD`'D#]UWD
+M.UWD?13&1?,`A=)U-H-]Z`5V,,9%\P'K*L9%\P"#?>@`=06#^@5W&\9%\P'K
+M%9"`?F(`#Y1%\XI%\XA&8NL$QD7S`&;'1SH``+,`#[;#@WR&;`!T9HM$AFSV
+M0`$$=%SV1Q0$=04X7?-U48/L#/]U".C\____B47L@\0,:BA74.C\____#[;+
+MN`$```#3X&8)1SJ+5>R)>B3'0B``````QT(<`````(M$CFR)`H/$"%+_=0C_
+M4#R#Q!")]D.`^P%VBHGVC67T6UY?R<-5B>564XM-"(MU#(M>!`^V5@.`9@'[
+M@$M>`<=#9`````#'0V@`````_DM%@'M%`'4'@&,!^^L9D(I#7J@"=!&#X->(
+M0UZ%TG4'@&,!^XUV`/9#`01U&H-[0``/A.H```"#[`A34?]30(/$$.G:````
+MA=)U%(M3;,9"`P&+0W#&0`,`B4-LB5-P@WL$`'0)BT,$]D`!!'1UBT-L@#@#
+M=6V#[`A34>C\____B<*#Q!"%P'1:Q@`#QD`#`8E8!*$,````B4(\H1@```")
+M0D#V0P$0=!&`2@$0BT)4B4(,QT(0`````,=&!`````")4W"*0UZ#X/Z#R`J(
+M0U[^0T6#[`A2:@?H_/___X/$$(GV@WL$`'0+B?:+6P2#>P0`=?>+0U2)0UB+
+M0U")0U2+0TR)0U"+0TB)0TSH_/___XE#2,9#8P&#[`Q3Z/S___^-9?A;7LG#
+MC78`58GE5U93@>PL`@``BT4,BTT4BQ")E>3]__^+0"2)A=3]__^+6!C'A>#]
+M__\1````C97H_?__A=MT#&8/MD`4@^`!.<AU*HG3B[74_?__@WX<`'0045)6
+M_W4(_U8<@\00A<!U#+@`````Z0`!``")]HN]U/W__X!_,?\/A-,````/MT\T
+MP>$)O@```0!F@WL$`'0$#[=S!#GQ=DB0BY7D_?__BD(#B[W4_?__.D<P=12+
+M`XM3!(M]$(D'B5<$@\<(B7T0D"GQ@\,(O@```0!F@WL$`'0$#[=S!/^-X/W_
+M_SGQ=[F+E>3]__^*0@.+O=3]__\Z1S!U&8L#BU40B0)FB4H$9L="!@"`N`$`
+M``#K7Y`Y\7,VB<@#`XM]$(D'B?!F*<AFB4<$9H%[!@"`=0UFQT<&`("X`0``
+M`.LSBT409L=`!@``@\`(B440@\,(_XW@_?__@^P$BX7@_?__P>`#4%/_=1#H
+M_/___[@!````C67T6UY?R<.)]E6)Y8M5#(M-$(M%"(I``SI",'489HM"-&:)
+M00R+0BB+4BR)002)40CK&(GV9HM",F:)00S'000`````QT$(`````,G#58GE
+M5U93@^P(BU4(BT4,BU@$BW`(9HM`#&:)1?+'1>P`````N0````"`>D0`#X2<
+M````D(M\BFPY=Q!W!W)].5\,=GB+50R)6BB)<BR(2C"X`0```-/@9@E".@^W
+M1?*Z``````'8$?([5Q!R/G<%.T<,=C?'1>P!````C4$!BU4,B$(Q08M%[-/@
+M9@E".F:+1PQF*=AFB4(T9HM5\F8IPHG0BU4,9HE",NLDBT4,QD`Q_V:+5?)F
+MB5`TZQ,K7PP;=Q!!#[9"1#G(#X=E____BT7L@\0(6UY?R<.)]E6)Y593BW4(
+MBU4,BUHDBP(/MD@#N/[____3P&8A0SJ`>A4!=`:*0A6(0Q6#[`A25NC\____
+M@\009H-[.@!U&H![%0!U!,9#%0&#[`13_W,@5NC\____@\00C67X6U[)PU6)
+MY5=64X/L#(M]#(L'B47P]D`!!'49QD<5`H/L!%?_=R#_=0CH_/___^G)````
+MD%?_=?#HB_[__X/$"&:#?SH`=1G&1Q4"@^P$5_]W(/]U".C\____Z9T```"0
+MO@````"+5?"`>D0`#X2*````B?8/MT<ZB?'3^*@!=&R#[`S_=0CH_/___XG#
+MBT7PBT2P;(E%[(D#B7LDBE<4@^("BD,4@^#]"="(0Q2*5Q2#X@2#X/L)T(A#
+M%(I'#HA##E-7_W7LZ+G]___'0R``````QT,<`````(/$%%/_=0B+5>S_4CR#
+MQ!"-=@!&BTWP#[9!1#GP#X]X____C67T6UY?R<-5B>6#[`B+10R+4`2`8`'[
+M@&(!^_Y*18!*7@&#>D``=`^#[`A2_W4(_U)`@\00B?;)PXGV58GE4XM="(M-
+M#(N4BXPQ``"%TG0)BP*)A(N,,0``B=!;R<.058GE4XM="(M-#(M5$(N$DXPQ
+M``")`8F,DXPQ``!;R<-5B>575E.#[`R+10R[`(```#T`0```=V%FNP!`/0`@
+M``!W5F:[`"`]`!```'=+9KL`$#T`"```=T!FNP`(/0`$``!W-6:[``0]``(`
+M`'<J9KL``CT``0``=Q]FNP`!/8````!W%&:[@`"#^$!W"X/X(1G;@^/@@\-`
+MBT40#Z_#!?\/``#!Z`R)1?#'1>P`````N`````"!^P`0```/A]8```#_3?"#
+M??#_#X3&````D(/L#/]U".C\____B<;_1>R_`````(/$$+@`$```N@````#W
+M\X/X``^&BP```(UV`+@*````@?L`0```=U>P"8'[`"```'=-L`B!^P`0``!W
+M0[`'@?L`"```=SFP!H'[``0``'<OL`6!^P`"``!W);`$@?L``0``=QNP`X'[
+M@````'<1L`*#^T!W"H/[(`^7P`^VP)!05O]U".B2_O__`=Z#Q`Q'N``0``"Z
+M`````/?S.?@/AWC_____3?"#??#_#X4[____BT7LC67T6UY?R<-5B>564XMU
+M"(M=#+@`````.9ZX,0``<DIJ`E;H'/[__XG!@\0(A<!T-XD82X/[_W0OC78`
+MN@````"#OK0Q````=!2+EK0Q``"+`HF&M#$``/^.N#$``(E4F01+@_O_==2)
+MR(UE^%M>R<.-=@!5B>564XM="(MU#(L.28/Y_W0?D(M4C@2+@[0Q``")`HF3
+MM#$``/^#N#$``$F#^?]UXFH"5E/HN?W__XUE^%M>R<.)]E6)Y593BW4(BQY+
+M@_O_=!R#[`1H`!```&H`_W2>!.C\____@\002X/[_W7DC67X6U[)PY!5B>53
+MBUT(BPM)@_G_=">+1(L$N@````"#.`!T![@`````ZQ="@\`$@?K_`P``=NA)
+M@_G_==FX`0```%O)PXGV58GE@^P,:A!J`/]U".C\____R<-5B>6+30R#>10`
+M=`F+412+01")0A"+41"+012)`L=!$`````!J`%'_=0CH^?S__\G#C78`58GE
+M4XM5"(M-#(U:.(M".(E!%(7`=`F+4CB-012)0A")61")"UO)PU6)Y5=64XMU
+M&(M]'(M%#(M8.(7;="V)]CE[!'<?<@0Y,W,9BU44.5,,<A%W"(M5$#E3"'8'
+MN`````#K+XM;%(7;==5J`/]U".A;_/__B<.+11"+512)`XE3!(ES"(E[#%/_
+M=0SH;____XG8C67T6UY?R<.058GE4XM-"(I1+0^VVHT$W0`````IV(U<@3!"
+MB%$MB0O&0P4`QD,&`,9#!P")V%O)PXUV`%6)Y5=64XM]"(MU#+L`````#[96
+M*HU"_='X`<*#^@!^(XUV`/^TGK`'``!7Z/_]__^#Q`A##[96*HU"_='X`<(Y
+MVG_@:@=65^C7^___C67T6UY?R<.-=@!5B>575E.#[!R*10R(1?.+51AFB57P
+MBT4(BYBX,0``P>,##[?*#[95\XU"_='X`<(/K\HYRP^#X0````^V5?.)5>2)
+MT(E5X`^W5?"-0/W1^`-%Y(G3#Z_8BT4(!70Q``"+50@Y@G0Q```/A,L```"+
+MLG0Q``"+5@2+!HE0!(D"B3:)=@2#?A``=!Z#?A0`=`F+5A2+1A")0A"+5A"+
+M1A2)`L=&$`````"+1?!F.48H=4N*5?,X5BIU0XDVB78$BT40BU44B48@B58D
+MOP````"#?>0`?B"+7>"#[`R)^,'@!(V$,%@(``!0Z*/]__^#Q!!'.?M_XXGP
+MZ1L!``!6_W4(Z*/^__^#Q`B+50B+@K@Q``#!X`,YV`^"//___VH'_W4(Z(+Z
+M__^)QH/$"+@`````A?8/A-\```#K"K@`````Z=,```")-HEV!(M%$(M5%(E&
+M((E6)(M5\&:)5BB*1?.(1BK'1A@`````OP`````/MM"-0OW1^`'"@_H`#XZ4
+M````BT7P9L'H`P^WP(E%Z`^V5?.-0OW1^`'"B57L_W7H_W4(Z,7[__^)A+ZP
+M!P``@\0(A<!U,T^#__]T&9#_M+ZP!P``_W4(Z`W\__^#Q`A/@___=>AJ!U;_
+M=0CH[?G__[@`````ZS&)]H/L#(G[P>,$`?.-@]@'``!0Z)+\__^!PU@(``")
+M'"3HA/S__X/$$$<Y?>Q_AXGPC67T6UY?R<.058GE5U93@^P,BW48BT4,#[9(
+M1HM%$-/H)?\#``"+30R+432-'(*+.X7_="^+510S5R2+11`S1R`)PG48BU<$
+MBP>)4`2)`HD_B7\$B?CIF0```(GVBW\4A?]UT8/L#`^WQE#_=13_=1"+50P/
+MMD)$4/]U".AH_?__B<>#Q""%P'1HBTT,B4@<BP.)1Q2%P'0(BQ.-1Q2)0A")
+M7Q").XM%#(I81(A?*@^V2$:+11"+510/K=#3ZO;!('0'B="Z`````(E%Z(E5
+M[(M-#`^V042Z`````%)0_W7L_W7HZ/S___^#Q!`HPTN(7RN)^(UE]%M>7\G#
+MD%6)Y5=64X'LS````(M%#(I0%(C0T.B#\`&)P8/A`8F-5/___XM%#(-X&`!T
+M!?;"`70@C958____B950____:@%2_W4,_W4(BTT,_U$<@\00ZPR+10R+0!B)
+MA5#____'A3C___\```$`BY50____9H-Z!`!T"@^W2@2)C3C____'A4#___\`
+M````QX5,____`````(M%#(!X2``/A-P!``"+E4S___^+30R+5)$TB95$____
+MBHHP"0``B(U+____.(HQ"0``#X*8`0``BH5+____BY5$____.$(K#X1E`0``
+M#[;`B=%FBY2"$`D``&:+A($2"0``9HF%/O___XG09L'H`P^WP(F%-/___X/B
+M!V:)E3S___\/M\*)PL'B";@(````9BN%//___V:)A3S___]FBX4^____9CF%
+M//___W8'9HF%//___P^WA3S___^)QL'F"0^VA4O___^+C43___^+A(&P!P``
+MB=>+C33___\#?(@$D(N%./___SF%0/___W4R@X50____",>%./___P```0"+
+ME5#___]F@WH$`'0*#[=*!(F-./___\>%0/___P````"+G3C___\KG4#___\Y
+M\W8"B?.#O53___\`="&#[`13BX5`____BY50____`P)05^C\____@\00ZQ^-
+M=@"#[`135XN%0/___XN-4/___P,!4.C\____@\00`9U`____*=YT!P'?Z5?_
+M__^+A3S___]F*84^____=!G_A33___^Z`````&;'A3S___\(`.GK_O___H5+
+M____BI5+____BXU$____.)$Q"0``#X-H_O___X5,____BU4,#[9"2#N%3/__
+M_P^/)/[__X/L!&H`_W4,_W4(_U40C67T6UY?R<.)]E6)Y5=64X/L#(-]$`!T
+M!XM%#,9`%0O'1?``````BU4,@'I(``^$P0```(M%"`5\,0``B47LBU4(@<)T
+M,0``B57HC78`BT7PBU4,BUR"-,>#"`D```````")W[$`@'LJ`'9!B?8/ML'!
+MX`0!^(V0V`<``+X`````@[C8!P```'44@WH$`'4.@WH(`'4(@WH,`'0'B?:^
+M`0```(7V=2%!.$\J=\&X`````(7`=!R+5>R+0@2)6@2)$XE#!(D8ZQJX`0``
+M`.OCC78`BU7HBT($B5H$B1.)0P2)&/]%\(M5#`^V0D@[1?`/CUG___^#[`C_
+M=0S_=0CH0T```(UE]%M>7\G#C78`58GE5U93@^P\BW4,B[X("0``BT4(_XB\
+M,0``C48(BT@$BU8(B4H$B1&)1@B)0`2%_P^$Y0(``/9'%"`/A)<!``"+%XE5
+MZ`^W1BBZ``````-&(!-6)(E%X(E5Y&:+3BAFB4W>QX8("0```````(M%"`5T
+M,0``BU`$B7`$B0:)5@2),H"^,@D```%U<H!_#@)U8P^V1BO_M(:P!P``Z`/W
+M__^#Q`2%P'5,QH8R"0``#(M%Z(!(7@J+5>@/MT)<]]B9BTX@(<&+7B0ATXM%
+MZ#E8:'(B=P4Y2&1V&XM5Z`^W0ESWV)DC1B`C5B2+3>B)062)46B)]H"^,@D`
+M``%T&HJ&,@D``(A'%8/L"%?_=0CH)C\``.FI`P``BT7H#[=`7(E%N,=%O```
+M``"+3P2+7PB#P0&#TP"+1;CWX8E%T(E5U(M5N`^OTXMUU`'6BT6\#Z_!C00&
+MB474BTWD.<AR/7<(BU7@.570=C.#[`P/MT7>4/]UY/]UX/]UZ/]U".CT^?__
+MB;@("0``B4<T@\084/]U".B_#P``Z28#``"+3>@/MT%<N@`````#060346B+
+M3>0QT3-%X`G!=0^+1>"+5>2+3>B)062)46B#[`A7_W4(Z&4^``#IZ`(``(I'
+M24"(1TDZ1T@/A60"``#V1Q0$#X3"````QD7O`(!_2``/AJ````"+10@%=#$`
+M`(E%Q(M5"('"?#$``(E5P)`/MD7OBW2'-,>&"`D```````"`OC()```!=46)
+M=<BS`(!^*@!V)XGV@^P,#[;#P>`$BTW(C80(V`<``%#HB_7__X/$$$.+1<@X
+M6"IWVXM5Q(M"!(ER!(D6B48$B3#K&I"*AC()``"(1Q6+3<"+002)<02)#HE&
+M!(DP_D7OBD7O.$=(#X=X____@^P(5_]U".B,/0``@\00Z9@!``#&1>\`@'](
+M`'8GB?8/MD7OBW2'-("^,@D```%T"8J&,@D``(A'%?Y%[XI5[SA72'?;@'\5
+M`'49@^P$:)0I``!7_W4(Z&SY__^#Q!#I2`$``(/L!&H`5_]U".CJ^___@\00
+MZ3(!``")]H"^,@D```%U=XGWLP"`?BH`=B"0@^P,#[;#P>`$C80XV`<``%#H
+MGO3__X/$$$,X7RIWX8.^#`D```!T*HN&#`D``(F&"`D``,>&#`D```````"#
+M[`A6_W4(Z-H-``"#Q!#IR@```(M%"`5T,0``BU`$B7`$B0:)5@2),NM7C78`
+MBT4(!7PQ``"+4`2)<`2)!HE6!(DR@[X,"0```'0VBY8,"0``BH8R"0``B$(5
+M@^P$_[8,"0``:-!J``#_=0CH_/___\>&#`D```````#IT@```(GV_W88_W4(
+MZ/WS___'1A@`````BT8<@\0(@W@@`'09@^P$@\`@4&@`````_W4(Z/S___^#
+MQ!#K)8M-"(.YQ#$```!T&8/L!(G(!<0Q``!0:`````!1Z/S___^#Q!"+10B#
+MN,`Q````=&B`OC()```!=5^+1AR#>"P`=#V#[`Q0Z#$Z``"#Q!"%P'4M@^P$
+MBT8<_W`PBT8<_W`L_W4(Z/S___^+1AS'0"P`````BU4(_XK`,0``@\00BTT(
+M@[G`,0```'0-@^P,4>C\____@\00D(UE]%M>7\G#58GE@^P(BT4,BP"`>"X`
+M=!O&0"X`@^P$4&B(.0``_W4(Z/S___^#Q!"-=@#)PXGV58GE5U93@^P,BU4,
+MBWT0BT(DBP@/MD`)BX2!L`<``(E%\(M"!"M!(,'@"0^W<@S!Y@F)PH'B_P\`
+M`,'H#(E%[+@`$```B<,ITSGS=@*)\X-]%`!T#XM%[(M-\`-4@03K&XUV`(/L
+M#(M%[(M-\`-4@012Z/S___^#Q!")PHD79HE?!#GS=!5FQT<&``"#QPC_1>PI
+MWKH`````ZZ5FQT<&`("X`0```(UE]%M>7\G#B?95B>575E.+50B*0@H"0@N(
+M0@J-6@R^`0```.L3@'H*`'D*N`````#I\@```/Y""@^V2@J#^1]W$(GPT^"%
+M0@P/E<`/ML#K39"#^3]W$X/I((GPT^"%0P0/E<`/ML#K-9"#^5]W$X/I0(GP
+MT^"%0P@/E<`/ML#K'9"X`````(/Y?W<2@^E@B?#3X(5##`^5P`^VP(GVA<!T
+MA,9""P&->@P/MEH*O@$```#K!8GV_D(+#[9""XT,`X/Y'W<1B?#3X(5"#`^5
+MP`^VP.M.B?:#^3]W$X/I((GPT^"%1P0/E<`/ML#K-9"#^5]W$H/I0(GPT^"%
+M1P@/E<`/ML#K';@`````@_E_=Q.#Z6")\-/@A4<,#Y7`#[;`C78`A<!UD+`!
+M6UY?R<.058GE5U93@^P4BWT(BU4,BUHDBS.*0A6(0P925^C\____@\00@'L&
+M`75F4^BL_O__@\0$A<!T$<9#!@"#[`A35^B/````ZU>0@'L$`75"BD,(.$8K
+M=#HX0PEU-0^VR(G(P>`$C8PP6`@``(US#(L!"T,,B0&+000+1@2)002+00@+
+M1@B)00B+00P+1@R)00R0QD,%`H/L"%-7Z%[]__^-9?1;7E_)PXGV58GE4X/L
+M!(M=#,9#"P#&0PH`4^@<_O__@^P$4_]U".@(````BUW\R<.-=@!5B>575E.#
+M[!B+70R+,XM6'`^V0PB+?()L_W4(Z/S___^)P8DX@\00@'L$`74*@$@4`L9`
+M#B#K"(!(%`3&0`XP#[9#"KH``````T8@$U8DB4$$B5$(9@^V0PMFB4$,QT$<
+MD"\``(E9),=!(&0Q``"#[`A1_W4(_U<\C67T6UY?R<.-=@!5B>575E.#[`B+
+M?0R^`````,=%\`````"+10B)1>SK$X-]\']V"HGPZ4<!``"-=@#_1?"+5?"#
+M^A]W%[@!````BDWPT^"+50B%`@^5P`^VP.M:@_H_=QB-2N"X`0```-/@BU7L
+MA4($#Y7`#[;`ZSV#^E]W&(U*P+@!````T^"+5>R%0@@/E<`/ML#K(+@`````
+M@_I_=Q:-2J"P`=/@BU7LA4(,#Y7`#[;`C78`A<`/A&S___^[`0```(M5".L#
+MB?9#BTWP`=F#^1]W$;@!````T^"%`@^5P`^VP.M4@_D_=Q>#Z2"X`0```-/@
+MA4($#Y7`#[;`ZSJ)]H/Y7W<7@^E`N`$```#3X(5""`^5P`^VP.L>B?:X````
+M`(/Y?W<2@^E@L`'3X(5"#`^5P`^VP(GVA<!UC(M5\`%=\(GVB=#!Z`.(!+>(
+MT(/@!XA$MP&Q""C!B$RW`@^VP3G8<P<IPP'"1NO9B%RW`D:#??!_#X;!_O__
+MB?"#Q`A;7E_)PU6)Y5=64X'L3`$``(M%#(LPBU@(@'L5``^$.@$``(-[$`!U
+M"(E#$.GF`0``QD,5`(V%Z/[__U!3Z$?^__^)A<S^__\/MD,4BX2&L`<``(F%
+MW/[__XM#$`^V0`R+A(:P!P``B878_O__BU4,#[9"#(N$AK`'``")A=3^__^[
+M`````(/$"#N=S/[__P^-<@$```^VA)WI_O__B<'!X0D/MH2=ZO[__XG&P>8)
+MBH2=Z/[__XB%T_[__P^VT(G(B[W8_O__`T27!(F%X/[__XN%U/[__XM\D`0!
+MSXF]M/[__XF]Y/[__XN%W/[__XM\D`0!SSF]X/[__W4D@^P$5O^UM/[__XG(
+MB[7<_O__`T26!%#H_/___X/$$.LJC78`5O^UY/[___^UX/[__P^VA=/^__^+
+MO=S^__\#3(<$4>C\____@\000SN=S/[__P^,0/___^FM````C78`C87H_O__
+M4%/H'_W__XF%S/[__P^V0Q2+A(:P!P``B87<_O__BU4,#[9"#(N$AK`'``")
+MA=C^__^[`````(/$"#N=S/[__WUB#[:$G>G^__^)P<'A"0^VA)WJ_O__B<;!
+MY@D/MI2=Z/[__XG(B[W<_O__`T27!(F%X/[__XG(B[W8_O__`T27!(F%Y/[_
+M_X/L!%90_[7@_O__Z/S___^#Q!!#.YW,_O__?)Z#[`1J`/]U#/]U".AJ`@``
+MC67T6UY?R<.)]E6)Y5=64X'L+`$``(M%#(L8C87H_O__4(M%#(/`"%#H1/S_
+M_XF%V/[__XM5#`^V0AB+A(.P!P``B87<_O__#[9"&8N$@[`'``")A=3^__^^
+M`````(/$"#NUV/[__WU=D`^VA+7I_O__P>`)#[:,M>K^___!X0D/MIRUZ/[_
+M_XG"B[W<_O__`U2?!(F5X/[__XN5U/[__P-$F@2)A>3^__^#[`114/^UX/[_
+M_^C\____@\001CNUV/[__WRD@^P$:@#_=0S_=0CHE`$``(UE]%M>7\G#58GE
+M5U93@>Q\`0``BT4,BS"+6`B-A>C^__]04^AS^___B864_O__#[9#%(N$AK`'
+M``")A:3^__^Q`(/$"(M5#(!Z%`!V)(I:%(UV``^VP8M]#`^V5`<,BY26L`<`
+M`(F4A<C^__]!.,MWXL>%F/[__P````"+A93^__\YA9C^__\/C>X```")]HN5
+MF/[__P^VA)7I_O__B<?!YPD/MH25ZO[__\'@"8F%H/[__XJ,E>C^__^(C9_^
+M__^Q`(M=#(![%`!V,0^VM9_^__^*0Q2(A8?^__\/ML&+E(7(_O__BURR!(T4
+M'XF4A:C^__]!.(V'_O__=]\/MI6?_O__B?B+C:3^__\#1)$$.86H_O__=2"#
+M[`3_M:#^____M:S^__^)^`-$D010Z/S___^#Q!#K+/^UH/[___^UK/[___^U
+MJ/[__P^VA9_^__^+G:3^__\#?(,$5^C\____@\00_X68_O__B[V4_O__.;V8
+M_O__#XP4____@^P$:@#_=0S_=0CH"````(UE]%M>7\G#58GE5U93@^P4BWT(
+MBUT,BW40QD,%`H/^`1G`@^#U@\`,B$,&4U?H@?;__X/$$(![!`-U,(M#"(M0
+M$(72=";'0!``````QD(%`H/^`1G`@^#U@\`,B$(&@^P(4E?H2_;__X/$$(UE
+M]%M>7\G#58GE5E.+70B+=0P/MDX'A<ET29`/MI1+P`8``(T$U0`````IT(U$
+M@S"`>`4"=`FX`````.LKB?:`>`8!=!+&1@4"BD`&B$8&N`````#K$I`/MHQ+
+MP08``(7)=;BX`0```%M>R<.-=@!5B>575E.#[!R+?0S&1RX`@+\S"0```'1[
+MO@````"-7S"`?RT`=$F0@'L%`74V@'L$`W4EBT,(@'@5`'0<@W@0`'06QT`0
+M`````,9#!0**AS()``"(0P;K"\9'+@'I]P$``(GV1H/#'`^V1RTY\'^X@^P(
+M5_]U".B4\/__Z=@!``"*0P:(AS()``#&AS,)```!ZX:0QT7P`````,=%[`$`
+M``"^`````(U?,(!_+0`/A'P!``"`>P4`#X66````4U?HT_[__X/$"(7`='S&
+M0P4!BT4(B47HB=H/MD,$@_@&=V?_)(4`````@^P(4_]UZ.B0]___@\00ZT^#
+M[`A3_W7HZ*OY__^#Q!#K/H/L"%/_=>CHMOO__X/$$.LM@^P(4_]UZ.AY_/__
+M@\00ZQS&1R\!QD(%`L9"!@&#[`A2_W7HZ)3T__^#Q!"0@'L%`G4,_T7PC78`
+M@'L%`G0.QT7L`````.FZ````B?:`>P8!#X2N````@'\O``^$!?___XM''`^V
+M4PB+1)!L]D`!!`^$B````,=%[`````#&0P4!QD,&`(M%"(E%Y(G:#[9#!(/X
+M!G=O_R2%'````(/L"%/_=>3HP/;__X/$$.M7@^P(4_]UY.C;^/__@\00ZT:#
+M[`A3_W7DZ.;Z__^#Q!#K-8/L"%/_=>3HJ?O__X/$$.LDQD<O`<9"!0+&0@8!
+M@^P(4O]UY.C$\___@\00ZP?&0P8!C78`1H/#'`^V1RTY\`^/A/[__X-]\``/
+MA5K^__^#?>P`=!7&AS()```!@^P(5_]U".B][O__ZP3&1RX!C67T6UY?R<.-
+M=@!5B>575E.![&P!``"+10R+>!R+D`@)``")E<3^___&A:W^__\`A=)U.XG!
+M#[=`*+H`````B<Z+22"+7B0!R!':4E!345?_=0CHL^;__XE&&(/$&+C_____
+M@WX8``^$42L``(GVBT4(_X"\,0``BT4,@\`(BU4(@<*$,0``BTH$B4($BUT,
+MB5,(B4@$B0%F@W]@`'1(]D=>`742BT=DBU=H.U,D<@=W*CM#('<EO@`````/
+MMT=@B<*H`74,D$:)T(GQT_BH`73UB?.+?0R(7RSK.HM%#,9`+`CK,8GV]D=>
+M`G0BBT=DBU=HBTT,.U$D=Q1R!3M!('<-BUT,BD,KB$,LZPF)]HMU#,9&+`B+
+M?0S&1RT`QH?`!@```,9'+P#&AS()````QH<S"0```,>'#`D```````"#O<3^
+M__\`#X1^$P``BX7$_O__]D`4(`^$=@D```^V0`Z#^`(/A(P%``"#^`)_#H/X
+M`0^$1`$``.DN*@``@_@##X4E*@``@^P,C9W8_O__4^@&Y?__@\00OP````"+
+M50P/MW(HLP"#_Q]W4@^VPXV4A=C^__^)O:C^__^Y(````"GY.?%V`HGQ@_D@
+M=0C'`O_____K$K@!````T^!(BHVH_O__T^`)`K@@````*?@Y\',4C70^X+\`
+M````ZP.#[R!#@/L#=J"#[`R+70S_L[`'``#H$.3__\:%K_[__P"#Q!"`>RH`
+M#X:`*0``@^P,#[:=K_[__\'C!`-=#(V#V`<``%#H5.3__X'#6`@``(D<).A&
+MY/__@\00_W4,Z!_E__^#Q`3&0`0"BI6O_O__B%`(QD`)`(N5V/[__XE0#(N5
+MW/[__XE0$(N5X/[__XE0%(N5Y/[__XE0&/Z%K_[__XJ-K_[__XM=##A+*@^'
+M>____^GV*```N`$```#K38MU#+$`@'XJ`'8]#[;!P>`$`?"-D-@'``"[````
+M`(.XV`<```!U$H-Z!`!U#(-Z"`!U!H-Z#`!T!;L!````A=MUMT$X3BIWP[@`
+M````A<!T'HN]Q/[__XMU#(F^#`D``,>&"`D```````#IH!$``(/L#(V=V/[_
+M_U/H8>/__X/$$+\`````BT4,#[=P*+,`@_\?=U(/ML.-E(78_O__B;VD_O__
+MN2`````I^3GQ=@*)\8/Y('4(QP+_____ZQ*X`0```-/@2(J-I/[__]/@"0*X
+M(````"GX.?!S%(UT/N"_`````.L#@^\@0X#[`W:@BUT,@'LL"'4&BD,KB$,L
+MBW4,BEXLB)[L"```QH;M"````8N%V/[__XF&V`@``(N%W/[__XF&W`@``(N%
+MX/[__XF&X`@``(N%Y/[__XF&Y`@``,>&Z`@```````!6Z'+C__^#Q`3&0`0"
+MB%@(B%@)BY78_O__B5`,BY7<_O__B5`0BY7@_O__B5`4BY7D_O__B5`8B<>`
+M?BH"#X=4`0``B?.!P]@(``!6Z"?C__^#Q`3&0`0%B5@(QD`4`(F%O/[__XL?
+M_H/`!@``#[:SP`8``(G"*=J#ZC#!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"
+M]]B(A'/`!@``BD<'B(1SP08``(GPB$<'QH6O_O__`(M5#(!Z*@`/AN0F``"*
+MC:_^__^+70PX2RP/A*@```!3Z*#B__^#Q`3&0`0!BI6O_O__B%`(B%`)BY78
+M_O__B5`,BY7<_O__B5`0BY7@_O__B5`4BY7D_O__B5`8BXV\_O__BE$4#[;*
+MBIVO_O__B[6\_O__B%P.#$*(5A2+'OZ#P`8```^VL\`&```IV(/H,,'X`HT4
+MP(T4T(T4T(T4T(G1P>$/`<J-%-#WVHB4<\`&``"+O;S^__^*1P>(A'/!!@``
+MB?"(1P?^A:_^__^*E:_^__^+30PX42H/AR[____I#28``,:%K_[__P"+70R`
+M>RH`#X;Y)0``@</8"```B9V@_O__BH6O_O__BU4,.$(L#X0"`0``4NBIX?__
+M@\0$QD`$`8J-K_[__XA("(A("8N5V/[__XE0#(N5W/[__XE0$(N5X/[__XE0
+M%(N5Y/[__XE0&(F%P/[___]U#.ADX?__@\0$QD`$`XN=H/[__XE8"(J5K_[_
+M_XA0#(F%O/[__XL8_H/`!@``#[:SP`8``(N5P/[__RG:@^HPP?H"C032C03"
+MC03"C03"B<'!X0\!R(T$PO?8B(1SP`8``(N-O/[__XI!!XB$<\$&``")\XA9
+M!XL?_H/`!@``#[:SP`8``(G**=J#ZC#!^@*-!-*-!,*-!,*-!,*)P<'A#P'(
+MC03"]]B(A'/`!@``BD<'B(1SP08``(GPB$<'_H6O_O__BI6O_O__BTT,.%$J
+M#X?4_O__Z;PD``"X`0```.M1BW4,L0"`?BH`=D&)]@^VP<'@!`'PC9#8!P``
+MNP````"#N-@'````=12#>@0`=0Z#>@@`=0B#>@P`=`>)]KL!````A=MULT$X
+M3BIWP;@`````A<!T'HNUQ/[__XM=#(FS#`D``,>#"`D```````#I8@T``(/L
+M#(V=V/[__U/H(]___X/$$+\`````BT4,#[=P*+,`@_\?=U(/ML.-E(78_O__
+MB;V<_O__N2`````I^3GQ=@*)\8/Y('4(QP+_____ZQ*X`0```-/@2(J-G/[_
+M_]/@"0*X(````"GX.?!S%(UT/N"_`````.L#@^\@0X#[`W:@BUT,BD,KB(/L
+M"```QH/M"````(N%V/[__XF#V`@``(N%W/[__XF#W`@``(N%X/[__XF#X`@`
+M`(N%Y/[__XF#Y`@``,>#Z`@```````"`>RH"#X<``0``BUT,@</8"```_W4,
+MZ"[?__^#Q`3&0`0%B5@(QD`4`(F%O/[__\:%K_[__P"+=0R`?BH`#X8R(P``
+M_W4,Z/[>__^#Q`3&0`0!BI6O_O__B%`(B%`)BY78_O__B5`,BY7<_O__B5`0
+MBY7@_O__B5`4BY7D_O__B5`8BXV\_O__BE$4#[;*BIVO_O__B[6\_O__B%P.
+M#$*(5A2+'OZ#P`8```^VL\`&```IV(/H,,'X`HT4P(T4T(T4T(T4T(G1P>$/
+M`<J-%-#WVHB4<\`&``"+O;S^__^*1P>(A'/!!@``B?"(1P?^A:_^__^*E:_^
+M__^+30PX42H/AS[____I:R(``(MU#(I>*U;H,][__X/$!,9`!`&(6`B(6`F+
+ME=C^__^)4`R+E=S^__^)4!"+E>#^__^)4!2+E>3^__^)4!B)A;C^___&A:_^
+M__\`@'XJ``^&%R(``(GW@<?8"```BH6O_O__BU4,.$(K#X0&`0``4NC+W?__
+M@\0$QD`$`8J-K_[__XA("(A("8N5V/[__XE0#(N5W/[__XE0$(N5X/[__XE0
+M%(N5Y/[__XE0&(F%P/[___]U#.B&W?__@\0$QD`$`XEX"(J=K_[__XA8#(F%
+MO/[__XL8_H/`!@``#[:SP`8``(N5P/[__RG:@^HPP?H"C032C03"C03"C03"
+MB<'!X0\!R(T$PO?8B(1SP`8``(N5O/[__XI"!XB$<\$&``")\8A*!XL:_H/`
+M!@``#[:SP`8``(N5N/[__RG:@^HPP?H"C032C03"C03"C03"B<'!X0\!R(T$
+MPO?8B(1SP`8``(N5O/[__XI"!XB$<\$&``")\8A*!_Z%K_[__XJ=K_[__XMU
+M##A>*@^'T/[__^G:(```B?:#O<3^__\`#X3K"0``B[W$_O__]D<4`@^$VPD`
+M`(M%#(J`,`D``(B%K_[__XM5##B",0D```^"B`$``)"*C:_^__^+70PX2RL/
+MA%H!``"#[`P/MMF)V,'@!(VT!6C___]6Z&+;__^#Q!")M9C^__^+=0P/MY2>
+M$`D```^WO)X2"0``O@````"0@_H?=U>)\0^VP8N-F/[__XT<@8F5E/[__[D@
+M````*=$Y^78"B?F#^2!U"<<#_____^L3D+@!````T^!(BHV4_O__T^`)`[@@
+M````*=`Y^',6C7P7X+H`````ZP.#ZB!&B?.`^P-VF0^VG:_^__^)VHG8P>`$
+MBW4,C9PP6`@``(L+]]&)C=C^__^+0P3WT(F%W/[__XM#"/?0B87@_O__BT,,
+M]]")A>3^__^)UL'F!(V<->C^__^-E#5H____(PJ)"XM"!".%W/[__XE#!(M"
+M"".%X/[__XE#"(M"#".%Y/[__XE##(J%K_[__XM5##A"+'4MN@````"#.P!U
+M$H-[!`!U#(-["`!U!H-[#`!T!;H!````A=)T",:%K?[__P&0_H6O_O__BHVO
+M_O__BUT,.(LQ"0``#X-Y_O__@+VM_O__``^$9`<``(/L#(V%V/[__U#HZ=G_
+M_\:%K_[__P"#Q!"+=0R`?BH`=G>)]HJ%K_[__XM5##A"+'13.$(K=$X/MM#!
+MX@0#50R-BM@'``"+A=C^__\+@M@'``")A=C^__^+A=S^__\+002)A=S^__^+
+MA>#^__\+00B)A>#^__^+A>3^__\+00R)A>3^___^A:_^__^*C:_^__^+70PX
+M2RIWBXMU#`^V?BS!YP2-G#WH_O__B[78_O__(S.)M<C^__^+C=S^__\C2P2)
+MC<S^__^+E>#^__\C4PB)E=#^__^+A>3^__\C0PR)A=3^___WUHFUV/[___?1
+MB8W<_O__]]*)E>#^___WT(F%Y/[__R,SB;78_O__(TL$B8W<_O__(U,(B97@
+M_O__(T,,B87D_O___W4,Z*S9__^#Q`3&0`0`B86P_O__N`````"#O=C^__\`
+M=1N#O=S^__\`=1*#O>#^__\`=0F#O>3^__\`=`6X`0```(7`#X0\`@``BWT,
+MBD<LB(?L"```BX78_O__B8?8"```BX7<_O__B8?<"```BX7@_O__B8?@"```
+MBX7D_O__B8?D"```QH?M"````<>'Z`@```````#&A:_^__\`@'\J``^&I@(`
+M`(J%K_[__XM5##A"+`^$KP$``#B",`D``'<-.((Q"0``<@4X0BMU1_]U#.C<
+MV/__@\0$QD`$`8J-K_[__XA("(A("8N5V/[__XE0#(N5W/[__XE0$(N5X/[_
+M_XE0%(N5Y/[__XE0&(F%P/[__^MW#[:-K_[__\'A!(V<#>C^__^+A=C^__\+
+M`XD#BX7<_O__"T,$B4,$BX7@_O__"T,(B4,(BX7D_O__"T,,B4,,_W4,Z%;8
+M__^#Q`3&0`0!BI6O_O__B%`(B%`)BQ.)4`R+4P2)4!"+4PB)4!2+4PR)4!B)
+MA<#^__^+70R!P]@(``#_=0SH%=C__X/$!,9`!`.)6`B*C:_^__^(2`R)A;S^
+M__^+&/Z#P`8```^VL\`&``"+E<#^__\IVH/J,,'Z`HT$THT$PHT$PHT$PHG!
+MP>$/`<B-!,+WV(B$<\`&``"+O;S^__^*1P>(A'/!!@``B?"(1P>*E:_^__^+
+M30PX42MU4XNUL/[__XL>_H/`!@``#[:SP`8``(GZ*=J#ZC#!^@*-!-*-!,*-
+M!,*-!,*)P<'A#P'(C03"]]B(A'/`!@``B[VP_O__BD<'B(1SP08``(GPB$<'
+M_H6O_O__BI6O_O__BTT,.%$J#X<G_O__Z<@```#&A:_^__\`BUT,@'LJ``^&
+MM````(J%K_[__XM5##B",`D```^'AP```#B",0D``')_.$(K='HX0BQT=0^V
+MP,'@!(V$!>C^__^Z`````(,X`'42@W@$`'4,@W@(`'4&@W@,`'0%N@$```"%
+MTG1##[:%K_[__\'@!(V<!>C^____=0SHI];__X/$!,9`!`&*C:_^__^(2`B(
+M2`F+$XE0#(M3!(E0$(M3"(E0%(M3#(E0&/Z%K_[__XJ=K_[__XMU##A>*@^'
+M3/___[@`````@[W(_O__`'4;@[W,_O__`'42@[W0_O__`'4)@[W4_O__`'0%
+MN`$```"%P`^$6QH``(M%#(I`+(B%D_[__XM5#(B"!`D``(N%R/[__XF"\`@`
+M`(N%S/[__XF"]`@``(N%T/[__XF"^`@``(N%U/[__XF"_`@``,:"!0D```#'
+M@@`)````````BEHK4NC0U?__@\0$QD`$`8A8"(J-D_[__XA("8N5R/[__XE0
+M#(N5S/[__XE0$(N5T/[__XE0%(N5U/[__XE0&(F%N/[__\>%M/[__P````#&
+MA:_^__\`BUT,@'LJ``^&H1D``(J%K_[__XM5##A"+`^$S`$``#A"*P^$PP$`
+M`(I:*U+H4=7__X/$!,9`!`&*C:_^__^(2`B(6`F+E<C^__^)4`R+E<S^__^)
+M4!"+E=#^__^)4!2+E=3^__^)4!B)A<#^__^+&/Z#P`8```^VL\`&``"+E;#^
+M__\IVH/J,,'Z`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<\`&``"+O<#^
+M__^*1P>(A'/!!@``B?"(1P>#O;3^__\`=$N+'_Z#P`8```^VL\`&``"+E;3^
+M__\IVH/J,,'Z`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<\`&``"*1P>(
+MA'/!!@``B?*(5P>+70R!P_`(``"+30R*22N(C9+^____=0SH4M3__X/$!,9`
+M!`.)6`B*G9+^__^(6`R)A;S^__^)A;3^__^+&/Z#P`8```^VL\`&``"+E<#^
+M__\IVH/J,,'Z`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<\`&``"+O;S^
+M__^*1P>(A'/!!@``B?"(1P>+'_Z#P`8```^VL\`&``"+E;C^__\IVH/J,,'Z
+M`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<\`&``"*1P>(A'/!!@``B?*(
+M5P?^A:_^__^*C:_^__^+70PX2RH/APK^___IIA<``(GVBT4,BH`P"0``B(6O
+M_O__BU4,.((Q"0``#X*&%P``B?:*C:_^__^+70PX2RMT=@^VP<'@!(V$!>C^
+M__^Z`````(,X`'43@W@$`'4-@W@(`'4'@W@,`'0&D+H!````A=)T0P^VA:_^
+M___!X`2-G`7H_O___W4,Z/[2__^#Q`3&0`0!BI6O_O__B%`(B%`)BQ.)4`R+
+M4P2)4!"+4PB)4!2+4PR)4!C^A:_^__^*C:_^__^+70PXBS$)```/@V'____I
+MX!8``(MU#(!^+`</AA\,``"#[`R-A=C^__]0Z+31___&A:[^__\`QH6O_O__
+M`(/$$(!^*@`/AKD```"0BH6O_O__BU4,.$(K#X2.````#[;`P>`$`="-D-@'
+M``"Y`````(.XV`<```!U$H-Z!`!U#(-Z"`!U!H-Z#`!T!;D!````A<ET5P^V
+ME:_^__^)T,'@!(M-#(V4"-@'``"+A=C^__\+`HF%V/[__XN%W/[__PM"!(F%
+MW/[__XN%X/[__PM""(F%X/[__XN%Y/[__PM"#(F%Y/[___Z%KO[___Z%K_[_
+M_XJ=K_[__XMU##A>*@^'2/___P^VE:[^__^+?0P/MD<J@^@#T?@YP@^.E@8`
+M`(I?*XB?[`@``(N%V/[__XF'V`@``(N%W/[__XF'W`@``(N%X/[__XF'X`@`
+M`(N%Y/[__XF'Y`@``,:'[0@```''A^@(````````5^A9T?__@\0$QD`$`HA8
+M"(A8"8N5V/[__XE0#(N5W/[__XE0$(N5X/[__XE0%(N5Y/[__XE0&(G'_W4,
+MZ![1__^#Q`3&0`0&B86P_O__BQ_^@\`&```/MK/`!@``B<(IVH/J,,'Z`HT$
+MTHT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<\`&``"*1P>(A'/!!@``B?"(1P>+
+M50R`>BH"#X?6`@``B=.!P]@(``!2Z*_0__^#Q`3&0`0%B5@(QD`4`(F%O/[_
+M_XN-L/[__XL9_H/`!@``#[:SP`8``(G"*=J#ZC#!^@*-!-*-!,*-!,*-!,*)
+MP<'A#P'(C03"]]B(A'/`!@``B[VP_O__BD<'B(1SP08``(GPB$<'QH6O_O__
+M`(M5#(!Z*@`/AF`4``"*C:_^__^+70PX2RL/A!X"``"+M;S^__^*1A0/MM"(
+M3!8,0(A&%`^VV<'C!(M]#(T$.XV(6`@``(N06`@``/?2B97(_O__BT$$]]")
+MA<S^__^+00CWT(F%T/[__XM!#/?0B874_O__C8P=Z/[__R.5V/[__XD1BX7<
+M_O__(X7,_O__B4$$BX7@_O__(X70_O__B4$(BX7D_O__(X74_O__B4$,N@``
+M``"#.0!U$H-Y!`!U#(-Y"`!U!H-Y#`!T!;H!````A=(/A)0````/MH6O_O__
+MP>`$C9P%Z/[___]U#.A/S___@\0$QD`$`8J5K_[__XA0"(A0"8L3B5`,BU,$
+MB5`0BU,(B5`4BU,,B5`8BXV\_O__BQG^@\`&```/MK/`!@``*=B#Z##!^`*-
+M%,"-%-"-%-"-%-")T<'A#P'*C130]]J(E'/`!@``B[V\_O__BD<'B(1SP08`
+M`(GPB$<'#[:%K_[__\'@!(M5#(V$$-@'``"Z`````(,X`'42@W@$`'4,@W@(
+M`'4&@W@,`'0%N@$```"%T@^$DP````^VG:_^__^)V,'@!(M-#(V<"-@'``!1
+MZ'O.__^#Q`3&0`0"BI6O_O__B%`(B%`)BQ.)4`R+4P2)4!"+4PB)4!2+4PR)
+M4!B)QXL8_H/`!@``#[:SP`8``(N5L/[__RG:@^HPP?H"C032C03"C03"C03"
+MB<'!X0\!R(T$PO?8B(1SP`8``(I'!XB$<\$&``")\8A/!_Z%K_[__XJ=K_[_
+M_XMU##A>*@^'N/W__^D3$@``QH6O_O__`(M]#(!_*@`/AO\1``"-=@"*A:_^
+M__^+50PX0BL/A(X"```/MOC!YP2-!!>-B%@(``"+D%@(``#WTHF5R/[__XM!
+M!/?0B87,_O__BT$(]]")A=#^__^+00SWT(F%U/[__XV,/>C^__\CE=C^__^)
+M$8N%W/[__R.%S/[__XE!!(N%X/[__R.%T/[__XE!"(N%Y/[__R.%U/[__XE!
+M#(M=#('#V`@``/]U#.@SS?__@\0$QD`$`XE8"(J-K_[__XA(#(F%O/[__XNU
+ML/[__XL>_H/`!@``#[:SP`8``(G"*=J#ZC#!^@*-!-*-!,*-!,*-!,*)P<'A
+M#P'(C03"]]B(A'/`!@``BY6P_O__BD('B(1SP08``(GQB$H'C80]Z/[__[H`
+M````@S@`=1*#>`0`=0R#>`@`=0:#>`P`=`6Z`0```(72#X24````#[:%K_[_
+M_\'@!(V<!>C^____=0SH?LS__X/$!,9`!`&*E:_^__^(4`B(4`F+$XE0#(M3
+M!(E0$(M3"(E0%(M3#(E0&(N-O/[__XL9_H/`!@``#[:SP`8``"G8@^@PP?@"
+MC13`C130C130C130B='!X0\!RHT4T/?:B)1SP`8``(N]O/[__XI'!XB$<\$&
+M``")\(A'!P^VA:_^___!X`2+50R-A!#8!P``N@````"#.`!U$H-X!`!U#(-X
+M"`!U!H-X#`!T!;H!````A=(/A)8````/MIVO_O__B=C!X`2+30R-G`C8!P``
+M4>BJR___@\0$QD`$`HJ5K_[__XA0"(A0"8L3B5`,BU,$B5`0BU,(B5`4BU,,
+MB5`8B<>+&/Z#P`8```^VL\`&``"+E;#^__\IVH/J,,'Z`HT$THT$PHT$PHT$
+MPHG!P>$/`<B-!,+WV(B$<\`&``"*1P>(A'/!!@``B?&(3P>-=@#^A:_^__^*
+MG:_^__^+=0PX7BH/ATC]___I/P\``(M]#(I?*U?H!\O__\9`!`&(6`B(6`F+
+ME=C^__^)4`R+E=S^__^)4!"+E>#^__^)4!2+E>3^__^)4!B)A;C^__^*7RN)
+M/"3HR,K__X/$!,9`!`*(6`B(6`F+E=C^__^)4`R+E=S^__^)4!"+E>#^__^)
+M4!2+E>3^__^)4!B)Q_]U#.B-RO__@\0$QD`$!HF%L/[__XL?_H/`!@``#[:S
+MP`8``(G"*=J#ZC#!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'/`!@``
+MBD<'B(1SP08``(GPB$<'QH6O_O__`(M5#(!Z*@`/AE$.``"0BHVO_O__BUT,
+M.$LK#X1J`P``#[;!P>`$`=B-D-@'``"Y`````(.XV`<```!U$H-Z!`!U#(-Z
+M"`!U!H-Z#`!T!;D!````A<D/A"\#``#^C:[^__^*A:[^__^+50R*4BJ--!`/
+MMIVO_O__B=^)V,'@!(M-#(V<"-@'``!1Z*3)___&0`0!BI6O_O__B%`(B?&(
+M2`F+$XE0#(M3!(E0$(M3"(E0%(M3#(E0&(F%P/[__XM=#(I;*XB=D?[__\'G
+M!(M%#(V<!]@'``")!"3H5,G__\9`!`2*E9'^__^(4!B)\8A(&8L3B5`(BU,$
+MB5`,BU,(B5`0BU,,B5`4B86\_O__BQC^@\`&```/MK/`!@``BY6X_O__*=J#
+MZC#!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'/`!@``BY6\_O__BD('
+MB(1SP08``(GQB$H'BQK^@\`&```/MK/`!@``BY7`_O__*=J#ZC#!^@*-!-*-
+M!,*-!,*-!,*)P<'A#P'(C03"]]B(A'/`!@``BY6\_O__BD('B(1SP08``(GQ
+MB$H'B[6P_O__BQ[^@\`&```/MK/`!@``BY6\_O__*=J#ZC#!^@*-!-*-!,*-
+M!,*-!,*)P<'A#P'(C03"]]B(A'/`!@``BY6P_O__BD('B(1SP08``(GQB$H'
+MBUT,BELKB)V0_O__BW4,C9PWV`<``(DT).@.R/__QD`$!(J5D/[__XA0&(J-
+MK_[__XA(&8L3B5`(BU,$B5`,BU,(B5`0BU,,B5`4B86\_O__BQC^@\`&```/
+MMK/`!@``BY6X_O__*=J#ZC#!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(
+MA'/`!@``BY6\_O__BD('B(1SP08``(GQB$H'B[6P_O__BQ[^@\`&```/MK/`
+M!@``BY6\_O__*=J#ZC#!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'/`
+M!@``BY6P_O__BD('B(1SP08``(GQB$H'BUT,C;P?V`<``(D<).@AQ___@\0$
+MQD`$`HJ5K_[__XA0"(A0"8L7B5`,BU<$B5`0BU<(B5`4BU<,B5`8B<>+&/Z#
+MP`8```^VL\`&``"+E;#^__\IVH/J,,'Z`HT$THT$PHT$PHT$PHG!P>$/`<B-
+M!,+WV(B$<\`&``"*1P>(A'/!!@``B?&(3P>)]OZ%K_[__XJ=K_[__XMU##A>
+M*@^';/S__^FW"@``C78`BWT,BD<L.D<K#X6Z````QH6O_O__`(!_*@`/AI0*
+M``"*A:_^__^+50PX0BMT?@^VP,'@!`'0C9#8!P``N0````"#N-@'````=1*#
+M>@0`=0R#>@@`=0:#>@P`=`6Y`0```(7)=$</MIVO_O__B=C!X`2+30R-G`C8
+M!P``4>@'QO__@\0$QD`$`HJ5K_[__XA0"(A0"8L3B5`,BU,$B5`0BU,(B5`4
+MBU,,B5`8D/Z%K_[__XJ-K_[__XM=##A+*@^'7/___^GK"0``@^P,C878_O__
+M4.C,Q/__@\00_W4,Z*7%__^#Q`3&0`0&B86P_O__QH6O_O__`(MU#(!^*@`/
+MAE0!``"*A:_^__^+50PX0BL/A"H!```/ML#!X`0!T(V0V`<``+D`````@[C8
+M!P```'42@WH$`'4,@WH(`'4&@WH,`'0%N0$```"%R0^$[P````^VE:_^__^)
+MT8G0P>`$BUT,C908V`<``(N%V/[__PL"B878_O__BX7<_O__"T($B87<_O__
+MBX7@_O__"T((B87@_O__BX7D_O__"T(,B87D_O__BH6O_O__.$,L#X2-````
+MB<O!XP2+50R-G!/8!P``4NC`Q/__@\0$QD`$`HJ-K_[__XA("(A("8L3B5`,
+MBU,$B5`0BU,(B5`4BU,,B5`8B<>+&/Z#P`8```^VL\`&``"+E;#^__\IVH/J
+M,,'Z`HT$THT$PHT$PHT$PHG!P>$/`<B-!,+WV(B$<\`&``"*1P>(A'/!!@``
+MB?.(7P>0_H6O_O__BH6O_O__BU4,.$(J#X>L_O__BTT,BEDK4>@DQ/__@\0$
+MQD`$`HA8"(A8"8N5V/[__XE0#(N5W/[__XE0$(N5X/[__XE0%(N5Y/[__XE0
+M&(G'BQC^@\`&```/MK/`!@``BY6P_O__*=J#ZC#!^@*-!-*-!,*-!,*-!,*)
+MP<'A#P'(C03"]]B(A'/`!@``BD<'B(1SP08``(GSB%\'BW4,#[9>+(G>B=C!
+MX`2+?0R-G#A8"```BP/WT(F%R/[__XM3!/?2B97,_O__BTL(]]&)C=#^__^+
+M6PSWTR.%V/[__XF%R/[__XN]W/[__R'ZB97,_O__BY7@_O__(=&)C=#^__^+
+MA>3^__\APXF=U/[__\'F!(M-#(VT#E@(``"+C=C^__\C#HF-V/[__R-^!(F]
+MW/[__R-6"(F5X/[__R-&#(F%Y/[__[@`````A<EU$87_=0V%TG4)@[WD_O__
+M`'0%N`$```"%P`^$N@(``(M=#(I#*XB#[`@``(N%V/[__XF#V`@``(N%W/[_
+M_XF#W`@``(N%X/[__XF#X`@``(N%Y/[__XF#Y`@``,:#[0@```''@^@(````
+M````QH6O_O__`(![*@`/AEP"``"!P]@(``")G8S^__^*A:_^__^+50PX0BQU
+M=E+H6,+__X/$!,9`!`.+C8S^__^)2`B*G:_^__^(6`R+M;#^__^+'OZ#P`8`
+M``^VL\`&```IV(/H,,'X`HT4P(T4T(T4T(T4T(G1P>$/`<J-%-#WVHB4<\`&
+M``"+O;#^__^*1P>(A'/!!@``B?"(1P?IM0$``)"*E:_^__^+30PX42L/A*(!
+M```/MOK!YP2-C#WH_O__BUT,C90?6`@``(L"]]")`8M"!/?0B4$$BT((]]")
+M00B+0@SWT(E!#(L!(X78_O__B0&+000CA=S^__^)002+00@CA>#^__^)00B+
+M00PCA>3^__^)00Q3Z&W!__^#Q`3&0`0#B[6,_O__B7`(BI6O_O__B%`,B86\
+M_O__BXVP_O__BQG^@\`&```/MK/`!@``B<(IVH/J,,'Z`HT$THT$PHT$PHT$
+MPHG!P>$/`<B-!,+WV(B$<\`&``"+E;#^__^*0@>(A'/!!@``B?&(2@>-A#WH
+M_O__N@````"#.`!U$H-X!`!U#(-X"`!U!H-X#`!T!;H!````A=(/A)<````/
+MMH6O_O__P>`$C9P%Z/[___]U#.BRP/__@\0$QD`$`8J5K_[__XA0"(A0"8L3
+MB5`,BU,$B5`0BU,(B5`4BU,,B5`8BXV\_O__BQG^@\`&```/MK/`!@``*=B#
+MZ##!^`*-%,"-%-"-%-"-%-")T<'A#P'*C130]]J(E'/`!@``B[V\_O__BD<'
+MB(1SP08``(GPB$<'C78`_H6O_O__BI6O_O__BTT,.%$J#X>P_?__N`````"#
+MO<C^__\`=1N#O<S^__\`=1*#O=#^__\`=0F#O=3^__\`=`6X`0```(7`#X02
+M!```BW4,BEXK5NC:O___@\0$QD`$`8A8"(A8"8N5R/[__XE0#(N5S/[__XE0
+M$(N5T/[__XE0%(N5U/[__XE0&(F%N/[__\>%M/[__P````#&A:_^__\`@'XJ
+M``^&M`,``(J%K_[__XM5##A"+`^$B@,``#A"*P^$@0,```^VP,'@!(V<!>C^
+M__\!T(V(V`<``(N5R/[__R.0V`<``(D3BX7,_O__(T$$B4,$BX70_O__(T$(
+MB4,(BX74_O__(T$,B4,,N`````"#.P!U$H-[!`!U#(-["`!U!H-[#`!T!;@!
+M````A<`/A!$#``"+30R*22R(C8O^__\/MH6O_O__P>`$C9P%Z/[___]U#.C8
+MOO__@\0$QD`$`8J5K_[__XA0"(J-B_[__XA("8L3B5`,BU,$B5`0BU,(B5`4
+MBU,,B5`8B87`_O__@[VT_O__`'11BQC^@\`&```/MK/`!@``BY6T_O__*=J#
+MZC#!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'/`!@``B[W`_O__BD<'
+MB(1SP08``(GPB$<'BU4,BE(KB)6*_O__BTT,BDDLB(V)_O__#[:]K_[__\'G
+M!(V</>C^____=0SH%[[__X/$!,9`!`2*E8K^__^(4!B*C8G^__^(2!F+$XE0
+M"(M3!(E0#(M3"(E0$(M3#(E0%(F%O/[__XF%M/[__XL8_H/`!@``#[:SP`8`
+M`(N5N/[__RG:@^HPP?H"C032C03"C03"C03"B<'!X0\!R(T$PO?8B(1SP`8`
+M`(N5O/[__XI"!XB$<\$&``")\8A*!XL:_H/`!@``#[:SP`8``(N5P/[__RG:
+M@^HPP?H"C032C03"C03"C03"B<'!X0\!R(T$PO?8B(1SP`8``(N5O/[__XI"
+M!XB$<\$&``")\8A*!XNUL/[__XL>_H/`!@``#[:SP`8``(N5O/[__RG:@^HP
+MP?H"C032C03"C03"C03"B<'!X0\!R(T$PO?8B(1SP`8``(N5L/[__XI"!XB$
+M<\$&``")\8A*!XM=#(I;*XB=B/[__XV</>C^____=0SHQ[S__X/$!,9`!`2*
+ME8C^__^(4!B*C:_^__^(2!F+$XE0"(M3!(E0#(M3"(E0$(M3#(E0%(F%O/[_
+M_XL8_H/`!@``#[:SP`8``(N5N/[__RG:@^HPP?H"C032C03"C03"C03"B<'!
+MX0\!R(T$PO?8B(1SP`8``(N]O/[__XI'!XB$<\$&``")\(A'!XN5L/[__XL:
+M_H/`!@``#[:SP`8``(GZ*=J#ZC#!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"
+M]]B(A'/`!@``BXVP_O__BD$'B(1SP08``(GSB%D'D/Z%K_[__XJ%K_[__XM5
+M##A"*@^'3/S__X/L"/]U#/]U".CNT?__N`````"-9?1;7E_)PY!5B>575E.#
+M[`R+10B#N+PQ```##X</`0``!7PQ``"+50@Y@GPQ```/A/L```")1>R+BGPQ
+M``")3?"-=@"+7?"+`XE%\(M3!(L#B5`$B0*)&XE;!(M#'/9``00/A8@```")
+MW[X`````@'LJ`'8FC78`@^P,B?(/ML+!X`2-A#C8!P``4.A,NO__@\001HGQ
+M.$\J=]V+50B!PG0Q``"+30B+@70Q``")6`2)`XE3!(F9=#$``(M#'(-X+`!T
+M8(/L!/]P,(M#'/]P+%'H_/___XM#',=`+`````"+10C_B,`Q``"#Q!#K-HGV
+M@^P(4_]U".A0T___@\00A<!T+8M5"('"?#$``(M-"(N!?#$``(E8!(D#B5,$
+MB9E\,0``D(M%[#E%\`^%%/___XUE]%M>7\G#58GE4X/L!(M%"(M8"(.[O#$`
+M``!U#HV#?#$``#F#?#$``'0S@^P,4^C\____B1PDZ/S___^)'"3H_/___X/$
+M$(.[O#$```!UVXV#?#$``#F#?#$``'7-N`````"+7?S)PXUV`%6)Y5=64X/L
+M!(M%"(M`"(E%\(N(?#$```5\,0``.<@/A($```"-=@"+50@Y41QU:(G/LP"`
+M>2H`=D&)]@^VP\'@!`'XC9#8!P``O@````"#N-@'````=12#>@0`=0Z#>@@`
+M=0B#>@P`=`>)]KX!````A?9U&4,X7RIWP;@`````A<!T%+@!````Z:T```"X
+M`0```.OKC78`BPF+1?`%?#$``#G(=8*+1?"+B(0Q```%A#$``#G(='Z-0?B+
+M50@Y4!QU98G#O@````"`>"H`=D&)\@^VPL'@!`'8C9#8!P``OP````"#N-@'
+M````=1*#>@0`=0R#>@@`=0:#>@P`=`6_`0```(7_=1A&B?`X0RIWO[@`````
+MA<!T#K@!````ZQJX`0```.ONBPF+1?`%A#$``#G(=8*X`````(/$!%M>7\G#
+MD%6)Y5=64X/L#(M="(M]$(MS"(-[+`!U#5/HGO[__X/$!(7`=0N#[`A75O]5
+M#.L9D(M%#(E#+(E[,/^&P#$``(/L#%;H_/___XUE]%M>7\G#58GE5E.+=0B+
+M70R`>Q4`=03&0Q4!@'L5`709@'L5!G03@'L5`W0-]D,4('4'QD,5"XUV`/]S
+M,%;H@[?__XD<)/]S(%;H_/___XL#@\00@W@@`'08@^P$@\`@4&@`````5NC\
+M____@\00ZUV0@[[$,0```'0KC89T,0``.89T,0``=!V#[`2-AL0Q``!0:```
+M``!6Z/S___^#Q!#K*XUV`(&^N#$``/\```!W'(V&=#$``#F&=#$``'4.@^P,
+M5NC\____@\00B?:-9?A;7LG#D%6)Y5=64X'LW````(M]$(M%#(M0)(L*B8T@
+M____#[991$N)G33___]FBT(,9HF%5O___XM*4(M:5(F-2/___XF=3/___P^V
+M6DZ)G3#___\/MD)/B84L____9HM*6F:)C53___]FBUI8@WH8`'0-9@^V0A2#
+MX`$[111U.+D`````@WH<``^$[@(``(V%6/___XF%)/____]U%%!2_W4(_U(<
+M@\00N0````"%P`^$QP(``.L)BU(8B94D____O@````"+50R+`@^V0`.)A2C_
+M___'A3C___\`````QX4\____``````^WP[H``````X5(____$Y5,____B85`
+M____B95$____BXTH____.8TP____#X5:`0``BYT\____"YTX____=%:+A4#_
+M__\KA3C___^)P\'C"71#@WT4`'0'H0````#K$8/L#/\U`````.C\____@\00
+MB0=FQT<&``"!^P`0```/AO0```!FQT<$`!"#QPB!ZP`0``!UO0^WG53____!
+MXPF+A23___\/MU`$A=)U!;H```$`B=`I\#G8<C&)\(N-)/___P,!B0=FB5\$
+M9L='!@``@\<(`=XYUG5&O@````"#P0B)C23____K-HGVB?"+C23___\#`8D'
+MB=!F*?!FB4<$9L='!@``@\<(B=`I\"G#@\$(B8TD____O@````#K@`^WG53_
+M__^)G3C____'A3S___\`````BY5`____BXU$____`94X____$8T\____BTT,
+M#[=!#+H``````T$$$U$(BXT\____,=$SA3C___\)P0^$$@$``.M/9HE?!(/'
+M".D1____C78``=[K/`^WG53____!XPF)]HN%)/___P^W4`2%TG4%N@```0")
+MT"GP.=AWU8G0*?`IPX.%)/___PB^`````.O1D(N55/___V8IE5;___\/A*X`
+M``"[`````/^%,/___XN-+/___SF-,/___W4(_X4P____B?:+E2#___\/MD)$
+M.X4P____=4Z#O2S___\`=`C_C2S____K#(N--/___XF-+/___X.]+/___P`/
+ME,`/ML")A3#___^+C2#___\/MT%<N@`````!A4C___\1E4S___^-=@"+A2#_
+M__]FBT!<9HF%5/___V:+E5;___]F.=`/AH/]__]FB954____Z7?]__]FQT?^
+M`("Y`0```(G(C67T6UY?R<.)]E6)Y593BW4(BU4,BUHD@'H5`70&BD(5B$,5
+M@^P(4E;H_/___XI#34"(0TV#Q!`Z0TQU+8![%0!U!,9#%0&`>Q4!=!"`>Q4&
+M=`J`>Q4#=`3&0Q4+@^P(4U;_4R"#Q!")]HUE^%M>R<.058GE5U93@^P\BT4,
+MBP")1>B+50SV0A0$#X3]`0``QT7L`````(!Z2``/A'L!``"+3>R+70R+3(LT
+MB4WDBIDP"0``B%WC.)DQ"0``#X)&`0``C78`BD7CBU7D.$(K#X0?`0``#[;`
+MB<+!X@2+3>2-E`K8!P``B57<#[>4@1`)```/M[2!$@D``+\`````C78`@_H?
+M=U.)^P^VPXM-W(T<@8E5V+D@````*=$Y\78"B?&#^2!U"\<#_____^L2C78`
+MN`$```#3X$B*3=C3X`D#N"`````IT#GP<QF-=!;@N@````#K!HUV`(/J($>)
+M^X#[`W:=#[9UXXGPP>`$BWWDC80X6`@``(E%U`^WG+<0"0``#[>TMQ()``"_
+M`````(GV@_L?=U.)^@^VPHM-U(T4@8E=T+D@````*=DY\78"B?&#^2!U"\<"
+M_____^L2C78`N`$```#3X$B*3=#3X`D"N"`````IV#GP<QB-=![@NP````#K
+M!HUV`(/K($>)^#P#=I[^1>.*5>.+3>0XD3$)```/@[W^____1>R+70P/MD-(
+M.T7L#X^%_O__BW4(@[YP,0````^$H@,``,=%[`````"+?0R`?T@`=#Z)\H'"
+M?#$``(M%[(M-#(M$@32)1>3'@`@)````````BT($BTWDB4H$B1&)002)"/]%
+M[(M=#`^V0T@[1>Q_RH/L"/]U#/]U".@N^?__Z7@#``"+=0SV1A0"#X0T`P``
+MBWT(@<?(,0``B7W,BT4(!0@R``")1<B+5>CV0EX##X40`P``@^P$:A!J`%#H
+M_/___\=%[`````"#Q!"`?D@`#X03`0``BTWLBUT,BTR+-(E-Y(G.L0"`?BH`
+M=D8/ML'!X`0!\(V0V`<``+L`````@[C8!P```'42@WH$`'4,@WH(`'4&@WH,
+M`'0%NP$```"%VW0)N`$```#K#8GV03A.*G>ZN`````"%P`^%A0(``(M%Y(J`
+M,`D``(A%XXM5Y#B",0D``')_BDWCBUWD.$LK=&,/MLF+=<AF@SQ.`'4M#[>$
+MBQ`)``"Z`````(G?`T,@$U,DBUW,B03+B53+!&:+A(\2"0``9HD$3NLI#[95
+MXXMUY&:+1B!F`X26$`D``&8#A)82"0``BWW,9BL$UXM-R&:)!%'^1>.*7>.+
+M=>0XGC$)``!S@?]%[(M]#`^V1T@[1>P/C^W^__^+10S_<##_=0CH=J___\=%
+M[`````"#Q`B+50R`>D@`#X0$`0``BTT(@<%T,0``B4W$BUWLBW4,BUR>-(E=
+MY(-][`!U3HM#((M3)(M]#(E'4(E75(J#,`D``(A'3HI#*XA'3P^V@S`)``!F
+MBX2#$`D``&:)1U@/MH,P"0``9HN$@Q()``!FB4=:QD=,`,9'30#K<8M-Y(M!
+M((M1)(M=##M35')@=P4[0U!V68MUZ`^W1ESWV(E%N(G'P?\?B7V\BTVXBT7D
+M(T@@BUV\(U@DBT6XBW4,(T90BU6\(U94B=XQUC'("<9U'8M]Y`^VES`)``"+
+M30QFBT%:9@.$EQ()``!FB4%:BUW$BT,$BW7DB7,$B1Z)1@2),/]%[(M]#`^V
+M1T@[1>P/CPC___^+10B#N,0Q````=!F#[`0%Q#$``%!H`````/]U".C\____
+M@\00QD7C`(M5Z(!Z1``/AK0````/MG7CBTW(9H,\<0!T7HM]Z(M<MVR#[`S_
+M=0CH_/___XM5#/Y"3,9`#B"+3<AFBQ1Q9HE0#(M]S(L4]XM,]P2)4`2)2`B`
+M2!0"QT`<H&L``,=`("1O``")&(M5#(E0)(/$"%#_=0C_4SR#Q!#^1>.*3>.+
+M7>@X2T1WANLXD,=%[`````"+=0R`?D@`=">#[`B+?>R+10S_=+@T_W4(Z-_&
+M__^#Q!!'B7WLBU4,#[9"2#GX?]F-9?1;7E_)PY!5B>575E.#[%R+10R+`(E%
+M[,=%V`````!FBU!<9HE5WF:!^H``=@9FQT7>@`"+30SV010@=$Z#[`P/MT7>
+M4(M=$/]S%/]S$/]U[/]U".B2L/__B478@\0@N/____^#?=@`#X2.`P``BT4,
+MQD!(`8M5V(E0-(F""`D``+@`````Z7$#``"+31`/MD$BN@````!24(G+_W$$
+M_S'H_/___X/$$(A%UXM-[`^V042Z`````%)0_W,,_W,(Z/S___^#Q!"*2R(H
+MP8A-UCA-UX!=U_^+1>QFBU!<C4+_9HM+&"'!9BG*9HE5W&8Y4R!S"&:+4R!F
+MB57<BUT,QD-(`,9#20#'1=`!````#[=%WHE%S/?8B47`F8E5Q(M="('#=#$`
+M`(E=L`^WP;H`````BTT0`T$0$U$4B47@B57DBUT(@<-\,0``B5VTC78`9HM%
+MWD@C1>!FBWW>9BG'9CM]W'8#BWW<BUW`(UW@BW7$(W7D@WW0``^$<@$``,=%
+MT`````!FBU7>BT7L9CE07'8^N0````"+50P/MD)(B46\@_@`?BJ)]HM%#(M$
+MB#2)1=B+4"0Q\HE5J(M0(#':BT6H"=`/A"8!``!!.4V\?]B#[`S_=<Q64_]U
+M[/]U".@)K___B478@\0@A<`/A<L```"+50S^2DB`>DC_#X2O````BTVTB4VX
+MBWVPBUT,#[9#2(M$@S2)1=C'@`@)````````B<:Q`(!X*@!V/P^VP<'@!`'P
+MC9#8!P``NP````"#N-@'````=12#>@0`=0Z#>@@`=0B#>@P`=`>)]KL!````
+MA=MU)$$X3BIWP;@`````A<!T'(M5N(M"!(M-V(E*!(D1B4$$B0CK%[@!````
+MZ^"+1P2+7=B)7P2).XE#!(D8BT4,_DA(@'A(_P^%6O___[C_____Z4,!``")
+M]HM5#(I22(A5IP^VRHM5V(M%#(E4B#2*1:=`BTT,B$%(B8H("0``QH(P"0``
+M",:",0D````/ME77BT7@9BG8BUW89HF$DQ`)``!FB;R3$@D``(I%USB#,`D`
+M`'8&B(,P"0``BE77BTW8.)$Q"0``<P:(D3$)``"+71!F*7L@9BE]W'0:#[?'
+MN@`````!1>`15>3'1=`!````Z??]__^+11!F@W@@``^$D0```+D`````_D77
+MBE76.%77=0/^1=>*7=>+1>PX6$1U.H!]U@!T!?Y-UNL)BU40BE(BB%76@'W6
+M``^41=>+7>P/MT-<N@````"+71`!0Q`14Q3'1=`!````ZQ1FBU7>BT7L9CE0
+M7'8'QT70`0```(M=$&:+6R!FB5W<BT7L9CM87`^&/_W__V:+4%QFB57<Z3+]
+M__^X`````(UE]%M>7\G#C78`58GE@^P(BU4(BT4,@WT0`'0:QD`5"X/L!%!H
+MT&H``%+H_/___X/$$.L/B?:#[`A04N@N]O__@\00R<.058GE5U93@>S,````
+MBT4,BP")1;3V0`$$=1Z+50S&0A4"@^P$4O]R(/]U".C\____Z0\$``"-=@"+
+M3;2#>30`=2=J!_]U".CEI?__BUVTB4,TQP0D`!```&H`_W,TZ/S___^#Q!"-
+M=@"+50R*0A2H(`^%$@(``*@&=1K&0A4!@^P$4O]R(/]U".C\____Z;(#``")
+M]HM-#/9!%`1T+XM=M(-[+`!T)H/L!/]S,/]S+/]U".C\____QT,L`````(M%
+M"/^(P#$``(/$$(GVBTT,BU$$BTD(B95`____B8U$____B570B4W4BUT,9HM#
+M#&:)1=B+5;2*0D1(B$7:#[9*1HN%0/___XN51/___P^MT-/J]L$@=`>)T+H`
+M````B46@B56DB46XB56\#[9%VKH`````4E#_=:3_=:#H_/___X/$$(E%P(E5
+MQ(M=M`^V2T8/I<+3X/;!('0'B<*X`````(E%R(E5S`^W0UP/ME7:B56<#Z_"
+MB46P#[=-V(E-D,=%E`````"+19"+590#A4#___\3E43___^)18B)58R+59R)
+ME3#____'A33___\`````BT7(]Z4P____B46`B56$BY4P____#Z]5S(M]A`'7
+MBT7(#Z^%-/___XT$!XE%A(MUB(M]C"MU@!M]A(M%L+H``````<81UXFU</__
+M_XF]=/___X/&_X/7_U)05U;H_/___X/$$(F%,/___XF5-/___XM-M`^W25R)
+MC6C____'A6S___\`````BX5H____]Z4P____B85@____B95D____BY5L____
+M#Z^5,/___XNU9/___P'6BX5H____#Z^%-/___XT$!HF%9/___XN-8/___XE-
+MK.F;````BUVT]D->`70;BT4,QD`5!H/L!%#_<"#_=0CH_/___^F8`0``BU6T
+M#[=27(E5K(F54/___\>%5/___P````"+30R+202)C3S___^+A5#____WX8F%
+M,/___XF5-/___XN-4/___XM5#`^O2@B+G33___\!RXN-//___P^OC53___^-
+M#`N)C33___^+A3#___^+E33___^)1<B)5<R+1:RZ`````(MUR(M]S`'P$?I2
+M4%=6_W6T_W4(Z$2F__^+50R)0C"#Q!B%P'4?QT(L`````(/L"%*+1;2#P"!0
+MZ/S____IUP```(UV`(/L!(U%N%#_=0S_=0CH0OC__X/$$(7`='.+30S_<3#_
+M=0CHE:7__XM="(N39"(``(/$"#F3:"(``'0FN2("``"+10B!O-!4$0``````
+M`'1;0HG0F??YBUT(.9-H(@``==^+10S'0"P`````@^P(4(M%"`7$,0``4.C\
+M____@\0$_W4(Z/S____K2HGVBU4,]D(4!'0N@^P$:"AY``!2_W4(Z(:I__^#
+MQ!#K*8M-#,9!%06#[`11_W$@_W4(Z/S____K$8/L"/]U#/]U".CG\?__@\00
+MC67T6UY?R<-5B>53@^P$BUT,@WLT`'1.@^P,4^C\____N@````"#Q!"-=@"+
+M0S2+!)"%P'00B?;'0!``````BT`4A<!U\D*!^O\#``!VW6H'_W,T_W4(Z+2A
+M___'0S0`````@\0,BUW\R<.058GE5U93@^P0BWT(QX=P,0```````(V'=#$`
+M`(F'=#$``(F'>#$``(V'?#$``(F'?#$``(F'@#$``(V'A#$``(F'A#$``(F'
+MB#$``*$`````P>`,NJNJJJKWXHG3P>L/4V@T"0``5^A8H?__B<:#Q`R#PR!3
+M:AA7Z$>A__\!QH/$#*$`````P>`,P>@.4&I$5^@NH?__`<:#Q`QJ"&@`$```
+M5^@<H?__`<:)/"3H_/___Z,`````@\001CLU`````',QD(/L#%?H_/___XG"
+M@\00A<!T'HN'M#$``(D"B9>T,0``_X>X,0``1CLU`````'+1D(UE]%M>7\G#
+M58GE5U93@^P,BWT(BW4,BUX$#[9.`[@!````B<+3XH!F`?O'0V0`````QT-H
+M`````/9#7@)T"6:#>V``=`_K!V:#>V``="UFA5-@=2=F"5-@@&,!^X-[0`!T
+M#8/L"%-7_U-`@\00B?:`8UX?Z;L```"-=@"*0UYFB5-@_DM%QT-D`````,=#
+M:`````"#R`6(0UZ$P'D.@^!_B$->Z8L```"-=@"`8UZ?@^P(4U?H_/___XG"
+M@\00A<!T3,8``XI&`XA"`XE:!(!*`0BA#````(E"/*$@````B4)`QT8$````
+M``^V0@.)5(-LBD->@^#^@\@*B$->_D-%@^P(4FH'Z/S___^#Q!"#>P0`=`R-
+M=@"+6P2#>P0`=??H_/___XE#2(/L#%/H_/___XGVC67T6UY?R<-5B>53BTT(
+MNP````"+50Q*@_K_=`^-=@`/M@$!PT%*@_K_=?0/ML-;R<.)]E6)Y593BW4(
+M@#X#=D:[`````(!^1`!T-8-\GFP`="6+3)YLBE8!@^(!BD$!@^#^"="(00&#
+M[`S_=)YLZ/S___^#Q!"00P^V1D0YV'_+@&9>^^L)@^P,5N@(````C67X6U[)
+MPY!5B>575E.![!P"``#'A>3]__\`````C;7H_?__BT4(@'A$``^$-@(``(MX
+M!(7_=`^#?P0`=`F)O>3]__^+?P2#[`1H``(``&H`5NC\____QP;S%GA:@\00
+MN`````"%_W0#BT=(B48$BU4(@'I,`'0*@$X)`HI"3XA&"HM-"(I12(C3@^,!
+MBH:3````@^#\B-&#X0()V`G(B-.#XP2#X/.(T8/A"`G8"<B(TX/C$(/@SXC1
+M@^$@"=@)R(C1@^%`@^`_@^*`"<@)T(B&DP```(M%"/9``0%T!(!."0&P`(7_
+M=`R#O>3]__\!&<"#P`*(1@N%_P^$N````(M'#(E&#(M'$(F&E````(H'B$80
+MBD=$B$81@[WD_?__`'0+BY7D_?__BD(#ZP:+30B*00.(1A**1T:(1A/V1UX"
+M=`2`3A0!9HM'8&:)1A:+1V2)1AB+1VB)AI@```"#[`1J$(V'C````%"-1BQ0
+MZ/S___^#Q`QJ!(V'G````%"-1CQ0Z/S___^#Q`QJ$(V'X````%"-AH````!0
+MZ/S___^#Q`QJ0(V'H````%"-1D!0Z/S___^#Q!"#O>3]__\`=%R+E>3]__^+
+M0@R)1AR+C>3]__^+01")AIP```"*`8A&((I!1(A&(8M5"(I"`XA&(HI!1HA&
+M(_9!7@)T!(!.)`&+C>3]__]FBT%@9HE&)HM!9(E&*(M!:(F&H````(7_=0N+
+M50B*`HA&$(UV`&B0````5NC\____]]B(1@AH``(``%;H_/____?8B(:0````
+M5FHPBTT(BT%4@^@*4(G(@\!$4.C\____C67T6UY?R<.058GEBTT(B<B`.0-V
+M+[@`````@'E$`'00#[911(-\@6P`=0Q`.<)_]+@`````ZPV#[`S_=(%LZ/S_
+M__^0R<.)]E6)Y593BW4(@#X#=B^[`````(!^1`!T*(-\GFP`=!&#[`S_=)YL
+MZ/S___^#Q!")]D,/MD9$.=A_W^L%D(!F`?Z-9?A;7LG#D%6)Y8M-"(M1"+@`
+M````B?8Y#()U"\<$@@````#K"(GV0(/X!W;JR<-5B>6+10R`8`'[4.C\____
+MR<.)]E6)Y5=64X'L'`0``(M]"(VUZ/W__XG[BD<!J`0/A!D!``"`/P(/AA`!
+M``"#X/V(1P&#[`1H``(``&H`5NC\____@\00@#\#='B-A>C[__^0BUML@#\(
+M=62%VW0'9H-_8`%U68G#QX7D^___`0````^V1T2#^`%^6E-J(&H`BY7D^___
+MBT27;(/`1%#H_/___[H`````@\00BP26,P23B0260H/Z?W[Q_X7D^___#[9'
+M1#N%Y/O__W^_ZQ>0@#L#=8]6:B!J`(U#1%#H_/___X/$$&:!OOX!``!5JG5>
+M@[[*`0```'0;@7X&3$E,3W0,@;YV`0``1U)50G4&@$\!`NLZQX7D^___````
+M`(N%Y/O__\'@!`'P@+B^`0``@'4-@[C*`0```'0$@$\!`O^%Y/O__X.]Y/O_
+M_P-^T(UE]%M>7\G#D%6)Y593BTT(BYE0$0``C4,!OB("``"9]_Z)UHM%#(E$
+MV3R+D5`1``"+11")1-%`B;%0$0``6U[)PXUV`%6)Y5=64X/L#(MU"(N&3!$`
+M`#N&4!$``'0VOR("``"0BX9,$0``BTS&/(M<QD!`F??_B99,$0``@^P(4U;_
+MT8/$$(N&3!$``#N&4!$``'70C67T6UY?R<-5B>564XM-"(N9:"(``(U#`;XB
+M`@``F??^B=:+10R)A-E4$0``BY%H(@``BT40B8316!$``(FQ:"(``%M>R<.0
+M58GE5U93@^P,BUT(BX-D(@``.X-H(@``=%:)]HN#9"(``(NTPU01``"+O,-8
+M$0``0+HB`@``B=&9]_F)DV0B``"#N[PQ````=`Z#[`Q3Z/S___^#Q!")]H/L
+M"%=3_]:#Q!"+@V0B```[@V@B``!UK(UE]%M>7\G#58GE4X/L!(M5"+@`````
+M@WHX`'07BUHXBP.)0CB#[`1J7&H`4^C\____B=B+7?S)PXUV`%6)Y8M-"(M5
+M#(M!.(D"B5$XR<.058GEBTT(BU4,@SD`=!*+`8M`*(E"*(L!B5`HZP:-=@")
+M4BB)$<G#D%6)Y5=64X/L#(MU#(,^`'0UBSZ0BP:+6"@YV'4+QP8`````ZPN-
+M=@"+%HM#*(E"*(/L"%/_=0C_4RR#Q!`Y^W0%@SX`=<Z-9?1;7E_)PXGV58GE
+M@^P(BT4(@#@(=0Z#[`Q0Z/S___^#Q!")]LG#B?95B>53@^P$BT4(BUT,BTT0
+MBU`(@#@(=1"#[`114U#H_/___^L*C78`@^P(45+_TXM=_,G#58GE5U93@^P4
+MBT4(BE44B%7SBW@HB@"(1?(/MMA35^C\____@\0,:@!35^C\____@\0,:@!J
+M`&H`:@!J`U-7Z/S___^#Q""Z`````(7`#X2M````]T4,````\`^5P`^VR(/L
+M#(7)=!2X)````(!]\R!T#;@T````ZP:)]@^V1?-0N$````"%R740BT4,BU40
+M#ZS0&(/(0`^VP%"+10R+51`/K-`0#[?8#[;#4(M%#(M5$`^LT`@/ML!0#[95
+M#`^WPH7)=`F)V"4`_P``"=!0:@%J`&@``0``_W4848!]\S`/E,`/ML!`4`^V
+M7?)35^C\____B<:#Q#A35^C\____B?*)T(UE]%M>7\G#D%6)Y8I%"(G"@^(#
+MB='!X0V-D0`@``"H!'0*C8$`(`,`ZPB)]HV"```"`,G#58GE5E.#[!R+=0B*
+M10R(1?=H(*$'`.C\____NR"A!P"#Q!"0@^P(#[9%]U#HH____P4<`0``B00D
+M_W8,Z/S___^#Q!"$P'@(N`$```#K))"#[`QH$"<``.C\____@\00@<,0)P``
+M@?L_2TP`=K:X`````(UE^%M>R<.)]E6)Y593BUT(@^P$:@`/MD4,4.A!____
+MB<:-0`B)!"3_<PSH_/___X/$#&@8`0``C48,4/]S#.C\____@\00C67X6U[)
+MPXUV`%6)Y8/L#&H`#[9%#%#H_O[__X/`#(D$)(M%"/]P#.C\____R<.-=@!5
+MB>575E.+70B+?1"+=12Y`````(U3"HM&$(D#BT84B4,$@SX`=0*Q`0^V1P31
+MX`G!9HE+"(M%#(.X.`(```!T#X.X.`(```(/A48!``")]H-^!`$/A<8```!F
+M#[9&#X#,$6:)`H/"`F8/MD8.@,P19HD"@\("#[9'!,'@`R7X````@,P29HD"
+M@\("9@^V1@N`S!-FB0*#P@)F#[9&"(#,$V:)`H/"`F8/MD8,@,P49HD"@\("
+M9@^V1@F`S!1FB0*#P@)F#[9&#8#,%6:)`H/"`F8/MD8*@,P59HD"@\("9L<"
+M0!:#P@*#/@!U&;!@BTT,@[DX`@```@^$@@$``+`FZ7L!``"P88M-#(.Y.`(`
+M``(/A&D!``"P-NEB`0``B?9F#[9&#H#,$6:)`H/"`@^V1P3!X`,E^````(#,
+M$F:)`H/"`F8/MD8(@,P39HD"@\("9@^V1@F`S!1FB0*#P@)F#[9&"H#,%6:)
+M`H/"`HM&""4````/P>@8#4`6``!FB0*#P@*#/@$9P(/@^X/H-.GM````D(-^
+M!`$/A88```!F#[9&#X#,$F:)`H/"`F8/MD8.@,P29HD"@\("9@^V1@N`S!-F
+MB0*#P@)F#[9&"(#,$V:)`H/"`F8/MD8,@,P49HD"@\("9@^V1@F`S!1FB0*#
+MP@)F#[9&#8#,%6:)`H/"`F8/MD8*@,P59HD"@\("9L<"0!:#P@*#/@$9P(/@
+M\(/`->M=D&8/MD8.@,P29HD"@\("9@^V1@B`S!-FB0*#P@)F#[9&"8#,%&:)
+M`H/"`F8/MD8*@,P59HD"@\("BT8()0````_!Z!@-0!8``&:)`H/"`H,^`1G`
+M@^#^@^@VC78`9@^VP`T`E___9HD"6UY?R<.-=@!5B>575E.#[""+50B+?12+
+M6@P/MD4,BT2")(MP,&H`C88@`0``B47P4%/H_/___X/$"(V&!`$``%!3Z/S_
+M__^(!X/$"(V&"`$``(E%[%!3Z/S___]F#[;`9HE'`H/$"(V&#`$``(E%Z%!3
+MZ/S___]F#[;`9HE'!(/$"(V&$`$``(E%Y%!3Z/S___]F#[;`9HE'!H/$"(V&
+M%`$``(E%X%!3Z/S___]F#[;`9HE'"(/$$(-]$`%U;H/L!&B`````_W7P4^C\
+M____@\0(_W7L4^C\____P>`(9@E'`H/$"/]UZ%/H_/___\'@"&8)1P2#Q`C_
+M=>13Z/S____!X`AF"4<&@\0(_W7@4^C\____P>`(9@E'"(/$#&H`_W7P4^C\
+M____@\00@^P(C888`0``4%/H_/___XA'"H/$"(V&'`$``%!3Z/S___^(1PN-
+M9?1;7E_)PXGV58GE5U93@^PTBT409HE%U@^V50R)5="+10B+?)`DBT<P@\`P
+M4(M5"/]R#.C\____@^`?C13%`````"G"C;371`(``(/$$(,^`71!C5X4C478
+M4/]S!/]UT/]U".A,_O___H]1"0``@\0,C5784FH`#[=%UE#_<QQJ`?]UT/]W
+M*/]3&(/$&%97Z,01``"-9?1;7E_)PU6)Y5=64X/L/(M5$(I%#(A%S\=%R```
+M```/ML"+30B+=($D9L=%Q@``9HL"9HE%T(U-T&:+0@)FB4$"BT($B4$$9HM%
+MT(G#@^,?C03=`````"G8C9S&1`(``&:+00*$P'0NQT7(`0```&:+00(E_P``
+M`&:)1<9F@4W&``''ADP)````````QX8T`@```````(U[%(U%T&:+0`*H!'0:
+MC4784/]W!`^V1<]0_W4(Z&;]__^#Q!"-=@"#.P$/A),```#^CE$)``"#[`2-
+M1=A0C470BT`$4`^W1<90_W<<_W7(#[9%SXE%P%#_=BC_5QB#Q!A35NC$$```
+M@\00@[Y,"0```'10@[Y$"0```'1'BX9$"0``@W@0`74[@^P(_W7`_W4(Z,$2
+M``"#Q`C_MD0)``!6Z`X4``"#Q!"%P'47@^P$:@'_MD0)``!6Z$8&``"#Q!"-
+M=@"-9?1;7E_)PU6)Y593BUT(@^P(:"P-``#_<PSH_/___XG&@\0,@\@!4&@L
+M#0``_W,,Z/S___^#Q`AH+`T``/]S#.C\____@\0(:/`$`0#_<PSH_/___XM5
+M#/?2(=`+11"#Q`Q0:/`$`0#_<PSH_/___X/$"&CP!`$`_W,,Z/S___^#Q`Q6
+M:"P-``#_<PSH_/___XUE^%M>R<.-=@!5B>575E.#[!R+10B+0`R)1>S'1>@`
+M````#[9%#(T,A0````"(3?.*11`(1?,/MD7SBU4(BW2")(-]&`!T:X7V#X3-
+M````BY[<"0``@^P$BT44P>`#"T8D4(M&,(/`)%#_=>SH_/___X/$$#M=%'0C
+M#[9]\X/L!(M&%(T$V%!7_W4(Z(G]__]#@^,?@\00.UT4=>&#ODP)````=0?'
+M1>@!````B9[<"0``@WT<`'4*@WWH``^$_P$``(/L"`^V1?-0Z+;W__^#P`B)
+M1>2)!"3_=>SH_/___XG'@\0,#[?8B=CWT%#_=>3_=>SH_/___X/$$/;#"`^$
+M%@$``(7V=!3'ADP)````````QX8T`@```````(M-"(-Y9`%T!H-Y:`%U&H/L
+M!+@``0``BDWST^!04/]U".@S_O__@\00BT4(@WA@`70,@WAD`70&@WAH`745
+M@^P(#[9%\U#_=0CH:PD``(/$$.MZBU4(@WI<`70&@WI@`75K@^P$:@0/MEWS
+M4^CX]O__C7`HB30D_W7LZ/S___^#Q`A6_W7LZ/S____'!"09````Z/S___^#
+MQ`QJ`%;_=>SH_/___X/$"%;_=>SH_/___\<$)-`'``#H_/___X/$"%/_=0CH
+MM`<``(/$$)"#[`@/MEWS4_]U".C\____@\00A<`/A;T```!3:@!J`?]U"(M-
+M"/]1((/$$.FG````]\<0````=%&#[`@/MD7S4/]U".AG!P``@\00BT4(@WAD
+M`70&@WAH`74;@^P$:@"X``$``(I-\]/@4/]U".@9_?__@\00#[9%\U!J`6H!
+M_W4(BU4(_U(@ZTX/M\?VQ`%T1H.^-`(```%U*,>&3`D```````#'AC0"````
+M````@^P$4`^V1?-0_W4(Z-SZ__^#Q!"#/0`````!=0R#[`Q6Z$L0``"#Q!"-
+M9?1;7E_)PU6)Y5.#[`2+70@/MD4,P>`""T40#[;0BTR3)(7)=0V#[`A24^@'
+M#@``ZT60BY%$"0``A=)U$H/L"`^VP%!3Z.T-``#K*XUV`(,Z`70&@WH0`701
+M@^P(#[;`4%/HT`T``.L.B?:#[`A24>@*````B?:+7?S)PXUV`%6)Y5=64X/L
+M)(M5"(M"*(MP#(M:,(H*@^$#B<\/M@*#X`3!Z`*(1=B-@R`!``!05NC\____
+M@\0(@<,<`0``4U;H_/___XC#@\0,N``!``")^=/@]]!0@'W8`1G`)0``__\%
+M%``#`%!6Z/S___^#Q!"$VP^(*`$``/;#`707@^P$:@'_=0S_=0CHWP$``.D.
+M`0``B?:+50R+0A2#^`%T+8/X`7(0@_@"#X2(````Z>X```")]H/L!&H`_W4,
+M_W4(Z*@!``"#Q!#IU````/;#0'12@^P(BT4,@\`44/]U".C%````@\00@_@!
+M=2.+30R#>2``#X6H````@^P$:@!1_W4(Z&8!``"#Q!#ID@```(/L!&H!_W4,
+M_W4(Z$X!``"#Q!#K?8/L!&H!_W4,_W4(Z#D!``#K:P^VPZA`=%"H('5,BT4,
+M@W@@`'43@^P$:@!0_W4(Z!4!``"#Q!#K1(/L"(M%#(/`%%#_=0CH.@```(/$
+M$(7`=2N#[`1J`?]U#/]U".CG````@\00ZQ:)]H/L!&H!_W4,_W4(Z-````"#
+MQ!"0C67T6UY?R<-5B>575E.#[`R+?0B+=0RX`````(%^#/\````/AI@```"+
+M%H/Z`711N`````"#^@$/@H,```"#^@)U>;L`````@^P$BT8(#[<04H/``HE&
+M"(M',`4``0``4(M'*/]P#.C\____@\000X'[_P```';0@6X,``$``.L[NP``
+M``")]H/L"(M',`4``0``4(M'*/]P#.C\____BU8(9HD"@T8(`H/$$$.!^_\`
+M``!VTX%N#``!``"X`0```(UE]%M>7\G#C78`58GE5U93@^P<BW4(OP````"+
+M70R#PQ2-1=A0_W,$#[8&4/]V*.A:]O__@\00@WT0`7419K\!`,>&3`D`````
+M``"-=@"#[`2-1=A0:@!J`/]S(%</M@90_W8H_U,<@\08_W4,5NB_"0``@\00
+M@WT0`746@ST``````74-@^P,5NC8#```@\00D(.^1`D````/A+L```"+AD0)
+M``"#>!`!=2^#[`A05N@%#0``@\00A<`/A9H```"#[`1J`?^V1`D``%;H.?__
+M_X/$$.F!````D(.^.`(```!U,X/L"`^V!E#_=BCH9`H``(/$"(M&,(/`*%"+
+M1BC_<`SH_/___\<$)`$```#H_/___X/$$(/L"`^V!E#_=BCHA0H``(N>1`D`
+M`(/$$(7;="B#>Q``=2*)]H/L!(U#%%!35NBZ"P``BUL(@\00A=MT"(-[$`!T
+MXHGVC67T6UY?R<-5B>575E.#[!2+70B+0RB+>`R+0S")1?")QH/&*%97Z/S_
+M__^#Q!"H!'0V@^P$:@)65^C\____@\0(5E?H_/___\<$)-`'``#H_/___X/$
+M"`^V`U#_<RCH.`(``(/$$.L5@^P$:@*+1?"#P"A05^C\____@\00QH,\`@``
+M`,:#4`D```#&@U$)````QX/8"0```````,>#W`D```````#'@S0"````````
+MQX/4"0``(````+H`````B9235`D``$*#^A]^\[H`````B?:-!-4`````*=#'
+MA,-$`@```0```$*#^A]^YL>#1`D```````#'@T@)````````QX-,"0``````
+M`(/L!&H`BT7P@\`(4%?H_/___X/$#&@8`0``BT7P@\`,4%?H_/___X/$#/]S
+M&(M%\(/`$%!7Z/S___^#Q`R+0QPE`/S__U"+1?"#P!105^C\____@\0,BT,H
+MN@````"#>'@`=`.+4QQ2BT7P@\`84%?H_/___X/$#/]S((M%\(/`'%!7Z/S_
+M__^#Q`R+0RBZ`````(-X>`!T`XM3'%*+1?"#P"!05^C\____@\0,BT,DL`!0
+MBT7P@\`D4%?H_/___[@!````C67T6UY?R<.-=@!5B>575E.#["R+=0B+111F
+MB476@WT,``^%F@```+L`````B?:-!-T`````*=B-!,:#N$0"````=72#N%0"
+M```!=1J+D%P"``"+N'@"``"+@'0"``")1=#K)(UV`(T$W0`````IV(T$QHN0
+M7`(``(NX=`(``(N`<`(``(E%T(U%V%!2#[8&4/]V*.C*\O__@\0,C4784&H`
+M#[=%UE!7_W40#[8&4/]V*/]5T(/$($.#^Q\/CFW___^-9?1;7E_)PY!5B>57
+M5E.#[!R+70@/MG4,B?"#X`3!Z`*(1=B_`P```"'W@WM<`70&@WM@`75K@^P(
+MB?H/ML*)PL'B"(V"#`$``(!]V`!T"8V"#`$#`.L&D`4```(`4/]S#.C\____
+MB<&#X?R#R0&#Q`Q1B?H/ML*)PL'B"(V"#`$``(!]V`!T"(V"#`$#`.L%!0``
+M`@!0_W,,Z/S___^#Q!"#[`B)^@^VPHG"P>((C8)T`0``@'W8`'0*C8)T`0,`
+MZP>)]@4```(`4/]S#.C\____B<&`X1^)\@^VP@^VE!B)````P>(%@>+@````
+M"=&`Y></MH08D0```,'@"R4`&```"<&#Q`Q1B?H/ML*)PL'B"(V"=`$``(!]
+MV`!T"HV"=`$#`.L'B?8%```"`%#_<PSH_/___X/$$(UE]%M>7\G#C78`58GE
+M5U93@^P,BUT(#[9U#%;HFNW__X/L!(UX*%93Z'WN__^#Q`QJ!%?_<PSH_/__
+M_X/$"%?_<PSH_/___\<$)!D```#H_/___X/$#&H`5_]S#.C\____@\0(5_]S
+M#.C\____@\0(5E/H5_[__X/$"%93Z.'M__^-9?1;7E_)PY!5B>575E.#[`S&
+M1?(`QD7S`(UV`(I%\HI5\XT<@@^VVU/H"NW__XG':@*-<"A6BT4(_W`,Z/S_
+M__^#Q`A6BU4(_W(,Z/S___^#Q`A3_W4(Z"S___^#Q`QJ`%:+10C_<`SH_/__
+M_X/$#&@?`0``5XM5"/]R#.C\____@\0,:@"-1P10BT4(_W`,Z/S___^#Q`QJ
+M`(U'"%"+50C_<@SH_/___X/$#&H`C4<,4(M%"/]P#.C\____@\0,:@"-1Q!0
+MBU4(_W(,Z/S___^#Q`QJ`(U'%%"+10C_<`SH_/___X/$#&H`C4<84(M5"/]R
+M#.C\____@\0,:@"-1QQ0BT4(_W`,Z/S___^#Q`QJ`(U')%"+50C_<@SH_/__
+M_X/$#&H`C4<@4(M%"/]P#.C\____@\0,:@"-1RQ0BU4(_W(,Z/S___^#Q`QH
+MO````(U'-%"+10C_<`SH_/___X/$$/Y%\X!]\P,/AJS^__^`??(!&=N!XP``
+M__^!PP```P"#[`1J`(U##%"+50C_<@SH_/___X/$#&H`C4,04(M%"/]P#.C\
+M____@\0,:@"-0Q10BU4(_W(,Z/S___^#Q`QJ`(U#&%"+10C_<`SH_/___X/$
+M"(/#(%.+50C_<@SH_/___R4<'!P<#0,#`P.#Q`Q04XM%"/]P#.C\____@\00
+M_D7R@'WR`0^&!_[__XUE]%M>7\G#B?95B>6#[`QH___/#VAL!`$`BT4(_W`,
+MZ/S____)PXUV`%6)Y5.#[`2+70B+0P2P`#T``(!0=">#[`AH+`T``/]S#.C\
+M____@\@!@\0,4&@L#0``_W,,Z/S___^#Q!"#[`AH``T``/]S#.C\____)?__
+M`/^#Q`Q0:``-``#_<PSH_/___X/$#&H`:`0-``#_<PSH_/___X/$#&H`:#@,
+M``#_<PSH_/___X/$#&C_``$`:`0=``#_<PSH_/___X/$#&H`:&0=``#_<PSH
+M_/___X/$#&H`:"@,``#_<PSH_/___X/$#&H`:%@=``#_<PSH_/___X/$#&H`
+M:%P=``#_<PSH_/___X/$#&H`:$`=``#_<PSH_/___X/$#&H`:$0=``#_<PSH
+M_/___X/$#&H`:$@=``#_<PSH_/___X/$#&H`:%`=``#_<PSH_/___XM=_,G#
+MC78`58GEBU4(BTT,QT$(`````(N"2`D``(E!#(.Z2`D```!T"8N"2`D``(E(
+M"(F*2`D``(.Z1`D```!U!HF*1`D``,G#B?95B>53BUT(BTT,@WD(`'48BT$,
+MB8-("0``A<!T%,=`"`````#K"XGVBU$(BT$,B4(,@WD,`'49BT$(B8-$"0``
+MA<!T%<=`#`````#K#(UV`(M1#(M!"(E"",=!"`````#'00P`````6\G#B?95
+MB>575E.#[`R+?0B+=0R+71"#.P!U&8/L!&H@C4,$4(U&%%#H_/___X/$$.L=
+MB?:#[`1J)(U#!%"-1A10Z/S____^AU`)``"#Q!"+`XE&$%97Z/G^___'!@``
+M``#^ASP"``"-9?1;7E_)PY!5B>564XM="(MU#(-^$`!T!OZ+4`D``%93Z`K_
+M__^+@]0)```/ME8$B92#5`D``$")@]0)``#'!@$```#^BSP"``"-9?A;7LG#
+MC78`58GEBD4(/`-V$@^VR(U,"0*X`0```-/@ZQ")]@^VR(U,"0&X`0```-/@
+MR<-5B>575E.#[`R+?0B+=U0/MET,4^B[____@^P$"?")1U13Z!'H__\%'`$`
+M`(D$)/]W#.C\____@\0,B=F#X0.X``$``-/@]]!0@^,$P?L"@_L!&<`E``#_
+M_P44``,`4/]W#.C\____@\0(:&0=``#_=PSH_/___X/$$#GP=2:#[`3_=U1H
+M9!T``/]W#.C\____@\0(:&0=``#_=PSH_/___X/$$(UE]%M>7\G#58GE5E.+
+M=0B+7E0/MD4,4.@3____@^P$]]`AV(E&5&AD'0``_W8,Z/S___^#Q!`YV'49
+M@^P$_W94:&0=``#_=@SH_/___X/$$(UV`(UE^%M>R<.058GE5U93@^P0BET,
+MBT4(BT`,B47P#[;3BT4(BW20)(M^,,>&-`(```$```"#X@3!Z@*)V8/A`[@!
+M`0``T^#WT%"`^@$9P"4``/__!10``P!0_W7PZ/S___^#Q`QJ`(M&,(/`"%#_
+M=?#H_/___X/$"`^VVU/_=0CH,/___X/$"(V''`$``%#_=?#H_/___\>&0`(`
+M``$```"#Q`QJ`8/'*%?_=?#H_/___XUE]%M>7\G#C78`58GE5U93@^P0BD4,
+MB$7SNP````"+50B+>@P/ML"+1((DBW`PQX`T`@```````&H"C48H4%?H_/__
+M_X/$$(UV`(/L"(U&*%!7Z/S___^#Q!"H`70<@^P,:.@#``#H_/___X/$$$.!
+M^^<#``!VT^L)D('[YP,``'83@^P(#[9%\U#_=0CH3/C__X/$$(/L"`^V1?-0
+M_W4(Z+']__^-9?1;7E_)PY!5B>564XM="(M#*(MP#/]U$/]U#%.+@]@)``#!
+MX`4#0Q!0Z-'F__^+D]@)``!"@^(?B9/8"0``_H-1"0``@\0,BT,<)0#\___!
+MX@4)T%"+0S"#P!105NC\____C67X6U[)PXGV58GE4X/L!(M="&H`:@)J`%/H
+MNO7__XD<).C>\___B1PDZ/S___^#Q!"#^`%U'L>#3`D```$```"#[`@/M@-0
+M_W,HZ/W\__^#Q!")]HM=_,G#C78`58GE5U93@^P4BWT,@\<4BU4(BT(HBW`,
+MBUHPC8,<`0``4%;H_/___R7!````@\00N@````"#^$`/A=X!``"#?P0!=7"#
+M[`0/MD<14(V#!`$``%!6Z/S___^#Q`P/MD<34(V#"`$``%!6Z/S___^#Q`P/
+MMD<54(V##`$``%!6Z/S___^#Q`P/MD<74(V#$`$``%!6Z/S___^#Q`P/MD<9
+M4(V#%`$``%!6Z/S___^#Q!#K-(GV9O='$`#_=2!F]T<2`/]U&&;W1Q0`_W40
+M9O='%@#_=0AF]T<8`/]T"KH`````Z38!``"#[`0/MD<04(V#!`$``%!6Z/S_
+M__^#Q`P/MD<24(V#"`$``%!6Z/S___^#Q`P/MD<44(V##`$``%!6Z/S___^#
+MQ`P/MD<64(V#$`$``%!6Z/S___^#Q`P/MD<84(V#%`$``%!6Z/S___^#Q`P/
+MMD<:4(V#&`$``%!6Z/S___^#Q`P/MD<;4(V#'`$``%!6Z/S___^#Q!"#/P(/
+MA9````"#[`B-@R`!``!05NC\____QP0DR````&@0)P``:@%J`/]U".C\____
+M@\0@N@````"%P'1C@^P(C8,<`0``4%;H_/___R6)````@\00N@````"#^`AU
+M0<=%\`````"!PP`!``"#[`2+1P@/MQ!2@\`"B4<(4U;H_/___X/$$/]%\(%]
+M\/\```!VVH%O#``!``"Z`0```(GVB="-9?1;7E_)PXGV58GE5U93@^P0BW4(
+MQT94`````&H`:&0=``#_=@SH_/___X/$!/]V#.C\____B$8$@\00N`````"`
+M?@0`#X32`@``QT9<`````,=&8`````#'1F0`````QT9H`````,=&;`````#'
+M1G``````QT9T`````,:&@`````&X`````(-^(``/A(L"``"X`````&:!?@:!
+M4`^%>@(```^V5@6#^@$/A&T"``"#^@%_!H72=`GK&8/Z`G0+ZQ+'1F`!````
+MZQ#'1F0!````ZP?'1F@!````LP"#[`@/MM.)T(/@`\'@"(V(=`$``/;"!'0'
+M!70!`P#K!HV!```"`%#_=@SH_/___P^VRXG"@>+@````P>H%B)0QB0```"4`
+M&```P>@+B(0QD0```(/$$$.`^P=VI(/L#%;HE_3__XDT).B?]O__B30DZ+?V
+M__^#Q`QJ`&CP!`$`_W8,Z/S___^#Q`AH+`T``/]V#.C\____B47P@V7P_H/$
+M#/]U\&@L#0``_W8,Z/S___^#Q!"#OH0`````=5>#[`AH``T``/]V#.C\____
+MB47P@\00J#!T.8M&1*G@`P"`=`@E'_S_?XE&1(-^7`%T$H-^8`%T#(-^9`%T
+M!H-^:`%U$XM&1*@0=`R#X.^)1D3K!(-F1,^S`(GV@^P(#[;#4%;H&_+__X/$
+M$$.`^P=VZH/L!/]V1&@`#```_W8,Z/S___^#Q`S_=DAH*`P``/]V#.C\____
+M@\0,_W9,:%P=``#_=@SH_/___[,`@\00@^P$#[;#_W2&$(#[`1G`)0``__\%
+M#``#`%#_=@SH_/___X/$#`^VP_]TAAB`^P$9P"4``/__!1```P!0_W8,Z/S_
+M__^#Q!!#@/L!=K/'1E15JP8`LP")]H/L"`^VPU!6Z`/A__^#Q!!#@/L'=NJ#
+M[`QH4,,``.C\____@\00@WYD`70&@WYH`75#QT7P`````+,`D(/L"`^V^U=6
+MZ/S___^#Q!"%P'4+9K@``8GYT^`)1?!#@/L'=MN#[`3_=?!H`/\``%;HYN;_
+M_X/$$+@!````B?:-9?1;7E_)PU6)Y8/L#&H`:&0=``"+10C_<`SH_/___[@!
+M````R<.058GEQP4``````0```,G#D%6)Y<<%``````````#)PY!5B>564XMU
+M"(I5#`^VPHM<AB2X`````(7;="P/ML)0Z(#?__^#[`B)0S")<RC'@TP)````
+M````QX,T`@```````%/HW>W__XUE^%M>R<.)]E6)Y0^V50R+10B+5)`DN```
+M``"%TG0-@[I,"0```0^5P`^VP,G#B?95B>564XMU"(I%#(G"@^(#B='!X0B-
+MD0`!``"H!'0)C9D``0,`ZP>0C9H```(`@^P(4_]V#.C\____@^`/@\00@_@!
+M=`^#^`%R0H/X`W0UZSN-=@"#[`A3_W8,Z/S____'!"1`#0,`Z/S___^#Q`A3
+M_W8,Z/S___^#X`^#Q!"#^`-U"9"X`0```.L&D+@`````C67X6U[)PU6)Y5=6
+M4X/L+(M]"(I%#(A%\P^VP(M4AR2+3PR)3>RX`````(72#X0``@``BT(PB47H
+MN`````"#NDP)```!#X3H`0``QT7D`````)#_1>2#?>0*=@NX`````.G-`0``
+MD(/L"`^V7?-35^AV\/__@\0(4U?H#-___XI5\X/B`XA5XX/C!(G>P>X"QT7<
+M`````(/$$`^VPHG!P>$(B4W4@<$(`0``B4W8P>`(B470@^P(BU74C8((`0,`
+MB?&$R74)BU78C8(```(`4/]W#.C\____B<.#X_"#RP&#Q`Q3BT70C9`(`0``
+MC8`(`0,`B?&$R74&C8(```(`4/]W#.C\____@\0(#[9%XXG"P>((C8((`0``
+MB?&$R70+C8((`0,`ZPB-=@`%```"`%#_=PSH_/___\<$)!D```#H_/___X/C
+M\(/$#%,/MD7CB<+!X@B-@@@!``")\83)=`J-@@@!`P#K!XGV!0```@!0_W<,
+MZ/S___^#Q`@/MD7CB<+!X@B-@@@!``")\83)=`J-@@@!`P#K!XGV!0```@!0
+M_W<,Z/S____'!"30!P``Z/S___^#Q`@/MEWS4U?H_/___X/$$(7`=1__1=R#
+M?=P"#X;=_O__@^P(4U?H8MW__X/$$.EJ_O__@^P(BT7H!1P!``!0_W7LZ/S_
+M__\EP````(/$$(/X0'05@^P(#[9%\U!7Z"O=__^X`````.L4@^P(#[9%\U!7
+MZ!;=__^X`0```)"-9?1;7E_)PU6)Y5=64X/L#(M5"(I%%(A%\P^V10R+7((D
+MN0````"%VW1UBWH,BW,PN0````"#NTP)```!=&&#[`A65^C\____B<*#Q!"#
+M?1``=2B*1?-(N0`````\'W<_QX,X`@```````(/BP`^V1?-("<*`S@+K$HGV
+MQX,X`@```0```('BP/W__X#.`8/L!%)65^C\____N0$```"0B<B-9?1;7E_)
+MPXGV58GE4X/L!(M="(I-#`^VP8M4@R2X`````(72="JX`````(.Z3`D```%T
+M',>"3`D```$```"#[`@/ML%04^A"]/__N`$```"+7?S)PU6)Y5.#[`2+70B*
+M50P/ML*Y`````(-\@R0`="`/MM*+1),DQX!,"0```````(/L"%)3Z+7T__^Y
+M`0```(G(BUW\R<.058GE4X/L!`^V50R+10B+7)`DN`````"%VW0HN`````"#
+MNTP)```!=!IJ`&H"_W404^A*Z___B1PDZ&[I__^X`0```(M=_,G#58GE#[95
+M#(M%"(M4D"2X_P```(72=`</MH(\`@``R<-5B>575E.#[`R*70P/MG40#[9]
+M%(C:@^(#B=B#X`3!Z`+WQO@```!U"/?'_````'0+N`````#IC0```)`/MM*)
+MT<'A"(V1=`$``(3`=`Z!P70!`P")3?#K#(UV`('"```"`(E5\(/L"/]U\(M%
+M"/]P#.C\____)!^)\L'B!8'BX`````G0@.3GB?K!X@N!X@`8```)T(/$#%#_
+M=?"+50C_<@SH_/___P^VPXGYBU4(B(P0D0```(GQB(P0B0```(/$$+@!````
+MD(UE]%M>7\G#58GE5U93@^P4BW4(BET,OP,````AWX/C!,'K`H#[`1G`)0``
+M__\%&``#`%#_=@SH_/___XGY#[;1C4H8N@$```#3X@G0@\0,4(#[`1G`)0``
+M__\%&``#`%#_=@SH_/___X/$"(#[`1G`)0``__\%&``#`%#_=@SH_/___X/$
+M$+@!````C67T6UY?R<-5B>575E.#[!2+=0@/MGT,B?B#X`.(1?.)^`^VT(G0
+M@^`$B</!ZP)25NA.ZO__@\0(@/L!&<`E``#__P48``,`4/]V#.C\____#[9-
+M\X/!&+K^____T\(AT(/$#%"`^P$9P"4``/__!1@``P!0_W8,Z/S___^#Q`B`
+M^P$9P"4``/__!1@``P!0_W8,Z/S___^#Q`@/MD7SB<+!X@B-@@@!``"$VW0*
+MC8((`0,`ZP>)]@4```(`4/]V#.C\____@^#P@\@!@\0,4`^V1?.)PL'B"(V"
+M"`$``(3;=`F-@@@!`P#K!I`%```"`%#_=@SH_/___X/$"(GZ#[;"4%;H>^G_
+M_X/$$+@!````C67T6UY?R<.-=@!5B>575E.#[!2+?0B+=1"*10R(1?.+1PR)
+M1>P/MD7SBUR')(G"@^(#B='!X0B-D70!``"H!'0(C8%T`0,`ZP:-@@```@!0
+M_W<,Z/S___^)1EB#Q!"%VW40QP8`````N`$```#I_P```(M#,(E%Z(/L"`^V
+M1?-05^C\____B0:#Q!"X`0```(,^``^$V````(N#3`D``(E&+(N#.`(``(E&
+M,(J#/`(``(A&-+H`````D(I$$VJ(1!8$0H/Z)W;R@^P(_W7H_W7LZ/S___^)
+M1CB#Q`B+1>B#P!!0_W7LZ/S___^)1CR#Q`B+1>B#P!10_W7LZ/S___^)1D"#
+MQ`B+1>B#P!A0_W7LZ/S___^)1D2#Q`B+1>B#P!Q0_W7LZ/S___^)1DB#Q`B+
+M1>B#P"!0_W7LZ/S___^)1DR#Q`B+1>B#P"10_W7LZ/S___^)1E"#Q`B+1>B#
+MP"A0_W7LZ/S___^)1E2X`0```(UE]%M>7\G#D%6)Y5=64X/L#(I=#`^VPXM5
+M"(MT@B2X`0```(.^3`D````/A$D!``"X`@```("^/`(``!\/A#<!``"+AM0)
+M``!(B8;4"0``BY2&5`D``(T$U0`````IT(V\QD0"``"(5P2+11"#.``/A:L`
+M``"#P`2#OC@"```"=0O'0`0!````ZRZ)]H-X!`%U)H-^"`!U((N&U`D``(F4
+MAE0)``!`B8;4"0``N`,```#IPP```(GV@+Y0"0```'5+@[XT`@```'4>@^P(
+M#[;;4_]U".B'[O__@\0(4_]U".C/[O__@\00@^P$_W405U;HV^S__X/$#(M%
+M$(/`!%!75N@&\/__@\00ZVF0@^P$_W405U;HM^S__X/$$.M6B?:#[`3_=1!7
+M5NBC[/__@\00@+X\`@```74[@[XT`@```742@^P(#[;#4/]U".@7[___@\00
+M@^P(5U;H9O#__X/$$(7`=0]75NC0[/__N`$```#K!I"X`````(UE]%M>7\G#
+MC78`58GE5U93@^PDBT4(BT`,B47D:&`=``!0Z/S___^)QHM5"(M25(E5\(/$
+M$+@`````A=8/A(L!``#WQ@``!`!T6H/L"(M%"(.XA`````$9P"58!```!0`9
+M``!0_W7DZ/S___^)PX/$#/?04(M5"(.ZA`````$9P"58!```!0`9``!0_W7D
+MZ/S___]J`%-J`/]U"(M5"/]2((/$(,9%ZP#WQO\!```/A`(!``"`?>L!&=N!
+MXP``__^!PQ0``P"#[`1J[U/_=>3H_/___X/$"%/_=>3H_/___XG'@\0,]]"#
+MR!!04_]UY.C\____@\0(@'WK`1G`)0``__\%"``#`%#_=>3H_/___XE%X+,`
+M@\00#[9%ZXE%V(UV``^VR[@``0``T^`A^(E%[+@!````T^")\H/B`2'X=02%
+MTG0A@^P$5U)0BT7@@^`?4`^VPU`/MD7K4/]U".B3V___@\0@@WWL`'0VBU78
+MB57<B=#!X`()V`^VP%#HC.O__X/$!(5%\'08@^P$#[;#4/]UW/]U".@:WO__
+M@\00C78`P>X"P6W@"$.`^P,/AF_____K!)#![@C1[OY%ZX!]ZP$/AN#^__^X
+M`0```(UE]%M>7\G#D%6)Y8/L#&H`:&0=``"+10C_<`SH_/___[@!````R<.0
+M58GE@^P,BT4(_W!4:&0=``#_<`SH_/___[@!````R<-5B>575E.#[`R+70B+
+M?12*10R(1?.*11"(1?*^`````#G^<UR#[`B+0S`%'`$``%"+0RC_<`SH_/__
+M_XC"@\00A,!X%(I%\PI%\B'0.D7S#Y3`#[;`ZRZ0@^P,_W48Z/S___^#Q`@/
+MM@-0_W,HZ/S___^#Q!"%P'0,1CG^<J:)]K@`````C67T6UY?R<.-=@!5B>53
+M@^P(BUT(:@"+0S`%(`$``%"+0RC_<`SH_/___X/$"(M#,`4@`0``4(M#*/]P
+M#.C\____BUW\R<-5B>53@^P(BUT(:@*+0S`%(`$``%"+0RC_<`SH_/___X/$
+M"(M#,`4<`0``4(M#*/]P#.C\____BUW\R<-5B>575E.#[`R+50@/MD4,BUR"
+M)+@`````A=MT;XMZ#(MS,+@`````@[M,"0```71;@^P,4^C\____@\0,:.$`
+M``"-AAP!``!05^C\____QP0D9````&@0)P``:@%J`%/H_/___X/$((7`=1"#
+M[`Q3Z/S___^X`````.L0@^P,4^C\____N`$```")]HUE]%M>7\G#58GE5U93
+M@^P,BWT(BD4,B$7S#[;`BW2')+@`````A?8/A*8```"-7C2-=@"#[`QH[```
+M`&H`:@!J`&H`:@!J`&@``0``C48T4&H`:@$/MD7S4%?H_/___X/$0(7`=&WV
+M`P1T+F:!>P3(-W4F@^P$:@!J`&H`:@!J!P^V1?-05^C\____@\0@A<!T06;'
+M`P``ZYKV@Z````#@="RQ`+@!````@+O^`0``I74AN@`````/M\("#!A"9H'Z
+M_P%V\K@`````A,EU!;@!````C67T6UY?R<-5B>6#[`@/ME4,BT4(BU20)+@`
+M````A=)T%[@`````@[I,"0```70)@^P,4NC\____R<.058GE@^P4:.\```!J
+M``^V12!0#[9%'%`/MD484`^V1110#[9%$%!J`&H`:@!J``^V10Q0_W4(Z/S_
+M___)PXUV`%6)Y5=64X/L#(I%#(A%\XM-(&:)3?"+121FB47NBTTH9HE-[(M]
+M+(MU,(I=-(I%.(A%ZP^V1?.Z`````(M-"(-\@20`=#Z#[`P/MD7K4`^VPU`/
+MM\90#[?'4`^W1>Q0#[=%[E`/MT7P4/]U'/]U&/]U%/]U$`^V1?-0_W4(Z`X`
+M``")PHG0C67T6UY?R<.)]E6)Y5=64X/L7(M5"(M]((M%)&:)1=B+12AFB47(
+MBT4L9HE%N(M%,&:)1:B*132(1:>*13B(1:8/MD4,BUR")(MR#(M3,(E5H(.[
+M-`(```%T"8.[3`D```%U"KH`````Z00#``"#[`QHZ`,``&BX"P``:@!J0%/H
+M_/___X/$(+H`````A<`/A-T"``"#[`Q3Z/S___^#Q!"#?10!#X6!````@^P$
+MB?H/ML90BT6@!00!``!05NC\____@\0,BU78#[;&4(M%H`4(`0``4%;H_/__
+M_X/$#(M5R`^VQE"+1:`%#`$``%!6Z/S___^#Q`R+5;@/ML90BT6@!1`!``!0
+M5NC\____@\0,BU6H#[;&4(M%H`44`0``4%;H_/___X/$$.L_]\<`_P``=23W
+M1=@`_P``=1OW1<@`_P``=1+W1;@`_P``=0GW1:@`_P``=!.#[`Q3Z/S___^Z
+M`````.D'`@``@^P$B?H/ML)0BT6@!00!``!05NC\____@\0,#[9%V%"+1:`%
+M"`$``%!6Z/S___^#Q`P/MD7(4(M%H`4,`0``4%;H_/___X/$#`^V1;A0BT6@
+M!1`!``!05NC\____@\0,#[9%J%"+1:`%%`$``%!6Z/S___^#Q`P/MD6G4(M%
+MH`48`0``4%;H_/___X/$#`^V1:90BT6@!1P!``!05NC\____@\00@WT0`'5$
+M@^P,:!`G``!H'`P``&H!:@!3Z/S___^#Q""%P'43@^P,4^C\____N@````#I
+M*P$``(/L#%/H_/___[H!````Z1@!``"#[`QH$"<``&@<#```:@%J`%/H_/__
+M_X/$((7`=1.#[`Q3Z/S___^Z`````.GG````@^P(BT6@!1P!``!05NC\____
+M@\00J`AU$X/L#%/H_/___[H`````Z;L```"_`````#M]''-GBT6@!0`!``")
+M19R)^H32=1N#[`QJ9&A0PP``:@%J`%/H_/___X/$((7`=&:#?1`!=1B#[`C_
+M=9Q6Z/S___^+51AFB01Z@\00ZQ>#[`2+51@/MP1Z4/]UG%;H_/___X/$$$<[
+M?1QRI(/L#&ID:%##``!J`6H`4^C\____@\0@A<!U((/L#%/H_/___[H`````
+MZQ^#[`Q3Z/S___^Z`````.L/@^P,4^C\____N@$```"0B="-9?1;7E_)PXGV
+M58GE5U93@^P0BUT(BT,HBW`,BWLP:@:-AR`!``!05NC\____@\0(BT,P!2`!
+M``!05NC\____QP0D"@```.C\____B1PDZ/S____'!"3T`0``Z/S____'!"3T
+M`0``Z/S____'!"3T`0``Z/S____'!"3T`0``Z/S___^[`````(/$$(GV@^P(
+MC8<<`0``4%;H_/___X/$$(3`>`FX`0```.L@B?:#[`QH]`$``.C\____@\00
+M0X'[#R<``';'N`````"-9?1;7E_)PXGV58GE4X/L$(M="%/H)/___X/$$+H!
+M````@_@!=!>#[`QH]`$``.C\____B1PDZ`+___^)PHG0BUW\R<.058GE5E.+
+M=0B#[`1HH````*'@````BT`8!0``!`!05NC\____NP````"#Q!"#[`BAX```
+M`(M`$`4```0`4%;H_/___X/$$$.#^P1^X+L`````C78`@^P(H>````"+0!0%
+M```$`%!6Z/S___^#Q!!#@_L%?N"[`````(UV`(/L"*'@````BT`0!0``!`!0
+M5NC\____@\000X/[!'[@C67X6U[)PY!5B>53@^P(BUT(:(````"AX````(M`
+M#`4```0`4%/H_/___X/$#&BP````H>````"+0!@%```$`%!3Z/S___^+7?S)
+MPU6)Y593BW4(@^P,5N@'____@\0,:@"AX````(M`"`4```0`4%;H_/___X/$
+M"*'@````BP`%```$`%!6Z/S___^(PXDT).AR____#[;;B=B-9?A;7LG#B?95
+MB>575E.#[`R+70B#/00`````#X4'`0``@^P(:"P-``!3Z/S___^)QX/$#(/(
+M`5!H+`T``%/H_/___X/$"&CP!`$`4^C\____B<:#X&*#Q!"#^&)T&H/L!(GP
+M@\AB#[;`4&CP!`$`4^C\____@\00@^P(:```!`!3Z/S___^)'"3H.O[__X/$
+M#&H'H>````"+0`@%```$`%!3Z/S___^#Q`QJ$:'@````BP`%```$`%!3Z/S_
+M__^#Q`QJ!:'@````BT`(!0``!`!04^C\____@\0,:A&AX````(L`!0``!`!0
+M4^C\____B1PDZ'3^__^#Q`Q6:/`$`0!3Z/S___^#Q`AH\`0!`%/H_/___X/$
+M#%=H+`T``%/H_/___X/$$)"-9?1;7E_)PU6)Y5=64X/L%(M="&@L#0``4^C\
+M____B<>#Q`R#R`%0:"P-``!3Z/S___^#Q`AH\`0!`%/H_/___XG&@^!B@\00
+M@_AB=!J#[`2)\(/(8@^VP%!H\`0!`%/H_/___X/$$(/L"&@```0`4^C\____
+MB1PDZ"+]__^#Q`QJ!Z'@````BT`(!0``!`!04^C\____@\0,:@"AX````(L`
+M!0``!`!04^C\____@\0,:@6AX````(M`"`4```0`4%/H_/___X/$#&H`H>``
+M``"+``4```0`4%/H_/___XD<).A<_?__@\0,5FCP!`$`4^C\____@\0(:/`$
+M`0!3Z/S___^#Q`Q7:"P-``!3Z/S___^#Q!"-9?1;7E_)PY!5B>53@^P0BUT(
+M4^AP_/__@\0,:@JAX````(M`"`4```0`4%/H_/___X/$#&H`H>````"+``4`
+M``0`4%/H_/___XD<).C;_/__@\0(:`$`!`!3Z/S___^#Q!"Z_____Z@"=5"#
+M[`Q3Z!3\__^#Q`QJ`:'@````BP`%```$`%!3Z/S___^)'"3HF/S__\<$)&0`
+M``#H_/___X/$"&@!``0`4^C\____T>B#X`&#Q!"#^`$9THG0BUW\R<.)]E6)
+MY5=64X/L%(M]"(I%#(A%\XM?#&@L#0``4^C\____B47L@\0,@\@!4&@L#0``
+M4^C\____@\0(:/`$`0!3Z/S___^)QH/@8H/$$(/X8G0:@^P$B?"#R&(/ML!0
+M:/`$`0!3Z/S___^#Q!"#[`AH```$`%/H_/___X/$#(I%\XB'B`````^VP%"A
+MX````(M`'`4```0`4%/H_/___X/$#%9H\`0!`%/H_/___X/$"&CP!`$`4^C\
+M____@\0,_W7L:"P-``!3Z/S___^#Q!"-9?1;7E_)PXUV`%6)Y8/L"(M5"(I-
+M#(!]$`!T$K@!````T^`(@H@```#K$(UV`+C^____T\`@@H@```"#[`@/MH*(
+M````4%+H_/___\G#58GE5U93@^P4BWT(QD7S`&@L#0``5^C\____B47H@\0,
+M@\@!4&@L#0``5^C\____@\0(:/`$`0!7Z/S___^)1>R#X&*#Q!"#^&)T&X/L
+M!(I%[(/(8@^VP%!H\`0!`%?H_/___X/$$(/L"&@```0`5^C\____@\0(:```
+M!`!7Z/S___^#Q!!F/56J#X7U````O@````"-=@"[`````#GS?R>-=@"#[`1H
+MH````*'@````BT`8!0``!`!05^C\____@\000SGS?MR!_L@```!^$(/L#&H!
+MZ/S___^#Q!"-=@"#[`AH```$`%?H_/___XG#@\0,:+````"AX````(M`&`4`
+M``0`4%?H_/___X/$$&:!^U6J=11&@?['````#XYU____9H'[5:IT6X/L!&BP
+M````H>````"+0!@%```$`%!7Z/S___^#Q`AH```$`%?H_/___X/$$&8]5:IU
+M*,9%\P&#[`Q7Z";Z__^#Q!`\/G44@^P,5^BN_/__@\00A<!U!,9%\P*#[`1H
+ML````*'@````BT`8!0``!`!05^C\____@\0,_W7L:/`$`0!7Z/S___^#Q`AH
+M\`0!`%?H_/___X/$#/]UZ&@L#0``5^C\____@\00#[9%\XUE]%M>7\G#58GE
+M5E.+=0B[`````(UV`,<%X````*````"#[`Q6Z/W]__^#Q!"$P'4CQP7@````
+MP````(/L#%;HX_W__X/$$(3`=0E#@?OG`P``?L,/ML"-9?A;7LG#D%6)Y8M%
+M#(!X`0)U&(!X`@%U$@^V0`.C!````+@`````ZP>)]KC_____R<.058GE5U93
+M@^P4BT4(BW`,BWT0:"P-``!6Z/S___^)1>R#Q`R#R`%0:"P-``!6Z/S___^#
+MQ`AH\`0!`%;H_/___XE%\(/@8H/$$(/X8G0;@^P$BD7P@\AB#[;`4&CP!`$`
+M5NC\____@\00@^P(:```!`!6Z/S___^#Q!"#?1@`=#"[`````#M=%'U6B?:#
+M[`B+50R-A!H```0`4%;H_/___X@'@\000T<[711\X.LRB?:[`````#M=%'TF
+MB?:#[`0/M@=0BU4,C80:```$`%!6Z/S___^#Q!!#1SM=%'S>B?:#[`3_=?!H
+M\`0!`%;H_/___X/$"&CP!`$`5NC\____@\0,_W7L:"P-``!6Z/S___^#Q!"X
+M`0```(UE]%M>7\G#``````````````````0`````````````````````````
M````````````````````````````````````````````````````````````
M````````````````````````````````````````````````````````````
-M`````````````````0```````0`!``$``@`!``,``0`$``$`!0`!``8``0``
-M``$``"`!``!``0``8`$``(`!``"@`0``P`$`1#8``/PU``#\-0``#38``!XV
-M```O-@``0#8``!0W``#,-@``S#8``-TV``#N-@``_S8``!`W````1T-#.B`H
+M`````````````````````````````0``````````````````````````````
+M`````````0`!``$``@`!``,``0`$``$`!0`!``8``0`'``$````!```@`0``
+M0`$``&`!``"``0``H`$``,`!``#@`0#`````N#H``'`Z``!P.@``@3H``)(Z
+M``"C.@``M#H``(@[``!`.P``0#L``%$[``!B.P``<SL``(0[````1T-#.B`H
M1TY5*2`S+C0N,B!;1G)E94)31%T@,C`P-#`W,C@``"YS>6UT86(`+G-T<G1A
M8@`N<VAS=')T86(`+G)E;"YT97AT`"YR96PN9&%T80`N8G-S`"YR96PN<F]D
M871A`"YC;VUM96YT````````````````````````````````````````````
-M`````````````!\````!````!@`````````T````$[T`````````````!```
-M```````;````"0``````````````--L``*@1```*`````0````0````(````
-M*0````$````#`````````&"]``#````````````````@`````````"4````)
-M``````````````#<[```@`````H````#````!`````@````O````"`````,`
-M````````(+X```@```````````````0`````````.`````$````"````````
-M`""^```X```````````````$`````````#0````)``````````````!<[0``
-M<`````H````&````!`````@```!``````0``````````````6+X``"4`````
-M``````````$`````````$0````,``````````````'V^``!)````````````
-M```!``````````$````"``````````````"HP```$`T```L```!A````!```
-M`!`````)`````P``````````````N,T``'P-``````````````$`````````
+M`````````````!\````!````!@`````````T````(,8`````````````!```
+M```````;````"0``````````````P.0``"`2```*`````0````0````(````
+M*0````$````#`````````&#&``#D```````````````@`````````"4````)
+M``````````````#@]@``B`````H````#````!`````@````O````"`````,`
+M````````1,<```@```````````````0`````````.`````$````"````````
+M`$3'```X```````````````$`````````#0````)``````````````!H]P``
+M<`````H````&````!`````@```!``````0``````````````?,<``"4`````
+M``````````$`````````$0````,``````````````*''``!)````````````
+M```!``````````$````"``````````````#,R0``8`T```L```!A````!```
+M`!`````)`````P``````````````+-<``),-``````````````$`````````
M``````````````````````$```````````````0`\?\````````````````#
-M``$``````````````````P`#``````````````````,`!0`(````<`H``'\`
-M```"``$`&0```/`*``#V`````@`!`"P```#\#0``9`````(``0`Y````G!,`
-M`*H!```"``$`1@```)P9```U`````@`!`%4```#4&0``LP````(``0!F````
-M'!P``",````"``$`<@```$`<```@`````@`!`'T`````````!`````$`!0"*
-M````8!P``(`!```"``$`F@```.`=``!I`````@`!`*,```!,'@``0@````(`
-M`0"K````D!X``#,````"``$`LP```,0>```^`````@`!`+X````$'P``%```
-M``(``0#&````&!\``#$````"``$`V````$P?```H`````@`!`.<```!T'P``
-M4P````(``0#R````R!\``#$````"``$`_P```/P?``!5`````@`!``L!``!4
-M(```$P(```(``0`8`0``:"(``+L````"``$`)0$``"0C``"2`@```@`!`"\!
-M``"X)0```0$```(``0`^`0``%&8``,\````"``$`20$``+PF```\!````@`!
-M`%4!``!X-P``<RL```(``0!C`0``@&0``$,!```"``$`;P$``/@J```N````
-M`@`!`'D!```4-0``80(```(``0"+`0``*"L``*X````"``$`G`$``-@K```C
-M`0```@`!`*D!``#\+```I@````(``0"V`0``T"T``'8````"``$`PP$``*0M
-M```I`````@`!`,X!``!(+@``?`$```(``0#9`0``Q"\``!H"```"``$`Y0$`
-M`$`T``!L`````@`!`/,!``#@,0``U`````(``0```@``M#(``(P!```"``$`
-M#0(``*PT``!E`````@`!``````````````````,`!@`>`@``Y&8```H#```"
-M``$`+@(``/!I``!G`````@`!`$4"``!8:@``-P4```(``0!0`@``D&\``)P#
-M```"``$`7`(``"QS```[`````@`!`&P"``#$>```:P(```(``0!Y`@``D(``
-M`"P````"``$`B@(``#B!``!%`````@`!`)\"``"`@0``)0````(``0"R`@``
-MJ($``$(````"``$`OP(``.R!``"1`@```@`!`-4"``"`A```7@$```(``0#L
-M`@``X(4``)0````"``$`!`,``/B7``!)`````@`!`!(#``!TA@``7`$```(`
-M`0`E`P``W)D``$X````"``$`-`,``.2:```:`@```@`!`$@#``#TC0``6`$`
-M``(``0!;`P``T(<``)$````"``$`:@,``&2(``#$`@```@`!`'X#``#XD@``
-M?P````(``0"0`P``P)$``#4!```"``$`G@,``)":``!1`````@`!`*L#```H
-MBP``=0````(``0#!`P``^)@``"\````"``$`V`,``*"+``"0`0```@`!`.L#
-M```PC0``P0````(``0#[`P``*)D``+$````"``$`"`0``"R:``!B`````@`!
-M`!L$``!,CP``L0$```(``0`L!````)$``+\````"``$`.@0``'B3```.`@``
-M`@`!`$L$``"(E0``'0````(``0!D!```J)4``#$!```"``$`>P0``-R6``!"
-M`````@`!`)`$```@EP``:@````(``0"D!```C)<``&L````"``$`KP0``$28
-M```L`````@`!`,$$``!PF```B`````(``0#7!```>*X``.0````"``$`[P0`
-M`*"T``#*`````@`!`/P$``"(````'`````$``P`&!0``I````!P````!``,`
-M$`4``*BU``"C`````@`!`!D%```$````!`````$`!0`A!0``3+8``$0````"
-M``$`*04``)"V``!6`````@`!`#0%```8N0``N@````(``0`\!0``W+H``.`!
-M```"``$``````````````````P`(`%0%````````6`4``!(``0!@!0``(```
+M``$``````````````````P`#``````````````````,`!0`(````?`P``*X`
+M```"``$`&0```"P-```>`0```@`!`"P```!D$```9`````(``0`Y````>!8`
+M`,X!```"``$`1@```.`<``!$`````@`!`%4````D'0``V@````(``0!F````
+ME!\``",````"``$`<@```+@?```@`````@`!`'T`````````!`````$`!0"*
+M````V!\``(`!```"``$`F@```%@A``!I`````@`!`*,```#$(0``0@````(`
+M`0"K````""(``#,````"``$`LP```#PB```^`````@`!`+X```!\(@``%```
+M``(``0#&````D"(``#$````"``$`V````,0B```H`````@`!`.<```#L(@``
+M<P````(``0#R````8",``#$````"``$`_P```)0C``!5`````@`!``L!``#L
+M(P``'P(```(``0`8`0``#"8``/,````"``$`)0$````G``"2`@```@`!`"\!
+M``"4*0```0$```(``0`^`0``T&H``,\````"``$`20$``)@J``#(!````@`!
+M`%4!``#L.P``NRL```(``0!C`0``/&D``$,!```"``$`;P$``&`O```N````
+M`@`!`'D!``"(.0``80(```(``0"+`0``D"\``*X````"``$`G`$``$`P```C
+M`0```@`!`*D!``!D,0``I@````(``0"V`0``.#(``($````"``$`PP$```PR
+M```I`````@`!`,X!``"\,@``?`$```(``0#9`0``.#0``!H"```"``$`Y0$`
+M`+0X``!L`````@`!`/,!``!4-@``U`````(``0```@``*#<``(P!```"``$`
+M#0(``"`Y``!E`````@`!``````````````````,`!@`>`@``H&L``((#```"
+M``$`+@(``"1O``!G`````@`!`$4"``",;P``FP4```(``0!0`@``*'4``/T#
+M```"``$`7`(``"AY```[`````@`!`&P"``#4@```9P(```(``0!Y`@``L(@`
+M`"P````"``$`B@(``%B)``!%`````@`!`)\"``"@B0``)0````(``0"R`@``
+MR(D``)$"```"``$`R`(``%R,``!2`0```@`!`-\"``"PC0``E`````(``0#W
+M`@```*```$D````"``$`!0,``$2.``!<`0```@`!`!@#```LH@``HP````(`
+M`0`G`P``B*,``"8"```"``$`.P,``-B5``!8`0```@`!`$X#``"@CP``D0``
+M``(``0!=`P``-)```,`"```"``$`<0,```";``!_`````@`!`(,#``#$F0``
+M.0$```(``0"1`P``-*,``%$````"``$`G@,``/22``!U`````@`!`+0#```D
+MH0``4P````(``0#+`P``;),``*@!```"``$`W@,``!25``#!`````@`!`.X#
+M``!XH0``L0````(``0#[`P``T*(``&(````"``$`#@0``#"7``#1`0```@`!
+M`!\$```$F0``OP````(``0`M!```@)L```X"```"``$`/@0``)"=```=````
+M`@`!`%<$``"PG0``,0$```(``0!N!```Y)X``$(````"``$`@P0``"B?``!J
+M`````@`!`)<$``"4GP``:P````(``0"B!```3*```"P````"``$`M`0``'B@
+M``"L`````@`!`,H$``#(N```<@,```(``0#@!```/+P``,H````"``$`[00`
+M`*`````@`````0`#`/<$``#`````(`````$``P`!!0``X`````0````!``,`
+M"04```0````$`````0`%`!@%``!$O0``HP````(``0`A!0``Z+T``$0````"
+M``$`*04``"R^``!6`````@`!`#0%``#$P```N@````(``0`\!0``G,(``.`!
+M```"``$``````````````````P`(`%0%````````,`<``!(``0!@!0``(```
M`"0````1``,`;P4`````````````$````'P%``!@````)````!$``P",!0``
-M-'@``"H````2``$`E04`````````````$````*,%`````````````!````"M
-M!0`````````````0````MP4``%@%``#+````$@`!`,$%`````````````!``
-M``#.!0`````````````0````X`4``"0&``"<`0``$@`!`/`%````````````
-M`!````#Y!0``8'@``&,````2``$`!P8``,`'``!6````$@`!`!H&``#@>P``
-M$@```!(``0`H!@``&`@``$`!```2``$`-08``+A[```H````$@`!`$<&``"L
-M=0``8P```!(``0!2!@``6`D``!4!```2``$`908``.@+``!@````$@`!`'8&
-M``"X?@``$P```!(``0""!@``.'T``#D````2``$`D@8``$@,`````0``$@`!
-M`*0&``"$?@``,0```!(``0"T!@``2`T``$(````2``$`QP8``(P-``!O````
-M$@`!`-D&``!@#@``9`$``!(``0#O!@``Q`\``(`````2``$`#`<``$00``"4
-M````$@`!`"`'``#T?@``3@```!(``0`N!P``V!```+<````2``$`10<``)`1
-M```_`0``$@`!`%T'``#0$@``RP```!(``0!S!P`````````````0````?0<`
-M`$@5``"P`0``$@`!`(\'``#,?@``)P```!(``0"@!P``^!8``"L!```2``$`
-MLP<``"08``!V`0``$@`!`,0'``"(&@``8````!(``0#4!P``Z!H````!```2
-M``$`Y0<``.@;```R````$@`!`/<'````````!````!$``P`'"```````````
-M```0````%0@``.QB```P`0``$@`!`"@(`````````````!`````["```````
-M```````0````0@@`````````````$````$D(```<9```80```!(``0!5"```
-M```````````0````=P@```Q^``!X````$@`!`(4(``#$90``4````!(``0"7
-M"```:',``$0"```2``$`J0@```QW```H`0``$@`!`+P(```0=@``_````!(`
-M`0#."``````````````0````X`@`````````````$````/,(```P>P``/@``
-M`!(``0`""0``<'L``$<````2``$`$0D``/1[``!#`0``$@`!`"`)``!T?0``
-M6````!(``0`Q"0``S'T``#\````2``$`/@D``$1_```>````$@`!`$D)``!D
-M?P``-````!(``0!9"0``F'\``/8````2``$`90D``*"D``!#````$@`!`'T)
-M``#DI```2````!(``0"1"0``N+```#T````2``$`K`D``/BP``".````$@`!
-M`-$)``!4I```3````!(``0#H"0``O(```'H````2``$`_PD`````````````
-M$````!,*`````````````!`````D"@`````````````0````-PH``(0````$
-M````$0`#`$H*`````````````!````!<"@`````````````0````;@H`````
-M````````$````(`*`````````````!````"1"@``;+4``#L````2``$`H`H`
-M`*"M``!>````$@`!`+H*````G0``Y`(``!(``0#,"@``G*```)@````2``$`
-MZPH``.2?```?````$@`!``$+```$H```#P```!(``0`3"P``%*````\````2
-M``$`)@L``"2@``!.````$@`!`#T+``!TH```)@```!(``0!1"P``-*$``&0"
-M```2``$`:`L``)BC``"Z````$@`!`'T+```LI0``(````!(``0"4"P``3*4`
-M`'T````2``$`M0L``,RE``#,````$@`!`,\+``"8I@``C````!(``0#H"P``
-M)*<``!$!```2``$```P``#BH``!O`0``$@`!`!<,``"HJ0``4@```!(``0`N
-M#```_*D``+D!```2``$`00P``+BK``"G`0``$@`!`%\,``!@K0``'P```!(`
-M`0!Z#```@*T``"`````2``$`EPP```"N```\````$@`!`+$,```\K@``/```
-M`!(``0#,#```7*\``)`````2``$`Z0P``.RO``"5````$@`!``<-``"$L```
-M,P```!(``0`F#0``B+$``!8#```2``$`/`T``.BV```7`0``$@`!`$,-````
-MN```%P$``!(``0!+#0``U+D``,D````2``$`60T``*"Z```Z````$@`!`&8-
-M``"\O```5P```!(``0``<F%I9"YC`%-T<FEP94=E=$-O;6UA;F0`4W1R:7!E
-M4W!L:71#;VUM86YD`$ES5D1E=D]N;&EN90!$;T-O;G1R;VQ#;60`2D)/1$=E
-M=$-O;6UA;F0`2D)/1%-P;&ET0V]M;6%N9`!?7VAP=%]A;&QO8P!?7VAP=%]F
-M<F5E`&=A<F)A9V5?861D<@!I;FET7VAE87!?8FQO8VL`8V)?86QL;V,`8V)?
-M9G)E90!C8E]Z97)O`&-B7VES7WIE<F\`8V9?:6YI=`!R96UO=F5?<F%N9V5?
-M;&]C:P!A9&1?<F%N9V5?;&]C:P!L;V-K7W)A;F=E`%]?86QL;V-?=&%S:P!F
-M<F5E7W-T<FEP90!A;&QO8U]S=')I<&4`7U]G971?<W1R:7!E`&1A=&%?>&9E
-M<@!R96%D7WAF97)?9&]N90!R86ED-5]D;VYE`'-T<FEP95]D;VYE`&AA;F1L
-M95]S=')I<&4`<F%I9#5?9&ER='D`=&%S:U]D;VYE`'-T<FEP95]C:&5C:U]T
-M87-K`')W7W1A<VM?8G5I;&1S9VP`<G=?9V5T7W)A;F=E`')W7W1A<VM?9&]N
-M90!?7V1O7W)W7W1A<VL`9&]?<G=?=&%S:P!G971?<VQI8V5S`&1O7WAO<E]T
-M87-K`'AO<E]T87-K7V1O;F4`9&]?>&]R,E]T87-K`&1O7WAO<FY?=&%S:P!C
-M:&5C:U]D97!E;F1E;F-Y`&1I<F5C=%]R96%D7W-G;`!D:7)E8W1?<F5A9%]C
-M;VUP;&5T:6]N`&AA;F1L95]C;60`9V5T7W-T<FEP97,`=W)I=&5?>&9E<E]D
-M;VYE`%-Y;F-$:7-K26YF;P!G971%9&UA4F5G3V9F<V5T`'5N;6%S:T5D;6%)
-M;G1E<G)U<'1S`&UA<VM%9&UA26YT97)R=7!T<P!I<T5X=$-O;6UA;F0`=W)I
-M=&5%9&UA4F5Q=65S=$5N=')Y`&1U;7!!=&%$979I8V5296=I<W1E<G,`:&%N
-M9&QE161M849A:6QE9$-O;6UA;F0`<F5M;W9E0V]M;6%N9`!H86YD;&5%9&UA
-M4F5S<&]N<V4`9&5A8W1I=F%T945D;6$`<V5N9$YO;F559&UA0V]M;6%N9`!C
-M;VUP;&5T95!)3T-O;6UA;F0`4V5T1U!)3T-T<FQ296<`:&%N9&QE161M84EN
-M=&5R<G5P=`!?8VAA;FYE;$AA<F1297-E=`!?9FEX4&AY4&%R86US`%]D;T%U
-M=&]&;'5S:`!H86YD;&5$979I8V5);G1E<G)U<'0`9&ES86)L95-A1&5V26YT
-M97)R=71P<P!H86YD;&5024]);G1E<G)U<'0`=')A;G-F97)024]$871A`&%C
-M=&EV871E161M80!%9&UA4F5Q475E=65);G-E<G0`<F5S971%9&UA0VAA;FYE
-M;`!F;'5S:$1M85%U975E`')E=F5R=%-A=&%(0U)E9W,`<F5V97)T1FQA<VA)
-M;G1E<F9A8V5296=S`')E=F5R=%!#24EN=&5R9F%C95)E9W,`8V]M;6%N9'-1
-M=65U94%D9%1A:6P`8V]M;6%N9'-1=65U95)E;6]V90!A9&1#;VUM86YD`%-A
-M1&5V26YT97)R=71P0FET`&5N86)L95-A1&5V26YT97)R=71P<P!I<U-T;W)A
-M9V5$979296%D>49O<E!)3P!?9&]3;V9T4F5S970`7V%D9')-87`Q`%]A9&1R
-M36%P,@!%;G1E<C8P,0!A9&1R36%P`$5X:70V,#$`9V5T7S8P,5]I9`!S971?
-M8W1L`%]?8VAE8VM?<')O=&5C=%]C:7)C=6ET`&9#:&5C:T%R<F%Y`'!F;E-E
-M;F1#;VUM86YD`&9$95)E8617<FET90!P9FY$979I8V5&86EL960`0VAE8VM3
-M=6T`9D1E4V5L96-T36]D90!O<U]M96US970`;W-?;65M8W!Y`&9!9&13<&%R
-M90!'9713<&%R941I<VL`:6]C=&Q?4F5P;W)T179E;G0`1FEX=7!!<G)A>5-T
-M871E`$=E=%-T86UP`%-Y;F-!<G)A>4EN9F\`0VAE8VM!<G)A>4-R:71I8V%L
-M`&9/<T1I<VM&86EL960`9D1E;&5T94%R<F%Y`%5N<F5G:7-T97)61&5V:6-E
-M`')A:60U7V9R964`4W1R:7!E0G5I;&139U1A8FQE`&9204E$,$UE;6)E<D1O
-M;F4`1G)E94-O;6UA;F0`0V%L;$%F=&5R4F5T=7)N`&9204E$,%-E;F1#;VUM
-M86YD`$%L;&]C871E0V]M;6%N9`!F4D%)1#!-96UB97)&86EL960`4D%)1#%"
-M=6EL9%-G5&%B;&4`4D%)1#%-96UB97)#;VUP;&5T:6]N`%)!240Q26YI=%)E
-M8G5I;&1"=6EL9%-G5&%B;&4`4D%)1#%);FET0V]M<&QE=&EO;@!$;U=A:71I
-M;F=,:7-T`%)!240Q4F5B=6EL9$-O;7!L971I;VX`4D%)1#%697)I9GE"=6EL
-M9%-G5&%B;&4`4D%)1#%697)I9GE#;VUP;&5T:6]N`&]S7VUE;6-M<`!F4D%)
-M1#%396YD0V]M;6%N9`!!9&14;U=A:71I;F=,:7-T`&9204E$,4UE;6)E<D9A
-M:6QE9`!*0D]$0G5I;&139U1A8FQE`&9*0D]$365M8F5R1&]N90!F2D)/1%-E
-M;F1#;VUM86YD`&9*0D]$365M8F5R1F%I;&5D`&YU;5]R86ED-5]P86=E<P!O
-M<U]A;&QO8U]P86=E`&9L=7-H7W-T<FEP95]C86-H90!F3W-0:'ES:6-A;$%D
-M9')E<W,`1&]8;W(R`$1O6&]R,0!F;'5S:%]R86ED-0!F0V]M<&QE=&5!;&Q#
-M;VUM86YD<U-Y;F-H<F]N;W5S;'D`0VAE8VM)9&QE0V%L;`!F;'5S:%]R86ED
-M-5]A<WEN8P!F4D%)1#5396YD0V]M;6%N9`!F4D%)1#5-96UB97)&86EL960`
-M:6YI=%]R86ED-5]M96UO<GD`;W-?86QL;V-?9&UA7W!A9V4`9D1E=FEC95-E
-M;F1#;VUM86YD`&9'971&:7)S=$-H:6QD`&9297-E=$)O;W1-87)K`&9#:&5C
-M:T)O;W1A8FQE`$-H96-K4&5N9&EN9T-A;&P`0V%L;%=H96Y)9&QE`&9&;'5S
-M:%9$978`9D9L=7-H5D1E=D%S>6YC`&UV4F5A9%=R:71E`&UV4V%T841I<V%B
-M;&5#:&%N;F5L1&UA`&UV4V%T849L=7-H1&UA475E=64`;793=&]R86=E1&5V
-M051!4V5T1F5A='5R97,`;793=&]R86=E1&5V051!17AE8W5T94YO;E5$34%#
-M;VUM86YD`&UV4V%T845N86)L94-H86YN96Q$;6$`=V%I=$9O<D)U<WE!9G1E
-M<DA297-E=`!M=DUI8W)O4V5C;VYD<T1E;&%Y`$U67U)%1U]214%$7T)95$4`
-M359?4D5'7U=2251%7T173U)$`&UV075T;T9L=7-H3VY%<G)O<@!-5E]214=?
-M5U))5$5?0EE410!-5E]214=?4D5!1%]$5T]21`!-5E]214=?5U))5$5?5T]2
-M1`!-5E]214=?4D5!1%]73U)$`%]D;TUV4V]F=%)E<V5T`'=A:717:&EL95-T
-M;W)A9V5$979)<T)U<WD`;793871A26YI=$%D87!T97(`;793871A27-3=&]R
-M86=E1&5V:6-E0V]N;F5C=&5D`&UV4V%T85-H=71D;W=N061A<'1E<@!M=D5N
-M86)L94%U=&]&;'5S:`!M=D1I<V%B;&5!=71O1FQU<V@`;793871A0V]N9FEG
-M=7)E0VAA;FYE;`!M=E-A=&%296UO=F5#:&%N;F5L`&UV4V%T84-H86YN96Q(
-M87)D4F5S970`;793871A0V]N9FEG161M84UO9&4`;793871A3G5M3V9$;6%#
-M;VUM86YD<P!M=E-A=&%#:&%N;F5L4V5T161M84QO;W!"86-K36]D90!M=E-A
-M=&%3971#:&%N;F5L4&AY4&%R86US`&UV4V%T84-H86YN96Q0:'E3:'5T9&]W
-M;@!M=E-A=&%#:&%N;F5L4&AY4&]W97)/;@!M=E-A=&%'971#:&%N;F5L4W1A
-M='5S`&UV4V%T85%U975E541M84-O;6UA;F0`;793871A475E=65#;VUM86YD
-M`&UV4V%T84EN=&5R<G5P=%-E<G9I8V52;W5T:6YE`&UV4V%T84UA<VM!9&%P
-M=&5R26YT97)R=7!T`&UV4V%T855N;6%S:T%D87!T97));G1E<G)U<'0`96YA
-M8FQE4W1O<F%G941E=DEN=&5R<G5P=`!D:7-A8FQE4W1O<F%G941E=DEN=&5R
-M<G5P=`!M=E-T;W)A9V5$979!5$%)9&QE26UM961I871E`&UV4W1O<F%G941E
-M=D%404ED96YT:69Y1&5V:6-E`&UV4W1O<F%G941E=D%405-O9G1297-E=$1E
-M=FEC90!E>&5C=71E3F]N541-04-O;6UA;F0`0F5E<$]N`$)E97!/9F8`<V5T
-M7V9A:6Q?;&5D<P!S971?9F%I;%]L960`8VAE8VM?<')O=&5C=%]C:7)C=6ET
-M`$P````!8@``<`````)C``"*`````60``*H````"90``V0````)F``#P````
-M`F4``!(!```"9P``E0$```%D``#"`0```6(``%0"```"9P``UP(```%B``#R
-M`@```F@```T#```":```*`,```)H``!#`P```F@``+X#```"9P``0P0```%B
-M``!0!````60``'X$```":```F00```)H``"T!````F@``,\$```":```"@4`
-M``%D``!(!0```60``)H%```":@``Q04```%B``#2!0```60```X&```":P``
-MD08```)L``#S!@```FD``'L'```":0``I0<```)M``"Q!P```FX``/,'```"
-M;````P@```%P```R"````G(``$8(```"<P``AP@```)Q``"Q"````7```-X(
-M```"9P``\@@```)C```1"0```FX``#`)```"9P``&0P```)V```Z#````G<`
-M`&X,```"=P``F@P```)W``#+#````GD``!(-```!=0``&0T```%T``#+#@``
-M`F<``!T/```"9P``7@\```)V``"3#P```G<``'D0```"=@``K1````)W``##
-M$````7\``,D0```"=P``%1$```)G``!:$0```G8``&<1```"=P``?1$```%_
-M``"#$0```G<```\3```"9P``-Q,```*#``!F$P```G8``',3```"=P``B1,`
-M``%_``"/$P```G<```@4```"9P``(10```)Y``!#%````7X``$H4```!?0``
-M@Q0```)Y``"E%````8```*P4```!?0``UQ0```)Y``#Y%````8(````5```!
-M@0``)14```)W```T%0```7\``#H5```"=P``:Q4```)W``!]%0```0(``,\5
-M```!A```W!4```*%``">%@```GD``*T6```":```R!8```%\``#/%@```7L`
-M`)47```":@``K1<```%B``"U%P```60``.P7```":P``#!@```)M```8&```
-M`FX``(D9```":```N1H```)V``#:&@```G<```X;```"=P``.AL```)W``!K
-M&P```GD``+(;```!B```N1L```&'```7'0```HP``*\>```"9P``$A\```)G
-M```()0```F@``"DE```":```%RD```$"```#*@```0(```LJ```"=P``1BH`
-M``%_``!.*@```G<``&\J```!?P``=2H```)W``"]*@```G<``.@J```"C0``
-M$BL```$"```:*P```G<``)LK```"C@``&2T```)V``#M+0```GD``"8N```!
-M`@``,"X```$"``#4,````H\````Q```"D```MC$```*/``",,@```H\``-LS
-M```"CP``"30```*0``#X-0```2X``,@V```!+@``MF,```)W``!%9````HT`
-M`$UD```"D@``560```*3```(9@```HT``%EF```"=P``<&8```%_``!V9@``
-M`G<``*)F```!?P``J&8```)W``#39@```HT``.MG```!!```]F<```$$``#[
-M9P```HX``!!J```"=@``H6P```)G``#!;@```7\``,=N```"=P``^&X```)Y
-M```>;P```0(``"5O```!`@``1W,```$"``!-<P```G<``(MS```"=P``LG,`
-M``)G``#:<P```G<``/US```"=P``D70```)W``#'=````94``-1T```"A0``
-M)G4```&6``!`=0```94``%)U```"A0``774```*-``!N=0```0(``(]U```"
-M=P``P74```*1``!==@```8L``)-V```!BP``OG8```*8``##=@```00``,UV
-M```!BP``V78```*8``#]=@```8L``*YW```":@``S'<```%B``#4=P```60`
-M``!X```":P``&G@```)M```F>````FX``)QX```";@``#WD```)G```M>@``
-M`F@``$)Z```":```6GH```)H``!O>@```F@``/-Z```"90```WL```)E```C
-M>P```F,``&=[```"F@``EWL```*;``#L>P```G(``#%\```"9P``@'P```)C
-M``"_?````F,``%M^```"D@``JGX```)G``!7?P```I$``(-_```"E```N'\`
-M``*B``#$?P```J,``-A_```"I```<H````*E``!^@````J8``-.````"J```
-M^8````*I```5@0```J@``%N!```"J@``;X$```*J``"?@0```JH``*:$```"
-MJ0``NX0```*I``#6A````JD``/&$```"J0``#(4```*I```TA0```JD``$J%
-M```"K```5H4```*I``!IA0```JD``'R%```"J0``CX4```*I``"GA0```JP`
-M`+R%```"J0``SX4```*I```,A@```JT``.2'```"K0``^H<```*J```*B```
-M`JT``!J(```"K0``-8@```*J``!%B````JT``%:(```"J@``R(@```*J```W
-MB0```JT``$^)```"J@``\HD```*J``#^B0```JT```J*```"J```&(H```*J
-M```DB@```JT``#"*```"J```78H```*I```+BP```:L``-&+```"J0``X8L`
-M``*I```)C````JH``)"-```"K@``PXT```*O``!HC@```:L``.V.```"K0``
-M^8X```*H``!LCP```JT``'^/```"J@``B8\```*M``"5CP```J@``+N/```"
-MJ@``7I````*J``!SD````JH``(:0```"J@``GY````*J``"QD````JH``,20
-M```"J@``UI````*J``#LD````JH``!J2```"K0``4I(```*J``"&D@```JT`
-M`.:2```"J@``)9,```*J```QDP```JT``#V3```"J```2Y,```*J``!7DP``
-M`JT``*V3```"J@``O),```*M``#9DP```JH``.V3```"J@```90```*J```5
-ME````JH``"F4```"J@``/90```*J``!1E````JH``&64```"J@``>90```*J
-M``"-E````JH``*&4```"J@``M90```*J``#,E````JH```*5```"J@``%I4`
-M``*J```JE0```JH``#Z5```"J@``4)4```*M``!JE0```JH``)^5```"J@``
-MRI4```*M``#>E0```JH``/&5```"K0``!Y8```*J```9E@```JH``"N6```"
-MJ@``0)8```*J``!2E@```JH``&26```"J@``=I8```*J``"(E@```JH``)J6
-M```"J@``K)8```*J``"^E@```JH``-"6```"J@``L9<```)H``#*EP```F@`
-M`)J8```"J0``RI@```*J``#=F````JH``.V8```"K0``'ID```*J``!]F0``
-M`JH``)&9```"J@``LID```*I``#-F0```JH```B:```"J@``$IH```*M``"#
-MF@```JH``+*:```"L```")L```*I```YFP```JP``$Z;```"K```8YL```*L
-M``!XFP```JP``(V;```"K```VYL```*L``#PFP```JP```6<```"K```&IP`
-M``*L```OG````JP``$2<```"K```69P```*L``!UG````JD``("<```"L0``
-MG)P```*I``#3G````JX``!Z=```"J@``WYT```*M```TG@```JH``$2>```"
-MK0``6IX```*J``!JG@```JT``-F>```"J@``[)X```*J``#_G@```JH``":?
-M```"J@``2)\```*J``!_GP```J@``*B?```"LP``^)\```*J```)H````:L`
-M`!F@```!JP``TJ````*M``#XH````JT```2A```"J```$*$```*M``"JH0``
-M`JH``+:A```"K0``PJ$```*H``#0H0```JH``-RA```"K0``,:(```*M``!A
-MH@```JH``)*B```"K0``GJ(```*H``#2H@```JH```*C```"K0``#J,```*H
-M```<HP```J<``%6C```"J0``W*,```*M```\I````JH``'2E```"K0``E:4`
-M``*J``"TI0```JH``#ZF```"K0``;Z8```*J``#(I@```JT``/6F```"J@``
-M$*<```*M``!IIP```JT``)6G```"J@``L*<```*M``#>IP```JT``!*H```"
-MJ@``@J@```*M``"PJ````K,```"I```"K0``%:D```*M```JJ0```JT``#^I
-M```"K0``5*D```*M``!IJ0```JT``'ZI```"K0``DZD```*M``#TJ0```L(`
-M`-&K```"K0``!*P```*M```9K````JH``%RL```"J@``:*P```*M``!\K```
-M`JH``)BL```"K0``=*T```*J``"5K0```JH``,BM```"J0``Y:T```*H```<
-MK@```JP``#.N```"J0``6*X```*L``!OK@```JD``+6N```"J0``QJX```*H
-M``#>K@```JD``/VN```"LP``$:\```*H```JKP```K$``#RO```"J0``E:\`
-M``+'``"JKP```JP``+BO```"L0``R*\```+&``#9KP```L8``"ZP```"I0``
-ML;````*P``#OL````J4``':Q```"RP``[+$```+'```,L@```JP``".R```"
-MK```.K(```*L``!1L@```JP``&BR```"K```O[(```*L``#4L@```JP``.FR
-M```"K```_K(```*L```3LP```JP``"BS```"K```/;,```*L``!4LP```K$`
-M`&2S```"Q@``=[,```+&``"/LP```K$``)^S```"Q@``N;,```*I``#)LP``
-M`L8``/^S```"L0``&+0```*O```^M````JX``%JT```"L0``:K0```+&``!Z
-MM````L8``(JT```"Q@``P+0```*L``#2M````JD``-ZT```"J```YK0```+&
-M``#RM````J@``/ZT```"J```"K4```*H```6M0```J@``#"U```"J0``3;4`
-M``*H``"2M0```J@``+FU```!!```R+4```*L``#8M0```00``.>U```"J0``
-M`+8```$$```/M@```JD``"BV```!!```-[8```*I``!<M@```00``&NV```"
-MK```>+8```$$``"'M@```JP``*>V```!!```MK8```*L``"^M@```00``,RV
-M```"J0``^[8```*M```/MP```JH``!VW```"K0``0;<```*N``!2MP```JT`
-M`&2W```!!```<[<```*L``!]MP```00``(NW```"K```E;<```$$``"DMP``
-M`JP``*ZW```!!```O+<```*L``#3MP```JH``.&W```"K0``\+<```*J```3
-MN````JT``">X```"J@``-;@```*M``!9N````JX``&JX```"K0``?+@```$$
-M``"+N````JP``)6X```!!```H[@```*L``"MN````00``+RX```"K```QK@`
-M``$$``#4N````JP``.NX```"J@``^;@```*M```(N0```JH``"ZY```!!```
-M/;D```*L``!'N0```00``%6Y```"K```:[D```*I``"*N0```00``)BY```"
-MK```K+D```*H``"ZN0```JD``/"Y```"K0``!;H```*J```3N@```JT``#>Z
-M```"K@``2+H```*M``!@N@```JP``&^Z```"J@``?;H```*M``".N@```JH`
-M`-2Z```"S@``\[H```*M```(NP```JH``!:[```"K0``/+L```*N``!-NP``
-M`JT``%N[```"KP``B;L```$$``"8NP```JP``+*[```"J```QKL```*O``#5
-MNP```00``.2[```"K```#[P```$$```>O````JP``"R\```"KP``:KP```$$
-M``!YO````JP``(J\```"J@``F+P```*M``"IO````JH``,Z\```!!```TKP`
-M``$#``#HO````00``.R\```!`P``(`````&9```D`````9D``"@````!F0``
-M+`````&9```P`````8D``#0````!>```.`````&$``!``````94``&`````!
-M<```9`````%P``!H`````7```&P````!<```<`````&*``!T`````7H``'@`
-M```!A@``@`````&6`````````0(```0````!`@``"`````$"```,`````0(`
-M`!`````!`@``%`````$"```8`````0(``!P````!`@``(`````$"```D````
-D`0(``"@````!`@``+`````$"```P`````0(``#0````!`@``
+M1(```"H````2``$`E04`````````````$````*,%`````````````!````"M
+M!0`````````````0````MP4`````````````$````,$%`````````````!``
+M``#2!0`````````````0````X@4`````````````$````.P%```P!P``VP``
+M`!(``0#V!0`````````````0`````P8`````````````$````!4&```,"```
+MO`$``!(``0`E!@`````````````0````+@8``'"```!C````$@`!`#P&``#(
+M"0``6@```!(``0!/!@``[(,``!(````2``$`708``"0*``!``0``$@`!`&H&
+M``#$@P``*````!(``0!\!@``L'T``&,````2``$`AP8``&0+```5`0``$@`!
+M`)H&`````````````!````"D!@`````````````0````K@8``$P.``!@````
+M$@`!`+\&``#$A@``$P```!(``0#+!@``1(4``#D````2``$`VP8``*P.```$
+M`0``$@`!`.T&``"0A@``,0```!(``0#]!@``L`\``$(````2``$`$`<``/0/
+M``!O````$@`!`"('``#($```9`$``!(``0`X!P``+!(``(`````2``$`50<`
+M`*P2``"\````$@`!`&D'````AP``3@```!(``0!W!P``:!,``-D````2``$`
+MC@<``$04```_`0``$@`!`*8'``"$%0``\P```!(``0"\!P`````````````0
+M````Q@<``$@8``#,`0``$@`!`-@'``#8A@``)P```!(``0#I!P``%!H``%$!
+M```2``$`_`<``&@;``!V`0``$@`!``T(````'@``8````!(``0`="```8!X`
+M```!```2``$`+@@``&`?```R````$@`!`$`(````````!````!$``P!0"```
+M```````````0````7@@``*AG```P`0``$@`!`'$(`````````````!````"$
+M"``````````````0````BP@`````````````$````)((``#8:```80```!(`
+M`0">"``````````````0````P`@``!B&``!X````$@`!`,X(``"`:@``4```
+M`!(``0#@"```9'D``$P$```2``$`\@@``!!_```T`0``$@`!``4)```4?@``
+M_````!(``0`7"0`````````````0````*0D`````````````$````#P)```\
+M@P``/@```!(``0!+"0``?(,``$<````2``$`6@D```"$``!#`0``$@`!`&D)
+M``"`A0``6````!(``0!Z"0``V(4``#\````2``$`APD``%"'```>````$@`!
+M`)()``!PAP``-````!(``0"B"0``I(<```L!```2``$`K@D``$"M``!#````
+M$@`!`,8)``"$K0``2````!(``0#:"0``^+<``#T````2``$`]0D``#BX``".
+M````$@`!`!H*``#TK```3````!(``0`Q"@``W(@``'H````2``$`2`H`````
+M````````$````%P*`````````````!````!M"@`````````````0````@`H`
+M`(0````$````$0`#`),*`````````````!````"E"@`````````````0````
+MMPH``(2I``"8````$@`!`-8*`````````````!````#H"@`````````````0
+M````^0H```B]```[````$@`!``@+``!4M0``C0```!(``0`="P``L*4``!P#
+M```2``$`+PL``'S$``!7````$@`!`$4+``#,J```'P```!(``0!;"P``[*@`
+M``\````2``$`;0L``/RH```/````$@`!`(`+```,J0``3@```!(``0"7"P``
+M7*D``"8````2``$`JPL``!RJ```T`@``$@`!`,(+``!0K```H@```!(``0#7
+M"P``S*T``"`````2``$`[@L``.RM``#0````$@`!``@,``"\K@``C````!(`
+M`0`A#```2*\``!$!```2``$`.0P``%RP``!O`0``$@`!`%`,``#,L0``>0$`
+M`!(``0!C#```2+,``,L!```2``$`@0P``!2U```?````$@`!`)P,```TM0``
+M(````!(``0"Y#```Y+4``#P````2``$`TPP``""V```\````$@`!`.X,``!<
+MM@``E````!(``0`+#0``\+8``-0````2``$`*0T``,2W```S````$@`!`$@-
+M``"$O@``*`$``!(``0!/#0``K+\``!<!```2``$`5PT``(#!``#5````$@`!
+M`&4-``!8P@``1````!(``0!R#0``U,0``"L````2``$`?PT```#%```@`0``
+M$@`!``!R86ED+F,`4W1R:7!E1V5T0V]M;6%N9`!3=')I<&53<&QI=$-O;6UA
+M;F0`27-61&5V3VYL:6YE`$1O0V]N=')O;$-M9`!*0D]$1V5T0V]M;6%N9`!*
+M0D]$4W!L:71#;VUM86YD`%]?:'!T7V%L;&]C`%]?:'!T7V9R964`9V%R8F%G
+M95]A9&1R`&EN:71?:&5A<%]B;&]C:P!C8E]A;&QO8P!C8E]F<F5E`&-B7WIE
+M<F\`8V)?:7-?>F5R;P!C9E]I;FET`')E;6]V95]R86YG95]L;V-K`&%D9%]R
+M86YG95]L;V-K`&QO8VM?<F%N9V4`7U]A;&QO8U]T87-K`&9R965?<W1R:7!E
+M`&%L;&]C7W-T<FEP90!?7V=E=%]S=')I<&4`9&%T85]X9F5R`')E861?>&9E
+M<E]D;VYE`')A:60U7V1O;F4`<W1R:7!E7V1O;F4`:&%N9&QE7W-T<FEP90!R
+M86ED-5]D:7)T>0!T87-K7V1O;F4`<W1R:7!E7V-H96-K7W1A<VL`<G=?=&%S
+M:U]B=6EL9'-G;`!R=U]G971?<F%N9V4`<G=?=&%S:U]D;VYE`%]?9&]?<G=?
+M=&%S:P!D;U]R=U]T87-K`&=E=%]S;&EC97,`9&]?>&]R7W1A<VL`>&]R7W1A
+M<VM?9&]N90!D;U]X;W(R7W1A<VL`9&]?>&]R;E]T87-K`&-H96-K7V1E<&5N
+M9&5N8WD`9&ER96-T7W)E861?<V=L`&1I<F5C=%]R96%D7V-O;7!L971I;VX`
+M:&%N9&QE7V-M9`!G971?<W1R:7!E<P!W<FET95]X9F5R7V1O;F4`4WEN8T1I
+M<VM);F9O`&=E=$5D;6%296=/9F9S970`=6YM87-K161M84EN=&5R<G5P=',`
+M;6%S:T5D;6%);G1E<G)U<'1S`'=R:71E161M85)E<75E<W1%;G1R>0!D=6UP
+M071A1&5V:6-E4F5G:7-T97)S`&AA;F1L945D;6%&86EL961#;VUM86YD`')E
+M;6]V94-O;6UA;F0`:&%N9&QE161M85)E<W!O;G-E`&1E86-T:79A=&5%9&UA
+M`'-E;F1.;VYE561M84-O;6UA;F0`8V]M<&QE=&5024]#;VUM86YD`%-E=$=0
+M24]#=')L4F5G`&AA;F1L945D;6%);G1E<G)U<'0`7V-H86YN96Q(87)D4F5S
+M970`7V9I>%!H>5!A<F%M<P!?9&]!=71O1FQU<V@`:&%N9&QE1&5V:6-E26YT
+M97)R=7!T`&1I<V%B;&53841E=DEN=&5R<G5T<',`:&%N9&QE4$E/26YT97)R
+M=7!T`'1R86YS9F5R4$E/1&%T80!A8W1I=F%T945D;6$`161M85)E<5%U975E
+M26YS97)T`')E<V5T161M84-H86YN96P`9FQU<VA$;6%1=65U90!R979E<G13
+M871A2$-296=S`')E=F5R=$9L87-H26YT97)F86-E4F5G<P!R979E<G100TE)
+M;G1E<F9A8V5296=S`&-O;6UA;F1S475E=65!9&1486EL`&-O;6UA;F1S475E
+M=65296UO=F4`861D0V]M;6%N9`!3841E=DEN=&5R<G5T<$)I=`!E;F%B;&53
+M841E=DEN=&5R<G5T<',`97AE8W5T94YO;E5$34%#;VUM86YD`%]D;U-O9G12
+M97-E=`!?861D<DUA<#$`7V%D9')-87`R`&%D9')-87``9&ES86)L95]B965P
+M97(`16YT97(V,#$`17AI=#8P,0!G971?-C`Q7VED`'-E=%]C=&P`7U]C:&5C
+M:U]P<F]T96-T7V-I<F-U:70`9D-H96-K07)R87D`<&9N4V5N9$-O;6UA;F0`
+M9D1E4F5A9%=R:71E`'!F;D1E=FEC949A:6QE9`!#:&5C:U-U;0!F1&5396QE
+M8W1-;V1E`&]S7VUE;7-E=`!F1&5397140U$`9D1E4V5T3D-1`&9$95-E=%=R
+M:71E0V%C:&4`9D1E4V5T4F5A9$%H96%D`&]S7VUE;6-P>0!F061D4W!A<F4`
+M1V5T4W!A<F5$:7-K`&EO8W1L7U)E<&]R=$5V96YT`$9I>'5P07)R87E3=&%T
+M90!'9713=&%M<`!3>6YC07)R87E);F9O`$-H96-K07)R87E#<FET:6-A;`!F
+M3W-$:7-K1F%I;&5D`&9$96QE=&5!<G)A>0!5;G)E9VES=&5R5D1E=FEC90!R
+M86ED-5]F<F5E`%-T<FEP94)U:6QD4V=486)L90!?7W5D:79D:3,`7U]U;6]D
+M9&DS`&9204E$,$UE;6)E<D1O;F4`1G)E94-O;6UA;F0`0V%L;$%F=&5R4F5T
+M=7)N`&9204E$,%-E;F1#;VUM86YD`$%L;&]C871E0V]M;6%N9`!F4D%)1#!-
+M96UB97)&86EL960`4D%)1#%"=6EL9%-G5&%B;&4`4D%)1#%-96UB97)#;VUP
+M;&5T:6]N`%)!240Q26YI=%)E8G5I;&1"=6EL9%-G5&%B;&4`4D%)1#%);FET
+M0V]M<&QE=&EO;@!$;U=A:71I;F=,:7-T`%)!240Q4F5B=6EL9$-O;7!L971I
+M;VX`4D%)1#%697)I9GE"=6EL9%-G5&%B;&4`4D%)1#%697)I9GE#;VUP;&5T
+M:6]N`&]S7VUE;6-M<`!F4D%)1#%396YD0V]M;6%N9`!!9&14;U=A:71I;F=,
+M:7-T`&9204E$,4UE;6)E<D9A:6QE9`!*0D]$0G5I;&139U1A8FQE`&9*0D]$
+M365M8F5R1&]N90!F2D)/1%-E;F1#;VUM86YD`&9*0D]$365M8F5R1F%I;&5D
+M`&YU;5]R86ED-5]P86=E<P!O<U]A;&QO8U]P86=E`&9L=7-H7W-T<FEP95]C
+M86-H90!F3W-0:'ES:6-A;$%D9')E<W,`1&]8;W(R`$1O6&]R,0!F;'5S:%]R
+M86ED-0!F0V]M<&QE=&5!;&Q#;VUM86YD<U-Y;F-H<F]N;W5S;'D`0VAE8VM)
+M9&QE0V%L;`!F;'5S:%]R86ED-5]A<WEN8P!F4D%)1#5396YD0V]M;6%N9`!F
+M4D%)1#5-96UB97)&86EL960`:6YI=%]R86ED-5]M96UO<GD`;W-?86QL;V-?
+M9&UA7W!A9V4`9D1E=FEC95-E;F1#;VUM86YD`&9'971&:7)S=$-H:6QD`&92
+M97-E=$)O;W1-87)K`&9#:&5C:T)O;W1A8FQE`$-H96-K4&5N9&EN9T-A;&P`
+M0V%L;%=H96Y)9&QE`&9&;'5S:%9$978`9D9L=7-H5D1E=D%S>6YC`&UV4F5A
+M9%=R:71E`&UV4V%T841I<V%B;&5#:&%N;F5L1&UA`&UV4V%T849L=7-H1&UA
+M475E=64`;793=&]R86=E1&5V051!4V5T1F5A='5R97,`;793=&]R86=E1&5V
+M051!17AE8W5T94YO;E5$34%#;VUM86YD`&UV4V%T845N86)L94-H86YN96Q$
+M;6$`=V%I=$9O<D)U<WE!9G1E<DA297-E=`!M=DUI8W)O4V5C;VYD<T1E;&%Y
+M`$U67U)%1U]214%$7T)95$4`359?4D5'7U=2251%7T173U)$`&UV075T;T9L
+M=7-H3VY%<G)O<@!-5E]214=?5U))5$5?0EE410!-5E]214=?4D5!1%]$5T]2
+M1`!M=E-A=&%)<U-T;W)A9V5$979I8V5#;VYN96-T960`359?4D5'7U=2251%
+M7U=/4D0`359?4D5'7U)%041?5T]21`!?9&]-=E-O9G1297-E=`!M=E-T;W)A
+M9V5$979786ET4W1A=`!M=E-A=&%);FET061A<'1E<@!C:&5C:U]P<F]T96-T
+M7V-I<F-U:70`;793871A4VAU=&1O=VY!9&%P=&5R`&UV16YA8FQE075T;T9L
+M=7-H`&UV1&ES86)L94%U=&]&;'5S:`!M=E-A=&%#;VYF:6=U<F5#:&%N;F5L
+M`&UV4V%T85)E;6]V94-H86YN96P`;793871A0VAA;FYE;$AA<F1297-E=`!M
+M=E-A=&%#;VYF:6=%9&UA36]D90!M=E-A=&%.=6U/9D1M84-O;6UA;F1S`&UV
+M4V%T85-E=$-H86YN96Q0:'E087)A;7,`;793871A0VAA;FYE;%!H>5-H=71D
+M;W=N`&UV4V%T84-H86YN96Q0:'E0;W=E<D]N`&UV4V%T84=E=$-H86YN96Q3
+M=&%T=7,`;793871A475E=65#;VUM86YD`&UV4V%T84EN=&5R<G5P=%-E<G9I
+M8V52;W5T:6YE`&UV4V%T84UA<VM!9&%P=&5R26YT97)R=7!T`&UV4V%T855N
+M;6%S:T%D87!T97));G1E<G)U<'0`96YA8FQE4W1O<F%G941E=DEN=&5R<G5P
+M=`!D:7-A8FQE4W1O<F%G941E=DEN=&5R<G5P=`!M=E-T;W)A9V5$979!5$%)
+M9&QE26UM961I871E`&UV4W1O<F%G941E=D%404ED96YT:69Y1&5V:6-E`&UV
+M4W1O<F%G941E=D%405-O9G1297-E=$1E=FEC90!"965P3VX`0F5E<$]F9@!S
+M971?9F%I;%]L961S`'-E=%]F86EL7VQE9`!S>#4P.'A?:6]C=&P`<W@U,#AX
+M7V9L87-H7V%C8V5S<P``5`````%B``""`````F,``)X````!9```O@````)E
+M``#M`````F8```0!```"90``)@$```)G``",`0```F@``*@!```":0``P@$`
+M``)J``#<`0```FL``!$"```!9```/@(```%B```-`P```F<``+\#```!8@``
+MW0,```)L``#X`P```FP``!,$```";```+@0```)L```0!0```F<``-<%```!
+M8@``Y`4```%D```6!@```FP``#8&```";```5@8```)L``!V!@```FP``,$&
+M```!9```(0<```%D``!R!P```FX``*$'```!8@``K@<```%D``#X!P```F\`
+M`'D(```"<```VP@```)M``!K"0```FT``*T)```"<0``N0D```)R``#^"0``
+M`G````X*```!=```/@H```)V``!2"@```G<``),*```"=0``O0H```%T``#J
+M"@```F<``/X*```"8P``'0L```)R```\"P```F<``((-```">0``M@T```)Z
+M``!]#@```GP``)X.```"?0``T@X```)]```!#P```GT``#,/```"?P``>@\`
+M``%[``"!#P```7@``#,1```"9P``A1$```)G``#&$0```GP``/L1```"?0``
+MY!(```)\```[$P```GT``%$3```!A0``61,```)]``"E$P```F<```@4```"
+M?```%Q0```)]```M%````84``#44```"?0``QQ4```)G``#S%0```HD``$(6
+M```"?```3Q8```)]``!E%@```84``&L6```"?0``ZA8```)G```#%P```G\`
+M`"L7```!A```,A<```&#``!Q%P```G\``)D7```!A@``H!<```&#``#1%P``
+M`G\``/D7```!B````!@```&'```E&````GT``#08```!A0``.A@```)]``!K
+M&````GT``'T8```!`@``ZQ@```&*``#X&````HL``+H9```"?P``R1D```)L
+M``#D&0```8(``.L9```!@0``N1H```)N``#1&@```6(``-D:```!9```%QL`
+M``)O``!*&P```G$``%H;```"<@``S1P```)L```Q'@```GP``%(>```"?0``
+MAAX```)]``"R'@```GT``.,>```"?P``*A\```&.```Q'P```8T``(\@```"
+MD@``)R(```)G``"*(@```F<``.@F```">@``Y"@```)L```%*0```FP``(<M
+M```!`@``:RX```$"``!S+@```GT``*XN```!A0``MBX```)]``#7+@```84`
+M`-TN```"?0``)2\```)]``!0+P```I,``'HO```!`@``@B\```)]```#,```
+M`I0``($Q```"?```53(```)_``"9,@```0(``*,R```!`@``2#4```*5``!T
+M-0```I8``"HV```"E0```#<```*5``!/.````I4``'TX```"E@``;#H```$N
+M```\.P```2X``')H```"?0```6D```*3```):0```I@``!%I```"F0``Q&H`
+M``*3```5:P```GT``"QK```!A0``,FL```)]``!>:P```84``&1K```"?0``
+MCVL```*3``#>;````00``.EL```!!```[FP```*4``!$;P```GP``.%Q```"
+M9P``2W0```&%``!3=````GT``(=T```"?P``MW0```$"``"^=````0(``,)U
+M```">@``X74```)Z``!#>0```0(``$EY```"?0``D'D```)]``#">0```F<`
+M`.UY```"?0``%WH```)]``"?>@```GD``'%[```">0``!WP```)]``"X?```
+M`9L``,A\```"BP``'GT```&<```[?0```9L``$U]```"BP``6'T```*3``!M
+M?0```0(``)%]```"?0``Q7T```*7``!A?@```9$``)=^```!D0``PGX```*>
+M``#'?@```00``-%^```!D0``W7X```*>```!?P```9$``+Y_```";@``W'\`
+M``%B``#D?P```60``!"````";P``*H````)Q```V@````G(``*R````"<@``
+M'X$```)G```[@@```FP``%""```";```:((```)L``!]@@```FP``/^"```"
+M90``#X,```)E```O@P```F,``'.#```"H```HX,```*A``#X@P```G8``#V$
+M```"9P``C(0```)C``#+A````F,``&>&```"F```MH8```)G``!CAP```I<`
+M`(^'```"F@``Q(<```*H``#0AP```JD``.2'```"J@``DX@```*K``"?B```
+M`JP``/.(```"K@``&8D```*O```UB0```JX``'N)```"L```CXD```*P``"_
+MB0```K```(>,```"L@``EXP```*O``"LC````J\``,>,```"KP``XHP```*O
+M``#]C````J\``!^-```"L@``*XT```*O```^C0```J\``%&-```"KP``9(T`
+M``*O``!YC0```K(``(R-```"KP``GXT```*O``#<C0```K,``+2/```"LP``
+MRH\```*P``#:CP```K,``.J/```"LP``!9````*P```5D````K,``":0```"
+ML```F)````*P```'D0```K,``!^1```"L```PI$```*P``#.D0```K,``-J1
+M```"K@``Z)$```*P``#TD0```K,```"2```"K@``()(```*T``#9D@```;$`
+M`)V3```"KP``K9,```*O``#5DP```K```'25```"M0``IY4```*V``!,E@``
+M`;$``-&6```"LP``W98```*N``!0EP```K,``&.7```"L```;9<```*S``!Y
+MEP```JX``)^7```"L```0I@```*P``!7F````K```&J8```"L```@Y@```*P
+M``"EF````K```+B8```"L```VI@```*P``#PF````K```!Z:```"LP``5IH`
+M``*P``"*F@```K,``.Z:```"L```+9L```*P```YFP```K,``$6;```"K@``
+M4YL```*P``!?FP```K,``+6;```"L```Q)L```*S``#AFP```K```/6;```"
+ML```"9P```*P```=G````K```#&<```"L```19P```*P``!9G````K```&V<
+M```"L```@9P```*P``"5G````K```*F<```"L```O9P```*P``#4G````K``
+M``J=```"L```'IT```*P```RG0```K```$:=```"L```6)T```*S``!RG0``
+M`K```*>=```"L```TIT```*S``#FG0```K```/F=```"LP``#YX```*P```A
+MG@```K```#.>```"L```2)X```*P``!:G@```K```&R>```"L```?IX```*P
+M``"0G@```K```**>```"L```M)X```*P``#&G@```K```-B>```"L```N9\`
+M``)L``#2GP```FP``*N@```"KP``VZ````*P``#KH````K,```6A```"L```
+M%:$```*S``!,H0```K,``&:A```"L```S:$```*P``#AH0```K````*B```"
+MKP``':(```*P``!BH@```K```'6B```"LP``B:(```*N```GHP```K```%:C
+M```"MP``K*,```*O``#=HP```K(``/*C```"L@``!Z0```*R```<I````K(`
+M`#&D```"L@``?Z0```*R``"4I````K(``*FD```"L@``OJ0```*R``#3I```
+M`K(``.BD```"L@``_:0```*R```9I0```J\``#&E```"N```3:4```*O``"#
+MI0```K4``,ZE```"L```V:4```*Z``"OI@```K,```>G```"L```%Z<```*S
+M```QIP```K```$VG```"LP``P:<```*P``#4IP```K```.>G```"L```#J@`
+M``*P```PJ````K```&>H```"K@``C:@```*T``#@J````K```/&H```!L0``
+M`:D```&Q``"ZJ0```K,``."I```"LP``[*D```*N``#XJ0```K,``.FJ```"
+MLP``&:L```*P``!*JP```K,``%:K```"K@``BJL```*P``"ZJP```K,``,:K
+M```"K@``U*L```*M```.K````J\``(VL```"LP``WJP```*P``!>K@```K,`
+M`(^N```"L```[*X```*S```9KP```K```#2O```"LP``C:\```*S``"YKP``
+M`K```-2O```"LP```K````*S```VL````K```*:P```"LP``U+````*T```D
+ML0```K,``#FQ```"LP``3K$```*S``!CL0```K,``'BQ```"LP``C;$```*S
+M``"BL0```K,``+>Q```"LP``8;,```*S``"FLP```K,``,VS```"L```#K0`
+M``*P```:M````K,``"ZT```"L```2K0```*S```HM0```K```$FU```"L```
+MB[4```*O``"SM0```JX``,*U```"M````+8```*R```7M@```J\``#RV```"
+ML@``4[8```*O``"2M@```LP``*>V```"L@``O;8```*X``#-M@```LL``-VV
+M```"RP``1+<```*K``!PMP```JH``/&W```"MP``+[@```*K```_N0```K@`
+M`%BY```"S```?;D```*R``"6N0```K(``*^Y```"L@``R+D```*R``#AN0``
+M`K(``!NZ```"RP``/;H```*R``!4N@```K(``&NZ```"L@``@KH```*R``"9
+MN@```K(``+"Z```"L@``Q[H```*R``#GN@```K@``/>Z```"RP``"KL```++
+M```KNP```K@``#N[```"RP``5[L```*O``!GNP```LL``*"[```"N```N;L`
+M``*V``#9NP```K4``/:[```"N```!KP```++```6O````LL``":\```"RP``
+M7+P```*R``!NO````J\``'J\```"K@``@KP```++``".O````JX``)J\```"
+MK@``IKP```*N``"RO````JX``,R\```"KP``Z;P```*N```NO0```JX``%6]
+M```!`P``9+T```*R``!TO0```0,``(.]```"KP``G+T```$#``"KO0```J\`
+M`,2]```!`P``T[T```*O``#XO0```0,```>^```"L@``%+X```$#```CO@``
+M`K(``$.^```!`P``4KX```*R``!:O@```0,``&B^```"KP``DKX```$$``"G
+MO@```K,``+N^```"L```R;X```*S``#MO@```K4``/Z^```"LP``$+\```$#
+M```?OP```K(``"F_```!`P``-[\```*R``!!OP```0,``%"_```"L@``6K\`
+M``$#``!HOP```K(``'^_```"L```C;\```*S``"<OP```K```+^_```"LP``
+MT[\```*P``#AOP```K,```7````"M0``%L````*S```HP````0,``#?````"
+ML@``0<````$#``!/P````K(``%G````!`P``:,````*R``!RP````0,``(#`
+M```"L@``E\````*P``"EP````K,``+3````"L```VL````$#``#IP````K(`
+M`//````!`P```<$```*R```7P0```J\``#;!```!`P``1,$```*R``!8P0``
+M`JX``&;!```"KP``G,$```*S``"QP0```K```+_!```"LP``X\$```*U``#T
+MP0```K,```G"```!`P``&,(```*R```GP@```K```#7"```"LP``1L(```*P
+M``"6P@```M(``+/"```"LP``R,(```*P``#6P@```K,``/S"```"M0``#<,`
+M``*S```;PP```K8``$G#```!`P``6,,```*R``!RPP```JX``(;#```"M@``
+ME<,```$#``"DPP```K(``,_#```!`P``WL,```*R``#LPP```K8``"K$```!
+M`P``.<0```*R``!*Q````K```%C$```"LP``:<0```*P``".Q````0,``)+$
+M```!`P``J,0```$#``"LQ````0,``.O$```!!```&<4```*S```NQ0```K``
+M`#S%```"LP``8L4```*U``!SQ0```K,``)S%```"KP``T,4```*R``#MQ0``
+M`K```/O%```"LP``#,8```*P```@`````9\``"0````!GP``*`````&?```L
+M`````9\``#`````!CP``-`````%^```X`````8H``$`````!FP``8`````%T
+M``!D`````70``&@````!=```;`````%T``!P`````9```'0````!@```>```
+M``&,``"``````9P``.`````!`P````````$"```$`````0(```@````!`@``
+M#`````$"```0`````0(``!0````!`@``&`````$"```<`````0(``"`````!
+K`@``)`````$"```H`````0(``"P````!`@``,`````$"```T`````0(`````
`
end
diff --git a/sys/dev/hptmv/ioctl.c b/sys/dev/hptmv/ioctl.c
index bf80700..5887822 100644
--- a/sys/dev/hptmv/ioctl.c
+++ b/sys/dev/hptmv/ioctl.c
@@ -209,7 +209,11 @@ lock_driver_idle(IAL_ADAPTER_T *pAdapter)
#if (__FreeBSD_version < 500000)
YIELD_THREAD;
#else
+#if (__FreeBSD_version > 700033)
pause("switch", 1);
+#else
+ tsleep(lock_driver_idle, PPAUSE, "switch", 1);
+#endif
#endif
oldspl = lock_driver();
}
@@ -337,6 +341,7 @@ int Kernel_DeviceIoControl(_VBUS_ARG
case HPT_IOCTL_GET_CHANNEL_INFO:
case HPT_IOCTL_GET_LOGICAL_DEVICES:
case HPT_IOCTL_GET_DEVICE_INFO:
+ case HPT_IOCTL_GET_DEVICE_INFO_V2:
case HPT_IOCTL_GET_EVENT:
case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize,
@@ -351,10 +356,14 @@ int Kernel_DeviceIoControl(_VBUS_ARG
switch(dwIoControlCode) {
case HPT_IOCTL_CREATE_ARRAY:
pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break;
+ case HPT_IOCTL_CREATE_ARRAY_V2:
+ pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break;
case HPT_IOCTL_SET_ARRAY_INFO:
pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break;
case HPT_IOCTL_SET_DEVICE_INFO:
pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break;
+ case HPT_IOCTL_SET_DEVICE_INFO_V2:
+ pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break;
case HPT_IOCTL_SET_BOOT_MARK:
case HPT_IOCTL_ADD_SPARE_DISK:
case HPT_IOCTL_REMOVE_SPARE_DISK:
@@ -410,6 +419,22 @@ int Kernel_DeviceIoControl(_VBUS_ARG
break;
}
+
+ case HPT_IOCTL_CREATE_ARRAY_V2:
+ {
+ pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt;
+ oldspl = lock_driver();
+ if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) {
+ (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0;
+ hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE);
+ } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) {
+ hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE);
+ } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) {
+ hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY);
+ }
+ unlock_driver(oldspl);
+ break;
+ }
case HPT_IOCTL_ADD_DISK_TO_ARRAY:
{
PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray);
@@ -424,7 +449,11 @@ int Kernel_DeviceIoControl(_VBUS_ARG
unlock_driver(oldspl);
while (!pArray->u.array.rf_rebuilding)
{
+#if (__FreeBSD_version > 700033)
pause("pause", 1);
+#else
+ tsleep((caddr_t)Kernel_DeviceIoControl, PPAUSE, "pause", 1);
+#endif
if ( timeout >= hz*3)
break;
timeout ++;
@@ -489,7 +518,11 @@ hpt_set_array_state(DEVICEID idArray, DWORD state)
while (!pVDevice->u.array.rf_rebuilding)
{
+#if (__FreeBSD_version > 700033)
pause("pause", 1);
+#else
+ tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
+#endif
if ( timeout >= hz*20)
break;
timeout ++;
@@ -514,7 +547,11 @@ hpt_set_array_state(DEVICEID idArray, DWORD state)
while (pVDevice->u.array.rf_abort_rebuild)
{
+#if (__FreeBSD_version > 700033)
pause("pause", 1);
+#else
+ tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
+#endif
if ( timeout >= hz*20)
break;
timeout ++;
@@ -538,7 +575,11 @@ hpt_set_array_state(DEVICEID idArray, DWORD state)
while (!pVDevice->u.array.rf_verifying)
{
+#if (__FreeBSD_version > 700033)
pause("pause", 1);
+#else
+ tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
+#endif
if ( timeout >= hz*20)
break;
timeout ++;
@@ -557,7 +598,11 @@ hpt_set_array_state(DEVICEID idArray, DWORD state)
while (pVDevice->u.array.rf_abort_rebuild)
{
+#if (__FreeBSD_version > 700033)
pause("pause", 1);
+#else
+ tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
+#endif
if ( timeout >= hz*80)
break;
timeout ++;
@@ -578,7 +623,11 @@ hpt_set_array_state(DEVICEID idArray, DWORD state)
while (!pVDevice->u.array.rf_initializing)
{
+#if (__FreeBSD_version > 700033)
pause("pause", 1);
+#else
+ tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
+#endif
if ( timeout >= hz*80)
break;
timeout ++;
@@ -597,7 +646,11 @@ hpt_set_array_state(DEVICEID idArray, DWORD state)
while (pVDevice->u.array.rf_abort_rebuild)
{
+#if (__FreeBSD_version > 700033)
pause("pause", 1);
+#else
+ tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1);
+#endif
if ( timeout >= hz*80)
break;
timeout ++;
@@ -952,7 +1005,11 @@ fail:
#if (__FreeBSD_version < 500000)
YIELD_THREAD;
#else
+#if (__FreeBSD_version > 700033)
pause("switch", 1);
+#else
+ tsleep(hpt_rebuild_data_block, PPAUSE, "switch", 1);
+#endif
#endif
oldspl = lock_driver();
}
diff --git a/sys/dev/hptmv/mvOs.h b/sys/dev/hptmv/mvOs.h
index 510f790..a1ababc 100644
--- a/sys/dev/hptmv/mvOs.h
+++ b/sys/dev/hptmv/mvOs.h
@@ -28,7 +28,7 @@
#ifndef __INCmvOsBsdh
#define __INCmvOsBsdh
-#ifdef DBG
+#ifdef DEBUG
#define MV_DEBUG_LOG
#endif
@@ -58,10 +58,10 @@ typedef void *PVOID, *LPVOID;
typedef void *ADDRESS;
typedef int LONG;
-typedef unsigned int ULONG, *PULONG, LBA_T;
+typedef unsigned int ULONG, *PULONG;
typedef unsigned int DWORD, *LPDWORD, *PDWORD;
typedef unsigned long ULONG_PTR, UINT_PTR, BUS_ADDR;
-typedef unsigned long long HPT_U64;
+typedef unsigned long long HPT_U64, LBA_T;
typedef enum mvBoolean{MV_FALSE, MV_TRUE} MV_BOOLEAN;
diff --git a/sys/dev/hptmv/mvSata.h b/sys/dev/hptmv/mvSata.h
index bf77fbf..982743c 100644
--- a/sys/dev/hptmv/mvSata.h
+++ b/sys/dev/hptmv/mvSata.h
@@ -36,15 +36,34 @@
#define SUPPORT_MV_SATA_GEN_2 0
#endif
-#if SUPPORT_MV_SATA_GEN_1==1 && SUPPORT_MV_SATA_GEN_2==1
+#ifndef SUPPORT_MV_SATA_GEN_2E
+#define SUPPORT_MV_SATA_GEN_2E 0
+#endif
+
+#if (SUPPORT_MV_SATA_GEN_1 + SUPPORT_MV_SATA_GEN_2 + SUPPORT_MV_SATA_GEN_2E) > 1
+
#define MV_SATA_GEN_1(x) ((x)->sataAdapterGeneration==1)
-#define MV_SATA_GEN_2(x) ((x)->sataAdapterGeneration==2)
+#define MV_SATA_GEN_2(x) ((x)->sataAdapterGeneration>=2)
+#define MV_SATA_GEN_2E(x) ((x)->sataAdapterGeneration==3)
+
#elif SUPPORT_MV_SATA_GEN_1==1
+
#define MV_SATA_GEN_1(x) 1
#define MV_SATA_GEN_2(x) 0
+#define MV_SATA_GEN_2E(x) 0
+
#elif SUPPORT_MV_SATA_GEN_2==1
+
#define MV_SATA_GEN_1(x) 0
#define MV_SATA_GEN_2(x) 1
+#define MV_SATA_GEN_2E(x) 0
+
+#elif SUPPORT_MV_SATA_GEN_2E==1
+
+#define MV_SATA_GEN_1(x) 0
+#define MV_SATA_GEN_2(x) 1 /* gen2E impiles gen2 */
+#define MV_SATA_GEN_2E(x) 1
+
#else
#error "Which IC do you support?"
#endif
@@ -56,8 +75,15 @@
#define MV_SATA_DEVICE_ID_5081 0x5081
#define MV_SATA_DEVICE_ID_6080 0x6080
#define MV_SATA_DEVICE_ID_6081 0x6081
+
+#if defined(RR2310) || defined(RR1740) || defined(RR2210) || defined (RR2522)
+#define MV_SATA_CHANNELS_NUM 4
+#define MV_SATA_UNITS_NUM 1
+#else
#define MV_SATA_CHANNELS_NUM 8
#define MV_SATA_UNITS_NUM 2
+#endif
+
#define MV_SATA_PCI_BAR0_SPACE_SIZE (1<<18) /* 256 Kb*/
#define CHANNEL_QUEUE_LENGTH 32
@@ -156,7 +182,7 @@ typedef MV_BOOLEAN (* HPTLIBAPI mvSataCommandCompletionCallBack_t)(struct mvSata
MV_COMPLETION_TYPE,
MV_VOID_PTR, MV_U16,
MV_U32,
- struct mvStorageDevRegisters FAR*);
+ struct mvStorageDevRegisters SS_SEG*);
typedef enum mvQueuedCommandType
{
@@ -222,8 +248,8 @@ typedef struct mvSataChannel
MV_BOOLEAN waitingForInterrupt;
MV_BOOLEAN lba48Address;
MV_BOOLEAN maxReadTransfer;
- struct mvDmaRequestQueueEntry FAR *requestQueue;
- struct mvDmaResponseQueueEntry FAR *responseQueue;
+ struct mvDmaRequestQueueEntry SS_SEG *requestQueue;
+ struct mvDmaResponseQueueEntry SS_SEG *responseQueue;
MV_U32 requestQueuePciHiAddress;
MV_U32 requestQueuePciLowAddress;
MV_U32 responseQueuePciHiAddress;
@@ -243,7 +269,7 @@ typedef struct mvSataChannel
MV_BOOLEAN queueCommandsEnabled;
MV_U8 noneUdmaOutstandingCommands;
MV_U8 EdmaQueuedCommands;
- MV_U32 freeIDsStack[MV_EDMA_QUEUE_LENGTH];
+ MV_U32 freeIDsStack[CHANNEL_QUEUE_LENGTH];
MV_U32 freeIDsNum;
MV_U32 reqInPtr;
MV_U32 rspOutPtr;
@@ -279,7 +305,10 @@ typedef struct mvSataAdapter
MV_BOOLEAN implement60X1A0Workarounds;
MV_BOOLEAN implement60X1A1Workarounds;
MV_BOOLEAN implement60X1B0Workarounds;
+ MV_BOOLEAN implement7042A0Workarounds;
+ MV_BOOLEAN implement7042A1Workarounds;
MV_U8 sataAdapterGeneration;
+ MV_BOOLEAN isPEX;
MV_U8 failLEDMask;
MV_U8 signalAmps[MV_SATA_CHANNELS_NUM];
MV_U8 pre[MV_SATA_CHANNELS_NUM];
@@ -394,21 +423,9 @@ MV_BOOLEAN HPTLIBAPI mvSataChannelSetEdmaLoopBackMode(MV_SATA_ADAPTER *pAdapter,
MV_BOOLEAN HPTLIBAPI mvSataGetChannelStatus(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex,
MV_SATA_CHANNEL_STATUS *pChannelStatus);
-/* Execute UDMA ATA commands */
-MV_EDMA_QUEUE_RESULT HPTLIBAPI mvSataQueueUDmaCommand(MV_SATA_ADAPTER *pAdapter,
- MV_U8 channelIndex,
- MV_UDMA_TYPE readWrite,
- MV_U32 lowLBAAddr,
- MV_U16 highLBAAddr,
- MV_U16 sectorCount,
- MV_U32 prdLowAddr,
- MV_U32 prdHighAddr,
- mvSataCommandCompletionCallBack_t callBack,
- MV_VOID_PTR commandId);
-
MV_QUEUE_COMMAND_RESULT HPTLIBAPI mvSataQueueCommand(MV_SATA_ADAPTER *pAdapter,
MV_U8 channelIndex,
- MV_QUEUE_COMMAND_INFO FAR *pCommandParams);
+ MV_QUEUE_COMMAND_INFO SS_SEG *pCommandParams);
/* Interrupt Service Routine */
MV_BOOLEAN HPTLIBAPI mvSataInterruptServiceRoutine(MV_SATA_ADAPTER *pAdapter);
diff --git a/sys/dev/hptmv/mvStorageDev.h b/sys/dev/hptmv/mvStorageDev.h
index 48aad93..d9cdce6 100644
--- a/sys/dev/hptmv/mvStorageDev.h
+++ b/sys/dev/hptmv/mvStorageDev.h
@@ -207,6 +207,9 @@ MV_BOOLEAN HPTLIBAPI mvStorageDevATAFlushWriteCache(MV_SATA_ADAPTER *pAdapter,
MV_BOOLEAN HPTLIBAPI mvStorageDevATASoftResetDevice(MV_SATA_ADAPTER *pAdapter,
MV_U8 channelIndex);
+MV_BOOLEAN HPTLIBAPI mvStorageDevWaitStat(MV_SATA_CHANNEL *pSataChannel,
+ MV_U8 good, MV_U8 bad, MV_U32 loops, MV_U32 delay);
+
MV_BOOLEAN HPTLIBAPI mvReadWrite(MV_SATA_CHANNEL *pSataChannel, LBA_T Lba, UCHAR Cmd, void *tmpBuffer);
#endif
diff --git a/sys/dev/hptmv/osbsd.h b/sys/dev/hptmv/osbsd.h
index 904bb39..e71e3ed 100644
--- a/sys/dev/hptmv/osbsd.h
+++ b/sys/dev/hptmv/osbsd.h
@@ -42,7 +42,7 @@
#include <vm/pmap.h>
#include <vm/vm_extern.h>
-#if (__FreeBSD_version < 600030)
+#if (__FreeBSD_version < 600000)
#include <machine/bus_memio.h>
#endif
#include <machine/bus.h>
@@ -102,11 +102,6 @@ typedef struct _INQUIRYDATA {
UCHAR Reserved3[40];
} INQUIRYDATA, *PINQUIRYDATA;
-typedef struct _READ_CAPACITY_DATA {
- ULONG LogicalBlockAddress;
- ULONG BytesPerBlock;
-} READ_CAPACITY_DATA, *PREAD_CAPACITY_DATA;
-
#define MV_IAL_HT_SACOALT_DEFAULT 1
#define MV_IAL_HT_SAITMTH_DEFAULT 1
@@ -145,7 +140,13 @@ typedef struct _MV_CHANNEL
unsigned int maxUltraDmaModeSupported;
unsigned int maxDmaModeSupported;
unsigned int maxPioModeSupported;
- MV_BOOLEAN online;
+ MV_BOOLEAN online;
+ MV_BOOLEAN writeCacheSupported;
+ MV_BOOLEAN writeCacheEnabled;
+ MV_BOOLEAN readAheadSupported;
+ MV_BOOLEAN readAheadEnabled;
+ MV_U8 queueDepth;
+
} MV_CHANNEL;
typedef struct _BUS_DMAMAP
@@ -302,12 +303,27 @@ typedef struct _HPT_SET_DEVICE_INFO
ALTERABLE_DEVICE_INFO Info;
} HPT_SET_DEVICE_INFO, *PHPT_SET_DEVICE_INFO;
+typedef struct _HPT_SET_DEVICE_INFO_V2
+{
+ DEVICEID idDisk;
+ ALTERABLE_DEVICE_INFO_V2 Info;
+} HPT_SET_DEVICE_INFO_V2, *PHPT_SET_DEVICE_INFO_V2;
+
typedef struct _HPT_ADD_DISK_TO_ARRAY
{
DEVICEID idArray;
DEVICEID idDisk;
} HPT_ADD_DISK_TO_ARRAY, *PHPT_ADD_DISK_TO_ARRAY;
+typedef struct _HPT_DEVICE_IO
+{
+ DEVICEID id;
+ int cmd;
+ ULONG lba;
+ DWORD nSector;
+ UCHAR buffer[0];
+} HPT_DEVICE_IO, *PHPT_DEVICE_IO;
+
int check_VDevice_valid(PVDevice);
int hpt_default_ioctl(_VBUS_ARG DWORD, PVOID, DWORD, PVOID, DWORD, PDWORD);
diff --git a/sys/dev/hptmv/raid5n.h b/sys/dev/hptmv/raid5n.h
index 135177a..52dd95b 100644
--- a/sys/dev/hptmv/raid5n.h
+++ b/sys/dev/hptmv/raid5n.h
@@ -61,10 +61,10 @@ void HPTLIBAPI DoXor2(ULONG *p0, ULONG *p2, UINT nBytes);
#define xor_init(arg) 0
#define xor_add_item(handle, dest, src, nsrc, bytes) \
do {\
- if (((void**)src)[0]==dest)\
- DoXor2((PULONG)(dest), ((PULONG *)src)[1], bytes);\
+ if (((void**)(src))[0]==dest)\
+ DoXor2((PULONG)(dest), ((PULONG *)(src))[1], bytes);\
else\
- DoXor1((PULONG)(dest), ((PULONG *)src)[0], ((PULONG *)src)[1], bytes);\
+ DoXor1((PULONG)(dest), ((PULONG *)(src))[0], ((PULONG *)(src))[1], bytes);\
} while(0)
#define xor_exec(handle, done, tag) done(_VBUS_P tag, 0)
#define xor_poll()
diff --git a/sys/dev/hptmv/readme.txt b/sys/dev/hptmv/readme.txt
index 6d21e98..6143076 100644
--- a/sys/dev/hptmv/readme.txt
+++ b/sys/dev/hptmv/readme.txt
@@ -1,9 +1,22 @@
-RocketRAID 182x Driver for FreeBSD
-Copyright (C) 2004-2005 HighPoint Technologies, Inc. All rights reserved.
+RocketRAID 18xx Driver for FreeBSD
+Copyright (C) 2007-2008 HighPoint Technologies, Inc. All rights reserved.
$FreeBSD$
#############################################################################
Revision History:
+ v1.16 2008-2-29
+ Fix 7.0 compile error.
+
+ v1.15 2007-8-6
+ Override kernel driver(built-in) to support over 2T RAID array.
+
+ v1.14 2006-3-21
+ Fix 48-bit LBA compatibility for Seagate drives.
+ Fix 16 bytes CDB support.
+
+ v1.13 2006-2-13
+ Fix fail LED/beeper control.
+ Add 16 bytes CDB support.
v1.12 2005-6-10
Fix over 4G memory support on amd64.
@@ -21,7 +34,7 @@ Revision History:
1. Overview
---------------------
This package contains FreeBSD driver source code for HighPoint RocketRAID
- 182x SATA controller.
+ 18xx SATA controller.
NO WARRANTY
@@ -41,7 +54,7 @@ Revision History:
SUCH HARDWARE, OR DATA.
-2. Rebuild the kernel with RR182x support
+2. Rebuild the kernel with RR18xx support
--------------------------------------------
1) Install kernel source package and building tools.
@@ -49,7 +62,7 @@ Revision History:
2) Extract the driver files under the kernel source tree:
# cd /usr/src/sys/
- # tar xvzf /your/path/to/rr182x-opensource-v1.12-bsd.tgz
+ # tar xvzf /your/path/to/rr18xx-opensource-v1.12-bsd.tgz
3) Update the kernel configuration file to include the HighPoint source.
Assume the configure file is GENERIC, and new kernel configure file is
@@ -61,7 +74,7 @@ Revision History:
4) Edit MYKERNEL, and add the following line under "RAID controllers
interfaced to the SCSI subsystem":
- device hptmv #HighPoint RocketRAID 182x
+ device hptmv #HighPoint RocketRAID 18xx
5) For i386 system, edit /usr/src/sys/conf/files.i386 and append the lines
shown below:
@@ -91,13 +104,13 @@ Revision History:
dev/hptmv/entry.c optional hptmv
dev/hptmv/mv.c optional hptmv
- Note FreeBSD 5.3/5.4 i386 already have a built-in RR182x driver, you should
- replace the old configuration lines with the lines listed above.
+ Note FreeBSD 5.3/5.4/6.x/7.x i386 already have a built-in RR18xx driver,
+ you should replace the old configuration lines with the lines listed above.
6) Rebuild and install the kernel:
- a) for FreeBSD 5.x-i386:
+ a) for FreeBSD 5.x/6.x/7.x i386:
# cd /usr/src/sys/i386/conf/
# /usr/sbin/config MYKERNEL
@@ -106,7 +119,7 @@ Revision History:
# make
# make install
- b) for FreeBSD 5.x-amd64:
+ b) for FreeBSD 5.x/6.x/7.x amd64:
# cd /usr/src/sys/amd64/conf/
# /usr/sbin/config MYKERNEL
@@ -139,7 +152,7 @@ Revision History:
2) Extract the driver files under the kernel source tree:
# cd /usr/src/sys/
- # tar xvzf /your/path/to/rr182x-opensource-v1.12-bsd.tgz
+ # tar xvzf /your/path/to/rr18xx-opensource-v1.12-bsd.tgz
4) Build the driver module:
@@ -153,7 +166,7 @@ Revision History:
# cp hptmv.ko /modules/
- For FreeBSD 5.x:
+ For FreeBSD 5.x/6.x/7.x:
# cp hptmv.ko /boot/kernel/
@@ -179,7 +192,7 @@ Revision History:
/modules/hptmv.ko text=0xf571 data=0x2c8+0x254
ok boot
- For FreeBSD 5.x, you can select 6 on the boot menu to get a loader prompt.
+ For FreeBSD 5.x/6.x/7.x, you can select 6 on the boot menu to get a loader prompt.
7) You can add a below line into /boot/defaults/loader.conf to load the
driver automatically:
diff --git a/sys/dev/hptmv/vdevice.h b/sys/dev/hptmv/vdevice.h
index 8d06f10..e0bddc7 100644
--- a/sys/dev/hptmv/vdevice.h
+++ b/sys/dev/hptmv/vdevice.h
@@ -35,20 +35,20 @@
typedef struct _VDevice
{
- UCHAR VDeviceType;
- UCHAR vf_bootmark: 1; /* is boot device? */
- UCHAR vf_bootable: 1; /* has active partition */
- UCHAR vf_online: 1; /* is usable? */
- UCHAR vf_cache_disk: 1; /* Cache enabled */
+ UCHAR VDeviceType;
+ UCHAR vf_bootmark: 1; /* is boot device? */
+ UCHAR vf_bootable: 1; /* has active partition */
+ UCHAR vf_online: 1; /* is usable? */
+ UCHAR vf_cache_disk: 1; /* Cache enabled */
UCHAR vf_format_v2: 1; /* old array block */
UCHAR vf_freed: 1; /* memory free */
- UCHAR reserve1;
- UCHAR bSerialNumber; /* valid if pParent!=0 */
+ UCHAR reserve1;
+ UCHAR bSerialNumber; /* valid if pParent!=0 */
- PVDevice pParent; /* parent array */
+ PVDevice pParent; /* parent array */
PVBus pVBus; /* vbus this device located. Must not be NULL. */
- LBA_T VDeviceCapacity; /* number of blocks */
+ LBA_T VDeviceCapacity; /* number of blocks */
LBA_T LockedLba;
USHORT LockedSectors;
@@ -58,16 +58,16 @@ typedef struct _VDevice
void *QuiesceArg;
void (* HPTLIBAPI flush_callback)(_VBUS_ARG void *arg);
void *flush_callback_arg;
-
+
#if defined(_RAID5N_)
struct stripe **CacheEntry;
struct range_lock *range_lock;
#endif
- void (* HPTLIBAPI pfnSendCommand)(_VBUS_ARG PCommand pCmd); /* call this to send a command to a VDevice */
- void (* HPTLIBAPI pfnDeviceFailed)(_VBUS_ARG PVDevice pVDev); /* call this when a VDevice failed */
-
+ void (* HPTLIBAPI pfnSendCommand)(_VBUS_ARG PCommand pCmd); /* call this to send a command to a VDevice */
+ void (* HPTLIBAPI pfnDeviceFailed)(_VBUS_ARG PVDevice pVDev); /* call this when a VDevice failed */
+
union {
#ifdef SUPPORT_ARRAY
RaidArray array;
@@ -85,10 +85,10 @@ typedef struct _VDevice
/*
* bUserDeviceMode
*/
-#define MEMBER_NOT_SET_MODE 0x5F
+#define MEMBER_NOT_SET_MODE 0x5F
-/*
- * arrayType
+/*
+ * arrayType
*/
#define VD_SPARE 0
#define VD_REMOVABLE 1
@@ -120,10 +120,10 @@ void HPTLIBAPI fSingleDiskFailed(_VBUS_ARG PVDevice pVDev);
typedef struct _VBus {
/* pVDevice[] may be non-continuous */
- PVDevice pVDevice[MAX_VDEVICE_PER_VBUS];
+ PVDevice pVDevice[MAX_VDEVICE_PER_VBUS];
- UINT nInstances;
- PChipInstance pChipInstance[MAX_CHIP_IN_VBUS];
+ UINT nInstances;
+ PChipInstance pChipInstance[MAX_CHIP_IN_VBUS];
void * OsExt; /* for OS private use */
@@ -176,16 +176,20 @@ typedef struct _VBus {
for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) \
if ((pVDev=pVBus->pVDevice[i])==0) continue; else
-#define FOR_EACH_DEV_ON_ALL_VBUS(pVBus, pVDev, i) \
+
+#define FOR_EACH_VBUS(pVBus) \
for(pVBus = gVBus; pVBus < &gVBus[MAX_VBUS]; pVBus++) \
- for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) \
- if ((pVDev=pVBus->pVDevice[i])==0) continue; else
#define FOR_EACH_ARRAY_ON_ALL_VBUS(pVBus, pArray, i) \
for(pVBus = gVBus; pVBus < &gVBus[MAX_VBUS]; pVBus++) \
for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) \
if ((pArray=((PVDevice)&pVBus->_ArrayTables[i*ARRAY_VDEV_SIZE]))->u.array.dArStamp==0) continue; else
+#define FOR_EACH_DEV_ON_ALL_VBUS(pVBus, pVDev, i) \
+ FOR_EACH_VBUS(pVBus) \
+ for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) \
+ if ((pVDev=pVBus->pVDevice[i])==0) continue; else
+
/***************************************************************************
* Description: the functions called by IDE layer
***************************************************************************/
@@ -196,10 +200,10 @@ void HPTLIBAPI IdeRegisterDevice(PDevice pDev);
#endif
/***************************************************************************
- * Description: the functions OS must provided
+ * Description: the functions OS must provided
***************************************************************************/
-void OsSetDeviceTable(PDevice pDevice, PIDENTIFY_DATA pIdentify);
+void HPTLIBAPI OsSetDeviceTable(PDevice pDevice, PIDENTIFY_DATA pIdentify);
/*
* allocate and free data structure
@@ -240,12 +244,12 @@ void VBus_Config(PVBus pVBus, char *str);
#endif
#pragma pack(1)
-struct fdisk_partition_table
+struct fdisk_partition_table
{
UCHAR bootid; /* bootable? 0=no, 128=yes */
UCHAR beghead; /* beginning head number */
UCHAR begsect; /* beginning sector number */
- UCHAR begcyl; /* 10 bit nmbr, with high 2 bits put in begsect */
+ UCHAR begcyl; /* 10 bit nmbr, with high 2 bits put in begsect */
UCHAR systid; /* Operating System type indicator code */
UCHAR endhead; /* ending head number */
UCHAR endsect; /* ending sector number */
@@ -254,7 +258,7 @@ struct fdisk_partition_table
ULONG numsect; /* number of sectors in partition */
};
-typedef struct _Master_Boot_Record
+typedef struct _Master_Boot_Record
{
UCHAR bootinst[446]; /* space to hold actual boot code */
struct fdisk_partition_table parts[4];
@@ -278,5 +282,5 @@ typedef struct _TIME_RECORD {
#endif
#endif
-#pragma pack()
+#pragma pack()
#endif
diff --git a/sys/dev/ichwd/ichwd.c b/sys/dev/ichwd/ichwd.c
index 917a31a..71662a5 100644
--- a/sys/dev/ichwd/ichwd.c
+++ b/sys/dev/ichwd/ichwd.c
@@ -141,26 +141,55 @@ static devclass_t ichwd_devclass;
device_printf(dev, __VA_ARGS__);\
} while (0)
+/*
+ * Disable the watchdog timeout SMI handler.
+ *
+ * Apparently, some BIOSes install handlers that reset or disable the
+ * watchdog timer instead of resetting the system, so we disable the SMI
+ * (by clearing the SMI_TCO_EN bit of the SMI_EN register) to prevent this
+ * from happening.
+ */
static __inline void
-ichwd_intr_enable(struct ichwd_softc *sc)
+ichwd_smi_disable(struct ichwd_softc *sc)
{
ichwd_write_smi_4(sc, SMI_EN, ichwd_read_smi_4(sc, SMI_EN) & ~SMI_TCO_EN);
}
+/*
+ * Enable the watchdog timeout SMI handler. See above for details.
+ */
static __inline void
-ichwd_intr_disable(struct ichwd_softc *sc)
+ichwd_smi_enable(struct ichwd_softc *sc)
{
ichwd_write_smi_4(sc, SMI_EN, ichwd_read_smi_4(sc, SMI_EN) | SMI_TCO_EN);
}
+/*
+ * Reset the watchdog status bits.
+ */
static __inline void
ichwd_sts_reset(struct ichwd_softc *sc)
{
+ /*
+ * The watchdog status bits are set to 1 by the hardware to
+ * indicate various conditions. They can be cleared by software
+ * by writing a 1, not a 0.
+ */
ichwd_write_tco_2(sc, TCO1_STS, TCO_TIMEOUT);
+ /*
+ * XXX The datasheet says that TCO_SECOND_TO_STS must be cleared
+ * before TCO_BOOT_STS, not the other way around.
+ */
ichwd_write_tco_2(sc, TCO2_STS, TCO_BOOT_STS);
ichwd_write_tco_2(sc, TCO2_STS, TCO_SECOND_TO_STS);
}
+/*
+ * Enable the watchdog timer by clearing the TCO_TMR_HALT bit in the
+ * TCO1_CNT register. This is complicated by the need to preserve bit 9
+ * of that same register, and the requirement that all other bits must be
+ * written back as zero.
+ */
static __inline void
ichwd_tmr_enable(struct ichwd_softc *sc)
{
@@ -172,6 +201,9 @@ ichwd_tmr_enable(struct ichwd_softc *sc)
ichwd_verbose_printf(sc->device, "timer enabled\n");
}
+/*
+ * Disable the watchdog timer. See above for details.
+ */
static __inline void
ichwd_tmr_disable(struct ichwd_softc *sc)
{
@@ -183,6 +215,11 @@ ichwd_tmr_disable(struct ichwd_softc *sc)
ichwd_verbose_printf(sc->device, "timer disabled\n");
}
+/*
+ * Reload the watchdog timer: writing anything to any of the lower five
+ * bits of the TCO_RLD register reloads the timer from the last value
+ * written to TCO_TMR.
+ */
static __inline void
ichwd_tmr_reload(struct ichwd_softc *sc)
{
@@ -194,6 +231,10 @@ ichwd_tmr_reload(struct ichwd_softc *sc)
ichwd_verbose_printf(sc->device, "timer reloaded\n");
}
+/*
+ * Set the initial timeout value. Note that this must always be followed
+ * by a reload.
+ */
static __inline void
ichwd_tmr_set(struct ichwd_softc *sc, unsigned int timeout)
{
@@ -262,7 +303,8 @@ ichwd_clear_noreboot(struct ichwd_softc *sc)
}
/*
- * Watchdog event handler.
+ * Watchdog event handler - called by the framework to enable or disable
+ * the watchdog or change the initial timeout value.
*/
static void
ichwd_event(void *arg, unsigned int cmd, int *error)
@@ -426,6 +468,13 @@ ichwd_attach(device_t dev)
device_printf(dev, "%s (ICH%d or equivalent)\n",
device_get_desc(dev), sc->ich_version);
+ /*
+ * XXX we should check the status registers (specifically, the
+ * TCO_SECOND_TO_STS bit in the TCO2_STS register) to see if we
+ * just came back from a watchdog-induced reset, and let the user
+ * know.
+ */
+
/* reset the watchdog status registers */
ichwd_sts_reset(sc);
@@ -435,8 +484,8 @@ ichwd_attach(device_t dev)
/* register the watchdog event handler */
sc->ev_tag = EVENTHANDLER_REGISTER(watchdog_list, ichwd_event, sc, 0);
- /* enable watchdog timeout interrupts */
- ichwd_intr_enable(sc);
+ /* disable the SMI handler */
+ ichwd_smi_disable(sc);
return (0);
fail:
@@ -466,8 +515,8 @@ ichwd_detach(device_t dev)
if (sc->active)
ichwd_tmr_disable(sc);
- /* disable watchdog timeout interrupts */
- ichwd_intr_disable(sc);
+ /* enable the SMI handler */
+ ichwd_smi_enable(sc);
/* deregister event handler */
if (sc->ev_tag != NULL)
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c
index 976253c..a3bda2c 100644
--- a/sys/dev/if_ndis/if_ndis.c
+++ b/sys/dev/if_ndis/if_ndis.c
@@ -753,7 +753,8 @@ ndis_attach(dev)
ic->ic_ifp = ifp;
ic->ic_opmode = IEEE80211_M_STA;
ic->ic_phytype = IEEE80211_T_DS;
- ic->ic_caps = IEEE80211_C_STA | IEEE80211_C_IBSS;
+ ic->ic_caps = IEEE80211_C_8023ENCAP |
+ IEEE80211_C_STA | IEEE80211_C_IBSS;
setbit(ic->ic_modecaps, IEEE80211_MODE_AUTO);
len = 0;
r = ndis_get_info(sc, OID_802_11_NETWORK_TYPES_SUPPORTED,
@@ -937,8 +938,7 @@ got_crypto:
if (r == 0)
ic->ic_caps |= IEEE80211_C_TXPMGT;
- bcopy(eaddr, &ic->ic_myaddr, sizeof(eaddr));
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, eaddr);
ic->ic_raw_xmit = ndis_raw_xmit;
ic->ic_scan_start = ndis_scan_start;
ic->ic_scan_end = ndis_scan_end;
@@ -2408,7 +2408,7 @@ ndis_setstate_80211(sc)
/* Set the BSSID to our value so the driver doesn't associate */
len = IEEE80211_ADDR_LEN;
- bcopy(ic->ic_myaddr, bssid, len);
+ bcopy(IF_LLADDR(ifp), bssid, len);
DPRINTF(("Setting BSSID to %6D\n", (uint8_t *)&bssid, ":"));
rval = ndis_set_info(sc, OID_802_11_BSSID, &bssid, &len);
if (rval)
@@ -3250,8 +3250,10 @@ ndis_stop(sc)
NDIS_LOCK(sc);
for (i = 0; i < NDIS_EVENTS; i++) {
- if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL)
+ if (sc->ndis_evt[i].ne_sts && sc->ndis_evt[i].ne_buf != NULL) {
free(sc->ndis_evt[i].ne_buf, M_TEMP);
+ sc->ndis_evt[i].ne_buf = NULL;
+ }
sc->ndis_evt[i].ne_sts = 0;
sc->ndis_evt[i].ne_len = 0;
}
diff --git a/sys/dev/if_ndis/if_ndis_usb.c b/sys/dev/if_ndis/if_ndis_usb.c
index 7aeed9a..ec9741b 100644
--- a/sys/dev/if_ndis/if_ndis_usb.c
+++ b/sys/dev/if_ndis/if_ndis_usb.c
@@ -210,6 +210,10 @@ ndisusb_detach(device_t self)
ndis_pnpevent_nic(self, NDIS_PNP_EVENT_SURPRISE_REMOVED);
+ if (sc->ndisusb_status & NDISUSB_STATUS_SETUP_EP) {
+ usb2_transfer_unsetup(sc->ndisusb_dread_ep.ne_xfer, 1);
+ usb2_transfer_unsetup(sc->ndisusb_dwrite_ep.ne_xfer, 1);
+ }
for (i = 0; i < NDISUSB_ENDPT_MAX; i++) {
ne = &sc->ndisusb_ep[i];
usb2_transfer_unsetup(ne->ne_xfer, 1);
diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h
index c86b267..6db48a6 100644
--- a/sys/dev/if_ndis/if_ndisvar.h
+++ b/sys/dev/if_ndis/if_ndisvar.h
@@ -146,6 +146,7 @@ struct ndisusb_task {
unsigned nt_type;
#define NDISUSB_TASK_TSTART 0
#define NDISUSB_TASK_IRPCANCEL 1
+#define NDISUSB_TASK_VENDOR 2
void *nt_ctx;
list_entry nt_tasklist;
};
@@ -229,6 +230,8 @@ struct ndis_softc {
struct usb2_device *ndisusb_dev;
struct mtx ndisusb_mtx;
+ struct ndisusb_ep ndisusb_dread_ep;
+ struct ndisusb_ep ndisusb_dwrite_ep;
#define NDISUSB_GET_ENDPT(addr) \
((UE_GET_DIR(addr) >> 7) | (UE_GET_ADDR(addr) << 1))
#define NDISUSB_ENDPT_MAX ((UE_ADDR + 1) * 2)
@@ -241,6 +244,7 @@ struct ndis_softc {
kspin_lock ndisusb_tasklock;
int ndisusb_status;
#define NDISUSB_STATUS_DETACH 0x1
+#define NDISUSB_STATUS_SETUP_EP 0x2
};
#define NDIS_LOCK(_sc) mtx_lock(&(_sc)->ndis_mtx)
diff --git a/sys/dev/ipmi/ipmi_linux.c b/sys/dev/ipmi/ipmi_linux.c
new file mode 100644
index 0000000..fcf2bd5
--- /dev/null
+++ b/sys/dev/ipmi/ipmi_linux.c
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 2009 IronPort Systems Inc. <ambrisko@ironport.com>
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Linux ioctl handler for the ipmi device driver
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/file.h>
+#include <sys/proc.h>
+#ifdef __amd64__
+#include <machine/../linux32/linux.h>
+#include <machine/../linux32/linux32_proto.h>
+#else
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#endif
+#include <compat/linux/linux_ioctl.h>
+#include <sys/ioccom.h>
+#include <sys/ipmi.h>
+
+/* There are multiple ioctl number ranges that need to be handled */
+#define IPMI_LINUX_IOCTL_MIN 0x690b
+#define IPMI_LINUX_IOCTL_MAX 0x6915
+
+/* Linux versions of ioctl's */
+#define L_IPMICTL_RECEIVE_MSG_TRUNC _IOWR(IPMI_IOC_MAGIC, 11, struct ipmi_recv)
+#define L_IPMICTL_RECEIVE_MSG _IOWR(IPMI_IOC_MAGIC, 12, struct ipmi_recv)
+#define L_IPMICTL_SEND_COMMAND _IOW(IPMI_IOC_MAGIC, 13, struct ipmi_req)
+#define L_IPMICTL_REGISTER_FOR_CMD _IOW(IPMI_IOC_MAGIC, 14, struct ipmi_cmdspec)
+#define L_IPMICTL_UNREGISTER_FOR_CMD _IOW(IPMI_IOC_MAGIC, 15, struct ipmi_cmdspec)
+#define L_IPMICTL_SET_GETS_EVENTS_CMD _IOW(IPMI_IOC_MAGIC, 16, int)
+#define L_IPMICTL_SET_MY_ADDRESS_CMD _IOW(IPMI_IOC_MAGIC, 17, unsigned int)
+#define L_IPMICTL_GET_MY_ADDRESS_CMD _IOW(IPMI_IOC_MAGIC, 18, unsigned int)
+#define L_IPMICTL_SET_MY_LUN_CMD _IOW(IPMI_IOC_MAGIC, 19, unsigned int)
+#define L_IPMICTL_GET_MY_LUN_CMD _IOW(IPMI_IOC_MAGIC, 20, unsigned int)
+
+static linux_ioctl_function_t ipmi_linux_ioctl;
+static struct linux_ioctl_handler ipmi_linux_handler = {ipmi_linux_ioctl,
+ IPMI_LINUX_IOCTL_MIN,
+ IPMI_LINUX_IOCTL_MAX};
+
+SYSINIT (ipmi_linux_register, SI_SUB_KLD, SI_ORDER_MIDDLE,
+ linux_ioctl_register_handler, &ipmi_linux_handler);
+SYSUNINIT(ipmi_linux_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE,
+ linux_ioctl_unregister_handler, &ipmi_linux_handler);
+
+static int
+ipmi_linux_modevent(module_t mod, int type, void *data)
+{
+ /* Do we care about any specific load/unload actions? */
+ return (0);
+}
+
+DEV_MODULE(ipmi_linux, ipmi_linux_modevent, NULL);
+MODULE_DEPEND(ipmi_linux, linux, 1, 1, 1);
+
+static int
+ipmi_linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ u_long cmd;
+ int error;
+
+ if ((error = fget(td, args->fd, &fp)) != 0)
+ return (error);
+ cmd = args->cmd;
+
+ switch(cmd) {
+ case L_IPMICTL_GET_MY_ADDRESS_CMD:
+ cmd = IPMICTL_GET_MY_ADDRESS_CMD;
+ break;
+ case L_IPMICTL_GET_MY_LUN_CMD:
+ cmd = IPMICTL_GET_MY_LUN_CMD;
+ break;
+ }
+ /*
+ * Pass the ioctl off to our standard handler.
+ */
+ error = (fo_ioctl(fp, cmd, (caddr_t)args->arg, td->td_ucred, td));
+ fdrop(fp, td);
+ return (error);
+}
diff --git a/sys/dev/ipw/if_ipw.c b/sys/dev/ipw/if_ipw.c
index b20d3f6..b9c5c75 100644
--- a/sys/dev/ipw/if_ipw.c
+++ b/sys/dev/ipw/if_ipw.c
@@ -231,6 +231,7 @@ ipw_attach(device_t dev)
struct ieee80211_channel *c;
uint16_t val;
int error, i;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
@@ -315,14 +316,14 @@ ipw_attach(device_t dev)
/* read MAC address from EEPROM */
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 0);
- ic->ic_myaddr[0] = val >> 8;
- ic->ic_myaddr[1] = val & 0xff;
+ macaddr[0] = val >> 8;
+ macaddr[1] = val & 0xff;
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 1);
- ic->ic_myaddr[2] = val >> 8;
- ic->ic_myaddr[3] = val & 0xff;
+ macaddr[2] = val >> 8;
+ macaddr[3] = val & 0xff;
val = ipw_read_prom_word(sc, IPW_EEPROM_MAC + 2);
- ic->ic_myaddr[4] = val >> 8;
- ic->ic_myaddr[5] = val & 0xff;
+ macaddr[4] = val >> 8;
+ macaddr[5] = val & 0xff;
/* set supported .11b channels (read from EEPROM) */
if ((val = ipw_read_prom_word(sc, IPW_EEPROM_CHANNEL_LIST)) == 0)
@@ -341,7 +342,7 @@ ipw_attach(device_t dev)
if (!(ipw_read_prom_word(sc, IPW_EEPROM_RADIO) & 8))
sc->flags |= IPW_FLAG_HAS_RADIO_SWITCH;
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, macaddr);
ic->ic_scan_start = ipw_scan_start;
ic->ic_scan_end = ipw_scan_end;
ic->ic_set_channel = ipw_set_channel;
@@ -1794,11 +1795,6 @@ ipw_start_locked(struct ifnet *ifp)
break;
}
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- m = ieee80211_encap(ni, m);
- if (m == NULL) {
- ieee80211_free_node(ni);
- continue;
- }
if (ipw_tx_start(ifp, m, ni) != 0) {
ieee80211_free_node(ni);
ifp->if_oerrors++;
diff --git a/sys/dev/iwi/if_iwi.c b/sys/dev/iwi/if_iwi.c
index 81e0220..83ab3e5 100644
--- a/sys/dev/iwi/if_iwi.c
+++ b/sys/dev/iwi/if_iwi.c
@@ -280,6 +280,7 @@ iwi_attach(device_t dev)
uint16_t val;
int i, error;
uint8_t bands;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
@@ -403,14 +404,14 @@ iwi_attach(device_t dev)
/* read MAC address from EEPROM */
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 0);
- ic->ic_myaddr[0] = val & 0xff;
- ic->ic_myaddr[1] = val >> 8;
+ macaddr[0] = val & 0xff;
+ macaddr[1] = val >> 8;
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 1);
- ic->ic_myaddr[2] = val & 0xff;
- ic->ic_myaddr[3] = val >> 8;
+ macaddr[2] = val & 0xff;
+ macaddr[3] = val >> 8;
val = iwi_read_prom_word(sc, IWI_EEPROM_MAC + 2);
- ic->ic_myaddr[4] = val & 0xff;
- ic->ic_myaddr[5] = val >> 8;
+ macaddr[4] = val & 0xff;
+ macaddr[5] = val >> 8;
bands = 0;
setbit(&bands, IEEE80211_MODE_11B);
@@ -419,7 +420,7 @@ iwi_attach(device_t dev)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, macaddr);
/* override default methods */
ic->ic_node_alloc = iwi_node_alloc;
sc->sc_node_free = ic->ic_node_free;
@@ -1981,13 +1982,6 @@ iwi_start_locked(struct ifnet *ifp)
BPF_MTAP(ifp, m);
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- m = ieee80211_encap(ni, m);
- if (m == NULL) {
- ieee80211_free_node(ni);
- ifp->if_oerrors++;
- continue;
- }
-
if (iwi_tx_start(ifp, m, ni, ac) != 0) {
ieee80211_free_node(ni);
ifp->if_oerrors++;
@@ -2568,9 +2562,8 @@ iwi_config(struct iwi_softc *sc)
IWI_LOCK_ASSERT(sc);
- IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
- DPRINTF(("Setting MAC address to %6D\n", ic->ic_myaddr, ":"));
- error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, ic->ic_myaddr,
+ DPRINTF(("Setting MAC address to %6D\n", IF_LLADDR(ifp), ":"));
+ error = iwi_cmd(sc, IWI_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp),
IEEE80211_ADDR_LEN);
if (error != 0)
return error;
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index 21d17f1..2928c0f 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -132,7 +132,8 @@ void iwn_cmd_intr(struct iwn_softc *, struct iwn_rx_desc *);
static void iwn_bmiss(void *, int);
void iwn_notif_intr(struct iwn_softc *);
void iwn_intr(void *);
-void iwn_read_eeprom(struct iwn_softc *);
+void iwn_read_eeprom(struct iwn_softc *,
+ uint8_t macaddr[IEEE80211_ADDR_LEN]);
static void iwn_read_eeprom_channels(struct iwn_softc *);
void iwn_print_power_group(struct iwn_softc *, int);
uint8_t iwn_plcp_signal(int);
@@ -254,6 +255,7 @@ iwn_attach(device_t dev)
struct ieee80211com *ic;
struct ifnet *ifp;
int i, error, result;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
@@ -410,7 +412,7 @@ iwn_attach(device_t dev)
;
#endif
/* read supported channels and MAC address from EEPROM */
- iwn_read_eeprom(sc);
+ iwn_read_eeprom(sc, macaddr);
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_softc = sc;
@@ -422,7 +424,7 @@ iwn_attach(device_t dev)
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
IFQ_SET_READY(&ifp->if_snd);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, macaddr);
ic->ic_vap_create = iwn_vap_create;
ic->ic_vap_delete = iwn_vap_delete;
ic->ic_raw_xmit = iwn_raw_xmit;
@@ -2120,12 +2122,6 @@ iwn_start_locked(struct ifnet *ifp)
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
pri = M_WME_GETAC(m);
txq = &sc->txq[pri];
- m = ieee80211_encap(ni, m);
- if (m == NULL) {
- ifp->if_oerrors++;
- ieee80211_free_node(ni);
- continue;
- }
if (txq->queued >= IWN_TX_RING_COUNT - 8) {
/* XXX not right */
/* ring is nearly full, stop flow */
@@ -2134,7 +2130,6 @@ iwn_start_locked(struct ifnet *ifp)
if (iwn_tx_data(sc, m, ni, txq) != 0) {
ifp->if_oerrors++;
ieee80211_free_node(ni);
- IWN_UNLOCK(sc);
break;
}
}
@@ -2410,10 +2405,8 @@ iwn_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
void
-iwn_read_eeprom(struct iwn_softc *sc)
+iwn_read_eeprom(struct iwn_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
char domain[4];
uint16_t val;
int i, error;
@@ -2428,8 +2421,8 @@ iwn_read_eeprom(struct iwn_softc *sc)
device_printf(sc->sc_dev,"Reg Domain: %.4s", domain);
/* read and print MAC address */
- iwn_read_prom_data(sc, IWN_EEPROM_MAC, ic->ic_myaddr, 6);
- printf(", address %s\n", ether_sprintf(ic->ic_myaddr));
+ iwn_read_prom_data(sc, IWN_EEPROM_MAC, macaddr, 6);
+ printf(", address %6D\n", macaddr, ":");
/* read the list of authorized channels */
iwn_read_eeprom_channels(sc);
@@ -3755,7 +3748,7 @@ iwn_scan(struct iwn_softc *sc)
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
- IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
+ IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(ifp));
IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr);
*(u_int16_t *)&wh->i_dur[0] = 0; /* filled by h/w */
*(u_int16_t *)&wh->i_seq[0] = 0; /* filled by h/w */
@@ -3893,8 +3886,8 @@ iwn_config(struct iwn_softc *sc)
/* configure adapter */
memset(&sc->config, 0, sizeof (struct iwn_config));
- IEEE80211_ADDR_COPY(sc->config.myaddr, ic->ic_myaddr);
- IEEE80211_ADDR_COPY(sc->config.wlap, ic->ic_myaddr);
+ IEEE80211_ADDR_COPY(sc->config.myaddr, IF_LLADDR(ifp));
+ IEEE80211_ADDR_COPY(sc->config.wlap, IF_LLADDR(ifp));
/* set default channel */
sc->config.chan = htole16(ieee80211_chan2ieee(ic, ic->ic_curchan));
sc->config.flags = htole32(IWN_CONFIG_TSF);
diff --git a/sys/dev/ixgbe/LICENSE b/sys/dev/ixgbe/LICENSE
index b6fd3b7..39264e0 100644
--- a/sys/dev/ixgbe/LICENSE
+++ b/sys/dev/ixgbe/LICENSE
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/sys/dev/ixgbe/README b/sys/dev/ixgbe/README
index 40bbe5f..0b27deb 100644
--- a/sys/dev/ixgbe/README
+++ b/sys/dev/ixgbe/README
@@ -1,6 +1,8 @@
FreeBSD Driver for 10 Gigabit PCI Express Server Adapters
=============================================
-$FreeBSD$
+/*$FreeBSD$*/
+
+May 14, 2008
Contents
@@ -258,7 +260,7 @@ For general information and support, go to the Intel support website at:
If an issue is identified with the released source code on the supported
kernel with a supported adapter, email the specific information related to
-the issue to freebsdnic@mailbox.intel.com.
+the issue to freebsd@intel.com.
diff --git a/sys/dev/ixgbe/ixgbe.c b/sys/dev/ixgbe/ixgbe.c
index 3b71cb6..e2827f4 100644
--- a/sys/dev/ixgbe/ixgbe.c
+++ b/sys/dev/ixgbe/ixgbe.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -46,7 +46,7 @@ int ixgbe_display_debug_stats = 0;
/*********************************************************************
* Driver version
*********************************************************************/
-char ixgbe_driver_version[] = "1.6.2";
+char ixgbe_driver_version[] = "1.7.4";
/*********************************************************************
* PCI Device ID Table
@@ -71,6 +71,8 @@ static ixgbe_vendor_info_t ixgbe_vendor_info_array[] =
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598AT, 0, 0, 0},
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM, 0, 0, 0},
{IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82598EB_SFP_LOM, 0, 0, 0},
+ {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_KX4, 0, 0, 0},
+ {IXGBE_INTEL_VENDOR_ID, IXGBE_DEV_ID_82599_SFP, 0, 0, 0},
/* required last entry */
{0, 0, 0, 0, 0}
};
@@ -104,7 +106,9 @@ static int ixgbe_allocate_pci_resources(struct adapter *);
static int ixgbe_allocate_msix(struct adapter *);
static int ixgbe_allocate_legacy(struct adapter *);
static int ixgbe_allocate_queues(struct adapter *);
+#if __FreeBSD_version >= 602105
static int ixgbe_setup_msix(struct adapter *);
+#endif
static void ixgbe_free_pci_resources(struct adapter *);
static void ixgbe_local_timer(void *);
static int ixgbe_hardware_init(struct adapter *);
@@ -124,6 +128,7 @@ static void ixgbe_initialize_receive_units(struct adapter *);
static void ixgbe_free_receive_structures(struct adapter *);
static void ixgbe_free_receive_buffers(struct rx_ring *);
+static void ixgbe_init_moderation(struct adapter *);
static void ixgbe_enable_intr(struct adapter *);
static void ixgbe_disable_intr(struct adapter *);
static void ixgbe_update_stats_counters(struct adapter *);
@@ -146,7 +151,7 @@ static int ixgbe_dma_malloc(struct adapter *, bus_size_t,
static void ixgbe_dma_free(struct adapter *, struct ixgbe_dma_alloc *);
static void ixgbe_add_rx_process_limit(struct adapter *, const char *,
const char *, int *, int);
-static boolean_t ixgbe_tx_ctx_setup(struct tx_ring *, struct mbuf *);
+static int ixgbe_tx_ctx_setup(struct tx_ring *, struct mbuf *);
static boolean_t ixgbe_tso_setup(struct tx_ring *, struct mbuf *, u32 *);
static void ixgbe_set_ivar(struct adapter *, u16, u8, s8);
static void ixgbe_configure_ivars(struct adapter *);
@@ -157,6 +162,12 @@ static void ixgbe_register_vlan(void *, struct ifnet *, u16);
static void ixgbe_unregister_vlan(void *, struct ifnet *, u16);
#endif
+#ifdef IXGBE_TIMESYNC
+/* Precision Time sync support */
+static int ixgbe_tsync_init(struct adapter *);
+static void ixgbe_tsync_disable(struct adapter *);
+#endif
+
static void ixgbe_update_aim(struct rx_ring *);
/* Support for pluggable optic modules */
@@ -165,14 +176,19 @@ static bool ixgbe_sfp_probe(struct adapter *);
/* Legacy (single vector interrupt handler */
static void ixgbe_legacy_irq(void *);
+#if __FreeBSD_version >= 602105
/* The MSI/X Interrupt handlers */
static void ixgbe_msix_tx(void *);
static void ixgbe_msix_rx(void *);
static void ixgbe_msix_link(void *);
+#endif
-/* Legacy interrupts use deferred handlers */
-static void ixgbe_handle_tx(void *context, int pending);
-static void ixgbe_handle_rx(void *context, int pending);
+/* Deferred interrupt tasklets */
+static void ixgbe_handle_tx(void *, int);
+static void ixgbe_handle_rx(void *, int);
+static void ixgbe_handle_link(void *, int);
+static void ixgbe_handle_msf(void *, int);
+static void ixgbe_handle_mod(void *, int);
/*********************************************************************
@@ -213,8 +229,8 @@ static int ixgbe_enable_aim = TRUE;
TUNABLE_INT("hw.ixgbe.enable_aim", &ixgbe_enable_aim);
static int ixgbe_low_latency = IXGBE_LOW_LATENCY;
TUNABLE_INT("hw.ixgbe.low_latency", &ixgbe_low_latency);
-static int ixgbe_ave_latency = IXGBE_LOW_LATENCY;
-TUNABLE_INT("hw.ixgbe.ave_latency", &ixgbe_low_latency);
+static int ixgbe_ave_latency = IXGBE_AVE_LATENCY;
+TUNABLE_INT("hw.ixgbe.ave_latency", &ixgbe_ave_latency);
static int ixgbe_bulk_latency = IXGBE_BULK_LATENCY;
TUNABLE_INT("hw.ixgbe.bulk_latency", &ixgbe_bulk_latency);
@@ -222,8 +238,8 @@ TUNABLE_INT("hw.ixgbe.bulk_latency", &ixgbe_bulk_latency);
static int ixgbe_rx_process_limit = 100;
TUNABLE_INT("hw.ixgbe.rx_process_limit", &ixgbe_rx_process_limit);
-/* Flow control setting, default to full */
-static int ixgbe_flow_control = ixgbe_fc_none;
+/* Flow control setting, default to off */
+static int ixgbe_flow_control = ixgbe_fc_full;
TUNABLE_INT("hw.ixgbe.flow_control", &ixgbe_flow_control);
/*
@@ -239,11 +255,16 @@ TUNABLE_INT("hw.ixgbe.enable_lro", &ixgbe_enable_lro);
* MSIX should be the default for best performance,
* but this allows it to be forced off for testing.
*/
+#if __FreeBSD_version >= 602105
static int ixgbe_enable_msix = 1;
+#else
+static int ixgbe_enable_msix = 0;
+#endif
TUNABLE_INT("hw.ixgbe.enable_msix", &ixgbe_enable_msix);
/*
* Enable RX Header Split
+ * WARNING: disable this if bridging or forwarding!!
*/
static int ixgbe_rx_hdr_split = 1;
TUNABLE_INT("hw.ixgbe.rx_hdr_split", &ixgbe_rx_hdr_split);
@@ -268,6 +289,13 @@ TUNABLE_INT("hw.ixgbe.rxd", &ixgbe_rxd);
/* Total number of Interfaces - need for config sanity check */
static int ixgbe_total_ports;
+/*
+** The number of scatter-gather segments
+** differs for 82598 and 82599, default to
+** the former.
+*/
+static int ixgbe_num_segs = IXGBE_82598_SCATTER;
+
/*********************************************************************
* Device identification routine
*
@@ -312,6 +340,7 @@ ixgbe_probe(device_t dev)
ixgbe_strings[ent->index],
ixgbe_driver_version);
device_set_desc_copy(dev, adapter_name);
+ ++ixgbe_total_ports;
return (0);
}
ent++;
@@ -333,6 +362,7 @@ static int
ixgbe_attach(device_t dev)
{
struct adapter *adapter;
+ struct ixgbe_hw *hw;
int error = 0;
u16 pci_device_id;
u32 ctrl_ext;
@@ -342,37 +372,34 @@ ixgbe_attach(device_t dev)
/* Allocate, clear, and link in our adapter structure */
adapter = device_get_softc(dev);
adapter->dev = adapter->osdep.dev = dev;
+ hw = &adapter->hw;
/* Core Lock Init*/
IXGBE_CORE_LOCK_INIT(adapter, device_get_nameunit(dev));
- /* Keep track of number of ports and optics */
+ /* Keep track of optics */
pci_device_id = pci_get_device(dev);
switch (pci_device_id) {
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT :
+ case IXGBE_DEV_ID_82598EB_CX4 :
adapter->optics = IFM_10G_CX4;
- ixgbe_total_ports += 2;
break;
case IXGBE_DEV_ID_82598AF_DUAL_PORT :
- adapter->optics = IFM_10G_SR;
- ixgbe_total_ports += 2;
- break;
+ case IXGBE_DEV_ID_82598_DA_DUAL_PORT :
case IXGBE_DEV_ID_82598AF_SINGLE_PORT :
+ case IXGBE_DEV_ID_82598AT :
adapter->optics = IFM_10G_SR;
- ixgbe_total_ports += 1;
break;
case IXGBE_DEV_ID_82598EB_XF_LR :
adapter->optics = IFM_10G_LR;
- ixgbe_total_ports += 1;
break;
- case IXGBE_DEV_ID_82598EB_CX4 :
- adapter->optics = IFM_10G_CX4;
- ixgbe_total_ports += 1;
+ case IXGBE_DEV_ID_82599_SFP :
+ adapter->optics = IFM_10G_SR;
+ ixgbe_num_segs = IXGBE_82599_SCATTER;
break;
- case IXGBE_DEV_ID_82598AT :
- ixgbe_total_ports += 1;
- case IXGBE_DEV_ID_82598_DA_DUAL_PORT :
- ixgbe_total_ports += 2;
+ case IXGBE_DEV_ID_82599_KX4 :
+ adapter->optics = IFM_10G_CX4;
+ ixgbe_num_segs = IXGBE_82599_SCATTER;
default:
break;
}
@@ -474,7 +501,7 @@ ixgbe_attach(device_t dev)
}
/* Initialize the shared code */
- error = ixgbe_init_shared_code(&adapter->hw);
+ error = ixgbe_init_shared_code(hw);
if (error == IXGBE_ERR_SFP_NOT_PRESENT) {
/*
** No optics in this port, set up
@@ -525,11 +552,11 @@ ixgbe_attach(device_t dev)
adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
ixgbe_unregister_vlan, 0, EVENTHANDLER_PRI_FIRST);
#endif
-
+
/* let hardware know driver is loaded */
- ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
+ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
ctrl_ext |= IXGBE_CTRL_EXT_DRV_LOAD;
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_CTRL_EXT, ctrl_ext);
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
INIT_DEBUGOUT("ixgbe_attach: end");
return (0);
@@ -590,6 +617,14 @@ ixgbe_detach(device_t dev)
}
}
+ /* Drain the Link queue */
+ if (adapter->tq) {
+ taskqueue_drain(adapter->tq, &adapter->link_task);
+ taskqueue_drain(adapter->tq, &adapter->mod_task);
+ taskqueue_drain(adapter->tq, &adapter->msf_task);
+ taskqueue_free(adapter->tq);
+ }
+
/* let hardware know driver is unloading */
ctrl_ext = IXGBE_READ_REG(&adapter->hw, IXGBE_CTRL_EXT);
ctrl_ext &= ~IXGBE_CTRL_EXT_DRV_LOAD;
@@ -662,6 +697,19 @@ ixgbe_start_locked(struct tx_ring *txr, struct ifnet * ifp)
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
if (m_head == NULL)
break;
+ /*
+ * Force a cleanup if number of TX descriptors
+ * available is below the threshold. If it fails
+ * to get above, then abort transmit.
+ */
+ if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD) {
+ ixgbe_txeof(txr);
+ /* Make sure things have improved */
+ if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) {
+ txr->no_tx_desc_avail++;
+ break;
+ }
+ }
if (ixgbe_xmit(txr, &m_head)) {
if (m_head == NULL)
@@ -701,7 +749,8 @@ ixgbe_start(struct ifnet *ifp)
txr = &adapter->tx_rings[queue];
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- IXGBE_TX_LOCK(txr);
+ if (IXGBE_TX_TRYLOCK(txr) == 0)
+ return;
ixgbe_start_locked(txr, ifp);
IXGBE_TX_UNLOCK(txr);
}
@@ -803,6 +852,67 @@ ixgbe_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
#endif
break;
}
+#ifdef IXGBE_TIMESYNC
+ /*
+ ** IOCTL support for Precision Time (IEEE 1588) Support
+ */
+ case IXGBE_TIMESYNC_READTS:
+ {
+ u32 rx_ctl, tx_ctl;
+ struct ixgbe_tsync_read *tdata;
+
+ tdata = (struct ixgbe_tsync_read *) ifr->ifr_data;
+
+ if (tdata->read_current_time) {
+ getnanotime(&tdata->system_time);
+ tdata->network_time = IXGBE_READ_REG(&adapter->hw,
+ IXGBE_SYSTIML);
+ tdata->network_time |=
+ (u64)IXGBE_READ_REG(&adapter->hw,
+ IXGBE_SYSTIMH ) << 32;
+ }
+
+ rx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCRXCTL);
+ tx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCTXCTL);
+
+ if (rx_ctl & 0x1) {
+ u32 tmp;
+ unsigned char *tmp_cp;
+
+ tdata->rx_valid = 1;
+ tdata->rx_stamp = IXGBE_READ_REG(&adapter->hw,
+ IXGBE_RXSTMPL);
+ tdata->rx_stamp |= (u64)IXGBE_READ_REG(&adapter->hw,
+ IXGBE_RXSTMPH) << 32;
+
+ tmp = IXGBE_READ_REG(&adapter->hw, IXGBE_RXSATRL);
+ tmp_cp = (unsigned char *) &tmp;
+ tdata->srcid[0] = tmp_cp[0];
+ tdata->srcid[1] = tmp_cp[1];
+ tdata->srcid[2] = tmp_cp[2];
+ tdata->srcid[3] = tmp_cp[3];
+ tmp = IXGBE_READ_REG(&adapter->hw, IXGBE_RXSATRH);
+ tmp_cp = (unsigned char *) &tmp;
+ tdata->srcid[4] = tmp_cp[0];
+ tdata->srcid[5] = tmp_cp[1];
+ tdata->seqid = tmp >> 16;
+ tdata->seqid = htons(tdata->seqid);
+ } else
+ tdata->rx_valid = 0;
+
+ if (tx_ctl & 0x1) {
+ tdata->tx_valid = 1;
+ tdata->tx_stamp = IXGBE_READ_REG(&adapter->hw,
+ IXGBE_TXSTMPL);
+ tdata->tx_stamp |= (u64) IXGBE_READ_REG(&adapter->hw,
+ IXGBE_TXSTMPH) << 32;
+ } else
+ tdata->tx_valid = 0;
+
+ return (0);
+ }
+#endif /* IXGBE_TIMESYNC */
+
default:
IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)\n", (int)command);
error = ether_ioctl(ifp, command, data);
@@ -905,13 +1015,12 @@ ixgbe_watchdog(struct adapter *adapter)
static void
ixgbe_init_locked(struct adapter *adapter)
{
- struct rx_ring *rxr = adapter->rx_rings;
- struct tx_ring *txr = adapter->tx_rings;
struct ifnet *ifp = adapter->ifp;
device_t dev = adapter->dev;
struct ixgbe_hw *hw;
u32 k, txdctl, mhadd, gpie;
u32 rxdctl, rxctrl;
+ int err;
INIT_DEBUGOUT("ixgbe_init: begin");
@@ -951,13 +1060,6 @@ ixgbe_init_locked(struct adapter *adapter)
ixgbe_initialize_transmit_units(adapter);
- /* TX irq moderation rate is fixed */
- for (int i = 0; i < adapter->num_tx_queues; i++, txr++) {
- IXGBE_WRITE_REG(&adapter->hw,
- IXGBE_EITR(txr->msix), ixgbe_ave_latency);
- txr->watchdog_timer = FALSE;
- }
-
/* Setup Multicast table */
ixgbe_set_multi(adapter);
@@ -980,23 +1082,21 @@ ixgbe_init_locked(struct adapter *adapter)
/* Configure RX settings */
ixgbe_initialize_receive_units(adapter);
- /* RX moderation will be adapted over time, set default */
- for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) {
- IXGBE_WRITE_REG(&adapter->hw,
- IXGBE_EITR(rxr->msix), ixgbe_low_latency);
- }
-
- /* Set Link moderation */
- IXGBE_WRITE_REG(&adapter->hw,
- IXGBE_EITR(adapter->linkvec), IXGBE_LINK_ITR);
+ /* Configure Interrupt Moderation */
+ ixgbe_init_moderation(adapter);
gpie = IXGBE_READ_REG(&adapter->hw, IXGBE_GPIE);
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+ gpie |= IXGBE_SDP1_GPIEN;
+ gpie |= IXGBE_SDP2_GPIEN;
+ }
+
/* Enable Fan Failure Interrupt */
- if (adapter->hw.phy.media_type == ixgbe_media_type_copper)
+ if (hw->device_id == IXGBE_DEV_ID_82598AT)
gpie |= IXGBE_SDP1_GPIEN;
- if (adapter->msix) {
+ if (adapter->msix > 2) {
/* Enable Enhanced MSIX mode */
gpie |= IXGBE_GPIE_MSIX_MODE;
gpie |= IXGBE_GPIE_EIAME | IXGBE_GPIE_PBA_SUPPORT |
@@ -1058,9 +1158,40 @@ ixgbe_init_locked(struct adapter *adapter)
/* Set up MSI/X routing */
if (ixgbe_enable_msix)
ixgbe_configure_ivars(adapter);
+ else { /* Simple settings for Legacy/MSI */
+ ixgbe_set_ivar(adapter, 0, 0, 0);
+ ixgbe_set_ivar(adapter, 0, 0, 1);
+ }
ixgbe_enable_intr(adapter);
+ /*
+ ** Check on any SFP devices that
+ ** need to be kick-started
+ */
+ err = hw->phy.ops.identify(hw);
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ device_printf(dev,
+ "Unsupported SFP+ module type was detected.\n");
+ ixgbe_detach(dev);
+ return;
+ }
+ if (ixgbe_is_sfp(hw)) {
+ if (hw->phy.multispeed_fiber) {
+ hw->mac.ops.setup_sfp(hw);
+ taskqueue_enqueue(adapter->tq, &adapter->msf_task);
+ } else
+ taskqueue_enqueue(adapter->tq, &adapter->mod_task);
+ } else
+ taskqueue_enqueue(adapter->tq, &adapter->link_task);
+
+
+#ifdef IXGBE_TIMESYNC
+ /* Initialize IEEE 1588 support */
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+ ixgbe_tsync_init(adapter);
+#endif
+
/* Now inform the stack we're ready */
ifp->if_drv_flags |= IFF_DRV_RUNNING;
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
@@ -1081,7 +1212,7 @@ ixgbe_init(void *arg)
/*
-** MSIX Interrupt Handlers
+** MSIX Interrupt Tasklets
*/
static void
@@ -1136,7 +1267,8 @@ ixgbe_legacy_irq(void *arg)
struct ixgbe_hw *hw = &adapter->hw;
struct tx_ring *txr = adapter->tx_rings;
struct rx_ring *rxr = adapter->rx_rings;
- u32 reg_eicr;
+ bool more;
+ u32 reg_eicr, loop = MAX_LOOP;
reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
@@ -1148,7 +1280,15 @@ ixgbe_legacy_irq(void *arg)
if (ixgbe_rxeof(rxr, adapter->rx_process_limit))
taskqueue_enqueue(rxr->tq, &rxr->rx_task);
- if (ixgbe_txeof(txr))
+
+ IXGBE_TX_LOCK(txr);
+ ++txr->tx_irq;
+ do {
+ more = ixgbe_txeof(txr);
+ } while (loop-- && more);
+ IXGBE_TX_UNLOCK(txr);
+
+ if (more)
taskqueue_enqueue(txr->tq, &txr->tx_task);
/* Check for fan failure */
@@ -1160,20 +1300,27 @@ ixgbe_legacy_irq(void *arg)
}
/* Link status change */
- if (reg_eicr & IXGBE_EICR_LSC)
+ if (reg_eicr & IXGBE_EICR_LSC) {
+ ixgbe_check_link(&adapter->hw,
+ &adapter->link_speed, &adapter->link_up, 0);
ixgbe_update_link_status(adapter);
+ }
+
+ /* Update interrupt rate */
+ if (ixgbe_enable_aim == TRUE)
+ ixgbe_update_aim(rxr);
ixgbe_enable_intr(adapter);
return;
}
+#if __FreeBSD_version >= 602105
/*********************************************************************
*
* MSI TX Interrupt Service routine
*
**********************************************************************/
-
void
ixgbe_msix_tx(void *arg)
{
@@ -1181,6 +1328,8 @@ ixgbe_msix_tx(void *arg)
struct adapter *adapter = txr->adapter;
bool more;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, txr->eims);
+
IXGBE_TX_LOCK(txr);
++txr->tx_irq;
more = ixgbe_txeof(txr);
@@ -1198,7 +1347,6 @@ ixgbe_msix_tx(void *arg)
* MSIX RX Interrupt Service routine
*
**********************************************************************/
-
static void
ixgbe_msix_rx(void *arg)
{
@@ -1206,18 +1354,72 @@ ixgbe_msix_rx(void *arg)
struct adapter *adapter = rxr->adapter;
bool more;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rxr->eims);
+
++rxr->rx_irq;
- more = ixgbe_rxeof(rxr, -1);
+ more = ixgbe_rxeof(rxr, adapter->rx_process_limit);
+
+ /* Update interrupt rate */
+ if (ixgbe_enable_aim == TRUE)
+ ixgbe_update_aim(rxr);
+
if (more)
taskqueue_enqueue(rxr->tq, &rxr->rx_task);
else
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, rxr->eims);
- /* Update interrupt rate */
- if (ixgbe_enable_aim == TRUE)
- ixgbe_update_aim(rxr);
return;
}
+
+static void
+ixgbe_msix_link(void *arg)
+{
+ struct adapter *adapter = arg;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 reg_eicr;
+
+ ++adapter->link_irq;
+
+ /* First get the cause */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, IXGBE_EIMS_OTHER);
+ reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
+ /* Clear with write */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, reg_eicr);
+
+ /* Link status change */
+ if (reg_eicr & IXGBE_EICR_LSC)
+ taskqueue_enqueue(adapter->tq, &adapter->link_task);
+
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+ if (reg_eicr & IXGBE_EICR_ECC) {
+ device_printf(adapter->dev, "\nCRITICAL: ECC ERROR!! "
+ "Please Reboot!!\n");
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_ECC);
+ }
+ if (reg_eicr & IXGBE_EICR_GPI_SDP1) {
+ /* Clear the interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+ taskqueue_enqueue(adapter->tq, &adapter->msf_task);
+ } else if (reg_eicr & IXGBE_EICR_GPI_SDP2) {
+ /* Clear the interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP2);
+ taskqueue_enqueue(adapter->tq, &adapter->mod_task);
+ }
+ }
+
+ /* Check for fan failure */
+ if ((hw->device_id == IXGBE_DEV_ID_82598AT) &&
+ (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
+ device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! "
+ "REPLACE IMMEDIATELY!!\n");
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+ }
+
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
+ return;
+}
+#endif /* FreeBSD_version >= 602105 */
+
/*
** Routine to do adjust the RX EITR value based on traffic,
** its a simple three state model, but seems to help.
@@ -1267,33 +1469,36 @@ ixgbe_update_aim(struct rx_ring *rxr)
return;
}
-
static void
-ixgbe_msix_link(void *arg)
+ixgbe_init_moderation(struct adapter *adapter)
{
- struct adapter *adapter = arg;
- struct ixgbe_hw *hw = &adapter->hw;
- u32 reg_eicr;
-
- ++adapter->link_irq;
+ struct rx_ring *rxr = adapter->rx_rings;
+ struct tx_ring *txr = adapter->tx_rings;
- reg_eicr = IXGBE_READ_REG(hw, IXGBE_EICR);
+ /* Single interrupt - MSI or Legacy? */
+ if (adapter->msix < 2) {
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITR(0), 100);
+ return;
+ }
- if (reg_eicr & IXGBE_EICR_LSC)
- ixgbe_update_link_status(adapter);
+ /* TX irq moderation rate is fixed */
+ for (int i = 0; i < adapter->num_tx_queues; i++, txr++) {
+ IXGBE_WRITE_REG(&adapter->hw,
+ IXGBE_EITR(txr->msix), ixgbe_ave_latency);
+ txr->watchdog_timer = FALSE;
+ }
- /* Check for fan failure */
- if ((hw->phy.media_type == ixgbe_media_type_copper) &&
- (reg_eicr & IXGBE_EICR_GPI_SDP1)) {
- device_printf(adapter->dev, "\nCRITICAL: FAN FAILURE!! "
- "REPLACE IMMEDIATELY!!\n");
- IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EICR_GPI_SDP1);
+ /* RX moderation will be adapted over time, set default */
+ for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) {
+ IXGBE_WRITE_REG(&adapter->hw,
+ IXGBE_EITR(rxr->msix), ixgbe_low_latency);
}
- IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
- return;
-}
+ /* Set Link moderation */
+ IXGBE_WRITE_REG(&adapter->hw,
+ IXGBE_EITR(adapter->linkvec), IXGBE_LINK_ITR);
+}
/*********************************************************************
*
@@ -1382,12 +1587,12 @@ static int
ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
{
struct adapter *adapter = txr->adapter;
- u32 olinfo_status = 0, cmd_type_len = 0;
+ u32 olinfo_status = 0, cmd_type_len;
u32 paylen = 0;
int i, j, error, nsegs;
- int first, last = 0;
+ int first, last = 0, offload = 0;
struct mbuf *m_head;
- bus_dma_segment_t segs[IXGBE_MAX_SCATTER];
+ bus_dma_segment_t segs[ixgbe_num_segs];
bus_dmamap_t map;
struct ixgbe_tx_buf *txbuf, *txbuf_mapped;
union ixgbe_adv_tx_desc *txd = NULL;
@@ -1395,26 +1600,12 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
m_head = *m_headp;
/* Basic descriptor defines */
- cmd_type_len |= IXGBE_ADVTXD_DTYP_DATA;
- cmd_type_len |= IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT;
+ cmd_type_len = (IXGBE_ADVTXD_DTYP_DATA |
+ IXGBE_ADVTXD_DCMD_IFCS | IXGBE_ADVTXD_DCMD_DEXT);
if (m_head->m_flags & M_VLANTAG)
cmd_type_len |= IXGBE_ADVTXD_DCMD_VLE;
- /*
- * Force a cleanup if number of TX descriptors
- * available is below the threshold. If it fails
- * to get above, then abort transmit.
- */
- if (txr->tx_avail <= IXGBE_TX_CLEANUP_THRESHOLD) {
- ixgbe_txeof(txr);
- /* Make sure things have improved */
- if (txr->tx_avail <= IXGBE_TX_OP_THRESHOLD) {
- txr->no_tx_desc_avail++;
- return (ENOBUFS);
- }
- }
-
/*
* Important to capture the first descriptor
* used because it will contain the index of
@@ -1475,19 +1666,27 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
m_head = *m_headp;
/*
- ** Set the appropriate offload context
+ ** Set up the appropriate offload context
** this becomes the first descriptor of
** a packet.
*/
- if (ixgbe_tso_setup(txr, m_head, &paylen)) {
- cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
- olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
- olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
- olinfo_status |= paylen << IXGBE_ADVTXD_PAYLEN_SHIFT;
- ++adapter->tso_tx;
- } else if (ixgbe_tx_ctx_setup(txr, m_head))
+ if (m_head->m_pkthdr.csum_flags & CSUM_TSO) {
+ if (ixgbe_tso_setup(txr, m_head, &paylen)) {
+ cmd_type_len |= IXGBE_ADVTXD_DCMD_TSE;
+ olinfo_status |= IXGBE_TXD_POPTS_IXSM << 8;
olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
-
+ olinfo_status |= paylen << IXGBE_ADVTXD_PAYLEN_SHIFT;
+ ++adapter->tso_tx;
+ } else
+ return (ENXIO);
+ } else /* Offloads other than TSO */
+ offload = ixgbe_tx_ctx_setup(txr, m_head);
+ if (offload == TRUE)
+ olinfo_status |= IXGBE_TXD_POPTS_TXSM << 8;
+#ifdef IXGBE_TIMESYNC
+ if (offload == IXGBE_TIMESTAMP)
+ cmd_type_len |= IXGBE_ADVTXD_TSTAMP;
+#endif
/* Record payload length */
if (paylen == 0)
olinfo_status |= m_head->m_pkthdr.len <<
@@ -1513,6 +1712,7 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
i = 0;
txbuf->m_head = NULL;
+ txbuf->eop_index = -1;
}
txd->read.cmd_type_len |=
@@ -1526,6 +1726,7 @@ ixgbe_xmit(struct tx_ring *txr, struct mbuf **m_headp)
/* Set the index of the descriptor that will be marked done */
txbuf = &txr->tx_buffers[first];
+ txbuf->eop_index = last;
bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -1685,17 +1886,20 @@ out:
callout_reset(&adapter->timer, hz, ixgbe_local_timer, adapter);
}
+/*
+** Note: this routine updates the OS on the link state
+** the real check of the hardware only happens with
+** a link interrupt.
+*/
static void
ixgbe_update_link_status(struct adapter *adapter)
{
- boolean_t link_up = FALSE;
struct ifnet *ifp = adapter->ifp;
struct tx_ring *txr = adapter->tx_rings;
device_t dev = adapter->dev;
- ixgbe_check_link(&adapter->hw, &adapter->link_speed, &link_up, 0);
- if (link_up){
+ if (adapter->link_up){
if (adapter->link_active == FALSE) {
if (bootverbose)
device_printf(dev,"Link is up %d Gbps %s \n",
@@ -1720,7 +1924,6 @@ ixgbe_update_link_status(struct adapter *adapter)
}
-
/*********************************************************************
*
* This routine disables all traffic on the adapter by issuing a
@@ -1743,6 +1946,11 @@ ixgbe_stop(void *arg)
/* Tell the stack that the interface is no longer active */
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+#ifdef IXGBE_TIMESYNC
+ /* Disable IEEE 1588 support */
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+ ixgbe_tsync_disable(adapter);
+#endif
ixgbe_reset_hw(&adapter->hw);
adapter->hw.adapter_stopped = FALSE;
ixgbe_stop_adapter(&adapter->hw);
@@ -1817,8 +2025,13 @@ ixgbe_allocate_legacy(struct adapter *adapter)
device_get_nameunit(adapter->dev));
taskqueue_start_threads(&rxr->tq, 1, PI_NET, "%s rxq",
device_get_nameunit(adapter->dev));
+
if ((error = bus_setup_intr(dev, adapter->res[0],
+#if __FreeBSD_version >= 700000
INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_legacy_irq,
+#else
+ INTR_TYPE_NET | INTR_MPSAFE, ixgbe_legacy_irq,
+#endif
adapter, &adapter->tag[0])) != 0) {
device_printf(dev, "Failed to register fast interrupt "
"handler: %d\n", error);
@@ -1833,6 +2046,7 @@ ixgbe_allocate_legacy(struct adapter *adapter)
}
+#if __FreeBSD_version >= 602105
/*********************************************************************
*
* Setup MSIX Interrupt resources and handlers
@@ -1859,7 +2073,10 @@ ixgbe_allocate_msix(struct adapter *adapter)
}
/* Set the handler function */
error = bus_setup_intr(dev, adapter->res[vector],
- INTR_TYPE_NET | INTR_MPSAFE, NULL,
+ INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version > 700000
+ NULL,
+#endif
ixgbe_msix_tx, txr, &adapter->tag[vector]);
if (error) {
adapter->res[vector] = NULL;
@@ -1867,7 +2084,7 @@ ixgbe_allocate_msix(struct adapter *adapter)
return (error);
}
txr->msix = vector;
- txr->eims = IXGBE_IVAR_TX_QUEUE(vector);
+ txr->eims = 1 << vector;
TASK_INIT(&txr->tx_task, 0, ixgbe_handle_tx, txr);
txr->tq = taskqueue_create_fast("ixgbe_txq", M_NOWAIT,
taskqueue_thread_enqueue, &txr->tq);
@@ -1888,15 +2105,18 @@ ixgbe_allocate_msix(struct adapter *adapter)
}
/* Set the handler function */
error = bus_setup_intr(dev, adapter->res[vector],
- INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_rx,
- rxr, &adapter->tag[vector]);
+ INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version > 700000
+ NULL,
+#endif
+ ixgbe_msix_rx, rxr, &adapter->tag[vector]);
if (error) {
adapter->res[vector] = NULL;
device_printf(dev, "Failed to register RX handler");
return (error);
}
rxr->msix = vector;
- rxr->eims = IXGBE_IVAR_RX_QUEUE(vector);
+ rxr->eims = 1 << vector;
/* used in local timer */
adapter->rx_mask |= rxr->eims;
TASK_INIT(&rxr->rx_task, 0, ixgbe_handle_rx, rxr);
@@ -1916,19 +2136,37 @@ ixgbe_allocate_msix(struct adapter *adapter)
}
/* Set the link handler function */
error = bus_setup_intr(dev, adapter->res[vector],
- INTR_TYPE_NET | INTR_MPSAFE, NULL, ixgbe_msix_link,
- adapter, &adapter->tag[vector]);
+ INTR_TYPE_NET | INTR_MPSAFE,
+#if __FreeBSD_version > 700000
+ NULL,
+#endif
+ ixgbe_msix_link, adapter, &adapter->tag[vector]);
if (error) {
adapter->res[vector] = NULL;
device_printf(dev, "Failed to register LINK handler");
return (error);
}
adapter->linkvec = vector;
+ /* Tasklets for Link, SFP and Multispeed Fiber */
+ TASK_INIT(&adapter->link_task, 0, ixgbe_handle_link, adapter);
+ TASK_INIT(&adapter->mod_task, 0, ixgbe_handle_mod, adapter);
+ TASK_INIT(&adapter->msf_task, 0, ixgbe_handle_msf, adapter);
+ adapter->tq = taskqueue_create_fast("ixgbe_link", M_NOWAIT,
+ taskqueue_thread_enqueue, &adapter->tq);
+ taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s linkq",
+ device_get_nameunit(adapter->dev));
return (0);
}
+#else /* Freebsd 6.1/2 */
+static int
+ixgbe_allocate_msix(struct adapter *adapter)
+{
+ return (1);
+}
+#endif
-
+#if __FreeBSD_version >= 602105
/*
* Setup Either MSI/X or MSI
*/
@@ -1996,6 +2234,7 @@ msi:
device_printf(adapter->dev,"Using MSI interrupt\n");
return (msgs);
}
+#endif /* FreeBSD_version >= 602105 */
static int
ixgbe_allocate_pci_resources(struct adapter *adapter)
@@ -2031,9 +2270,10 @@ ixgbe_allocate_pci_resources(struct adapter *adapter)
adapter->num_tx_queues = 1;
adapter->num_rx_queues = 1;
+#if __FreeBSD_version >= 602105
/* Now setup MSI or MSI/X */
adapter->msix = ixgbe_setup_msix(adapter);
-
+#endif
adapter->hw.back = &adapter->osdep;
return (0);
}
@@ -2051,7 +2291,10 @@ ixgbe_free_pci_resources(struct adapter * adapter)
if (adapter->msix == 0)
adapter->msix = 1;
- rid = PCIR_BAR(MSIX_82598_BAR);
+ if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ rid = PCIR_BAR(MSIX_82598_BAR);
+ else
+ rid = PCIR_BAR(MSIX_82599_BAR);
/*
* First release all the interrupt resources:
@@ -2071,12 +2314,14 @@ ixgbe_free_pci_resources(struct adapter * adapter)
}
}
+#if __FreeBSD_version >= 602105
if (adapter->msix)
pci_release_msi(dev);
if (adapter->msix_mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
rid, adapter->msix_mem);
+#endif
if (adapter->pci_mem != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
@@ -2215,7 +2460,7 @@ ixgbe_dma_malloc(struct adapter *adapter, bus_size_t size,
int r;
r = bus_dma_tag_create(NULL, /* parent */
- PAGE_SIZE, 0, /* alignment, bounds */
+ 1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
@@ -2415,12 +2660,12 @@ ixgbe_allocate_transmit_buffers(struct tx_ring *txr)
* Setup DMA descriptor areas.
*/
if ((error = bus_dma_tag_create(NULL, /* parent */
- PAGE_SIZE, 0, /* alignment, bounds */
+ 1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
IXGBE_TSO_SIZE, /* maxsize */
- IXGBE_MAX_SCATTER, /* nsegments */
+ ixgbe_num_segs, /* nsegments */
PAGE_SIZE, /* maxsegsize */
0, /* flags */
NULL, /* lockfunc */
@@ -2484,6 +2729,8 @@ ixgbe_setup_transmit_ring(struct tx_ring *txr)
m_freem(txbuf->m_head);
txbuf->m_head = NULL;
}
+ /* Clear the EOP index */
+ txbuf->eop_index = -1;
}
/* Set number of descriptors available */
@@ -2491,7 +2738,6 @@ ixgbe_setup_transmit_ring(struct tx_ring *txr)
bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
}
/*********************************************************************
@@ -2524,8 +2770,7 @@ ixgbe_initialize_transmit_units(struct adapter *adapter)
/* Setup the Base and Length of the Tx Descriptor Ring */
for (int i = 0; i < adapter->num_tx_queues; i++, txr++) {
- u64 txhwb = 0, tdba = txr->txdma.dma_paddr;
- u32 txctrl;
+ u64 tdba = txr->txdma.dma_paddr;
IXGBE_WRITE_REG(hw, IXGBE_TDBAL(i),
(tdba & 0x00000000ffffffffULL));
@@ -2533,17 +2778,6 @@ ixgbe_initialize_transmit_units(struct adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_TDLEN(i),
adapter->num_tx_desc * sizeof(struct ixgbe_legacy_tx_desc));
- /* Setup for Head WriteBack */
- txhwb = (u64)vtophys(&txr->tx_hwb);
- txhwb |= IXGBE_TDWBAL_HEAD_WB_ENABLE;
- IXGBE_WRITE_REG(hw, IXGBE_TDWBAL(i),
- (txhwb & 0x00000000ffffffffULL));
- IXGBE_WRITE_REG(hw, IXGBE_TDWBAH(i),
- (txhwb >> 32));
- txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i));
- txctrl &= ~IXGBE_DCA_TXCTRL_TX_WB_RO_EN;
- IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), txctrl);
-
/* Setup the HW Tx Head and Tail descriptor pointers */
IXGBE_WRITE_REG(hw, IXGBE_TDH(i), 0);
IXGBE_WRITE_REG(hw, IXGBE_TDT(i), 0);
@@ -2554,6 +2788,13 @@ ixgbe_initialize_transmit_units(struct adapter *adapter)
txr->watchdog_timer = 0;
}
+ if (hw->mac.type == ixgbe_mac_82599EB) {
+ u32 dmatxctl;
+ dmatxctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
+ dmatxctl |= IXGBE_DMATXCTL_TE;
+ IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, dmatxctl);
+ }
+
return;
}
@@ -2634,7 +2875,7 @@ ixgbe_free_transmit_buffers(struct tx_ring *txr)
*
**********************************************************************/
-static boolean_t
+static int
ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
{
struct adapter *adapter = txr->adapter;
@@ -2642,12 +2883,12 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
struct ixgbe_tx_buf *tx_buffer;
u32 vlan_macip_lens = 0, type_tucmd_mlhl = 0;
struct ether_vlan_header *eh;
- struct ip *ip;
+ struct ip *ip = NULL;
struct ip6_hdr *ip6;
int ehdrlen, ip_hlen = 0;
u16 etype;
u8 ipproto = 0;
- bool offload = TRUE;
+ bool offload = FALSE;
int ctxd = txr->next_avail_tx_desc;
#if __FreeBSD_version < 700000
struct m_tag *mtag;
@@ -2656,8 +2897,8 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
#endif
- if ((mp->m_pkthdr.csum_flags & CSUM_OFFLOAD) == 0)
- offload = FALSE;
+ if (mp->m_pkthdr.csum_flags & CSUM_OFFLOAD)
+ offload = TRUE;
tx_buffer = &txr->tx_buffers[ctxd];
TXD = (struct ixgbe_adv_tx_context_desc *) &txr->tx_base[ctxd];
@@ -2671,14 +2912,14 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
if (mtag != NULL) {
vlan_macip_lens |=
htole16(VLAN_TAG_VALUE(mtag)) << IXGBE_ADVTXD_VLAN_SHIFT;
- } else if (offload == FALSE)
- return FALSE; /* No need for CTX */
+ offload = TRUE;
+ }
#else
if (mp->m_flags & M_VLANTAG) {
vtag = htole16(mp->m_pkthdr.ether_vtag);
vlan_macip_lens |= (vtag << IXGBE_ADVTXD_VLAN_SHIFT);
- } else if (offload == FALSE)
- return FALSE;
+ offload = TRUE;
+ }
#endif
/*
* Determine where frame payload starts.
@@ -2714,9 +2955,12 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
ipproto = ip6->ip6_nxt;
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_IPV6;
break;
+#ifdef IXGBE_TIMESYNC
+ case ETHERTYPE_IEEE1588:
+ return (IXGBE_TIMESTAMP);
+#endif
default:
- offload = FALSE;
- break;
+ return (FALSE);
}
vlan_macip_lens |= ip_hlen;
@@ -2724,18 +2968,36 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
switch (ipproto) {
case IPPROTO_TCP:
- if (mp->m_pkthdr.csum_flags & CSUM_TCP)
+ if (mp->m_pkthdr.csum_flags & CSUM_TCP) {
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_TCP;
+ offload = TRUE;
+ }
break;
+
case IPPROTO_UDP:
- if (mp->m_pkthdr.csum_flags & CSUM_UDP)
+ {
+#ifdef IXGBE_TIMESYNC
+ void *hdr = (caddr_t) ip + ip_hlen;
+ struct udphdr *uh = (struct udphdr *)hdr;
+
+ if (uh->uh_dport == htons(TSYNC_UDP_PORT))
+ return (IXGBE_TIMESTAMP);
+#endif
+ if (mp->m_pkthdr.csum_flags & CSUM_UDP) {
type_tucmd_mlhl |= IXGBE_ADVTXD_TUCMD_L4T_UDP;
+ offload = TRUE;
+ }
break;
+
+ }
+
default:
- offload = FALSE;
- break;
+ return (FALSE);
}
+ if (offload != TRUE )
+ return (FALSE);
+
/* Now copy bits into descriptor */
TXD->vlan_macip_lens |= htole32(vlan_macip_lens);
TXD->type_tucmd_mlhl |= htole32(type_tucmd_mlhl);
@@ -2743,6 +3005,7 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
TXD->mss_l4len_idx = htole32(0);
tx_buffer->m_head = NULL;
+ tx_buffer->eop_index = -1;
/* We've consumed the first desc, adjust counters */
if (++ctxd == adapter->num_tx_desc)
@@ -2750,7 +3013,7 @@ ixgbe_tx_ctx_setup(struct tx_ring *txr, struct mbuf *mp)
txr->next_avail_tx_desc = ctxd;
--txr->tx_avail;
- return (offload);
+ return (TRUE);
}
#if __FreeBSD_version >= 700000
@@ -2774,9 +3037,6 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
struct ip *ip;
struct tcphdr *th;
- if (((mp->m_pkthdr.csum_flags & CSUM_TSO) == 0) ||
- (mp->m_pkthdr.len <= IXGBE_TX_BUFFER_SIZE))
- return FALSE;
/*
* Determine where frame payload starts.
@@ -2799,7 +3059,6 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
ip = (struct ip *)(mp->m_data + ehdrlen);
if (ip->ip_p != IPPROTO_TCP)
return FALSE; /* 0 */
- ip->ip_len = 0;
ip->ip_sum = 0;
ip_hlen = ip->ip_hl << 2;
th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
@@ -2807,6 +3066,7 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
ip->ip_dst.s_addr, htons(IPPROTO_TCP));
tcp_hlen = th->th_off << 2;
hdrlen = ehdrlen + ip_hlen + tcp_hlen;
+
/* This is used in the transmit desc in encap */
*paylen = mp->m_pkthdr.len - hdrlen;
@@ -2834,6 +3094,7 @@ ixgbe_tso_setup(struct tx_ring *txr, struct mbuf *mp, u32 *paylen)
TXD->seqnum_seed = htole32(0);
tx_buffer->m_head = NULL;
+ tx_buffer->eop_index = -1;
if (++ctxd == adapter->num_tx_desc)
ctxd = 0;
@@ -2867,9 +3128,9 @@ ixgbe_txeof(struct tx_ring *txr)
u32 first, last, done, num_avail;
u32 cleaned = 0;
struct ixgbe_tx_buf *tx_buffer;
- struct ixgbe_legacy_tx_desc *tx_desc;
+ struct ixgbe_legacy_tx_desc *tx_desc, *eop_desc;
- mtx_assert(&txr->mtx, MA_OWNED);
+ mtx_assert(&txr->tx_mtx, MA_OWNED);
if (txr->tx_avail == adapter->num_tx_desc)
return FALSE;
@@ -2880,16 +3141,28 @@ ixgbe_txeof(struct tx_ring *txr)
tx_buffer = &txr->tx_buffers[first];
/* For cleanup we just use legacy struct */
tx_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[first];
+ last = tx_buffer->eop_index;
+ if (last == -1)
+ return FALSE;
- /* Get the HWB */
- rmb();
- done = txr->tx_hwb;
+ eop_desc = (struct ixgbe_legacy_tx_desc *)&txr->tx_base[last];
+ /*
+ ** Get the index of the first descriptor
+ ** BEYOND the EOP and call that 'done'.
+ ** I do this so the comparison in the
+ ** inner while loop below can be simple
+ */
+ if (++last == adapter->num_tx_desc) last = 0;
+ done = last;
bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
BUS_DMASYNC_POSTREAD);
-
- while (TRUE) {
- /* We clean the range til last head write back */
+ /*
+ ** Only the EOP descriptor of a packet now has the DD
+ ** bit set, this is what we look for...
+ */
+ while (eop_desc->upper.fields.status & IXGBE_TXD_STAT_DD) {
+ /* We clean the range of the packet */
while (first != done) {
tx_desc->upper.data = 0;
tx_desc->lower.data = 0;
@@ -2907,6 +3180,7 @@ ixgbe_txeof(struct tx_ring *txr)
tx_buffer->m_head = NULL;
tx_buffer->map = NULL;
}
+ tx_buffer->eop_index = -1;
if (++first == adapter->num_tx_desc)
first = 0;
@@ -2916,10 +3190,14 @@ ixgbe_txeof(struct tx_ring *txr)
(struct ixgbe_legacy_tx_desc *)&txr->tx_base[first];
}
/* See if there is more work now */
- last = done;
- rmb();
- done = txr->tx_hwb;
- if (last == done)
+ last = tx_buffer->eop_index;
+ if (last != -1) {
+ eop_desc =
+ (struct ixgbe_legacy_tx_desc *)&txr->tx_base[last];
+ /* Get next done point */
+ if (++last == adapter->num_tx_desc) last = 0;
+ done = last;
+ } else
break;
}
bus_dmamap_sync(txr->txdma.dma_tag, txr->txdma.dma_map,
@@ -3091,7 +3369,7 @@ ixgbe_allocate_receive_buffers(struct rx_ring *rxr)
** it may not always use this.
*/
if ((error = bus_dma_tag_create(NULL, /* parent */
- PAGE_SIZE, 0, /* alignment, bounds */
+ 1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
@@ -3244,7 +3522,7 @@ fail:
* the rings that completed, the failing case will have
* cleaned up for itself. 'j' failed, so its the terminus.
*/
- for (int i = 0; i < j; i++) {
+ for (int i = 0; i < j; ++i) {
rxr = &adapter->rx_rings[i];
for (int n = 0; n < adapter->num_rx_desc; n++) {
struct ixgbe_rx_buf *rxbuf;
@@ -3314,9 +3592,21 @@ ixgbe_initialize_receive_units(struct adapter *adapter)
srrctl |= ((IXGBE_RX_HDR << IXGBE_SRRCTL_BSIZEHDRSIZE_SHIFT)
& IXGBE_SRRCTL_BSIZEHDR_MASK);
srrctl |= IXGBE_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS;
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+ /* PSRTYPE must be initialized in 82599 */
+ u32 psrtype = IXGBE_PSRTYPE_TCPHDR |
+ IXGBE_PSRTYPE_UDPHDR |
+ IXGBE_PSRTYPE_IPV4HDR |
+ IXGBE_PSRTYPE_IPV6HDR;
+ psrtype |= (7 << 29);
+ IXGBE_WRITE_REG(hw, IXGBE_PSRTYPE(0), psrtype);
+ }
} else
srrctl |= IXGBE_SRRCTL_DESCTYPE_ADV_ONEBUF;
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+ srrctl |= IXGBE_SRRCTL_DROP_EN;
+
IXGBE_WRITE_REG(hw, IXGBE_SRRCTL(0), srrctl);
for (int i = 0; i < adapter->num_rx_queues; i++, rxr++) {
@@ -3356,6 +3646,9 @@ ixgbe_initialize_receive_units(struct adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_RSSRK(i), random[i]);
/* Perform hash on these packet types */
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB)
+ mrqc = IXGBE_MRQC_VMDQRSS32EN;
+
mrqc |= IXGBE_MRQC_RSSEN
| IXGBE_MRQC_RSS_FIELD_IPV4
| IXGBE_MRQC_RSS_FIELD_IPV4_TCP
@@ -3380,6 +3673,14 @@ ixgbe_initialize_receive_units(struct adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_RXCSUM, rxcsum);
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+ u32 rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
+ rdrxctl |= IXGBE_RDRXCTL_AGGDIS;
+ rdrxctl |= IXGBE_RDRXCTL_RSCLLIDIS;
+ rdrxctl |= IXGBE_RDRXCTL_MVMEN;
+ IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
+ }
+
return;
}
@@ -3594,9 +3895,15 @@ ixgbe_rxeof(struct rx_ring *rxr, int count)
else
rxr->fmp->m_pkthdr.csum_flags = 0;
if (staterr & IXGBE_RXD_STAT_VP) {
+#if __FreeBSD_version >= 700000
rxr->fmp->m_pkthdr.ether_vtag =
le16toh(cur->wb.upper.vlan);
rxr->fmp->m_flags |= M_VLANTAG;
+#else
+ VLAN_INPUT_TAG_NEW(ifp, rxr->fmp,
+ (le16toh(cur->wb.upper.vlan) &
+ IXGBE_RX_DESC_SPECIAL_VLAN_MASK));
+#endif
}
sendmp = rxr->fmp;
rxr->fmp = NULL;
@@ -3765,14 +4072,23 @@ ixgbe_enable_intr(struct adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
u32 mask = IXGBE_EIMS_ENABLE_MASK;
+
/* Enable Fan Failure detection */
- if (hw->phy.media_type == ixgbe_media_type_copper)
+ if (hw->device_id == IXGBE_DEV_ID_82598AT)
mask |= IXGBE_EIMS_GPI_SDP1;
+ /* 82599 specific interrupts */
+ if (adapter->hw.mac.type == ixgbe_mac_82599EB) {
+ mask |= IXGBE_EIMS_ECC;
+ mask |= IXGBE_EIMS_GPI_SDP1;
+ mask |= IXGBE_EIMS_GPI_SDP2;
+ }
+
IXGBE_WRITE_REG(hw, IXGBE_EIMS, mask);
/* With RSS we use auto clear */
if (adapter->msix_mem) {
+ mask = IXGBE_EIMS_ENABLE_MASK;
/* Dont autoclear Link */
mask &= ~IXGBE_EIMS_OTHER;
mask &= ~IXGBE_EIMS_LSC;
@@ -3805,6 +4121,15 @@ ixgbe_read_pci_cfg(struct ixgbe_hw *hw, u32 reg)
return (value);
}
+void
+ixgbe_write_pci_cfg(struct ixgbe_hw *hw, u32 reg, u16 value)
+{
+ pci_write_config(((struct ixgbe_osdep *)hw->back)->dev,
+ reg, value, 2);
+
+ return;
+}
+
/*
** Setup the correct IVAR register for a particular MSIX interrupt
** (yes this is all very magic and confusing :)
@@ -3834,6 +4159,21 @@ ixgbe_set_ivar(struct adapter *adapter, u16 entry, u8 vector, s8 type)
IXGBE_WRITE_REG(&adapter->hw, IXGBE_IVAR(index), ivar);
break;
+ case ixgbe_mac_82599EB:
+ if (type == -1) { /* MISC IVAR */
+ index = (entry & 1) * 8;
+ ivar = IXGBE_READ_REG(hw, IXGBE_IVAR_MISC);
+ ivar &= ~(0xFF << index);
+ ivar |= (vector << index);
+ IXGBE_WRITE_REG(hw, IXGBE_IVAR_MISC, ivar);
+ } else { /* RX/TX IVARS */
+ index = (16 * (entry & 1)) + (8 * type);
+ ivar = IXGBE_READ_REG(hw, IXGBE_IVAR(entry >> 1));
+ ivar &= ~(0xFF << index);
+ ivar |= (vector << index);
+ IXGBE_WRITE_REG(hw, IXGBE_IVAR(entry >> 1), ivar);
+ }
+
default:
break;
}
@@ -3886,6 +4226,63 @@ out:
return (result);
}
+/*
+** Tasklet handler for MSIX Link interrupts
+** - do outside interrupt since it might sleep
+*/
+static void
+ixgbe_handle_link(void *context, int pending)
+{
+ struct adapter *adapter = context;
+
+ ixgbe_check_link(&adapter->hw,
+ &adapter->link_speed, &adapter->link_up, 0);
+ ixgbe_update_link_status(adapter);
+}
+
+/*
+** Tasklet for handling SFP module interrupts
+*/
+static void
+ixgbe_handle_mod(void *context, int pending)
+{
+ struct adapter *adapter = context;
+ struct ixgbe_hw *hw = &adapter->hw;
+ device_t dev = adapter->dev;
+ u32 err;
+
+ err = hw->phy.ops.identify_sfp(hw);
+ if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ device_printf(dev,
+ "Unsupported SFP+ module type was detected.\n");
+ return;
+ }
+ hw->mac.ops.setup_sfp(hw);
+ taskqueue_enqueue(adapter->tq, &adapter->msf_task);
+ return;
+}
+
+
+/*
+** Tasklet for handling MSF (multispeed fiber) interrupts
+*/
+static void
+ixgbe_handle_msf(void *context, int pending)
+{
+ struct adapter *adapter = context;
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 autoneg;
+
+ if (hw->mac.ops.get_link_capabilities)
+ hw->mac.ops.get_link_capabilities(hw, &autoneg,
+ &hw->mac.autoneg);
+ if (hw->mac.ops.setup_link_speed)
+ hw->mac.ops.setup_link_speed(hw, autoneg, TRUE, TRUE);
+ ixgbe_check_link(&adapter->hw,
+ &adapter->link_speed, &adapter->link_up, 0);
+ ixgbe_update_link_status(adapter);
+ return;
+}
/**********************************************************************
*
@@ -3935,6 +4332,9 @@ ixgbe_update_stats_counters(struct adapter *adapter)
adapter->stats.prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
adapter->stats.rlec += IXGBE_READ_REG(hw, IXGBE_RLEC);
+ adapter->stats.lxonrxc += IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
+ adapter->stats.lxoffrxc += IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+
lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
adapter->stats.lxontxc += lxon;
lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
@@ -4147,7 +4547,7 @@ ixgbe_set_flowcntl(SYSCTL_HANDLER_ARGS)
adapter->hw.fc.requested_mode = ixgbe_fc_none;
}
- ixgbe_setup_fc(&adapter->hw, 0);
+ ixgbe_fc_enable(&adapter->hw, 0);
return error;
}
@@ -4160,3 +4560,97 @@ ixgbe_add_rx_process_limit(struct adapter *adapter, const char *name,
SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
}
+
+#ifdef IXGBE_TIMESYNC
+/*
+ * Initialize the Time Sync Feature
+ */
+static int
+ixgbe_tsync_init(struct adapter *adapter)
+{
+ device_t dev = adapter->dev;
+ u32 tx_ctl, rx_ctl;
+
+
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_TIMINCA, (1<<24) |
+ 20833/PICOSECS_PER_TICK);
+
+ adapter->last_stamp = IXGBE_READ_REG(&adapter->hw, IXGBE_SYSTIML);
+ adapter->last_stamp |= (u64)IXGBE_READ_REG(&adapter->hw,
+ IXGBE_SYSTIMH) << 32ULL;
+
+ /* Enable the TX side */
+ tx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCTXCTL);
+ tx_ctl |= 0x10;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_TSYNCTXCTL, tx_ctl);
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+
+ tx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCTXCTL);
+ if ((tx_ctl & 0x10) == 0) {
+ device_printf(dev, "Failed to enable TX timestamping\n");
+ return (ENXIO);
+ }
+
+ /* Enable RX */
+ rx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCRXCTL);
+ rx_ctl |= 0x10; /* Enable the feature */
+ rx_ctl |= 0x04; /* This value turns on Ver 1 and 2 */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_TSYNCRXCTL, rx_ctl);
+
+ /*
+ * Ethertype Filter Queue Filter[0][15:0] = 0x88F7 (Ethertype)
+ * Ethertype Filter Queue Filter[0][30] = 0x1 (Enable filter)
+ * Ethertype Filter Queue Filter[0][31] = 0x1 (Enable Timestamping)
+ */
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_ETQF(0), 0xC00088f7);
+
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+
+ rx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCRXCTL);
+ if ((rx_ctl & 0x10) == 0) {
+ device_printf(dev, "Failed to enable RX timestamping\n");
+ return (ENXIO);
+ }
+
+ device_printf(dev, "IEEE 1588 Precision Time Protocol enabled\n");
+
+ return (0);
+}
+
+/*
+ * Disable the Time Sync Feature
+ */
+static void
+ixgbe_tsync_disable(struct adapter *adapter)
+{
+ u32 tx_ctl, rx_ctl;
+
+ tx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCTXCTL);
+ tx_ctl &= ~0x10;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_TSYNCTXCTL, tx_ctl);
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+
+ /* Invalidate TX Timestamp */
+ IXGBE_READ_REG(&adapter->hw, IXGBE_TXSTMPH);
+
+ tx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCTXCTL);
+ if (tx_ctl & 0x10)
+ HW_DEBUGOUT("Failed to disable TX timestamping\n");
+
+ rx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCRXCTL);
+ rx_ctl &= ~0x10;
+
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_TSYNCRXCTL, rx_ctl);
+ IXGBE_WRITE_FLUSH(&adapter->hw);
+
+ /* Invalidate RX Timestamp */
+ IXGBE_READ_REG(&adapter->hw, IXGBE_RXSATRH);
+
+ rx_ctl = IXGBE_READ_REG(&adapter->hw, IXGBE_TSYNCRXCTL);
+ if (rx_ctl & 0x10)
+ HW_DEBUGOUT("Failed to disable RX timestamping\n");
+
+ return;
+}
+
+#endif /* IXGBE_TIMESYNC */
diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h
index 5a5e2ef..e6bebd1 100644
--- a/sys/dev/ixgbe/ixgbe.h
+++ b/sys/dev/ixgbe/ixgbe.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -64,6 +64,7 @@
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
+#include <netinet/tcp_lro.h>
#include <netinet/udp.h>
#include <machine/in_cksum.h>
@@ -83,8 +84,12 @@
#include <sys/taskqueue.h>
#include <sys/pcpu.h>
+#ifdef IXGBE_TIMESYNC
+#include <sys/ioccom.h>
+#include <sys/time.h>
+#endif
+
#include "ixgbe_api.h"
-#include "tcp_lro.h"
/* Tunables */
@@ -95,7 +100,7 @@
* bytes. Performance tests have show the 2K value to be optimal for top
* performance.
*/
-#define DEFAULT_TXD 256
+#define DEFAULT_TXD 1024
#define PERFORM_TXD 2048
#define MAX_TXD 4096
#define MIN_TXD 64
@@ -110,7 +115,7 @@
* against the system mbuf pool limit, you can tune nmbclusters
* to adjust for this.
*/
-#define DEFAULT_RXD 256
+#define DEFAULT_RXD 1024
#define PERFORM_RXD 2048
#define MAX_RXD 4096
#define MIN_RXD 64
@@ -159,7 +164,8 @@
#define HW_DEBUGOUT2(S, A, B) if (DEBUG_HW) printf(S "\n", A, B)
#define MAX_NUM_MULTICAST_ADDRESSES 128
-#define IXGBE_MAX_SCATTER 100
+#define IXGBE_82598_SCATTER 100
+#define IXGBE_82599_SCATTER 32
#define MSIX_82598_BAR 3
#define MSIX_82599_BAR 4
#define IXGBE_TSO_SIZE 65535
@@ -171,12 +177,13 @@
#define IXGBE_MSGS 18
/* For 6.X code compatibility */
-#if __FreeBSD_version < 700000
+#if !defined(ETHER_BPF_MTAP)
#define ETHER_BPF_MTAP BPF_MTAP
+#endif
+
+#if __FreeBSD_version < 700000
#define CSUM_TSO 0
#define IFCAP_TSO4 0
-#define FILTER_STRAY
-#define FILTER_HANDLED
#endif
/*
@@ -214,6 +221,7 @@ typedef struct _ixgbe_vendor_info_t {
struct ixgbe_tx_buf {
+ u32 eop_index;
struct mbuf *m_head;
bus_dmamap_t map;
};
@@ -314,8 +322,6 @@ struct adapter {
/*
* Interrupt resources:
- * Oplin has 20 MSIX messages
- * so allocate that for now.
*/
void *tag[IXGBE_MSGS];
struct resource *res[IXGBE_MSGS];
@@ -334,6 +340,7 @@ struct adapter {
bool link_active;
u16 max_frame_size;
u32 link_speed;
+ bool link_up;
u32 linkvec;
u32 tx_int_delay;
u32 tx_abs_int_delay;
@@ -343,8 +350,12 @@ struct adapter {
/* Mbuf cluster size */
u32 rx_mbuf_sz;
- /* Check for missing optics */
+ /* Support for pluggable optics */
bool sfp_probe;
+ struct task link_task; /* Link tasklet */
+ struct task mod_task; /* SFP tasklet */
+ struct task msf_task; /* Multispeed Fiber tasklet */
+ struct taskqueue *tq;
/*
* Transmit rings:
@@ -364,6 +375,12 @@ struct adapter {
u32 rx_mask;
u32 rx_process_limit;
+#ifdef IXGBE_TIMESYNC
+ u64 last_stamp;
+ u64 last_sec;
+ u32 last_ns;
+#endif
+
/* Misc stats maintained by the driver */
unsigned long dropped_pkts;
unsigned long mbuf_defrag_failed;
@@ -378,6 +395,32 @@ struct adapter {
struct ixgbe_hw_stats stats;
};
+#ifdef IXGBE_TIMESYNC
+/* Precision Time Sync (IEEE 1588) defines */
+#define ETHERTYPE_IEEE1588 0x88F7
+#define PICOSECS_PER_TICK 20833
+#define TSYNC_UDP_PORT 319 /* UDP port for the protocol */
+#define IXGBE_ADVTXD_TSTAMP 0x00080000
+
+/* TIMESYNC IOCTL defines */
+#define IXGBE_TIMESYNC_READTS _IOWR('i', 127, struct ixgbe_tsync_read)
+#define IXGBE_TIMESTAMP 5 /* A unique return value */
+
+/* Used in the READTS IOCTL */
+struct ixgbe_tsync_read {
+ int read_current_time;
+ struct timespec system_time;
+ u64 network_time;
+ u64 rx_stamp;
+ u64 tx_stamp;
+ u16 seqid;
+ unsigned char srcid[6];
+ int rx_valid;
+ int tx_valid;
+};
+
+#endif /* IXGBE_TIMESYNC */
+
#define IXGBE_CORE_LOCK_INIT(_sc, _name) \
mtx_init(&(_sc)->core_mtx, _name, "IXGBE Core Lock", MTX_DEF)
#define IXGBE_CORE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->core_mtx)
@@ -385,6 +428,7 @@ struct adapter {
#define IXGBE_RX_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rx_mtx)
#define IXGBE_CORE_LOCK(_sc) mtx_lock(&(_sc)->core_mtx)
#define IXGBE_TX_LOCK(_sc) mtx_lock(&(_sc)->tx_mtx)
+#define IXGBE_TX_TRYLOCK(_sc) mtx_trylock(&(_sc)->tx_mtx)
#define IXGBE_RX_LOCK(_sc) mtx_lock(&(_sc)->rx_mtx)
#define IXGBE_CORE_UNLOCK(_sc) mtx_unlock(&(_sc)->core_mtx)
#define IXGBE_TX_UNLOCK(_sc) mtx_unlock(&(_sc)->tx_mtx)
@@ -393,4 +437,20 @@ struct adapter {
#define IXGBE_TX_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->tx_mtx, MA_OWNED)
+static inline bool
+ixgbe_is_sfp(struct ixgbe_hw *hw)
+{
+ switch (hw->phy.type) {
+ case ixgbe_phy_sfp_avago:
+ case ixgbe_phy_sfp_ftl:
+ case ixgbe_phy_sfp_intel:
+ case ixgbe_phy_sfp_unknown:
+ case ixgbe_phy_tw_tyco:
+ case ixgbe_phy_tw_unknown:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
#endif /* _IXGBE_H_ */
diff --git a/sys/dev/ixgbe/ixgbe_82598.c b/sys/dev/ixgbe/ixgbe_82598.c
index c94b2f9..fd90d16 100644
--- a/sys/dev/ixgbe/ixgbe_82598.c
+++ b/sys/dev/ixgbe/ixgbe_82598.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -37,15 +37,12 @@
#include "ixgbe_common.h"
#include "ixgbe_phy.h"
+u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw);
s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw);
static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
ixgbe_link_speed *speed,
bool *autoneg);
-s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw,
- ixgbe_link_speed *speed,
- bool *autoneg);
static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw);
-s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num);
s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num);
static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw);
static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
@@ -60,22 +57,41 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
-#ifndef NO_82598_A0_SUPPORT
-s32 ixgbe_reset_hw_rev_0_82598(struct ixgbe_hw *hw);
-#endif
static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw);
s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan,
u32 vind, bool vlan_on);
static s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw);
-static s32 ixgbe_blink_led_stop_82598(struct ixgbe_hw *hw, u32 index);
-static s32 ixgbe_blink_led_start_82598(struct ixgbe_hw *hw, u32 index);
s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val);
s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val);
s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
u8 *eeprom_data);
u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw);
+s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw);
+
+/**
+ * ixgbe_get_pcie_msix_count_82598 - Gets MSI-X vector count
+ * @hw: pointer to hardware structure
+ *
+ * Read PCIe configuration space, and get the MSI-X vector count from
+ * the capabilities table.
+ **/
+u32 ixgbe_get_pcie_msix_count_82598(struct ixgbe_hw *hw)
+{
+ u32 msix_count = 18;
+
+ if (hw->mac.msix_vectors_from_pcie) {
+ msix_count = IXGBE_READ_PCIE_WORD(hw,
+ IXGBE_PCIE_MSIX_82598_CAPS);
+ msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
+
+ /* MSI-X count is zero-based in HW, so increment to give
+ * proper value */
+ msix_count++;
+ }
+ return msix_count;
+}
/**
* ixgbe_init_ops_82598 - Inits func ptrs and MAC type
@@ -89,30 +105,21 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw)
struct ixgbe_mac_info *mac = &hw->mac;
struct ixgbe_phy_info *phy = &hw->phy;
s32 ret_val;
- u16 list_offset, data_offset;
ret_val = ixgbe_init_phy_ops_generic(hw);
ret_val = ixgbe_init_ops_generic(hw);
+ /* PHY */
+ phy->ops.init = &ixgbe_init_phy_ops_82598;
+
/* MAC */
-#ifndef NO_82598_A0_SUPPORT
- if (hw->revision_id == 0)
- mac->ops.reset_hw = &ixgbe_reset_hw_rev_0_82598;
- else
- mac->ops.reset_hw = &ixgbe_reset_hw_82598;
-#else
mac->ops.reset_hw = &ixgbe_reset_hw_82598;
-#endif
mac->ops.get_media_type = &ixgbe_get_media_type_82598;
mac->ops.get_supported_physical_layer =
&ixgbe_get_supported_physical_layer_82598;
mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_82598;
mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_82598;
- /* LEDs */
- mac->ops.blink_led_start = &ixgbe_blink_led_start_82598;
- mac->ops.blink_led_stop = &ixgbe_blink_led_stop_82598;
-
/* RAR, Multicast, VLAN */
mac->ops.set_vmdq = &ixgbe_set_vmdq_82598;
mac->ops.clear_vmdq = &ixgbe_clear_vmdq_82598;
@@ -120,42 +127,67 @@ s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw)
mac->ops.clear_vfta = &ixgbe_clear_vfta_82598;
/* Flow Control */
- mac->ops.setup_fc = &ixgbe_setup_fc_82598;
-
- /* Link */
- mac->ops.check_link = &ixgbe_check_mac_link_82598;
- if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
- mac->ops.setup_link = &ixgbe_setup_copper_link_82598;
- mac->ops.setup_link_speed =
- &ixgbe_setup_copper_link_speed_82598;
- mac->ops.get_link_capabilities =
- &ixgbe_get_copper_link_capabilities_82598;
- } else {
- mac->ops.setup_link = &ixgbe_setup_mac_link_82598;
- mac->ops.setup_link_speed = &ixgbe_setup_mac_link_speed_82598;
- mac->ops.get_link_capabilities =
- &ixgbe_get_link_capabilities_82598;
- }
+ mac->ops.fc_enable = &ixgbe_fc_enable_82598;
mac->mcft_size = 128;
mac->vft_size = 128;
mac->num_rar_entries = 16;
mac->max_tx_queues = 32;
mac->max_rx_queues = 64;
+ mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82598(hw);
/* SFP+ Module */
phy->ops.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_82598;
- /* Call PHY identify routine to get the phy type */
+ /* Link */
+ mac->ops.check_link = &ixgbe_check_mac_link_82598;
+ mac->ops.setup_link = &ixgbe_setup_mac_link_82598;
+ mac->ops.setup_link_speed = &ixgbe_setup_mac_link_speed_82598;
+ mac->ops.get_link_capabilities =
+ &ixgbe_get_link_capabilities_82598;
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_init_phy_ops_82598 - PHY/SFP specific init
+ * @hw: pointer to hardware structure
+ *
+ * Initialize any function pointers that were not able to be
+ * set during init_shared_code because the PHY/SFP type was
+ * not known. Perform the SFP init if necessary.
+ *
+ **/
+s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ struct ixgbe_phy_info *phy = &hw->phy;
+ s32 ret_val = IXGBE_SUCCESS;
+ u16 list_offset, data_offset;
+
+
+ /* Identify the PHY */
phy->ops.identify(hw);
- /* PHY Init */
+ /* Overwrite the link function pointers if copper PHY */
+ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
+ mac->ops.setup_link = &ixgbe_setup_copper_link_82598;
+ mac->ops.setup_link_speed =
+ &ixgbe_setup_copper_link_speed_82598;
+ mac->ops.get_link_capabilities =
+ &ixgbe_get_copper_link_capabilities_generic;
+ }
+
switch (hw->phy.type) {
case ixgbe_phy_tn:
phy->ops.check_link = &ixgbe_check_phy_link_tnx;
phy->ops.get_firmware_version =
&ixgbe_get_phy_firmware_version_tnx;
break;
+ case ixgbe_phy_aq:
+ phy->ops.get_firmware_version =
+ &ixgbe_get_phy_firmware_version_aq;
+ break;
case ixgbe_phy_nl:
phy->ops.reset = &ixgbe_reset_phy_nl;
@@ -198,18 +230,19 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
bool *autoneg)
{
s32 status = IXGBE_SUCCESS;
- s32 autoc_reg;
+ u32 autoc = 0;
- autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-
- if (hw->mac.link_settings_loaded) {
- autoc_reg &= ~IXGBE_AUTOC_LMS_ATTACH_TYPE;
- autoc_reg &= ~IXGBE_AUTOC_LMS_MASK;
- autoc_reg |= hw->mac.link_attach_type;
- autoc_reg |= hw->mac.link_mode_select;
- }
+ /*
+ * Determine link capabilities based on the stored value of AUTOC,
+ * which represents EEPROM defaults. If AUTOC value has not been
+ * stored, use the current register value.
+ */
+ if (hw->mac.orig_link_settings_stored)
+ autoc = hw->mac.orig_autoc;
+ else
+ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
- switch (autoc_reg & IXGBE_AUTOC_LMS_MASK) {
+ switch (autoc & IXGBE_AUTOC_LMS_MASK) {
case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
*speed = IXGBE_LINK_SPEED_1GB_FULL;
*autoneg = FALSE;
@@ -228,9 +261,9 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
case IXGBE_AUTOC_LMS_KX4_AN:
case IXGBE_AUTOC_LMS_KX4_AN_1G_AN:
*speed = IXGBE_LINK_SPEED_UNKNOWN;
- if (autoc_reg & IXGBE_AUTOC_KX4_SUPP)
+ if (autoc & IXGBE_AUTOC_KX4_SUPP)
*speed |= IXGBE_LINK_SPEED_10GB_FULL;
- if (autoc_reg & IXGBE_AUTOC_KX_SUPP)
+ if (autoc & IXGBE_AUTOC_KX_SUPP)
*speed |= IXGBE_LINK_SPEED_1GB_FULL;
*autoneg = TRUE;
break;
@@ -244,38 +277,6 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
}
/**
- * ixgbe_get_copper_link_capabilities_82598 - Determines link capabilities
- * @hw: pointer to hardware structure
- * @speed: pointer to link speed
- * @autoneg: boolean auto-negotiation value
- *
- * Determines the link capabilities by reading the AUTOC register.
- **/
-s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw,
- ixgbe_link_speed *speed,
- bool *autoneg)
-{
- s32 status = IXGBE_ERR_LINK_SETUP;
- u16 speed_ability;
-
- *speed = 0;
- *autoneg = TRUE;
-
- status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY,
- IXGBE_MDIO_PMA_PMD_DEV_TYPE,
- &speed_ability);
-
- if (status == IXGBE_SUCCESS) {
- if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G)
- *speed |= IXGBE_LINK_SPEED_10GB_FULL;
- if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G)
- *speed |= IXGBE_LINK_SPEED_1GB_FULL;
- }
-
- return status;
-}
-
-/**
* ixgbe_get_media_type_82598 - Determines media type
* @hw: pointer to hardware structure
*
@@ -285,9 +286,18 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
{
enum ixgbe_media_type media_type;
+ /* Detect if there is a copper PHY attached. */
+ if (hw->phy.type == ixgbe_phy_cu_unknown ||
+ hw->phy.type == ixgbe_phy_tn ||
+ hw->phy.type == ixgbe_phy_aq) {
+ media_type = ixgbe_media_type_copper;
+ goto out;
+ }
+
/* Media type for I82598 is based on device ID */
switch (hw->device_id) {
case IXGBE_DEV_ID_82598:
+ case IXGBE_DEV_ID_82598_BX:
/* Default device ID is mezzanine card KX/KX4 */
media_type = ixgbe_media_type_backplane;
break;
@@ -308,7 +318,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
media_type = ixgbe_media_type_unknown;
break;
}
-
+out:
return media_type;
}
@@ -328,6 +338,12 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
DEBUGFUNC("ixgbe_fc_enable_82598");
+ /* Negotiate the fc mode to use */
+ ret_val = ixgbe_fc_autoneg(hw);
+ if (ret_val)
+ goto out;
+
+ /* Disable any previous flow control settings */
fctrl_reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
fctrl_reg &= ~(IXGBE_FCTRL_RFCE | IXGBE_FCTRL_RPFCE);
@@ -339,14 +355,16 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
* 0: Flow control is completely disabled
* 1: Rx flow control is enabled (we can receive pause frames,
* but not send pause frames).
- * 2: Tx flow control is enabled (we can send pause frames but
+ * 2: Tx flow control is enabled (we can send pause frames but
* we do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled.
* other: Invalid.
*/
switch (hw->fc.current_mode) {
case ixgbe_fc_none:
- /* Flow control completely disabled by software override. */
+ /* Flow control is disabled by software override or autoneg.
+ * The code below will actually disable it in the HW.
+ */
break;
case ixgbe_fc_rx_pause:
/*
@@ -378,7 +396,8 @@ s32 ixgbe_fc_enable_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
break;
}
- /* Enable 802.3x based flow control settings. */
+ /* Set 802.3x based flow control settings. */
+ fctrl_reg |= IXGBE_FCTRL_DPF;
IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl_reg);
IXGBE_WRITE_REG(hw, IXGBE_RMCS, rmcs_reg);
@@ -411,73 +430,6 @@ out:
}
/**
- * ixgbe_setup_fc_82598 - Set up flow control
- * @hw: pointer to hardware structure
- *
- * Sets up flow control.
- **/
-s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
-{
- s32 ret_val = IXGBE_SUCCESS;
- ixgbe_link_speed speed;
- bool link_up;
-
- /* Validate the packetbuf configuration */
- if (packetbuf_num < 0 || packetbuf_num > 7) {
- DEBUGOUT1("Invalid packet buffer number [%d], expected range is"
- " 0-7\n", packetbuf_num);
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
- }
-
- /*
- * Validate the water mark configuration. Zero water marks are invalid
- * because it causes the controller to just blast out fc packets.
- */
- if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
- DEBUGOUT("Invalid water mark configuration\n");
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
- }
-
- /*
- * Validate the requested mode. Strict IEEE mode does not allow
- * ixgbe_fc_rx_pause because it will cause testing anomalies.
- */
- if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
- DEBUGOUT("ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
- ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
- goto out;
- }
-
- /*
- * 10gig parts do not have a word in the EEPROM to determine the
- * default flow control setting, so we explicitly set it to full.
- */
- if (hw->fc.requested_mode == ixgbe_fc_default)
- hw->fc.requested_mode = ixgbe_fc_full;
-
- /*
- * Save off the requested flow control mode for use later. Depending
- * on the link partner's capabilities, we may or may not use this mode.
- */
- hw->fc.current_mode = hw->fc.requested_mode;
-
- /* Decide whether to use autoneg or not. */
- hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
- if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL))
- ret_val = ixgbe_fc_autoneg(hw);
-
- if (ret_val)
- goto out;
-
- ret_val = ixgbe_fc_enable_82598(hw, packetbuf_num);
-
-out:
- return ret_val;
-}
-
-/**
* ixgbe_setup_mac_link_82598 - Configures MAC link settings
* @hw: pointer to hardware structure
*
@@ -491,27 +443,17 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw)
u32 i;
s32 status = IXGBE_SUCCESS;
- autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-
- if (hw->mac.link_settings_loaded) {
- autoc_reg &= ~IXGBE_AUTOC_LMS_ATTACH_TYPE;
- autoc_reg &= ~IXGBE_AUTOC_LMS_MASK;
- autoc_reg |= hw->mac.link_attach_type;
- autoc_reg |= hw->mac.link_mode_select;
-
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
- IXGBE_WRITE_FLUSH(hw);
- msec_delay(50);
- }
-
/* Restart link */
+ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
autoc_reg |= IXGBE_AUTOC_AN_RESTART;
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
/* Only poll for autoneg to complete if specified to do so */
if (hw->phy.autoneg_wait_to_complete) {
- if (hw->mac.link_mode_select == IXGBE_AUTOC_LMS_KX4_AN ||
- hw->mac.link_mode_select == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) {
+ if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
+ IXGBE_AUTOC_LMS_KX4_AN ||
+ (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
+ IXGBE_AUTOC_LMS_KX4_AN_1G_AN) {
links_reg = 0; /* Just in case Autoneg time = 0 */
for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
@@ -526,9 +468,6 @@ static s32 ixgbe_setup_mac_link_82598(struct ixgbe_hw *hw)
}
}
- /* Set up flow control */
- status = ixgbe_setup_fc_82598(hw, 0);
-
/* Add delay to filter out noises during initial link setup */
msec_delay(50);
@@ -616,6 +555,11 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
else
*speed = IXGBE_LINK_SPEED_1GB_FULL;
+ /* if link is down, zero out the current_mode */
+ if (*link_up == FALSE) {
+ hw->fc.current_mode = ixgbe_fc_none;
+ hw->fc.fc_was_autonegged = FALSE;
+ }
out:
return IXGBE_SUCCESS;
}
@@ -633,28 +577,34 @@ static s32 ixgbe_setup_mac_link_speed_82598(struct ixgbe_hw *hw,
ixgbe_link_speed speed, bool autoneg,
bool autoneg_wait_to_complete)
{
- s32 status = IXGBE_SUCCESS;
+ s32 status = IXGBE_SUCCESS;
+ ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
+ u32 curr_autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ u32 autoc = curr_autoc;
+ u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
- /* If speed is 10G, then check for CX4 or XAUI. */
- if ((speed == IXGBE_LINK_SPEED_10GB_FULL) &&
- (!(hw->mac.link_attach_type & IXGBE_AUTOC_10G_KX4))) {
- hw->mac.link_mode_select = IXGBE_AUTOC_LMS_10G_LINK_NO_AN;
- } else if ((speed == IXGBE_LINK_SPEED_1GB_FULL) && (!autoneg)) {
- hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_LINK_NO_AN;
- } else if (autoneg) {
- /* BX mode - Autonegotiate 1G */
- if (!(hw->mac.link_attach_type & IXGBE_AUTOC_1G_PMA_PMD))
- hw->mac.link_mode_select = IXGBE_AUTOC_LMS_1G_AN;
- else /* KX/KX4 mode */
- hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN_1G_AN;
- } else {
+ /* Check to see if speed passed in is supported. */
+ ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg);
+ speed &= link_capabilities;
+
+ if (speed == IXGBE_LINK_SPEED_UNKNOWN)
status = IXGBE_ERR_LINK_SETUP;
+
+ /* Set KX4/KX support according to speed requested */
+ else if (link_mode == IXGBE_AUTOC_LMS_KX4_AN ||
+ link_mode == IXGBE_AUTOC_LMS_KX4_AN_1G_AN) {
+ autoc &= ~IXGBE_AUTOC_KX4_KX_SUPP_MASK;
+ if (speed & IXGBE_LINK_SPEED_10GB_FULL)
+ autoc |= IXGBE_AUTOC_KX4_SUPP;
+ if (speed & IXGBE_LINK_SPEED_1GB_FULL)
+ autoc |= IXGBE_AUTOC_KX_SUPP;
+ if (autoc != curr_autoc)
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
}
if (status == IXGBE_SUCCESS) {
hw->phy.autoneg_wait_to_complete = autoneg_wait_to_complete;
- hw->mac.link_settings_loaded = TRUE;
/*
* Setup and restart the link based on the new values in
* ixgbe_hw This will write the AUTOC register based on the new
@@ -683,10 +633,6 @@ static s32 ixgbe_setup_copper_link_82598(struct ixgbe_hw *hw)
/* Restart autonegotiation on PHY */
status = hw->phy.ops.setup_link(hw);
- /* Set MAC to KX/KX4 autoneg, which defaults to Parallel detection */
- hw->mac.link_attach_type = (IXGBE_AUTOC_10G_KX4 | IXGBE_AUTOC_1G_KX);
- hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN;
-
/* Set up MAC */
ixgbe_setup_mac_link_82598(hw);
@@ -712,110 +658,12 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
/* Setup the PHY according to input speed */
status = hw->phy.ops.setup_link_speed(hw, speed, autoneg,
autoneg_wait_to_complete);
-
- /* Set MAC to KX/KX4 autoneg, which defaults to Parallel detection */
- hw->mac.link_attach_type = (IXGBE_AUTOC_10G_KX4 | IXGBE_AUTOC_1G_KX);
- hw->mac.link_mode_select = IXGBE_AUTOC_LMS_KX4_AN;
-
/* Set up MAC */
ixgbe_setup_mac_link_82598(hw);
return status;
}
-#ifndef NO_82598_A0_SUPPORT
-/**
- * ixgbe_reset_hw_rev_0_82598 - Performs hardware reset
- * @hw: pointer to hardware structure
- *
- * Resets the hardware by resetting the transmit and receive units, masks and
- * clears all interrupts, performing a PHY reset, and performing a link (MAC)
- * reset.
- **/
-s32 ixgbe_reset_hw_rev_0_82598(struct ixgbe_hw *hw)
-{
- s32 status = IXGBE_SUCCESS;
- u32 ctrl;
- u32 gheccr;
- u32 autoc;
- u32 i;
- u32 resets;
-
- /* Call adapter stop to disable tx/rx and clear interrupts */
- hw->mac.ops.stop_adapter(hw);
-
- /* Reset PHY */
- hw->phy.ops.reset(hw);
-
- for (resets = 0; resets < 10; resets++) {
- /*
- * Prevent the PCI-E bus from from hanging by disabling PCI-E
- * master access and verify no pending requests before reset
- */
- if (ixgbe_disable_pcie_master(hw) != IXGBE_SUCCESS) {
- status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
- DEBUGOUT("PCI-E Master disable polling has failed.\n");
- }
-
- /*
- * Issue global reset to the MAC. This needs to be a SW reset.
- * If link reset is used, it might reset the MAC when mng is
- * using it.
- */
- ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
- IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST));
- IXGBE_WRITE_FLUSH(hw);
-
- /*
- * Poll for reset bit to self-clear indicating reset is
- * complete
- */
- for (i = 0; i < 10; i++) {
- usec_delay(1);
- ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
- if (!(ctrl & IXGBE_CTRL_RST))
- break;
- }
- if (ctrl & IXGBE_CTRL_RST) {
- status = IXGBE_ERR_RESET_FAILED;
- DEBUGOUT("Reset polling failed to complete.\n");
- }
- }
-
- msec_delay(50);
-
- gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR);
- gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6));
- IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr);
-
- /*
- * AUTOC register which stores link settings gets cleared
- * and reloaded from EEPROM after reset. We need to restore
- * our stored value from init in case SW changed the attach
- * type or speed. If this is the first time and link settings
- * have not been stored, store default settings from AUTOC.
- */
- autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
- if (hw->mac.link_settings_loaded) {
- autoc &= ~(IXGBE_AUTOC_LMS_ATTACH_TYPE);
- autoc &= ~(IXGBE_AUTOC_LMS_MASK);
- autoc |= hw->mac.link_attach_type;
- autoc |= hw->mac.link_mode_select;
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
- } else {
- hw->mac.link_attach_type =
- (autoc & IXGBE_AUTOC_LMS_ATTACH_TYPE);
- hw->mac.link_mode_select = (autoc & IXGBE_AUTOC_LMS_MASK);
- hw->mac.link_settings_loaded = TRUE;
- }
-
- /* Store the permanent mac address */
- hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
-
- return status;
-}
-
-#endif /* NO_A0_SUPPORT */
/**
* ixgbe_reset_hw_82598 - Performs hardware reset
* @hw: pointer to hardware structure
@@ -870,14 +718,23 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
}
/* Reset PHY */
- if (hw->phy.reset_disable == FALSE)
+ if (hw->phy.reset_disable == FALSE) {
+ /* PHY ops must be identified and initialized prior to reset */
+
+ /* Init PHY and function pointers, perform SFP setup */
+ status = hw->phy.ops.init(hw);
+ if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ goto reset_hw_out;
+
hw->phy.ops.reset(hw);
+ }
/*
* Prevent the PCI-E bus from from hanging by disabling PCI-E master
* access and verify no pending requests before reset
*/
- if (ixgbe_disable_pcie_master(hw) != IXGBE_SUCCESS) {
+ status = ixgbe_disable_pcie_master(hw);
+ if (status != IXGBE_SUCCESS) {
status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
DEBUGOUT("PCI-E Master disable polling has failed.\n");
}
@@ -909,29 +766,27 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr);
/*
- * AUTOC register which stores link settings gets cleared
- * and reloaded from EEPROM after reset. We need to restore
- * our stored value from init in case SW changed the attach
- * type or speed. If this is the first time and link settings
- * have not been stored, store default settings from AUTOC.
+ * Store the original AUTOC value if it has not been
+ * stored off yet. Otherwise restore the stored original
+ * AUTOC value since the reset operation sets back to deaults.
*/
autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
- if (hw->mac.link_settings_loaded) {
- autoc &= ~(IXGBE_AUTOC_LMS_ATTACH_TYPE);
- autoc &= ~(IXGBE_AUTOC_LMS_MASK);
- autoc |= hw->mac.link_attach_type;
- autoc |= hw->mac.link_mode_select;
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
- } else {
- hw->mac.link_attach_type =
- (autoc & IXGBE_AUTOC_LMS_ATTACH_TYPE);
- hw->mac.link_mode_select = (autoc & IXGBE_AUTOC_LMS_MASK);
- hw->mac.link_settings_loaded = TRUE;
- }
+ if (hw->mac.orig_link_settings_stored == FALSE) {
+ hw->mac.orig_autoc = autoc;
+ hw->mac.orig_link_settings_stored = TRUE;
+ } else if (autoc != hw->mac.orig_autoc)
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
+
+ /*
+ * Store MAC address from RAR0, clear receive address registers, and
+ * clear the multicast table
+ */
+ hw->mac.ops.init_rx_addrs(hw);
/* Store the permanent mac address */
hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
+reset_hw_out:
return status;
}
@@ -1049,61 +904,6 @@ static s32 ixgbe_clear_vfta_82598(struct ixgbe_hw *hw)
}
/**
- * ixgbe_blink_led_start_82598 - Blink LED based on index.
- * @hw: pointer to hardware structure
- * @index: led number to blink
- **/
-static s32 ixgbe_blink_led_start_82598(struct ixgbe_hw *hw, u32 index)
-{
- ixgbe_link_speed speed = 0;
- bool link_up = 0;
- u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
- u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
-
- /*
- * Link must be up to auto-blink the LEDs on the 82598EB MAC;
- * force it if link is down.
- */
- hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
-
- if (!link_up) {
- autoc_reg |= IXGBE_AUTOC_FLU;
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
- msec_delay(10);
- }
-
- led_reg &= ~IXGBE_LED_MODE_MASK(index);
- led_reg |= IXGBE_LED_BLINK(index);
- IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
- IXGBE_WRITE_FLUSH(hw);
-
- return IXGBE_SUCCESS;
-}
-
-/**
- * ixgbe_blink_led_stop_82598 - Stop blinking LED based on index.
- * @hw: pointer to hardware structure
- * @index: led number to stop blinking
- **/
-static s32 ixgbe_blink_led_stop_82598(struct ixgbe_hw *hw, u32 index)
-{
- u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
- u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
-
- autoc_reg &= ~IXGBE_AUTOC_FLU;
- autoc_reg |= IXGBE_AUTOC_AN_RESTART;
- IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
-
- led_reg &= ~IXGBE_LED_MODE_MASK(index);
- led_reg &= ~IXGBE_LED_BLINK(index);
- led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
- IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
- IXGBE_WRITE_FLUSH(hw);
-
- return IXGBE_SUCCESS;
-}
-
-/**
* ixgbe_read_analog_reg8_82598 - Reads 8 bit Atlas analog register
* @hw: pointer to hardware structure
* @reg: analog register to read
@@ -1216,33 +1016,56 @@ out:
u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
{
u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+ u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ u32 pma_pmd_10g = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
+ u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
+ u16 ext_ability = 0;
+
+ hw->phy.ops.identify(hw);
+
+ /* Copper PHY must be checked before AUTOC LMS to determine correct
+ * physical layer because 10GBase-T PHYs use LMS = KX4/KX */
+ if (hw->phy.type == ixgbe_phy_tn ||
+ hw->phy.type == ixgbe_phy_cu_unknown) {
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
+ if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
+ if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
+ if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
+ goto out;
+ }
- switch (hw->device_id) {
- case IXGBE_DEV_ID_82598:
- /* Default device ID is mezzanine card KX/KX4 */
- physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_KX4 |
- IXGBE_PHYSICAL_LAYER_1000BASE_KX);
- break;
- case IXGBE_DEV_ID_82598EB_CX4:
- case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
- break;
- case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
- physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
+ switch (autoc & IXGBE_AUTOC_LMS_MASK) {
+ case IXGBE_AUTOC_LMS_1G_AN:
+ case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
+ if (pma_pmd_1g == IXGBE_AUTOC_1G_KX)
+ physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX;
+ else
+ physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_BX;
break;
- case IXGBE_DEV_ID_82598AF_DUAL_PORT:
- case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
- case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
+ case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
+ if (pma_pmd_10g == IXGBE_AUTOC_10G_CX4)
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
+ else if (pma_pmd_10g == IXGBE_AUTOC_10G_KX4)
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
+ else /* XAUI */
+ physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
break;
- case IXGBE_DEV_ID_82598EB_XF_LR:
- physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
+ case IXGBE_AUTOC_LMS_KX4_AN:
+ case IXGBE_AUTOC_LMS_KX4_AN_1G_AN:
+ if (autoc & IXGBE_AUTOC_KX_SUPP)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
+ if (autoc & IXGBE_AUTOC_KX4_SUPP)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
break;
- case IXGBE_DEV_ID_82598AT:
- physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T |
- IXGBE_PHYSICAL_LAYER_1000BASE_T);
+ default:
break;
- case IXGBE_DEV_ID_82598EB_SFP_LOM:
+ }
+
+ if (hw->phy.type == ixgbe_phy_nl) {
hw->phy.ops.identify_sfp(hw);
switch (hw->phy.sfp_type) {
@@ -1259,12 +1082,24 @@ u32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
break;
}
- break;
+ }
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
+ physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
+ break;
+ case IXGBE_DEV_ID_82598AF_DUAL_PORT:
+ case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
+ case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
+ break;
+ case IXGBE_DEV_ID_82598EB_XF_LR:
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
+ break;
default:
- physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
break;
}
+out:
return physical_layer;
}
diff --git a/sys/dev/ixgbe/ixgbe_82599.c b/sys/dev/ixgbe/ixgbe_82599.c
new file mode 100644
index 0000000..4f438a2
--- /dev/null
+++ b/sys/dev/ixgbe/ixgbe_82599.c
@@ -0,0 +1,2444 @@
+/******************************************************************************
+
+ Copyright (c) 2001-2009, Intel Corporation
+ 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 Intel Corporation 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 OWNER 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 "ixgbe_type.h"
+#include "ixgbe_api.h"
+#include "ixgbe_common.h"
+#include "ixgbe_phy.h"
+
+u32 ixgbe_get_pcie_msix_count_82599(struct ixgbe_hw *hw);
+s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw);
+s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *autoneg);
+enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw);
+s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw);
+s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed, bool autoneg,
+ bool autoneg_wait_to_complete);
+s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw);
+s32 ixgbe_check_mac_link_82599(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *link_up, bool link_up_wait_to_complete);
+s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg,
+ bool autoneg_wait_to_complete);
+static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw);
+static s32 ixgbe_setup_copper_link_speed_82599(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg,
+ bool autoneg_wait_to_complete);
+s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw);
+void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw);
+s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw);
+s32 ixgbe_set_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
+s32 ixgbe_clear_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq);
+s32 ixgbe_insert_mac_addr_82599(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
+s32 ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan,
+ u32 vind, bool vlan_on);
+s32 ixgbe_clear_vfta_82599(struct ixgbe_hw *hw);
+s32 ixgbe_init_uta_tables_82599(struct ixgbe_hw *hw);
+s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val);
+s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val);
+s32 ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw);
+s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw);
+s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw);
+u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw);
+s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval);
+s32 ixgbe_get_san_mac_addr_offset_82599(struct ixgbe_hw *hw,
+ u16 *san_mac_offset);
+s32 ixgbe_get_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr);
+s32 ixgbe_set_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr);
+s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps);
+
+void ixgbe_init_mac_link_ops_82599(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+
+ DEBUGFUNC("ixgbe_init_mac_link_ops_82599");
+
+ if (hw->phy.multispeed_fiber) {
+ /* Set up dual speed SFP+ support */
+ mac->ops.setup_link =
+ &ixgbe_setup_mac_link_multispeed_fiber;
+ mac->ops.setup_link_speed =
+ &ixgbe_setup_mac_link_speed_multispeed_fiber;
+ } else {
+ mac->ops.setup_link =
+ &ixgbe_setup_mac_link_82599;
+ mac->ops.setup_link_speed =
+ &ixgbe_setup_mac_link_speed_82599;
+ }
+}
+
+/**
+ * ixgbe_init_phy_ops_82599 - PHY/SFP specific init
+ * @hw: pointer to hardware structure
+ *
+ * Initialize any function pointers that were not able to be
+ * set during init_shared_code because the PHY/SFP type was
+ * not known. Perform the SFP init if necessary.
+ *
+ **/
+s32 ixgbe_init_phy_ops_82599(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ struct ixgbe_phy_info *phy = &hw->phy;
+ s32 ret_val = IXGBE_SUCCESS;
+
+ DEBUGFUNC("ixgbe_init_phy_ops_82599");
+
+ /* Identify the PHY or SFP module */
+ ret_val = phy->ops.identify(hw);
+ if (ret_val == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ goto init_phy_ops_out;
+
+ /* Setup function pointers based on detected SFP module and speeds */
+ ixgbe_init_mac_link_ops_82599(hw);
+ if (hw->phy.sfp_type != ixgbe_sfp_type_unknown)
+ hw->phy.ops.reset = NULL;
+
+ /* If copper media, overwrite with copper function pointers */
+ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper) {
+ mac->ops.setup_link = &ixgbe_setup_copper_link_82599;
+ mac->ops.setup_link_speed =
+ &ixgbe_setup_copper_link_speed_82599;
+ mac->ops.get_link_capabilities =
+ &ixgbe_get_copper_link_capabilities_generic;
+ }
+
+ /* Set necessary function pointers based on phy type */
+ switch (hw->phy.type) {
+ case ixgbe_phy_tn:
+ phy->ops.check_link = &ixgbe_check_phy_link_tnx;
+ phy->ops.get_firmware_version =
+ &ixgbe_get_phy_firmware_version_tnx;
+ break;
+ case ixgbe_phy_aq:
+ phy->ops.get_firmware_version =
+ &ixgbe_get_phy_firmware_version_aq;
+ break;
+ default:
+ break;
+ }
+init_phy_ops_out:
+ return ret_val;
+}
+
+s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
+{
+ s32 ret_val = IXGBE_SUCCESS;
+ u16 list_offset, data_offset, data_value;
+
+ DEBUGFUNC("ixgbe_setup_sfp_modules_82599");
+
+ if (hw->phy.sfp_type != ixgbe_sfp_type_unknown) {
+ ixgbe_init_mac_link_ops_82599(hw);
+
+ hw->phy.ops.reset = NULL;
+
+ ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
+ &data_offset);
+ if (ret_val != IXGBE_SUCCESS)
+ goto setup_sfp_out;
+
+ hw->eeprom.ops.read(hw, ++data_offset, &data_value);
+ while (data_value != 0xffff) {
+ IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value);
+ IXGBE_WRITE_FLUSH(hw);
+ hw->eeprom.ops.read(hw, ++data_offset, &data_value);
+ }
+ /* Now restart DSP */
+ IXGBE_WRITE_REG(hw, IXGBE_CORECTL, 0x00000102);
+ IXGBE_WRITE_REG(hw, IXGBE_CORECTL, 0x00000b1d);
+ IXGBE_WRITE_FLUSH(hw);
+ }
+
+setup_sfp_out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_get_pcie_msix_count_82599 - Gets MSI-X vector count
+ * @hw: pointer to hardware structure
+ *
+ * Read PCIe configuration space, and get the MSI-X vector count from
+ * the capabilities table.
+ **/
+u32 ixgbe_get_pcie_msix_count_82599(struct ixgbe_hw *hw)
+{
+ u32 msix_count = 64;
+
+ if (hw->mac.msix_vectors_from_pcie) {
+ msix_count = IXGBE_READ_PCIE_WORD(hw,
+ IXGBE_PCIE_MSIX_82599_CAPS);
+ msix_count &= IXGBE_PCIE_MSIX_TBL_SZ_MASK;
+
+ /* MSI-X count is zero-based in HW, so increment to give
+ * proper value */
+ msix_count++;
+ }
+
+ return msix_count;
+}
+
+/**
+ * ixgbe_init_ops_82599 - Inits func ptrs and MAC type
+ * @hw: pointer to hardware structure
+ *
+ * Initialize the function pointers and assign the MAC type for 82599.
+ * Does not touch the hardware.
+ **/
+
+s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ struct ixgbe_phy_info *phy = &hw->phy;
+ s32 ret_val;
+
+ ret_val = ixgbe_init_phy_ops_generic(hw);
+ ret_val = ixgbe_init_ops_generic(hw);
+
+ /* PHY */
+ phy->ops.identify = &ixgbe_identify_phy_82599;
+ phy->ops.init = &ixgbe_init_phy_ops_82599;
+
+ /* MAC */
+ mac->ops.reset_hw = &ixgbe_reset_hw_82599;
+ mac->ops.get_media_type = &ixgbe_get_media_type_82599;
+ mac->ops.get_supported_physical_layer =
+ &ixgbe_get_supported_physical_layer_82599;
+ mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_82599;
+ mac->ops.read_analog_reg8 = &ixgbe_read_analog_reg8_82599;
+ mac->ops.write_analog_reg8 = &ixgbe_write_analog_reg8_82599;
+ mac->ops.start_hw = &ixgbe_start_hw_rev_1_82599;
+ mac->ops.get_san_mac_addr = &ixgbe_get_san_mac_addr_82599;
+ mac->ops.set_san_mac_addr = &ixgbe_set_san_mac_addr_82599;
+ mac->ops.get_device_caps = &ixgbe_get_device_caps_82599;
+
+ /* RAR, Multicast, VLAN */
+ mac->ops.set_vmdq = &ixgbe_set_vmdq_82599;
+ mac->ops.clear_vmdq = &ixgbe_clear_vmdq_82599;
+ mac->ops.insert_mac_addr = &ixgbe_insert_mac_addr_82599;
+ mac->rar_highwater = 1;
+ mac->ops.set_vfta = &ixgbe_set_vfta_82599;
+ mac->ops.clear_vfta = &ixgbe_clear_vfta_82599;
+ mac->ops.init_uta_tables = &ixgbe_init_uta_tables_82599;
+ mac->ops.setup_sfp = &ixgbe_setup_sfp_modules_82599;
+
+ /* Link */
+ mac->ops.get_link_capabilities = &ixgbe_get_link_capabilities_82599;
+ mac->ops.check_link = &ixgbe_check_mac_link_82599;
+ ixgbe_init_mac_link_ops_82599(hw);
+
+ mac->mcft_size = 128;
+ mac->vft_size = 128;
+ mac->num_rar_entries = 128;
+ mac->max_tx_queues = 128;
+ mac->max_rx_queues = 128;
+ mac->max_msix_vectors = ixgbe_get_pcie_msix_count_82599(hw);
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_get_link_capabilities_82599 - Determines link capabilities
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @negotiation: TRUE when autoneg or autotry is enabled
+ *
+ * Determines the link capabilities by reading the AUTOC register.
+ **/
+s32 ixgbe_get_link_capabilities_82599(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *negotiation)
+{
+ s32 status = IXGBE_SUCCESS;
+ u32 autoc = 0;
+
+ /*
+ * Determine link capabilities based on the stored value of AUTOC,
+ * which represents EEPROM defaults. If AUTOC value has not
+ * been stored, use the current register values.
+ */
+ if (hw->mac.orig_link_settings_stored)
+ autoc = hw->mac.orig_autoc;
+ else
+ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+
+ switch (autoc & IXGBE_AUTOC_LMS_MASK) {
+ case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
+ *speed = IXGBE_LINK_SPEED_1GB_FULL;
+ *negotiation = FALSE;
+ break;
+
+ case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
+ *speed = IXGBE_LINK_SPEED_10GB_FULL;
+ *negotiation = FALSE;
+ break;
+
+ case IXGBE_AUTOC_LMS_1G_AN:
+ *speed = IXGBE_LINK_SPEED_1GB_FULL;
+ *negotiation = TRUE;
+ break;
+
+ case IXGBE_AUTOC_LMS_10G_SERIAL:
+ *speed = IXGBE_LINK_SPEED_10GB_FULL;
+ *negotiation = FALSE;
+ break;
+
+ case IXGBE_AUTOC_LMS_KX4_KX_KR:
+ case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
+ *speed = IXGBE_LINK_SPEED_UNKNOWN;
+ if (autoc & IXGBE_AUTOC_KR_SUPP)
+ *speed |= IXGBE_LINK_SPEED_10GB_FULL;
+ if (autoc & IXGBE_AUTOC_KX4_SUPP)
+ *speed |= IXGBE_LINK_SPEED_10GB_FULL;
+ if (autoc & IXGBE_AUTOC_KX_SUPP)
+ *speed |= IXGBE_LINK_SPEED_1GB_FULL;
+ *negotiation = TRUE;
+ break;
+
+ case IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII:
+ *speed = IXGBE_LINK_SPEED_100_FULL;
+ if (autoc & IXGBE_AUTOC_KR_SUPP)
+ *speed |= IXGBE_LINK_SPEED_10GB_FULL;
+ if (autoc & IXGBE_AUTOC_KX4_SUPP)
+ *speed |= IXGBE_LINK_SPEED_10GB_FULL;
+ if (autoc & IXGBE_AUTOC_KX_SUPP)
+ *speed |= IXGBE_LINK_SPEED_1GB_FULL;
+ *negotiation = TRUE;
+ break;
+
+ case IXGBE_AUTOC_LMS_SGMII_1G_100M:
+ *speed = IXGBE_LINK_SPEED_1GB_FULL | IXGBE_LINK_SPEED_100_FULL;
+ *negotiation = FALSE;
+ break;
+
+ default:
+ status = IXGBE_ERR_LINK_SETUP;
+ goto out;
+ break;
+ }
+
+ if (hw->phy.multispeed_fiber) {
+ *speed |= IXGBE_LINK_SPEED_10GB_FULL |
+ IXGBE_LINK_SPEED_1GB_FULL;
+ *negotiation = TRUE;
+ }
+
+out:
+ return status;
+}
+
+/**
+ * ixgbe_get_media_type_82599 - Get media type
+ * @hw: pointer to hardware structure
+ *
+ * Returns the media type (fiber, copper, backplane)
+ **/
+enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw)
+{
+ enum ixgbe_media_type media_type;
+
+ /* Detect if there is a copper PHY attached. */
+ if (hw->phy.type == ixgbe_phy_cu_unknown ||
+ hw->phy.type == ixgbe_phy_tn ||
+ hw->phy.type == ixgbe_phy_aq) {
+ media_type = ixgbe_media_type_copper;
+ goto out;
+ }
+
+ switch (hw->device_id) {
+ case IXGBE_DEV_ID_82599_KX4:
+ /* Default device ID is mezzanine card KX/KX4 */
+ media_type = ixgbe_media_type_backplane;
+ break;
+ case IXGBE_DEV_ID_82599_SFP:
+ media_type = ixgbe_media_type_fiber;
+ break;
+ case IXGBE_DEV_ID_82599_CX4:
+ media_type = ixgbe_media_type_fiber;
+ break;
+ default:
+ media_type = ixgbe_media_type_unknown;
+ break;
+ }
+out:
+ return media_type;
+}
+
+/**
+ * ixgbe_setup_mac_link_82599 - Setup MAC link settings
+ * @hw: pointer to hardware structure
+ *
+ * Configures link settings based on values in the ixgbe_hw struct.
+ * Restarts the link. Performs autonegotiation if needed.
+ **/
+s32 ixgbe_setup_mac_link_82599(struct ixgbe_hw *hw)
+{
+ u32 autoc_reg;
+ u32 links_reg;
+ u32 i;
+ s32 status = IXGBE_SUCCESS;
+
+ /* Restart link */
+ autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ autoc_reg |= IXGBE_AUTOC_AN_RESTART;
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+
+ /* Only poll for autoneg to complete if specified to do so */
+ if (hw->phy.autoneg_wait_to_complete) {
+ if ((autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
+ IXGBE_AUTOC_LMS_KX4_KX_KR ||
+ (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
+ IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN
+ || (autoc_reg & IXGBE_AUTOC_LMS_MASK) ==
+ IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
+ links_reg = 0; /* Just in case Autoneg time = 0 */
+ for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
+ links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
+ if (links_reg & IXGBE_LINKS_KX_AN_COMP)
+ break;
+ msec_delay(100);
+ }
+ if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
+ status = IXGBE_ERR_AUTONEG_NOT_COMPLETE;
+ DEBUGOUT("Autoneg did not complete.\n");
+ }
+ }
+ }
+
+ /* Add delay to filter out noises during initial link setup */
+ msec_delay(50);
+
+ return status;
+}
+
+/**
+ * ixgbe_setup_mac_link_multispeed_fiber - Setup MAC link settings
+ * @hw: pointer to hardware structure
+ *
+ * Configures link settings based on values in the ixgbe_hw struct.
+ * Restarts the link for multi-speed fiber at 1G speed, if link
+ * fails at 10G.
+ * Performs autonegotiation if needed.
+ **/
+s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw)
+{
+ s32 status = IXGBE_SUCCESS;
+ ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_82599_AUTONEG;
+ DEBUGFUNC("ixgbe_setup_mac_link_multispeed_fiber");
+
+ status = ixgbe_setup_mac_link_speed_multispeed_fiber(hw,
+ link_speed, TRUE, true);
+ return status;
+}
+
+/**
+ * ixgbe_setup_mac_link_speed_multispeed_fiber - Set MAC link speed
+ * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg: TRUE if autonegotiation enabled
+ * @autoneg_wait_to_complete: TRUE when waiting for completion is needed
+ *
+ * Set the link speed in the AUTOC register and restarts link.
+ **/
+s32 ixgbe_setup_mac_link_speed_multispeed_fiber(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed, bool autoneg,
+ bool autoneg_wait_to_complete)
+{
+ s32 status = IXGBE_SUCCESS;
+ ixgbe_link_speed link_speed;
+ ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
+ u32 speedcnt = 0;
+ u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+ bool link_up = FALSE;
+ bool negotiation;
+
+ /* Mask off requested but non-supported speeds */
+ status = ixgbe_get_link_capabilities(hw, &link_speed, &negotiation);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ speed &= link_speed;
+
+ /*
+ * Try each speed one by one, highest priority first. We do this in
+ * software because 10gb fiber doesn't support speed autonegotiation.
+ */
+ if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
+ speedcnt++;
+ highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
+
+ /* If we already have link at this speed, just jump out */
+ status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
+ goto out;
+
+ /* Set hardware SDP's */
+ esdp_reg |= (IXGBE_ESDP_SDP5_DIR | IXGBE_ESDP_SDP5);
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+
+ /* Allow module to change analog characteristics (1G->10G) */
+ msec_delay(40);
+
+ status = ixgbe_setup_mac_link_speed_82599(
+ hw, IXGBE_LINK_SPEED_10GB_FULL, autoneg,
+ autoneg_wait_to_complete);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ msec_delay(100);
+
+ /* If we have link, just jump out */
+ status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ if (link_up)
+ goto out;
+ }
+
+ if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
+ speedcnt++;
+ if (highest_link_speed == IXGBE_LINK_SPEED_UNKNOWN)
+ highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
+
+ /* If we already have link at this speed, just jump out */
+ status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
+ goto out;
+
+ /* Set hardware SDP's */
+ esdp_reg &= ~IXGBE_ESDP_SDP5;
+ esdp_reg |= IXGBE_ESDP_SDP5_DIR;
+ IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp_reg);
+
+ /* Allow module to change analog characteristics (10G->1G) */
+ msec_delay(40);
+
+ status = ixgbe_setup_mac_link_speed_82599(
+ hw, IXGBE_LINK_SPEED_1GB_FULL, autoneg,
+ autoneg_wait_to_complete);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ msec_delay(100);
+
+ /* If we have link, just jump out */
+ status = ixgbe_check_link(hw, &link_speed, &link_up, FALSE);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ if (link_up)
+ goto out;
+ }
+
+ /*
+ * We didn't get link. Configure back to the highest speed we tried,
+ * (if there was more than one). We call ourselves back with just the
+ * single highest speed that the user requested.
+ */
+ if (speedcnt > 1)
+ status = ixgbe_setup_mac_link_speed_multispeed_fiber(hw,
+ highest_link_speed, autoneg, autoneg_wait_to_complete);
+
+out:
+ return status;
+}
+
+/**
+ * ixgbe_check_mac_link_82599 - Determine link and speed status
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @link_up: TRUE when link is up
+ * @link_up_wait_to_complete: bool used to wait for link up or not
+ *
+ * Reads the links register to determine if link is up and the current speed
+ **/
+s32 ixgbe_check_mac_link_82599(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
+ bool *link_up, bool link_up_wait_to_complete)
+{
+ u32 links_reg;
+ u32 i;
+
+ links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
+ if (link_up_wait_to_complete) {
+ for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
+ if (links_reg & IXGBE_LINKS_UP) {
+ *link_up = TRUE;
+ break;
+ } else {
+ *link_up = FALSE;
+ }
+ msec_delay(100);
+ links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
+ }
+ } else {
+ if (links_reg & IXGBE_LINKS_UP)
+ *link_up = TRUE;
+ else
+ *link_up = FALSE;
+ }
+
+ if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
+ IXGBE_LINKS_SPEED_10G_82599)
+ *speed = IXGBE_LINK_SPEED_10GB_FULL;
+ else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
+ IXGBE_LINKS_SPEED_1G_82599)
+ *speed = IXGBE_LINK_SPEED_1GB_FULL;
+ else
+ *speed = IXGBE_LINK_SPEED_100_FULL;
+
+ /* if link is down, zero out the current_mode */
+ if (*link_up == FALSE) {
+ hw->fc.current_mode = ixgbe_fc_none;
+ hw->fc.fc_was_autonegged = FALSE;
+ }
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_setup_mac_link_speed_82599 - Set MAC link speed
+ * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg: TRUE if autonegotiation enabled
+ * @autoneg_wait_to_complete: TRUE when waiting for completion is needed
+ *
+ * Set the link speed in the AUTOC register and restarts link.
+ **/
+s32 ixgbe_setup_mac_link_speed_82599(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed, bool autoneg,
+ bool autoneg_wait_to_complete)
+{
+ s32 status = IXGBE_SUCCESS;
+ u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
+ u32 orig_autoc = 0;
+ u32 link_mode = autoc & IXGBE_AUTOC_LMS_MASK;
+ u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
+ u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
+ u32 links_reg;
+ u32 i;
+ ixgbe_link_speed link_capabilities = IXGBE_LINK_SPEED_UNKNOWN;
+
+ /* Check to see if speed passed in is supported. */
+ status = ixgbe_get_link_capabilities(hw, &link_capabilities, &autoneg);
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ speed &= link_capabilities;
+
+ /* Use stored value (EEPROM defaults) of AUTOC to find KR/KX4 support*/
+ if (hw->mac.orig_link_settings_stored)
+ orig_autoc = hw->mac.orig_autoc;
+ else
+ orig_autoc = autoc;
+
+
+ if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
+ status = IXGBE_ERR_LINK_SETUP;
+ } else if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
+ link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
+ link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
+ /* Set KX4/KX/KR support according to speed requested */
+ autoc &= ~(IXGBE_AUTOC_KX4_KX_SUPP_MASK | IXGBE_AUTOC_KR_SUPP);
+ if (speed & IXGBE_LINK_SPEED_10GB_FULL)
+ if (orig_autoc & IXGBE_AUTOC_KX4_SUPP)
+ autoc |= IXGBE_AUTOC_KX4_SUPP;
+ if (orig_autoc & IXGBE_AUTOC_KR_SUPP)
+ autoc |= IXGBE_AUTOC_KR_SUPP;
+ if (speed & IXGBE_LINK_SPEED_1GB_FULL)
+ autoc |= IXGBE_AUTOC_KX_SUPP;
+ } else if ((pma_pmd_1g == IXGBE_AUTOC_1G_SFI) &&
+ (link_mode == IXGBE_AUTOC_LMS_1G_LINK_NO_AN ||
+ link_mode == IXGBE_AUTOC_LMS_1G_AN)) {
+ /* Switch from 1G SFI to 10G SFI if requested */
+ if ((speed == IXGBE_LINK_SPEED_10GB_FULL) &&
+ (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)) {
+ autoc &= ~IXGBE_AUTOC_LMS_MASK;
+ autoc |= IXGBE_AUTOC_LMS_10G_SERIAL;
+ }
+ } else if ((pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI) &&
+ (link_mode == IXGBE_AUTOC_LMS_10G_SERIAL)) {
+ /* Switch from 10G SFI to 1G SFI if requested */
+ if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
+ (pma_pmd_1g == IXGBE_AUTOC_1G_SFI)) {
+ autoc &= ~IXGBE_AUTOC_LMS_MASK;
+ if (autoneg)
+ autoc |= IXGBE_AUTOC_LMS_1G_AN;
+ else
+ autoc |= IXGBE_AUTOC_LMS_1G_LINK_NO_AN;
+ }
+ }
+
+ if (status == IXGBE_SUCCESS) {
+ /* Restart link */
+ autoc |= IXGBE_AUTOC_AN_RESTART;
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc);
+
+ /* Only poll for autoneg to complete if specified to do so */
+ if (autoneg_wait_to_complete) {
+ if (link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR ||
+ link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN ||
+ link_mode == IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII) {
+ links_reg = 0; /*Just in case Autoneg time=0*/
+ for (i = 0; i < IXGBE_AUTO_NEG_TIME; i++) {
+ links_reg =
+ IXGBE_READ_REG(hw, IXGBE_LINKS);
+ if (links_reg & IXGBE_LINKS_KX_AN_COMP)
+ break;
+ msec_delay(100);
+ }
+ if (!(links_reg & IXGBE_LINKS_KX_AN_COMP)) {
+ status =
+ IXGBE_ERR_AUTONEG_NOT_COMPLETE;
+ DEBUGOUT("Autoneg did not complete.\n");
+ }
+ }
+ }
+
+ /* Add delay to filter out noises during initial link setup */
+ msec_delay(50);
+ }
+
+out:
+ return status;
+}
+
+/**
+ * ixgbe_setup_copper_link_82599 - Setup copper link settings
+ * @hw: pointer to hardware structure
+ *
+ * Restarts the link on PHY and then MAC. Performs autonegotiation if needed.
+ **/
+static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw)
+{
+ s32 status;
+
+ /* Restart autonegotiation on PHY */
+ status = hw->phy.ops.setup_link(hw);
+
+ /* Set up MAC */
+ ixgbe_setup_mac_link_82599(hw);
+
+ return status;
+}
+
+/**
+ * ixgbe_setup_copper_link_speed_82599 - Set the PHY autoneg advertised field
+ * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg: TRUE if autonegotiation enabled
+ * @autoneg_wait_to_complete: TRUE if waiting is needed to complete
+ *
+ * Restarts link on PHY and MAC based on settings passed in.
+ **/
+static s32 ixgbe_setup_copper_link_speed_82599(struct ixgbe_hw *hw,
+ ixgbe_link_speed speed,
+ bool autoneg,
+ bool autoneg_wait_to_complete)
+{
+ s32 status;
+
+ /* Setup the PHY according to input speed */
+ status = hw->phy.ops.setup_link_speed(hw, speed, autoneg,
+ autoneg_wait_to_complete);
+ /* Set up MAC */
+ ixgbe_setup_mac_link_82599(hw);
+
+ return status;
+}
+/**
+ * ixgbe_reset_hw_82599 - Perform hardware reset
+ * @hw: pointer to hardware structure
+ *
+ * Resets the hardware by resetting the transmit and receive units, masks
+ * and clears all interrupts, perform a PHY reset, and perform a link (MAC)
+ * reset.
+ **/
+s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
+{
+ s32 status = IXGBE_SUCCESS;
+ u32 ctrl, ctrl_ext;
+ u32 i;
+ u32 autoc;
+ u32 autoc2;
+
+ /* Call adapter stop to disable tx/rx and clear interrupts */
+ hw->mac.ops.stop_adapter(hw);
+
+ /* PHY ops must be identified and initialized prior to reset */
+
+ /* Identify PHY and related function pointers */
+ status = hw->phy.ops.init(hw);
+
+ if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ goto reset_hw_out;
+
+
+ /* Setup SFP module if there is one present. */
+ if (hw->phy.sfp_setup_needed) {
+ status = hw->mac.ops.setup_sfp(hw);
+ hw->phy.sfp_setup_needed = FALSE;
+ }
+
+ if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+ goto reset_hw_out;
+
+ /* Reset PHY */
+ if (hw->phy.reset_disable == FALSE && hw->phy.ops.reset != NULL)
+ hw->phy.ops.reset(hw);
+
+ /*
+ * Prevent the PCI-E bus from from hanging by disabling PCI-E master
+ * access and verify no pending requests before reset
+ */
+ status = ixgbe_disable_pcie_master(hw);
+ if (status != IXGBE_SUCCESS) {
+ status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
+ DEBUGOUT("PCI-E Master disable polling has failed.\n");
+ }
+
+ /*
+ * Issue global reset to the MAC. This needs to be a SW reset.
+ * If link reset is used, it might reset the MAC when mng is using it
+ */
+ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST));
+ IXGBE_WRITE_FLUSH(hw);
+
+ /* Poll for reset bit to self-clear indicating reset is complete */
+ for (i = 0; i < 10; i++) {
+ usec_delay(1);
+ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
+ if (!(ctrl & IXGBE_CTRL_RST))
+ break;
+ }
+ if (ctrl & IXGBE_CTRL_RST) {
+ status = IXGBE_ERR_RESET_FAILED;
+ DEBUGOUT("Reset polling failed to complete.\n");
+ }
+ /* Clear PF Reset Done bit so PF/VF Mail Ops can work */
+ ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
+ ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
+
+ msec_delay(50);
+
+
+
+ /*
+ * Store the original AUTOC/AUTOC2 values if they have not been
+ * stored off yet. Otherwise restore the stored original
+ * values since the reset operation sets back to defaults.
+ */
+ autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
+ if (hw->mac.orig_link_settings_stored == FALSE) {
+ hw->mac.orig_autoc = autoc;
+ hw->mac.orig_autoc2 = autoc2;
+ hw->mac.orig_link_settings_stored = TRUE;
+ } else {
+ if (autoc != hw->mac.orig_autoc)
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc |
+ IXGBE_AUTOC_AN_RESTART));
+
+ if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
+ (hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
+ autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK;
+ autoc2 |= (hw->mac.orig_autoc2 &
+ IXGBE_AUTOC2_UPPER_MASK);
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
+ }
+ }
+
+ /*
+ * Store MAC address from RAR0, clear receive address registers, and
+ * clear the multicast table. Also reset num_rar_entries to 128,
+ * since we modify this value when programming the SAN MAC address.
+ */
+ hw->mac.num_rar_entries = 128;
+ hw->mac.ops.init_rx_addrs(hw);
+
+ /* Store the permanent mac address */
+ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
+
+ /* Store the permanent SAN mac address */
+ hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
+
+ /* Add the SAN MAC address to the RAR only if it's a valid address */
+ if (ixgbe_validate_mac_addr(hw->mac.san_addr) == 0) {
+ hw->mac.ops.set_rar(hw, hw->mac.num_rar_entries - 1,
+ hw->mac.san_addr, 0, IXGBE_RAH_AV);
+
+ /* Reserve the last RAR for the SAN MAC address */
+ hw->mac.num_rar_entries--;
+ }
+
+reset_hw_out:
+ return status;
+}
+
+/**
+ * ixgbe_insert_mac_addr_82599 - Find a RAR for this mac address
+ * @hw: pointer to hardware structure
+ * @addr: Address to put into receive address register
+ * @vmdq: VMDq pool to assign
+ *
+ * Puts an ethernet address into a receive address register, or
+ * finds the rar that it is aleady in; adds to the pool list
+ **/
+s32 ixgbe_insert_mac_addr_82599(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
+{
+ static const u32 NO_EMPTY_RAR_FOUND = 0xFFFFFFFF;
+ u32 first_empty_rar = NO_EMPTY_RAR_FOUND;
+ u32 rar;
+ u32 rar_low, rar_high;
+ u32 addr_low, addr_high;
+
+ /* swap bytes for HW little endian */
+ addr_low = addr[0] | (addr[1] << 8)
+ | (addr[2] << 16)
+ | (addr[3] << 24);
+ addr_high = addr[4] | (addr[5] << 8);
+
+ /*
+ * Either find the mac_id in rar or find the first empty space.
+ * rar_highwater points to just after the highest currently used
+ * rar in order to shorten the search. It grows when we add a new
+ * rar to the top.
+ */
+ for (rar = 0; rar < hw->mac.rar_highwater; rar++) {
+ rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
+
+ if (((IXGBE_RAH_AV & rar_high) == 0)
+ && first_empty_rar == NO_EMPTY_RAR_FOUND) {
+ first_empty_rar = rar;
+ } else if ((rar_high & 0xFFFF) == addr_high) {
+ rar_low = IXGBE_READ_REG(hw, IXGBE_RAL(rar));
+ if (rar_low == addr_low)
+ break; /* found it already in the rars */
+ }
+ }
+
+ if (rar < hw->mac.rar_highwater) {
+ /* already there so just add to the pool bits */
+ ixgbe_set_vmdq(hw, rar, vmdq);
+ } else if (first_empty_rar != NO_EMPTY_RAR_FOUND) {
+ /* stick it into first empty RAR slot we found */
+ rar = first_empty_rar;
+ ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
+ } else if (rar == hw->mac.rar_highwater) {
+ /* add it to the top of the list and inc the highwater mark */
+ ixgbe_set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
+ hw->mac.rar_highwater++;
+ } else if (rar >= hw->mac.num_rar_entries) {
+ return IXGBE_ERR_INVALID_MAC_ADDR;
+ }
+
+ /*
+ * If we found rar[0], make sure the default pool bit (we use pool 0)
+ * remains cleared to be sure default pool packets will get delivered
+ */
+ if (rar == 0)
+ ixgbe_clear_vmdq(hw, rar, 0);
+
+ return rar;
+}
+
+/**
+ * ixgbe_clear_vmdq_82599 - Disassociate a VMDq pool index from a rx address
+ * @hw: pointer to hardware struct
+ * @rar: receive address register index to disassociate
+ * @vmdq: VMDq pool index to remove from the rar
+ **/
+s32 ixgbe_clear_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
+{
+ u32 mpsar_lo, mpsar_hi;
+ u32 rar_entries = hw->mac.num_rar_entries;
+
+ if (rar < rar_entries) {
+ mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
+ mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
+
+ if (!mpsar_lo && !mpsar_hi)
+ goto done;
+
+ if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
+ if (mpsar_lo) {
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
+ mpsar_lo = 0;
+ }
+ if (mpsar_hi) {
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
+ mpsar_hi = 0;
+ }
+ } else if (vmdq < 32) {
+ mpsar_lo &= ~(1 << vmdq);
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
+ } else {
+ mpsar_hi &= ~(1 << (vmdq - 32));
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
+ }
+
+ /* was that the last pool using this rar? */
+ if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
+ hw->mac.ops.clear_rar(hw, rar);
+ } else {
+ DEBUGOUT1("RAR index %d is out of range.\n", rar);
+ }
+
+done:
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_set_vmdq_82599 - Associate a VMDq pool index with a rx address
+ * @hw: pointer to hardware struct
+ * @rar: receive address register index to associate with a VMDq index
+ * @vmdq: VMDq pool index
+ **/
+s32 ixgbe_set_vmdq_82599(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
+{
+ u32 mpsar;
+ u32 rar_entries = hw->mac.num_rar_entries;
+
+ if (rar < rar_entries) {
+ if (vmdq < 32) {
+ mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
+ mpsar |= 1 << vmdq;
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
+ } else {
+ mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
+ mpsar |= 1 << (vmdq - 32);
+ IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
+ }
+ } else {
+ DEBUGOUT1("RAR index %d is out of range.\n", rar);
+ }
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_set_vfta_82599 - Set VLAN filter table
+ * @hw: pointer to hardware structure
+ * @vlan: VLAN id to write to VLAN filter
+ * @vind: VMDq output index that maps queue to VLAN id in VFVFB
+ * @vlan_on: boolean flag to turn on/off VLAN in VFVF
+ *
+ * Turn on/off specified VLAN in the VLAN filter table.
+ **/
+s32 ixgbe_set_vfta_82599(struct ixgbe_hw *hw, u32 vlan, u32 vind,
+ bool vlan_on)
+{
+ u32 regindex;
+ u32 bitindex;
+ u32 bits;
+ u32 first_empty_slot;
+
+ if (vlan > 4095)
+ return IXGBE_ERR_PARAM;
+
+ /*
+ * this is a 2 part operation - first the VFTA, then the
+ * VLVF and VLVFB if vind is set
+ */
+
+ /* Part 1
+ * The VFTA is a bitstring made up of 128 32-bit registers
+ * that enable the particular VLAN id, much like the MTA:
+ * bits[11-5]: which register
+ * bits[4-0]: which bit in the register
+ */
+ regindex = (vlan >> 5) & 0x7F;
+ bitindex = vlan & 0x1F;
+ bits = IXGBE_READ_REG(hw, IXGBE_VFTA(regindex));
+ if (vlan_on)
+ bits |= (1 << bitindex);
+ else
+ bits &= ~(1 << bitindex);
+ IXGBE_WRITE_REG(hw, IXGBE_VFTA(regindex), bits);
+
+
+ /* Part 2
+ * If the vind is set
+ * Either vlan_on
+ * make sure the vlan is in VLVF
+ * set the vind bit in the matching VLVFB
+ * Or !vlan_on
+ * clear the pool bit and possibly the vind
+ */
+ if (vind) {
+ /* find the vlanid or the first empty slot */
+ first_empty_slot = 0;
+
+ for (regindex = 1; regindex < IXGBE_VLVF_ENTRIES; regindex++) {
+ bits = IXGBE_READ_REG(hw, IXGBE_VLVF(regindex));
+ if (!bits && !first_empty_slot)
+ first_empty_slot = regindex;
+ else if ((bits & 0x0FFF) == vlan)
+ break;
+ }
+
+ if (regindex >= IXGBE_VLVF_ENTRIES) {
+ if (first_empty_slot)
+ regindex = first_empty_slot;
+ else {
+ DEBUGOUT("No space in VLVF.\n");
+ goto out;
+ }
+ }
+
+
+ if (vlan_on) {
+ /* set the pool bit */
+ if (vind < 32) {
+ bits =
+ IXGBE_READ_REG(hw, IXGBE_VLVFB(regindex*2));
+ bits |= (1 << vind);
+ IXGBE_WRITE_REG(hw,
+ IXGBE_VLVFB(regindex*2), bits);
+ } else {
+ bits = IXGBE_READ_REG(hw,
+ IXGBE_VLVFB((regindex*2)+1));
+ bits |= (1 << vind);
+ IXGBE_WRITE_REG(hw,
+ IXGBE_VLVFB((regindex*2)+1), bits);
+ }
+ } else {
+ /* clear the pool bit */
+ if (vind < 32) {
+ bits = IXGBE_READ_REG(hw,
+ IXGBE_VLVFB(regindex*2));
+ bits &= ~(1 << vind);
+ IXGBE_WRITE_REG(hw,
+ IXGBE_VLVFB(regindex*2), bits);
+ bits |= IXGBE_READ_REG(hw,
+ IXGBE_VLVFB((regindex*2)+1));
+ } else {
+ bits = IXGBE_READ_REG(hw,
+ IXGBE_VLVFB((regindex*2)+1));
+ bits &= ~(1 << vind);
+ IXGBE_WRITE_REG(hw,
+ IXGBE_VLVFB((regindex*2)+1), bits);
+ bits |= IXGBE_READ_REG(hw,
+ IXGBE_VLVFB(regindex*2));
+ }
+ }
+
+ if (bits)
+ IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex),
+ (IXGBE_VLVF_VIEN | vlan));
+ else
+ IXGBE_WRITE_REG(hw, IXGBE_VLVF(regindex), 0);
+ }
+
+out:
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_clear_vfta_82599 - Clear VLAN filter table
+ * @hw: pointer to hardware structure
+ *
+ * Clears the VLAN filer table, and the VMDq index associated with the filter
+ **/
+s32 ixgbe_clear_vfta_82599(struct ixgbe_hw *hw)
+{
+ u32 offset;
+
+ for (offset = 0; offset < hw->mac.vft_size; offset++)
+ IXGBE_WRITE_REG(hw, IXGBE_VFTA(offset), 0);
+
+ for (offset = 0; offset < IXGBE_VLVF_ENTRIES; offset++) {
+ IXGBE_WRITE_REG(hw, IXGBE_VLVF(offset), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_VLVFB(offset*2), 0);
+ IXGBE_WRITE_REG(hw, IXGBE_VLVFB((offset*2)+1), 0);
+ }
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_init_uta_tables_82599 - Initialize the Unicast Table Array
+ * @hw: pointer to hardware structure
+ **/
+s32 ixgbe_init_uta_tables_82599(struct ixgbe_hw *hw)
+{
+ int i;
+ DEBUGOUT(" Clearing UTA\n");
+
+ for (i = 0; i < 128; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_reinit_fdir_tables_82599 - Reinitialize Flow Director tables.
+ * @hw: pointer to hardware structure
+ **/
+s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw)
+{
+ u32 fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
+ fdirctrl &= ~IXGBE_FDIRCTRL_INIT_DONE;
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRFREE, 0);
+ IXGBE_WRITE_FLUSH(hw);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
+
+ return IXGBE_SUCCESS;
+}
+
+#define IXGBE_FDIR_INIT_DONE_POLL 10
+/**
+ * ixgbe_init_fdir_signature_82599 - Initialize Flow Director signature filters
+ * @hw: pointer to hardware structure
+ * @pballoc: which mode to allocate filters with
+ **/
+s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc)
+{
+ u32 fdirctrl = 0;
+ u32 pbsize;
+ int i;
+
+ /*
+ * Before enabling Flow Director, the Rx Packet Buffer size
+ * must be reduced. The new value is the current size minus
+ * flow director memory usage size.
+ */
+ pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
+ (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
+
+ /*
+ * The defaults in the HW for RX PB 1-7 are not zero and so should be
+ * intialized to zero for non DCB mode otherwise actual total RX PB
+ * would be bigger than programmed and filter space would run into
+ * the PB 0 region.
+ */
+ for (i = 1; i < 8; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
+
+ /* Send interrupt when 64 filters are left */
+ fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
+
+ /* Set the maximum length per hash bucket to 0xA filters */
+ fdirctrl |= 0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT;
+
+ switch (pballoc) {
+ case IXGBE_FDIR_PBALLOC_64K:
+ /* 8k - 1 signature filters */
+ fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
+ break;
+ case IXGBE_FDIR_PBALLOC_128K:
+ /* 16k - 1 signature filters */
+ fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
+ break;
+ case IXGBE_FDIR_PBALLOC_256K:
+ /* 32k - 1 signature filters */
+ fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
+ break;
+ default:
+ /* bad value */
+ return IXGBE_ERR_CONFIG;
+ };
+
+ /* Move the flexible bytes to use the ethertype - shift 6 words */
+ fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
+
+
+ /* Prime the keys for hashing */
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY,
+ IXGBE_HTONL(IXGBE_ATR_BUCKET_HASH_KEY));
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY,
+ IXGBE_HTONL(IXGBE_ATR_SIGNATURE_HASH_KEY));
+
+ /*
+ * Poll init-done after we write the register. Estimated times:
+ * 10G: PBALLOC = 11b, timing is 60us
+ * 1G: PBALLOC = 11b, timing is 600us
+ * 100M: PBALLOC = 11b, timing is 6ms
+ *
+ * Multiple these timings by 4 if under full Rx load
+ *
+ * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
+ * 1 msec per poll time. If we're at line rate and drop to 100M, then
+ * this might not finish in our poll time, but we can live with that
+ * for now.
+ */
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
+ IXGBE_WRITE_FLUSH(hw);
+ for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
+ if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
+ IXGBE_FDIRCTRL_INIT_DONE)
+ break;
+ msec_delay(1);
+ }
+ if (i >= IXGBE_FDIR_INIT_DONE_POLL)
+ DEBUGOUT("Flow Director Signature poll time exceeded!\n");
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_init_fdir_perfect_82599 - Initialize Flow Director perfect filters
+ * @hw: pointer to hardware structure
+ * @pballoc: which mode to allocate filters with
+ **/
+s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc)
+{
+ u32 fdirctrl = 0;
+ u32 pbsize;
+ int i;
+
+ /*
+ * Before enabling Flow Director, the Rx Packet Buffer size
+ * must be reduced. The new value is the current size minus
+ * flow director memory usage size.
+ */
+
+ pbsize = (1 << (IXGBE_FDIR_PBALLOC_SIZE_SHIFT + pballoc));
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0),
+ (IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(0)) - pbsize));
+
+ /*
+ * The defaults in the HW for RX PB 1-7 are not zero and so should be
+ * intialized to zero for non DCB mode otherwise actual total RX PB
+ * would be bigger than programmed and filter space would run into
+ * the PB 0 region.
+ */
+ for (i = 1; i < 8; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), 0);
+
+ /* Send interrupt when 64 filters are left */
+ fdirctrl |= 4 << IXGBE_FDIRCTRL_FULL_THRESH_SHIFT;
+
+ switch (pballoc) {
+ case IXGBE_FDIR_PBALLOC_64K:
+ /* 2k - 1 perfect filters */
+ fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_64K;
+ break;
+ case IXGBE_FDIR_PBALLOC_128K:
+ /* 4k - 1 perfect filters */
+ fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_128K;
+ break;
+ case IXGBE_FDIR_PBALLOC_256K:
+ /* 8k - 1 perfect filters */
+ fdirctrl |= IXGBE_FDIRCTRL_PBALLOC_256K;
+ break;
+ default:
+ /* bad value */
+ return IXGBE_ERR_CONFIG;
+ };
+
+ /* Turn perfect match filtering on */
+ fdirctrl |= IXGBE_FDIRCTRL_PERFECT_MATCH;
+ fdirctrl |= IXGBE_FDIRCTRL_REPORT_STATUS;
+
+ /* Move the flexible bytes to use the ethertype - shift 6 words */
+ fdirctrl |= (0x6 << IXGBE_FDIRCTRL_FLEX_SHIFT);
+
+ /* Prime the keys for hashing */
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHKEY,
+ IXGBE_HTONL(IXGBE_ATR_BUCKET_HASH_KEY));
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRSKEY,
+ IXGBE_HTONL(IXGBE_ATR_SIGNATURE_HASH_KEY));
+
+ /*
+ * Poll init-done after we write the register. Estimated times:
+ * 10G: PBALLOC = 11b, timing is 60us
+ * 1G: PBALLOC = 11b, timing is 600us
+ * 100M: PBALLOC = 11b, timing is 6ms
+ *
+ * Multiple these timings by 4 if under full Rx load
+ *
+ * So we'll poll for IXGBE_FDIR_INIT_DONE_POLL times, sleeping for
+ * 1 msec per poll time. If we're at line rate and drop to 100M, then
+ * this might not finish in our poll time, but we can live with that
+ * for now.
+ */
+
+ /* Set the maximum length per hash bucket to 0xA filters */
+ fdirctrl |= (0xA << IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT);
+
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
+ IXGBE_WRITE_FLUSH(hw);
+ for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
+ if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
+ IXGBE_FDIRCTRL_INIT_DONE)
+ break;
+ msec_delay(1);
+ }
+ if (i >= IXGBE_FDIR_INIT_DONE_POLL)
+ DEBUGOUT("Flow Director Perfect poll time exceeded!\n");
+
+ return IXGBE_SUCCESS;
+}
+
+
+/**
+ * ixgbe_atr_compute_hash_82599 - Compute the hashes for SW ATR
+ * @stream: input bitstream to compute the hash on
+ * @key: 32-bit hash key
+ **/
+u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *atr_input, u32 key)
+{
+ /*
+ * The algorithm is as follows:
+ * Hash[15:0] = Sum { S[n] x K[n+16] }, n = 0...350
+ * where Sum {A[n]}, n = 0...n is bitwise XOR of A[0], A[1]...A[n]
+ * and A[n] x B[n] is bitwise AND between same length strings
+ *
+ * K[n] is 16 bits, defined as:
+ * for n modulo 32 >= 15, K[n] = K[n % 32 : (n % 32) - 15]
+ * for n modulo 32 < 15, K[n] =
+ * K[(n % 32:0) | (31:31 - (14 - (n % 32)))]
+ *
+ * S[n] is 16 bits, defined as:
+ * for n >= 15, S[n] = S[n:n - 15]
+ * for n < 15, S[n] = S[(n:0) | (350:350 - (14 - n))]
+ *
+ * To simplify for programming, the algorithm is implemented
+ * in software this way:
+ *
+ * Key[31:0], Stream[335:0]
+ *
+ * tmp_key[11 * 32 - 1:0] = 11{Key[31:0] = key concatenated 11 times
+ * int_key[350:0] = tmp_key[351:1]
+ * int_stream[365:0] = Stream[14:0] | Stream[335:0] | Stream[335:321]
+ *
+ * hash[15:0] = 0;
+ * for (i = 0; i < 351; i++) {
+ * if (int_key[i])
+ * hash ^= int_stream[(i + 15):i];
+ * }
+ */
+
+ union {
+ u32 key[11];
+ u8 key_stream[44];
+ } tmp_key;
+
+ u8 *stream = (u8 *)atr_input;
+ u8 int_key[44]; /* upper-most bit unused */
+ u8 hash_str[46]; /* upper-most 2 bits unused */
+ u16 hash_result = 0;
+ u16 tmp = 0;
+ int i, j, k, h;
+
+ memset(&tmp_key, 0, sizeof(tmp_key));
+ /* First load the temporary key stream */
+ for (i = 0; i < 11; i++)
+ tmp_key.key[i] = key;
+
+ /*
+ * Set the interim key for the hashing. Bit 352 is unused, so we must
+ * shift and compensate when building the key.
+ */
+ int_key[0] = tmp_key.key_stream[0] >> 1;
+ for (i = 1, j = 0; i < 44; i++) {
+ int_key[i] = (tmp_key.key_stream[j] & 0x1) << 7;
+ j++;
+ int_key[i] |= tmp_key.key_stream[j] >> 1;
+ }
+
+ /*
+ * Set the interim bit string for the hashing. Bits 368 and 367 are
+ * unused, so shift and compensate when building the string.
+ */
+ hash_str[0] = (stream[40] & 0x7f) >> 1;
+ for (i = 1, j = 40; i < 46; i++) {
+ hash_str[i] = (stream[j] & 0x1) << 7;
+ j++;
+ if (j > 41)
+ j = 0;
+ hash_str[i] |= stream[j] >> 1;
+ }
+
+ /*
+ * Now compute the hash. i is the index into hash_str, j is into our
+ * key stream, k is counting the number of bits, and h interates within
+ * each byte.
+ */
+ for (i = 45, j = 43, k = 0; k < 351 && i >= 2 && j >= 0; i--, j--) {
+ for (h = 0; h < 8 && k < 351; h++, k++) {
+ if ((int_key[j] >> h) & 0x1) {
+ /*
+ * Key bit is set, XOR in the current 16-bit
+ * string. Example of processing:
+ * h = 0,
+ * tmp = (hash_str[i - 2] & 0 << 16) |
+ * (hash_str[i - 1] & 0xff << 8) |
+ * (hash_str[i] & 0xff >> 0)
+ * So tmp = hash_str[15 + k:k], since the
+ * i + 2 clause rolls off the 16-bit value
+ * h = 7,
+ * tmp = (hash_str[i - 2] & 0x7f << 9) |
+ * (hash_str[i - 1] & 0xff << 1) |
+ * (hash_str[i] & 0x80 >> 7)
+ */
+ tmp = ((hash_str[i] & (0xff << h)) >> h);
+ tmp |= ((hash_str[i - 1] & 0xff) << (8 - h));
+ tmp |= (hash_str[i - 2] & (0xff >> (8 - h)))
+ << (16 - h);
+ hash_result ^= tmp;
+ }
+ }
+ }
+
+ return hash_result;
+}
+
+/**
+ * ixgbe_atr_set_vlan_id_82599 - Sets the VLAN id in the ATR input stream
+ * @input: input stream to modify
+ * @vlan: the VLAN id to load
+ **/
+s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan)
+{
+ input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] = vlan >> 8;
+ input->byte_stream[IXGBE_ATR_VLAN_OFFSET] = vlan & 0xff;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_set_src_ipv4_82599 - Sets the source IPv4 address
+ * @input: input stream to modify
+ * @src_addr: the IP address to load
+ **/
+s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr)
+{
+ input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] = src_addr >> 24;
+ input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] =
+ (src_addr >> 16) & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] =
+ (src_addr >> 8) & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET] = src_addr & 0xff;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_set_dst_ipv4_82599 - Sets the destination IPv4 address
+ * @input: input stream to modify
+ * @dst_addr: the IP address to load
+ **/
+s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr)
+{
+ input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] = dst_addr >> 24;
+ input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] =
+ (dst_addr >> 16) & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] =
+ (dst_addr >> 8) & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET] = dst_addr & 0xff;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_set_src_ipv6_82599 - Sets the source IPv6 address
+ * @input: input stream to modify
+ * @src_addr_1: the first 4 bytes of the IP address to load
+ * @src_addr_2: the second 4 bytes of the IP address to load
+ * @src_addr_3: the third 4 bytes of the IP address to load
+ * @src_addr_4: the fourth 4 bytes of the IP address to load
+ **/
+s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input,
+ u32 src_addr_1, u32 src_addr_2,
+ u32 src_addr_3, u32 src_addr_4)
+{
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET] = src_addr_4 & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] =
+ (src_addr_4 >> 8) & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] =
+ (src_addr_4 >> 16) & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] = src_addr_4 >> 24;
+
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4] = src_addr_3 & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] =
+ (src_addr_3 >> 8) & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] =
+ (src_addr_3 >> 16) & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] = src_addr_3 >> 24;
+
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8] = src_addr_2 & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] =
+ (src_addr_2 >> 8) & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] =
+ (src_addr_2 >> 16) & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] = src_addr_2 >> 24;
+
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12] = src_addr_1 & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] =
+ (src_addr_1 >> 8) & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] =
+ (src_addr_1 >> 16) & 0xff;
+ input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] = src_addr_1 >> 24;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_set_dst_ipv6_82599 - Sets the destination IPv6 address
+ * @input: input stream to modify
+ * @dst_addr_1: the first 4 bytes of the IP address to load
+ * @dst_addr_2: the second 4 bytes of the IP address to load
+ * @dst_addr_3: the third 4 bytes of the IP address to load
+ * @dst_addr_4: the fourth 4 bytes of the IP address to load
+ **/
+s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input,
+ u32 dst_addr_1, u32 dst_addr_2,
+ u32 dst_addr_3, u32 dst_addr_4)
+{
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET] = dst_addr_4 & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] =
+ (dst_addr_4 >> 8) & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] =
+ (dst_addr_4 >> 16) & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] = dst_addr_4 >> 24;
+
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4] = dst_addr_3 & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] =
+ (dst_addr_3 >> 8) & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] =
+ (dst_addr_3 >> 16) & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] = dst_addr_3 >> 24;
+
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8] = dst_addr_2 & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] =
+ (dst_addr_2 >> 8) & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] =
+ (dst_addr_2 >> 16) & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] = dst_addr_2 >> 24;
+
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12] = dst_addr_1 & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] =
+ (dst_addr_1 >> 8) & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] =
+ (dst_addr_1 >> 16) & 0xff;
+ input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] = dst_addr_1 >> 24;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_set_src_port_82599 - Sets the source port
+ * @input: input stream to modify
+ * @src_port: the source port to load
+ **/
+s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port)
+{
+ input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1] = src_port >> 8;
+ input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] = src_port & 0xff;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_set_dst_port_82599 - Sets the destination port
+ * @input: input stream to modify
+ * @dst_port: the destination port to load
+ **/
+s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port)
+{
+ input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1] = dst_port >> 8;
+ input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] = dst_port & 0xff;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_set_flex_byte_82599 - Sets the flexible bytes
+ * @input: input stream to modify
+ * @flex_bytes: the flexible bytes to load
+ **/
+s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte)
+{
+ input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] = flex_byte >> 8;
+ input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET] = flex_byte & 0xff;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_set_vm_pool_82599 - Sets the Virtual Machine pool
+ * @input: input stream to modify
+ * @vm_pool: the Virtual Machine pool to load
+ **/
+s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, u8 vm_pool)
+{
+ input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET] = vm_pool;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_set_l4type_82599 - Sets the layer 4 packet type
+ * @input: input stream to modify
+ * @l4type: the layer 4 type value to load
+ **/
+s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type)
+{
+ input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET] = l4type;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_get_vlan_id_82599 - Gets the VLAN id from the ATR input stream
+ * @input: input stream to search
+ * @vlan: the VLAN id to load
+ **/
+s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan)
+{
+ *vlan = input->byte_stream[IXGBE_ATR_VLAN_OFFSET];
+ *vlan |= input->byte_stream[IXGBE_ATR_VLAN_OFFSET + 1] << 8;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_get_src_ipv4_82599 - Gets the source IPv4 address
+ * @input: input stream to search
+ * @src_addr: the IP address to load
+ **/
+s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, u32 *src_addr)
+{
+ *src_addr = input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET];
+ *src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 1] << 8;
+ *src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 2] << 16;
+ *src_addr |= input->byte_stream[IXGBE_ATR_SRC_IPV4_OFFSET + 3] << 24;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_get_dst_ipv4_82599 - Gets the destination IPv4 address
+ * @input: input stream to search
+ * @dst_addr: the IP address to load
+ **/
+s32 ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 *dst_addr)
+{
+ *dst_addr = input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET];
+ *dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 1] << 8;
+ *dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 2] << 16;
+ *dst_addr |= input->byte_stream[IXGBE_ATR_DST_IPV4_OFFSET + 3] << 24;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_get_src_ipv6_82599 - Gets the source IPv6 address
+ * @input: input stream to search
+ * @src_addr_1: the first 4 bytes of the IP address to load
+ * @src_addr_2: the second 4 bytes of the IP address to load
+ * @src_addr_3: the third 4 bytes of the IP address to load
+ * @src_addr_4: the fourth 4 bytes of the IP address to load
+ **/
+s32 ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input,
+ u32 *src_addr_1, u32 *src_addr_2,
+ u32 *src_addr_3, u32 *src_addr_4)
+{
+ *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 12];
+ *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 13] << 8;
+ *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 14] << 16;
+ *src_addr_1 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 15] << 24;
+
+ *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 8];
+ *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 9] << 8;
+ *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 10] << 16;
+ *src_addr_2 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 11] << 24;
+
+ *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 4];
+ *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 5] << 8;
+ *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 6] << 16;
+ *src_addr_3 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 7] << 24;
+
+ *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET];
+ *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 1] << 8;
+ *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 2] << 16;
+ *src_addr_4 = input->byte_stream[IXGBE_ATR_SRC_IPV6_OFFSET + 3] << 24;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_get_dst_ipv6_82599 - Gets the destination IPv6 address
+ * @input: input stream to search
+ * @dst_addr_1: the first 4 bytes of the IP address to load
+ * @dst_addr_2: the second 4 bytes of the IP address to load
+ * @dst_addr_3: the third 4 bytes of the IP address to load
+ * @dst_addr_4: the fourth 4 bytes of the IP address to load
+ **/
+s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input,
+ u32 *dst_addr_1, u32 *dst_addr_2,
+ u32 *dst_addr_3, u32 *dst_addr_4)
+{
+ *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 12];
+ *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 13] << 8;
+ *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 14] << 16;
+ *dst_addr_1 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 15] << 24;
+
+ *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 8];
+ *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 9] << 8;
+ *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 10] << 16;
+ *dst_addr_2 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 11] << 24;
+
+ *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 4];
+ *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 5] << 8;
+ *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 6] << 16;
+ *dst_addr_3 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 7] << 24;
+
+ *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET];
+ *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 1] << 8;
+ *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 2] << 16;
+ *dst_addr_4 = input->byte_stream[IXGBE_ATR_DST_IPV6_OFFSET + 3] << 24;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_get_src_port_82599 - Gets the source port
+ * @input: input stream to modify
+ * @src_port: the source port to load
+ *
+ * Even though the input is given in big-endian, the FDIRPORT registers
+ * expect the ports to be programmed in little-endian. Hence the need to swap
+ * endianness when retrieving the data. This can be confusing since the
+ * internal hash engine expects it to be big-endian.
+ **/
+s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, u16 *src_port)
+{
+ *src_port = input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET] << 8;
+ *src_port |= input->byte_stream[IXGBE_ATR_SRC_PORT_OFFSET + 1];
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_get_dst_port_82599 - Gets the destination port
+ * @input: input stream to modify
+ * @dst_port: the destination port to load
+ *
+ * Even though the input is given in big-endian, the FDIRPORT registers
+ * expect the ports to be programmed in little-endian. Hence the need to swap
+ * endianness when retrieving the data. This can be confusing since the
+ * internal hash engine expects it to be big-endian.
+ **/
+s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, u16 *dst_port)
+{
+ *dst_port = input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET] << 8;
+ *dst_port |= input->byte_stream[IXGBE_ATR_DST_PORT_OFFSET + 1];
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_get_flex_byte_82599 - Gets the flexible bytes
+ * @input: input stream to modify
+ * @flex_bytes: the flexible bytes to load
+ **/
+s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input, u16 *flex_byte)
+{
+ *flex_byte = input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET];
+ *flex_byte |= input->byte_stream[IXGBE_ATR_FLEX_BYTE_OFFSET + 1] << 8;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_get_vm_pool_82599 - Gets the Virtual Machine pool
+ * @input: input stream to modify
+ * @vm_pool: the Virtual Machine pool to load
+ **/
+s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, u8 *vm_pool)
+{
+ *vm_pool = input->byte_stream[IXGBE_ATR_VM_POOL_OFFSET];
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_get_l4type_82599 - Gets the layer 4 packet type
+ * @input: input stream to modify
+ * @l4type: the layer 4 type value to load
+ **/
+s32 ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, u8 *l4type)
+{
+ *l4type = input->byte_stream[IXGBE_ATR_L4TYPE_OFFSET];
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_atr_add_signature_filter_82599 - Adds a signature hash filter
+ * @hw: pointer to hardware structure
+ * @stream: input bitstream
+ * @queue: queue index to direct traffic to
+ **/
+s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
+ struct ixgbe_atr_input *input,
+ u8 queue)
+{
+ u64 fdirhashcmd;
+ u64 fdircmd;
+ u32 fdirhash;
+ u16 bucket_hash, sig_hash;
+ u8 l4type;
+
+ bucket_hash = ixgbe_atr_compute_hash_82599(input,
+ IXGBE_ATR_BUCKET_HASH_KEY);
+
+ /* bucket_hash is only 15 bits */
+ bucket_hash &= IXGBE_ATR_HASH_MASK;
+
+ sig_hash = ixgbe_atr_compute_hash_82599(input,
+ IXGBE_ATR_SIGNATURE_HASH_KEY);
+
+ /* Get the l4type in order to program FDIRCMD properly */
+ /* lowest 2 bits are FDIRCMD.L4TYPE, third lowest bit is FDIRCMD.IPV6 */
+ ixgbe_atr_get_l4type_82599(input, &l4type);
+
+ /*
+ * The lower 32-bits of fdirhashcmd is for FDIRHASH, the upper 32-bits
+ * is for FDIRCMD. Then do a 64-bit register write from FDIRHASH.
+ */
+ fdirhash = sig_hash << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash;
+
+ fdircmd = (IXGBE_FDIRCMD_CMD_ADD_FLOW | IXGBE_FDIRCMD_FILTER_UPDATE |
+ IXGBE_FDIRCMD_LAST | IXGBE_FDIRCMD_QUEUE_EN);
+
+ switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
+ case IXGBE_ATR_L4TYPE_TCP:
+ fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP;
+ break;
+ case IXGBE_ATR_L4TYPE_UDP:
+ fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP;
+ break;
+ case IXGBE_ATR_L4TYPE_SCTP:
+ fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP;
+ break;
+ default:
+ DEBUGOUT(" Error on l4type input\n");
+ return IXGBE_ERR_CONFIG;
+ }
+
+ if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK)
+ fdircmd |= IXGBE_FDIRCMD_IPV6;
+
+ fdircmd |= ((u64)queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT);
+ fdirhashcmd = ((fdircmd << 32) | fdirhash);
+
+ DEBUGOUT2("Tx Queue=%x hash=%x\n", queue, fdirhash & 0x7FFF7FFF);
+ IXGBE_WRITE_REG64(hw, IXGBE_FDIRHASH, fdirhashcmd);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_fdir_add_perfect_filter_82599 - Adds a perfect filter
+ * @hw: pointer to hardware structure
+ * @input: input bitstream
+ * @queue: queue index to direct traffic to
+ *
+ * Note that the caller to this function must lock before calling, since the
+ * hardware writes must be protected from one another.
+ **/
+s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
+ struct ixgbe_atr_input *input,
+ u16 soft_id,
+ u8 queue)
+{
+ u32 fdircmd = 0;
+ u32 fdirhash;
+ u32 src_ipv4, dst_ipv4;
+ u32 src_ipv6_1, src_ipv6_2, src_ipv6_3, src_ipv6_4;
+ u16 src_port, dst_port, vlan_id, flex_bytes;
+ u16 bucket_hash;
+ u8 l4type;
+
+ /* Get our input values */
+ ixgbe_atr_get_l4type_82599(input, &l4type);
+
+ /*
+ * Check l4type formatting, and bail out before we touch the hardware
+ * if there's a configuration issue
+ */
+ switch (l4type & IXGBE_ATR_L4TYPE_MASK) {
+ case IXGBE_ATR_L4TYPE_TCP:
+ fdircmd |= IXGBE_FDIRCMD_L4TYPE_TCP;
+ break;
+ case IXGBE_ATR_L4TYPE_UDP:
+ fdircmd |= IXGBE_FDIRCMD_L4TYPE_UDP;
+ break;
+ case IXGBE_ATR_L4TYPE_SCTP:
+ fdircmd |= IXGBE_FDIRCMD_L4TYPE_SCTP;
+ break;
+ default:
+ DEBUGOUT(" Error on l4type input\n");
+ return IXGBE_ERR_CONFIG;
+ }
+
+ bucket_hash = ixgbe_atr_compute_hash_82599(input,
+ IXGBE_ATR_BUCKET_HASH_KEY);
+
+ /* bucket_hash is only 15 bits */
+ bucket_hash &= IXGBE_ATR_HASH_MASK;
+
+ ixgbe_atr_get_vlan_id_82599(input, &vlan_id);
+ ixgbe_atr_get_src_port_82599(input, &src_port);
+ ixgbe_atr_get_dst_port_82599(input, &dst_port);
+ ixgbe_atr_get_flex_byte_82599(input, &flex_bytes);
+
+ fdirhash = soft_id << IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT | bucket_hash;
+
+ /* Now figure out if we're IPv4 or IPv6 */
+ if (l4type & IXGBE_ATR_L4TYPE_IPV6_MASK) {
+ /* IPv6 */
+ ixgbe_atr_get_src_ipv6_82599(input, &src_ipv6_1, &src_ipv6_2,
+ &src_ipv6_3, &src_ipv6_4);
+
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(0), src_ipv6_1);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(1), src_ipv6_2);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRSIPv6(2), src_ipv6_3);
+ /* The last 4 bytes is the same register as IPv4 */
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv6_4);
+
+ fdircmd |= IXGBE_FDIRCMD_IPV6;
+ fdircmd |= IXGBE_FDIRCMD_IPv6DMATCH;
+ } else {
+ /* IPv4 */
+ ixgbe_atr_get_src_ipv4_82599(input, &src_ipv4);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRIPSA, src_ipv4);
+
+ }
+
+ ixgbe_atr_get_dst_ipv4_82599(input, &dst_ipv4);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRIPDA, dst_ipv4);
+
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRVLAN, (vlan_id |
+ (flex_bytes << IXGBE_FDIRVLAN_FLEX_SHIFT)));
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRPORT, (src_port |
+ (dst_port << IXGBE_FDIRPORT_DESTINATION_SHIFT)));
+
+ fdircmd |= IXGBE_FDIRCMD_CMD_ADD_FLOW;
+ fdircmd |= IXGBE_FDIRCMD_FILTER_UPDATE;
+ fdircmd |= IXGBE_FDIRCMD_LAST;
+ fdircmd |= IXGBE_FDIRCMD_QUEUE_EN;
+ fdircmd |= queue << IXGBE_FDIRCMD_RX_QUEUE_SHIFT;
+
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRHASH, fdirhash);
+ IXGBE_WRITE_REG(hw, IXGBE_FDIRCMD, fdircmd);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_read_analog_reg8_82599 - Reads 8 bit Omer analog register
+ * @hw: pointer to hardware structure
+ * @reg: analog register to read
+ * @val: read value
+ *
+ * Performs read operation to Omer analog register specified.
+ **/
+s32 ixgbe_read_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 *val)
+{
+ u32 core_ctl;
+
+ IXGBE_WRITE_REG(hw, IXGBE_CORECTL, IXGBE_CORECTL_WRITE_CMD |
+ (reg << 8));
+ IXGBE_WRITE_FLUSH(hw);
+ usec_delay(10);
+ core_ctl = IXGBE_READ_REG(hw, IXGBE_CORECTL);
+ *val = (u8)core_ctl;
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_write_analog_reg8_82599 - Writes 8 bit Omer analog register
+ * @hw: pointer to hardware structure
+ * @reg: atlas register to write
+ * @val: value to write
+ *
+ * Performs write operation to Omer analog register specified.
+ **/
+s32 ixgbe_write_analog_reg8_82599(struct ixgbe_hw *hw, u32 reg, u8 val)
+{
+ u32 core_ctl;
+
+ core_ctl = (reg << 8) | val;
+ IXGBE_WRITE_REG(hw, IXGBE_CORECTL, core_ctl);
+ IXGBE_WRITE_FLUSH(hw);
+ usec_delay(10);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_start_hw_rev_1_82599 - Prepare hardware for Tx/Rx
+ * @hw: pointer to hardware structure
+ *
+ * Starts the hardware using the generic start_hw function.
+ * Then performs revision-specific operations:
+ * Clears the rate limiter registers.
+ **/
+s32 ixgbe_start_hw_rev_1_82599(struct ixgbe_hw *hw)
+{
+ u32 q_num;
+ s32 ret_val = IXGBE_SUCCESS;
+
+ ret_val = ixgbe_start_hw_generic(hw);
+
+ /* Clear the rate limiters */
+ for (q_num = 0; q_num < hw->mac.max_tx_queues; q_num++) {
+ IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, q_num);
+ IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, 0);
+ }
+ IXGBE_WRITE_FLUSH(hw);
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_identify_phy_82599 - Get physical layer module
+ * @hw: pointer to hardware structure
+ *
+ * Determines the physical layer module found on the current adapter.
+ * If PHY already detected, maintains current PHY type in hw struct,
+ * otherwise executes the PHY detection routine.
+ **/
+s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
+{
+ s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+
+ /* Detect PHY if not unknown - returns success if already detected. */
+ status = ixgbe_identify_phy_generic(hw);
+ if (status != IXGBE_SUCCESS)
+ status = ixgbe_identify_sfp_module_generic(hw);
+ /* Set PHY type none if no PHY detected */
+ if (hw->phy.type == ixgbe_phy_unknown) {
+ hw->phy.type = ixgbe_phy_none;
+ status = IXGBE_SUCCESS;
+ }
+
+ /* Return error if SFP module has been detected but is not supported */
+ if (hw->phy.type == ixgbe_phy_sfp_unsupported)
+ status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+
+ return status;
+}
+
+/**
+ * ixgbe_get_supported_physical_layer_82599 - Returns physical layer type
+ * @hw: pointer to hardware structure
+ *
+ * Determines physical layer capabilities of the current configuration.
+ **/
+u32 ixgbe_get_supported_physical_layer_82599(struct ixgbe_hw *hw)
+{
+ u32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+ u32 autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ u32 autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
+ u32 pma_pmd_10g_serial = autoc2 & IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK;
+ u32 pma_pmd_10g_parallel = autoc & IXGBE_AUTOC_10G_PMA_PMD_MASK;
+ u32 pma_pmd_1g = autoc & IXGBE_AUTOC_1G_PMA_PMD_MASK;
+ u16 ext_ability = 0;
+ u8 comp_codes_10g = 0;
+
+ hw->phy.ops.identify(hw);
+
+ if (hw->phy.type == ixgbe_phy_tn ||
+ hw->phy.type == ixgbe_phy_aq ||
+ hw->phy.type == ixgbe_phy_cu_unknown) {
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_EXT_ABILITY,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE, &ext_ability);
+ if (ext_ability & IXGBE_MDIO_PHY_10GBASET_ABILITY)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
+ if (ext_ability & IXGBE_MDIO_PHY_1000BASET_ABILITY)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_T;
+ if (ext_ability & IXGBE_MDIO_PHY_100BASETX_ABILITY)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
+ goto out;
+ }
+
+ switch (autoc & IXGBE_AUTOC_LMS_MASK) {
+ case IXGBE_AUTOC_LMS_1G_AN:
+ case IXGBE_AUTOC_LMS_1G_LINK_NO_AN:
+ if (pma_pmd_1g == IXGBE_AUTOC_1G_KX_BX) {
+ physical_layer = IXGBE_PHYSICAL_LAYER_1000BASE_KX |
+ IXGBE_PHYSICAL_LAYER_1000BASE_BX;
+ goto out;
+ } else
+ /* SFI mode so read SFP module */
+ goto sfp_check;
+ break;
+ case IXGBE_AUTOC_LMS_10G_LINK_NO_AN:
+ if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_CX4)
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
+ else if (pma_pmd_10g_parallel == IXGBE_AUTOC_10G_KX4)
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
+ goto out;
+ break;
+ case IXGBE_AUTOC_LMS_10G_SERIAL:
+ if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_KR) {
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_KR;
+ goto out;
+ } else if (pma_pmd_10g_serial == IXGBE_AUTOC2_10G_SFI)
+ goto sfp_check;
+ break;
+ case IXGBE_AUTOC_LMS_KX4_KX_KR:
+ case IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN:
+ if (autoc & IXGBE_AUTOC_KX_SUPP)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_1000BASE_KX;
+ if (autoc & IXGBE_AUTOC_KX4_SUPP)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KX4;
+ if (autoc & IXGBE_AUTOC_KR_SUPP)
+ physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_KR;
+ goto out;
+ break;
+ default:
+ goto out;
+ break;
+ }
+
+sfp_check:
+ /* SFP check must be done last since DA modules are sometimes used to
+ * test KR mode - we need to id KR mode correctly before SFP module.
+ * Call identify_sfp because the pluggable module may have changed */
+ hw->phy.ops.identify_sfp(hw);
+ if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
+ goto out;
+
+ switch (hw->phy.type) {
+ case ixgbe_phy_tw_tyco:
+ case ixgbe_phy_tw_unknown:
+ physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
+ break;
+ case ixgbe_phy_sfp_avago:
+ case ixgbe_phy_sfp_ftl:
+ case ixgbe_phy_sfp_intel:
+ case ixgbe_phy_sfp_unknown:
+ hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_10GBE_COMP_CODES, &comp_codes_10g);
+ if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
+ else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
+ break;
+ default:
+ break;
+ }
+
+out:
+ return physical_layer;
+}
+
+/**
+ * ixgbe_enable_rx_dma_82599 - Enable the Rx DMA unit on 82599
+ * @hw: pointer to hardware structure
+ * @regval: register value to write to RXCTRL
+ *
+ * Enables the Rx DMA unit for 82599
+ **/
+s32 ixgbe_enable_rx_dma_82599(struct ixgbe_hw *hw, u32 regval)
+{
+#define IXGBE_MAX_SECRX_POLL 30
+ int i;
+ int secrxreg;
+
+ /*
+ * Workaround for 82599 silicon errata when enabling the Rx datapath.
+ * If traffic is incoming before we enable the Rx unit, it could hang
+ * the Rx DMA unit. Therefore, make sure the security engine is
+ * completely disabled prior to enabling the Rx unit.
+ */
+ secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+ secrxreg |= IXGBE_SECRXCTRL_RX_DIS;
+ IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg);
+ for (i = 0; i < IXGBE_MAX_SECRX_POLL; i++) {
+ secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT);
+ if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY)
+ break;
+ else
+ /* Use interrupt-safe sleep just in case */
+ usec_delay(10);
+ }
+
+ /* For informational purposes only */
+ if (i >= IXGBE_MAX_SECRX_POLL)
+ DEBUGOUT("Rx unit being enabled before security "
+ "path fully disabled. Continuing with init.\n");
+
+ IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval);
+ secrxreg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
+ secrxreg &= ~IXGBE_SECRXCTRL_RX_DIS;
+ IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, secrxreg);
+ IXGBE_WRITE_FLUSH(hw);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_get_device_caps_82599 - Get additional device capabilities
+ * @hw: pointer to hardware structure
+ * @device_caps: the EEPROM word with the extra device capabilities
+ *
+ * This function will read the EEPROM location for the device capabilities,
+ * and return the word through device_caps.
+ **/
+s32 ixgbe_get_device_caps_82599(struct ixgbe_hw *hw, u16 *device_caps)
+{
+ hw->eeprom.ops.read(hw, IXGBE_DEVICE_CAPS, device_caps);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_get_san_mac_addr_offset_82599 - SAN MAC address offset for 82599
+ * @hw: pointer to hardware structure
+ * @san_mac_offset: SAN MAC address offset
+ *
+ * This function will read the EEPROM location for the SAN MAC address
+ * pointer, and returns the value at that location. This is used in both
+ * get and set mac_addr routines.
+ **/
+s32 ixgbe_get_san_mac_addr_offset_82599(struct ixgbe_hw *hw,
+ u16 *san_mac_offset)
+{
+ /*
+ * First read the EEPROM pointer to see if the MAC addresses are
+ * available.
+ */
+ hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_get_san_mac_addr_82599 - SAN MAC address retrieval for 82599
+ * @hw: pointer to hardware structure
+ * @san_mac_addr: SAN MAC address
+ *
+ * Reads the SAN MAC address from the EEPROM, if it's available. This is
+ * per-port, so set_lan_id() must be called before reading the addresses.
+ * set_lan_id() is called by identify_sfp(), but this cannot be relied
+ * upon for non-SFP connections, so we must call it here.
+ **/
+s32 ixgbe_get_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr)
+{
+ u16 san_mac_data, san_mac_offset;
+ u8 i;
+
+ /*
+ * First read the EEPROM pointer to see if the MAC addresses are
+ * available. If they're not, no point in calling set_lan_id() here.
+ */
+ ixgbe_get_san_mac_addr_offset_82599(hw, &san_mac_offset);
+
+ if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
+ /*
+ * No addresses available in this EEPROM. It's not an
+ * error though, so just wipe the local address and return.
+ */
+ for (i = 0; i < 6; i++)
+ san_mac_addr[i] = 0xFF;
+
+ goto san_mac_addr_out;
+ }
+
+ /* make sure we know which port we need to program */
+ hw->mac.ops.set_lan_id(hw);
+ /* apply the port offset to the address offset */
+ (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
+ (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
+ for (i = 0; i < 3; i++) {
+ hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data);
+ san_mac_addr[i * 2] = (u8)(san_mac_data);
+ san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8);
+ san_mac_offset++;
+ }
+
+san_mac_addr_out:
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_set_san_mac_addr_82599 - Write the SAN MAC address to the EEPROM
+ * @hw: pointer to hardware structure
+ * @san_mac_addr: SAN MAC address
+ *
+ * Write a SAN MAC address to the EEPROM.
+ **/
+s32 ixgbe_set_san_mac_addr_82599(struct ixgbe_hw *hw, u8 *san_mac_addr)
+{
+ s32 status = IXGBE_SUCCESS;
+ u16 san_mac_data, san_mac_offset;
+ u8 i;
+
+ /* Look for SAN mac address pointer. If not defined, return */
+ ixgbe_get_san_mac_addr_offset_82599(hw, &san_mac_offset);
+
+ if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
+ status = IXGBE_ERR_NO_SAN_ADDR_PTR;
+ goto san_mac_addr_out;
+ }
+
+ /* Make sure we know which port we need to write */
+ hw->mac.ops.set_lan_id(hw);
+ /* Apply the port offset to the address offset */
+ (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
+ (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
+
+ for (i = 0; i < 3; i++) {
+ san_mac_data = (u16)((u16)(san_mac_addr[i * 2 + 1]) << 8);
+ san_mac_data |= (u16)(san_mac_addr[i * 2]);
+ hw->eeprom.ops.write(hw, san_mac_offset, san_mac_data);
+ san_mac_offset++;
+ }
+
+san_mac_addr_out:
+ return status;
+}
diff --git a/sys/dev/ixgbe/ixgbe_api.c b/sys/dev/ixgbe/ixgbe_api.c
index 49dac7d..a3e7b35 100644
--- a/sys/dev/ixgbe/ixgbe_api.c
+++ b/sys/dev/ixgbe/ixgbe_api.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,7 @@
#include "ixgbe_common.h"
extern s32 ixgbe_init_ops_82598(struct ixgbe_hw *hw);
+extern s32 ixgbe_init_ops_82599(struct ixgbe_hw *hw);
/**
* ixgbe_init_shared_code - Initialize the shared code
@@ -62,6 +63,9 @@ s32 ixgbe_init_shared_code(struct ixgbe_hw *hw)
case ixgbe_mac_82598EB:
status = ixgbe_init_ops_82598(hw);
break;
+ case ixgbe_mac_82599EB:
+ status = ixgbe_init_ops_82599(hw);
+ break;
default:
status = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
break;
@@ -86,6 +90,7 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw)
if (hw->vendor_id == IXGBE_INTEL_VENDOR_ID) {
switch (hw->device_id) {
case IXGBE_DEV_ID_82598:
+ case IXGBE_DEV_ID_82598_BX:
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
case IXGBE_DEV_ID_82598AT:
@@ -97,6 +102,11 @@ s32 ixgbe_set_mac_type(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82598EB_SFP_LOM:
hw->mac.type = ixgbe_mac_82598EB;
break;
+ case IXGBE_DEV_ID_82599_KX4:
+ case IXGBE_DEV_ID_82599_SFP:
+ case IXGBE_DEV_ID_82599_CX4:
+ hw->mac.type = ixgbe_mac_82599EB;
+ break;
default:
ret_val = IXGBE_ERR_DEVICE_NOT_SUPPORTED;
break;
@@ -193,6 +203,46 @@ s32 ixgbe_get_mac_addr(struct ixgbe_hw *hw, u8 *mac_addr)
}
/**
+ * ixgbe_get_san_mac_addr - Get SAN MAC address
+ * @hw: pointer to hardware structure
+ * @san_mac_addr: SAN MAC address
+ *
+ * Reads the SAN MAC address from the EEPROM, if it's available. This is
+ * per-port, so set_lan_id() must be called before reading the addresses.
+ **/
+s32 ixgbe_get_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr)
+{
+ return ixgbe_call_func(hw, hw->mac.ops.get_san_mac_addr,
+ (hw, san_mac_addr), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_set_san_mac_addr - Write a SAN MAC address
+ * @hw: pointer to hardware structure
+ * @san_mac_addr: SAN MAC address
+ *
+ * Writes A SAN MAC address to the EEPROM.
+ **/
+s32 ixgbe_set_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr)
+{
+ return ixgbe_call_func(hw, hw->mac.ops.set_san_mac_addr,
+ (hw, san_mac_addr), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_get_device_caps - Get additional device capabilities
+ * @hw: pointer to hardware structure
+ * @device_caps: the EEPROM word for device capabilities
+ *
+ * Reads the extra device capabilities from the EEPROM
+ **/
+s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps)
+{
+ return ixgbe_call_func(hw, hw->mac.ops.get_device_caps,
+ (hw, device_caps), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
* ixgbe_get_bus_info - Set PCI bus info
* @hw: pointer to hardware structure
*
@@ -319,6 +369,9 @@ s32 ixgbe_get_phy_firmware_version(struct ixgbe_hw *hw, u16 *firmware_version)
s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
u16 *phy_data)
{
+ if (hw->phy.id == 0)
+ ixgbe_identify_phy(hw);
+
return ixgbe_call_func(hw, hw->phy.ops.read_reg, (hw, reg_addr,
device_type, phy_data), IXGBE_NOT_IMPLEMENTED);
}
@@ -334,6 +387,9 @@ s32 ixgbe_read_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
s32 ixgbe_write_phy_reg(struct ixgbe_hw *hw, u32 reg_addr, u32 device_type,
u16 phy_data)
{
+ if (hw->phy.id == 0)
+ ixgbe_identify_phy(hw);
+
return ixgbe_call_func(hw, hw->phy.ops.write_reg, (hw, reg_addr,
device_type, phy_data), IXGBE_NOT_IMPLEMENTED);
}
@@ -557,6 +613,22 @@ s32 ixgbe_update_eeprom_checksum(struct ixgbe_hw *hw)
}
/**
+ * ixgbe_insert_mac_addr - Find a RAR for this mac address
+ * @hw: pointer to hardware structure
+ * @addr: Address to put into receive address register
+ * @vmdq: VMDq pool to assign
+ *
+ * Puts an ethernet address into a receive address register, or
+ * finds the rar that it is aleady in; adds to the pool list
+ **/
+s32 ixgbe_insert_mac_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
+{
+ return ixgbe_call_func(hw, hw->mac.ops.insert_mac_addr,
+ (hw, addr, vmdq),
+ IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
* ixgbe_set_rar - Set Rx address register
* @hw: pointer to hardware structure
* @index: Receive address register to write
@@ -724,15 +796,15 @@ s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan, u32 vind, bool vlan_on)
}
/**
- * ixgbe_setup_fc - Set flow control
+ * ixgbe_fc_enable - Enable flow control
* @hw: pointer to hardware structure
* @packetbuf_num: packet buffer number (0-7)
*
* Configures the flow control settings based on SW configuration.
**/
-s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
+s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num)
{
- return ixgbe_call_func(hw, hw->mac.ops.setup_fc, (hw, packetbuf_num),
+ return ixgbe_call_func(hw, hw->mac.ops.fc_enable, (hw, packetbuf_num),
IXGBE_NOT_IMPLEMENTED);
}
@@ -778,6 +850,53 @@ s32 ixgbe_init_uta_tables(struct ixgbe_hw *hw)
}
/**
+ * ixgbe_read_i2c_byte - Reads 8 bit word over I2C at specified device address
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to read
+ * @data: value read
+ *
+ * Performs byte read operation to SFP module's EEPROM over I2C interface.
+ **/
+s32 ixgbe_read_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
+ u8 *data)
+{
+ return ixgbe_call_func(hw, hw->phy.ops.read_i2c_byte, (hw, byte_offset,
+ dev_addr, data), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_write_i2c_byte - Writes 8 bit word over I2C
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to write
+ * @data: value to write
+ *
+ * Performs byte write operation to SFP module's EEPROM over I2C interface
+ * at a specified device address.
+ **/
+s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
+ u8 data)
+{
+ return ixgbe_call_func(hw, hw->phy.ops.write_i2c_byte, (hw, byte_offset,
+ dev_addr, data), IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
+ * ixgbe_write_i2c_eeprom - Writes 8 bit EEPROM word over I2C interface
+ * @hw: pointer to hardware structure
+ * @byte_offset: EEPROM byte offset to write
+ * @eeprom_data: value to write
+ *
+ * Performs byte write operation to SFP module's EEPROM over I2C interface.
+ **/
+s32 ixgbe_write_i2c_eeprom(struct ixgbe_hw *hw,
+ u8 byte_offset, u8 eeprom_data)
+{
+ return ixgbe_call_func(hw, hw->phy.ops.write_i2c_eeprom,
+ (hw, byte_offset, eeprom_data),
+ IXGBE_NOT_IMPLEMENTED);
+}
+
+/**
* ixgbe_read_i2c_eeprom - Reads 8 bit EEPROM word over I2C interface
* @hw: pointer to hardware structure
* @byte_offset: EEPROM byte offset to read
@@ -803,3 +922,16 @@ u32 ixgbe_get_supported_physical_layer(struct ixgbe_hw *hw)
return ixgbe_call_func(hw, hw->mac.ops.get_supported_physical_layer,
(hw), IXGBE_PHYSICAL_LAYER_UNKNOWN);
}
+
+/**
+ * ixgbe_enable_rx_dma - Enables Rx DMA unit, dependant on device specifics
+ * @hw: pointer to hardware structure
+ * @regval: bitfield to write to the Rx DMA register
+ *
+ * Enables the Rx DMA unit of the device.
+ **/
+s32 ixgbe_enable_rx_dma(struct ixgbe_hw *hw, u32 regval)
+{
+ return ixgbe_call_func(hw, hw->mac.ops.enable_rx_dma,
+ (hw, regval), IXGBE_NOT_IMPLEMENTED);
+}
diff --git a/sys/dev/ixgbe/ixgbe_api.h b/sys/dev/ixgbe/ixgbe_api.h
index 8022f90..ba987ed 100644
--- a/sys/dev/ixgbe/ixgbe_api.h
+++ b/sys/dev/ixgbe/ixgbe_api.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -85,6 +85,7 @@ s32 ixgbe_read_eeprom(struct ixgbe_hw *hw, u16 offset, u16 *data);
s32 ixgbe_validate_eeprom_checksum(struct ixgbe_hw *hw, u16 *checksum_val);
s32 ixgbe_update_eeprom_checksum(struct ixgbe_hw *hw);
+s32 ixgbe_insert_mac_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
s32 ixgbe_set_rar(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
u32 enable_addr);
s32 ixgbe_clear_rar(struct ixgbe_hw *hw, u32 index);
@@ -102,7 +103,7 @@ s32 ixgbe_clear_vfta(struct ixgbe_hw *hw);
s32 ixgbe_set_vfta(struct ixgbe_hw *hw, u32 vlan,
u32 vind, bool vlan_on);
-s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
+s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packetbuf_num);
void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr);
s32 ixgbe_get_phy_firmware_version(struct ixgbe_hw *hw,
@@ -112,5 +113,54 @@ s32 ixgbe_write_analog_reg8(struct ixgbe_hw *hw, u32 reg, u8 val);
s32 ixgbe_init_uta_tables(struct ixgbe_hw *hw);
s32 ixgbe_read_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 *eeprom_data);
u32 ixgbe_get_supported_physical_layer(struct ixgbe_hw *hw);
+s32 ixgbe_enable_rx_dma(struct ixgbe_hw *hw, u32 regval);
+s32 ixgbe_reinit_fdir_tables_82599(struct ixgbe_hw *hw);
+s32 ixgbe_init_fdir_signature_82599(struct ixgbe_hw *hw, u32 pballoc);
+s32 ixgbe_init_fdir_perfect_82599(struct ixgbe_hw *hw, u32 pballoc);
+s32 ixgbe_fdir_add_signature_filter_82599(struct ixgbe_hw *hw,
+ struct ixgbe_atr_input *input,
+ u8 queue);
+s32 ixgbe_fdir_add_perfect_filter_82599(struct ixgbe_hw *hw,
+ struct ixgbe_atr_input *input,
+ u16 soft_id,
+ u8 queue);
+u16 ixgbe_atr_compute_hash_82599(struct ixgbe_atr_input *input, u32 key);
+s32 ixgbe_atr_set_vlan_id_82599(struct ixgbe_atr_input *input, u16 vlan_id);
+s32 ixgbe_atr_set_src_ipv4_82599(struct ixgbe_atr_input *input, u32 src_addr);
+s32 ixgbe_atr_set_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 dst_addr);
+s32 ixgbe_atr_set_src_ipv6_82599(struct ixgbe_atr_input *input, u32 src_addr_1,
+ u32 src_addr_2, u32 src_addr_3,
+ u32 src_addr_4);
+s32 ixgbe_atr_set_dst_ipv6_82599(struct ixgbe_atr_input *input, u32 dst_addr_1,
+ u32 dst_addr_2, u32 dst_addr_3,
+ u32 dst_addr_4);
+s32 ixgbe_atr_set_src_port_82599(struct ixgbe_atr_input *input, u16 src_port);
+s32 ixgbe_atr_set_dst_port_82599(struct ixgbe_atr_input *input, u16 dst_port);
+s32 ixgbe_atr_set_flex_byte_82599(struct ixgbe_atr_input *input, u16 flex_byte);
+s32 ixgbe_atr_set_vm_pool_82599(struct ixgbe_atr_input *input, u8 vm_pool);
+s32 ixgbe_atr_set_l4type_82599(struct ixgbe_atr_input *input, u8 l4type);
+s32 ixgbe_atr_get_vlan_id_82599(struct ixgbe_atr_input *input, u16 *vlan_id);
+s32 ixgbe_atr_get_src_ipv4_82599(struct ixgbe_atr_input *input, u32 *src_addr);
+s32 ixgbe_atr_get_dst_ipv4_82599(struct ixgbe_atr_input *input, u32 *dst_addr);
+s32 ixgbe_atr_get_src_ipv6_82599(struct ixgbe_atr_input *input, u32 *src_addr_1,
+ u32 *src_addr_2, u32 *src_addr_3,
+ u32 *src_addr_4);
+s32 ixgbe_atr_get_dst_ipv6_82599(struct ixgbe_atr_input *input, u32 *dst_addr_1,
+ u32 *dst_addr_2, u32 *dst_addr_3,
+ u32 *dst_addr_4);
+s32 ixgbe_atr_get_src_port_82599(struct ixgbe_atr_input *input, u16 *src_port);
+s32 ixgbe_atr_get_dst_port_82599(struct ixgbe_atr_input *input, u16 *dst_port);
+s32 ixgbe_atr_get_flex_byte_82599(struct ixgbe_atr_input *input,
+ u16 *flex_byte);
+s32 ixgbe_atr_get_vm_pool_82599(struct ixgbe_atr_input *input, u8 *vm_pool);
+s32 ixgbe_atr_get_l4type_82599(struct ixgbe_atr_input *input, u8 *l4type);
+s32 ixgbe_read_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
+ u8 *data);
+s32 ixgbe_write_i2c_byte(struct ixgbe_hw *hw, u8 byte_offset, u8 dev_addr,
+ u8 data);
+s32 ixgbe_write_i2c_eeprom(struct ixgbe_hw *hw, u8 byte_offset, u8 eeprom_data);
+s32 ixgbe_get_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr);
+s32 ixgbe_set_san_mac_addr(struct ixgbe_hw *hw, u8 *san_mac_addr);
+s32 ixgbe_get_device_caps(struct ixgbe_hw *hw, u16 *device_caps);
#endif /* _IXGBE_API_H_ */
diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c
index 53e4aff..030605c 100644
--- a/sys/dev/ixgbe/ixgbe_common.c
+++ b/sys/dev/ixgbe/ixgbe_common.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -49,11 +49,7 @@ static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
static u16 ixgbe_calc_eeprom_checksum(struct ixgbe_hw *hw);
-static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index);
-static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index);
static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
-void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr);
-void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
/**
* ixgbe_init_ops_generic - Inits function ptrs
@@ -86,6 +82,7 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
mac->ops.clear_hw_cntrs = &ixgbe_clear_hw_cntrs_generic;
mac->ops.get_media_type = NULL;
mac->ops.get_supported_physical_layer = NULL;
+ mac->ops.enable_rx_dma = &ixgbe_enable_rx_dma_generic;
mac->ops.get_mac_addr = &ixgbe_get_mac_addr_generic;
mac->ops.stop_adapter = &ixgbe_stop_adapter_generic;
mac->ops.get_bus_info = &ixgbe_get_bus_info_generic;
@@ -94,12 +91,13 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
/* LEDs */
mac->ops.led_on = &ixgbe_led_on_generic;
mac->ops.led_off = &ixgbe_led_off_generic;
- mac->ops.blink_led_start = NULL;
- mac->ops.blink_led_stop = NULL;
+ mac->ops.blink_led_start = &ixgbe_blink_led_start_generic;
+ mac->ops.blink_led_stop = &ixgbe_blink_led_stop_generic;
/* RAR, Multicast, VLAN */
mac->ops.set_rar = &ixgbe_set_rar_generic;
mac->ops.clear_rar = &ixgbe_clear_rar_generic;
+ mac->ops.insert_mac_addr = NULL;
mac->ops.set_vmdq = NULL;
mac->ops.clear_vmdq = NULL;
mac->ops.init_rx_addrs = &ixgbe_init_rx_addrs_generic;
@@ -111,6 +109,8 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
mac->ops.set_vfta = NULL;
mac->ops.init_uta_tables = NULL;
+ /* Flow Control */
+ mac->ops.fc_enable = &ixgbe_fc_enable_generic;
/* Link */
mac->ops.get_link_capabilities = NULL;
@@ -133,28 +133,16 @@ s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw)
s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
{
u32 ctrl_ext;
+ s32 ret_val = IXGBE_SUCCESS;
/* Set the media type */
hw->phy.media_type = hw->mac.ops.get_media_type(hw);
- /* Set bus info */
- hw->mac.ops.get_bus_info(hw);
-
- /* Identify the PHY */
- hw->phy.ops.identify(hw);
-
- /*
- * Store MAC address from RAR0, clear receive address registers, and
- * clear the multicast table
- */
- hw->mac.ops.init_rx_addrs(hw);
+ /* PHY ops initialization must be done in reset_hw() */
/* Clear the VLAN filter table */
hw->mac.ops.clear_vfta(hw);
- /* Set up link */
- hw->mac.ops.setup_link(hw);
-
/* Clear statistics registers */
hw->mac.ops.clear_hw_cntrs(hw);
@@ -164,10 +152,13 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
IXGBE_WRITE_FLUSH(hw);
+ /* Setup flow control */
+ ixgbe_setup_fc(hw, 0);
+
/* Clear adapter stopped flag */
hw->adapter_stopped = FALSE;
- return IXGBE_SUCCESS;
+ return ret_val;
}
/**
@@ -182,13 +173,17 @@ s32 ixgbe_start_hw_generic(struct ixgbe_hw *hw)
**/
s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw)
{
+ s32 status = IXGBE_SUCCESS;
+
/* Reset the hardware */
- hw->mac.ops.reset_hw(hw);
+ status = hw->mac.ops.reset_hw(hw);
- /* Start the HW */
- hw->mac.ops.start_hw(hw);
+ if (status == IXGBE_SUCCESS) {
+ /* Start the HW */
+ status = hw->mac.ops.start_hw(hw);
+ }
- return IXGBE_SUCCESS;
+ return status;
}
/**
@@ -214,15 +209,28 @@ s32 ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
IXGBE_READ_REG(hw, IXGBE_RLEC);
IXGBE_READ_REG(hw, IXGBE_LXONTXC);
IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
- IXGBE_READ_REG(hw, IXGBE_LXONRXC);
- IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+ if (hw->mac.type >= ixgbe_mac_82599EB) {
+ IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
+ IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+ } else {
+ IXGBE_READ_REG(hw, IXGBE_LXONRXC);
+ IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+ }
for (i = 0; i < 8; i++) {
IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
- IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
- IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+ if (hw->mac.type >= ixgbe_mac_82599EB) {
+ IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
+ IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
+ } else {
+ IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
+ IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+ }
}
+ if (hw->mac.type >= ixgbe_mac_82599EB)
+ for (i = 0; i < 8; i++)
+ IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
IXGBE_READ_REG(hw, IXGBE_PRC64);
IXGBE_READ_REG(hw, IXGBE_PRC127);
IXGBE_READ_REG(hw, IXGBE_PRC255);
@@ -391,6 +399,7 @@ void ixgbe_set_lan_id_multi_port_pcie(struct ixgbe_hw *hw)
reg = IXGBE_READ_REG(hw, IXGBE_STATUS);
bus->func = (reg & IXGBE_STATUS_LAN_ID) >> IXGBE_STATUS_LAN_ID_SHIFT;
+ bus->lan_id = bus->func;
/* check for a port swap */
reg = IXGBE_READ_REG(hw, IXGBE_FACTPS);
@@ -595,7 +604,6 @@ s32 ixgbe_write_eeprom_generic(struct ixgbe_hw *hw, u16 offset, u16 data)
ixgbe_shift_out_eeprom_bits(hw, data, 16);
ixgbe_standby_eeprom(hw);
- msec_delay(hw->eeprom.semaphore_delay);
/* Done with writing - release the EEPROM */
ixgbe_release_eeprom(hw);
}
@@ -802,7 +810,7 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
status = IXGBE_SUCCESS;
break;
}
- msec_delay(1);
+ usec_delay(50);
}
/* Now get the semaphore between SW/FW through the SWESMBI bit */
@@ -830,11 +838,14 @@ static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
* was not granted because we don't have access to the EEPROM
*/
if (i >= timeout) {
- DEBUGOUT("Driver can't access the Eeprom - Semaphore "
+ DEBUGOUT("SWESMBI Software EEPROM semaphore "
"not granted.\n");
ixgbe_release_eeprom_semaphore(hw);
status = IXGBE_ERR_EEPROM;
}
+ } else {
+ DEBUGOUT("Software semaphore SMBI between device drivers "
+ "not granted.\n");
}
return status;
@@ -1296,38 +1307,6 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
}
/**
- * ixgbe_enable_rar - Enable Rx address register
- * @hw: pointer to hardware structure
- * @index: index into the RAR table
- *
- * Enables the select receive address register.
- **/
-static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index)
-{
- u32 rar_high;
-
- rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
- rar_high |= IXGBE_RAH_AV;
- IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
-}
-
-/**
- * ixgbe_disable_rar - Disable Rx address register
- * @hw: pointer to hardware structure
- * @index: index into the RAR table
- *
- * Disables the select receive address register.
- **/
-static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index)
-{
- u32 rar_high;
-
- rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
- rar_high &= (~IXGBE_RAH_AV);
- IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
-}
-
-/**
* ixgbe_init_rx_addrs_generic - Initializes receive address filters.
* @hw: pointer to hardware structure
*
@@ -1378,7 +1357,6 @@ s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw)
}
/* Clear the MTA */
- hw->addr_ctrl.mc_addr_in_rar_count = 0;
hw->addr_ctrl.mta_in_use = 0;
IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
@@ -1411,8 +1389,7 @@ void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
* else put the controller into promiscuous mode
*/
if (hw->addr_ctrl.rar_used_count < rar_entries) {
- rar = hw->addr_ctrl.rar_used_count -
- hw->addr_ctrl.mc_addr_in_rar_count;
+ rar = hw->addr_ctrl.rar_used_count;
hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
DEBUGOUT1("Added a secondary address to RAR[%d]\n", rar);
hw->addr_ctrl.rar_used_count++;
@@ -1451,14 +1428,13 @@ s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
* Clear accounting of old secondary address list,
* don't count RAR[0]
*/
- uc_addr_in_use = hw->addr_ctrl.rar_used_count -
- hw->addr_ctrl.mc_addr_in_rar_count - 1;
+ uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1;
hw->addr_ctrl.rar_used_count -= uc_addr_in_use;
hw->addr_ctrl.overflow_promisc = 0;
/* Zero out the other receive addresses */
- DEBUGOUT1("Clearing RAR[1-%d]\n", uc_addr_in_use);
- for (i = 1; i <= uc_addr_in_use; i++) {
+ DEBUGOUT1("Clearing RAR[1-%d]\n", hw->addr_ctrl.rar_used_count);
+ for (i = 1; i <= hw->addr_ctrl.rar_used_count; i++) {
IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
}
@@ -1568,40 +1544,6 @@ void ixgbe_set_mta(struct ixgbe_hw *hw, u8 *mc_addr)
}
/**
- * ixgbe_add_mc_addr - Adds a multicast address.
- * @hw: pointer to hardware structure
- * @mc_addr: new multicast address
- *
- * Adds it to unused receive address register or to the multicast table.
- **/
-void ixgbe_add_mc_addr(struct ixgbe_hw *hw, u8 *mc_addr)
-{
- u32 rar_entries = hw->mac.num_rar_entries;
- u32 rar;
-
- DEBUGOUT6(" MC Addr =%.2X %.2X %.2X %.2X %.2X %.2X\n",
- mc_addr[0], mc_addr[1], mc_addr[2],
- mc_addr[3], mc_addr[4], mc_addr[5]);
-
- /*
- * Place this multicast address in the RAR if there is room,
- * else put it in the MTA
- */
- if (hw->addr_ctrl.rar_used_count < rar_entries) {
- /* use RAR from the end up for multicast */
- rar = rar_entries - hw->addr_ctrl.mc_addr_in_rar_count - 1;
- hw->mac.ops.set_rar(hw, rar, mc_addr, 0, IXGBE_RAH_AV);
- DEBUGOUT1("Added a multicast address to RAR[%d]\n", rar);
- hw->addr_ctrl.rar_used_count++;
- hw->addr_ctrl.mc_addr_in_rar_count++;
- } else {
- ixgbe_set_mta(hw, mc_addr);
- }
-
- DEBUGOUT("ixgbe_add_mc_addr Complete\n");
-}
-
-/**
* ixgbe_update_mc_addr_list_generic - Updates MAC list of multicast addresses
* @hw: pointer to hardware structure
* @mc_addr_list: the list of new multicast addresses
@@ -1617,7 +1559,6 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
u32 mc_addr_count, ixgbe_mc_addr_itr next)
{
u32 i;
- u32 rar_entries = hw->mac.num_rar_entries;
u32 vmdq;
/*
@@ -1625,18 +1566,8 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
* use.
*/
hw->addr_ctrl.num_mc_addrs = mc_addr_count;
- hw->addr_ctrl.rar_used_count -= hw->addr_ctrl.mc_addr_in_rar_count;
- hw->addr_ctrl.mc_addr_in_rar_count = 0;
hw->addr_ctrl.mta_in_use = 0;
- /* Zero out the other receive addresses. */
- DEBUGOUT2("Clearing RAR[%d-%d]\n", hw->addr_ctrl.rar_used_count,
- rar_entries - 1);
- for (i = hw->addr_ctrl.rar_used_count; i < rar_entries; i++) {
- IXGBE_WRITE_REG(hw, IXGBE_RAL(i), 0);
- IXGBE_WRITE_REG(hw, IXGBE_RAH(i), 0);
- }
-
/* Clear the MTA */
DEBUGOUT(" Clearing MTA\n");
for (i = 0; i < hw->mac.mcft_size; i++)
@@ -1645,7 +1576,7 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
/* Add the new addresses */
for (i = 0; i < mc_addr_count; i++) {
DEBUGOUT(" Adding the multicast addresses:\n");
- ixgbe_add_mc_addr(hw, next(hw, &mc_addr_list, &vmdq));
+ ixgbe_set_mta(hw, next(hw, &mc_addr_list, &vmdq));
}
/* Enable mta */
@@ -1665,15 +1596,8 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
**/
s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
{
- u32 i;
- u32 rar_entries = hw->mac.num_rar_entries;
struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
- if (a->mc_addr_in_rar_count > 0)
- for (i = (rar_entries - a->mc_addr_in_rar_count);
- i < rar_entries; i++)
- ixgbe_enable_rar(hw, i);
-
if (a->mta_in_use > 0)
IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE |
hw->mac.mc_filter_type);
@@ -1689,52 +1613,56 @@ s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
**/
s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
{
- u32 i;
- u32 rar_entries = hw->mac.num_rar_entries;
struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
- if (a->mc_addr_in_rar_count > 0)
- for (i = (rar_entries - a->mc_addr_in_rar_count);
- i < rar_entries; i++)
- ixgbe_disable_rar(hw, i);
-
if (a->mta_in_use > 0)
IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
return IXGBE_SUCCESS;
}
-
/**
- * ixgbe_fc_autoneg - Configure flow control
+ * ixgbe_fc_enable_generic - Enable flow control
* @hw: pointer to hardware structure
+ * @packetbuf_num: packet buffer number (0-7)
*
- * Negotiates flow control capabilities with link partner using autoneg and
- * applies the results.
+ * Enable flow control according to the current settings.
**/
-s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packetbuf_num)
{
s32 ret_val = IXGBE_SUCCESS;
- u32 i, reg, pcs_anadv_reg, pcs_lpab_reg;
+ u32 mflcn_reg, fccfg_reg;
+ u32 reg;
- DEBUGFUNC("ixgbe_fc_autoneg");
+ DEBUGFUNC("ixgbe_fc_enable_generic");
- reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+ /* Negotiate the fc mode to use */
+ ret_val = ixgbe_fc_autoneg(hw);
+ if (ret_val)
+ goto out;
+
+ /* Disable any previous flow control settings */
+ mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
+ mflcn_reg &= ~(IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE);
+
+ fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
+ fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY);
/*
* The possible values of fc.current_mode are:
- * 0: Flow control is completely disabled
- * 1: Rx flow control is enabled (we can receive pause frames,
- * but not send pause frames).
- * 2: Tx flow control is enabled (we can send pause frames but
- * we do not support receiving pause frames).
- * 3: Both Rx and Tx flow control (symmetric) are enabled.
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames,
+ * but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but
+ * we do not support receiving pause frames).
+ * 3: Both Rx and Tx flow control (symmetric) are enabled.
* other: Invalid.
*/
switch (hw->fc.current_mode) {
case ixgbe_fc_none:
- /* Flow control completely disabled by software override. */
- reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ /* Flow control is disabled by software override or autoneg.
+ * The code below will actually disable it in the HW.
+ */
break;
case ixgbe_fc_rx_pause:
/*
@@ -1745,19 +1673,19 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
* symmetric and asymmetric Rx PAUSE. Later, we will
* disable the adapter's ability to send PAUSE frames.
*/
- reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ mflcn_reg |= IXGBE_MFLCN_RFCE;
break;
case ixgbe_fc_tx_pause:
/*
* Tx Flow control is enabled, and Rx Flow control is
* disabled by software override.
*/
- reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
- reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
+ fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
break;
case ixgbe_fc_full:
/* Flow control (both Rx and Tx) is enabled by SW override. */
- reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ mflcn_reg |= IXGBE_MFLCN_RFCE;
+ fccfg_reg |= IXGBE_FCCFG_TFCE_802_3X;
break;
default:
DEBUGOUT("Flow control param set incorrectly\n");
@@ -1766,39 +1694,80 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
break;
}
- IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
- reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
+ /* Set 802.3x based flow control settings. */
+ mflcn_reg |= IXGBE_MFLCN_DPF;
+ IXGBE_WRITE_REG(hw, IXGBE_MFLCN, mflcn_reg);
+ IXGBE_WRITE_REG(hw, IXGBE_FCCFG, fccfg_reg);
- /* Set PCS register for autoneg */
- /* Enable and restart autoneg */
- reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART;
+ /* Set up and enable Rx high/low water mark thresholds, enable XON. */
+ if (hw->fc.current_mode & ixgbe_fc_tx_pause) {
+ if (hw->fc.send_xon) {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num),
+ (hw->fc.low_water | IXGBE_FCRTL_XONE));
+ } else {
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(packetbuf_num),
+ hw->fc.low_water);
+ }
- /* Disable AN timeout */
- if (hw->fc.strict_ieee)
- reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(packetbuf_num),
+ (hw->fc.high_water | IXGBE_FCRTH_FCEN));
+ }
- DEBUGOUT1("Configuring Autoneg; PCS_LCTL = 0x%08X\n", reg);
- IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+ /* Configure pause time (2 TCs per register) */
+ reg = IXGBE_READ_REG(hw, IXGBE_FCTTV(packetbuf_num));
+ if ((packetbuf_num & 1) == 0)
+ reg = (reg & 0xFFFF0000) | hw->fc.pause_time;
+ else
+ reg = (reg & 0x0000FFFF) | (hw->fc.pause_time << 16);
+ IXGBE_WRITE_REG(hw, IXGBE_FCTTV(packetbuf_num / 2), reg);
- /* See if autonegotiation has succeeded */
- hw->mac.autoneg_succeeded = 0;
- for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) {
- msec_delay(10);
- reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
- if ((reg & (IXGBE_PCS1GLSTA_LINK_OK |
- IXGBE_PCS1GLSTA_AN_COMPLETE)) ==
- (IXGBE_PCS1GLSTA_LINK_OK |
- IXGBE_PCS1GLSTA_AN_COMPLETE)) {
- if (!(reg & IXGBE_PCS1GLSTA_AN_TIMED_OUT))
- hw->mac.autoneg_succeeded = 1;
- break;
- }
- }
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, (hw->fc.pause_time >> 1));
- if (!hw->mac.autoneg_succeeded) {
- /* Autoneg failed to achieve a link, so we turn fc off */
- hw->fc.current_mode = ixgbe_fc_none;
- DEBUGOUT("Flow Control = NONE.\n");
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_fc_autoneg - Configure flow control
+ * @hw: pointer to hardware structure
+ *
+ * Compares our advertised flow control capabilities to those advertised by
+ * our link partner, and determines the proper flow control mode to use.
+ **/
+s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
+{
+ s32 ret_val = IXGBE_SUCCESS;
+ ixgbe_link_speed speed;
+ u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
+ bool link_up;
+
+ DEBUGFUNC("ixgbe_fc_autoneg");
+
+ /*
+ * AN should have completed when the cable was plugged in.
+ * Look for reasons to bail out. Bail out if:
+ * - FC autoneg is disabled, or if
+ * - we don't have multispeed fiber, or if
+ * - we're not running at 1G, or if
+ * - link is not up, or if
+ * - link is up but AN did not complete, or if
+ * - link is up and AN completed but timed out
+ *
+ * Since we're being called from an LSC, link is already know to be up.
+ * So use link_up_wait_to_complete=FALSE.
+ */
+ hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
+ linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
+
+ if (hw->fc.disable_fc_autoneg ||
+ !hw->phy.multispeed_fiber ||
+ (speed != IXGBE_LINK_SPEED_1GB_FULL) ||
+ !link_up ||
+ ((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+ ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+ hw->fc.fc_was_autonegged = FALSE;
+ hw->fc.current_mode = hw->fc.requested_mode;
+ DEBUGOUT("Autoneg FC was skipped.\n");
goto out;
}
@@ -1841,10 +1810,128 @@ s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
DEBUGOUT("Flow Control = NONE.\n");
}
+ /* Record that current_mode is the result of a successful autoneg */
+ hw->fc.fc_was_autonegged = TRUE;
+
out:
return ret_val;
}
+/**
+ * ixgbe_setup_fc - Set up flow control
+ * @hw: pointer to hardware structure
+ *
+ * Called at init time to set up flow control.
+ **/
+s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
+{
+ s32 ret_val = IXGBE_SUCCESS;
+ u32 reg;
+
+
+ /* Validate the packetbuf configuration */
+ if (packetbuf_num < 0 || packetbuf_num > 7) {
+ DEBUGOUT1("Invalid packet buffer number [%d], expected range is"
+ " 0-7\n", packetbuf_num);
+ ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+ goto out;
+ }
+
+ /*
+ * Validate the water mark configuration. Zero water marks are invalid
+ * because it causes the controller to just blast out fc packets.
+ */
+ if (!hw->fc.low_water || !hw->fc.high_water || !hw->fc.pause_time) {
+ DEBUGOUT("Invalid water mark configuration\n");
+ ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+ goto out;
+ }
+
+ /*
+ * Validate the requested mode. Strict IEEE mode does not allow
+ * ixgbe_fc_rx_pause because it will cause us to fail at UNH.
+ */
+ if (hw->fc.strict_ieee && hw->fc.requested_mode == ixgbe_fc_rx_pause) {
+ DEBUGOUT("ixgbe_fc_rx_pause not valid in strict IEEE mode\n");
+ ret_val = IXGBE_ERR_INVALID_LINK_SETTINGS;
+ goto out;
+ }
+
+ /*
+ * 10gig parts do not have a word in the EEPROM to determine the
+ * default flow control setting, so we explicitly set it to full.
+ */
+ if (hw->fc.requested_mode == ixgbe_fc_default)
+ hw->fc.requested_mode = ixgbe_fc_full;
+
+ /*
+ * Set up the 1G flow control advertisement registers so the HW will be
+ * able to do fc autoneg once the cable is plugged in. If we end up
+ * using 10g instead, this is harmless.
+ */
+ reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+
+ /*
+ * The possible values of fc.requested_mode are:
+ * 0: Flow control is completely disabled
+ * 1: Rx flow control is enabled (we can receive pause frames,
+ * but not send pause frames).
+ * 2: Tx flow control is enabled (we can send pause frames but
+ * we do not support receiving pause frames).
+ * 3: Both Rx and Tx flow control (symmetric) are enabled.
+ * other: Invalid.
+ */
+ switch (hw->fc.requested_mode) {
+ case ixgbe_fc_none:
+ /* Flow control completely disabled by software override. */
+ reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ break;
+ case ixgbe_fc_rx_pause:
+ /*
+ * Rx Flow control is enabled and Tx Flow control is
+ * disabled by software override. Since there really
+ * isn't a way to advertise that we are capable of RX
+ * Pause ONLY, we will advertise that we support both
+ * symmetric and asymmetric Rx PAUSE. Later, we will
+ * disable the adapter's ability to send PAUSE frames.
+ */
+ reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ break;
+ case ixgbe_fc_tx_pause:
+ /*
+ * Tx Flow control is enabled, and Rx Flow control is
+ * disabled by software override.
+ */
+ reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
+ reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
+ break;
+ case ixgbe_fc_full:
+ /* Flow control (both Rx and Tx) is enabled by SW override. */
+ reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+ break;
+ default:
+ DEBUGOUT("Flow control param set incorrectly\n");
+ ret_val = -IXGBE_ERR_CONFIG;
+ goto out;
+ break;
+ }
+
+ IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
+ reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
+
+ /* Enable and restart autoneg to inform the link partner */
+ reg |= IXGBE_PCS1GLCTL_AN_ENABLE | IXGBE_PCS1GLCTL_AN_RESTART;
+
+ /* Disable AN timeout */
+ if (hw->fc.strict_ieee)
+ reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+
+ IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+ DEBUGOUT1("Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+
+out:
+ return ret_val;
+}
/**
* ixgbe_disable_pcie_master - Disable PCI-express master access
@@ -1904,6 +1991,10 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
s32 timeout = 200;
while (timeout) {
+ /*
+ * SW EEPROM semaphore bit is used for access to all
+ * SW_FW_SYNC/GSSR bits (not just EEPROM)
+ */
if (ixgbe_get_eeprom_semaphore(hw))
return -IXGBE_ERR_SWFW_SYNC;
@@ -1921,7 +2012,7 @@ s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
}
if (!timeout) {
- DEBUGOUT("Driver can't access resource, GSSR timeout.\n");
+ DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n");
return -IXGBE_ERR_SWFW_SYNC;
}
@@ -1952,5 +2043,77 @@ void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
IXGBE_WRITE_REG(hw, IXGBE_GSSR, gssr);
ixgbe_release_eeprom_semaphore(hw);
+
+ /* Delay before attempt to obtain semaphore again to allow FW access */
+ msec_delay(hw->eeprom.semaphore_delay);
+}
+
+/**
+ * ixgbe_enable_rx_dma_generic - Enable the Rx DMA unit
+ * @hw: pointer to hardware structure
+ * @regval: register value to write to RXCTRL
+ *
+ * Enables the Rx DMA unit
+ **/
+s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval)
+{
+ IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, regval);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_blink_led_start_generic - Blink LED based on index.
+ * @hw: pointer to hardware structure
+ * @index: led number to blink
+ **/
+s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index)
+{
+ ixgbe_link_speed speed = 0;
+ bool link_up = 0;
+ u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+
+ /*
+ * Link must be up to auto-blink the LEDs;
+ * Force it if link is down.
+ */
+ hw->mac.ops.check_link(hw, &speed, &link_up, FALSE);
+
+ if (!link_up) {
+ autoc_reg |= IXGBE_AUTOC_FLU;
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+ msec_delay(10);
+ }
+
+ led_reg &= ~IXGBE_LED_MODE_MASK(index);
+ led_reg |= IXGBE_LED_BLINK(index);
+ IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
+ IXGBE_WRITE_FLUSH(hw);
+
+ return IXGBE_SUCCESS;
+}
+
+/**
+ * ixgbe_blink_led_stop_generic - Stop blinking LED based on index.
+ * @hw: pointer to hardware structure
+ * @index: led number to stop blinking
+ **/
+s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index)
+{
+ u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+ u32 led_reg = IXGBE_READ_REG(hw, IXGBE_LEDCTL);
+
+ autoc_reg &= ~IXGBE_AUTOC_FLU;
+ autoc_reg |= IXGBE_AUTOC_AN_RESTART;
+ IXGBE_WRITE_REG(hw, IXGBE_AUTOC, autoc_reg);
+
+ led_reg &= ~IXGBE_LED_MODE_MASK(index);
+ led_reg &= ~IXGBE_LED_BLINK(index);
+ led_reg |= IXGBE_LED_LINK_ACTIVE << IXGBE_LED_MODE_SHIFT(index);
+ IXGBE_WRITE_REG(hw, IXGBE_LEDCTL, led_reg);
+ IXGBE_WRITE_FLUSH(hw);
+
+ return IXGBE_SUCCESS;
}
diff --git a/sys/dev/ixgbe/ixgbe_common.h b/sys/dev/ixgbe/ixgbe_common.h
index d94f674..0c53575 100644
--- a/sys/dev/ixgbe/ixgbe_common.h
+++ b/sys/dev/ixgbe/ixgbe_common.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,11 @@
#define _IXGBE_COMMON_H_
#include "ixgbe_type.h"
+#define IXGBE_WRITE_REG64(hw, reg, value) \
+ do { \
+ IXGBE_WRITE_REG(hw, reg, (u32) value); \
+ IXGBE_WRITE_REG(hw, reg + 4, (u32) (value >> 32)); \
+ } while (0)
s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_hw_generic(struct ixgbe_hw *hw);
@@ -68,11 +73,13 @@ s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw, u8 *mc_addr_list,
ixgbe_mc_addr_itr func);
s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw, u8 *addr_list,
u32 addr_count, ixgbe_mc_addr_itr func);
+void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw);
s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw);
+s32 ixgbe_enable_rx_dma_generic(struct ixgbe_hw *hw, u32 regval);
-s32 ixgbe_setup_fc_generic(struct ixgbe_hw *hw, s32 packetbuf_num);
-s32 ixgbe_fc_enable(struct ixgbe_hw *hw, s32 packtetbuf_num);
+s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
+s32 ixgbe_fc_enable_generic(struct ixgbe_hw *hw, s32 packtetbuf_num);
s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw);
s32 ixgbe_validate_mac_addr(u8 *mac_addr);
@@ -82,4 +89,7 @@ s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw);
s32 ixgbe_read_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 *val);
s32 ixgbe_write_analog_reg8_generic(struct ixgbe_hw *hw, u32 reg, u8 val);
+s32 ixgbe_blink_led_start_generic(struct ixgbe_hw *hw, u32 index);
+s32 ixgbe_blink_led_stop_generic(struct ixgbe_hw *hw, u32 index);
+
#endif /* IXGBE_COMMON */
diff --git a/sys/dev/ixgbe/ixgbe_osdep.h b/sys/dev/ixgbe/ixgbe_osdep.h
index be6f577..53b64f5 100644
--- a/sys/dev/ixgbe/ixgbe_osdep.h
+++ b/sys/dev/ixgbe/ixgbe_osdep.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -96,6 +96,7 @@ typedef boolean_t bool;
#define le16_to_cpu
+#if __FreeBSD_version < 800000
#if defined(__i386__) || defined(__amd64__)
#define mb() __asm volatile("mfence" ::: "memory")
#define wmb() __asm volatile("sfence" ::: "memory")
@@ -105,6 +106,7 @@ typedef boolean_t bool;
#define rmb()
#define wmb()
#endif
+#endif
struct ixgbe_osdep
{
@@ -113,11 +115,14 @@ struct ixgbe_osdep
struct device *dev;
};
-/* This is needed by the shared code */
+/* These routines are needed by the shared code */
struct ixgbe_hw;
extern u16 ixgbe_read_pci_cfg(struct ixgbe_hw *, u32);
#define IXGBE_READ_PCIE_WORD ixgbe_read_pci_cfg
+extern void ixgbe_write_pci_cfg(struct ixgbe_hw *, u32, u16);
+#define IXGBE_WRITE_PCIE_WORD ixgbe_write_pci_cfg
+
#define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS)
#define IXGBE_READ_REG(a, reg) (\
diff --git a/sys/dev/ixgbe/ixgbe_phy.c b/sys/dev/ixgbe/ixgbe_phy.c
index 291d454..afd30ee 100644
--- a/sys/dev/ixgbe/ixgbe_phy.c
+++ b/sys/dev/ixgbe/ixgbe_phy.c
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,19 @@
#include "ixgbe_common.h"
#include "ixgbe_phy.h"
+static void ixgbe_i2c_start(struct ixgbe_hw *hw);
+static void ixgbe_i2c_stop(struct ixgbe_hw *hw);
+static s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data);
+static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data);
+static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw);
+static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data);
+static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data);
+static s32 ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl);
+static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl);
+static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data);
+static bool ixgbe_get_i2c_data(u32 *i2cctl);
+void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw);
+
/**
* ixgbe_init_phy_ops_generic - Inits PHY function ptrs
* @hw: pointer to the hardware structure
@@ -55,6 +68,11 @@ s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw)
phy->ops.setup_link_speed = &ixgbe_setup_phy_link_speed_generic;
phy->ops.check_link = NULL;
phy->ops.get_firmware_version = NULL;
+ phy->ops.read_i2c_byte = &ixgbe_read_i2c_byte_generic;
+ phy->ops.write_i2c_byte = &ixgbe_write_i2c_byte_generic;
+ phy->ops.read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic;
+ phy->ops.write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic;
+ phy->ops.i2c_bus_clear = &ixgbe_i2c_bus_clear;
phy->ops.identify_sfp = &ixgbe_identify_sfp_module_generic;
phy->sfp_type = ixgbe_sfp_type_unknown;
@@ -71,6 +89,7 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
{
s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
u32 phy_addr;
+ u16 ext_ability = 0;
if (hw->phy.type == ixgbe_phy_unknown) {
for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
@@ -79,10 +98,29 @@ s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw)
ixgbe_get_phy_id(hw);
hw->phy.type =
ixgbe_get_phy_type_from_id(hw->phy.id);
+
+ if (hw->phy.type == ixgbe_phy_unknown) {
+ hw->phy.ops.read_reg(hw,
+ IXGBE_MDIO_PHY_EXT_ABILITY,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+ &ext_ability);
+ if (ext_ability &
+ IXGBE_MDIO_PHY_10GBASET_ABILITY ||
+ ext_ability &
+ IXGBE_MDIO_PHY_1000BASET_ABILITY)
+ hw->phy.type =
+ ixgbe_phy_cu_unknown;
+ else
+ hw->phy.type =
+ ixgbe_phy_generic;
+ }
+
status = IXGBE_SUCCESS;
break;
}
}
+ if (status != IXGBE_SUCCESS)
+ hw->phy.addr = 0;
} else {
status = IXGBE_SUCCESS;
}
@@ -149,6 +187,9 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
case TN1010_PHY_ID:
phy_type = ixgbe_phy_tn;
break;
+ case AQ1002_PHY_ID:
+ phy_type = ixgbe_phy_aq;
+ break;
case QT2022_PHY_ID:
phy_type = ixgbe_phy_qt;
break;
@@ -170,13 +211,40 @@ enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
**/
s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
{
+ u32 i;
+ u16 ctrl = 0;
+ s32 status = IXGBE_SUCCESS;
+
+ if (hw->phy.type == ixgbe_phy_unknown)
+ status = ixgbe_identify_phy_generic(hw);
+
+ if (status != IXGBE_SUCCESS || hw->phy.type == ixgbe_phy_none)
+ goto out;
+
/*
* Perform soft PHY reset to the PHY_XS.
* This will cause a soft reset to the PHY
*/
- return hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
- IXGBE_MDIO_PHY_XS_DEV_TYPE,
- IXGBE_MDIO_PHY_XS_RESET);
+ hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
+ IXGBE_MDIO_PHY_XS_DEV_TYPE,
+ IXGBE_MDIO_PHY_XS_RESET);
+
+ /* Poll for reset bit to self-clear indicating reset is complete */
+ for (i = 0; i < 500; i++) {
+ msec_delay(1);
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
+ IXGBE_MDIO_PHY_XS_DEV_TYPE, &ctrl);
+ if (!(ctrl & IXGBE_MDIO_PHY_XS_RESET))
+ break;
+ }
+
+ if (ctrl & IXGBE_MDIO_PHY_XS_RESET) {
+ status = IXGBE_ERR_RESET_FAILED;
+ DEBUGOUT("PHY reset polling failed to complete.\n");
+ }
+
+out:
+ return status;
}
/**
@@ -454,6 +522,9 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
if (speed & IXGBE_LINK_SPEED_1GB_FULL)
hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
+ if (speed & IXGBE_LINK_SPEED_100_FULL)
+ hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
+
/* Setup link based on the new speed settings */
hw->phy.ops.setup_link(hw);
@@ -461,6 +532,40 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
}
/**
+ * ixgbe_get_copper_link_capabilities_generic - Determines link capabilities
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @autoneg: boolean auto-negotiation value
+ *
+ * Determines the link capabilities by reading the AUTOC register.
+ **/
+s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *autoneg)
+{
+ s32 status = IXGBE_ERR_LINK_SETUP;
+ u16 speed_ability;
+
+ *speed = 0;
+ *autoneg = TRUE;
+
+ status = hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_SPEED_ABILITY,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+ &speed_ability);
+
+ if (status == IXGBE_SUCCESS) {
+ if (speed_ability & IXGBE_MDIO_PHY_SPEED_10G)
+ *speed |= IXGBE_LINK_SPEED_10GB_FULL;
+ if (speed_ability & IXGBE_MDIO_PHY_SPEED_1G)
+ *speed |= IXGBE_LINK_SPEED_1GB_FULL;
+ if (speed_ability & IXGBE_MDIO_PHY_SPEED_100M)
+ *speed |= IXGBE_LINK_SPEED_100_FULL;
+ }
+
+ return status;
+}
+
+/**
* ixgbe_check_phy_link_tnx - Determine link and speed status
* @hw: pointer to hardware structure
*
@@ -525,6 +630,24 @@ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
return status;
}
+
+/**
+ * ixgbe_get_phy_firmware_version_aq - Gets the PHY Firmware Version
+ * @hw: pointer to hardware structure
+ * @firmware_version: pointer to the PHY Firmware Version
+ **/
+s32 ixgbe_get_phy_firmware_version_aq(struct ixgbe_hw *hw,
+ u16 *firmware_version)
+{
+ s32 status = IXGBE_SUCCESS;
+
+ status = hw->phy.ops.read_reg(hw, AQ_FW_REV,
+ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ firmware_version);
+
+ return status;
+}
+
/**
* ixgbe_reset_phy_nl - Performs a PHY reset
* @hw: pointer to hardware structure
@@ -632,20 +755,30 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
{
s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
u32 vendor_oui = 0;
+ enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
u8 identifier = 0;
u8 comp_codes_1g = 0;
u8 comp_codes_10g = 0;
- u8 oui_bytes[4] = {0, 0, 0, 0};
+ u8 oui_bytes[3] = {0, 0, 0};
u8 transmission_media = 0;
+ u16 enforce_sfp = 0;
status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
&identifier);
- if (status == IXGBE_ERR_SFP_NOT_PRESENT) {
+ if (status == IXGBE_ERR_SFP_NOT_PRESENT || status == IXGBE_ERR_I2C) {
+ status = IXGBE_ERR_SFP_NOT_PRESENT;
hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+ if (hw->phy.type != ixgbe_phy_nl) {
+ hw->phy.id = 0;
+ hw->phy.type = ixgbe_phy_unknown;
+ }
goto out;
}
+ /* LAN ID is needed for sfp_type determination */
+ hw->mac.ops.set_lan_id(hw);
+
if (identifier == IXGBE_SFF_IDENTIFIER_SFP) {
hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES,
&comp_codes_1g);
@@ -659,22 +792,57 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
* 0 SFP_DA_CU
* 1 SFP_SR
* 2 SFP_LR
+ * 3 SFP_DA_CORE0 - 82599-specific
+ * 4 SFP_DA_CORE1 - 82599-specific
+ * 5 SFP_SR/LR_CORE0 - 82599-specific
+ * 6 SFP_SR/LR_CORE1 - 82599-specific
*/
- if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE)
- hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
- else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
- hw->phy.sfp_type = ixgbe_sfp_type_sr;
- else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
- hw->phy.sfp_type = ixgbe_sfp_type_lr;
- else
- hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+ if (hw->mac.type == ixgbe_mac_82598EB) {
+ if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE)
+ hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
+ else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
+ hw->phy.sfp_type = ixgbe_sfp_type_sr;
+ else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
+ hw->phy.sfp_type = ixgbe_sfp_type_lr;
+ else
+ hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+ } else if (hw->mac.type == ixgbe_mac_82599EB) {
+ if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE)
+ if (hw->bus.lan_id == 0)
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_da_cu_core0;
+ else
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_da_cu_core1;
+ else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
+ if (hw->bus.lan_id == 0)
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_srlr_core0;
+ else
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_srlr_core1;
+ else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
+ if (hw->bus.lan_id == 0)
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_srlr_core0;
+ else
+ hw->phy.sfp_type =
+ ixgbe_sfp_type_srlr_core1;
+ else
+ hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+ }
+
+ if (hw->phy.sfp_type != stored_sfp_type)
+ hw->phy.sfp_setup_needed = TRUE;
/* Determine if the SFP+ PHY is dual speed or not. */
- if ((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
- (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE))
+ if (((comp_codes_1g & IXGBE_SFF_1GBASESX_CAPABLE) &&
+ (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)) ||
+ ((comp_codes_1g & IXGBE_SFF_1GBASELX_CAPABLE) &&
+ (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)))
hw->phy.multispeed_fiber = TRUE;
/* Determine PHY vendor */
- if (hw->phy.type == ixgbe_phy_unknown) {
+ if (hw->phy.type != ixgbe_phy_nl) {
hw->phy.id = identifier;
hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_VENDOR_OUI_BYTE0,
@@ -703,6 +871,9 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
case IXGBE_SFF_VENDOR_OUI_AVAGO:
hw->phy.type = ixgbe_phy_sfp_avago;
break;
+ case IXGBE_SFF_VENDOR_OUI_INTEL:
+ hw->phy.type = ixgbe_phy_sfp_intel;
+ break;
default:
if (transmission_media &
IXGBE_SFF_TWIN_AX_CAPABLE)
@@ -712,7 +883,34 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
break;
}
}
- status = IXGBE_SUCCESS;
+
+ if (comp_codes_10g == 0) {
+ hw->phy.type = ixgbe_phy_sfp_unsupported;
+ status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+ goto out;
+ }
+ if (hw->mac.type == ixgbe_mac_82598EB ||
+ (hw->phy.sfp_type != ixgbe_sfp_type_sr &&
+ hw->phy.sfp_type != ixgbe_sfp_type_lr &&
+ hw->phy.sfp_type != ixgbe_sfp_type_srlr_core0 &&
+ hw->phy.sfp_type != ixgbe_sfp_type_srlr_core1)) {
+ status = IXGBE_SUCCESS;
+ goto out;
+ }
+
+ ixgbe_get_device_caps(hw, &enforce_sfp);
+ if (!(enforce_sfp & IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP)) {
+ /* Make sure we're a supported PHY type */
+ if (hw->phy.type == ixgbe_phy_sfp_intel) {
+ status = IXGBE_SUCCESS;
+ } else {
+ DEBUGOUT("SFP+ module not supported\n");
+ hw->phy.type = ixgbe_phy_sfp_unsupported;
+ status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+ }
+ } else {
+ status = IXGBE_SUCCESS;
+ }
}
out:
@@ -748,7 +946,7 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset);
if ((!*list_offset) || (*list_offset == 0xFFFF))
- return IXGBE_ERR_PHY;
+ return IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT;
/* Shift offset to first ID word */
(*list_offset)++;
@@ -784,3 +982,549 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
return IXGBE_SUCCESS;
}
+/**
+ * ixgbe_read_i2c_eeprom_generic - Reads 8 bit EEPROM word over I2C interface
+ * @hw: pointer to hardware structure
+ * @byte_offset: EEPROM byte offset to read
+ * @eeprom_data: value read
+ *
+ * Performs byte read operation to SFP module's EEPROM over I2C interface.
+ **/
+s32 ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 *eeprom_data)
+{
+ DEBUGFUNC("ixgbe_read_i2c_eeprom_generic");
+
+ return hw->phy.ops.read_i2c_byte(hw, byte_offset,
+ IXGBE_I2C_EEPROM_DEV_ADDR,
+ eeprom_data);
+}
+
+/**
+ * ixgbe_write_i2c_eeprom_generic - Writes 8 bit EEPROM word over I2C interface
+ * @hw: pointer to hardware structure
+ * @byte_offset: EEPROM byte offset to write
+ * @eeprom_data: value to write
+ *
+ * Performs byte write operation to SFP module's EEPROM over I2C interface.
+ **/
+s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 eeprom_data)
+{
+ DEBUGFUNC("ixgbe_write_i2c_eeprom_generic");
+
+ return hw->phy.ops.write_i2c_byte(hw, byte_offset,
+ IXGBE_I2C_EEPROM_DEV_ADDR,
+ eeprom_data);
+}
+
+/**
+ * ixgbe_read_i2c_byte_generic - Reads 8 bit word over I2C
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to read
+ * @data: value read
+ *
+ * Performs byte read operation to SFP module's EEPROM over I2C interface at
+ * a specified deivce address.
+ **/
+s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 *data)
+{
+ s32 status = IXGBE_SUCCESS;
+ u32 max_retry = 1;
+ u32 retry = 0;
+ u16 swfw_mask = 0;
+ bool nack = 1;
+
+ DEBUGFUNC("ixgbe_read_i2c_byte_generic");
+
+ if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
+ swfw_mask = IXGBE_GSSR_PHY1_SM;
+ else
+ swfw_mask = IXGBE_GSSR_PHY0_SM;
+
+ if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != IXGBE_SUCCESS) {
+ status = IXGBE_ERR_SWFW_SYNC;
+ goto read_byte_out;
+ }
+
+ do {
+ ixgbe_i2c_start(hw);
+
+ /* Device Address and write indication */
+ status = ixgbe_clock_out_i2c_byte(hw, dev_addr);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ status = ixgbe_get_i2c_ack(hw);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ status = ixgbe_clock_out_i2c_byte(hw, byte_offset);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ status = ixgbe_get_i2c_ack(hw);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ ixgbe_i2c_start(hw);
+
+ /* Device Address and read indication */
+ status = ixgbe_clock_out_i2c_byte(hw, (dev_addr | 0x1));
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ status = ixgbe_get_i2c_ack(hw);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ status = ixgbe_clock_in_i2c_byte(hw, data);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ status = ixgbe_clock_out_i2c_bit(hw, nack);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ ixgbe_i2c_stop(hw);
+ break;
+
+fail:
+ ixgbe_i2c_bus_clear(hw);
+ retry++;
+ if (retry < max_retry)
+ DEBUGOUT("I2C byte read error - Retrying.\n");
+ else
+ DEBUGOUT("I2C byte read error.\n");
+
+ } while (retry < max_retry);
+
+ ixgbe_release_swfw_sync(hw, swfw_mask);
+
+read_byte_out:
+ return status;
+}
+
+/**
+ * ixgbe_write_i2c_byte_generic - Writes 8 bit word over I2C
+ * @hw: pointer to hardware structure
+ * @byte_offset: byte offset to write
+ * @data: value to write
+ *
+ * Performs byte write operation to SFP module's EEPROM over I2C interface at
+ * a specified device address.
+ **/
+s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 data)
+{
+ s32 status = IXGBE_SUCCESS;
+ u32 max_retry = 1;
+ u32 retry = 0;
+ u16 swfw_mask = 0;
+
+ DEBUGFUNC("ixgbe_write_i2c_byte_generic");
+
+ if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
+ swfw_mask = IXGBE_GSSR_PHY1_SM;
+ else
+ swfw_mask = IXGBE_GSSR_PHY0_SM;
+
+ if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != IXGBE_SUCCESS) {
+ status = IXGBE_ERR_SWFW_SYNC;
+ goto write_byte_out;
+ }
+
+ do {
+ ixgbe_i2c_start(hw);
+
+ status = ixgbe_clock_out_i2c_byte(hw, dev_addr);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ status = ixgbe_get_i2c_ack(hw);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ status = ixgbe_clock_out_i2c_byte(hw, byte_offset);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ status = ixgbe_get_i2c_ack(hw);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ status = ixgbe_clock_out_i2c_byte(hw, data);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ status = ixgbe_get_i2c_ack(hw);
+ if (status != IXGBE_SUCCESS)
+ goto fail;
+
+ ixgbe_i2c_stop(hw);
+ break;
+
+fail:
+ ixgbe_i2c_bus_clear(hw);
+ retry++;
+ if (retry < max_retry)
+ DEBUGOUT("I2C byte write error - Retrying.\n");
+ else
+ DEBUGOUT("I2C byte write error.\n");
+ } while (retry < max_retry);
+
+ ixgbe_release_swfw_sync(hw, swfw_mask);
+
+write_byte_out:
+ return status;
+}
+
+/**
+ * ixgbe_i2c_start - Sets I2C start condition
+ * @hw: pointer to hardware structure
+ *
+ * Sets I2C start condition (High -> Low on SDA while SCL is High)
+ **/
+static void ixgbe_i2c_start(struct ixgbe_hw *hw)
+{
+ u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+
+ DEBUGFUNC("ixgbe_i2c_start");
+
+ /* Start condition must begin with data and clock high */
+ ixgbe_set_i2c_data(hw, &i2cctl, 1);
+ ixgbe_raise_i2c_clk(hw, &i2cctl);
+
+ /* Setup time for start condition (4.7us) */
+ usec_delay(IXGBE_I2C_T_SU_STA);
+
+ ixgbe_set_i2c_data(hw, &i2cctl, 0);
+
+ /* Hold time for start condition (4us) */
+ usec_delay(IXGBE_I2C_T_HD_STA);
+
+ ixgbe_lower_i2c_clk(hw, &i2cctl);
+
+ /* Minimum low period of clock is 4.7 us */
+ usec_delay(IXGBE_I2C_T_LOW);
+
+}
+
+/**
+ * ixgbe_i2c_stop - Sets I2C stop condition
+ * @hw: pointer to hardware structure
+ *
+ * Sets I2C stop condition (Low -> High on SDA while SCL is High)
+ **/
+static void ixgbe_i2c_stop(struct ixgbe_hw *hw)
+{
+ u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+
+ DEBUGFUNC("ixgbe_i2c_stop");
+
+ /* Stop condition must begin with data low and clock high */
+ ixgbe_set_i2c_data(hw, &i2cctl, 0);
+ ixgbe_raise_i2c_clk(hw, &i2cctl);
+
+ /* Setup time for stop condition (4us) */
+ usec_delay(IXGBE_I2C_T_SU_STO);
+
+ ixgbe_set_i2c_data(hw, &i2cctl, 1);
+
+ /* bus free time between stop and start (4.7us)*/
+ usec_delay(IXGBE_I2C_T_BUF);
+}
+
+/**
+ * ixgbe_clock_in_i2c_byte - Clocks in one byte via I2C
+ * @hw: pointer to hardware structure
+ * @data: data byte to clock in
+ *
+ * Clocks in one byte data via I2C data/clock
+ **/
+static s32 ixgbe_clock_in_i2c_byte(struct ixgbe_hw *hw, u8 *data)
+{
+ s32 status = IXGBE_SUCCESS;
+ s32 i;
+ bool bit = 0;
+
+ DEBUGFUNC("ixgbe_clock_in_i2c_byte");
+
+ for (i = 7; i >= 0; i--) {
+ status = ixgbe_clock_in_i2c_bit(hw, &bit);
+ *data |= bit<<i;
+
+ if (status != IXGBE_SUCCESS)
+ break;
+ }
+
+ return status;
+}
+
+/**
+ * ixgbe_clock_out_i2c_byte - Clocks out one byte via I2C
+ * @hw: pointer to hardware structure
+ * @data: data byte clocked out
+ *
+ * Clocks out one byte data via I2C data/clock
+ **/
+static s32 ixgbe_clock_out_i2c_byte(struct ixgbe_hw *hw, u8 data)
+{
+ s32 status = IXGBE_SUCCESS;
+ s32 i;
+ u32 i2cctl;
+ bool bit = 0;
+
+ DEBUGFUNC("ixgbe_clock_out_i2c_byte");
+
+ for (i = 7; i >= 0; i--) {
+ bit = (data >> i) & 0x1;
+ status = ixgbe_clock_out_i2c_bit(hw, bit);
+
+ if (status != IXGBE_SUCCESS)
+ break;
+ }
+
+ /* Release SDA line (set high) */
+ i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+ i2cctl |= IXGBE_I2C_DATA_OUT;
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, i2cctl);
+
+ return status;
+}
+
+/**
+ * ixgbe_get_i2c_ack - Polls for I2C ACK
+ * @hw: pointer to hardware structure
+ *
+ * Clocks in/out one bit via I2C data/clock
+ **/
+static s32 ixgbe_get_i2c_ack(struct ixgbe_hw *hw)
+{
+ s32 status;
+ u32 i = 0;
+ u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+ u32 timeout = 10;
+ bool ack = 1;
+
+ DEBUGFUNC("ixgbe_get_i2c_ack");
+
+ status = ixgbe_raise_i2c_clk(hw, &i2cctl);
+
+ if (status != IXGBE_SUCCESS)
+ goto out;
+
+ /* Minimum high period of clock is 4us */
+ usec_delay(IXGBE_I2C_T_HIGH);
+
+ /* Poll for ACK. Note that ACK in I2C spec is
+ * transition from 1 to 0 */
+ for (i = 0; i < timeout; i++) {
+ i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+ ack = ixgbe_get_i2c_data(&i2cctl);
+
+ usec_delay(1);
+ if (ack == 0)
+ break;
+ }
+
+ if (ack == 1) {
+ DEBUGOUT("I2C ack was not received.\n");
+ status = IXGBE_ERR_I2C;
+ }
+
+ ixgbe_lower_i2c_clk(hw, &i2cctl);
+
+ /* Minimum low period of clock is 4.7 us */
+ usec_delay(IXGBE_I2C_T_LOW);
+
+out:
+ return status;
+}
+
+/**
+ * ixgbe_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
+ * @hw: pointer to hardware structure
+ * @data: read data value
+ *
+ * Clocks in one bit via I2C data/clock
+ **/
+static s32 ixgbe_clock_in_i2c_bit(struct ixgbe_hw *hw, bool *data)
+{
+ s32 status;
+ u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+
+ status = ixgbe_raise_i2c_clk(hw, &i2cctl);
+
+ /* Minimum high period of clock is 4us */
+ usec_delay(IXGBE_I2C_T_HIGH);
+
+ i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+ *data = ixgbe_get_i2c_data(&i2cctl);
+
+ ixgbe_lower_i2c_clk(hw, &i2cctl);
+
+ /* Minimum low period of clock is 4.7 us */
+ usec_delay(IXGBE_I2C_T_LOW);
+
+ return status;
+}
+
+/**
+ * ixgbe_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
+ * @hw: pointer to hardware structure
+ * @data: data value to write
+ *
+ * Clocks out one bit via I2C data/clock
+ **/
+static s32 ixgbe_clock_out_i2c_bit(struct ixgbe_hw *hw, bool data)
+{
+ s32 status;
+ u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+
+ status = ixgbe_set_i2c_data(hw, &i2cctl, data);
+ if (status == IXGBE_SUCCESS) {
+ status = ixgbe_raise_i2c_clk(hw, &i2cctl);
+
+ /* Minimum high period of clock is 4us */
+ usec_delay(IXGBE_I2C_T_HIGH);
+
+ ixgbe_lower_i2c_clk(hw, &i2cctl);
+
+ /* Minimum low period of clock is 4.7 us.
+ * This also takes care of the data hold time.
+ */
+ usec_delay(IXGBE_I2C_T_LOW);
+ } else {
+ status = IXGBE_ERR_I2C;
+ DEBUGOUT1("I2C data was not set to %X\n", data);
+ }
+
+ return status;
+}
+/**
+ * ixgbe_raise_i2c_clk - Raises the I2C SCL clock
+ * @hw: pointer to hardware structure
+ * @i2cctl: Current value of I2CCTL register
+ *
+ * Raises the I2C clock line '0'->'1'
+ **/
+static s32 ixgbe_raise_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
+{
+ s32 status = IXGBE_SUCCESS;
+
+ *i2cctl |= IXGBE_I2C_CLK_OUT;
+
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl);
+
+ /* SCL rise time (1000ns) */
+ usec_delay(IXGBE_I2C_T_RISE);
+
+ return status;
+}
+
+/**
+ * ixgbe_lower_i2c_clk - Lowers the I2C SCL clock
+ * @hw: pointer to hardware structure
+ * @i2cctl: Current value of I2CCTL register
+ *
+ * Lowers the I2C clock line '1'->'0'
+ **/
+static void ixgbe_lower_i2c_clk(struct ixgbe_hw *hw, u32 *i2cctl)
+{
+
+ *i2cctl &= ~IXGBE_I2C_CLK_OUT;
+
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl);
+
+ /* SCL fall time (300ns) */
+ usec_delay(IXGBE_I2C_T_FALL);
+}
+
+/**
+ * ixgbe_set_i2c_data - Sets the I2C data bit
+ * @hw: pointer to hardware structure
+ * @i2cctl: Current value of I2CCTL register
+ * @data: I2C data value (0 or 1) to set
+ *
+ * Sets the I2C data bit
+ **/
+static s32 ixgbe_set_i2c_data(struct ixgbe_hw *hw, u32 *i2cctl, bool data)
+{
+ s32 status = IXGBE_SUCCESS;
+
+ if (data)
+ *i2cctl |= IXGBE_I2C_DATA_OUT;
+ else
+ *i2cctl &= ~IXGBE_I2C_DATA_OUT;
+
+ IXGBE_WRITE_REG(hw, IXGBE_I2CCTL, *i2cctl);
+
+ /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
+ usec_delay(IXGBE_I2C_T_RISE + IXGBE_I2C_T_FALL + IXGBE_I2C_T_SU_DATA);
+
+ /* Verify data was set correctly */
+ *i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+ if (data != ixgbe_get_i2c_data(i2cctl)) {
+ status = IXGBE_ERR_I2C;
+ DEBUGOUT1("Error - I2C data was not set to %X.\n", data);
+ }
+
+ return status;
+}
+
+/**
+ * ixgbe_get_i2c_data - Reads the I2C SDA data bit
+ * @hw: pointer to hardware structure
+ * @i2cctl: Current value of I2CCTL register
+ *
+ * Returns the I2C data bit value
+ **/
+static bool ixgbe_get_i2c_data(u32 *i2cctl)
+{
+ bool data;
+
+ if (*i2cctl & IXGBE_I2C_DATA_IN)
+ data = 1;
+ else
+ data = 0;
+
+ return data;
+}
+
+/**
+ * ixgbe_i2c_bus_clear - Clears the I2C bus
+ * @hw: pointer to hardware structure
+ *
+ * Clears the I2C bus by sending nine clock pulses.
+ * Used when data line is stuck low.
+ **/
+void ixgbe_i2c_bus_clear(struct ixgbe_hw *hw)
+{
+ u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
+ u32 i;
+
+ DEBUGFUNC("ixgbe_i2c_bus_clear");
+
+ ixgbe_i2c_start(hw);
+
+ ixgbe_set_i2c_data(hw, &i2cctl, 1);
+
+ for (i = 0; i < 9; i++) {
+ ixgbe_raise_i2c_clk(hw, &i2cctl);
+
+ /* Min high period of clock is 4us */
+ usec_delay(IXGBE_I2C_T_HIGH);
+
+ ixgbe_lower_i2c_clk(hw, &i2cctl);
+
+ /* Min low period of clock is 4.7us*/
+ usec_delay(IXGBE_I2C_T_LOW);
+ }
+
+ ixgbe_i2c_start(hw);
+
+ /* Put the i2c bus back to default state */
+ ixgbe_i2c_stop(hw);
+}
diff --git a/sys/dev/ixgbe/ixgbe_phy.h b/sys/dev/ixgbe/ixgbe_phy.h
index 7a1e4c7..047d31d 100644
--- a/sys/dev/ixgbe/ixgbe_phy.h
+++ b/sys/dev/ixgbe/ixgbe_phy.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -51,6 +51,7 @@
/* Bitmasks */
#define IXGBE_SFF_TWIN_AX_CAPABLE 0x80
#define IXGBE_SFF_1GBASESX_CAPABLE 0x1
+#define IXGBE_SFF_1GBASELX_CAPABLE 0x2
#define IXGBE_SFF_10GBASESR_CAPABLE 0x10
#define IXGBE_SFF_10GBASELR_CAPABLE 0x20
#define IXGBE_I2C_EEPROM_READ_MASK 0x100
@@ -61,14 +62,15 @@
#define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS 0x3
/* Bit-shift macros */
-#define IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT 12
-#define IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT 8
-#define IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT 4
+#define IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT 24
+#define IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT 16
+#define IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT 8
/* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */
#define IXGBE_SFF_VENDOR_OUI_TYCO 0x00407600
#define IXGBE_SFF_VENDOR_OUI_FTL 0x00906500
#define IXGBE_SFF_VENDOR_OUI_AVAGO 0x00176A00
+#define IXGBE_SFF_VENDOR_OUI_INTEL 0x001B2100
/* I2C SDA and SCL timing parameters for standard mode */
#define IXGBE_I2C_T_HD_STA 4
@@ -98,6 +100,9 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
+s32 ixgbe_get_copper_link_capabilities_generic(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *autoneg);
/* PHY specific */
s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
@@ -105,10 +110,20 @@ s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
bool *link_up);
s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
u16 *firmware_version);
+s32 ixgbe_get_phy_firmware_version_aq(struct ixgbe_hw *hw,
+ u16 *firmware_version);
s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
u16 *list_offset,
u16 *data_offset);
+s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 *data);
+s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 dev_addr, u8 data);
+s32 ixgbe_read_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 *eeprom_data);
+s32 ixgbe_write_i2c_eeprom_generic(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 eeprom_data);
#endif /* _IXGBE_PHY_H_ */
diff --git a/sys/dev/ixgbe/ixgbe_type.h b/sys/dev/ixgbe/ixgbe_type.h
index f265768..595a863 100644
--- a/sys/dev/ixgbe/ixgbe_type.h
+++ b/sys/dev/ixgbe/ixgbe_type.h
@@ -1,6 +1,6 @@
/******************************************************************************
- Copyright (c) 2001-2008, Intel Corporation
+ Copyright (c) 2001-2009, Intel Corporation
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -42,6 +42,7 @@
/* Device IDs */
#define IXGBE_DEV_ID_82598 0x10B6
+#define IXGBE_DEV_ID_82598_BX 0x1508
#define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6
#define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
#define IXGBE_DEV_ID_82598AT 0x10C8
@@ -51,6 +52,9 @@
#define IXGBE_DEV_ID_82598_DA_DUAL_PORT 0x10F1
#define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1
#define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4
+#define IXGBE_DEV_ID_82599_KX4 0x10F7
+#define IXGBE_DEV_ID_82599_CX4 0x10F9
+#define IXGBE_DEV_ID_82599_SFP 0x10FB
/* General Registers */
#define IXGBE_CTRL 0x00000
@@ -58,9 +62,12 @@
#define IXGBE_CTRL_EXT 0x00018
#define IXGBE_ESDP 0x00020
#define IXGBE_EODSDP 0x00028
+#define IXGBE_I2CCTL 0x00028
#define IXGBE_LEDCTL 0x00200
#define IXGBE_FRTIMER 0x00048
#define IXGBE_TCPTIMER 0x0004C
+#define IXGBE_CORESPARE 0x00600
+#define IXGBE_EXVET 0x05078
/* NVM Registers */
#define IXGBE_EEC 0x10010
@@ -74,6 +81,19 @@
#define IXGBE_FLOP 0x1013C
#define IXGBE_GRC 0x10200
+/* General Receive Control */
+#define IXGBE_GRC_MNG 0x00000001 /* Manageability Enable */
+#define IXGBE_GRC_APME 0x00000002 /* Advanced Power Management Enable */
+
+#define IXGBE_VPDDIAG0 0x10204
+#define IXGBE_VPDDIAG1 0x10208
+
+/* I2CCTL Bit Masks */
+#define IXGBE_I2C_CLK_IN 0x00000001
+#define IXGBE_I2C_CLK_OUT 0x00000002
+#define IXGBE_I2C_DATA_IN 0x00000004
+#define IXGBE_I2C_DATA_OUT 0x00000008
+
/* Interrupt Registers */
#define IXGBE_EICR 0x00800
#define IXGBE_EICS 0x00808
@@ -81,21 +101,45 @@
#define IXGBE_EIMC 0x00888
#define IXGBE_EIAC 0x00810
#define IXGBE_EIAM 0x00890
+#define IXGBE_EICS_EX(_i) (0x00A90 + (_i) * 4)
+#define IXGBE_EIMS_EX(_i) (0x00AA0 + (_i) * 4)
+#define IXGBE_EIMC_EX(_i) (0x00AB0 + (_i) * 4)
+#define IXGBE_EIAM_EX(_i) (0x00AD0 + (_i) * 4)
+/* 82599 EITR is only 12 bits, with the lower 3 always zero */
+/*
+ * 82598 EITR is 16 bits but set the limits based on the max
+ * supported by all ixgbe hardware
+ */
+#define IXGBE_MAX_INT_RATE 488281
+#define IXGBE_MIN_INT_RATE 956
+#define IXGBE_MAX_EITR 0x00000FF8
+#define IXGBE_MIN_EITR 8
#define IXGBE_EITR(_i) (((_i) <= 23) ? (0x00820 + ((_i) * 4)) : \
- (0x012300 + ((_i) * 4)))
-#define IXGBE_EITR_ITR_INT_MASK 0x00000FFF
+ (0x012300 + (((_i) - 24) * 4)))
+#define IXGBE_EITR_ITR_INT_MASK 0x00000FF8
+#define IXGBE_EITR_LLI_MOD 0x00008000
+#define IXGBE_EITR_CNT_WDIS 0x80000000
#define IXGBE_IVAR(_i) (0x00900 + ((_i) * 4)) /* 24 at 0x900-0x960 */
+#define IXGBE_IVAR_MISC 0x00A00 /* misc MSI-X interrupt causes */
+#define IXGBE_EITRSEL 0x00894
#define IXGBE_MSIXT 0x00000 /* MSI-X Table. 0x0000 - 0x01C */
#define IXGBE_MSIXPBA 0x02000 /* MSI-X Pending bit array */
#define IXGBE_PBACL(_i) (((_i) == 0) ? (0x11068) : (0x110C0 + ((_i) * 4)))
#define IXGBE_GPIE 0x00898
/* Flow Control Registers */
+#define IXGBE_FCADBUL 0x03210
+#define IXGBE_FCADBUH 0x03214
+#define IXGBE_FCAMACL 0x04328
+#define IXGBE_FCAMACH 0x0432C
+#define IXGBE_FCRTH_82599(_i) (0x03260 + ((_i) * 4)) /* 8 of these (0-7) */
+#define IXGBE_FCRTL_82599(_i) (0x03220 + ((_i) * 4)) /* 8 of these (0-7) */
#define IXGBE_PFCTOP 0x03008
#define IXGBE_FCTTV(_i) (0x03200 + ((_i) * 4)) /* 4 of these (0-3) */
#define IXGBE_FCRTL(_i) (0x03220 + ((_i) * 8)) /* 8 of these (0-7) */
#define IXGBE_FCRTH(_i) (0x03260 + ((_i) * 8)) /* 8 of these (0-7) */
#define IXGBE_FCRTV 0x032A0
+#define IXGBE_FCCFG 0x03D00
#define IXGBE_TFCS 0x0CE00
/* Receive DMA Registers */
@@ -111,6 +155,12 @@
(0x0D018 + ((_i - 64) * 0x40)))
#define IXGBE_RXDCTL(_i) (((_i) < 64) ? (0x01028 + ((_i) * 0x40)) : \
(0x0D028 + ((_i - 64) * 0x40)))
+#define IXGBE_RSCCTL(_i) (((_i) < 64) ? (0x0102C + ((_i) * 0x40)) : \
+ (0x0D02C + ((_i - 64) * 0x40)))
+#define IXGBE_RSCDBU 0x03028
+#define IXGBE_RDDCC 0x02F20
+#define IXGBE_RXMEMWRAP 0x03190
+#define IXGBE_STARCTRL 0x03024
/*
* Split and Replication Receive Control Registers
* 00-15 : 0x02100 + n*4
@@ -130,6 +180,7 @@
(((_i) < 64) ? (0x0100C + ((_i) * 0x40)) : \
(0x0D00C + ((_i - 64) * 0x40))))
#define IXGBE_RDRXCTL 0x02F00
+#define IXGBE_RDRXCTL_RSC_PUSH 0x80
#define IXGBE_RXPBSIZE(_i) (0x03C00 + ((_i) * 4))
/* 8 of these 0x03C00 - 0x03C1C */
#define IXGBE_RXCTRL 0x03000
@@ -147,6 +198,8 @@
(0x0A200 + ((_i) * 8)))
#define IXGBE_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
(0x0A204 + ((_i) * 8)))
+#define IXGBE_MPSAR_LO(_i) (0x0A600 + ((_i) * 8))
+#define IXGBE_MPSAR_HI(_i) (0x0A604 + ((_i) * 8))
/* Packet split receive type */
#define IXGBE_PSRTYPE(_i) (((_i) <= 15) ? (0x05480 + ((_i) * 4)) : \
(0x0EA00 + ((_i) * 4)))
@@ -158,6 +211,28 @@
#define IXGBE_VLNCTRL 0x05088
#define IXGBE_MCSTCTRL 0x05090
#define IXGBE_MRQC 0x05818
+#define IXGBE_SAQF(_i) (0x0E000 + ((_i) * 4)) /* Source Address Queue Filter */
+#define IXGBE_DAQF(_i) (0x0E200 + ((_i) * 4)) /* Dest. Address Queue Filter */
+#define IXGBE_SDPQF(_i) (0x0E400 + ((_i) * 4)) /* Src Dest. Addr Queue Filter */
+#define IXGBE_FTQF(_i) (0x0E600 + ((_i) * 4)) /* Five Tuple Queue Filter */
+#define IXGBE_ETQF(_i) (0x05128 + ((_i) * 4)) /* EType Queue Filter */
+#define IXGBE_ETQS(_i) (0x0EC00 + ((_i) * 4)) /* EType Queue Select */
+#define IXGBE_SYNQF 0x0EC30 /* SYN Packet Queue Filter */
+#define IXGBE_RQTC 0x0EC70
+#define IXGBE_MTQC 0x08120
+#define IXGBE_VLVF(_i) (0x0F100 + ((_i) * 4)) /* 64 of these (0-63) */
+#define IXGBE_VLVFB(_i) (0x0F200 + ((_i) * 4)) /* 128 of these (0-127) */
+#define IXGBE_VT_CTL 0x051B0
+#define IXGBE_VFRE(_i) (0x051E0 + ((_i) * 4))
+#define IXGBE_VFTE(_i) (0x08110 + ((_i) * 4))
+#define IXGBE_QDE 0x2F04
+#define IXGBE_VMOLR(_i) (0x0F000 + ((_i) * 4)) /* 64 total */
+#define IXGBE_UTA(_i) (0x0F400 + ((_i) * 4))
+#define IXGBE_VMRCTL(_i) (0x0F600 + ((_i) * 4))
+#define IXGBE_VMRVLAN(_i) (0x0F610 + ((_i) * 4))
+#define IXGBE_VMRVM(_i) (0x0F630 + ((_i) * 4))
+#define IXGBE_L34T_IMIR(_i) (0x0E800 + ((_i) * 4)) /*128 of these (0-127)*/
+#define IXGBE_LLITHRESH 0x0EC90
#define IXGBE_IMIR(_i) (0x05A80 + ((_i) * 4)) /* 8 of these (0-7) */
#define IXGBE_IMIREXT(_i) (0x05AA0 + ((_i) * 4)) /* 8 of these (0-7) */
#define IXGBE_IMIRVP 0x05AC0
@@ -165,6 +240,33 @@
#define IXGBE_RETA(_i) (0x05C00 + ((_i) * 4)) /* 32 of these (0-31) */
#define IXGBE_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* 10 of these (0-9) */
+/* Flow Director registers */
+#define IXGBE_FDIRCTRL 0x0EE00
+#define IXGBE_FDIRHKEY 0x0EE68
+#define IXGBE_FDIRSKEY 0x0EE6C
+#define IXGBE_FDIRDIP4M 0x0EE3C
+#define IXGBE_FDIRSIP4M 0x0EE40
+#define IXGBE_FDIRTCPM 0x0EE44
+#define IXGBE_FDIRUDPM 0x0EE48
+#define IXGBE_FDIRIP6M 0x0EE74
+#define IXGBE_FDIRM 0x0EE70
+
+/* Flow Director Stats registers */
+#define IXGBE_FDIRFREE 0x0EE38
+#define IXGBE_FDIRLEN 0x0EE4C
+#define IXGBE_FDIRUSTAT 0x0EE50
+#define IXGBE_FDIRFSTAT 0x0EE54
+#define IXGBE_FDIRMATCH 0x0EE58
+#define IXGBE_FDIRMISS 0x0EE5C
+
+/* Flow Director Programming registers */
+#define IXGBE_FDIRSIPv6(_i) (0x0EE0C + ((_i) * 4)) /* 3 of these (0-2) */
+#define IXGBE_FDIRIPSA 0x0EE18
+#define IXGBE_FDIRIPDA 0x0EE1C
+#define IXGBE_FDIRPORT 0x0EE20
+#define IXGBE_FDIRVLAN 0x0EE24
+#define IXGBE_FDIRHASH 0x0EE28
+#define IXGBE_FDIRCMD 0x0EE2C
/* Transmit DMA registers */
#define IXGBE_TDBAL(_i) (0x06000 + ((_i) * 0x40)) /* 32 of these (0-31)*/
@@ -177,7 +279,20 @@
#define IXGBE_TDWBAH(_i) (0x0603C + ((_i) * 0x40))
#define IXGBE_DTXCTL 0x07E00
+#define IXGBE_DMATXCTL 0x04A80
+#define IXGBE_DTXMXSZRQ 0x08100
+#define IXGBE_DTXTCPFLGL 0x04A88
+#define IXGBE_DTXTCPFLGH 0x04A8C
+#define IXGBE_LBDRPEN 0x0CA00
+#define IXGBE_TXPBTHRESH(_i) (0x04950 + ((_i) * 4)) /* 8 of these 0 - 7 */
+
+#define IXGBE_DMATXCTL_TE 0x1 /* Transmit Enable */
+#define IXGBE_DMATXCTL_NS 0x2 /* No Snoop LSO hdr buffer */
+#define IXGBE_DMATXCTL_GDV 0x8 /* Global Double VLAN */
+#define IXGBE_DMATXCTL_VT_SHIFT 16 /* VLAN EtherType */
#define IXGBE_DCA_TXCTRL(_i) (0x07200 + ((_i) * 4)) /* 16 of these (0-15) */
+/* Tx DCA Control register : 128 of these (0-127) */
+#define IXGBE_DCA_TXCTRL_82599(_i) (0x0600C + ((_i) * 0x40))
#define IXGBE_TIPG 0x0CB00
#define IXGBE_TXPBSIZE(_i) (0x0CC00 + ((_i) * 4)) /* 8 of these */
#define IXGBE_MNGTXMAP 0x0CD10
@@ -269,6 +384,193 @@
#define IXGBE_TDPT2TCSR(_i) (0x0CD40 + ((_i) * 4)) /* 8 of these (0-7) */
+/* Security Control Registers */
+#define IXGBE_SECTXCTRL 0x08800
+#define IXGBE_SECTXSTAT 0x08804
+#define IXGBE_SECTXBUFFAF 0x08808
+#define IXGBE_SECTXMINIFG 0x08810
+#define IXGBE_SECTXSTAT 0x08804
+#define IXGBE_SECRXCTRL 0x08D00
+#define IXGBE_SECRXSTAT 0x08D04
+
+/* Security Bit Fields and Masks */
+#define IXGBE_SECTXCTRL_SECTX_DIS 0x00000001
+#define IXGBE_SECTXCTRL_TX_DIS 0x00000002
+#define IXGBE_SECTXCTRL_STORE_FORWARD 0x00000004
+
+#define IXGBE_SECTXSTAT_SECTX_RDY 0x00000001
+#define IXGBE_SECTXSTAT_ECC_TXERR 0x00000002
+
+#define IXGBE_SECRXCTRL_SECRX_DIS 0x00000001
+#define IXGBE_SECRXCTRL_RX_DIS 0x00000002
+
+#define IXGBE_SECRXSTAT_SECRX_RDY 0x00000001
+#define IXGBE_SECRXSTAT_ECC_RXERR 0x00000002
+
+/* LinkSec (MacSec) Registers */
+#define IXGBE_LSECTXCAP 0x08A00
+#define IXGBE_LSECRXCAP 0x08F00
+#define IXGBE_LSECTXCTRL 0x08A04
+#define IXGBE_LSECTXSCL 0x08A08 /* SCI Low */
+#define IXGBE_LSECTXSCH 0x08A0C /* SCI High */
+#define IXGBE_LSECTXSA 0x08A10
+#define IXGBE_LSECTXPN0 0x08A14
+#define IXGBE_LSECTXPN1 0x08A18
+#define IXGBE_LSECTXKEY0(_n) (0x08A1C + (4 * (_n))) /* 4 of these (0-3) */
+#define IXGBE_LSECTXKEY1(_n) (0x08A2C + (4 * (_n))) /* 4 of these (0-3) */
+#define IXGBE_LSECRXCTRL 0x08F04
+#define IXGBE_LSECRXSCL 0x08F08
+#define IXGBE_LSECRXSCH 0x08F0C
+#define IXGBE_LSECRXSA(_i) (0x08F10 + (4 * (_i))) /* 2 of these (0-1) */
+#define IXGBE_LSECRXPN(_i) (0x08F18 + (4 * (_i))) /* 2 of these (0-1) */
+#define IXGBE_LSECRXKEY(_n, _m) (0x08F20 + ((0x10 * (_n)) + (4 * (_m))))
+#define IXGBE_LSECTXUT 0x08A3C /* OutPktsUntagged */
+#define IXGBE_LSECTXPKTE 0x08A40 /* OutPktsEncrypted */
+#define IXGBE_LSECTXPKTP 0x08A44 /* OutPktsProtected */
+#define IXGBE_LSECTXOCTE 0x08A48 /* OutOctetsEncrypted */
+#define IXGBE_LSECTXOCTP 0x08A4C /* OutOctetsProtected */
+#define IXGBE_LSECRXUT 0x08F40 /* InPktsUntagged/InPktsNoTag */
+#define IXGBE_LSECRXOCTD 0x08F44 /* InOctetsDecrypted */
+#define IXGBE_LSECRXOCTV 0x08F48 /* InOctetsValidated */
+#define IXGBE_LSECRXBAD 0x08F4C /* InPktsBadTag */
+#define IXGBE_LSECRXNOSCI 0x08F50 /* InPktsNoSci */
+#define IXGBE_LSECRXUNSCI 0x08F54 /* InPktsUnknownSci */
+#define IXGBE_LSECRXUNCH 0x08F58 /* InPktsUnchecked */
+#define IXGBE_LSECRXDELAY 0x08F5C /* InPktsDelayed */
+#define IXGBE_LSECRXLATE 0x08F60 /* InPktsLate */
+#define IXGBE_LSECRXOK(_n) (0x08F64 + (0x04 * (_n))) /* InPktsOk */
+#define IXGBE_LSECRXINV(_n) (0x08F6C + (0x04 * (_n))) /* InPktsInvalid */
+#define IXGBE_LSECRXNV(_n) (0x08F74 + (0x04 * (_n))) /* InPktsNotValid */
+#define IXGBE_LSECRXUNSA 0x08F7C /* InPktsUnusedSa */
+#define IXGBE_LSECRXNUSA 0x08F80 /* InPktsNotUsingSa */
+
+/* LinkSec (MacSec) Bit Fields and Masks */
+#define IXGBE_LSECTXCAP_SUM_MASK 0x00FF0000
+#define IXGBE_LSECTXCAP_SUM_SHIFT 16
+#define IXGBE_LSECRXCAP_SUM_MASK 0x00FF0000
+#define IXGBE_LSECRXCAP_SUM_SHIFT 16
+
+#define IXGBE_LSECTXCTRL_EN_MASK 0x00000003
+#define IXGBE_LSECTXCTRL_DISABLE 0x0
+#define IXGBE_LSECTXCTRL_AUTH 0x1
+#define IXGBE_LSECTXCTRL_AUTH_ENCRYPT 0x2
+#define IXGBE_LSECTXCTRL_AISCI 0x00000020
+#define IXGBE_LSECTXCTRL_PNTHRSH_MASK 0xFFFFFF00
+#define IXGBE_LSECTXCTRL_RSV_MASK 0x000000D8
+
+#define IXGBE_LSECRXCTRL_EN_MASK 0x0000000C
+#define IXGBE_LSECRXCTRL_EN_SHIFT 2
+#define IXGBE_LSECRXCTRL_DISABLE 0x0
+#define IXGBE_LSECRXCTRL_CHECK 0x1
+#define IXGBE_LSECRXCTRL_STRICT 0x2
+#define IXGBE_LSECRXCTRL_DROP 0x3
+#define IXGBE_LSECRXCTRL_PLSH 0x00000040
+#define IXGBE_LSECRXCTRL_RP 0x00000080
+#define IXGBE_LSECRXCTRL_RSV_MASK 0xFFFFFF33
+
+/* IpSec Registers */
+#define IXGBE_IPSTXIDX 0x08900
+#define IXGBE_IPSTXSALT 0x08904
+#define IXGBE_IPSTXKEY(_i) (0x08908 + (4 * (_i))) /* 4 of these (0-3) */
+#define IXGBE_IPSRXIDX 0x08E00
+#define IXGBE_IPSRXIPADDR(_i) (0x08E04 + (4 * (_i))) /* 4 of these (0-3) */
+#define IXGBE_IPSRXSPI 0x08E14
+#define IXGBE_IPSRXIPIDX 0x08E18
+#define IXGBE_IPSRXKEY(_i) (0x08E1C + (4 * (_i))) /* 4 of these (0-3) */
+#define IXGBE_IPSRXSALT 0x08E2C
+#define IXGBE_IPSRXMOD 0x08E30
+
+#define IXGBE_SECTXCTRL_STORE_FORWARD_ENABLE 0x4
+
+/* DCB registers */
+#define IXGBE_RTRPCS 0x02430
+#define IXGBE_RTTDCS 0x04900
+#define IXGBE_RTTDCS_ARBDIS 0x00000040 /* DCB arbiter disable */
+#define IXGBE_RTTPCS 0x0CD00
+#define IXGBE_RTRUP2TC 0x03020
+#define IXGBE_RTTUP2TC 0x0C800
+#define IXGBE_RTRPT4C(_i) (0x02140 + ((_i) * 4)) /* 8 of these (0-7) */
+#define IXGBE_RTRPT4S(_i) (0x02160 + ((_i) * 4)) /* 8 of these (0-7) */
+#define IXGBE_RTTDT2C(_i) (0x04910 + ((_i) * 4)) /* 8 of these (0-7) */
+#define IXGBE_RTTDT2S(_i) (0x04930 + ((_i) * 4)) /* 8 of these (0-7) */
+#define IXGBE_RTTPT2C(_i) (0x0CD20 + ((_i) * 4)) /* 8 of these (0-7) */
+#define IXGBE_RTTPT2S(_i) (0x0CD40 + ((_i) * 4)) /* 8 of these (0-7) */
+#define IXGBE_RTTDQSEL 0x04904
+#define IXGBE_RTTDT1C 0x04908
+#define IXGBE_RTTDT1S 0x0490C
+#define IXGBE_RTTDTECC 0x04990
+#define IXGBE_RTTDTECC_NO_BCN 0x00000100
+
+#define IXGBE_RTTBCNRC 0x04984
+
+/* BCN (for DCB) Registers */
+#define IXGBE_RTTBCNRM 0x04980
+#define IXGBE_RTTBCNRS 0x04988
+#define IXGBE_RTTBCNCR 0x08B00
+#define IXGBE_RTTBCNACH 0x08B04
+#define IXGBE_RTTBCNACL 0x08B08
+#define IXGBE_RTTBCNTG 0x04A90
+#define IXGBE_RTTBCNIDX 0x08B0C
+#define IXGBE_RTTBCNCP 0x08B10
+#define IXGBE_RTFRTIMER 0x08B14
+#define IXGBE_RTTBCNRTT 0x05150
+#define IXGBE_RTTBCNRD 0x0498C
+
+/* FCoE DMA Context Registers */
+#define IXGBE_FCPTRL 0x02410 /* FC User Desc. PTR Low */
+#define IXGBE_FCPTRH 0x02414 /* FC USer Desc. PTR High */
+#define IXGBE_FCBUFF 0x02418 /* FC Buffer Control */
+#define IXGBE_FCDMARW 0x02420 /* FC Receive DMA RW */
+#define IXGBE_FCINVST0 0x03FC0 /* FC Invalid DMA Context Status Reg 0 */
+#define IXGBE_FCINVST(_i) (IXGBE_FCINVST0 + ((_i) * 4))
+#define IXGBE_FCBUFF_VALID (1 << 0) /* DMA Context Valid */
+#define IXGBE_FCBUFF_BUFFSIZE (3 << 3) /* User Buffer Size */
+#define IXGBE_FCBUFF_WRCONTX (1 << 7) /* 0: Initiator, 1: Target */
+#define IXGBE_FCBUFF_BUFFCNT 0x0000ff00 /* Number of User Buffers */
+#define IXGBE_FCBUFF_OFFSET 0xffff0000 /* User Buffer Offset */
+#define IXGBE_FCBUFF_BUFFSIZE_SHIFT 3
+#define IXGBE_FCBUFF_BUFFCNT_SHIFT 8
+#define IXGBE_FCBUFF_OFFSET_SHIFT 16
+#define IXGBE_FCDMARW_WE (1 << 14) /* Write enable */
+#define IXGBE_FCDMARW_RE (1 << 15) /* Read enable */
+#define IXGBE_FCDMARW_FCOESEL 0x000001ff /* FC X_ID: 11 bits */
+#define IXGBE_FCDMARW_LASTSIZE 0xffff0000 /* Last User Buffer Size */
+#define IXGBE_FCDMARW_LASTSIZE_SHIFT 16
+/* FCoE SOF/EOF */
+#define IXGBE_TEOFF 0x04A94 /* Tx FC EOF */
+#define IXGBE_TSOFF 0x04A98 /* Tx FC SOF */
+#define IXGBE_REOFF 0x05158 /* Rx FC EOF */
+#define IXGBE_RSOFF 0x051F8 /* Rx FC SOF */
+/* FCoE Filter Context Registers */
+#define IXGBE_FCFLT 0x05108 /* FC FLT Context */
+#define IXGBE_FCFLTRW 0x05110 /* FC Filter RW Control */
+#define IXGBE_FCPARAM 0x051d8 /* FC Offset Parameter */
+#define IXGBE_FCFLT_VALID (1 << 0) /* Filter Context Valid */
+#define IXGBE_FCFLT_FIRST (1 << 1) /* Filter First */
+#define IXGBE_FCFLT_SEQID 0x00ff0000 /* Sequence ID */
+#define IXGBE_FCFLT_SEQCNT 0xff000000 /* Sequence Count */
+#define IXGBE_FCFLTRW_RVALDT (1 << 13) /* Fast Re-Validation */
+#define IXGBE_FCFLTRW_WE (1 << 14) /* Write Enable */
+#define IXGBE_FCFLTRW_RE (1 << 15) /* Read Enable */
+/* FCoE Receive Control */
+#define IXGBE_FCRXCTRL 0x05100 /* FC Receive Control */
+#define IXGBE_FCRXCTRL_FCOELLI (1 << 0) /* Low latency interrupt */
+#define IXGBE_FCRXCTRL_SAVBAD (1 << 1) /* Save Bad Frames */
+#define IXGBE_FCRXCTRL_FRSTRDH (1 << 2) /* EN 1st Read Header */
+#define IXGBE_FCRXCTRL_LASTSEQH (1 << 3) /* EN Last Header in Seq */
+#define IXGBE_FCRXCTRL_ALLH (1 << 4) /* EN All Headers */
+#define IXGBE_FCRXCTRL_FRSTSEQH (1 << 5) /* EN 1st Seq. Header */
+#define IXGBE_FCRXCTRL_ICRC (1 << 6) /* Ignore Bad FC CRC */
+#define IXGBE_FCRXCTRL_FCCRCBO (1 << 7) /* FC CRC Byte Ordering */
+#define IXGBE_FCRXCTRL_FCOEVER 0x00000f00 /* FCoE Version: 4 bits */
+#define IXGBE_FCRXCTRL_FCOEVER_SHIFT 8
+/* FCoE Redirection */
+#define IXGBE_FCRECTL 0x0ED00 /* FC Redirection Control */
+#define IXGBE_FCRETA0 0x0ED10 /* FC Redirection Table 0 */
+#define IXGBE_FCRETA(_i) (IXGBE_FCRETA0 + ((_i) * 4)) /* FCoE Redir */
+#define IXGBE_FCRECTL_ENA 0x1 /* FCoE Redir Table Enable */
+#define IXGBE_FCRETA_SIZE 8 /* Max entries in FCRETA */
+#define IXGBE_FCRETA_ENTRY_MASK 0x0000007f /* 7 bits for the queue index */
/* Stats registers */
#define IXGBE_CRCERRS 0x04000
@@ -283,6 +585,11 @@
#define IXGBE_LXONRXC 0x0CF60
#define IXGBE_LXOFFTXC 0x03F68
#define IXGBE_LXOFFRXC 0x0CF68
+#define IXGBE_LXONRXCNT 0x041A4
+#define IXGBE_LXOFFRXCNT 0x041A8
+#define IXGBE_PXONRXCNT(_i) (0x04140 + ((_i) * 4)) /* 8 of these */
+#define IXGBE_PXOFFRXCNT(_i) (0x04160 + ((_i) * 4)) /* 8 of these */
+#define IXGBE_PXON2OFFCNT(_i) (0x03240 + ((_i) * 4)) /* 8 of these */
#define IXGBE_PXONTXC(_i) (0x03F00 + ((_i) * 4)) /* 8 of these 3F00-3F1C*/
#define IXGBE_PXONRXC(_i) (0x0CF00 + ((_i) * 4)) /* 8 of these CF00-CF1C*/
#define IXGBE_PXOFFTXC(_i) (0x03F20 + ((_i) * 4)) /* 8 of these 3F20-3F3C*/
@@ -322,15 +629,29 @@
#define IXGBE_MPTC 0x040F0
#define IXGBE_BPTC 0x040F4
#define IXGBE_XEC 0x04120
+#define IXGBE_SSVPC 0x08780
#define IXGBE_RQSMR(_i) (0x02300 + ((_i) * 4))
#define IXGBE_TQSMR(_i) (((_i) <= 7) ? (0x07300 + ((_i) * 4)) : \
(0x08600 + ((_i) * 4)))
+#define IXGBE_TQSM(_i) (0x08600 + ((_i) * 4))
#define IXGBE_QPRC(_i) (0x01030 + ((_i) * 0x40)) /* 16 of these */
#define IXGBE_QPTC(_i) (0x06030 + ((_i) * 0x40)) /* 16 of these */
#define IXGBE_QBRC(_i) (0x01034 + ((_i) * 0x40)) /* 16 of these */
#define IXGBE_QBTC(_i) (0x06034 + ((_i) * 0x40)) /* 16 of these */
+#define IXGBE_QPRDC(_i) (0x01430 + ((_i) * 0x40)) /* 16 of these */
+#define IXGBE_QBTC_L(_i) (0x08700 + ((_i) * 0x8)) /* 16 of these */
+#define IXGBE_QBTC_H(_i) (0x08704 + ((_i) * 0x8)) /* 16 of these */
+#define IXGBE_FCCRC 0x05118 /* Count of Good Eth CRC w/ Bad FC CRC */
+#define IXGBE_FCOERPDC 0x0241C /* FCoE Rx Packets Dropped Count */
+#define IXGBE_FCLAST 0x02424 /* FCoE Last Error Count */
+#define IXGBE_FCOEPRC 0x02428 /* Number of FCoE Packets Received */
+#define IXGBE_FCOEDWRC 0x0242C /* Number of FCoE DWords Received */
+#define IXGBE_FCOEPTC 0x08784 /* Number of FCoE Packets Transmitted */
+#define IXGBE_FCOEDWTC 0x08788 /* Number of FCoE DWords Transmitted */
+#define IXGBE_FCCRC_CNT_MASK 0x0000FFFF /* CRC_CNT: bit 0 - 15 */
+#define IXGBE_FCLAST_CNT_MASK 0x0000FFFF /* Last_CNT: bit 0 - 15 */
/* Management */
#define IXGBE_MAVTV(_i) (0x05010 + ((_i) * 4)) /* 8 of these (0-7) */
@@ -343,6 +664,9 @@
#define IXGBE_MMAL(_i) (0x05910 + ((_i) * 8)) /* 4 of these (0-3) */
#define IXGBE_MMAH(_i) (0x05914 + ((_i) * 8)) /* 4 of these (0-3) */
#define IXGBE_FTFT 0x09400 /* 0x9400-0x97FC */
+#define IXGBE_METF(_i) (0x05190 + ((_i) * 4)) /* 4 of these (0-3) */
+#define IXGBE_MDEF_EXT(_i) (0x05160 + ((_i) * 4)) /* 8 of these (0-7) */
+#define IXGBE_LSWFW 0x15014
/* ARC Subsystem registers */
#define IXGBE_HICR 0x15F00
@@ -375,16 +699,65 @@
#define IXGBE_DCA_ID 0x11070
#define IXGBE_DCA_CTRL 0x11074
+/* PCI-E registers 82599-Specific */
+#define IXGBE_GCR_EXT 0x11050
+#define IXGBE_GSCL_5_82599 0x11030
+#define IXGBE_GSCL_6_82599 0x11034
+#define IXGBE_GSCL_7_82599 0x11038
+#define IXGBE_GSCL_8_82599 0x1103C
+#define IXGBE_PHYADR_82599 0x11040
+#define IXGBE_PHYDAT_82599 0x11044
+#define IXGBE_PHYCTL_82599 0x11048
+#define IXGBE_PBACLR_82599 0x11068
+#define IXGBE_CIAA_82599 0x11088
+#define IXGBE_CIAD_82599 0x1108C
+#define IXGBE_PCIE_DIAG_0_82599 0x11090
+#define IXGBE_PCIE_DIAG_1_82599 0x11094
+#define IXGBE_PCIE_DIAG_2_82599 0x11098
+#define IXGBE_PCIE_DIAG_3_82599 0x1109C
+#define IXGBE_PCIE_DIAG_4_82599 0x110A0
+#define IXGBE_PCIE_DIAG_5_82599 0x110A4
+#define IXGBE_PCIE_DIAG_6_82599 0x110A8
+#define IXGBE_PCIE_DIAG_7_82599 0x110C0
+#define IXGBE_INTRPT_CSR_82599 0x110B0
+#define IXGBE_INTRPT_MASK_82599 0x110B8
+#define IXGBE_CDQ_MBR_82599 0x110B4
+#define IXGBE_MISC_REG_82599 0x110F0
+#define IXGBE_ECC_CTRL_0_82599 0x11100
+#define IXGBE_ECC_CTRL_1_82599 0x11104
+#define IXGBE_ECC_STATUS_82599 0x110E0
+#define IXGBE_BAR_CTRL_82599 0x110F4
+
+/* Time Sync Registers */
+#define IXGBE_TSYNCRXCTL 0x05188 /* Rx Time Sync Control register - RW */
+#define IXGBE_TSYNCTXCTL 0x08C00 /* Tx Time Sync Control register - RW */
+#define IXGBE_RXSTMPL 0x051E8 /* Rx timestamp Low - RO */
+#define IXGBE_RXSTMPH 0x051A4 /* Rx timestamp High - RO */
+#define IXGBE_RXSATRL 0x051A0 /* Rx timestamp attribute low - RO */
+#define IXGBE_RXSATRH 0x051A8 /* Rx timestamp attribute high - RO */
+#define IXGBE_RXMTRL 0x05120 /* RX message type register low - RW */
+#define IXGBE_TXSTMPL 0x08C04 /* Tx timestamp value Low - RO */
+#define IXGBE_TXSTMPH 0x08C08 /* Tx timestamp value High - RO */
+#define IXGBE_SYSTIML 0x08C0C /* System time register Low - RO */
+#define IXGBE_SYSTIMH 0x08C10 /* System time register High - RO */
+#define IXGBE_TIMINCA 0x08C14 /* Increment attributes register - RW */
+#define IXGBE_RXUDP 0x08C1C /* Time Sync Rx UDP Port - RW */
+
/* Diagnostic Registers */
#define IXGBE_RDSTATCTL 0x02C20
#define IXGBE_RDSTAT(_i) (0x02C00 + ((_i) * 4)) /* 0x02C00-0x02C1C */
#define IXGBE_RDHMPN 0x02F08
#define IXGBE_RIC_DW(_i) (0x02F10 + ((_i) * 4))
#define IXGBE_RDPROBE 0x02F20
+#define IXGBE_RDMAM 0x02F30
+#define IXGBE_RDMAD 0x02F34
#define IXGBE_TDSTATCTL 0x07C20
#define IXGBE_TDSTAT(_i) (0x07C00 + ((_i) * 4)) /* 0x07C00 - 0x07C1C */
#define IXGBE_TDHMPN 0x07F08
+#define IXGBE_TDHMPN2 0x082FC
+#define IXGBE_TXDESCIC 0x082CC
#define IXGBE_TIC_DW(_i) (0x07F10 + ((_i) * 4))
+#define IXGBE_TIC_DW2(_i) (0x082B0 + ((_i) * 4))
#define IXGBE_TDPROBE 0x07F20
#define IXGBE_TXBUFCTRL 0x0C600
#define IXGBE_TXBUFDATA0 0x0C610
@@ -412,6 +785,10 @@
#define IXGBE_TXDATARDPTR(_i) (0x0C720 + ((_i) * 4)) /* 8 of these C720-C72C*/
#define IXGBE_TXDESCRDPTR(_i) (0x0C730 + ((_i) * 4)) /* 8 of these C730-C73C*/
#define IXGBE_PCIEECCCTL 0x1106C
+#define IXGBE_PCIEECCCTL0 0x11100
+#define IXGBE_PCIEECCCTL1 0x11104
+#define IXGBE_RXDBUECC 0x03F70
+#define IXGBE_TXDBUECC 0x0CF70
#define IXGBE_PBTXECC 0x0C300
#define IXGBE_PBRXECC 0x03300
#define IXGBE_GHECCR 0x110B0
@@ -437,24 +814,74 @@
#define IXGBE_MSRWD 0x04260
#define IXGBE_MLADD 0x04264
#define IXGBE_MHADD 0x04268
+#define IXGBE_MAXFRS 0x04268
#define IXGBE_TREG 0x0426C
#define IXGBE_PCSS1 0x04288
#define IXGBE_PCSS2 0x0428C
#define IXGBE_XPCSS 0x04290
+#define IXGBE_MFLCN 0x04294
#define IXGBE_SERDESC 0x04298
#define IXGBE_MACS 0x0429C
#define IXGBE_AUTOC 0x042A0
#define IXGBE_LINKS 0x042A4
+#define IXGBE_LINKS2 0x04324
#define IXGBE_AUTOC2 0x042A8
#define IXGBE_AUTOC3 0x042AC
#define IXGBE_ANLP1 0x042B0
#define IXGBE_ANLP2 0x042B4
#define IXGBE_ATLASCTL 0x04800
+#define IXGBE_MMNGC 0x042D0
+#define IXGBE_ANLPNP1 0x042D4
+#define IXGBE_ANLPNP2 0x042D8
+#define IXGBE_KRPCSFC 0x042E0
+#define IXGBE_KRPCSS 0x042E4
+#define IXGBE_FECS1 0x042E8
+#define IXGBE_FECS2 0x042EC
+#define IXGBE_SMADARCTL 0x14F10
+#define IXGBE_MPVC 0x04318
+#define IXGBE_SGMIIC 0x04314
+
+/* Omer CORECTL */
+#define IXGBE_CORECTL 0x014F00
+/* BARCTRL */
+#define IXGBE_BARCTRL 0x110F4
+#define IXGBE_BARCTRL_FLSIZE 0x0700
+#define IXGBE_BARCTRL_CSRSIZE 0x2000
+
+/* RSCCTL Bit Masks */
+#define IXGBE_RSCCTL_RSCEN 0x01
+#define IXGBE_RSCCTL_MAXDESC_1 0x00
+#define IXGBE_RSCCTL_MAXDESC_4 0x04
+#define IXGBE_RSCCTL_MAXDESC_8 0x08
+#define IXGBE_RSCCTL_MAXDESC_16 0x0C
+
+/* RSCDBU Bit Masks */
+#define IXGBE_RSCDBU_RSCSMALDIS_MASK 0x0000007F
+#define IXGBE_RSCDBU_RSCACKDIS 0x00000080
/* RDRXCTL Bit Masks */
#define IXGBE_RDRXCTL_RDMTS_1_2 0x00000000 /* Rx Desc Min Threshold Size */
+#define IXGBE_RDRXCTL_CRCSTRIP 0x00000002 /* CRC Strip */
#define IXGBE_RDRXCTL_MVMEN 0x00000020
#define IXGBE_RDRXCTL_DMAIDONE 0x00000008 /* DMA init cycle done */
+#define IXGBE_RDRXCTL_AGGDIS 0x00010000 /* Aggregation disable */
+#define IXGBE_RDRXCTL_RSCFRSTSIZE 0x003E0000 /* RSC First packet size */
+#define IXGBE_RDRXCTL_RSCLLIDIS 0x00800000 /* Disable RSC compl on LLI */
+
+/* RQTC Bit Masks and Shifts */
+#define IXGBE_RQTC_SHIFT_TC(_i) ((_i) * 4)
+#define IXGBE_RQTC_TC0_MASK (0x7 << 0)
+#define IXGBE_RQTC_TC1_MASK (0x7 << 4)
+#define IXGBE_RQTC_TC2_MASK (0x7 << 8)
+#define IXGBE_RQTC_TC3_MASK (0x7 << 12)
+#define IXGBE_RQTC_TC4_MASK (0x7 << 16)
+#define IXGBE_RQTC_TC5_MASK (0x7 << 20)
+#define IXGBE_RQTC_TC6_MASK (0x7 << 24)
+#define IXGBE_RQTC_TC7_MASK (0x7 << 28)
+
+/* PSRTYPE.RQPL Bit masks and shift */
+#define IXGBE_PSRTYPE_RQPL_MASK 0x7
+#define IXGBE_PSRTYPE_RQPL_SHIFT 29
/* CTRL Bit Masks */
#define IXGBE_CTRL_GIO_DIS 0x00000004 /* Global IO Master Disable bit */
@@ -482,11 +909,18 @@
#define IXGBE_DCA_CTRL_DCA_MODE_CB2 0x02 /* DCA Mode CB2 */
#define IXGBE_DCA_RXCTRL_CPUID_MASK 0x0000001F /* Rx CPUID Mask */
+#define IXGBE_DCA_RXCTRL_CPUID_MASK_82599 0xFF000000 /* Rx CPUID Mask */
+#define IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599 24 /* Rx CPUID Shift */
#define IXGBE_DCA_RXCTRL_DESC_DCA_EN (1 << 5) /* DCA Rx Desc enable */
#define IXGBE_DCA_RXCTRL_HEAD_DCA_EN (1 << 6) /* DCA Rx Desc header enable */
#define IXGBE_DCA_RXCTRL_DATA_DCA_EN (1 << 7) /* DCA Rx Desc payload enable */
+#define IXGBE_DCA_RXCTRL_DESC_RRO_EN (1 << 9) /* DCA Rx rd Desc Relax Order */
+#define IXGBE_DCA_RXCTRL_DESC_WRO_EN (1 << 13) /* DCA Rx wr Desc Relax Order */
+#define IXGBE_DCA_RXCTRL_DESC_HSRO_EN (1 << 15) /* DCA Rx Split Header RO */
#define IXGBE_DCA_TXCTRL_CPUID_MASK 0x0000001F /* Tx CPUID Mask */
+#define IXGBE_DCA_TXCTRL_CPUID_MASK_82599 0xFF000000 /* Tx CPUID Mask */
+#define IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599 24 /* Tx CPUID Shift */
#define IXGBE_DCA_TXCTRL_DESC_DCA_EN (1 << 5) /* DCA Tx Desc enable */
#define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
#define IXGBE_DCA_MAX_QUEUES_82598 16 /* DCA regs only on 16 queues */
@@ -530,6 +964,8 @@
#define IXGBE_ATLAS_PDN_TX_1G_QL_ALL 0xF0
#define IXGBE_ATLAS_PDN_TX_AN_QL_ALL 0xF0
+/* Omer bit masks */
+#define IXGBE_CORECTL_WRITE_CMD 0x00010000
/* Device Type definitions for new protocol MDIO commands */
#define IXGBE_MDIO_PMA_PMD_DEV_TYPE 0x1
@@ -557,6 +993,11 @@
#define IXGBE_MDIO_PHY_SPEED_ABILITY 0x4 /* Speed Ability Reg */
#define IXGBE_MDIO_PHY_SPEED_10G 0x0001 /* 10G capable */
#define IXGBE_MDIO_PHY_SPEED_1G 0x0010 /* 1G capable */
+#define IXGBE_MDIO_PHY_SPEED_100M 0x0020 /* 100M capable */
+#define IXGBE_MDIO_PHY_EXT_ABILITY 0xB /* Ext Ability Reg */
+#define IXGBE_MDIO_PHY_10GBASET_ABILITY 0x0004 /* 10GBaseT capable */
+#define IXGBE_MDIO_PHY_1000BASET_ABILITY 0x0020 /* 1000BaseT capable */
+#define IXGBE_MDIO_PHY_100BASETX_ABILITY 0x0080 /* 100BaseTX capable */
#define IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR 0xC30A /* PHY_XS SDA/SCL Addr Reg */
#define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */
@@ -576,6 +1017,8 @@
/* PHY IDs*/
#define TN1010_PHY_ID 0x00A19410
#define TNX_FW_REV 0xB
+#define AQ1002_PHY_ID 0x03A1B420
+#define AQ_FW_REV 0x20
#define QT2022_PHY_ID 0x0043A400
#define ATH_PHY_ID 0x03429050
@@ -597,11 +1040,17 @@
/* General purpose Interrupt Enable */
#define IXGBE_SDP0_GPIEN 0x00000001 /* SDP0 */
#define IXGBE_SDP1_GPIEN 0x00000002 /* SDP1 */
+#define IXGBE_SDP2_GPIEN 0x00000004 /* SDP2 */
#define IXGBE_GPIE_MSIX_MODE 0x00000010 /* MSI-X mode */
#define IXGBE_GPIE_OCD 0x00000020 /* Other Clear Disable */
#define IXGBE_GPIE_EIMEN 0x00000040 /* Immediate Interrupt Enable */
#define IXGBE_GPIE_EIAME 0x40000000
#define IXGBE_GPIE_PBA_SUPPORT 0x80000000
+#define IXGBE_GPIE_RSC_DELAY_SHIFT 11
+#define IXGBE_GPIE_VTMODE_MASK 0x0000C000 /* VT Mode Mask */
+#define IXGBE_GPIE_VTMODE_16 0x00004000 /* 16 VFs 8 queues per VF */
+#define IXGBE_GPIE_VTMODE_32 0x00008000 /* 32 VFs 4 queues per VF */
+#define IXGBE_GPIE_VTMODE_64 0x0000C000 /* 64 VFs 2 queues per VF */
/* Transmit Flow Control status */
#define IXGBE_TFCS_TXOFF 0x00000001
@@ -642,6 +1091,23 @@
#define IXGBE_VMD_CTL_VMDQ_EN 0x00000001
#define IXGBE_VMD_CTL_VMDQ_FILTER 0x00000002
+/* VT_CTL bitmasks */
+#define IXGBE_VT_CTL_DIS_DEFPL 0x20000000 /* disable default pool */
+#define IXGBE_VT_CTL_REPLEN 0x40000000 /* replication enabled */
+#define IXGBE_VT_CTL_VT_ENABLE 0x00000001 /* Enable VT Mode */
+#define IXGBE_VT_CTL_POOL_SHIFT 7
+#define IXGBE_VT_CTL_POOL_MASK (0x3F << IXGBE_VT_CTL_POOL_SHIFT)
+
+/* VMOLR bitmasks */
+#define IXGBE_VMOLR_AUPE 0x01000000 /* accept untagged packets */
+#define IXGBE_VMOLR_ROMPE 0x02000000 /* accept packets in MTA tbl */
+#define IXGBE_VMOLR_ROPE 0x04000000 /* accept packets in UC tbl */
+#define IXGBE_VMOLR_BAM 0x08000000 /* accept broadcast packets */
+#define IXGBE_VMOLR_MPE 0x10000000 /* multicast promiscuous */
+
+/* VFRE bitmask */
+#define IXGBE_VFRE_ENABLE_ALL 0xFFFFFFFF
+
/* RDHMPN and TDHMPN bitmasks */
#define IXGBE_RDHMPN_RDICADDR 0x007FF800
#define IXGBE_RDHMPN_RDICRDREQ 0x00800000
@@ -650,6 +1116,41 @@
#define IXGBE_TDHMPN_TDICRDREQ 0x00800000
#define IXGBE_TDHMPN_TDICADDR_SHIFT 11
+#define IXGBE_RDMAM_MEM_SEL_SHIFT 13
+#define IXGBE_RDMAM_DWORD_SHIFT 9
+#define IXGBE_RDMAM_DESC_COMP_FIFO 1
+#define IXGBE_RDMAM_DFC_CMD_FIFO 2
+#define IXGBE_RDMAM_RSC_HEADER_ADDR 3
+#define IXGBE_RDMAM_TCN_STATUS_RAM 4
+#define IXGBE_RDMAM_WB_COLL_FIFO 5
+#define IXGBE_RDMAM_QSC_CNT_RAM 6
+#define IXGBE_RDMAM_QSC_FCOE_RAM 7
+#define IXGBE_RDMAM_QSC_QUEUE_CNT 8
+#define IXGBE_RDMAM_QSC_QUEUE_RAM 0xA
+#define IXGBE_RDMAM_QSC_RSC_RAM 0xB
+#define IXGBE_RDMAM_DESC_COM_FIFO_RANGE 135
+#define IXGBE_RDMAM_DESC_COM_FIFO_COUNT 4
+#define IXGBE_RDMAM_DFC_CMD_FIFO_RANGE 48
+#define IXGBE_RDMAM_DFC_CMD_FIFO_COUNT 7
+#define IXGBE_RDMAM_RSC_HEADER_ADDR_RANGE 32
+#define IXGBE_RDMAM_RSC_HEADER_ADDR_COUNT 4
+#define IXGBE_RDMAM_TCN_STATUS_RAM_RANGE 256
+#define IXGBE_RDMAM_TCN_STATUS_RAM_COUNT 9
+#define IXGBE_RDMAM_WB_COLL_FIFO_RANGE 8
+#define IXGBE_RDMAM_WB_COLL_FIFO_COUNT 4
+#define IXGBE_RDMAM_QSC_CNT_RAM_RANGE 64
+#define IXGBE_RDMAM_QSC_CNT_RAM_COUNT 4
+#define IXGBE_RDMAM_QSC_FCOE_RAM_RANGE 512
+#define IXGBE_RDMAM_QSC_FCOE_RAM_COUNT 5
+#define IXGBE_RDMAM_QSC_QUEUE_CNT_RANGE 32
+#define IXGBE_RDMAM_QSC_QUEUE_CNT_COUNT 4
+#define IXGBE_RDMAM_QSC_QUEUE_RAM_RANGE 128
+#define IXGBE_RDMAM_QSC_QUEUE_RAM_COUNT 8
+#define IXGBE_RDMAM_QSC_RSC_RAM_RANGE 32
+#define IXGBE_RDMAM_QSC_RSC_RAM_COUNT 8
+
+#define IXGBE_TXDESCIC_READY 0x80000000
+
/* Receive Checksum Control */
#define IXGBE_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */
#define IXGBE_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */
@@ -670,15 +1171,25 @@
#define IXGBE_RMCS_TFCE_PRIORITY 0x00000010 /* Tx Priority FC ena */
#define IXGBE_RMCS_ARBDIS 0x00000040 /* Arbitration disable bit */
+/* FCCFG Bit Masks */
+#define IXGBE_FCCFG_TFCE_802_3X 0x00000008 /* Tx link FC enable */
+#define IXGBE_FCCFG_TFCE_PRIORITY 0x00000010 /* Tx priority FC enable */
/* Interrupt register bitmasks */
/* Extended Interrupt Cause Read */
#define IXGBE_EICR_RTX_QUEUE 0x0000FFFF /* RTx Queue Interrupt */
+#define IXGBE_EICR_FLOW_DIR 0x00010000 /* FDir Exception */
+#define IXGBE_EICR_RX_MISS 0x00020000 /* Packet Buffer Overrun */
+#define IXGBE_EICR_PCI 0x00040000 /* PCI Exception */
+#define IXGBE_EICR_MAILBOX 0x00080000 /* VF to PF Mailbox Interrupt */
#define IXGBE_EICR_LSC 0x00100000 /* Link Status Change */
+#define IXGBE_EICR_LINKSEC 0x00200000 /* PN Threshold */
#define IXGBE_EICR_MNG 0x00400000 /* Manageability Event Interrupt */
#define IXGBE_EICR_GPI_SDP0 0x01000000 /* Gen Purpose Interrupt on SDP0 */
#define IXGBE_EICR_GPI_SDP1 0x02000000 /* Gen Purpose Interrupt on SDP1 */
+#define IXGBE_EICR_GPI_SDP2 0x04000000 /* Gen Purpose Interrupt on SDP2 */
+#define IXGBE_EICR_ECC 0x10000000 /* ECC Error */
#define IXGBE_EICR_PBUR 0x10000000 /* Packet Buffer Handler Error */
#define IXGBE_EICR_DHER 0x20000000 /* Descriptor Handler Error */
#define IXGBE_EICR_TCP_TIMER 0x40000000 /* TCP Timer */
@@ -686,10 +1197,16 @@
/* Extended Interrupt Cause Set */
#define IXGBE_EICS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */
+#define IXGBE_EICS_FLOW_DIR IXGBE_EICR_FLOW_DIR /* FDir Exception */
+#define IXGBE_EICS_RX_MISS IXGBE_EICR_RX_MISS /* Pkt Buffer Overrun */
+#define IXGBE_EICS_PCI IXGBE_EICR_PCI /* PCI Exception */
+#define IXGBE_EICS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */
#define IXGBE_EICS_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EICS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
#define IXGBE_EICS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */
#define IXGBE_EICS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */
+#define IXGBE_EICS_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */
+#define IXGBE_EICS_ECC IXGBE_EICR_ECC /* ECC Error */
#define IXGBE_EICS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */
#define IXGBE_EICS_DHER IXGBE_EICR_DHER /* Desc Handler Error */
#define IXGBE_EICS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */
@@ -697,10 +1214,16 @@
/* Extended Interrupt Mask Set */
#define IXGBE_EIMS_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */
+#define IXGBE_EIMS_FLOW_DIR IXGBE_EICR_FLOW_DIR /* FDir Exception */
+#define IXGBE_EIMS_RX_MISS IXGBE_EICR_RX_MISS /* Packet Buffer Overrun */
+#define IXGBE_EIMS_PCI IXGBE_EICR_PCI /* PCI Exception */
+#define IXGBE_EIMS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */
#define IXGBE_EIMS_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EIMS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
#define IXGBE_EIMS_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */
#define IXGBE_EIMS_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */
+#define IXGBE_EIMS_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */
+#define IXGBE_EIMS_ECC IXGBE_EICR_ECC /* ECC Error */
#define IXGBE_EIMS_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */
#define IXGBE_EIMS_DHER IXGBE_EICR_DHER /* Descr Handler Error */
#define IXGBE_EIMS_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */
@@ -708,10 +1231,16 @@
/* Extended Interrupt Mask Clear */
#define IXGBE_EIMC_RTX_QUEUE IXGBE_EICR_RTX_QUEUE /* RTx Queue Interrupt */
+#define IXGBE_EIMC_FLOW_DIR IXGBE_EICR_FLOW_DIR /* FDir Exception */
+#define IXGBE_EIMC_RX_MISS IXGBE_EICR_RX_MISS /* Packet Buffer Overrun */
+#define IXGBE_EIMC_PCI IXGBE_EICR_PCI /* PCI Exception */
+#define IXGBE_EIMC_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */
#define IXGBE_EIMC_LSC IXGBE_EICR_LSC /* Link Status Change */
#define IXGBE_EIMC_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
#define IXGBE_EIMC_GPI_SDP0 IXGBE_EICR_GPI_SDP0 /* SDP0 Gen Purpose Int */
#define IXGBE_EIMC_GPI_SDP1 IXGBE_EICR_GPI_SDP1 /* SDP1 Gen Purpose Int */
+#define IXGBE_EIMC_GPI_SDP2 IXGBE_EICR_GPI_SDP2 /* SDP2 Gen Purpose Int */
+#define IXGBE_EIMC_ECC IXGBE_EICR_ECC /* ECC Error */
#define IXGBE_EIMC_PBUR IXGBE_EICR_PBUR /* Pkt Buf Handler Err */
#define IXGBE_EIMC_DHER IXGBE_EICR_DHER /* Desc Handler Err */
#define IXGBE_EIMC_TCP_TIMER IXGBE_EICR_TCP_TIMER /* TCP Timer */
@@ -734,12 +1263,45 @@
#define IXGBE_IMIREXT_CTRL_SYN 0x00020000 /* Check SYN bit in header */
#define IXGBE_IMIREXT_CTRL_FIN 0x00040000 /* Check FIN bit in header */
#define IXGBE_IMIREXT_CTRL_BP 0x00080000 /* Bypass check of control bits */
+#define IXGBE_IMIR_SIZE_BP_82599 0x00001000 /* Packet size bypass */
+#define IXGBE_IMIR_CTRL_URG_82599 0x00002000 /* Check URG bit in header */
+#define IXGBE_IMIR_CTRL_ACK_82599 0x00004000 /* Check ACK bit in header */
+#define IXGBE_IMIR_CTRL_PSH_82599 0x00008000 /* Check PSH bit in header */
+#define IXGBE_IMIR_CTRL_RST_82599 0x00010000 /* Check RST bit in header */
+#define IXGBE_IMIR_CTRL_SYN_82599 0x00020000 /* Check SYN bit in header */
+#define IXGBE_IMIR_CTRL_FIN_82599 0x00040000 /* Check FIN bit in header */
+#define IXGBE_IMIR_CTRL_BP_82599 0x00080000 /* Bypass check of control bits */
+#define IXGBE_IMIR_LLI_EN_82599 0x00100000 /* Enables low latency Int */
+#define IXGBE_IMIR_RX_QUEUE_MASK_82599 0x0000007F /* Rx Queue Mask */
+#define IXGBE_IMIR_RX_QUEUE_SHIFT_82599 21 /* Rx Queue Shift */
+#define IXGBE_IMIRVP_PRIORITY_MASK 0x00000007 /* VLAN priority mask */
+#define IXGBE_IMIRVP_PRIORITY_EN 0x00000008 /* VLAN priority enable */
+
+#define IXGBE_MAX_FTQF_FILTERS 128
+#define IXGBE_FTQF_PROTOCOL_MASK 0x00000003
+#define IXGBE_FTQF_PROTOCOL_TCP 0x00000000
+#define IXGBE_FTQF_PROTOCOL_UDP 0x00000001
+#define IXGBE_FTQF_PROTOCOL_SCTP 2
+#define IXGBE_FTQF_PRIORITY_MASK 0x00000007
+#define IXGBE_FTQF_PRIORITY_SHIFT 2
+#define IXGBE_FTQF_POOL_MASK 0x0000003F
+#define IXGBE_FTQF_POOL_SHIFT 8
+#define IXGBE_FTQF_5TUPLE_MASK_MASK 0x0000001F
+#define IXGBE_FTQF_5TUPLE_MASK_SHIFT 25
+#define IXGBE_FTQF_SOURCE_ADDR_MASK 0x1E
+#define IXGBE_FTQF_DEST_ADDR_MASK 0x1D
+#define IXGBE_FTQF_SOURCE_PORT_MASK 0x1B
+#define IXGBE_FTQF_DEST_PORT_MASK 0x17
+#define IXGBE_FTQF_PROTOCOL_COMP_MASK 0x0F
+#define IXGBE_FTQF_POOL_MASK_EN 0x40000000
+#define IXGBE_FTQF_QUEUE_ENABLE 0x80000000
/* Interrupt clear mask */
#define IXGBE_IRQ_CLEAR_MASK 0xFFFFFFFF
/* Interrupt Vector Allocation Registers */
#define IXGBE_IVAR_REG_NUM 25
+#define IXGBE_IVAR_REG_NUM_82599 64
#define IXGBE_IVAR_TXRX_ENTRY 96
#define IXGBE_IVAR_RX_ENTRY 64
#define IXGBE_IVAR_RX_QUEUE(_i) (0 + (_i))
@@ -753,6 +1315,32 @@
#define IXGBE_IVAR_ALLOC_VAL 0x80 /* Interrupt Allocation valid */
+/* ETYPE Queue Filter/Select Bit Masks */
+#define IXGBE_MAX_ETQF_FILTERS 8
+#define IXGBE_ETQF_FCOE 0x08000000 /* bit 27 */
+#define IXGBE_ETQF_BCN 0x10000000 /* bit 28 */
+#define IXGBE_ETQF_1588 0x40000000 /* bit 30 */
+#define IXGBE_ETQF_FILTER_EN 0x80000000 /* bit 31 */
+#define IXGBE_ETQF_POOL_ENABLE (1 << 26) /* bit 26 */
+
+#define IXGBE_ETQS_RX_QUEUE 0x007F0000 /* bits 22:16 */
+#define IXGBE_ETQS_RX_QUEUE_SHIFT 16
+#define IXGBE_ETQS_LLI 0x20000000 /* bit 29 */
+#define IXGBE_ETQS_QUEUE_EN 0x80000000 /* bit 31 */
+
+/*
+ * ETQF filter list: one static filter per filter consumer. This is
+ * to avoid filter collisions later. Add new filters
+ * here!!
+ *
+ * Current filters:
+ * EAPOL 802.1x (0x888e): Filter 0
+ * FCoE (0x8906): Filter 2
+ * 1588 (0x88f7): Filter 3
+ */
+#define IXGBE_ETQF_FILTER_EAPOL 0
+#define IXGBE_ETQF_FILTER_FCOE 2
+#define IXGBE_ETQF_FILTER_1588 3
/* VLAN Control Bit Masks */
#define IXGBE_VLNCTRL_VET 0x0000FFFF /* bits 0-15 */
#define IXGBE_VLNCTRL_CFI 0x10000000 /* bit 28 */
@@ -760,6 +1348,9 @@
#define IXGBE_VLNCTRL_VFE 0x40000000 /* bit 30 */
#define IXGBE_VLNCTRL_VME 0x80000000 /* bit 31 */
+/* VLAN pool filtering masks */
+#define IXGBE_VLVF_VIEN 0x80000000 /* filter is valid */
+#define IXGBE_VLVF_ENTRIES 64
#define IXGBE_ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.1q protocol */
@@ -772,7 +1363,8 @@
#define IXGBE_STATUS_LAN_ID_1 0x00000004 /* LAN ID 1 */
/* ESDP Bit Masks */
-#define IXGBE_ESDP_SDP1 0x00000001
+#define IXGBE_ESDP_SDP0 0x00000001
+#define IXGBE_ESDP_SDP1 0x00000002
#define IXGBE_ESDP_SDP4 0x00000010 /* SDP4 Data Value */
#define IXGBE_ESDP_SDP5 0x00000020 /* SDP5 Data Value */
#define IXGBE_ESDP_SDP6 0x00000040 /* SDP6 Data Value */
@@ -800,7 +1392,7 @@
#define IXGBE_LED_OFF 0xF
/* AUTOC Bit Masks */
-#define IXGBE_AUTOC_KX4_KX_SUPP 0xC0000000
+#define IXGBE_AUTOC_KX4_KX_SUPP_MASK 0xC0000000
#define IXGBE_AUTOC_KX4_SUPP 0x80000000
#define IXGBE_AUTOC_KX_SUPP 0x40000000
#define IXGBE_AUTOC_PAUSE 0x30000000
@@ -809,9 +1401,17 @@
#define IXGBE_AUTOC_AN_RX_LOOSE 0x01000000
#define IXGBE_AUTOC_AN_RX_DRIFT 0x00800000
#define IXGBE_AUTOC_AN_RX_ALIGN 0x007C0000
+#define IXGBE_AUTOC_FECA 0x00040000
+#define IXGBE_AUTOC_FECR 0x00020000
+#define IXGBE_AUTOC_KR_SUPP 0x00010000
#define IXGBE_AUTOC_AN_RESTART 0x00001000
#define IXGBE_AUTOC_FLU 0x00000001
#define IXGBE_AUTOC_LMS_SHIFT 13
+#define IXGBE_AUTOC_LMS_10G_SERIAL (0x3 << IXGBE_AUTOC_LMS_SHIFT)
+#define IXGBE_AUTOC_LMS_KX4_KX_KR (0x4 << IXGBE_AUTOC_LMS_SHIFT)
+#define IXGBE_AUTOC_LMS_SGMII_1G_100M (0x5 << IXGBE_AUTOC_LMS_SHIFT)
+#define IXGBE_AUTOC_LMS_KX4_KX_KR_1G_AN (0x6 << IXGBE_AUTOC_LMS_SHIFT)
+#define IXGBE_AUTOC_LMS_KX4_KX_KR_SGMII (0x7 << IXGBE_AUTOC_LMS_SHIFT)
#define IXGBE_AUTOC_LMS_MASK (0x7 << IXGBE_AUTOC_LMS_SHIFT)
#define IXGBE_AUTOC_LMS_1G_LINK_NO_AN (0x0 << IXGBE_AUTOC_LMS_SHIFT)
#define IXGBE_AUTOC_LMS_10G_LINK_NO_AN (0x1 << IXGBE_AUTOC_LMS_SHIFT)
@@ -820,15 +1420,24 @@
#define IXGBE_AUTOC_LMS_KX4_AN_1G_AN (0x6 << IXGBE_AUTOC_LMS_SHIFT)
#define IXGBE_AUTOC_LMS_ATTACH_TYPE (0x7 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT)
-#define IXGBE_AUTOC_1G_PMA_PMD 0x00000200
-#define IXGBE_AUTOC_10G_PMA_PMD 0x00000180
-#define IXGBE_AUTOC_10G_PMA_PMD_SHIFT 7
-#define IXGBE_AUTOC_1G_PMA_PMD_SHIFT 9
+#define IXGBE_AUTOC_1G_PMA_PMD_MASK 0x00000200
+#define IXGBE_AUTOC_1G_PMA_PMD_SHIFT 9
+#define IXGBE_AUTOC_10G_PMA_PMD_MASK 0x00000180
+#define IXGBE_AUTOC_10G_PMA_PMD_SHIFT 7
#define IXGBE_AUTOC_10G_XAUI (0x0 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT)
#define IXGBE_AUTOC_10G_KX4 (0x1 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT)
#define IXGBE_AUTOC_10G_CX4 (0x2 << IXGBE_AUTOC_10G_PMA_PMD_SHIFT)
#define IXGBE_AUTOC_1G_BX (0x0 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT)
#define IXGBE_AUTOC_1G_KX (0x1 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT)
+#define IXGBE_AUTOC_1G_SFI (0x0 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT)
+#define IXGBE_AUTOC_1G_KX_BX (0x1 << IXGBE_AUTOC_1G_PMA_PMD_SHIFT)
+
+#define IXGBE_AUTOC2_UPPER_MASK 0xFFFF0000
+#define IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_MASK 0x00030000
+#define IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT 16
+#define IXGBE_AUTOC2_10G_KR (0x0 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT)
+#define IXGBE_AUTOC2_10G_XFI (0x1 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT)
+#define IXGBE_AUTOC2_10G_SFI (0x2 << IXGBE_AUTOC2_10G_SERIAL_PMA_PMD_SHIFT)
/* LINKS Bit Masks */
#define IXGBE_LINKS_KX_AN_COMP 0x80000000
@@ -838,6 +1447,7 @@
#define IXGBE_LINKS_RX_MODE 0x06000000
#define IXGBE_LINKS_TX_MODE 0x01800000
#define IXGBE_LINKS_XGXS_EN 0x00400000
+#define IXGBE_LINKS_SGMII_EN 0x02000000
#define IXGBE_LINKS_PCS_1G_EN 0x00200000
#define IXGBE_LINKS_1G_AN_EN 0x00100000
#define IXGBE_LINKS_KX_AN_IDLE 0x00080000
@@ -847,11 +1457,13 @@
#define IXGBE_LINKS_TL_FAULT 0x00001000
#define IXGBE_LINKS_SIGNAL 0x00000F00
+#define IXGBE_LINKS_SPEED_82599 0x30000000
+#define IXGBE_LINKS_SPEED_10G_82599 0x30000000
+#define IXGBE_LINKS_SPEED_1G_82599 0x20000000
+#define IXGBE_LINKS_SPEED_100_82599 0x10000000
#define IXGBE_LINK_UP_TIME 90 /* 9.0 Seconds */
#define IXGBE_AUTO_NEG_TIME 45 /* 4.5 Seconds */
-#define FIBER_LINK_UP_LIMIT 50
-
/* PCS1GLSTA Bit Masks */
#define IXGBE_PCS1GLSTA_LINK_OK 1
#define IXGBE_PCS1GLSTA_SYNK_OK 0x10
@@ -923,6 +1535,13 @@
#define IXGBE_FW_PTR 0x0F
#define IXGBE_PBANUM0_PTR 0x15
#define IXGBE_PBANUM1_PTR 0x16
+#define IXGBE_SAN_MAC_ADDR_PTR 0x28
+#define IXGBE_DEVICE_CAPS 0x2C
+#define IXGBE_PCIE_MSIX_82599_CAPS 0x72
+#define IXGBE_PCIE_MSIX_82598_CAPS 0x62
+
+/* MSI-X capability fields masks */
+#define IXGBE_PCIE_MSIX_TBL_SZ_MASK 0x7FF
/* Legacy EEPROM word offsets */
#define IXGBE_ISCSI_BOOT_CAPS 0x0033
@@ -961,6 +1580,11 @@
#define IXGBE_EERD_ATTEMPTS 100000
#endif
+#define IXGBE_SAN_MAC_ADDR_PORT0_OFFSET 0x0
+#define IXGBE_SAN_MAC_ADDR_PORT1_OFFSET 0x3
+#define IXGBE_DEVICE_CAPS_ALLOW_ANY_SFP 0x1
+#define IXGBE_DEVICE_CAPS_FCOE_OFFLOADS 0x2
+
/* PCI Bus Info */
#define IXGBE_PCI_LINK_STATUS 0xB2
#define IXGBE_PCI_LINK_WIDTH 0x3F0
@@ -1025,6 +1649,7 @@
#define IXGBE_RXCTRL_RXEN 0x00000001 /* Enable Receiver */
#define IXGBE_RXCTRL_DMBYPS 0x00000002 /* Descriptor Monitor Bypass */
#define IXGBE_RXDCTL_ENABLE 0x02000000 /* Enable specific Rx Queue */
+#define IXGBE_RXDCTL_VME 0x40000000 /* VLAN mode enable */
#define IXGBE_FCTRL_SBP 0x00000002 /* Store Bad Packet */
#define IXGBE_FCTRL_MPE 0x00000100 /* Multicast Promiscuous Ena*/
@@ -1035,9 +1660,23 @@
/* Receive Priority Flow Control Enable */
#define IXGBE_FCTRL_RPFCE 0x00004000
#define IXGBE_FCTRL_RFCE 0x00008000 /* Receive Flow Control Ena */
+#define IXGBE_MFLCN_PMCF 0x00000001 /* Pass MAC Control Frames */
+#define IXGBE_MFLCN_DPF 0x00000002 /* Discard Pause Frame */
+#define IXGBE_MFLCN_RPFCE 0x00000004 /* Receive Priority FC Enable */
+#define IXGBE_MFLCN_RFCE 0x00000008 /* Receive FC Enable */
/* Multiple Receive Queue Control */
#define IXGBE_MRQC_RSSEN 0x00000001 /* RSS Enable */
+#define IXGBE_MRQC_MRQE_MASK 0xF /* Bits 3:0 */
+#define IXGBE_MRQC_RT8TCEN 0x00000002 /* 8 TC no RSS */
+#define IXGBE_MRQC_RT4TCEN 0x00000003 /* 4 TC no RSS */
+#define IXGBE_MRQC_RTRSS8TCEN 0x00000004 /* 8 TC w/ RSS */
+#define IXGBE_MRQC_RTRSS4TCEN 0x00000005 /* 4 TC w/ RSS */
+#define IXGBE_MRQC_VMDQEN 0x00000008 /* VMDq2 64 pools no RSS */
+#define IXGBE_MRQC_VMDQRSS32EN 0x0000000A /* VMDq2 32 pools w/ RSS */
+#define IXGBE_MRQC_VMDQRSS64EN 0x0000000B /* VMDq2 64 pools w/ RSS */
+#define IXGBE_MRQC_VMDQRT8TCEN 0x0000000C /* VMDq2/RT 16 pool 8 TC */
+#define IXGBE_MRQC_VMDQRT4TCEN 0x0000000D /* VMDq2/RT 32 pool 4 TC */
#define IXGBE_MRQC_RSS_FIELD_MASK 0xFFFF0000
#define IXGBE_MRQC_RSS_FIELD_IPV4_TCP 0x00010000
#define IXGBE_MRQC_RSS_FIELD_IPV4 0x00020000
@@ -1048,6 +1687,12 @@
#define IXGBE_MRQC_RSS_FIELD_IPV4_UDP 0x00400000
#define IXGBE_MRQC_RSS_FIELD_IPV6_UDP 0x00800000
#define IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP 0x01000000
+#define IXGBE_MRQC_L3L4TXSWEN 0x00008000
+
+/* Queue Drop Enable */
+#define IXGBE_QDE_ENABLE 0x00000001
+#define IXGBE_QDE_IDX_MASK 0x00007F00
+#define IXGBE_QDE_IDX_SHIFT 8
#define IXGBE_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */
#define IXGBE_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */
@@ -1059,10 +1704,26 @@
#define IXGBE_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */
#define IXGBE_TXD_STAT_DD 0x00000001 /* Descriptor Done */
+#define IXGBE_RXDADV_IPSEC_STATUS_SECP 0x00020000
+#define IXGBE_RXDADV_IPSEC_ERROR_INVALID_PROTOCOL 0x08000000
+#define IXGBE_RXDADV_IPSEC_ERROR_INVALID_LENGTH 0x10000000
+#define IXGBE_RXDADV_IPSEC_ERROR_AUTH_FAILED 0x18000000
+#define IXGBE_RXDADV_IPSEC_ERROR_BIT_MASK 0x18000000
+/* Multiple Transmit Queue Command Register */
+#define IXGBE_MTQC_RT_ENA 0x1 /* DCB Enable */
+#define IXGBE_MTQC_VT_ENA 0x2 /* VMDQ2 Enable */
+#define IXGBE_MTQC_64Q_1PB 0x0 /* 64 queues 1 pack buffer */
+#define IXGBE_MTQC_32VF 0x8 /* 4 TX Queues per pool w/32VF's */
+#define IXGBE_MTQC_64VF 0x4 /* 2 TX Queues per pool w/64VF's */
+#define IXGBE_MTQC_8TC_8TQ 0xC /* 8 TC if RT_ENA or 8 TQ if VT_ENA */
+
/* Receive Descriptor bit definitions */
#define IXGBE_RXD_STAT_DD 0x01 /* Descriptor Done */
#define IXGBE_RXD_STAT_EOP 0x02 /* End of Packet */
+#define IXGBE_RXD_STAT_FLM 0x04 /* FDir Match */
#define IXGBE_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */
+#define IXGBE_RXDADV_NEXTP_MASK 0x000FFFF0 /* Next Descriptor Index */
+#define IXGBE_RXDADV_NEXTP_SHIFT 0x00000004
#define IXGBE_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */
#define IXGBE_RXD_STAT_L4CS 0x20 /* L4 xsum calculated */
#define IXGBE_RXD_STAT_IPCS 0x40 /* IP xsum calculated */
@@ -1071,6 +1732,10 @@
#define IXGBE_RXD_STAT_VEXT 0x200 /* 1st VLAN found */
#define IXGBE_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */
#define IXGBE_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */
+#define IXGBE_RXD_STAT_LLINT 0x800 /* Pkt caused Low Latency Interrupt */
+#define IXGBE_RXD_STAT_TS 0x10000 /* Time Stamp */
+#define IXGBE_RXD_STAT_SECP 0x20000 /* Security Processing */
+#define IXGBE_RXD_STAT_LB 0x40000 /* Loopback Status */
#define IXGBE_RXD_STAT_ACK 0x8000 /* ACK Packet indication */
#define IXGBE_RXD_ERR_CE 0x01 /* CRC Error */
#define IXGBE_RXD_ERR_LE 0x02 /* Length Error */
@@ -1079,6 +1744,13 @@
#define IXGBE_RXD_ERR_USE 0x20 /* Undersize Error */
#define IXGBE_RXD_ERR_TCPE 0x40 /* TCP/UDP Checksum Error */
#define IXGBE_RXD_ERR_IPE 0x80 /* IP Checksum Error */
+#define IXGBE_RXDADV_ERR_MASK 0xfff00000 /* RDESC.ERRORS mask */
+#define IXGBE_RXDADV_ERR_SHIFT 20 /* RDESC.ERRORS shift */
+#define IXGBE_RXDADV_ERR_FCEOFE 0x80000000 /* FCoEFe/IPE */
+#define IXGBE_RXDADV_ERR_FCERR 0x00700000 /* FCERR/FDIRERR */
+#define IXGBE_RXDADV_ERR_FDIR_LEN 0x00100000 /* FDIR Length error */
+#define IXGBE_RXDADV_ERR_FDIR_DROP 0x00200000 /* FDIR Drop error */
+#define IXGBE_RXDADV_ERR_FDIR_COLL 0x00400000 /* FDIR Collision error */
#define IXGBE_RXDADV_ERR_HBO 0x00800000 /*Header Buffer Overflow */
#define IXGBE_RXDADV_ERR_CE 0x01000000 /* CRC Error */
#define IXGBE_RXDADV_ERR_LE 0x02000000 /* Length Error */
@@ -1093,9 +1765,29 @@
#define IXGBE_RXD_CFI_MASK 0x1000 /* CFI is bit 12 */
#define IXGBE_RXD_CFI_SHIFT 12
+#define IXGBE_RXDADV_STAT_DD IXGBE_RXD_STAT_DD /* Done */
+#define IXGBE_RXDADV_STAT_EOP IXGBE_RXD_STAT_EOP /* End of Packet */
+#define IXGBE_RXDADV_STAT_FLM IXGBE_RXD_STAT_FLM /* FDir Match */
+#define IXGBE_RXDADV_STAT_VP IXGBE_RXD_STAT_VP /* IEEE VLAN Pkt */
+#define IXGBE_RXDADV_STAT_MASK 0x000fffff /* Stat/NEXTP: bit 0-19 */
+#define IXGBE_RXDADV_STAT_FCEOFS 0x00000040 /* FCoE EOF/SOF Stat */
+#define IXGBE_RXDADV_STAT_FCSTAT 0x00000030 /* FCoE Pkt Stat */
+#define IXGBE_RXDADV_STAT_FCSTAT_NOMTCH 0x00000000 /* 00: No Ctxt Match */
+#define IXGBE_RXDADV_STAT_FCSTAT_NODDP 0x00000010 /* 01: Ctxt w/o DDP */
+#define IXGBE_RXDADV_STAT_FCSTAT_FCPRSP 0x00000020 /* 10: Recv. FCP_RSP */
+#define IXGBE_RXDADV_STAT_FCSTAT_DDP 0x00000030 /* 11: Ctxt w/ DDP */
+
+/* PSRTYPE bit definitions */
+#define IXGBE_PSRTYPE_TCPHDR 0x00000010
+#define IXGBE_PSRTYPE_UDPHDR 0x00000020
+#define IXGBE_PSRTYPE_IPV4HDR 0x00000100
+#define IXGBE_PSRTYPE_IPV6HDR 0x00000200
/* SRRCTL bit definitions */
#define IXGBE_SRRCTL_BSIZEPKT_SHIFT 10 /* so many KBs */
+#define IXGBE_SRRCTL_RDMTS_SHIFT 22
+#define IXGBE_SRRCTL_RDMTS_MASK 0x01C00000
+#define IXGBE_SRRCTL_DROP_EN 0x10000000
#define IXGBE_SRRCTL_BSIZEPKT_MASK 0x0000007F
#define IXGBE_SRRCTL_BSIZEHDR_MASK 0x00003F00
#define IXGBE_SRRCTL_DESCTYPE_LEGACY 0x00000000
@@ -1110,7 +1802,10 @@
#define IXGBE_RXDADV_RSSTYPE_MASK 0x0000000F
#define IXGBE_RXDADV_PKTTYPE_MASK 0x0000FFF0
+#define IXGBE_RXDADV_PKTTYPE_MASK_EX 0x0001FFF0
#define IXGBE_RXDADV_HDRBUFLEN_MASK 0x00007FE0
+#define IXGBE_RXDADV_RSCCNT_MASK 0x001E0000
+#define IXGBE_RXDADV_RSCCNT_SHIFT 17
#define IXGBE_RXDADV_HDRBUFLEN_SHIFT 5
#define IXGBE_RXDADV_SPLITHEADER_EN 0x00001000
#define IXGBE_RXDADV_SPH 0x8000
@@ -1137,6 +1832,20 @@
#define IXGBE_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */
#define IXGBE_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */
#define IXGBE_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */
+#define IXGBE_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */
+#define IXGBE_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */
+#define IXGBE_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */
+#define IXGBE_RXDADV_PKTTYPE_ETQF 0x00008000 /* PKTTYPE is ETQF index */
+#define IXGBE_RXDADV_PKTTYPE_ETQF_MASK 0x00000070 /* ETQF has 8 indices */
+#define IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT 4 /* Right-shift 4 bits */
+
+/* Security Processing bit Indication */
+#define IXGBE_RXDADV_LNKSEC_STATUS_SECP 0x00020000
+#define IXGBE_RXDADV_LNKSEC_ERROR_NO_SA_MATCH 0x08000000
+#define IXGBE_RXDADV_LNKSEC_ERROR_REPLAY_ERROR 0x10000000
+#define IXGBE_RXDADV_LNKSEC_ERROR_BIT_MASK 0x18000000
+#define IXGBE_RXDADV_LNKSEC_ERROR_BAD_SIG 0x18000000
+
/* Masks to determine if packets should be dropped due to frame errors */
#define IXGBE_RXD_ERR_FRAME_ERR_MASK ( \
IXGBE_RXD_ERR_CE | \
@@ -1166,10 +1875,14 @@
#define IXGBE_RX_DESC_SPECIAL_PRI_SHIFT 0x000D /* Priority in upper 3 of 16 */
#define IXGBE_TX_DESC_SPECIAL_PRI_SHIFT IXGBE_RX_DESC_SPECIAL_PRI_SHIFT
-#ifndef __le16
/* Little Endian defines */
+#ifndef __le16
#define __le16 u16
+#endif
+#ifndef __le32
#define __le32 u32
+#endif
+#ifndef __le64
#define __le64 u64
#endif
@@ -1180,6 +1893,77 @@
#define __be64 u64
#endif
+enum ixgbe_fdir_pballoc_type {
+ IXGBE_FDIR_PBALLOC_64K = 0,
+ IXGBE_FDIR_PBALLOC_128K,
+ IXGBE_FDIR_PBALLOC_256K,
+};
+#define IXGBE_FDIR_PBALLOC_SIZE_SHIFT 16
+
+/* Flow Director register values */
+#define IXGBE_FDIRCTRL_PBALLOC_64K 0x00000001
+#define IXGBE_FDIRCTRL_PBALLOC_128K 0x00000002
+#define IXGBE_FDIRCTRL_PBALLOC_256K 0x00000003
+#define IXGBE_FDIRCTRL_INIT_DONE 0x00000008
+#define IXGBE_FDIRCTRL_PERFECT_MATCH 0x00000010
+#define IXGBE_FDIRCTRL_REPORT_STATUS 0x00000020
+#define IXGBE_FDIRCTRL_REPORT_STATUS_ALWAYS 0x00000080
+#define IXGBE_FDIRCTRL_DROP_Q_SHIFT 8
+#define IXGBE_FDIRCTRL_FLEX_SHIFT 16
+#define IXGBE_FDIRCTRL_SEARCHLIM 0x00800000
+#define IXGBE_FDIRCTRL_MAX_LENGTH_SHIFT 24
+#define IXGBE_FDIRCTRL_FULL_THRESH_MASK 0xF0000000
+#define IXGBE_FDIRCTRL_FULL_THRESH_SHIFT 28
+
+#define IXGBE_FDIRTCPM_DPORTM_SHIFT 16
+#define IXGBE_FDIRUDPM_DPORTM_SHIFT 16
+#define IXGBE_FDIRIP6M_DIPM_SHIFT 16
+#define IXGBE_FDIRM_VLANID 0x00000001
+#define IXGBE_FDIRM_VLANP 0x00000002
+#define IXGBE_FDIRM_POOL 0x00000004
+#define IXGBE_FDIRM_L3P 0x00000008
+#define IXGBE_FDIRM_L4P 0x00000010
+#define IXGBE_FDIRM_FLEX 0x00000020
+#define IXGBE_FDIRM_DIPv6 0x00000040
+
+#define IXGBE_FDIRFREE_FREE_MASK 0xFFFF
+#define IXGBE_FDIRFREE_FREE_SHIFT 0
+#define IXGBE_FDIRFREE_COLL_MASK 0x7FFF0000
+#define IXGBE_FDIRFREE_COLL_SHIFT 16
+#define IXGBE_FDIRLEN_MAXLEN_MASK 0x3F
+#define IXGBE_FDIRLEN_MAXLEN_SHIFT 0
+#define IXGBE_FDIRLEN_MAXHASH_MASK 0x7FFF0000
+#define IXGBE_FDIRLEN_MAXHASH_SHIFT 16
+#define IXGBE_FDIRUSTAT_ADD_MASK 0xFFFF
+#define IXGBE_FDIRUSTAT_ADD_SHIFT 0
+#define IXGBE_FDIRUSTAT_REMOVE_MASK 0xFFFF0000
+#define IXGBE_FDIRUSTAT_REMOVE_SHIFT 16
+#define IXGBE_FDIRFSTAT_FADD_MASK 0x00FF
+#define IXGBE_FDIRFSTAT_FADD_SHIFT 0
+#define IXGBE_FDIRFSTAT_FREMOVE_MASK 0xFF00
+#define IXGBE_FDIRFSTAT_FREMOVE_SHIFT 8
+#define IXGBE_FDIRPORT_DESTINATION_SHIFT 16
+#define IXGBE_FDIRVLAN_FLEX_SHIFT 16
+#define IXGBE_FDIRHASH_BUCKET_VALID_SHIFT 15
+#define IXGBE_FDIRHASH_SIG_SW_INDEX_SHIFT 16
+
+#define IXGBE_FDIRCMD_CMD_ADD_FLOW 0x00000001
+#define IXGBE_FDIRCMD_CMD_REMOVE_FLOW 0x00000002
+#define IXGBE_FDIRCMD_CMD_QUERY_REM_FILT 0x00000003
+#define IXGBE_FDIRCMD_CMD_QUERY_REM_HASH 0x00000007
+#define IXGBE_FDIRCMD_FILTER_UPDATE 0x00000008
+#define IXGBE_FDIRCMD_IPv6DMATCH 0x00000010
+#define IXGBE_FDIRCMD_L4TYPE_UDP 0x00000020
+#define IXGBE_FDIRCMD_L4TYPE_TCP 0x00000040
+#define IXGBE_FDIRCMD_L4TYPE_SCTP 0x00000060
+#define IXGBE_FDIRCMD_IPV6 0x00000080
+#define IXGBE_FDIRCMD_DROP 0x00000200
+#define IXGBE_FDIRCMD_INT 0x00000400
+#define IXGBE_FDIRCMD_LAST 0x00000800
+#define IXGBE_FDIRCMD_COLLISION 0x00001000
+#define IXGBE_FDIRCMD_QUEUE_EN 0x00008000
+#define IXGBE_FDIRCMD_RX_QUEUE_SHIFT 16
+#define IXGBE_FDIRCMD_VT_POOL_SHIFT 24
/* Transmit Descriptor - Legacy */
struct ixgbe_legacy_tx_desc {
@@ -1267,6 +2051,9 @@ struct ixgbe_adv_tx_context_desc {
/* Adv Transmit Descriptor Config Masks */
#define IXGBE_ADVTXD_DTALEN_MASK 0x0000FFFF /* Data buf length(bytes) */
+#define IXGBE_ADVTXD_MAC_LINKSEC 0x00040000 /* Insert LinkSec */
+#define IXGBE_ADVTXD_IPSEC_SA_INDEX_MASK 0x000003FF /* IPSec SA index */
+#define IXGBE_ADVTXD_IPSEC_ESP_LEN_MASK 0x000001FF /* IPSec ESP length */
#define IXGBE_ADVTXD_DTYP_MASK 0x00F00000 /* DTYP mask */
#define IXGBE_ADVTXD_DTYP_CTXT 0x00200000 /* Advanced Context Desc */
#define IXGBE_ADVTXD_DTYP_DATA 0x00300000 /* Advanced Data Descriptor */
@@ -1301,6 +2088,19 @@ struct ixgbe_adv_tx_context_desc {
#define IXGBE_ADVTXD_TUCMD_L4T_TCP 0x00000800 /* L4 Packet TYPE of TCP */
#define IXGBE_ADVTXD_TUCMD_L4T_SCTP 0x00001000 /* L4 Packet TYPE of SCTP */
#define IXGBE_ADVTXD_TUCMD_MKRREQ 0x00002000 /*Req requires Markers and CRC*/
+#define IXGBE_ADVTXD_POPTS_IPSEC 0x00000400 /* IPSec offload request */
+#define IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP 0x00002000 /* IPSec Type ESP */
+#define IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN 0x00004000/* ESP Encrypt Enable */
+#define IXGBE_ADVTXT_TUCMD_FCOE 0x00008000 /* FCoE Frame Type */
+#define IXGBE_ADVTXD_FCOEF_EOF_MASK (0x3 << 10) /* FC EOF index */
+#define IXGBE_ADVTXD_FCOEF_SOF ((1 << 2) << 10) /* FC SOF index */
+#define IXGBE_ADVTXD_FCOEF_PARINC ((1 << 3) << 10) /* Rel_Off in F_CTL */
+#define IXGBE_ADVTXD_FCOEF_ORIE ((1 << 4) << 10) /* Orientation: End */
+#define IXGBE_ADVTXD_FCOEF_ORIS ((1 << 5) << 10) /* Orientation: Start */
+#define IXGBE_ADVTXD_FCOEF_EOF_N (0x0 << 10) /* 00: EOFn */
+#define IXGBE_ADVTXD_FCOEF_EOF_T (0x1 << 10) /* 01: EOFt */
+#define IXGBE_ADVTXD_FCOEF_EOF_NI (0x2 << 10) /* 10: EOFni */
+#define IXGBE_ADVTXD_FCOEF_EOF_A (0x3 << 10) /* 11: EOFa */
#define IXGBE_ADVTXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */
#define IXGBE_ADVTXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */
@@ -1314,13 +2114,17 @@ typedef u32 ixgbe_link_speed;
#define IXGBE_LINK_SPEED_10GB_FULL 0x0080
#define IXGBE_LINK_SPEED_82598_AUTONEG (IXGBE_LINK_SPEED_1GB_FULL | \
IXGBE_LINK_SPEED_10GB_FULL)
+#define IXGBE_LINK_SPEED_82599_AUTONEG (IXGBE_LINK_SPEED_100_FULL | \
+ IXGBE_LINK_SPEED_1GB_FULL | \
+ IXGBE_LINK_SPEED_10GB_FULL)
+
/* Physical layer type */
typedef u32 ixgbe_physical_layer;
#define IXGBE_PHYSICAL_LAYER_UNKNOWN 0
#define IXGBE_PHYSICAL_LAYER_10GBASE_T 0x0001
#define IXGBE_PHYSICAL_LAYER_1000BASE_T 0x0002
-#define IXGBE_PHYSICAL_LAYER_100BASE_T 0x0004
+#define IXGBE_PHYSICAL_LAYER_100BASE_TX 0x0004
#define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU 0x0008
#define IXGBE_PHYSICAL_LAYER_10GBASE_LR 0x0010
#define IXGBE_PHYSICAL_LAYER_10GBASE_LRM 0x0020
@@ -1329,7 +2133,46 @@ typedef u32 ixgbe_physical_layer;
#define IXGBE_PHYSICAL_LAYER_10GBASE_CX4 0x0100
#define IXGBE_PHYSICAL_LAYER_1000BASE_KX 0x0200
#define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x0400
-
+#define IXGBE_PHYSICAL_LAYER_10GBASE_KR 0x0800
+
+/* Software ATR hash keys */
+#define IXGBE_ATR_BUCKET_HASH_KEY 0xE214AD3D
+#define IXGBE_ATR_SIGNATURE_HASH_KEY 0x14364D17
+
+/* Software ATR input stream offsets and masks */
+#define IXGBE_ATR_VLAN_OFFSET 0
+#define IXGBE_ATR_SRC_IPV6_OFFSET 2
+#define IXGBE_ATR_SRC_IPV4_OFFSET 14
+#define IXGBE_ATR_DST_IPV6_OFFSET 18
+#define IXGBE_ATR_DST_IPV4_OFFSET 30
+#define IXGBE_ATR_SRC_PORT_OFFSET 34
+#define IXGBE_ATR_DST_PORT_OFFSET 36
+#define IXGBE_ATR_FLEX_BYTE_OFFSET 38
+#define IXGBE_ATR_VM_POOL_OFFSET 40
+#define IXGBE_ATR_L4TYPE_OFFSET 41
+
+#define IXGBE_ATR_L4TYPE_MASK 0x3
+#define IXGBE_ATR_L4TYPE_IPV6_MASK 0x4
+#define IXGBE_ATR_L4TYPE_UDP 0x1
+#define IXGBE_ATR_L4TYPE_TCP 0x2
+#define IXGBE_ATR_L4TYPE_SCTP 0x3
+#define IXGBE_ATR_HASH_MASK 0x7fff
+
+/* Flow Director ATR input struct. */
+struct ixgbe_atr_input {
+ /* Byte layout in order, all values with MSB first:
+ *
+ * vlan_id - 2 bytes
+ * src_ip - 16 bytes
+ * dst_ip - 16 bytes
+ * src_port - 2 bytes
+ * dst_port - 2 bytes
+ * flex_bytes - 2 bytes
+ * vm_pool - 1 byte
+ * l4type - 1 byte
+ */
+ u8 byte_stream[42];
+};
enum ixgbe_eeprom_type {
ixgbe_eeprom_uninitialized = 0,
@@ -1340,12 +2183,16 @@ enum ixgbe_eeprom_type {
enum ixgbe_mac_type {
ixgbe_mac_unknown = 0,
ixgbe_mac_82598EB,
+ ixgbe_mac_82599EB,
ixgbe_num_macs
};
enum ixgbe_phy_type {
ixgbe_phy_unknown = 0,
+ ixgbe_phy_none,
ixgbe_phy_tn,
+ ixgbe_phy_aq,
+ ixgbe_phy_cu_unknown,
ixgbe_phy_qt,
ixgbe_phy_xaui,
ixgbe_phy_nl,
@@ -1354,6 +2201,8 @@ enum ixgbe_phy_type {
ixgbe_phy_sfp_avago,
ixgbe_phy_sfp_ftl,
ixgbe_phy_sfp_unknown,
+ ixgbe_phy_sfp_intel,
+ ixgbe_phy_sfp_unsupported, /*Enforce bit set with unsupported module*/
ixgbe_phy_generic
};
@@ -1365,11 +2214,19 @@ enum ixgbe_phy_type {
* 0 SFP_DA_CU
* 1 SFP_SR
* 2 SFP_LR
+ * 3 SFP_DA_CU_CORE0 - 82599-specific
+ * 4 SFP_DA_CU_CORE1 - 82599-specific
+ * 5 SFP_SR/LR_CORE0 - 82599-specific
+ * 6 SFP_SR/LR_CORE1 - 82599-specific
*/
enum ixgbe_sfp_type {
ixgbe_sfp_type_da_cu = 0,
ixgbe_sfp_type_sr = 1,
ixgbe_sfp_type_lr = 2,
+ ixgbe_sfp_type_da_cu_core0 = 3,
+ ixgbe_sfp_type_da_cu_core1 = 4,
+ ixgbe_sfp_type_srlr_core0 = 5,
+ ixgbe_sfp_type_srlr_core1 = 6,
ixgbe_sfp_type_not_present = 0xFFFE,
ixgbe_sfp_type_unknown = 0xFFFF
};
@@ -1428,7 +2285,6 @@ enum ixgbe_bus_width {
struct ixgbe_addr_filter_info {
u32 num_mc_addrs;
u32 rar_used_count;
- u32 mc_addr_in_rar_count;
u32 mta_in_use;
u32 overflow_promisc;
bool user_set_promisc;
@@ -1441,6 +2297,7 @@ struct ixgbe_bus_info {
enum ixgbe_bus_type type;
u16 func;
+ u16 lan_id;
};
/* Flow control parameters */
@@ -1450,6 +2307,8 @@ struct ixgbe_fc_info {
u16 pause_time; /* Flow Control Pause timer */
bool send_xon; /* Flow control send XON */
bool strict_ieee; /* Strict IEEE mode */
+ bool disable_fc_autoneg; /* Do not autonegotiate FC */
+ bool fc_was_autonegged; /* Is current_mode the result of autonegging? */
enum ixgbe_fc_mode current_mode; /* FC mode in effect */
enum ixgbe_fc_mode requested_mode; /* FC mode requested by caller */
};
@@ -1511,6 +2370,21 @@ struct ixgbe_hw_stats {
u64 qptc[16];
u64 qbrc[16];
u64 qbtc[16];
+ u64 qprdc[16];
+ u64 pxon2offc[8];
+ u64 fdirustat_add;
+ u64 fdirustat_remove;
+ u64 fdirfstat_fadd;
+ u64 fdirfstat_fremove;
+ u64 fdirmatch;
+ u64 fdirmiss;
+ u64 fccrc;
+ u64 fclast;
+ u64 fcoerpdc;
+ u64 fcoeprc;
+ u64 fcoeptc;
+ u64 fcoedwrc;
+ u64 fcoedwtc;
};
/* forward declaration */
@@ -1537,11 +2411,16 @@ struct ixgbe_mac_operations {
enum ixgbe_media_type (*get_media_type)(struct ixgbe_hw *);
u32 (*get_supported_physical_layer)(struct ixgbe_hw *);
s32 (*get_mac_addr)(struct ixgbe_hw *, u8 *);
+ s32 (*get_san_mac_addr)(struct ixgbe_hw *, u8 *);
+ s32 (*set_san_mac_addr)(struct ixgbe_hw *, u8 *);
+ s32 (*get_device_caps)(struct ixgbe_hw *, u16 *);
s32 (*stop_adapter)(struct ixgbe_hw *);
s32 (*get_bus_info)(struct ixgbe_hw *);
void (*set_lan_id)(struct ixgbe_hw *);
s32 (*read_analog_reg8)(struct ixgbe_hw*, u32, u8*);
s32 (*write_analog_reg8)(struct ixgbe_hw*, u32, u8);
+ s32 (*setup_sfp)(struct ixgbe_hw *);
+ s32 (*enable_rx_dma)(struct ixgbe_hw *, u32);
/* Link */
s32 (*setup_link)(struct ixgbe_hw *);
@@ -1560,6 +2439,7 @@ struct ixgbe_mac_operations {
/* RAR, Multicast, VLAN */
s32 (*set_rar)(struct ixgbe_hw *, u32, u8 *, u32, u32);
s32 (*clear_rar)(struct ixgbe_hw *, u32);
+ s32 (*insert_mac_addr)(struct ixgbe_hw *, u8 *, u32);
s32 (*set_vmdq)(struct ixgbe_hw *, u32, u32);
s32 (*clear_vmdq)(struct ixgbe_hw *, u32, u32);
s32 (*init_rx_addrs)(struct ixgbe_hw *);
@@ -1574,12 +2454,13 @@ struct ixgbe_mac_operations {
s32 (*init_uta_tables)(struct ixgbe_hw *);
/* Flow Control */
- s32 (*setup_fc)(struct ixgbe_hw *, s32);
+ s32 (*fc_enable)(struct ixgbe_hw *, s32);
};
struct ixgbe_phy_operations {
s32 (*identify)(struct ixgbe_hw *);
s32 (*identify_sfp)(struct ixgbe_hw *);
+ s32 (*init)(struct ixgbe_hw *);
s32 (*reset)(struct ixgbe_hw *);
s32 (*read_reg)(struct ixgbe_hw *, u32, u32, u16 *);
s32 (*write_reg)(struct ixgbe_hw *, u32, u32, u16);
@@ -1592,12 +2473,13 @@ struct ixgbe_phy_operations {
s32 (*write_i2c_byte)(struct ixgbe_hw *, u8, u8, u8);
s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *);
s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8);
+ void (*i2c_bus_clear)(struct ixgbe_hw *);
};
struct ixgbe_eeprom_info {
struct ixgbe_eeprom_operations ops;
enum ixgbe_eeprom_type type;
- u32 semaphore_delay;
+ u32 semaphore_delay;
u16 word_size;
u16 address_bits;
};
@@ -1607,16 +2489,19 @@ struct ixgbe_mac_info {
enum ixgbe_mac_type type;
u8 addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
u8 perm_addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
+ u8 san_addr[IXGBE_ETH_LENGTH_OF_ADDRESS];
s32 mc_filter_type;
u32 mcft_size;
u32 vft_size;
u32 num_rar_entries;
+ u32 rar_highwater;
u32 max_tx_queues;
u32 max_rx_queues;
- u32 link_attach_type;
- u32 link_mode_select;
- u32 link_kx4_kx_supp;
- bool link_settings_loaded;
+ u32 max_msix_vectors;
+ bool msix_vectors_from_pcie;
+ u32 orig_autoc;
+ u32 orig_autoc2;
+ bool orig_link_settings_stored;
bool autoneg;
bool autoneg_succeeded;
};
@@ -1627,6 +2512,7 @@ struct ixgbe_phy_info {
u32 addr;
u32 id;
enum ixgbe_sfp_type sfp_type;
+ bool sfp_setup_needed;
u32 revision;
enum ixgbe_media_type media_type;
bool reset_disable;
@@ -1677,6 +2563,8 @@ struct ixgbe_hw {
#define IXGBE_ERR_I2C -18
#define IXGBE_ERR_SFP_NOT_SUPPORTED -19
#define IXGBE_ERR_SFP_NOT_PRESENT -20
+#define IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT -21
+#define IXGBE_ERR_NO_SAN_ADDR_PTR -22
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
#define UNREFERENCED_PARAMETER(_p)
diff --git a/sys/dev/kbd/kbdreg.h b/sys/dev/kbd/kbdreg.h
index 5b81123..ff4a694 100644
--- a/sys/dev/kbd/kbdreg.h
+++ b/sys/dev/kbd/kbdreg.h
@@ -60,6 +60,7 @@ struct keyboard {
#define KB_INITIALIZED (1 << 19) /* device initialized */
#define KB_REGISTERED (1 << 20) /* device registered to kbdio */
#define KB_BUSY (1 << 21) /* device used by a client */
+#define KB_POLLED (1 << 22) /* device is polled */
int kb_active; /* 0: inactive */
void *kb_token; /* id of the current client */
keyboard_callback_t kb_callback;/* callback function */
@@ -107,6 +108,9 @@ struct keyboard {
#define KBD_IS_BUSY(k) ((k)->kb_flags & KB_BUSY)
#define KBD_BUSY(k) ((k)->kb_flags |= KB_BUSY)
#define KBD_UNBUSY(k) ((k)->kb_flags &= ~KB_BUSY)
+#define KBD_IS_POLLED(k) ((k)->kb_flags & KB_POLLED)
+#define KBD_POLL(k) ((k)->kb_flags |= KB_POLLED)
+#define KBD_UNPOLL(k) ((k)->kb_flags &= ~KB_POLLED)
#define KBD_IS_ACTIVE(k) ((k)->kb_active)
#define KBD_ACTIVATE(k) (++(k)->kb_active)
#define KBD_DEACTIVATE(k) (--(k)->kb_active)
@@ -170,7 +174,7 @@ typedef struct keyboard_switch {
(*kbdsw[(kbd)->kb_index]->intr)((kbd), (arg))
#define kbdd_test_if(kbd) \
(*kbdsw[(kbd)->kb_index]->test_if)((kbd))
-#define kbdd_enable(kbd) \
+#define kbdd_enable(kbd) \
(*kbdsw[(kbd)->kb_index]->enable)((kbd))
#define kbdd_disable(kbd) \
(*kbdsw[(kbd)->kb_index]->disable)((kbd))
@@ -194,7 +198,7 @@ typedef struct keyboard_switch {
(*kbdsw[(kbd)->kb_index]->get_state)((kbd), (buf), (len))
#define kbdd_set_state(kbd, buf, len) \
(*kbdsw[(kbd)->kb_index]->set_state)((kbd), (buf), (len))
-#define kbdd_get_fkeystr(kbd, fkey, len) \
+#define kbdd_get_fkeystr(kbd, fkey, len) \
(*kbdsw[(kbd)->kb_index]->get_fkeystr)((kbd), (fkey), (len))
#define kbdd_poll(kbd, on) \
(*kbdsw[(kbd)->kb_index]->poll)((kbd), (on))
diff --git a/sys/dev/kbdmux/kbdmux.c b/sys/dev/kbdmux/kbdmux.c
index 07b592f..ac6095c 100644
--- a/sys/dev/kbdmux/kbdmux.c
+++ b/sys/dev/kbdmux/kbdmux.c
@@ -104,10 +104,10 @@ MALLOC_DEFINE(M_KBDMUX, KEYBOARD_NAME, "Keyboard multiplexor");
#define KBDMUX_LOCK_DESTROY(s)
-#define KBDMUX_LOCK(s) \
- mtx_lock(&Giant)
-#define KBDMUX_UNLOCK(s) \
- mtx_unlock(&Giant)
+#define KBDMUX_LOCK(s)
+
+#define KBDMUX_UNLOCK(s)
+
#define KBDMUX_LOCK_ASSERT(s, w)
#define KBDMUX_SLEEP(s, f, d, t) \
diff --git a/sys/dev/malo/if_malo.c b/sys/dev/malo/if_malo.c
index 681c824..c17e98c 100644
--- a/sys/dev/malo/if_malo.c
+++ b/sys/dev/malo/if_malo.c
@@ -175,16 +175,10 @@ malo_bar0_write4(struct malo_softc *sc, bus_size_t off, uint32_t val)
bus_space_write_4(sc->malo_io0t, sc->malo_io0h, off, val);
}
-static uint8_t
-malo_bar1_read1(struct malo_softc *sc, bus_size_t off)
-{
- return bus_space_read_1(sc->malo_io1t, sc->malo_io1h, off);
-}
-
int
malo_attach(uint16_t devid, struct malo_softc *sc)
{
- int error, i;
+ int error;
struct ieee80211com *ic;
struct ifnet *ifp;
struct malo_hal *mh;
@@ -203,16 +197,6 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
if_initname(ifp, device_get_name(sc->malo_dev),
device_get_unit(sc->malo_dev));
- /*
- * NB: get mac address from hardware directly here before we set DMAs
- * for HAL because we don't want to disturb operations of HAL at BAR 1.
- */
- for (i = 0; i < IEEE80211_ADDR_LEN; i++) {
- /* XXX remove a magic number but we don't have documents. */
- ic->ic_myaddr[i] = malo_bar1_read1(sc, 0xa528 + i);
- DELAY(1000);
- }
-
mh = malo_hal_attach(sc->malo_dev, devid,
sc->malo_io1h, sc->malo_io1t, sc->malo_dmat);
if (mh == NULL) {
@@ -276,7 +260,7 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
}
error = malo_setup_hwdma(sc); /* push to firmware */
if (error != 0) /* NB: malo_setupdma prints msg */
- goto bad1;
+ goto bad2;
sc->malo_tq = taskqueue_create_fast("malo_taskq", M_NOWAIT,
taskqueue_thread_enqueue, &sc->malo_tq);
@@ -319,11 +303,8 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
ic->ic_headroom = sizeof(struct malo_txrec) -
sizeof(struct ieee80211_frame);
- /* get mac address from hardware */
- IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->malo_hwspecs.macaddr);
-
/* call MI attach routine. */
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, sc->malo_hwspecs.macaddr);
/* override default methods */
ic->ic_vap_create = malo_vap_create;
ic->ic_vap_delete = malo_vap_delete;
@@ -348,6 +329,8 @@ malo_attach(uint16_t devid, struct malo_softc *sc)
malo_announce(sc);
return 0;
+bad2:
+ malo_dma_cleanup(sc);
bad1:
malo_hal_detach(mh);
bad:
@@ -1307,20 +1290,9 @@ malo_start(struct ifnet *ifp)
break;
}
/*
- * Encapsulate the packet in prep for transmission.
- */
- m = ieee80211_encap(ni, m);
- if (m == NULL) {
- DPRINTF(sc, MALO_DEBUG_XMIT,
- "%s: encapsulation failure\n", __func__);
- sc->malo_stats.mst_tx_encap++;
- goto bad;
- }
- /*
* Pass the frame to the h/w for transmission.
*/
if (malo_tx_start(sc, ni, bf, m)) {
- bad:
ifp->if_oerrors++;
if (bf != NULL) {
bf->bf_m = NULL;
@@ -1636,14 +1608,6 @@ malo_mode_init(struct malo_softc *sc)
struct malo_hal *mh = sc->malo_mh;
/*
- * Handle any link-level address change. Note that we only
- * need to force ic_myaddr; any other addresses are handled
- * as a byproduct of the ifnet code marking the interface
- * down then up.
- */
- IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
-
- /*
* NB: Ignore promisc in hostap mode; it's set by the
* bridge. This is wrong but we have no way to
* identify internal requests (from the bridge)
diff --git a/sys/dev/malo/if_malo_pci.c b/sys/dev/malo/if_malo_pci.c
index 8a3b346..2df6dd1 100644
--- a/sys/dev/malo/if_malo_pci.c
+++ b/sys/dev/malo/if_malo_pci.c
@@ -245,7 +245,7 @@ malo_pci_attach(device_t dev)
BUS_SPACE_MAXADDR, /* maxsize */
0, /* nsegments */
BUS_SPACE_MAXADDR, /* maxsegsize */
- BUS_DMA_ALLOCNOW, /* flags */
+ 0, /* flags */
NULL, /* lockfunc */
NULL, /* lockarg */
&sc->malo_dmat)) {
@@ -260,12 +260,13 @@ malo_pci_attach(device_t dev)
error = malo_attach(pci_get_device(dev), sc);
- if (error != 0) {
- malo_pci_detach(dev);
- return (error);
- }
+ if (error != 0)
+ goto bad2;
return (error);
+
+bad2:
+ bus_dma_tag_destroy(sc->malo_dmat);
bad1:
if (psc->malo_msi == 0)
bus_teardown_intr(dev, psc->malo_res_irq[0],
@@ -275,10 +276,11 @@ bad1:
bus_teardown_intr(dev, psc->malo_res_irq[i],
psc->malo_intrhand[i]);
}
-
+ bus_release_resources(dev, psc->malo_irq_spec, psc->malo_res_irq);
bad:
if (psc->malo_msi != 0)
pci_release_msi(dev);
+ bus_release_resources(dev, psc->malo_mem_spec, psc->malo_res_mem);
return (error);
}
diff --git a/sys/dev/malo/if_malohal.c b/sys/dev/malo/if_malohal.c
index b14bff2..d244b98 100644
--- a/sys/dev/malo/if_malohal.c
+++ b/sys/dev/malo/if_malohal.c
@@ -128,7 +128,7 @@ malo_hal_attach(device_t dev, uint16_t devid,
NULL, /* lockarg */
&mh->mh_dmat);
if (error != 0) {
- device_printf(dev, "unable to allocate memory for cmd buffer, "
+ device_printf(dev, "unable to allocate memory for cmd tag, "
"error %u\n", error);
goto fail;
}
@@ -163,8 +163,6 @@ malo_hal_attach(device_t dev, uint16_t devid,
return (mh);
fail:
- free(mh, M_DEVBUF);
-
if (mh->mh_dmamap != NULL) {
bus_dmamap_unload(mh->mh_dmat, mh->mh_dmamap);
if (mh->mh_cmdbuf != NULL)
@@ -174,6 +172,7 @@ fail:
}
if (mh->mh_dmat)
bus_dma_tag_destroy(mh->mh_dmat);
+ free(mh, M_DEVBUF);
return (NULL);
}
diff --git a/sys/dev/mii/axphy.c b/sys/dev/mii/axphy.c
new file mode 100644
index 0000000..21ac6f0
--- /dev/null
+++ b/sys/dev/mii/axphy.c
@@ -0,0 +1,207 @@
+/*-
+ * Copyright (c) 2009, M. Warner Losh
+ * 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 unmodified, 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$");
+
+/*
+ * driver for internal phy in the AX88x9x chips.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+#include <sys/bus.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include "miidevs.h"
+
+#include <dev/mii/axphyreg.h>
+
+#include "miibus_if.h"
+
+static int axphy_probe(device_t dev);
+static int axphy_attach(device_t dev);
+
+static device_method_t axphy_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, axphy_probe),
+ DEVMETHOD(device_attach, axphy_attach),
+ DEVMETHOD(device_detach, mii_phy_detach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ { 0, 0 }
+};
+
+static devclass_t axphy_devclass;
+
+static driver_t axphy_driver = {
+ "axphy",
+ axphy_methods,
+ sizeof(struct mii_softc)
+};
+
+DRIVER_MODULE(axphy, miibus, axphy_driver, axphy_devclass, 0, 0);
+
+static int axphy_service(struct mii_softc *, struct mii_data *, int);
+static void axphy_status(struct mii_softc *);
+
+static const struct mii_phydesc axphys[] = {
+ MII_PHY_DESC(ASIX, AX88X9X),
+ MII_PHY_END
+};
+
+static int
+axphy_probe(device_t dev)
+{
+
+ return (mii_phy_dev_probe(dev, axphys, BUS_PROBE_DEFAULT));
+}
+
+static int
+axphy_attach(device_t dev)
+{
+ struct mii_softc *sc;
+ struct mii_attach_args *ma;
+ struct mii_data *mii;
+
+ sc = device_get_softc(dev);
+ ma = device_get_ivars(dev);
+ sc->mii_dev = device_get_parent(dev);
+ mii = device_get_softc(sc->mii_dev);
+ LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
+
+ sc->mii_inst = mii->mii_instance;
+ sc->mii_phy = ma->mii_phyno;
+ sc->mii_service = axphy_service;
+ sc->mii_pdata = mii;
+ sc->mii_flags |= MIIF_NOISOLATE;
+ mii->mii_instance++;
+
+ mii_phy_reset(sc);
+
+ sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
+ device_printf(dev, " ");
+ mii_phy_add_media(sc);
+ printf("\n");
+
+ MIIBUS_MEDIAINIT(sc->mii_dev);
+ mii_phy_setmedia(sc);
+
+ return (0);
+}
+
+static int
+axphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
+{
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ int reg;
+
+ switch (cmd) {
+ case MII_POLLSTAT:
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
+ return (0);
+ break;
+
+ case MII_MEDIACHG:
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst) {
+ reg = PHY_READ(sc, MII_BMCR);
+ PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO);
+ return (0);
+ }
+
+ /*
+ * If the interface is not up, don't do anything.
+ */
+ if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+ break;
+
+ mii_phy_setmedia(sc);
+ break;
+
+ case MII_TICK:
+ if (IFM_INST(ife->ifm_media) != sc->mii_inst)
+ return (0);
+ if (mii_phy_tick(sc) == EJUSTRETURN)
+ return (0);
+ break;
+ }
+
+ /* Update the media status. */
+ axphy_status(sc);
+
+ /* Callback if something changed. */
+ mii_phy_update(sc, cmd);
+ return (0);
+}
+
+static void
+axphy_status(struct mii_softc *sc)
+{
+ struct mii_data *mii = sc->mii_pdata;
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+ int bmsr, bmcr;
+
+ mii->mii_media_status = IFM_AVALID;
+ mii->mii_media_active = IFM_ETHER;
+
+ bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+ if (bmsr & BMSR_LINK)
+ mii->mii_media_status |= IFM_ACTIVE;
+
+ bmcr = PHY_READ(sc, MII_BMCR);
+ if (bmcr & BMCR_ISO) {
+ mii->mii_media_active |= IFM_NONE;
+ mii->mii_media_status = 0;
+ return;
+ }
+
+ if (bmcr & BMCR_LOOP)
+ mii->mii_media_active |= IFM_LOOP;
+
+ if (bmcr & BMCR_AUTOEN) {
+ if ((bmsr & BMSR_ACOMP) == 0) {
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+
+#if 0
+ scr = PHY_READ(sc, MII_AXPHY_SCR);
+ if (scr & SCR_S100)
+ mii->mii_media_active |= IFM_100_TX;
+ else
+ mii->mii_media_active |= IFM_10_T;
+ if (scr & SCR_FDX)
+ mii->mii_media_active |= IFM_FDX;
+#endif
+ } else
+ mii->mii_media_active = ife->ifm_media;
+}
diff --git a/sys/mips/atheros/apbvar.h b/sys/dev/mii/axphyreg.h
index e1d29f4..2d9e933 100644
--- a/sys/mips/atheros/apbvar.h
+++ b/sys/dev/mii/axphyreg.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
+ * Copyright (c) 2009, M. Warner Losh
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -23,26 +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 _APBVAR_H_
-#define _APBVAR_H_
-
-#define APB_IRQ_BASE 0
-#define APB_IRQ_END 7
-#define APB_NIRQS 8
-
-struct apb_softc {
- struct rman apb_irq_rman;
- /* IRQ events structs for child devices */
- struct intr_event *sc_eventstab[APB_NIRQS];
- /* Resources and cookies for MIPS CPU INTs */
- struct resource *sc_misc_irq;
- void *sc_misc_ih;
-};
-
-struct apb_ivar {
- struct resource_list resources;
-};
-
-#endif /* _APBVAR_H_ */
diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs
index 7cc8868..6bc07fa 100644
--- a/sys/dev/mii/miidevs
+++ b/sys/dev/mii/miidevs
@@ -52,6 +52,7 @@ $FreeBSD$
oui AGERE 0x00a0bc Agere Systems
oui ALTIMA 0x0010a9 Altima Communications
oui AMD 0x00001a Advanced Micro Devices
+oui ASIX 0x00602e Asix Semiconductor
oui ATHEROS 0x001374 Atheros Communications
oui BROADCOM 0x001018 Broadcom Corporation
oui BROADCOM2 0x000af7 Broadcom Corporation
@@ -120,6 +121,9 @@ model AMD 79c973phy 0x0036 Am79c973 internal PHY
model AMD 79c978 0x0039 Am79c978 HomePNA PHY
model xxAMD 79C873 0x0000 Am79C873/DM9101 10/100 media interface
+/* Asix semiconductor PHYs. */
+model ASIX AX88X9X 0x0031 Ax88x9x internal PHY
+
/* Atheros Communications/Attansic PHYs. */
model ATHEROS F1 0x0001 Atheros F1 10/100/1000 PHY
model ATHEROS F2 0x0002 Atheros F2 10/100 PHY
diff --git a/sys/dev/msk/if_msk.c b/sys/dev/msk/if_msk.c
index 2620f9f..17bced0 100644
--- a/sys/dev/msk/if_msk.c
+++ b/sys/dev/msk/if_msk.c
@@ -287,9 +287,8 @@ static int msk_miibus_writereg(device_t, int, int, int);
static void msk_miibus_statchg(device_t);
static void msk_link_task(void *, int);
-static void msk_setmulti(struct msk_if_softc *);
+static void msk_rxfilter(struct msk_if_softc *);
static void msk_setvlan(struct msk_if_softc *, struct ifnet *);
-static void msk_setpromisc(struct msk_if_softc *);
static void msk_stats_clear(struct msk_if_softc *);
static void msk_stats_update(struct msk_if_softc *);
@@ -560,7 +559,7 @@ msk_link_task(void *arg, int pending)
}
static void
-msk_setmulti(struct msk_if_softc *sc_if)
+msk_rxfilter(struct msk_if_softc *sc_if)
{
struct msk_softc *sc;
struct ifnet *ifp;
@@ -577,15 +576,14 @@ msk_setmulti(struct msk_if_softc *sc_if)
bzero(mchash, sizeof(mchash));
mode = GMAC_READ_2(sc, sc_if->msk_port, GM_RX_CTRL);
- mode |= GM_RXCR_UCF_ENA;
- if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) {
- if ((ifp->if_flags & IFF_PROMISC) != 0)
- mode &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
- else if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
- mchash[0] = 0xffff;
- mchash[1] = 0xffff;
- }
+ if ((ifp->if_flags & IFF_PROMISC) != 0)
+ mode &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+ else if ((ifp->if_flags & IFF_ALLMULTI) != 0) {
+ mode |= GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA;
+ mchash[0] = 0xffff;
+ mchash[1] = 0xffff;
} else {
+ mode |= GM_RXCR_UCF_ENA;
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
if (ifma->ifma_addr->sa_family != AF_LINK)
@@ -598,7 +596,8 @@ msk_setmulti(struct msk_if_softc *sc_if)
mchash[crc >> 5] |= 1 << (crc & 0x1f);
}
IF_ADDR_UNLOCK(ifp);
- mode |= GM_RXCR_MCF_ENA;
+ if (mchash[0] != 0 || mchash[1] != 0)
+ mode |= GM_RXCR_MCF_ENA;
}
GMAC_WRITE_2(sc, sc_if->msk_port, GM_MC_ADDR_H1,
@@ -631,26 +630,6 @@ msk_setvlan(struct msk_if_softc *sc_if, struct ifnet *ifp)
}
}
-static void
-msk_setpromisc(struct msk_if_softc *sc_if)
-{
- struct msk_softc *sc;
- struct ifnet *ifp;
- uint16_t mode;
-
- MSK_IF_LOCK_ASSERT(sc_if);
-
- sc = sc_if->msk_softc;
- ifp = sc_if->msk_ifp;
-
- mode = GMAC_READ_2(sc, sc_if->msk_port, GM_RX_CTRL);
- if (ifp->if_flags & IFF_PROMISC)
- mode &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
- else
- mode |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
- GMAC_WRITE_2(sc, sc_if->msk_port, GM_RX_CTRL, mode);
-}
-
static int
msk_init_rx_ring(struct msk_if_softc *sc_if)
{
@@ -954,10 +933,8 @@ msk_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
if ((ifp->if_flags & IFF_UP) != 0) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
if (((ifp->if_flags ^ sc_if->msk_if_flags)
- & IFF_PROMISC) != 0) {
- msk_setpromisc(sc_if);
- msk_setmulti(sc_if);
- }
+ & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
+ msk_rxfilter(sc_if);
} else {
if (sc_if->msk_detach == 0)
msk_init_locked(sc_if);
@@ -973,7 +950,7 @@ msk_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
case SIOCDELMULTI:
MSK_IF_LOCK(sc_if);
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
- msk_setmulti(sc_if);
+ msk_rxfilter(sc_if);
MSK_IF_UNLOCK(sc_if);
break;
case SIOCGIFMEDIA:
@@ -3594,11 +3571,8 @@ msk_init_locked(struct msk_if_softc *sc_if)
CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_CTRL_T),
GMF_OPER_ON | GMF_RX_F_FL_ON);
- /* Set promiscuous mode. */
- msk_setpromisc(sc_if);
-
- /* Set multicast filter. */
- msk_setmulti(sc_if);
+ /* Set receive filter. */
+ msk_rxfilter(sc_if);
/* Flush Rx MAC FIFO on any flow control or error. */
CSR_WRITE_4(sc, MR_ADDR(sc_if->msk_port, RX_GMF_FL_MSK),
@@ -4196,7 +4170,7 @@ msk_sysctl_node(struct msk_if_softc *sc_if)
child, rx_pkts_too_long, "frames too long");
MSK_SYSCTL_STAT32(sc_if, ctx, "jabbers",
child, rx_pkts_jabbers, "Jabber errors");
- MSK_SYSCTL_STAT32(sc_if, ctx, "jabbers",
+ MSK_SYSCTL_STAT32(sc_if, ctx, "overflows",
child, rx_fifo_oflows, "FIFO overflows");
tree = SYSCTL_ADD_NODE(ctx, schild, OID_AUTO, "tx", CTLFLAG_RD,
diff --git a/sys/dev/my/if_my.c b/sys/dev/my/if_my.c
index 65c0dcc..b25ae22 100644
--- a/sys/dev/my/if_my.c
+++ b/sys/dev/my/if_my.c
@@ -1700,7 +1700,7 @@ my_watchdog(struct ifnet * ifp)
my_init_locked(sc);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
my_start_locked(ifp);
- MY_LOCK(sc);
+ MY_UNLOCK(sc);
return;
}
diff --git a/sys/dev/ofw/ofw_standard.c b/sys/dev/ofw/ofw_standard.c
index e097145..a05f072 100644
--- a/sys/dev/ofw/ofw_standard.c
+++ b/sys/dev/ofw/ofw_standard.c
@@ -204,7 +204,7 @@ ofw_std_interpret(ofw_t ofw, const char *cmd, int nreturns,
}
status = args.slot[i++];
while (i < 1 + nreturns)
- returns[j] = args.slot[i++];
+ returns[j++] = args.slot[i++];
return (status);
}
diff --git a/sys/dev/ofw/openfirm.c b/sys/dev/ofw/openfirm.c
index 4c33c9f..06b58d0 100644
--- a/sys/dev/ofw/openfirm.c
+++ b/sys/dev/ofw/openfirm.c
@@ -164,9 +164,11 @@ OF_interpret(const char *cmd, int nreturns, ...)
int status;
status = OFW_INTERPRET(ofw_obj, cmd, nreturns, slots);
+ if (status == -1)
+ return (status);
va_start(ap, nreturns);
- while (i < 1 + nreturns)
+ while (i < nreturns)
*va_arg(ap, cell_t *) = slots[i++];
va_end(ap);
diff --git a/sys/dev/pccard/pccarddevs b/sys/dev/pccard/pccarddevs
index 83872d1..2c42ebf 100644
--- a/sys/dev/pccard/pccarddevs
+++ b/sys/dev/pccard/pccarddevs
@@ -146,8 +146,8 @@ vendor ARTEM 0x0268 ARtem
vendor SYMBOL 0x026c Symbol
vendor BUFFALO 0x026f BUFFALO (Melco Corporation)
vendor BROMAX 0x0274 Bromax communications, Inc
-vendor IODATA2 0x028a I-O DATA
vendor NECINFORTIA 0x0288 NEC Inforntia
+vendor IODATA2 0x028a I-O DATA
vendor ASUS 0x02aa ASUS
vendor SIEMENS 0x02ac Siemens
vendor UNGERMANN 0x02c0 Ungermann Bass
@@ -181,6 +181,7 @@ vendor RALINK 0x1814 Ralink Technology
* with '0xc' look coherent enough that maybe somebody other than PCMCIA is
* assigning numbers in that range. Maybe JEITA?
*/
+vendor RIOS 0x492f RIOS Systems Co
vendor AIRVAST 0x50c2 AirVast Technology
vendor ARCHOS 0x5241 Archos
vendor DUAL 0x890f Dual
@@ -265,6 +266,7 @@ product BREEZECOM BREEZENET 0x0102 BreezeCOM BreezeNET
/* Bromax Communications, Inc (Linksys OEM) */
product BROMAX IPORT 0x1103 iPort 10/100 Ethernet
+product BROMAX AXNET 0x1106 AXNET based 10/100 Ethernet
product BROMAX IPORT2 0x1121 iPort 10Mbps Ethernet
product BROMAX IWN 0x1612 Instant Wireless Network PC Card
product BROMAX IWN3 0x1613 Instant Wireless Network PC Card, V3
@@ -342,6 +344,7 @@ product FUJITSU WL110 0x2003 PEGA-WL110 Wireless LAN
product GEMPLUS GPR400 0x3004 GPR400 Smartcard Reader
/* GlobalVillage */
+product GLOBALVILLAGE POWERPORT 0x0103 GlobalVillage PowerPort PlatinumPro
product GLOBALVILLAGE LANMODEM 0x0105 GlobalVillage Ethernet + Modem
/* Grey Cell Systems, Ltd */
@@ -545,6 +548,9 @@ product RAYTHEON WLAN 0x0000 WLAN Adapter
/* RELIA Technologies Corporation */
product RELIA COMBO 0x2452 Reliable Combo-L/M-56K
+/* RIOS Systems Co */
+product RIOS PCCARD3 0x0000 PC Card Ethernet
+
/* Roland */
product ROLAND SCP55 0x0001 Roland SCP-55
@@ -671,6 +677,7 @@ vendor IODATA3 -1 I-O DATA
vendor LANTECH -1 Lantech Computer Company
vendor MELCO2 -1 Melco Corporation
vendor MICRORESEARCH -1 Micro Research
+vendor MITSUBISHI -1 Mitsubishi Electronics Corp
vendor NDC -1 NDC
vendor NEC -1 NEC
vendor OEM2 -1 Generic OEM
@@ -745,6 +752,7 @@ product MACNICA MPS100 { "MACNICA", "MIRACLE&spSCSI", "mPS100", "D.0" } Macnica
product MEGAHERTZ XJ2288 { "MEGAHERTZ", "MODEM&spXJ2288", NULL, NULL } Megahertz XJ2288 Modem
product MELCO2 LPC2_TX { "MELCO", "LPC2-TX", NULL, NULL } Melco LPC2-TX
product MICRORESEARCH MR10TPC { "MICRO-RESEARCH-MR10TPC", "Ethernet", NULL, NULL } Micro Research MR10TPC
+product MITSUBISHI B8895 { "MITSUBISHI&spELECTRIC&spCORPORATION", "B8895", NULL, NULL } Mitsubishi Electronics Corporation B8895
product NANOSPEED PRISM2 { "NANOSPEED", "HFA384x/IEEE", "Version&sp01.02", NULL } NANOSPEED ROOT-RZ2000 WLAN Card
product NDC ND5100_E { "NDC", "Ethernet", "A", NULL } Sohoware ND5100E NE2000 Compatible Card
product NEC CMZ_RT_WP { "NEC", "Wireless&spCard&spCMZ-RT-WP", "Version&sp01.01", NULL } NEC Wireless Card CMZ-RT-WP
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index d90cd6a..ad6220f 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -1030,8 +1030,9 @@ pci_get_vpd_readonly_method(device_t dev, device_t child, const char *kw,
}
/*
- * Return the offset in configuration space of the requested extended
- * capability entry or 0 if the specified capability was not found.
+ * Find the requested extended capability and return the offset in
+ * configuration space via the pointer provided. The function returns
+ * 0 on success and error code otherwise.
*/
int
pci_find_extcap_method(device_t dev, device_t child, int capability,
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 4e1c8ef..15cad92 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -413,12 +413,14 @@ pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
}
} else {
ok = 1;
-#if 1
- if (start < sc->iobase && end > sc->iolimit) {
- start = sc->iobase;
- end = sc->iolimit;
- }
-#endif
+#if 0
+ /*
+ * If we overlap with the subtractive range, then
+ * pick the upper range to use.
+ */
+ if (start < sc->iolimit && end > sc->iobase)
+ start = sc->iolimit + 1;
+#endif
}
if (end < start) {
device_printf(dev, "ioport: end (%lx) < start (%lx)\n",
@@ -478,18 +480,16 @@ pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
}
} else if (!ok) {
ok = 1; /* subtractive bridge: always ok */
+#if 0
if (pcib_is_nonprefetch_open(sc)) {
- if (start < sc->membase && end > sc->memlimit) {
- start = sc->membase;
- end = sc->memlimit;
- }
+ if (start < sc->memlimit && end > sc->membase)
+ start = sc->memlimit + 1;
}
if (pcib_is_prefetch_open(sc)) {
- if (start < sc->pmembase && end > sc->pmemlimit) {
- start = sc->pmembase;
- end = sc->pmemlimit;
- }
+ if (start < sc->pmemlimit && end > sc->pmembase)
+ start = sc->pmemlimit + 1;
}
+#endif
}
if (end < start) {
device_printf(dev, "memory: end (%lx) < start (%lx)\n",
@@ -536,13 +536,13 @@ pcib_maxslots(device_t dev)
* Since we are a child of a PCI bus, its parent must support the pcib interface.
*/
uint32_t
-pcib_read_config(device_t dev, int b, int s, int f, int reg, int width)
+pcib_read_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, int width)
{
return(PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, width));
}
void
-pcib_write_config(device_t dev, int b, int s, int f, int reg, uint32_t val, int width)
+pcib_write_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, uint32_t val, int width)
{
PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg, val, width);
}
diff --git a/sys/dev/pci/pcib_private.h b/sys/dev/pci/pcib_private.h
index 6159839..c7d6818 100644
--- a/sys/dev/pci/pcib_private.h
+++ b/sys/dev/pci/pcib_private.h
@@ -74,8 +74,8 @@ int pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value);
struct resource *pcib_alloc_resource(device_t dev, device_t child, int type, int *rid,
u_long start, u_long end, u_long count, u_int flags);
int pcib_maxslots(device_t dev);
-uint32_t pcib_read_config(device_t dev, int b, int s, int f, int reg, int width);
-void pcib_write_config(device_t dev, int b, int s, int f, int reg, uint32_t val, int width);
+uint32_t pcib_read_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, int width);
+void pcib_write_config(device_t dev, u_int b, u_int s, u_int f, u_int reg, uint32_t val, int width);
int pcib_route_interrupt(device_t pcib, device_t dev, int pin);
int pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs);
int pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs);
diff --git a/sys/dev/powermac_nvram/powermac_nvram.c b/sys/dev/powermac_nvram/powermac_nvram.c
index a55fcae..f6e930b 100644
--- a/sys/dev/powermac_nvram/powermac_nvram.c
+++ b/sys/dev/powermac_nvram/powermac_nvram.c
@@ -131,19 +131,25 @@ powermac_nvram_attach(device_t dev)
{
struct powermac_nvram_softc *sc;
phandle_t node;
- u_int32_t reg[2];
- int gen0, gen1;
+ u_int32_t reg[3];
+ int gen0, gen1, i;
node = ofw_bus_get_node(dev);
sc = device_get_softc(dev);
- if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8)
+ if ((i = OF_getprop(node, "reg", reg, sizeof(reg))) < 8)
return ENXIO;
sc->sc_dev = dev;
sc->sc_node = node;
- sc->sc_bank0 = (vm_offset_t)pmap_mapdev(reg[0], NVRAM_SIZE * 2);
+ /*
+ * Find which byte of reg corresponds to the 32-bit physical address.
+ * We should probably read #address-cells from /chosen instead.
+ */
+ i = (i/4) - 2;
+
+ sc->sc_bank0 = (vm_offset_t)pmap_mapdev(reg[i], NVRAM_SIZE * 2);
sc->sc_bank1 = sc->sc_bank0 + NVRAM_SIZE;
gen0 = powermac_nvram_check((void *)sc->sc_bank0);
diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c
index a0b06a3..936fe8e 100644
--- a/sys/dev/ral/rt2560.c
+++ b/sys/dev/ral/rt2560.c
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
#include <net/if_types.h>
#include <net80211/ieee80211_var.h>
-#include <net80211/ieee80211_phy.h>
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_amrr.h>
@@ -202,6 +201,7 @@ rt2560_attach(device_t dev, int id)
struct ifnet *ifp;
int error;
uint8_t bands;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
@@ -260,7 +260,7 @@ rt2560_attach(device_t dev, int id)
ic = ifp->if_l2com;
/* retrieve MAC address */
- rt2560_get_macaddr(sc, ic->ic_myaddr);
+ rt2560_get_macaddr(sc, macaddr);
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
@@ -300,7 +300,7 @@ rt2560_attach(device_t dev, int id)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, macaddr);
ic->ic_newassoc = rt2560_newassoc;
ic->ic_raw_xmit = rt2560_raw_xmit;
ic->ic_updateslot = rt2560_update_slot;
@@ -1476,7 +1476,7 @@ rt2560_setup_tx_desc(struct rt2560_softc *sc, struct rt2560_tx_desc *desc,
desc->plcp_service = 4;
len += IEEE80211_CRC_LEN;
- if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) {
+ if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) {
desc->flags |= htole32(RT2560_TX_OFDM);
plcp_length = len & 0xfff;
@@ -1621,7 +1621,7 @@ rt2560_tx_mgt(struct rt2560_softc *sc, struct mbuf *m0,
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
flags |= RT2560_TX_ACK;
- dur = ieee80211_ack_duration(sc->sc_rates,
+ dur = ieee80211_ack_duration(ic->ic_rt,
rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
*(uint16_t *)wh->i_dur = htole16(dur);
@@ -1671,16 +1671,16 @@ rt2560_sendprot(struct rt2560_softc *sc,
wh = mtod(m, const struct ieee80211_frame *);
pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
- protrate = ieee80211_ctl_rate(sc->sc_rates, rate);
- ackrate = ieee80211_ack_rate(sc->sc_rates, rate);
+ protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
+ ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
- dur = ieee80211_compute_duration(sc->sc_rates, pktlen, rate, isshort)
- + ieee80211_ack_duration(sc->sc_rates, rate, isshort);
+ dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
+ + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags = RT2560_TX_MORE_FRAG;
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
- dur += ieee80211_ack_duration(sc->sc_rates, rate, isshort);
+ dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags |= RT2560_TX_ACK;
mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
} else {
@@ -1851,7 +1851,7 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
prot = IEEE80211_PROT_RTSCTS;
else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
- ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM)
+ ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM)
prot = ic->ic_protmode;
if (prot != IEEE80211_PROT_NONE) {
error = rt2560_sendprot(sc, m0, ni, prot, rate);
@@ -1921,7 +1921,7 @@ rt2560_tx_data(struct rt2560_softc *sc, struct mbuf *m0,
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
flags |= RT2560_TX_ACK;
- dur = ieee80211_ack_duration(sc->sc_rates,
+ dur = ieee80211_ack_duration(ic->ic_rt,
rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
*(uint16_t *)wh->i_dur = htole16(dur);
}
@@ -1963,15 +1963,7 @@ rt2560_start_locked(struct ifnet *ifp)
sc->sc_flags |= RT2560_F_DATA_OACTIVE;
break;
}
-
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- m = ieee80211_encap(ni, m);
- if (m == NULL) {
- ieee80211_free_node(ni);
- ifp->if_oerrors++;
- continue;
- }
-
if (rt2560_tx_data(sc, m, ni) != 0) {
ieee80211_free_node(ni);
ifp->if_oerrors++;
@@ -2145,8 +2137,6 @@ rt2560_set_chan(struct rt2560_softc *sc, struct ieee80211_channel *c)
chan = ieee80211_chan2ieee(ic, c);
KASSERT(chan != 0 && chan != IEEE80211_CHAN_ANY, ("chan 0x%x", chan));
- sc->sc_rates = ieee80211_get_ratetable(c);
-
if (IEEE80211_IS_CHAN_2GHZ(c))
power = min(sc->txpow[chan - 1], 31);
else
@@ -2683,8 +2673,7 @@ rt2560_init_locked(struct rt2560_softc *sc)
for (i = 0; i < N(rt2560_def_mac); i++)
RAL_WRITE(sc, rt2560_def_mac[i].reg, rt2560_def_mac[i].val);
- IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
- rt2560_set_macaddr(sc, ic->ic_myaddr);
+ rt2560_set_macaddr(sc, IF_LLADDR(ifp));
/* set basic rate set (will be updated later) */
RAL_WRITE(sc, RT2560_ARSP_PLCP_1, 0x153);
diff --git a/sys/dev/ral/rt2560var.h b/sys/dev/ral/rt2560var.h
index 0841444..d53c0d1 100644
--- a/sys/dev/ral/rt2560var.h
+++ b/sys/dev/ral/rt2560var.h
@@ -122,8 +122,6 @@ struct rt2560_softc {
int sc_tx_timer;
int sc_invalid;
int sc_debug;
-
- const struct ieee80211_rate_table *sc_rates;
/*
* The same in both up to here
* ------------------------------------------------
diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c
index 215a1b7..a3b1986 100644
--- a/sys/dev/ral/rt2661.c
+++ b/sys/dev/ral/rt2661.c
@@ -53,7 +53,6 @@ __FBSDID("$FreeBSD$");
#include <net/if_types.h>
#include <net80211/ieee80211_var.h>
-#include <net80211/ieee80211_phy.h>
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_amrr.h>
@@ -155,7 +154,7 @@ static int rt2661_wme_update(struct ieee80211com *) __unused;
static void rt2661_update_slot(struct ifnet *);
static const char *rt2661_get_rf(int);
static void rt2661_read_eeprom(struct rt2661_softc *,
- struct ieee80211com *);
+ uint8_t macaddr[IEEE80211_ADDR_LEN]);
static int rt2661_bbp_init(struct rt2661_softc *);
static void rt2661_init_locked(struct rt2661_softc *);
static void rt2661_init(void *);
@@ -204,6 +203,7 @@ rt2661_attach(device_t dev, int id)
uint32_t val;
int error, ac, ntries;
uint8_t bands;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_id = id;
sc->sc_dev = dev;
@@ -234,7 +234,7 @@ rt2661_attach(device_t dev, int id)
}
/* retrieve RF rev. no and various other things from EEPROM */
- rt2661_read_eeprom(sc, ic);
+ rt2661_read_eeprom(sc, macaddr);
device_printf(dev, "MAC/BBP RT%X, RF %s\n", val,
rt2661_get_rf(sc->rf_rev));
@@ -303,7 +303,7 @@ rt2661_attach(device_t dev, int id)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, macaddr);
ic->ic_newassoc = rt2661_newassoc;
ic->ic_node_alloc = rt2661_node_alloc;
#if 0
@@ -319,8 +319,6 @@ rt2661_attach(device_t dev, int id)
ic->ic_vap_create = rt2661_vap_create;
ic->ic_vap_delete = rt2661_vap_delete;
- sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
-
bpfattach(ifp, DLT_IEEE802_11_RADIO,
sizeof (struct ieee80211_frame) + sizeof (sc->sc_txtap));
@@ -1301,7 +1299,7 @@ rt2661_setup_tx_desc(struct rt2661_softc *sc, struct rt2661_tx_desc *desc,
desc->plcp_service = 4;
len += IEEE80211_CRC_LEN;
- if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) {
+ if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) {
desc->flags |= htole32(RT2661_TX_OFDM);
plcp_length = len & 0xfff;
@@ -1387,7 +1385,7 @@ rt2661_tx_mgt(struct rt2661_softc *sc, struct mbuf *m0,
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
flags |= RT2661_TX_NEED_ACK;
- dur = ieee80211_ack_duration(sc->sc_rates,
+ dur = ieee80211_ack_duration(ic->ic_rt,
rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
*(uint16_t *)wh->i_dur = htole16(dur);
@@ -1437,16 +1435,16 @@ rt2661_sendprot(struct rt2661_softc *sc, int ac,
wh = mtod(m, const struct ieee80211_frame *);
pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
- protrate = ieee80211_ctl_rate(sc->sc_rates, rate);
- ackrate = ieee80211_ack_rate(sc->sc_rates, rate);
+ protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
+ ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
- dur = ieee80211_compute_duration(sc->sc_rates, pktlen, rate, isshort)
- + ieee80211_ack_duration(sc->sc_rates, rate, isshort);
+ dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
+ + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags = RT2661_TX_MORE_FRAG;
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
- dur += ieee80211_ack_duration(sc->sc_rates, rate, isshort);
+ dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags |= RT2661_TX_NEED_ACK;
mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
} else {
@@ -1543,7 +1541,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
prot = IEEE80211_PROT_RTSCTS;
else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
- ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM)
+ ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM)
prot = ic->ic_protmode;
if (prot != IEEE80211_PROT_NONE) {
error = rt2661_sendprot(sc, ac, m0, ni, prot, rate);
@@ -1614,7 +1612,7 @@ rt2661_tx_data(struct rt2661_softc *sc, struct mbuf *m0,
if (!noack && !IEEE80211_IS_MULTICAST(wh->i_addr1)) {
flags |= RT2661_TX_NEED_ACK;
- dur = ieee80211_ack_duration(sc->sc_rates,
+ dur = ieee80211_ack_duration(ic->ic_rt,
rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE);
*(uint16_t *)wh->i_dur = htole16(dur);
}
@@ -1662,15 +1660,7 @@ rt2661_start_locked(struct ifnet *ifp)
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
-
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- m = ieee80211_encap(ni, m);
- if (m == NULL) {
- ieee80211_free_node(ni);
- ifp->if_oerrors++;
- continue;
- }
-
if (rt2661_tx_data(sc, m, ni, ac) != 0) {
ieee80211_free_node(ni);
ifp->if_oerrors++;
@@ -2040,8 +2030,6 @@ rt2661_set_chan(struct rt2661_softc *sc, struct ieee80211_channel *c)
chan = ieee80211_chan2ieee(ic, c);
KASSERT(chan != 0 && chan != IEEE80211_CHAN_ANY, ("chan 0x%x", chan));
- sc->sc_rates = ieee80211_get_ratetable(c);
-
/* select the appropriate RF settings based on what EEPROM says */
rfprog = (sc->rfprog == 0) ? rt2661_rf5225_1 : rt2661_rf5225_2;
@@ -2219,23 +2207,23 @@ rt2661_get_rf(int rev)
}
static void
-rt2661_read_eeprom(struct rt2661_softc *sc, struct ieee80211com *ic)
+rt2661_read_eeprom(struct rt2661_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
{
uint16_t val;
int i;
/* read MAC address */
val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC01);
- ic->ic_myaddr[0] = val & 0xff;
- ic->ic_myaddr[1] = val >> 8;
+ macaddr[0] = val & 0xff;
+ macaddr[1] = val >> 8;
val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC23);
- ic->ic_myaddr[2] = val & 0xff;
- ic->ic_myaddr[3] = val >> 8;
+ macaddr[2] = val & 0xff;
+ macaddr[3] = val >> 8;
val = rt2661_eeprom_read(sc, RT2661_EEPROM_MAC45);
- ic->ic_myaddr[4] = val & 0xff;
- ic->ic_myaddr[5] = val >> 8;
+ macaddr[4] = val & 0xff;
+ macaddr[5] = val >> 8;
val = rt2661_eeprom_read(sc, RT2661_EEPROM_ANTENNA);
/* XXX: test if different from 0xffff? */
@@ -2413,8 +2401,7 @@ rt2661_init_locked(struct rt2661_softc *sc)
for (i = 0; i < N(rt2661_def_mac); i++)
RAL_WRITE(sc, rt2661_def_mac[i].reg, rt2661_def_mac[i].val);
- IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
- rt2661_set_macaddr(sc, ic->ic_myaddr);
+ rt2661_set_macaddr(sc, IF_LLADDR(ifp));
/* set host ready */
RAL_WRITE(sc, RT2661_MAC_CSR1, 3);
diff --git a/sys/dev/ral/rt2661var.h b/sys/dev/ral/rt2661var.h
index 0c15840..6fc958a 100644
--- a/sys/dev/ral/rt2661var.h
+++ b/sys/dev/ral/rt2661var.h
@@ -114,8 +114,6 @@ struct rt2661_softc {
int sc_tx_timer;
int sc_invalid;
int sc_debug;
-
- const struct ieee80211_rate_table *sc_rates;
/*
* The same in both up to here
* ------------------------------------------------
diff --git a/sys/dev/re/if_re.c b/sys/dev/re/if_re.c
index 7a017c6..fe7dad9 100644
--- a/sys/dev/re/if_re.c
+++ b/sys/dev/re/if_re.c
@@ -419,6 +419,7 @@ re_gmii_readreg(device_t dev, int phy, int reg)
}
CSR_WRITE_4(sc, RL_PHYAR, reg << 16);
+ DELAY(1000);
for (i = 0; i < RL_PHY_TIMEOUT; i++) {
rval = CSR_READ_4(sc, RL_PHYAR);
@@ -446,6 +447,7 @@ re_gmii_writereg(device_t dev, int phy, int reg, int data)
CSR_WRITE_4(sc, RL_PHYAR, (reg << 16) |
(data & RL_PHYAR_PHYDATA) | RL_PHYAR_BUSY);
+ DELAY(1000);
for (i = 0; i < RL_PHY_TIMEOUT; i++) {
rval = CSR_READ_4(sc, RL_PHYAR);
diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c
index 1f997f7..e580944 100644
--- a/sys/dev/sound/pci/hda/hdac.c
+++ b/sys/dev/sound/pci/hda/hdac.c
@@ -83,7 +83,7 @@
#include "mixer_if.h"
-#define HDA_DRV_TEST_REV "20090226_0129"
+#define HDA_DRV_TEST_REV "20090401_0132"
SND_DECLARE_FILE("$FreeBSD$");
@@ -247,6 +247,7 @@ SND_DECLARE_FILE("$FreeBSD$");
#define ACER_A4715_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0133)
#define ACER_3681WXM_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x0110)
#define ACER_T6292_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011b)
+#define ACER_T5320_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0x011f)
#define ACER_ALL_SUBVENDOR HDA_MODEL_CONSTRUCT(ACER, 0xffff)
/* Asus */
@@ -260,6 +261,7 @@ SND_DECLARE_FILE("$FreeBSD$");
#define ASUS_A7T_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x13c2)
#define ASUS_W2J_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1971)
#define ASUS_M5200_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x1993)
+#define ASUS_P5PL2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x817f)
#define ASUS_P1AH2_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb)
#define ASUS_M2NPVMX_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81cb)
#define ASUS_M2V_SUBVENDOR HDA_MODEL_CONSTRUCT(ASUS, 0x81e7)
@@ -2424,13 +2426,20 @@ hdac_widget_pin_getconfig(struct hdac_widget *w)
/* New patches */
if (id == HDA_CODEC_AD1986A &&
(sc->pci_subvendor == ASUS_M2NPVMX_SUBVENDOR ||
- sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR)) {
+ sc->pci_subvendor == ASUS_A8NVMCSM_SUBVENDOR ||
+ sc->pci_subvendor == ASUS_P5PL2_SUBVENDOR)) {
switch (nid) {
- case 28: /* 5.1 out => 2.0 out + 2 inputs */
+ case 26: /* Headphones with redirection */
+ patch = "as=1 seq=15";
+ break;
+ case 28: /* 5.1 out => 2.0 out + 1 input */
patch = "device=Line-in as=8 seq=1";
break;
- case 29:
- patch = "device=Mic as=8 seq=2";
+ case 29: /* Can't use this as input, as the only available mic
+ * preamplifier is busy by front panel mic (nid 31).
+ * If you want to use this rear connector as mic input,
+ * you have to disable the front panel one. */
+ patch = "as=0";
break;
case 31: /* Lot of inputs configured with as=15 and unusable */
patch = "as=8 seq=3";
@@ -2452,13 +2461,14 @@ hdac_widget_pin_getconfig(struct hdac_widget *w)
patch = "seq=15 device=Headphones";
break;
}
- } else if (id == HDA_CODEC_ALC268 &&
- HDA_DEV_MATCH(ACER_ALL_SUBVENDOR, sc->pci_subvendor)) {
+ } else if (id == HDA_CODEC_ALC268) {
+ if (sc->pci_subvendor == ACER_T5320_SUBVENDOR) {
switch (nid) {
- case 28:
- patch = "device=CD conn=fixed";
+ case 20: /* Headphones Jack */
+ patch = "as=1 seq=15";
break;
}
+ }
}
if (patch != NULL)
@@ -4729,6 +4739,35 @@ hdac_vendor_patch_parse(struct hdac_devinfo *devinfo)
w = hdac_widget_get(devinfo, 15);
if (w != NULL)
w->connsenable[3] = 0;
+ /* There is only one mic preamplifier, use it effectively. */
+ w = hdac_widget_get(devinfo, 31);
+ if (w != NULL) {
+ if ((w->wclass.pin.config &
+ HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
+ HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
+ w = hdac_widget_get(devinfo, 16);
+ if (w != NULL)
+ w->connsenable[2] = 0;
+ } else {
+ w = hdac_widget_get(devinfo, 15);
+ if (w != NULL)
+ w->connsenable[0] = 0;
+ }
+ }
+ w = hdac_widget_get(devinfo, 32);
+ if (w != NULL) {
+ if ((w->wclass.pin.config &
+ HDA_CONFIG_DEFAULTCONF_DEVICE_MASK) ==
+ HDA_CONFIG_DEFAULTCONF_DEVICE_MIC_IN) {
+ w = hdac_widget_get(devinfo, 16);
+ if (w != NULL)
+ w->connsenable[0] = 0;
+ } else {
+ w = hdac_widget_get(devinfo, 15);
+ if (w != NULL)
+ w->connsenable[1] = 0;
+ }
+ }
if (subvendor == ASUS_A8X_SUBVENDOR) {
/*
@@ -5278,7 +5317,7 @@ hdac_audio_bind_as(struct hdac_devinfo *devinfo)
sizeof(struct hdac_chan) * cnt,
M_HDAC, M_ZERO | M_NOWAIT);
if (sc->chans == NULL) {
- device_printf(devinfo->codec->sc->dev,
+ device_printf(sc->dev,
"Channels memory allocation failed!\n");
return;
}
@@ -5288,17 +5327,20 @@ hdac_audio_bind_as(struct hdac_devinfo *devinfo)
M_HDAC, M_ZERO | M_NOWAIT);
if (sc->chans == NULL) {
sc->num_chans = 0;
- device_printf(devinfo->codec->sc->dev,
+ device_printf(sc->dev,
"Channels memory allocation failed!\n");
return;
}
+ /* Fixup relative pointers after realloc */
+ for (j = 0; j < sc->num_chans; j++)
+ sc->chans[j].caps.fmtlist = sc->chans[j].fmtlist;
}
free = sc->num_chans;
sc->num_chans += cnt;
for (j = free; j < free + cnt; j++) {
- devinfo->codec->sc->chans[j].devinfo = devinfo;
- devinfo->codec->sc->chans[j].as = -1;
+ sc->chans[j].devinfo = devinfo;
+ sc->chans[j].as = -1;
}
/* Assign associations in order of their numbers, */
@@ -5307,10 +5349,10 @@ hdac_audio_bind_as(struct hdac_devinfo *devinfo)
continue;
as[j].chan = free;
- devinfo->codec->sc->chans[free].as = j;
- devinfo->codec->sc->chans[free].dir =
+ sc->chans[free].as = j;
+ sc->chans[free].dir =
(as[j].dir == HDA_CTL_IN) ? PCMDIR_REC : PCMDIR_PLAY;
- hdac_pcmchannel_setup(&devinfo->codec->sc->chans[free]);
+ hdac_pcmchannel_setup(&sc->chans[free]);
free++;
}
}
@@ -7923,9 +7965,9 @@ hdac_pcm_attach(device_t dev)
device_printf(dev, "+--------------------------------------+\n");
hdac_dump_pcmchannels(pdevinfo);
device_printf(dev, "\n");
- device_printf(dev, "+--------------------------------+\n");
- device_printf(dev, "| DUMPING Playback/Record Pathes |\n");
- device_printf(dev, "+--------------------------------+\n");
+ device_printf(dev, "+-------------------------------+\n");
+ device_printf(dev, "| DUMPING Playback/Record Paths |\n");
+ device_printf(dev, "+-------------------------------+\n");
hdac_dump_dac(pdevinfo);
hdac_dump_adc(pdevinfo);
hdac_dump_mix(pdevinfo);
diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c
index 50728ee..50866da 100644
--- a/sys/dev/sound/usb/uaudio.c
+++ b/sys/dev/sound/usb/uaudio.c
@@ -400,20 +400,20 @@ static const struct usb2_config
.type = UE_ISOCHRONOUS,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UAUDIO_MINFRAMES,
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.callback = &uaudio_chan_record_callback,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UAUDIO_MINFRAMES,
+ .flags = {.short_xfer_ok = 1,},
+ .callback = &uaudio_chan_record_callback,
},
[1] = {
.type = UE_ISOCHRONOUS,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UAUDIO_MINFRAMES,
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.callback = &uaudio_chan_record_callback,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UAUDIO_MINFRAMES,
+ .flags = {.short_xfer_ok = 1,},
+ .callback = &uaudio_chan_record_callback,
},
};
@@ -423,20 +423,20 @@ static const struct usb2_config
.type = UE_ISOCHRONOUS,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UAUDIO_MINFRAMES,
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.callback = &uaudio_chan_play_callback,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UAUDIO_MINFRAMES,
+ .flags = {.short_xfer_ok = 1,},
+ .callback = &uaudio_chan_play_callback,
},
[1] = {
.type = UE_ISOCHRONOUS,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UAUDIO_MINFRAMES,
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.callback = &uaudio_chan_play_callback,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UAUDIO_MINFRAMES,
+ .flags = {.short_xfer_ok = 1,},
+ .callback = &uaudio_chan_play_callback,
},
};
@@ -446,9 +446,9 @@ static const struct usb2_config
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = (sizeof(struct usb2_device_request) + 4),
- .mh.callback = &uaudio_mixer_write_cfg_callback,
- .mh.timeout = 1000, /* 1 second */
+ .bufsize = (sizeof(struct usb2_device_request) + 4),
+ .callback = &uaudio_mixer_write_cfg_callback,
+ .timeout = 1000, /* 1 second */
},
};
@@ -478,40 +478,40 @@ static const struct usb2_config
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UMIDI_BULK_SIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &umidi_bulk_write_callback,
+ .bufsize = UMIDI_BULK_SIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &umidi_bulk_write_callback,
},
[1] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UMIDI_BULK_SIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &umidi_bulk_read_callback,
+ .bufsize = UMIDI_BULK_SIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &umidi_bulk_read_callback,
},
[2] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umidi_write_clear_stall_callback,
- .mh.timeout = 1000, /* 1 second */
- .mh.interval = 50, /* 50ms */
+ .bufsize = sizeof(struct usb2_device_request),
+ .flags = {},
+ .callback = &umidi_write_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
},
[3] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umidi_read_clear_stall_callback,
- .mh.timeout = 1000, /* 1 second */
- .mh.interval = 50, /* 50ms */
+ .bufsize = sizeof(struct usb2_device_request),
+ .flags = {},
+ .callback = &umidi_read_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
},
};
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c
index 6791d64..77f4e61 100644
--- a/sys/dev/syscons/syscons.c
+++ b/sys/dev/syscons/syscons.c
@@ -173,7 +173,6 @@ static void scshutdown(void *arg, int howto);
static u_int scgetc(sc_softc_t *sc, u_int flags);
#define SCGETC_CN 1
#define SCGETC_NONBLOCK 2
-static int sccngetch(int flags);
static void sccnupdate(scr_stat *scp);
static scr_stat *alloc_scp(sc_softc_t *sc, int vty);
static void init_scp(sc_softc_t *sc, int vty, scr_stat *scp);
@@ -1533,12 +1532,6 @@ sc_cnputc(struct consdev *cd, int c)
static int
sc_cngetc(struct consdev *cd)
{
- return sccngetch(SCGETC_NONBLOCK);
-}
-
-static int
-sccngetch(int flags)
-{
static struct fkeytab fkey;
static int fkeycp;
scr_stat *scp;
@@ -1579,7 +1572,7 @@ sccngetch(int flags)
kbdd_ioctl(scp->sc->kbd, KDSKBMODE, (caddr_t)&scp->kbd_mode);
kbdd_poll(scp->sc->kbd, TRUE);
- c = scgetc(scp->sc, SCGETC_CN | flags);
+ c = scgetc(scp->sc, SCGETC_CN | SCGETC_NONBLOCK);
kbdd_poll(scp->sc->kbd, FALSE);
scp->kbd_mode = cur_mode;
diff --git a/sys/dev/syscons/teken/teken.c b/sys/dev/syscons/teken/teken.c
index f5555b0..30845c4 100644
--- a/sys/dev/syscons/teken/teken.c
+++ b/sys/dev/syscons/teken/teken.c
@@ -361,8 +361,6 @@ void
teken_set_winsize(teken_t *t, const teken_pos_t *p)
{
- teken_assert(p->tp_col <= T_NUMCOL);
-
t->t_winsize = *p;
/* XXX: bounds checking with cursor/etc! */
t->t_scrollreg.ts_begin = 0;
diff --git a/sys/dev/syscons/teken/teken_subr.h b/sys/dev/syscons/teken/teken_subr.h
index 2ca2c30..21982e2 100644
--- a/sys/dev/syscons/teken/teken_subr.h
+++ b/sys/dev/syscons/teken/teken_subr.h
@@ -37,7 +37,8 @@ teken_tab_isset(teken_t *t, unsigned int col)
{
unsigned int b, o;
- teken_assert(col <= T_NUMCOL);
+ if (col >= T_NUMCOL)
+ return ((col % 8) == 0);
b = col / (sizeof(unsigned int) * 8);
o = col % (sizeof(unsigned int) * 8);
@@ -50,7 +51,8 @@ teken_tab_clear(teken_t *t, unsigned int col)
{
unsigned int b, o;
- teken_assert(col <= T_NUMCOL);
+ if (col >= T_NUMCOL)
+ return;
b = col / (sizeof(unsigned int) * 8);
o = col % (sizeof(unsigned int) * 8);
@@ -63,7 +65,8 @@ teken_tab_set(teken_t *t, unsigned int col)
{
unsigned int b, o;
- teken_assert(col <= T_NUMCOL);
+ if (col >= T_NUMCOL)
+ return;
b = col / (sizeof(unsigned int) * 8);
o = col % (sizeof(unsigned int) * 8);
diff --git a/sys/dev/twa/tw_cl_init.c b/sys/dev/twa/tw_cl_init.c
index 52864b2..ca282fa 100644
--- a/sys/dev/twa/tw_cl_init.c
+++ b/sys/dev/twa/tw_cl_init.c
@@ -692,7 +692,7 @@ tw_cli_init_connection(struct tw_cli_ctlr_context *ctlr,
init_connect->message_credits = TW_CL_SWAP16(message_credits);
init_connect->features = TW_CL_SWAP32(set_features);
if (ctlr->flags & TW_CL_64BIT_ADDRESSES)
- init_connect->features |= TWA_64BIT_SG_ADDRESSES;
+ init_connect->features |= TW_CL_SWAP32(TWA_64BIT_SG_ADDRESSES);
if (set_features & TWA_EXTENDED_INIT_CONNECT) {
/*
* Fill in the extra fields needed for an extended
diff --git a/sys/dev/twa/tw_osl.h b/sys/dev/twa/tw_osl.h
index d68cc5e..6082253 100644
--- a/sys/dev/twa/tw_osl.h
+++ b/sys/dev/twa/tw_osl.h
@@ -57,6 +57,12 @@
#define TW_OSLI_DEFERRED_INTR_USED
*/
+#ifdef PAE
+#define TW_OSLI_DMA_BOUNDARY (1u << 31)
+#else
+#define TW_OSLI_DMA_BOUNDARY ((bus_size_t)((uint64_t)1 << 32))
+#endif
+
/* Possible values of req->state. */
#define TW_OSLI_REQ_STATE_INIT 0x0 /* being initialized */
#define TW_OSLI_REQ_STATE_BUSY 0x1 /* submitted to CL */
diff --git a/sys/dev/twa/tw_osl_freebsd.c b/sys/dev/twa/tw_osl_freebsd.c
index d18fd0a..85b3af1 100644
--- a/sys/dev/twa/tw_osl_freebsd.c
+++ b/sys/dev/twa/tw_osl_freebsd.c
@@ -491,8 +491,8 @@ tw_osli_alloc_mem(struct twa_softc *sc)
/* Create the parent dma tag. */
if (bus_dma_tag_create(NULL, /* parent */
sc->alignment, /* alignment */
- 0, /* boundary */
- BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+ TW_OSLI_DMA_BOUNDARY, /* boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
TW_CL_MAX_IO_SIZE, /* maxsize */
@@ -515,7 +515,7 @@ tw_osli_alloc_mem(struct twa_softc *sc)
if (bus_dma_tag_create(sc->parent_tag, /* parent */
sc->alignment, /* alignment */
0, /* boundary */
- BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+ BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
dma_mem_size, /* maxsize */
@@ -562,7 +562,7 @@ tw_osli_alloc_mem(struct twa_softc *sc)
if (bus_dma_tag_create(sc->parent_tag, /* parent */
sc->alignment, /* alignment */
0, /* boundary */
- BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+ BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
TW_CL_MAX_IO_SIZE, /* maxsize */
@@ -588,7 +588,7 @@ tw_osli_alloc_mem(struct twa_softc *sc)
if (bus_dma_tag_create(sc->parent_tag, /* parent */
sc->alignment, /* alignment */
0, /* boundary */
- BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+ BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
TW_CL_MAX_IO_SIZE, /* maxsize */
@@ -1347,7 +1347,7 @@ static TW_VOID
twa_map_load_callback(TW_VOID *arg, bus_dma_segment_t *segs,
TW_INT32 nsegments, TW_INT32 error)
{
- *((bus_addr_t *)arg) = segs[0].ds_addr;
+ *((TW_UINT64 *)arg) = segs[0].ds_addr;
}
diff --git a/sys/dev/uart/uart_cpu_powerpc.c b/sys/dev/uart/uart_cpu_powerpc.c
index 0945970..f97eda0 100644
--- a/sys/dev/uart/uart_cpu_powerpc.c
+++ b/sys/dev/uart/uart_cpu_powerpc.c
@@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
#include <machine/bus.h>
@@ -53,8 +55,11 @@ bus_space_tag_t uart_bus_space_mem = &bs_le_tag;
int
uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
{
-
+#ifdef MPC85XX
return ((b1->bsh == b2->bsh) ? 1 : 0);
+#else
+ return ((pmap_kextract(b1->bsh) == pmap_kextract(b2->bsh)) ? 1 : 0);
+#endif
}
#ifdef MPC85XX
@@ -116,7 +121,16 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
return (ENXIO);
if (OF_getprop(input, "name", buf, sizeof(buf)) == -1)
return (ENXIO);
- if (strcmp(buf, "ch-a"))
+
+ if (strcmp(buf, "ch-a") == 0) {
+ class = &uart_z8530_class;
+ di->bas.regshft = 4;
+ di->bas.chan = 1;
+ } else if (strcmp(buf,"serial") == 0) {
+ class = &uart_ns8250_class;
+ di->bas.regshft = 0;
+ di->bas.chan = 0;
+ } else
return (ENXIO);
error = OF_decode_addr(input, 0, &di->bas.bst, &di->bas.bsh);
@@ -125,11 +139,13 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
di->ops = uart_getops(class);
- di->bas.rclk = 230400;
- di->bas.chan = 1;
- di->bas.regshft = 4;
+ if (OF_getprop(input, "clock-frequency", &di->bas.rclk,
+ sizeof(di->bas.rclk)) == -1)
+ di->bas.rclk = 230400;
+ if (OF_getprop(input, "current-speed", &di->baudrate,
+ sizeof(di->baudrate)) == -1)
+ di->baudrate = 0;
- di->baudrate = 0;
di->databits = 8;
di->stopbits = 1;
di->parity = UART_PARITY_NONE;
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 81642b2..c01fd61 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -50,14 +50,16 @@ __FBSDID("$FreeBSD$");
static void
ns8250_clrint(struct uart_bas *bas)
{
- uint8_t iir;
+ uint8_t iir, lsr;
iir = uart_getreg(bas, REG_IIR);
while ((iir & IIR_NOPEND) == 0) {
iir &= IIR_IMASK;
- if (iir == IIR_RLS)
- (void)uart_getreg(bas, REG_LSR);
- else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
+ if (iir == IIR_RLS) {
+ lsr = uart_getreg(bas, REG_LSR);
+ if (lsr & (LSR_BI|LSR_FE|LSR_PE))
+ (void)uart_getreg(bas, REG_DATA);
+ } else if (iir == IIR_RXRDY || iir == IIR_RXTOUT)
(void)uart_getreg(bas, REG_DATA);
else if (iir == IIR_MLSC)
(void)uart_getreg(bas, REG_MSR);
@@ -587,7 +589,6 @@ ns8250_bus_ipend(struct uart_softc *sc)
ipend = 0;
if (iir & IIR_RXRDY) {
lsr = uart_getreg(bas, REG_LSR);
- uart_unlock(sc->sc_hwmtx);
if (lsr & LSR_OE)
ipend |= SER_INT_OVERRUN;
if (lsr & LSR_BI)
@@ -595,12 +596,14 @@ ns8250_bus_ipend(struct uart_softc *sc)
if (lsr & LSR_RXRDY)
ipend |= SER_INT_RXREADY;
} else {
- uart_unlock(sc->sc_hwmtx);
if (iir & IIR_TXRDY)
ipend |= SER_INT_TXIDLE;
else
ipend |= SER_INT_SIGCHG;
}
+ if (ipend == 0)
+ ns8250_clrint(bas);
+ uart_unlock(sc->sc_hwmtx);
return ((sc->sc_leaving) ? 0 : ipend);
}
diff --git a/sys/dev/usb/bluetooth/ng_ubt.c b/sys/dev/usb/bluetooth/ng_ubt.c
index 5e94578..a5a19ded 100644
--- a/sys/dev/usb/bluetooth/ng_ubt.c
+++ b/sys/dev/usb/bluetooth/ng_ubt.c
@@ -276,9 +276,9 @@ static const struct usb2_config ubt_config[UBT_N_TRANSFER] =
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.if_index = 0,
- .mh.bufsize = UBT_BULK_WRITE_BUFFER_SIZE,
- .mh.flags = { .pipe_bof = 1, .force_short_xfer = 1, },
- .mh.callback = &ubt_bulk_write_callback,
+ .bufsize = UBT_BULK_WRITE_BUFFER_SIZE,
+ .flags = { .pipe_bof = 1, .force_short_xfer = 1, },
+ .callback = &ubt_bulk_write_callback,
},
/* Incoming bulk transfer - ACL packets */
[UBT_IF_0_BULK_DT_RD] = {
@@ -286,9 +286,9 @@ static const struct usb2_config ubt_config[UBT_N_TRANSFER] =
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.if_index = 0,
- .mh.bufsize = UBT_BULK_READ_BUFFER_SIZE,
- .mh.flags = { .pipe_bof = 1, .short_xfer_ok = 1, },
- .mh.callback = &ubt_bulk_read_callback,
+ .bufsize = UBT_BULK_READ_BUFFER_SIZE,
+ .flags = { .pipe_bof = 1, .short_xfer_ok = 1, },
+ .callback = &ubt_bulk_read_callback,
},
/* Incoming interrupt transfer - HCI events */
[UBT_IF_0_INTR_DT_RD] = {
@@ -296,9 +296,9 @@ static const struct usb2_config ubt_config[UBT_N_TRANSFER] =
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.if_index = 0,
- .mh.flags = { .pipe_bof = 1, .short_xfer_ok = 1, },
- .mh.bufsize = UBT_INTR_BUFFER_SIZE,
- .mh.callback = &ubt_intr_read_callback,
+ .flags = { .pipe_bof = 1, .short_xfer_ok = 1, },
+ .bufsize = UBT_INTR_BUFFER_SIZE,
+ .callback = &ubt_intr_read_callback,
},
/* Outgoing control transfer - HCI commands */
[UBT_IF_0_CTRL_DT_WR] = {
@@ -306,9 +306,9 @@ static const struct usb2_config ubt_config[UBT_N_TRANSFER] =
.endpoint = 0x00, /* control pipe */
.direction = UE_DIR_ANY,
.if_index = 0,
- .mh.bufsize = UBT_CTRL_BUFFER_SIZE,
- .mh.callback = &ubt_ctrl_write_callback,
- .mh.timeout = 5000, /* 5 seconds */
+ .bufsize = UBT_CTRL_BUFFER_SIZE,
+ .callback = &ubt_ctrl_write_callback,
+ .timeout = 5000, /* 5 seconds */
},
/*
@@ -321,10 +321,10 @@ static const struct usb2_config ubt_config[UBT_N_TRANSFER] =
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.if_index = 1,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UBT_ISOC_NFRAMES,
- .mh.flags = { .short_xfer_ok = 1, },
- .mh.callback = &ubt_isoc_read_callback,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UBT_ISOC_NFRAMES,
+ .flags = { .short_xfer_ok = 1, },
+ .callback = &ubt_isoc_read_callback,
},
/* Incoming isochronous transfer #2 - SCO packets */
[UBT_IF_1_ISOC_DT_RD2] = {
@@ -332,10 +332,10 @@ static const struct usb2_config ubt_config[UBT_N_TRANSFER] =
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.if_index = 1,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UBT_ISOC_NFRAMES,
- .mh.flags = { .short_xfer_ok = 1, },
- .mh.callback = &ubt_isoc_read_callback,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UBT_ISOC_NFRAMES,
+ .flags = { .short_xfer_ok = 1, },
+ .callback = &ubt_isoc_read_callback,
},
/* Outgoing isochronous transfer #1 - SCO packets */
[UBT_IF_1_ISOC_DT_WR1] = {
@@ -343,10 +343,10 @@ static const struct usb2_config ubt_config[UBT_N_TRANSFER] =
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.if_index = 1,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UBT_ISOC_NFRAMES,
- .mh.flags = { .short_xfer_ok = 1, },
- .mh.callback = &ubt_isoc_write_callback,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UBT_ISOC_NFRAMES,
+ .flags = { .short_xfer_ok = 1, },
+ .callback = &ubt_isoc_write_callback,
},
/* Outgoing isochronous transfer #2 - SCO packets */
[UBT_IF_1_ISOC_DT_WR2] = {
@@ -354,10 +354,10 @@ static const struct usb2_config ubt_config[UBT_N_TRANSFER] =
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.if_index = 1,
- .mh.bufsize = 0, /* use "wMaxPacketSize * frames" */
- .mh.frames = UBT_ISOC_NFRAMES,
- .mh.flags = { .short_xfer_ok = 1, },
- .mh.callback = &ubt_isoc_write_callback,
+ .bufsize = 0, /* use "wMaxPacketSize * frames" */
+ .frames = UBT_ISOC_NFRAMES,
+ .flags = { .short_xfer_ok = 1, },
+ .callback = &ubt_isoc_write_callback,
},
};
@@ -426,6 +426,7 @@ ubt_attach(device_t dev)
struct usb2_attach_arg *uaa = device_get_ivars(dev);
struct ubt_softc *sc = device_get_softc(dev);
struct usb2_endpoint_descriptor *ed;
+ struct usb2_interface_descriptor *id;
uint16_t wMaxPacketSize;
uint8_t alt_index, i, j;
uint8_t iface_index[2] = { 0, 1 };
@@ -496,31 +497,34 @@ ubt_attach(device_t dev)
alt_index = 0;
i = 0;
j = 0;
+ ed = NULL;
- /* Search through all the descriptors looking for bidir mode */
- while (1) {
- uint16_t temp;
-
- ed = usb2_find_edesc(usb2_get_config_descriptor(uaa->device),
- 1, i, j);
- if (ed == NULL) {
- if (j != 0) {
- /* next interface */
- j = 0;
- i ++;
- continue;
- }
-
- break; /* end of interfaces */
+ /*
+ * Search through all the descriptors looking for the largest
+ * packet size:
+ */
+ while ((ed = (struct usb2_endpoint_descriptor *)usb2_desc_foreach(
+ usb2_get_config_descriptor(uaa->device),
+ (struct usb2_descriptor *)ed))) {
+
+ if ((ed->bDescriptorType == UDESC_INTERFACE) &&
+ (ed->bLength >= sizeof(*id))) {
+ id = (struct usb2_interface_descriptor *)ed;
+ i = id->bInterfaceNumber;
+ j = id->bAlternateSetting;
}
- temp = UGETW(ed->wMaxPacketSize);
- if (temp > wMaxPacketSize) {
- wMaxPacketSize = temp;
- alt_index = i;
- }
+ if ((ed->bDescriptorType == UDESC_ENDPOINT) &&
+ (ed->bLength >= sizeof(*ed)) &&
+ (i == 1)) {
+ uint16_t temp;
- j ++;
+ temp = UGETW(ed->wMaxPacketSize);
+ if (temp > wMaxPacketSize) {
+ wMaxPacketSize = temp;
+ alt_index = j;
+ }
+ }
}
/* Set alt configuration on interface #1 only if we found it */
diff --git a/sys/dev/usb/bluetooth/ubtbcmfw.c b/sys/dev/usb/bluetooth/ubtbcmfw.c
index bfa390f..1932a39 100644
--- a/sys/dev/usb/bluetooth/ubtbcmfw.c
+++ b/sys/dev/usb/bluetooth/ubtbcmfw.c
@@ -118,10 +118,10 @@ static const struct usb2_config ubtbcmfw_config[UBTBCMFW_N_TRANSFER] =
.endpoint = 0x02, /* fixed */
.direction = UE_DIR_OUT,
.if_index = UBTBCMFW_IFACE_IDX,
- .mh.bufsize = UBTBCMFW_BSIZE,
- .mh.flags = { .pipe_bof = 1, .force_short_xfer = 1,
+ .bufsize = UBTBCMFW_BSIZE,
+ .flags = { .pipe_bof = 1, .force_short_xfer = 1,
.proxy_buffer = 1, },
- .mh.callback = &ubtbcmfw_write_callback,
+ .callback = &ubtbcmfw_write_callback,
},
[UBTBCMFW_INTR_DT_RD] = {
@@ -129,10 +129,10 @@ static const struct usb2_config ubtbcmfw_config[UBTBCMFW_N_TRANSFER] =
.endpoint = 0x01, /* fixed */
.direction = UE_DIR_IN,
.if_index = UBTBCMFW_IFACE_IDX,
- .mh.bufsize = UBTBCMFW_BSIZE,
- .mh.flags = { .pipe_bof = 1, .short_xfer_ok = 1,
+ .bufsize = UBTBCMFW_BSIZE,
+ .flags = { .pipe_bof = 1, .short_xfer_ok = 1,
.proxy_buffer = 1, },
- .mh.callback = &ubtbcmfw_read_callback,
+ .callback = &ubtbcmfw_read_callback,
},
};
diff --git a/sys/dev/usb/controller/at91dci.c b/sys/dev/usb/controller/at91dci.c
index fec3b27..ade0c2a 100644
--- a/sys/dev/usb/controller/at91dci.c
+++ b/sys/dev/usb/controller/at91dci.c
@@ -38,7 +38,7 @@ __FBSDID("$FreeBSD$");
/*
* NOTE: The "fifo_bank" is not reset in hardware when the endpoint is
- * reset !
+ * reset.
*
* NOTE: When the chip detects BUS-reset it will also reset the
* endpoints, Function-address and more.
@@ -47,7 +47,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR at91dcidebug
@@ -55,7 +54,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_transfer.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_hub.h>
@@ -67,10 +65,10 @@ __FBSDID("$FreeBSD$");
#define AT9100_DCI_BUS2SC(bus) \
((struct at91dci_softc *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((struct at91dci_softc *)0)->sc_bus))))
+ ((uint8_t *)&(((struct at91dci_softc *)0)->sc_bus))))
#define AT9100_DCI_PC2SC(pc) \
- AT9100_DCI_BUS2SC((pc)->tag_parent->info->bus)
+ AT9100_DCI_BUS2SC(USB_DMATAG_TO_XROOT((pc)->tag_parent)->bus)
#if USB_DEBUG
static int at91dcidebug = 0;
@@ -89,8 +87,6 @@ struct usb2_pipe_methods at91dci_device_bulk_methods;
struct usb2_pipe_methods at91dci_device_ctrl_methods;
struct usb2_pipe_methods at91dci_device_intr_methods;
struct usb2_pipe_methods at91dci_device_isoc_fs_methods;
-struct usb2_pipe_methods at91dci_root_ctrl_methods;
-struct usb2_pipe_methods at91dci_root_intr_methods;
static at91dci_cmd_t at91dci_setup_rx;
static at91dci_cmd_t at91dci_data_rx;
@@ -98,11 +94,8 @@ static at91dci_cmd_t at91dci_data_tx;
static at91dci_cmd_t at91dci_data_tx_sync;
static void at91dci_device_done(struct usb2_xfer *, usb2_error_t);
static void at91dci_do_poll(struct usb2_bus *);
-static void at91dci_root_ctrl_poll(struct at91dci_softc *);
static void at91dci_standard_done(struct usb2_xfer *);
-
-static usb2_sw_transfer_func_t at91dci_root_intr_done;
-static usb2_sw_transfer_func_t at91dci_root_ctrl_done;
+static void at91dci_root_intr(struct at91dci_softc *sc);
/*
* NOTE: Some of the bits in the CSR register have inverse meaning so
@@ -257,10 +250,8 @@ at91dci_pull_down(struct at91dci_softc *sc)
}
static void
-at91dci_wakeup_peer(struct usb2_xfer *xfer)
+at91dci_wakeup_peer(struct at91dci_softc *sc)
{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
-
if (!(sc->sc_flags.status_suspend)) {
return;
}
@@ -306,14 +297,11 @@ at91dci_setup_rx(struct at91dci_td *td)
AT91_UDP_CSR_TXCOMP);
if (!(csr & AT91_UDP_CSR_RXSETUP)) {
- /* abort any ongoing transfer */
- if (!td->did_stall) {
- DPRINTFN(5, "stalling\n");
- temp |= AT91_UDP_CSR_FORCESTALL;
- td->did_stall = 1;
- }
goto not_complete;
}
+ /* clear did stall */
+ td->did_stall = 0;
+
/* get the packet byte count */
count = (csr & AT91_UDP_CSR_RXBYTECNT) >> 16;
@@ -363,6 +351,13 @@ at91dci_setup_rx(struct at91dci_td *td)
return (0); /* complete */
not_complete:
+ /* abort any ongoing transfer */
+ if (!td->did_stall) {
+ DPRINTFN(5, "stalling\n");
+ temp |= AT91_UDP_CSR_FORCESTALL;
+ td->did_stall = 1;
+ }
+
/* clear interrupts, if any */
if (temp) {
DPRINTFN(5, "clearing 0x%08x\n", temp);
@@ -733,9 +728,7 @@ at91dci_vbus_interrupt(struct at91dci_softc *sc, uint8_t is_on)
sc->sc_flags.status_vbus = 1;
/* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &at91dci_root_intr_done);
+ at91dci_root_intr(sc);
}
} else {
if (sc->sc_flags.status_vbus) {
@@ -746,9 +739,7 @@ at91dci_vbus_interrupt(struct at91dci_softc *sc, uint8_t is_on)
sc->sc_flags.change_connect = 1;
/* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &at91dci_root_intr_done);
+ at91dci_root_intr(sc);
}
}
USB_BUS_UNLOCK(&sc->sc_bus);
@@ -825,9 +816,7 @@ at91dci_interrupt(struct at91dci_softc *sc)
}
}
/* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &at91dci_root_intr_done);
+ at91dci_root_intr(sc);
}
/* check for any endpoint interrupts */
@@ -888,8 +877,8 @@ at91dci_setup_standard_chain(struct usb2_xfer *xfer)
temp.td = NULL;
temp.td_next = xfer->td_start[0];
- temp.setup_alt_next = xfer->flags_int.short_frames_ok;
temp.offset = 0;
+ temp.setup_alt_next = xfer->flags_int.short_frames_ok;
sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
ep_no = (xfer->endpoint & UE_ADDR);
@@ -903,6 +892,12 @@ at91dci_setup_standard_chain(struct usb2_xfer *xfer)
temp.len = xfer->frlengths[0];
temp.pc = xfer->frbuffers + 0;
temp.short_pkt = temp.len ? 1 : 0;
+ /* check for last frame */
+ if (xfer->nframes == 1) {
+ /* no STATUS stage yet, SETUP is last */
+ if (xfer->flags_int.control_act)
+ temp.setup_alt_next = 0;
+ }
at91dci_setup_standard_chain_sub(&temp);
}
@@ -934,7 +929,13 @@ at91dci_setup_standard_chain(struct usb2_xfer *xfer)
x++;
if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
+ if (xfer->flags_int.control_xfr) {
+ if (xfer->flags_int.control_act) {
+ temp.setup_alt_next = 0;
+ }
+ } else {
+ temp.setup_alt_next = 0;
+ }
}
if (temp.len == 0) {
@@ -959,47 +960,46 @@ at91dci_setup_standard_chain(struct usb2_xfer *xfer)
}
}
- /* always setup a valid "pc" pointer for status and sync */
- temp.pc = xfer->frbuffers + 0;
-
- /* check if we need to sync */
- if (need_sync && xfer->flags_int.control_xfr) {
-
- /* we need a SYNC point after TX */
- temp.func = &at91dci_data_tx_sync;
- temp.len = 0;
- temp.short_pkt = 0;
-
- at91dci_setup_standard_chain_sub(&temp);
- }
- /* check if we should append a status stage */
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
+ /* check for control transfer */
+ if (xfer->flags_int.control_xfr) {
- /*
- * Send a DATA1 message and invert the current
- * endpoint direction.
- */
- if (xfer->endpoint & UE_DIR_IN) {
- temp.func = &at91dci_data_rx;
- need_sync = 0;
- } else {
- temp.func = &at91dci_data_tx;
- need_sync = 1;
- }
+ /* always setup a valid "pc" pointer for status and sync */
+ temp.pc = xfer->frbuffers + 0;
temp.len = 0;
temp.short_pkt = 0;
+ temp.setup_alt_next = 0;
- at91dci_setup_standard_chain_sub(&temp);
+ /* check if we need to sync */
if (need_sync) {
/* we need a SYNC point after TX */
temp.func = &at91dci_data_tx_sync;
- temp.len = 0;
- temp.short_pkt = 0;
+ at91dci_setup_standard_chain_sub(&temp);
+ }
+
+ /* check if we should append a status stage */
+ if (!xfer->flags_int.control_act) {
+
+ /*
+ * Send a DATA1 message and invert the current
+ * endpoint direction.
+ */
+ if (xfer->endpoint & UE_DIR_IN) {
+ temp.func = &at91dci_data_rx;
+ need_sync = 0;
+ } else {
+ temp.func = &at91dci_data_tx;
+ need_sync = 1;
+ }
at91dci_setup_standard_chain_sub(&temp);
+ if (need_sync) {
+ /* we need a SYNC point after TX */
+ temp.func = &at91dci_data_tx_sync;
+ at91dci_setup_standard_chain_sub(&temp);
+ }
}
}
+
/* must have at least one frame! */
td = temp.td;
xfer->td_transfer_last = td;
@@ -1056,31 +1056,17 @@ at91dci_start_standard_chain(struct usb2_xfer *xfer)
}
static void
-at91dci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
+at91dci_root_intr(struct at91dci_softc *sc)
{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
-
DPRINTFN(9, "\n");
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- at91dci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
/* set port bit */
sc->sc_hub_idata[0] = 0x02; /* we only have one port */
-done:
- return;
+ uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
+ sizeof(sc->sc_hub_idata));
}
static usb2_error_t
@@ -1474,7 +1460,6 @@ at91dci_do_poll(struct usb2_bus *bus)
USB_BUS_LOCK(&sc->sc_bus);
at91dci_interrupt_poll(sc);
- at91dci_root_ctrl_poll(sc);
USB_BUS_UNLOCK(&sc->sc_bus);
}
@@ -1513,8 +1498,6 @@ struct usb2_pipe_methods at91dci_device_bulk_methods =
.close = at91dci_device_bulk_close,
.enter = at91dci_device_bulk_enter,
.start = at91dci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -1552,8 +1535,6 @@ struct usb2_pipe_methods at91dci_device_ctrl_methods =
.close = at91dci_device_ctrl_close,
.enter = at91dci_device_ctrl_enter,
.start = at91dci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -1591,8 +1572,6 @@ struct usb2_pipe_methods at91dci_device_intr_methods =
.close = at91dci_device_intr_close,
.enter = at91dci_device_intr_enter,
.start = at91dci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -1675,38 +1654,14 @@ struct usb2_pipe_methods at91dci_device_isoc_fs_methods =
.close = at91dci_device_isoc_fs_close,
.enter = at91dci_device_isoc_fs_enter,
.start = at91dci_device_isoc_fs_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
* at91dci root control support
*------------------------------------------------------------------------*
- * simulate a hardware HUB by handling
- * all the necessary requests
+ * Simulate a hardware HUB by handling all the necessary requests.
*------------------------------------------------------------------------*/
-static void
-at91dci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- at91dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/*
- * USB descriptors for the virtual Root HUB:
- */
-
static const struct usb2_device_descriptor at91dci_devd = {
.bLength = sizeof(struct usb2_device_descriptor),
.bDescriptorType = UDESC_DEVICE,
@@ -1751,7 +1706,6 @@ static const struct at91dci_config_desc at91dci_confd = {
.bInterfaceSubClass = UISUBCLASS_HUB,
.bInterfaceProtocol = UIPROTO_HSHUBSTT,
},
-
.endpd = {
.bLength = sizeof(struct usb2_endpoint_descriptor),
.bDescriptorType = UDESC_ENDPOINT,
@@ -1791,44 +1745,15 @@ USB_MAKE_STRING_DESC(STRING_VENDOR, at91dci_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, at91dci_product);
static void
-at91dci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_root_ctrl_start(struct usb2_xfer *xfer)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-at91dci_root_ctrl_task(struct usb2_bus *bus)
-{
- at91dci_root_ctrl_poll(AT9100_DCI_BUS2SC(bus));
-}
-
-static void
-at91dci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
+at91dci_roothub_exec(struct usb2_bus *bus)
{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
+ struct at91dci_softc *sc = AT9100_DCI_BUS2SC(bus);
+ struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
uint16_t value;
uint16_t index;
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- at91dci_device_done(xfer, std->err);
- }
- goto done;
- }
/* buffer reset */
std->ptr = USB_ADD_BYTES(&sc->sc_hub_temp, 0);
std->len = 0;
@@ -2087,7 +2012,7 @@ tr_handle_clear_port_feature:
switch (value) {
case UHF_PORT_SUSPEND:
- at91dci_wakeup_peer(xfer);
+ at91dci_wakeup_peer(sc);
break;
case UHF_PORT_ENABLE:
@@ -2211,67 +2136,6 @@ done:
}
static void
-at91dci_root_ctrl_poll(struct at91dci_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &at91dci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods at91dci_root_ctrl_methods =
-{
- .open = at91dci_root_ctrl_open,
- .close = at91dci_root_ctrl_close,
- .enter = at91dci_root_ctrl_enter,
- .start = at91dci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-at91dci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_root_intr_close(struct usb2_xfer *xfer)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- at91dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-at91dci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-at91dci_root_intr_start(struct usb2_xfer *xfer)
-{
- struct at91dci_softc *sc = AT9100_DCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods at91dci_root_intr_methods =
-{
- .open = at91dci_root_intr_open,
- .close = at91dci_root_intr_close,
- .enter = at91dci_root_intr_enter,
- .start = at91dci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
at91dci_xfer_setup(struct usb2_setup_params *parm)
{
const struct usb2_hw_ep_profile *pf;
@@ -2397,24 +2261,7 @@ at91dci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *ede
edesc->bEndpointAddress, udev->flags.usb2_mode,
sc->sc_rt_addr);
- if (udev->device_index == sc->sc_rt_addr) {
-
- if (udev->flags.usb2_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &at91dci_root_ctrl_methods;
- break;
- case UE_DIR_IN | AT9100_DCI_INTR_ENDPT:
- pipe->methods = &at91dci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
+ if (udev->device_index != sc->sc_rt_addr) {
if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
/* not supported */
@@ -2452,5 +2299,5 @@ struct usb2_bus_methods at91dci_bus_methods =
.get_hw_ep_profile = &at91dci_get_hw_ep_profile,
.set_stall = &at91dci_set_stall,
.clear_stall = &at91dci_clear_stall,
- .roothub_exec = &at91dci_root_ctrl_task,
+ .roothub_exec = &at91dci_roothub_exec,
};
diff --git a/sys/dev/usb/controller/at91dci.h b/sys/dev/usb/controller/at91dci.h
index 6464ad7..8a745c8 100644
--- a/sys/dev/usb/controller/at91dci.h
+++ b/sys/dev/usb/controller/at91dci.h
@@ -27,8 +27,8 @@
*/
/*
- * USB Device Port (UDP) register definition, based on
- * "AT91RM9200.h" provided by ATMEL.
+ * USB Device Port (UDP) register definition, based on "AT91RM9200.h" provided
+ * by ATMEL.
*/
#ifndef _AT9100_DCI_H_
@@ -204,8 +204,6 @@ struct at91dci_softc {
struct usb2_bus sc_bus;
union at91dci_hub_temp sc_hub_temp;
LIST_HEAD(, usb2_xfer) sc_interrupt_list_head;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
struct usb2_device *sc_devices[AT91_MAX_DEVICES];
struct resource *sc_io_res;
diff --git a/sys/dev/usb/controller/at91dci_atmelarm.c b/sys/dev/usb/controller/at91dci_atmelarm.c
index 71d2937..aedd30f 100644
--- a/sys/dev/usb/controller/at91dci_atmelarm.c
+++ b/sys/dev/usb/controller/at91dci_atmelarm.c
@@ -28,13 +28,11 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
@@ -205,10 +203,10 @@ at91_udp_attach(device_t dev)
#if (__FreeBSD_version >= 700031)
err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl);
+ NULL, (driver_intr_t *)at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl);
#else
err = bus_setup_intr(dev, sc->sc_dci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl);
+ (driver_intr_t *)at91dci_interrupt, sc, &sc->sc_dci.sc_intr_hdl);
#endif
if (err) {
sc->sc_dci.sc_intr_hdl = NULL;
@@ -216,10 +214,10 @@ at91_udp_attach(device_t dev)
}
#if (__FreeBSD_version >= 700031)
err = bus_setup_intr(dev, sc->sc_vbus_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl);
+ NULL, (driver_intr_t *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl);
#else
err = bus_setup_intr(dev, sc->sc_vbus_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl);
+ (driver_intr_t *)at91_vbus_poll, sc, &sc->sc_vbus_intr_hdl);
#endif
if (err) {
sc->sc_vbus_intr_hdl = NULL;
diff --git a/sys/dev/usb/controller/atmegadci.c b/sys/dev/usb/controller/atmegadci.c
index edaef19..e182fc1 100644
--- a/sys/dev/usb/controller/atmegadci.c
+++ b/sys/dev/usb/controller/atmegadci.c
@@ -27,9 +27,8 @@ __FBSDID("$FreeBSD$");
*/
/*
- * This file contains the driver for the ATMEGA series USB OTG
- * Controller. This driver currently only supports the DCI mode of the
- * USB hardware.
+ * This file contains the driver for the ATMEGA series USB OTG Controller. This
+ * driver currently only supports the DCI mode of the USB hardware.
*/
/*
@@ -40,7 +39,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR atmegadci_debug
@@ -48,7 +46,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_transfer.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_hub.h>
@@ -60,10 +57,10 @@ __FBSDID("$FreeBSD$");
#define ATMEGA_BUS2SC(bus) \
((struct atmegadci_softc *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((struct atmegadci_softc *)0)->sc_bus))))
+ ((uint8_t *)&(((struct atmegadci_softc *)0)->sc_bus))))
#define ATMEGA_PC2SC(pc) \
- ATMEGA_BUS2SC((pc)->tag_parent->info->bus)
+ ATMEGA_BUS2SC(USB_DMATAG_TO_XROOT((pc)->tag_parent)->bus)
#if USB_DEBUG
static int atmegadci_debug = 0;
@@ -78,12 +75,8 @@ SYSCTL_INT(_hw_usb2_atmegadci, OID_AUTO, debug, CTLFLAG_RW,
/* prototypes */
struct usb2_bus_methods atmegadci_bus_methods;
-struct usb2_pipe_methods atmegadci_device_bulk_methods;
-struct usb2_pipe_methods atmegadci_device_ctrl_methods;
-struct usb2_pipe_methods atmegadci_device_intr_methods;
+struct usb2_pipe_methods atmegadci_device_non_isoc_methods;
struct usb2_pipe_methods atmegadci_device_isoc_fs_methods;
-struct usb2_pipe_methods atmegadci_root_ctrl_methods;
-struct usb2_pipe_methods atmegadci_root_intr_methods;
static atmegadci_cmd_t atmegadci_setup_rx;
static atmegadci_cmd_t atmegadci_data_rx;
@@ -91,11 +84,8 @@ static atmegadci_cmd_t atmegadci_data_tx;
static atmegadci_cmd_t atmegadci_data_tx_sync;
static void atmegadci_device_done(struct usb2_xfer *, usb2_error_t);
static void atmegadci_do_poll(struct usb2_bus *);
-static void atmegadci_root_ctrl_poll(struct atmegadci_softc *);
static void atmegadci_standard_done(struct usb2_xfer *);
-
-static usb2_sw_transfer_func_t atmegadci_root_intr_done;
-static usb2_sw_transfer_func_t atmegadci_root_ctrl_done;
+static void atmegadci_root_intr(struct atmegadci_softc *sc);
/*
* Here is a list of what the chip supports:
@@ -202,9 +192,8 @@ atmegadci_pull_down(struct atmegadci_softc *sc)
}
static void
-atmegadci_wakeup_peer(struct usb2_xfer *xfer)
+atmegadci_wakeup_peer(struct atmegadci_softc *sc)
{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
uint8_t temp;
if (!sc->sc_flags.status_suspend) {
@@ -251,16 +240,10 @@ atmegadci_setup_rx(struct atmegadci_td *td)
DPRINTFN(5, "UEINTX=0x%02x\n", temp);
if (!(temp & ATMEGA_UEINTX_RXSTPI)) {
- /* abort any ongoing transfer */
- if (!td->did_stall) {
- DPRINTFN(5, "stalling\n");
- ATMEGA_WRITE_1(sc, ATMEGA_UECONX,
- ATMEGA_UECONX_EPEN |
- ATMEGA_UECONX_STALLRQ);
- td->did_stall = 1;
- }
goto not_complete;
}
+ /* clear did stall */
+ td->did_stall = 0;
/* get the packet byte count */
count =
(ATMEGA_READ_1(sc, ATMEGA_UEBCHX) << 8) |
@@ -305,6 +288,18 @@ atmegadci_setup_rx(struct atmegadci_td *td)
return (0); /* complete */
not_complete:
+ /* abort any ongoing transfer */
+ if (!td->did_stall) {
+ DPRINTFN(5, "stalling\n");
+ ATMEGA_WRITE_1(sc, ATMEGA_UECONX,
+ ATMEGA_UECONX_EPEN |
+ ATMEGA_UECONX_STALLRQ);
+ td->did_stall = 1;
+ }
+ if (temp & ATMEGA_UEINTX_RXSTPI) {
+ /* clear SETUP packet interrupt */
+ ATMEGA_WRITE_1(sc, ATMEGA_UEINTX, ~ATMEGA_UEINTX_RXSTPI);
+ }
/* we only want to know if there is a SETUP packet */
ATMEGA_WRITE_1(sc, ATMEGA_UEIENX, ATMEGA_UEIENX_RXSTPE);
return (1); /* not complete */
@@ -620,8 +615,7 @@ atmegadci_vbus_interrupt(struct atmegadci_softc *sc, uint8_t is_on)
/* complete root HUB interrupt endpoint */
- usb2_sw_transfer(&sc->sc_root_intr,
- &atmegadci_root_intr_done);
+ atmegadci_root_intr(sc);
}
} else {
if (sc->sc_flags.status_vbus) {
@@ -633,8 +627,7 @@ atmegadci_vbus_interrupt(struct atmegadci_softc *sc, uint8_t is_on)
/* complete root HUB interrupt endpoint */
- usb2_sw_transfer(&sc->sc_root_intr,
- &atmegadci_root_intr_done);
+ atmegadci_root_intr(sc);
}
}
}
@@ -650,7 +643,7 @@ atmegadci_interrupt(struct atmegadci_softc *sc)
status = ATMEGA_READ_1(sc, ATMEGA_UDINT);
/* clear all set interrupts */
- ATMEGA_WRITE_1(sc, ATMEGA_UDINT, ~status);
+ ATMEGA_WRITE_1(sc, ATMEGA_UDINT, (~status) & 0x7D);
DPRINTFN(14, "UDINT=0x%02x\n", status);
@@ -671,8 +664,7 @@ atmegadci_interrupt(struct atmegadci_softc *sc)
ATMEGA_UDINT_EORSTE);
/* complete root HUB interrupt endpoint */
- usb2_sw_transfer(&sc->sc_root_intr,
- &atmegadci_root_intr_done);
+ atmegadci_root_intr(sc);
}
/*
* If resume and suspend is set at the same time we interpret
@@ -694,8 +686,7 @@ atmegadci_interrupt(struct atmegadci_softc *sc)
ATMEGA_UDINT_EORSTE);
/* complete root HUB interrupt endpoint */
- usb2_sw_transfer(&sc->sc_root_intr,
- &atmegadci_root_intr_done);
+ atmegadci_root_intr(sc);
}
} else if (status & ATMEGA_UDINT_SUSPI) {
@@ -712,15 +703,14 @@ atmegadci_interrupt(struct atmegadci_softc *sc)
ATMEGA_UDINT_EORSTE);
/* complete root HUB interrupt endpoint */
- usb2_sw_transfer(&sc->sc_root_intr,
- &atmegadci_root_intr_done);
+ atmegadci_root_intr(sc);
}
}
/* check VBUS */
status = ATMEGA_READ_1(sc, ATMEGA_USBINT);
/* clear all set interrupts */
- ATMEGA_WRITE_1(sc, ATMEGA_USBINT, ~status);
+ ATMEGA_WRITE_1(sc, ATMEGA_USBINT, (~status) & 0x03);
if (status & ATMEGA_USBINT_VBUSTI) {
uint8_t temp;
@@ -732,10 +722,7 @@ atmegadci_interrupt(struct atmegadci_softc *sc)
}
/* check for any endpoint interrupts */
status = ATMEGA_READ_1(sc, ATMEGA_UEINT);
-
- /* clear all set interrupts */
- ATMEGA_WRITE_1(sc, ATMEGA_UEINT, ~status);
-
+ /* the hardware will clear the UEINT bits automatically */
if (status) {
DPRINTFN(5, "real endpoint interrupt UEINT=0x%02x\n", status);
@@ -792,8 +779,8 @@ atmegadci_setup_standard_chain(struct usb2_xfer *xfer)
temp.td = NULL;
temp.td_next = xfer->td_start[0];
- temp.setup_alt_next = xfer->flags_int.short_frames_ok;
temp.offset = 0;
+ temp.setup_alt_next = xfer->flags_int.short_frames_ok;
sc = ATMEGA_BUS2SC(xfer->xroot->bus);
ep_no = (xfer->endpoint & UE_ADDR);
@@ -807,6 +794,12 @@ atmegadci_setup_standard_chain(struct usb2_xfer *xfer)
temp.len = xfer->frlengths[0];
temp.pc = xfer->frbuffers + 0;
temp.short_pkt = temp.len ? 1 : 0;
+ /* check for last frame */
+ if (xfer->nframes == 1) {
+ /* no STATUS stage yet, SETUP is last */
+ if (xfer->flags_int.control_act)
+ temp.setup_alt_next = 0;
+ }
atmegadci_setup_standard_chain_sub(&temp);
}
@@ -838,7 +831,13 @@ atmegadci_setup_standard_chain(struct usb2_xfer *xfer)
x++;
if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
+ if (xfer->flags_int.control_xfr) {
+ if (xfer->flags_int.control_act) {
+ temp.setup_alt_next = 0;
+ }
+ } else {
+ temp.setup_alt_next = 0;
+ }
}
if (temp.len == 0) {
@@ -863,45 +862,42 @@ atmegadci_setup_standard_chain(struct usb2_xfer *xfer)
}
}
- /* always setup a valid "pc" pointer for status and sync */
- temp.pc = xfer->frbuffers + 0;
-
- /* check if we need to sync */
- if (need_sync && xfer->flags_int.control_xfr) {
-
- /* we need a SYNC point after TX */
- temp.func = &atmegadci_data_tx_sync;
- temp.len = 0;
- temp.short_pkt = 0;
-
- atmegadci_setup_standard_chain_sub(&temp);
- }
- /* check if we should append a status stage */
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
+ if (xfer->flags_int.control_xfr) {
- /*
- * Send a DATA1 message and invert the current
- * endpoint direction.
- */
- if (xfer->endpoint & UE_DIR_IN) {
- temp.func = &atmegadci_data_rx;
- need_sync = 0;
- } else {
- temp.func = &atmegadci_data_tx;
- need_sync = 1;
- }
+ /* always setup a valid "pc" pointer for status and sync */
+ temp.pc = xfer->frbuffers + 0;
temp.len = 0;
temp.short_pkt = 0;
+ temp.setup_alt_next = 0;
- atmegadci_setup_standard_chain_sub(&temp);
+ /* check if we need to sync */
if (need_sync) {
/* we need a SYNC point after TX */
temp.func = &atmegadci_data_tx_sync;
- temp.len = 0;
- temp.short_pkt = 0;
+ atmegadci_setup_standard_chain_sub(&temp);
+ }
+
+ /* check if we should append a status stage */
+ if (!xfer->flags_int.control_act) {
+
+ /*
+ * Send a DATA1 message and invert the current
+ * endpoint direction.
+ */
+ if (xfer->endpoint & UE_DIR_IN) {
+ temp.func = &atmegadci_data_rx;
+ need_sync = 0;
+ } else {
+ temp.func = &atmegadci_data_tx;
+ need_sync = 1;
+ }
atmegadci_setup_standard_chain_sub(&temp);
+ if (need_sync) {
+ /* we need a SYNC point after TX */
+ temp.func = &atmegadci_data_tx_sync;
+ atmegadci_setup_standard_chain_sub(&temp);
+ }
}
}
/* must have at least one frame! */
@@ -942,32 +938,18 @@ atmegadci_start_standard_chain(struct usb2_xfer *xfer)
}
static void
-atmegadci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
+atmegadci_root_intr(struct atmegadci_softc *sc)
{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
-
DPRINTFN(9, "\n");
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- atmegadci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
/* set port bit */
sc->sc_hub_idata[0] = 0x02; /* we only have one port */
-done:
- return;
-}
+ uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
+ sizeof(sc->sc_hub_idata));
+ }
static usb2_error_t
atmegadci_standard_done_sub(struct usb2_xfer *xfer)
@@ -1241,6 +1223,12 @@ atmegadci_init(struct atmegadci_softc *sc)
ATMEGA_WRITE_1(sc, ATMEGA_UHWCON,
ATMEGA_UHWCON_UVREGE | ATMEGA_UHWCON_UIMOD);
#endif
+ /* make sure USB is enabled */
+ ATMEGA_WRITE_1(sc, ATMEGA_USBCON,
+ ATMEGA_USBCON_USBE |
+ ATMEGA_USBCON_OTGPADE |
+ ATMEGA_USBCON_VBUSTE);
+
/* turn on clocks */
(sc->sc_clocks_on) (&sc->sc_bus);
@@ -1346,125 +1334,46 @@ atmegadci_do_poll(struct usb2_bus *bus)
USB_BUS_LOCK(&sc->sc_bus);
atmegadci_interrupt_poll(sc);
- atmegadci_root_ctrl_poll(sc);
USB_BUS_UNLOCK(&sc->sc_bus);
}
/*------------------------------------------------------------------------*
* at91dci bulk support
- *------------------------------------------------------------------------*/
-static void
-atmegadci_device_bulk_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_device_bulk_close(struct usb2_xfer *xfer)
-{
- atmegadci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-atmegadci_device_bulk_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_device_bulk_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- atmegadci_setup_standard_chain(xfer);
- atmegadci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods atmegadci_device_bulk_methods =
-{
- .open = atmegadci_device_bulk_open,
- .close = atmegadci_device_bulk_close,
- .enter = atmegadci_device_bulk_enter,
- .start = atmegadci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
* at91dci control support
- *------------------------------------------------------------------------*/
-static void
-atmegadci_device_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_device_ctrl_close(struct usb2_xfer *xfer)
-{
- atmegadci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-atmegadci_device_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_device_ctrl_start(struct usb2_xfer *xfer)
-{
- /* setup TDs */
- atmegadci_setup_standard_chain(xfer);
- atmegadci_start_standard_chain(xfer);
-}
-
-struct usb2_pipe_methods atmegadci_device_ctrl_methods =
-{
- .open = atmegadci_device_ctrl_open,
- .close = atmegadci_device_ctrl_close,
- .enter = atmegadci_device_ctrl_enter,
- .start = atmegadci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-/*------------------------------------------------------------------------*
* at91dci interrupt support
*------------------------------------------------------------------------*/
static void
-atmegadci_device_intr_open(struct usb2_xfer *xfer)
+atmegadci_device_non_isoc_open(struct usb2_xfer *xfer)
{
return;
}
static void
-atmegadci_device_intr_close(struct usb2_xfer *xfer)
+atmegadci_device_non_isoc_close(struct usb2_xfer *xfer)
{
atmegadci_device_done(xfer, USB_ERR_CANCELLED);
}
static void
-atmegadci_device_intr_enter(struct usb2_xfer *xfer)
+atmegadci_device_non_isoc_enter(struct usb2_xfer *xfer)
{
return;
}
static void
-atmegadci_device_intr_start(struct usb2_xfer *xfer)
+atmegadci_device_non_isoc_start(struct usb2_xfer *xfer)
{
/* setup TDs */
atmegadci_setup_standard_chain(xfer);
atmegadci_start_standard_chain(xfer);
}
-struct usb2_pipe_methods atmegadci_device_intr_methods =
+struct usb2_pipe_methods atmegadci_device_non_isoc_methods =
{
- .open = atmegadci_device_intr_open,
- .close = atmegadci_device_intr_close,
- .enter = atmegadci_device_intr_enter,
- .start = atmegadci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
+ .open = atmegadci_device_non_isoc_open,
+ .close = atmegadci_device_non_isoc_close,
+ .enter = atmegadci_device_non_isoc_enter,
+ .start = atmegadci_device_non_isoc_start,
};
/*------------------------------------------------------------------------*
@@ -1551,38 +1460,14 @@ struct usb2_pipe_methods atmegadci_device_isoc_fs_methods =
.close = atmegadci_device_isoc_fs_close,
.enter = atmegadci_device_isoc_fs_enter,
.start = atmegadci_device_isoc_fs_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
* at91dci root control support
*------------------------------------------------------------------------*
- * simulate a hardware HUB by handling
- * all the necessary requests
+ * Simulate a hardware HUB by handling all the necessary requests.
*------------------------------------------------------------------------*/
-static void
-atmegadci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- atmegadci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/*
- * USB descriptors for the virtual Root HUB:
- */
-
static const struct usb2_device_descriptor atmegadci_devd = {
.bLength = sizeof(struct usb2_device_descriptor),
.bDescriptorType = UDESC_DEVICE,
@@ -1627,7 +1512,6 @@ static const struct atmegadci_config_desc atmegadci_confd = {
.bInterfaceSubClass = UISUBCLASS_HUB,
.bInterfaceProtocol = UIPROTO_HSHUBSTT,
},
-
.endpd = {
.bLength = sizeof(struct usb2_endpoint_descriptor),
.bDescriptorType = UDESC_ENDPOINT,
@@ -1667,45 +1551,16 @@ USB_MAKE_STRING_DESC(STRING_VENDOR, atmegadci_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, atmegadci_product);
static void
-atmegadci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_root_ctrl_start(struct usb2_xfer *xfer)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-atmegadci_root_ctrl_task(struct usb2_bus *bus)
-{
- atmegadci_root_ctrl_poll(ATMEGA_BUS2SC(bus));
-}
-
-static void
-atmegadci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
+atmegadci_roothub_exec(struct usb2_bus *bus)
{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
+ struct atmegadci_softc *sc = ATMEGA_BUS2SC(bus);
+ struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
uint16_t value;
uint16_t index;
uint8_t temp;
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- atmegadci_device_done(xfer, std->err);
- }
- goto done;
- }
/* buffer reset */
std->ptr = USB_ADD_BYTES(&sc->sc_hub_temp, 0);
std->len = 0;
@@ -1964,7 +1819,7 @@ tr_handle_clear_port_feature:
switch (value) {
case UHF_PORT_SUSPEND:
- atmegadci_wakeup_peer(xfer);
+ atmegadci_wakeup_peer(sc);
break;
case UHF_PORT_ENABLE:
@@ -2113,67 +1968,6 @@ done:
}
static void
-atmegadci_root_ctrl_poll(struct atmegadci_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &atmegadci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods atmegadci_root_ctrl_methods =
-{
- .open = atmegadci_root_ctrl_open,
- .close = atmegadci_root_ctrl_close,
- .enter = atmegadci_root_ctrl_enter,
- .start = atmegadci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-atmegadci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_root_intr_close(struct usb2_xfer *xfer)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- atmegadci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-atmegadci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-atmegadci_root_intr_start(struct usb2_xfer *xfer)
-{
- struct atmegadci_softc *sc = ATMEGA_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods atmegadci_root_intr_methods =
-{
- .open = atmegadci_root_intr_open,
- .close = atmegadci_root_intr_close,
- .enter = atmegadci_root_intr_enter,
- .start = atmegadci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
atmegadci_xfer_setup(struct usb2_setup_params *parm)
{
const struct usb2_hw_ep_profile *pf;
@@ -2201,34 +1995,21 @@ atmegadci_xfer_setup(struct usb2_setup_params *parm)
/*
* compute maximum number of TDs
*/
- if (parm->methods == &atmegadci_device_ctrl_methods) {
+ if ((xfer->pipe->edesc->bmAttributes & UE_XFERTYPE) == UE_CONTROL) {
- ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC 1 */
+ ntd = xfer->nframes + 1 /* STATUS */ + 1 /* SYNC 1 */
+ 1 /* SYNC 2 */ ;
-
- } else if (parm->methods == &atmegadci_device_bulk_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else if (parm->methods == &atmegadci_device_intr_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
- } else if (parm->methods == &atmegadci_device_isoc_fs_methods) {
-
- ntd = xfer->nframes + 1 /* SYNC */ ;
-
} else {
- ntd = 0;
+ ntd = xfer->nframes + 1 /* SYNC */ ;
}
/*
* check if "usb2_transfer_setup_sub" set an error
*/
- if (parm->err) {
+ if (parm->err)
return;
- }
+
/*
* allocate transfer descriptors
*/
@@ -2237,19 +2018,13 @@ atmegadci_xfer_setup(struct usb2_setup_params *parm)
/*
* get profile stuff
*/
- if (ntd) {
-
- ep_no = xfer->endpoint & UE_ADDR;
- atmegadci_get_hw_ep_profile(parm->udev, &pf, ep_no);
+ ep_no = xfer->endpoint & UE_ADDR;
+ atmegadci_get_hw_ep_profile(parm->udev, &pf, ep_no);
- if (pf == NULL) {
- /* should not happen */
- parm->err = USB_ERR_INVAL;
- return;
- }
- } else {
- ep_no = 0;
- pf = NULL;
+ if (pf == NULL) {
+ /* should not happen */
+ parm->err = USB_ERR_INVAL;
+ return;
}
/* align data */
@@ -2296,24 +2071,7 @@ atmegadci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *e
edesc->bEndpointAddress, udev->flags.usb2_mode,
sc->sc_rt_addr, udev->device_index);
- if (udev->device_index == sc->sc_rt_addr) {
-
- if (udev->flags.usb2_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &atmegadci_root_ctrl_methods;
- break;
- case UE_DIR_IN | ATMEGA_INTR_ENDPT:
- pipe->methods = &atmegadci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
+ if (udev->device_index != sc->sc_rt_addr) {
if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
/* not supported */
@@ -2323,23 +2081,10 @@ atmegadci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *e
/* not supported */
return;
}
- switch (edesc->bmAttributes & UE_XFERTYPE) {
- case UE_CONTROL:
- pipe->methods = &atmegadci_device_ctrl_methods;
- break;
- case UE_INTERRUPT:
- pipe->methods = &atmegadci_device_intr_methods;
- break;
- case UE_ISOCHRONOUS:
+ if ((edesc->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS)
pipe->methods = &atmegadci_device_isoc_fs_methods;
- break;
- case UE_BULK:
- pipe->methods = &atmegadci_device_bulk_methods;
- break;
- default:
- /* do nothing */
- break;
- }
+ else
+ pipe->methods = &atmegadci_device_non_isoc_methods;
}
}
@@ -2351,5 +2096,5 @@ struct usb2_bus_methods atmegadci_bus_methods =
.get_hw_ep_profile = &atmegadci_get_hw_ep_profile,
.set_stall = &atmegadci_set_stall,
.clear_stall = &atmegadci_clear_stall,
- .roothub_exec = &atmegadci_root_ctrl_task,
+ .roothub_exec = &atmegadci_roothub_exec,
};
diff --git a/sys/dev/usb/controller/atmegadci.h b/sys/dev/usb/controller/atmegadci.h
index 1e7d964..af61eeb 100644
--- a/sys/dev/usb/controller/atmegadci.h
+++ b/sys/dev/usb/controller/atmegadci.h
@@ -25,8 +25,8 @@
*/
/*
- * USB Device Port register definitions, copied from ATMEGA
- * documentation provided by ATMEL.
+ * USB Device Port register definitions, copied from ATMEGA documentation
+ * provided by ATMEL.
*/
#ifndef _ATMEGADCI_H_
@@ -34,10 +34,6 @@
#define ATMEGA_MAX_DEVICES (USB_MIN_DEVICES + 1)
-#ifndef ATMEGA_HAVE_BUS_SPACE
-#define ATMEGA_HAVE_BUS_SPACE 1
-#endif
-
#define ATMEGA_UEINT 0xF4
#define ATMEGA_UEINT_MASK(n) (1 << (n)) /* endpoint interrupt mask */
@@ -241,8 +237,6 @@ struct atmegadci_softc {
struct usb2_bus sc_bus;
union atmegadci_hub_temp sc_hub_temp;
LIST_HEAD(, usb2_xfer) sc_interrupt_list_head;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
/* must be set by by the bus interface layer */
atmegadci_clocks_t *sc_clocks_on;
@@ -251,11 +245,10 @@ struct atmegadci_softc {
struct usb2_device *sc_devices[ATMEGA_MAX_DEVICES];
struct resource *sc_irq_res;
void *sc_intr_hdl;
-#if (ATMEGA_HAVE_BUS_SPACE != 0)
struct resource *sc_io_res;
bus_space_tag_t sc_io_tag;
bus_space_handle_t sc_io_hdl;
-#endif
+
uint8_t sc_rt_addr; /* root hub address */
uint8_t sc_dv_addr; /* device address */
uint8_t sc_conf; /* root hub config */
diff --git a/sys/dev/usb/controller/atmegadci_atmelarm.c b/sys/dev/usb/controller/atmegadci_atmelarm.c
index 7cf2eb4..df305ac 100644
--- a/sys/dev/usb/controller/atmegadci_atmelarm.c
+++ b/sys/dev/usb/controller/atmegadci_atmelarm.c
@@ -26,13 +26,11 @@ __FBSDID("$FreeBSD$");
* SUCH DAMAGE.
*/
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
@@ -114,7 +112,7 @@ atmegadci_attach(device_t dev)
device_set_ivars(sc->sc_otg.sc_bus.bdev, &sc->sc_otg.sc_bus);
err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)atmegadci_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
+ NULL, (driver_intr_t *)atmegadci_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
if (err) {
sc->sc_otg.sc_intr_hdl = NULL;
goto error;
diff --git a/sys/dev/usb/controller/ehci.c b/sys/dev/usb/controller/ehci.c
index 7c873d9..8be6bec 100644
--- a/sys/dev/usb/controller/ehci.c
+++ b/sys/dev/usb/controller/ehci.c
@@ -39,7 +39,7 @@
*/
/*
- * TODO:
+ * TODO:
* 1) command failures are not recovered correctly
*/
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR ehcidebug
@@ -57,7 +56,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_transfer.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_hub.h>
@@ -67,8 +65,9 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_bus.h>
#include <dev/usb/controller/ehci.h>
-#define EHCI_BUS2SC(bus) ((ehci_softc_t *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((ehci_softc_t *)0)->sc_bus))))
+#define EHCI_BUS2SC(bus) \
+ ((ehci_softc_t *)(((uint8_t *)(bus)) - \
+ ((uint8_t *)&(((ehci_softc_t *)0)->sc_bus))))
#if USB_DEBUG
static int ehcidebug = 0;
@@ -93,17 +92,12 @@ extern struct usb2_pipe_methods ehci_device_ctrl_methods;
extern struct usb2_pipe_methods ehci_device_intr_methods;
extern struct usb2_pipe_methods ehci_device_isoc_fs_methods;
extern struct usb2_pipe_methods ehci_device_isoc_hs_methods;
-extern struct usb2_pipe_methods ehci_root_ctrl_methods;
-extern struct usb2_pipe_methods ehci_root_intr_methods;
static void ehci_do_poll(struct usb2_bus *bus);
-static void ehci_root_ctrl_poll(ehci_softc_t *sc);
static void ehci_device_done(struct usb2_xfer *xfer, usb2_error_t error);
static uint8_t ehci_check_transfer(struct usb2_xfer *xfer);
static void ehci_timeout(void *arg);
-
-static usb2_sw_transfer_func_t ehci_root_intr_done;
-static usb2_sw_transfer_func_t ehci_root_ctrl_done;
+static void ehci_root_intr(ehci_softc_t *sc);
struct ehci_std_temp {
ehci_softc_t *sc;
@@ -117,7 +111,7 @@ struct ehci_std_temp {
uint8_t shortpkt;
uint8_t auto_data_toggle;
uint8_t setup_alt_next;
- uint8_t short_frames_ok;
+ uint8_t last_frame;
};
void
@@ -1415,8 +1409,7 @@ ehci_pcd_enable(ehci_softc_t *sc)
/* acknowledge any PCD interrupt */
EOWRITE4(sc, EHCI_USBSTS, EHCI_STS_PCD);
- usb2_sw_transfer(&sc->sc_root_intr,
- &ehci_root_intr_done);
+ ehci_root_intr(sc);
}
static void
@@ -1486,8 +1479,7 @@ ehci_interrupt(ehci_softc_t *sc)
sc->sc_eintrs &= ~EHCI_STS_PCD;
EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
- usb2_sw_transfer(&sc->sc_root_intr,
- &ehci_root_intr_done);
+ ehci_root_intr(sc);
/* do not allow RHSC interrupts > 1 per second */
usb2_callout_reset(&sc->sc_tmo_pcd, hz,
@@ -1531,7 +1523,6 @@ ehci_do_poll(struct usb2_bus *bus)
USB_BUS_LOCK(&sc->sc_bus);
ehci_interrupt_poll(sc);
- ehci_root_ctrl_poll(sc);
USB_BUS_UNLOCK(&sc->sc_bus);
}
@@ -1546,10 +1537,12 @@ ehci_setup_standard_chain_sub(struct ehci_std_temp *temp)
uint32_t buf_offset;
uint32_t average;
uint32_t len_old;
+ uint32_t terminate;
uint8_t shortpkt_old;
uint8_t precompute;
- qtd_altnext = htohc32(temp->sc, EHCI_LINK_TERMINATE);
+ terminate = htohc32(temp->sc, EHCI_LINK_TERMINATE);
+ qtd_altnext = terminate;
td_alt_next = NULL;
buf_offset = 0;
shortpkt_old = temp->shortpkt;
@@ -1696,14 +1689,17 @@ restart:
precompute = 0;
/* setup alt next pointer, if any */
- if (temp->short_frames_ok) {
- if (temp->setup_alt_next) {
- td_alt_next = td_next;
- qtd_altnext = td_next->qtd_self;
- }
+ if (temp->last_frame) {
+ td_alt_next = NULL;
+ qtd_altnext = terminate;
} else {
/* we use this field internally */
td_alt_next = td_next;
+ if (temp->setup_alt_next) {
+ qtd_altnext = td_next->qtd_self;
+ } else {
+ qtd_altnext = terminate;
+ }
}
/* restore */
@@ -1730,7 +1726,7 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
xfer->address, UE_GET_ADDR(xfer->endpoint),
xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
- temp.average = xfer->max_usb2_frame_size;
+ temp.average = xfer->max_hc_frame_size;
temp.max_frame_size = xfer->max_frame_size;
temp.sc = EHCI_BUS2SC(xfer->xroot->bus);
@@ -1746,8 +1742,8 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
temp.td = NULL;
temp.td_next = td;
temp.qtd_status = 0;
+ temp.last_frame = 0;
temp.setup_alt_next = xfer->flags_int.short_frames_ok;
- temp.short_frames_ok = xfer->flags_int.short_frames_ok;
if (xfer->flags_int.control_xfr) {
if (xfer->pipe->toggle_next) {
@@ -1780,7 +1776,14 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
temp.len = xfer->frlengths[0];
temp.pc = xfer->frbuffers + 0;
temp.shortpkt = temp.len ? 1 : 0;
-
+ /* check for last frame */
+ if (xfer->nframes == 1) {
+ /* no STATUS stage yet, SETUP is last */
+ if (xfer->flags_int.control_act) {
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
+ }
+ }
ehci_setup_standard_chain_sub(&temp);
}
x = 1;
@@ -1798,7 +1801,16 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
x++;
if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
+ if (xfer->flags_int.control_xfr) {
+ /* no STATUS stage yet, DATA is last */
+ if (xfer->flags_int.control_act) {
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
+ }
+ } else {
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
+ }
}
/* keep previous data toggle and error count */
@@ -1855,6 +1867,8 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
temp.len = 0;
temp.pc = NULL;
temp.shortpkt = 0;
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
ehci_setup_standard_chain_sub(&temp);
}
@@ -1956,28 +1970,15 @@ ehci_setup_standard_chain(struct usb2_xfer *xfer, ehci_qh_t **qh_last)
}
static void
-ehci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
+ehci_root_intr(ehci_softc_t *sc)
{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
uint16_t i;
uint16_t m;
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- ehci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
/* clear any old interrupt data */
- bzero(sc->sc_hub_idata, sizeof(sc->sc_hub_idata));
+ memset(sc->sc_hub_idata, 0, sizeof(sc->sc_hub_idata));
/* set bits */
m = (sc->sc_noport + 1);
@@ -1991,8 +1992,8 @@ ehci_root_intr_done(struct usb2_xfer *xfer,
DPRINTF("port %d changed\n", i);
}
}
-done:
- return;
+ uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
+ sizeof(sc->sc_hub_idata));
}
static void
@@ -2208,8 +2209,6 @@ struct usb2_pipe_methods ehci_device_bulk_methods =
.close = ehci_device_bulk_close,
.enter = ehci_device_bulk_enter,
.start = ehci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -2251,8 +2250,6 @@ struct usb2_pipe_methods ehci_device_ctrl_methods =
.close = ehci_device_ctrl_close,
.enter = ehci_device_ctrl_enter,
.start = ehci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -2349,8 +2346,6 @@ struct usb2_pipe_methods ehci_device_intr_methods =
.close = ehci_device_intr_close,
.enter = ehci_device_intr_enter,
.start = ehci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -2634,8 +2629,6 @@ struct usb2_pipe_methods ehci_device_isoc_fs_methods =
.close = ehci_device_isoc_fs_close,
.enter = ehci_device_isoc_fs_enter,
.start = ehci_device_isoc_fs_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -2902,38 +2895,14 @@ struct usb2_pipe_methods ehci_device_isoc_hs_methods =
.close = ehci_device_isoc_hs_close,
.enter = ehci_device_isoc_hs_enter,
.start = ehci_device_isoc_hs_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
* ehci root control support
*------------------------------------------------------------------------*
- * simulate a hardware hub by handling
- * all the necessary requests
+ * Simulate a hardware hub by handling all the necessary requests.
*------------------------------------------------------------------------*/
-static void
-ehci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- ehci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/* data structures and routines
- * to emulate the root hub:
- */
-
static const
struct usb2_device_descriptor ehci_devd =
{
@@ -2974,7 +2943,6 @@ static const struct ehci_config_desc ehci_confd = {
.bmAttributes = UC_SELF_POWERED,
.bMaxPower = 0 /* max power */
},
-
.ifcd = {
.bLength = sizeof(struct usb2_interface_descriptor),
.bDescriptorType = UDESC_INTERFACE,
@@ -2984,7 +2952,6 @@ static const struct ehci_config_desc ehci_confd = {
.bInterfaceProtocol = UIPROTO_HSHUBSTT,
0
},
-
.endpd = {
.bLength = sizeof(struct usb2_endpoint_descriptor),
.bDescriptorType = UDESC_ENDPOINT,
@@ -3021,34 +2988,10 @@ ehci_disown(ehci_softc_t *sc, uint16_t index, uint8_t lowspeed)
}
static void
-ehci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_root_ctrl_start(struct usb2_xfer *xfer)
+ehci_roothub_exec(struct usb2_bus *bus)
{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- DPRINTF("\n");
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-ehci_root_ctrl_task(struct usb2_bus *bus)
-{
- ehci_root_ctrl_poll(EHCI_BUS2SC(bus));
-}
-
-static void
-ehci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
+ ehci_softc_t *sc = EHCI_BUS2SC(bus);
+ struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
char *ptr;
uint32_t port;
uint32_t v;
@@ -3059,13 +3002,6 @@ ehci_root_ctrl_done(struct usb2_xfer *xfer,
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- ehci_device_done(xfer, std->err);
- }
- goto done;
- }
/* buffer reset */
std->ptr = sc->sc_hub_desc.temp;
std->len = 0;
@@ -3168,7 +3104,7 @@ ehci_root_ctrl_done(struct usb2_xfer *xfer,
USETW(sc->sc_hub_desc.stat.wStatus, 0);
break;
case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
- if (value >= USB_MAX_DEVICES) {
+ if (value >= EHCI_MAX_DEVICES) {
std->err = USB_ERR_IOERROR;
goto done;
}
@@ -3439,67 +3375,6 @@ done:
}
static void
-ehci_root_ctrl_poll(ehci_softc_t *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &ehci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods ehci_root_ctrl_methods =
-{
- .open = ehci_root_ctrl_open,
- .close = ehci_root_ctrl_close,
- .enter = ehci_root_ctrl_enter,
- .start = ehci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * ehci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-ehci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_root_intr_close(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- ehci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ehci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ehci_root_intr_start(struct usb2_xfer *xfer)
-{
- ehci_softc_t *sc = EHCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods ehci_root_intr_methods =
-{
- .open = ehci_root_intr_open,
- .close = ehci_root_intr_close,
- .enter = ehci_root_intr_enter,
- .start = ehci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
ehci_xfer_setup(struct usb2_setup_params *parm)
{
struct usb2_page_search page_info;
@@ -3564,7 +3439,7 @@ ehci_xfer_setup(struct usb2_setup_params *parm)
nqh = 1;
nqtd = ((2 * xfer->nframes) + 1 /* STATUS */
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
+ + (xfer->max_data_length / xfer->max_hc_frame_size));
} else if (parm->methods == &ehci_device_bulk_methods) {
@@ -3577,7 +3452,7 @@ ehci_xfer_setup(struct usb2_setup_params *parm)
nqh = 1;
nqtd = ((2 * xfer->nframes)
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
+ + (xfer->max_data_length / xfer->max_hc_frame_size));
} else if (parm->methods == &ehci_device_intr_methods) {
@@ -3599,7 +3474,7 @@ ehci_xfer_setup(struct usb2_setup_params *parm)
nqh = 1;
nqtd = ((2 * xfer->nframes)
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
+ + (xfer->max_data_length / xfer->max_hc_frame_size));
} else if (parm->methods == &ehci_device_isoc_fs_methods) {
@@ -3771,19 +3646,8 @@ ehci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
/* not supported */
return;
}
- if (udev->device_index == sc->sc_addr) {
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &ehci_root_ctrl_methods;
- break;
- case UE_DIR_IN | EHCI_INTR_ENDPT:
- pipe->methods = &ehci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
+ if (udev->device_index != sc->sc_addr) {
+
if ((udev->speed != USB_SPEED_HIGH) &&
((udev->hs_hub_addr == 0) ||
(udev->hs_port_no == 0) ||
@@ -3941,5 +3805,5 @@ struct usb2_bus_methods ehci_bus_methods =
.device_resume = ehci_device_resume,
.device_suspend = ehci_device_suspend,
.set_hw_power = ehci_set_hw_power,
- .roothub_exec = ehci_root_ctrl_task,
+ .roothub_exec = ehci_roothub_exec,
};
diff --git a/sys/dev/usb/controller/ehci.h b/sys/dev/usb/controller/ehci.h
index 5b54809..0f3580f 100644
--- a/sys/dev/usb/controller/ehci.h
+++ b/sys/dev/usb/controller/ehci.h
@@ -38,9 +38,9 @@
#ifndef _EHCI_H_
#define _EHCI_H_
-#define EHCI_MAX_DEVICES USB_MAX_DEVICES
+#define EHCI_MAX_DEVICES MIN(USB_MAX_DEVICES, 128)
-/* PCI config registers */
+/* PCI config registers */
#define PCI_CBMEM 0x10 /* configuration base MEM */
#define PCI_INTERFACE_EHCI 0x20
#define PCI_USBREV 0x60 /* RO USB protocol revision */
@@ -457,8 +457,6 @@ typedef struct ehci_softc {
struct usb2_bus sc_bus; /* base device */
struct usb2_callout sc_tmo_pcd;
union ehci_hub_desc sc_hub_desc;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
struct usb2_device *sc_devices[EHCI_MAX_DEVICES];
struct resource *sc_io_res;
diff --git a/sys/dev/usb/controller/ehci_ixp4xx.c b/sys/dev/usb/controller/ehci_ixp4xx.c
index 1e0e253..672a6ee 100644
--- a/sys/dev/usb/controller/ehci_ixp4xx.c
+++ b/sys/dev/usb/controller/ehci_ixp4xx.c
@@ -32,13 +32,11 @@ __FBSDID("$FreeBSD$");
#include "opt_bus.h"
#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
@@ -190,7 +188,7 @@ ehci_ixp_attach(device_t self)
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+ NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
if (err) {
device_printf(self, "Could not setup irq, %d\n", err);
sc->sc_intr_hdl = NULL;
diff --git a/sys/dev/usb/controller/ehci_mbus.c b/sys/dev/usb/controller/ehci_mbus.c
index 66cf8cc..c508269 100644
--- a/sys/dev/usb/controller/ehci_mbus.c
+++ b/sys/dev/usb/controller/ehci_mbus.c
@@ -39,13 +39,11 @@ __FBSDID("$FreeBSD$");
#include "opt_bus.h"
#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
@@ -211,7 +209,7 @@ ehci_mbus_attach(device_t self)
MV_USB_DEVICE_UNDERFLOW);
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+ NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
if (err) {
device_printf(self, "Could not setup irq, %d\n", err);
sc->sc_intr_hdl = NULL;
diff --git a/sys/dev/usb/controller/ehci_pci.c b/sys/dev/usb/controller/ehci_pci.c
index 2f097fc..744f5f5 100644
--- a/sys/dev/usb/controller/ehci_pci.c
+++ b/sys/dev/usb/controller/ehci_pci.c
@@ -53,13 +53,11 @@ __FBSDID("$FreeBSD$");
*/
#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
@@ -339,10 +337,10 @@ ehci_pci_attach(device_t self)
#if (__FreeBSD_version >= 700031)
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+ NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
#else
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)(void *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+ (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
#endif
if (err) {
device_printf(self, "Could not setup irq, %d\n", err);
diff --git a/sys/dev/usb/controller/musb_otg.c b/sys/dev/usb/controller/musb_otg.c
index cda1a67..249b0b7 100644
--- a/sys/dev/usb/controller/musb_otg.c
+++ b/sys/dev/usb/controller/musb_otg.c
@@ -25,8 +25,8 @@
*/
/*
- * Thanks to Mentor Graphics for providing a reference driver for this
- * USB chip at their homepage.
+ * Thanks to Mentor Graphics for providing a reference driver for this USB chip
+ * at their homepage.
*/
/*
@@ -39,7 +39,6 @@
#include <dev/usb/usb.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR musbotgdebug
@@ -47,7 +46,6 @@
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_transfer.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_hub.h>
@@ -64,7 +62,7 @@
USB_P2U(&(((struct musbotg_softc *)0)->sc_bus))))
#define MUSBOTG_PC2SC(pc) \
- MUSBOTG_BUS2SC((pc)->tag_parent->info->bus)
+ MUSBOTG_BUS2SC(USB_DMATAG_TO_XROOT((pc)->tag_parent)->bus)
#if USB_DEBUG
static int musbotgdebug = 0;
@@ -81,8 +79,6 @@ struct usb2_pipe_methods musbotg_device_bulk_methods;
struct usb2_pipe_methods musbotg_device_ctrl_methods;
struct usb2_pipe_methods musbotg_device_intr_methods;
struct usb2_pipe_methods musbotg_device_isoc_methods;
-struct usb2_pipe_methods musbotg_root_ctrl_methods;
-struct usb2_pipe_methods musbotg_root_intr_methods;
static musbotg_cmd_t musbotg_setup_rx;
static musbotg_cmd_t musbotg_setup_data_rx;
@@ -92,12 +88,9 @@ static musbotg_cmd_t musbotg_data_rx;
static musbotg_cmd_t musbotg_data_tx;
static void musbotg_device_done(struct usb2_xfer *, usb2_error_t);
static void musbotg_do_poll(struct usb2_bus *);
-static void musbotg_root_ctrl_poll(struct musbotg_softc *);
static void musbotg_standard_done(struct usb2_xfer *);
static void musbotg_interrupt_poll(struct musbotg_softc *);
-
-static usb2_sw_transfer_func_t musbotg_root_intr_done;
-static usb2_sw_transfer_func_t musbotg_root_ctrl_done;
+static void musbotg_root_intr(struct musbotg_softc *);
/*
* Here is a configuration that the chip supports.
@@ -202,9 +195,8 @@ musbotg_pull_down(struct musbotg_softc *sc)
}
static void
-musbotg_wakeup_peer(struct usb2_xfer *xfer)
+musbotg_wakeup_peer(struct musbotg_softc *sc)
{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
uint8_t temp;
if (!(sc->sc_flags.status_suspend)) {
@@ -256,6 +248,8 @@ musbotg_setup_rx(struct musbotg_td *td)
* callback, hence the status stage is not complete.
*/
if (csr & MUSB2_MASK_CSR0L_DATAEND) {
+ /* do not stall at this point */
+ td->did_stall = 1;
/* wait for interrupt */
goto not_complete;
}
@@ -277,18 +271,13 @@ musbotg_setup_rx(struct musbotg_td *td)
sc->sc_ep0_busy = 0;
}
if (sc->sc_ep0_busy) {
- /* abort any ongoing transfer */
- if (!td->did_stall) {
- DPRINTFN(4, "stalling\n");
- MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
- MUSB2_MASK_CSR0L_SENDSTALL);
- td->did_stall = 1;
- }
goto not_complete;
}
if (!(csr & MUSB2_MASK_CSR0L_RXPKTRDY)) {
goto not_complete;
}
+ /* clear did stall flag */
+ td->did_stall = 0;
/* get the packet byte count */
count = MUSB2_READ_2(sc, MUSB2_REG_RXCOUNT);
@@ -296,11 +285,15 @@ musbotg_setup_rx(struct musbotg_td *td)
if (count != td->remainder) {
DPRINTFN(0, "Invalid SETUP packet "
"length, %d bytes\n", count);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+ MUSB2_MASK_CSR0L_RXPKTRDY_CLR);
goto not_complete;
}
if (count != sizeof(req)) {
DPRINTFN(0, "Unsupported SETUP packet "
"length, %d bytes\n", count);
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+ MUSB2_MASK_CSR0L_RXPKTRDY_CLR);
goto not_complete;
}
/* receive data */
@@ -329,6 +322,13 @@ musbotg_setup_rx(struct musbotg_td *td)
return (0); /* complete */
not_complete:
+ /* abort any ongoing transfer */
+ if (!td->did_stall) {
+ DPRINTFN(4, "stalling\n");
+ MUSB2_WRITE_1(sc, MUSB2_REG_TXCSRL,
+ MUSB2_MASK_CSR0L_SENDSTALL);
+ td->did_stall = 1;
+ }
return (1); /* not complete */
}
@@ -958,9 +958,7 @@ musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on)
sc->sc_flags.status_vbus = 1;
/* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &musbotg_root_intr_done);
+ musbotg_root_intr(sc);
}
} else {
if (sc->sc_flags.status_vbus) {
@@ -971,9 +969,7 @@ musbotg_vbus_interrupt(struct musbotg_softc *sc, uint8_t is_on)
sc->sc_flags.change_connect = 1;
/* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &musbotg_root_intr_done);
+ musbotg_root_intr(sc);
}
}
@@ -1067,9 +1063,7 @@ repeat:
}
}
/* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &musbotg_root_intr_done);
+ musbotg_root_intr(sc);
}
/* check for any endpoint interrupts */
@@ -1133,8 +1127,8 @@ musbotg_setup_standard_chain(struct usb2_xfer *xfer)
temp.td = NULL;
temp.td_next = xfer->td_start[0];
- temp.setup_alt_next = xfer->flags_int.short_frames_ok;
temp.offset = 0;
+ temp.setup_alt_next = xfer->flags_int.short_frames_ok;
sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
ep_no = (xfer->endpoint & UE_ADDR);
@@ -1181,7 +1175,13 @@ musbotg_setup_standard_chain(struct usb2_xfer *xfer)
x++;
if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
+ if (xfer->flags_int.control_xfr) {
+ if (xfer->flags_int.control_act) {
+ temp.setup_alt_next = 0;
+ }
+ } else {
+ temp.setup_alt_next = 0;
+ }
}
if (temp.len == 0) {
@@ -1206,23 +1206,24 @@ musbotg_setup_standard_chain(struct usb2_xfer *xfer)
}
}
- /* always setup a valid "pc" pointer for status and sync */
- temp.pc = xfer->frbuffers + 0;
-
- /* check if we should append a status stage */
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
+ /* check for control transfer */
+ if (xfer->flags_int.control_xfr) {
- /*
- * Send a DATA1 message and invert the current
- * endpoint direction.
- */
- temp.func = &musbotg_setup_status;
+ /* always setup a valid "pc" pointer for status and sync */
+ temp.pc = xfer->frbuffers + 0;
temp.len = 0;
temp.short_pkt = 0;
+ temp.setup_alt_next = 0;
- musbotg_setup_standard_chain_sub(&temp);
+ /* check if we should append a status stage */
+ if (!xfer->flags_int.control_act) {
+ /*
+ * Send a DATA1 message and invert the current
+ * endpoint direction.
+ */
+ temp.func = &musbotg_setup_status;
+ musbotg_setup_standard_chain_sub(&temp);
+ }
}
/* must have at least one frame! */
td = temp.td;
@@ -1306,31 +1307,17 @@ musbotg_start_standard_chain(struct usb2_xfer *xfer)
}
static void
-musbotg_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
+musbotg_root_intr(struct musbotg_softc *sc)
{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
DPRINTFN(8, "\n");
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- musbotg_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
/* set port bit */
sc->sc_hub_idata[0] = 0x02; /* we only have one port */
-done:
- return;
+ uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
+ sizeof(sc->sc_hub_idata));
}
static usb2_error_t
@@ -1873,7 +1860,6 @@ musbotg_do_poll(struct usb2_bus *bus)
USB_BUS_LOCK(&sc->sc_bus);
musbotg_interrupt_poll(sc);
- musbotg_root_ctrl_poll(sc);
USB_BUS_UNLOCK(&sc->sc_bus);
}
@@ -1912,8 +1898,6 @@ struct usb2_pipe_methods musbotg_device_bulk_methods =
.close = musbotg_device_bulk_close,
.enter = musbotg_device_bulk_enter,
.start = musbotg_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -1951,8 +1935,6 @@ struct usb2_pipe_methods musbotg_device_ctrl_methods =
.close = musbotg_device_ctrl_close,
.enter = musbotg_device_ctrl_enter,
.start = musbotg_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -1990,8 +1972,6 @@ struct usb2_pipe_methods musbotg_device_intr_methods =
.close = musbotg_device_intr_close,
.enter = musbotg_device_intr_enter,
.start = musbotg_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -2081,36 +2061,13 @@ struct usb2_pipe_methods musbotg_device_isoc_methods =
.close = musbotg_device_isoc_close,
.enter = musbotg_device_isoc_enter,
.start = musbotg_device_isoc_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
* musbotg root control support
*------------------------------------------------------------------------*
- * simulate a hardware HUB by handling
- * all the necessary requests
+ * Simulate a hardware HUB by handling all the necessary requests.
*------------------------------------------------------------------------*/
-static void
-musbotg_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_root_ctrl_close(struct usb2_xfer *xfer)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- musbotg_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/*
- * USB descriptors for the virtual Root HUB:
- */
static const struct usb2_device_descriptor musbotg_devd = {
.bLength = sizeof(struct usb2_device_descriptor),
@@ -2156,7 +2113,6 @@ static const struct musbotg_config_desc musbotg_confd = {
.bInterfaceSubClass = UISUBCLASS_HUB,
.bInterfaceProtocol = UIPROTO_HSHUBSTT,
},
-
.endpd = {
.bLength = sizeof(struct usb2_endpoint_descriptor),
.bDescriptorType = UDESC_ENDPOINT,
@@ -2197,44 +2153,15 @@ USB_MAKE_STRING_DESC(STRING_VENDOR, musbotg_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, musbotg_product);
static void
-musbotg_root_ctrl_enter(struct usb2_xfer *xfer)
+musbotg_roothub_exec(struct usb2_bus *bus)
{
- return;
-}
-
-static void
-musbotg_root_ctrl_start(struct usb2_xfer *xfer)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-musbotg_root_ctrl_task(struct usb2_bus *bus)
-{
- musbotg_root_ctrl_poll(MUSBOTG_BUS2SC(bus));
-}
-
-static void
-musbotg_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
+ struct musbotg_softc *sc = MUSBOTG_BUS2SC(bus);
+ struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
uint16_t value;
uint16_t index;
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- musbotg_device_done(xfer, std->err);
- }
- goto done;
- }
/* buffer reset */
std->ptr = USB_ADD_BYTES(&sc->sc_hub_temp, 0);
std->len = 0;
@@ -2493,7 +2420,7 @@ tr_handle_clear_port_feature:
switch (value) {
case UHF_PORT_SUSPEND:
- musbotg_wakeup_peer(xfer);
+ musbotg_wakeup_peer(sc);
break;
case UHF_PORT_ENABLE:
@@ -2620,67 +2547,6 @@ done:
}
static void
-musbotg_root_ctrl_poll(struct musbotg_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &musbotg_root_ctrl_done);
-}
-
-struct usb2_pipe_methods musbotg_root_ctrl_methods =
-{
- .open = musbotg_root_ctrl_open,
- .close = musbotg_root_ctrl_close,
- .enter = musbotg_root_ctrl_enter,
- .start = musbotg_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * musbotg root interrupt support
- *------------------------------------------------------------------------*/
-static void
-musbotg_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_root_intr_close(struct usb2_xfer *xfer)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- musbotg_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-musbotg_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-musbotg_root_intr_start(struct usb2_xfer *xfer)
-{
- struct musbotg_softc *sc = MUSBOTG_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods musbotg_root_intr_methods =
-{
- .open = musbotg_root_intr_open,
- .close = musbotg_root_intr_close,
- .enter = musbotg_root_intr_enter,
- .start = musbotg_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
musbotg_xfer_setup(struct usb2_setup_params *parm)
{
const struct usb2_hw_ep_profile *pf;
@@ -2804,24 +2670,7 @@ musbotg_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *ede
edesc->bEndpointAddress, udev->flags.usb2_mode,
sc->sc_rt_addr);
- if (udev->device_index == sc->sc_rt_addr) {
-
- if (udev->flags.usb2_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &musbotg_root_ctrl_methods;
- break;
- case UE_DIR_IN | MUSBOTG_INTR_ENDPT:
- pipe->methods = &musbotg_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
+ if (udev->device_index != sc->sc_rt_addr) {
if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
/* not supported */
@@ -2860,5 +2709,5 @@ struct usb2_bus_methods musbotg_bus_methods =
.get_hw_ep_profile = &musbotg_get_hw_ep_profile,
.set_stall = &musbotg_set_stall,
.clear_stall = &musbotg_clear_stall,
- .roothub_exec = &musbotg_root_ctrl_task,
+ .roothub_exec = &musbotg_roothub_exec,
};
diff --git a/sys/dev/usb/controller/musb_otg.h b/sys/dev/usb/controller/musb_otg.h
index 0d880e1..2dd2ce3 100644
--- a/sys/dev/usb/controller/musb_otg.h
+++ b/sys/dev/usb/controller/musb_otg.h
@@ -25,8 +25,8 @@
*/
/*
- * This header file defines the registers of the Mentor Graphics
- * USB OnTheGo Inventra chip.
+ * This header file defines the registers of the Mentor Graphics USB OnTheGo
+ * Inventra chip.
*/
#ifndef _MUSB2_OTG_H_
@@ -363,8 +363,6 @@ struct musbotg_flags {
struct musbotg_softc {
struct usb2_bus sc_bus;
union musbotg_hub_temp sc_hub_temp;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
struct usb2_hw_ep_profile sc_hw_ep_profile[16];
struct usb2_device *sc_devices[MUSB2_MAX_DEVICES];
diff --git a/sys/dev/usb/controller/musb_otg_atmelarm.c b/sys/dev/usb/controller/musb_otg_atmelarm.c
index 3ee5cfb..2589287 100644
--- a/sys/dev/usb/controller/musb_otg_atmelarm.c
+++ b/sys/dev/usb/controller/musb_otg_atmelarm.c
@@ -25,13 +25,11 @@
*/
#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
@@ -131,10 +129,10 @@ musbotg_attach(device_t dev)
#if (__FreeBSD_version >= 700031)
err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
+ NULL, (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
#else
err = bus_setup_intr(dev, sc->sc_otg.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
+ (driver_intr_t *)musbotg_interrupt, sc, &sc->sc_otg.sc_intr_hdl);
#endif
if (err) {
sc->sc_otg.sc_intr_hdl = NULL;
diff --git a/sys/dev/usb/controller/ohci.c b/sys/dev/usb/controller/ohci.c
index ad2b1cc..fc05ece 100644
--- a/sys/dev/usb/controller/ohci.c
+++ b/sys/dev/usb/controller/ohci.c
@@ -32,13 +32,12 @@ __FBSDID("$FreeBSD$");
* USB Open Host Controller driver.
*
* OHCI spec: http://www.compaq.com/productinfo/development/openhci.html
- * USB spec: http://www.usb.org/developers/docs/usbspec.zip
+ * USB spec: http://www.usb.org/developers/docs/usbspec.zip
*/
#include <dev/usb/usb.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR ohcidebug
@@ -46,7 +45,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_transfer.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_hub.h>
@@ -56,8 +54,9 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_bus.h>
#include <dev/usb/controller/ohci.h>
-#define OHCI_BUS2SC(bus) ((ohci_softc_t *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((ohci_softc_t *)0)->sc_bus))))
+#define OHCI_BUS2SC(bus) \
+ ((ohci_softc_t *)(((uint8_t *)(bus)) - \
+ ((uint8_t *)&(((ohci_softc_t *)0)->sc_bus))))
#if USB_DEBUG
static int ohcidebug = 0;
@@ -93,17 +92,12 @@ extern struct usb2_pipe_methods ohci_device_bulk_methods;
extern struct usb2_pipe_methods ohci_device_ctrl_methods;
extern struct usb2_pipe_methods ohci_device_intr_methods;
extern struct usb2_pipe_methods ohci_device_isoc_methods;
-extern struct usb2_pipe_methods ohci_root_ctrl_methods;
-extern struct usb2_pipe_methods ohci_root_intr_methods;
-static void ohci_root_ctrl_poll(struct ohci_softc *sc);
static void ohci_do_poll(struct usb2_bus *bus);
static void ohci_device_done(struct usb2_xfer *xfer, usb2_error_t error);
-
-static usb2_sw_transfer_func_t ohci_root_intr_done;
-static usb2_sw_transfer_func_t ohci_root_ctrl_done;
static void ohci_timeout(void *arg);
static uint8_t ohci_check_transfer(struct usb2_xfer *xfer);
+static void ohci_root_intr(ohci_softc_t *sc);
struct ohci_std_temp {
struct usb2_page_cache *pc;
@@ -115,7 +109,7 @@ struct ohci_std_temp {
uint16_t max_frame_size;
uint8_t shortpkt;
uint8_t setup_alt_next;
- uint8_t short_frames_ok;
+ uint8_t last_frame;
};
static struct ohci_hcca *
@@ -1020,6 +1014,23 @@ ohci_check_transfer_sub(struct usb2_xfer *xfer)
usb2_pc_cpu_flush(ed->page_cache);
DPRINTFN(13, "xfer=%p following alt next\n", xfer);
+
+ /*
+ * Make sure that the OHCI re-scans the schedule by
+ * writing the BLF and CLF bits:
+ */
+
+ if (xfer->xroot->udev->pwr_save.suspended) {
+ /* nothing to do */
+ } else if (xfer->pipe->methods == &ohci_device_bulk_methods) {
+ ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
+
+ OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
+ } else if (xfer->pipe->methods == &ohci_device_ctrl_methods) {
+ ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
+
+ OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
+ }
}
}
@@ -1034,7 +1045,6 @@ static uint8_t
ohci_check_transfer(struct usb2_xfer *xfer)
{
ohci_ed_t *ed;
- uint32_t ed_flags;
uint32_t ed_headp;
uint32_t ed_tailp;
@@ -1043,12 +1053,10 @@ ohci_check_transfer(struct usb2_xfer *xfer)
ed = xfer->qh_start[xfer->flags_int.curr_dma_set];
usb2_pc_cpu_invalidate(ed->page_cache);
- ed_flags = le32toh(ed->ed_flags);
ed_headp = le32toh(ed->ed_headp);
ed_tailp = le32toh(ed->ed_tailp);
- if ((ed_flags & OHCI_ED_SKIP) ||
- (ed_headp & OHCI_HALTED) ||
+ if ((ed_headp & OHCI_HALTED) ||
(((ed_headp ^ ed_tailp) & (~0xF)) == 0)) {
if (xfer->pipe->methods == &ohci_device_isoc_methods) {
/* isochronous transfer */
@@ -1090,8 +1098,7 @@ ohci_rhsc_enable(ohci_softc_t *sc)
/* acknowledge any RHSC interrupt */
OWRITE4(sc, OHCI_INTERRUPT_STATUS, OHCI_RHSC);
- usb2_sw_transfer(&sc->sc_root_intr,
- &ohci_root_intr_done);
+ ohci_root_intr(sc);
}
static void
@@ -1205,8 +1212,7 @@ ohci_interrupt(ohci_softc_t *sc)
sc->sc_eintrs &= ~OHCI_RHSC;
OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_RHSC);
- usb2_sw_transfer(&sc->sc_root_intr,
- &ohci_root_intr_done);
+ ohci_root_intr(sc);
/* do not allow RHSC interrupts > 1 per second */
usb2_callout_reset(&sc->sc_tmo_rhsc, hz,
@@ -1251,7 +1257,6 @@ ohci_do_poll(struct usb2_bus *bus)
USB_BUS_LOCK(&sc->sc_bus);
ohci_interrupt_poll(sc);
- ohci_root_ctrl_poll(sc);
USB_BUS_UNLOCK(&sc->sc_bus);
}
@@ -1336,9 +1341,12 @@ restart:
temp->td_flags &= ~htole32(OHCI_TD_TOGGLE_MASK);
if (average == 0) {
-
+ /*
+ * The buffer start and end phys addresses should be
+ * 0x0 for a zero length packet.
+ */
td->td_cbp = 0;
- td->td_be = ~0;
+ td->td_be = 0;
td->len = 0;
} else {
@@ -1379,10 +1387,9 @@ restart:
precompute = 0;
/* setup alt next pointer, if any */
- if (temp->short_frames_ok) {
- if (temp->setup_alt_next) {
- td_alt_next = td_next;
- }
+ if (temp->last_frame) {
+ /* no alternate next */
+ td_alt_next = NULL;
} else {
/* we use this field internally */
td_alt_next = td_next;
@@ -1411,7 +1418,7 @@ ohci_setup_standard_chain(struct usb2_xfer *xfer, ohci_ed_t **ed_last)
xfer->address, UE_GET_ADDR(xfer->endpoint),
xfer->sumlen, usb2_get_speed(xfer->xroot->udev));
- temp.average = xfer->max_usb2_frame_size;
+ temp.average = xfer->max_hc_frame_size;
temp.max_frame_size = xfer->max_frame_size;
/* toggle the DMA set we are using */
@@ -1425,8 +1432,8 @@ ohci_setup_standard_chain(struct usb2_xfer *xfer, ohci_ed_t **ed_last)
temp.td = NULL;
temp.td_next = td;
+ temp.last_frame = 0;
temp.setup_alt_next = xfer->flags_int.short_frames_ok;
- temp.short_frames_ok = xfer->flags_int.short_frames_ok;
methods = xfer->pipe->methods;
@@ -1441,7 +1448,14 @@ ohci_setup_standard_chain(struct usb2_xfer *xfer, ohci_ed_t **ed_last)
temp.len = xfer->frlengths[0];
temp.pc = xfer->frbuffers + 0;
temp.shortpkt = temp.len ? 1 : 0;
-
+ /* check for last frame */
+ if (xfer->nframes == 1) {
+ /* no STATUS stage yet, SETUP is last */
+ if (xfer->flags_int.control_act) {
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
+ }
+ }
ohci_setup_standard_chain_sub(&temp);
/*
@@ -1482,7 +1496,16 @@ ohci_setup_standard_chain(struct usb2_xfer *xfer, ohci_ed_t **ed_last)
x++;
if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
+ if (xfer->flags_int.control_xfr) {
+ /* no STATUS stage yet, DATA is last */
+ if (xfer->flags_int.control_act) {
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
+ }
+ } else {
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
+ }
}
if (temp.len == 0) {
@@ -1523,11 +1546,14 @@ ohci_setup_standard_chain(struct usb2_xfer *xfer, ohci_ed_t **ed_last)
temp.len = 0;
temp.pc = NULL;
temp.shortpkt = 0;
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
ohci_setup_standard_chain_sub(&temp);
}
td = temp.td;
+ /* Ensure that last TD is terminating: */
td->td_next = htole32(OHCI_TD_NEXT_END);
td->td_flags &= ~htole32(OHCI_TD_INTR_MASK);
td->td_flags |= htole32(OHCI_TD_SET_DI(1));
@@ -1583,33 +1609,20 @@ ohci_setup_standard_chain(struct usb2_xfer *xfer, ohci_ed_t **ed_last)
}
static void
-ohci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
+ohci_root_intr(ohci_softc_t *sc)
{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
uint32_t hstatus;
uint16_t i;
uint16_t m;
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- ohci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
/* clear any old interrupt data */
- bzero(sc->sc_hub_idata, sizeof(sc->sc_hub_idata));
+ memset(sc->sc_hub_idata, 0, sizeof(sc->sc_hub_idata));
hstatus = OREAD4(sc, OHCI_RH_STATUS);
- DPRINTF("sc=%p xfer=%p hstatus=0x%08x\n",
- sc, xfer, hstatus);
+ DPRINTF("sc=%p hstatus=0x%08x\n",
+ sc, hstatus);
/* set bits */
m = (sc->sc_noport + 1);
@@ -1623,8 +1636,9 @@ ohci_root_intr_done(struct usb2_xfer *xfer,
DPRINTF("port %d changed\n", i);
}
}
-done:
- return;
+
+ uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
+ sizeof(sc->sc_hub_idata));
}
/* NOTE: "done" can be run two times in a row,
@@ -1705,8 +1719,6 @@ struct usb2_pipe_methods ohci_device_bulk_methods =
.close = ohci_device_bulk_close,
.enter = ohci_device_bulk_enter,
.start = ohci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -1748,8 +1760,6 @@ struct usb2_pipe_methods ohci_device_ctrl_methods =
.close = ohci_device_ctrl_close,
.enter = ohci_device_ctrl_enter,
.start = ohci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -1822,8 +1832,6 @@ struct usb2_pipe_methods ohci_device_intr_methods =
.close = ohci_device_intr_close,
.enter = ohci_device_intr_enter,
.start = ohci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -2032,37 +2040,14 @@ struct usb2_pipe_methods ohci_device_isoc_methods =
.close = ohci_device_isoc_close,
.enter = ohci_device_isoc_enter,
.start = ohci_device_isoc_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
* ohci root control support
*------------------------------------------------------------------------*
- * simulate a hardware hub by handling
- * all the necessary requests
+ * Simulate a hardware hub by handling all the necessary requests.
*------------------------------------------------------------------------*/
-static void
-ohci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- ohci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/* data structures and routines
- * to emulate the root hub:
- */
static const
struct usb2_device_descriptor ohci_devd =
{
@@ -2091,7 +2076,6 @@ struct ohci_config_desc ohci_confd =
.bmAttributes = UC_SELF_POWERED,
.bMaxPower = 0, /* max power */
},
-
.ifcd = {
.bLength = sizeof(struct usb2_interface_descriptor),
.bDescriptorType = UDESC_INTERFACE,
@@ -2100,7 +2084,6 @@ struct ohci_config_desc ohci_confd =
.bInterfaceSubClass = UISUBCLASS_HUB,
.bInterfaceProtocol = UIPROTO_FSHUB,
},
-
.endpd = {
.bLength = sizeof(struct usb2_endpoint_descriptor),
.bDescriptorType = UDESC_ENDPOINT,
@@ -2124,32 +2107,10 @@ struct usb2_hub_descriptor ohci_hubd =
};
static void
-ohci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_root_ctrl_start(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-ohci_root_ctrl_task(struct usb2_bus *bus)
-{
- ohci_root_ctrl_poll(OHCI_BUS2SC(bus));
-}
-
-static void
-ohci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
+ohci_roothub_exec(struct usb2_bus *bus)
{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
+ ohci_softc_t *sc = OHCI_BUS2SC(bus);
+ struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
char *ptr;
uint32_t port;
uint32_t v;
@@ -2159,13 +2120,6 @@ ohci_root_ctrl_done(struct usb2_xfer *xfer,
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- ohci_device_done(xfer, std->err);
- }
- goto done;
- }
/* buffer reset */
std->ptr = sc->sc_hub_desc.temp;
std->len = 0;
@@ -2256,7 +2210,7 @@ ohci_root_ctrl_done(struct usb2_xfer *xfer,
USETW(sc->sc_hub_desc.stat.wStatus, 0);
break;
case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
- if (value >= USB_MAX_DEVICES) {
+ if (value >= OHCI_MAX_DEVICES) {
std->err = USB_ERR_IOERROR;
goto done;
}
@@ -2439,67 +2393,6 @@ done:
}
static void
-ohci_root_ctrl_poll(struct ohci_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &ohci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods ohci_root_ctrl_methods =
-{
- .open = ohci_root_ctrl_open,
- .close = ohci_root_ctrl_close,
- .enter = ohci_root_ctrl_enter,
- .start = ohci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * ohci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-ohci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_root_intr_close(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- ohci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-ohci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-ohci_root_intr_start(struct usb2_xfer *xfer)
-{
- ohci_softc_t *sc = OHCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods ohci_root_intr_methods =
-{
- .open = ohci_root_intr_open,
- .close = ohci_root_intr_close,
- .enter = ohci_root_intr_enter,
- .start = ohci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
ohci_xfer_setup(struct usb2_setup_params *parm)
{
struct usb2_page_search page_info;
@@ -2529,7 +2422,7 @@ ohci_xfer_setup(struct usb2_setup_params *parm)
nitd = 0;
ntd = ((2 * xfer->nframes) + 1 /* STATUS */
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
+ + (xfer->max_data_length / xfer->max_hc_frame_size));
nqh = 1;
} else if (parm->methods == &ohci_device_bulk_methods) {
@@ -2539,7 +2432,7 @@ ohci_xfer_setup(struct usb2_setup_params *parm)
nitd = 0;
ntd = ((2 * xfer->nframes)
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
+ + (xfer->max_data_length / xfer->max_hc_frame_size));
nqh = 1;
} else if (parm->methods == &ohci_device_intr_methods) {
@@ -2549,7 +2442,7 @@ ohci_xfer_setup(struct usb2_setup_params *parm)
nitd = 0;
ntd = ((2 * xfer->nframes)
- + (xfer->max_data_length / xfer->max_usb2_frame_size));
+ + (xfer->max_data_length / xfer->max_hc_frame_size));
nqh = 1;
} else if (parm->methods == &ohci_device_isoc_methods) {
@@ -2678,19 +2571,7 @@ ohci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
/* not supported */
return;
}
- if (udev->device_index == sc->sc_addr) {
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &ohci_root_ctrl_methods;
- break;
- case UE_DIR_IN | OHCI_INTR_ENDPT:
- pipe->methods = &ohci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
+ if (udev->device_index != sc->sc_addr) {
switch (edesc->bmAttributes & UE_XFERTYPE) {
case UE_CONTROL:
pipe->methods = &ohci_device_ctrl_methods;
@@ -2849,5 +2730,5 @@ struct usb2_bus_methods ohci_bus_methods =
.device_resume = ohci_device_resume,
.device_suspend = ohci_device_suspend,
.set_hw_power = ohci_set_hw_power,
- .roothub_exec = ohci_root_ctrl_task,
+ .roothub_exec = ohci_roothub_exec,
};
diff --git a/sys/dev/usb/controller/ohci.h b/sys/dev/usb/controller/ohci.h
index 84a6afd..322324a 100644
--- a/sys/dev/usb/controller/ohci.h
+++ b/sys/dev/usb/controller/ohci.h
@@ -39,9 +39,9 @@
#ifndef _OHCI_H_
#define _OHCI_H_
-#define OHCI_MAX_DEVICES USB_MAX_DEVICES
+#define OHCI_MAX_DEVICES MIN(USB_MAX_DEVICES, 128)
-/* PCI config registers */
+/* PCI config registers */
#define PCI_CBMEM 0x10 /* configuration base memory */
#define PCI_INTERFACE_OHCI 0x10
@@ -322,8 +322,6 @@ typedef struct ohci_softc {
struct usb2_bus sc_bus; /* base device */
struct usb2_callout sc_tmo_rhsc;
union ohci_hub_desc sc_hub_desc;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
struct usb2_device *sc_devices[OHCI_MAX_DEVICES];
struct resource *sc_io_res;
diff --git a/sys/dev/usb/controller/ohci_atmelarm.c b/sys/dev/usb/controller/ohci_atmelarm.c
index 562cf3d..0f213c5 100644
--- a/sys/dev/usb/controller/ohci_atmelarm.c
+++ b/sys/dev/usb/controller/ohci_atmelarm.c
@@ -26,13 +26,11 @@
__FBSDID("$FreeBSD$");
#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
@@ -112,10 +110,10 @@ ohci_atmelarm_attach(device_t dev)
#if (__FreeBSD_version >= 700031)
err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)ohci_interrupt, sc, &sc->sc_ohci.sc_intr_hdl);
+ NULL, (driver_intr_t *)ohci_interrupt, sc, &sc->sc_ohci.sc_intr_hdl);
#else
err = bus_setup_intr(dev, sc->sc_ohci.sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)ohci_interrupt, sc, &sc->sc_ohci.sc_intr_hdl);
+ (driver_intr_t *)ohci_interrupt, sc, &sc->sc_ohci.sc_intr_hdl);
#endif
if (err) {
sc->sc_ohci.sc_intr_hdl = NULL;
diff --git a/sys/dev/usb/controller/ohci_pci.c b/sys/dev/usb/controller/ohci_pci.c
index c9f586d..031be52 100644
--- a/sys/dev/usb/controller/ohci_pci.c
+++ b/sys/dev/usb/controller/ohci_pci.c
@@ -52,12 +52,10 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
@@ -290,10 +288,10 @@ ohci_pci_attach(device_t self)
#if (__FreeBSD_version >= 700031)
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)(void *)ohci_interrupt, sc, &sc->sc_intr_hdl);
+ NULL, (driver_intr_t *)ohci_interrupt, sc, &sc->sc_intr_hdl);
#else
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)(void *)ohci_interrupt, sc, &sc->sc_intr_hdl);
+ (driver_intr_t *)ohci_interrupt, sc, &sc->sc_intr_hdl);
#endif
if (err) {
device_printf(self, "Could not setup irq, %d\n", err);
diff --git a/sys/dev/usb/controller/uhci.c b/sys/dev/usb/controller/uhci.c
index 82a9623..bc32557 100644
--- a/sys/dev/usb/controller/uhci.c
+++ b/sys/dev/usb/controller/uhci.c
@@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$");
* Handles e.g. PIIX3 and PIIX4.
*
* UHCI spec: http://developer.intel.com/design/USB/UHCI11D.htm
- * USB spec: http://www.usb.org/developers/docs/usbspec.zip
+ * USB spec: http://www.usb.org/developers/docs/usbspec.zip
* PIIXn spec: ftp://download.intel.com/design/intarch/datashts/29055002.pdf
* ftp://download.intel.com/design/intarch/datashts/29056201.pdf
*/
@@ -41,7 +41,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR uhcidebug
@@ -49,7 +48,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_transfer.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_hub.h>
@@ -60,8 +58,9 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/controller/uhci.h>
#define alt_next next
-#define UHCI_BUS2SC(bus) ((uhci_softc_t *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((uhci_softc_t *)0)->sc_bus))))
+#define UHCI_BUS2SC(bus) \
+ ((uhci_softc_t *)(((uint8_t *)(bus)) - \
+ ((uint8_t *)&(((uhci_softc_t *)0)->sc_bus))))
#if USB_DEBUG
static int uhcidebug = 0;
@@ -124,7 +123,7 @@ struct uhci_std_temp {
uint16_t max_frame_size;
uint8_t shortpkt;
uint8_t setup_alt_next;
- uint8_t short_frames_ok;
+ uint8_t last_frame;
};
extern struct usb2_bus_methods uhci_bus_methods;
@@ -132,16 +131,13 @@ extern struct usb2_pipe_methods uhci_device_bulk_methods;
extern struct usb2_pipe_methods uhci_device_ctrl_methods;
extern struct usb2_pipe_methods uhci_device_intr_methods;
extern struct usb2_pipe_methods uhci_device_isoc_methods;
-extern struct usb2_pipe_methods uhci_root_ctrl_methods;
-extern struct usb2_pipe_methods uhci_root_intr_methods;
-static void uhci_root_ctrl_poll(struct uhci_softc *);
static void uhci_do_poll(struct usb2_bus *);
static void uhci_device_done(struct usb2_xfer *, usb2_error_t);
static void uhci_transfer_intr_enqueue(struct usb2_xfer *);
-static void uhci_root_intr_check(void *);
static void uhci_timeout(void *);
static uint8_t uhci_check_transfer(struct usb2_xfer *);
+static void uhci_root_intr(uhci_softc_t *sc);
void
uhci_iterate_hw_softc(struct usb2_bus *bus, usb2_bus_mem_sub_cb_t *cb)
@@ -317,6 +313,13 @@ done_2:
UWRITE4(sc, UHCI_FLBASEADDR, buf_res.physaddr);
UWRITE2(sc, UHCI_FRNUM, sc->sc_saved_frnum);
UWRITE1(sc, UHCI_SOF, sc->sc_saved_sof);
+
+ USB_BUS_UNLOCK(&sc->sc_bus);
+
+ /* stop root interrupt */
+ usb2_callout_drain(&sc->sc_root_intr);
+
+ USB_BUS_LOCK(&sc->sc_bus);
}
static void
@@ -358,7 +361,8 @@ uhci_start(uhci_softc_t *sc)
"cannot start HC controller\n");
done:
- return;
+ /* start root interrupt */
+ uhci_root_intr(sc);
}
static struct uhci_qh *
@@ -408,12 +412,13 @@ uhci_init(uhci_softc_t *sc)
DPRINTF("start\n");
+ usb2_callout_init_mtx(&sc->sc_root_intr, &sc->sc_bus.bus_mtx, 0);
+
#if USB_DEBUG
if (uhcidebug > 2) {
uhci_dumpregs(sc);
}
#endif
-
sc->sc_saved_sof = 0x40; /* default value */
sc->sc_saved_frnum = 0; /* default frame number */
@@ -1253,30 +1258,33 @@ uhci_check_transfer_sub(struct usb2_xfer *xfer)
td_self = td->td_self;
td_alt_next = td->alt_next;
- if ((td->td_token ^ td_token) & htole32(UHCI_TD_SET_DT(1))) {
+ if (xfer->flags_int.control_xfr)
+ goto skip; /* don't touch the DT value! */
- /*
- * The data toggle is wrong and
- * we need to switch it !
- */
+ if (!((td->td_token ^ td_token) & htole32(UHCI_TD_SET_DT(1))))
+ goto skip; /* data toggle has correct value */
- while (1) {
+ /*
+ * The data toggle is wrong and we need to toggle it !
+ */
+ while (1) {
- td->td_token ^= htole32(UHCI_TD_SET_DT(1));
- usb2_pc_cpu_flush(td->page_cache);
+ td->td_token ^= htole32(UHCI_TD_SET_DT(1));
+ usb2_pc_cpu_flush(td->page_cache);
- if (td == xfer->td_transfer_last) {
- /* last transfer */
- break;
- }
- td = td->obj_next;
+ if (td == xfer->td_transfer_last) {
+ /* last transfer */
+ break;
+ }
+ td = td->obj_next;
- if (td->alt_next != td_alt_next) {
- /* next frame */
- break;
- }
+ if (td->alt_next != td_alt_next) {
+ /* next frame */
+ break;
}
}
+skip:
+
/* update the QH */
qh->qh_e_next = td_self;
usb2_pc_cpu_flush(qh->page_cache);
@@ -1502,7 +1510,6 @@ uhci_do_poll(struct usb2_bus *bus)
USB_BUS_LOCK(&sc->sc_bus);
uhci_interrupt_poll(sc);
- uhci_root_ctrl_poll(sc);
USB_BUS_UNLOCK(&sc->sc_bus);
}
@@ -1631,10 +1638,8 @@ restart:
precompute = 0;
/* setup alt next pointer, if any */
- if (temp->short_frames_ok) {
- if (temp->setup_alt_next) {
- td_alt_next = td_next;
- }
+ if (temp->last_frame) {
+ td_alt_next = NULL;
} else {
/* we use this field internally */
td_alt_next = td_next;
@@ -1673,8 +1678,8 @@ uhci_setup_standard_chain(struct usb2_xfer *xfer)
temp.td = NULL;
temp.td_next = td;
+ temp.last_frame = 0;
temp.setup_alt_next = xfer->flags_int.short_frames_ok;
- temp.short_frames_ok = xfer->flags_int.short_frames_ok;
uhci_mem_layout_init(&temp.ml, xfer);
@@ -1707,7 +1712,14 @@ uhci_setup_standard_chain(struct usb2_xfer *xfer)
temp.len = xfer->frlengths[0];
temp.ml.buf_pc = xfer->frbuffers + 0;
temp.shortpkt = temp.len ? 1 : 0;
-
+ /* check for last frame */
+ if (xfer->nframes == 1) {
+ /* no STATUS stage yet, SETUP is last */
+ if (xfer->flags_int.control_act) {
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
+ }
+ }
uhci_setup_standard_chain_sub(&temp);
}
x = 1;
@@ -1725,7 +1737,16 @@ uhci_setup_standard_chain(struct usb2_xfer *xfer)
x++;
if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
+ if (xfer->flags_int.control_xfr) {
+ /* no STATUS stage yet, DATA is last */
+ if (xfer->flags_int.control_act) {
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
+ }
+ } else {
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
+ }
}
/*
* Keep previous data toggle,
@@ -1780,11 +1801,14 @@ uhci_setup_standard_chain(struct usb2_xfer *xfer)
temp.len = 0;
temp.ml.buf_pc = NULL;
temp.shortpkt = 0;
+ temp.last_frame = 1;
+ temp.setup_alt_next = 0;
uhci_setup_standard_chain_sub(&temp);
}
td = temp.td;
+ /* Ensure that last TD is terminating: */
td->td_next = htole32(UHCI_PTR_T);
/* set interrupt bit */
@@ -1915,8 +1939,6 @@ struct usb2_pipe_methods uhci_device_bulk_methods =
.close = uhci_device_bulk_close,
.enter = uhci_device_bulk_enter,
.start = uhci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -1979,8 +2001,6 @@ struct usb2_pipe_methods uhci_device_ctrl_methods =
.close = uhci_device_ctrl_close,
.enter = uhci_device_ctrl_enter,
.start = uhci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -2070,8 +2090,6 @@ struct usb2_pipe_methods uhci_device_intr_methods =
.close = uhci_device_intr_close,
.enter = uhci_device_intr_enter,
.start = uhci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -2280,38 +2298,14 @@ struct usb2_pipe_methods uhci_device_isoc_methods =
.close = uhci_device_isoc_close,
.enter = uhci_device_isoc_enter,
.start = uhci_device_isoc_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
* uhci root control support
*------------------------------------------------------------------------*
- * simulate a hardware hub by handling
- * all the necessary requests
+ * Simulate a hardware hub by handling all the necessary requests.
*------------------------------------------------------------------------*/
-static void
-uhci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- uhci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/* data structures and routines
- * to emulate the root hub:
- */
-
static const
struct usb2_device_descriptor uhci_devd =
{
@@ -2338,7 +2332,6 @@ static const struct uhci_config_desc uhci_confd = {
.bmAttributes = UC_SELF_POWERED,
.bMaxPower = 0 /* max power */
},
-
.ifcd = {
.bLength = sizeof(struct usb2_interface_descriptor),
.bDescriptorType = UDESC_INTERFACE,
@@ -2347,7 +2340,6 @@ static const struct uhci_config_desc uhci_confd = {
.bInterfaceSubClass = UISUBCLASS_HUB,
.bInterfaceProtocol = UIPROTO_FSHUB,
},
-
.endpd = {
.bLength = sizeof(struct usb2_endpoint_descriptor),
.bDescriptorType = UDESC_ENDPOINT,
@@ -2491,34 +2483,10 @@ done:
}
static void
-uhci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_root_ctrl_start(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- DPRINTF("\n");
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-uhci_root_ctrl_task(struct usb2_bus *bus)
-{
- uhci_root_ctrl_poll(UHCI_BUS2SC(bus));
-}
-
-static void
-uhci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
+uhci_roothub_exec(struct usb2_bus *bus)
{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
+ uhci_softc_t *sc = UHCI_BUS2SC(bus);
+ struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
char *ptr;
uint16_t x;
uint16_t port;
@@ -2529,13 +2497,6 @@ uhci_root_ctrl_done(struct usb2_xfer *xfer,
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- uhci_device_done(xfer, std->err);
- }
- goto done;
- }
/* buffer reset */
std->ptr = sc->sc_hub_desc.temp;
std->len = 0;
@@ -2626,7 +2587,7 @@ uhci_root_ctrl_done(struct usb2_xfer *xfer,
USETW(sc->sc_hub_desc.stat.wStatus, 0);
break;
case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
- if (value >= USB_MAX_DEVICES) {
+ if (value >= UHCI_MAX_DEVICES) {
std->err = USB_ERR_IOERROR;
goto done;
}
@@ -2836,92 +2797,13 @@ done:
return;
}
-static void
-uhci_root_ctrl_poll(struct uhci_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &uhci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods uhci_root_ctrl_methods =
-{
- .open = uhci_root_ctrl_open,
- .close = uhci_root_ctrl_close,
- .enter = uhci_root_ctrl_enter,
- .start = uhci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * uhci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-uhci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_root_intr_close(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- uhci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uhci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uhci_root_intr_start(struct usb2_xfer *xfer)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-
- usb2_transfer_timeout_ms(xfer,
- &uhci_root_intr_check, xfer->interval);
-}
-
-static void
-uhci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
-{
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
- USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
-
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer is transferred */
- uhci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-done:
- return;
-}
-
/*
- * this routine is executed periodically and simulates interrupts
- * from the root controller interrupt pipe for port status change
+ * This routine is executed periodically and simulates interrupts from
+ * the root controller interrupt pipe for port status change:
*/
static void
-uhci_root_intr_check(void *arg)
+uhci_root_intr(uhci_softc_t *sc)
{
- struct usb2_xfer *xfer = arg;
- uhci_softc_t *sc = UHCI_BUS2SC(xfer->xroot->bus);
-
DPRINTFN(21, "\n");
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
@@ -2936,27 +2818,17 @@ uhci_root_intr_check(void *arg)
UHCI_PORTSC_OCIC | UHCI_PORTSC_RD)) {
sc->sc_hub_idata[0] |= 1 << 2;
}
- if (sc->sc_hub_idata[0] == 0) {
- /*
- * no change or controller not running, try again in a while
- */
- uhci_root_intr_start(xfer);
- } else {
- usb2_sw_transfer(&sc->sc_root_intr,
- &uhci_root_intr_done);
+
+ /* restart timer */
+ usb2_callout_reset(&sc->sc_root_intr, hz,
+ (void *)&uhci_root_intr, sc);
+
+ if (sc->sc_hub_idata[0] != 0) {
+ uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
+ sizeof(sc->sc_hub_idata));
}
}
-struct usb2_pipe_methods uhci_root_intr_methods =
-{
- .open = uhci_root_intr_open,
- .close = uhci_root_intr_close,
- .enter = uhci_root_intr_enter,
- .start = uhci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
static void
uhci_xfer_setup(struct usb2_setup_params *parm)
{
@@ -3168,19 +3040,7 @@ uhci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *edesc,
/* not supported */
return;
}
- if (udev->device_index == sc->sc_addr) {
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &uhci_root_ctrl_methods;
- break;
- case UE_DIR_IN | UHCI_INTR_ENDPT:
- pipe->methods = &uhci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
+ if (udev->device_index != sc->sc_addr) {
switch (edesc->bmAttributes & UE_XFERTYPE) {
case UE_CONTROL:
pipe->methods = &uhci_device_ctrl_methods;
@@ -3354,5 +3214,5 @@ struct usb2_bus_methods uhci_bus_methods =
.device_resume = uhci_device_resume,
.device_suspend = uhci_device_suspend,
.set_hw_power = uhci_set_hw_power,
- .roothub_exec = uhci_root_ctrl_task,
+ .roothub_exec = uhci_roothub_exec,
};
diff --git a/sys/dev/usb/controller/uhci.h b/sys/dev/usb/controller/uhci.h
index 9365a4c..64a80cf 100644
--- a/sys/dev/usb/controller/uhci.h
+++ b/sys/dev/usb/controller/uhci.h
@@ -39,9 +39,9 @@
#ifndef _UHCI_H_
#define _UHCI_H_
-#define UHCI_MAX_DEVICES USB_MAX_DEVICES
+#define UHCI_MAX_DEVICES MIN(USB_MAX_DEVICES, 128)
-/* PCI config registers */
+/* PCI config registers */
#define PCI_USBREV 0x60 /* USB protocol revision */
#define PCI_USB_REV_MASK 0xff
#define PCI_USB_REV_PRE_1_0 0x00
@@ -271,19 +271,19 @@ typedef struct uhci_softc {
struct uhci_hw_softc sc_hw;
struct usb2_bus sc_bus; /* base device */
union uhci_hub_desc sc_hub_desc;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
+ struct usb2_callout sc_root_intr;
struct usb2_device *sc_devices[UHCI_MAX_DEVICES];
- struct uhci_td *sc_isoc_p_last[UHCI_VFRAMELIST_COUNT]; /* pointer to last TD
- * for isochronous */
- struct uhci_qh *sc_intr_p_last[UHCI_IFRAMELIST_COUNT]; /* pointer to last QH
- * for interrupt */
- struct uhci_qh *sc_ls_ctl_p_last; /* pointer to last QH for low
- * speed control */
- struct uhci_qh *sc_fs_ctl_p_last; /* pointer to last QH for full
- * speed control */
- struct uhci_qh *sc_bulk_p_last; /* pointer to last QH for bulk */
+ /* pointer to last TD for isochronous */
+ struct uhci_td *sc_isoc_p_last[UHCI_VFRAMELIST_COUNT];
+ /* pointer to last QH for interrupt */
+ struct uhci_qh *sc_intr_p_last[UHCI_IFRAMELIST_COUNT];
+ /* pointer to last QH for low speed control */
+ struct uhci_qh *sc_ls_ctl_p_last;
+ /* pointer to last QH for full speed control */
+ struct uhci_qh *sc_fs_ctl_p_last;
+ /* pointer to last QH for bulk */
+ struct uhci_qh *sc_bulk_p_last;
struct uhci_qh *sc_reclaim_qh_p;
struct uhci_qh *sc_last_qh_p;
struct uhci_td *sc_last_td_p;
diff --git a/sys/dev/usb/controller/uhci_pci.c b/sys/dev/usb/controller/uhci_pci.c
index a61693b..061a178 100644
--- a/sys/dev/usb/controller/uhci_pci.c
+++ b/sys/dev/usb/controller/uhci_pci.c
@@ -49,13 +49,11 @@ __FBSDID("$FreeBSD$");
*/
#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_debug.h>
@@ -324,10 +322,10 @@ uhci_pci_attach(device_t self)
#if (__FreeBSD_version >= 700031)
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)(void *)uhci_interrupt, sc, &sc->sc_intr_hdl);
+ NULL, (driver_intr_t *)uhci_interrupt, sc, &sc->sc_intr_hdl);
#else
err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)(void *)uhci_interrupt, sc, &sc->sc_intr_hdl);
+ (driver_intr_t *)uhci_interrupt, sc, &sc->sc_intr_hdl);
#endif
if (err) {
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index f835ec1..474cbe5 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -25,7 +25,6 @@
*/
#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb.h>
@@ -42,7 +41,7 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
-/* function prototypes */
+/* function prototypes */
static device_probe_t usb2_probe;
static device_attach_t usb2_attach;
@@ -50,16 +49,6 @@ static device_detach_t usb2_detach;
static void usb2_attach_sub(device_t, struct usb2_bus *);
static void usb2_post_init(void *);
-static void usb2_bus_mem_flush_all_cb(struct usb2_bus *,
- struct usb2_page_cache *, struct usb2_page *, uint32_t,
- uint32_t);
-static void usb2_bus_mem_alloc_all_cb(struct usb2_bus *,
- struct usb2_page_cache *, struct usb2_page *, uint32_t,
- uint32_t);
-static void usb2_bus_mem_free_all_cb(struct usb2_bus *,
- struct usb2_page_cache *, struct usb2_page *, uint32_t,
- uint32_t);
-static void usb2_bus_roothub(struct usb2_proc_msg *pm);
/* static variables */
@@ -176,10 +165,6 @@ usb2_detach(device_t dev)
usb2_proc_free(&bus->giant_callback_proc);
usb2_proc_free(&bus->non_giant_callback_proc);
- /* Get rid of USB roothub process */
-
- usb2_proc_free(&bus->roothub_proc);
-
/* Get rid of USB explore process */
usb2_proc_free(&bus->explore_proc);
@@ -219,7 +204,6 @@ usb2_bus_explore(struct usb2_proc_msg *pm)
* First update the USB power state!
*/
usb2_bus_powerd(bus);
-
/*
* Explore the Root USB HUB. This call can sleep,
* exiting Giant, which is actually Giant.
@@ -264,8 +248,8 @@ usb2_bus_detach(struct usb2_proc_msg *pm)
* Free USB Root device, but not any sub-devices, hence they
* are freed by the caller of this function:
*/
- usb2_detach_device(udev, USB_IFACE_INDEX_ANY, 0);
- usb2_free_device(udev);
+ usb2_free_device(udev,
+ USB_UNCFG_FLAG_FREE_EP0);
mtx_unlock(&Giant);
USB_BUS_LOCK(bus);
@@ -287,7 +271,7 @@ usb2_power_wdog(void *arg)
usb2_bus_power_update(bus);
- return;
+ USB_BUS_LOCK(bus);
}
/*------------------------------------------------------------------------*
@@ -338,6 +322,20 @@ usb2_bus_attach(struct usb2_proc_msg *pm)
USB_BUS_UNLOCK(bus);
mtx_lock(&Giant); /* XXX not required by USB */
+ /* default power_mask value */
+ bus->hw_power_state =
+ USB_HW_POWER_CONTROL |
+ USB_HW_POWER_BULK |
+ USB_HW_POWER_INTERRUPT |
+ USB_HW_POWER_ISOC |
+ USB_HW_POWER_NON_ROOT_HUB;
+
+ /* make sure power is set at least once */
+
+ if (bus->methods->set_hw_power != NULL) {
+ (bus->methods->set_hw_power) (bus);
+ }
+
/* Allocate the Root USB device */
child = usb2_alloc_device(bus->bdev, bus, NULL, 0, 0, 1,
@@ -366,11 +364,8 @@ usb2_bus_attach(struct usb2_proc_msg *pm)
/* set softc - we are ready */
device_set_softc(dev, bus);
- /* start watchdog - this function will unlock the BUS lock ! */
+ /* start watchdog */
usb2_power_wdog(bus);
-
- /* need to return locked */
- USB_BUS_LOCK(bus);
}
/*------------------------------------------------------------------------*
@@ -403,12 +398,7 @@ usb2_attach_sub(device_t dev, struct usb2_bus *bus)
bus->attach_msg[1].hdr.pm_callback = &usb2_bus_attach;
bus->attach_msg[1].bus = bus;
- bus->roothub_msg[0].hdr.pm_callback = &usb2_bus_roothub;
- bus->roothub_msg[0].bus = bus;
- bus->roothub_msg[1].hdr.pm_callback = &usb2_bus_roothub;
- bus->roothub_msg[1].bus = bus;
-
- /* Create USB explore, roothub and callback processes */
+ /* Create USB explore and callback processes */
if (usb2_proc_create(&bus->giant_callback_proc,
&bus->bus_mtx, pname, USB_PRI_MED)) {
@@ -418,10 +408,6 @@ usb2_attach_sub(device_t dev, struct usb2_bus *bus)
&bus->bus_mtx, pname, USB_PRI_HIGH)) {
printf("WARNING: Creation of USB non-Giant "
"callback process failed.\n");
- } else if (usb2_proc_create(&bus->roothub_proc,
- &bus->bus_mtx, pname, USB_PRI_HIGH)) {
- printf("WARNING: Creation of USB roothub "
- "process failed.\n");
} else if (usb2_proc_create(&bus->explore_proc,
&bus->bus_mtx, pname, USB_PRI_MED)) {
printf("WARNING: Creation of USB explore "
@@ -488,16 +474,19 @@ SYSUNINIT(usb2_bus_unload, SI_SUB_KLD, SI_ORDER_ANY, usb2_bus_unload, NULL);
/*------------------------------------------------------------------------*
* usb2_bus_mem_flush_all_cb
*------------------------------------------------------------------------*/
+#if USB_HAVE_BUSDMA
static void
usb2_bus_mem_flush_all_cb(struct usb2_bus *bus, struct usb2_page_cache *pc,
struct usb2_page *pg, uint32_t size, uint32_t align)
{
usb2_pc_cpu_flush(pc);
}
+#endif
/*------------------------------------------------------------------------*
* usb2_bus_mem_flush_all - factored out code
*------------------------------------------------------------------------*/
+#if USB_HAVE_BUSDMA
void
usb2_bus_mem_flush_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb)
{
@@ -505,10 +494,12 @@ usb2_bus_mem_flush_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb)
cb(bus, &usb2_bus_mem_flush_all_cb);
}
}
+#endif
/*------------------------------------------------------------------------*
* usb2_bus_mem_alloc_all_cb
*------------------------------------------------------------------------*/
+#if USB_HAVE_BUSDMA
static void
usb2_bus_mem_alloc_all_cb(struct usb2_bus *bus, struct usb2_page_cache *pc,
struct usb2_page *pg, uint32_t size, uint32_t align)
@@ -520,6 +511,7 @@ usb2_bus_mem_alloc_all_cb(struct usb2_bus *bus, struct usb2_page_cache *pc,
bus->alloc_failed = 1;
}
}
+#endif
/*------------------------------------------------------------------------*
* usb2_bus_mem_alloc_all - factored out code
@@ -538,13 +530,14 @@ usb2_bus_mem_alloc_all(struct usb2_bus *bus, bus_dma_tag_t dmat,
NULL, MTX_DEF | MTX_RECURSE);
usb2_callout_init_mtx(&bus->power_wdog,
- &bus->bus_mtx, CALLOUT_RETURNUNLOCKED);
+ &bus->bus_mtx, 0);
TAILQ_INIT(&bus->intr_q.head);
+#if USB_HAVE_BUSDMA
usb2_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
- dmat, &bus->bus_mtx, NULL, NULL, 32, USB_BUS_DMA_TAG_MAX);
-
+ dmat, &bus->bus_mtx, NULL, 32, USB_BUS_DMA_TAG_MAX);
+#endif
if ((bus->devices_max > USB_MAX_DEVICES) ||
(bus->devices_max < USB_MIN_DEVICES) ||
(bus->devices == NULL)) {
@@ -552,9 +545,11 @@ usb2_bus_mem_alloc_all(struct usb2_bus *bus, bus_dma_tag_t dmat,
"initialised properly!\n");
bus->alloc_failed = 1; /* failure */
}
+#if USB_HAVE_BUSDMA
if (cb) {
cb(bus, &usb2_bus_mem_alloc_all_cb);
}
+#endif
if (bus->alloc_failed) {
usb2_bus_mem_free_all(bus, cb);
}
@@ -564,12 +559,14 @@ usb2_bus_mem_alloc_all(struct usb2_bus *bus, bus_dma_tag_t dmat,
/*------------------------------------------------------------------------*
* usb2_bus_mem_free_all_cb
*------------------------------------------------------------------------*/
+#if USB_HAVE_BUSDMA
static void
usb2_bus_mem_free_all_cb(struct usb2_bus *bus, struct usb2_page_cache *pc,
struct usb2_page *pg, uint32_t size, uint32_t align)
{
usb2_pc_free_mem(pc);
}
+#endif
/*------------------------------------------------------------------------*
* usb2_bus_mem_free_all - factored out code
@@ -577,45 +574,12 @@ usb2_bus_mem_free_all_cb(struct usb2_bus *bus, struct usb2_page_cache *pc,
void
usb2_bus_mem_free_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb)
{
+#if USB_HAVE_BUSDMA
if (cb) {
cb(bus, &usb2_bus_mem_free_all_cb);
}
usb2_dma_tag_unsetup(bus->dma_parent_tag);
+#endif
mtx_destroy(&bus->bus_mtx);
}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_roothub
- *
- * This function is used to execute roothub control requests on the
- * roothub and is called from the roothub process.
- *------------------------------------------------------------------------*/
-static void
-usb2_bus_roothub(struct usb2_proc_msg *pm)
-{
- struct usb2_bus *bus;
-
- bus = ((struct usb2_bus_msg *)pm)->bus;
-
- USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
-
- (bus->methods->roothub_exec) (bus);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_bus_roothub_exec
- *
- * This function is used to schedule the "roothub_done" bus callback
- * method. The bus lock must be locked when calling this function.
- *------------------------------------------------------------------------*/
-void
-usb2_bus_roothub_exec(struct usb2_bus *bus)
-{
- USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
-
- if (usb2_proc_msignal(&bus->roothub_proc,
- &bus->roothub_msg[0], &bus->roothub_msg[1])) {
- /* ignore */
- }
-}
diff --git a/sys/dev/usb/controller/uss820dci.c b/sys/dev/usb/controller/uss820dci.c
index 5fc8e98..9582869 100644
--- a/sys/dev/usb/controller/uss820dci.c
+++ b/sys/dev/usb/controller/uss820dci.c
@@ -29,14 +29,13 @@
* This file contains the driver for the USS820 series USB Device
* Controller
*
- * NOTE: The datasheet does not document everything!
+ * NOTE: The datasheet does not document everything.
*/
#include <dev/usb/usb.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_revision.h>
#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR uss820dcidebug
@@ -44,7 +43,6 @@
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_transfer.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_hub.h>
@@ -56,10 +54,10 @@
#define USS820_DCI_BUS2SC(bus) \
((struct uss820dci_softc *)(((uint8_t *)(bus)) - \
- USB_P2U(&(((struct uss820dci_softc *)0)->sc_bus))))
+ ((uint8_t *)&(((struct uss820dci_softc *)0)->sc_bus))))
#define USS820_DCI_PC2SC(pc) \
- USS820_DCI_BUS2SC((pc)->tag_parent->info->bus)
+ USS820_DCI_BUS2SC(USB_DMATAG_TO_XROOT((pc)->tag_parent)->bus)
#if USB_DEBUG
static int uss820dcidebug = 0;
@@ -78,8 +76,6 @@ struct usb2_pipe_methods uss820dci_device_bulk_methods;
struct usb2_pipe_methods uss820dci_device_ctrl_methods;
struct usb2_pipe_methods uss820dci_device_intr_methods;
struct usb2_pipe_methods uss820dci_device_isoc_fs_methods;
-struct usb2_pipe_methods uss820dci_root_ctrl_methods;
-struct usb2_pipe_methods uss820dci_root_intr_methods;
static uss820dci_cmd_t uss820dci_setup_rx;
static uss820dci_cmd_t uss820dci_data_rx;
@@ -87,14 +83,11 @@ static uss820dci_cmd_t uss820dci_data_tx;
static uss820dci_cmd_t uss820dci_data_tx_sync;
static void uss820dci_device_done(struct usb2_xfer *, usb2_error_t);
static void uss820dci_do_poll(struct usb2_bus *);
-static void uss820dci_root_ctrl_poll(struct uss820dci_softc *);
static void uss820dci_standard_done(struct usb2_xfer *);
static void uss820dci_intr_set(struct usb2_xfer *, uint8_t);
static void uss820dci_update_shared_1(struct uss820dci_softc *, uint8_t,
uint8_t, uint8_t);
-
-static usb2_sw_transfer_func_t uss820dci_root_intr_done;
-static usb2_sw_transfer_func_t uss820dci_root_ctrl_done;
+static void uss820dci_root_intr(struct uss820dci_softc *);
/*
* Here is a list of what the USS820D chip can support. The main
@@ -249,19 +242,11 @@ uss820dci_setup_rx(struct uss820dci_td *td)
DPRINTFN(5, "rx_stat=0x%02x rem=%u\n", rx_stat, td->remainder);
if (!(rx_stat & USS820_RXSTAT_RXSETUP)) {
- /* abort any ongoing transfer */
- if (!td->did_stall) {
- DPRINTFN(5, "stalling\n");
-
- /* set stall */
-
- uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF,
- (USS820_EPCON_TXSTL | USS820_EPCON_RXSTL));
-
- td->did_stall = 1;
- }
goto not_complete;
}
+ /* clear did stall */
+ td->did_stall = 0;
+
/* clear stall and all I/O */
uss820dci_update_shared_1(sc, USS820_EPCON,
0xFF ^ (USS820_EPCON_TXSTL |
@@ -284,12 +269,12 @@ uss820dci_setup_rx(struct uss820dci_td *td)
if (count != td->remainder) {
DPRINTFN(0, "Invalid SETUP packet "
"length, %d bytes\n", count);
- goto not_complete;
+ goto setup_not_complete;
}
if (count != sizeof(req)) {
DPRINTFN(0, "Unsupported SETUP packet "
"length, %d bytes\n", count);
- goto not_complete;
+ goto setup_not_complete;
}
/* receive data */
bus_space_read_multi_1(td->io_tag, td->io_hdl,
@@ -332,7 +317,28 @@ uss820dci_setup_rx(struct uss820dci_td *td)
}
return (0); /* complete */
+setup_not_complete:
+
+ /* set RXFFRC bit */
+ temp = bus_space_read_1(td->io_tag, td->io_hdl,
+ td->rx_cntl_reg);
+ temp |= USS820_RXCON_RXFFRC;
+ bus_space_write_1(td->io_tag, td->io_hdl,
+ td->rx_cntl_reg, temp);
+
+ /* FALLTHROUGH */
+
not_complete:
+ /* abort any ongoing transfer */
+ if (!td->did_stall) {
+ DPRINTFN(5, "stalling\n");
+ /* set stall */
+ uss820dci_update_shared_1(sc, USS820_EPCON, 0xFF,
+ (USS820_EPCON_TXSTL | USS820_EPCON_RXSTL));
+
+ td->did_stall = 1;
+ }
+
/* clear end overwrite flag, if any */
if (rx_stat & USS820_RXSTAT_RXSETUP) {
uss820dci_update_shared_1(sc, USS820_RXSTAT,
@@ -774,9 +780,7 @@ uss820dci_interrupt(struct uss820dci_softc *sc)
DPRINTF("real bus interrupt 0x%02x\n", ssr);
/* complete root HUB interrupt endpoint */
-
- usb2_sw_transfer(&sc->sc_root_intr,
- &uss820dci_root_intr_done);
+ uss820dci_root_intr(sc);
}
}
/* acknowledge all SBI interrupts */
@@ -837,8 +841,8 @@ uss820dci_setup_standard_chain(struct usb2_xfer *xfer)
temp.td = NULL;
temp.td_next = xfer->td_start[0];
- temp.setup_alt_next = xfer->flags_int.short_frames_ok;
temp.offset = 0;
+ temp.setup_alt_next = xfer->flags_int.short_frames_ok;
sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
ep_no = (xfer->endpoint & UE_ADDR);
@@ -852,6 +856,12 @@ uss820dci_setup_standard_chain(struct usb2_xfer *xfer)
temp.len = xfer->frlengths[0];
temp.pc = xfer->frbuffers + 0;
temp.short_pkt = temp.len ? 1 : 0;
+ /* check for last frame */
+ if (xfer->nframes == 1) {
+ /* no STATUS stage yet, SETUP is last */
+ if (xfer->flags_int.control_act)
+ temp.setup_alt_next = 0;
+ }
uss820dci_setup_standard_chain_sub(&temp);
}
@@ -879,7 +889,13 @@ uss820dci_setup_standard_chain(struct usb2_xfer *xfer)
x++;
if (x == xfer->nframes) {
- temp.setup_alt_next = 0;
+ if (xfer->flags_int.control_xfr) {
+ if (xfer->flags_int.control_act) {
+ temp.setup_alt_next = 0;
+ }
+ } else {
+ temp.setup_alt_next = 0;
+ }
}
if (temp.len == 0) {
@@ -904,37 +920,39 @@ uss820dci_setup_standard_chain(struct usb2_xfer *xfer)
}
}
- /* always setup a valid "pc" pointer for status and sync */
- temp.pc = xfer->frbuffers + 0;
-
- /* check if we should append a status stage */
-
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
+ /* check for control transfer */
+ if (xfer->flags_int.control_xfr) {
uint8_t need_sync;
- /*
- * Send a DATA1 message and invert the current
- * endpoint direction.
- */
- if (xfer->endpoint & UE_DIR_IN) {
- temp.func = &uss820dci_data_rx;
- need_sync = 0;
- } else {
- temp.func = &uss820dci_data_tx;
- need_sync = 1;
- }
+ /* always setup a valid "pc" pointer for status and sync */
+ temp.pc = xfer->frbuffers + 0;
temp.len = 0;
temp.short_pkt = 0;
+ temp.setup_alt_next = 0;
- uss820dci_setup_standard_chain_sub(&temp);
- if (need_sync) {
- /* we need a SYNC point after TX */
- temp.func = &uss820dci_data_tx_sync;
+ /* check if we should append a status stage */
+ if (!xfer->flags_int.control_act) {
+
+ /*
+ * Send a DATA1 message and invert the current
+ * endpoint direction.
+ */
+ if (xfer->endpoint & UE_DIR_IN) {
+ temp.func = &uss820dci_data_rx;
+ need_sync = 0;
+ } else {
+ temp.func = &uss820dci_data_tx;
+ need_sync = 1;
+ }
temp.len = 0;
temp.short_pkt = 0;
uss820dci_setup_standard_chain_sub(&temp);
+ if (need_sync) {
+ /* we need a SYNC point after TX */
+ temp.func = &uss820dci_data_tx_sync;
+ uss820dci_setup_standard_chain_sub(&temp);
+ }
}
}
/* must have at least one frame! */
@@ -1021,31 +1039,17 @@ uss820dci_start_standard_chain(struct usb2_xfer *xfer)
}
static void
-uss820dci_root_intr_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
+uss820dci_root_intr(struct uss820dci_softc *sc)
{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
-
DPRINTFN(9, "\n");
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_PRE_DATA) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- uss820dci_device_done(xfer, std->err);
- }
- goto done;
- }
- /* setup buffer */
- std->ptr = sc->sc_hub_idata;
- std->len = sizeof(sc->sc_hub_idata);
-
/* set port bit */
sc->sc_hub_idata[0] = 0x02; /* we only have one port */
-done:
- return;
+ uhub_root_intr(&sc->sc_bus, sc->sc_hub_idata,
+ sizeof(sc->sc_hub_idata));
}
static usb2_error_t
@@ -1499,7 +1503,6 @@ uss820dci_do_poll(struct usb2_bus *bus)
USB_BUS_LOCK(&sc->sc_bus);
uss820dci_interrupt_poll(sc);
- uss820dci_root_ctrl_poll(sc);
USB_BUS_UNLOCK(&sc->sc_bus);
}
@@ -1538,8 +1541,6 @@ struct usb2_pipe_methods uss820dci_device_bulk_methods =
.close = uss820dci_device_bulk_close,
.enter = uss820dci_device_bulk_enter,
.start = uss820dci_device_bulk_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -1577,8 +1578,6 @@ struct usb2_pipe_methods uss820dci_device_ctrl_methods =
.close = uss820dci_device_ctrl_close,
.enter = uss820dci_device_ctrl_enter,
.start = uss820dci_device_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -1616,8 +1615,6 @@ struct usb2_pipe_methods uss820dci_device_intr_methods =
.close = uss820dci_device_intr_close,
.enter = uss820dci_device_intr_enter,
.start = uss820dci_device_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
@@ -1700,38 +1697,14 @@ struct usb2_pipe_methods uss820dci_device_isoc_fs_methods =
.close = uss820dci_device_isoc_fs_close,
.enter = uss820dci_device_isoc_fs_enter,
.start = uss820dci_device_isoc_fs_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
};
/*------------------------------------------------------------------------*
* at91dci root control support
*------------------------------------------------------------------------*
- * simulate a hardware HUB by handling
- * all the necessary requests
+ * Simulate a hardware HUB by handling all the necessary requests.
*------------------------------------------------------------------------*/
-static void
-uss820dci_root_ctrl_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_root_ctrl_close(struct usb2_xfer *xfer)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_ctrl.xfer == xfer) {
- sc->sc_root_ctrl.xfer = NULL;
- }
- uss820dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-/*
- * USB descriptors for the virtual Root HUB:
- */
-
static const struct usb2_device_descriptor uss820dci_devd = {
.bLength = sizeof(struct usb2_device_descriptor),
.bDescriptorType = UDESC_DEVICE,
@@ -1816,44 +1789,15 @@ USB_MAKE_STRING_DESC(STRING_VENDOR, uss820dci_vendor);
USB_MAKE_STRING_DESC(STRING_PRODUCT, uss820dci_product);
static void
-uss820dci_root_ctrl_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_root_ctrl_start(struct usb2_xfer *xfer)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_ctrl.xfer = xfer;
-
- usb2_bus_roothub_exec(xfer->xroot->bus);
-}
-
-static void
-uss820dci_root_ctrl_task(struct usb2_bus *bus)
-{
- uss820dci_root_ctrl_poll(USS820_DCI_BUS2SC(bus));
-}
-
-static void
-uss820dci_root_ctrl_done(struct usb2_xfer *xfer,
- struct usb2_sw_transfer *std)
+uss820dci_roothub_exec(struct usb2_bus *bus)
{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
+ struct uss820dci_softc *sc = USS820_DCI_BUS2SC(bus);
+ struct usb2_sw_transfer *std = &sc->sc_bus.roothub_req;
uint16_t value;
uint16_t index;
USB_BUS_LOCK_ASSERT(&sc->sc_bus, MA_OWNED);
- if (std->state != USB_SW_TR_SETUP) {
- if (std->state == USB_SW_TR_PRE_CALLBACK) {
- /* transfer transferred */
- uss820dci_device_done(xfer, std->err);
- }
- goto done;
- }
/* buffer reset */
std->ptr = USB_ADD_BYTES(&sc->sc_hub_temp, 0);
std->len = 0;
@@ -2227,67 +2171,6 @@ done:
}
static void
-uss820dci_root_ctrl_poll(struct uss820dci_softc *sc)
-{
- usb2_sw_transfer(&sc->sc_root_ctrl,
- &uss820dci_root_ctrl_done);
-}
-
-struct usb2_pipe_methods uss820dci_root_ctrl_methods =
-{
- .open = uss820dci_root_ctrl_open,
- .close = uss820dci_root_ctrl_close,
- .enter = uss820dci_root_ctrl_enter,
- .start = uss820dci_root_ctrl_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 0,
-};
-
-/*------------------------------------------------------------------------*
- * at91dci root interrupt support
- *------------------------------------------------------------------------*/
-static void
-uss820dci_root_intr_open(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_root_intr_close(struct usb2_xfer *xfer)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
-
- if (sc->sc_root_intr.xfer == xfer) {
- sc->sc_root_intr.xfer = NULL;
- }
- uss820dci_device_done(xfer, USB_ERR_CANCELLED);
-}
-
-static void
-uss820dci_root_intr_enter(struct usb2_xfer *xfer)
-{
- return;
-}
-
-static void
-uss820dci_root_intr_start(struct usb2_xfer *xfer)
-{
- struct uss820dci_softc *sc = USS820_DCI_BUS2SC(xfer->xroot->bus);
-
- sc->sc_root_intr.xfer = xfer;
-}
-
-struct usb2_pipe_methods uss820dci_root_intr_methods =
-{
- .open = uss820dci_root_intr_open,
- .close = uss820dci_root_intr_close,
- .enter = uss820dci_root_intr_enter,
- .start = uss820dci_root_intr_start,
- .enter_is_cancelable = 1,
- .start_is_cancelable = 1,
-};
-
-static void
uss820dci_xfer_setup(struct usb2_setup_params *parm)
{
const struct usb2_hw_ep_profile *pf;
@@ -2426,24 +2309,7 @@ uss820dci_pipe_init(struct usb2_device *udev, struct usb2_endpoint_descriptor *e
edesc->bEndpointAddress, udev->flags.usb2_mode,
sc->sc_rt_addr);
- if (udev->device_index == sc->sc_rt_addr) {
-
- if (udev->flags.usb2_mode != USB_MODE_HOST) {
- /* not supported */
- return;
- }
- switch (edesc->bEndpointAddress) {
- case USB_CONTROL_ENDPOINT:
- pipe->methods = &uss820dci_root_ctrl_methods;
- break;
- case UE_DIR_IN | USS820_DCI_INTR_ENDPT:
- pipe->methods = &uss820dci_root_intr_methods;
- break;
- default:
- /* do nothing */
- break;
- }
- } else {
+ if (udev->device_index != sc->sc_rt_addr) {
if (udev->flags.usb2_mode != USB_MODE_DEVICE) {
/* not supported */
@@ -2481,5 +2347,5 @@ struct usb2_bus_methods uss820dci_bus_methods =
.get_hw_ep_profile = &uss820dci_get_hw_ep_profile,
.set_stall = &uss820dci_set_stall,
.clear_stall = &uss820dci_clear_stall,
- .roothub_exec = &uss820dci_root_ctrl_task,
+ .roothub_exec = &uss820dci_roothub_exec,
};
diff --git a/sys/dev/usb/controller/uss820dci.h b/sys/dev/usb/controller/uss820dci.h
index fcddb4a..637f562 100644
--- a/sys/dev/usb/controller/uss820dci.h
+++ b/sys/dev/usb/controller/uss820dci.h
@@ -345,8 +345,6 @@ struct uss820dci_softc {
struct usb2_bus sc_bus;
union uss820_hub_temp sc_hub_temp;
LIST_HEAD(, usb2_xfer) sc_interrupt_list_head;
- struct usb2_sw_transfer sc_root_ctrl;
- struct usb2_sw_transfer sc_root_intr;
struct usb2_device *sc_devices[USS820_MAX_DEVICES];
struct resource *sc_io_res;
diff --git a/sys/dev/usb/controller/uss820dci_atmelarm.c b/sys/dev/usb/controller/uss820dci_atmelarm.c
index 5691d4b..c01c2c5 100644
--- a/sys/dev/usb/controller/uss820dci_atmelarm.c
+++ b/sys/dev/usb/controller/uss820dci_atmelarm.c
@@ -28,13 +28,11 @@ __FBSDID("$FreeBSD$");
*/
#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_sw_transfer.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_controller.h>
@@ -171,10 +169,10 @@ uss820_atmelarm_attach(device_t dev)
#if (__FreeBSD_version >= 700031)
err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- NULL, (void *)uss820dci_interrupt, sc, &sc->sc_intr_hdl);
+ NULL, (driver_intr_t *)uss820dci_interrupt, sc, &sc->sc_intr_hdl);
#else
err = bus_setup_intr(dev, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
- (void *)uss820dci_interrupt, sc, &sc->sc_intr_hdl);
+ (driver_intr_t *)uss820dci_interrupt, sc, &sc->sc_intr_hdl);
#endif
if (err) {
sc->sc_intr_hdl = NULL;
diff --git a/sys/dev/usb/image/uscanner.c b/sys/dev/usb/image/uscanner.c
deleted file mode 100644
index 916295e..0000000
--- a/sys/dev/usb/image/uscanner.c
+++ /dev/null
@@ -1,641 +0,0 @@
-/* $NetBSD: uscanner.c,v 1.30 2002/07/11 21:14:36 augustss Exp$ */
-
-/* Also already merged from NetBSD:
- * $NetBSD: uscanner.c,v 1.33 2002/09/23 05:51:24 simonb Exp $
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*-
- * Copyright (c) 2000 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Lennart Augustsson (lennart@augustsson.net) at
- * Carlstedt Research & Technology
- * and Nick Hibma (n_hibma@qubesoft.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.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "usbdevs.h"
-#include <dev/usb/usb.h>
-#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_error.h>
-
-#define USB_DEBUG_VAR uscanner_debug
-
-#include <dev/usb/usb_core.h>
-#include <dev/usb/usb_debug.h>
-#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_request.h>
-#include <dev/usb/usb_lookup.h>
-#include <dev/usb/usb_util.h>
-#include <dev/usb/usb_busdma.h>
-#include <dev/usb/usb_mbuf.h>
-#include <dev/usb/usb_dev.h>
-
-#if USB_DEBUG
-static int uscanner_debug = 0;
-
-SYSCTL_NODE(_hw_usb2, OID_AUTO, uscanner, CTLFLAG_RW, 0, "USB uscanner");
-SYSCTL_INT(_hw_usb2_uscanner, OID_AUTO, debug, CTLFLAG_RW, &uscanner_debug,
- 0, "uscanner debug level");
-#endif
-
-/*
- * uscanner transfers macros definition.
- */
-#define USCANNER_BSIZE (1 << 15)
-#define USCANNER_IFQ_MAXLEN 2
-
-/*
- * Transfers stallings handling flags definition.
- */
-#define USCANNER_FLAG_READ_STALL 0x01
-#define USCANNER_FLAG_WRITE_STALL 0x02
-
-/*
- * uscanner_info flags definition.
- */
-#define USCANNER_FLAG_KEEP_OPEN 0x04
-
-enum {
- USCANNER_BULK_DT_WR,
- USCANNER_BULK_DT_RD,
- USCANNER_BULK_CS_WR,
- USCANNER_BULK_CS_RD,
- USCANNER_N_TRANSFER = 4,
-};
-
-struct uscanner_softc {
- struct usb2_fifo_sc sc_fifo;
- struct mtx sc_mtx;
-
- struct usb2_xfer *sc_xfer[USCANNER_N_TRANSFER];
-
- uint8_t sc_flags; /* Used to prevent stalls */
-};
-
-/*
- * Prototypes for driver handling routines (sorted by use).
- */
-static device_probe_t uscanner_probe;
-static device_attach_t uscanner_attach;
-static device_detach_t uscanner_detach;
-
-/*
- * Prototypes for xfer transfer callbacks.
- */
-static usb2_callback_t uscanner_read_callback;
-static usb2_callback_t uscanner_read_clear_stall_callback;
-static usb2_callback_t uscanner_write_callback;
-static usb2_callback_t uscanner_write_clear_stall_callback;
-
-/*
- * Prototypes for the character device handling routines.
- */
-static usb2_fifo_close_t uscanner_close;
-static usb2_fifo_cmd_t uscanner_start_read;
-static usb2_fifo_cmd_t uscanner_start_write;
-static usb2_fifo_cmd_t uscanner_stop_read;
-static usb2_fifo_cmd_t uscanner_stop_write;
-static usb2_fifo_open_t uscanner_open;
-
-static struct usb2_fifo_methods uscanner_fifo_methods = {
- .f_close = &uscanner_close,
- .f_open = &uscanner_open,
- .f_start_read = &uscanner_start_read,
- .f_start_write = &uscanner_start_write,
- .f_stop_read = &uscanner_stop_read,
- .f_stop_write = &uscanner_stop_write,
- .basename[0] = "uscanner",
-};
-
-/*
- * xfer transfers array. Resolve-stalling callbacks are marked as control
- * transfers.
- */
-static const struct usb2_config uscanner_config[USCANNER_N_TRANSFER] = {
- [USCANNER_BULK_DT_WR] = {
- .type = UE_BULK,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_OUT,
- .mh.bufsize = USCANNER_BSIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,.force_short_xfer = 1,},
- .mh.callback = &uscanner_write_callback,
- },
-
- [USCANNER_BULK_DT_RD] = {
- .type = UE_BULK,
- .endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_IN,
- .mh.bufsize = USCANNER_BSIZE,
- .mh.flags = {.pipe_bof = 1,.proxy_buffer = 1,.short_xfer_ok = 1,},
- .mh.callback = &uscanner_read_callback,
- },
-
- [USCANNER_BULK_CS_WR] = {
- .type = UE_CONTROL,
- .endpoint = 0x00, /* Control pipe */
- .direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &uscanner_write_clear_stall_callback,
- .mh.timeout = 1000,
- .mh.interval = 50, /* 50ms */
- },
-
- [USCANNER_BULK_CS_RD] = {
- .type = UE_CONTROL,
- .endpoint = 0x00,
- .direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &uscanner_read_clear_stall_callback,
- .mh.timeout = 1000,
- .mh.interval = 50, /* 50ms */
- },
-};
-
-static devclass_t uscanner_devclass;
-
-static device_method_t uscanner_methods[] = {
- DEVMETHOD(device_probe, uscanner_probe),
- DEVMETHOD(device_attach, uscanner_attach),
- DEVMETHOD(device_detach, uscanner_detach),
- {0, 0}
-};
-
-static driver_t uscanner_driver = {
- .name = "uscanner",
- .methods = uscanner_methods,
- .size = sizeof(struct uscanner_softc),
-};
-
-DRIVER_MODULE(uscanner, uhub, uscanner_driver, uscanner_devclass, NULL, 0);
-MODULE_DEPEND(uscanner, usb, 1, 1, 1);
-
-/*
- * USB scanners device IDs
- */
-static const struct usb2_device_id uscanner_devs[] = {
- /* Acer */
- {USB_VPI(USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_320U, 0)},
- {USB_VPI(USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_640U, 0)},
- {USB_VPI(USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_640BT, 0)},
- {USB_VPI(USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_620U, 0)},
- {USB_VPI(USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_1240U, 0)},
- {USB_VPI(USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_C310U, 0)},
- {USB_VPI(USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_4300U, 0)},
- /* AGFA */
- {USB_VPI(USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1236U, 0)},
- {USB_VPI(USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1212U, 0)},
- {USB_VPI(USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1212U2, 0)},
- {USB_VPI(USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANTOUCH, 0)},
- {USB_VPI(USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE40, 0)},
- {USB_VPI(USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE50, 0)},
- {USB_VPI(USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE20, 0)},
- {USB_VPI(USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE25, 0)},
- {USB_VPI(USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE26, 0)},
- {USB_VPI(USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE52, 0)},
- /* Avision */
- {USB_VPI(USB_VENDOR_AVISION, USB_PRODUCT_AVISION_1200U, 0)},
- /* Canon */
- {USB_VPI(USB_VENDOR_CANON, USB_PRODUCT_CANON_N656U, 0)},
- {USB_VPI(USB_VENDOR_CANON, USB_PRODUCT_CANON_N676U, 0)},
- {USB_VPI(USB_VENDOR_CANON, USB_PRODUCT_CANON_N1220U, 0)},
- {USB_VPI(USB_VENDOR_CANON, USB_PRODUCT_CANON_D660U, 0)},
- {USB_VPI(USB_VENDOR_CANON, USB_PRODUCT_CANON_N1240U, 0)},
- {USB_VPI(USB_VENDOR_CANON, USB_PRODUCT_CANON_LIDE25, 0)},
- /* Epson */
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_636, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_610, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1200, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1240, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1250, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1270, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1600, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1640, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_640U, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1650, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1660, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1670, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1260, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_RX425, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_3200, USCANNER_FLAG_KEEP_OPEN)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_GT9700F, USCANNER_FLAG_KEEP_OPEN)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_CX5400, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_DX7400, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_GT9300UF, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_2480, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_3500, USCANNER_FLAG_KEEP_OPEN)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_3590, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_4200, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_4800, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_4990, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_5000, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_6000, 0)},
- {USB_VPI(USB_VENDOR_EPSON, USB_PRODUCT_EPSON_DX8400, 0)},
- /* HP */
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_2200C, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_3300C, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_3400CSE, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_4100C, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_4200C, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_4300C, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_4470C, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_4670V, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_S20, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_5200C, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_5300C, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_5400C, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_6200C, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_6300C, 0)},
- {USB_VPI(USB_VENDOR_HP, USB_PRODUCT_HP_82x0C, 0)},
- /* Kye */
- {USB_VPI(USB_VENDOR_KYE, USB_PRODUCT_KYE_VIVIDPRO, 0)},
- /* Microtek */
- {USB_VPI(USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_X6U, 0)},
- {USB_VPI(USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_336CX, 0)},
- {USB_VPI(USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_336CX2, 0)},
- {USB_VPI(USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_C6, 0)},
- {USB_VPI(USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6USL, 0)},
- {USB_VPI(USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6USL2, 0)},
- {USB_VPI(USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6UL, 0)},
- /* Minolta */
- {USB_VPI(USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_5400, 0)},
- /* Mustek */
- {USB_VPI(USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200CU, 0)},
- {USB_VPI(USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_BEARPAW1200F, 0)},
- {USB_VPI(USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_BEARPAW1200TA, 0)},
- {USB_VPI(USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_600USB, 0)},
- {USB_VPI(USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_600CU, 0)},
- {USB_VPI(USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200USB, 0)},
- {USB_VPI(USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200UB, 0)},
- {USB_VPI(USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200USBPLUS, 0)},
- {USB_VPI(USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200CUPLUS, 0)},
- /* National */
- {USB_VPI(USB_VENDOR_NATIONAL, USB_PRODUCT_NATIONAL_BEARPAW1200, 0)},
- {USB_VPI(USB_VENDOR_NATIONAL, USB_PRODUCT_NATIONAL_BEARPAW2400, 0)},
- /* Nikon */
- {USB_VPI(USB_VENDOR_NIKON, USB_PRODUCT_NIKON_LS40, 0)},
- /* Primax */
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2X300, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E300, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2300, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E3002, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_9600, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_600U, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_6200, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_19200, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_1200U, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G600, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_636I, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2600, 0)},
- {USB_VPI(USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E600, 0)},
- /* Scanlogic */
- {USB_VPI(USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_336CX, 0)},
- /* Ultima */
- {USB_VPI(USB_VENDOR_ULTIMA, USB_PRODUCT_ULTIMA_1200UBPLUS, 0)},
- /* UMAX */
- {USB_VPI(USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1220U, 0)},
- {USB_VPI(USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1236U, 0)},
- {USB_VPI(USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2000U, 0)},
- {USB_VPI(USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2100U, 0)},
- {USB_VPI(USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2200U, 0)},
- {USB_VPI(USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA3400, 0)},
- /* Visioneer */
- {USB_VPI(USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_3000, 0)},
- {USB_VPI(USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_5300, 0)},
- {USB_VPI(USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_7600, 0)},
- {USB_VPI(USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_6100, 0)},
- {USB_VPI(USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_6200, 0)},
- {USB_VPI(USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_8100, 0)},
- {USB_VPI(USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_8600, 0)}
-};
-
-/*
- * uscanner device probing method.
- */
-static int
-uscanner_probe(device_t dev)
-{
- struct usb2_attach_arg *uaa;
-
- DPRINTFN(11, "\n");
-
- uaa = device_get_ivars(dev);
- if (uaa->usb2_mode != USB_MODE_HOST) {
- return (ENXIO);
- }
- /* Give other class drivers a chance for multifunctional scanners. */
- if (uaa->use_generic == 0) {
- return (ENXIO);
- }
- return (usb2_lookup_id_by_uaa(uscanner_devs, sizeof(uscanner_devs), uaa));
-}
-
-/*
- * uscanner device attaching method.
- */
-static int
-uscanner_attach(device_t dev)
-{
- struct usb2_attach_arg *uaa;
- struct uscanner_softc *sc;
- int unit;
- int error;
-
- uaa = device_get_ivars(dev);
- sc = device_get_softc(dev);
- unit = device_get_unit(dev);
-
- /*
- * A first path softc structure filling. sc_fifo and
- * sc_xfer are initialised later.
- */
- sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
- mtx_init(&sc->sc_mtx, "uscanner mutex", NULL, MTX_DEF | MTX_RECURSE);
-
- /*
- * Announce the device:
- */
- device_set_usb2_desc(dev);
-
- /*
- * Setup the transfer.
- */
- if ((error = usb2_transfer_setup(uaa->device, &uaa->info.bIfaceIndex, sc->sc_xfer,
- uscanner_config, USCANNER_N_TRANSFER, sc, &sc->sc_mtx))) {
- device_printf(dev, "could not setup transfers, "
- "error=%s\n", usb2_errstr(error));
- goto detach;
- }
-
- error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
- &uscanner_fifo_methods, &sc->sc_fifo,
- unit, 0 - 1, uaa->info.bIfaceIndex,
- UID_ROOT, GID_OPERATOR, 0644);
- if (error) {
- goto detach;
- }
- return (0);
-
-detach:
- uscanner_detach(dev);
- return (ENOMEM);
-}
-
-/*
- * uscanner device detaching method.
- */
-static int
-uscanner_detach(device_t dev)
-{
- struct uscanner_softc *sc;
-
- sc = device_get_softc(dev);
-
- usb2_fifo_detach(&sc->sc_fifo);
- usb2_transfer_unsetup(sc->sc_xfer, USCANNER_N_TRANSFER);
- mtx_destroy(&sc->sc_mtx);
-
- return (0);
-}
-
-/*
- * Reading callback. Implemented as an "in" bulk transfer.
- */
-static void
-uscanner_read_callback(struct usb2_xfer *xfer)
-{
- struct uscanner_softc *sc;
- struct usb2_fifo *f;
-
- sc = xfer->priv_sc;
- f = sc->sc_fifo.fp[USB_FIFO_RX];
-
- switch (USB_GET_STATE(xfer)) {
- case USB_ST_TRANSFERRED:
- usb2_fifo_put_data(f, xfer->frbuffers, 0,
- xfer->actlen, 1);
-
- case USB_ST_SETUP:
- /*
- * If reading is in stall, just jump to clear stall callback and
- * solve the situation.
- */
- if (sc->sc_flags & USCANNER_FLAG_READ_STALL) {
- usb2_transfer_start(sc->sc_xfer[USCANNER_BULK_CS_RD]);
- break;
- }
- if (usb2_fifo_put_bytes_max(f) != 0) {
- xfer->frlengths[0] = xfer->max_data_length;
- usb2_start_hardware(xfer);
- }
- break;
-
- default: /* Error */
- if (xfer->error != USB_ERR_CANCELLED) {
- sc->sc_flags |= USCANNER_FLAG_READ_STALL;
- usb2_transfer_start(sc->sc_xfer[USCANNER_BULK_CS_RD]);
- }
- break;
- }
-}
-
-/*
- * Removing stall on reading callback.
- */
-static void
-uscanner_read_clear_stall_callback(struct usb2_xfer *xfer)
-{
- struct uscanner_softc *sc = xfer->priv_sc;
- struct usb2_xfer *xfer_other = sc->sc_xfer[USCANNER_BULK_DT_RD];
-
- if (usb2_clear_stall_callback(xfer, xfer_other)) {
- DPRINTF("stall cleared\n");
- sc->sc_flags &= ~USCANNER_FLAG_READ_STALL;
- usb2_transfer_start(xfer_other);
- }
-}
-
-/*
- * Writing callback. Implemented as an "out" bulk transfer.
- */
-static void
-uscanner_write_callback(struct usb2_xfer *xfer)
-{
- struct uscanner_softc *sc;
- struct usb2_fifo *f;
- uint32_t actlen;
-
- sc = xfer->priv_sc;
- f = sc->sc_fifo.fp[USB_FIFO_TX];
-
- switch (USB_GET_STATE(xfer)) {
- case USB_ST_SETUP:
- case USB_ST_TRANSFERRED:
- /*
- * If writing is in stall, just jump to clear stall callback and
- * solve the situation.
- */
- if (sc->sc_flags & USCANNER_FLAG_WRITE_STALL) {
- usb2_transfer_start(sc->sc_xfer[USCANNER_BULK_CS_WR]);
- break;
- }
- /*
- * Write datas, setup and perform hardware transfer.
- */
- if (usb2_fifo_get_data(f, xfer->frbuffers, 0,
- xfer->max_data_length, &actlen, 0)) {
- xfer->frlengths[0] = actlen;
- usb2_start_hardware(xfer);
- }
- break;
-
- default: /* Error */
- if (xfer->error != USB_ERR_CANCELLED) {
- sc->sc_flags |= USCANNER_FLAG_WRITE_STALL;
- usb2_transfer_start(sc->sc_xfer[USCANNER_BULK_CS_WR]);
- }
- break;
- }
-}
-
-/*
- * Removing stall on writing callback.
- */
-static void
-uscanner_write_clear_stall_callback(struct usb2_xfer *xfer)
-{
- struct uscanner_softc *sc = xfer->priv_sc;
- struct usb2_xfer *xfer_other = sc->sc_xfer[USCANNER_BULK_DT_WR];
-
- if (usb2_clear_stall_callback(xfer, xfer_other)) {
- DPRINTF("stall cleared\n");
- sc->sc_flags &= ~USCANNER_FLAG_WRITE_STALL;
- usb2_transfer_start(xfer_other);
- }
-}
-
-/*
- * uscanner character device opening method.
- */
-static int
-uscanner_open(struct usb2_fifo *fifo, int fflags)
-{
- struct uscanner_softc *sc;
-
- sc = fifo->priv_sc0;
-
- if (!(sc->sc_flags & USCANNER_FLAG_KEEP_OPEN)) {
- if (fflags & FWRITE) {
- sc->sc_flags |= USCANNER_FLAG_WRITE_STALL;
- }
- if (fflags & FREAD) {
- sc->sc_flags |= USCANNER_FLAG_READ_STALL;
- }
- }
- if (fflags & FREAD) {
- if (usb2_fifo_alloc_buffer(fifo,
- sc->sc_xfer[USCANNER_BULK_DT_RD]->max_data_length,
- USCANNER_IFQ_MAXLEN)) {
- return (ENOMEM);
- }
- }
- if (fflags & FWRITE) {
- if (usb2_fifo_alloc_buffer(fifo,
- sc->sc_xfer[USCANNER_BULK_DT_WR]->max_data_length,
- USCANNER_IFQ_MAXLEN)) {
- return (ENOMEM);
- }
- }
- return (0);
-}
-
-static void
-uscanner_close(struct usb2_fifo *fifo, int fflags)
-{
- if (fflags & (FREAD | FWRITE)) {
- usb2_fifo_free_buffer(fifo);
- }
-}
-
-/*
- * uscanner character device start reading method.
- */
-static void
-uscanner_start_read(struct usb2_fifo *fifo)
-{
- struct uscanner_softc *sc;
-
- sc = fifo->priv_sc0;
- usb2_transfer_start(sc->sc_xfer[USCANNER_BULK_DT_RD]);
-}
-
-/*
- * uscanner character device start writing method.
- */
-static void
-uscanner_start_write(struct usb2_fifo *fifo)
-{
- struct uscanner_softc *sc;
-
- sc = fifo->priv_sc0;
- usb2_transfer_start(sc->sc_xfer[USCANNER_BULK_DT_WR]);
-}
-
-/*
- * uscanner character device stop reading method.
- */
-static void
-uscanner_stop_read(struct usb2_fifo *fifo)
-{
- struct uscanner_softc *sc;
-
- sc = fifo->priv_sc0;
- usb2_transfer_stop(sc->sc_xfer[USCANNER_BULK_CS_RD]);
- usb2_transfer_stop(sc->sc_xfer[USCANNER_BULK_DT_RD]);
-}
-
-/*
- * uscanner character device stop writing method.
- */
-static void
-uscanner_stop_write(struct usb2_fifo *fifo)
-{
- struct uscanner_softc *sc;
-
- sc = fifo->priv_sc0;
- usb2_transfer_stop(sc->sc_xfer[USCANNER_BULK_CS_WR]);
- usb2_transfer_stop(sc->sc_xfer[USCANNER_BULK_DT_WR]);
-}
diff --git a/sys/dev/usb/input/uhid.c b/sys/dev/usb/input/uhid.c
index 99e4b5d..78931bd 100644
--- a/sys/dev/usb/input/uhid.c
+++ b/sys/dev/usb/input/uhid.c
@@ -316,27 +316,27 @@ static const struct usb2_config uhid_config[UHID_N_TRANSFER] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = UHID_BSIZE,
- .mh.callback = &uhid_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = UHID_BSIZE,
+ .callback = &uhid_intr_callback,
},
[UHID_CTRL_DT_WR] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request) + UHID_BSIZE,
- .mh.callback = &uhid_write_callback,
- .mh.timeout = 1000, /* 1 second */
+ .bufsize = sizeof(struct usb2_device_request) + UHID_BSIZE,
+ .callback = &uhid_write_callback,
+ .timeout = 1000, /* 1 second */
},
[UHID_CTRL_DT_RD] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request) + UHID_BSIZE,
- .mh.callback = &uhid_read_callback,
- .mh.timeout = 1000, /* 1 second */
+ .bufsize = sizeof(struct usb2_device_request) + UHID_BSIZE,
+ .callback = &uhid_read_callback,
+ .timeout = 1000, /* 1 second */
},
};
@@ -668,8 +668,8 @@ uhid_attach(device_t dev)
* feature report ID 2 before it'll start
* returning digitizer data.
*/
- error = usb2_req_set_report
- (uaa->device, &Giant, reportbuf, sizeof(reportbuf),
+ error = usb2_req_set_report(uaa->device, NULL,
+ reportbuf, sizeof(reportbuf),
uaa->info.bIfaceIndex, UHID_FEATURE_REPORT, 2);
if (error) {
@@ -691,16 +691,16 @@ uhid_attach(device_t dev)
}
if (sc->sc_repdesc_ptr == NULL) {
- error = usb2_req_get_hid_desc
- (uaa->device, &Giant, &sc->sc_repdesc_ptr,
- &sc->sc_repdesc_size, M_USBDEV, uaa->info.bIfaceIndex);
+ error = usb2_req_get_hid_desc(uaa->device, NULL,
+ &sc->sc_repdesc_ptr, &sc->sc_repdesc_size,
+ M_USBDEV, uaa->info.bIfaceIndex);
if (error) {
device_printf(dev, "no report descriptor\n");
goto detach;
}
}
- error = usb2_req_set_idle(uaa->device, &Giant,
+ error = usb2_req_set_idle(uaa->device, NULL,
uaa->info.bIfaceIndex, 0, 0);
if (error) {
diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
index df81ad9..58e8151 100644
--- a/sys/dev/usb/input/ukbd.c
+++ b/sys/dev/usb/input/ukbd.c
@@ -562,28 +562,28 @@ static const struct usb2_config ukbd_config[UKBD_N_TRANSFER] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = &ukbd_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &ukbd_intr_callback,
},
[UKBD_INTR_CS] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.callback = &ukbd_clear_stall_callback,
- .mh.timeout = 1000, /* 1 second */
- .mh.interval = 50, /* 50ms */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &ukbd_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
},
[UKBD_CTRL_LED] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request) + 1,
- .mh.callback = &ukbd_set_leds_callback,
- .mh.timeout = 1000, /* 1 second */
+ .bufsize = sizeof(struct usb2_device_request) + 1,
+ .callback = &ukbd_set_leds_callback,
+ .timeout = 1000, /* 1 second */
},
};
diff --git a/sys/dev/usb/input/ums.c b/sys/dev/usb/input/ums.c
index 5b884e8..6ed030d 100644
--- a/sys/dev/usb/input/ums.c
+++ b/sys/dev/usb/input/ums.c
@@ -84,27 +84,20 @@ SYSCTL_INT(_hw_usb2_ums, OID_AUTO, debug, CTLFLAG_RW,
#define UMS_IFQ_MAXLEN 50 /* units */
#define UMS_BUTTON_MAX 31 /* exclusive, must be less than 32 */
#define UMS_BUT(i) ((i) < 3 ? (((i) + 2) % 3) : (i))
+#define UMS_INFO_MAX 2 /* maximum number of HID sets */
enum {
UMS_INTR_DT,
UMS_N_TRANSFER,
};
-struct ums_softc {
- struct usb2_fifo_sc sc_fifo;
- struct mtx sc_mtx;
- struct usb2_callout sc_callout;
+struct ums_info {
struct hid_location sc_loc_w;
struct hid_location sc_loc_x;
struct hid_location sc_loc_y;
struct hid_location sc_loc_z;
struct hid_location sc_loc_t;
struct hid_location sc_loc_btn[UMS_BUTTON_MAX];
- mousehw_t sc_hw;
- mousemode_t sc_mode;
- mousestatus_t sc_status;
-
- struct usb2_xfer *sc_xfer[UMS_N_TRANSFER];
uint32_t sc_flags;
#define UMS_FLAG_X_AXIS 0x0001
@@ -115,14 +108,29 @@ struct ums_softc {
#define UMS_FLAG_REVZ 0x0020 /* Z-axis is reversed */
#define UMS_FLAG_W_AXIS 0x0040
- uint8_t sc_buttons;
- uint8_t sc_iid;
uint8_t sc_iid_w;
uint8_t sc_iid_x;
uint8_t sc_iid_y;
uint8_t sc_iid_z;
uint8_t sc_iid_t;
uint8_t sc_iid_btn[UMS_BUTTON_MAX];
+ uint8_t sc_buttons;
+};
+
+struct ums_softc {
+ struct usb2_fifo_sc sc_fifo;
+ struct mtx sc_mtx;
+ struct usb2_callout sc_callout;
+ struct ums_info sc_info[UMS_INFO_MAX];
+
+ mousehw_t sc_hw;
+ mousemode_t sc_mode;
+ mousestatus_t sc_status;
+
+ struct usb2_xfer *sc_xfer[UMS_N_TRANSFER];
+
+ uint8_t sc_buttons;
+ uint8_t sc_iid;
uint8_t sc_temp[64];
};
@@ -165,14 +173,15 @@ static void
ums_intr_callback(struct usb2_xfer *xfer)
{
struct ums_softc *sc = xfer->priv_sc;
+ struct ums_info *info = &sc->sc_info[0];
uint8_t *buf = sc->sc_temp;
uint16_t len = xfer->actlen;
int32_t buttons = 0;
- int32_t dw;
- int32_t dx;
- int32_t dy;
- int32_t dz;
- int32_t dt;
+ int32_t dw = 0;
+ int32_t dx = 0;
+ int32_t dy = 0;
+ int32_t dz = 0;
+ int32_t dt = 0;
uint8_t i;
uint8_t id;
@@ -205,49 +214,50 @@ ums_intr_callback(struct usb2_xfer *xfer)
} else {
id = 0;
- if (sc->sc_flags & UMS_FLAG_SBU) {
+ if (sc->sc_info[0].sc_flags & UMS_FLAG_SBU) {
if ((*buf == 0x14) || (*buf == 0x15)) {
goto tr_setup;
}
}
}
- if ((sc->sc_flags & UMS_FLAG_W_AXIS) && (id == sc->sc_iid_w))
- dw = hid_get_data(buf, len, &sc->sc_loc_w);
- else
- dw = 0;
-
- if ((sc->sc_flags & UMS_FLAG_X_AXIS) && (id == sc->sc_iid_x))
- dx = hid_get_data(buf, len, &sc->sc_loc_x);
- else
- dx = 0;
-
- if ((sc->sc_flags & UMS_FLAG_Y_AXIS) && (id == sc->sc_iid_y))
- dy = -hid_get_data(buf, len, &sc->sc_loc_y);
- else
- dy = 0;
-
- if ((sc->sc_flags & UMS_FLAG_Z_AXIS) && (id == sc->sc_iid_z))
- dz = -hid_get_data(buf, len, &sc->sc_loc_z);
- else
- dz = 0;
-
- if (sc->sc_flags & UMS_FLAG_REVZ)
- dz = -dz;
+ repeat:
+ if ((info->sc_flags & UMS_FLAG_W_AXIS) &&
+ (id == info->sc_iid_w))
+ dw += hid_get_data(buf, len, &info->sc_loc_w);
+
+ if ((info->sc_flags & UMS_FLAG_X_AXIS) &&
+ (id == info->sc_iid_x))
+ dx += hid_get_data(buf, len, &info->sc_loc_x);
+
+ if ((info->sc_flags & UMS_FLAG_Y_AXIS) &&
+ (id == info->sc_iid_y))
+ dy = -hid_get_data(buf, len, &info->sc_loc_y);
+
+ if ((info->sc_flags & UMS_FLAG_Z_AXIS) &&
+ (id == info->sc_iid_z)) {
+ int32_t temp;
+ temp = hid_get_data(buf, len, &info->sc_loc_z);
+ if (info->sc_flags & UMS_FLAG_REVZ)
+ temp = -temp;
+ dz -= temp;
+ }
- if ((sc->sc_flags & UMS_FLAG_T_AXIS) && (id == sc->sc_iid_t))
- dt = -hid_get_data(buf, len, &sc->sc_loc_t);
- else
- dt = 0;
+ if ((info->sc_flags & UMS_FLAG_T_AXIS) &&
+ (id == info->sc_iid_t))
+ dt -= hid_get_data(buf, len, &info->sc_loc_t);
- for (i = 0; i < sc->sc_buttons; i++) {
- if (id != sc->sc_iid_btn[i])
+ for (i = 0; i < info->sc_buttons; i++) {
+ if (id != info->sc_iid_btn[i])
continue;
- if (hid_get_data(buf, len, &sc->sc_loc_btn[i])) {
+ if (hid_get_data(buf, len, &info->sc_loc_btn[i])) {
buttons |= (1 << UMS_BUT(i));
}
}
+ if (++info != &sc->sc_info[UMS_INFO_MAX])
+ goto repeat;
+
if (dx || dy || dz || dt || dw ||
(buttons != sc->sc_status.button)) {
@@ -273,7 +283,7 @@ ums_intr_callback(struct usb2_xfer *xfer)
* to the queue. In any other case we delete
* the timeout event.
*/
- if ((sc->sc_flags & UMS_FLAG_SBU) &&
+ if ((sc->sc_info[0].sc_flags & UMS_FLAG_SBU) &&
(dx == 0) && (dy == 0) && (dz == 0) && (dt == 0) &&
(dw == 0) && (buttons == 0)) {
@@ -312,9 +322,9 @@ static const struct usb2_config ums_config[UMS_N_TRANSFER] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = &ums_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &ums_intr_callback,
},
};
@@ -338,7 +348,7 @@ ums_probe(device_t dev)
(id->bInterfaceClass != UICLASS_HID))
return (ENXIO);
- error = usb2_req_get_hid_desc(uaa->device, &Giant,
+ error = usb2_req_get_hid_desc(uaa->device, NULL,
&d_ptr, &d_len, M_TEMP, uaa->info.bIfaceIndex);
if (error)
@@ -357,90 +367,56 @@ ums_probe(device_t dev)
return (error);
}
-static int
-ums_attach(device_t dev)
+static void
+ums_hid_parse(struct ums_softc *sc, device_t dev, const uint8_t *buf,
+ uint16_t len, uint8_t index)
{
- struct usb2_attach_arg *uaa = device_get_ivars(dev);
- struct ums_softc *sc = device_get_softc(dev);
- void *d_ptr = NULL;
- int unit = device_get_unit(dev);
- int isize;
- int isizebits;
- int err;
+ struct ums_info *info = &sc->sc_info[index];
uint32_t flags;
- uint16_t d_len;
uint8_t i;
- DPRINTFN(11, "sc=%p\n", sc);
-
- device_set_usb2_desc(dev);
-
- mtx_init(&sc->sc_mtx, "ums lock", NULL, MTX_DEF | MTX_RECURSE);
-
- usb2_callout_init_mtx(&sc->sc_callout, &sc->sc_mtx, 0);
-
- /*
- * Force the report (non-boot) protocol.
- *
- * Mice without boot protocol support may choose not to implement
- * Set_Protocol at all; Ignore any error.
- */
- err = usb2_req_set_protocol(uaa->device, NULL, uaa->info.bIfaceIndex, 1);
-
- err = usb2_transfer_setup(uaa->device,
- &uaa->info.bIfaceIndex, sc->sc_xfer, ums_config,
- UMS_N_TRANSFER, sc, &sc->sc_mtx);
-
- if (err) {
- DPRINTF("error=%s\n", usb2_errstr(err));
- goto detach;
- }
- err = usb2_req_get_hid_desc
- (uaa->device, &Giant, &d_ptr,
- &d_len, M_TEMP, uaa->info.bIfaceIndex);
-
- if (err) {
- device_printf(dev, "error reading report description\n");
- goto detach;
- }
- if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
- hid_input, &sc->sc_loc_x, &flags, &sc->sc_iid_x)) {
+ if (hid_locate(buf, len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
+ hid_input, index, &info->sc_loc_x, &flags, &info->sc_iid_x)) {
if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) {
- sc->sc_flags |= UMS_FLAG_X_AXIS;
+ info->sc_flags |= UMS_FLAG_X_AXIS;
}
}
- if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
- hid_input, &sc->sc_loc_y, &flags, &sc->sc_iid_y)) {
+ if (hid_locate(buf, len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
+ hid_input, index, &info->sc_loc_y, &flags, &info->sc_iid_y)) {
if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) {
- sc->sc_flags |= UMS_FLAG_Y_AXIS;
+ info->sc_flags |= UMS_FLAG_Y_AXIS;
}
}
/* Try the wheel first as the Z activator since it's tradition. */
- if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP,
- HUG_WHEEL), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid_z) ||
- hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP,
- HUG_TWHEEL), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid_z)) {
+ if (hid_locate(buf, len, HID_USAGE2(HUP_GENERIC_DESKTOP,
+ HUG_WHEEL), hid_input, index, &info->sc_loc_z, &flags,
+ &info->sc_iid_z) ||
+ hid_locate(buf, len, HID_USAGE2(HUP_GENERIC_DESKTOP,
+ HUG_TWHEEL), hid_input, index, &info->sc_loc_z, &flags,
+ &info->sc_iid_z)) {
if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) {
- sc->sc_flags |= UMS_FLAG_Z_AXIS;
+ info->sc_flags |= UMS_FLAG_Z_AXIS;
}
/*
* We might have both a wheel and Z direction, if so put
* put the Z on the W coordinate.
*/
- if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP,
- HUG_Z), hid_input, &sc->sc_loc_w, &flags, &sc->sc_iid_w)) {
+ if (hid_locate(buf, len, HID_USAGE2(HUP_GENERIC_DESKTOP,
+ HUG_Z), hid_input, index, &info->sc_loc_w, &flags,
+ &info->sc_iid_w)) {
if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) {
- sc->sc_flags |= UMS_FLAG_W_AXIS;
+ info->sc_flags |= UMS_FLAG_W_AXIS;
}
}
- } else if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP,
- HUG_Z), hid_input, &sc->sc_loc_z, &flags, &sc->sc_iid_z)) {
+ } else if (hid_locate(buf, len, HID_USAGE2(HUP_GENERIC_DESKTOP,
+ HUG_Z), hid_input, index, &info->sc_loc_z, &flags,
+ &info->sc_iid_z)) {
if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) {
- sc->sc_flags |= UMS_FLAG_Z_AXIS;
+ info->sc_flags |= UMS_FLAG_Z_AXIS;
}
}
/*
@@ -450,25 +426,89 @@ ums_attach(device_t dev)
* There are no other HID axis descriptors other than X,Y and
* TWHEEL
*/
- if (hid_locate(d_ptr, d_len, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_TWHEEL),
- hid_input, &sc->sc_loc_t, &flags, &sc->sc_iid_t)) {
+ if (hid_locate(buf, len, HID_USAGE2(HUP_GENERIC_DESKTOP,
+ HUG_TWHEEL), hid_input, index, &info->sc_loc_t,
+ &flags, &info->sc_iid_t)) {
- sc->sc_loc_t.pos += 8;
+ info->sc_loc_t.pos += 8;
if ((flags & MOUSE_FLAGS_MASK) == MOUSE_FLAGS) {
- sc->sc_flags |= UMS_FLAG_T_AXIS;
+ info->sc_flags |= UMS_FLAG_T_AXIS;
}
}
/* figure out the number of buttons */
for (i = 0; i < UMS_BUTTON_MAX; i++) {
- if (!hid_locate(d_ptr, d_len, HID_USAGE2(HUP_BUTTON, (i + 1)),
- hid_input, &sc->sc_loc_btn[i], NULL, &sc->sc_iid_btn[i])) {
+ if (!hid_locate(buf, len, HID_USAGE2(HUP_BUTTON, (i + 1)),
+ hid_input, index, &info->sc_loc_btn[i], NULL,
+ &info->sc_iid_btn[i])) {
break;
}
}
+ info->sc_buttons = i;
+
+ if (i > sc->sc_buttons)
+ sc->sc_buttons = i;
+
+ if (info->sc_flags == 0)
+ return;
+
+ /* announce information about the mouse */
+ device_printf(dev, "%d buttons and [%s%s%s%s%s] coordinates ID=%u\n",
+ (info->sc_buttons),
+ (info->sc_flags & UMS_FLAG_X_AXIS) ? "X" : "",
+ (info->sc_flags & UMS_FLAG_Y_AXIS) ? "Y" : "",
+ (info->sc_flags & UMS_FLAG_Z_AXIS) ? "Z" : "",
+ (info->sc_flags & UMS_FLAG_T_AXIS) ? "T" : "",
+ (info->sc_flags & UMS_FLAG_W_AXIS) ? "W" : "",
+ info->sc_iid_x);
+}
+
+static int
+ums_attach(device_t dev)
+{
+ struct usb2_attach_arg *uaa = device_get_ivars(dev);
+ struct ums_softc *sc = device_get_softc(dev);
+ struct ums_info *info;
+ void *d_ptr = NULL;
+ int isize;
+ int err;
+ uint16_t d_len;
+ uint8_t i;
+ uint8_t j;
+
+ DPRINTFN(11, "sc=%p\n", sc);
+
+ device_set_usb2_desc(dev);
+
+ mtx_init(&sc->sc_mtx, "ums lock", NULL, MTX_DEF | MTX_RECURSE);
+
+ usb2_callout_init_mtx(&sc->sc_callout, &sc->sc_mtx, 0);
+
+ /*
+ * Force the report (non-boot) protocol.
+ *
+ * Mice without boot protocol support may choose not to implement
+ * Set_Protocol at all; Ignore any error.
+ */
+ err = usb2_req_set_protocol(uaa->device, NULL,
+ uaa->info.bIfaceIndex, 1);
+
+ err = usb2_transfer_setup(uaa->device,
+ &uaa->info.bIfaceIndex, sc->sc_xfer, ums_config,
+ UMS_N_TRANSFER, sc, &sc->sc_mtx);
+
+ if (err) {
+ DPRINTF("error=%s\n", usb2_errstr(err));
+ goto detach;
+ }
+ err = usb2_req_get_hid_desc(uaa->device, NULL, &d_ptr,
+ &d_len, M_TEMP, uaa->info.bIfaceIndex);
- sc->sc_buttons = i;
+ if (err) {
+ device_printf(dev, "error reading report description\n");
+ goto detach;
+ }
isize = hid_report_size(d_ptr, d_len, hid_input, &sc->sc_iid);
@@ -479,83 +519,66 @@ ums_attach(device_t dev)
* it has two addional buttons and a tilt wheel.
*/
if (usb2_test_quirk(uaa, UQ_MS_BAD_CLASS)) {
- sc->sc_flags = (UMS_FLAG_X_AXIS |
+ info = &sc->sc_info[0];
+ info->sc_flags = (UMS_FLAG_X_AXIS |
UMS_FLAG_Y_AXIS |
UMS_FLAG_Z_AXIS |
UMS_FLAG_SBU);
- sc->sc_buttons = 3;
+ info->sc_buttons = 3;
isize = 5;
- sc->sc_iid = 0;
- sc->sc_iid_x = 0;
- sc->sc_iid_y = 0;
- sc->sc_iid_z = 0;
- sc->sc_iid_btn[0] = 0;
- sc->sc_iid_btn[1] = 0;
- sc->sc_iid_btn[2] = 0;
/* 1st byte of descriptor report contains garbage */
- sc->sc_loc_x.pos = 16;
- sc->sc_loc_y.pos = 24;
- sc->sc_loc_z.pos = 32;
- sc->sc_loc_btn[0].pos = 8;
- sc->sc_loc_btn[1].pos = 9;
- sc->sc_loc_btn[2].pos = 10;
- }
+ info->sc_loc_x.pos = 16;
+ info->sc_loc_y.pos = 24;
+ info->sc_loc_z.pos = 32;
+ info->sc_loc_btn[0].pos = 8;
+ info->sc_loc_btn[1].pos = 9;
+ info->sc_loc_btn[2].pos = 10;
- /*
- * Some Microsoft devices have incorrectly high location
- * positions. Correct this:
- */
- isizebits = isize * 8;
- if ((sc->sc_iid != 0) && (isizebits > 8)) {
- isizebits -= 8; /* remove size of report ID */
- sc->sc_loc_w.pos %= isizebits;
- sc->sc_loc_x.pos %= isizebits;
- sc->sc_loc_y.pos %= isizebits;
- sc->sc_loc_z.pos %= isizebits;
- sc->sc_loc_t.pos %= isizebits;
- for (i = 0; i != UMS_BUTTON_MAX; i++)
- sc->sc_loc_btn[i].pos %= isizebits;
+ /* Announce device */
+ device_printf(dev, "3 buttons and [XYZ] "
+ "coordinates ID=0\n");
+
+ } else {
+ /* Search the HID descriptor and announce device */
+ for (i = 0; i < UMS_INFO_MAX; i++) {
+ ums_hid_parse(sc, dev, d_ptr, d_len, i);
+ }
}
if (usb2_test_quirk(uaa, UQ_MS_REVZ)) {
+ info = &sc->sc_info[0];
/* Some wheels need the Z axis reversed. */
- sc->sc_flags |= UMS_FLAG_REVZ;
+ info->sc_flags |= UMS_FLAG_REVZ;
}
if (isize > sc->sc_xfer[UMS_INTR_DT]->max_frame_size) {
DPRINTF("WARNING: report size, %d bytes, is larger "
"than interrupt size, %d bytes!\n",
isize, sc->sc_xfer[UMS_INTR_DT]->max_frame_size);
}
- /* announce information about the mouse */
-
- device_printf(dev, "%d buttons and [%s%s%s%s%s] coordinates\n",
- (sc->sc_buttons),
- (sc->sc_flags & UMS_FLAG_X_AXIS) ? "X" : "",
- (sc->sc_flags & UMS_FLAG_Y_AXIS) ? "Y" : "",
- (sc->sc_flags & UMS_FLAG_Z_AXIS) ? "Z" : "",
- (sc->sc_flags & UMS_FLAG_T_AXIS) ? "T" : "",
- (sc->sc_flags & UMS_FLAG_W_AXIS) ? "W" : "");
-
free(d_ptr, M_TEMP);
d_ptr = NULL;
#if USB_DEBUG
- DPRINTF("sc=%p\n", sc);
- DPRINTF("X\t%d/%d id=%d\n", sc->sc_loc_x.pos,
- sc->sc_loc_x.size, sc->sc_iid_x);
- DPRINTF("Y\t%d/%d id=%d\n", sc->sc_loc_y.pos,
- sc->sc_loc_y.size, sc->sc_iid_y);
- DPRINTF("Z\t%d/%d id=%d\n", sc->sc_loc_z.pos,
- sc->sc_loc_z.size, sc->sc_iid_z);
- DPRINTF("T\t%d/%d id=%d\n", sc->sc_loc_t.pos,
- sc->sc_loc_t.size, sc->sc_iid_t);
- DPRINTF("W\t%d/%d id=%d\n", sc->sc_loc_w.pos,
- sc->sc_loc_w.size, sc->sc_iid_w);
-
- for (i = 0; i < sc->sc_buttons; i++) {
- DPRINTF("B%d\t%d/%d id=%d\n",
- i + 1, sc->sc_loc_btn[i].pos,
- sc->sc_loc_btn[i].size, sc->sc_iid_btn[i]);
+ for (j = 0; j < UMS_INFO_MAX; j++) {
+ info = &sc->sc_info[j];
+
+ DPRINTF("sc=%p, index=%d\n", sc, j);
+ DPRINTF("X\t%d/%d id=%d\n", info->sc_loc_x.pos,
+ info->sc_loc_x.size, info->sc_iid_x);
+ DPRINTF("Y\t%d/%d id=%d\n", info->sc_loc_y.pos,
+ info->sc_loc_y.size, info->sc_iid_y);
+ DPRINTF("Z\t%d/%d id=%d\n", info->sc_loc_z.pos,
+ info->sc_loc_z.size, info->sc_iid_z);
+ DPRINTF("T\t%d/%d id=%d\n", info->sc_loc_t.pos,
+ info->sc_loc_t.size, info->sc_iid_t);
+ DPRINTF("W\t%d/%d id=%d\n", info->sc_loc_w.pos,
+ info->sc_loc_w.size, info->sc_iid_w);
+
+ for (i = 0; i < info->sc_buttons; i++) {
+ DPRINTF("B%d\t%d/%d id=%d\n",
+ i + 1, info->sc_loc_btn[i].pos,
+ info->sc_loc_btn[i].size, info->sc_iid_btn[i]);
+ }
}
DPRINTF("size=%d, id=%d\n", isize, sc->sc_iid);
#endif
@@ -579,16 +602,9 @@ ums_attach(device_t dev)
sc->sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
sc->sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
- sc->sc_status.flags = 0;
- sc->sc_status.button = 0;
- sc->sc_status.obutton = 0;
- sc->sc_status.dx = 0;
- sc->sc_status.dy = 0;
- sc->sc_status.dz = 0;
-
err = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx,
&ums_fifo_methods, &sc->sc_fifo,
- unit, 0 - 1, uaa->info.bIfaceIndex,
+ device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex,
UID_ROOT, GID_OPERATOR, 0644);
if (err) {
goto detach;
diff --git a/sys/dev/usb/misc/udbp.c b/sys/dev/usb/misc/udbp.c
index 2b40ff1..e8acba8 100644
--- a/sys/dev/usb/misc/udbp.c
+++ b/sys/dev/usb/misc/udbp.c
@@ -192,41 +192,39 @@ static const struct usb2_config udbp_config[UDBP_T_MAX] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UDBP_BUFFERSIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &udbp_bulk_write_callback,
- .mh.timeout = UDBP_TIMEOUT,
+ .bufsize = UDBP_BUFFERSIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &udbp_bulk_write_callback,
+ .timeout = UDBP_TIMEOUT,
},
[UDBP_T_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UDBP_BUFFERSIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &udbp_bulk_read_callback,
+ .bufsize = UDBP_BUFFERSIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &udbp_bulk_read_callback,
},
[UDBP_T_WR_CS] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &udbp_bulk_write_clear_stall_callback,
- .mh.timeout = 1000, /* 1 second */
- .mh.interval = 50, /* 50ms */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &udbp_bulk_write_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
},
[UDBP_T_RD_CS] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &udbp_bulk_read_clear_stall_callback,
- .mh.timeout = 1000, /* 1 second */
- .mh.interval = 50, /* 50ms */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &udbp_bulk_read_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
},
};
diff --git a/sys/dev/usb/net/if_aue.c b/sys/dev/usb/net/if_aue.c
index b014b01..ca72948 100644
--- a/sys/dev/usb/net/if_aue.c
+++ b/sys/dev/usb/net/if_aue.c
@@ -209,28 +209,28 @@ static const struct usb2_config aue_config[AUE_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = (MCLBYTES + 2),
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = aue_bulk_write_callback,
- .mh.timeout = 10000, /* 10 seconds */
+ .bufsize = (MCLBYTES + 2),
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = aue_bulk_write_callback,
+ .timeout = 10000, /* 10 seconds */
},
[AUE_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = (MCLBYTES + 4 + ETHER_CRC_LEN),
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = aue_bulk_read_callback,
+ .bufsize = (MCLBYTES + 4 + ETHER_CRC_LEN),
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = aue_bulk_read_callback,
},
[AUE_INTR_DT_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = aue_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = aue_intr_callback,
},
};
diff --git a/sys/dev/usb/net/if_axe.c b/sys/dev/usb/net/if_axe.c
index 43ac676..c0db84b 100644
--- a/sys/dev/usb/net/if_axe.c
+++ b/sys/dev/usb/net/if_axe.c
@@ -182,10 +182,10 @@ static const struct usb2_config axe_config[AXE_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = AXE_BULK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = axe_bulk_write_callback,
- .mh.timeout = 10000, /* 10 seconds */
+ .bufsize = AXE_BULK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = axe_bulk_write_callback,
+ .timeout = 10000, /* 10 seconds */
},
[AXE_BULK_DT_RD] = {
@@ -195,19 +195,19 @@ static const struct usb2_config axe_config[AXE_N_TRANSFER] = {
#if (MCLBYTES < 2048)
#error "(MCLBYTES < 2048)"
#endif
- .mh.bufsize = MCLBYTES,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = axe_bulk_read_callback,
- .mh.timeout = 0, /* no timeout */
+ .bufsize = MCLBYTES,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = axe_bulk_read_callback,
+ .timeout = 0, /* no timeout */
},
[AXE_INTR_DT_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = axe_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = axe_intr_callback,
},
};
diff --git a/sys/dev/usb/net/if_cdce.c b/sys/dev/usb/net/if_cdce.c
index a54ddc0..9a9cb37 100644
--- a/sys/dev/usb/net/if_cdce.c
+++ b/sys/dev/usb/net/if_cdce.c
@@ -48,7 +48,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb_cdc.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR cdce_debug
@@ -97,59 +96,54 @@ SYSCTL_INT(_hw_usb2_cdce, OID_AUTO, debug, CTLFLAG_RW, &cdce_debug, 0,
static const struct usb2_config cdce_config[CDCE_N_TRANSFER] = {
- [CDCE_BULK_A] = {
+ [CDCE_BULK_RX] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_OUT,
+ .direction = UE_DIR_RX,
.if_index = 0,
- /* Host Mode */
- .mh.frames = CDCE_FRAMES_MAX,
- .mh.bufsize = (CDCE_FRAMES_MAX * MCLBYTES),
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,},
- .mh.callback = cdce_bulk_write_callback,
- .mh.timeout = 10000, /* 10 seconds */
- /* Device Mode */
- .md.frames = CDCE_FRAMES_MAX,
- .md.bufsize = (CDCE_FRAMES_MAX * MCLBYTES),
- .md.flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,},
- .md.callback = cdce_bulk_read_callback,
- .md.timeout = 0, /* no timeout */
+ .frames = CDCE_FRAMES_MAX,
+ .bufsize = (CDCE_FRAMES_MAX * MCLBYTES),
+ .flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,},
+ .callback = cdce_bulk_read_callback,
+ .timeout = 0, /* no timeout */
+ .usb_mode = USB_MODE_MAX, /* both modes */
},
- [CDCE_BULK_B] = {
+ [CDCE_BULK_TX] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_IN,
+ .direction = UE_DIR_TX,
.if_index = 0,
- /* Host Mode */
- .mh.frames = CDCE_FRAMES_MAX,
- .mh.bufsize = (CDCE_FRAMES_MAX * MCLBYTES),
- .mh.flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,},
- .mh.callback = cdce_bulk_read_callback,
- .mh.timeout = 0, /* no timeout */
- /* Device Mode */
- .md.frames = CDCE_FRAMES_MAX,
- .md.bufsize = (CDCE_FRAMES_MAX * MCLBYTES),
- .md.flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,},
- .md.callback = cdce_bulk_write_callback,
- .md.timeout = 10000, /* 10 seconds */
+ .frames = CDCE_FRAMES_MAX,
+ .bufsize = (CDCE_FRAMES_MAX * MCLBYTES),
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,},
+ .callback = cdce_bulk_write_callback,
+ .timeout = 10000, /* 10 seconds */
+ .usb_mode = USB_MODE_MAX, /* both modes */
},
- [CDCE_INTR] = {
+ [CDCE_INTR_RX] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
- .direction = UE_DIR_IN,
+ .direction = UE_DIR_RX,
.if_index = 1,
- /* Host Mode */
- .mh.bufsize = CDCE_IND_SIZE_MAX,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
- .mh.callback = cdce_intr_read_callback,
- .mh.timeout = 0,
- /* Device Mode */
- .md.bufsize = CDCE_IND_SIZE_MAX,
- .md.flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,},
- .md.callback = cdce_intr_write_callback,
- .md.timeout = 10000, /* 10 seconds */
+ .bufsize = CDCE_IND_SIZE_MAX,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
+ .callback = cdce_intr_read_callback,
+ .timeout = 0,
+ .usb_mode = USB_MODE_HOST,
+ },
+
+ [CDCE_INTR_TX] = {
+ .type = UE_INTERRUPT,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_TX,
+ .if_index = 1,
+ .bufsize = CDCE_IND_SIZE_MAX,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,},
+ .callback = cdce_intr_write_callback,
+ .timeout = 10000, /* 10 seconds */
+ .usb_mode = USB_MODE_DEVICE,
},
};
@@ -417,8 +411,8 @@ cdce_start(struct usb2_ether *ue)
/*
* Start the USB transfers, if not already started:
*/
- usb2_transfer_start(sc->sc_xfer[CDCE_BULK_B]);
- usb2_transfer_start(sc->sc_xfer[CDCE_BULK_A]);
+ usb2_transfer_start(sc->sc_xfer[CDCE_BULK_TX]);
+ usb2_transfer_start(sc->sc_xfer[CDCE_BULK_RX]);
}
static void
@@ -558,13 +552,11 @@ cdce_init(struct usb2_ether *ue)
ifp->if_drv_flags |= IFF_DRV_RUNNING;
/* start interrupt transfer */
- usb2_transfer_start(sc->sc_xfer[CDCE_INTR]);
+ usb2_transfer_start(sc->sc_xfer[CDCE_INTR_RX]);
+ usb2_transfer_start(sc->sc_xfer[CDCE_INTR_TX]);
/* stall data write direction, which depends on USB mode */
- if (usb2_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST)
- usb2_transfer_set_stall(sc->sc_xfer[CDCE_BULK_A]);
- else
- usb2_transfer_set_stall(sc->sc_xfer[CDCE_BULK_B]);
+ usb2_transfer_set_stall(sc->sc_xfer[CDCE_BULK_TX]);
/* start data transfers */
cdce_start(ue);
@@ -583,9 +575,10 @@ cdce_stop(struct usb2_ether *ue)
/*
* stop all the transfers, if not already stopped:
*/
- usb2_transfer_stop(sc->sc_xfer[CDCE_BULK_A]);
- usb2_transfer_stop(sc->sc_xfer[CDCE_BULK_B]);
- usb2_transfer_stop(sc->sc_xfer[CDCE_INTR]);
+ usb2_transfer_stop(sc->sc_xfer[CDCE_BULK_RX]);
+ usb2_transfer_stop(sc->sc_xfer[CDCE_BULK_TX]);
+ usb2_transfer_stop(sc->sc_xfer[CDCE_INTR_RX]);
+ usb2_transfer_stop(sc->sc_xfer[CDCE_INTR_TX]);
}
static void
diff --git a/sys/dev/usb/net/if_cdcereg.h b/sys/dev/usb/net/if_cdcereg.h
index dac5121..0bcdde7 100644
--- a/sys/dev/usb/net/if_cdcereg.h
+++ b/sys/dev/usb/net/if_cdcereg.h
@@ -39,9 +39,10 @@
#define CDCE_IND_SIZE_MAX 32 /* bytes */
enum {
- CDCE_BULK_A,
- CDCE_BULK_B,
- CDCE_INTR,
+ CDCE_BULK_RX,
+ CDCE_BULK_TX,
+ CDCE_INTR_RX,
+ CDCE_INTR_TX,
CDCE_N_TRANSFER,
};
diff --git a/sys/dev/usb/net/if_cue.c b/sys/dev/usb/net/if_cue.c
index 54bff1d..10fd038 100644
--- a/sys/dev/usb/net/if_cue.c
+++ b/sys/dev/usb/net/if_cue.c
@@ -121,19 +121,19 @@ static const struct usb2_config cue_config[CUE_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = (MCLBYTES + 2),
- .mh.flags = {.pipe_bof = 1,},
- .mh.callback = cue_bulk_write_callback,
- .mh.timeout = 10000, /* 10 seconds */
+ .bufsize = (MCLBYTES + 2),
+ .flags = {.pipe_bof = 1,},
+ .callback = cue_bulk_write_callback,
+ .timeout = 10000, /* 10 seconds */
},
[CUE_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = (MCLBYTES + 2),
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = cue_bulk_read_callback,
+ .bufsize = (MCLBYTES + 2),
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = cue_bulk_read_callback,
},
};
diff --git a/sys/dev/usb/net/if_kue.c b/sys/dev/usb/net/if_kue.c
index 8a648a4..3056692 100644
--- a/sys/dev/usb/net/if_kue.c
+++ b/sys/dev/usb/net/if_kue.c
@@ -163,20 +163,20 @@ static const struct usb2_config kue_config[KUE_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = (MCLBYTES + 2 + 64),
- .mh.flags = {.pipe_bof = 1,},
- .mh.callback = kue_bulk_write_callback,
- .mh.timeout = 10000, /* 10 seconds */
+ .bufsize = (MCLBYTES + 2 + 64),
+ .flags = {.pipe_bof = 1,},
+ .callback = kue_bulk_write_callback,
+ .timeout = 10000, /* 10 seconds */
},
[KUE_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = (MCLBYTES + 2),
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = kue_bulk_read_callback,
- .mh.timeout = 0, /* no timeout */
+ .bufsize = (MCLBYTES + 2),
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = kue_bulk_read_callback,
+ .timeout = 0, /* no timeout */
},
};
diff --git a/sys/dev/usb/net/if_rue.c b/sys/dev/usb/net/if_rue.c
index 73958d1..dc7a31f 100644
--- a/sys/dev/usb/net/if_rue.c
+++ b/sys/dev/usb/net/if_rue.c
@@ -141,29 +141,29 @@ static const struct usb2_config rue_config[RUE_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = MCLBYTES,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = rue_bulk_write_callback,
- .mh.timeout = 10000, /* 10 seconds */
+ .bufsize = MCLBYTES,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = rue_bulk_write_callback,
+ .timeout = 10000, /* 10 seconds */
},
[RUE_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = (MCLBYTES + 4),
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = rue_bulk_read_callback,
- .mh.timeout = 0, /* no timeout */
+ .bufsize = (MCLBYTES + 4),
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = rue_bulk_read_callback,
+ .timeout = 0, /* no timeout */
},
[RUE_INTR_DT_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = rue_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = rue_intr_callback,
},
};
diff --git a/sys/dev/usb/net/if_udav.c b/sys/dev/usb/net/if_udav.c
index 76cdef4..5962d19 100644
--- a/sys/dev/usb/net/if_udav.c
+++ b/sys/dev/usb/net/if_udav.c
@@ -101,29 +101,29 @@ static const struct usb2_config udav_config[UDAV_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = (MCLBYTES + 2),
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = udav_bulk_write_callback,
- .mh.timeout = 10000, /* 10 seconds */
+ .bufsize = (MCLBYTES + 2),
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = udav_bulk_write_callback,
+ .timeout = 10000, /* 10 seconds */
},
[UDAV_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = (MCLBYTES + 3),
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = udav_bulk_read_callback,
- .mh.timeout = 0, /* no timeout */
+ .bufsize = (MCLBYTES + 3),
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = udav_bulk_read_callback,
+ .timeout = 0, /* no timeout */
},
[UDAV_INTR_DT_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = udav_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = udav_intr_callback,
},
};
diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c
index 4b79aae..19009c6 100644
--- a/sys/dev/usb/serial/u3g.c
+++ b/sys/dev/usb/serial/u3g.c
@@ -34,7 +34,6 @@
#include <dev/usb/usb.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR u3g_debug
@@ -117,18 +116,18 @@ static const struct usb2_config u3g_config[U3G_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = U3G_BSIZE,/* bytes */
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &u3g_write_callback,
+ .bufsize = U3G_BSIZE,/* bytes */
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &u3g_write_callback,
},
[U3G_BULK_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = U3G_BSIZE,/* bytes */
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &u3g_read_callback,
+ .bufsize = U3G_BSIZE,/* bytes */
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &u3g_read_callback,
},
};
diff --git a/sys/dev/usb/serial/uark.c b/sys/dev/usb/serial/uark.c
index e0f9db7a5..bc0bace 100644
--- a/sys/dev/usb/serial/uark.c
+++ b/sys/dev/usb/serial/uark.c
@@ -106,18 +106,18 @@ static const struct usb2_config
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UARK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &uark_bulk_write_callback,
+ .bufsize = UARK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &uark_bulk_write_callback,
},
[UARK_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UARK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &uark_bulk_read_callback,
+ .bufsize = UARK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &uark_bulk_read_callback,
},
};
diff --git a/sys/dev/usb/serial/ubsa.c b/sys/dev/usb/serial/ubsa.c
index 244ca65..a52c828 100644
--- a/sys/dev/usb/serial/ubsa.c
+++ b/sys/dev/usb/serial/ubsa.c
@@ -188,27 +188,27 @@ static const struct usb2_config ubsa_config[UBSA_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UBSA_BSIZE, /* bytes */
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &ubsa_write_callback,
+ .bufsize = UBSA_BSIZE, /* bytes */
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &ubsa_write_callback,
},
[UBSA_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UBSA_BSIZE, /* bytes */
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &ubsa_read_callback,
+ .bufsize = UBSA_BSIZE, /* bytes */
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &ubsa_read_callback,
},
[UBSA_INTR_DT_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = &ubsa_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &ubsa_intr_callback,
},
};
diff --git a/sys/dev/usb/serial/ubser.c b/sys/dev/usb/serial/ubser.c
index 3aaad78..6ec67ae 100644
--- a/sys/dev/usb/serial/ubser.c
+++ b/sys/dev/usb/serial/ubser.c
@@ -80,7 +80,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb_cdc.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR ubser_debug
@@ -157,18 +156,18 @@ static const struct usb2_config ubser_config[UBSER_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &ubser_write_callback,
+ .bufsize = 0, /* use wMaxPacketSize */
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &ubser_write_callback,
},
[UBSER_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &ubser_read_callback,
+ .bufsize = 0, /* use wMaxPacketSize */
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &ubser_read_callback,
},
};
@@ -244,8 +243,8 @@ ubser_attach(device_t dev)
req.wIndex[0] = sc->sc_iface_no;
req.wIndex[1] = 0;
USETW(req.wLength, 1);
- error = usb2_do_request_flags
- (uaa->device, &Giant, &req, &sc->sc_numser,
+ error = usb2_do_request_flags(uaa->device, NULL,
+ &req, &sc->sc_numser,
0, NULL, USB_DEFAULT_TIMEOUT);
if (error || (sc->sc_numser == 0)) {
diff --git a/sys/dev/usb/serial/uchcom.c b/sys/dev/usb/serial/uchcom.c
index b99f048..413fb12 100644
--- a/sys/dev/usb/serial/uchcom.c
+++ b/sys/dev/usb/serial/uchcom.c
@@ -233,27 +233,27 @@ static const struct usb2_config uchcom_config_data[UCHCOM_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UCHCOM_BULK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &uchcom_write_callback,
+ .bufsize = UCHCOM_BULK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &uchcom_write_callback,
},
[UCHCOM_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UCHCOM_BULK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &uchcom_read_callback,
+ .bufsize = UCHCOM_BULK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &uchcom_read_callback,
},
[UCHCOM_INTR_DT_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = &uchcom_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &uchcom_intr_callback,
},
};
diff --git a/sys/dev/usb/serial/ucycom.c b/sys/dev/usb/serial/ucycom.c
index ff965ca..a044c00 100644
--- a/sys/dev/usb/serial/ucycom.c
+++ b/sys/dev/usb/serial/ucycom.c
@@ -120,19 +120,18 @@ static const struct usb2_config ucycom_config[UCYCOM_N_TRANSFER] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = (sizeof(struct usb2_device_request) + UCYCOM_MAX_IOLEN),
- .mh.flags = {},
- .mh.callback = &ucycom_ctrl_write_callback,
- .mh.timeout = 1000, /* 1 second */
+ .bufsize = (sizeof(struct usb2_device_request) + UCYCOM_MAX_IOLEN),
+ .callback = &ucycom_ctrl_write_callback,
+ .timeout = 1000, /* 1 second */
},
[UCYCOM_INTR_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = UCYCOM_MAX_IOLEN,
- .mh.callback = &ucycom_intr_read_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = UCYCOM_MAX_IOLEN,
+ .callback = &ucycom_intr_read_callback,
},
};
@@ -222,8 +221,7 @@ ucycom_attach(device_t dev)
/* get report descriptor */
- error = usb2_req_get_hid_desc
- (uaa->device, &Giant,
+ error = usb2_req_get_hid_desc(uaa->device, NULL,
&urd_ptr, &urd_len, M_USBDEV,
UCYCOM_IFACE_INDEX);
diff --git a/sys/dev/usb/serial/ufoma.c b/sys/dev/usb/serial/ufoma.c
index f29e44c..62471e7 100644
--- a/sys/dev/usb/serial/ufoma.c
+++ b/sys/dev/usb/serial/ufoma.c
@@ -232,29 +232,28 @@ static const struct usb2_config
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = sizeof(struct usb2_cdc_notification),
- .mh.callback = &ufoma_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = sizeof(struct usb2_cdc_notification),
+ .callback = &ufoma_intr_callback,
},
[UFOMA_CTRL_ENDPT_READ] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = (sizeof(struct usb2_device_request) + UFOMA_CMD_BUF_SIZE),
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.callback = &ufoma_ctrl_read_callback,
- .mh.timeout = 1000, /* 1 second */
+ .bufsize = (sizeof(struct usb2_device_request) + UFOMA_CMD_BUF_SIZE),
+ .flags = {.short_xfer_ok = 1,},
+ .callback = &ufoma_ctrl_read_callback,
+ .timeout = 1000, /* 1 second */
},
[UFOMA_CTRL_ENDPT_WRITE] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = (sizeof(struct usb2_device_request) + 1),
- .mh.flags = {},
- .mh.callback = &ufoma_ctrl_write_callback,
- .mh.timeout = 1000, /* 1 second */
+ .bufsize = (sizeof(struct usb2_device_request) + 1),
+ .callback = &ufoma_ctrl_write_callback,
+ .timeout = 1000, /* 1 second */
},
};
@@ -265,18 +264,18 @@ static const struct usb2_config
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UFOMA_BULK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &ufoma_bulk_write_callback,
+ .bufsize = UFOMA_BULK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &ufoma_bulk_write_callback,
},
[UFOMA_BULK_ENDPT_READ] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UFOMA_BULK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &ufoma_bulk_read_callback,
+ .bufsize = UFOMA_BULK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &ufoma_bulk_read_callback,
},
};
diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c
index d03638f..c075b06 100644
--- a/sys/dev/usb/serial/uftdi.c
+++ b/sys/dev/usb/serial/uftdi.c
@@ -150,18 +150,18 @@ static const struct usb2_config uftdi_config[UFTDI_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UFTDI_OBUFSIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &uftdi_write_callback,
+ .bufsize = UFTDI_OBUFSIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &uftdi_write_callback,
},
[UFTDI_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UFTDI_IBUFSIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &uftdi_read_callback,
+ .bufsize = UFTDI_IBUFSIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &uftdi_read_callback,
},
};
diff --git a/sys/dev/usb/serial/ugensa.c b/sys/dev/usb/serial/ugensa.c
index c85e57d..f370e1b 100644
--- a/sys/dev/usb/serial/ugensa.c
+++ b/sys/dev/usb/serial/ugensa.c
@@ -47,7 +47,6 @@
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb_cdc.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR usb2_debug
@@ -107,18 +106,18 @@ static const struct usb2_config
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UGENSA_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &ugensa_bulk_write_callback,
+ .bufsize = UGENSA_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &ugensa_bulk_write_callback,
},
[UGENSA_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UGENSA_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &ugensa_bulk_read_callback,
+ .bufsize = UGENSA_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &ugensa_bulk_read_callback,
},
};
diff --git a/sys/dev/usb/serial/uipaq.c b/sys/dev/usb/serial/uipaq.c
index daebe8b..24dbd25 100644
--- a/sys/dev/usb/serial/uipaq.c
+++ b/sys/dev/usb/serial/uipaq.c
@@ -115,18 +115,18 @@ static const struct usb2_config uipaq_config_data[UIPAQ_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UIPAQ_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &uipaq_write_callback,
+ .bufsize = UIPAQ_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &uipaq_write_callback,
},
[UIPAQ_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UIPAQ_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &uipaq_read_callback,
+ .bufsize = UIPAQ_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &uipaq_read_callback,
},
};
diff --git a/sys/dev/usb/serial/ulpt.c b/sys/dev/usb/serial/ulpt.c
index 2ecce99..024325e 100644
--- a/sys/dev/usb/serial/ulpt.c
+++ b/sys/dev/usb/serial/ulpt.c
@@ -200,7 +200,8 @@ ulpt_write_callback(struct usb2_xfer *xfer)
DPRINTF("no FIFO\n");
return;
}
- DPRINTF("state=0x%x\n", USB_GET_STATE(xfer));
+ DPRINTF("state=0x%x actlen=%u\n",
+ USB_GET_STATE(xfer), xfer->actlen);
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
@@ -208,7 +209,6 @@ ulpt_write_callback(struct usb2_xfer *xfer)
tr_setup:
if (usb2_fifo_get_data(f, xfer->frbuffers,
0, xfer->max_data_length, &actlen, 0)) {
-
xfer->frlengths[0] = actlen;
usb2_start_hardware(xfer);
}
@@ -338,27 +338,27 @@ static const struct usb2_config ulpt_config[ULPT_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = ULPT_BSIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1},
- .mh.callback = &ulpt_write_callback,
+ .bufsize = ULPT_BSIZE,
+ .flags = {.pipe_bof = 1,.proxy_buffer = 1},
+ .callback = &ulpt_write_callback,
},
[ULPT_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = ULPT_BSIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1},
- .mh.callback = &ulpt_read_callback,
+ .bufsize = ULPT_BSIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1},
+ .callback = &ulpt_read_callback,
},
[ULPT_INTR_DT_RD] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request) + 1,
- .mh.callback = &ulpt_status_callback,
- .mh.timeout = 1000, /* 1 second */
+ .bufsize = sizeof(struct usb2_device_request) + 1,
+ .callback = &ulpt_status_callback,
+ .timeout = 1000, /* 1 second */
},
};
diff --git a/sys/dev/usb/serial/umct.c b/sys/dev/usb/serial/umct.c
index dba38d2..db3ddb4 100644
--- a/sys/dev/usb/serial/umct.c
+++ b/sys/dev/usb/serial/umct.c
@@ -49,7 +49,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb_cdc.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR usb2_debug
@@ -138,18 +137,18 @@ static const struct usb2_config umct_config[UMCT_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &umct_write_callback,
+ .bufsize = 0, /* use wMaxPacketSize */
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &umct_write_callback,
},
[UMCT_BULK_DT_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = &umct_read_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &umct_read_callback,
.ep_index = 0, /* first interrupt endpoint */
},
@@ -157,9 +156,9 @@ static const struct usb2_config umct_config[UMCT_N_TRANSFER] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = &umct_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &umct_intr_callback,
.ep_index = 1, /* second interrupt endpoint */
},
};
diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c
index 9960635..35186fd 100644
--- a/sys/dev/usb/serial/umodem.c
+++ b/sys/dev/usb/serial/umodem.c
@@ -86,7 +86,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_error.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/usb_ioctl.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR umodem_debug
@@ -190,9 +189,9 @@ static const struct usb2_config umodem_config[UMODEM_N_TRANSFER] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
.if_index = 0,
- .mh.bufsize = UMODEM_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &umodem_write_callback,
+ .bufsize = UMODEM_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &umodem_write_callback,
},
[UMODEM_BULK_RD] = {
@@ -200,9 +199,9 @@ static const struct usb2_config umodem_config[UMODEM_N_TRANSFER] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.if_index = 0,
- .mh.bufsize = UMODEM_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &umodem_read_callback,
+ .bufsize = UMODEM_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &umodem_read_callback,
},
[UMODEM_INTR_RD] = {
@@ -210,9 +209,9 @@ static const struct usb2_config umodem_config[UMODEM_N_TRANSFER] = {
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
.if_index = 1,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = &umodem_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &umodem_intr_callback,
},
};
@@ -769,7 +768,7 @@ umodem_set_comm_feature(struct usb2_device *udev, uint8_t iface_no,
USETW(req.wLength, UCDC_ABSTRACT_STATE_LENGTH);
USETW(ast.wState, state);
- return (usb2_do_request(udev, &Giant, &req, &ast));
+ return (usb2_do_request(udev, NULL, &req, &ast));
}
static int
diff --git a/sys/dev/usb/serial/umoscom.c b/sys/dev/usb/serial/umoscom.c
index 8ced0c8..f2820ae 100644
--- a/sys/dev/usb/serial/umoscom.c
+++ b/sys/dev/usb/serial/umoscom.c
@@ -204,27 +204,27 @@ static const struct usb2_config umoscom_config_data[UMOSCOM_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UMOSCOM_BUFSIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &umoscom_write_callback,
+ .bufsize = UMOSCOM_BUFSIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &umoscom_write_callback,
},
[UMOSCOM_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UMOSCOM_BUFSIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &umoscom_read_callback,
+ .bufsize = UMOSCOM_BUFSIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &umoscom_read_callback,
},
[UMOSCOM_INTR_DT_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = &umoscom_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &umoscom_intr_callback,
},
};
diff --git a/sys/dev/usb/serial/uplcom.c b/sys/dev/usb/serial/uplcom.c
index 44e676b..24a4b36 100644
--- a/sys/dev/usb/serial/uplcom.c
+++ b/sys/dev/usb/serial/uplcom.c
@@ -187,9 +187,9 @@ static const struct usb2_config uplcom_config_data[UPLCOM_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UPLCOM_BULK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &uplcom_write_callback,
+ .bufsize = UPLCOM_BULK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &uplcom_write_callback,
.if_index = 0,
},
@@ -197,9 +197,9 @@ static const struct usb2_config uplcom_config_data[UPLCOM_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UPLCOM_BULK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &uplcom_read_callback,
+ .bufsize = UPLCOM_BULK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &uplcom_read_callback,
.if_index = 0,
},
@@ -207,9 +207,9 @@ static const struct usb2_config uplcom_config_data[UPLCOM_N_TRANSFER] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = &uplcom_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &uplcom_intr_callback,
.if_index = 1,
},
};
@@ -441,7 +441,7 @@ uplcom_reset(struct uplcom_softc *sc, struct usb2_device *udev)
req.wIndex[1] = 0;
USETW(req.wLength, 0);
- return (usb2_do_request(udev, &Giant, &req, NULL));
+ return (usb2_do_request(udev, NULL, &req, NULL));
}
struct pl2303x_init {
@@ -485,7 +485,7 @@ uplcom_pl2303x_init(struct usb2_device *udev)
USETW(req.wIndex, pl2303x[i].index);
USETW(req.wLength, pl2303x[i].length);
- err = usb2_do_request(udev, &Giant, &req, buf);
+ err = usb2_do_request(udev, NULL, &req, buf);
if (err) {
DPRINTF("error=%s\n", usb2_errstr(err));
return (EIO);
diff --git a/sys/dev/usb/serial/usb_serial.c b/sys/dev/usb/serial/usb_serial.c
index 38fd818..6f5558a 100644
--- a/sys/dev/usb/serial/usb_serial.c
+++ b/sys/dev/usb/serial/usb_serial.c
@@ -412,6 +412,12 @@ usb2_com_queue_command(struct usb2_com_softc *sc,
if (fn == usb2_com_cfg_close)
usb2_proc_mwait(&ssc->sc_tq, t0, t1);
+ /*
+ * In case of multiple configure requests,
+ * keep track of the last one!
+ */
+ if (fn == usb2_com_cfg_start_transfers)
+ sc->sc_last_start_xfer = &task->hdr;
}
static void
@@ -458,7 +464,9 @@ usb2_com_cfg_start_transfers(struct usb2_proc_msg *_task)
/* TTY device closed */
return;
}
- sc->sc_flag |= UCOM_FLAG_GP_DATA;
+
+ if (_task == sc->sc_last_start_xfer)
+ sc->sc_flag |= UCOM_FLAG_GP_DATA;
if (sc->sc_callback->usb2_com_start_read) {
(sc->sc_callback->usb2_com_start_read) (sc);
diff --git a/sys/dev/usb/serial/usb_serial.h b/sys/dev/usb/serial/usb_serial.h
index c7d57a0..7b5837a 100644
--- a/sys/dev/usb/serial/usb_serial.h
+++ b/sys/dev/usb/serial/usb_serial.h
@@ -152,6 +152,8 @@ struct usb2_com_softc {
struct usb2_com_cfg_task sc_status_task[2];
struct usb2_com_param_task sc_param_task[2];
struct cv sc_cv;
+ /* Used to set "UCOM_FLAG_GP_DATA" flag: */
+ struct usb2_proc_msg *sc_last_start_xfer;
const struct usb2_com_callback *sc_callback;
struct usb2_com_super_softc *sc_super;
struct tty *sc_tty;
diff --git a/sys/dev/usb/serial/uslcom.c b/sys/dev/usb/serial/uslcom.c
index d1351aa..5df0abb 100644
--- a/sys/dev/usb/serial/uslcom.c
+++ b/sys/dev/usb/serial/uslcom.c
@@ -128,18 +128,18 @@ static const struct usb2_config uslcom_config[USLCOM_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = USLCOM_BULK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &uslcom_write_callback,
+ .bufsize = USLCOM_BULK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &uslcom_write_callback,
},
[USLCOM_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = USLCOM_BULK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &uslcom_read_callback,
+ .bufsize = USLCOM_BULK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &uslcom_read_callback,
},
};
diff --git a/sys/dev/usb/serial/uvisor.c b/sys/dev/usb/serial/uvisor.c
index 0fb0658..54de2e2 100644
--- a/sys/dev/usb/serial/uvisor.c
+++ b/sys/dev/usb/serial/uvisor.c
@@ -196,18 +196,18 @@ static const struct usb2_config uvisor_config[UVISOR_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UVISOR_BUFSIZE, /* bytes */
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &uvisor_write_callback,
+ .bufsize = UVISOR_BUFSIZE, /* bytes */
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &uvisor_write_callback,
},
[UVISOR_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UVISOR_BUFSIZE, /* bytes */
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &uvisor_read_callback,
+ .bufsize = UVISOR_BUFSIZE, /* bytes */
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &uvisor_read_callback,
},
};
@@ -373,8 +373,8 @@ uvisor_init(struct uvisor_softc *sc, struct usb2_device *udev, struct usb2_confi
USETW(req.wValue, 0);
USETW(req.wIndex, 0);
USETW(req.wLength, UVISOR_CONNECTION_INFO_SIZE);
- err = usb2_do_request_flags
- (udev, &Giant, &req, &coninfo, USB_SHORT_XFER_OK,
+ err = usb2_do_request_flags(udev, NULL,
+ &req, &coninfo, USB_SHORT_XFER_OK,
&actlen, USB_DEFAULT_TIMEOUT);
if (err) {
@@ -427,7 +427,7 @@ uvisor_init(struct uvisor_softc *sc, struct usb2_device *udev, struct usb2_confi
USETW(req.wLength, UVISOR_GET_PALM_INFORMATION_LEN);
err = usb2_do_request_flags
- (udev, &Giant, &req, &pconinfo, USB_SHORT_XFER_OK,
+ (udev, NULL, &req, &pconinfo, USB_SHORT_XFER_OK,
&actlen, USB_DEFAULT_TIMEOUT);
if (err) {
@@ -468,7 +468,7 @@ uvisor_init(struct uvisor_softc *sc, struct usb2_device *udev, struct usb2_confi
USETW(req.wIndex, 0);
USETW(req.wLength, 1);
- err = usb2_do_request(udev, &Giant, &req, buffer);
+ err = usb2_do_request(udev, NULL, &req, buffer);
if (err) {
goto done;
}
@@ -479,7 +479,7 @@ uvisor_init(struct uvisor_softc *sc, struct usb2_device *udev, struct usb2_confi
USETW(req.wValue, 0);
USETW(req.wIndex, 0);
USETW(req.wLength, 1);
- err = usb2_do_request(udev, &Giant, &req, buffer);
+ err = usb2_do_request(udev, NULL, &req, buffer);
if (err) {
goto done;
}
@@ -490,7 +490,7 @@ uvisor_init(struct uvisor_softc *sc, struct usb2_device *udev, struct usb2_confi
USETW(req.wValue, 0);
USETW(req.wIndex, 5);
USETW(req.wLength, sizeof(wAvail));
- err = usb2_do_request(udev, &Giant, &req, &wAvail);
+ err = usb2_do_request(udev, NULL, &req, &wAvail);
if (err) {
goto done;
}
diff --git a/sys/dev/usb/serial/uvscom.c b/sys/dev/usb/serial/uvscom.c
index 6de4f5b..cfda9f8 100644
--- a/sys/dev/usb/serial/uvscom.c
+++ b/sys/dev/usb/serial/uvscom.c
@@ -179,27 +179,27 @@ static const struct usb2_config uvscom_config[UVSCOM_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UVSCOM_BULK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = &uvscom_write_callback,
+ .bufsize = UVSCOM_BULK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = &uvscom_write_callback,
},
[UVSCOM_BULK_DT_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UVSCOM_BULK_BUF_SIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = &uvscom_read_callback,
+ .bufsize = UVSCOM_BULK_BUF_SIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = &uvscom_read_callback,
},
[UVSCOM_INTR_DT_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = &uvscom_intr_callback,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &uvscom_intr_callback,
},
};
diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c
index 8a80300..2f2a163 100644
--- a/sys/dev/usb/storage/umass.c
+++ b/sys/dev/usb/storage/umass.c
@@ -458,6 +458,7 @@ static const struct umass_devdescr umass_devdescr[] = {
{USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE, RID_WILDCARD,
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
FORCE_SHORT_INQUIRY | NO_START_STOP | IGNORE_RESIDUE
+ | NO_SYNCHRONIZE_CACHE
},
{USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE_2, RID_WILDCARD,
UMASS_PROTO_ATAPI | UMASS_PROTO_BBB,
@@ -609,7 +610,7 @@ static const struct umass_devdescr umass_devdescr[] = {
},
{USB_VENDOR_MYSON, USB_PRODUCT_MYSON_HEDEN, RID_WILDCARD,
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
- NO_INQUIRY | IGNORE_RESIDUE
+ IGNORE_RESIDUE | NO_SYNCHRONIZE_CACHE
},
{USB_VENDOR_MYSON, USB_PRODUCT_MYSON_STARREADER, RID_WILDCARD,
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
@@ -847,6 +848,10 @@ static const struct umass_devdescr umass_devdescr[] = {
UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
NO_QUIRKS
},
+ {USB_VENDOR_SUPERTOP, USB_PRODUCT_SUPERTOP_IDE, RID_WILDCARD,
+ UMASS_PROTO_SCSI | UMASS_PROTO_BBB,
+ IGNORE_RESIDUE | NO_SYNCHRONIZE_CACHE
+ },
{USB_VENDOR_TAUGA, USB_PRODUCT_TAUGA_CAMERAMATE, RID_WILDCARD,
UMASS_PROTO_SCSI,
NO_QUIRKS
@@ -1058,93 +1063,87 @@ struct usb2_config umass_bbb_config[UMASS_T_BBB_MAX] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umass_t_bbb_reset1_callback,
- .mh.timeout = 5000, /* 5 seconds */
- .mh.interval = 500, /* 500 milliseconds */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &umass_t_bbb_reset1_callback,
+ .timeout = 5000, /* 5 seconds */
+ .interval = 500, /* 500 milliseconds */
},
[UMASS_T_BBB_RESET2] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umass_t_bbb_reset2_callback,
- .mh.timeout = 5000, /* 5 seconds */
- .mh.interval = 50, /* 50 milliseconds */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &umass_t_bbb_reset2_callback,
+ .timeout = 5000, /* 5 seconds */
+ .interval = 50, /* 50 milliseconds */
},
[UMASS_T_BBB_RESET3] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umass_t_bbb_reset3_callback,
- .mh.timeout = 5000, /* 5 seconds */
- .mh.interval = 50, /* 50 milliseconds */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &umass_t_bbb_reset3_callback,
+ .timeout = 5000, /* 5 seconds */
+ .interval = 50, /* 50 milliseconds */
},
[UMASS_T_BBB_COMMAND] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = sizeof(umass_bbb_cbw_t),
- .mh.flags = {},
- .mh.callback = &umass_t_bbb_command_callback,
- .mh.timeout = 5000, /* 5 seconds */
+ .bufsize = sizeof(umass_bbb_cbw_t),
+ .callback = &umass_t_bbb_command_callback,
+ .timeout = 5000, /* 5 seconds */
},
[UMASS_T_BBB_DATA_READ] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UMASS_BULK_SIZE,
- .mh.flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
- .mh.callback = &umass_t_bbb_data_read_callback,
- .mh.timeout = 0, /* overwritten later */
+ .bufsize = UMASS_BULK_SIZE,
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .callback = &umass_t_bbb_data_read_callback,
+ .timeout = 0, /* overwritten later */
},
[UMASS_T_BBB_DATA_RD_CS] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umass_t_bbb_data_rd_cs_callback,
- .mh.timeout = 5000, /* 5 seconds */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &umass_t_bbb_data_rd_cs_callback,
+ .timeout = 5000, /* 5 seconds */
},
[UMASS_T_BBB_DATA_WRITE] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UMASS_BULK_SIZE,
- .mh.flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
- .mh.callback = &umass_t_bbb_data_write_callback,
- .mh.timeout = 0, /* overwritten later */
+ .bufsize = UMASS_BULK_SIZE,
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .callback = &umass_t_bbb_data_write_callback,
+ .timeout = 0, /* overwritten later */
},
[UMASS_T_BBB_DATA_WR_CS] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umass_t_bbb_data_wr_cs_callback,
- .mh.timeout = 5000, /* 5 seconds */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &umass_t_bbb_data_wr_cs_callback,
+ .timeout = 5000, /* 5 seconds */
},
[UMASS_T_BBB_STATUS] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = sizeof(umass_bbb_csw_t),
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.callback = &umass_t_bbb_status_callback,
- .mh.timeout = 5000, /* ms */
+ .bufsize = sizeof(umass_bbb_csw_t),
+ .flags = {.short_xfer_ok = 1,},
+ .callback = &umass_t_bbb_status_callback,
+ .timeout = 5000, /* ms */
},
};
@@ -1154,105 +1153,98 @@ struct usb2_config umass_cbi_config[UMASS_T_CBI_MAX] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = (sizeof(struct usb2_device_request) +
+ .bufsize = (sizeof(struct usb2_device_request) +
UMASS_CBI_DIAGNOSTIC_CMDLEN),
- .mh.flags = {},
- .mh.callback = &umass_t_cbi_reset1_callback,
- .mh.timeout = 5000, /* 5 seconds */
- .mh.interval = 500, /* 500 milliseconds */
+ .callback = &umass_t_cbi_reset1_callback,
+ .timeout = 5000, /* 5 seconds */
+ .interval = 500, /* 500 milliseconds */
},
[UMASS_T_CBI_RESET2] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umass_t_cbi_reset2_callback,
- .mh.timeout = 5000, /* 5 seconds */
- .mh.interval = 50, /* 50 milliseconds */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &umass_t_cbi_reset2_callback,
+ .timeout = 5000, /* 5 seconds */
+ .interval = 50, /* 50 milliseconds */
},
[UMASS_T_CBI_RESET3] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umass_t_cbi_reset3_callback,
- .mh.timeout = 5000, /* 5 seconds */
- .mh.interval = 50, /* 50 milliseconds */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &umass_t_cbi_reset3_callback,
+ .timeout = 5000, /* 5 seconds */
+ .interval = 50, /* 50 milliseconds */
},
[UMASS_T_CBI_COMMAND] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = (sizeof(struct usb2_device_request) +
+ .bufsize = (sizeof(struct usb2_device_request) +
UMASS_MAX_CMDLEN),
- .mh.flags = {},
- .mh.callback = &umass_t_cbi_command_callback,
- .mh.timeout = 5000, /* 5 seconds */
+ .callback = &umass_t_cbi_command_callback,
+ .timeout = 5000, /* 5 seconds */
},
[UMASS_T_CBI_DATA_READ] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = UMASS_BULK_SIZE,
- .mh.flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
- .mh.callback = &umass_t_cbi_data_read_callback,
- .mh.timeout = 0, /* overwritten later */
+ .bufsize = UMASS_BULK_SIZE,
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .callback = &umass_t_cbi_data_read_callback,
+ .timeout = 0, /* overwritten later */
},
[UMASS_T_CBI_DATA_RD_CS] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umass_t_cbi_data_rd_cs_callback,
- .mh.timeout = 5000, /* 5 seconds */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &umass_t_cbi_data_rd_cs_callback,
+ .timeout = 5000, /* 5 seconds */
},
[UMASS_T_CBI_DATA_WRITE] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = UMASS_BULK_SIZE,
- .mh.flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
- .mh.callback = &umass_t_cbi_data_write_callback,
- .mh.timeout = 0, /* overwritten later */
+ .bufsize = UMASS_BULK_SIZE,
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1, UMASS_USB_FLAGS},
+ .callback = &umass_t_cbi_data_write_callback,
+ .timeout = 0, /* overwritten later */
},
[UMASS_T_CBI_DATA_WR_CS] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umass_t_cbi_data_wr_cs_callback,
- .mh.timeout = 5000, /* 5 seconds */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &umass_t_cbi_data_wr_cs_callback,
+ .timeout = 5000, /* 5 seconds */
},
[UMASS_T_CBI_STATUS] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.bufsize = sizeof(umass_cbi_sbl_t),
- .mh.callback = &umass_t_cbi_status_callback,
- .mh.timeout = 5000, /* ms */
+ .flags = {.short_xfer_ok = 1,},
+ .bufsize = sizeof(umass_cbi_sbl_t),
+ .callback = &umass_t_cbi_status_callback,
+ .timeout = 5000, /* ms */
},
[UMASS_T_CBI_RESET4] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &umass_t_cbi_reset4_callback,
- .mh.timeout = 5000, /* ms */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &umass_t_cbi_reset4_callback,
+ .timeout = 5000, /* ms */
},
};
@@ -1579,7 +1571,7 @@ umass_attach(device_t dev)
* some devices need a delay after that the configuration value is
* set to function properly:
*/
- usb2_pause_mtx(&Giant, hz);
+ usb2_pause_mtx(NULL, hz);
/* register the SIM */
err = umass_cam_attach_sim(sc);
@@ -1638,7 +1630,7 @@ umass_init_shuttle(struct umass_softc *sc)
req.wIndex[0] = sc->sc_iface_no;
req.wIndex[1] = 0;
USETW(req.wLength, sizeof(status));
- err = usb2_do_request(sc->sc_udev, &Giant, &req, &status);
+ err = usb2_do_request(sc->sc_udev, NULL, &req, &status);
DPRINTF(sc, UDMASS_GEN, "Shuttle init returned 0x%02x%02x\n",
status[0], status[1]);
@@ -2022,7 +2014,7 @@ umass_t_bbb_status_callback(struct usb2_xfer *xfer)
residue = UGETDW(sc->csw.dCSWDataResidue);
- if (!residue) {
+ if ((!residue) || (sc->sc_quirks & IGNORE_RESIDUE)) {
residue = (sc->sc_transfer.data_len -
sc->sc_transfer.actlen);
}
@@ -2157,7 +2149,7 @@ umass_bbb_get_max_lun(struct umass_softc *sc)
req.wIndex[1] = 0;
USETW(req.wLength, 1);
- err = usb2_do_request(sc->sc_udev, &Giant, &req, &buf);
+ err = usb2_do_request(sc->sc_udev, NULL, &req, &buf);
if (err) {
buf = 0;
diff --git a/sys/dev/usb/storage/urio.c b/sys/dev/usb/storage/urio.c
index e87a7cd..0c27aa0 100644
--- a/sys/dev/usb/storage/urio.c
+++ b/sys/dev/usb/storage/urio.c
@@ -130,40 +130,38 @@ static const struct usb2_config urio_config[URIO_T_MAX] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = URIO_BSIZE,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,},
- .mh.callback = &urio_write_callback,
+ .bufsize = URIO_BSIZE,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,},
+ .callback = &urio_write_callback,
},
[URIO_T_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = URIO_BSIZE,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,},
- .mh.callback = &urio_read_callback,
+ .bufsize = URIO_BSIZE,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,},
+ .callback = &urio_read_callback,
},
[URIO_T_WR_CS] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &urio_write_clear_stall_callback,
- .mh.timeout = 1000, /* 1 second */
- .mh.interval = 50, /* 50ms */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &urio_write_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
},
[URIO_T_RD_CS] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &urio_read_clear_stall_callback,
- .mh.timeout = 1000, /* 1 second */
- .mh.interval = 50, /* 50ms */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &urio_read_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
},
};
diff --git a/sys/dev/usb/storage/ustorage_fs.c b/sys/dev/usb/storage/ustorage_fs.c
index e119232..efea84c 100644
--- a/sys/dev/usb/storage/ustorage_fs.c
+++ b/sys/dev/usb/storage/ustorage_fs.c
@@ -39,7 +39,6 @@
#include <dev/usb/usb.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR ustorage_fs_debug
@@ -60,10 +59,38 @@ SYSCTL_INT(_hw_usb2_ustorage_fs, OID_AUTO, debug, CTLFLAG_RW,
/* Define some limits */
-#define USTORAGE_FS_BULK_SIZE (1 << 17)
-#define USTORAGE_FS_MAX_LUN 8
-#define USTORAGE_FS_RELEASE 0x0101
-#define USTORAGE_FS_RAM_SECT (1 << 13)
+#ifndef USTORAGE_FS_BULK_SIZE
+#define USTORAGE_FS_BULK_SIZE (1UL << 17) /* bytes */
+#endif
+
+#ifndef USTORAGE_FS_MAX_LUN
+#define USTORAGE_FS_MAX_LUN 8 /* units */
+#endif
+
+#ifndef USTORAGE_QDATA_MAX
+#define USTORAGE_QDATA_MAX 40 /* bytes */
+#endif
+
+#define sc_cmd_data sc_cbw.CBWCDB
+
+/*
+ * The SCSI ID string must be exactly 28 characters long
+ * exluding the terminating zero.
+ */
+#ifndef USTORAGE_FS_ID_STRING
+#define USTORAGE_FS_ID_STRING \
+ "FreeBSD " /* 8 */ \
+ "File-Stor Gadget" /* 16 */ \
+ "0101" /* 4 */
+#endif
+
+/*
+ * The following macro defines the number of
+ * sectors to be allocated for the RAM disk:
+ */
+#ifndef USTORAGE_FS_RAM_SECT
+#define USTORAGE_FS_RAM_SECT (1UL << 13)
+#endif
static uint8_t *ustorage_fs_ramdisk;
@@ -120,7 +147,7 @@ typedef struct {
struct ustorage_fs_lun {
- void *memory_image;
+ uint8_t *memory_image;
uint32_t num_sectors;
uint32_t sense_data;
@@ -153,7 +180,6 @@ struct ustorage_fs_softc {
uint8_t cbw_dir;
uint8_t cmd_dir;
uint8_t lun;
- uint8_t cmd_data[CBWCDBLENGTH];
uint8_t cmd_len;
uint8_t data_short:1;
uint8_t data_error:1;
@@ -163,13 +189,10 @@ struct ustorage_fs_softc {
struct usb2_device *sc_udev;
struct usb2_xfer *sc_xfer[USTORAGE_FS_T_BBB_MAX];
- uint32_t sc_unit;
-
- uint8_t sc_name[16];
uint8_t sc_iface_no; /* interface number */
uint8_t sc_last_lun;
uint8_t sc_last_xfer_index;
- uint8_t sc_qdata[1024];
+ uint8_t sc_qdata[USTORAGE_QDATA_MAX];
};
/* prototypes */
@@ -239,45 +262,50 @@ struct usb2_config ustorage_fs_bbb_config[USTORAGE_FS_T_BBB_MAX] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .md.bufsize = sizeof(ustorage_fs_bbb_cbw_t),
- .md.flags = {.ext_buffer = 1,},
- .md.callback = &ustorage_fs_t_bbb_command_callback,
+ .bufsize = sizeof(ustorage_fs_bbb_cbw_t),
+ .flags = {.ext_buffer = 1,},
+ .callback = &ustorage_fs_t_bbb_command_callback,
+ .usb_mode = USB_MODE_DEVICE,
},
[USTORAGE_FS_T_BBB_DATA_DUMP] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .md.bufsize = 0, /* use wMaxPacketSize */
- .md.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
- .md.callback = &ustorage_fs_t_bbb_data_dump_callback,
+ .bufsize = 0, /* use wMaxPacketSize */
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
+ .callback = &ustorage_fs_t_bbb_data_dump_callback,
+ .usb_mode = USB_MODE_DEVICE,
},
[USTORAGE_FS_T_BBB_DATA_READ] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .md.bufsize = USTORAGE_FS_BULK_SIZE,
- .md.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
- .md.callback = &ustorage_fs_t_bbb_data_read_callback,
+ .bufsize = USTORAGE_FS_BULK_SIZE,
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
+ .callback = &ustorage_fs_t_bbb_data_read_callback,
+ .usb_mode = USB_MODE_DEVICE,
},
[USTORAGE_FS_T_BBB_DATA_WRITE] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .md.bufsize = USTORAGE_FS_BULK_SIZE,
- .md.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
- .md.callback = &ustorage_fs_t_bbb_data_write_callback,
+ .bufsize = USTORAGE_FS_BULK_SIZE,
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,.ext_buffer = 1},
+ .callback = &ustorage_fs_t_bbb_data_write_callback,
+ .usb_mode = USB_MODE_DEVICE,
},
[USTORAGE_FS_T_BBB_STATUS] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .md.bufsize = sizeof(ustorage_fs_bbb_csw_t),
- .md.flags = {.short_xfer_ok = 1,.ext_buffer = 1,},
- .md.callback = &ustorage_fs_t_bbb_status_callback,
+ .bufsize = sizeof(ustorage_fs_bbb_csw_t),
+ .flags = {.short_xfer_ok = 1,.ext_buffer = 1,},
+ .callback = &ustorage_fs_t_bbb_status_callback,
+ .usb_mode = USB_MODE_DEVICE,
},
};
@@ -316,6 +344,7 @@ ustorage_fs_attach(device_t dev)
struct usb2_attach_arg *uaa = device_get_ivars(dev);
struct usb2_interface_descriptor *id;
int err;
+ int unit;
/*
* NOTE: the softc struct is bzero-ed in device_set_driver.
@@ -325,9 +354,9 @@ ustorage_fs_attach(device_t dev)
sc->sc_dev = dev;
sc->sc_udev = uaa->device;
- sc->sc_unit = device_get_unit(dev);
+ unit = device_get_unit(dev);
- if (sc->sc_unit == 0) {
+ if (unit == 0) {
if (ustorage_fs_ramdisk == NULL) {
/*
* allocate a memory image for our ramdisk until
@@ -343,8 +372,6 @@ ustorage_fs_attach(device_t dev)
sc->sc_lun[0].num_sectors = USTORAGE_FS_RAM_SECT;
sc->sc_lun[0].removable = 1;
}
- snprintf(sc->sc_name, sizeof(sc->sc_name),
- "%s", device_get_nameunit(dev));
device_set_usb2_desc(dev);
@@ -525,11 +552,6 @@ ustorage_fs_t_bbb_command_callback(struct usb2_xfer *xfer)
sc->sc_transfer.cmd_len);
break;
}
- bcopy(sc->sc_cbw.CBWCDB, sc->sc_transfer.cmd_data,
- sc->sc_transfer.cmd_len);
-
- bzero(sc->sc_cbw.CBWCDB + sc->sc_transfer.cmd_len,
- sizeof(sc->sc_cbw.CBWCDB) - sc->sc_transfer.cmd_len);
error = ustorage_fs_do_cmd(sc);
if (error) {
@@ -908,17 +930,17 @@ ustorage_fs_verify(struct ustorage_fs_softc *sc)
/*
* Get the starting Logical Block Address
*/
- lba = get_be32(&sc->sc_transfer.cmd_data[2]);
+ lba = get_be32(&sc->sc_cmd_data[2]);
/*
* We allow DPO (Disable Page Out = don't save data in the cache)
* but we don't implement it.
*/
- if ((sc->sc_transfer.cmd_data[1] & ~0x10) != 0) {
+ if ((sc->sc_cmd_data[1] & ~0x10) != 0) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
- vlen = get_be16(&sc->sc_transfer.cmd_data[7]);
+ vlen = get_be16(&sc->sc_cmd_data[7]);
if (vlen == 0) {
goto done;
}
@@ -955,8 +977,6 @@ static uint8_t
ustorage_fs_inquiry(struct ustorage_fs_softc *sc)
{
uint8_t *buf = sc->sc_transfer.data_ptr;
- static const char vendor_id[] = "FreeBSD ";
- static const char product_id[] = "File-Stor Gadget";
struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
@@ -978,12 +998,12 @@ ustorage_fs_inquiry(struct ustorage_fs_softc *sc)
buf[4] = 31;
/* Additional length */
/* No special options */
- /*
- * NOTE: We are writing an extra zero here, that is not
- * transferred to the peer:
- */
- snprintf(buf + 8, 28 + 1, "%-8s%-16s%04x", vendor_id, product_id,
- USTORAGE_FS_RELEASE);
+ /* Copy in ID string */
+ memcpy(buf + 8, USTORAGE_FS_ID_STRING, 28);
+
+#if (USTORAGE_QDATA_MAX < 36)
+#error "(USTORAGE_QDATA_MAX < 36)"
+#endif
return (ustorage_fs_min_len(sc, 36, 0 - 1));
}
@@ -1049,10 +1069,13 @@ ustorage_fs_request_sense(struct ustorage_fs_softc *sc)
/* Additional sense length */
buf[12] = ASC(sd);
buf[13] = ASCQ(sd);
+
+#if (USTORAGE_QDATA_MAX < 18)
+#error "(USTORAGE_QDATA_MAX < 18)"
+#endif
return (ustorage_fs_min_len(sc, 18, 0 - 1));
}
-
/*------------------------------------------------------------------------*
* ustorage_fs_read_capacity
*
@@ -1065,22 +1088,25 @@ ustorage_fs_read_capacity(struct ustorage_fs_softc *sc)
{
uint8_t *buf = sc->sc_transfer.data_ptr;
struct ustorage_fs_lun *currlun = sc->sc_transfer.currlun;
- uint32_t lba = get_be32(&sc->sc_transfer.cmd_data[2]);
- uint8_t pmi = sc->sc_transfer.cmd_data[8];
+ uint32_t lba = get_be32(&sc->sc_cmd_data[2]);
+ uint8_t pmi = sc->sc_cmd_data[8];
/* Check the PMI and LBA fields */
if ((pmi > 1) || ((pmi == 0) && (lba != 0))) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
- put_be32(&buf[0], currlun->num_sectors - 1);
/* Max logical block */
- put_be32(&buf[4], 512);
+ put_be32(&buf[0], currlun->num_sectors - 1);
/* Block length */
+ put_be32(&buf[4], 512);
+
+#if (USTORAGE_QDATA_MAX < 8)
+#error "(USTORAGE_QDATA_MAX < 8)"
+#endif
return (ustorage_fs_min_len(sc, 8, 0 - 1));
}
-
/*------------------------------------------------------------------------*
* ustorage_fs_mode_sense
*
@@ -1096,7 +1122,7 @@ ustorage_fs_mode_sense(struct ustorage_fs_softc *sc)
uint8_t *buf0;
uint16_t len;
uint16_t limit;
- uint8_t mscmnd = sc->sc_transfer.cmd_data[0];
+ uint8_t mscmnd = sc->sc_cmd_data[0];
uint8_t pc;
uint8_t page_code;
uint8_t changeable_values;
@@ -1104,13 +1130,13 @@ ustorage_fs_mode_sense(struct ustorage_fs_softc *sc)
buf0 = buf;
- if ((sc->sc_transfer.cmd_data[1] & ~0x08) != 0) {
+ if ((sc->sc_cmd_data[1] & ~0x08) != 0) {
/* Mask away DBD */
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
- pc = sc->sc_transfer.cmd_data[2] >> 6;
- page_code = sc->sc_transfer.cmd_data[2] & 0x3f;
+ pc = sc->sc_cmd_data[2] >> 6;
+ page_code = sc->sc_cmd_data[2] & 0x3f;
if (pc == 3) {
currlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED;
return (1);
@@ -1181,6 +1207,10 @@ ustorage_fs_mode_sense(struct ustorage_fs_softc *sc)
buf0[0] = len - 1;
else
put_be16(buf0, len - 2);
+
+#if (USTORAGE_QDATA_MAX < 24)
+#error "(USTORAGE_QDATA_MAX < 24)"
+#endif
return (ustorage_fs_min_len(sc, len, 0 - 1));
}
@@ -1203,9 +1233,9 @@ ustorage_fs_start_stop(struct ustorage_fs_softc *sc)
currlun->sense_data = SS_INVALID_COMMAND;
return (1);
}
- immed = sc->sc_transfer.cmd_data[1] & 0x01;
- loej = sc->sc_transfer.cmd_data[4] & 0x02;
- start = sc->sc_transfer.cmd_data[4] & 0x01;
+ immed = sc->sc_cmd_data[1] & 0x01;
+ loej = sc->sc_cmd_data[4] & 0x02;
+ start = sc->sc_cmd_data[4] & 0x01;
if (immed || loej || start) {
/* compile fix */
@@ -1230,8 +1260,8 @@ ustorage_fs_prevent_allow(struct ustorage_fs_softc *sc)
currlun->sense_data = SS_INVALID_COMMAND;
return (1);
}
- prevent = sc->sc_transfer.cmd_data[4] & 0x01;
- if ((sc->sc_transfer.cmd_data[4] & ~0x01) != 0) {
+ prevent = sc->sc_cmd_data[4] & 0x01;
+ if ((sc->sc_cmd_data[4] & ~0x01) != 0) {
/* Mask away Prevent */
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
@@ -1261,12 +1291,16 @@ ustorage_fs_read_format_capacities(struct ustorage_fs_softc *sc)
/* Only the Current / Maximum Capacity Descriptor */
buf += 4;
- put_be32(&buf[0], currlun->num_sectors);
/* Number of blocks */
- put_be32(&buf[4], 512);
+ put_be32(&buf[0], currlun->num_sectors);
/* Block length */
- buf[4] = 0x02;
+ put_be32(&buf[4], 512);
/* Current capacity */
+ buf[4] = 0x02;
+
+#if (USTORAGE_QDATA_MAX < 12)
+#error "(USTORAGE_QDATA_MAX < 12)"
+#endif
return (ustorage_fs_min_len(sc, 12, 0 - 1));
}
@@ -1331,18 +1365,18 @@ ustorage_fs_read(struct ustorage_fs_softc *sc)
* Get the starting Logical Block Address and check that it's not
* too big
*/
- if (sc->sc_transfer.cmd_data[0] == SC_READ_6) {
- lba = (sc->sc_transfer.cmd_data[1] << 16) |
- get_be16(&sc->sc_transfer.cmd_data[2]);
+ if (sc->sc_cmd_data[0] == SC_READ_6) {
+ lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
+ get_be16(&sc->sc_cmd_data[2]);
} else {
- lba = get_be32(&sc->sc_transfer.cmd_data[2]);
+ lba = get_be32(&sc->sc_cmd_data[2]);
/*
* We allow DPO (Disable Page Out = don't save data in the
* cache) and FUA (Force Unit Access = don't read from the
* cache), but we don't implement them.
*/
- if ((sc->sc_transfer.cmd_data[1] & ~0x18) != 0) {
+ if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
@@ -1359,8 +1393,7 @@ ustorage_fs_read(struct ustorage_fs_softc *sc)
file_offset = lba;
file_offset <<= 9;
- sc->sc_transfer.data_ptr =
- USB_ADD_BYTES(currlun->memory_image, (uint32_t)file_offset);
+ sc->sc_transfer.data_ptr = currlun->memory_image + file_offset;
return (0);
}
@@ -1390,11 +1423,11 @@ ustorage_fs_write(struct ustorage_fs_softc *sc)
* Get the starting Logical Block Address and check that it's not
* too big.
*/
- if (sc->sc_transfer.cmd_data[0] == SC_WRITE_6)
- lba = (sc->sc_transfer.cmd_data[1] << 16) |
- get_be16(&sc->sc_transfer.cmd_data[2]);
+ if (sc->sc_cmd_data[0] == SC_WRITE_6)
+ lba = (((uint32_t)sc->sc_cmd_data[1]) << 16) |
+ get_be16(&sc->sc_cmd_data[2]);
else {
- lba = get_be32(&sc->sc_transfer.cmd_data[2]);
+ lba = get_be32(&sc->sc_cmd_data[2]);
/*
* We allow DPO (Disable Page Out = don't save data in the
@@ -1402,11 +1435,11 @@ ustorage_fs_write(struct ustorage_fs_softc *sc)
* medium). We don't implement DPO; we implement FUA by
* performing synchronous output.
*/
- if ((sc->sc_transfer.cmd_data[1] & ~0x18) != 0) {
+ if ((sc->sc_cmd_data[1] & ~0x18) != 0) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
return (1);
}
- if (sc->sc_transfer.cmd_data[1] & 0x08) {
+ if (sc->sc_cmd_data[1] & 0x08) {
/* FUA */
/* XXX set SYNC flag here */
}
@@ -1424,8 +1457,7 @@ ustorage_fs_write(struct ustorage_fs_softc *sc)
file_offset = lba;
file_offset <<= 9;
- sc->sc_transfer.data_ptr =
- USB_ADD_BYTES(currlun->memory_image, (uint32_t)file_offset);
+ sc->sc_transfer.data_ptr = currlun->memory_image + file_offset;
return (0);
}
@@ -1483,7 +1515,7 @@ ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
uint16_t mask, uint8_t needs_medium)
{
struct ustorage_fs_lun *currlun;
- uint8_t lun = (sc->sc_transfer.cmd_data[1] >> 5);
+ uint8_t lun = (sc->sc_cmd_data[1] >> 5);
uint8_t i;
/* Verify the length of the command itself */
@@ -1494,7 +1526,7 @@ ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
return (1);
}
/* Mask away the LUN */
- sc->sc_transfer.cmd_data[1] &= 0x1f;
+ sc->sc_cmd_data[1] &= 0x1f;
/* Check if LUN is correct */
if (lun != sc->sc_transfer.lun) {
@@ -1504,7 +1536,7 @@ ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
if (sc->sc_transfer.lun <= sc->sc_last_lun) {
sc->sc_transfer.currlun = currlun =
sc->sc_lun + sc->sc_transfer.lun;
- if (sc->sc_transfer.cmd_data[0] != SC_REQUEST_SENSE) {
+ if (sc->sc_cmd_data[0] != SC_REQUEST_SENSE) {
currlun->sense_data = SS_NO_SENSE;
currlun->sense_data_info = 0;
currlun->info_valid = 0;
@@ -1515,8 +1547,8 @@ ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
* else must fail!
*/
if ((currlun->unit_attention_data != SS_NO_SENSE) &&
- (sc->sc_transfer.cmd_data[0] != SC_INQUIRY) &&
- (sc->sc_transfer.cmd_data[0] != SC_REQUEST_SENSE)) {
+ (sc->sc_cmd_data[0] != SC_INQUIRY) &&
+ (sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
currlun->sense_data = currlun->unit_attention_data;
currlun->unit_attention_data = SS_NO_SENSE;
return (1);
@@ -1528,8 +1560,8 @@ ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
* INQUIRY and REQUEST SENSE commands are explicitly allowed
* to use unsupported LUNs; all others may not.
*/
- if ((sc->sc_transfer.cmd_data[0] != SC_INQUIRY) &&
- (sc->sc_transfer.cmd_data[0] != SC_REQUEST_SENSE)) {
+ if ((sc->sc_cmd_data[0] != SC_INQUIRY) &&
+ (sc->sc_cmd_data[0] != SC_REQUEST_SENSE)) {
return (1);
}
}
@@ -1539,7 +1571,7 @@ ustorage_fs_check_cmd(struct ustorage_fs_softc *sc, uint8_t min_cmd_size,
* non-zero.
*/
for (i = 0; i != min_cmd_size; i++) {
- if (sc->sc_transfer.cmd_data[i] && !(mask & (1 << i))) {
+ if (sc->sc_cmd_data[i] && !(mask & (1UL << i))) {
if (currlun) {
currlun->sense_data = SS_INVALID_FIELD_IN_CDB;
}
@@ -1570,22 +1602,24 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
{
uint8_t error = 1;
uint8_t i;
+ uint32_t temp;
+ const uint32_t mask9 = (0xFFFFFFFFUL >> 9) << 9;
/* set default data transfer pointer */
sc->sc_transfer.data_ptr = sc->sc_qdata;
DPRINTF("cmd_data[0]=0x%02x, data_rem=0x%08x\n",
- sc->sc_transfer.cmd_data[0], sc->sc_transfer.data_rem);
+ sc->sc_cmd_data[0], sc->sc_transfer.data_rem);
- switch (sc->sc_transfer.cmd_data[0]) {
+ switch (sc->sc_cmd_data[0]) {
case SC_INQUIRY:
sc->sc_transfer.cmd_dir = DIR_WRITE;
- error = ustorage_fs_min_len(sc, sc->sc_transfer.cmd_data[4], 0 - 1);
+ error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], 0 - 1);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 6,
- (1 << 4) | 1, 0);
+ (1UL << 4) | 1, 0);
if (error) {
break;
}
@@ -1595,12 +1629,12 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_MODE_SELECT_6:
sc->sc_transfer.cmd_dir = DIR_READ;
- error = ustorage_fs_min_len(sc, sc->sc_transfer.cmd_data[4], 0 - 1);
+ error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], 0 - 1);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 6,
- (1 << 1) | (1 << 4) | 1, 0);
+ (1UL << 1) | (1UL << 4) | 1, 0);
if (error) {
break;
}
@@ -1611,12 +1645,12 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_MODE_SELECT_10:
sc->sc_transfer.cmd_dir = DIR_READ;
error = ustorage_fs_min_len(sc,
- get_be16(&sc->sc_transfer.cmd_data[7]), 0 - 1);
+ get_be16(&sc->sc_cmd_data[7]), 0 - 1);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 10,
- (1 << 1) | (3 << 7) | 1, 0);
+ (1UL << 1) | (3UL << 7) | 1, 0);
if (error) {
break;
}
@@ -1626,12 +1660,12 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_MODE_SENSE_6:
sc->sc_transfer.cmd_dir = DIR_WRITE;
- error = ustorage_fs_min_len(sc, sc->sc_transfer.cmd_data[4], 0 - 1);
+ error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], 0 - 1);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 6,
- (1 << 1) | (1 << 2) | (1 << 4) | 1, 0);
+ (1UL << 1) | (1UL << 2) | (1UL << 4) | 1, 0);
if (error) {
break;
}
@@ -1642,12 +1676,12 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_MODE_SENSE_10:
sc->sc_transfer.cmd_dir = DIR_WRITE;
error = ustorage_fs_min_len(sc,
- get_be16(&sc->sc_transfer.cmd_data[7]), 0 - 1);
+ get_be16(&sc->sc_cmd_data[7]), 0 - 1);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 10,
- (1 << 1) | (1 << 2) | (3 << 7) | 1, 0);
+ (1UL << 1) | (1UL << 2) | (3UL << 7) | 1, 0);
if (error) {
break;
}
@@ -1661,7 +1695,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
break;
}
error = ustorage_fs_check_cmd(sc, 6,
- (1 << 4) | 1, 0);
+ (1UL << 4) | 1, 0);
if (error) {
break;
}
@@ -1670,15 +1704,15 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
break;
case SC_READ_6:
- i = sc->sc_transfer.cmd_data[4];
+ i = sc->sc_cmd_data[4];
sc->sc_transfer.cmd_dir = DIR_WRITE;
- error = ustorage_fs_min_len(sc,
- ((i == 0) ? 256 : i) << 9, 0 - (1 << 9));
+ temp = ((i == 0) ? 256UL : i);
+ error = ustorage_fs_min_len(sc, temp << 9, mask9);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 6,
- (7 << 1) | (1 << 4) | 1, 1);
+ (7UL << 1) | (1UL << 4) | 1, 1);
if (error) {
break;
}
@@ -1688,13 +1722,13 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_READ_10:
sc->sc_transfer.cmd_dir = DIR_WRITE;
- error = ustorage_fs_min_len(sc,
- get_be16(&sc->sc_transfer.cmd_data[7]) << 9, 0 - (1 << 9));
+ temp = get_be16(&sc->sc_cmd_data[7]);
+ error = ustorage_fs_min_len(sc, temp << 9, mask9);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 10,
- (1 << 1) | (0xf << 2) | (3 << 7) | 1, 1);
+ (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
if (error) {
break;
}
@@ -1704,13 +1738,19 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_READ_12:
sc->sc_transfer.cmd_dir = DIR_WRITE;
- error = ustorage_fs_min_len(sc,
- get_be32(&sc->sc_transfer.cmd_data[6]) << 9, 0 - (1 << 9));
+ temp = get_be32(&sc->sc_cmd_data[6]);
+ if (temp >= (1UL << (32 - 9))) {
+ /* numerical overflow */
+ sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
+ error = 1;
+ break;
+ }
+ error = ustorage_fs_min_len(sc, temp << 9, mask9);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 12,
- (1 << 1) | (0xf << 2) | (0xf << 6) | 1, 1);
+ (1UL << 1) | (0xfUL << 2) | (0xfUL << 6) | 1, 1);
if (error) {
break;
}
@@ -1721,7 +1761,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_READ_CAPACITY:
sc->sc_transfer.cmd_dir = DIR_WRITE;
error = ustorage_fs_check_cmd(sc, 10,
- (0xf << 2) | (1 << 8) | 1, 1);
+ (0xfUL << 2) | (1UL << 8) | 1, 1);
if (error) {
break;
}
@@ -1732,12 +1772,12 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_READ_FORMAT_CAPACITIES:
sc->sc_transfer.cmd_dir = DIR_WRITE;
error = ustorage_fs_min_len(sc,
- get_be16(&sc->sc_transfer.cmd_data[7]), 0 - 1);
+ get_be16(&sc->sc_cmd_data[7]), 0 - 1);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 10,
- (3 << 7) | 1, 1);
+ (3UL << 7) | 1, 1);
if (error) {
break;
}
@@ -1747,12 +1787,12 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_REQUEST_SENSE:
sc->sc_transfer.cmd_dir = DIR_WRITE;
- error = ustorage_fs_min_len(sc, sc->sc_transfer.cmd_data[4], 0 - 1);
+ error = ustorage_fs_min_len(sc, sc->sc_cmd_data[4], 0 - 1);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 6,
- (1 << 4) | 1, 0);
+ (1UL << 4) | 1, 0);
if (error) {
break;
}
@@ -1766,7 +1806,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
break;
}
error = ustorage_fs_check_cmd(sc, 6,
- (1 << 1) | (1 << 4) | 1, 0);
+ (1UL << 1) | (1UL << 4) | 1, 0);
if (error) {
break;
}
@@ -1780,7 +1820,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
break;
}
error = ustorage_fs_check_cmd(sc, 10,
- (0xf << 2) | (3 << 7) | 1, 1);
+ (0xfUL << 2) | (3UL << 7) | 1, 1);
if (error) {
break;
}
@@ -1807,7 +1847,7 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
break;
}
error = ustorage_fs_check_cmd(sc, 10,
- (1 << 1) | (0xf << 2) | (3 << 7) | 1, 1);
+ (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
if (error) {
break;
}
@@ -1816,15 +1856,15 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
break;
case SC_WRITE_6:
- i = sc->sc_transfer.cmd_data[4];
+ i = sc->sc_cmd_data[4];
sc->sc_transfer.cmd_dir = DIR_READ;
- error = ustorage_fs_min_len(sc,
- ((i == 0) ? 256 : i) << 9, 0 - (1 << 9));
+ temp = ((i == 0) ? 256UL : i);
+ error = ustorage_fs_min_len(sc, temp << 9, mask9);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 6,
- (7 << 1) | (1 << 4) | 1, 1);
+ (7UL << 1) | (1UL << 4) | 1, 1);
if (error) {
break;
}
@@ -1834,13 +1874,13 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_WRITE_10:
sc->sc_transfer.cmd_dir = DIR_READ;
- error = ustorage_fs_min_len(sc,
- get_be16(&sc->sc_transfer.cmd_data[7]) << 9, 0 - (1 << 9));
+ temp = get_be16(&sc->sc_cmd_data[7]);
+ error = ustorage_fs_min_len(sc, temp << 9, mask9);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 10,
- (1 << 1) | (0xf << 2) | (3 << 7) | 1, 1);
+ (1UL << 1) | (0xfUL << 2) | (3UL << 7) | 1, 1);
if (error) {
break;
}
@@ -1850,13 +1890,19 @@ ustorage_fs_do_cmd(struct ustorage_fs_softc *sc)
case SC_WRITE_12:
sc->sc_transfer.cmd_dir = DIR_READ;
- error = ustorage_fs_min_len(sc,
- get_be32(&sc->sc_transfer.cmd_data[6]) << 9, 0 - (1 << 9));
+ temp = get_be32(&sc->sc_cmd_data[6]);
+ if (temp > (mask9 >> 9)) {
+ /* numerical overflow */
+ sc->sc_csw.bCSWStatus = CSWSTATUS_FAILED;
+ error = 1;
+ break;
+ }
+ error = ustorage_fs_min_len(sc, temp << 9, mask9);
if (error) {
break;
}
error = ustorage_fs_check_cmd(sc, 12,
- (1 << 1) | (0xf << 2) | (0xf << 6) | 1, 1);
+ (1UL << 1) | (0xfUL << 2) | (0xfUL << 6) | 1, 1);
if (error) {
break;
}
diff --git a/sys/dev/usb/template/usb_template.c b/sys/dev/usb/template/usb_template.c
index 31c853a..dd1a536 100644
--- a/sys/dev/usb/template/usb_template.c
+++ b/sys/dev/usb/template/usb_template.c
@@ -32,7 +32,6 @@
#include <dev/usb/usb.h>
#include <dev/usb/usb_cdc.h>
#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_error.h>
#define USB_DEBUG_VAR usb2_debug
diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h
index fa5e5dd..3d9dcc3 100644
--- a/sys/dev/usb/usb.h
+++ b/sys/dev/usb/usb.h
@@ -461,8 +461,10 @@ struct usb2_endpoint_descriptor {
uByte bEndpointAddress;
#define UE_GET_DIR(a) ((a) & 0x80)
#define UE_SET_DIR(a,d) ((a) | (((d)&1) << 7))
-#define UE_DIR_IN 0x80
-#define UE_DIR_OUT 0x00
+#define UE_DIR_IN 0x80 /* IN-token endpoint, fixed */
+#define UE_DIR_OUT 0x00 /* OUT-token endpoint, fixed */
+#define UE_DIR_RX 0xfd /* for internal use only! */
+#define UE_DIR_TX 0xfe /* for internal use only! */
#define UE_DIR_ANY 0xff /* for internal use only! */
#define UE_ADDR 0x0f
#define UE_ADDR_ANY 0xff /* for internal use only! */
diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h
index d2fecb9..43cdf35 100644
--- a/sys/dev/usb/usb_bus.h
+++ b/sys/dev/usb/usb_bus.h
@@ -28,8 +28,8 @@
#define _USB2_BUS_H_
/*
- * The following structure defines the USB explore message sent to the
- * USB explore process.
+ * The following structure defines the USB explore message sent to the USB
+ * explore process.
*/
struct usb2_bus_msg {
@@ -45,6 +45,17 @@ struct usb2_bus_stat {
};
/*
+ * The following structure is used to keep the state of a standard
+ * root transfer.
+ */
+struct usb2_sw_transfer {
+ struct usb2_device_request req;
+ uint8_t *ptr;
+ uint16_t len;
+ usb2_error_t err;
+};
+
+/*
* The following structure defines an USB BUS. There is one USB BUS
* for every Host or Device controller.
*/
@@ -52,7 +63,7 @@ struct usb2_bus {
struct usb2_bus_stat stats_err;
struct usb2_bus_stat stats_ok;
struct usb2_process explore_proc;
- struct usb2_process roothub_proc;
+ struct usb2_sw_transfer roothub_req;
struct root_hold_token *bus_roothold;
/*
* There are two callback processes. One for Giant locked
@@ -64,7 +75,6 @@ struct usb2_bus {
struct usb2_bus_msg explore_msg[2];
struct usb2_bus_msg detach_msg[2];
struct usb2_bus_msg attach_msg[2];
- struct usb2_bus_msg roothub_msg[2];
/*
* This mutex protects the USB hardware:
*/
@@ -75,15 +85,16 @@ struct usb2_bus {
device_t parent;
device_t bdev; /* filled by HC driver */
+#if USB_HAVE_BUSDMA
struct usb2_dma_parent_tag dma_parent_tag[1];
struct usb2_dma_tag dma_tags[USB_BUS_DMA_TAG_MAX];
-
+#endif
struct usb2_bus_methods *methods; /* filled by HC driver */
struct usb2_device **devices;
- uint32_t hw_power_state; /* see USB_HW_POWER_XXX */
- uint32_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
- uint32_t transfer_count[4];
+ usb2_power_mask_t hw_power_state; /* see USB_HW_POWER_XXX */
+ usb2_size_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
+
uint16_t isoc_time_last; /* in milliseconds */
uint8_t alloc_failed; /* Set if memory allocation failed. */
diff --git a/sys/dev/usb/usb_busdma.c b/sys/dev/usb/usb_busdma.c
index 809c3bf..c8f30ed 100644
--- a/sys/dev/usb/usb_busdma.c
+++ b/sys/dev/usb/usb_busdma.c
@@ -27,7 +27,6 @@
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR usb2_debug
@@ -42,20 +41,20 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
-static void usb2_dma_tag_create(struct usb2_dma_tag *, uint32_t, uint32_t);
+#if USB_HAVE_BUSDMA
+static void usb2_dma_tag_create(struct usb2_dma_tag *, usb2_size_t, usb2_size_t);
static void usb2_dma_tag_destroy(struct usb2_dma_tag *);
+#endif
-#ifdef __FreeBSD__
+#if USB_HAVE_BUSDMA && defined(__FreeBSD__)
static void usb2_dma_lock_cb(void *, bus_dma_lock_op_t);
-static int32_t usb2_m_copy_in_cb(void *, void *, uint32_t);
static void usb2_pc_alloc_mem_cb(void *, bus_dma_segment_t *, int, int);
static void usb2_pc_load_mem_cb(void *, bus_dma_segment_t *, int, int);
static void usb2_pc_common_mem_cb(void *, bus_dma_segment_t *, int, int,
uint8_t);
#endif
-#ifdef __NetBSD__
-static int32_t usb2_m_copy_in_cb(void *, caddr_t, uint32_t);
+#if USB_HAVE_BUSDMA && defined(__NetBSD__)
static void usb2_pc_common_mem_cb(struct usb2_page_cache *,
bus_dma_segment_t *, int, int, uint8_t);
#endif
@@ -67,11 +66,12 @@ static void usb2_pc_common_mem_cb(struct usb2_page_cache *,
* been properly initialized !
*------------------------------------------------------------------------*/
void
-usb2_get_page(struct usb2_page_cache *pc, uint32_t offset,
+usb2_get_page(struct usb2_page_cache *pc, usb2_frlength_t offset,
struct usb2_page_search *res)
{
struct usb2_page *page;
+#if USB_HAVE_BUSDMA
if (pc->page_start) {
/* Case 1 - something has been loaded into DMA */
@@ -106,22 +106,24 @@ usb2_get_page(struct usb2_page_cache *pc, uint32_t offset,
res->buffer = USB_ADD_BYTES(page->buffer, offset);
}
- } else {
-
- /* Case 2 - Plain PIO */
-
- res->buffer = USB_ADD_BYTES(pc->buffer, offset);
- res->length = 0 - 1;
- res->physaddr = 0;
+ return;
}
+#endif
+ /* Case 2 - Plain PIO */
+
+ res->buffer = USB_ADD_BYTES(pc->buffer, offset);
+ res->length = 0 - 1;
+#if USB_HAVE_BUSDMA
+ res->physaddr = 0;
+#endif
}
/*------------------------------------------------------------------------*
* usb2_copy_in - copy directly to DMA-able memory
*------------------------------------------------------------------------*/
void
-usb2_copy_in(struct usb2_page_cache *cache, uint32_t offset,
- const void *ptr, uint32_t len)
+usb2_copy_in(struct usb2_page_cache *cache, usb2_frlength_t offset,
+ const void *ptr, usb2_frlength_t len)
{
struct usb2_page_search buf_res;
@@ -147,9 +149,10 @@ usb2_copy_in(struct usb2_page_cache *cache, uint32_t offset,
* 0: Success
* Else: Failure
*------------------------------------------------------------------------*/
+#if USB_HAVE_USER_IO
int
-usb2_copy_in_user(struct usb2_page_cache *cache, uint32_t offset,
- const void *ptr, uint32_t len)
+usb2_copy_in_user(struct usb2_page_cache *cache, usb2_frlength_t offset,
+ const void *ptr, usb2_frlength_t len)
{
struct usb2_page_search buf_res;
int error;
@@ -171,16 +174,18 @@ usb2_copy_in_user(struct usb2_page_cache *cache, uint32_t offset,
}
return (0); /* success */
}
+#endif
/*------------------------------------------------------------------------*
* usb2_m_copy_in - copy a mbuf chain directly into DMA-able memory
*------------------------------------------------------------------------*/
+#if USB_HAVE_MBUF
struct usb2_m_copy_in_arg {
struct usb2_page_cache *cache;
- uint32_t dst_offset;
+ usb2_frlength_t dst_offset;
};
-static int32_t
+static int
#ifdef __FreeBSD__
usb2_m_copy_in_cb(void *arg, void *src, uint32_t count)
#else
@@ -195,21 +200,23 @@ usb2_m_copy_in_cb(void *arg, caddr_t src, uint32_t count)
}
void
-usb2_m_copy_in(struct usb2_page_cache *cache, uint32_t dst_offset,
- struct mbuf *m, uint32_t src_offset, uint32_t src_len)
+usb2_m_copy_in(struct usb2_page_cache *cache, usb2_frlength_t dst_offset,
+ struct mbuf *m, usb2_size_t src_offset, usb2_frlength_t src_len)
{
struct usb2_m_copy_in_arg arg = {cache, dst_offset};
- register int error;
+ int error;
error = m_apply(m, src_offset, src_len, &usb2_m_copy_in_cb, &arg);
}
+#endif
/*------------------------------------------------------------------------*
* usb2_uiomove - factored out code
*------------------------------------------------------------------------*/
+#if USB_HAVE_USER_IO
int
usb2_uiomove(struct usb2_page_cache *pc, struct uio *uio,
- uint32_t pc_offset, uint32_t len)
+ usb2_frlength_t pc_offset, usb2_frlength_t len)
{
struct usb2_page_search res;
int error = 0;
@@ -235,13 +242,14 @@ usb2_uiomove(struct usb2_page_cache *pc, struct uio *uio,
}
return (error);
}
+#endif
/*------------------------------------------------------------------------*
* usb2_copy_out - copy directly from DMA-able memory
*------------------------------------------------------------------------*/
void
-usb2_copy_out(struct usb2_page_cache *cache, uint32_t offset,
- void *ptr, uint32_t len)
+usb2_copy_out(struct usb2_page_cache *cache, usb2_frlength_t offset,
+ void *ptr, usb2_frlength_t len)
{
struct usb2_page_search res;
@@ -267,9 +275,10 @@ usb2_copy_out(struct usb2_page_cache *cache, uint32_t offset,
* 0: Success
* Else: Failure
*------------------------------------------------------------------------*/
+#if USB_HAVE_USER_IO
int
-usb2_copy_out_user(struct usb2_page_cache *cache, uint32_t offset,
- void *ptr, uint32_t len)
+usb2_copy_out_user(struct usb2_page_cache *cache, usb2_frlength_t offset,
+ void *ptr, usb2_frlength_t len)
{
struct usb2_page_search res;
int error;
@@ -291,12 +300,14 @@ usb2_copy_out_user(struct usb2_page_cache *cache, uint32_t offset,
}
return (0); /* success */
}
+#endif
/*------------------------------------------------------------------------*
* usb2_bzero - zero DMA-able memory
*------------------------------------------------------------------------*/
void
-usb2_bzero(struct usb2_page_cache *cache, uint32_t offset, uint32_t len)
+usb2_bzero(struct usb2_page_cache *cache, usb2_frlength_t offset,
+ usb2_frlength_t len)
{
struct usb2_page_search res;
@@ -314,8 +325,7 @@ usb2_bzero(struct usb2_page_cache *cache, uint32_t offset, uint32_t len)
}
}
-
-#ifdef __FreeBSD__
+#if USB_HAVE_BUSDMA && defined(__FreeBSD__)
/*------------------------------------------------------------------------*
* usb2_dma_lock_cb - dummy callback
@@ -334,7 +344,7 @@ usb2_dma_lock_cb(void *arg, bus_dma_lock_op_t op)
*------------------------------------------------------------------------*/
static void
usb2_dma_tag_create(struct usb2_dma_tag *udt,
- uint32_t size, uint32_t align)
+ usb2_size_t size, usb2_size_t align)
{
bus_dma_tag_t tag;
@@ -399,7 +409,7 @@ usb2_pc_common_mem_cb(void *arg, bus_dma_segment_t *segs,
struct usb2_dma_parent_tag *uptag;
struct usb2_page_cache *pc;
struct usb2_page *pg;
- uint32_t rem;
+ usb2_size_t rem;
uint8_t owned;
pc = arg;
@@ -462,7 +472,7 @@ done:
*------------------------------------------------------------------------*/
uint8_t
usb2_pc_alloc_mem(struct usb2_page_cache *pc, struct usb2_page *pg,
- uint32_t size, uint32_t align)
+ usb2_size_t size, usb2_size_t align)
{
struct usb2_dma_parent_tag *uptag;
struct usb2_dma_tag *utag;
@@ -585,7 +595,7 @@ usb2_pc_free_mem(struct usb2_page_cache *pc)
* Else: Error
*------------------------------------------------------------------------*/
uint8_t
-usb2_pc_load_mem(struct usb2_page_cache *pc, uint32_t size, uint8_t sync)
+usb2_pc_load_mem(struct usb2_page_cache *pc, usb2_size_t size, uint8_t sync)
{
/* setup page cache */
pc->page_offset_buf = 0;
@@ -686,13 +696,13 @@ usb2_pc_cpu_flush(struct usb2_page_cache *pc)
* Else: Failure
*------------------------------------------------------------------------*/
uint8_t
-usb2_pc_dmamap_create(struct usb2_page_cache *pc, uint32_t size)
+usb2_pc_dmamap_create(struct usb2_page_cache *pc, usb2_size_t size)
{
struct usb2_xfer_root *info;
struct usb2_dma_tag *utag;
/* get info */
- info = pc->tag_parent->info;
+ info = USB_DMATAG_TO_XROOT(pc->tag_parent);
/* sanity check */
if (info == NULL) {
@@ -732,7 +742,7 @@ usb2_pc_dmamap_destroy(struct usb2_page_cache *pc)
#endif
-#ifdef __NetBSD__
+#if USB_HAVE_BUSDMA && defined(__NetBSD__)
/*------------------------------------------------------------------------*
* usb2_dma_tag_create - allocate a DMA tag
@@ -742,9 +752,9 @@ usb2_pc_dmamap_destroy(struct usb2_page_cache *pc)
*------------------------------------------------------------------------*/
static void
usb2_dma_tag_create(struct usb2_dma_tag *udt,
- uint32_t size, uint32_t align)
+ usb2_size_t size, usb2_size_t align)
{
- uint32_t nseg;
+ usb2_size_t nseg;
if (align == 1) {
nseg = (2 + (size / USB_PAGE_SIZE));
@@ -780,7 +790,7 @@ usb2_pc_common_mem_cb(struct usb2_page_cache *pc, bus_dma_segment_t *segs,
{
struct usb2_dma_parent_tag *uptag;
struct usb2_page *pg;
- uint32_t rem;
+ usb2_size_t rem;
uint8_t ext_seg; /* extend last segment */
uptag = pc->tag_parent;
@@ -846,7 +856,7 @@ done:
*------------------------------------------------------------------------*/
uint8_t
usb2_pc_alloc_mem(struct usb2_page_cache *pc, struct usb2_page *pg,
- uint32_t size, uint32_t align)
+ usb2_size_t size, usb2_size_t align)
{
struct usb2_dma_parent_tag *uptag;
struct usb2_dma_tag *utag;
@@ -969,7 +979,7 @@ usb2_pc_free_mem(struct usb2_page_cache *pc)
* Else: Error
*------------------------------------------------------------------------*/
uint8_t
-usb2_pc_load_mem(struct usb2_page_cache *pc, uint32_t size, uint8_t sync)
+usb2_pc_load_mem(struct usb2_page_cache *pc, usb2_size_t size, uint8_t sync)
{
int error;
@@ -1019,7 +1029,7 @@ usb2_pc_load_mem(struct usb2_page_cache *pc, uint32_t size, uint8_t sync)
void
usb2_pc_cpu_invalidate(struct usb2_page_cache *pc)
{
- uint32_t len;
+ usb2_size_t len;
len = pc->page_offset_end - pc->page_offset_buf;
@@ -1037,7 +1047,7 @@ usb2_pc_cpu_invalidate(struct usb2_page_cache *pc)
void
usb2_pc_cpu_flush(struct usb2_page_cache *pc)
{
- uint32_t len;
+ usb2_size_t len;
len = pc->page_offset_end - pc->page_offset_buf;
@@ -1057,13 +1067,13 @@ usb2_pc_cpu_flush(struct usb2_page_cache *pc)
* Else: Failure
*------------------------------------------------------------------------*/
uint8_t
-usb2_pc_dmamap_create(struct usb2_page_cache *pc, uint32_t size)
+usb2_pc_dmamap_create(struct usb2_page_cache *pc, usb2_size_t size)
{
struct usb2_xfer_root *info;
struct usb2_dma_tag *utag;
/* get info */
- info = pc->tag_parent->info;
+ info = USB_DMATAG_TO_XROOT(pc->tag_parent);
/* sanity check */
if (info == NULL) {
@@ -1107,12 +1117,14 @@ usb2_pc_dmamap_destroy(struct usb2_page_cache *pc)
#endif
+#if USB_HAVE_BUSDMA
+
/*------------------------------------------------------------------------*
* usb2_dma_tag_find - factored out code
*------------------------------------------------------------------------*/
struct usb2_dma_tag *
usb2_dma_tag_find(struct usb2_dma_parent_tag *udpt,
- uint32_t size, uint32_t align)
+ usb2_size_t size, usb2_size_t align)
{
struct usb2_dma_tag *udt;
uint8_t nudt;
@@ -1149,8 +1161,7 @@ void
usb2_dma_tag_setup(struct usb2_dma_parent_tag *udpt,
struct usb2_dma_tag *udt, bus_dma_tag_t dmat,
struct mtx *mtx, usb2_dma_callback_t *func,
- struct usb2_xfer_root *info, uint8_t ndmabits,
- uint8_t nudt)
+ uint8_t ndmabits, uint8_t nudt)
{
bzero(udpt, sizeof(*udpt));
@@ -1168,7 +1179,6 @@ usb2_dma_tag_setup(struct usb2_dma_parent_tag *udpt,
/* store some information */
udpt->mtx = mtx;
- udpt->info = info;
udpt->func = func;
udpt->tag = dmat;
udpt->utag_first = udt;
@@ -1223,7 +1233,7 @@ usb2_bdma_work_loop(struct usb2_xfer_queue *pq)
{
struct usb2_xfer_root *info;
struct usb2_xfer *xfer;
- uint32_t nframes;
+ usb2_frcount_t nframes;
xfer = pq->curr;
info = xfer->xroot;
@@ -1239,7 +1249,7 @@ usb2_bdma_work_loop(struct usb2_xfer_queue *pq)
}
if (!xfer->flags_int.bdma_setup) {
struct usb2_page *pg;
- uint32_t frlength_0;
+ usb2_frlength_t frlength_0;
uint8_t isread;
xfer->flags_int.bdma_setup = 1;
@@ -1350,7 +1360,7 @@ usb2_bdma_done_event(struct usb2_dma_parent_tag *udpt)
{
struct usb2_xfer_root *info;
- info = udpt->info;
+ info = USB_DMATAG_TO_XROOT(udpt);
mtx_assert(info->xfer_mtx, MA_OWNED);
@@ -1372,7 +1382,7 @@ void
usb2_bdma_pre_sync(struct usb2_xfer *xfer)
{
struct usb2_page_cache *pc;
- uint32_t nframes;
+ usb2_frcount_t nframes;
if (xfer->flags_int.isochronous_xfr) {
/* only one frame buffer */
@@ -1405,7 +1415,7 @@ void
usb2_bdma_post_sync(struct usb2_xfer *xfer)
{
struct usb2_page_cache *pc;
- uint32_t nframes;
+ usb2_frcount_t nframes;
if (xfer->flags_int.isochronous_xfr) {
/* only one frame buffer */
@@ -1424,3 +1434,5 @@ usb2_bdma_post_sync(struct usb2_xfer *xfer)
pc++;
}
}
+
+#endif
diff --git a/sys/dev/usb/usb_busdma.h b/sys/dev/usb/usb_busdma.h
index 3c1600b..9653006 100644
--- a/sys/dev/usb/usb_busdma.h
+++ b/sys/dev/usb/usb_busdma.h
@@ -48,6 +48,7 @@
struct usb2_xfer_root;
struct usb2_dma_parent_tag;
+struct usb2_dma_tag;
/*
* The following typedef defines the USB DMA load done callback.
@@ -60,8 +61,10 @@ typedef void (usb2_dma_callback_t)(struct usb2_dma_parent_tag *udpt);
* address of a memory page having size USB_PAGE_SIZE.
*/
struct usb2_page {
+#if USB_HAVE_BUSDMA
bus_size_t physaddr;
void *buffer; /* non Kernel Virtual Address */
+#endif
};
/*
@@ -71,8 +74,10 @@ struct usb2_page {
*/
struct usb2_page_search {
void *buffer;
+#if USB_HAVE_BUSDMA
bus_size_t physaddr;
- uint32_t length;
+#endif
+ usb2_size_t length;
};
/*
@@ -81,100 +86,108 @@ struct usb2_page_search {
*/
struct usb2_page_cache {
-#ifdef __FreeBSD__
+#if USB_HAVE_BUSDMA && defined(__FreeBSD__)
bus_dma_tag_t tag;
bus_dmamap_t map;
#endif
-#ifdef __NetBSD__
+#if USB_HAVE_BUSDMA && defined(__NetBSD__)
bus_dma_tag_t tag;
bus_dmamap_t map;
bus_dma_segment_t *p_seg;
#endif
+#if USB_HAVE_BUSDMA
struct usb2_page *page_start;
+#endif
struct usb2_dma_parent_tag *tag_parent; /* always set */
void *buffer; /* virtual buffer pointer */
-#ifdef __NetBSD__
+#if USB_HAVE_BUSDMA && defined(_NetBSD__)
int n_seg;
#endif
- uint32_t page_offset_buf;
- uint32_t page_offset_end;
+#if USB_HAVE_BUSDMA
+ usb2_size_t page_offset_buf;
+ usb2_size_t page_offset_end;
uint8_t isread:1; /* set if we are currently reading
* from the memory. Else write. */
uint8_t ismultiseg:1; /* set if we can have multiple
* segments */
+#endif
};
/*
* The following structure describes the parent USB DMA tag.
*/
+#if USB_HAVE_BUSDMA
struct usb2_dma_parent_tag {
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__)
struct cv cv[1]; /* internal condition variable */
#endif
-
bus_dma_tag_t tag; /* always set */
struct mtx *mtx; /* private mutex, always set */
- struct usb2_xfer_root *info; /* used by the callback function */
usb2_dma_callback_t *func; /* load complete callback function */
struct usb2_dma_tag *utag_first;/* pointer to first USB DMA tag */
-
uint8_t dma_error; /* set if DMA load operation failed */
uint8_t dma_bits; /* number of DMA address lines */
uint8_t utag_max; /* number of USB DMA tags */
};
+#else
+struct usb2_dma_parent_tag {}; /* empty struct */
+#endif
/*
* The following structure describes an USB DMA tag.
*/
+#if USB_HAVE_BUSDMA
struct usb2_dma_tag {
-#ifdef __NetBSD__
+#if defined(__NetBSD__)
bus_dma_segment_t *p_seg;
#endif
struct usb2_dma_parent_tag *tag_parent;
bus_dma_tag_t tag;
- uint32_t align;
- uint32_t size;
-#ifdef __NetBSD__
- uint32_t n_seg;
+ usb2_size_t align;
+ usb2_size_t size;
+#if defined(__NetBSD__)
+ usb2_size_t n_seg;
#endif
};
+#else
+struct usb2_dma_tag {}; /* empty struct */
+#endif
/* function prototypes */
int usb2_uiomove(struct usb2_page_cache *pc, struct uio *uio,
- uint32_t pc_offset, uint32_t len);
+ usb2_frlength_t pc_offset, usb2_frlength_t len);
struct usb2_dma_tag *usb2_dma_tag_find(struct usb2_dma_parent_tag *udpt,
- uint32_t size, uint32_t align);
+ usb2_size_t size, usb2_size_t align);
uint8_t usb2_pc_alloc_mem(struct usb2_page_cache *pc, struct usb2_page *pg,
- uint32_t size, uint32_t align);
-uint8_t usb2_pc_dmamap_create(struct usb2_page_cache *pc, uint32_t size);
-uint8_t usb2_pc_load_mem(struct usb2_page_cache *pc, uint32_t size,
+ usb2_size_t size, usb2_size_t align);
+uint8_t usb2_pc_dmamap_create(struct usb2_page_cache *pc, usb2_size_t size);
+uint8_t usb2_pc_load_mem(struct usb2_page_cache *pc, usb2_size_t size,
uint8_t sync);
void usb2_bdma_done_event(struct usb2_dma_parent_tag *udpt);
void usb2_bdma_post_sync(struct usb2_xfer *xfer);
void usb2_bdma_pre_sync(struct usb2_xfer *xfer);
void usb2_bdma_work_loop(struct usb2_xfer_queue *pq);
-void usb2_bzero(struct usb2_page_cache *cache, uint32_t offset,
- uint32_t len);
-void usb2_copy_in(struct usb2_page_cache *cache, uint32_t offset,
- const void *ptr, uint32_t len);
-int usb2_copy_in_user(struct usb2_page_cache *cache, uint32_t offset,
- const void *ptr, uint32_t len);
-void usb2_copy_out(struct usb2_page_cache *cache, uint32_t offset,
- void *ptr, uint32_t len);
-int usb2_copy_out_user(struct usb2_page_cache *cache, uint32_t offset,
- void *ptr, uint32_t len);
+void usb2_bzero(struct usb2_page_cache *cache, usb2_frlength_t offset,
+ usb2_frlength_t len);
+void usb2_copy_in(struct usb2_page_cache *cache, usb2_frlength_t offset,
+ const void *ptr, usb2_frlength_t len);
+int usb2_copy_in_user(struct usb2_page_cache *cache, usb2_frlength_t offset,
+ const void *ptr, usb2_frlength_t len);
+void usb2_copy_out(struct usb2_page_cache *cache, usb2_frlength_t offset,
+ void *ptr, usb2_frlength_t len);
+int usb2_copy_out_user(struct usb2_page_cache *cache, usb2_frlength_t offset,
+ void *ptr, usb2_frlength_t len);
void usb2_dma_tag_setup(struct usb2_dma_parent_tag *udpt,
struct usb2_dma_tag *udt, bus_dma_tag_t dmat, struct mtx *mtx,
- usb2_dma_callback_t *func, struct usb2_xfer_root *info,
- uint8_t ndmabits, uint8_t nudt);
+ usb2_dma_callback_t *func, uint8_t ndmabits, uint8_t nudt);
void usb2_dma_tag_unsetup(struct usb2_dma_parent_tag *udpt);
-void usb2_get_page(struct usb2_page_cache *pc, uint32_t offset,
+void usb2_get_page(struct usb2_page_cache *pc, usb2_frlength_t offset,
struct usb2_page_search *res);
-void usb2_m_copy_in(struct usb2_page_cache *cache, uint32_t dst_offset,
- struct mbuf *m, uint32_t src_offset, uint32_t src_len);
+void usb2_m_copy_in(struct usb2_page_cache *cache, usb2_frlength_t dst_offset,
+ struct mbuf *m, usb2_size_t src_offset, usb2_frlength_t src_len);
void usb2_pc_cpu_flush(struct usb2_page_cache *pc);
void usb2_pc_cpu_invalidate(struct usb2_page_cache *pc);
void usb2_pc_dmamap_destroy(struct usb2_page_cache *pc);
diff --git a/sys/dev/usb/usb_compat_linux.c b/sys/dev/usb/usb_compat_linux.c
index 6d6c857..eed72ce 100644
--- a/sys/dev/usb/usb_compat_linux.c
+++ b/sys/dev/usb/usb_compat_linux.c
@@ -25,7 +25,6 @@
* SUCH DAMAGE.
*/
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_error.h>
@@ -68,7 +67,7 @@ static usb2_callback_t usb_linux_non_isoc_callback;
static usb_complete_t usb_linux_wait_complete;
static uint16_t usb_max_isoc_frames(struct usb_device *);
-static int usb_start_wait_urb(struct urb *, uint32_t, uint16_t *);
+static int usb_start_wait_urb(struct urb *, usb2_timeout_t, uint16_t *);
static const struct usb_device_id *usb_linux_lookup_id(
const struct usb_device_id *, struct usb2_attach_arg *);
static struct usb_driver *usb_linux_get_usb_driver(struct usb_linux_softc *);
@@ -565,7 +564,7 @@ usb_clear_halt(struct usb_device *dev, struct usb_host_endpoint *uhe)
* Linux USB transfers.
*------------------------------------------------------------------------*/
static int
-usb_start_wait_urb(struct urb *urb, uint32_t timeout, uint16_t *p_actlen)
+usb_start_wait_urb(struct urb *urb, usb2_timeout_t timeout, uint16_t *p_actlen)
{
int err;
@@ -621,7 +620,7 @@ int
usb_control_msg(struct usb_device *dev, struct usb_host_endpoint *uhe,
uint8_t request, uint8_t requesttype,
uint16_t value, uint16_t index, void *data,
- uint16_t size, uint32_t timeout)
+ uint16_t size, usb2_timeout_t timeout)
{
struct usb2_device_request req;
struct urb *urb;
@@ -742,7 +741,7 @@ usb_set_interface(struct usb_device *dev, uint8_t iface_no, uint8_t alt_index)
*------------------------------------------------------------------------*/
int
usb_setup_endpoint(struct usb_device *dev,
- struct usb_host_endpoint *uhe, uint32_t bufsize)
+ struct usb_host_endpoint *uhe, usb2_size_t bufsize)
{
struct usb2_config cfg[2];
uint8_t type = uhe->desc.bmAttributes & UE_XFERTYPE;
@@ -771,10 +770,10 @@ usb_setup_endpoint(struct usb_device *dev,
cfg[0].type = type;
cfg[0].endpoint = addr & UE_ADDR;
cfg[0].direction = addr & (UE_DIR_OUT | UE_DIR_IN);
- cfg[0].mh.callback = &usb_linux_isoc_callback;
- cfg[0].mh.bufsize = 0; /* use wMaxPacketSize */
- cfg[0].mh.frames = usb_max_isoc_frames(dev);
- cfg[0].mh.flags.proxy_buffer = 1;
+ cfg[0].callback = &usb_linux_isoc_callback;
+ cfg[0].bufsize = 0; /* use wMaxPacketSize */
+ cfg[0].frames = usb_max_isoc_frames(dev);
+ cfg[0].flags.proxy_buffer = 1;
#if 0
/*
* The Linux USB API allows non back-to-back
@@ -783,9 +782,9 @@ usb_setup_endpoint(struct usb_device *dev,
* do a copy, and then we need a buffer for
* that. Enable this at your own risk.
*/
- cfg[0].mh.flags.ext_buffer = 1;
+ cfg[0].flags.ext_buffer = 1;
#endif
- cfg[0].mh.flags.short_xfer_ok = 1;
+ cfg[0].flags.short_xfer_ok = 1;
bcopy(cfg, cfg + 1, sizeof(*cfg));
@@ -805,11 +804,11 @@ usb_setup_endpoint(struct usb_device *dev,
cfg[0].type = type;
cfg[0].endpoint = addr & UE_ADDR;
cfg[0].direction = addr & (UE_DIR_OUT | UE_DIR_IN);
- cfg[0].mh.callback = &usb_linux_non_isoc_callback;
- cfg[0].mh.bufsize = bufsize;
- cfg[0].mh.flags.ext_buffer = 1; /* enable zero-copy */
- cfg[0].mh.flags.proxy_buffer = 1;
- cfg[0].mh.flags.short_xfer_ok = 1;
+ cfg[0].callback = &usb_linux_non_isoc_callback;
+ cfg[0].bufsize = bufsize;
+ cfg[0].flags.ext_buffer = 1; /* enable zero-copy */
+ cfg[0].flags.proxy_buffer = 1;
+ cfg[0].flags.short_xfer_ok = 1;
if (usb2_transfer_setup(dev->bsd_udev, &uhe->bsd_iface_index,
uhe->bsd_xfer, cfg, 1, uhe, &Giant)) {
@@ -837,7 +836,7 @@ usb_linux_create_usb_device(struct usb2_device *udev, device_t dev)
struct usb_interface *p_ui = NULL;
struct usb_host_interface *p_uhi = NULL;
struct usb_host_endpoint *p_uhe = NULL;
- uint32_t size;
+ usb2_size_t size;
uint16_t niface_total;
uint16_t nedesc;
uint16_t iface_no_curr;
@@ -972,7 +971,7 @@ struct urb *
usb_alloc_urb(uint16_t iso_packets, uint16_t mem_flags)
{
struct urb *urb;
- uint32_t size;
+ usb2_size_t size;
if (iso_packets == 0xFFFF) {
/*
@@ -1103,7 +1102,7 @@ usb_ifnum_to_if(struct usb_device *dev, uint8_t iface_no)
* usb_buffer_alloc
*------------------------------------------------------------------------*/
void *
-usb_buffer_alloc(struct usb_device *dev, uint32_t size, uint16_t mem_flags, uint8_t *dma_addr)
+usb_buffer_alloc(struct usb_device *dev, usb2_size_t size, uint16_t mem_flags, uint8_t *dma_addr)
{
return (malloc(size, M_USBDEV, M_WAITOK | M_ZERO));
}
@@ -1194,7 +1193,7 @@ usb_linux_free_device(struct usb_device *dev)
* usb_buffer_free
*------------------------------------------------------------------------*/
void
-usb_buffer_free(struct usb_device *dev, uint32_t size,
+usb_buffer_free(struct usb_device *dev, usb2_size_t size,
void *addr, uint8_t dma_addr)
{
free(addr, M_USBDEV);
@@ -1327,9 +1326,9 @@ usb_linux_complete(struct usb2_xfer *xfer)
static void
usb_linux_isoc_callback(struct usb2_xfer *xfer)
{
- uint32_t max_frame = xfer->max_frame_size;
- uint32_t offset;
- uint16_t x;
+ usb2_frlength_t max_frame = xfer->max_frame_size;
+ usb2_frlength_t offset;
+ usb2_frcount_t x;
struct urb *urb = xfer->priv_fifo;
struct usb_host_endpoint *uhe = xfer->priv_sc;
struct usb_iso_packet_descriptor *uipd;
@@ -1501,7 +1500,7 @@ usb_linux_non_isoc_callback(struct usb2_xfer *xfer)
struct urb *urb = xfer->priv_fifo;
struct usb_host_endpoint *uhe = xfer->priv_sc;
uint8_t *ptr;
- uint32_t max_bulk = xfer->max_data_length;
+ usb2_frlength_t max_bulk = xfer->max_data_length;
uint8_t data_frame = xfer->flags_int.control_xfr ? 1 : 0;
DPRINTF("\n");
diff --git a/sys/dev/usb/usb_compat_linux.h b/sys/dev/usb/usb_compat_linux.h
index 8ebb7e3..c63d82e 100644
--- a/sys/dev/usb/usb_compat_linux.h
+++ b/sys/dev/usb/usb_compat_linux.h
@@ -321,7 +321,7 @@ struct usb_host_endpoint {
uint8_t *extra; /* Extra descriptors */
- uint32_t fbsd_buf_size;
+ usb2_frlength_t fbsd_buf_size;
uint16_t extralen;
@@ -406,10 +406,10 @@ struct urb {
void *context; /* (in) context for completion */
usb_complete_t *complete; /* (in) completion routine */
- uint32_t transfer_buffer_length;/* (in) data buffer length */
- uint32_t actual_length; /* (return) actual transfer length */
- uint32_t bsd_length_rem;
- uint32_t timeout; /* FreeBSD specific */
+ usb2_size_t transfer_buffer_length;/* (in) data buffer length */
+ usb2_size_t bsd_length_rem;
+ usb2_size_t actual_length; /* (return) actual transfer length */
+ usb2_timeout_t timeout; /* FreeBSD specific */
uint16_t transfer_flags; /* (in) */
#define URB_SHORT_NOT_OK 0x0001 /* report short transfers like errors */
@@ -420,8 +420,8 @@ struct urb {
#define URB_WAIT_WAKEUP 0x0010 /* custom flags */
#define URB_IS_SLEEPING 0x0020 /* custom flags */
- uint16_t start_frame; /* (modify) start frame (ISO) */
- uint16_t number_of_packets; /* (in) number of ISO packets */
+ usb2_frcount_t start_frame; /* (modify) start frame (ISO) */
+ usb2_frcount_t number_of_packets; /* (in) number of ISO packets */
uint16_t interval; /* (modify) transfer interval
* (INT/ISO) */
uint16_t error_count; /* (return) number of ISO errors */
@@ -441,11 +441,11 @@ int usb_unlink_urb(struct urb *urb);
int usb_clear_halt(struct usb_device *dev, struct usb_host_endpoint *uhe);
int usb_control_msg(struct usb_device *dev, struct usb_host_endpoint *pipe,
uint8_t request, uint8_t requesttype, uint16_t value,
- uint16_t index, void *data, uint16_t size, uint32_t timeout);
+ uint16_t index, void *data, uint16_t size, usb2_timeout_t timeout);
int usb_set_interface(struct usb_device *dev, uint8_t ifnum,
uint8_t alternate);
int usb_setup_endpoint(struct usb_device *dev,
- struct usb_host_endpoint *uhe, uint32_t bufsize);
+ struct usb_host_endpoint *uhe, usb2_frlength_t bufsize);
struct usb_host_endpoint *usb_find_host_endpoint(struct usb_device *dev,
uint8_t type, uint8_t ep);
@@ -454,11 +454,11 @@ struct usb_host_interface *usb_altnum_to_altsetting(
const struct usb_interface *intf, uint8_t alt_index);
struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, uint8_t iface_no);
-void *usb_buffer_alloc(struct usb_device *dev, uint32_t size,
+void *usb_buffer_alloc(struct usb_device *dev, usb2_size_t size,
uint16_t mem_flags, uint8_t *dma_addr);
void *usb_get_intfdata(struct usb_interface *intf);
-void usb_buffer_free(struct usb_device *dev, uint32_t size, void *addr, uint8_t dma_addr);
+void usb_buffer_free(struct usb_device *dev, usb2_size_t size, void *addr, uint8_t dma_addr);
void usb_free_urb(struct urb *urb);
void usb_init_urb(struct urb *urb);
void usb_kill_urb(struct urb *urb);
diff --git a/sys/dev/usb/usb_controller.h b/sys/dev/usb/usb_controller.h
index ed329d8..08be1c9 100644
--- a/sys/dev/usb/usb_controller.h
+++ b/sys/dev/usb/usb_controller.h
@@ -31,7 +31,7 @@
#define USB_BUS_DMA_TAG_MAX 8
-/* structure prototypes */
+/* structure prototypes */
struct usb2_bus;
struct usb2_page;
@@ -45,7 +45,7 @@ struct usb2_endpoint_descriptor;
/* typedefs */
-typedef void (usb2_bus_mem_sub_cb_t)(struct usb2_bus *bus, struct usb2_page_cache *pc, struct usb2_page *pg, uint32_t size, uint32_t align);
+typedef void (usb2_bus_mem_sub_cb_t)(struct usb2_bus *bus, struct usb2_page_cache *pc, struct usb2_page *pg, usb2_size_t size, usb2_size_t align);
typedef void (usb2_bus_mem_cb_t)(struct usb2_bus *bus, usb2_bus_mem_sub_cb_t *scb);
/*
@@ -108,20 +108,15 @@ struct usb2_pipe_methods {
/* Mandatory USB Device and Host mode callbacks: */
- void (*open) (struct usb2_xfer *xfer);
- void (*close) (struct usb2_xfer *xfer);
+ usb2_callback_t *open;
+ usb2_callback_t *close;
- void (*enter) (struct usb2_xfer *xfer);
- void (*start) (struct usb2_xfer *xfer);
+ usb2_callback_t *enter;
+ usb2_callback_t *start;
/* Optional */
void *info;
-
- /* Flags */
-
- uint8_t enter_is_cancelable:1;
- uint8_t start_is_cancelable:1;
};
/*
@@ -175,7 +170,7 @@ struct usb2_hw_ep_scratch {
*/
struct usb2_temp_setup {
void *buf;
- uint32_t size;
+ usb2_size_t size;
uint8_t usb2_speed;
uint8_t self_powered;
uint8_t bNumEndpoints;
@@ -190,7 +185,6 @@ struct usb2_temp_setup {
void usb2_bus_mem_flush_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb);
uint8_t usb2_bus_mem_alloc_all(struct usb2_bus *bus, bus_dma_tag_t dmat, usb2_bus_mem_cb_t *cb);
void usb2_bus_mem_free_all(struct usb2_bus *bus, usb2_bus_mem_cb_t *cb);
-void usb2_bus_roothub_exec(struct usb2_bus *bus);
uint16_t usb2_isoc_time_expand(struct usb2_bus *bus, uint16_t isoc_time_curr);
uint16_t usb2_fs_isoc_schedule_isoc_time_expand(struct usb2_device *udev, struct usb2_fs_isoc_schedule **pp_start, struct usb2_fs_isoc_schedule **pp_end, uint16_t isoc_time);
uint8_t usb2_fs_isoc_schedule_alloc(struct usb2_fs_isoc_schedule *fss, uint8_t *pstart, uint16_t len);
diff --git a/sys/dev/usb/usb_core.h b/sys/dev/usb/usb_core.h
index 6067815..cb08476 100644
--- a/sys/dev/usb/usb_core.h
+++ b/sys/dev/usb/usb_core.h
@@ -25,23 +25,116 @@
*/
/*
- * Including this file is mandatory for all USB related c-files in the
- * kernel.
+ * Including this file is mandatory for all USB related c-files in the kernel.
*/
#ifndef _USB2_CORE_H_
#define _USB2_CORE_H_
+#define USB_STACK_VERSION 2000 /* 2.0 */
+
+/* Allow defines in "opt_usb.h" to override configuration */
+
+#include "opt_usb.h"
+#include "opt_bus.h"
+
/* Default USB configuration */
-#ifndef USB_USE_CONDVAR
-#define USB_USE_CONDVAR 0
+/*
+ * The following macro defines if the code shall use cv_xxx() instead
+ * of msleep() and wakeup().
+ */
+#ifndef USB_HAVE_CONDVAR
+#define USB_HAVE_CONDVAR 0
#endif
+/*
+ * The following macro defines if the code shall support
+ * /dev/usb/x.y.z.
+ */
#ifndef USB_HAVE_UGEN
#define USB_HAVE_UGEN 1
#endif
+/*
+ * The following macro defines if the code shall support any forms of
+ * ASCII strings.
+ */
+#ifndef USB_HAVE_STRINGS
+#define USB_HAVE_STRINGS 1
+#endif
+
+/*
+ * The following macro defines if the code shall support BUS-DMA.
+ */
+#ifndef USB_HAVE_BUSDMA
+#define USB_HAVE_BUSDMA 1
+#endif
+
+/*
+ * The following macro defines if the code shall support the Linux
+ * compatibility layer.
+ */
+#ifndef USB_HAVE_COMPAT_LINUX
+#define USB_HAVE_COMPAT_LINUX 1
+#endif
+
+/*
+ * The following macro defines if the code shall support
+ * userland data transfer via copyin() and copyout()
+ */
+#ifndef USB_HAVE_USER_IO
+#define USB_HAVE_USER_IO 1
+#endif
+
+/*
+ * The following macro defines if the code shall support copy in via
+ * bsd-mbufs to USB.
+ */
+#ifndef USB_HAVE_MBUF
+#define USB_HAVE_MBUF 1
+#endif
+
+/*
+ * The following macro defines if the code shall compile a table
+ * describing USB vendor and product IDs.
+ */
+#ifndef USB_VERBOSE
+#define USB_VERBOSE 1
+#endif
+
+/*
+ * The following macro defines if USB debugging support shall be
+ * compiled for the USB core and all drivers.
+ */
+#ifndef USB_DEBUG
+#define USB_DEBUG 1
+#endif
+
+/*
+ * The following macro defines if USB transaction translator support
+ * shall be supported for the USB HUB and USB controller drivers.
+ */
+#ifndef USB_HAVE_TT_SUPPORT
+#define USB_HAVE_TT_SUPPORT 1
+#endif
+
+/*
+ * The following macro defines if the USB power daemon shall
+ * be supported in the USB core.
+ */
+#ifndef USB_HAVE_POWERD
+#define USB_HAVE_POWERD 1
+#endif
+
+/*
+ * The following macro defines if the USB autoinstall detection shall
+ * be supported in the USB core.
+ */
+#ifndef USB_HAVE_MSCTEST
+#define USB_HAVE_MSCTEST 1
+#endif
+
#ifndef USB_TD_GET_PROC
#define USB_TD_GET_PROC(td) (td)->td_proc
#endif
@@ -72,34 +165,57 @@
#include <sys/malloc.h>
#include <sys/priv.h>
-#include <dev/usb/usb_mfunc.h>
+#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_revision.h>
#include "usb_if.h"
-#include "opt_usb.h"
-#include "opt_bus.h"
-
-#define USB_STACK_VERSION 2000 /* 2.0 */
+#ifndef USB_HOST_ALIGN
#define USB_HOST_ALIGN 8 /* bytes, must be power of two */
+#endif
-#define USB_ISOC_TIME_MAX 128 /* ms */
+#ifndef USB_FS_ISOC_UFRAME_MAX
#define USB_FS_ISOC_UFRAME_MAX 4 /* exclusive unit */
+#endif
#if (USB_FS_ISOC_UFRAME_MAX > 6)
#error "USB_FS_ISOC_UFRAME_MAX cannot be set higher than 6"
#endif
+#ifndef USB_BUS_MAX
+#define USB_BUS_MAX 256 /* units */
+#endif
+
+#ifndef USB_MAX_DEVICES
+#define USB_MAX_DEVICES 128 /* units */
+#endif
+
+#if (USB_MAX_DEVICES < USB_MIN_DEVICES)
+#error "Minimum number of devices is greater than maximum number of devices."
+#endif
+
+#ifndef USB_IFACE_MAX
+#define USB_IFACE_MAX 32 /* units */
+#endif
+
+#ifndef USB_FIFO_MAX
+#define USB_FIFO_MAX 128 /* units */
+#endif
+
+#if (USB_FIFO_MAX & 1)
+#error "Number of FIFOs must be odd."
+#endif
+
#define USB_MAX_FS_ISOC_FRAMES_PER_XFER (120) /* units */
#define USB_MAX_HS_ISOC_FRAMES_PER_XFER (8*120) /* units */
-#define USB_MAX_IPACKET 8 /* maximum size of the initial USB
- * data packet */
-#ifndef USB_VERBOSE
-#define USB_VERBOSE 1
+#ifndef USB_HUB_MAX_DEPTH
+#define USB_HUB_MAX_DEPTH 5
#endif
-#define USB_HUB_MAX_DEPTH 5
+#ifndef USB_EP0_BUFSIZE
+#define USB_EP0_BUFSIZE 1024 /* bytes */
+#endif
/* USB transfer states */
@@ -157,10 +273,36 @@ struct usb2_xfer_root;
/* typedefs */
-typedef uint8_t usb2_error_t;
-
typedef void (usb2_callback_t)(struct usb2_xfer *);
+#ifndef USB_HAVE_USB_ERROR_T
+typedef uint8_t usb2_error_t; /* see "USB_ERR_XXX" */
+#endif
+
+#ifndef USB_HAVE_TIMEOUT_T
+typedef uint32_t usb2_timeout_t; /* milliseconds */
+#endif
+
+#ifndef USB_HAVE_FRLENGTH_T
+typedef uint32_t usb2_frlength_t; /* bytes */
+#endif
+
+#ifndef USB_HAVE_FRCOUNT_T
+typedef uint32_t usb2_frcount_t; /* units */
+#endif
+
+#ifndef USB_HAVE_SIZE_T
+typedef uint32_t usb2_size_t; /* bytes */
+#endif
+
+#ifndef USB_HAVE_TICKS_T
+typedef uint32_t usb2_ticks_t; /* system defined */
+#endif
+
+#ifndef USB_HAVE_POWER_MASK_T
+typedef uint16_t usb2_power_mask_t; /* see "USB_HW_POWER_XXX" */
+#endif
+
/* structures */
/*
@@ -226,12 +368,14 @@ struct usb2_xfer_flags_int {
uint8_t short_frames_ok:1; /* filtered version */
uint8_t short_xfer_ok:1; /* filtered version */
+#if USB_HAVE_BUSDMA
uint8_t bdma_enable:1; /* filtered version (only set if
* hardware supports DMA) */
uint8_t bdma_no_post_sync:1; /* set if the USB callback wrapper
* should not do the BUS-DMA post sync
* operation */
uint8_t bdma_setup:1; /* set if BUS-DMA has been setup */
+#endif
uint8_t isochronous_xfr:1; /* set if isochronous transfer */
uint8_t usb2_mode:1; /* shadow copy of "udev->usb2_mode" */
uint8_t curr_dma_set:1; /* used by USB HC/DC driver */
@@ -240,31 +384,24 @@ struct usb2_xfer_flags_int {
};
/*
- * The following structure defines the symmetric part of an USB config
- * structure.
- */
-struct usb2_config_sub {
- usb2_callback_t *callback; /* USB transfer callback */
- uint32_t bufsize; /* total pipe buffer size in bytes */
- uint32_t frames; /* maximum number of USB frames */
- uint16_t interval; /* interval in milliseconds */
-#define USB_DEFAULT_INTERVAL 0
- uint16_t timeout; /* transfer timeout in milliseconds */
- struct usb2_xfer_flags flags; /* transfer flags */
-};
-
-/*
* The following structure define an USB configuration, that basically
* is used when setting up an USB transfer.
*/
struct usb2_config {
- struct usb2_config_sub mh; /* parameters for USB_MODE_HOST */
- struct usb2_config_sub md; /* parameters for USB_MODE_DEVICE */
+ usb2_callback_t *callback; /* USB transfer callback */
+ usb2_frlength_t bufsize; /* total pipe buffer size in bytes */
+ usb2_frcount_t frames; /* maximum number of USB frames */
+ usb2_timeout_t interval; /* interval in milliseconds */
+#define USB_DEFAULT_INTERVAL 0
+ usb2_timeout_t timeout; /* transfer timeout in milliseconds */
+ struct usb2_xfer_flags flags; /* transfer flags */
uint8_t type; /* pipe type */
uint8_t endpoint; /* pipe number */
uint8_t direction; /* pipe direction */
uint8_t ep_index; /* pipe index match to use */
uint8_t if_index; /* "ifaces" index to use */
+ uint8_t usb_mode; /* see "USB_MODE_XXX",
+ * "USB_MODE_MAX" means any mode! */
};
/*
@@ -288,29 +425,29 @@ struct usb2_xfer {
void *priv_sc; /* device driver data pointer 1 */
void *priv_fifo; /* device driver data pointer 2 */
void *local_buffer;
- uint32_t *frlengths;
+ usb2_frlength_t *frlengths;
struct usb2_page_cache *frbuffers;
usb2_callback_t *callback;
- uint32_t max_usb2_frame_size;
- uint32_t max_data_length;
- uint32_t sumlen; /* sum of all lengths in bytes */
- uint32_t actlen; /* actual length in bytes */
- uint32_t timeout; /* milliseconds */
+ usb2_frlength_t max_hc_frame_size;
+ usb2_frlength_t max_data_length;
+ usb2_frlength_t sumlen; /* sum of all lengths in bytes */
+ usb2_frlength_t actlen; /* actual length in bytes */
+ usb2_timeout_t timeout; /* milliseconds */
#define USB_NO_TIMEOUT 0
#define USB_DEFAULT_TIMEOUT 5000 /* 5000 ms = 5 seconds */
- uint32_t max_frame_count; /* initial value of "nframes" after
+ usb2_frcount_t max_frame_count; /* initial value of "nframes" after
* setup */
- uint32_t nframes; /* number of USB frames to transfer */
- uint32_t aframes; /* actual number of USB frames
+ usb2_frcount_t nframes; /* number of USB frames to transfer */
+ usb2_frcount_t aframes; /* actual number of USB frames
* transferred */
uint16_t max_packet_size;
uint16_t max_frame_size;
uint16_t qh_pos;
uint16_t isoc_time_complete; /* in ms */
- uint16_t interval; /* milliseconds */
+ usb2_timeout_t interval; /* milliseconds */
uint8_t address; /* physical USB address */
uint8_t endpoint; /* physical USB endpoint */
@@ -395,9 +532,9 @@ usb2_error_t usb2_transfer_setup(struct usb2_device *udev,
const struct usb2_config *setup_start, uint16_t n_setup,
void *priv_sc, struct mtx *priv_mtx);
void usb2_set_frame_data(struct usb2_xfer *xfer, void *ptr,
- uint32_t frindex);
-void usb2_set_frame_offset(struct usb2_xfer *xfer, uint32_t offset,
- uint32_t frindex);
+ usb2_frcount_t frindex);
+void usb2_set_frame_offset(struct usb2_xfer *xfer, usb2_frlength_t offset,
+ usb2_frcount_t frindex);
void usb2_start_hardware(struct usb2_xfer *xfer);
void usb2_transfer_clear_stall(struct usb2_xfer *xfer);
void usb2_transfer_drain(struct usb2_xfer *xfer);
diff --git a/sys/dev/usb/usb_debug.c b/sys/dev/usb/usb_debug.c
index b7eeea7..da317fe 100644
--- a/sys/dev/usb/usb_debug.c
+++ b/sys/dev/usb/usb_debug.c
@@ -25,7 +25,6 @@
*/
#include <dev/usb/usb.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_debug.h>
diff --git a/sys/dev/usb/usb_debug.h b/sys/dev/usb/usb_debug.h
index 92dcbd5..3d1f872 100644
--- a/sys/dev/usb/usb_debug.h
+++ b/sys/dev/usb/usb_debug.h
@@ -35,11 +35,6 @@ SYSCTL_DECL(_hw_usb2);
/* Declare global USB debug variable. */
extern int usb2_debug;
-/* Force debugging until further */
-#ifndef USB_DEBUG
-#define USB_DEBUG 1
-#endif
-
/* Check if USB debugging is enabled. */
#ifdef USB_DEBUG_VAR
#if (USB_DEBUG != 0)
diff --git a/sys/dev/usb/usb_defs.h b/sys/dev/usb/usb_defs.h
index 64caf39..4f72ea5 100644
--- a/sys/dev/usb/usb_defs.h
+++ b/sys/dev/usb/usb_defs.h
@@ -27,22 +27,16 @@
#ifndef _USB2_DEFS_H_
#define _USB2_DEFS_H_
-/* Definition of some USB constants */
+/* Definition of some hardcoded USB constants. */
+
+#define USB_MAX_IPACKET 8 /* initial USB packet size */
-#define USB_BUS_MAX 256 /* units */
-#define USB_DEV_MAX 128 /* units */
-#define USB_IFACE_MAX 32 /* units */
#define USB_EP_MAX (2*16) /* hardcoded */
-#define USB_FIFO_MAX (4 * USB_EP_MAX)
#define USB_ROOT_HUB_ADDR 1 /* index */
#define USB_MIN_DEVICES 2 /* unused + root HUB */
-#define USB_MAX_DEVICES USB_DEV_MAX /* including virtual root HUB and
- * address zero */
-#define USB_MAX_ENDPOINTS USB_EP_MAX /* 2 directions on 16 endpoints */
-
#define USB_UNCONFIG_INDEX 0xFF /* internal use only */
#define USB_IFACE_INDEX_ANY 0xFF /* internal use only */
@@ -57,20 +51,10 @@
#define USB_FS_BYTES_PER_HS_UFRAME 188 /* bytes */
#define USB_HS_MICRO_FRAMES_MAX 8 /* units */
+#define USB_ISOC_TIME_MAX 128 /* ms */
+
/* sanity checks */
-#if (USB_FIFO_MAX < USB_EP_MAX)
-#error "There cannot be less FIFOs than USB endpoints."
-#endif
-#if (USB_FIFO_MAX & 1)
-#error "Number of FIFOs must be odd."
-#endif
-#if (USB_EP_MAX < (2*16))
-#error "Number of hardware USB endpoints cannot be less than 32."
-#endif
-#if (USB_MAX_DEVICES < USB_MIN_DEVICES)
-#error "Minimum number of devices is greater than maximum number of devices."
-#endif
#if (USB_ROOT_HUB_ADDR >= USB_MIN_DEVICES)
#error "The root hub address must be less than USB_MIN_DEVICES."
#endif
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c
index 512b1f8..d9d81e0 100644
--- a/sys/dev/usb/usb_dev.c
+++ b/sys/dev/usb/usb_dev.c
@@ -29,7 +29,6 @@
#include <dev/usb/usb.h>
#include <dev/usb/usb_ioctl.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
@@ -55,6 +54,8 @@
#include <machine/stdarg.h>
+#if USB_HAVE_UGEN
+
#if USB_DEBUG
static int usb2_fifo_debug = 0;
@@ -72,7 +73,8 @@ SYSCTL_INT(_hw_usb2_dev, OID_AUTO, debug, CTLFLAG_RW,
/* prototypes */
-static int usb2_fifo_open(struct usb2_fifo *, int);
+static int usb2_fifo_open(struct usb2_cdev_privdata *,
+ struct usb2_fifo *, int);
static void usb2_fifo_close(struct usb2_fifo *, int);
static void usb2_dev_init(void *);
static void usb2_dev_init_post(void *);
@@ -87,7 +89,7 @@ static void usb2_loc_fill(struct usb2_fs_privdata *,
struct usb2_cdev_privdata *);
static void usb2_close(void *);
static usb2_error_t usb2_ref_device(struct usb2_cdev_privdata *, int);
-static usb2_error_t usb2_uref_location(struct usb2_cdev_privdata *);
+static usb2_error_t usb2_usb_ref_device(struct usb2_cdev_privdata *);
static void usb2_unref_device(struct usb2_cdev_privdata *);
static d_open_t usb2_open;
@@ -160,7 +162,6 @@ usb2_ref_device(struct usb2_cdev_privdata* cpd, int need_uref)
{
struct usb2_fifo **ppf;
struct usb2_fifo *f;
- int dev_ep_index;
DPRINTFN(2, "usb2_ref_device, cpd=%p need uref=%d\n", cpd, need_uref);
@@ -179,8 +180,23 @@ usb2_ref_device(struct usb2_cdev_privdata* cpd, int need_uref)
DPRINTFN(2, "no dev ref\n");
goto error;
}
+ if (need_uref) {
+ DPRINTFN(2, "ref udev - needed\n");
+ cpd->udev->refcount++;
+ cpd->is_uref = 1;
+
+ mtx_unlock(&usb2_ref_lock);
+
+ /*
+ * We need to grab the sx-lock before grabbing the
+ * FIFO refs to avoid deadlock at detach!
+ */
+ sx_xlock(cpd->udev->default_sx + 1);
+
+ mtx_lock(&usb2_ref_lock);
+ }
+
/* check if we are doing an open */
- dev_ep_index = cpd->ep_addr;
if (cpd->fflags == 0) {
/* set defaults */
cpd->txfifo = NULL;
@@ -200,15 +216,12 @@ usb2_ref_device(struct usb2_cdev_privdata* cpd, int need_uref)
cpd->is_write = 1; /* ref */
if (f == NULL || f->refcount == USB_FIFO_REF_MAX)
goto error;
+ if (f->curr_cpd != cpd)
+ goto error;
/* check if USB-FS is active */
if (f->fs_ep_max != 0) {
cpd->is_usbfs = 1;
}
- /*
- * Get real endpoint index associated with
- * this FIFO:
- */
- dev_ep_index = f->dev_ep_index;
} else {
cpd->txfifo = NULL;
cpd->is_write = 0; /* no ref */
@@ -222,15 +235,12 @@ usb2_ref_device(struct usb2_cdev_privdata* cpd, int need_uref)
cpd->is_read = 1; /* ref */
if (f == NULL || f->refcount == USB_FIFO_REF_MAX)
goto error;
+ if (f->curr_cpd != cpd)
+ goto error;
/* check if USB-FS is active */
if (f->fs_ep_max != 0) {
cpd->is_usbfs = 1;
}
- /*
- * Get real endpoint index associated with
- * this FIFO:
- */
- dev_ep_index = f->dev_ep_index;
} else {
cpd->rxfifo = NULL;
cpd->is_read = 0; /* no ref */
@@ -246,31 +256,28 @@ usb2_ref_device(struct usb2_cdev_privdata* cpd, int need_uref)
DPRINTFN(2, "ref read\n");
cpd->rxfifo->refcount++;
}
- if (need_uref) {
- DPRINTFN(2, "ref udev - needed\n");
- cpd->udev->refcount++;
- cpd->is_uref = 1;
- }
mtx_unlock(&usb2_ref_lock);
if (cpd->is_uref) {
- /*
- * We are about to alter the bus-state. Apply the
- * required locks.
- */
- sx_xlock(cpd->udev->default_sx + 1);
mtx_lock(&Giant); /* XXX */
}
return (0);
error:
+ if (cpd->is_uref) {
+ sx_unlock(cpd->udev->default_sx + 1);
+ if (--(cpd->udev->refcount) == 0) {
+ usb2_cv_signal(cpd->udev->default_cv + 1);
+ }
+ cpd->is_uref = 0;
+ }
mtx_unlock(&usb2_ref_lock);
DPRINTFN(2, "fail\n");
return (USB_ERR_INVAL);
}
/*------------------------------------------------------------------------*
- * usb2_uref_location
+ * usb2_usb_ref_device
*
* This function is used to upgrade an USB reference to include the
* USB device reference on a USB location.
@@ -280,46 +287,21 @@ error:
* Else: Failure.
*------------------------------------------------------------------------*/
static usb2_error_t
-usb2_uref_location(struct usb2_cdev_privdata *cpd)
+usb2_usb_ref_device(struct usb2_cdev_privdata *cpd)
{
/*
* Check if we already got an USB reference on this location:
*/
- if (cpd->is_uref) {
+ if (cpd->is_uref)
return (0); /* success */
- }
- mtx_lock(&usb2_ref_lock);
- if (cpd->bus != devclass_get_softc(usb2_devclass_ptr, cpd->bus_index)) {
- DPRINTFN(2, "bus changed at %u\n", cpd->bus_index);
- goto error;
- }
- if (cpd->udev != cpd->bus->devices[cpd->dev_index]) {
- DPRINTFN(2, "device changed at %u\n", cpd->dev_index);
- goto error;
- }
- if (cpd->udev->refcount == USB_DEV_REF_MAX) {
- DPRINTFN(2, "no dev ref\n");
- goto error;
- }
- DPRINTFN(2, "ref udev\n");
- cpd->udev->refcount++;
- mtx_unlock(&usb2_ref_lock);
-
- /* set "uref" */
- cpd->is_uref = 1;
/*
- * We are about to alter the bus-state. Apply the
- * required locks.
+ * To avoid deadlock at detach we need to drop the FIFO ref
+ * and re-acquire a new ref!
*/
- sx_xlock(cpd->udev->default_sx + 1);
- mtx_lock(&Giant); /* XXX */
- return (0);
+ usb2_unref_device(cpd);
-error:
- mtx_unlock(&usb2_ref_lock);
- DPRINTFN(2, "fail\n");
- return (USB_ERR_INVAL);
+ return (usb2_ref_device(cpd, 1 /* need uref */));
}
/*------------------------------------------------------------------------*
@@ -434,7 +416,7 @@ usb2_fifo_create(struct usb2_cdev_privdata *cpd)
/* wrong endpoint index */
continue;
}
- if (f->opened) {
+ if (f->curr_cpd != NULL) {
/* FIFO is opened */
is_busy = 1;
continue;
@@ -451,7 +433,7 @@ usb2_fifo_create(struct usb2_cdev_privdata *cpd)
/* wrong endpoint index */
continue;
}
- if (f->opened) {
+ if (f->curr_cpd != NULL) {
/* FIFO is opened */
is_busy = 1;
continue;
@@ -466,10 +448,20 @@ usb2_fifo_create(struct usb2_cdev_privdata *cpd)
if (no_null == 0) {
if (ep >= (USB_EP_MAX / 2)) {
/* we don't create any endpoints in this range */
- DPRINTFN(5, "dev_ep_index out of range\n");
+ DPRINTFN(5, "ep out of range\n");
return (is_busy ? EBUSY : EINVAL);
}
}
+
+ if ((ep != 0) && is_busy) {
+ /*
+ * Only the default control endpoint is allowed to be
+ * opened multiple times!
+ */
+ DPRINTFN(5, "busy\n");
+ return (EBUSY);
+ }
+
/* Check TX FIFO */
if (is_tx &&
(udev->fifo[n + USB_FIFO_TX] == NULL)) {
@@ -639,7 +631,8 @@ usb2_dev_get_pipe(struct usb2_device *udev, uint8_t ep_index, uint8_t dir)
* Else: Failure
*------------------------------------------------------------------------*/
static int
-usb2_fifo_open(struct usb2_fifo *f, int fflags)
+usb2_fifo_open(struct usb2_cdev_privdata *cpd,
+ struct usb2_fifo *f, int fflags)
{
int err;
@@ -660,11 +653,14 @@ usb2_fifo_open(struct usb2_fifo *f, int fflags)
/* check if we are already opened */
/* we don't need any locks when checking this variable */
- if (f->opened) {
+ if (f->curr_cpd != NULL) {
err = EBUSY;
goto done;
}
+ /* reset short flag before open */
+ f->flag_short = 0;
+
/* call open method */
err = (f->methods->f_open) (f, fflags);
if (err) {
@@ -690,9 +686,9 @@ usb2_fifo_open(struct usb2_fifo *f, int fflags)
/* reset ASYNC proc flag */
f->async_p = NULL;
- /* flag the fifo as opened to prevent others */
mtx_lock(&usb2_ref_lock);
- f->opened = 1;
+ /* flag the fifo as opened to prevent others */
+ f->curr_cpd = cpd;
mtx_unlock(&usb2_ref_lock);
/* reset queue */
@@ -733,14 +729,14 @@ usb2_fifo_close(struct usb2_fifo *f, int fflags)
int err;
/* check if we are not opened */
- if (!f->opened) {
+ if (f->curr_cpd == NULL) {
/* nothing to do - already closed */
return;
}
mtx_lock(f->priv_mtx);
- /* clear current file flag */
- f->opened = 0;
+ /* clear current cdev private data pointer */
+ f->curr_cpd = NULL;
/* check if we are selected */
if (f->flag_isselect) {
@@ -813,7 +809,7 @@ usb2_open(struct cdev *dev, int fflags, int devtype, struct thread *td)
struct usb2_cdev_privdata *cpd;
int err, ep;
- DPRINTFN(2, "fflags=0x%08x\n", fflags);
+ DPRINTFN(2, "%s fflags=0x%08x\n", dev->si_name, fflags);
KASSERT(fflags & (FREAD|FWRITE), ("invalid open flags"));
if (((fflags & FREAD) && !(pd->mode & FREAD)) ||
@@ -834,21 +830,6 @@ usb2_open(struct cdev *dev, int fflags, int devtype, struct thread *td)
}
cpd->fflags = fflags; /* access mode for open lifetime */
- /* Check if the endpoint is already open, we always allow EP0 */
- if (ep > 0) {
- if ((fflags & FREAD && cpd->udev->ep_rd_opened & (1 << ep)) ||
- (fflags & FWRITE && cpd->udev->ep_wr_opened & (1 << ep))) {
- DPRINTFN(2, "endpoint already open\n");
- usb2_unref_device(cpd);
- free(cpd, M_USBDEV);
- return (EBUSY);
- }
- if (fflags & FREAD)
- cpd->udev->ep_rd_opened |= (1 << ep);
- if (fflags & FWRITE)
- cpd->udev->ep_wr_opened |= (1 << ep);
- }
-
/* create FIFOs, if any */
err = usb2_fifo_create(cpd);
/* check for error */
@@ -859,7 +840,7 @@ usb2_open(struct cdev *dev, int fflags, int devtype, struct thread *td)
return (err);
}
if (fflags & FREAD) {
- err = usb2_fifo_open(cpd->rxfifo, fflags);
+ err = usb2_fifo_open(cpd, cpd->rxfifo, fflags);
if (err) {
DPRINTFN(2, "read open failed\n");
usb2_unref_device(cpd);
@@ -868,7 +849,7 @@ usb2_open(struct cdev *dev, int fflags, int devtype, struct thread *td)
}
}
if (fflags & FWRITE) {
- err = usb2_fifo_open(cpd->txfifo, fflags);
+ err = usb2_fifo_open(cpd, cpd->txfifo, fflags);
if (err) {
DPRINTFN(2, "write open failed\n");
if (fflags & FREAD) {
@@ -892,27 +873,20 @@ static void
usb2_close(void *arg)
{
struct usb2_cdev_privdata *cpd = arg;
- struct usb2_device *udev;
int err;
- DPRINTFN(2, "usb2_close, cpd=%p\n", cpd);
+ DPRINTFN(2, "cpd=%p\n", cpd);
err = usb2_ref_device(cpd, 1);
if (err) {
free(cpd, M_USBDEV);
return;
}
-
- udev = cpd->udev;
if (cpd->fflags & FREAD) {
usb2_fifo_close(cpd->rxfifo, cpd->fflags);
- /* clear read bitmask */
- udev->ep_rd_opened &= ~(1 << cpd->ep_addr);
}
if (cpd->fflags & FWRITE) {
usb2_fifo_close(cpd->txfifo, cpd->fflags);
- /* clear write bitmask */
- udev->ep_wr_opened &= ~(1 << cpd->ep_addr);
}
usb2_unref_device(cpd);
@@ -1004,6 +978,7 @@ usb2_ioctl_f_sub(struct usb2_fifo *f, u_long cmd, void *addr,
default:
return (ENOIOCTL);
}
+ DPRINTFN(3, "cmd 0x%lx = %d\n", cmd, error);
return (error);
}
@@ -1018,6 +993,8 @@ usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread*
int fflags;
int err;
+ DPRINTFN(2, "cmd=0x%lx\n", cmd);
+
err = devfs_get_cdevpriv((void **)&cpd);
if (err != 0)
return (err);
@@ -1033,8 +1010,6 @@ usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread*
}
fflags = cpd->fflags;
- DPRINTFN(2, "fflags=%u, cmd=0x%lx\n", fflags, cmd);
-
f = NULL; /* set default value */
err = ENOIOCTL; /* set default value */
@@ -1049,12 +1024,14 @@ usb2_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread*
KASSERT(f != NULL, ("fifo not found"));
if (err == ENOIOCTL) {
err = (f->methods->f_ioctl) (f, cmd, addr, fflags);
+ DPRINTFN(2, "f_ioctl cmd 0x%lx = %d\n", cmd, err);
if (err == ENOIOCTL) {
- if (usb2_uref_location(cpd)) {
+ if (usb2_usb_ref_device(cpd)) {
err = ENXIO;
goto done;
}
err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags);
+ DPRINTFN(2, "f_ioctl_post cmd 0x%lx = %d\n", cmd, err);
}
}
if (err == ENOIOCTL) {
@@ -1621,7 +1598,7 @@ usb2_fifo_attach(struct usb2_device *udev, void *priv_sc,
/* initialise FIFO structures */
f_tx->fifo_index = n + USB_FIFO_TX;
- f_tx->dev_ep_index = (n / 2) + (USB_EP_MAX / 2);
+ f_tx->dev_ep_index = -1;
f_tx->priv_mtx = priv_mtx;
f_tx->priv_sc0 = priv_sc;
f_tx->methods = pm;
@@ -1629,7 +1606,7 @@ usb2_fifo_attach(struct usb2_device *udev, void *priv_sc,
f_tx->udev = udev;
f_rx->fifo_index = n + USB_FIFO_RX;
- f_rx->dev_ep_index = (n / 2) + (USB_EP_MAX / 2);
+ f_rx->dev_ep_index = -1;
f_rx->priv_mtx = priv_mtx;
f_rx->priv_sc0 = priv_sc;
f_rx->methods = pm;
@@ -1684,12 +1661,13 @@ usb2_fifo_attach(struct usb2_device *udev, void *priv_sc,
pd->bus_index = device_get_unit(udev->bus->bdev);
pd->dev_index = udev->device_index;
pd->ep_addr = -1; /* not an endpoint */
- pd->fifo_index = f_tx->fifo_index;
+ pd->fifo_index = f_tx->fifo_index & f_rx->fifo_index;
pd->mode = FREAD|FWRITE;
/* Now, create the device itself */
f_sc->dev = make_dev(&usb2_devsw, 0, uid, gid, mode,
devname);
+ /* XXX setting si_drv1 and creating the device is not atomic! */
f_sc->dev->si_drv1 = pd;
}
@@ -1705,7 +1683,7 @@ usb2_fifo_attach(struct usb2_device *udev, void *priv_sc,
* Else failure
*------------------------------------------------------------------------*/
int
-usb2_fifo_alloc_buffer(struct usb2_fifo *f, uint32_t bufsize,
+usb2_fifo_alloc_buffer(struct usb2_fifo *f, usb2_size_t bufsize,
uint16_t nbuf)
{
usb2_fifo_free_buffer(f);
@@ -1762,17 +1740,19 @@ usb2_fifo_detach(struct usb2_fifo_sc *f_sc)
f_sc->fp[USB_FIFO_RX] = NULL;
if (f_sc->dev != NULL) {
- destroy_dev_sched_cb(f_sc->dev, usb2_fifo_cleanup, f_sc->dev->si_drv1);
+ destroy_dev_sched_cb(f_sc->dev,
+ usb2_fifo_cleanup, f_sc->dev->si_drv1);
+ f_sc->dev = NULL;
}
DPRINTFN(2, "detached %p\n", f_sc);
}
-uint32_t
+usb2_size_t
usb2_fifo_put_bytes_max(struct usb2_fifo *f)
{
struct usb2_mbuf *m;
- uint32_t len;
+ usb2_size_t len;
USB_IF_POLL(&f->free_q, m);
@@ -1793,10 +1773,10 @@ usb2_fifo_put_bytes_max(struct usb2_fifo *f)
*------------------------------------------------------------------------*/
void
usb2_fifo_put_data(struct usb2_fifo *f, struct usb2_page_cache *pc,
- uint32_t offset, uint32_t len, uint8_t what)
+ usb2_frlength_t offset, usb2_frlength_t len, uint8_t what)
{
struct usb2_mbuf *m;
- uint32_t io_len;
+ usb2_frlength_t io_len;
while (len || (what == 1)) {
@@ -1831,10 +1811,10 @@ usb2_fifo_put_data(struct usb2_fifo *f, struct usb2_page_cache *pc,
void
usb2_fifo_put_data_linear(struct usb2_fifo *f, void *ptr,
- uint32_t len, uint8_t what)
+ usb2_size_t len, uint8_t what)
{
struct usb2_mbuf *m;
- uint32_t io_len;
+ usb2_size_t io_len;
while (len || (what == 1)) {
@@ -1868,7 +1848,7 @@ usb2_fifo_put_data_linear(struct usb2_fifo *f, void *ptr,
}
uint8_t
-usb2_fifo_put_data_buffer(struct usb2_fifo *f, void *ptr, uint32_t len)
+usb2_fifo_put_data_buffer(struct usb2_fifo *f, void *ptr, usb2_size_t len)
{
struct usb2_mbuf *m;
@@ -1904,11 +1884,11 @@ usb2_fifo_put_data_error(struct usb2_fifo *f)
*------------------------------------------------------------------------*/
uint8_t
usb2_fifo_get_data(struct usb2_fifo *f, struct usb2_page_cache *pc,
- uint32_t offset, uint32_t len, uint32_t *actlen,
+ usb2_frlength_t offset, usb2_frlength_t len, usb2_frlength_t *actlen,
uint8_t what)
{
struct usb2_mbuf *m;
- uint32_t io_len;
+ usb2_frlength_t io_len;
uint8_t tr_data = 0;
actlen[0] = 0;
@@ -1949,6 +1929,13 @@ usb2_fifo_get_data(struct usb2_fifo *f, struct usb2_page_cache *pc,
break;
}
if (f->flag_flushing) {
+ /* check if we should send a short packet */
+ if (f->flag_short != 0) {
+ f->flag_short = 0;
+ tr_data = 1;
+ break;
+ }
+ /* flushing complete */
f->flag_flushing = 0;
usb2_fifo_wakeup(f);
}
@@ -1963,10 +1950,10 @@ usb2_fifo_get_data(struct usb2_fifo *f, struct usb2_page_cache *pc,
uint8_t
usb2_fifo_get_data_linear(struct usb2_fifo *f, void *ptr,
- uint32_t len, uint32_t *actlen, uint8_t what)
+ usb2_size_t len, usb2_size_t *actlen, uint8_t what)
{
struct usb2_mbuf *m;
- uint32_t io_len;
+ usb2_size_t io_len;
uint8_t tr_data = 0;
actlen[0] = 0;
@@ -2007,6 +1994,13 @@ usb2_fifo_get_data_linear(struct usb2_fifo *f, void *ptr,
break;
}
if (f->flag_flushing) {
+ /* check if we should send a short packet */
+ if (f->flag_short != 0) {
+ f->flag_short = 0;
+ tr_data = 1;
+ break;
+ }
+ /* flushing complete */
f->flag_flushing = 0;
usb2_fifo_wakeup(f);
}
@@ -2020,7 +2014,7 @@ usb2_fifo_get_data_linear(struct usb2_fifo *f, void *ptr,
}
uint8_t
-usb2_fifo_get_data_buffer(struct usb2_fifo *f, void **pptr, uint32_t *plen)
+usb2_fifo_get_data_buffer(struct usb2_fifo *f, void **pptr, usb2_size_t *plen)
{
struct usb2_mbuf *m;
@@ -2186,3 +2180,14 @@ usb2_read_symlink(uint8_t *user_ptr, uint32_t startentry, uint32_t user_len)
sx_unlock(&usb2_sym_lock);
return (error);
}
+
+void
+usb2_fifo_set_close_zlp(struct usb2_fifo *f, uint8_t onoff)
+{
+ if (f == NULL)
+ return;
+
+ /* send a Zero Length Packet, ZLP, before close */
+ f->flag_short = onoff;
+}
+#endif /* USB_HAVE_UGEN */
diff --git a/sys/dev/usb/usb_dev.h b/sys/dev/usb/usb_dev.h
index 92be7af..af252c5 100644
--- a/sys/dev/usb/usb_dev.h
+++ b/sys/dev/usb/usb_dev.h
@@ -93,12 +93,12 @@ struct usb2_cdev_privdata {
int bus_index; /* bus index */
int dev_index; /* device index */
int ep_addr; /* endpoint address */
+ int fflags;
uint8_t fifo_index; /* FIFO index */
uint8_t is_read; /* location has read access */
uint8_t is_write; /* location has write access */
uint8_t is_uref; /* USB refcount decr. needed */
uint8_t is_usbfs; /* USB-FS is active */
- int fflags;
};
struct usb2_fs_privdata {
@@ -130,13 +130,14 @@ struct usb2_fifo {
struct usb2_xfer *xfer[2];
struct usb2_xfer **fs_xfer;
struct mtx *priv_mtx; /* client data */
- int opened; /* set if FIFO is opened by a FILE */
+ /* set if FIFO is opened by a FILE: */
+ struct usb2_cdev_privdata *curr_cpd;
void *priv_sc0; /* client data */
void *priv_sc1; /* client data */
void *queue_data;
- uint32_t timeout; /* timeout in milliseconds */
- uint32_t bufsize; /* BULK and INTERRUPT buffer size */
- uint16_t nframes; /* for isochronous mode */
+ usb2_timeout_t timeout; /* timeout in milliseconds */
+ usb2_frlength_t bufsize; /* BULK and INTERRUPT buffer size */
+ usb2_frcount_t nframes; /* for isochronous mode */
uint16_t dev_ep_index; /* our device endpoint index */
uint8_t flag_sleeping; /* set if FIFO is sleeping */
uint8_t flag_iscomplete; /* set if a USB transfer is complete */
@@ -174,17 +175,18 @@ int usb2_fifo_attach(struct usb2_device *udev, void *priv_sc,
void usb2_fifo_detach(struct usb2_fifo_sc *f_sc);
uint32_t usb2_fifo_put_bytes_max(struct usb2_fifo *fifo);
void usb2_fifo_put_data(struct usb2_fifo *fifo, struct usb2_page_cache *pc,
- uint32_t offset, uint32_t len, uint8_t what);
+ usb2_frlength_t offset, usb2_frlength_t len, uint8_t what);
void usb2_fifo_put_data_linear(struct usb2_fifo *fifo, void *ptr,
- uint32_t len, uint8_t what);
-uint8_t usb2_fifo_put_data_buffer(struct usb2_fifo *f, void *ptr, uint32_t len);
+ usb2_size_t len, uint8_t what);
+uint8_t usb2_fifo_put_data_buffer(struct usb2_fifo *f, void *ptr, usb2_size_t len);
void usb2_fifo_put_data_error(struct usb2_fifo *fifo);
uint8_t usb2_fifo_get_data(struct usb2_fifo *fifo, struct usb2_page_cache *pc,
- uint32_t offset, uint32_t len, uint32_t *actlen, uint8_t what);
+ usb2_frlength_t offset, usb2_frlength_t len, usb2_frlength_t *actlen,
+ uint8_t what);
uint8_t usb2_fifo_get_data_linear(struct usb2_fifo *fifo, void *ptr,
- uint32_t len, uint32_t *actlen, uint8_t what);
+ usb2_size_t len, usb2_size_t *actlen, uint8_t what);
uint8_t usb2_fifo_get_data_buffer(struct usb2_fifo *f, void **pptr,
- uint32_t *plen);
+ usb2_size_t *plen);
void usb2_fifo_get_data_error(struct usb2_fifo *fifo);
uint8_t usb2_fifo_opened(struct usb2_fifo *fifo);
void usb2_fifo_free(struct usb2_fifo *f);
@@ -194,5 +196,6 @@ struct usb2_symlink *usb2_alloc_symlink(const char *target);
void usb2_free_symlink(struct usb2_symlink *ps);
int usb2_read_symlink(uint8_t *user_ptr, uint32_t startentry,
uint32_t user_len);
+void usb2_fifo_set_close_zlp(struct usb2_fifo *, uint8_t);
#endif /* _USB2_DEV_H_ */
diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c
index 8bd7326..f50a29d 100644
--- a/sys/dev/usb/usb_device.c
+++ b/sys/dev/usb/usb_device.c
@@ -24,7 +24,6 @@
* SUCH DAMAGE.
*/
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb.h>
@@ -45,21 +44,23 @@
#include <dev/usb/usb_hub.h>
#include <dev/usb/usb_util.h>
#include <dev/usb/usb_mbuf.h>
-#include <dev/usb/usb_dev.h>
#include <dev/usb/usb_msctest.h>
+#if USB_HAVE_UGEN
+#include <dev/usb/usb_dev.h>
#include <dev/usb/usb_generic.h>
+#endif
#include <dev/usb/quirk/usb_quirk.h>
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
-/* function prototypes */
+/* function prototypes */
-static void usb2_fill_pipe_data(struct usb2_device *, uint8_t,
+static void usb2_init_pipe(struct usb2_device *, uint8_t,
struct usb2_endpoint_descriptor *, struct usb2_pipe *);
-static void usb2_free_pipe_data(struct usb2_device *, uint8_t, uint8_t);
-static void usb2_free_iface_data(struct usb2_device *);
+static void usb2_unconfigure(struct usb2_device *, uint8_t);
+static void usb2_detach_device(struct usb2_device *, uint8_t, uint8_t);
static void usb2_detach_device_sub(struct usb2_device *, device_t *,
uint8_t);
static uint8_t usb2_probe_and_attach_sub(struct usb2_device *,
@@ -69,12 +70,12 @@ static void usb2_init_attach_arg(struct usb2_device *,
static void usb2_suspend_resume_sub(struct usb2_device *, device_t,
uint8_t);
static void usb2_clear_stall_proc(struct usb2_proc_msg *_pm);
+usb2_error_t usb2_config_parse(struct usb2_device *, uint8_t, uint8_t);
+#if USB_HAVE_STRINGS
static void usb2_check_strings(struct usb2_device *);
-static usb2_error_t usb2_fill_iface_data(struct usb2_device *, uint8_t,
- uint8_t);
-static void usb2_notify_addq(const char *type, struct usb2_device *);
-
+#endif
#if USB_HAVE_UGEN
+static void usb2_notify_addq(const char *type, struct usb2_device *);
static void usb2_fifo_free_wrap(struct usb2_device *, uint8_t, uint8_t);
static struct cdev *usb2_make_dev(struct usb2_device *, int, int);
static void usb2_cdev_create(struct usb2_device *);
@@ -104,7 +105,7 @@ struct usb2_pipe *
usb2_get_pipe_by_addr(struct usb2_device *udev, uint8_t ea_val)
{
struct usb2_pipe *pipe = udev->pipes;
- struct usb2_pipe *pipe_end = udev->pipes + USB_EP_MAX;
+ struct usb2_pipe *pipe_end = udev->pipes + udev->pipes_max;
enum {
EA_MASK = (UE_DIR_IN | UE_DIR_OUT | UE_ADDR),
};
@@ -159,7 +160,7 @@ usb2_get_pipe(struct usb2_device *udev, uint8_t iface_index,
const struct usb2_config *setup)
{
struct usb2_pipe *pipe = udev->pipes;
- struct usb2_pipe *pipe_end = udev->pipes + USB_EP_MAX;
+ struct usb2_pipe *pipe_end = udev->pipes + udev->pipes_max;
uint8_t index = setup->ep_index;
uint8_t ea_mask;
uint8_t ea_val;
@@ -171,9 +172,25 @@ usb2_get_pipe(struct usb2_device *udev, uint8_t iface_index,
udev, iface_index, setup->endpoint,
setup->type, setup->direction, setup->ep_index);
+ /* check USB mode */
+
+ if ((setup->usb_mode != USB_MODE_MAX) &&
+ (udev->flags.usb2_mode != setup->usb_mode)) {
+ /* wrong mode - no pipe */
+ return (NULL);
+ }
+
/* setup expected endpoint direction mask and value */
- if (setup->direction == UE_DIR_ANY) {
+ if (setup->direction == UE_DIR_RX) {
+ ea_mask = (UE_DIR_IN | UE_DIR_OUT);
+ ea_val = (udev->flags.usb2_mode == USB_MODE_DEVICE) ?
+ UE_DIR_OUT : UE_DIR_IN;
+ } else if (setup->direction == UE_DIR_TX) {
+ ea_mask = (UE_DIR_IN | UE_DIR_OUT);
+ ea_val = (udev->flags.usb2_mode == USB_MODE_DEVICE) ?
+ UE_DIR_IN : UE_DIR_OUT;
+ } else if (setup->direction == UE_DIR_ANY) {
/* match any endpoint direction */
ea_mask = 0;
ea_val = 0;
@@ -266,71 +283,47 @@ usb2_interface_count(struct usb2_device *udev, uint8_t *count)
*count = 0;
return (USB_ERR_NOT_CONFIGURED);
}
- *count = udev->cdesc->bNumInterface;
+ *count = udev->ifaces_max;
return (USB_ERR_NORMAL_COMPLETION);
}
/*------------------------------------------------------------------------*
- * usb2_fill_pipe_data
+ * usb2_init_pipe
*
* This function will initialise the USB pipe structure pointed to by
- * the "pipe" argument.
+ * the "pipe" argument. The structure pointed to by "pipe" must be
+ * zeroed before calling this function.
*------------------------------------------------------------------------*/
static void
-usb2_fill_pipe_data(struct usb2_device *udev, uint8_t iface_index,
+usb2_init_pipe(struct usb2_device *udev, uint8_t iface_index,
struct usb2_endpoint_descriptor *edesc, struct usb2_pipe *pipe)
{
+ struct usb2_bus_methods *methods;
- bzero(pipe, sizeof(*pipe));
+ methods = udev->bus->methods;
- (udev->bus->methods->pipe_init) (udev, edesc, pipe);
+ (methods->pipe_init) (udev, edesc, pipe);
- if (pipe->methods == NULL) {
- /* the pipe is invalid: just return */
- return;
- }
/* initialise USB pipe structure */
pipe->edesc = edesc;
pipe->iface_index = iface_index;
TAILQ_INIT(&pipe->pipe_q.head);
pipe->pipe_q.command = &usb2_pipe_start;
+ /* the pipe is not supported by the hardware */
+ if (pipe->methods == NULL)
+ return;
+
/* clear stall, if any */
- if (udev->bus->methods->clear_stall) {
+ if (methods->clear_stall != NULL) {
USB_BUS_LOCK(udev->bus);
- (udev->bus->methods->clear_stall) (udev, pipe);
+ (methods->clear_stall) (udev, pipe);
USB_BUS_UNLOCK(udev->bus);
}
}
-/*------------------------------------------------------------------------*
- * usb2_free_pipe_data
- *
- * This function will free USB pipe data for the given interface
- * index. Hence we do not have any dynamic allocations we simply clear
- * "pipe->edesc" to indicate that the USB pipe structure can be
- * reused. The pipes belonging to the given interface should not be in
- * use when this function is called and no check is performed to
- * prevent this.
- *------------------------------------------------------------------------*/
-static void
-usb2_free_pipe_data(struct usb2_device *udev,
- uint8_t iface_index, uint8_t iface_mask)
-{
- struct usb2_pipe *pipe = udev->pipes;
- struct usb2_pipe *pipe_end = udev->pipes + USB_EP_MAX;
-
- while (pipe != pipe_end) {
- if ((pipe->iface_index & iface_mask) == iface_index) {
- /* free pipe */
- pipe->edesc = NULL;
- }
- pipe++;
- }
-}
-
-/*------------------------------------------------------------------------*
+/*-----------------------------------------------------------------------*
* usb2_pipe_foreach
*
* This function will iterate all the USB endpoints except the control
@@ -343,7 +336,7 @@ usb2_free_pipe_data(struct usb2_device *udev,
struct usb2_pipe *
usb2_pipe_foreach(struct usb2_device *udev, struct usb2_pipe *pipe)
{
- struct usb2_pipe *pipe_end = udev->pipes + USB_EP_MAX;
+ struct usb2_pipe *pipe_end = udev->pipes + udev->pipes_max;
/* be NULL safe */
if (udev == NULL)
@@ -365,148 +358,62 @@ usb2_pipe_foreach(struct usb2_device *udev, struct usb2_pipe *pipe)
}
/*------------------------------------------------------------------------*
- * usb2_fill_iface_data
+ * usb2_unconfigure
*
- * This function will fill in interface data and allocate USB pipes
- * for all the endpoints that belong to the given interface. This
- * function is typically called when setting the configuration or when
- * setting an alternate interface.
+ * This function will free all USB interfaces and USB pipes belonging
+ * to an USB device.
+ *
+ * Flag values, see "USB_UNCFG_FLAG_XXX".
*------------------------------------------------------------------------*/
-static usb2_error_t
-usb2_fill_iface_data(struct usb2_device *udev,
- uint8_t iface_index, uint8_t alt_index)
+static void
+usb2_unconfigure(struct usb2_device *udev, uint8_t flag)
{
- struct usb2_interface *iface = usb2_get_iface(udev, iface_index);
- struct usb2_pipe *pipe;
- struct usb2_pipe *pipe_end;
- struct usb2_interface_descriptor *id;
- struct usb2_endpoint_descriptor *ed = NULL;
- struct usb2_descriptor *desc;
- uint8_t nendpt;
+ uint8_t do_unlock;
- if (iface == NULL) {
- return (USB_ERR_INVAL);
+ /* automatic locking */
+ if (sx_xlocked(udev->default_sx + 1)) {
+ do_unlock = 0;
+ } else {
+ do_unlock = 1;
+ sx_xlock(udev->default_sx + 1);
}
- DPRINTFN(5, "iface_index=%d alt_index=%d\n",
- iface_index, alt_index);
- sx_assert(udev->default_sx + 1, SA_LOCKED);
-
- pipe = udev->pipes;
- pipe_end = udev->pipes + USB_EP_MAX;
-
- /*
- * Check if any USB pipes on the given USB interface are in
- * use:
- */
- while (pipe != pipe_end) {
- if ((pipe->edesc != NULL) &&
- (pipe->iface_index == iface_index) &&
- (pipe->refcount != 0)) {
- return (USB_ERR_IN_USE);
- }
- pipe++;
- }
+ /* detach all interface drivers */
+ usb2_detach_device(udev, USB_IFACE_INDEX_ANY, flag);
- pipe = &udev->pipes[0];
+#if USB_HAVE_UGEN
+ /* free all FIFOs except control endpoint FIFOs */
+ usb2_fifo_free_wrap(udev, USB_IFACE_INDEX_ANY, flag);
- id = usb2_find_idesc(udev->cdesc, iface_index, alt_index);
- if (id == NULL) {
- return (USB_ERR_INVAL);
- }
/*
- * Free old pipes after we know that an interface descriptor exists,
- * if any.
+ * Free all cdev's, if any.
*/
- usb2_free_pipe_data(udev, iface_index, 0 - 1);
-
- /* Setup USB interface structure */
- iface->idesc = id;
- iface->alt_index = alt_index;
- iface->parent_iface_index = USB_IFACE_INDEX_ANY;
-
- nendpt = id->bNumEndpoints;
- DPRINTFN(5, "found idesc nendpt=%d\n", nendpt);
-
- desc = (void *)id;
-
- while (nendpt--) {
- DPRINTFN(11, "endpt=%d\n", nendpt);
-
- while ((desc = usb2_desc_foreach(udev->cdesc, desc))) {
- if ((desc->bDescriptorType == UDESC_ENDPOINT) &&
- (desc->bLength >= sizeof(*ed))) {
- goto found;
- }
- if (desc->bDescriptorType == UDESC_INTERFACE) {
- break;
- }
- }
- goto error;
-
-found:
- ed = (void *)desc;
-
- /* find a free pipe */
- while (pipe != pipe_end) {
- if (pipe->edesc == NULL) {
- /* pipe is free */
- usb2_fill_pipe_data(udev, iface_index, ed, pipe);
- break;
- }
- pipe++;
- }
- }
- return (USB_ERR_NORMAL_COMPLETION);
-
-error:
- /* passed end, or bad desc */
- DPRINTFN(0, "%s: bad descriptor(s), addr=%d!\n",
- __FUNCTION__, udev->address);
-
- /* free old pipes if any */
- usb2_free_pipe_data(udev, iface_index, 0 - 1);
- return (USB_ERR_INVAL);
-}
-
-/*------------------------------------------------------------------------*
- * usb2_free_iface_data
- *
- * This function will free all USB interfaces and USB pipes belonging
- * to an USB device.
- *------------------------------------------------------------------------*/
-static void
-usb2_free_iface_data(struct usb2_device *udev)
-{
- struct usb2_interface *iface = udev->ifaces;
- struct usb2_interface *iface_end = udev->ifaces + USB_IFACE_MAX;
-
- /* mtx_assert() */
+ usb2_cdev_free(udev);
+#endif
+#if USB_HAVE_COMPAT_LINUX
/* free Linux compat device, if any */
if (udev->linux_dev) {
usb_linux_free_device(udev->linux_dev);
udev->linux_dev = NULL;
}
- /* free all pipes, if any */
- usb2_free_pipe_data(udev, 0, 0);
+#endif
- /* free all interfaces, if any */
- while (iface != iface_end) {
- iface->idesc = NULL;
- iface->alt_index = 0;
- iface->parent_iface_index = USB_IFACE_INDEX_ANY;
- iface++;
- }
+ usb2_config_parse(udev, USB_IFACE_INDEX_ANY, USB_CFG_FREE);
- /* free "cdesc" after "ifaces", if any */
- if (udev->cdesc) {
- free(udev->cdesc, M_USB);
+ /* free "cdesc" after "ifaces" and "pipes", if any */
+ if (udev->cdesc != NULL) {
+ if (udev->flags.usb2_mode != USB_MODE_DEVICE)
+ free(udev->cdesc, M_USB);
udev->cdesc = NULL;
}
/* set unconfigured state */
udev->curr_config_no = USB_UNCONFIG_NO;
udev->curr_config_index = USB_UNCONFIG_INDEX;
+
+ if (do_unlock) {
+ sx_unlock(udev->default_sx + 1);
+ }
}
/*------------------------------------------------------------------------*
@@ -524,11 +431,9 @@ usb2_error_t
usb2_set_config_index(struct usb2_device *udev, uint8_t index)
{
struct usb2_status ds;
- struct usb2_hub_descriptor hd;
struct usb2_config_descriptor *cdp;
uint16_t power;
uint16_t max_power;
- uint8_t nifc;
uint8_t selfpowered;
uint8_t do_unlock;
usb2_error_t err;
@@ -543,30 +448,26 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
sx_xlock(udev->default_sx + 1);
}
- /* detach all interface drivers */
- usb2_detach_device(udev, USB_IFACE_INDEX_ANY, 1);
-
-#if USB_HAVE_UGEN
- /* free all FIFOs except control endpoint FIFOs */
- usb2_fifo_free_wrap(udev, USB_IFACE_INDEX_ANY, 0);
-
- /* free all configuration data structures */
- usb2_cdev_free(udev);
-#endif
- usb2_free_iface_data(udev);
+ usb2_unconfigure(udev, USB_UNCFG_FLAG_FREE_SUBDEV);
if (index == USB_UNCONFIG_INDEX) {
/*
* Leave unallocated when unconfiguring the
- * device. "usb2_free_iface_data()" will also reset
+ * device. "usb2_unconfigure()" will also reset
* the current config number and index.
*/
err = usb2_req_set_config(udev, NULL, USB_UNCONFIG_NO);
goto done;
}
/* get the full config descriptor */
- err = usb2_req_get_config_desc_full(udev,
- NULL, &cdp, M_USB, index);
+ if (udev->flags.usb2_mode == USB_MODE_DEVICE) {
+ /* save some memory */
+ err = usb2_req_get_config_desc_ptr(udev, &cdp, index);
+ } else {
+ /* normal request */
+ err = usb2_req_get_config_desc_full(udev,
+ NULL, &cdp, M_USB, index);
+ }
if (err) {
goto done;
}
@@ -574,10 +475,6 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
udev->cdesc = cdp;
- if (cdp->bNumInterface > USB_IFACE_MAX) {
- DPRINTFN(0, "too many interfaces: %d\n", cdp->bNumInterface);
- cdp->bNumInterface = USB_IFACE_MAX;
- }
/* Figure out if the device is self or bus powered. */
selfpowered = 0;
if ((!udev->flags.uq_bus_powered) &&
@@ -586,45 +483,23 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
/* May be self powered. */
if (cdp->bmAttributes & UC_BUS_POWERED) {
/* Must ask device. */
- if (udev->flags.uq_power_claim) {
- /*
- * HUB claims to be self powered, but isn't.
- * It seems that the power status can be
- * determined by the HUB characteristics.
- */
- err = usb2_req_get_hub_descriptor
- (udev, NULL, &hd, 1);
- if (err) {
- DPRINTFN(0, "could not read "
- "HUB descriptor: %s\n",
- usb2_errstr(err));
-
- } else if (UGETW(hd.wHubCharacteristics) &
- UHD_PWR_INDIVIDUAL) {
- selfpowered = 1;
- }
- DPRINTF("characteristics=0x%04x\n",
- UGETW(hd.wHubCharacteristics));
- } else {
- err = usb2_req_get_device_status
- (udev, NULL, &ds);
- if (err) {
- DPRINTFN(0, "could not read "
- "device status: %s\n",
- usb2_errstr(err));
- } else if (UGETW(ds.wStatus) & UDS_SELF_POWERED) {
- selfpowered = 1;
- }
- DPRINTF("status=0x%04x \n",
- UGETW(ds.wStatus));
+ err = usb2_req_get_device_status(udev, NULL, &ds);
+ if (err) {
+ DPRINTFN(0, "could not read "
+ "device status: %s\n",
+ usb2_errstr(err));
+ } else if (UGETW(ds.wStatus) & UDS_SELF_POWERED) {
+ selfpowered = 1;
}
+ DPRINTF("status=0x%04x \n",
+ UGETW(ds.wStatus));
} else
selfpowered = 1;
}
DPRINTF("udev=%p cdesc=%p (addr %d) cno=%d attr=0x%02x, "
"selfpowered=%d, power=%d\n",
udev, cdp,
- cdp->bConfigurationValue, udev->address, cdp->bmAttributes,
+ udev->address, cdp->bConfigurationValue, cdp->bmAttributes,
selfpowered, cdp->bMaxPower * 2);
/* Check if we have enough power. */
@@ -654,14 +529,17 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
if (err) {
goto done;
}
- /* Allocate and fill interface data. */
- nifc = cdp->bNumInterface;
- while (nifc--) {
- err = usb2_fill_iface_data(udev, nifc, 0);
- if (err) {
- goto done;
- }
+
+ err = usb2_config_parse(udev, USB_IFACE_INDEX_ANY, USB_CFG_ALLOC);
+ if (err) {
+ goto done;
+ }
+
+ err = usb2_config_parse(udev, USB_IFACE_INDEX_ANY, USB_CFG_INIT);
+ if (err) {
+ goto done;
}
+
#if USB_HAVE_UGEN
/* create device nodes for each endpoint */
usb2_cdev_create(udev);
@@ -670,10 +548,7 @@ usb2_set_config_index(struct usb2_device *udev, uint8_t index)
done:
DPRINTF("error=%s\n", usb2_errstr(err));
if (err) {
-#if USB_HAVE_UGEN
- usb2_cdev_free(udev);
-#endif
- usb2_free_iface_data(udev);
+ usb2_unconfigure(udev, USB_UNCFG_FLAG_FREE_SUBDEV);
}
if (do_unlock) {
sx_unlock(udev->default_sx + 1);
@@ -682,6 +557,205 @@ done:
}
/*------------------------------------------------------------------------*
+ * usb2_config_parse
+ *
+ * This function will allocate and free USB interfaces and USB pipes,
+ * parse the USB configuration structure and initialise the USB pipes
+ * and interfaces. If "iface_index" is not equal to
+ * "USB_IFACE_INDEX_ANY" then the "cmd" parameter is the
+ * alternate_setting to be selected for the given interface. Else the
+ * "cmd" parameter is defined by "USB_CFG_XXX". "iface_index" can be
+ * "USB_IFACE_INDEX_ANY" or a valid USB interface index. This function
+ * is typically called when setting the configuration or when setting
+ * an alternate interface.
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+usb2_error_t
+usb2_config_parse(struct usb2_device *udev, uint8_t iface_index, uint8_t cmd)
+{
+ struct usb2_idesc_parse_state ips;
+ struct usb2_interface_descriptor *id;
+ struct usb2_endpoint_descriptor *ed;
+ struct usb2_interface *iface;
+ struct usb2_pipe *pipe;
+ usb2_error_t err;
+ uint8_t ep_curr;
+ uint8_t ep_max;
+ uint8_t temp;
+ uint8_t do_init;
+ uint8_t alt_index;
+
+ if (iface_index != USB_IFACE_INDEX_ANY) {
+ /* parameter overload */
+ alt_index = cmd;
+ cmd = USB_CFG_INIT;
+ } else {
+ /* not used */
+ alt_index = 0;
+ }
+
+ err = 0;
+
+ DPRINTFN(5, "iface_index=%d cmd=%d\n",
+ iface_index, cmd);
+
+ if (cmd == USB_CFG_FREE)
+ goto cleanup;
+
+ if (cmd == USB_CFG_INIT) {
+ sx_assert(udev->default_sx + 1, SA_LOCKED);
+
+ /* check for in-use pipes */
+
+ pipe = udev->pipes;
+ ep_max = udev->pipes_max;
+ while (ep_max--) {
+ /* look for matching pipes */
+ if ((iface_index == USB_IFACE_INDEX_ANY) ||
+ (iface_index == pipe->iface_index)) {
+ if (pipe->refcount != 0) {
+ /*
+ * This typically indicates a
+ * more serious error.
+ */
+ err = USB_ERR_IN_USE;
+ } else {
+ /* reset pipe */
+ memset(pipe, 0, sizeof(*pipe));
+ /* make sure we don't zero the pipe again */
+ pipe->iface_index = USB_IFACE_INDEX_ANY;
+ }
+ }
+ pipe++;
+ }
+
+ if (err)
+ return (err);
+ }
+
+ memset(&ips, 0, sizeof(ips));
+
+ ep_curr = 0;
+ ep_max = 0;
+
+ while ((id = usb2_idesc_foreach(udev->cdesc, &ips))) {
+
+ /* check for interface overflow */
+ if (ips.iface_index == USB_IFACE_MAX)
+ break; /* crazy */
+
+ iface = udev->ifaces + ips.iface_index;
+
+ /* check for specific interface match */
+
+ if (cmd == USB_CFG_INIT) {
+ if ((iface_index != USB_IFACE_INDEX_ANY) &&
+ (iface_index != ips.iface_index)) {
+ /* wrong interface */
+ do_init = 0;
+ } else if (alt_index != ips.iface_index_alt) {
+ /* wrong alternate setting */
+ do_init = 0;
+ } else {
+ /* initialise interface */
+ do_init = 1;
+ }
+ } else
+ do_init = 0;
+
+ /* check for new interface */
+ if (ips.iface_index_alt == 0) {
+ /* update current number of endpoints */
+ ep_curr = ep_max;
+ }
+ /* check for init */
+ if (do_init) {
+ /* setup the USB interface structure */
+ iface->idesc = id;
+ /* default setting */
+ iface->parent_iface_index = USB_IFACE_INDEX_ANY;
+ /* set alternate index */
+ iface->alt_index = alt_index;
+ }
+
+ DPRINTFN(5, "found idesc nendpt=%d\n", id->bNumEndpoints);
+
+ ed = (struct usb2_endpoint_descriptor *)id;
+
+ temp = ep_curr;
+
+ /* iterate all the endpoint descriptors */
+ while ((ed = usb2_edesc_foreach(udev->cdesc, ed))) {
+
+ if (temp == USB_EP_MAX)
+ break; /* crazy */
+
+ pipe = udev->pipes + temp;
+
+ if (do_init) {
+ usb2_init_pipe(udev,
+ ips.iface_index, ed, pipe);
+ }
+
+ temp ++;
+
+ /* find maximum number of endpoints */
+ if (ep_max < temp)
+ ep_max = temp;
+
+ /* optimalisation */
+ id = (struct usb2_interface_descriptor *)ed;
+ }
+ }
+
+ /* NOTE: It is valid to have no interfaces and no endpoints! */
+
+ if (cmd == USB_CFG_ALLOC) {
+ udev->ifaces_max = ips.iface_index;
+ udev->ifaces = NULL;
+ if (udev->ifaces_max != 0) {
+ udev->ifaces = malloc(sizeof(*iface) * udev->ifaces_max,
+ M_USB, M_WAITOK | M_ZERO);
+ if (udev->ifaces == NULL) {
+ err = USB_ERR_NOMEM;
+ goto done;
+ }
+ }
+ udev->pipes_max = ep_max;
+ udev->pipes = NULL;
+ if (udev->pipes_max != 0) {
+ udev->pipes = malloc(sizeof(*pipe) * udev->pipes_max,
+ M_USB, M_WAITOK | M_ZERO);
+ if (udev->pipes == NULL) {
+ err = USB_ERR_NOMEM;
+ goto done;
+ }
+ }
+ }
+
+done:
+ if (err) {
+ if (cmd == USB_CFG_ALLOC) {
+cleanup:
+ /* cleanup */
+ if (udev->ifaces != NULL)
+ free(udev->ifaces, M_USB);
+ if (udev->pipes != NULL)
+ free(udev->pipes, M_USB);
+
+ udev->ifaces = NULL;
+ udev->pipes = NULL;
+ udev->ifaces_max = 0;
+ udev->pipes_max = 0;
+ }
+ }
+ return (err);
+}
+
+/*------------------------------------------------------------------------*
* usb2_set_alt_interface_index
*
* This function will select an alternate interface index for the
@@ -715,7 +789,8 @@ usb2_set_alt_interface_index(struct usb2_device *udev,
goto done;
}
if (udev->flags.usb2_mode == USB_MODE_DEVICE) {
- usb2_detach_device(udev, iface_index, 1);
+ usb2_detach_device(udev, iface_index,
+ USB_UNCFG_FLAG_FREE_SUBDEV);
} else {
if (iface->alt_index == alt_index) {
/*
@@ -734,7 +809,7 @@ usb2_set_alt_interface_index(struct usb2_device *udev,
usb2_fifo_free_wrap(udev, iface_index, 0);
#endif
- err = usb2_fill_iface_data(udev, iface_index, alt_index);
+ err = usb2_config_parse(udev, iface_index, alt_index);
if (err) {
goto done;
}
@@ -842,7 +917,7 @@ usb2_reset_iface_endpoints(struct usb2_device *udev, uint8_t iface_index)
usb2_error_t err;
pipe = udev->pipes;
- pipe_end = udev->pipes + USB_EP_MAX;
+ pipe_end = udev->pipes + udev->pipes_max;
for (; pipe != pipe_end; pipe++) {
@@ -864,15 +939,17 @@ usb2_reset_iface_endpoints(struct usb2_device *udev, uint8_t iface_index)
*
* This function will try to detach an USB device. If it fails a panic
* will result.
+ *
+ * Flag values, see "USB_UNCFG_FLAG_XXX".
*------------------------------------------------------------------------*/
static void
usb2_detach_device_sub(struct usb2_device *udev, device_t *ppdev,
- uint8_t free_subdev)
+ uint8_t flag)
{
device_t dev;
int err;
- if (!free_subdev) {
+ if (!(flag & USB_UNCFG_FLAG_FREE_SUBDEV)) {
*ppdev = NULL;
@@ -918,14 +995,15 @@ error:
*
* The following function will detach the matching interfaces.
* This function is NULL safe.
+ *
+ * Flag values, see "USB_UNCFG_FLAG_XXX".
*------------------------------------------------------------------------*/
void
usb2_detach_device(struct usb2_device *udev, uint8_t iface_index,
- uint8_t free_subdev)
+ uint8_t flag)
{
struct usb2_interface *iface;
uint8_t i;
- uint8_t do_unlock;
if (udev == NULL) {
/* nothing to do */
@@ -933,13 +1011,7 @@ usb2_detach_device(struct usb2_device *udev, uint8_t iface_index,
}
DPRINTFN(4, "udev=%p\n", udev);
- /* automatic locking */
- if (sx_xlocked(udev->default_sx + 1)) {
- do_unlock = 0;
- } else {
- do_unlock = 1;
- sx_xlock(udev->default_sx + 1);
- }
+ sx_assert(udev->default_sx + 1, SA_LOCKED);
/*
* First detach the child to give the child's detach routine a
@@ -964,11 +1036,7 @@ usb2_detach_device(struct usb2_device *udev, uint8_t iface_index,
/* looks like the end of the USB interfaces */
break;
}
- usb2_detach_device_sub(udev, &iface->subdev, free_subdev);
- }
-
- if (do_unlock) {
- sx_unlock(udev->default_sx + 1);
+ usb2_detach_device_sub(udev, &iface->subdev, flag);
}
}
@@ -1373,8 +1441,6 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
usb2_cv_init(udev->default_cv, "WCTRL");
usb2_cv_init(udev->default_cv + 1, "UGONE");
- LIST_INIT(&udev->pd_list);
-
/* initialise our mutex */
mtx_init(udev->default_mtx, "USB device mutex", NULL, MTX_DEF);
@@ -1392,7 +1458,7 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
udev->depth = depth;
udev->bus = bus;
udev->address = USB_START_ADDR; /* default value */
- udev->plugtime = (uint32_t)ticks;
+ udev->plugtime = (usb2_ticks_t)ticks;
/*
* We need to force the power mode to "on" because there are plenty
* of USB devices out there that do not work very well with
@@ -1400,7 +1466,6 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
*/
udev->power_mode = USB_POWER_MODE_ON;
udev->pwr_save.last_xfer_time = ticks;
-
/* we are not ready yet */
udev->refcount = 1;
@@ -1417,10 +1482,6 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
udev->speed = speed;
udev->flags.usb2_mode = usb2_mode;
- /* speed combination should be checked by the parent HUB */
-
- hub = udev->parent_hub;
-
/* search for our High Speed USB HUB, if any */
adev = udev;
@@ -1437,25 +1498,26 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
}
/* init the default pipe */
- usb2_fill_pipe_data(udev, 0,
+ usb2_init_pipe(udev, 0,
&udev->default_ep_desc,
&udev->default_pipe);
/* set device index */
udev->device_index = device_index;
+#if USB_HAVE_UGEN
/* Create ugen name */
snprintf(udev->ugen_name, sizeof(udev->ugen_name),
USB_GENERIC_NAME "%u.%u", device_get_unit(bus->bdev),
device_index);
-#if USB_HAVE_UGEN
+ LIST_INIT(&udev->pd_list);
+
/* Create the control endpoint device */
udev->default_dev = usb2_make_dev(udev, 0, FREAD|FWRITE);
/* Create a link from /dev/ugenX.X to the default endpoint */
make_dev_alias(udev->default_dev, udev->ugen_name);
#endif
-
if (udev->flags.usb2_mode == USB_MODE_HOST) {
err = usb2_req_set_address(udev, NULL, device_index);
@@ -1475,7 +1537,8 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
*/
if (err) {
DPRINTFN(0, "set address %d failed "
- "(ignored)\n", udev->address);
+ "(%s, ignored)\n", udev->address,
+ usb2_errstr(err));
}
/* allow device time to set new address */
usb2_pause_mtx(NULL,
@@ -1511,7 +1574,8 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
if (err) {
DPRINTFN(0, "getting device descriptor "
- "at addr %d failed!\n", udev->address);
+ "at addr %d failed, %s!\n", udev->address,
+ usb2_errstr(err));
/* XXX try to re-enumerate the device */
err = usb2_req_re_enumerate(udev, NULL);
if (err) {
@@ -1544,9 +1608,6 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
if (usb2_test_quirk(&uaa, UQ_BUS_POWERED)) {
udev->flags.uq_bus_powered = 1;
}
- if (usb2_test_quirk(&uaa, UQ_POWER_CLAIM)) {
- udev->flags.uq_power_claim = 1;
- }
if (usb2_test_quirk(&uaa, UQ_NO_STRINGS)) {
udev->flags.no_strings = 1;
}
@@ -1585,6 +1646,7 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
/* assume 100mA bus powered for now. Changed when configured. */
udev->power = USB_MIN_POWER;
+#if USB_HAVE_STRINGS
/* get serial number string */
err = usb2_req_get_string_any
(udev, NULL, (char *)scratch_ptr,
@@ -1608,6 +1670,7 @@ usb2_alloc_device(device_t parent_dev, struct usb2_bus *bus,
/* finish up all the strings */
usb2_check_strings(udev);
+#endif
if (udev->flags.usb2_mode == USB_MODE_HOST) {
uint8_t config_index;
@@ -1643,9 +1706,7 @@ repeat_set_config:
DPRINTF("setting config %u\n", config_index);
/* get the USB device configured */
- sx_xlock(udev->default_sx + 1);
err = usb2_set_config_index(udev, config_index);
- sx_unlock(udev->default_sx + 1);
if (err) {
if (udev->ddesc.bNumConfigurations != 0) {
if (!set_config_failed) {
@@ -1673,7 +1734,8 @@ repeat_set_config:
} else if ((config_index + 1) < udev->ddesc.bNumConfigurations) {
if ((udev->cdesc->bNumInterface < 2) &&
- (usb2_get_no_endpoints(udev->cdesc) == 0)) {
+ (usb2_get_no_descriptors(udev->cdesc,
+ UDESC_ENDPOINT) == 0)) {
DPRINTFN(0, "Found no endpoints "
"(trying next config)!\n");
config_index++;
@@ -1706,18 +1768,22 @@ repeat_set_config:
usb2_bus_port_set_device(bus, parent_hub ?
parent_hub->hub->ports + port_index : NULL, udev, device_index);
- /* Link and announce the ugen device name */
#if USB_HAVE_UGEN
+ /* Symlink the ugen device name */
udev->ugen_symlink = usb2_alloc_symlink(udev->ugen_name);
-#endif
+
+ /* Announce device */
printf("%s: <%s> at %s\n", udev->ugen_name, udev->manufacturer,
device_get_nameunit(udev->bus->bdev));
usb2_notify_addq("+", udev);
+#endif
done:
if (err) {
/* free device */
- usb2_free_device(udev);
+ usb2_free_device(udev,
+ USB_UNCFG_FLAG_FREE_SUBDEV |
+ USB_UNCFG_FLAG_FREE_EP0);
udev = NULL;
}
return (udev);
@@ -1817,7 +1883,6 @@ usb2_cdev_free(struct usb2_device *udev)
while ((pd = LIST_FIRST(&udev->pd_list)) != NULL) {
KASSERT(pd->cdev->si_drv1 == pd, ("privdata corrupt"));
- KASSERT(pd->ep_addr > 0, ("freeing EP0"));
destroy_dev_sched_cb(pd->cdev, usb2_cdev_cleanup, pd);
pd->cdev = NULL;
@@ -1836,14 +1901,22 @@ usb2_cdev_cleanup(void* arg)
* usb2_free_device
*
* This function is NULL safe and will free an USB device.
+ *
+ * Flag values, see "USB_UNCFG_FLAG_XXX".
*------------------------------------------------------------------------*/
void
-usb2_free_device(struct usb2_device *udev)
+usb2_free_device(struct usb2_device *udev, uint8_t flag)
{
- struct usb2_bus *bus = udev->bus;;
+ struct usb2_bus *bus;
+
+ if (udev == NULL)
+ return; /* already freed */
DPRINTFN(4, "udev=%p port=%d\n", udev, udev->port_no);
+ bus = udev->bus;;
+
+#if USB_HAVE_UGEN
usb2_notify_addq("-", udev);
printf("%s: <%s> at %s (disconnected)\n", udev->ugen_name,
@@ -1851,11 +1924,10 @@ usb2_free_device(struct usb2_device *udev)
/* Destroy UGEN symlink, if any */
if (udev->ugen_symlink) {
-#if USB_HAVE_UGEN
usb2_free_symlink(udev->ugen_symlink);
-#endif
udev->ugen_symlink = NULL;
}
+#endif
/*
* Unregister our device first which will prevent any further
* references:
@@ -1866,33 +1938,24 @@ usb2_free_device(struct usb2_device *udev)
#if USB_HAVE_UGEN
/* wait for all pending references to go away: */
-
mtx_lock(&usb2_ref_lock);
udev->refcount--;
while (udev->refcount != 0) {
usb2_cv_wait(udev->default_cv + 1, &usb2_ref_lock);
}
mtx_unlock(&usb2_ref_lock);
+
+ destroy_dev_sched_cb(udev->default_dev, usb2_cdev_cleanup,
+ udev->default_dev->si_drv1);
#endif
if (udev->flags.usb2_mode == USB_MODE_DEVICE) {
/* stop receiving any control transfers (Device Side Mode) */
usb2_transfer_unsetup(udev->default_xfer, USB_DEFAULT_XFER_MAX);
}
-#if USB_HAVE_UGEN
- /* free all FIFOs */
- usb2_fifo_free_wrap(udev, USB_IFACE_INDEX_ANY, 1);
- /*
- * Free all interface related data and FIFOs, if any.
- */
- usb2_cdev_free(udev);
-#endif
- usb2_free_iface_data(udev);
-#if USB_HAVE_UGEN
- destroy_dev_sched_cb(udev->default_dev, usb2_cdev_cleanup,
- udev->default_dev->si_drv1);
-#endif
+ /* the following will get the device unconfigured in software */
+ usb2_unconfigure(udev, flag);
/* unsetup any leftover default USB transfers */
usb2_transfer_unsetup(udev->default_xfer, USB_DEFAULT_XFER_MAX);
@@ -1916,7 +1979,9 @@ usb2_free_device(struct usb2_device *udev)
usb2_cv_destroy(udev->default_cv + 1);
mtx_destroy(udev->default_mtx);
+#if USB_HAVE_UGEN
KASSERT(LIST_FIRST(&udev->pd_list) == NULL, ("leaked cdev entries"));
+#endif
/* free device */
free(udev, M_USB);
@@ -1937,12 +2002,8 @@ usb2_get_iface(struct usb2_device *udev, uint8_t iface_index)
{
struct usb2_interface *iface = udev->ifaces + iface_index;
- if ((iface < udev->ifaces) ||
- (iface_index >= USB_IFACE_MAX) ||
- (udev->cdesc == NULL) ||
- (iface_index >= udev->cdesc->bNumInterface)) {
+ if (iface_index >= udev->ifaces_max)
return (NULL);
- }
return (iface);
}
@@ -2019,20 +2080,31 @@ usb2_devinfo(struct usb2_device *udev, char *dst_ptr, uint16_t dst_len)
if (udd->bDeviceClass != 0xFF) {
snprintf(dst_ptr, dst_len, "%s %s, class %d/%d, rev %x.%02x/"
- "%x.%02x, addr %d", udev->manufacturer, udev->product,
+ "%x.%02x, addr %d",
+#if USB_HAVE_STRINGS
+ udev->manufacturer, udev->product,
+#else
+ "-", "-",
+#endif
udd->bDeviceClass, udd->bDeviceSubClass,
(bcdUSB >> 8), bcdUSB & 0xFF,
(bcdDevice >> 8), bcdDevice & 0xFF,
udev->address);
} else {
snprintf(dst_ptr, dst_len, "%s %s, rev %x.%02x/"
- "%x.%02x, addr %d", udev->manufacturer, udev->product,
+ "%x.%02x, addr %d",
+#if USB_HAVE_STRINGS
+ udev->manufacturer, udev->product,
+#else
+ "-", "-",
+#endif
(bcdUSB >> 8), bcdUSB & 0xFF,
(bcdDevice >> 8), bcdDevice & 0xFF,
udev->address);
}
}
+#if USB_HAVE_STRINGS
#if USB_VERBOSE
/*
* Descriptions of of known vendors and devices ("products").
@@ -2129,6 +2201,7 @@ usb2_check_strings(struct usb2_device *udev)
sizeof(udev->product), "product 0x%04x", product_id);
}
}
+#endif
/*
* Returns:
@@ -2221,6 +2294,7 @@ usb2_get_device_index(struct usb2_device *udev)
return (udev->device_index);
}
+#if USB_HAVE_UGEN
/*------------------------------------------------------------------------*
* usb2_notify_addq
*
@@ -2243,65 +2317,48 @@ usb2_notify_addq(const char *type, struct usb2_device *udev)
return;
/* String it all together. */
- if (udev->parent_hub) {
- snprintf(data, 1024,
- "%s"
- "%s "
- "vendor=0x%04x "
- "product=0x%04x "
- "devclass=0x%02x "
- "devsubclass=0x%02x "
- "sernum=\"%s\" "
- "at "
- "port=%u "
- "on "
- "%s\n",
- type,
- udev->ugen_name,
- UGETW(udev->ddesc.idVendor),
- UGETW(udev->ddesc.idProduct),
- udev->ddesc.bDeviceClass,
- udev->ddesc.bDeviceSubClass,
- udev->serial,
- udev->port_no,
- udev->parent_hub->ugen_name);
- } else {
- snprintf(data, 1024,
- "%s"
- "%s "
- "vendor=0x%04x "
- "product=0x%04x "
- "devclass=0x%02x "
- "devsubclass=0x%02x "
- "sernum=\"%s\" "
- "at port=%u "
- "on "
- "%s\n",
- type,
- udev->ugen_name,
- UGETW(udev->ddesc.idVendor),
- UGETW(udev->ddesc.idProduct),
- udev->ddesc.bDeviceClass,
- udev->ddesc.bDeviceSubClass,
- udev->serial,
- udev->port_no,
- device_get_nameunit(device_get_parent(udev->bus->bdev)));
- }
+ snprintf(data, 1024,
+ "%s"
+ "%s "
+ "vendor=0x%04x "
+ "product=0x%04x "
+ "devclass=0x%02x "
+ "devsubclass=0x%02x "
+ "sernum=\"%s\" "
+ "at "
+ "port=%u "
+ "on "
+ "%s\n",
+ type,
+ udev->ugen_name,
+ UGETW(udev->ddesc.idVendor),
+ UGETW(udev->ddesc.idProduct),
+ udev->ddesc.bDeviceClass,
+ udev->ddesc.bDeviceSubClass,
+#if USB_HAVE_STRINGS
+ udev->serial,
+#else
+ "",
+#endif
+ udev->port_no,
+ udev->parent_hub != NULL ?
+ udev->parent_hub->ugen_name :
+ device_get_nameunit(device_get_parent(udev->bus->bdev)));
+
devctl_queue_data(data);
}
-#if USB_HAVE_UGEN
/*------------------------------------------------------------------------*
* usb2_fifo_free_wrap
*
* This function will free the FIFOs.
*
- * Flag values, if "iface_index" is equal to "USB_IFACE_INDEX_ANY".
- * 0: Free all FIFOs except generic control endpoints.
- * 1: Free all FIFOs.
- *
- * Flag values, if "iface_index" is not equal to "USB_IFACE_INDEX_ANY".
- * Not used.
+ * Description of "flag" argument: If the USB_UNCFG_FLAG_FREE_EP0 flag
+ * is set and "iface_index" is set to "USB_IFACE_INDEX_ANY", we free
+ * all FIFOs. If the USB_UNCFG_FLAG_FREE_EP0 flag is not set and
+ * "iface_index" is set to "USB_IFACE_INDEX_ANY", we free all non
+ * control endpoint FIFOs. If "iface_index" is not set to
+ * "USB_IFACE_INDEX_ANY" the flag has no effect.
*------------------------------------------------------------------------*/
static void
usb2_fifo_free_wrap(struct usb2_device *udev,
@@ -2334,7 +2391,8 @@ usb2_fifo_free_wrap(struct usb2_device *udev,
}
} else if (iface_index == USB_IFACE_INDEX_ANY) {
if ((f->methods == &usb2_ugen_methods) &&
- (f->dev_ep_index == 0) && (flag == 0) &&
+ (f->dev_ep_index == 0) &&
+ (!(flag & USB_UNCFG_FLAG_FREE_EP0)) &&
(f->fs_xfer == NULL)) {
/* no need to free this FIFO */
continue;
diff --git a/sys/dev/usb/usb_device.h b/sys/dev/usb/usb_device.h
index 8ebf9e5..5ae9779 100644
--- a/sys/dev/usb/usb_device.h
+++ b/sys/dev/usb/usb_device.h
@@ -27,10 +27,23 @@
#ifndef _USB2_DEVICE_H_
#define _USB2_DEVICE_H_
-struct usb2_symlink;
+struct usb2_symlink; /* UGEN */
+struct usb_device; /* linux compat */
#define USB_DEFAULT_XFER_MAX 2
+/* "usb2_parse_config()" commands */
+
+#define USB_CFG_ALLOC 0
+#define USB_CFG_FREE 1
+#define USB_CFG_INIT 2
+
+/* "usb2_unconfigure()" flags */
+
+#define USB_UNCFG_FLAG_NONE 0x00
+#define USB_UNCFG_FLAG_FREE_SUBDEV 0x01 /* subdevices are freed */
+#define USB_UNCFG_FLAG_FREE_EP0 0x02 /* endpoint zero is freed */
+
struct usb2_clear_stall_msg {
struct usb2_proc_msg hdr;
struct usb2_device *udev;
@@ -43,7 +56,6 @@ struct usb2_clear_stall_msg {
struct usb2_pipe {
struct usb2_xfer_queue pipe_q; /* queue of USB transfers */
- struct usb2_xfer *xfer_block; /* blocking USB transfer */
struct usb2_endpoint_descriptor *edesc;
struct usb2_pipe_methods *methods; /* set by HC driver */
@@ -78,7 +90,6 @@ struct usb2_device_flags {
* strings */
uint8_t remote_wakeup:1; /* set if remote wakeup is enabled */
uint8_t uq_bus_powered:1; /* set if BUS powered quirk is present */
- uint8_t uq_power_claim:1; /* set if power claim quirk is present */
};
/*
@@ -86,10 +97,10 @@ struct usb2_device_flags {
* in this structure is protected by the USB BUS lock.
*/
struct usb2_power_save {
- int last_xfer_time; /* copy of "ticks" */
- uint32_t type_refs[4]; /* transfer reference count */
- uint32_t read_refs; /* data read references */
- uint32_t write_refs; /* data write references */
+ usb2_ticks_t last_xfer_time; /* copy of "ticks" */
+ usb2_size_t type_refs[4]; /* transfer reference count */
+ usb2_size_t read_refs; /* data read references */
+ usb2_size_t write_refs; /* data write references */
uint8_t suspended; /* set if USB device is suspended */
};
@@ -103,32 +114,30 @@ struct usb2_device {
struct sx default_sx[2];
struct mtx default_mtx[1];
struct cv default_cv[2];
- struct usb2_interface ifaces[USB_IFACE_MAX];
+ struct usb2_interface *ifaces;
struct usb2_pipe default_pipe; /* Control Endpoint 0 */
- struct cdev *default_dev; /* Control Endpoint 0 device node */
- struct usb2_pipe pipes[USB_EP_MAX];
+ struct usb2_pipe *pipes;
struct usb2_power_save pwr_save;/* power save data */
-
struct usb2_bus *bus; /* our USB BUS */
device_t parent_dev; /* parent device */
struct usb2_device *parent_hub;
struct usb2_config_descriptor *cdesc; /* full config descr */
struct usb2_hub *hub; /* only if this is a hub */
+#if USB_HAVE_COMPAT_LINUX
struct usb_device *linux_dev;
+#endif
struct usb2_xfer *default_xfer[USB_DEFAULT_XFER_MAX];
struct usb2_temp_data *usb2_template_ptr;
struct usb2_pipe *pipe_curr; /* current clear stall pipe */
+#if USB_HAVE_UGEN
struct usb2_fifo *fifo[USB_FIFO_MAX];
-
- char ugen_name[20]; /* name of ugenX.X device */
struct usb2_symlink *ugen_symlink; /* our generic symlink */
-
+ struct cdev *default_dev; /* Control Endpoint 0 device node */
LIST_HEAD(,usb2_fs_privdata) pd_list;
+ char ugen_name[20]; /* name of ugenX.X device */
+#endif
+ usb2_ticks_t plugtime; /* copy of "ticks" */
- uint32_t plugtime; /* copy of "ticks" */
-
- uint16_t ep_rd_opened; /* bitmask of endpoints opened */
- uint16_t ep_wr_opened; /* from the device nodes. */
uint16_t refcount;
#define USB_DEV_REF_MAX 0xffff
@@ -147,6 +156,8 @@ struct usb2_device {
uint8_t hs_port_no; /* high-speed HUB port number */
uint8_t driver_added_refcount; /* our driver added generation count */
uint8_t power_mode; /* see USB_POWER_XXX */
+ uint8_t ifaces_max; /* number of interfaces present */
+ uint8_t pipes_max; /* number of pipes present */
/* the "flags" field is write-protected by "bus->mtx" */
@@ -155,9 +166,11 @@ struct usb2_device {
struct usb2_endpoint_descriptor default_ep_desc; /* for pipe 0 */
struct usb2_device_descriptor ddesc; /* device descriptor */
+#if USB_HAVE_STRINGS
char serial[64]; /* serial number */
char manufacturer[64]; /* manufacturer string */
char product[64]; /* product string */
+#endif
};
/* globals */
@@ -183,10 +196,8 @@ usb2_error_t usb2_set_endpoint_stall(struct usb2_device *udev,
struct usb2_pipe *pipe, uint8_t do_stall);
usb2_error_t usb2_suspend_resume(struct usb2_device *udev,
uint8_t do_suspend);
-void usb2_detach_device(struct usb2_device *udev, uint8_t iface_index,
- uint8_t free_subdev);
void usb2_devinfo(struct usb2_device *udev, char *dst_ptr, uint16_t dst_len);
-void usb2_free_device(struct usb2_device *udev);
+void usb2_free_device(struct usb2_device *, uint8_t);
void *usb2_find_descriptor(struct usb2_device *udev, void *id,
uint8_t iface_index, uint8_t type, uint8_t type_mask,
uint8_t subtype, uint8_t subtype_mask);
diff --git a/sys/dev/usb/usb_dynamic.c b/sys/dev/usb/usb_dynamic.c
index 6983f64..8c0a644 100644
--- a/sys/dev/usb/usb_dynamic.c
+++ b/sys/dev/usb/usb_dynamic.c
@@ -24,7 +24,6 @@
* SUCH DAMAGE.
*/
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb.h>
diff --git a/sys/dev/usb/usb_endian.h b/sys/dev/usb/usb_endian.h
index 2f49008..f7d2244 100644
--- a/sys/dev/usb/usb_endian.h
+++ b/sys/dev/usb/usb_endian.h
@@ -48,19 +48,19 @@ typedef uint8_t uQWord[8];
#define UGETW(w) \
((w)[0] | \
- ((w)[1] << 8))
+ (((uint16_t)((w)[1])) << 8))
#define UGETDW(w) \
((w)[0] | \
- ((w)[1] << 8) | \
- ((w)[2] << 16) | \
- ((w)[3] << 24))
+ (((uint16_t)((w)[1])) << 8) | \
+ (((uint32_t)((w)[2])) << 16) | \
+ (((uint32_t)((w)[3])) << 24))
#define UGETQW(w) \
((w)[0] | \
- ((w)[1] << 8) | \
- ((w)[2] << 16) | \
- ((w)[3] << 24) | \
+ (((uint16_t)((w)[1])) << 8) | \
+ (((uint32_t)((w)[2])) << 16) | \
+ (((uint32_t)((w)[3])) << 24) | \
(((uint64_t)((w)[4])) << 32) | \
(((uint64_t)((w)[5])) << 40) | \
(((uint64_t)((w)[6])) << 48) | \
diff --git a/sys/dev/usb/usb_generic.c b/sys/dev/usb/usb_generic.c
index c7cf056..27de49b 100644
--- a/sys/dev/usb/usb_generic.c
+++ b/sys/dev/usb/usb_generic.c
@@ -24,7 +24,6 @@
* SUCH DAMAGE.
*/
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb.h>
#include <dev/usb/usb_ioctl.h>
@@ -48,6 +47,8 @@
#include <dev/usb/usb_controller.h>
#include <dev/usb/usb_bus.h>
+#if USB_HAVE_UGEN
+
/* defines */
#define UGEN_BULK_FS_BUFFER_SIZE (64*32) /* bytes */
@@ -221,28 +222,29 @@ ugen_open_pipe_write(struct usb2_fifo *f)
usb2_config[1].type = UE_CONTROL;
usb2_config[1].endpoint = 0;
usb2_config[1].direction = UE_DIR_ANY;
- usb2_config[1].mh.timeout = 1000; /* 1 second */
- usb2_config[1].mh.interval = 50;/* 50 milliseconds */
- usb2_config[1].mh.bufsize = sizeof(struct usb2_device_request);
- usb2_config[1].mh.callback = &ugen_write_clear_stall_callback;
+ usb2_config[1].timeout = 1000; /* 1 second */
+ usb2_config[1].interval = 50;/* 50 milliseconds */
+ usb2_config[1].bufsize = sizeof(struct usb2_device_request);
+ usb2_config[1].callback = &ugen_write_clear_stall_callback;
+ usb2_config[1].usb_mode = USB_MODE_HOST;
usb2_config[0].type = ed->bmAttributes & UE_XFERTYPE;
usb2_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
- usb2_config[0].direction = ed->bEndpointAddress & (UE_DIR_OUT | UE_DIR_IN);
- usb2_config[0].mh.interval = USB_DEFAULT_INTERVAL;
- usb2_config[0].mh.flags.proxy_buffer = 1;
+ usb2_config[0].direction = UE_DIR_TX;
+ usb2_config[0].interval = USB_DEFAULT_INTERVAL;
+ usb2_config[0].flags.proxy_buffer = 1;
+ usb2_config[0].usb_mode = USB_MODE_MAX; /* both modes */
switch (ed->bmAttributes & UE_XFERTYPE) {
case UE_INTERRUPT:
case UE_BULK:
if (f->flag_short) {
- usb2_config[0].mh.flags.force_short_xfer = 1;
+ usb2_config[0].flags.force_short_xfer = 1;
}
- usb2_config[0].mh.callback = &ugen_default_write_callback;
- usb2_config[0].mh.timeout = f->timeout;
- usb2_config[0].mh.frames = 1;
- usb2_config[0].mh.bufsize = f->bufsize;
- usb2_config[0].md = usb2_config[0].mh; /* symmetric config */
+ usb2_config[0].callback = &ugen_default_write_callback;
+ usb2_config[0].timeout = f->timeout;
+ usb2_config[0].frames = 1;
+ usb2_config[0].bufsize = f->bufsize;
if (ugen_transfer_setup(f, usb2_config, 2)) {
return (EIO);
}
@@ -251,12 +253,11 @@ ugen_open_pipe_write(struct usb2_fifo *f)
break;
case UE_ISOCHRONOUS:
- usb2_config[0].mh.flags.short_xfer_ok = 1;
- usb2_config[0].mh.bufsize = 0; /* use default */
- usb2_config[0].mh.frames = f->nframes;
- usb2_config[0].mh.callback = &ugen_isoc_write_callback;
- usb2_config[0].mh.timeout = 0;
- usb2_config[0].md = usb2_config[0].mh; /* symmetric config */
+ usb2_config[0].flags.short_xfer_ok = 1;
+ usb2_config[0].bufsize = 0; /* use default */
+ usb2_config[0].frames = f->nframes;
+ usb2_config[0].callback = &ugen_isoc_write_callback;
+ usb2_config[0].timeout = 0;
/* clone configuration */
usb2_config[1] = usb2_config[0];
@@ -289,28 +290,29 @@ ugen_open_pipe_read(struct usb2_fifo *f)
usb2_config[1].type = UE_CONTROL;
usb2_config[1].endpoint = 0;
usb2_config[1].direction = UE_DIR_ANY;
- usb2_config[1].mh.timeout = 1000; /* 1 second */
- usb2_config[1].mh.interval = 50;/* 50 milliseconds */
- usb2_config[1].mh.bufsize = sizeof(struct usb2_device_request);
- usb2_config[1].mh.callback = &ugen_read_clear_stall_callback;
+ usb2_config[1].timeout = 1000; /* 1 second */
+ usb2_config[1].interval = 50;/* 50 milliseconds */
+ usb2_config[1].bufsize = sizeof(struct usb2_device_request);
+ usb2_config[1].callback = &ugen_read_clear_stall_callback;
+ usb2_config[1].usb_mode = USB_MODE_HOST;
usb2_config[0].type = ed->bmAttributes & UE_XFERTYPE;
usb2_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
- usb2_config[0].direction = UE_DIR_IN;
- usb2_config[0].mh.interval = USB_DEFAULT_INTERVAL;
- usb2_config[0].mh.flags.proxy_buffer = 1;
+ usb2_config[0].direction = UE_DIR_RX;
+ usb2_config[0].interval = USB_DEFAULT_INTERVAL;
+ usb2_config[0].flags.proxy_buffer = 1;
+ usb2_config[0].usb_mode = USB_MODE_MAX; /* both modes */
switch (ed->bmAttributes & UE_XFERTYPE) {
case UE_INTERRUPT:
case UE_BULK:
if (f->flag_short) {
- usb2_config[0].mh.flags.short_xfer_ok = 1;
+ usb2_config[0].flags.short_xfer_ok = 1;
}
- usb2_config[0].mh.timeout = f->timeout;
- usb2_config[0].mh.frames = 1;
- usb2_config[0].mh.callback = &ugen_default_read_callback;
- usb2_config[0].mh.bufsize = f->bufsize;
- usb2_config[0].md = usb2_config[0].mh; /* symmetric config */
+ usb2_config[0].timeout = f->timeout;
+ usb2_config[0].frames = 1;
+ usb2_config[0].callback = &ugen_default_read_callback;
+ usb2_config[0].bufsize = f->bufsize;
if (ugen_transfer_setup(f, usb2_config, 2)) {
return (EIO);
@@ -320,12 +322,11 @@ ugen_open_pipe_read(struct usb2_fifo *f)
break;
case UE_ISOCHRONOUS:
- usb2_config[0].mh.flags.short_xfer_ok = 1;
- usb2_config[0].mh.bufsize = 0; /* use default */
- usb2_config[0].mh.frames = f->nframes;
- usb2_config[0].mh.callback = &ugen_isoc_read_callback;
- usb2_config[0].mh.timeout = 0;
- usb2_config[0].md = usb2_config[0].mh; /* symmetric config */
+ usb2_config[0].flags.short_xfer_ok = 1;
+ usb2_config[0].bufsize = 0; /* use default */
+ usb2_config[0].frames = f->nframes;
+ usb2_config[0].callback = &ugen_isoc_read_callback;
+ usb2_config[0].timeout = 0;
/* clone configuration */
usb2_config[1] = usb2_config[0];
@@ -417,6 +418,8 @@ ugen_default_read_callback(struct usb2_xfer *xfer)
default: /* Error */
if (xfer->error != USB_ERR_CANCELLED) {
+ /* send a zero length packet to userland */
+ usb2_fifo_put_data(f, xfer->frbuffers, 0, 0, 1);
f->flag_stall = 1;
f->fifo_zlp = 0;
usb2_transfer_start(f->xfer[1]);
@@ -429,7 +432,7 @@ static void
ugen_default_write_callback(struct usb2_xfer *xfer)
{
struct usb2_fifo *f = xfer->priv_sc;
- uint32_t actlen;
+ usb2_frlength_t actlen;
DPRINTFN(4, "actlen=%u, aframes=%u\n", xfer->actlen, xfer->aframes);
@@ -501,8 +504,8 @@ static void
ugen_isoc_read_callback(struct usb2_xfer *xfer)
{
struct usb2_fifo *f = xfer->priv_sc;
- uint32_t offset;
- uint16_t n;
+ usb2_frlength_t offset;
+ usb2_frcount_t n;
DPRINTFN(4, "actlen=%u, aframes=%u\n", xfer->actlen, xfer->aframes);
@@ -540,9 +543,9 @@ static void
ugen_isoc_write_callback(struct usb2_xfer *xfer)
{
struct usb2_fifo *f = xfer->priv_sc;
- uint32_t actlen;
- uint32_t offset;
- uint16_t n;
+ usb2_frlength_t actlen;
+ usb2_frlength_t offset;
+ usb2_frcount_t n;
DPRINTFN(4, "actlen=%u, aframes=%u\n", xfer->actlen, xfer->aframes);
@@ -798,12 +801,14 @@ usb2_gen_fill_deviceinfo(struct usb2_fifo *f, struct usb2_device_info *di)
di->udi_bus = device_get_unit(udev->bus->bdev);
di->udi_addr = udev->address;
di->udi_index = udev->device_index;
+#if USB_HAVE_STRINGS
strlcpy(di->udi_serial, udev->serial,
sizeof(di->udi_serial));
strlcpy(di->udi_vendor, udev->manufacturer,
sizeof(di->udi_vendor));
strlcpy(di->udi_product, udev->product,
sizeof(di->udi_product));
+#endif
usb2_printBCD(di->udi_release, sizeof(di->udi_release),
UGETW(udev->ddesc.bcdDevice));
di->udi_vendorNo = UGETW(udev->ddesc.idVendor);
@@ -1021,10 +1026,10 @@ ugen_fs_copy_in(struct usb2_fifo *f, uint8_t ep_index)
struct usb2_fs_endpoint fs_ep;
void *uaddr; /* userland pointer */
void *kaddr;
- uint32_t offset;
+ usb2_frlength_t offset;
+ usb2_frlength_t rem;
+ usb2_frcount_t n;
uint32_t length;
- uint32_t n;
- uint32_t rem;
int error;
uint8_t isread;
@@ -1198,21 +1203,21 @@ ugen_fs_copy_out(struct usb2_fifo *f, uint8_t ep_index)
struct usb2_fs_endpoint *fs_ep_uptr; /* userland ptr */
void *uaddr; /* userland ptr */
void *kaddr;
- uint32_t offset;
+ usb2_frlength_t offset;
+ usb2_frlength_t rem;
+ usb2_frcount_t n;
uint32_t length;
uint32_t temp;
- uint32_t n;
- uint32_t rem;
int error;
uint8_t isread;
- if (ep_index >= f->fs_ep_max) {
+ if (ep_index >= f->fs_ep_max)
return (EINVAL);
- }
+
xfer = f->fs_xfer[ep_index];
- if (xfer == NULL) {
+ if (xfer == NULL)
return (EINVAL);
- }
+
mtx_lock(f->priv_mtx);
if (usb2_transfer_pending(xfer)) {
mtx_unlock(f->priv_mtx);
@@ -1458,13 +1463,13 @@ ugen_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags)
usb2_config[0].type = ed->bmAttributes & UE_XFERTYPE;
usb2_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
usb2_config[0].direction = ed->bEndpointAddress & (UE_DIR_OUT | UE_DIR_IN);
- usb2_config[0].mh.interval = USB_DEFAULT_INTERVAL;
- usb2_config[0].mh.flags.proxy_buffer = 1;
- usb2_config[0].mh.callback = &ugen_default_fs_callback;
- usb2_config[0].mh.timeout = 0; /* no timeout */
- usb2_config[0].mh.frames = u.popen->max_frames;
- usb2_config[0].mh.bufsize = u.popen->max_bufsize;
- usb2_config[0].md = usb2_config[0].mh; /* symmetric config */
+ usb2_config[0].interval = USB_DEFAULT_INTERVAL;
+ usb2_config[0].flags.proxy_buffer = 1;
+ usb2_config[0].callback = &ugen_default_fs_callback;
+ usb2_config[0].timeout = 0; /* no timeout */
+ usb2_config[0].frames = u.popen->max_frames;
+ usb2_config[0].bufsize = u.popen->max_bufsize;
+ usb2_config[0].usb_mode = USB_MODE_MAX; /* both modes */
if (usb2_config[0].type == UE_CONTROL) {
if (f->udev->flags.usb2_mode != USB_MODE_HOST) {
@@ -1615,10 +1620,10 @@ ugen_get_frame_size(struct usb2_fifo *f, void *addr)
static int
ugen_set_buffer_size(struct usb2_fifo *f, void *addr)
{
- uint32_t t;
+ usb2_frlength_t t;
- if (*(int *)addr < 1024)
- t = 1024;
+ if (*(int *)addr < 0)
+ t = 0; /* use "wMaxPacketSize" */
else if (*(int *)addr < (256 * 1024))
t = *(int *)addr;
else
@@ -2182,3 +2187,4 @@ ugen_default_fs_callback(struct usb2_xfer *xfer)
break;
}
}
+#endif /* USB_HAVE_UGEN */
diff --git a/sys/dev/usb/usb_handle_request.c b/sys/dev/usb/usb_handle_request.c
index 3d2425a..7a9a697 100644
--- a/sys/dev/usb/usb_handle_request.c
+++ b/sys/dev/usb/usb_handle_request.c
@@ -24,7 +24,6 @@
* SUCH DAMAGE.
*/
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb.h>
@@ -212,7 +211,7 @@ tr_repeat:
(iface->subdev != NULL) &&
device_is_attached(iface->subdev)) {
#if 0
- DEVMETHOD(usb2_handle_request, NULL); /* dummy */
+ DEVMETHOD(usb_handle_request, NULL); /* dummy */
#endif
error = USB_HANDLE_REQUEST(iface->subdev,
&req, ppdata, plen,
@@ -399,9 +398,7 @@ usb2_handle_remote_wakeup(struct usb2_xfer *xfer, uint8_t is_on)
USB_BUS_UNLOCK(bus);
/* In case we are out of sync, update the power state. */
-
usb2_bus_power_update(udev->bus);
-
return (0); /* success */
}
diff --git a/sys/dev/usb/usb_hid.c b/sys/dev/usb/usb_hid.c
index 5ac1930..555d324 100644
--- a/sys/dev/usb/usb_hid.c
+++ b/sys/dev/usb/usb_hid.c
@@ -43,7 +43,6 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usbhid.h>
#define USB_DEBUG_VAR usb2_debug
@@ -106,7 +105,7 @@ hid_clear_local(struct hid_item *c)
* hid_start_parse
*------------------------------------------------------------------------*/
struct hid_data *
-hid_start_parse(const void *d, int len, int kindset)
+hid_start_parse(const void *d, usb2_size_t len, int kindset)
{
struct hid_data *s;
@@ -441,7 +440,7 @@ hid_get_item(struct hid_data *s, struct hid_item *h)
/* sanity check */
if ((s->nusage < MAXUSAGE) &&
- (c->usage_minimum < c->usage_maximum)) {
+ (c->usage_minimum <= c->usage_maximum)) {
/* add usage range */
s->usages_min[s->nusage] =
c->usage_minimum;
@@ -491,7 +490,7 @@ hid_get_item(struct hid_data *s, struct hid_item *h)
* hid_report_size
*------------------------------------------------------------------------*/
int
-hid_report_size(const void *buf, int len, enum hid_kind k, uint8_t *id)
+hid_report_size(const void *buf, usb2_size_t len, enum hid_kind k, uint8_t *id)
{
struct hid_data *d;
struct hid_item h;
@@ -544,14 +543,16 @@ hid_report_size(const void *buf, int len, enum hid_kind k, uint8_t *id)
* hid_locate
*------------------------------------------------------------------------*/
int
-hid_locate(const void *desc, int size, uint32_t u, enum hid_kind k,
- struct hid_location *loc, uint32_t *flags, uint8_t *id)
+hid_locate(const void *desc, usb2_size_t size, uint32_t u, enum hid_kind k,
+ uint8_t index, struct hid_location *loc, uint32_t *flags, uint8_t *id)
{
struct hid_data *d;
struct hid_item h;
for (d = hid_start_parse(desc, size, 1 << k); hid_get_item(d, &h);) {
if (h.kind == k && !(h.flags & HIO_CONST) && h.usage == u) {
+ if (index--)
+ continue;
if (loc != NULL)
*loc = h.loc;
if (flags != NULL)
@@ -576,7 +577,7 @@ hid_locate(const void *desc, int size, uint32_t u, enum hid_kind k,
* hid_get_data
*------------------------------------------------------------------------*/
uint32_t
-hid_get_data(const uint8_t *buf, uint32_t len, struct hid_location *loc)
+hid_get_data(const uint8_t *buf, usb2_size_t len, struct hid_location *loc)
{
uint32_t hpos = loc->pos;
uint32_t hsize = loc->size;
@@ -619,7 +620,7 @@ hid_get_data(const uint8_t *buf, uint32_t len, struct hid_location *loc)
* hid_is_collection
*------------------------------------------------------------------------*/
int
-hid_is_collection(const void *desc, int size, uint32_t usage)
+hid_is_collection(const void *desc, usb2_size_t size, uint32_t usage)
{
struct hid_data *hd;
struct hid_item hi;
diff --git a/sys/dev/usb/usb_hid.h b/sys/dev/usb/usb_hid.h
index 0711c47..8febc4e 100644
--- a/sys/dev/usb/usb_hid.h
+++ b/sys/dev/usb/usb_hid.h
@@ -74,17 +74,17 @@ struct hid_item {
/* prototypes from "usb2_hid.c" */
-struct hid_data *hid_start_parse(const void *d, int len, int kindset);
+struct hid_data *hid_start_parse(const void *d, usb2_size_t len, int kindset);
void hid_end_parse(struct hid_data *s);
int hid_get_item(struct hid_data *s, struct hid_item *h);
-int hid_report_size(const void *buf, int len, enum hid_kind k,
+int hid_report_size(const void *buf, usb2_size_t len, enum hid_kind k,
uint8_t *id);
-int hid_locate(const void *desc, int size, uint32_t usage,
- enum hid_kind kind, struct hid_location *loc,
+int hid_locate(const void *desc, usb2_size_t size, uint32_t usage,
+ enum hid_kind kind, uint8_t index, struct hid_location *loc,
uint32_t *flags, uint8_t *id);
-uint32_t hid_get_data(const uint8_t *buf, uint32_t len,
+uint32_t hid_get_data(const uint8_t *buf, usb2_size_t len,
struct hid_location *loc);
-int hid_is_collection(const void *desc, int size, uint32_t usage);
+int hid_is_collection(const void *desc, usb2_size_t size, uint32_t usage);
struct usb2_hid_descriptor *hid_get_descriptor_from_usb(
struct usb2_config_descriptor *cd,
struct usb2_interface_descriptor *id);
diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c
index 67190ed..627d8a7 100644
--- a/sys/dev/usb/usb_hub.c
+++ b/sys/dev/usb/usb_hub.c
@@ -27,10 +27,9 @@
*/
/*
- * USB spec: http://www.usb.org/developers/docs/usbspec.zip
+ * USB spec: http://www.usb.org/developers/docs/usbspec.zip
*/
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb.h>
@@ -63,10 +62,12 @@ SYSCTL_INT(_hw_usb2_uhub, OID_AUTO, debug, CTLFLAG_RW, &uhub_debug, 0,
"Debug level");
#endif
+#if USB_HAVE_POWERD
static int usb2_power_timeout = 30; /* seconds */
SYSCTL_INT(_hw_usb2, OID_AUTO, power_timeout, CTLFLAG_RW,
&usb2_power_timeout, 0, "USB power timeout");
+#endif
struct uhub_current_state {
uint16_t port_change;
@@ -110,11 +111,11 @@ static const struct usb2_config uhub_config[UHUB_N_TRANSFER] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_ANY,
- .mh.timeout = 0,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.bufsize = 0, /* use wMaxPacketSize */
- .mh.callback = &uhub_intr_callback,
- .mh.interval = UHUB_INTR_INTERVAL,
+ .timeout = 0,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .bufsize = 0, /* use wMaxPacketSize */
+ .callback = &uhub_intr_callback,
+ .interval = UHUB_INTR_INTERVAL,
},
};
@@ -124,23 +125,24 @@ static const struct usb2_config uhub_config[UHUB_N_TRANSFER] = {
*/
static devclass_t uhub_devclass;
-static driver_t uhub_driver =
-{
+static device_method_t uhub_methods[] = {
+ DEVMETHOD(device_probe, uhub_probe),
+ DEVMETHOD(device_attach, uhub_attach),
+ DEVMETHOD(device_detach, uhub_detach),
+
+ DEVMETHOD(device_suspend, uhub_suspend),
+ DEVMETHOD(device_resume, uhub_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+
+ DEVMETHOD(bus_child_location_str, uhub_child_location_string),
+ DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_string),
+ DEVMETHOD(bus_driver_added, uhub_driver_added),
+ {0, 0}
+};
+
+static driver_t uhub_driver = {
.name = "uhub",
- .methods = (device_method_t[]){
- DEVMETHOD(device_probe, uhub_probe),
- DEVMETHOD(device_attach, uhub_attach),
- DEVMETHOD(device_detach, uhub_detach),
-
- DEVMETHOD(device_suspend, uhub_suspend),
- DEVMETHOD(device_resume, uhub_resume),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
-
- DEVMETHOD(bus_child_location_str, uhub_child_location_string),
- DEVMETHOD(bus_child_pnpinfo_str, uhub_child_pnpinfo_string),
- DEVMETHOD(bus_driver_added, uhub_driver_added),
- {0, 0}
- },
+ .methods = uhub_methods,
.size = sizeof(struct uhub_softc)
};
@@ -298,8 +300,9 @@ repeat:
/* detach any existing devices */
if (child) {
- usb2_detach_device(child, USB_IFACE_INDEX_ANY, 1);
- usb2_free_device(child);
+ usb2_free_device(child,
+ USB_UNCFG_FLAG_FREE_SUBDEV |
+ USB_UNCFG_FLAG_FREE_EP0);
child = NULL;
}
/* get fresh status */
@@ -418,8 +421,9 @@ repeat:
error:
if (child) {
- usb2_detach_device(child, USB_IFACE_INDEX_ANY, 1);
- usb2_free_device(child);
+ usb2_free_device(child,
+ USB_UNCFG_FLAG_FREE_SUBDEV |
+ USB_UNCFG_FLAG_FREE_EP0);
child = NULL;
}
if (err == 0) {
@@ -500,6 +504,21 @@ done:
}
/*------------------------------------------------------------------------*
+ * uhub_root_interrupt
+ *
+ * This function is called when a Root HUB interrupt has
+ * happened. "ptr" and "len" makes up the Root HUB interrupt
+ * packet. This function is called having the "bus_mtx" locked.
+ *------------------------------------------------------------------------*/
+void
+uhub_root_intr(struct usb2_bus *bus, const uint8_t *ptr, uint8_t len)
+{
+ USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
+
+ usb2_needs_explore(bus, 0);
+}
+
+/*------------------------------------------------------------------------*
* uhub_explore
*
* Returns:
@@ -711,9 +730,10 @@ uhub_attach(device_t dev)
}
udev->hub = hub;
+#if USB_HAVE_TT_SUPPORT
/* init FULL-speed ISOCHRONOUS schedule */
usb2_fs_isoc_schedule_init_all(hub->fs_isoc_schedule);
-
+#endif
/* initialize HUB structure */
hub->hubsoftc = sc;
hub->explore = &uhub_explore;
@@ -729,8 +749,14 @@ uhub_attach(device_t dev)
/* set up interrupt pipe */
iface_index = 0;
- err = usb2_transfer_setup(udev, &iface_index, sc->sc_xfer,
- uhub_config, UHUB_N_TRANSFER, sc, &Giant);
+ if (udev->parent_hub == NULL) {
+ /* root HUB is special */
+ err = 0;
+ } else {
+ /* normal HUB */
+ err = usb2_transfer_setup(udev, &iface_index, sc->sc_xfer,
+ uhub_config, UHUB_N_TRANSFER, sc, &Giant);
+ }
if (err) {
DPRINTFN(0, "cannot setup interrupt transfer, "
"errstr=%s!\n", usb2_errstr(err));
@@ -802,11 +828,13 @@ uhub_attach(device_t dev)
"removable, %s powered\n", nports, (nports != 1) ? "s" : "",
removable, udev->flags.self_powered ? "self" : "bus");
- /* start the interrupt endpoint */
+ /* Start the interrupt endpoint, if any */
- USB_XFER_LOCK(sc->sc_xfer[0]);
- usb2_transfer_start(sc->sc_xfer[0]);
- USB_XFER_UNLOCK(sc->sc_xfer[0]);
+ if (sc->sc_xfer[0] != NULL) {
+ USB_XFER_LOCK(sc->sc_xfer[0]);
+ usb2_transfer_start(sc->sc_xfer[0]);
+ USB_XFER_UNLOCK(sc->sc_xfer[0]);
+ }
/* Enable automatic power save on all USB HUBs */
@@ -853,9 +881,8 @@ uhub_detach(device_t dev)
* Subdevices are not freed, because the caller of
* uhub_detach() will do that.
*/
- usb2_detach_device(child, USB_IFACE_INDEX_ANY, 0);
- usb2_free_device(child);
- child = NULL;
+ usb2_free_device(child,
+ USB_UNCFG_FLAG_FREE_EP0);
}
usb2_transfer_unsetup(sc->sc_xfer, UHUB_N_TRANSFER);
@@ -979,7 +1006,11 @@ uhub_child_pnpinfo_string(device_t parent, device_t child,
UGETW(res.udev->ddesc.idProduct),
res.udev->ddesc.bDeviceClass,
res.udev->ddesc.bDeviceSubClass,
+#if USB_HAVE_STRINGS
res.udev->serial,
+#else
+ "",
+#endif
iface->idesc->bInterfaceClass,
iface->idesc->bInterfaceSubClass);
} else {
@@ -1031,9 +1062,9 @@ done:
* The best Transaction Translation slot for an interrupt endpoint.
*------------------------------------------------------------------------*/
static uint8_t
-usb2_intr_find_best_slot(uint32_t *ptr, uint8_t start, uint8_t end)
+usb2_intr_find_best_slot(usb2_size_t *ptr, uint8_t start, uint8_t end)
{
- uint32_t max = 0xffffffff;
+ usb2_size_t max = 0 - 1;
uint8_t x;
uint8_t y;
@@ -1111,6 +1142,7 @@ usb2_intr_schedule_adjust(struct usb2_device *udev, int16_t len, uint8_t slot)
* This function initialises an USB FULL speed isochronous schedule
* entry.
*------------------------------------------------------------------------*/
+#if USB_HAVE_TT_SUPPORT
static void
usb2_fs_isoc_schedule_init_sub(struct usb2_fs_isoc_schedule *fss)
{
@@ -1119,6 +1151,7 @@ usb2_fs_isoc_schedule_init_sub(struct usb2_fs_isoc_schedule *fss)
fss->frame_bytes = (USB_FS_BYTES_PER_HS_UFRAME);
fss->frame_slot = 0;
}
+#endif
/*------------------------------------------------------------------------*
* usb2_fs_isoc_schedule_init_all
@@ -1126,6 +1159,7 @@ usb2_fs_isoc_schedule_init_sub(struct usb2_fs_isoc_schedule *fss)
* This function will reset the complete USB FULL speed isochronous
* bandwidth schedule.
*------------------------------------------------------------------------*/
+#if USB_HAVE_TT_SUPPORT
void
usb2_fs_isoc_schedule_init_all(struct usb2_fs_isoc_schedule *fss)
{
@@ -1136,6 +1170,7 @@ usb2_fs_isoc_schedule_init_all(struct usb2_fs_isoc_schedule *fss)
fss++;
}
}
+#endif
/*------------------------------------------------------------------------*
* usb2_isoc_time_expand
@@ -1183,6 +1218,7 @@ usb2_isoc_time_expand(struct usb2_bus *bus, uint16_t isoc_time_curr)
* NOTE: This function depends on being called regularly with
* intervals less than "USB_ISOC_TIME_MAX".
*------------------------------------------------------------------------*/
+#if USB_HAVE_TT_SUPPORT
uint16_t
usb2_fs_isoc_schedule_isoc_time_expand(struct usb2_device *udev,
struct usb2_fs_isoc_schedule **pp_start,
@@ -1229,6 +1265,7 @@ usb2_fs_isoc_schedule_isoc_time_expand(struct usb2_device *udev,
}
return (isoc_time);
}
+#endif
/*------------------------------------------------------------------------*
* usb2_fs_isoc_schedule_alloc
@@ -1243,6 +1280,7 @@ usb2_fs_isoc_schedule_isoc_time_expand(struct usb2_device *udev,
* 0: Success
* Else: Error
*------------------------------------------------------------------------*/
+#if USB_HAVE_TT_SUPPORT
uint8_t
usb2_fs_isoc_schedule_alloc(struct usb2_fs_isoc_schedule *fss,
uint8_t *pstart, uint16_t len)
@@ -1275,6 +1313,7 @@ usb2_fs_isoc_schedule_alloc(struct usb2_fs_isoc_schedule *fss,
*pstart = slot;
return (0); /* success */
}
+#endif
/*------------------------------------------------------------------------*
* usb2_bus_port_get_device
@@ -1346,13 +1385,25 @@ usb2_bus_port_set_device(struct usb2_bus *bus, struct usb2_port *up,
void
usb2_needs_explore(struct usb2_bus *bus, uint8_t do_probe)
{
+ uint8_t do_unlock;
+
DPRINTF("\n");
if (bus == NULL) {
DPRINTF("No bus pointer!\n");
return;
}
- USB_BUS_LOCK(bus);
+ if ((bus->devices == NULL) ||
+ (bus->devices[USB_ROOT_HUB_ADDR] == NULL)) {
+ DPRINTF("No root HUB\n");
+ return;
+ }
+ if (mtx_owned(&bus->bus_mtx)) {
+ do_unlock = 0;
+ } else {
+ USB_BUS_LOCK(bus);
+ do_unlock = 1;
+ }
if (do_probe) {
bus->do_probe = 1;
}
@@ -1360,7 +1411,9 @@ usb2_needs_explore(struct usb2_bus *bus, uint8_t do_probe)
&bus->explore_msg[0], &bus->explore_msg[1])) {
/* ignore */
}
- USB_BUS_UNLOCK(bus);
+ if (do_unlock) {
+ USB_BUS_UNLOCK(bus);
+ }
}
/*------------------------------------------------------------------------*
@@ -1407,11 +1460,13 @@ usb2_needs_explore_all(void)
* properly suspended or resumed according to the device transfer
* state.
*------------------------------------------------------------------------*/
+#if USB_HAVE_POWERD
void
usb2_bus_power_update(struct usb2_bus *bus)
{
usb2_needs_explore(bus, 0 /* no probe */ );
}
+#endif
/*------------------------------------------------------------------------*
* usb2_transfer_power_ref
@@ -1420,10 +1475,11 @@ usb2_bus_power_update(struct usb2_bus *bus)
* wakeup the USB device associated with the given USB transfer, if
* needed.
*------------------------------------------------------------------------*/
+#if USB_HAVE_POWERD
void
usb2_transfer_power_ref(struct usb2_xfer *xfer, int val)
{
- static const uint32_t power_mask[4] = {
+ static const usb2_power_mask_t power_mask[4] = {
[UE_CONTROL] = USB_HW_POWER_CONTROL,
[UE_BULK] = USB_HW_POWER_BULK,
[UE_INTERRUPT] = USB_HW_POWER_INTERRUPT,
@@ -1489,8 +1545,8 @@ usb2_transfer_power_ref(struct usb2_xfer *xfer, int val)
(udev->bus->methods->set_hw_power) (udev->bus);
}
}
- return;
}
+#endif
/*------------------------------------------------------------------------*
* usb2_bus_powerd
@@ -1498,14 +1554,15 @@ usb2_transfer_power_ref(struct usb2_xfer *xfer, int val)
* This function implements the USB power daemon and is called
* regularly from the USB explore thread.
*------------------------------------------------------------------------*/
+#if USB_HAVE_POWERD
void
usb2_bus_powerd(struct usb2_bus *bus)
{
struct usb2_device *udev;
- unsigned int temp;
- unsigned int limit;
- unsigned int mintime;
- uint32_t type_refs[5];
+ usb2_ticks_t temp;
+ usb2_ticks_t limit;
+ usb2_ticks_t mintime;
+ usb2_size_t type_refs[5];
uint8_t x;
uint8_t rem_wakeup;
@@ -1621,6 +1678,7 @@ usb2_bus_powerd(struct usb2_bus *bus)
}
return;
}
+#endif
/*------------------------------------------------------------------------*
* usb2_dev_resume_peer
@@ -1680,6 +1738,7 @@ usb2_dev_resume_peer(struct usb2_device *udev)
USB_BUS_LOCK(bus);
/* set that this device is now resumed */
udev->pwr_save.suspended = 0;
+#if USB_HAVE_POWERD
/* make sure that we don't go into suspend right away */
udev->pwr_save.last_xfer_time = ticks;
@@ -1692,6 +1751,7 @@ usb2_dev_resume_peer(struct usb2_device *udev)
bus->hw_power_state |= USB_HW_POWER_INTERRUPT;
if (udev->pwr_save.type_refs[UE_ISOCHRONOUS] != 0)
bus->hw_power_state |= USB_HW_POWER_ISOC;
+#endif
USB_BUS_UNLOCK(bus);
if (bus->methods->set_hw_power != NULL) {
@@ -1728,7 +1788,6 @@ usb2_dev_suspend_peer(struct usb2_device *udev)
{
struct usb2_device *hub;
struct usb2_device *child;
- uint32_t temp;
int err;
uint8_t x;
uint8_t nports;
@@ -1801,6 +1860,7 @@ repeat:
USB_BUS_UNLOCK(udev->bus);
if (udev->bus->methods->device_suspend != NULL) {
+ usb2_timeout_t temp;
/* suspend device on the USB controller */
(udev->bus->methods->device_suspend) (udev);
@@ -1840,7 +1900,7 @@ usb2_set_power_mode(struct usb2_device *udev, uint8_t power_mode)
}
udev->power_mode = power_mode; /* update copy of power mode */
+#if USB_HAVE_POWERD
usb2_bus_power_update(udev->bus);
-
- return;
+#endif
}
diff --git a/sys/dev/usb/usb_hub.h b/sys/dev/usb/usb_hub.h
index 87d85b3..0c8905d 100644
--- a/sys/dev/usb/usb_hub.h
+++ b/sys/dev/usb/usb_hub.h
@@ -28,7 +28,7 @@
#define _USB2_HUB_H_
/*
- * The following structure defines an USB port.
+ * The following structure defines an USB port.
*/
struct usb2_port {
uint8_t restartcnt;
@@ -52,11 +52,13 @@ struct usb2_fs_isoc_schedule {
* The following structure defines an USB HUB.
*/
struct usb2_hub {
+#if USB_HAVE_TT_SUPPORT
struct usb2_fs_isoc_schedule fs_isoc_schedule[USB_ISOC_TIME_MAX];
+#endif
struct usb2_device *hubudev; /* the HUB device */
usb2_error_t (*explore) (struct usb2_device *hub);
void *hubsoftc;
- uint32_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
+ usb2_size_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
uint16_t portpower; /* mA per USB port */
uint8_t isoc_last_time;
uint8_t nports;
@@ -76,5 +78,6 @@ void usb2_needs_explore(struct usb2_bus *bus, uint8_t do_probe);
void usb2_needs_explore_all(void);
void usb2_bus_power_update(struct usb2_bus *bus);
void usb2_bus_powerd(struct usb2_bus *bus);
+void uhub_root_intr(struct usb2_bus *, const uint8_t *, uint8_t);
#endif /* _USB2_HUB_H_ */
diff --git a/sys/dev/usb/usb_lookup.c b/sys/dev/usb/usb_lookup.c
index a8fa271..6c707ce 100644
--- a/sys/dev/usb/usb_lookup.c
+++ b/sys/dev/usb/usb_lookup.c
@@ -42,7 +42,7 @@
* Else: Pointer to matching entry.
*------------------------------------------------------------------------*/
const struct usb2_device_id *
-usb2_lookup_id_by_info(const struct usb2_device_id *id, uint32_t sizeof_id,
+usb2_lookup_id_by_info(const struct usb2_device_id *id, usb2_size_t sizeof_id,
const struct usb2_lookup_info *info)
{
const struct usb2_device_id *id_end;
@@ -121,7 +121,7 @@ done:
* Else: Failure
*------------------------------------------------------------------------*/
int
-usb2_lookup_id_by_uaa(const struct usb2_device_id *id, uint32_t sizeof_id,
+usb2_lookup_id_by_uaa(const struct usb2_device_id *id, usb2_size_t sizeof_id,
struct usb2_attach_arg *uaa)
{
id = usb2_lookup_id_by_info(id, sizeof_id, &uaa->info);
diff --git a/sys/dev/usb/usb_lookup.h b/sys/dev/usb/usb_lookup.h
index e447292..74d02e5 100644
--- a/sys/dev/usb/usb_lookup.h
+++ b/sys/dev/usb/usb_lookup.h
@@ -114,9 +114,9 @@ struct usb2_device_id {
(((const uint8_t *)((did)->driver_info)) - ((const uint8_t *)0))
const struct usb2_device_id *usb2_lookup_id_by_info(
- const struct usb2_device_id *id, uint32_t sizeof_id,
+ const struct usb2_device_id *id, usb2_size_t sizeof_id,
const struct usb2_lookup_info *info);
int usb2_lookup_id_by_uaa(const struct usb2_device_id *id,
- uint32_t sizeof_id, struct usb2_attach_arg *uaa);
+ usb2_size_t sizeof_id, struct usb2_attach_arg *uaa);
#endif /* _USB2_LOOKUP_H_ */
diff --git a/sys/dev/usb/usb_mbuf.c b/sys/dev/usb/usb_mbuf.c
index 3ae6ee6..e4d92b6 100644
--- a/sys/dev/usb/usb_mbuf.c
+++ b/sys/dev/usb/usb_mbuf.c
@@ -36,12 +36,12 @@
*------------------------------------------------------------------------*/
void *
usb2_alloc_mbufs(struct malloc_type *type, struct usb2_ifqueue *ifq,
- uint32_t block_size, uint16_t nblocks)
+ usb2_size_t block_size, uint16_t nblocks)
{
struct usb2_mbuf *m_ptr;
uint8_t *data_ptr;
void *free_ptr = NULL;
- uint32_t alloc_size;
+ usb2_size_t alloc_size;
/* align data */
block_size += ((-block_size) & (USB_HOST_ALIGN - 1));
diff --git a/sys/dev/usb/usb_mbuf.h b/sys/dev/usb/usb_mbuf.h
index 109340c..c748dbc 100644
--- a/sys/dev/usb/usb_mbuf.h
+++ b/sys/dev/usb/usb_mbuf.h
@@ -37,8 +37,8 @@ struct usb2_mbuf {
struct usb2_mbuf *usb2_nextpkt;
struct usb2_mbuf *usb2_next;
- uint32_t cur_data_len;
- uint32_t max_data_len;
+ usb2_size_t cur_data_len;
+ usb2_size_t max_data_len;
uint8_t last_packet:1;
uint8_t unused:7;
};
@@ -51,8 +51,8 @@ struct usb2_ifqueue {
struct usb2_mbuf *ifq_head;
struct usb2_mbuf *ifq_tail;
- uint32_t ifq_len;
- uint32_t ifq_maxlen;
+ usb2_size_t ifq_len;
+ usb2_size_t ifq_maxlen;
};
#define USB_IF_ENQUEUE(ifq, m) do { \
@@ -97,6 +97,6 @@ struct usb2_ifqueue {
/* prototypes */
void *usb2_alloc_mbufs(struct malloc_type *type, struct usb2_ifqueue *ifq,
- uint32_t block_size, uint16_t nblocks);
+ usb2_size_t block_size, uint16_t nblocks);
#endif /* _USB2_MBUF_H_ */
diff --git a/sys/dev/usb/usb_msctest.c b/sys/dev/usb/usb_msctest.c
index 35b71ec..960cd95 100644
--- a/sys/dev/usb/usb_msctest.c
+++ b/sys/dev/usb/usb_msctest.c
@@ -32,7 +32,6 @@
* mass storage quirks for not supported SCSI commands!
*/
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb.h>
@@ -110,10 +109,10 @@ struct bbb_transfer {
uint8_t *data_ptr;
- uint32_t data_len; /* bytes */
- uint32_t data_rem; /* bytes */
- uint32_t data_timeout; /* ms */
- uint32_t actlen; /* bytes */
+ usb2_size_t data_len; /* bytes */
+ usb2_size_t data_rem; /* bytes */
+ usb2_timeout_t data_timeout; /* ms */
+ usb2_frlength_t actlen; /* bytes */
uint8_t cmd_len; /* bytes */
uint8_t dir;
@@ -138,60 +137,57 @@ static const struct usb2_config bbb_config[ST_MAX] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = sizeof(struct bbb_cbw),
- .mh.flags = {},
- .mh.callback = &bbb_command_callback,
- .mh.timeout = 4 * USB_MS_HZ, /* 4 seconds */
+ .bufsize = sizeof(struct bbb_cbw),
+ .callback = &bbb_command_callback,
+ .timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
[ST_DATA_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = BULK_SIZE,
- .mh.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
- .mh.callback = &bbb_data_read_callback,
- .mh.timeout = 4 * USB_MS_HZ, /* 4 seconds */
+ .bufsize = BULK_SIZE,
+ .flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
+ .callback = &bbb_data_read_callback,
+ .timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
[ST_DATA_RD_CS] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &bbb_data_rd_cs_callback,
- .mh.timeout = 1 * USB_MS_HZ, /* 1 second */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &bbb_data_rd_cs_callback,
+ .timeout = 1 * USB_MS_HZ, /* 1 second */
},
[ST_DATA_WR] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = BULK_SIZE,
- .mh.flags = {.proxy_buffer = 1,},
- .mh.callback = &bbb_data_write_callback,
- .mh.timeout = 4 * USB_MS_HZ, /* 4 seconds */
+ .bufsize = BULK_SIZE,
+ .flags = {.proxy_buffer = 1,},
+ .callback = &bbb_data_write_callback,
+ .timeout = 4 * USB_MS_HZ, /* 4 seconds */
},
[ST_DATA_WR_CS] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &bbb_data_wr_cs_callback,
- .mh.timeout = 1 * USB_MS_HZ, /* 1 second */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &bbb_data_wr_cs_callback,
+ .timeout = 1 * USB_MS_HZ, /* 1 second */
},
[ST_STATUS] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = sizeof(struct bbb_csw),
- .mh.flags = {.short_xfer_ok = 1,},
- .mh.callback = &bbb_status_callback,
- .mh.timeout = 1 * USB_MS_HZ, /* 1 second */
+ .bufsize = sizeof(struct bbb_csw),
+ .flags = {.short_xfer_ok = 1,},
+ .callback = &bbb_status_callback,
+ .timeout = 1 * USB_MS_HZ, /* 1 second */
},
};
@@ -266,7 +262,7 @@ bbb_command_callback(struct usb2_xfer *xfer)
tag = UGETDW(sc->cbw.dCBWTag) + 1;
USETDW(sc->cbw.dCBWSignature, CBWSIGNATURE);
USETDW(sc->cbw.dCBWTag, tag);
- USETDW(sc->cbw.dCBWDataTransferLength, sc->data_len);
+ USETDW(sc->cbw.dCBWDataTransferLength, (uint32_t)sc->data_len);
sc->cbw.bCBWFlags = ((sc->dir == DIR_IN) ? CBWFLAGS_IN : CBWFLAGS_OUT);
sc->cbw.bCBWLUN = sc->lun;
sc->cbw.bCDBLength = sc->cmd_len;
@@ -290,7 +286,7 @@ static void
bbb_data_read_callback(struct usb2_xfer *xfer)
{
struct bbb_transfer *sc = xfer->priv_sc;
- uint32_t max_bulk = xfer->max_data_length;
+ usb2_frlength_t max_bulk = xfer->max_data_length;
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
@@ -341,7 +337,7 @@ static void
bbb_data_write_callback(struct usb2_xfer *xfer)
{
struct bbb_transfer *sc = xfer->priv_sc;
- uint32_t max_bulk = xfer->max_data_length;
+ usb2_frlength_t max_bulk = xfer->max_data_length;
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
@@ -439,8 +435,8 @@ bbb_status_callback(struct usb2_xfer *xfer)
*------------------------------------------------------------------------*/
static uint8_t
bbb_command_start(struct bbb_transfer *sc, uint8_t dir, uint8_t lun,
- void *data_ptr, uint32_t data_len, uint8_t cmd_len,
- uint32_t data_timeout)
+ void *data_ptr, usb2_size_t data_len, uint8_t cmd_len,
+ usb2_timeout_t data_timeout)
{
sc->lun = lun;
sc->dir = data_len ? dir : DIR_NONE;
diff --git a/sys/dev/usb/usb_parse.c b/sys/dev/usb/usb_parse.c
index 381f546..710d8fa 100644
--- a/sys/dev/usb/usb_parse.c
+++ b/sys/dev/usb/usb_parse.c
@@ -84,113 +84,109 @@ usb2_desc_foreach(struct usb2_config_descriptor *cd,
}
/*------------------------------------------------------------------------*
- * usb2_find_idesc
+ * usb2_idesc_foreach
*
- * This function will return the interface descriptor, if any, that
- * has index "iface_index" and alternate index "alt_index".
+ * This function will iterate the interface descriptors in the config
+ * descriptor. The parse state structure should be zeroed before
+ * calling this function the first time.
*
* Return values:
* NULL: End of descriptors
* Else: A valid interface descriptor
*------------------------------------------------------------------------*/
struct usb2_interface_descriptor *
-usb2_find_idesc(struct usb2_config_descriptor *cd,
- uint8_t iface_index, uint8_t alt_index)
+usb2_idesc_foreach(struct usb2_config_descriptor *cd,
+ struct usb2_idesc_parse_state *ps)
{
- struct usb2_descriptor *desc = NULL;
struct usb2_interface_descriptor *id;
- uint8_t curidx = 0;
- uint8_t lastidx = 0;
- uint8_t curaidx = 0;
- uint8_t first = 1;
-
- while ((desc = usb2_desc_foreach(cd, desc))) {
- if ((desc->bDescriptorType == UDESC_INTERFACE) &&
- (desc->bLength >= sizeof(*id))) {
- id = (void *)desc;
-
- if (first) {
- first = 0;
- lastidx = id->bInterfaceNumber;
-
- } else if (id->bInterfaceNumber != lastidx) {
+ uint8_t new_iface;
- lastidx = id->bInterfaceNumber;
- curidx++;
- curaidx = 0;
+ /* retrieve current descriptor */
+ id = (struct usb2_interface_descriptor *)ps->desc;
+ /* default is to start a new interface */
+ new_iface = 1;
- } else {
- curaidx++;
- }
-
- if ((iface_index == curidx) && (alt_index == curaidx)) {
- return (id);
- }
+ while (1) {
+ id = (struct usb2_interface_descriptor *)
+ usb2_desc_foreach(cd, (struct usb2_descriptor *)id);
+ if (id == NULL)
+ break;
+ if ((id->bDescriptorType == UDESC_INTERFACE) &&
+ (id->bLength >= sizeof(*id))) {
+ if (ps->iface_no_last == id->bInterfaceNumber)
+ new_iface = 0;
+ ps->iface_no_last = id->bInterfaceNumber;
+ break;
}
}
- return (NULL);
+
+ if (ps->desc == NULL) {
+ /* first time */
+ } else if (new_iface) {
+ /* new interface */
+ ps->iface_index ++;
+ ps->iface_index_alt = 0;
+ } else {
+ /* new alternate interface */
+ ps->iface_index_alt ++;
+ }
+
+ /* store and return current descriptor */
+ ps->desc = (struct usb2_descriptor *)id;
+ return (id);
}
/*------------------------------------------------------------------------*
- * usb2_find_edesc
+ * usb2_edesc_foreach
*
- * This function will return the endpoint descriptor for the passed
- * interface index, alternate index and endpoint index.
+ * This function will iterate all the endpoint descriptors within an
+ * interface descriptor. Starting value for the "ped" argument should
+ * be a valid interface descriptor.
*
* Return values:
* NULL: End of descriptors
* Else: A valid endpoint descriptor
*------------------------------------------------------------------------*/
struct usb2_endpoint_descriptor *
-usb2_find_edesc(struct usb2_config_descriptor *cd,
- uint8_t iface_index, uint8_t alt_index, uint8_t ep_index)
+usb2_edesc_foreach(struct usb2_config_descriptor *cd,
+ struct usb2_endpoint_descriptor *ped)
{
- struct usb2_descriptor *desc = NULL;
- struct usb2_interface_descriptor *d;
- uint8_t curidx = 0;
-
- d = usb2_find_idesc(cd, iface_index, alt_index);
- if (d == NULL)
- return (NULL);
-
- if (ep_index >= d->bNumEndpoints) /* quick exit */
- return (NULL);
+ struct usb2_descriptor *desc;
- desc = ((void *)d);
+ desc = ((struct usb2_descriptor *)ped);
while ((desc = usb2_desc_foreach(cd, desc))) {
if (desc->bDescriptorType == UDESC_INTERFACE) {
break;
}
if (desc->bDescriptorType == UDESC_ENDPOINT) {
- if (curidx == ep_index) {
- if (desc->bLength <
- sizeof(struct usb2_endpoint_descriptor)) {
- /* endpoint index is invalid */
- break;
- }
- return ((void *)desc);
+ if (desc->bLength < sizeof(*ped)) {
+ /* endpoint index is invalid */
+ break;
}
- curidx++;
+ return ((struct usb2_endpoint_descriptor *)desc);
}
}
return (NULL);
}
/*------------------------------------------------------------------------*
- * usb2_get_no_endpoints
+ * usb2_get_no_descriptors
*
- * This function will count the total number of endpoints available.
+ * This function will count the total number of descriptors in the
+ * configuration descriptor of type "type".
*------------------------------------------------------------------------*/
-uint16_t
-usb2_get_no_endpoints(struct usb2_config_descriptor *cd)
+uint8_t
+usb2_get_no_descriptors(struct usb2_config_descriptor *cd, uint8_t type)
{
struct usb2_descriptor *desc = NULL;
- uint16_t count = 0;
+ uint8_t count = 0;
while ((desc = usb2_desc_foreach(cd, desc))) {
- if (desc->bDescriptorType == UDESC_ENDPOINT) {
+ if (desc->bDescriptorType == type) {
count++;
+ if (count == 0xFF)
+ break; /* crazy */
}
}
return (count);
@@ -200,25 +196,30 @@ usb2_get_no_endpoints(struct usb2_config_descriptor *cd)
* usb2_get_no_alts
*
* Return value:
- * Number of alternate settings for the given "ifaceno".
- *
- * NOTE: The returned can be larger than the actual number of
- * alternate settings.
+ * Number of alternate settings for the given interface descriptor pointer.
*------------------------------------------------------------------------*/
-uint16_t
-usb2_get_no_alts(struct usb2_config_descriptor *cd, uint8_t ifaceno)
+uint8_t
+usb2_get_no_alts(struct usb2_config_descriptor *cd,
+ struct usb2_interface_descriptor *id)
{
- struct usb2_descriptor *desc = NULL;
- struct usb2_interface_descriptor *id;
- uint16_t n = 0;
+ struct usb2_descriptor *desc;
+ uint8_t n = 0;
+ uint8_t ifaceno;
+
+ ifaceno = id->bInterfaceNumber;
+
+ desc = (struct usb2_descriptor *)id;
while ((desc = usb2_desc_foreach(cd, desc))) {
if ((desc->bDescriptorType == UDESC_INTERFACE) &&
(desc->bLength >= sizeof(*id))) {
- id = (void *)desc;
+ id = (struct usb2_interface_descriptor *)desc;
if (id->bInterfaceNumber == ifaceno) {
n++;
- }
+ if (n == 0xFF)
+ break; /* crazy */
+ } else
+ break; /* end */
}
}
return (n);
diff --git a/sys/dev/usb/usb_parse.h b/sys/dev/usb/usb_parse.h
index a9e6509..b836b57 100644
--- a/sys/dev/usb/usb_parse.h
+++ b/sys/dev/usb/usb_parse.h
@@ -27,15 +27,28 @@
#ifndef _USB2_PARSE_H_
#define _USB2_PARSE_H_
+/* structures */
+
+struct usb2_idesc_parse_state {
+ struct usb2_descriptor *desc;
+ uint8_t iface_index; /* current interface index */
+ uint8_t iface_no_last;
+ uint8_t iface_index_alt; /* current alternate setting */
+};
+
+/* prototypes */
+
struct usb2_descriptor *usb2_desc_foreach(struct usb2_config_descriptor *cd,
struct usb2_descriptor *desc);
-struct usb2_interface_descriptor *usb2_find_idesc(
- struct usb2_config_descriptor *cd, uint8_t iface_index,
- uint8_t alt_index);
-struct usb2_endpoint_descriptor *usb2_find_edesc(
- struct usb2_config_descriptor *cd, uint8_t iface_index,
- uint8_t alt_index, uint8_t ep_index);
-uint16_t usb2_get_no_endpoints(struct usb2_config_descriptor *cd);
-uint16_t usb2_get_no_alts(struct usb2_config_descriptor *cd, uint8_t ifaceno);
+struct usb2_interface_descriptor *usb2_idesc_foreach(
+ struct usb2_config_descriptor *cd,
+ struct usb2_idesc_parse_state *ps);
+struct usb2_endpoint_descriptor *usb2_edesc_foreach(
+ struct usb2_config_descriptor *cd,
+ struct usb2_endpoint_descriptor *ped);
+uint8_t usb2_get_no_descriptors(struct usb2_config_descriptor *cd,
+ uint8_t type);
+uint8_t usb2_get_no_alts(struct usb2_config_descriptor *cd,
+ struct usb2_interface_descriptor *id);
#endif /* _USB2_PARSE_H_ */
diff --git a/sys/dev/usb/usb_process.c b/sys/dev/usb/usb_process.c
index 0354284..5ec46d1 100644
--- a/sys/dev/usb/usb_process.c
+++ b/sys/dev/usb/usb_process.c
@@ -243,7 +243,7 @@ usb2_proc_msignal(struct usb2_process *up, void *_pm0, void *_pm1)
struct usb2_proc_msg *pm0 = _pm0;
struct usb2_proc_msg *pm1 = _pm1;
struct usb2_proc_msg *pm2;
- uint32_t d;
+ usb2_size_t d;
uint8_t t;
/* check if gone, return dummy value */
diff --git a/sys/dev/usb/usb_process.h b/sys/dev/usb/usb_process.h
index 756b929..c151f66 100644
--- a/sys/dev/usb/usb_process.h
+++ b/sys/dev/usb/usb_process.h
@@ -51,7 +51,7 @@ typedef void (usb2_proc_callback_t)(struct usb2_proc_msg *hdr);
struct usb2_proc_msg {
TAILQ_ENTRY(usb2_proc_msg) pm_qentry;
usb2_proc_callback_t *pm_callback;
- uint32_t pm_num;
+ usb2_size_t pm_num;
};
/*
@@ -66,7 +66,7 @@ struct usb2_process {
struct thread *up_curtd;
struct mtx *up_mtx;
- uint32_t up_msg_num;
+ usb2_size_t up_msg_num;
uint8_t up_prio;
uint8_t up_gone;
diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c
index 47f7ec7..4a1425c 100644
--- a/sys/dev/usb/usb_request.c
+++ b/sys/dev/usb/usb_request.c
@@ -24,9 +24,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.
- */
+ */
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb.h>
@@ -98,7 +97,7 @@ usb2_do_clear_stall_callback(struct usb2_xfer *xfer)
struct usb2_pipe *pipe;
struct usb2_pipe *pipe_end;
struct usb2_pipe *pipe_first;
- uint8_t to = USB_EP_MAX;
+ uint8_t to;
udev = xfer->xroot->udev;
@@ -107,8 +106,9 @@ usb2_do_clear_stall_callback(struct usb2_xfer *xfer)
/* round robin pipe clear stall */
pipe = udev->pipe_curr;
- pipe_end = udev->pipes + USB_EP_MAX;
+ pipe_end = udev->pipes + udev->pipes_max;
pipe_first = udev->pipes;
+ to = udev->pipes_max;
if (pipe == NULL) {
pipe = pipe_first;
}
@@ -229,15 +229,15 @@ tr_setup:
*------------------------------------------------------------------------*/
usb2_error_t
usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
- struct usb2_device_request *req, void *data, uint32_t flags,
- uint16_t *actlen, uint32_t timeout)
+ struct usb2_device_request *req, void *data, uint16_t flags,
+ uint16_t *actlen, usb2_timeout_t timeout)
{
struct usb2_xfer *xfer;
const void *desc;
int err = 0;
- uint32_t start_ticks;
- uint32_t delta_ticks;
- uint32_t max_ticks;
+ usb2_ticks_t start_ticks;
+ usb2_ticks_t delta_ticks;
+ usb2_ticks_t max_ticks;
uint16_t length;
uint16_t temp;
@@ -262,29 +262,33 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
* Set "actlen" to a known value in case the caller does not
* check the return value:
*/
- if (actlen) {
+ if (actlen)
*actlen = 0;
- }
+
+#if (USB_HAVE_USER_IO == 0)
+ if (flags & USB_USER_DATA_PTR)
+ return (USB_ERR_INVAL);
+#endif
if (udev->flags.usb2_mode == USB_MODE_DEVICE) {
DPRINTF("USB device mode\n");
(usb2_temp_get_desc_p) (udev, req, &desc, &temp);
if (length > temp) {
- if (!(flags & USB_SHORT_XFER_OK)) {
+ if (!(flags & USB_SHORT_XFER_OK))
return (USB_ERR_SHORT_XFER);
- }
length = temp;
}
- if (actlen) {
+ if (actlen)
*actlen = length;
- }
+
if (length > 0) {
+#if USB_HAVE_USER_IO
if (flags & USB_USER_DATA_PTR) {
if (copyout(desc, data, length)) {
return (USB_ERR_INVAL);
}
- } else {
+ } else
+#endif
bcopy(desc, data, length);
- }
}
return (0); /* success */
}
@@ -301,6 +305,59 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
sx_xlock(udev->default_sx);
+ if (udev->parent_hub == NULL) {
+ struct usb2_sw_transfer *std = &udev->bus->roothub_req;
+
+ /* root HUB code - stripped down */
+
+ if (req->bmRequestType & UT_READ) {
+ std->ptr = NULL;
+ } else {
+ if (length != 0) {
+ DPRINTFN(1, "Root HUB does not support "
+ "writing data!\n");
+ err = USB_ERR_INVAL;
+ goto done;
+ }
+ }
+ /* setup request */
+ std->req = *req;
+ std->err = 0;
+ std->len = 0;
+
+ USB_BUS_LOCK(udev->bus);
+ (udev->bus->methods->roothub_exec) (udev->bus);
+ USB_BUS_UNLOCK(udev->bus);
+
+ err = std->err;
+ if (err)
+ goto done;
+
+ if (length > std->len) {
+ length = std->len;
+ if (!(flags & USB_SHORT_XFER_OK)) {
+ err = USB_ERR_SHORT_XFER;
+ goto done;
+ }
+ }
+
+ if (actlen)
+ *actlen = length;
+
+ if (length > 0) {
+#if USB_HAVE_USER_IO
+ if (flags & USB_USER_DATA_PTR) {
+ if (copyout(std->ptr, data, length)) {
+ err = USB_ERR_INVAL;
+ goto done;
+ }
+ } else
+#endif
+ bcopy(std->ptr, data, length);
+ }
+ goto done;
+ }
+
/*
* Setup a new USB transfer or use the existing one, if any:
*/
@@ -314,11 +371,15 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
}
USB_XFER_LOCK(xfer);
- if (flags & USB_DELAY_STATUS_STAGE) {
+ if (flags & USB_DELAY_STATUS_STAGE)
xfer->flags.manual_status = 1;
- } else {
+ else
xfer->flags.manual_status = 0;
- }
+
+ if (flags & USB_SHORT_XFER_OK)
+ xfer->flags.short_xfer_ok = 1;
+ else
+ xfer->flags.short_xfer_ok = 0;
xfer->timeout = timeout;
@@ -340,6 +401,7 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
if (temp > 0) {
if (!(req->bmRequestType & UT_READ)) {
+#if USB_HAVE_USER_IO
if (flags & USB_USER_DATA_PTR) {
USB_XFER_UNLOCK(xfer);
err = usb2_copy_in_user(xfer->frbuffers + 1,
@@ -349,9 +411,10 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
err = USB_ERR_INVAL;
break;
}
- } else {
- usb2_copy_in(xfer->frbuffers + 1, 0, data, temp);
- }
+ } else
+#endif
+ usb2_copy_in(xfer->frbuffers + 1,
+ 0, data, temp);
}
xfer->nframes = 2;
} else {
@@ -402,13 +465,11 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
if (temp > xfer->actlen) {
temp = xfer->actlen;
- if (!(flags & USB_SHORT_XFER_OK)) {
- err = USB_ERR_SHORT_XFER;
- }
length = temp;
}
if (temp > 0) {
if (req->bmRequestType & UT_READ) {
+#if USB_HAVE_USER_IO
if (flags & USB_USER_DATA_PTR) {
USB_XFER_UNLOCK(xfer);
err = usb2_copy_out_user(xfer->frbuffers + 1,
@@ -418,10 +479,10 @@ usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
err = USB_ERR_INVAL;
break;
}
- } else {
+ } else
+#endif
usb2_copy_out(xfer->frbuffers + 1,
0, data, temp);
- }
}
}
/*
@@ -480,8 +541,8 @@ done:
*------------------------------------------------------------------------*/
usb2_error_t
usb2_do_request_proc(struct usb2_device *udev, struct usb2_process *pproc,
- struct usb2_device_request *req, void *data, uint32_t flags,
- uint16_t *actlen, uint32_t timeout)
+ struct usb2_device_request *req, void *data, uint16_t flags,
+ uint16_t *actlen, usb2_timeout_t timeout)
{
usb2_error_t err;
uint16_t len;
@@ -826,6 +887,40 @@ usb2_req_get_string_desc(struct usb2_device *udev, struct mtx *mtx, void *sdesc,
}
/*------------------------------------------------------------------------*
+ * usb2_req_get_config_desc_ptr
+ *
+ * This function is used in device side mode to retrieve the pointer
+ * to the generated config descriptor. This saves allocating space for
+ * an additional config descriptor when setting the configuration.
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+usb2_error_t
+usb2_req_get_config_desc_ptr(struct usb2_device *udev,
+ struct usb2_config_descriptor **ppcd, uint8_t config_index)
+{
+ uint16_t len;
+
+ struct usb2_device_request req;
+
+ if (udev->flags.usb2_mode != USB_MODE_DEVICE)
+ return (USB_ERR_INVAL);
+
+ req.bmRequestType = UT_READ_DEVICE;
+ req.bRequest = UR_GET_DESCRIPTOR;
+ USETW2(req.wValue, UDESC_CONFIG, config_index);
+ USETW(req.wIndex, 0);
+ USETW(req.wLength, 0);
+
+ (usb2_temp_get_desc_p) (udev, &req,
+ __DECONST(const void **, ppcd), &len);
+
+ return (*ppcd ? USB_ERR_NORMAL_COMPLETION : USB_ERR_INVAL);
+}
+
+/*------------------------------------------------------------------------*
* usb2_req_get_config_desc
*
* Returns:
@@ -1392,7 +1487,8 @@ usb2_req_re_enumerate(struct usb2_device *udev, struct mtx *mtx)
retry:
err = usb2_req_reset_port(parent_hub, mtx, udev->port_no);
if (err) {
- DPRINTFN(0, "addr=%d, port reset failed\n", old_addr);
+ DPRINTFN(0, "addr=%d, port reset failed, %s\n",
+ old_addr, usb2_errstr(err));
goto done;
}
/*
@@ -1410,8 +1506,8 @@ retry:
err = usb2_req_set_address(udev, mtx, old_addr);
if (err) {
/* XXX ignore any errors! */
- DPRINTFN(0, "addr=%d, set address failed! (ignored)\n",
- old_addr);
+ DPRINTFN(0, "addr=%d, set address failed! (%s, ignored)\n",
+ old_addr, usb2_errstr(err));
}
/* restore device address */
udev->address = old_addr;
@@ -1424,14 +1520,16 @@ retry:
USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
if (err) {
DPRINTFN(0, "getting device descriptor "
- "at addr %d failed!\n", udev->address);
+ "at addr %d failed, %s!\n", udev->address,
+ usb2_errstr(err));
goto done;
}
/* get the full device descriptor */
err = usb2_req_get_device_desc(udev, mtx, &udev->ddesc);
if (err) {
DPRINTFN(0, "addr=%d, getting device "
- "descriptor failed!\n", old_addr);
+ "descriptor failed, %s!\n", old_addr,
+ usb2_errstr(err));
goto done;
}
done:
diff --git a/sys/dev/usb/usb_request.h b/sys/dev/usb/usb_request.h
index 402daa0..6d30fd4 100644
--- a/sys/dev/usb/usb_request.h
+++ b/sys/dev/usb/usb_request.h
@@ -30,11 +30,11 @@
struct usb2_process;
usb2_error_t usb2_do_request_flags(struct usb2_device *udev, struct mtx *mtx,
- struct usb2_device_request *req, void *data, uint32_t flags,
- uint16_t *actlen, uint32_t timeout);
+ struct usb2_device_request *req, void *data, uint16_t flags,
+ uint16_t *actlen, usb2_timeout_t timeout);
usb2_error_t usb2_do_request_proc(struct usb2_device *udev, struct usb2_process *pproc,
- struct usb2_device_request *req, void *data, uint32_t flags,
- uint16_t *actlen, uint32_t timeout);
+ struct usb2_device_request *req, void *data, uint16_t flags,
+ uint16_t *actlen, usb2_timeout_t timeout);
usb2_error_t usb2_req_clear_hub_feature(struct usb2_device *udev,
struct mtx *mtx, uint16_t sel);
usb2_error_t usb2_req_clear_port_feature(struct usb2_device *udev,
@@ -44,6 +44,8 @@ usb2_error_t usb2_req_get_alt_interface_no(struct usb2_device *udev,
uint8_t iface_index);
usb2_error_t usb2_req_get_config(struct usb2_device *udev, struct mtx *mtx,
uint8_t *pconf);
+usb2_error_t usb2_req_get_config_desc_ptr(struct usb2_device *udev,
+ struct usb2_config_descriptor **ppcd, uint8_t config_index);
usb2_error_t usb2_req_get_config_desc(struct usb2_device *udev, struct mtx *mtx,
struct usb2_config_descriptor *d, uint8_t conf_index);
usb2_error_t usb2_req_get_config_desc_full(struct usb2_device *udev,
diff --git a/sys/dev/usb/usb_sw_transfer.c b/sys/dev/usb/usb_sw_transfer.c
deleted file mode 100644
index 984c233..0000000
--- a/sys/dev/usb/usb_sw_transfer.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 Hans Petter Selasky. 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.
- */
-
-#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb.h>
-#include <dev/usb/usb_error.h>
-#include <dev/usb/usb_defs.h>
-
-#define USB_DEBUG_VAR usb2_debug
-
-#include <dev/usb/usb_core.h>
-#include <dev/usb/usb_process.h>
-#include <dev/usb/usb_busdma.h>
-#include <dev/usb/usb_transfer.h>
-#include <dev/usb/usb_sw_transfer.h>
-#include <dev/usb/usb_device.h>
-#include <dev/usb/usb_debug.h>
-
-#include <dev/usb/usb_controller.h>
-#include <dev/usb/usb_bus.h>
-
-/*------------------------------------------------------------------------*
- * usb2_sw_transfer - factored out code
- *
- * This function is basically used for the Virtual Root HUB, and can
- * emulate control, bulk and interrupt endpoints. Data is exchanged
- * using the "std->ptr" and "std->len" fields, that allows kernel
- * virtual memory to be transferred. All state is kept in the
- * structure pointed to by the "std" argument passed to this
- * function. The "func" argument points to a function that is called
- * back in the various states, so that the application using this
- * function can get a chance to select the outcome. The "func"
- * function is allowed to sleep, exiting all mutexes. If this function
- * will sleep the "enter" and "start" methods must be marked
- * non-cancelable, hence there is no extra cancelled checking in this
- * function.
- *------------------------------------------------------------------------*/
-void
-usb2_sw_transfer(struct usb2_sw_transfer *std,
- usb2_sw_transfer_func_t *func)
-{
- struct usb2_xfer *xfer;
- uint32_t len;
- uint8_t shortpkt = 0;
-
- xfer = std->xfer;
- if (xfer == NULL) {
- /* the transfer is gone */
- DPRINTF("xfer gone\n");
- return;
- }
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
-
- std->xfer = NULL;
-
- /* check for control transfer */
- if (xfer->flags_int.control_xfr) {
- /* check if we are transferring the SETUP packet */
- if (xfer->flags_int.control_hdr) {
-
- /* copy out the USB request */
-
- if (xfer->frlengths[0] == sizeof(std->req)) {
- usb2_copy_out(xfer->frbuffers, 0,
- &std->req, sizeof(std->req));
- } else {
- std->err = USB_ERR_INVAL;
- goto done;
- }
-
- xfer->aframes = 1;
-
- std->err = 0;
- std->state = USB_SW_TR_SETUP;
-
- (func) (xfer, std);
-
- if (std->err) {
- goto done;
- }
- } else {
- /* skip the first frame in this case */
- xfer->aframes = 1;
- }
- }
- std->err = 0;
- std->state = USB_SW_TR_PRE_DATA;
-
- (func) (xfer, std);
-
- if (std->err) {
- goto done;
- }
- /* Transfer data. Iterate accross all frames. */
- while (xfer->aframes != xfer->nframes) {
-
- len = xfer->frlengths[xfer->aframes];
-
- if (len > std->len) {
- len = std->len;
- shortpkt = 1;
- }
- if (len > 0) {
- if ((xfer->endpoint & (UE_DIR_IN | UE_DIR_OUT)) == UE_DIR_IN) {
- usb2_copy_in(xfer->frbuffers + xfer->aframes, 0,
- std->ptr, len);
- } else {
- usb2_copy_out(xfer->frbuffers + xfer->aframes, 0,
- std->ptr, len);
- }
- }
- std->ptr += len;
- std->len -= len;
- xfer->frlengths[xfer->aframes] = len;
- xfer->aframes++;
-
- if (shortpkt) {
- break;
- }
- }
-
- std->err = 0;
- std->state = USB_SW_TR_POST_DATA;
-
- (func) (xfer, std);
-
- if (std->err) {
- goto done;
- }
- /* check if the control transfer is complete */
- if (xfer->flags_int.control_xfr &&
- !xfer->flags_int.control_act) {
-
- std->err = 0;
- std->state = USB_SW_TR_STATUS;
-
- (func) (xfer, std);
-
- if (std->err) {
- goto done;
- }
- }
-done:
- DPRINTF("done err=%s\n", usb2_errstr(std->err));
- std->state = USB_SW_TR_PRE_CALLBACK;
- (func) (xfer, std);
-}
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index 71bbb08..41b07f1 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -22,12 +22,11 @@
* 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 <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb.h>
-#include <dev/usb/usb_defs.h>
#define USB_DEBUG_VAR usb2_debug
@@ -51,45 +50,7 @@ struct usb2_std_packet_size {
uint16_t fixed[4];
};
-/*
- * This table stores the all the allowed packet sizes based on
- * endpoint type and USB speed:
- */
-static const struct usb2_std_packet_size
- usb2_std_packet_size[4][USB_SPEED_MAX] = {
-
- [UE_INTERRUPT] = {
- [USB_SPEED_LOW] = {.range = {0, 8}},
- [USB_SPEED_FULL] = {.range = {0, 64}},
- [USB_SPEED_HIGH] = {.range = {0, 1024}},
- [USB_SPEED_VARIABLE] = {.range = {0, 1024}},
- [USB_SPEED_SUPER] = {.range = {0, 1024}},
- },
-
- [UE_CONTROL] = {
- [USB_SPEED_LOW] = {.fixed = {8, 8, 8, 8}},
- [USB_SPEED_FULL] = {.fixed = {8, 16, 32, 64}},
- [USB_SPEED_HIGH] = {.fixed = {64, 64, 64, 64}},
- [USB_SPEED_VARIABLE] = {.fixed = {512, 512, 512, 512}},
- [USB_SPEED_SUPER] = {.fixed = {512, 512, 512, 512}},
- },
-
- [UE_BULK] = {
- [USB_SPEED_LOW] = {.fixed = {0, 0, 0, 0}}, /* invalid */
- [USB_SPEED_FULL] = {.fixed = {8, 16, 32, 64}},
- [USB_SPEED_HIGH] = {.fixed = {512, 512, 512, 512}},
- [USB_SPEED_VARIABLE] = {.fixed = {512, 512, 1024, 1536}},
- [USB_SPEED_SUPER] = {.fixed = {1024, 1024, 1024, 1024}},
- },
-
- [UE_ISOCHRONOUS] = {
- [USB_SPEED_LOW] = {.fixed = {0, 0, 0, 0}}, /* invalid */
- [USB_SPEED_FULL] = {.range = {0, 1023}},
- [USB_SPEED_HIGH] = {.range = {0, 1024}},
- [USB_SPEED_VARIABLE] = {.range = {0, 3584}},
- [USB_SPEED_SUPER] = {.range = {0, 1024}},
- },
-};
+static usb2_callback_t usb2_request_callback;
static const struct usb2_config usb2_control_ep_cfg[USB_DEFAULT_XFER_MAX] = {
@@ -99,12 +60,10 @@ static const struct usb2_config usb2_control_ep_cfg[USB_DEFAULT_XFER_MAX] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control endpoint */
.direction = UE_DIR_ANY,
- .mh.bufsize = 1024, /* bytes */
- .mh.flags = {.proxy_buffer = 1,.short_xfer_ok = 1,},
- .mh.callback = &usb2_do_request_callback,
- .md.bufsize = 1024, /* bytes */
- .md.flags = {.proxy_buffer = 1,.short_xfer_ok = 0,},
- .md.callback = &usb2_handle_request_callback,
+ .bufsize = USB_EP0_BUFSIZE, /* bytes */
+ .flags = {.proxy_buffer = 1,},
+ .callback = &usb2_request_callback,
+ .usb_mode = USB_MODE_MAX, /* both modes */
},
/* This transfer is used for generic clear stall only */
@@ -113,11 +72,11 @@ static const struct usb2_config usb2_control_ep_cfg[USB_DEFAULT_XFER_MAX] = {
.type = UE_CONTROL,
.endpoint = 0x00, /* Control pipe */
.direction = UE_DIR_ANY,
- .mh.bufsize = sizeof(struct usb2_device_request),
- .mh.flags = {},
- .mh.callback = &usb2_do_clear_stall_callback,
- .mh.timeout = 1000, /* 1 second */
- .mh.interval = 50, /* 50ms */
+ .bufsize = sizeof(struct usb2_device_request),
+ .callback = &usb2_do_clear_stall_callback,
+ .timeout = 1000, /* 1 second */
+ .interval = 50, /* 50ms */
+ .usb_mode = USB_MODE_HOST,
},
};
@@ -133,6 +92,20 @@ static void usb2_callback_wrapper(struct usb2_xfer_queue *);
static void usb2_dma_delay_done_cb(void *);
static void usb2_transfer_start_cb(void *);
static uint8_t usb2_callback_wrapper_sub(struct usb2_xfer *);
+static void usb2_get_std_packet_size(struct usb2_std_packet_size *ptr,
+ uint8_t type, uint8_t usb_speed);
+
+/*------------------------------------------------------------------------*
+ * usb2_request_callback
+ *------------------------------------------------------------------------*/
+static void
+usb2_request_callback(struct usb2_xfer *xfer)
+{
+ if (xfer->flags_int.usb2_mode == USB_MODE_DEVICE)
+ usb2_handle_request_callback(xfer);
+ else
+ usb2_do_request_callback(xfer);
+}
/*------------------------------------------------------------------------*
* usb2_update_max_frame_size
@@ -164,7 +137,7 @@ usb2_update_max_frame_size(struct usb2_xfer *xfer)
* 0: no DMA delay required
* Else: milliseconds of DMA delay
*------------------------------------------------------------------------*/
-uint32_t
+usb2_timeout_t
usb2_get_dma_delay(struct usb2_bus *bus)
{
uint32_t temp = 0;
@@ -192,20 +165,21 @@ usb2_get_dma_delay(struct usb2_bus *bus)
* 0: Success
* Else: Failure
*------------------------------------------------------------------------*/
+#if USB_HAVE_BUSDMA
uint8_t
usb2_transfer_setup_sub_malloc(struct usb2_setup_params *parm,
- struct usb2_page_cache **ppc, uint32_t size, uint32_t align,
- uint32_t count)
+ struct usb2_page_cache **ppc, usb2_size_t size, usb2_size_t align,
+ usb2_size_t count)
{
struct usb2_page_cache *pc;
struct usb2_page *pg;
void *buf;
- uint32_t n_dma_pc;
- uint32_t n_obj;
- uint32_t x;
- uint32_t y;
- uint32_t r;
- uint32_t z;
+ usb2_size_t n_dma_pc;
+ usb2_size_t n_obj;
+ usb2_size_t x;
+ usb2_size_t y;
+ usb2_size_t r;
+ usb2_size_t z;
USB_ASSERT(align > 1, ("Invalid alignment, 0x%08x!\n",
align));
@@ -302,6 +276,7 @@ usb2_transfer_setup_sub_malloc(struct usb2_setup_params *parm,
parm->dma_page_ptr = pg;
return (0);
}
+#endif
/*------------------------------------------------------------------------*
* usb2_transfer_setup_sub - transfer setup subroutine
@@ -320,12 +295,12 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
MIN_PKT = 8,
};
struct usb2_xfer *xfer = parm->curr_xfer;
- const struct usb2_config_sub *setup_sub = parm->curr_setup_sub;
+ const struct usb2_config *setup = parm->curr_setup;
struct usb2_endpoint_descriptor *edesc;
struct usb2_std_packet_size std_size;
- uint32_t n_frlengths;
- uint32_t n_frbuffers;
- uint32_t x;
+ usb2_frcount_t n_frlengths;
+ usb2_frcount_t n_frbuffers;
+ usb2_frcount_t x;
uint8_t type;
uint8_t zmps;
@@ -343,18 +318,18 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
type = (edesc->bmAttributes & UE_XFERTYPE);
- xfer->flags = setup_sub->flags;
- xfer->nframes = setup_sub->frames;
- xfer->timeout = setup_sub->timeout;
- xfer->callback = setup_sub->callback;
- xfer->interval = setup_sub->interval;
+ xfer->flags = setup->flags;
+ xfer->nframes = setup->frames;
+ xfer->timeout = setup->timeout;
+ xfer->callback = setup->callback;
+ xfer->interval = setup->interval;
xfer->endpoint = edesc->bEndpointAddress;
xfer->max_packet_size = UGETW(edesc->wMaxPacketSize);
xfer->max_packet_count = 1;
/* make a shadow copy: */
xfer->flags_int.usb2_mode = parm->udev->flags.usb2_mode;
- parm->bufsize = setup_sub->bufsize;
+ parm->bufsize = setup->bufsize;
if (parm->speed == USB_SPEED_HIGH) {
xfer->max_packet_count += (xfer->max_packet_size >> 11) & 3;
@@ -373,7 +348,7 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
}
/* filter "wMaxPacketSize" according to standard sizes */
- std_size = usb2_std_packet_size[type][parm->speed];
+ usb2_get_std_packet_size(&std_size, type, parm->speed);
if (std_size.range.min || std_size.range.max) {
@@ -405,7 +380,7 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
if (type == UE_ISOCHRONOUS) {
- uint32_t frame_limit;
+ uint16_t frame_limit;
xfer->interval = 0; /* not used, must be zero */
xfer->flags_int.isochronous_xfr = 1; /* set flag */
@@ -644,6 +619,7 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
if (parm->bufsize_max < parm->bufsize) {
parm->bufsize_max = parm->bufsize;
}
+#if USB_HAVE_BUSDMA
if (xfer->flags_int.bdma_enable) {
/*
* Setup "dma_page_ptr".
@@ -671,17 +647,18 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
parm->dma_page_ptr += (2 * n_frbuffers);
parm->dma_page_ptr += (parm->bufsize / USB_PAGE_SIZE);
}
+#endif
if (zmps) {
/* correct maximum data length */
xfer->max_data_length = 0;
}
/* subtract USB frame remainder from "hc_max_frame_size" */
- xfer->max_usb2_frame_size =
+ xfer->max_hc_frame_size =
(parm->hc_max_frame_size -
(parm->hc_max_frame_size % xfer->max_frame_size));
- if (xfer->max_usb2_frame_size == 0) {
+ if (xfer->max_hc_frame_size == 0) {
parm->err = USB_ERR_INVAL;
goto done;
}
@@ -695,7 +672,7 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
for (x = 0; x != n_frbuffers; x++) {
xfer->frbuffers[x].tag_parent =
&xfer->xroot->dma_parent_tag;
-
+#if USB_HAVE_BUSDMA
if (xfer->flags_int.bdma_enable &&
(parm->bufsize_max > 0)) {
@@ -706,6 +683,7 @@ usb2_transfer_setup_sub(struct usb2_setup_params *parm)
goto done;
}
}
+#endif
}
}
done:
@@ -713,7 +691,7 @@ done:
/*
* Set some dummy values so that we avoid division by zero:
*/
- xfer->max_usb2_frame_size = 1;
+ xfer->max_hc_frame_size = 1;
xfer->max_frame_size = 1;
xfer->max_packet_size = 1;
xfer->max_data_length = 0;
@@ -776,13 +754,11 @@ usb2_transfer_setup(struct usb2_device *udev,
/* sanity checks */
for (setup = setup_start, n = 0;
setup != setup_end; setup++, n++) {
- if ((setup->mh.bufsize == 0xffffffff) ||
- (setup->md.bufsize == 0xffffffff)) {
+ if (setup->bufsize == (usb2_frlength_t)-1) {
parm.err = USB_ERR_BAD_BUFSIZE;
DPRINTF("invalid bufsize\n");
}
- if ((setup->mh.callback == NULL) &&
- (setup->md.callback == NULL)) {
+ if (setup->callback == NULL) {
parm.err = USB_ERR_NO_CALLBACK;
DPRINTF("no callback\n");
}
@@ -816,28 +792,31 @@ usb2_transfer_setup(struct usb2_device *udev,
info->memory_base = buf;
info->memory_size = parm.size[0];
+#if USB_HAVE_BUSDMA
info->dma_page_cache_start = USB_ADD_BYTES(buf, parm.size[4]);
info->dma_page_cache_end = USB_ADD_BYTES(buf, parm.size[5]);
+#endif
info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm.size[5]);
info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm.size[2]);
usb2_cv_init(&info->cv_drain, "WDRAIN");
info->xfer_mtx = xfer_mtx;
-
+#if USB_HAVE_BUSDMA
usb2_dma_tag_setup(&info->dma_parent_tag,
parm.dma_tag_p, udev->bus->dma_parent_tag[0].tag,
- xfer_mtx, &usb2_bdma_done_event, info, 32, parm.dma_tag_max);
+ xfer_mtx, &usb2_bdma_done_event, 32, parm.dma_tag_max);
+#endif
info->bus = udev->bus;
info->udev = udev;
TAILQ_INIT(&info->done_q.head);
info->done_q.command = &usb2_callback_wrapper;
-
+#if USB_HAVE_BUSDMA
TAILQ_INIT(&info->dma_q.head);
info->dma_q.command = &usb2_bdma_work_loop;
-
+#endif
info->done_m[0].hdr.pm_callback = &usb2_callback_proc;
info->done_m[0].xroot = info;
info->done_m[1].hdr.pm_callback = &usb2_callback_proc;
@@ -859,33 +838,30 @@ usb2_transfer_setup(struct usb2_device *udev,
for (setup = setup_start, n = 0;
setup != setup_end; setup++, n++) {
- /* select mode specific structure */
- if (udev->flags.usb2_mode == USB_MODE_HOST) {
- parm.curr_setup_sub = &setup->mh;
- } else {
- parm.curr_setup_sub = &setup->md;
- }
/* skip USB transfers without callbacks: */
- if (parm.curr_setup_sub->callback == NULL) {
+ if (setup->callback == NULL) {
continue;
}
/* see if there is a matching endpoint */
pipe = usb2_get_pipe(udev,
ifaces[setup->if_index], setup);
- if (!pipe) {
- if (parm.curr_setup_sub->flags.no_pipe_ok) {
+ if ((pipe == NULL) || (pipe->methods == NULL)) {
+ if (setup->flags.no_pipe_ok)
+ continue;
+ if ((setup->usb_mode != USB_MODE_MAX) &&
+ (setup->usb_mode != udev->flags.usb2_mode))
continue;
- }
parm.err = USB_ERR_NO_PIPE;
goto done;
}
- /* store current setup pointer */
- parm.curr_setup = setup;
/* align data properly */
parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1));
+ /* store current setup pointer */
+ parm.curr_setup = setup;
+
if (buf) {
/*
* Common initialization of the
@@ -1068,13 +1044,13 @@ static void
usb2_transfer_unsetup_sub(struct usb2_xfer_root *info, uint8_t needs_delay)
{
struct usb2_page_cache *pc;
- uint32_t temp;
USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
/* wait for any outstanding DMA operations */
if (needs_delay) {
+ usb2_timeout_t temp;
temp = usb2_get_dma_delay(info->bus);
usb2_pause_mtx(&info->bus->bus_mtx,
USB_MS_TO_TICKS(temp));
@@ -1085,6 +1061,7 @@ usb2_transfer_unsetup_sub(struct usb2_xfer_root *info, uint8_t needs_delay)
USB_BUS_UNLOCK(info->bus);
+#if USB_HAVE_BUSDMA
/* free DMA'able memory, if any */
pc = info->dma_page_cache_start;
while (pc != info->dma_page_cache_end) {
@@ -1101,6 +1078,7 @@ usb2_transfer_unsetup_sub(struct usb2_xfer_root *info, uint8_t needs_delay)
/* free all DMA tags */
usb2_dma_tag_unsetup(&info->dma_parent_tag);
+#endif
usb2_cv_destroy(&info->cv_drain);
@@ -1162,9 +1140,10 @@ usb2_transfer_unsetup(struct usb2_xfer **pxfer, uint16_t n_setup)
usb2_transfer_drain(xfer);
+#if USB_HAVE_BUSDMA
if (xfer->flags_int.bdma_enable)
needs_delay = 1;
-
+#endif
/*
* NOTE: default pipe does not have an
* interface, even if pipe->iface_index == 0
@@ -1234,13 +1213,27 @@ usb2_control_transfer_init(struct usb2_xfer *xfer)
static uint8_t
usb2_start_hardware_sub(struct usb2_xfer *xfer)
{
- uint32_t len;
+ usb2_frlength_t len;
/* Check for control endpoint stall */
if (xfer->flags.stall_pipe) {
/* no longer active */
xfer->flags_int.control_act = 0;
}
+
+ /* Check for invalid number of frames */
+ if (xfer->nframes > 2) {
+ /*
+ * If you need to split a control transfer, you
+ * have to do one part at a time. Only with
+ * non-control transfers you can do multiple
+ * parts a time.
+ */
+ DPRINTFN(0, "Too many frames: %u\n",
+ (unsigned int)xfer->nframes);
+ goto error;
+ }
+
/*
* Check if there is a control
* transfer in progress:
@@ -1363,7 +1356,7 @@ error:
void
usb2_start_hardware(struct usb2_xfer *xfer)
{
- uint32_t x;
+ usb2_frcount_t x;
DPRINTF("xfer=%p, pipe=%p, nframes=%d, dir=%s\n",
xfer, xfer->pipe, xfer->nframes, USB_GET_DATA_ISREAD(xfer) ?
@@ -1395,9 +1388,10 @@ usb2_start_hardware(struct usb2_xfer *xfer)
/* set "transferring" flag */
xfer->flags_int.transferring = 1;
+#if USB_HAVE_POWERD
/* increment power reference */
usb2_transfer_power_ref(xfer, 1);
-
+#endif
/*
* Check if the transfer is waiting on a queue, most
* frequently the "done_q":
@@ -1413,9 +1407,10 @@ usb2_start_hardware(struct usb2_xfer *xfer)
/* clear "did_close" flag */
xfer->flags_int.did_close = 0;
+#if USB_HAVE_BUSDMA
/* clear "bdma_setup" flag */
xfer->flags_int.bdma_setup = 0;
-
+#endif
/* by default we cannot cancel any USB transfer immediately */
xfer->flags_int.can_cancel_immed = 0;
@@ -1484,23 +1479,28 @@ usb2_start_hardware(struct usb2_xfer *xfer)
*/
if (USB_GET_DATA_ISREAD(xfer)) {
- if (xfer->flags_int.control_xfr) {
-
- /*
- * Control transfers do not support reception
- * of multiple short USB frames !
- */
-
- if (xfer->flags.short_xfer_ok) {
- xfer->flags_int.short_xfer_ok = 1;
- }
- } else {
+ if (xfer->flags.short_frames_ok) {
+ xfer->flags_int.short_xfer_ok = 1;
+ xfer->flags_int.short_frames_ok = 1;
+ } else if (xfer->flags.short_xfer_ok) {
+ xfer->flags_int.short_xfer_ok = 1;
- if (xfer->flags.short_frames_ok) {
- xfer->flags_int.short_xfer_ok = 1;
+ /* check for control transfer */
+ if (xfer->flags_int.control_xfr) {
+ /*
+ * 1) Control transfers do not support
+ * reception of multiple short USB
+ * frames in host mode and device side
+ * mode, with exception of:
+ *
+ * 2) Due to sometimes buggy device
+ * side firmware we need to do a
+ * STATUS stage in case of short
+ * control transfers in USB host mode.
+ * The STATUS stage then becomes the
+ * "alt_next" to the DATA stage.
+ */
xfer->flags_int.short_frames_ok = 1;
- } else if (xfer->flags.short_xfer_ok) {
- xfer->flags_int.short_xfer_ok = 1;
}
}
}
@@ -1508,11 +1508,13 @@ usb2_start_hardware(struct usb2_xfer *xfer)
* Check if BUS-DMA support is enabled and try to load virtual
* buffers into DMA, if any:
*/
+#if USB_HAVE_BUSDMA
if (xfer->flags_int.bdma_enable) {
/* insert the USB transfer last in the BUS-DMA queue */
usb2_command_wrapper(&xfer->xroot->dma_q, xfer);
return;
}
+#endif
/*
* Enter the USB transfer into the Host Controller or
* Device Controller schedule:
@@ -1539,18 +1541,14 @@ usb2_pipe_enter(struct usb2_xfer *xfer)
/* enter the transfer */
(pipe->methods->enter) (xfer);
- /* check cancelability */
- if (pipe->methods->enter_is_cancelable) {
- xfer->flags_int.can_cancel_immed = 1;
- /* check for transfer error */
- if (xfer->error) {
- /* some error has happened */
- usb2_transfer_done(xfer, 0);
- USB_BUS_UNLOCK(xfer->xroot->bus);
- return;
- }
- } else {
- xfer->flags_int.can_cancel_immed = 0;
+ xfer->flags_int.can_cancel_immed = 1;
+
+ /* check for transfer error */
+ if (xfer->error) {
+ /* some error has happened */
+ usb2_transfer_done(xfer, 0);
+ USB_BUS_UNLOCK(xfer->xroot->bus);
+ return;
}
/* start the transfer */
@@ -1762,7 +1760,7 @@ usb2_transfer_drain(struct usb2_xfer *xfer)
* than zero gives undefined results!
*------------------------------------------------------------------------*/
void
-usb2_set_frame_data(struct usb2_xfer *xfer, void *ptr, uint32_t frindex)
+usb2_set_frame_data(struct usb2_xfer *xfer, void *ptr, usb2_frcount_t frindex)
{
/* set virtual address to load and length */
xfer->frbuffers[frindex].buffer = ptr;
@@ -1775,8 +1773,8 @@ usb2_set_frame_data(struct usb2_xfer *xfer, void *ptr, uint32_t frindex)
* of the USB DMA buffer allocated for this USB transfer.
*------------------------------------------------------------------------*/
void
-usb2_set_frame_offset(struct usb2_xfer *xfer, uint32_t offset,
- uint32_t frindex)
+usb2_set_frame_offset(struct usb2_xfer *xfer, usb2_frlength_t offset,
+ usb2_frcount_t frindex)
{
USB_ASSERT(!xfer->flags.ext_buffer, ("Cannot offset data frame "
"when the USB buffer is external!\n"));
@@ -1864,8 +1862,8 @@ usb2_callback_wrapper(struct usb2_xfer_queue *pq)
struct usb2_xfer *xfer = pq->curr;
struct usb2_xfer_root *info = xfer->xroot;
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
- if (!mtx_owned(xfer->xroot->xfer_mtx)) {
+ USB_BUS_LOCK_ASSERT(info->bus, MA_OWNED);
+ if (!mtx_owned(info->xfer_mtx)) {
/*
* Cases that end up here:
*
@@ -1896,27 +1894,28 @@ usb2_callback_wrapper(struct usb2_xfer_queue *pq)
/* get next USB transfer in the queue */
info->done_q.curr = NULL;
- USB_BUS_UNLOCK(xfer->xroot->bus);
- USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_NOTOWNED);
+ USB_BUS_UNLOCK(info->bus);
+ USB_BUS_LOCK_ASSERT(info->bus, MA_NOTOWNED);
/* set correct USB state for callback */
if (!xfer->flags_int.transferring) {
xfer->usb2_state = USB_ST_SETUP;
if (!xfer->flags_int.started) {
/* we got stopped before we even got started */
- USB_BUS_LOCK(xfer->xroot->bus);
+ USB_BUS_LOCK(info->bus);
goto done;
}
} else {
if (usb2_callback_wrapper_sub(xfer)) {
/* the callback has been deferred */
- USB_BUS_LOCK(xfer->xroot->bus);
+ USB_BUS_LOCK(info->bus);
goto done;
}
+#if USB_HAVE_POWERD
/* decrement power reference */
usb2_transfer_power_ref(xfer, -1);
-
+#endif
xfer->flags_int.transferring = 0;
if (xfer->error) {
@@ -1924,12 +1923,13 @@ usb2_callback_wrapper(struct usb2_xfer_queue *pq)
} else {
/* set transferred state */
xfer->usb2_state = USB_ST_TRANSFERRED;
-
+#if USB_HAVE_BUSDMA
/* sync DMA memory, if any */
if (xfer->flags_int.bdma_enable &&
(!xfer->flags_int.bdma_no_post_sync)) {
usb2_bdma_post_sync(xfer);
}
+#endif
}
}
@@ -1937,7 +1937,7 @@ usb2_callback_wrapper(struct usb2_xfer_queue *pq)
(xfer->callback) (xfer);
/* pickup the USB mutex again */
- USB_BUS_LOCK(xfer->xroot->bus);
+ USB_BUS_LOCK(info->bus);
/*
* Check if we got started after that we got cancelled, but
@@ -1959,7 +1959,7 @@ done:
(!xfer->flags_int.transferring)) {
/* "usb2_transfer_drain()" is waiting for end of transfer */
xfer->flags_int.draining = 0;
- usb2_cv_broadcast(&xfer->xroot->cv_drain);
+ usb2_cv_broadcast(&info->cv_drain);
}
/* do the next callback, if any */
@@ -2043,8 +2043,6 @@ usb2_transfer_enqueue(struct usb2_xfer_queue *pq, struct usb2_xfer *xfer)
void
usb2_transfer_done(struct usb2_xfer *xfer, usb2_error_t error)
{
- struct usb2_xfer_queue *pq;
-
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
DPRINTF("err=%s\n", usb2_errstr(error));
@@ -2071,7 +2069,10 @@ usb2_transfer_done(struct usb2_xfer *xfer, usb2_error_t error)
*/
usb2_transfer_dequeue(xfer);
+#if USB_HAVE_BUSDMA
if (mtx_owned(xfer->xroot->xfer_mtx)) {
+ struct usb2_xfer_queue *pq;
+
/*
* If the private USB lock is not locked, then we assume
* that the BUS-DMA load stage has been passed:
@@ -2083,6 +2084,7 @@ usb2_transfer_done(struct usb2_xfer *xfer, usb2_error_t error)
usb2_command_wrapper(pq, NULL);
}
}
+#endif
/* keep some statistics */
if (xfer->error) {
xfer->xroot->bus->stats_err.uds_requests
@@ -2116,15 +2118,12 @@ usb2_transfer_start_cb(void *arg)
/* start the transfer */
(pipe->methods->start) (xfer);
- /* check cancelability */
- if (pipe->methods->start_is_cancelable) {
- xfer->flags_int.can_cancel_immed = 1;
- if (xfer->error) {
- /* some error has happened */
- usb2_transfer_done(xfer, 0);
- }
- } else {
- xfer->flags_int.can_cancel_immed = 0;
+ xfer->flags_int.can_cancel_immed = 1;
+
+ /* check for error */
+ if (xfer->error) {
+ /* some error has happened */
+ usb2_transfer_done(xfer, 0);
}
}
@@ -2270,15 +2269,12 @@ usb2_pipe_start(struct usb2_xfer_queue *pq)
/* start USB transfer */
(pipe->methods->start) (xfer);
- /* check cancelability */
- if (pipe->methods->start_is_cancelable) {
- xfer->flags_int.can_cancel_immed = 1;
- if (xfer->error) {
- /* some error has happened */
- usb2_transfer_done(xfer, 0);
- }
- } else {
- xfer->flags_int.can_cancel_immed = 0;
+ xfer->flags_int.can_cancel_immed = 1;
+
+ /* check for error */
+ if (xfer->error) {
+ /* some error has happened */
+ usb2_transfer_done(xfer, 0);
}
}
@@ -2291,7 +2287,7 @@ usb2_pipe_start(struct usb2_xfer_queue *pq)
*------------------------------------------------------------------------*/
void
usb2_transfer_timeout_ms(struct usb2_xfer *xfer,
- void (*cb) (void *arg), uint32_t ms)
+ void (*cb) (void *arg), usb2_timeout_t ms)
{
USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_OWNED);
@@ -2321,7 +2317,7 @@ static uint8_t
usb2_callback_wrapper_sub(struct usb2_xfer *xfer)
{
struct usb2_pipe *pipe;
- uint32_t x;
+ usb2_frcount_t x;
if ((!xfer->flags_int.open) &&
(!xfer->flags_int.did_close)) {
@@ -2341,7 +2337,7 @@ usb2_callback_wrapper_sub(struct usb2_xfer *xfer)
(xfer->error == USB_ERR_TIMEOUT)) &&
(!xfer->flags_int.did_dma_delay)) {
- uint32_t temp;
+ usb2_timeout_t temp;
/* only delay once */
xfer->flags_int.did_dma_delay = 1;
@@ -2541,6 +2537,9 @@ usb2_default_transfer_setup(struct usb2_device *udev)
uint8_t no_resetup;
uint8_t iface_index;
+ /* check for root HUB */
+ if (udev->parent_hub == NULL)
+ return;
repeat:
xfer = udev->default_xfer[0];
@@ -2635,9 +2634,9 @@ usb2_clear_data_toggle(struct usb2_device *udev, struct usb2_pipe *pipe)
* .direction = UE_DIR_ANY,
* .interval = 50, //50 milliseconds
* .bufsize = sizeof(struct usb2_device_request),
- * .mh.timeout = 1000, //1.000 seconds
- * .mh.flags = { },
- * .mh.callback = &my_clear_stall_callback, // **
+ * .timeout = 1000, //1.000 seconds
+ * .callback = &my_clear_stall_callback, // **
+ * .usb_mode = USB_MODE_HOST,
* };
*
* ** "my_clear_stall_callback" calls "usb2_clear_stall_callback"
@@ -2716,3 +2715,78 @@ usb2_do_poll(struct usb2_xfer **ppxfer, uint16_t max)
"not supported!\n");
}
}
+
+static void
+usb2_get_std_packet_size(struct usb2_std_packet_size *ptr,
+ uint8_t type, uint8_t usb_speed)
+{
+ static const uint16_t intr_range_max[USB_SPEED_MAX] = {
+ [USB_SPEED_LOW] = 8,
+ [USB_SPEED_FULL] = 64,
+ [USB_SPEED_HIGH] = 1024,
+ [USB_SPEED_VARIABLE] = 1024,
+ [USB_SPEED_SUPER] = 1024,
+ };
+
+ static const uint16_t isoc_range_max[USB_SPEED_MAX] = {
+ [USB_SPEED_LOW] = 0, /* invalid */
+ [USB_SPEED_FULL] = 1023,
+ [USB_SPEED_HIGH] = 1024,
+ [USB_SPEED_VARIABLE] = 3584,
+ [USB_SPEED_SUPER] = 1024,
+ };
+
+ static const uint16_t control_min[USB_SPEED_MAX] = {
+ [USB_SPEED_LOW] = 8,
+ [USB_SPEED_FULL] = 8,
+ [USB_SPEED_HIGH] = 64,
+ [USB_SPEED_VARIABLE] = 512,
+ [USB_SPEED_SUPER] = 512,
+ };
+
+ static const uint16_t bulk_min[USB_SPEED_MAX] = {
+ [USB_SPEED_LOW] = 0, /* not supported */
+ [USB_SPEED_FULL] = 8,
+ [USB_SPEED_HIGH] = 512,
+ [USB_SPEED_VARIABLE] = 512,
+ [USB_SPEED_SUPER] = 1024,
+ };
+
+ uint16_t temp;
+
+ memset(ptr, 0, sizeof(*ptr));
+
+ switch (type) {
+ case UE_INTERRUPT:
+ ptr->range.max = intr_range_max[usb_speed];
+ break;
+ case UE_ISOCHRONOUS:
+ ptr->range.max = isoc_range_max[usb_speed];
+ break;
+ default:
+ if (type == UE_BULK)
+ temp = bulk_min[usb_speed];
+ else /* UE_CONTROL */
+ temp = control_min[usb_speed];
+
+ /* default is fixed */
+ ptr->fixed[0] = temp;
+ ptr->fixed[1] = temp;
+ ptr->fixed[2] = temp;
+ ptr->fixed[3] = temp;
+
+ if (usb_speed == USB_SPEED_FULL) {
+ /* multiple sizes */
+ ptr->fixed[1] = 16;
+ ptr->fixed[2] = 32;
+ ptr->fixed[3] = 64;
+ }
+ if ((usb_speed == USB_SPEED_VARIABLE) &&
+ (type == UE_BULK)) {
+ /* multiple sizes */
+ ptr->fixed[2] = 1024;
+ ptr->fixed[3] = 1536;
+ }
+ break;
+ }
+}
diff --git a/sys/dev/usb/usb_transfer.h b/sys/dev/usb/usb_transfer.h
index 34124c5..a15e8a3 100644
--- a/sys/dev/usb/usb_transfer.h
+++ b/sys/dev/usb/usb_transfer.h
@@ -36,36 +36,46 @@ struct usb2_done_msg {
struct usb2_xfer_root *xroot;
};
+#define USB_DMATAG_TO_XROOT(dpt) \
+ ((struct usb2_xfer_root *)( \
+ ((uint8_t *)(dpt)) - \
+ ((uint8_t *)&((struct usb2_xfer_root *)0)->dma_parent_tag)))
+
/*
* The following structure is used to keep information about memory
* that should be automatically freed at the moment all USB transfers
* have been freed.
*/
struct usb2_xfer_root {
+ struct usb2_dma_parent_tag dma_parent_tag;
+#if USB_HAVE_BUSDMA
struct usb2_xfer_queue dma_q;
+#endif
struct usb2_xfer_queue done_q;
struct usb2_done_msg done_m[2];
struct cv cv_drain;
- struct usb2_dma_parent_tag dma_parent_tag;
struct usb2_process *done_p; /* pointer to callback process */
void *memory_base;
struct mtx *xfer_mtx; /* cannot be changed during operation */
+#if USB_HAVE_BUSDMA
struct usb2_page_cache *dma_page_cache_start;
struct usb2_page_cache *dma_page_cache_end;
+#endif
struct usb2_page_cache *xfer_page_cache_start;
struct usb2_page_cache *xfer_page_cache_end;
struct usb2_bus *bus; /* pointer to USB bus (cached) */
struct usb2_device *udev; /* pointer to USB device */
- uint32_t memory_size;
- uint32_t setup_refcount;
- uint32_t page_size;
- uint32_t dma_nframes; /* number of page caches to load */
- uint32_t dma_currframe; /* currect page cache number */
- uint32_t dma_frlength_0; /* length of page cache zero */
+ usb2_size_t memory_size;
+ usb2_size_t setup_refcount;
+#if USB_HAVE_BUSDMA
+ usb2_frcount_t dma_nframes; /* number of page caches to load */
+ usb2_frcount_t dma_currframe; /* currect page cache number */
+ usb2_frlength_t dma_frlength_0; /* length of page cache zero */
uint8_t dma_error; /* set if virtual memory could not be
* loaded */
+#endif
uint8_t done_sleep; /* set if done thread is sleeping */
};
@@ -83,16 +93,15 @@ struct usb2_setup_params {
struct usb2_device *udev;
struct usb2_xfer *curr_xfer;
const struct usb2_config *curr_setup;
- const struct usb2_config_sub *curr_setup_sub;
const struct usb2_pipe_methods *methods;
void *buf;
- uint32_t *xfer_length_ptr;
+ usb2_frlength_t *xfer_length_ptr;
- uint32_t size[7];
- uint32_t bufsize;
- uint32_t bufsize_max;
- uint32_t hc_max_frame_size;
+ usb2_size_t size[7];
+ usb2_frlength_t bufsize;
+ usb2_frlength_t bufsize_max;
+ uint16_t hc_max_frame_size;
uint16_t hc_max_packet_size;
uint8_t hc_max_packet_count;
uint8_t speed;
@@ -103,8 +112,8 @@ struct usb2_setup_params {
/* function prototypes */
uint8_t usb2_transfer_setup_sub_malloc(struct usb2_setup_params *parm,
- struct usb2_page_cache **ppc, uint32_t size, uint32_t align,
- uint32_t count);
+ struct usb2_page_cache **ppc, usb2_size_t size, usb2_size_t align,
+ usb2_size_t count);
void usb2_command_wrapper(struct usb2_xfer_queue *pq,
struct usb2_xfer *xfer);
void usb2_pipe_enter(struct usb2_xfer *xfer);
@@ -122,8 +131,8 @@ usb2_callback_t usb2_do_request_callback;
usb2_callback_t usb2_handle_request_callback;
usb2_callback_t usb2_do_clear_stall_callback;
void usb2_transfer_timeout_ms(struct usb2_xfer *xfer,
- void (*cb) (void *arg), uint32_t ms);
-uint32_t usb2_get_dma_delay(struct usb2_bus *bus);
+ void (*cb) (void *arg), usb2_timeout_t ms);
+usb2_timeout_t usb2_get_dma_delay(struct usb2_bus *bus);
void usb2_transfer_power_ref(struct usb2_xfer *xfer, int val);
#endif /* _USB2_TRANSFER_H_ */
diff --git a/sys/dev/usb/usb_util.c b/sys/dev/usb/usb_util.c
index 541cd55..5eba73c 100644
--- a/sys/dev/usb/usb_util.c
+++ b/sys/dev/usb/usb_util.c
@@ -24,7 +24,6 @@
* SUCH DAMAGE.
*/
-#include <dev/usb/usb_defs.h>
#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
#include <dev/usb/usb.h>
@@ -40,7 +39,7 @@
#include <dev/usb/usb_bus.h>
/* function prototypes */
-#if (USB_USE_CONDVAR == 0)
+#if (USB_HAVE_CONDVAR == 0)
static int usb2_msleep(void *chan, struct mtx *mtx, int priority, const char *wmesg, int timo);
#endif
@@ -48,6 +47,7 @@ static int usb2_msleep(void *chan, struct mtx *mtx, int priority, const char *wm
/*------------------------------------------------------------------------*
* device_delete_all_children - delete all children of a device
*------------------------------------------------------------------------*/
+#ifndef device_delete_all_children
int
device_delete_all_children(device_t dev)
{
@@ -67,6 +67,7 @@ device_delete_all_children(device_t dev)
}
return (error);
}
+#endif
/*------------------------------------------------------------------------*
* device_set_usb2_desc
@@ -77,6 +78,7 @@ device_delete_all_children(device_t dev)
void
device_set_usb2_desc(device_t dev)
{
+#if USB_HAVE_STRINGS
struct usb2_attach_arg *uaa;
struct usb2_device *udev;
struct usb2_interface *iface;
@@ -119,6 +121,7 @@ device_set_usb2_desc(device_t dev)
device_set_desc_copy(dev, temp_p);
device_printf(dev, "<%s> on %s\n", temp_p,
device_get_nameunit(udev->bus->bdev));
+#endif
}
/*------------------------------------------------------------------------*
@@ -178,6 +181,7 @@ usb2_printBCD(char *p, uint16_t p_len, uint16_t bcd)
* This function removes spaces at the beginning and the end of the string
* pointed to by the "p" argument.
*------------------------------------------------------------------------*/
+#if USB_HAVE_STRINGS
void
usb2_trim_spaces(char *p)
{
@@ -194,20 +198,7 @@ usb2_trim_spaces(char *p)
e = p;
*e = 0; /* kill trailing spaces */
}
-
-/*------------------------------------------------------------------------*
- * usb2_get_devid
- *
- * This function returns the USB Vendor and Product ID like a 32-bit
- * unsigned integer.
- *------------------------------------------------------------------------*/
-uint32_t
-usb2_get_devid(device_t dev)
-{
- struct usb2_attach_arg *uaa = device_get_ivars(dev);
-
- return ((uaa->info.idVendor << 16) | (uaa->info.idProduct));
-}
+#endif
/*------------------------------------------------------------------------*
* usb2_make_str_desc - convert an ASCII string into a UNICODE string
@@ -247,7 +238,7 @@ usb2_make_str_desc(void *ptr, uint16_t max_len, const char *s)
return (totlen);
}
-#if (USB_USE_CONDVAR == 0)
+#if (USB_HAVE_CONDVAR == 0)
/*------------------------------------------------------------------------*
* usb2_cv_init - wrapper function
diff --git a/sys/dev/usb/usb_util.h b/sys/dev/usb/usb_util.h
index e081c31..a265a44 100644
--- a/sys/dev/usb/usb_util.h
+++ b/sys/dev/usb/usb_util.h
@@ -28,14 +28,13 @@
#define _USB2_UTIL_H_
int device_delete_all_children(device_t dev);
-uint32_t usb2_get_devid(device_t dev);
uint8_t usb2_make_str_desc(void *ptr, uint16_t max_len, const char *s);
void device_set_usb2_desc(device_t dev);
void usb2_pause_mtx(struct mtx *mtx, int _ticks);
void usb2_printBCD(char *p, uint16_t p_len, uint16_t bcd);
void usb2_trim_spaces(char *p);
-#if (USB_USE_CONDVAR == 0)
+#if (USB_HAVE_CONDVAR == 0)
void usb2_cv_init(struct cv *cv, const char *desc);
void usb2_cv_destroy(struct cv *cv);
void usb2_cv_wait(struct cv *cv, struct mtx *mtx);
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index bec012e..2406ad4 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -593,6 +593,7 @@ vendor SILICOM 0x1485 Silicom
vendor RALINK 0x148f Ralink Technology
vendor IMAGINATION 0x149a Imagination Technologies
vendor CONCEPTRONIC2 0x14b2 Conceptronic
+vendor SUPERTOP 0x14cd Super Top
vendor PLANEX3 0x14ea Planex Communications
vendor SILICONPORTALS 0x1527 Silicon Portals
vendor UBIQUAM 0x1529 UBIQUAM Co., Ltd.
@@ -1632,6 +1633,7 @@ product LOGITECH QUICKCAMWEB 0x0801 QuickCam Web
product LOGITECH QUICKCAMPRO 0x0810 QuickCam Pro
product LOGITECH QUICKCAMEXP 0x0840 QuickCam Express
product LOGITECH QUICKCAM 0x0850 QuickCam
+product LOGITECH QUICKCAMPRO3 0x0990 QuickCam Pro 9000
product LOGITECH N43 0xc000 N43
product LOGITECH N48 0xc001 N48 mouse
product LOGITECH MBA47 0xc002 M-BA47 mouse
@@ -2025,6 +2027,7 @@ product PUTERCOM UPA100 0x047e USB-1284 BRIDGE
/* Qcom products */
product QCOM RT2573 0x6196 RT2573
product QCOM RT2573_2 0x6229 RT2573
+product QCOM RT2573_3 0x6238 RT2573
/* Qualcomm products */
product QUALCOMM CDMA_MSM 0x6000 CDMA Technologies MSM phone
@@ -2308,9 +2311,14 @@ product SUNTAC AS64LX 0x000b SUNTAC U-Cable type A3
product SUNTAC AS144L4 0x0011 SUNTAC U-Cable type A4
/* Sun Microsystems products */
-product SUN KEYBOARD 0x0005 Type 6 USB keyboard
+product SUN KEYBOARD_TYPE_6 0x0005 Type 6 USB keyboard
+product SUN KEYBOARD_TYPE_7 0x00a2 Type 7 USB keyboard
/* XXX The above is a North American PC style keyboard possibly */
product SUN MOUSE 0x0100 Type 6 USB mouse
+product SUN KBD_HUB 0x100e Kbd Hub
+
+/* Super Top products */
+product SUPERTOP IDE 0x6600 USB-IDE
/* Supra products */
product DIAMOND2 SUPRAEXPRESS56K 0x07da Supra Express 56K modem
diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c
index 659010c..856ed38 100644
--- a/sys/dev/usb/wlan/if_rum.c
+++ b/sys/dev/usb/wlan/if_rum.c
@@ -95,6 +95,7 @@ static const struct usb2_device_id rum_devs[] = {
{ USB_VP(USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUSMM) },
{ USB_VP(USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573) },
{ USB_VP(USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573_2) },
+ { USB_VP(USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573_3) },
{ USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573) },
{ USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573_2) },
{ USB_VP(USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2671) },
@@ -362,18 +363,18 @@ static const struct usb2_config rum_config[RUM_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = (MCLBYTES + RT2573_TX_DESC_SIZE + 8),
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = rum_bulk_write_callback,
- .mh.timeout = 5000, /* ms */
+ .bufsize = (MCLBYTES + RT2573_TX_DESC_SIZE + 8),
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = rum_bulk_write_callback,
+ .timeout = 5000, /* ms */
},
[RUM_BULK_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = (MCLBYTES + RT2573_RX_DESC_SIZE),
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = rum_bulk_read_callback,
+ .bufsize = (MCLBYTES + RT2573_RX_DESC_SIZE),
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = rum_bulk_read_callback,
},
};
@@ -494,7 +495,6 @@ rum_attach_post(struct usb2_proc_msg *pm)
ic->ic_ifp = ifp;
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
- IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_bssid);
/* set device capabilities */
ic->ic_caps =
@@ -516,7 +516,7 @@ rum_attach_post(struct usb2_proc_msg *pm)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, sc->sc_bssid);
ic->ic_update_promisc = rum_update_promisc;
ic->ic_newassoc = rum_newassoc;
ic->ic_raw_xmit = rum_raw_xmit;
@@ -528,8 +528,6 @@ rum_attach_post(struct usb2_proc_msg *pm)
ic->ic_vap_create = rum_vap_create;
ic->ic_vap_delete = rum_vap_delete;
- sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
-
bpfattach(ifp, DLT_IEEE802_11_RADIO,
sizeof (struct ieee80211_frame) + sizeof(sc->sc_txtap));
@@ -1068,7 +1066,7 @@ rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
desc->plcp_service = 4;
len += IEEE80211_CRC_LEN;
- if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) {
+ if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) {
desc->flags |= htole32(RT2573_TX_OFDM);
plcp_length = len & 0xfff;
@@ -1107,16 +1105,16 @@ rum_sendprot(struct rum_softc *sc,
wh = mtod(m, const struct ieee80211_frame *);
pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
- protrate = ieee80211_ctl_rate(sc->sc_rates, rate);
- ackrate = ieee80211_ack_rate(sc->sc_rates, rate);
+ protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
+ ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
- dur = ieee80211_compute_duration(sc->sc_rates, pktlen, rate, isshort);
- + ieee80211_ack_duration(sc->sc_rates, rate, isshort);
+ dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort);
+ + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags = RT2573_TX_MORE_FRAG;
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
- dur += ieee80211_ack_duration(sc->sc_rates, rate, isshort);
+ dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags |= RT2573_TX_NEED_ACK;
mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
} else {
@@ -1175,7 +1173,7 @@ rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
flags |= RT2573_TX_NEED_ACK;
- dur = ieee80211_ack_duration(sc->sc_rates, tp->mgmtrate,
+ dur = ieee80211_ack_duration(ic->ic_rt, tp->mgmtrate,
ic->ic_flags & IEEE80211_F_SHPREAMBLE);
*(uint16_t *)wh->i_dur = htole16(dur);
@@ -1295,7 +1293,7 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
prot = IEEE80211_PROT_RTSCTS;
else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
- ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM)
+ ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM)
prot = ic->ic_protmode;
if (prot != IEEE80211_PROT_NONE) {
error = rum_sendprot(sc, m0, ni, prot, rate);
@@ -1319,7 +1317,7 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
flags |= RT2573_TX_NEED_ACK;
flags |= RT2573_TX_MORE_FRAG;
- dur = ieee80211_ack_duration(sc->sc_rates, rate,
+ dur = ieee80211_ack_duration(ic->ic_rt, rate,
ic->ic_flags & IEEE80211_F_SHPREAMBLE);
*(uint16_t *)wh->i_dur = htole16(dur);
}
@@ -1357,12 +1355,6 @@ rum_start(struct ifnet *ifp)
break;
}
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- m = ieee80211_encap(ni, m);
- if (m == NULL) {
- ieee80211_free_node(ni);
- ifp->if_oerrors++;
- continue;
- }
if (rum_tx_data(sc, m, ni) != 0) {
ieee80211_free_node(ni);
ifp->if_oerrors++;
@@ -2064,8 +2056,7 @@ rum_init_task(struct usb2_proc_msg *pm)
/* clear STA registers */
rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
- IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
- rum_set_macaddr(sc, ic->ic_myaddr);
+ rum_set_macaddr(sc, IF_LLADDR(ifp));
/* initialize ASIC */
rum_write(sc, RT2573_MAC_CSR1, 4);
@@ -2369,7 +2360,6 @@ rum_set_channel(struct ieee80211com *ic)
RUM_LOCK(sc);
/* do it in a process context */
sc->sc_scan_action = RUM_SET_CHANNEL;
- sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
rum_queue_command(sc, rum_scantask,
&sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
RUM_UNLOCK(sc);
diff --git a/sys/dev/usb/wlan/if_rumvar.h b/sys/dev/usb/wlan/if_rumvar.h
index ed08e36..d6b8137 100644
--- a/sys/dev/usb/wlan/if_rumvar.h
+++ b/sys/dev/usb/wlan/if_rumvar.h
@@ -101,7 +101,6 @@ struct rum_softc {
struct usb2_device *sc_udev;
struct usb2_process sc_tq;
- const struct ieee80211_rate_table *sc_rates;
struct usb2_xfer *sc_xfer[RUM_N_TRANSFER];
struct rum_task *sc_last_task;
diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c
new file mode 100644
index 0000000..eb1c31c
--- /dev/null
+++ b/sys/dev/usb/wlan/if_uath.c
@@ -0,0 +1,2862 @@
+/*-
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * This driver is distantly derived from a driver of the same name
+ * by Damien Bergamini. The original copyright is included below:
+ *
+ * Copyright (c) 2006
+ * Damien Bergamini <damien.bergamini@free.fr>
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*-
+ * Driver for Atheros AR5523 USB parts.
+ *
+ * The driver requires firmware to be loaded into the device. This
+ * is done on device discovery from a user application (uathload)
+ * that is launched by devd when a device with suitable product ID
+ * is recognized. Once firmware has been loaded the device will
+ * reset the USB port and re-attach with the original product ID+1
+ * and this driver will be attached. The firmware is licensed for
+ * general use (royalty free) and may be incorporated in products.
+ * Note that the firmware normally packaged with the NDIS drivers
+ * for these devices does not work in this way and so does not work
+ * with this driver.
+ */
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+#endif
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_radiotap.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_error.h>
+#include <dev/usb/usb_lookup.h>
+#include <dev/usb/usb_util.h>
+#include "usbdevs.h"
+
+#include <dev/usb/wlan/if_uathreg.h>
+#include <dev/usb/wlan/if_uathvar.h>
+
+SYSCTL_NODE(_hw_usb2, OID_AUTO, uath, CTLFLAG_RW, 0, "USB Atheros");
+
+static int uath_countrycode = CTRY_DEFAULT; /* country code */
+SYSCTL_INT(_hw_usb2_uath, OID_AUTO, countrycode, CTLFLAG_RW, &uath_countrycode,
+ 0, "country code");
+TUNABLE_INT("hw.usb2.uath.countrycode", &uath_countrycode);
+static int uath_regdomain = 0; /* regulatory domain */
+SYSCTL_INT(_hw_usb2_uath, OID_AUTO, regdomain, CTLFLAG_RD, &uath_regdomain,
+ 0, "regulatory domain");
+
+#ifdef UATH_DEBUG
+int uath_debug = 0;
+SYSCTL_INT(_hw_usb2_uath, OID_AUTO, debug, CTLFLAG_RW, &uath_debug, 0,
+ "uath debug level");
+TUNABLE_INT("hw.usb.uath.debug", &uath_debug);
+enum {
+ UATH_DEBUG_XMIT = 0x00000001, /* basic xmit operation */
+ UATH_DEBUG_XMIT_DUMP = 0x00000002, /* xmit dump */
+ UATH_DEBUG_RECV = 0x00000004, /* basic recv operation */
+ UATH_DEBUG_TX_PROC = 0x00000008, /* tx ISR proc */
+ UATH_DEBUG_RX_PROC = 0x00000010, /* rx ISR proc */
+ UATH_DEBUG_RECV_ALL = 0x00000020, /* trace all frames (beacons) */
+ UATH_DEBUG_INIT = 0x00000040, /* initialization of dev */
+ UATH_DEBUG_DEVCAP = 0x00000080, /* dev caps */
+ UATH_DEBUG_CMDS = 0x00000100, /* commands */
+ UATH_DEBUG_CMDS_DUMP = 0x00000200, /* command buffer dump */
+ UATH_DEBUG_RESET = 0x00000400, /* reset processing */
+ UATH_DEBUG_STATE = 0x00000800, /* 802.11 state transitions */
+ UATH_DEBUG_MULTICAST = 0x00001000, /* multicast */
+ UATH_DEBUG_WME = 0x00002000, /* WME */
+ UATH_DEBUG_CHANNEL = 0x00004000, /* channel */
+ UATH_DEBUG_RATES = 0x00008000, /* rates */
+ UATH_DEBUG_CRYPTO = 0x00010000, /* crypto */
+ UATH_DEBUG_LED = 0x00020000, /* LED */
+ UATH_DEBUG_ANY = 0xffffffff
+};
+#define DPRINTF(sc, m, fmt, ...) do { \
+ if (sc->sc_debug & (m)) \
+ printf(fmt, __VA_ARGS__); \
+} while (0)
+#else
+#define DPRINTF(sc, m, fmt, ...) do { \
+ (void) sc; \
+} while (0)
+#endif
+
+/* unaligned little endian access */
+#define LE_READ_2(p) \
+ ((u_int16_t) \
+ ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8)))
+#define LE_READ_4(p) \
+ ((u_int32_t) \
+ ((((u_int8_t *)(p))[0] ) | (((u_int8_t *)(p))[1] << 8) | \
+ (((u_int8_t *)(p))[2] << 16) | (((u_int8_t *)(p))[3] << 24)))
+
+/* recognized device vendors/products */
+static const struct usb2_device_id uath_devs[] = {
+#define UATH_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
+ UATH_DEV(ATHEROS, AR5523),
+ UATH_DEV(ATHEROS2, AR5523_1),
+ UATH_DEV(ATHEROS2, AR5523_2),
+ UATH_DEV(ATHEROS2, AR5523_3),
+ UATH_DEV(CONCEPTRONIC, AR5523_1),
+ UATH_DEV(CONCEPTRONIC, AR5523_2),
+ UATH_DEV(DLINK, DWLAG122),
+ UATH_DEV(DLINK, DWLAG132),
+ UATH_DEV(DLINK, DWLG132),
+ UATH_DEV(GIGASET, AR5523),
+ UATH_DEV(GIGASET, SMCWUSBTG),
+ UATH_DEV(GLOBALSUN, AR5523_1),
+ UATH_DEV(GLOBALSUN, AR5523_2),
+ UATH_DEV(NETGEAR, WG111U),
+ UATH_DEV(NETGEAR3, WG111T),
+ UATH_DEV(NETGEAR3, WPN111),
+ UATH_DEV(UMEDIA, TEW444UBEU),
+ UATH_DEV(UMEDIA, AR5523_2),
+ UATH_DEV(WISTRONNEWEB, AR5523_1),
+ UATH_DEV(WISTRONNEWEB, AR5523_2),
+ UATH_DEV(ZCOM, AR5523)
+#undef UATH_DEV
+};
+
+static usb2_callback_t uath_intr_rx_callback;
+static usb2_callback_t uath_intr_tx_callback;
+static usb2_callback_t uath_bulk_rx_callback;
+static usb2_callback_t uath_bulk_tx_callback;
+
+static const struct usb2_config uath_usbconfig[UATH_N_XFERS] = {
+ [UATH_INTR_RX] = {
+ .type = UE_BULK,
+ .endpoint = 0x1,
+ .direction = UE_DIR_IN,
+ .bufsize = UATH_MAX_CMDSZ,
+ .flags = {
+ .pipe_bof = 1,
+ .short_xfer_ok = 1
+ },
+ .callback = uath_intr_rx_callback
+ },
+ [UATH_INTR_TX] = {
+ .type = UE_BULK,
+ .endpoint = 0x1,
+ .direction = UE_DIR_OUT,
+ .bufsize = UATH_MAX_CMDSZ,
+ .flags = {
+ .ext_buffer = 1,
+ .force_short_xfer = 1,
+ .pipe_bof = 1,
+ },
+ .callback = uath_intr_tx_callback,
+ .timeout = UATH_CMD_TIMEOUT
+ },
+ [UATH_BULK_RX] = {
+ .type = UE_BULK,
+ .endpoint = 0x2,
+ .direction = UE_DIR_IN,
+ .bufsize = MCLBYTES,
+ .flags = {
+ .ext_buffer = 1,
+ .pipe_bof = 1,
+ .short_xfer_ok = 1
+ },
+ .callback = uath_bulk_rx_callback
+ },
+ [UATH_BULK_TX] = {
+ .type = UE_BULK,
+ .endpoint = 0x2,
+ .direction = UE_DIR_OUT,
+ .bufsize = UATH_MAX_TXBUFSZ,
+ .flags = {
+ .ext_buffer = 1,
+ .force_short_xfer = 1,
+ .pipe_bof = 1
+ },
+ .callback = uath_bulk_tx_callback,
+ .timeout = UATH_DATA_TIMEOUT
+ }
+};
+
+static struct ieee80211vap *uath_vap_create(struct ieee80211com *,
+ const char name[IFNAMSIZ], int unit, int opmode,
+ int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
+ const uint8_t mac[IEEE80211_ADDR_LEN]);
+static void uath_vap_delete(struct ieee80211vap *);
+static int uath_alloc_cmd_list(struct uath_softc *, struct uath_cmd [],
+ int, int);
+static void uath_free_cmd_list(struct uath_softc *, struct uath_cmd [],
+ int);
+static int uath_host_available(struct uath_softc *);
+static int uath_get_capability(struct uath_softc *, uint32_t, uint32_t *);
+static int uath_get_devcap(struct uath_softc *);
+static struct uath_cmd *
+ uath_get_cmdbuf(struct uath_softc *);
+static int uath_cmd_read(struct uath_softc *, uint32_t, const void *,
+ int, void *, int, int);
+static int uath_cmd_write(struct uath_softc *, uint32_t, const void *,
+ int, int);
+static void uath_stat(void *);
+#ifdef UATH_DEBUG
+static void uath_dump_cmd(const uint8_t *, int, char);
+static const char *
+ uath_codename(int);
+#endif
+static int uath_get_devstatus(struct uath_softc *,
+ uint8_t macaddr[IEEE80211_ADDR_LEN]);
+static int uath_get_status(struct uath_softc *, uint32_t, void *, int);
+static int uath_alloc_rx_data_list(struct uath_softc *);
+static int uath_alloc_tx_data_list(struct uath_softc *);
+static void uath_free_rx_data_list(struct uath_softc *);
+static void uath_free_tx_data_list(struct uath_softc *);
+static int uath_init_locked(void *);
+static void uath_init(void *);
+static void uath_stop_locked(struct ifnet *);
+static void uath_stop(struct ifnet *);
+static int uath_ioctl(struct ifnet *, u_long, caddr_t);
+static void uath_start(struct ifnet *);
+static int uath_raw_xmit(struct ieee80211_node *, struct mbuf *,
+ const struct ieee80211_bpf_params *);
+static void uath_scan_start(struct ieee80211com *);
+static void uath_scan_end(struct ieee80211com *);
+static void uath_set_channel(struct ieee80211com *);
+static void uath_update_mcast(struct ifnet *);
+static void uath_update_promisc(struct ifnet *);
+static int uath_config(struct uath_softc *, uint32_t, uint32_t);
+static int uath_config_multi(struct uath_softc *, uint32_t, const void *,
+ int);
+static int uath_switch_channel(struct uath_softc *,
+ struct ieee80211_channel *);
+static int uath_set_rxfilter(struct uath_softc *, uint32_t, uint32_t);
+static void uath_watchdog(void *);
+static void uath_abort_xfers(struct uath_softc *);
+static int uath_dataflush(struct uath_softc *);
+static int uath_cmdflush(struct uath_softc *);
+static int uath_flush(struct uath_softc *);
+static int uath_set_ledstate(struct uath_softc *, int);
+static int uath_set_chan(struct uath_softc *, struct ieee80211_channel *);
+static int uath_reset_tx_queues(struct uath_softc *);
+static int uath_wme_init(struct uath_softc *);
+static struct uath_data *
+ uath_getbuf(struct uath_softc *);
+static int uath_newstate(struct ieee80211vap *, enum ieee80211_state,
+ int);
+static int uath_set_key(struct uath_softc *,
+ const struct ieee80211_key *, int);
+static int uath_set_keys(struct uath_softc *, struct ieee80211vap *);
+static void uath_sysctl_node(struct uath_softc *);
+
+static int
+uath_match(device_t dev)
+{
+ struct usb2_attach_arg *uaa = device_get_ivars(dev);
+
+ if (uaa->usb2_mode != USB_MODE_HOST)
+ return (ENXIO);
+ if (uaa->info.bConfigIndex != UATH_CONFIG_INDEX)
+ return (ENXIO);
+ if (uaa->info.bIfaceIndex != UATH_IFACE_INDEX)
+ return (ENXIO);
+
+ return (usb2_lookup_id_by_uaa(uath_devs, sizeof(uath_devs), uaa));
+}
+
+static int
+uath_attach(device_t dev)
+{
+ struct uath_softc *sc = device_get_softc(dev);
+ struct usb2_attach_arg *uaa = device_get_ivars(dev);
+ struct ieee80211com *ic;
+ struct ifnet *ifp;
+ uint8_t bands, iface_index = UATH_IFACE_INDEX; /* XXX */
+ usb2_error_t error;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
+
+ sc->sc_dev = dev;
+ sc->sc_udev = uaa->device;
+#ifdef UATH_DEBUG
+ sc->sc_debug = uath_debug;
+#endif
+
+ /*
+ * Only post-firmware devices here.
+ */
+ mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK,
+ MTX_DEF);
+ callout_init(&sc->stat_ch, 0);
+ callout_init_mtx(&sc->watchdog_ch, &sc->sc_mtx, 0);
+
+ /*
+ * Allocate xfers for firmware commands.
+ */
+ error = uath_alloc_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT,
+ UATH_MAX_CMDSZ);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "could not allocate Tx command list\n");
+ goto fail;
+ }
+
+ error = usb2_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
+ uath_usbconfig, UATH_N_XFERS, sc, &sc->sc_mtx);
+ if (error) {
+ device_printf(dev, "could not allocate USB transfers, "
+ "err=%s\n", usb2_errstr(error));
+ goto fail1;
+ }
+
+ /*
+ * We're now ready to send+receive firmware commands.
+ */
+ UATH_LOCK(sc);
+ error = uath_host_available(sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not initialize adapter\n");
+ goto fail3;
+ }
+ error = uath_get_devcap(sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "could not get device capabilities\n");
+ goto fail3;
+ }
+ UATH_UNLOCK(sc);
+
+ /* Create device sysctl node. */
+ uath_sysctl_node(sc);
+
+ ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
+ if (ifp == NULL) {
+ device_printf(sc->sc_dev, "can not allocate ifnet\n");
+ error = ENXIO;
+ goto fail2;
+ }
+
+ UATH_LOCK(sc);
+ error = uath_get_devstatus(sc, macaddr);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not get device status\n");
+ goto fail4;
+ }
+
+ /*
+ * Allocate xfers for Rx/Tx data pipes.
+ */
+ error = uath_alloc_rx_data_list(sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not allocate Rx data list\n");
+ goto fail4;
+ }
+ error = uath_alloc_tx_data_list(sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not allocate Tx data list\n");
+ goto fail4;
+ }
+ UATH_UNLOCK(sc);
+
+ ifp->if_softc = sc;
+ if_initname(ifp, "uath", device_get_unit(sc->sc_dev));
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_init = uath_init;
+ ifp->if_ioctl = uath_ioctl;
+ ifp->if_start = uath_start;
+ /* XXX UATH_TX_DATA_LIST_COUNT */
+ IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
+ ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
+ IFQ_SET_READY(&ifp->if_snd);
+
+ ic = ifp->if_l2com;
+ ic->ic_ifp = ifp;
+ ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
+ ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */
+
+ /* set device capabilities */
+ ic->ic_caps =
+ IEEE80211_C_STA | /* station mode */
+ IEEE80211_C_MONITOR | /* monitor mode supported */
+ IEEE80211_C_TXPMGT | /* tx power management */
+ IEEE80211_C_SHPREAMBLE | /* short preamble supported */
+ IEEE80211_C_SHSLOT | /* short slot time supported */
+ IEEE80211_C_WPA | /* 802.11i */
+ IEEE80211_C_BGSCAN | /* capable of bg scanning */
+ IEEE80211_C_TXFRAG; /* handle tx frags */
+
+ /* put a regulatory domain to reveal informations. */
+ uath_regdomain = sc->sc_devcap.regDomain;
+
+ bands = 0;
+ setbit(&bands, IEEE80211_MODE_11B);
+ setbit(&bands, IEEE80211_MODE_11G);
+ if ((sc->sc_devcap.analog5GhzRevision & 0xf0) == 0x30)
+ setbit(&bands, IEEE80211_MODE_11A);
+ /* XXX turbo */
+ ieee80211_init_channels(ic, NULL, &bands);
+
+ ieee80211_ifattach(ic, macaddr);
+ ic->ic_raw_xmit = uath_raw_xmit;
+ ic->ic_scan_start = uath_scan_start;
+ ic->ic_scan_end = uath_scan_end;
+ ic->ic_set_channel = uath_set_channel;
+
+ ic->ic_vap_create = uath_vap_create;
+ ic->ic_vap_delete = uath_vap_delete;
+ ic->ic_update_mcast = uath_update_mcast;
+ ic->ic_update_promisc = uath_update_promisc;
+
+ bpfattach(ifp, DLT_IEEE802_11_RADIO,
+ sizeof (struct ieee80211_frame) + sizeof(sc->sc_txtap));
+
+ sc->sc_rxtap_len = sizeof sc->sc_rxtap;
+ sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
+ sc->sc_rxtap.wr_ihdr.it_present = htole32(UATH_RX_RADIOTAP_PRESENT);
+
+ sc->sc_txtap_len = sizeof sc->sc_txtap;
+ sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
+ sc->sc_txtap.wt_ihdr.it_present = htole32(UATH_TX_RADIOTAP_PRESENT);
+
+ if (bootverbose)
+ ieee80211_announce(ic);
+
+ return (0);
+
+fail4: if_free(ifp);
+fail3: UATH_UNLOCK(sc);
+fail2: usb2_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
+fail1: uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
+fail:
+ return (error);
+}
+
+static int
+uath_detach(device_t dev)
+{
+ struct uath_softc *sc = device_get_softc(dev);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ if (!device_is_attached(dev))
+ return (0);
+
+ sc->sc_flags |= UATH_FLAG_INVALID;
+ uath_stop(ifp);
+ ieee80211_ifdetach(ic);
+
+ callout_drain(&sc->stat_ch);
+ callout_drain(&sc->watchdog_ch);
+
+ usb2_transfer_unsetup(sc->sc_xfer, UATH_N_XFERS);
+
+ /* free buffers */
+ UATH_LOCK(sc);
+ uath_free_rx_data_list(sc);
+ uath_free_tx_data_list(sc);
+ uath_free_cmd_list(sc, sc->sc_cmd, UATH_CMD_LIST_COUNT);
+ UATH_UNLOCK(sc);
+
+ bpfdetach(ifp);
+ if_free(ifp);
+ mtx_destroy(&sc->sc_mtx);
+ return (0);
+}
+
+static void
+uath_free_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[], int ncmd)
+{
+ int i;
+
+ for (i = 0; i < ncmd; i++)
+ if (cmds[i].buf != NULL)
+ free(cmds[i].buf, M_USBDEV);
+}
+
+static int
+uath_alloc_cmd_list(struct uath_softc *sc, struct uath_cmd cmds[],
+ int ncmd, int maxsz)
+{
+ int i, error;
+
+ STAILQ_INIT(&sc->sc_cmd_active);
+ STAILQ_INIT(&sc->sc_cmd_pending);
+ STAILQ_INIT(&sc->sc_cmd_waiting);
+ STAILQ_INIT(&sc->sc_cmd_inactive);
+
+ for (i = 0; i < ncmd; i++) {
+ struct uath_cmd *cmd = &cmds[i];
+
+ cmd->sc = sc; /* backpointer for callbacks */
+ cmd->msgid = i;
+ cmd->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
+ if (cmd->buf == NULL) {
+ device_printf(sc->sc_dev,
+ "could not allocate xfer buffer\n");
+ error = ENOMEM;
+ goto fail;
+ }
+ STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
+ UATH_STAT_INC(sc, st_cmd_inactive);
+ }
+ return (0);
+
+fail: uath_free_cmd_list(sc, cmds, ncmd);
+ return (error);
+}
+
+static int
+uath_host_available(struct uath_softc *sc)
+{
+ struct uath_cmd_host_available setup;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ /* inform target the host is available */
+ setup.sw_ver_major = htobe32(ATH_SW_VER_MAJOR);
+ setup.sw_ver_minor = htobe32(ATH_SW_VER_MINOR);
+ setup.sw_ver_patch = htobe32(ATH_SW_VER_PATCH);
+ setup.sw_ver_build = htobe32(ATH_SW_VER_BUILD);
+ return uath_cmd_read(sc, WDCMSG_HOST_AVAILABLE,
+ &setup, sizeof setup, NULL, 0, 0);
+}
+
+#ifdef UATH_DEBUG
+static void
+uath_dump_cmd(const uint8_t *buf, int len, char prefix)
+{
+ const char *sep = "";
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if ((i % 16) == 0) {
+ printf("%s%c ", sep, prefix);
+ sep = "\n";
+ }
+ else if ((i % 4) == 0)
+ printf(" ");
+ printf("%02x", buf[i]);
+ }
+ printf("\n");
+}
+
+static const char *
+uath_codename(int code)
+{
+#define N(a) (sizeof(a)/sizeof(a[0]))
+ static const char *names[] = {
+ "0x00",
+ "HOST_AVAILABLE",
+ "BIND",
+ "TARGET_RESET",
+ "TARGET_GET_CAPABILITY",
+ "TARGET_SET_CONFIG",
+ "TARGET_GET_STATUS",
+ "TARGET_GET_STATS",
+ "TARGET_START",
+ "TARGET_STOP",
+ "TARGET_ENABLE",
+ "TARGET_DISABLE",
+ "CREATE_CONNECTION",
+ "UPDATE_CONNECT_ATTR",
+ "DELETE_CONNECT",
+ "SEND",
+ "FLUSH",
+ "STATS_UPDATE",
+ "BMISS",
+ "DEVICE_AVAIL",
+ "SEND_COMPLETE",
+ "DATA_AVAIL",
+ "SET_PWR_MODE",
+ "BMISS_ACK",
+ "SET_LED_STEADY",
+ "SET_LED_BLINK",
+ "SETUP_BEACON_DESC",
+ "BEACON_INIT",
+ "RESET_KEY_CACHE",
+ "RESET_KEY_CACHE_ENTRY",
+ "SET_KEY_CACHE_ENTRY",
+ "SET_DECOMP_MASK",
+ "SET_REGULATORY_DOMAIN",
+ "SET_LED_STATE",
+ "WRITE_ASSOCID",
+ "SET_STA_BEACON_TIMERS",
+ "GET_TSF",
+ "RESET_TSF",
+ "SET_ADHOC_MODE",
+ "SET_BASIC_RATE",
+ "MIB_CONTROL",
+ "GET_CHANNEL_DATA",
+ "GET_CUR_RSSI",
+ "SET_ANTENNA_SWITCH",
+ "0x2c", "0x2d", "0x2e",
+ "USE_SHORT_SLOT_TIME",
+ "SET_POWER_MODE",
+ "SETUP_PSPOLL_DESC",
+ "SET_RX_MULTICAST_FILTER",
+ "RX_FILTER",
+ "PER_CALIBRATION",
+ "RESET",
+ "DISABLE",
+ "PHY_DISABLE",
+ "SET_TX_POWER_LIMIT",
+ "SET_TX_QUEUE_PARAMS",
+ "SETUP_TX_QUEUE",
+ "RELEASE_TX_QUEUE",
+ };
+ static char buf[8];
+
+ if (code < N(names))
+ return names[code];
+ if (code == WDCMSG_SET_DEFAULT_KEY)
+ return "SET_DEFAULT_KEY";
+ snprintf(buf, sizeof(buf), "0x%02x", code);
+ return buf;
+#undef N
+}
+#endif
+
+/*
+ * Low-level function to send read or write commands to the firmware.
+ */
+static int
+uath_cmdsend(struct uath_softc *sc, uint32_t code, const void *idata, int ilen,
+ void *odata, int olen, int flags)
+{
+ struct uath_cmd_hdr *hdr;
+ struct uath_cmd *cmd;
+ int error;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ /* grab a xfer */
+ cmd = uath_get_cmdbuf(sc);
+ if (cmd == NULL) {
+ device_printf(sc->sc_dev, "%s: empty inactive queue\n",
+ __func__);
+ return (ENOBUFS);
+ }
+ cmd->flags = flags;
+ /* always bulk-out a multiple of 4 bytes */
+ cmd->buflen = roundup2(sizeof(struct uath_cmd_hdr) + ilen, 4);
+
+ hdr = (struct uath_cmd_hdr *)cmd->buf;
+ bzero(hdr, sizeof (struct uath_cmd_hdr)); /* XXX not needed */
+ hdr->len = htobe32(cmd->buflen);
+ hdr->code = htobe32(code);
+ hdr->msgid = cmd->msgid; /* don't care about endianness */
+ hdr->magic = htobe32((cmd->flags & UATH_CMD_FLAG_MAGIC) ? 1 << 24 : 0);
+ bcopy(idata, (uint8_t *)(hdr + 1), ilen);
+
+#ifdef UATH_DEBUG
+ if (sc->sc_debug & UATH_DEBUG_CMDS) {
+ printf("%s: send %s [flags 0x%x] olen %d\n",
+ __func__, uath_codename(code), cmd->flags, olen);
+ if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP)
+ uath_dump_cmd(cmd->buf, cmd->buflen, '+');
+ }
+#endif
+ cmd->odata = odata;
+ KASSERT(odata == NULL ||
+ olen < UATH_MAX_CMDSZ - sizeof(*hdr) + sizeof(uint32_t),
+ ("odata %p olen %u", odata, olen));
+ cmd->olen = olen;
+
+ STAILQ_INSERT_TAIL(&sc->sc_cmd_pending, cmd, next);
+ UATH_STAT_INC(sc, st_cmd_pending);
+ usb2_transfer_start(sc->sc_xfer[UATH_INTR_TX]);
+
+ if (cmd->flags & UATH_CMD_FLAG_READ) {
+ usb2_transfer_start(sc->sc_xfer[UATH_INTR_RX]);
+
+ /* wait at most two seconds for command reply */
+ error = mtx_sleep(cmd, &sc->sc_mtx, 0, "uathcmd", 2 * hz);
+ cmd->odata = NULL; /* in case reply comes too late */
+ if (error != 0) {
+ device_printf(sc->sc_dev, "timeout waiting for reply "
+ "to cmd 0x%x (%u)\n", code, code);
+ } else if (cmd->olen != olen) {
+ device_printf(sc->sc_dev, "unexpected reply data count "
+ "to cmd 0x%x (%u), got %u, expected %u\n",
+ code, code, cmd->olen, olen);
+ error = EINVAL;
+ }
+ return (error);
+ }
+ return (0);
+}
+
+static int
+uath_cmd_read(struct uath_softc *sc, uint32_t code, const void *idata,
+ int ilen, void *odata, int olen, int flags)
+{
+
+ flags |= UATH_CMD_FLAG_READ;
+ return uath_cmdsend(sc, code, idata, ilen, odata, olen, flags);
+}
+
+static int
+uath_cmd_write(struct uath_softc *sc, uint32_t code, const void *data, int len,
+ int flags)
+{
+
+ flags &= ~UATH_CMD_FLAG_READ;
+ return uath_cmdsend(sc, code, data, len, NULL, 0, flags);
+}
+
+static struct uath_cmd *
+uath_get_cmdbuf(struct uath_softc *sc)
+{
+ struct uath_cmd *uc;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ uc = STAILQ_FIRST(&sc->sc_cmd_inactive);
+ if (uc != NULL) {
+ STAILQ_REMOVE_HEAD(&sc->sc_cmd_inactive, next);
+ UATH_STAT_DEC(sc, st_cmd_inactive);
+ } else
+ uc = NULL;
+ if (uc == NULL)
+ DPRINTF(sc, UATH_DEBUG_XMIT, "%s: %s\n", __func__,
+ "out of command xmit buffers");
+ return (uc);
+}
+
+/*
+ * This function is called periodically (every second) when associated to
+ * query device statistics.
+ */
+static void
+uath_stat(void *arg)
+{
+ struct uath_softc *sc = arg;
+ int error;
+
+ UATH_LOCK(sc);
+ /*
+ * Send request for statistics asynchronously. The timer will be
+ * restarted when we'll get the stats notification.
+ */
+ error = uath_cmd_write(sc, WDCMSG_TARGET_GET_STATS, NULL, 0,
+ UATH_CMD_FLAG_ASYNC);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "could not query stats, error %d\n", error);
+ }
+ UATH_UNLOCK(sc);
+}
+
+static int
+uath_get_capability(struct uath_softc *sc, uint32_t cap, uint32_t *val)
+{
+ int error;
+
+ cap = htobe32(cap);
+ error = uath_cmd_read(sc, WDCMSG_TARGET_GET_CAPABILITY,
+ &cap, sizeof cap, val, sizeof(uint32_t), UATH_CMD_FLAG_MAGIC);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not read capability %u\n",
+ be32toh(cap));
+ return (error);
+ }
+ *val = be32toh(*val);
+ return (error);
+}
+
+static int
+uath_get_devcap(struct uath_softc *sc)
+{
+#define GETCAP(x, v) do { \
+ error = uath_get_capability(sc, x, &v); \
+ if (error != 0) \
+ return (error); \
+ DPRINTF(sc, UATH_DEBUG_DEVCAP, \
+ "%s: %s=0x%08x\n", __func__, #x, v); \
+} while (0)
+ struct uath_devcap *cap = &sc->sc_devcap;
+ int error;
+
+ /* collect device capabilities */
+ GETCAP(CAP_TARGET_VERSION, cap->targetVersion);
+ GETCAP(CAP_TARGET_REVISION, cap->targetRevision);
+ GETCAP(CAP_MAC_VERSION, cap->macVersion);
+ GETCAP(CAP_MAC_REVISION, cap->macRevision);
+ GETCAP(CAP_PHY_REVISION, cap->phyRevision);
+ GETCAP(CAP_ANALOG_5GHz_REVISION, cap->analog5GhzRevision);
+ GETCAP(CAP_ANALOG_2GHz_REVISION, cap->analog2GhzRevision);
+
+ GETCAP(CAP_REG_DOMAIN, cap->regDomain);
+ GETCAP(CAP_REG_CAP_BITS, cap->regCapBits);
+#if 0
+ /* NB: not supported in rev 1.5 */
+ GETCAP(CAP_COUNTRY_CODE, cap->countryCode);
+#endif
+ GETCAP(CAP_WIRELESS_MODES, cap->wirelessModes);
+ GETCAP(CAP_CHAN_SPREAD_SUPPORT, cap->chanSpreadSupport);
+ GETCAP(CAP_COMPRESS_SUPPORT, cap->compressSupport);
+ GETCAP(CAP_BURST_SUPPORT, cap->burstSupport);
+ GETCAP(CAP_FAST_FRAMES_SUPPORT, cap->fastFramesSupport);
+ GETCAP(CAP_CHAP_TUNING_SUPPORT, cap->chapTuningSupport);
+ GETCAP(CAP_TURBOG_SUPPORT, cap->turboGSupport);
+ GETCAP(CAP_TURBO_PRIME_SUPPORT, cap->turboPrimeSupport);
+ GETCAP(CAP_DEVICE_TYPE, cap->deviceType);
+ GETCAP(CAP_WME_SUPPORT, cap->wmeSupport);
+ GETCAP(CAP_TOTAL_QUEUES, cap->numTxQueues);
+ GETCAP(CAP_CONNECTION_ID_MAX, cap->connectionIdMax);
+
+ GETCAP(CAP_LOW_5GHZ_CHAN, cap->low5GhzChan);
+ GETCAP(CAP_HIGH_5GHZ_CHAN, cap->high5GhzChan);
+ GETCAP(CAP_LOW_2GHZ_CHAN, cap->low2GhzChan);
+ GETCAP(CAP_HIGH_2GHZ_CHAN, cap->high2GhzChan);
+ GETCAP(CAP_TWICE_ANTENNAGAIN_5G, cap->twiceAntennaGain5G);
+ GETCAP(CAP_TWICE_ANTENNAGAIN_2G, cap->twiceAntennaGain2G);
+
+ GETCAP(CAP_CIPHER_AES_CCM, cap->supportCipherAES_CCM);
+ GETCAP(CAP_CIPHER_TKIP, cap->supportCipherTKIP);
+ GETCAP(CAP_MIC_TKIP, cap->supportMicTKIP);
+
+ cap->supportCipherWEP = 1; /* NB: always available */
+
+ return (0);
+}
+
+static int
+uath_get_devstatus(struct uath_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
+{
+ int error;
+
+ /* retrieve MAC address */
+ error = uath_get_status(sc, ST_MAC_ADDR, macaddr, IEEE80211_ADDR_LEN);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not read MAC address\n");
+ return (error);
+ }
+
+ error = uath_get_status(sc, ST_SERIAL_NUMBER,
+ &sc->sc_serial[0], sizeof(sc->sc_serial));
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "could not read device serial number\n");
+ return (error);
+ }
+ return (0);
+}
+
+static int
+uath_get_status(struct uath_softc *sc, uint32_t which, void *odata, int olen)
+{
+ int error;
+
+ which = htobe32(which);
+ error = uath_cmd_read(sc, WDCMSG_TARGET_GET_STATUS,
+ &which, sizeof(which), odata, olen, UATH_CMD_FLAG_MAGIC);
+ if (error != 0)
+ device_printf(sc->sc_dev,
+ "could not read EEPROM offset 0x%02x\n", be32toh(which));
+ return (error);
+}
+
+static void
+uath_free_data_list(struct uath_softc *sc, struct uath_data data[], int ndata,
+ int fillmbuf)
+{
+ int i;
+
+ for (i = 0; i < ndata; i++) {
+ struct uath_data *dp = &data[i];
+
+ if (fillmbuf == 1) {
+ if (dp->m != NULL) {
+ m_freem(dp->m);
+ dp->m = NULL;
+ dp->buf = NULL;
+ }
+ } else {
+ if (dp->buf != NULL) {
+ free(dp->buf, M_USBDEV);
+ dp->buf = NULL;
+ }
+ }
+#ifdef UATH_DEBUG
+ if (dp->ni != NULL)
+ device_printf(sc->sc_dev, "Node isn't NULL\n");
+#endif
+ }
+}
+
+static int
+uath_alloc_data_list(struct uath_softc *sc, struct uath_data data[],
+ int ndata, int maxsz, int fillmbuf)
+{
+ int i, error;
+
+ for (i = 0; i < ndata; i++) {
+ struct uath_data *dp = &data[i];
+
+ dp->sc = sc;
+ if (fillmbuf) {
+ /* XXX check maxsz */
+ dp->m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (dp->m == NULL) {
+ device_printf(sc->sc_dev,
+ "could not allocate rx mbuf\n");
+ error = ENOMEM;
+ goto fail;
+ }
+ dp->buf = mtod(dp->m, uint8_t *);
+ } else {
+ dp->m = NULL;
+ dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
+ if (dp->buf == NULL) {
+ device_printf(sc->sc_dev,
+ "could not allocate buffer\n");
+ error = ENOMEM;
+ goto fail;
+ }
+ }
+ dp->ni = NULL;
+ }
+
+ return (0);
+
+fail: uath_free_data_list(sc, data, ndata, fillmbuf);
+ return (error);
+}
+
+static int
+uath_alloc_rx_data_list(struct uath_softc *sc)
+{
+ int error, i;
+
+ /* XXX is it enough to store the RX packet with MCLBYTES bytes? */
+ error = uath_alloc_data_list(sc,
+ sc->sc_rx, UATH_RX_DATA_LIST_COUNT, MCLBYTES,
+ 1 /* setup mbufs */);
+ if (error != 0)
+ return (error);
+
+ STAILQ_INIT(&sc->sc_rx_active);
+ STAILQ_INIT(&sc->sc_rx_inactive);
+
+ for (i = 0; i < UATH_RX_DATA_LIST_COUNT; i++) {
+ STAILQ_INSERT_HEAD(&sc->sc_rx_inactive, &sc->sc_rx[i],
+ next);
+ UATH_STAT_INC(sc, st_rx_inactive);
+ }
+
+ return (0);
+}
+
+static int
+uath_alloc_tx_data_list(struct uath_softc *sc)
+{
+ int error, i;
+
+ error = uath_alloc_data_list(sc,
+ sc->sc_tx, UATH_TX_DATA_LIST_COUNT, UATH_MAX_TXBUFSZ,
+ 0 /* no mbufs */);
+ if (error != 0)
+ return (error);
+
+ STAILQ_INIT(&sc->sc_tx_active);
+ STAILQ_INIT(&sc->sc_tx_inactive);
+ STAILQ_INIT(&sc->sc_tx_pending);
+
+ for (i = 0; i < UATH_TX_DATA_LIST_COUNT; i++) {
+ STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, &sc->sc_tx[i],
+ next);
+ UATH_STAT_INC(sc, st_tx_inactive);
+ }
+
+ return (0);
+}
+
+static void
+uath_free_rx_data_list(struct uath_softc *sc)
+{
+
+ STAILQ_INIT(&sc->sc_rx_active);
+ STAILQ_INIT(&sc->sc_rx_inactive);
+
+ uath_free_data_list(sc, sc->sc_rx, UATH_RX_DATA_LIST_COUNT,
+ 1 /* free mbufs */);
+}
+
+static void
+uath_free_tx_data_list(struct uath_softc *sc)
+{
+
+ STAILQ_INIT(&sc->sc_tx_active);
+ STAILQ_INIT(&sc->sc_tx_inactive);
+ STAILQ_INIT(&sc->sc_tx_pending);
+
+ uath_free_data_list(sc, sc->sc_tx, UATH_TX_DATA_LIST_COUNT,
+ 0 /* no mbufs */);
+}
+
+static struct ieee80211vap *
+uath_vap_create(struct ieee80211com *ic,
+ const char name[IFNAMSIZ], int unit, int opmode, int flags,
+ const uint8_t bssid[IEEE80211_ADDR_LEN],
+ const uint8_t mac[IEEE80211_ADDR_LEN])
+{
+ struct uath_vap *uvp;
+ struct ieee80211vap *vap;
+
+ if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
+ return (NULL);
+ uvp = (struct uath_vap *) malloc(sizeof(struct uath_vap),
+ M_80211_VAP, M_NOWAIT | M_ZERO);
+ if (uvp == NULL)
+ return (NULL);
+ vap = &uvp->vap;
+ /* enable s/w bmiss handling for sta mode */
+ ieee80211_vap_setup(ic, vap, name, unit, opmode,
+ flags | IEEE80211_CLONE_NOBEACONS, bssid, mac);
+
+ /* override state transition machine */
+ uvp->newstate = vap->iv_newstate;
+ vap->iv_newstate = uath_newstate;
+
+ /* complete setup */
+ ieee80211_vap_attach(vap, ieee80211_media_change,
+ ieee80211_media_status);
+ ic->ic_opmode = opmode;
+ return (vap);
+}
+
+static void
+uath_vap_delete(struct ieee80211vap *vap)
+{
+ struct uath_vap *uvp = UATH_VAP(vap);
+
+ ieee80211_vap_detach(vap);
+ free(uvp, M_80211_VAP);
+}
+
+static int
+uath_init_locked(void *arg)
+{
+ struct uath_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ uint32_t val;
+ int error;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ uath_stop_locked(ifp);
+
+ /* reset variables */
+ sc->sc_intrx_nextnum = sc->sc_msgid = 0;
+
+ val = htobe32(0);
+ uath_cmd_write(sc, WDCMSG_BIND, &val, sizeof val, 0);
+
+ /* set MAC address */
+ uath_config_multi(sc, CFG_MAC_ADDR, IF_LLADDR(ifp), IEEE80211_ADDR_LEN);
+
+ /* XXX honor net80211 state */
+ uath_config(sc, CFG_RATE_CONTROL_ENABLE, 0x00000001);
+ uath_config(sc, CFG_DIVERSITY_CTL, 0x00000001);
+ uath_config(sc, CFG_ABOLT, 0x0000003f);
+ uath_config(sc, CFG_WME_ENABLED, 0x00000001);
+
+ uath_config(sc, CFG_SERVICE_TYPE, 1);
+ uath_config(sc, CFG_TP_SCALE, 0x00000000);
+ uath_config(sc, CFG_TPC_HALF_DBM5, 0x0000003c);
+ uath_config(sc, CFG_TPC_HALF_DBM2, 0x0000003c);
+ uath_config(sc, CFG_OVERRD_TX_POWER, 0x00000000);
+ uath_config(sc, CFG_GMODE_PROTECTION, 0x00000000);
+ uath_config(sc, CFG_GMODE_PROTECT_RATE_INDEX, 0x00000003);
+ uath_config(sc, CFG_PROTECTION_TYPE, 0x00000000);
+ uath_config(sc, CFG_MODE_CTS, 0x00000002);
+
+ error = uath_cmd_read(sc, WDCMSG_TARGET_START, NULL, 0,
+ &val, sizeof(val), UATH_CMD_FLAG_MAGIC);
+ if (error) {
+ device_printf(sc->sc_dev,
+ "could not start target, error %d\n", error);
+ goto fail;
+ }
+ DPRINTF(sc, UATH_DEBUG_INIT, "%s returns handle: 0x%x\n",
+ uath_codename(WDCMSG_TARGET_START), be32toh(val));
+
+ /* set default channel */
+ error = uath_switch_channel(sc, ic->ic_curchan);
+ if (error) {
+ device_printf(sc->sc_dev,
+ "could not switch channel, error %d\n", error);
+ goto fail;
+ }
+
+ val = htobe32(TARGET_DEVICE_AWAKE);
+ uath_cmd_write(sc, WDCMSG_SET_PWR_MODE, &val, sizeof val, 0);
+ /* XXX? check */
+ uath_cmd_write(sc, WDCMSG_RESET_KEY_CACHE, NULL, 0, 0);
+
+ usb2_transfer_start(sc->sc_xfer[UATH_BULK_RX]);
+ /* enable Rx */
+ uath_set_rxfilter(sc, 0x0, UATH_FILTER_OP_INIT);
+ uath_set_rxfilter(sc,
+ UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST |
+ UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON,
+ UATH_FILTER_OP_SET);
+
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ sc->sc_flags |= UATH_FLAG_INITDONE;
+
+ callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
+
+ return (0);
+
+fail:
+ uath_stop_locked(ifp);
+ return (error);
+}
+
+static void
+uath_init(void *arg)
+{
+ struct uath_softc *sc = arg;
+
+ UATH_LOCK(sc);
+ (void)uath_init_locked(sc);
+ UATH_UNLOCK(sc);
+}
+
+static void
+uath_stop_locked(struct ifnet *ifp)
+{
+ struct uath_softc *sc = ifp->if_softc;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ sc->sc_flags &= ~UATH_FLAG_INITDONE;
+
+ callout_stop(&sc->stat_ch);
+ callout_stop(&sc->watchdog_ch);
+ sc->sc_tx_timer = 0;
+ /* abort pending transmits */
+ uath_abort_xfers(sc);
+ /* flush data & control requests into the target */
+ (void)uath_flush(sc);
+ /* set a LED status to the disconnected. */
+ uath_set_ledstate(sc, 0);
+ /* stop the target */
+ uath_cmd_write(sc, WDCMSG_TARGET_STOP, NULL, 0, 0);
+}
+
+static void
+uath_stop(struct ifnet *ifp)
+{
+ struct uath_softc *sc = ifp->if_softc;
+
+ UATH_LOCK(sc);
+ uath_stop_locked(ifp);
+ UATH_UNLOCK(sc);
+}
+
+static int
+uath_config(struct uath_softc *sc, uint32_t reg, uint32_t val)
+{
+ struct uath_write_mac write;
+ int error;
+
+ write.reg = htobe32(reg);
+ write.len = htobe32(0); /* 0 = single write */
+ *(uint32_t *)write.data = htobe32(val);
+
+ error = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write,
+ 3 * sizeof (uint32_t), 0);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "could not write register 0x%02x\n",
+ reg);
+ }
+ return (error);
+}
+
+static int
+uath_config_multi(struct uath_softc *sc, uint32_t reg, const void *data,
+ int len)
+{
+ struct uath_write_mac write;
+ int error;
+
+ write.reg = htobe32(reg);
+ write.len = htobe32(len);
+ bcopy(data, write.data, len);
+
+ /* properly handle the case where len is zero (reset) */
+ error = uath_cmd_write(sc, WDCMSG_TARGET_SET_CONFIG, &write,
+ (len == 0) ? sizeof (uint32_t) : 2 * sizeof (uint32_t) + len, 0);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "could not write %d bytes to register 0x%02x\n", len, reg);
+ }
+ return (error);
+}
+
+static int
+uath_switch_channel(struct uath_softc *sc, struct ieee80211_channel *c)
+{
+ int error;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ /* set radio frequency */
+ error = uath_set_chan(sc, c);
+ if (error) {
+ device_printf(sc->sc_dev,
+ "could not set channel, error %d\n", error);
+ goto failed;
+ }
+ /* reset Tx rings */
+ error = uath_reset_tx_queues(sc);
+ if (error) {
+ device_printf(sc->sc_dev,
+ "could not reset Tx queues, error %d\n", error);
+ goto failed;
+ }
+ /* set Tx rings WME properties */
+ error = uath_wme_init(sc);
+ if (error) {
+ device_printf(sc->sc_dev,
+ "could not init Tx queues, error %d\n", error);
+ goto failed;
+ }
+ error = uath_set_ledstate(sc, 0);
+ if (error) {
+ device_printf(sc->sc_dev,
+ "could not set led state, error %d\n", error);
+ goto failed;
+ }
+ error = uath_flush(sc);
+ if (error) {
+ device_printf(sc->sc_dev,
+ "could not flush pipes, error %d\n", error);
+ goto failed;
+ }
+failed:
+ return (error);
+}
+
+static int
+uath_set_rxfilter(struct uath_softc *sc, uint32_t bits, uint32_t op)
+{
+ struct uath_cmd_rx_filter rxfilter;
+
+ rxfilter.bits = htobe32(bits);
+ rxfilter.op = htobe32(op);
+
+ DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
+ "setting Rx filter=0x%x flags=0x%x\n", bits, op);
+ return uath_cmd_write(sc, WDCMSG_RX_FILTER, &rxfilter,
+ sizeof rxfilter, 0);
+}
+
+static void
+uath_watchdog(void *arg)
+{
+ struct uath_softc *sc = arg;
+ struct ifnet *ifp = sc->sc_ifp;
+
+ if (sc->sc_tx_timer > 0) {
+ if (--sc->sc_tx_timer == 0) {
+ device_printf(sc->sc_dev, "device timeout\n");
+ /*uath_init(ifp); XXX needs a process context! */
+ ifp->if_oerrors++;
+ return;
+ }
+ callout_reset(&sc->watchdog_ch, hz, uath_watchdog, sc);
+ }
+}
+
+static void
+uath_abort_xfers(struct uath_softc *sc)
+{
+ int i;
+
+ UATH_ASSERT_LOCKED(sc);
+ /* abort any pending transfers */
+ for (i = 0; i < UATH_N_XFERS; i++)
+ usb2_transfer_stop(sc->sc_xfer[i]);
+}
+
+static int
+uath_flush(struct uath_softc *sc)
+{
+ int error;
+
+ error = uath_dataflush(sc);
+ if (error != 0)
+ goto failed;
+
+ error = uath_cmdflush(sc);
+ if (error != 0)
+ goto failed;
+
+failed:
+ return (error);
+}
+
+static int
+uath_cmdflush(struct uath_softc *sc)
+{
+
+ return uath_cmd_write(sc, WDCMSG_FLUSH, NULL, 0, 0);
+}
+
+static int
+uath_dataflush(struct uath_softc *sc)
+{
+ struct uath_data *data;
+ struct uath_chunk *chunk;
+ struct uath_tx_desc *desc;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ data = uath_getbuf(sc);
+ if (data == NULL)
+ return (ENOBUFS);
+ data->buflen = sizeof(struct uath_chunk) + sizeof(struct uath_tx_desc);
+ data->m = NULL;
+ data->ni = NULL;
+ chunk = (struct uath_chunk *)data->buf;
+ desc = (struct uath_tx_desc *)(chunk + 1);
+
+ /* one chunk only */
+ chunk->seqnum = 0;
+ chunk->flags = UATH_CFLAGS_FINAL;
+ chunk->length = htobe16(sizeof (struct uath_tx_desc));
+
+ bzero(desc, sizeof(struct uath_tx_desc));
+ desc->msglen = htobe32(sizeof(struct uath_tx_desc));
+ desc->msgid = (sc->sc_msgid++) + 1; /* don't care about endianness */
+ desc->type = htobe32(WDCMSG_FLUSH);
+ desc->txqid = htobe32(0);
+ desc->connid = htobe32(0);
+ desc->flags = htobe32(0);
+
+#ifdef UATH_DEBUG
+ if (sc->sc_debug & UATH_DEBUG_CMDS) {
+ DPRINTF(sc, UATH_DEBUG_RESET, "send flush ix %d\n",
+ desc->msgid);
+ if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP)
+ uath_dump_cmd(data->buf, data->buflen, '+');
+ }
+#endif
+
+ STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next);
+ UATH_STAT_INC(sc, st_tx_pending);
+ sc->sc_tx_timer = 5;
+ usb2_transfer_start(sc->sc_xfer[UATH_BULK_TX]);
+
+ return (0);
+}
+
+static struct uath_data *
+_uath_getbuf(struct uath_softc *sc)
+{
+ struct uath_data *bf;
+
+ bf = STAILQ_FIRST(&sc->sc_tx_inactive);
+ if (bf != NULL) {
+ STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next);
+ UATH_STAT_DEC(sc, st_tx_inactive);
+ } else
+ bf = NULL;
+ if (bf == NULL)
+ DPRINTF(sc, UATH_DEBUG_XMIT, "%s: %s\n", __func__,
+ "out of xmit buffers");
+ return (bf);
+}
+
+static struct uath_data *
+uath_getbuf(struct uath_softc *sc)
+{
+ struct uath_data *bf;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ bf = _uath_getbuf(sc);
+ if (bf == NULL) {
+ struct ifnet *ifp = sc->sc_ifp;
+
+ DPRINTF(sc, UATH_DEBUG_XMIT, "%s: stop queue\n", __func__);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+ }
+ return (bf);
+}
+
+static int
+uath_set_ledstate(struct uath_softc *sc, int connected)
+{
+
+ DPRINTF(sc, UATH_DEBUG_LED,
+ "set led state %sconnected\n", connected ? "" : "!");
+ connected = htobe32(connected);
+ return uath_cmd_write(sc, WDCMSG_SET_LED_STATE,
+ &connected, sizeof connected, 0);
+}
+
+static int
+uath_set_chan(struct uath_softc *sc, struct ieee80211_channel *c)
+{
+#ifdef UATH_DEBUG
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+#endif
+ struct uath_cmd_reset reset;
+
+ bzero(&reset, sizeof reset);
+ if (IEEE80211_IS_CHAN_2GHZ(c))
+ reset.flags |= htobe32(UATH_CHAN_2GHZ);
+ if (IEEE80211_IS_CHAN_5GHZ(c))
+ reset.flags |= htobe32(UATH_CHAN_5GHZ);
+ /* NB: 11g =>'s 11b so don't specify both OFDM and CCK */
+ if (IEEE80211_IS_CHAN_G(c))
+ reset.flags |= htobe32(UATH_CHAN_OFDM);
+ else if (IEEE80211_IS_CHAN_B(c))
+ reset.flags |= htobe32(UATH_CHAN_CCK);
+ /* turbo can be used in either 2GHz or 5GHz */
+ if (c->ic_flags & IEEE80211_CHAN_TURBO)
+ reset.flags |= htobe32(UATH_CHAN_TURBO);
+ reset.freq = htobe32(c->ic_freq);
+ reset.maxrdpower = htobe32(50); /* XXX */
+ reset.channelchange = htobe32(1);
+ reset.keeprccontent = htobe32(0);
+
+ DPRINTF(sc, UATH_DEBUG_CHANNEL, "set channel %d, flags 0x%x freq %u\n",
+ ieee80211_chan2ieee(ic, c),
+ be32toh(reset.flags), be32toh(reset.freq));
+ return uath_cmd_write(sc, WDCMSG_RESET, &reset, sizeof reset, 0);
+}
+
+static int
+uath_reset_tx_queues(struct uath_softc *sc)
+{
+ int ac, error;
+
+ DPRINTF(sc, UATH_DEBUG_RESET, "%s: reset Tx queues\n", __func__);
+ for (ac = 0; ac < 4; ac++) {
+ const uint32_t qid = htobe32(ac);
+
+ error = uath_cmd_write(sc, WDCMSG_RELEASE_TX_QUEUE, &qid,
+ sizeof qid, 0);
+ if (error != 0)
+ break;
+ }
+ return (error);
+}
+
+static int
+uath_wme_init(struct uath_softc *sc)
+{
+ /* XXX get from net80211 */
+ static const struct uath_wme_settings uath_wme_11g[4] = {
+ { 7, 4, 10, 0, 0 }, /* Background */
+ { 3, 4, 10, 0, 0 }, /* Best-Effort */
+ { 3, 3, 4, 26, 0 }, /* Video */
+ { 2, 2, 3, 47, 0 } /* Voice */
+ };
+ struct uath_cmd_txq_setup qinfo;
+ int ac, error;
+
+ DPRINTF(sc, UATH_DEBUG_WME, "%s: setup Tx queues\n", __func__);
+ for (ac = 0; ac < 4; ac++) {
+ qinfo.qid = htobe32(ac);
+ qinfo.len = htobe32(sizeof(qinfo.attr));
+ qinfo.attr.priority = htobe32(ac); /* XXX */
+ qinfo.attr.aifs = htobe32(uath_wme_11g[ac].aifsn);
+ qinfo.attr.logcwmin = htobe32(uath_wme_11g[ac].logcwmin);
+ qinfo.attr.logcwmax = htobe32(uath_wme_11g[ac].logcwmax);
+ qinfo.attr.bursttime = htobe32(UATH_TXOP_TO_US(
+ uath_wme_11g[ac].txop));
+ qinfo.attr.mode = htobe32(uath_wme_11g[ac].acm);/*XXX? */
+ qinfo.attr.qflags = htobe32(1); /* XXX? */
+
+ error = uath_cmd_write(sc, WDCMSG_SETUP_TX_QUEUE, &qinfo,
+ sizeof qinfo, 0);
+ if (error != 0)
+ break;
+ }
+ return (error);
+}
+
+static int
+uath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ifreq *ifr = (struct ifreq *) data;
+ int error = 0, startall = 0;
+
+ switch (cmd) {
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP) {
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ uath_init(ifp->if_softc);
+ startall = 1;
+ }
+ } else {
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ uath_stop(ifp);
+ }
+ if (startall)
+ ieee80211_start_all(ic);
+ break;
+ case SIOCGIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &ic->ic_media, cmd);
+ break;
+ case SIOCGIFADDR:
+ error = ether_ioctl(ifp, cmd, data);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+
+static int
+uath_tx_start(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
+ struct uath_data *data)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct uath_chunk *chunk;
+ struct uath_tx_desc *desc;
+ const struct ieee80211_frame *wh;
+ struct ieee80211_key *k;
+ int framelen, msglen;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ data->ni = ni;
+ data->m = m0;
+ chunk = (struct uath_chunk *)data->buf;
+ desc = (struct uath_tx_desc *)(chunk + 1);
+
+ if (bpf_peers_present(ifp->if_bpf)) {
+ struct uath_tx_radiotap_header *tap = &sc->sc_txtap;
+
+ tap->wt_flags = 0;
+ if (m0->m_flags & M_FRAG)
+ tap->wt_flags |= IEEE80211_RADIOTAP_F_FRAG;
+ tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
+ tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
+
+ bpf_mtap2(ifp->if_bpf, tap, sc->sc_txtap_len, m0);
+ }
+
+ wh = mtod(m0, struct ieee80211_frame *);
+ if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
+ k = ieee80211_crypto_encap(ni, m0);
+ if (k == NULL) {
+ m_freem(m0);
+ return (ENOBUFS);
+ }
+
+ /* packet header may have moved, reset our local pointer */
+ wh = mtod(m0, struct ieee80211_frame *);
+ }
+ m_copydata(m0, 0, m0->m_pkthdr.len, (uint8_t *)(desc + 1));
+
+ framelen = m0->m_pkthdr.len + IEEE80211_CRC_LEN;
+ msglen = framelen + sizeof (struct uath_tx_desc);
+ data->buflen = msglen + sizeof (struct uath_chunk);
+
+ /* one chunk only for now */
+ chunk->seqnum = sc->sc_seqnum++;
+ chunk->flags = (m0->m_flags & M_FRAG) ? 0 : UATH_CFLAGS_FINAL;
+ if (m0->m_flags & M_LASTFRAG)
+ chunk->flags |= UATH_CFLAGS_FINAL;
+ chunk->flags = UATH_CFLAGS_FINAL;
+ chunk->length = htobe16(msglen);
+
+ /* fill Tx descriptor */
+ desc->msglen = htobe32(msglen);
+ /* NB: to get UATH_TX_NOTIFY reply, `msgid' must be larger than 0 */
+ desc->msgid = (sc->sc_msgid++) + 1; /* don't care about endianness */
+ desc->type = htobe32(WDCMSG_SEND);
+ switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
+ case IEEE80211_FC0_TYPE_CTL:
+ case IEEE80211_FC0_TYPE_MGT:
+ /* NB: force all management frames to highest queue */
+ if (ni->ni_flags & IEEE80211_NODE_QOS) {
+ /* NB: force all management frames to highest queue */
+ desc->txqid = htobe32(WME_AC_VO | UATH_TXQID_MINRATE);
+ } else
+ desc->txqid = htobe32(WME_AC_BE | UATH_TXQID_MINRATE);
+ break;
+ case IEEE80211_FC0_TYPE_DATA:
+ /* XXX multicast frames should honor mcastrate */
+ desc->txqid = htobe32(M_WME_GETAC(m0));
+ break;
+ default:
+ device_printf(sc->sc_dev, "bogus frame type 0x%x (%s)\n",
+ wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK, __func__);
+ m_freem(m0);
+ return (EIO);
+ }
+ if (sc->sc_state == IEEE80211_S_AUTH ||
+ sc->sc_state == IEEE80211_S_ASSOC ||
+ sc->sc_state == IEEE80211_S_RUN)
+ desc->connid = htobe32(UATH_ID_BSS);
+ else
+ desc->connid = htobe32(UATH_ID_INVALID);
+ desc->flags = htobe32(0 /* no UATH_TX_NOTIFY */);
+ desc->buflen = htobe32(m0->m_pkthdr.len);
+
+#ifdef UATH_DEBUG
+ DPRINTF(sc, UATH_DEBUG_XMIT,
+ "send frame ix %u framelen %d msglen %d connid 0x%x txqid 0x%x\n",
+ desc->msgid, framelen, msglen, be32toh(desc->connid),
+ be32toh(desc->txqid));
+ if (sc->sc_debug & UATH_DEBUG_XMIT_DUMP)
+ uath_dump_cmd(data->buf, data->buflen, '+');
+#endif
+
+ STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next);
+ UATH_STAT_INC(sc, st_tx_pending);
+ usb2_transfer_start(sc->sc_xfer[UATH_BULK_TX]);
+
+ return (0);
+}
+
+/*
+ * Cleanup driver resources when we run out of buffers while processing
+ * fragments; return the tx buffers allocated and drop node references.
+ */
+static void
+uath_txfrag_cleanup(struct uath_softc *sc,
+ uath_datahead *frags, struct ieee80211_node *ni)
+{
+ struct uath_data *bf, *next;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ STAILQ_FOREACH_SAFE(bf, frags, next, next) {
+ /* NB: bf assumed clean */
+ STAILQ_REMOVE_HEAD(frags, next);
+ STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
+ UATH_STAT_INC(sc, st_tx_inactive);
+ ieee80211_node_decref(ni);
+ }
+}
+
+/*
+ * Setup xmit of a fragmented frame. Allocate a buffer for each frag and bump
+ * the node reference count to reflect the held reference to be setup by
+ * uath_tx_start.
+ */
+static int
+uath_txfrag_setup(struct uath_softc *sc, uath_datahead *frags,
+ struct mbuf *m0, struct ieee80211_node *ni)
+{
+ struct mbuf *m;
+ struct uath_data *bf;
+
+ UATH_ASSERT_LOCKED(sc);
+ for (m = m0->m_nextpkt; m != NULL; m = m->m_nextpkt) {
+ bf = uath_getbuf(sc);
+ if (bf == NULL) { /* out of buffers, cleanup */
+ uath_txfrag_cleanup(sc, frags, ni);
+ break;
+ }
+ ieee80211_node_incref(ni);
+ STAILQ_INSERT_TAIL(frags, bf, next);
+ }
+
+ return !STAILQ_EMPTY(frags);
+}
+
+/*
+ * Reclaim mbuf resources. For fragmented frames we need to claim each frag
+ * chained with m_nextpkt.
+ */
+static void
+uath_freetx(struct mbuf *m)
+{
+ struct mbuf *next;
+
+ do {
+ next = m->m_nextpkt;
+ m->m_nextpkt = NULL;
+ m_freem(m);
+ } while ((m = next) != NULL);
+}
+
+static void
+uath_start(struct ifnet *ifp)
+{
+ struct uath_data *bf;
+ struct uath_softc *sc = ifp->if_softc;
+ struct ieee80211_node *ni;
+ struct mbuf *m, *next;
+ uath_datahead frags;
+
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
+ (sc->sc_flags & UATH_FLAG_INVALID))
+ return;
+
+ UATH_LOCK(sc);
+ for (;;) {
+ bf = uath_getbuf(sc);
+ if (bf == NULL)
+ break;
+
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
+ if (m == NULL) {
+ STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
+ UATH_STAT_INC(sc, st_tx_inactive);
+ break;
+ }
+ ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
+ m->m_pkthdr.rcvif = NULL;
+
+ /*
+ * Check for fragmentation. If this frame has been broken up
+ * verify we have enough buffers to send all the fragments
+ * so all go out or none...
+ */
+ STAILQ_INIT(&frags);
+ if ((m->m_flags & M_FRAG) &&
+ !uath_txfrag_setup(sc, &frags, m, ni)) {
+ DPRINTF(sc, UATH_DEBUG_XMIT,
+ "%s: out of txfrag buffers\n", __func__);
+ uath_freetx(m);
+ goto bad;
+ }
+ sc->sc_seqnum = 0;
+ nextfrag:
+ /*
+ * Pass the frame to the h/w for transmission.
+ * Fragmented frames have each frag chained together
+ * with m_nextpkt. We know there are sufficient uath_data's
+ * to send all the frags because of work done by
+ * uath_txfrag_setup.
+ */
+ next = m->m_nextpkt;
+ if (uath_tx_start(sc, m, ni, bf) != 0) {
+ bad:
+ ifp->if_oerrors++;
+ reclaim:
+ STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
+ UATH_STAT_INC(sc, st_tx_inactive);
+ uath_txfrag_cleanup(sc, &frags, ni);
+ ieee80211_free_node(ni);
+ continue;
+ }
+
+ if (next != NULL) {
+ /*
+ * Beware of state changing between frags.
+ XXX check sta power-save state?
+ */
+ if (ni->ni_vap->iv_state != IEEE80211_S_RUN) {
+ DPRINTF(sc, UATH_DEBUG_XMIT,
+ "%s: flush fragmented packet, state %s\n",
+ __func__,
+ ieee80211_state_name[ni->ni_vap->iv_state]);
+ uath_freetx(next);
+ goto reclaim;
+ }
+ m = next;
+ bf = STAILQ_FIRST(&frags);
+ KASSERT(bf != NULL, ("no buf for txfrag"));
+ STAILQ_REMOVE_HEAD(&frags, next);
+ goto nextfrag;
+ }
+
+ sc->sc_tx_timer = 5;
+ }
+ UATH_UNLOCK(sc);
+}
+
+static int
+uath_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
+ const struct ieee80211_bpf_params *params)
+{
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct uath_data *bf;
+ struct uath_softc *sc = ifp->if_softc;
+
+ /* prevent management frames from being sent if we're not ready */
+ if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ m_freem(m);
+ ieee80211_free_node(ni);
+ return (ENETDOWN);
+ }
+
+ UATH_LOCK(sc);
+ /* grab a TX buffer */
+ bf = uath_getbuf(sc);
+ if (bf == NULL) {
+ ieee80211_free_node(ni);
+ m_freem(m);
+ UATH_UNLOCK(sc);
+ return (ENOBUFS);
+ }
+
+ sc->sc_seqnum = 0;
+ if (uath_tx_start(sc, m, ni, bf) != 0) {
+ ieee80211_free_node(ni);
+ ifp->if_oerrors++;
+ STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
+ UATH_STAT_INC(sc, st_tx_inactive);
+ UATH_UNLOCK(sc);
+ return (EIO);
+ }
+ UATH_UNLOCK(sc);
+
+ sc->sc_tx_timer = 5;
+ return (0);
+}
+
+static void
+uath_scan_start(struct ieee80211com *ic)
+{
+ /* do nothing */
+}
+
+static void
+uath_scan_end(struct ieee80211com *ic)
+{
+ /* do nothing */
+}
+
+static void
+uath_set_channel(struct ieee80211com *ic)
+{
+ struct ifnet *ifp = ic->ic_ifp;
+ struct uath_softc *sc = ifp->if_softc;
+
+ UATH_LOCK(sc);
+ (void)uath_switch_channel(sc, ic->ic_curchan);
+ UATH_UNLOCK(sc);
+}
+
+static int
+uath_set_rxmulti_filter(struct uath_softc *sc)
+{
+
+ return (0);
+}
+static void
+uath_update_mcast(struct ifnet *ifp)
+{
+ struct uath_softc *sc = ifp->if_softc;
+
+ /*
+ * this is for avoiding the race condition when we're try to
+ * connect to the AP with WPA.
+ */
+ if (!(sc->sc_flags & UATH_FLAG_INITDONE))
+ return;
+ (void)uath_set_rxmulti_filter(sc);
+}
+
+static void
+uath_update_promisc(struct ifnet *ifp)
+{
+ struct uath_softc *sc = ifp->if_softc;
+
+ if (!(sc->sc_flags & UATH_FLAG_INITDONE))
+ return;
+ uath_set_rxfilter(sc,
+ UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST |
+ UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON |
+ UATH_FILTER_RX_PROM, UATH_FILTER_OP_SET);
+}
+
+static int
+uath_create_connection(struct uath_softc *sc, uint32_t connid)
+{
+ const struct ieee80211_rateset *rs;
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct ieee80211_node *ni = vap->iv_bss;
+ struct uath_cmd_create_connection create;
+
+ bzero(&create, sizeof create);
+ create.connid = htobe32(connid);
+ create.bssid = htobe32(0);
+ /* XXX packed or not? */
+ create.size = htobe32(sizeof(struct uath_cmd_rateset));
+
+ rs = &ni->ni_rates;
+ create.connattr.rateset.length = rs->rs_nrates;
+ bcopy(rs->rs_rates, &create.connattr.rateset.set[0],
+ rs->rs_nrates);
+
+ /* XXX turbo */
+ if (IEEE80211_IS_CHAN_A(ni->ni_chan))
+ create.connattr.wlanmode = htobe32(WLAN_MODE_11a);
+ else if (IEEE80211_IS_CHAN_ANYG(ni->ni_chan))
+ create.connattr.wlanmode = htobe32(WLAN_MODE_11g);
+ else
+ create.connattr.wlanmode = htobe32(WLAN_MODE_11b);
+
+ return uath_cmd_write(sc, WDCMSG_CREATE_CONNECTION, &create,
+ sizeof create, 0);
+}
+
+static int
+uath_set_rates(struct uath_softc *sc, const struct ieee80211_rateset *rs)
+{
+ struct uath_cmd_rates rates;
+
+ bzero(&rates, sizeof rates);
+ rates.connid = htobe32(UATH_ID_BSS); /* XXX */
+ rates.size = htobe32(sizeof(struct uath_cmd_rateset));
+ /* XXX bounds check rs->rs_nrates */
+ rates.rateset.length = rs->rs_nrates;
+ bcopy(rs->rs_rates, &rates.rateset.set[0], rs->rs_nrates);
+
+ DPRINTF(sc, UATH_DEBUG_RATES,
+ "setting supported rates nrates=%d\n", rs->rs_nrates);
+ return uath_cmd_write(sc, WDCMSG_SET_BASIC_RATE,
+ &rates, sizeof rates, 0);
+}
+
+static int
+uath_write_associd(struct uath_softc *sc)
+{
+ struct ieee80211com *ic = sc->sc_ifp->if_l2com;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+ struct ieee80211_node *ni = vap->iv_bss;
+ struct uath_cmd_set_associd associd;
+
+ bzero(&associd, sizeof associd);
+ associd.defaultrateix = htobe32(1); /* XXX */
+ associd.associd = htobe32(ni->ni_associd);
+ associd.timoffset = htobe32(0x3b); /* XXX */
+ IEEE80211_ADDR_COPY(associd.bssid, ni->ni_bssid);
+ return uath_cmd_write(sc, WDCMSG_WRITE_ASSOCID, &associd,
+ sizeof associd, 0);
+}
+
+static int
+uath_set_ledsteady(struct uath_softc *sc, int lednum, int ledmode)
+{
+ struct uath_cmd_ledsteady led;
+
+ led.lednum = htobe32(lednum);
+ led.ledmode = htobe32(ledmode);
+
+ DPRINTF(sc, UATH_DEBUG_LED, "set %s led %s (steady)\n",
+ (lednum == UATH_LED_LINK) ? "link" : "activity",
+ ledmode ? "on" : "off");
+ return uath_cmd_write(sc, WDCMSG_SET_LED_STEADY, &led, sizeof led, 0);
+}
+
+static int
+uath_set_ledblink(struct uath_softc *sc, int lednum, int ledmode,
+ int blinkrate, int slowmode)
+{
+ struct uath_cmd_ledblink led;
+
+ led.lednum = htobe32(lednum);
+ led.ledmode = htobe32(ledmode);
+ led.blinkrate = htobe32(blinkrate);
+ led.slowmode = htobe32(slowmode);
+
+ DPRINTF(sc, UATH_DEBUG_LED, "set %s led %s (blink)\n",
+ (lednum == UATH_LED_LINK) ? "link" : "activity",
+ ledmode ? "on" : "off");
+ return uath_cmd_write(sc, WDCMSG_SET_LED_BLINK, &led, sizeof led, 0);
+}
+
+static int
+uath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
+{
+ enum ieee80211_state ostate = vap->iv_state;
+ int error;
+ struct ieee80211_node *ni = vap->iv_bss;
+ struct ieee80211com *ic = vap->iv_ic;
+ struct uath_softc *sc = ic->ic_ifp->if_softc;
+ struct uath_vap *uvp = UATH_VAP(vap);
+
+ DPRINTF(sc, UATH_DEBUG_STATE,
+ "%s: %s -> %s\n", __func__, ieee80211_state_name[vap->iv_state],
+ ieee80211_state_name[nstate]);
+
+ UATH_LOCK(sc);
+
+ callout_stop(&sc->stat_ch);
+ callout_stop(&sc->watchdog_ch);
+ sc->sc_state = nstate;
+
+ switch (nstate) {
+ case IEEE80211_S_INIT:
+ if (ostate == IEEE80211_S_RUN) {
+ /* turn link and activity LEDs off */
+ uath_set_ledstate(sc, 0);
+ }
+ break;
+
+ case IEEE80211_S_SCAN:
+ break;
+
+ case IEEE80211_S_AUTH:
+ /* XXX good place? set RTS threshold */
+ uath_config(sc, CFG_USER_RTS_THRESHOLD, vap->iv_rtsthreshold);
+ /* XXX bad place */
+ error = uath_set_keys(sc, vap);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "could not set crypto keys, error %d\n", error);
+ break;
+ }
+ if (uath_switch_channel(sc, ni->ni_chan) != 0) {
+ device_printf(sc->sc_dev, "could not switch channel\n");
+ break;
+ }
+ if (uath_create_connection(sc, UATH_ID_BSS) != 0) {
+ device_printf(sc->sc_dev,
+ "could not create connection\n");
+ break;
+ }
+ break;
+
+ case IEEE80211_S_ASSOC:
+ if (uath_set_rates(sc, &ni->ni_rates) != 0) {
+ device_printf(sc->sc_dev,
+ "could not set negotiated rate set\n");
+ break;
+ }
+ break;
+
+ case IEEE80211_S_RUN:
+ /* XXX monitor mode doesn't be tested */
+ if (ic->ic_opmode == IEEE80211_M_MONITOR) {
+ uath_set_ledstate(sc, 1);
+ break;
+ }
+
+ /*
+ * Tx rate is controlled by firmware, report the maximum
+ * negotiated rate in ifconfig output.
+ */
+ ni->ni_txrate = ni->ni_rates.rs_rates[ni->ni_rates.rs_nrates-1];
+
+ if (uath_write_associd(sc) != 0) {
+ device_printf(sc->sc_dev,
+ "could not write association id\n");
+ break;
+ }
+ /* turn link LED on */
+ uath_set_ledsteady(sc, UATH_LED_LINK, UATH_LED_ON);
+ /* make activity LED blink */
+ uath_set_ledblink(sc, UATH_LED_ACTIVITY, UATH_LED_ON, 1, 2);
+ /* set state to associated */
+ uath_set_ledstate(sc, 1);
+
+ /* start statistics timer */
+ callout_reset(&sc->stat_ch, hz, uath_stat, sc);
+ break;
+ default:
+ break;
+ }
+ UATH_UNLOCK(sc);
+
+ IEEE80211_LOCK(ic);
+ uvp->newstate(vap, nstate, arg);
+ if (vap->iv_newstate_cb != NULL)
+ vap->iv_newstate_cb(vap, nstate, arg);
+ IEEE80211_UNLOCK(ic);
+
+ return (0);
+}
+
+static int
+uath_set_key(struct uath_softc *sc, const struct ieee80211_key *wk,
+ int index)
+{
+#if 0
+ struct uath_cmd_crypto crypto;
+ int i;
+
+ bzero(&crypto, sizeof crypto);
+ crypto.keyidx = htobe32(index);
+ crypto.magic1 = htobe32(1);
+ crypto.size = htobe32(368);
+ crypto.mask = htobe32(0xffff);
+ crypto.flags = htobe32(0x80000068);
+ if (index != UATH_DEFAULT_KEY)
+ crypto.flags |= htobe32(index << 16);
+ memset(crypto.magic2, 0xff, sizeof crypto.magic2);
+
+ /*
+ * Each byte of the key must be XOR'ed with 10101010 before being
+ * transmitted to the firmware.
+ */
+ for (i = 0; i < wk->wk_keylen; i++)
+ crypto.key[i] = wk->wk_key[i] ^ 0xaa;
+
+ DPRINTF(sc, UATH_DEBUG_CRYPTO,
+ "setting crypto key index=%d len=%d\n", index, wk->wk_keylen);
+ return uath_cmd_write(sc, WDCMSG_SET_KEY_CACHE_ENTRY, &crypto,
+ sizeof crypto, 0);
+#else
+ /* XXX support H/W cryto */
+ return (0);
+#endif
+}
+
+static int
+uath_set_keys(struct uath_softc *sc, struct ieee80211vap *vap)
+{
+ int i, error;
+
+ error = 0;
+ for (i = 0; i < IEEE80211_WEP_NKID; i++) {
+ const struct ieee80211_key *wk = &vap->iv_nw_keys[i];
+
+ if (wk->wk_flags & (IEEE80211_KEY_XMIT|IEEE80211_KEY_RECV)) {
+ error = uath_set_key(sc, wk, i);
+ if (error)
+ return (error);
+ }
+ }
+ if (vap->iv_def_txkey != IEEE80211_KEYIX_NONE) {
+ error = uath_set_key(sc, &vap->iv_nw_keys[vap->iv_def_txkey],
+ UATH_DEFAULT_KEY);
+ }
+ return (error);
+}
+
+#define UATH_SYSCTL_STAT_ADD32(c, h, n, p, d) \
+ SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d)
+
+static void
+uath_sysctl_node(struct uath_softc *sc)
+{
+ struct sysctl_ctx_list *ctx;
+ struct sysctl_oid_list *child;
+ struct sysctl_oid *tree;
+ struct uath_stat *stats;
+
+ stats = &sc->sc_stat;
+ ctx = device_get_sysctl_ctx(sc->sc_dev);
+ child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->sc_dev));
+
+ tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
+ NULL, "UATH statistics");
+ child = SYSCTL_CHILDREN(tree);
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "badchunkseqnum",
+ &stats->st_badchunkseqnum, "Bad chunk sequence numbers");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "invalidlen", &stats->st_invalidlen,
+ "Invalid length");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "multichunk", &stats->st_multichunk,
+ "Multi chunks");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "toobigrxpkt",
+ &stats->st_toobigrxpkt, "Too big rx packets");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "stopinprogress",
+ &stats->st_stopinprogress, "Stop in progress");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "crcerrs", &stats->st_crcerr,
+ "CRC errors");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "phyerr", &stats->st_phyerr,
+ "PHY errors");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "decrypt_crcerr",
+ &stats->st_decrypt_crcerr, "Decryption CRC errors");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "decrypt_micerr",
+ &stats->st_decrypt_micerr, "Decryption Misc errors");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "decomperr", &stats->st_decomperr,
+ "Decomp errors");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "keyerr", &stats->st_keyerr,
+ "Key errors");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "err", &stats->st_err,
+ "Unknown errors");
+
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_active",
+ &stats->st_cmd_active, "Active numbers in Command queue");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_inactive",
+ &stats->st_cmd_inactive, "Inactive numbers in Command queue");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_pending",
+ &stats->st_cmd_pending, "Pending numbers in Command queue");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "cmd_waiting",
+ &stats->st_cmd_waiting, "Waiting numbers in Command queue");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "rx_active",
+ &stats->st_rx_active, "Active numbers in RX queue");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "rx_inactive",
+ &stats->st_rx_inactive, "Inactive numbers in RX queue");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_active",
+ &stats->st_tx_active, "Active numbers in TX queue");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_inactive",
+ &stats->st_tx_inactive, "Inactive numbers in TX queue");
+ UATH_SYSCTL_STAT_ADD32(ctx, child, "tx_pending",
+ &stats->st_tx_pending, "Pending numbers in TX queue");
+}
+
+#undef UATH_SYSCTL_STAT_ADD32
+
+static void
+uath_cmdeof(struct uath_softc *sc, struct uath_cmd *cmd)
+{
+ struct uath_cmd_hdr *hdr;
+ int dlen;
+
+ hdr = (struct uath_cmd_hdr *)cmd->buf;
+ /* NB: msgid is passed thru w/o byte swapping */
+#ifdef UATH_DEBUG
+ if (sc->sc_debug & UATH_DEBUG_CMDS) {
+ int len = be32toh(hdr->len);
+ printf("%s: %s [ix %u] len %u status %u\n",
+ __func__, uath_codename(be32toh(hdr->code)),
+ hdr->msgid, len, be32toh(hdr->magic));
+ if (sc->sc_debug & UATH_DEBUG_CMDS_DUMP)
+ uath_dump_cmd(cmd->buf,
+ len > UATH_MAX_CMDSZ ? sizeof(*hdr) : len, '-');
+ }
+#endif
+ hdr->code = be32toh(hdr->code);
+ hdr->len = be32toh(hdr->len);
+ hdr->magic = be32toh(hdr->magic); /* target status on return */
+
+ switch (hdr->code & 0xff) {
+ /* reply to a read command */
+ default:
+ dlen = hdr->len - sizeof(*hdr);
+ DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
+ "%s: code %d data len %u\n",
+ __func__, hdr->code & 0xff, dlen);
+ /*
+ * The first response from the target after the
+ * HOST_AVAILABLE has an invalid msgid so we must
+ * treat it specially.
+ */
+ if (hdr->msgid < UATH_CMD_LIST_COUNT) {
+ uint32_t *rp = (uint32_t *)(hdr+1);
+ u_int olen;
+
+ if (!(sizeof(*hdr) <= hdr->len &&
+ hdr->len < UATH_MAX_CMDSZ)) {
+ device_printf(sc->sc_dev,
+ "%s: invalid WDC msg length %u; "
+ "msg ignored\n", __func__, hdr->len);
+ return;
+ }
+ /*
+ * Calculate return/receive payload size; the
+ * first word, if present, always gives the
+ * number of bytes--unless it's 0 in which
+ * case a single 32-bit word should be present.
+ */
+ if (dlen >= sizeof(uint32_t)) {
+ olen = be32toh(rp[0]);
+ dlen -= sizeof(uint32_t);
+ if (olen == 0) {
+ /* convention is 0 =>'s one word */
+ olen = sizeof(uint32_t);
+ /* XXX KASSERT(olen == dlen ) */
+ }
+ } else
+ olen = 0;
+ if (cmd->odata != NULL) {
+ /* NB: cmd->olen validated in uath_cmd */
+ if (olen > cmd->olen) {
+ /* XXX complain? */
+ device_printf(sc->sc_dev,
+ "%s: cmd 0x%x olen %u cmd olen %u\n",
+ __func__, hdr->code, olen,
+ cmd->olen);
+ olen = cmd->olen;
+ }
+ if (olen > dlen) {
+ /* XXX complain, shouldn't happen */
+ device_printf(sc->sc_dev,
+ "%s: cmd 0x%x olen %u dlen %u\n",
+ __func__, hdr->code, olen, dlen);
+ olen = dlen;
+ }
+ /* XXX have submitter do this */
+ /* copy answer into caller's supplied buffer */
+ bcopy(&rp[1], cmd->odata, olen);
+ cmd->olen = olen;
+ }
+ }
+ wakeup_one(cmd); /* wake up caller */
+ break;
+
+ case WDCMSG_TARGET_START:
+ if (hdr->msgid >= UATH_CMD_LIST_COUNT) {
+ /* XXX */
+ return;
+ }
+ dlen = hdr->len - sizeof(*hdr);
+ if (dlen != sizeof(uint32_t)) {
+ /* XXX something wrong */
+ return;
+ }
+ /* XXX have submitter do this */
+ /* copy answer into caller's supplied buffer */
+ bcopy(hdr+1, cmd->odata, sizeof(uint32_t));
+ cmd->olen = sizeof(uint32_t);
+ wakeup_one(cmd); /* wake up caller */
+ break;
+
+ case WDCMSG_SEND_COMPLETE:
+ /* this notification is sent when UATH_TX_NOTIFY is set */
+ DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
+ "%s: received Tx notification\n", __func__);
+ break;
+
+ case WDCMSG_TARGET_GET_STATS:
+ DPRINTF(sc, UATH_DEBUG_RX_PROC | UATH_DEBUG_RECV_ALL,
+ "%s: received device statistics\n", __func__);
+ callout_reset(&sc->stat_ch, hz, uath_stat, sc);
+ break;
+ }
+}
+
+static void
+uath_intr_rx_callback(struct usb2_xfer *xfer)
+{
+ struct uath_softc *sc = xfer->priv_sc;
+ struct uath_cmd *cmd;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ cmd = STAILQ_FIRST(&sc->sc_cmd_waiting);
+ if (cmd == NULL)
+ goto setup;
+ STAILQ_REMOVE_HEAD(&sc->sc_cmd_waiting, next);
+ UATH_STAT_DEC(sc, st_cmd_waiting);
+ STAILQ_INSERT_TAIL(&sc->sc_cmd_inactive, cmd, next);
+ UATH_STAT_INC(sc, st_cmd_inactive);
+
+ KASSERT(xfer->actlen >= sizeof(struct uath_cmd_hdr),
+ ("short xfer error"));
+ usb2_copy_out(xfer->frbuffers, 0, cmd->buf, xfer->actlen);
+ uath_cmdeof(sc, cmd);
+ case USB_ST_SETUP:
+setup:
+ xfer->frlengths[0] = xfer->max_data_length;
+ usb2_start_hardware(xfer);
+ break;
+ default:
+ if (xfer->error != USB_ERR_CANCELLED) {
+ xfer->flags.stall_pipe = 1;
+ goto setup;
+ }
+ break;
+ }
+}
+
+static void
+uath_intr_tx_callback(struct usb2_xfer *xfer)
+{
+ struct uath_softc *sc = xfer->priv_sc;
+ struct uath_cmd *cmd;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ cmd = STAILQ_FIRST(&sc->sc_cmd_active);
+ if (cmd == NULL)
+ goto setup;
+ STAILQ_REMOVE_HEAD(&sc->sc_cmd_active, next);
+ UATH_STAT_DEC(sc, st_cmd_active);
+ STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_READ) ?
+ &sc->sc_cmd_waiting : &sc->sc_cmd_inactive, cmd, next);
+ if (cmd->flags & UATH_CMD_FLAG_READ)
+ UATH_STAT_INC(sc, st_cmd_waiting);
+ else
+ UATH_STAT_INC(sc, st_cmd_inactive);
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+setup:
+ cmd = STAILQ_FIRST(&sc->sc_cmd_pending);
+ if (cmd == NULL) {
+ DPRINTF(sc, UATH_DEBUG_XMIT, "%s: empty pending queue\n",
+ __func__);
+ return;
+ }
+ STAILQ_REMOVE_HEAD(&sc->sc_cmd_pending, next);
+ UATH_STAT_DEC(sc, st_cmd_pending);
+ STAILQ_INSERT_TAIL((cmd->flags & UATH_CMD_FLAG_ASYNC) ?
+ &sc->sc_cmd_inactive : &sc->sc_cmd_active, cmd, next);
+ if (cmd->flags & UATH_CMD_FLAG_ASYNC)
+ UATH_STAT_INC(sc, st_cmd_inactive);
+ else
+ UATH_STAT_INC(sc, st_cmd_active);
+
+ usb2_set_frame_data(xfer, cmd->buf, 0);
+ xfer->frlengths[0] = cmd->buflen;
+ usb2_start_hardware(xfer);
+ break;
+ default:
+ if (xfer->error != USB_ERR_CANCELLED) {
+ xfer->flags.stall_pipe = 1;
+ goto setup;
+ }
+ break;
+ }
+}
+
+static void
+uath_update_rxstat(struct uath_softc *sc, uint32_t status)
+{
+
+ switch (status) {
+ case UATH_STATUS_STOP_IN_PROGRESS:
+ UATH_STAT_INC(sc, st_stopinprogress);
+ break;
+ case UATH_STATUS_CRC_ERR:
+ UATH_STAT_INC(sc, st_crcerr);
+ break;
+ case UATH_STATUS_PHY_ERR:
+ UATH_STAT_INC(sc, st_phyerr);
+ break;
+ case UATH_STATUS_DECRYPT_CRC_ERR:
+ UATH_STAT_INC(sc, st_decrypt_crcerr);
+ break;
+ case UATH_STATUS_DECRYPT_MIC_ERR:
+ UATH_STAT_INC(sc, st_decrypt_micerr);
+ break;
+ case UATH_STATUS_DECOMP_ERR:
+ UATH_STAT_INC(sc, st_decomperr);
+ break;
+ case UATH_STATUS_KEY_ERR:
+ UATH_STAT_INC(sc, st_keyerr);
+ break;
+ case UATH_STATUS_ERR:
+ UATH_STAT_INC(sc, st_err);
+ break;
+ default:
+ break;
+ }
+}
+
+static struct mbuf *
+uath_data_rxeof(struct usb2_xfer *xfer, struct uath_data *data,
+ struct uath_rx_desc **pdesc)
+{
+ struct uath_softc *sc = xfer->priv_sc;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct uath_chunk *chunk;
+ struct uath_rx_desc *desc;
+ struct mbuf *m = data->m, *mnew, *mp;
+ uint16_t chunklen;
+
+ if (xfer->actlen < UATH_MIN_RXBUFSZ) {
+ DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
+ "%s: wrong xfer size (len=%d)\n", __func__, xfer->actlen);
+ ifp->if_ierrors++;
+ return (NULL);
+ }
+
+ chunk = (struct uath_chunk *)data->buf;
+ if (chunk->seqnum == 0 && chunk->flags == 0 && chunk->length == 0) {
+ device_printf(sc->sc_dev, "%s: strange response\n", __func__);
+ ifp->if_ierrors++;
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
+ if (chunk->seqnum != sc->sc_intrx_nextnum) {
+ DPRINTF(sc, UATH_DEBUG_XMIT, "invalid seqnum %d, expected %d\n",
+ chunk->seqnum, sc->sc_intrx_nextnum);
+ UATH_STAT_INC(sc, st_badchunkseqnum);
+ if (sc->sc_intrx_head != NULL)
+ m_freem(sc->sc_intrx_head);
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
+ /* check multi-chunk frames */
+ if ((chunk->seqnum == 0 && !(chunk->flags & UATH_CFLAGS_FINAL)) ||
+ (chunk->seqnum != 0 && (chunk->flags & UATH_CFLAGS_FINAL)) ||
+ chunk->flags & UATH_CFLAGS_RXMSG)
+ UATH_STAT_INC(sc, st_multichunk);
+
+ chunklen = be16toh(chunk->length);
+ if (chunk->flags & UATH_CFLAGS_FINAL)
+ chunklen -= sizeof(struct uath_rx_desc);
+
+ if (chunklen > 0 &&
+ (!(chunk->flags & UATH_CFLAGS_FINAL) || !(chunk->seqnum == 0))) {
+ /* we should use intermediate RX buffer */
+ if (chunk->seqnum == 0)
+ UATH_RESET_INTRX(sc);
+ if ((sc->sc_intrx_len + sizeof(struct uath_rx_desc) +
+ chunklen) > UATH_MAX_INTRX_SIZE) {
+ UATH_STAT_INC(sc, st_invalidlen);
+ ifp->if_iqdrops++;
+ if (sc->sc_intrx_head != NULL)
+ m_freem(sc->sc_intrx_head);
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
+ m->m_len = chunklen;
+ m->m_data += sizeof(struct uath_chunk);
+
+ if (sc->sc_intrx_head == NULL) {
+ sc->sc_intrx_head = m;
+ sc->sc_intrx_tail = m;
+ } else {
+ m->m_flags &= ~M_PKTHDR;
+ sc->sc_intrx_tail->m_next = m;
+ sc->sc_intrx_tail = m;
+ }
+ }
+ sc->sc_intrx_len += chunklen;
+
+ mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (mnew == NULL) {
+ DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
+ "%s: can't get new mbuf, drop frame\n", __func__);
+ ifp->if_ierrors++;
+ if (sc->sc_intrx_head != NULL)
+ m_freem(sc->sc_intrx_head);
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
+ data->m = mnew;
+ data->buf = mtod(mnew, uint8_t *);
+
+ /* if the frame is not final continue the transfer */
+ if (!(chunk->flags & UATH_CFLAGS_FINAL)) {
+ sc->sc_intrx_nextnum++;
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
+ /*
+ * if the frame is not set UATH_CFLAGS_RXMSG, then rx descriptor is
+ * located at the end, 32-bit aligned
+ */
+ desc = (chunk->flags & UATH_CFLAGS_RXMSG) ?
+ (struct uath_rx_desc *)(chunk + 1) :
+ (struct uath_rx_desc *)(((uint8_t *)chunk) +
+ sizeof(struct uath_chunk) + be16toh(chunk->length) -
+ sizeof(struct uath_rx_desc));
+ *pdesc = desc;
+
+ DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
+ "%s: frame len %u code %u status %u rate %u antenna %u "
+ "rssi %d channel %u phyerror %u connix %u decrypterror %u "
+ "keycachemiss %u\n", __func__, be32toh(desc->framelen)
+ , be32toh(desc->code), be32toh(desc->status), be32toh(desc->rate)
+ , be32toh(desc->antenna), be32toh(desc->rssi), be32toh(desc->channel)
+ , be32toh(desc->phyerror), be32toh(desc->connix)
+ , be32toh(desc->decrypterror), be32toh(desc->keycachemiss));
+
+ if (be32toh(desc->len) > MCLBYTES) {
+ DPRINTF(sc, UATH_DEBUG_RECV | UATH_DEBUG_RECV_ALL,
+ "%s: bad descriptor (len=%d)\n", __func__,
+ be32toh(desc->len));
+ ifp->if_iqdrops++;
+ UATH_STAT_INC(sc, st_toobigrxpkt);
+ if (sc->sc_intrx_head != NULL)
+ m_freem(sc->sc_intrx_head);
+ UATH_RESET_INTRX(sc);
+ return (NULL);
+ }
+
+ uath_update_rxstat(sc, be32toh(desc->status));
+
+ /* finalize mbuf */
+ if (sc->sc_intrx_head == NULL) {
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len =
+ be32toh(desc->framelen) - UATH_RX_DUMMYSIZE;
+ m->m_data += sizeof(struct uath_chunk);
+ } else {
+ mp = sc->sc_intrx_head;
+ mp->m_pkthdr.rcvif = ifp;
+ mp->m_flags |= M_PKTHDR;
+ mp->m_pkthdr.len = sc->sc_intrx_len;
+ m = mp;
+ }
+
+ /* there are a lot more fields in the RX descriptor */
+ if (bpf_peers_present(ifp->if_bpf)) {
+ struct uath_rx_radiotap_header *tap = &sc->sc_rxtap;
+
+ tap->wr_chan_freq = htole16(be32toh(desc->channel));
+ tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
+ tap->wr_dbm_antsignal = (int8_t)be32toh(desc->rssi);
+
+ bpf_mtap2(ifp->if_bpf, tap, sc->sc_rxtap_len, m);
+ }
+
+ ifp->if_ipackets++;
+ UATH_RESET_INTRX(sc);
+
+ return (m);
+}
+
+static void
+uath_bulk_rx_callback(struct usb2_xfer *xfer)
+{
+ struct uath_softc *sc = xfer->priv_sc;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211_frame *wh;
+ struct ieee80211_node *ni;
+ struct mbuf *m = NULL;
+ struct uath_data *data;
+ struct uath_rx_desc *desc = NULL;
+ int8_t nf;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ data = STAILQ_FIRST(&sc->sc_rx_active);
+ if (data == NULL)
+ goto setup;
+ STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next);
+ UATH_STAT_DEC(sc, st_rx_active);
+ m = uath_data_rxeof(xfer, data, &desc);
+ STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
+ UATH_STAT_INC(sc, st_rx_inactive);
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+setup:
+ data = STAILQ_FIRST(&sc->sc_rx_inactive);
+ if (data == NULL)
+ return;
+ STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next);
+ UATH_STAT_DEC(sc, st_rx_inactive);
+ STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
+ UATH_STAT_INC(sc, st_rx_active);
+ usb2_set_frame_data(xfer, data->buf, 0);
+ xfer->frlengths[0] = xfer->max_data_length;
+ usb2_start_hardware(xfer);
+
+ /*
+ * To avoid LOR we should unlock our private mutex here to call
+ * ieee80211_input() because here is at the end of a USB
+ * callback and safe to unlock.
+ */
+ UATH_UNLOCK(sc);
+ if (m != NULL && desc != NULL) {
+ wh = mtod(m, struct ieee80211_frame *);
+ ni = ieee80211_find_rxnode(ic,
+ (struct ieee80211_frame_min *)wh);
+ nf = -95; /* XXX */
+ if (ni != NULL) {
+ (void) ieee80211_input(ni, m,
+ (int)be32toh(desc->rssi), nf, 0);
+ /* node is no longer needed */
+ ieee80211_free_node(ni);
+ } else
+ (void) ieee80211_input_all(ic, m,
+ (int)be32toh(desc->rssi), nf, 0);
+ m = NULL;
+ desc = NULL;
+ }
+ UATH_LOCK(sc);
+ break;
+ default:
+ /* needs it to the inactive queue due to a error. */
+ data = STAILQ_FIRST(&sc->sc_rx_active);
+ if (data != NULL) {
+ STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next);
+ UATH_STAT_DEC(sc, st_rx_active);
+ STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
+ UATH_STAT_INC(sc, st_rx_inactive);
+ }
+ if (xfer->error != USB_ERR_CANCELLED) {
+ xfer->flags.stall_pipe = 1;
+ ifp->if_ierrors++;
+ goto setup;
+ }
+ break;
+ }
+}
+
+static void
+uath_data_txeof(struct usb2_xfer *xfer, struct uath_data *data)
+{
+ struct uath_softc *sc = xfer->priv_sc;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct mbuf *m;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ /*
+ * Do any tx complete callback. Note this must be done before releasing
+ * the node reference.
+ */
+ if (data->m) {
+ m = data->m;
+ if (m->m_flags & M_TXCB) {
+ /* XXX status? */
+ ieee80211_process_callback(data->ni, m, 0);
+ }
+ m_freem(m);
+ data->m = NULL;
+ }
+ if (data->ni) {
+ ieee80211_free_node(data->ni);
+ data->ni = NULL;
+ }
+ sc->sc_tx_timer = 0;
+ ifp->if_opackets++;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+}
+
+static void
+uath_bulk_tx_callback(struct usb2_xfer *xfer)
+{
+ struct uath_softc *sc = xfer->priv_sc;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct uath_data *data;
+
+ UATH_ASSERT_LOCKED(sc);
+
+ switch (USB_GET_STATE(xfer)) {
+ case USB_ST_TRANSFERRED:
+ data = STAILQ_FIRST(&sc->sc_tx_active);
+ if (data == NULL)
+ goto setup;
+ STAILQ_REMOVE_HEAD(&sc->sc_tx_active, next);
+ UATH_STAT_DEC(sc, st_tx_active);
+ uath_data_txeof(xfer, data);
+ STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
+ UATH_STAT_INC(sc, st_tx_inactive);
+ /* FALLTHROUGH */
+ case USB_ST_SETUP:
+setup:
+ data = STAILQ_FIRST(&sc->sc_tx_pending);
+ if (data == NULL) {
+ DPRINTF(sc, UATH_DEBUG_XMIT, "%s: empty pending queue\n",
+ __func__);
+ return;
+ }
+ STAILQ_REMOVE_HEAD(&sc->sc_tx_pending, next);
+ UATH_STAT_DEC(sc, st_tx_pending);
+ STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next);
+ UATH_STAT_INC(sc, st_tx_active);
+
+ usb2_set_frame_data(xfer, data->buf, 0);
+ xfer->frlengths[0] = data->buflen;
+ usb2_start_hardware(xfer);
+
+ UATH_UNLOCK(sc);
+ uath_start(ifp);
+ UATH_LOCK(sc);
+ break;
+ default:
+ data = STAILQ_FIRST(&sc->sc_tx_active);
+ if (data == NULL)
+ goto setup;
+ if (data->ni != NULL) {
+ ieee80211_free_node(data->ni);
+ data->ni = NULL;
+ ifp->if_oerrors++;
+ }
+ if (xfer->error != USB_ERR_CANCELLED) {
+ xfer->flags.stall_pipe = 1;
+ goto setup;
+ }
+ break;
+ }
+}
+
+static device_method_t uath_methods[] = {
+ DEVMETHOD(device_probe, uath_match),
+ DEVMETHOD(device_attach, uath_attach),
+ DEVMETHOD(device_detach, uath_detach),
+ { 0, 0 }
+};
+static driver_t uath_driver = {
+ "uath",
+ uath_methods,
+ sizeof(struct uath_softc)
+};
+static devclass_t uath_devclass;
+
+DRIVER_MODULE(uath, uhub, uath_driver, uath_devclass, NULL, 0);
+MODULE_DEPEND(uath, wlan, 1, 1, 1);
+MODULE_DEPEND(uath, usb, 1, 1, 1);
diff --git a/sys/dev/usb/wlan/if_uathreg.h b/sys/dev/usb/wlan/if_uathreg.h
new file mode 100644
index 0000000..1e7929b
--- /dev/null
+++ b/sys/dev/usb/wlan/if_uathreg.h
@@ -0,0 +1,601 @@
+/* $OpenBSD: if_uathreg.h,v 1.2 2006/09/18 16:34:23 damien Exp $ */
+/* $FreeBSD$ */
+
+/*-
+ * Copyright (c) 2006
+ * Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ *
+ * 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.
+ */
+
+#define UATH_CONFIG_INDEX 0
+#define UATH_IFACE_INDEX 0
+
+/* all fields are big endian */
+struct uath_fwblock {
+ uint32_t flags;
+#define UATH_WRITE_BLOCK (1 << 4)
+
+ uint32_t len;
+#define UATH_MAX_FWBLOCK_SIZE 2048
+
+ uint32_t total;
+ uint32_t remain;
+ uint32_t rxtotal;
+ uint32_t pad[123];
+} __packed;
+
+#define UATH_MAX_CMDSZ 512
+
+/*
+ * Messages are passed in Target Endianness. All fixed-size
+ * fields of a WDS Control Message are treated as 32-bit
+ * values and Control Msgs are guaranteed to be 32-bit aligned.
+ *
+ * The format of a WDS Control Message is as follows:
+ * Message Length 32 bits
+ * Message Opcode 32 bits
+ * Message ID 32 bits
+ * parameter 1
+ * parameter 2
+ * ...
+ *
+ * A variable-length parameter, or a parmeter that is larger than
+ * 32 bits is passed as <length, data> pair, where length is a
+ * 32-bit quantity and data is padded to 32 bits.
+ */
+struct uath_cmd_hdr {
+ uint32_t len; /* msg length including header */
+ uint32_t code; /* operation code */
+/* NB: these are defined for rev 1.5 firmware; rev 1.6 is different */
+/* messages from Host -> Target */
+#define WDCMSG_HOST_AVAILABLE 0x01
+#define WDCMSG_BIND 0x02
+#define WDCMSG_TARGET_RESET 0x03
+#define WDCMSG_TARGET_GET_CAPABILITY 0x04
+#define WDCMSG_TARGET_SET_CONFIG 0x05
+#define WDCMSG_TARGET_GET_STATUS 0x06
+#define WDCMSG_TARGET_GET_STATS 0x07
+#define WDCMSG_TARGET_START 0x08
+#define WDCMSG_TARGET_STOP 0x09
+#define WDCMSG_TARGET_ENABLE 0x0a
+#define WDCMSG_TARGET_DISABLE 0x0b
+#define WDCMSG_CREATE_CONNECTION 0x0c
+#define WDCMSG_UPDATE_CONNECT_ATTR 0x0d
+#define WDCMSG_DELETE_CONNECT 0x0e
+#define WDCMSG_SEND 0x0f
+#define WDCMSG_FLUSH 0x10
+/* messages from Target -> Host */
+#define WDCMSG_STATS_UPDATE 0x11
+#define WDCMSG_BMISS 0x12
+#define WDCMSG_DEVICE_AVAIL 0x13
+#define WDCMSG_SEND_COMPLETE 0x14
+#define WDCMSG_DATA_AVAIL 0x15
+#define WDCMSG_SET_PWR_MODE 0x16
+#define WDCMSG_BMISS_ACK 0x17
+#define WDCMSG_SET_LED_STEADY 0x18
+#define WDCMSG_SET_LED_BLINK 0x19
+/* more messages */
+#define WDCMSG_SETUP_BEACON_DESC 0x1a
+#define WDCMSG_BEACON_INIT 0x1b
+#define WDCMSG_RESET_KEY_CACHE 0x1c
+#define WDCMSG_RESET_KEY_CACHE_ENTRY 0x1d
+#define WDCMSG_SET_KEY_CACHE_ENTRY 0x1e
+#define WDCMSG_SET_DECOMP_MASK 0x1f
+#define WDCMSG_SET_REGULATORY_DOMAIN 0x20
+#define WDCMSG_SET_LED_STATE 0x21
+#define WDCMSG_WRITE_ASSOCID 0x22
+#define WDCMSG_SET_STA_BEACON_TIMERS 0x23
+#define WDCMSG_GET_TSF 0x24
+#define WDCMSG_RESET_TSF 0x25
+#define WDCMSG_SET_ADHOC_MODE 0x26
+#define WDCMSG_SET_BASIC_RATE 0x27
+#define WDCMSG_MIB_CONTROL 0x28
+#define WDCMSG_GET_CHANNEL_DATA 0x29
+#define WDCMSG_GET_CUR_RSSI 0x2a
+#define WDCMSG_SET_ANTENNA_SWITCH 0x2b
+#define WDCMSG_USE_SHORT_SLOT_TIME 0x2f
+#define WDCMSG_SET_POWER_MODE 0x30
+#define WDCMSG_SETUP_PSPOLL_DESC 0x31
+#define WDCMSG_SET_RX_MULTICAST_FILTER 0x32
+#define WDCMSG_RX_FILTER 0x33
+#define WDCMSG_PER_CALIBRATION 0x34
+#define WDCMSG_RESET 0x35
+#define WDCMSG_DISABLE 0x36
+#define WDCMSG_PHY_DISABLE 0x37
+#define WDCMSG_SET_TX_POWER_LIMIT 0x38
+#define WDCMSG_SET_TX_QUEUE_PARAMS 0x39
+#define WDCMSG_SETUP_TX_QUEUE 0x3a
+#define WDCMSG_RELEASE_TX_QUEUE 0x3b
+#define WDCMSG_SET_DEFAULT_KEY 0x43
+ uint32_t msgid; /* msg id (supplied by host) */
+ uint32_t magic; /* response desired/target status */
+ uint32_t debug[4]; /* debug data area */
+ /* msg data follows */
+} __packed;
+
+struct uath_chunk {
+ uint8_t seqnum; /* sequence number for ordering */
+ uint8_t flags;
+#define UATH_CFLAGS_FINAL 0x01 /* final chunk of a msg */
+#define UATH_CFLAGS_RXMSG 0x02 /* chunk contains rx completion */
+#define UATH_CFLAGS_DEBUG 0x04 /* for debugging */
+ uint16_t length; /* chunk size in bytes */
+ /* chunk data follows */
+} __packed;
+
+#define UATH_RX_DUMMYSIZE 4
+
+/*
+ * Message format for a WDCMSG_DATA_AVAIL message from Target to Host.
+ */
+struct uath_rx_desc {
+ uint32_t len; /* msg length including header */
+ uint32_t code; /* WDCMSG_DATA_AVAIL */
+ uint32_t gennum; /* generation number */
+ uint32_t status; /* start of RECEIVE_INFO */
+#define UATH_STATUS_OK 0
+#define UATH_STATUS_STOP_IN_PROGRESS 1
+#define UATH_STATUS_CRC_ERR 2
+#define UATH_STATUS_PHY_ERR 3
+#define UATH_STATUS_DECRYPT_CRC_ERR 4
+#define UATH_STATUS_DECRYPT_MIC_ERR 5
+#define UATH_STATUS_DECOMP_ERR 6
+#define UATH_STATUS_KEY_ERR 7
+#define UATH_STATUS_ERR 8
+ uint32_t tstamp_low; /* low-order 32-bits of rx timestamp */
+ uint32_t tstamp_high; /* high-order 32-bits of rx timestamp */
+ uint32_t framelen; /* frame length */
+ uint32_t rate; /* rx rate code */
+ uint32_t antenna;
+ int32_t rssi;
+ uint32_t channel;
+ uint32_t phyerror;
+ uint32_t connix; /* key table ix for bss traffic */
+ uint32_t decrypterror;
+ uint32_t keycachemiss;
+ uint32_t pad; /* XXX? */
+} __packed;
+
+struct uath_tx_desc {
+ uint32_t msglen;
+ uint32_t msgid; /* msg id (supplied by host) */
+ uint32_t type; /* opcode: WDMSG_SEND or WDCMSG_FLUSH */
+ uint32_t txqid; /* tx queue id and flags */
+#define UATH_TXQID_MASK 0x0f
+#define UATH_TXQID_MINRATE 0x10 /* use min tx rate */
+#define UATH_TXQID_FF 0x20 /* content is fast frame */
+ uint32_t connid; /* tx connection id */
+#define UATH_ID_INVALID 0xffffffff /* for sending prior to connection */
+ uint32_t flags; /* non-zero if response desired */
+#define UATH_TX_NOTIFY (1 << 24) /* f/w will send a UATH_NOTIF_TX */
+ uint32_t buflen; /* payload length */
+} __packed;
+
+struct uath_cmd_host_available {
+ uint32_t sw_ver_major;
+ uint32_t sw_ver_minor;
+ uint32_t sw_ver_patch;
+ uint32_t sw_ver_build;
+} __packed;
+#define ATH_SW_VER_MAJOR 1
+#define ATH_SW_VER_MINOR 5
+#define ATH_SW_VER_PATCH 0
+#define ATH_SW_VER_BUILD 9999
+
+struct uath_cmd_bind {
+ uint32_t targethandle;
+ uint32_t hostapiversion;
+} __packed;
+
+/* structure for command WDCMSG_RESET */
+struct uath_cmd_reset {
+ uint32_t flags; /* channel flags */
+#define UATH_CHAN_TURBO 0x0100
+#define UATH_CHAN_CCK 0x0200
+#define UATH_CHAN_OFDM 0x0400
+#define UATH_CHAN_2GHZ 0x1000
+#define UATH_CHAN_5GHZ 0x2000
+ uint32_t freq; /* channel frequency */
+ uint32_t maxrdpower;
+ uint32_t cfgctl;
+ uint32_t twiceantennareduction;
+ uint32_t channelchange;
+ uint32_t keeprccontent;
+} __packed;
+
+/* structure for commands UATH_CMD_READ_MAC and UATH_CMD_READ_EEPROM */
+struct uath_read_mac {
+ uint32_t len;
+ uint8_t data[32];
+} __packed;
+
+/* structure for command UATH_CMD_WRITE_MAC */
+struct uath_write_mac {
+ uint32_t reg;
+ uint32_t len;
+ uint8_t data[32];
+} __packed;
+
+/* structure for command UATH_CMD_STA_JOIN */
+struct uath_cmd_join_bss {
+ uint32_t bssid; /* NB: use zero */
+ uint32_t bssmac[2]; /* bssid mac address */
+ uint32_t bsstype;
+ uint32_t wlanmode;
+ uint32_t beaconinterval;
+ uint32_t dtiminterval;
+ uint32_t cfpinterval;
+ uint32_t atimwindow;
+ uint32_t defaultrateix;
+ uint32_t shortslottime11g;
+ uint32_t sleepduration;
+ uint32_t bmissthreshold;
+ uint32_t tcppowerlimit;
+ uint32_t quietduration;
+ uint32_t quietoffset;
+ uint32_t quietackctsallow;
+ uint32_t bssdefaultkey; /* XXX? */
+} __packed;
+
+struct uath_cmd_assoc_bss {
+ uint32_t bssid;
+ uint32_t associd;
+} __packed;
+
+struct uath_cmd_start_bss {
+ uint32_t bssid;
+} __packed;
+
+/* structure for command UATH_CMD_0C */
+struct uath_cmd_0c {
+ uint32_t magic1;
+ uint32_t magic2;
+ uint32_t magic3;
+} __packed;
+
+struct uath_cmd_ledsteady { /* WDCMSG_SET_LED_STEADY */
+ uint32_t lednum;
+#define UATH_LED_LINK 0
+#define UATH_LED_ACTIVITY 1
+ uint32_t ledmode;
+#define UATH_LED_OFF 0
+#define UATH_LED_ON 1
+} __packed;
+
+struct uath_cmd_ledblink { /* WDCMSG_SET_LED_BLINK */
+ uint32_t lednum;
+ uint32_t ledmode;
+ uint32_t blinkrate;
+ uint32_t slowmode;
+} __packed;
+
+struct uath_cmd_ledstate { /* WDCMSG_SET_LED_STATE */
+ uint32_t connected;
+} __packed;
+
+struct uath_connkey_rec {
+ uint8_t bssid[IEEE80211_ADDR_LEN];
+ uint32_t keyiv;
+ uint32_t extkeyiv;
+ uint16_t keyflags;
+ uint16_t keylen;
+ uint16_t keytype; /* WEP, TKIP or AES */
+ /* As far as I know, MIPS 4Kp is 32-bit processor */
+ uint32_t priv;
+ uint8_t keyval[32];
+ uint16_t aes_keylen;
+ uint8_t aes_keyval[16];
+ uint8_t mic_txkeyval[8];
+ uint8_t mic_rxkeyval[8];
+ int64_t keyrsc[17];
+ int32_t keytsc[17];
+ int32_t keyexttsc[17];
+} __packed;
+
+/* structure for command UATH_CMD_CRYPTO */
+struct uath_cmd_crypto {
+ uint32_t keyidx;
+#define UATH_DEFAULT_KEY 6
+ uint32_t xorkey;
+ uint32_t size;
+ struct uath_connkey_rec rec;
+} __packed;
+
+struct uath_cmd_rateset {
+ uint8_t length;
+#define UATH_MAX_NRATES 32
+ uint8_t set[UATH_MAX_NRATES];
+};
+
+/* structure for command WDCMSG_SET_BASIC_RATE */
+struct uath_cmd_rates {
+ uint32_t connid;
+ uint32_t keeprccontent;
+ uint32_t size;
+ struct uath_cmd_rateset rateset;
+} __packed;
+
+enum {
+ WLAN_MODE_NONE = 0,
+ WLAN_MODE_11b,
+ WLAN_MODE_11a,
+ WLAN_MODE_11g,
+ WLAN_MODE_11a_TURBO,
+ WLAN_MODE_11g_TURBO,
+ WLAN_MODE_11a_TURBO_PRIME,
+ WLAN_MODE_11g_TURBO_PRIME,
+ WLAN_MODE_11a_XR,
+ WLAN_MODE_11g_XR,
+};
+
+struct uath_cmd_connection_attr {
+ uint32_t longpreambleonly;
+ struct uath_cmd_rateset rateset;
+ uint32_t wlanmode;
+} __packed;
+
+/* structure for command WDCMSG_CREATE_CONNECTION */
+struct uath_cmd_create_connection {
+ uint32_t connid;
+ uint32_t bssid;
+ uint32_t size;
+ struct uath_cmd_connection_attr connattr;
+} __packed;
+
+struct uath_cmd_txq_setparams { /* WDCMSG_SET_TX_QUEUE_PARAMS */
+ uint32_t qnum;
+ uint32_t aifs;
+ uint32_t logcwmin;
+ uint32_t logcwmax;
+ uint32_t bursttime;
+ uint32_t qflags;
+} __packed;
+
+struct uath_cmd_txq_attr {
+ uint32_t priority;
+ uint32_t aifs;
+ uint32_t logcwmin;
+ uint32_t logcwmax;
+ uint32_t bursttime;
+ uint32_t mode;
+ uint32_t qflags;
+} __packed;
+
+struct uath_cmd_txq_setup { /* WDCMSG_SETUP_TX_QUEUE */
+ uint32_t qid;
+ uint32_t len;
+ struct uath_cmd_txq_attr attr;
+} __packed;
+
+struct uath_cmd_stoptxdma { /* WDCMSG_STOP_TX_DMA */
+ uint32_t qnum;
+ uint32_t msec;
+} __packed;
+
+/* structure for command UATH_CMD_31 */
+struct uath_cmd_31 {
+ uint32_t magic1;
+ uint32_t magic2;
+} __packed;
+
+struct uath_cmd_rx_filter { /* WDCMSG_RX_FILTER */
+ uint32_t bits;
+#define UATH_FILTER_RX_UCAST 0x00000001
+#define UATH_FILTER_RX_MCAST 0x00000002
+#define UATH_FILTER_RX_BCAST 0x00000004
+#define UATH_FILTER_RX_CONTROL 0x00000008
+#define UATH_FILTER_RX_BEACON 0x00000010 /* beacon frames */
+#define UATH_FILTER_RX_PROM 0x00000020 /* promiscuous mode */
+#define UATH_FILTER_RX_PHY_ERR 0x00000040 /* phy errors */
+#define UATH_FILTER_RX_PHY_RADAR 0x00000080 /* radar phy errors */
+#define UATH_FILTER_RX_XR_POOL 0x00000400 /* XR group polls */
+#define UATH_FILTER_RX_PROBE_REQ 0x00000800
+ uint32_t op;
+#define UATH_FILTER_OP_INIT 0x0
+#define UATH_FILTER_OP_SET 0x1
+#define UATH_FILTER_OP_CLEAR 0x2
+#define UATH_FILTER_OP_TEMP 0x3
+#define UATH_FILTER_OP_RESTORE 0x4
+} __packed;
+
+struct uath_cmd_rx_mcast_filter { /* WDCMSG_SET_RX_MCAST_FILTER */
+ uint32_t filter0;
+ uint32_t filter1;
+} __packed;
+
+struct uath_cmd_set_associd { /* WDCMSG_WRITE_ASSOCID */
+ uint32_t defaultrateix;
+ uint32_t associd;
+ uint32_t timoffset;
+ uint32_t turboprime;
+ uint32_t bssid[2];
+} __packed;
+
+struct uath_cmd_set_stabeacon_timers { /* WDCMSG_SET_STA_BEACON_TIMERS */
+ uint32_t nexttbtt;
+ uint32_t nextdtim;
+ uint32_t nextcfp;
+ uint32_t beaconperiod;
+ uint32_t dtimperiod;
+ uint32_t cfpperiod;
+ uint32_t cfpduration;
+ uint32_t sleepduration;
+ uint32_t bsmissthreshold;
+} __packed;
+
+enum {
+ CFG_NONE, /* Sentinal to indicate "no config" */
+ CFG_REG_DOMAIN, /* Regulatory Domain */
+ CFG_RATE_CONTROL_ENABLE,
+ CFG_DEF_XMIT_DATA_RATE, /* NB: if rate control is not enabled */
+ CFG_HW_TX_RETRIES,
+ CFG_SW_TX_RETRIES,
+ CFG_SLOW_CLOCK_ENABLE,
+ CFG_COMP_PROC,
+ CFG_USER_RTS_THRESHOLD,
+ CFG_XR2NORM_RATE_THRESHOLD,
+ CFG_XRMODE_SWITCH_COUNT,
+ CFG_PROTECTION_TYPE,
+ CFG_BURST_SEQ_THRESHOLD,
+ CFG_ABOLT,
+ CFG_IQ_LOG_COUNT_MAX,
+ CFG_MODE_CTS,
+ CFG_WME_ENABLED,
+ CFG_GPRS_CBR_PERIOD,
+ CFG_SERVICE_TYPE,
+ /* MAC Address to use. Overrides EEPROM */
+ CFG_MAC_ADDR,
+ CFG_DEBUG_EAR,
+ CFG_INIT_REGS,
+ /* An ID for use in error & debug messages */
+ CFG_DEBUG_ID,
+ CFG_COMP_WIN_SZ,
+ CFG_DIVERSITY_CTL,
+ CFG_TP_SCALE,
+ CFG_TPC_HALF_DBM5,
+ CFG_TPC_HALF_DBM2,
+ CFG_OVERRD_TX_POWER,
+ CFG_USE_32KHZ_CLOCK,
+ CFG_GMODE_PROTECTION,
+ CFG_GMODE_PROTECT_RATE_INDEX,
+ CFG_GMODE_NON_ERP_PREAMBLE,
+ CFG_WDC_TRANSPORT_CHUNK_SIZE,
+};
+
+enum {
+ /* Sentinal to indicate "no capability" */
+ CAP_NONE,
+ CAP_ALL, /* ALL capabilities */
+ CAP_TARGET_VERSION,
+ CAP_TARGET_REVISION,
+ CAP_MAC_VERSION,
+ CAP_MAC_REVISION,
+ CAP_PHY_REVISION,
+ CAP_ANALOG_5GHz_REVISION,
+ CAP_ANALOG_2GHz_REVISION,
+ /* Target supports WDC message debug features */
+ CAP_DEBUG_WDCMSG_SUPPORT,
+
+ CAP_REG_DOMAIN,
+ CAP_COUNTRY_CODE,
+ CAP_REG_CAP_BITS,
+
+ CAP_WIRELESS_MODES,
+ CAP_CHAN_SPREAD_SUPPORT,
+ CAP_SLEEP_AFTER_BEACON_BROKEN,
+ CAP_COMPRESS_SUPPORT,
+ CAP_BURST_SUPPORT,
+ CAP_FAST_FRAMES_SUPPORT,
+ CAP_CHAP_TUNING_SUPPORT,
+ CAP_TURBOG_SUPPORT,
+ CAP_TURBO_PRIME_SUPPORT,
+ CAP_DEVICE_TYPE,
+ CAP_XR_SUPPORT,
+ CAP_WME_SUPPORT,
+ CAP_TOTAL_QUEUES,
+ CAP_CONNECTION_ID_MAX, /* Should absorb CAP_KEY_CACHE_SIZE */
+
+ CAP_LOW_5GHZ_CHAN,
+ CAP_HIGH_5GHZ_CHAN,
+ CAP_LOW_2GHZ_CHAN,
+ CAP_HIGH_2GHZ_CHAN,
+
+ CAP_MIC_AES_CCM,
+ CAP_MIC_CKIP,
+ CAP_MIC_TKIP,
+ CAP_MIC_TKIP_WME,
+ CAP_CIPHER_AES_CCM,
+ CAP_CIPHER_CKIP,
+ CAP_CIPHER_TKIP,
+
+ CAP_TWICE_ANTENNAGAIN_5G,
+ CAP_TWICE_ANTENNAGAIN_2G,
+};
+
+enum {
+ ST_NONE, /* Sentinal to indicate "no status" */
+ ST_ALL,
+ ST_SERVICE_TYPE,
+ ST_WLAN_MODE,
+ ST_FREQ,
+ ST_BAND,
+ ST_LAST_RSSI,
+ ST_PS_FRAMES_DROPPED,
+ ST_CACHED_DEF_ANT,
+ ST_COUNT_OTHER_RX_ANT,
+ ST_USE_FAST_DIVERSITY,
+ ST_MAC_ADDR,
+ ST_RX_GENERATION_NUM,
+ ST_TX_QUEUE_DEPTH,
+ ST_SERIAL_NUMBER,
+ ST_WDC_TRANSPORT_CHUNK_SIZE,
+};
+
+enum {
+ BSS_ATTR_BEACON_INTERVAL,
+ BSS_ATTR_DTIM_INTERVAL,
+ BSS_ATTR_CFP_INTERVAL,
+ BSS_ATTR_CFP_MAX_DURATION,
+ BSS_ATTR_ATIM_WINDOW,
+ BSS_ATTR_DEFAULT_RATE_INDEX,
+ BSS_ATTR_SHORT_SLOT_TIME_11g,
+ BSS_ATTR_SLEEP_DURATION,
+ BSS_ATTR_BMISS_THRESHOLD,
+ BSS_ATTR_TPC_POWER_LIMIT,
+ BSS_ATTR_BSS_KEY_UPDATE,
+};
+
+struct uath_cmd_update_bss_attribute {
+ uint32_t bssid;
+ uint32_t attribute; /* BSS_ATTR_BEACON_INTERVAL, et al. */
+ uint32_t cfgsize; /* should be zero 0 */
+ uint32_t cfgdata;
+};
+
+struct uath_cmd_update_bss_attribute_key {
+ uint32_t bssid;
+ uint32_t attribute; /* BSS_ATTR_BSS_KEY_UPDATE */
+ uint32_t cfgsize; /* size of remaining data */
+ uint32_t bsskeyix;
+ uint32_t isdefaultkey;
+ uint32_t keyiv; /* IV generation control */
+ uint32_t extkeyiv; /* extended IV for TKIP & CCM */
+ uint32_t keyflags;
+ uint32_t keytype;
+ uint32_t initvalue; /* XXX */
+ uint32_t keyval[4];
+ uint32_t mictxkeyval[2];
+ uint32_t micrxkeyval[2];
+ uint32_t keyrsc[2];
+};
+
+enum {
+ TARGET_DEVICE_AWAKE,
+ TARGET_DEVICE_SLEEP,
+ TARGET_DEVICE_PWRDN,
+ TARGET_DEVICE_PWRSAVE,
+ TARGET_DEVICE_SUSPEND,
+ TARGET_DEVICE_RESUME,
+};
+
+#define UATH_MAX_TXBUFSZ \
+ (sizeof(struct uath_chunk) + sizeof(struct uath_tx_desc) + \
+ IEEE80211_MAX_LEN)
+
+/*
+ * it's not easy to measure how the chunk is passed into the host if the target
+ * passed the multi-chunks so just we check a minimal size we can imagine.
+ */
+#define UATH_MIN_RXBUFSZ (sizeof(struct uath_chunk))
diff --git a/sys/dev/usb/wlan/if_uathvar.h b/sys/dev/usb/wlan/if_uathvar.h
new file mode 100644
index 0000000..2717399
--- /dev/null
+++ b/sys/dev/usb/wlan/if_uathvar.h
@@ -0,0 +1,237 @@
+/* $OpenBSD: if_uathvar.h,v 1.3 2006/09/20 19:47:17 damien Exp $ */
+/* $FreeBSD$ */
+
+/*-
+ * Copyright (c) 2006
+ * Damien Bergamini <damien.bergamini@free.fr>
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
+ *
+ * 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.
+ */
+
+enum {
+ UATH_INTR_RX,
+ UATH_INTR_TX,
+ UATH_BULK_RX,
+ UATH_BULK_TX,
+ UATH_N_XFERS = 4,
+};
+
+#define UATH_ID_BSS 2 /* Connection ID */
+
+#define UATH_RX_DATA_LIST_COUNT 128
+#define UATH_TX_DATA_LIST_COUNT 16
+#define UATH_CMD_LIST_COUNT 60
+
+#define UATH_DATA_TIMEOUT 10000
+#define UATH_CMD_TIMEOUT 1000
+
+/* flags for sending firmware commands */
+#define UATH_CMD_FLAG_ASYNC (1 << 0)
+#define UATH_CMD_FLAG_READ (1 << 1)
+#define UATH_CMD_FLAG_MAGIC (1 << 2)
+
+struct uath_rx_radiotap_header {
+ struct ieee80211_radiotap_header wr_ihdr;
+ uint8_t wr_flags;
+ uint16_t wr_chan_freq;
+ uint16_t wr_chan_flags;
+ int8_t wr_dbm_antsignal;
+} __packed;
+
+#define UATH_RX_RADIOTAP_PRESENT \
+ ((1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL) | \
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL))
+
+struct uath_tx_radiotap_header {
+ struct ieee80211_radiotap_header wt_ihdr;
+ uint8_t wt_flags;
+ uint16_t wt_chan_freq;
+ uint16_t wt_chan_flags;
+} __packed;
+
+#define UATH_TX_RADIOTAP_PRESENT \
+ ((1 << IEEE80211_RADIOTAP_FLAGS) | \
+ (1 << IEEE80211_RADIOTAP_CHANNEL))
+
+struct uath_data {
+ struct uath_softc *sc;
+ uint8_t *buf;
+ uint16_t buflen;
+ struct mbuf *m;
+ struct ieee80211_node *ni; /* NB: tx only */
+ STAILQ_ENTRY(uath_data) next;
+};
+typedef STAILQ_HEAD(, uath_data) uath_datahead;
+
+struct uath_cmd {
+ struct uath_softc *sc;
+ uint32_t flags;
+ uint32_t msgid;
+ uint8_t *buf;
+ uint16_t buflen;
+ void *odata; /* NB: tx only */
+ int olen; /* space in odata */
+ STAILQ_ENTRY(uath_cmd) next;
+};
+typedef STAILQ_HEAD(, uath_cmd) uath_cmdhead;
+
+struct uath_wme_settings {
+ uint8_t aifsn;
+ uint8_t logcwmin;
+ uint8_t logcwmax;
+ uint16_t txop;
+#define UATH_TXOP_TO_US(txop) ((txop) << 5)
+ uint8_t acm;
+};
+
+struct uath_devcap {
+ uint32_t targetVersion;
+ uint32_t targetRevision;
+ uint32_t macVersion;
+ uint32_t macRevision;
+ uint32_t phyRevision;
+ uint32_t analog5GhzRevision;
+ uint32_t analog2GhzRevision;
+ uint32_t regDomain;
+ uint32_t regCapBits;
+ uint32_t countryCode;
+ uint32_t keyCacheSize;
+ uint32_t numTxQueues;
+ uint32_t connectionIdMax;
+ uint32_t wirelessModes;
+#define UATH_WIRELESS_MODE_11A 0x01
+#define UATH_WIRELESS_MODE_TURBO 0x02
+#define UATH_WIRELESS_MODE_11B 0x04
+#define UATH_WIRELESS_MODE_11G 0x08
+#define UATH_WIRELESS_MODE_108G 0x10
+ uint32_t chanSpreadSupport;
+ uint32_t compressSupport;
+ uint32_t burstSupport;
+ uint32_t fastFramesSupport;
+ uint32_t chapTuningSupport;
+ uint32_t turboGSupport;
+ uint32_t turboPrimeSupport;
+ uint32_t deviceType;
+ uint32_t wmeSupport;
+ uint32_t low2GhzChan;
+ uint32_t high2GhzChan;
+ uint32_t low5GhzChan;
+ uint32_t high5GhzChan;
+ uint32_t supportCipherWEP;
+ uint32_t supportCipherAES_CCM;
+ uint32_t supportCipherTKIP;
+ uint32_t supportCipherMicAES_CCM;
+ uint32_t supportMicTKIP;
+ uint32_t twiceAntennaGain5G;
+ uint32_t twiceAntennaGain2G;
+};
+
+struct uath_stat {
+ uint32_t st_badchunkseqnum;
+ uint32_t st_invalidlen;
+ uint32_t st_multichunk;
+ uint32_t st_toobigrxpkt;
+ uint32_t st_stopinprogress;
+ uint32_t st_crcerr;
+ uint32_t st_phyerr;
+ uint32_t st_decrypt_crcerr;
+ uint32_t st_decrypt_micerr;
+ uint32_t st_decomperr;
+ uint32_t st_keyerr;
+ uint32_t st_err;
+ /* CMD/RX/TX queues */
+ uint32_t st_cmd_active;
+ uint32_t st_cmd_inactive;
+ uint32_t st_cmd_pending;
+ uint32_t st_cmd_waiting;
+ uint32_t st_rx_active;
+ uint32_t st_rx_inactive;
+ uint32_t st_tx_active;
+ uint32_t st_tx_inactive;
+ uint32_t st_tx_pending;
+};
+#define UATH_STAT_INC(sc, var) (sc)->sc_stat.var++
+#define UATH_STAT_DEC(sc, var) (sc)->sc_stat.var--
+
+struct uath_vap {
+ struct ieee80211vap vap;
+ int (*newstate)(struct ieee80211vap *,
+ enum ieee80211_state, int);
+};
+#define UATH_VAP(vap) ((struct uath_vap *)(vap))
+
+struct uath_softc {
+ struct ifnet *sc_ifp;
+ device_t sc_dev;
+ struct usb2_device *sc_udev;
+ struct mtx sc_mtx;
+ uint32_t sc_debug;
+
+ struct uath_stat sc_stat;
+ int (*sc_newstate)(struct ieee80211com *,
+ enum ieee80211_state, int);
+ enum ieee80211_state sc_state;
+
+ struct usb2_xfer *sc_xfer[UATH_N_XFERS];
+ struct uath_cmd sc_cmd[UATH_CMD_LIST_COUNT];
+ uath_cmdhead sc_cmd_active;
+ uath_cmdhead sc_cmd_inactive;
+ uath_cmdhead sc_cmd_pending;
+ uath_cmdhead sc_cmd_waiting;
+ struct uath_data sc_rx[UATH_RX_DATA_LIST_COUNT];
+ uath_datahead sc_rx_active;
+ uath_datahead sc_rx_inactive;
+ struct uath_data sc_tx[UATH_TX_DATA_LIST_COUNT];
+ uath_datahead sc_tx_active;
+ uath_datahead sc_tx_inactive;
+ uath_datahead sc_tx_pending;
+
+ uint32_t sc_msgid;
+ uint32_t sc_seqnum;
+ int sc_tx_timer;
+ struct callout watchdog_ch;
+ struct callout stat_ch;
+ /* multi-chunked support */
+ struct mbuf *sc_intrx_head;
+ struct mbuf *sc_intrx_tail;
+ uint8_t sc_intrx_nextnum;
+ uint32_t sc_intrx_len;
+#define UATH_MAX_INTRX_SIZE 3616
+
+ struct uath_devcap sc_devcap;
+ uint8_t sc_serial[16];
+
+ /* unsorted */
+ uint32_t sc_flags;
+#define UATH_FLAG_INVALID (1 << 1)
+#define UATH_FLAG_INITDONE (1 << 2)
+
+ struct uath_rx_radiotap_header sc_rxtap;
+ int sc_rxtap_len;
+ struct uath_tx_radiotap_header sc_txtap;
+ int sc_txtap_len;
+};
+
+#define UATH_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
+#define UATH_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
+#define UATH_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
+
+#define UATH_RESET_INTRX(sc) do { \
+ (sc)->sc_intrx_head = NULL; \
+ (sc)->sc_intrx_tail = NULL; \
+ (sc)->sc_intrx_nextnum = 0; \
+ (sc)->sc_intrx_len = 0; \
+} while (0)
diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c
index 2844f2c..919b66d 100644
--- a/sys/dev/usb/wlan/if_ural.c
+++ b/sys/dev/usb/wlan/if_ural.c
@@ -339,18 +339,18 @@ static const struct usb2_config ural_config[URAL_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE + 4),
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = ural_bulk_write_callback,
- .mh.timeout = 5000, /* ms */
+ .bufsize = (RAL_FRAME_SIZE + RAL_TX_DESC_SIZE + 4),
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = ural_bulk_write_callback,
+ .timeout = 5000, /* ms */
},
[URAL_BULK_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = (RAL_FRAME_SIZE + RAL_RX_DESC_SIZE),
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = ural_bulk_read_callback,
+ .bufsize = (RAL_FRAME_SIZE + RAL_RX_DESC_SIZE),
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = ural_bulk_read_callback,
},
};
@@ -485,7 +485,6 @@ ural_attach_post(struct usb2_proc_msg *pm)
ic->ic_ifp = ifp;
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
- IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_bssid);
/* set device capabilities */
ic->ic_caps =
@@ -507,7 +506,7 @@ ural_attach_post(struct usb2_proc_msg *pm)
setbit(&bands, IEEE80211_MODE_11A);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, sc->sc_bssid);
ic->ic_update_promisc = ural_update_promisc;
ic->ic_newassoc = ural_newassoc;
ic->ic_raw_xmit = ural_raw_xmit;
@@ -519,8 +518,6 @@ ural_attach_post(struct usb2_proc_msg *pm)
ic->ic_vap_create = ural_vap_create;
ic->ic_vap_delete = ural_vap_delete;
- sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
-
bpfattach(ifp, DLT_IEEE802_11_RADIO,
sizeof (struct ieee80211_frame) + sizeof(sc->sc_txtap));
@@ -1109,7 +1106,7 @@ ural_setup_tx_desc(struct ural_softc *sc, struct ural_tx_desc *desc,
desc->plcp_service = 4;
len += IEEE80211_CRC_LEN;
- if (ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM) {
+ if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) {
desc->flags |= htole32(RAL_TX_OFDM);
plcp_length = len & 0xfff;
@@ -1210,7 +1207,7 @@ ural_tx_mgt(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
flags |= RAL_TX_ACK;
- dur = ieee80211_ack_duration(sc->sc_rates, tp->mgmtrate,
+ dur = ieee80211_ack_duration(ic->ic_rt, tp->mgmtrate,
ic->ic_flags & IEEE80211_F_SHPREAMBLE);
*(uint16_t *)wh->i_dur = htole16(dur);
@@ -1250,16 +1247,16 @@ ural_sendprot(struct ural_softc *sc,
wh = mtod(m, const struct ieee80211_frame *);
pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
- protrate = ieee80211_ctl_rate(sc->sc_rates, rate);
- ackrate = ieee80211_ack_rate(sc->sc_rates, rate);
+ protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
+ ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
- dur = ieee80211_compute_duration(sc->sc_rates, pktlen, rate, isshort);
- + ieee80211_ack_duration(sc->sc_rates, rate, isshort);
+ dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort);
+ + ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags = RAL_TX_RETRY(7);
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
- dur += ieee80211_ack_duration(sc->sc_rates, rate, isshort);
+ dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
flags |= RAL_TX_ACK;
mprot = ieee80211_alloc_rts(ic, wh->i_addr1, wh->i_addr2, dur);
} else {
@@ -1377,7 +1374,7 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
prot = IEEE80211_PROT_RTSCTS;
else if ((ic->ic_flags & IEEE80211_F_USEPROT) &&
- ieee80211_rate2phytype(sc->sc_rates, rate) == IEEE80211_T_OFDM)
+ ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM)
prot = ic->ic_protmode;
if (prot != IEEE80211_PROT_NONE) {
error = ural_sendprot(sc, m0, ni, prot, rate);
@@ -1401,7 +1398,7 @@ ural_tx_data(struct ural_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
flags |= RAL_TX_ACK;
flags |= RAL_TX_RETRY(7);
- dur = ieee80211_ack_duration(sc->sc_rates, rate,
+ dur = ieee80211_ack_duration(ic->ic_rt, rate,
ic->ic_flags & IEEE80211_F_SHPREAMBLE);
*(uint16_t *)wh->i_dur = htole16(dur);
}
@@ -1439,12 +1436,6 @@ ural_start(struct ifnet *ifp)
break;
}
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- m = ieee80211_encap(ni, m);
- if (m == NULL) {
- ieee80211_free_node(ni);
- ifp->if_oerrors++;
- continue;
- }
if (ural_tx_data(sc, m, ni) != 0) {
ieee80211_free_node(ni);
ifp->if_oerrors++;
@@ -1743,8 +1734,6 @@ ural_set_channel(struct ieee80211com *ic)
sc->sc_scan_action = URAL_SET_CHANNEL;
ural_queue_command(sc, ural_scantask,
&sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
-
- sc->sc_rates = ieee80211_get_ratetable(ic->ic_curchan);
RAL_UNLOCK(sc);
}
@@ -2216,8 +2205,7 @@ ural_init_task(struct usb2_proc_msg *pm)
ural_set_txantenna(sc, sc->tx_ant);
ural_set_rxantenna(sc, sc->rx_ant);
- IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
- ural_set_macaddr(sc, ic->ic_myaddr);
+ ural_set_macaddr(sc, IF_LLADDR(ifp));
/*
* Allocate Tx and Rx xfer queues.
diff --git a/sys/dev/usb/wlan/if_uralvar.h b/sys/dev/usb/wlan/if_uralvar.h
index 5e72339..13a3df8 100644
--- a/sys/dev/usb/wlan/if_uralvar.h
+++ b/sys/dev/usb/wlan/if_uralvar.h
@@ -106,8 +106,6 @@ struct ural_softc {
struct usb2_device *sc_udev;
struct usb2_process sc_tq;
- const struct ieee80211_rate_table *sc_rates;
-
uint32_t asic_rev;
uint8_t rf_rev;
diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c
index fa9580a..6858d55 100644
--- a/sys/dev/usb/wlan/if_zyd.c
+++ b/sys/dev/usb/wlan/if_zyd.c
@@ -232,38 +232,38 @@ static const struct usb2_config zyd_config[ZYD_N_TRANSFER] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = ZYD_MAX_TXBUFSZ,
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = zyd_bulk_write_callback,
+ .bufsize = ZYD_MAX_TXBUFSZ,
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = zyd_bulk_write_callback,
.ep_index = 0,
- .mh.timeout = 10000, /* 10 seconds */
+ .timeout = 10000, /* 10 seconds */
},
[ZYD_BULK_RD] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = ZYX_MAX_RXBUFSZ,
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = zyd_bulk_read_callback,
+ .bufsize = ZYX_MAX_RXBUFSZ,
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = zyd_bulk_read_callback,
.ep_index = 0,
},
[ZYD_INTR_WR] = {
.type = UE_BULK_INTR,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_OUT,
- .mh.bufsize = sizeof(struct zyd_cmd),
- .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,},
- .mh.callback = zyd_intr_write_callback,
- .mh.timeout = 1000, /* 1 second */
+ .bufsize = sizeof(struct zyd_cmd),
+ .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
+ .callback = zyd_intr_write_callback,
+ .timeout = 1000, /* 1 second */
.ep_index = 1,
},
[ZYD_INTR_RD] = {
.type = UE_INTERRUPT,
.endpoint = UE_ADDR_ANY,
.direction = UE_DIR_IN,
- .mh.bufsize = sizeof(struct zyd_cmd),
- .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
- .mh.callback = zyd_intr_read_callback,
+ .bufsize = sizeof(struct zyd_cmd),
+ .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
+ .callback = zyd_intr_read_callback,
},
};
#define zyd_read16_m(sc, val, data) do { \
@@ -396,7 +396,6 @@ zyd_attach_post(struct usb2_proc_msg *pm)
ic->ic_ifp = ifp;
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
ic->ic_opmode = IEEE80211_M_STA;
- IEEE80211_ADDR_COPY(ic->ic_myaddr, sc->sc_bssid);
/* set device capabilities */
ic->ic_caps =
@@ -413,7 +412,7 @@ zyd_attach_post(struct usb2_proc_msg *pm)
setbit(&bands, IEEE80211_MODE_11G);
ieee80211_init_channels(ic, NULL, &bands);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, sc->sc_bssid);
ic->ic_newassoc = zyd_newassoc;
ic->ic_raw_xmit = zyd_raw_xmit;
ic->ic_node_alloc = zyd_node_alloc;
@@ -2698,12 +2697,6 @@ zyd_start(struct ifnet *ifp)
break;
}
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
- m = ieee80211_encap(ni, m);
- if (m == NULL) {
- ieee80211_free_node(ni);
- ifp->if_oerrors++;
- continue;
- }
if (zyd_tx_data(sc, m, ni) != 0) {
ieee80211_free_node(ni);
ifp->if_oerrors++;
@@ -2859,10 +2852,9 @@ zyd_init_task(struct usb2_proc_msg *pm)
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
zyd_stop_task(pm);
- IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
- DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %s\n",
- ether_sprintf(ic->ic_myaddr));
- error = zyd_set_macaddr(sc, ic->ic_myaddr);
+ DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %6D\n",
+ IF_LLADDR(ifp), ":");
+ error = zyd_set_macaddr(sc, IF_LLADDR(ifp));
if (error != 0)
return;
diff --git a/sys/dev/usb/wlan/usb_wlan.h b/sys/dev/usb/wlan/usb_wlan.h
index 9db120e..aa0f1c4 100644
--- a/sys/dev/usb/wlan/usb_wlan.h
+++ b/sys/dev/usb/wlan/usb_wlan.h
@@ -46,7 +46,6 @@
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_amrr.h>
#include <net80211/ieee80211_regdomain.h>
-#include <net80211/ieee80211_phy.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index 62b7114..a4a74e4 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -89,6 +89,7 @@ __FBSDID("$FreeBSD$");
#include <net/if_arp.h>
#include <net/ethernet.h>
#include <net/if_dl.h>
+#include <net/if_llc.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -245,6 +246,7 @@ wi_attach(device_t dev)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int error;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
@@ -312,12 +314,12 @@ wi_attach(device_t dev)
* the probe to fail.
*/
buflen = IEEE80211_ADDR_LEN;
- error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen);
+ error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
if (error != 0) {
buflen = IEEE80211_ADDR_LEN;
- error = wi_read_rid(sc, WI_RID_MAC_NODE, ic->ic_myaddr, &buflen);
+ error = wi_read_rid(sc, WI_RID_MAC_NODE, macaddr, &buflen);
}
- if (error || IEEE80211_ADDR_EQ(ic->ic_myaddr, empty_macaddr)) {
+ if (error || IEEE80211_ADDR_EQ(macaddr, empty_macaddr)) {
if (error != 0)
device_printf(dev, "mac read failed %d\n", error);
else {
@@ -451,7 +453,7 @@ wi_attach(device_t dev)
sc->sc_portnum = WI_DEFAULT_PORT;
TASK_INIT(&sc->sc_oor_task, 0, wi_status_oor, ic);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, macaddr);
ic->ic_raw_xmit = wi_raw_xmit;
ic->ic_scan_start = wi_scan_start;
ic->ic_scan_end = wi_scan_end;
@@ -690,7 +692,6 @@ static void
wi_init_locked(struct wi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
int wasenabled;
WI_LOCK_ASSERT(sc);
@@ -699,8 +700,7 @@ wi_init_locked(struct wi_softc *sc)
if (wasenabled)
wi_stop_locked(sc, 1);
- IEEE80211_ADDR_COPY(ic->ic_myaddr, IF_LLADDR(ifp));
- if (wi_setup_locked(sc, sc->sc_porttype, 3, ic->ic_myaddr) != 0) {
+ if (wi_setup_locked(sc, sc->sc_porttype, 3, IF_LLADDR(ifp)) != 0) {
if_printf(ifp, "interface not running\n");
wi_stop_locked(sc, 1);
return;
@@ -979,6 +979,7 @@ wi_start_locked(struct ifnet *ifp)
struct mbuf *m0;
struct ieee80211_key *k;
struct wi_frame frmhdr;
+ const struct llc *llc;
int cur;
WI_LOCK_ASSERT(sc);
@@ -997,19 +998,33 @@ wi_start_locked(struct ifnet *ifp)
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
- /* NB: copy before 802.11 header is prepended */
- m_copydata(m0, 0, ETHER_HDR_LEN,
- (caddr_t)&frmhdr.wi_ehdr);
-
ni = (struct ieee80211_node *) m0->m_pkthdr.rcvif;
- m0 = ieee80211_encap(ni, m0);
- if (m0 == NULL) {
- ifp->if_oerrors++;
- ieee80211_free_node(ni);
- continue;
- }
+ /* reconstruct 802.3 header */
wh = mtod(m0, struct ieee80211_frame *);
+ switch (wh->i_fc[1]) {
+ case IEEE80211_FC1_DIR_TODS:
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_shost,
+ wh->i_addr2);
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_dhost,
+ wh->i_addr3);
+ break;
+ case IEEE80211_FC1_DIR_NODS:
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_shost,
+ wh->i_addr2);
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_dhost,
+ wh->i_addr1);
+ break;
+ case IEEE80211_FC1_DIR_FROMDS:
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_shost,
+ wh->i_addr3);
+ IEEE80211_ADDR_COPY(frmhdr.wi_ehdr.ether_dhost,
+ wh->i_addr1);
+ break;
+ }
+ llc = (const struct llc *)(
+ mtod(m0, const uint8_t *) + ieee80211_hdrsize(wh));
+ frmhdr.wi_ehdr.ether_type = llc->llc_snap.ether_type;
frmhdr.wi_tx_ctl = htole16(WI_ENC_TX_802_11|WI_TXCNTL_TX_EX);
if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
k = ieee80211_crypto_encap(ni, m0);
@@ -1504,6 +1519,7 @@ wi_status_connected(void *arg, int pending)
struct ieee80211com *ic = vap->iv_ic;
IEEE80211_LOCK(ic);
+ vap->iv_bss->ni_associd = 1 | 0xc000; /* NB: anything will do */
WI_VAP(vap)->wv_newstate(vap, IEEE80211_S_RUN, 0);
if (vap->iv_newstate_cb != NULL)
vap->iv_newstate_cb(vap, IEEE80211_S_RUN, 0);
@@ -1516,6 +1532,7 @@ wi_status_disconnected(void *arg, int pending)
struct ieee80211vap *vap = arg;
if (vap->iv_state == IEEE80211_S_RUN) {
+ vap->iv_bss->ni_associd = 0;
vap->iv_stats.is_rx_deauth++;
ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
}
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c
index 776d089..1e980aa 100644
--- a/sys/dev/wpi/if_wpi.c
+++ b/sys/dev/wpi/if_wpi.c
@@ -211,7 +211,8 @@ static void wpi_set_channel(struct ieee80211com *);
static void wpi_scan_curchan(struct ieee80211_scan_state *, unsigned long);
static void wpi_scan_mindwell(struct ieee80211_scan_state *);
static int wpi_ioctl(struct ifnet *, u_long, caddr_t);
-static void wpi_read_eeprom(struct wpi_softc *);
+static void wpi_read_eeprom(struct wpi_softc *,
+ uint8_t macaddr[IEEE80211_ADDR_LEN]);
static void wpi_read_eeprom_channels(struct wpi_softc *, int);
static void wpi_read_eeprom_group(struct wpi_softc *, int);
static int wpi_cmd(struct wpi_softc *, int, const void *, int, int);
@@ -493,6 +494,7 @@ wpi_attach(device_t dev)
int ac, error, supportsa = 1;
uint32_t tmp;
const struct wpi_ident *ident;
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
sc->sc_dev = dev;
@@ -650,7 +652,7 @@ wpi_attach(device_t dev)
* Read in the eeprom and also setup the channels for
* net80211. We don't set the rates as net80211 does this for us
*/
- wpi_read_eeprom(sc);
+ wpi_read_eeprom(sc, macaddr);
if (bootverbose || WPI_DEBUG_SET) {
device_printf(sc->sc_dev, "Regulatory Domain: %.4s\n", sc->domain);
@@ -675,7 +677,7 @@ wpi_attach(device_t dev)
ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
IFQ_SET_READY(&ifp->if_snd);
- ieee80211_ifattach(ic);
+ ieee80211_ifattach(ic, macaddr);
/* override default methods */
ic->ic_node_alloc = wpi_node_alloc;
ic->ic_newassoc = wpi_newassoc;
@@ -1473,6 +1475,20 @@ wpi_rx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc,
le16toh(head->len), (int8_t)stat->rssi, head->rate, head->chan,
(uintmax_t)le64toh(tail->tstamp)));
+ /* discard Rx frames with bad CRC early */
+ if ((le32toh(tail->flags) & WPI_RX_NOERROR) != WPI_RX_NOERROR) {
+ DPRINTFN(WPI_DEBUG_RX, ("%s: rx flags error %x\n", __func__,
+ le32toh(tail->flags)));
+ ifp->if_ierrors++;
+ return;
+ }
+ if (le16toh(head->len) < sizeof (struct ieee80211_frame)) {
+ DPRINTFN(WPI_DEBUG_RX, ("%s: frame too short: %d\n", __func__,
+ le16toh(head->len)));
+ ifp->if_ierrors++;
+ return;
+ }
+
/* XXX don't need mbuf, just dma buffer */
mnew = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
if (mnew == NULL) {
@@ -1573,7 +1589,7 @@ wpi_tx_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc)
*/
wn->amn.amn_txcnt++;
if (stat->ntries > 0) {
- DPRINTFN(3, ("%d retries\n", stat->ntries));
+ DPRINTFN(WPI_DEBUG_TX, ("%d retries\n", stat->ntries));
wn->amn.amn_retrycnt++;
}
@@ -2029,10 +2045,9 @@ wpi_start_locked(struct ifnet *ifp)
return;
for (;;) {
- IFQ_POLL(&ifp->if_snd, m);
+ IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
- /* no QoS encapsulation for EAPOL frames */
ac = M_WME_GETAC(m);
if (sc->txq[ac].queued > sc->txq[ac].count - 8) {
/* there is no place left in this ring */
@@ -2040,14 +2055,7 @@ wpi_start_locked(struct ifnet *ifp)
ifp->if_drv_flags |= IFF_DRV_OACTIVE;
break;
}
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
- m = ieee80211_encap(ni, m);
- if (m == NULL) {
- ieee80211_free_node(ni);
- ifp->if_oerrors++;
- continue;
- }
if (wpi_tx_data(sc, m, ni, ac) != 0) {
ieee80211_free_node(ni);
ifp->if_oerrors++;
@@ -2137,10 +2145,8 @@ wpi_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
* Extract various information from EEPROM.
*/
static void
-wpi_read_eeprom(struct wpi_softc *sc)
+wpi_read_eeprom(struct wpi_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
{
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
int i;
/* read the hardware capabilities, revision and SKU type */
@@ -2152,7 +2158,7 @@ wpi_read_eeprom(struct wpi_softc *sc)
wpi_read_prom_data(sc, WPI_EEPROM_DOMAIN, sc->domain, 4);
/* read in the hw MAC address */
- wpi_read_prom_data(sc, WPI_EEPROM_MAC, ic->ic_myaddr, 6);
+ wpi_read_prom_data(sc, WPI_EEPROM_MAC, macaddr, 6);
/* read the list of authorized channels */
for (i = 0; i < WPI_CHAN_BANDS_COUNT; i++)
@@ -2625,7 +2631,7 @@ wpi_scan(struct wpi_softc *sc)
IEEE80211_FC0_SUBTYPE_PROBE_REQ;
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
IEEE80211_ADDR_COPY(wh->i_addr1, ifp->if_broadcastaddr);
- IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr);
+ IEEE80211_ADDR_COPY(wh->i_addr2, IF_LLADDR(ifp));
IEEE80211_ADDR_COPY(wh->i_addr3, ifp->if_broadcastaddr);
*(u_int16_t *)&wh->i_dur[0] = 0; /* filled by h/w */
*(u_int16_t *)&wh->i_seq[0] = 0; /* filled by h/w */
@@ -2797,7 +2803,7 @@ wpi_config(struct wpi_softc *sc)
/* configure adapter */
memset(&sc->config, 0, sizeof (struct wpi_config));
- IEEE80211_ADDR_COPY(sc->config.myaddr, ic->ic_myaddr);
+ IEEE80211_ADDR_COPY(sc->config.myaddr, IF_LLADDR(ifp));
/*set default channel*/
sc->config.chan = htole16(ieee80211_chan2ieee(ic, ic->ic_curchan));
sc->config.flags = htole32(WPI_CONFIG_TSF);
diff --git a/sys/dev/wpi/if_wpireg.h b/sys/dev/wpi/if_wpireg.h
index 60692a2..2ccc21f 100644
--- a/sys/dev/wpi/if_wpireg.h
+++ b/sys/dev/wpi/if_wpireg.h
@@ -235,12 +235,10 @@ struct wpi_rx_head {
struct wpi_rx_tail {
uint32_t flags;
-#if 0
#define WPI_RX_NO_CRC_ERR (1 << 0)
#define WPI_RX_NO_OVFL_ERR (1 << 1)
/* shortcut for the above */
#define WPI_RX_NOERROR (WPI_RX_NO_CRC_ERR | WPI_RX_NO_OVFL_ERR)
-#endif
uint64_t tstamp;
uint32_t tbeacon;
} __packed;
diff --git a/sys/dev/xen/balloon/balloon.c b/sys/dev/xen/balloon/balloon.c
index c23433c..6948173 100644
--- a/sys/dev/xen/balloon/balloon.c
+++ b/sys/dev/xen/balloon/balloon.c
@@ -167,6 +167,8 @@ minimum_target(void)
{
#ifdef XENHVM
#define max_pfn physmem
+#else
+#define max_pfn HYPERVISOR_shared_info->arch.max_pfn
#endif
unsigned long min_pages, curr_pages = current_target();
@@ -256,6 +258,7 @@ increase_reservation(unsigned long nr_pages)
set_phys_to_machine(pfn, frame_list[i]);
+#if 0
#ifndef XENHVM
/* Link back into the page tables if not highmem. */
if (pfn < max_low_pfn) {
@@ -268,6 +271,7 @@ increase_reservation(unsigned long nr_pages)
("HYPERVISOR_update_va_mapping failed"));
}
#endif
+#endif
/* Relinquish the page back to the allocator. */
vm_page_unwire(page, 0);
@@ -447,6 +451,9 @@ balloon_init(void *arg)
{
#ifndef XENHVM
vm_page_t page;
+ unsigned long pfn;
+
+#define max_pfn HYPERVISOR_shared_info->arch.max_pfn
#endif
if (!is_running_on_xen())
@@ -477,6 +484,7 @@ balloon_init(void *arg)
page = PHYS_TO_VM_PAGE(pfn << PAGE_SHIFT);
balloon_append(page);
}
+#undef max_pfn
#endif
target_watch.callback = watch_target;
diff --git a/sys/dev/xen/console/console.c b/sys/dev/xen/console/console.c
index 0634dad..ac8ebac 100644
--- a/sys/dev/xen/console/console.c
+++ b/sys/dev/xen/console/console.c
@@ -225,7 +225,6 @@ static int
xc_attach(device_t dev)
{
int error;
- struct xc_softc *sc = (struct xc_softc *)device_get_softc(dev);
if (xen_start_info->flags & SIF_INITDOMAIN) {
xc_consdev.cn_putc = xccnputc_dom0;
@@ -247,7 +246,7 @@ xc_attach(device_t dev)
0,
"console",
NULL,
- xencons_priv_interrupt,
+ xencons_priv_interrupt, NULL,
INTR_TYPE_TTY, NULL);
KASSERT(error >= 0, ("can't register console interrupt"));
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index b890da7..215f943 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -1549,7 +1549,6 @@ static struct vop_vector devfs_specops = {
.vop_create = VOP_PANIC,
.vop_fsync = devfs_fsync,
.vop_getattr = devfs_getattr,
- .vop_lease = VOP_NULL,
.vop_link = VOP_PANIC,
.vop_mkdir = VOP_PANIC,
.vop_mknod = VOP_PANIC,
diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c
index c8bc5ab4..66963bc 100644
--- a/sys/fs/fifofs/fifo_vnops.c
+++ b/sys/fs/fifofs/fifo_vnops.c
@@ -118,7 +118,6 @@ struct vop_vector fifo_specops = {
.vop_getattr = VOP_EBADF,
.vop_ioctl = fifo_ioctl,
.vop_kqfilter = fifo_kqfilter,
- .vop_lease = VOP_NULL,
.vop_link = VOP_PANIC,
.vop_mkdir = VOP_PANIC,
.vop_mknod = VOP_PANIC,
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index 38da43f..3434deb 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -614,14 +614,6 @@ null_unlock(struct vop_unlock_args *ap)
return (error);
}
-static int
-null_islocked(struct vop_islocked_args *ap)
-{
- struct vnode *vp = ap->a_vp;
-
- return (lockstatus(vp->v_vnlock));
-}
-
/*
* There is no way to tell that someone issued remove/rmdir operation
* on the underlying filesystem. For now we just have to release lowervp
@@ -732,7 +724,7 @@ struct vop_vector null_vnodeops = {
.vop_getattr = null_getattr,
.vop_getwritemount = null_getwritemount,
.vop_inactive = null_inactive,
- .vop_islocked = null_islocked,
+ .vop_islocked = vop_stdislocked,
.vop_lock1 = null_lock,
.vop_lookup = null_lookup,
.vop_open = null_open,
diff --git a/sys/fs/pseudofs/pseudofs_vnops.c b/sys/fs/pseudofs/pseudofs_vnops.c
index be86f4e..cf2d3aa 100644
--- a/sys/fs/pseudofs/pseudofs_vnops.c
+++ b/sys/fs/pseudofs/pseudofs_vnops.c
@@ -52,6 +52,20 @@ __FBSDID("$FreeBSD$");
#include <fs/pseudofs/pseudofs.h>
#include <fs/pseudofs/pseudofs_internal.h>
+#define KASSERT_PN_IS_DIR(pn) \
+ KASSERT((pn)->pn_type == pfstype_root || \
+ (pn)->pn_type == pfstype_dir || \
+ (pn)->pn_type == pfstype_procdir, \
+ ("%s(): VDIR vnode refers to non-directory pfs_node", __func__))
+
+#define KASSERT_PN_IS_FILE(pn) \
+ KASSERT((pn)->pn_type == pfstype_file, \
+ ("%s(): VREG vnode refers to non-file pfs_node", __func__))
+
+#define KASSERT_PN_IS_LINK(pn) \
+ KASSERT((pn)->pn_type == pfstype_symlink, \
+ ("%s(): VLNK vnode refers to non-link pfs_node", __func__))
+
/*
* Returns the fileno, adjusted for target pid
*/
@@ -257,6 +271,7 @@ pfs_ioctl(struct vop_ioctl_args *va)
if (vn->v_type != VREG)
PFS_RETURN (EINVAL);
+ KASSERT_PN_IS_FILE(pn);
if (pn->pn_ioctl == NULL)
PFS_RETURN (ENOTTY);
@@ -411,6 +426,7 @@ pfs_lookup(struct vop_cachedlookup_args *va)
if (vn->v_type != VDIR)
PFS_RETURN (ENOTDIR);
+ KASSERT_PN_IS_DIR(pd);
error = VOP_ACCESS(vn, VEXEC, cnp->cn_cred, cnp->cn_thread);
if (error)
@@ -565,6 +581,7 @@ pfs_read(struct vop_read_args *va)
if (vn->v_type != VREG)
PFS_RETURN (EINVAL);
+ KASSERT_PN_IS_FILE(pn);
if (!(pn->pn_flags & PFS_RD))
PFS_RETURN (EBADF);
@@ -707,6 +724,7 @@ pfs_readdir(struct vop_readdir_args *va)
if (vn->v_type != VDIR)
PFS_RETURN (ENOTDIR);
+ KASSERT_PN_IS_DIR(pd);
uio = va->a_uio;
/* only allow reading entire entries */
@@ -815,6 +833,7 @@ pfs_readlink(struct vop_readlink_args *va)
if (vn->v_type != VLNK)
PFS_RETURN (EINVAL);
+ KASSERT_PN_IS_LINK(pn);
if (pn->pn_fill == NULL)
PFS_RETURN (EIO);
@@ -900,8 +919,7 @@ pfs_write(struct vop_write_args *va)
if (vn->v_type != VREG)
PFS_RETURN (EINVAL);
- KASSERT(pn->pn_type != pfstype_file,
- ("%s(): VREG vnode refers to non-file pfs_node", __func__));
+ KASSERT_PN_IS_FILE(pn);
if (!(pn->pn_flags & PFS_WR))
PFS_RETURN (EBADF);
@@ -921,9 +939,7 @@ pfs_write(struct vop_write_args *va)
}
if (pn->pn_flags & PFS_RAWWR) {
- pfs_lock(pn);
error = pn_fill(curthread, proc, pn, NULL, uio);
- pfs_unlock(pn);
if (proc != NULL)
PRELE(proc);
PFS_RETURN (error);
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c
index beaef2f..69165e3 100644
--- a/sys/fs/unionfs/union_subr.c
+++ b/sys/fs/unionfs/union_subr.c
@@ -805,10 +805,6 @@ unionfs_mkshadowdir(struct unionfs_mount *ump, struct vnode *udvp,
if ((error = vn_start_write(udvp, &mp, V_WAIT | PCATCH)))
goto unionfs_mkshadowdir_free_out;
- if ((error = VOP_LEASE(udvp, td, cn.cn_cred, LEASE_WRITE))) {
- vn_finished_write(mp);
- goto unionfs_mkshadowdir_free_out;
- }
unionfs_create_uppervattr_core(ump, &lva, &va, td);
error = VOP_MKDIR(udvp, &uvp, &cn, &va);
@@ -874,8 +870,7 @@ unionfs_mkwhiteout(struct vnode *dvp, struct componentname *cnp,
if ((error = vn_start_write(dvp, &mp, V_WAIT | PCATCH)))
goto unionfs_mkwhiteout_free_out;
- if (!(error = VOP_LEASE(dvp, td, td->td_ucred, LEASE_WRITE)))
- error = VOP_WHITEOUT(dvp, &cn, CREATE);
+ error = VOP_WHITEOUT(dvp, &cn, CREATE);
vn_finished_write(mp);
@@ -949,9 +944,6 @@ unionfs_vn_create_on_upper(struct vnode **vpp, struct vnode *udvp,
goto unionfs_vn_create_on_upper_free_out1;
}
- if ((error = VOP_LEASE(udvp, td, cred, LEASE_WRITE)) != 0)
- goto unionfs_vn_create_on_upper_free_out1;
-
if ((error = VOP_CREATE(udvp, &vp, &cn, uvap)) != 0)
goto unionfs_vn_create_on_upper_free_out1;
@@ -999,10 +991,6 @@ unionfs_copyfile_core(struct vnode *lvp, struct vnode *uvp,
uio.uio_segflg = UIO_SYSSPACE;
uio.uio_offset = 0;
- if ((error = VOP_LEASE(lvp, td, cred, LEASE_READ)) != 0)
- return (error);
- if ((error = VOP_LEASE(uvp, td, cred, LEASE_WRITE)) != 0)
- return (error);
buf = malloc(MAXBSIZE, M_TEMP, M_WAITOK);
while (error == 0) {
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
index d16851d..8505cac 100644
--- a/sys/fs/unionfs/union_vnops.c
+++ b/sys/fs/unionfs/union_vnops.c
@@ -902,27 +902,6 @@ unionfs_write(struct vop_write_args *ap)
}
static int
-unionfs_lease(struct vop_lease_args *ap)
-{
- int error;
- struct unionfs_node *unp;
- struct vnode *vp;
-
- UNIONFS_INTERNAL_DEBUG("unionfs_lease: enter\n");
-
- KASSERT_UNIONFS_VNODE(ap->a_vp);
-
- unp = VTOUNIONFS(ap->a_vp);
- vp = (unp->un_uppervp != NULLVP ? unp->un_uppervp : unp->un_lowervp);
-
- error = VOP_LEASE(vp, ap->a_td, ap->a_cred, ap->a_flag);
-
- UNIONFS_INTERNAL_DEBUG("unionfs_lease: lease (%d)\n", error);
-
- return (error);
-}
-
-static int
unionfs_ioctl(struct vop_ioctl_args *ap)
{
int error;
@@ -947,7 +926,7 @@ unionfs_ioctl(struct vop_ioctl_args *ap)
error = VOP_IOCTL(ovp, ap->a_command, ap->a_data, ap->a_fflag,
ap->a_cred, ap->a_td);
- UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: lease (%d)\n", error);
+ UNIONFS_INTERNAL_DEBUG("unionfs_ioctl: leave (%d)\n", error);
return (error);
}
@@ -2461,7 +2440,6 @@ struct vop_vector unionfs_vnodeops = {
.vop_getwritemount = unionfs_getwritemount,
.vop_inactive = unionfs_inactive,
.vop_ioctl = unionfs_ioctl,
- .vop_lease = unionfs_lease,
.vop_link = unionfs_link,
.vop_listextattr = unionfs_listextattr,
.vop_lock1 = unionfs_lock,
diff --git a/sys/geom/eli/g_eli.c b/sys/geom/eli/g_eli.c
index 596b455..2a405c5b 100644
--- a/sys/geom/eli/g_eli.c
+++ b/sys/geom/eli/g_eli.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bio.h>
#include <sys/sysctl.h>
#include <sys/malloc.h>
+#include <sys/eventhandler.h>
#include <sys/kthread.h>
#include <sys/proc.h>
#include <sys/sched.h>
@@ -81,8 +82,12 @@ TUNABLE_INT("kern.geom.eli.batch", &g_eli_batch);
SYSCTL_UINT(_kern_geom_eli, OID_AUTO, batch, CTLFLAG_RW, &g_eli_batch, 0,
"Use crypto operations batching");
+static eventhandler_tag g_eli_pre_sync = NULL;
+
static int g_eli_destroy_geom(struct gctl_req *req, struct g_class *mp,
struct g_geom *gp);
+static void g_eli_init(struct g_class *mp);
+static void g_eli_fini(struct g_class *mp);
static g_taste_t g_eli_taste;
static g_dumpconf_t g_eli_dumpconf;
@@ -92,7 +97,9 @@ struct g_class g_eli_class = {
.version = G_VERSION,
.ctlreq = g_eli_config,
.taste = g_eli_taste,
- .destroy_geom = g_eli_destroy_geom
+ .destroy_geom = g_eli_destroy_geom,
+ .init = g_eli_init,
+ .fini = g_eli_fini
};
@@ -996,7 +1003,6 @@ g_eli_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
/*
* We have correct key, let's attach provider.
*/
- md.md_flags |= G_ELI_FLAG_WO_DETACH;
gp = g_eli_create(NULL, mp, pp, &md, mkey, nkey);
bzero(mkey, sizeof(mkey));
bzero(&md, sizeof(md));
@@ -1076,5 +1082,52 @@ g_eli_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
g_eli_algo2str(sc->sc_ealgo));
}
+static void
+g_eli_shutdown_pre_sync(void *arg, int howto)
+{
+ struct g_class *mp;
+ struct g_geom *gp, *gp2;
+ struct g_provider *pp;
+ struct g_eli_softc *sc;
+ int error;
+
+ mp = arg;
+ DROP_GIANT();
+ g_topology_lock();
+ LIST_FOREACH_SAFE(gp, &mp->geom, geom, gp2) {
+ sc = gp->softc;
+ if (sc == NULL)
+ continue;
+ pp = LIST_FIRST(&gp->provider);
+ KASSERT(pp != NULL, ("No provider? gp=%p (%s)", gp, gp->name));
+ if (pp->acr + pp->acw + pp->ace == 0)
+ error = g_eli_destroy(sc, 1);
+ else {
+ sc->sc_flags |= G_ELI_FLAG_RW_DETACH;
+ gp->access = g_eli_access;
+ }
+ }
+ g_topology_unlock();
+ PICKUP_GIANT();
+}
+
+static void
+g_eli_init(struct g_class *mp)
+{
+
+ g_eli_pre_sync = EVENTHANDLER_REGISTER(shutdown_pre_sync,
+ g_eli_shutdown_pre_sync, mp, SHUTDOWN_PRI_FIRST);
+ if (g_eli_pre_sync == NULL)
+ G_ELI_DEBUG(0, "Warning! Cannot register shutdown event.");
+}
+
+static void
+g_eli_fini(struct g_class *mp)
+{
+
+ if (g_eli_pre_sync != NULL)
+ EVENTHANDLER_DEREGISTER(shutdown_pre_sync, g_eli_pre_sync);
+}
+
DECLARE_GEOM_CLASS(g_eli_class, g_eli);
MODULE_DEPEND(g_eli, crypto, 1, 1, 1);
diff --git a/sys/geom/label/g_label.c b/sys/geom/label/g_label.c
index a6685e9..288489a 100644
--- a/sys/geom/label/g_label.c
+++ b/sys/geom/label/g_label.c
@@ -77,7 +77,8 @@ struct g_class g_label_class = {
* 6. Add your file system to manual page sbin/geom/class/label/glabel.8.
*/
const struct g_label_desc *g_labels[] = {
- &g_label_ufs,
+ &g_label_ufs_id,
+ &g_label_ufs_volume,
&g_label_iso9660,
&g_label_msdosfs,
&g_label_ext2fs,
diff --git a/sys/geom/label/g_label.h b/sys/geom/label/g_label.h
index e2d7a5e..e3541a9 100644
--- a/sys/geom/label/g_label.h
+++ b/sys/geom/label/g_label.h
@@ -64,7 +64,8 @@ struct g_label_desc {
};
/* Supported labels. */
-extern const struct g_label_desc g_label_ufs;
+extern const struct g_label_desc g_label_ufs_id;
+extern const struct g_label_desc g_label_ufs_volume;
extern const struct g_label_desc g_label_iso9660;
extern const struct g_label_desc g_label_msdosfs;
extern const struct g_label_desc g_label_ext2fs;
diff --git a/sys/geom/label/g_label_ufs.c b/sys/geom/label/g_label_ufs.c
index a1801d5..8510fc0 100644
--- a/sys/geom/label/g_label_ufs.c
+++ b/sys/geom/label/g_label_ufs.c
@@ -39,12 +39,16 @@ __FBSDID("$FreeBSD$");
#include <geom/geom.h>
#include <geom/label/g_label.h>
-#define G_LABEL_UFS_DIR "ufs"
+#define G_LABEL_UFS_VOLUME_DIR "ufs"
+#define G_LABEL_UFS_ID_DIR "ufsid"
+
+#define G_LABEL_UFS_VOLUME 0
+#define G_LABEL_UFS_ID 1
static const int superblocks[] = SBLOCKSEARCH;
static void
-g_label_ufs_taste(struct g_consumer *cp, char *label, size_t size)
+g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int what)
{
struct g_provider *pp;
int sb, superblock;
@@ -96,18 +100,50 @@ g_label_ufs_taste(struct g_consumer *cp, char *label, size_t size)
}
G_LABEL_DEBUG(1, "%s file system detected on %s.",
fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2", pp->name);
- /* Check for volume label */
- if (fs->fs_volname[0] == '\0') {
- g_free(fs);
- continue;
+ switch (what) {
+ case G_LABEL_UFS_VOLUME:
+ /* Check for volume label */
+ if (fs->fs_volname[0] == '\0') {
+ g_free(fs);
+ continue;
+ }
+ strlcpy(label, fs->fs_volname, size);
+ break;
+ case G_LABEL_UFS_ID:
+ if (fs->fs_id[0] == 0 && fs->fs_id[1] == 0) {
+ g_free(fs);
+ continue;
+ }
+ snprintf(label, size, "%08x%08x", fs->fs_id[0],
+ fs->fs_id[1]);
+ break;
}
- strlcpy(label, fs->fs_volname, size);
g_free(fs);
break;
}
}
-const struct g_label_desc g_label_ufs = {
- .ld_taste = g_label_ufs_taste,
- .ld_dir = G_LABEL_UFS_DIR
+static void
+g_label_ufs_volume_taste(struct g_consumer *cp, char *label, size_t size)
+{
+
+ g_label_ufs_taste_common(cp, label, size, G_LABEL_UFS_VOLUME);
+}
+
+static void
+g_label_ufs_id_taste(struct g_consumer *cp, char *label, size_t size)
+{
+
+ g_label_ufs_taste_common(cp, label, size, G_LABEL_UFS_ID);
+}
+
+
+const struct g_label_desc g_label_ufs_volume = {
+ .ld_taste = g_label_ufs_volume_taste,
+ .ld_dir = G_LABEL_UFS_VOLUME_DIR
+};
+
+const struct g_label_desc g_label_ufs_id = {
+ .ld_taste = g_label_ufs_id_taste,
+ .ld_dir = G_LABEL_UFS_ID_DIR
};
diff --git a/sys/geom/part/g_part.c b/sys/geom/part/g_part.c
index 2e8bb98..447221a 100644
--- a/sys/geom/part/g_part.c
+++ b/sys/geom/part/g_part.c
@@ -49,6 +49,10 @@ __FBSDID("$FreeBSD$");
#include "g_part_if.h"
+#ifndef _PATH_DEV
+#define _PATH_DEV "/dev/"
+#endif
+
static kobj_method_t g_part_null_methods[] = {
{ 0, 0 }
};
@@ -273,12 +277,17 @@ g_part_new_provider(struct g_geom *gp, struct g_part_table *table,
}
static int
-g_part_parm_geom(const char *p, struct g_geom **v)
+g_part_parm_geom(const char *rawname, struct g_geom **v)
{
struct g_geom *gp;
+ const char *pname;
+ if (strncmp(rawname, _PATH_DEV, strlen(_PATH_DEV)) == 0)
+ pname = rawname + strlen(_PATH_DEV);
+ else
+ pname = rawname;
LIST_FOREACH(gp, &g_part_class.geom, geom) {
- if (!strcmp(p, gp->name))
+ if (!strcmp(pname, gp->name))
break;
}
if (gp == NULL)
@@ -288,11 +297,14 @@ g_part_parm_geom(const char *p, struct g_geom **v)
}
static int
-g_part_parm_provider(const char *p, struct g_provider **v)
+g_part_parm_provider(const char *pname, struct g_provider **v)
{
struct g_provider *pp;
- pp = g_provider_by_name(p);
+ if (strncmp(pname, _PATH_DEV, strlen(_PATH_DEV)) == 0)
+ pp = g_provider_by_name(pname + strlen(_PATH_DEV));
+ else
+ pp = g_provider_by_name(pname);
if (pp == NULL)
return (EINVAL);
*v = pp;
@@ -1714,7 +1726,10 @@ g_part_start(struct bio *bp)
* used.
*/
if (!G_PART_DUMPTO(table, entry)) {
- g_io_deliver(bp, ENXIO);
+ g_io_deliver(bp, ENODEV);
+ printf("GEOM_PART: Partition '%s' not suitable"
+ " for kernel dumps (wrong type?)\n",
+ pp->name);
return;
}
gkd = (struct g_kerneldump *)bp->bio_data;
diff --git a/sys/geom/part/g_part_apm.c b/sys/geom/part/g_part_apm.c
index e205da1..030a0e6 100644
--- a/sys/geom/part/g_part_apm.c
+++ b/sys/geom/part/g_part_apm.c
@@ -216,6 +216,11 @@ g_part_apm_create(struct g_part_table *basetable, struct g_part_parms *gpp)
{
struct g_provider *pp;
struct g_part_apm_table *table;
+ uint32_t last;
+
+ /* We don't nest, which means that our depth should be 0. */
+ if (basetable->gpt_depth != 0)
+ return (ENXIO);
table = (struct g_part_apm_table *)basetable;
pp = gpp->gpp_provider;
@@ -223,12 +228,15 @@ g_part_apm_create(struct g_part_table *basetable, struct g_part_parms *gpp)
pp->mediasize < (2 + 2 * basetable->gpt_entries) * pp->sectorsize)
return (ENOSPC);
+ /* APM uses 32-bit LBAs. */
+ last = MIN(pp->mediasize / pp->sectorsize, 0xffffffff) - 1;
+
basetable->gpt_first = 2 + basetable->gpt_entries;
- basetable->gpt_last = (pp->mediasize / pp->sectorsize) - 1;
+ basetable->gpt_last = last;
table->ddr.ddr_sig = APM_DDR_SIG;
table->ddr.ddr_blksize = pp->sectorsize;
- table->ddr.ddr_blkcount = basetable->gpt_last + 1;
+ table->ddr.ddr_blkcount = last + 1;
table->self.ent_sig = APM_ENT_SIG;
table->self.ent_pmblkcnt = basetable->gpt_entries + 1;
diff --git a/sys/geom/part/g_part_bsd.c b/sys/geom/part/g_part_bsd.c
index 34548b4..b476bfd 100644
--- a/sys/geom/part/g_part_bsd.c
+++ b/sys/geom/part/g_part_bsd.c
@@ -192,8 +192,7 @@ g_part_bsd_create(struct g_part_table *basetable, struct g_part_parms *gpp)
struct g_part_bsd_entry *entry;
struct g_part_bsd_table *table;
u_char *ptr;
- uint64_t msize;
- uint32_t ncyls, secpercyl;
+ uint32_t msize, ncyls, secpercyl;
pp = gpp->gpp_provider;
cp = LIST_FIRST(&pp->consumers);
@@ -203,7 +202,7 @@ g_part_bsd_create(struct g_part_table *basetable, struct g_part_parms *gpp)
if (BBSIZE % pp->sectorsize)
return (ENOTBLK);
- msize = pp->mediasize / pp->sectorsize;
+ msize = MIN(pp->mediasize / pp->sectorsize, 0xffffffff);
secpercyl = basetable->gpt_sectors * basetable->gpt_heads;
ncyls = msize / secpercyl;
diff --git a/sys/geom/part/g_part_ebr.c b/sys/geom/part/g_part_ebr.c
index c307330..0d0b527 100644
--- a/sys/geom/part/g_part_ebr.c
+++ b/sys/geom/part/g_part_ebr.c
@@ -237,7 +237,7 @@ g_part_ebr_create(struct g_part_table *basetable, struct g_part_parms *gpp)
char psn[8];
struct g_consumer *cp;
struct g_provider *pp;
- uint64_t msize;
+ uint32_t msize;
int error;
pp = gpp->gpp_provider;
@@ -257,10 +257,11 @@ g_part_ebr_create(struct g_part_table *basetable, struct g_part_parms *gpp)
if (strcmp(psn, "MBR"))
return (ENXIO);
- msize = pp->mediasize / pp->sectorsize;
- basetable->gpt_entries = msize / basetable->gpt_sectors;
+ msize = MIN(pp->mediasize / pp->sectorsize, 0xffffffff);
+ msize -= msize % basetable->gpt_sectors;
basetable->gpt_first = 0;
- basetable->gpt_last = msize - (msize % basetable->gpt_sectors) - 1;
+ basetable->gpt_last = msize - 1;
+ basetable->gpt_entries = msize / basetable->gpt_sectors;
return (0);
}
@@ -343,7 +344,7 @@ g_part_ebr_name(struct g_part_table *table, struct g_part_entry *entry,
char *buf, size_t bufsz)
{
- snprintf(buf, bufsz, ".%08u", entry->gpe_index);
+ snprintf(buf, bufsz, "+%08u", entry->gpe_index);
return (buf);
}
@@ -402,9 +403,14 @@ g_part_ebr_probe(struct g_part_table *table, struct g_consumer *cp)
if (magic != DOSMAGIC)
goto out;
- /* The sector is all zeroes, except for the partition entries. */
+ /*
+ * The sector is all zeroes, except for the partition entries
+ * and some signatures or disk serial number. Those can be
+ * found in the 9 bytes immediately in front of the partition
+ * table.
+ */
sum = 0;
- for (index = 0; index < DOSPARTOFF; index++)
+ for (index = 0; index < DOSPARTOFF - 9; index++)
sum += buf[index];
if (sum != 0)
goto out;
@@ -420,7 +426,7 @@ g_part_ebr_probe(struct g_part_table *table, struct g_consumer *cp)
goto out;
}
- res = G_PART_PROBE_PRI_HIGH;
+ res = G_PART_PROBE_PRI_NORM;
out:
g_free(buf);
diff --git a/sys/geom/part/g_part_gpt.c b/sys/geom/part/g_part_gpt.c
index db6ebdc..cfbd897 100644
--- a/sys/geom/part/g_part_gpt.c
+++ b/sys/geom/part/g_part_gpt.c
@@ -393,6 +393,10 @@ g_part_gpt_create(struct g_part_table *basetable, struct g_part_parms *gpp)
quad_t last;
size_t tblsz;
+ /* We don't nest, which means that our depth should be 0. */
+ if (basetable->gpt_depth != 0)
+ return (ENXIO);
+
table = (struct g_part_gpt_table *)basetable;
pp = gpp->gpp_provider;
tblsz = (basetable->gpt_entries * sizeof(struct gpt_ent) +
diff --git a/sys/geom/part/g_part_mbr.c b/sys/geom/part/g_part_mbr.c
index e058b05..72d0ecb 100644
--- a/sys/geom/part/g_part_mbr.c
+++ b/sys/geom/part/g_part_mbr.c
@@ -230,7 +230,7 @@ g_part_mbr_create(struct g_part_table *basetable, struct g_part_parms *gpp)
struct g_consumer *cp;
struct g_provider *pp;
struct g_part_mbr_table *table;
- uint64_t msize;
+ uint32_t msize;
pp = gpp->gpp_provider;
cp = LIST_FIRST(&pp->consumers);
@@ -238,7 +238,7 @@ g_part_mbr_create(struct g_part_table *basetable, struct g_part_parms *gpp)
if (pp->sectorsize < MBRSIZE)
return (ENOSPC);
- msize = pp->mediasize / pp->sectorsize;
+ msize = MIN(pp->mediasize / pp->sectorsize, 0xffffffff);
basetable->gpt_first = basetable->gpt_sectors;
basetable->gpt_last = msize - (msize % basetable->gpt_sectors) - 1;
diff --git a/sys/geom/part/g_part_pc98.c b/sys/geom/part/g_part_pc98.c
index f9be0cc..8857f9b 100644
--- a/sys/geom/part/g_part_pc98.c
+++ b/sys/geom/part/g_part_pc98.c
@@ -218,8 +218,7 @@ g_part_pc98_create(struct g_part_table *basetable, struct g_part_parms *gpp)
struct g_consumer *cp;
struct g_provider *pp;
struct g_part_pc98_table *table;
- uint64_t msize;
- uint32_t cyl;
+ uint32_t cyl, msize;
pp = gpp->gpp_provider;
cp = LIST_FIRST(&pp->consumers);
@@ -231,7 +230,7 @@ g_part_pc98_create(struct g_part_table *basetable, struct g_part_parms *gpp)
cyl = basetable->gpt_heads * basetable->gpt_sectors;
- msize = pp->mediasize / SECSIZE;
+ msize = MIN(pp->mediasize / SECSIZE, 0xffffffff);
basetable->gpt_first = cyl;
basetable->gpt_last = msize - (msize % cyl) - 1;
diff --git a/sys/geom/vinum/geom_vinum.c b/sys/geom/vinum/geom_vinum.c
index 1a915ed..4a6760a 100644
--- a/sys/geom/vinum/geom_vinum.c
+++ b/sys/geom/vinum/geom_vinum.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
+ * Copyright (c) 2007, 2009 Ulf Lilleengen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,6 +32,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bio.h>
#include <sys/kernel.h>
+#include <sys/kthread.h>
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/module.h>
@@ -41,7 +43,7 @@ __FBSDID("$FreeBSD$");
#include <geom/geom.h>
#include <geom/vinum/geom_vinum_var.h>
#include <geom/vinum/geom_vinum.h>
-#include <geom/vinum/geom_vinum_share.h>
+#include <geom/vinum/geom_vinum_raid5.h>
SYSCTL_DECL(_kern_geom);
SYSCTL_NODE(_kern_geom, OID_AUTO, vinum, CTLFLAG_RW, 0, "GEOM_VINUM stuff");
@@ -50,14 +52,18 @@ TUNABLE_INT("kern.geom.vinum.debug", &g_vinum_debug);
SYSCTL_UINT(_kern_geom_vinum, OID_AUTO, debug, CTLFLAG_RW, &g_vinum_debug, 0,
"Debug level");
-int gv_create(struct g_geom *, struct gctl_req *);
+static int gv_create(struct g_geom *, struct gctl_req *);
+static void gv_attach(struct gv_softc *, struct gctl_req *);
+static void gv_detach(struct gv_softc *, struct gctl_req *);
+static void gv_parityop(struct gv_softc *, struct gctl_req *);
+
static void
gv_orphan(struct g_consumer *cp)
{
struct g_geom *gp;
struct gv_softc *sc;
- int error;
+ struct gv_drive *d;
g_topology_assert();
@@ -65,59 +71,90 @@ gv_orphan(struct g_consumer *cp)
gp = cp->geom;
KASSERT(gp != NULL, ("gv_orphan: null gp"));
sc = gp->softc;
+ KASSERT(sc != NULL, ("gv_orphan: null sc"));
+ d = cp->private;
+ KASSERT(d != NULL, ("gv_orphan: null d"));
g_trace(G_T_TOPOLOGY, "gv_orphan(%s)", gp->name);
- if (cp->acr != 0 || cp->acw != 0 || cp->ace != 0)
- g_access(cp, -cp->acr, -cp->acw, -cp->ace);
- error = cp->provider->error;
- if (error == 0)
- error = ENXIO;
- g_detach(cp);
- g_destroy_consumer(cp);
- if (!LIST_EMPTY(&gp->consumer))
- return;
- g_free(sc);
- g_wither_geom(gp, error);
+ gv_post_event(sc, GV_EVENT_DRIVE_LOST, d, NULL, 0, 0);
}
-static void
+void
gv_start(struct bio *bp)
{
- struct bio *bp2;
struct g_geom *gp;
+ struct gv_softc *sc;
gp = bp->bio_to->geom;
- switch(bp->bio_cmd) {
+ sc = gp->softc;
+
+ switch (bp->bio_cmd) {
case BIO_READ:
case BIO_WRITE:
case BIO_DELETE:
- bp2 = g_clone_bio(bp);
- if (bp2 == NULL)
- g_io_deliver(bp, ENOMEM);
- else {
- bp2->bio_done = g_std_done;
- g_io_request(bp2, LIST_FIRST(&gp->consumer));
- }
- return;
+ break;
+ case BIO_GETATTR:
default:
g_io_deliver(bp, EOPNOTSUPP);
return;
}
+
+ mtx_lock(&sc->queue_mtx);
+ bioq_disksort(sc->bqueue, bp);
+ wakeup(sc);
+ mtx_unlock(&sc->queue_mtx);
}
-static int
+void
+gv_done(struct bio *bp)
+{
+ struct g_geom *gp;
+ struct gv_softc *sc;
+
+ KASSERT(bp != NULL, ("NULL bp"));
+
+ gp = bp->bio_from->geom;
+ sc = gp->softc;
+ bp->bio_cflags |= GV_BIO_DONE;
+
+ mtx_lock(&sc->queue_mtx);
+ bioq_disksort(sc->bqueue, bp);
+ wakeup(sc);
+ mtx_unlock(&sc->queue_mtx);
+}
+
+int
gv_access(struct g_provider *pp, int dr, int dw, int de)
{
struct g_geom *gp;
- struct g_consumer *cp;
+ struct gv_softc *sc;
+ struct gv_drive *d, *d2;
int error;
- gp = pp->geom;
error = ENXIO;
- cp = LIST_FIRST(&gp->consumer);
- error = g_access(cp, dr, dw, de);
- return (error);
+ gp = pp->geom;
+ sc = gp->softc;
+ if (dw > 0 && dr == 0)
+ dr = 1;
+ else if (dw < 0 && dr == 0)
+ dr = -1;
+ LIST_FOREACH(d, &sc->drives, drive) {
+ if (d->consumer == NULL)
+ continue;
+ error = g_access(d->consumer, dr, dw, de);
+ if (error) {
+ LIST_FOREACH(d2, &sc->drives, drive) {
+ if (d == d2)
+ break;
+ g_access(d2->consumer, -dr, -dw, -de);
+ }
+ G_VINUM_DEBUG(0, "g_access '%s' failed: %d", d->name,
+ error);
+ return (error);
+ }
+ }
+ return (0);
}
static void
@@ -136,14 +173,132 @@ gv_init(struct g_class *mp)
gp->softc = g_malloc(sizeof(struct gv_softc), M_WAITOK | M_ZERO);
sc = gp->softc;
sc->geom = gp;
+ sc->bqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
+ bioq_init(sc->bqueue);
LIST_INIT(&sc->drives);
LIST_INIT(&sc->subdisks);
LIST_INIT(&sc->plexes);
LIST_INIT(&sc->volumes);
+ TAILQ_INIT(&sc->equeue);
+ mtx_init(&sc->config_mtx, "gv_config", NULL, MTX_DEF);
+ mtx_init(&sc->queue_mtx, "gv_queue", NULL, MTX_DEF);
+ kproc_create(gv_worker, sc, NULL, 0, 0, "gv_worker");
+}
+
+static int
+gv_unload(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
+{
+ struct gv_softc *sc;
+
+ g_trace(G_T_TOPOLOGY, "gv_unload(%p)", mp);
+
+ g_topology_assert();
+ sc = gp->softc;
+
+ if (sc != NULL) {
+ gv_post_event(sc, GV_EVENT_THREAD_EXIT, NULL, NULL, 0, 0);
+ gp->softc = NULL;
+ g_wither_geom(gp, ENXIO);
+ return (EAGAIN);
+ }
+
+ return (0);
+}
+
+/* Handle userland request of attaching object. */
+static void
+gv_attach(struct gv_softc *sc, struct gctl_req *req)
+{
+ struct gv_volume *v;
+ struct gv_plex *p;
+ struct gv_sd *s;
+ off_t *offset;
+ int *rename, type_child, type_parent;
+ char *child, *parent;
+
+ child = gctl_get_param(req, "child", NULL);
+ if (child == NULL) {
+ gctl_error(req, "no child given");
+ return;
+ }
+ parent = gctl_get_param(req, "parent", NULL);
+ if (parent == NULL) {
+ gctl_error(req, "no parent given");
+ return;
+ }
+ offset = gctl_get_paraml(req, "offset", sizeof(*offset));
+ if (offset == NULL) {
+ gctl_error(req, "no offset given");
+ return;
+ }
+ rename = gctl_get_paraml(req, "rename", sizeof(*rename));
+ if (rename == NULL) {
+ gctl_error(req, "no rename flag given");
+ return;
+ }
+
+ type_child = gv_object_type(sc, child);
+ type_parent = gv_object_type(sc, parent);
+
+ switch (type_child) {
+ case GV_TYPE_PLEX:
+ if (type_parent != GV_TYPE_VOL) {
+ gctl_error(req, "no such volume to attach to");
+ return;
+ }
+ v = gv_find_vol(sc, parent);
+ p = gv_find_plex(sc, child);
+ gv_post_event(sc, GV_EVENT_ATTACH_PLEX, p, v, *offset, *rename);
+ break;
+ case GV_TYPE_SD:
+ if (type_parent != GV_TYPE_PLEX) {
+ gctl_error(req, "no such plex to attach to");
+ return;
+ }
+ p = gv_find_plex(sc, parent);
+ s = gv_find_sd(sc, child);
+ gv_post_event(sc, GV_EVENT_ATTACH_SD, s, p, *offset, *rename);
+ break;
+ default:
+ gctl_error(req, "invalid child type");
+ break;
+ }
+}
+
+/* Handle userland request of detaching object. */
+static void
+gv_detach(struct gv_softc *sc, struct gctl_req *req)
+{
+ struct gv_plex *p;
+ struct gv_sd *s;
+ int *flags, type;
+ char *object;
+
+ object = gctl_get_param(req, "object", NULL);
+ if (object == NULL) {
+ gctl_error(req, "no argument given");
+ return;
+ }
+
+ flags = gctl_get_paraml(req, "flags", sizeof(*flags));
+ type = gv_object_type(sc, object);
+ switch (type) {
+ case GV_TYPE_PLEX:
+ p = gv_find_plex(sc, object);
+ gv_post_event(sc, GV_EVENT_DETACH_PLEX, p, NULL, *flags, 0);
+ break;
+ case GV_TYPE_SD:
+ s = gv_find_sd(sc, object);
+ gv_post_event(sc, GV_EVENT_DETACH_SD, s, NULL, *flags, 0);
+ break;
+ default:
+ gctl_error(req, "invalid object type");
+ break;
+ }
}
/* Handle userland requests for creating new objects. */
-int
+static int
gv_create(struct g_geom *gp, struct gctl_req *req)
{
struct gv_softc *sc;
@@ -151,10 +306,9 @@ gv_create(struct g_geom *gp, struct gctl_req *req)
struct gv_plex *p, *p2;
struct gv_sd *s, *s2;
struct gv_volume *v, *v2;
- struct g_consumer *cp;
struct g_provider *pp;
- int error, i, *drives, *plexes, *subdisks, *volumes;
- char buf[20], errstr[ERRBUFSIZ];
+ int error, i, *drives, *flags, *plexes, *subdisks, *volumes;
+ char buf[20];
g_topology_assert();
@@ -170,6 +324,11 @@ gv_create(struct g_geom *gp, struct gctl_req *req)
gctl_error(req, "number of objects not given");
return (-1);
}
+ flags = gctl_get_paraml(req, "flags", sizeof(*flags));
+ if (flags == NULL) {
+ gctl_error(req, "flags not given");
+ return (-1);
+ }
/* First, handle drive definitions ... */
for (i = 0; i < *drives; i++) {
@@ -179,33 +338,33 @@ gv_create(struct g_geom *gp, struct gctl_req *req)
gctl_error(req, "no drive definition given");
return (-1);
}
- d = gv_find_drive(sc, d2->name);
- if (d != NULL) {
- gctl_error(req, "drive '%s' is already known",
- d->name);
- continue;
- }
-
- d = g_malloc(sizeof(*d), M_WAITOK | M_ZERO);
- bcopy(d2, d, sizeof(*d));
-
/*
- * Make sure that the provider specified in the drive
- * specification is an active GEOM provider.
+ * Make sure that the device specified in the drive config is
+ * an active GEOM provider.
*/
- pp = g_provider_by_name(d->device);
+ pp = g_provider_by_name(d2->device);
if (pp == NULL) {
- gctl_error(req, "%s: drive not found", d->device);
- g_free(d);
- return (-1);
+ gctl_error(req, "%s: device not found", d2->device);
+ goto error;
+ }
+ if (gv_find_drive(sc, d2->name) != NULL) {
+ /* Ignore error. */
+ if (*flags & GV_FLAG_F)
+ continue;
+ gctl_error(req, "drive '%s' already exists", d2->name);
+ goto error;
+ }
+ if (gv_find_drive_device(sc, d2->device) != NULL) {
+ gctl_error(req, "device '%s' already configured in "
+ "gvinum", d2->device);
+ goto error;
}
- d->size = pp->mediasize - GV_DATA_START;
- d->avail = d->size;
- gv_config_new_drive(d);
- d->flags |= GV_DRIVE_NEWBORN;
- LIST_INSERT_HEAD(&sc->drives, d, drive);
+ d = g_malloc(sizeof(*d), M_WAITOK | M_ZERO);
+ bcopy(d2, d, sizeof(*d));
+
+ gv_post_event(sc, GV_EVENT_CREATE_DRIVE, d, NULL, 0, 0);
}
/* ... then volume definitions ... */
@@ -217,19 +376,18 @@ gv_create(struct g_geom *gp, struct gctl_req *req)
gctl_error(req, "no volume definition given");
return (-1);
}
- v = gv_find_vol(sc, v2->name);
- if (v != NULL) {
- gctl_error(req, "volume '%s' is already known",
- v->name);
- return (-1);
+ if (gv_find_vol(sc, v2->name) != NULL) {
+ /* Ignore error. */
+ if (*flags & GV_FLAG_F)
+ continue;
+ gctl_error(req, "volume '%s' already exists", v2->name);
+ goto error;
}
v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
bcopy(v2, v, sizeof(*v));
- v->vinumconf = sc;
- LIST_INIT(&v->plexes);
- LIST_INSERT_HEAD(&sc->volumes, v, volume);
+ gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
}
/* ... then plex definitions ... */
@@ -241,35 +399,21 @@ gv_create(struct g_geom *gp, struct gctl_req *req)
gctl_error(req, "no plex definition given");
return (-1);
}
- p = gv_find_plex(sc, p2->name);
- if (p != NULL) {
- gctl_error(req, "plex '%s' is already known", p->name);
- return (-1);
+ if (gv_find_plex(sc, p2->name) != NULL) {
+ /* Ignore error. */
+ if (*flags & GV_FLAG_F)
+ continue;
+ gctl_error(req, "plex '%s' already exists", p2->name);
+ goto error;
}
p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
bcopy(p2, p, sizeof(*p));
- /* Find the volume this plex should be attached to. */
- v = gv_find_vol(sc, p->volume);
- if (v == NULL) {
- gctl_error(req, "volume '%s' not found", p->volume);
- g_free(p);
- continue;
- }
- if (v->plexcount)
- p->flags |= GV_PLEX_ADDED;
- p->vol_sc = v;
- v->plexcount++;
- LIST_INSERT_HEAD(&v->plexes, p, in_volume);
-
- p->vinumconf = sc;
- p->flags |= GV_PLEX_NEWBORN;
- LIST_INIT(&p->subdisks);
- LIST_INSERT_HEAD(&sc->plexes, p, plex);
+ gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
}
- /* ... and finally, subdisk definitions. */
+ /* ... and, finally, subdisk definitions. */
for (i = 0; i < *subdisks; i++) {
error = 0;
snprintf(buf, sizeof(buf), "sd%d", i);
@@ -278,122 +422,23 @@ gv_create(struct g_geom *gp, struct gctl_req *req)
gctl_error(req, "no subdisk definition given");
return (-1);
}
- s = gv_find_sd(sc, s2->name);
- if (s != NULL) {
- gctl_error(req, "subdisk '%s' is already known",
- s->name);
- return (-1);
+ if (gv_find_sd(sc, s2->name) != NULL) {
+ /* Ignore error. */
+ if (*flags & GV_FLAG_F)
+ continue;
+ gctl_error(req, "sd '%s' already exists", s2->name);
+ goto error;
}
s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
bcopy(s2, s, sizeof(*s));
- /* Find the drive where this subdisk should be put on. */
- d = gv_find_drive(sc, s->drive);
-
- /* drive not found - XXX */
- if (d == NULL) {
- gctl_error(req, "drive '%s' not found", s->drive);
- g_free(s);
- continue;
- }
-
- /* Find the plex where this subdisk belongs to. */
- p = gv_find_plex(sc, s->plex);
-
- /* plex not found - XXX */
- if (p == NULL) {
- gctl_error(req, "plex '%s' not found\n", s->plex);
- g_free(s);
- continue;
- }
-
- /*
- * First we give the subdisk to the drive, to handle autosized
- * values ...
- */
- error = gv_sd_to_drive(sc, d, s, errstr, sizeof(errstr));
- if (error) {
- gctl_error(req, errstr);
- g_free(s);
- continue;
- }
-
- /*
- * Then, we give the subdisk to the plex; we check if the
- * given values are correct and maybe adjust them.
- */
- error = gv_sd_to_plex(p, s, 1);
- if (error) {
- gctl_error(req, "GEOM_VINUM: couldn't give sd '%s' "
- "to plex '%s'\n", s->name, p->name);
- if (s->drive_sc)
- LIST_REMOVE(s, from_drive);
- gv_free_sd(s);
- g_free(s);
- /*
- * If this subdisk can't be created, we won't create
- * the attached plex either, if it is also a new one.
- */
- if (!(p->flags & GV_PLEX_NEWBORN))
- continue;
- LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2) {
- if (s->drive_sc)
- LIST_REMOVE(s, from_drive);
- p->sdcount--;
- LIST_REMOVE(s, in_plex);
- LIST_REMOVE(s, sd);
- gv_free_sd(s);
- g_free(s);
- }
- if (p->vol_sc != NULL) {
- LIST_REMOVE(p, in_volume);
- p->vol_sc->plexcount--;
- }
- LIST_REMOVE(p, plex);
- g_free(p);
- continue;
- }
- s->flags |= GV_SD_NEWBORN;
-
- s->vinumconf = sc;
- LIST_INSERT_HEAD(&sc->subdisks, s, sd);
+ gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
}
- LIST_FOREACH(s, &sc->subdisks, sd)
- gv_update_sd_state(s);
- LIST_FOREACH(p, &sc->plexes, plex)
- gv_update_plex_config(p);
- LIST_FOREACH(v, &sc->volumes, volume)
- gv_update_vol_state(v);
-
- /*
- * Write out the configuration to each drive. If the drive doesn't
- * have a valid geom_slice geom yet, attach it temporarily to our VINUM
- * geom.
- */
- LIST_FOREACH(d, &sc->drives, drive) {
- if (d->geom == NULL) {
- /*
- * XXX if the provider disapears before we get a chance
- * to write the config out to the drive, should this
- * be handled any differently?
- */
- pp = g_provider_by_name(d->device);
- if (pp == NULL) {
- G_VINUM_DEBUG(0, "%s: drive disappeared?",
- d->device);
- continue;
- }
- cp = g_new_consumer(gp);
- g_attach(cp, pp);
- gv_save_config(cp, d, sc);
- g_detach(cp);
- g_destroy_consumer(cp);
- } else
- gv_save_config(NULL, d, sc);
- d->flags &= ~GV_DRIVE_NEWBORN;
- }
+error:
+ gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
return (0);
}
@@ -411,13 +456,21 @@ gv_config(struct gctl_req *req, struct g_class *mp, char const *verb)
gp = LIST_FIRST(&mp->geom);
sc = gp->softc;
- if (!strcmp(verb, "list")) {
+ if (!strcmp(verb, "attach")) {
+ gv_attach(sc, req);
+
+ } else if (!strcmp(verb, "concat")) {
+ gv_concat(gp, req);
+
+ } else if (!strcmp(verb, "detach")) {
+ gv_detach(sc, req);
+
+ } else if (!strcmp(verb, "list")) {
gv_list(gp, req);
/* Save our configuration back to disk. */
} else if (!strcmp(verb, "saveconfig")) {
-
- gv_save_config_all(sc);
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
/* Return configuration in string form. */
} else if (!strcmp(verb, "getconfig")) {
@@ -435,11 +488,18 @@ gv_config(struct gctl_req *req, struct g_class *mp, char const *verb)
} else if (!strcmp(verb, "create")) {
gv_create(gp, req);
+ } else if (!strcmp(verb, "mirror")) {
+ gv_mirror(gp, req);
+
} else if (!strcmp(verb, "move")) {
gv_move(gp, req);
- } else if (!strcmp(verb, "parityop")) {
- gv_parityop(gp, req);
+ } else if (!strcmp(verb, "raid5")) {
+ gv_raid5(gp, req);
+
+ } else if (!strcmp(verb, "rebuildparity") ||
+ !strcmp(verb, "checkparity")) {
+ gv_parityop(sc, req);
} else if (!strcmp(verb, "remove")) {
gv_remove(gp, req);
@@ -448,100 +508,509 @@ gv_config(struct gctl_req *req, struct g_class *mp, char const *verb)
gv_rename(gp, req);
} else if (!strcmp(verb, "resetconfig")) {
- gv_resetconfig(gp, req);
+ gv_post_event(sc, GV_EVENT_RESET_CONFIG, sc, NULL, 0, 0);
} else if (!strcmp(verb, "start")) {
gv_start_obj(gp, req);
+ } else if (!strcmp(verb, "stripe")) {
+ gv_stripe(gp, req);
+
} else if (!strcmp(verb, "setstate")) {
gv_setstate(gp, req);
-
} else
gctl_error(req, "Unknown verb parameter");
}
-#if 0
-static int
-gv_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp)
+static void
+gv_parityop(struct gv_softc *sc, struct gctl_req *req)
{
- struct g_geom *gp2;
- struct g_consumer *cp;
- struct gv_softc *sc;
- struct gv_drive *d, *d2;
- struct gv_plex *p, *p2;
- struct gv_sd *s, *s2;
- struct gv_volume *v, *v2;
- struct gv_freelist *fl, *fl2;
+ struct gv_plex *p;
+ int *flags, *rebuild, type;
+ char *plex;
- g_trace(G_T_TOPOLOGY, "gv_destroy_geom: %s", gp->name);
- g_topology_assert();
+ plex = gctl_get_param(req, "plex", NULL);
+ if (plex == NULL) {
+ gctl_error(req, "no plex given");
+ return;
+ }
- KASSERT(gp != NULL, ("gv_destroy_geom: null gp"));
- KASSERT(gp->softc != NULL, ("gv_destroy_geom: null sc"));
+ flags = gctl_get_paraml(req, "flags", sizeof(*flags));
+ if (flags == NULL) {
+ gctl_error(req, "no flags given");
+ return;
+ }
- sc = gp->softc;
+ rebuild = gctl_get_paraml(req, "rebuild", sizeof(*rebuild));
+ if (rebuild == NULL) {
+ gctl_error(req, "no operation given");
+ return;
+ }
- /*
- * Check if any of our drives is still open; if so, refuse destruction.
- */
- LIST_FOREACH(d, &sc->drives, drive) {
- gp2 = d->geom;
- cp = LIST_FIRST(&gp2->consumer);
- if (cp != NULL)
- g_access(cp, -1, -1, -1);
- if (gv_is_open(gp2))
- return (EBUSY);
+ type = gv_object_type(sc, plex);
+ if (type != GV_TYPE_PLEX) {
+ gctl_error(req, "'%s' is not a plex", plex);
+ return;
}
+ p = gv_find_plex(sc, plex);
- /* Clean up and deallocate what we allocated. */
- LIST_FOREACH_SAFE(d, &sc->drives, drive, d2) {
- LIST_REMOVE(d, drive);
- g_free(d->hdr);
- d->hdr = NULL;
- LIST_FOREACH_SAFE(fl, &d->freelist, freelist, fl2) {
- d->freelist_entries--;
- LIST_REMOVE(fl, freelist);
- g_free(fl);
- fl = NULL;
- }
- d->geom->softc = NULL;
- g_free(d);
+ if (p->state != GV_PLEX_UP) {
+ gctl_error(req, "plex %s is not completely accessible",
+ p->name);
+ return;
}
- LIST_FOREACH_SAFE(s, &sc->subdisks, sd, s2) {
- LIST_REMOVE(s, sd);
- s->drive_sc = NULL;
- s->plex_sc = NULL;
- s->provider = NULL;
- s->consumer = NULL;
- g_free(s);
+ if (p->org != GV_PLEX_RAID5) {
+ gctl_error(req, "plex %s is not a RAID5 plex", p->name);
+ return;
}
- LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2) {
- LIST_REMOVE(p, plex);
- gv_kill_thread(p);
- p->vol_sc = NULL;
- p->geom->softc = NULL;
- p->provider = NULL;
- p->consumer = NULL;
- if (p->org == GV_PLEX_RAID5) {
- mtx_destroy(&p->worklist_mtx);
- }
- g_free(p);
+ /* Put it in the event queue. */
+ /* XXX: The state of the plex might have changed when this event is
+ * picked up ... We should perhaps check this afterwards. */
+ if (*rebuild)
+ gv_post_event(sc, GV_EVENT_PARITY_REBUILD, p, NULL, 0, 0);
+ else
+ gv_post_event(sc, GV_EVENT_PARITY_CHECK, p, NULL, 0, 0);
+}
+
+
+static struct g_geom *
+gv_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
+{
+ struct g_geom *gp;
+ struct g_consumer *cp;
+ struct gv_softc *sc;
+ struct gv_hdr vhdr;
+ int error;
+
+ g_topology_assert();
+ g_trace(G_T_TOPOLOGY, "gv_taste(%s, %s)", mp->name, pp->name);
+
+ gp = LIST_FIRST(&mp->geom);
+ if (gp == NULL) {
+ G_VINUM_DEBUG(0, "error: tasting, but not initialized?");
+ return (NULL);
}
+ sc = gp->softc;
- LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2) {
- LIST_REMOVE(v, volume);
- v->geom->softc = NULL;
- g_free(v);
+ cp = g_new_consumer(gp);
+ if (g_attach(cp, pp) != 0) {
+ g_destroy_consumer(cp);
+ return (NULL);
}
+ if (g_access(cp, 1, 0, 0) != 0) {
+ g_detach(cp);
+ g_destroy_consumer(cp);
+ return (NULL);
+ }
+ g_topology_unlock();
- gp->softc = NULL;
- g_free(sc);
- g_wither_geom(gp, ENXIO);
- return (0);
+ error = gv_read_header(cp, &vhdr);
+
+ g_topology_lock();
+ g_access(cp, -1, 0, 0);
+ g_detach(cp);
+ g_destroy_consumer(cp);
+
+ /* Check if what we've been given is a valid vinum drive. */
+ if (!error)
+ gv_post_event(sc, GV_EVENT_DRIVE_TASTED, pp, NULL, 0, 0);
+
+ return (NULL);
+}
+
+void
+gv_worker(void *arg)
+{
+ struct g_provider *pp;
+ struct gv_softc *sc;
+ struct gv_event *ev;
+ struct gv_volume *v;
+ struct gv_plex *p;
+ struct gv_sd *s;
+ struct gv_drive *d;
+ struct bio *bp;
+ int newstate, flags, err, rename;
+ char *newname;
+ off_t offset;
+
+ sc = arg;
+ KASSERT(sc != NULL, ("NULL sc"));
+ mtx_lock(&sc->queue_mtx);
+ for (;;) {
+ /* Look at the events first... */
+ ev = TAILQ_FIRST(&sc->equeue);
+ if (ev != NULL) {
+ TAILQ_REMOVE(&sc->equeue, ev, events);
+ mtx_unlock(&sc->queue_mtx);
+
+ switch (ev->type) {
+ case GV_EVENT_DRIVE_TASTED:
+ G_VINUM_DEBUG(2, "event 'drive tasted'");
+ pp = ev->arg1;
+ gv_drive_tasted(sc, pp);
+ break;
+
+ case GV_EVENT_DRIVE_LOST:
+ G_VINUM_DEBUG(2, "event 'drive lost'");
+ d = ev->arg1;
+ gv_drive_lost(sc, d);
+ break;
+
+ case GV_EVENT_CREATE_DRIVE:
+ G_VINUM_DEBUG(2, "event 'create drive'");
+ d = ev->arg1;
+ gv_create_drive(sc, d);
+ break;
+
+ case GV_EVENT_CREATE_VOLUME:
+ G_VINUM_DEBUG(2, "event 'create volume'");
+ v = ev->arg1;
+ gv_create_volume(sc, v);
+ break;
+
+ case GV_EVENT_CREATE_PLEX:
+ G_VINUM_DEBUG(2, "event 'create plex'");
+ p = ev->arg1;
+ gv_create_plex(sc, p);
+ break;
+
+ case GV_EVENT_CREATE_SD:
+ G_VINUM_DEBUG(2, "event 'create sd'");
+ s = ev->arg1;
+ gv_create_sd(sc, s);
+ break;
+
+ case GV_EVENT_RM_DRIVE:
+ G_VINUM_DEBUG(2, "event 'remove drive'");
+ d = ev->arg1;
+ flags = ev->arg3;
+ gv_rm_drive(sc, d, flags);
+ /*gv_setup_objects(sc);*/
+ break;
+
+ case GV_EVENT_RM_VOLUME:
+ G_VINUM_DEBUG(2, "event 'remove volume'");
+ v = ev->arg1;
+ gv_rm_vol(sc, v);
+ /*gv_setup_objects(sc);*/
+ break;
+
+ case GV_EVENT_RM_PLEX:
+ G_VINUM_DEBUG(2, "event 'remove plex'");
+ p = ev->arg1;
+ gv_rm_plex(sc, p);
+ /*gv_setup_objects(sc);*/
+ break;
+
+ case GV_EVENT_RM_SD:
+ G_VINUM_DEBUG(2, "event 'remove sd'");
+ s = ev->arg1;
+ gv_rm_sd(sc, s);
+ /*gv_setup_objects(sc);*/
+ break;
+
+ case GV_EVENT_SAVE_CONFIG:
+ G_VINUM_DEBUG(2, "event 'save config'");
+ gv_save_config(sc);
+ break;
+
+ case GV_EVENT_SET_SD_STATE:
+ G_VINUM_DEBUG(2, "event 'setstate sd'");
+ s = ev->arg1;
+ newstate = ev->arg3;
+ flags = ev->arg4;
+ err = gv_set_sd_state(s, newstate, flags);
+ if (err)
+ G_VINUM_DEBUG(0, "error setting subdisk"
+ " state: error code %d", err);
+ break;
+
+ case GV_EVENT_SET_DRIVE_STATE:
+ G_VINUM_DEBUG(2, "event 'setstate drive'");
+ d = ev->arg1;
+ newstate = ev->arg3;
+ flags = ev->arg4;
+ err = gv_set_drive_state(d, newstate, flags);
+ if (err)
+ G_VINUM_DEBUG(0, "error setting drive "
+ "state: error code %d", err);
+ break;
+
+ case GV_EVENT_SET_VOL_STATE:
+ G_VINUM_DEBUG(2, "event 'setstate volume'");
+ v = ev->arg1;
+ newstate = ev->arg3;
+ flags = ev->arg4;
+ err = gv_set_vol_state(v, newstate, flags);
+ if (err)
+ G_VINUM_DEBUG(0, "error setting volume "
+ "state: error code %d", err);
+ break;
+
+ case GV_EVENT_SET_PLEX_STATE:
+ G_VINUM_DEBUG(2, "event 'setstate plex'");
+ p = ev->arg1;
+ newstate = ev->arg3;
+ flags = ev->arg4;
+ err = gv_set_plex_state(p, newstate, flags);
+ if (err)
+ G_VINUM_DEBUG(0, "error setting plex "
+ "state: error code %d", err);
+ break;
+
+ case GV_EVENT_SETUP_OBJECTS:
+ G_VINUM_DEBUG(2, "event 'setup objects'");
+ gv_setup_objects(sc);
+ break;
+
+ case GV_EVENT_RESET_CONFIG:
+ G_VINUM_DEBUG(2, "event 'resetconfig'");
+ err = gv_resetconfig(sc);
+ if (err)
+ G_VINUM_DEBUG(0, "error resetting "
+ "config: error code %d", err);
+ break;
+
+ case GV_EVENT_PARITY_REBUILD:
+ /*
+ * Start the rebuild. The gv_plex_done will
+ * handle issuing of the remaining rebuild bio's
+ * until it's finished.
+ */
+ G_VINUM_DEBUG(2, "event 'rebuild'");
+ p = ev->arg1;
+ if (p->state != GV_PLEX_UP) {
+ G_VINUM_DEBUG(0, "plex %s is not "
+ "completely accessible", p->name);
+ break;
+ }
+ p->synced = 0;
+ g_topology_assert_not();
+ g_topology_lock();
+ err = gv_access(p->vol_sc->provider, 1, 1, 0);
+ if (err) {
+ G_VINUM_DEBUG(0, "unable to access "
+ "provider");
+ break;
+ }
+ g_topology_unlock();
+ gv_parity_request(p, GV_BIO_CHECK |
+ GV_BIO_PARITY, 0);
+ break;
+
+ case GV_EVENT_PARITY_CHECK:
+ /* Start parity check. */
+ G_VINUM_DEBUG(2, "event 'check'");
+ p = ev->arg1;
+ if (p->state != GV_PLEX_UP) {
+ G_VINUM_DEBUG(0, "plex %s is not "
+ "completely accessible", p->name);
+ break;
+ }
+ p->synced = 0;
+ g_topology_assert_not();
+ g_topology_lock();
+ err = gv_access(p->vol_sc->provider, 1, 1, 0);
+ if (err) {
+ G_VINUM_DEBUG(0, "unable to access "
+ "provider");
+ break;
+ }
+ g_topology_unlock();
+ gv_parity_request(p, GV_BIO_CHECK, 0);
+ break;
+
+ case GV_EVENT_START_PLEX:
+ G_VINUM_DEBUG(2, "event 'start' plex");
+ p = ev->arg1;
+ gv_start_plex(p);
+ break;
+
+ case GV_EVENT_START_VOLUME:
+ G_VINUM_DEBUG(2, "event 'start' volume");
+ v = ev->arg1;
+ gv_start_vol(v);
+ break;
+
+ case GV_EVENT_ATTACH_PLEX:
+ G_VINUM_DEBUG(2, "event 'attach' plex");
+ p = ev->arg1;
+ v = ev->arg2;
+ rename = ev->arg4;
+ err = gv_attach_plex(p, v, rename);
+ if (err)
+ G_VINUM_DEBUG(0, "error attaching %s to"
+ " %s: error code %d", p->name,
+ v->name, err);
+ break;
+
+ case GV_EVENT_ATTACH_SD:
+ G_VINUM_DEBUG(2, "event 'attach' sd");
+ s = ev->arg1;
+ p = ev->arg2;
+ offset = ev->arg3;
+ rename = ev->arg4;
+ err = gv_attach_sd(s, p, offset, rename);
+ if (err)
+ G_VINUM_DEBUG(0, "error attaching %s to"
+ " %s: error code %d", s->name,
+ p->name, err);
+ break;
+
+ case GV_EVENT_DETACH_PLEX:
+ G_VINUM_DEBUG(2, "event 'detach' plex");
+ p = ev->arg1;
+ flags = ev->arg3;
+ err = gv_detach_plex(p, flags);
+ if (err)
+ G_VINUM_DEBUG(0, "error detaching %s: "
+ "error code %d", p->name, err);
+ break;
+
+ case GV_EVENT_DETACH_SD:
+ G_VINUM_DEBUG(2, "event 'detach' sd");
+ s = ev->arg1;
+ flags = ev->arg3;
+ err = gv_detach_sd(s, flags);
+ if (err)
+ G_VINUM_DEBUG(0, "error detaching %s: "
+ "error code %d", s->name, err);
+ break;
+
+ case GV_EVENT_RENAME_VOL:
+ G_VINUM_DEBUG(2, "event 'rename' volume");
+ v = ev->arg1;
+ newname = ev->arg2;
+ flags = ev->arg3;
+ err = gv_rename_vol(sc, v, newname, flags);
+ if (err)
+ G_VINUM_DEBUG(0, "error renaming %s to "
+ "%s: error code %d", v->name,
+ newname, err);
+ g_free(newname);
+ /* Destroy and recreate the provider if we can. */
+ if (gv_provider_is_open(v->provider)) {
+ G_VINUM_DEBUG(0, "unable to rename "
+ "provider to %s: provider in use",
+ v->name);
+ break;
+ }
+ g_wither_provider(v->provider, ENOENT);
+ v->provider = NULL;
+ gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc,
+ NULL, 0, 0);
+ break;
+
+ case GV_EVENT_RENAME_PLEX:
+ G_VINUM_DEBUG(2, "event 'rename' plex");
+ p = ev->arg1;
+ newname = ev->arg2;
+ flags = ev->arg3;
+ err = gv_rename_plex(sc, p, newname, flags);
+ if (err)
+ G_VINUM_DEBUG(0, "error renaming %s to "
+ "%s: error code %d", p->name,
+ newname, err);
+ g_free(newname);
+ break;
+
+ case GV_EVENT_RENAME_SD:
+ G_VINUM_DEBUG(2, "event 'rename' sd");
+ s = ev->arg1;
+ newname = ev->arg2;
+ flags = ev->arg3;
+ err = gv_rename_sd(sc, s, newname, flags);
+ if (err)
+ G_VINUM_DEBUG(0, "error renaming %s to "
+ "%s: error code %d", s->name,
+ newname, err);
+ g_free(newname);
+ break;
+
+ case GV_EVENT_RENAME_DRIVE:
+ G_VINUM_DEBUG(2, "event 'rename' drive");
+ d = ev->arg1;
+ newname = ev->arg2;
+ flags = ev->arg3;
+ err = gv_rename_drive(sc, d, newname, flags);
+ if (err)
+ G_VINUM_DEBUG(0, "error renaming %s to "
+ "%s: error code %d", d->name,
+ newname, err);
+ g_free(newname);
+ break;
+
+ case GV_EVENT_MOVE_SD:
+ G_VINUM_DEBUG(2, "event 'move' sd");
+ s = ev->arg1;
+ d = ev->arg2;
+ flags = ev->arg3;
+ err = gv_move_sd(sc, s, d, flags);
+ if (err)
+ G_VINUM_DEBUG(0, "error moving %s to "
+ "%s: error code %d", s->name,
+ d->name, err);
+ break;
+
+ case GV_EVENT_THREAD_EXIT:
+ G_VINUM_DEBUG(2, "event 'thread exit'");
+ g_free(ev);
+ mtx_lock(&sc->queue_mtx);
+ gv_cleanup(sc);
+ mtx_destroy(&sc->queue_mtx);
+ g_free(sc->bqueue);
+ g_free(sc);
+ kproc_exit(ENXIO);
+ break; /* not reached */
+
+ default:
+ G_VINUM_DEBUG(1, "unknown event %d", ev->type);
+ }
+
+ g_free(ev);
+
+ mtx_lock(&sc->queue_mtx);
+ continue;
+ }
+
+ /* ... then do I/O processing. */
+ bp = bioq_takefirst(sc->bqueue);
+ if (bp == NULL) {
+ msleep(sc, &sc->queue_mtx, PRIBIO, "-", hz/10);
+ continue;
+ }
+ mtx_unlock(&sc->queue_mtx);
+
+ /* A bio that is coming up from an underlying device. */
+ if (bp->bio_cflags & GV_BIO_DONE) {
+ gv_bio_done(sc, bp);
+ /* A bio that interfered with another bio. */
+ } else if (bp->bio_cflags & GV_BIO_ONHOLD) {
+ s = bp->bio_caller1;
+ p = s->plex_sc;
+ /* Is it still locked out? */
+ if (gv_stripe_active(p, bp)) {
+ /* Park the bio on the waiting queue. */
+ bioq_disksort(p->wqueue, bp);
+ } else {
+ bp->bio_cflags &= ~GV_BIO_ONHOLD;
+ g_io_request(bp, s->drive_sc->consumer);
+ }
+ /* A special request requireing special handling. */
+ } else if (bp->bio_cflags & GV_BIO_INTERNAL ||
+ bp->bio_pflags & GV_BIO_INTERNAL) {
+ p = bp->bio_caller1;
+ gv_plex_start(p, bp);
+ /* A fresh bio, scheduled it down. */
+ } else {
+ gv_volume_start(sc, bp);
+ }
+
+ mtx_lock(&sc->queue_mtx);
+ }
}
-#endif
#define VINUM_CLASS_NAME "VINUM"
@@ -549,8 +1018,9 @@ static struct g_class g_vinum_class = {
.name = VINUM_CLASS_NAME,
.version = G_VERSION,
.init = gv_init,
- /*.destroy_geom = gv_destroy_geom,*/
+ .taste = gv_taste,
.ctlreq = gv_config,
+ .destroy_geom = gv_unload,
};
DECLARE_GEOM_CLASS(g_vinum_class, g_vinum);
diff --git a/sys/geom/vinum/geom_vinum.h b/sys/geom/vinum/geom_vinum.h
index 07c0410..2db22d3 100644
--- a/sys/geom/vinum/geom_vinum.h
+++ b/sys/geom/vinum/geom_vinum.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,20 +29,25 @@
#ifndef _GEOM_VINUM_H_
#define _GEOM_VINUM_H_
-#define ERRBUFSIZ 1024
+/* geom_vinum_create.c */
+void gv_concat(struct g_geom *gp, struct gctl_req *);
+void gv_mirror(struct g_geom *gp, struct gctl_req *);
+void gv_stripe(struct g_geom *gp, struct gctl_req *);
+void gv_raid5(struct g_geom *gp, struct gctl_req *);
+int gv_create_drive(struct gv_softc *, struct gv_drive *);
+int gv_create_volume(struct gv_softc *, struct gv_volume *);
+int gv_create_plex(struct gv_softc *, struct gv_plex *);
+int gv_create_sd(struct gv_softc *, struct gv_sd *);
/* geom_vinum_drive.c */
-void gv_config_new_drive(struct gv_drive *);
-void gv_drive_modify(struct gv_drive *);
+void gv_save_config(struct gv_softc *);
int gv_read_header(struct g_consumer *, struct gv_hdr *);
-void gv_save_config_all(struct gv_softc *);
-void gv_save_config(struct g_consumer *, struct gv_drive *,
- struct gv_softc *);
int gv_write_header(struct g_consumer *, struct gv_hdr *);
/* geom_vinum_init.c */
-void gv_parityop(struct g_geom *, struct gctl_req *);
void gv_start_obj(struct g_geom *, struct gctl_req *);
+int gv_start_plex(struct gv_plex *);
+int gv_start_vol(struct gv_volume *);
/* geom_vinum_list.c */
void gv_ld(struct g_geom *, struct gctl_req *, struct sbuf *);
@@ -53,48 +58,97 @@ void gv_list(struct g_geom *, struct gctl_req *);
/* geom_vinum_move.c */
void gv_move(struct g_geom *, struct gctl_req *);
+int gv_move_sd(struct gv_softc *, struct gv_sd *, struct gv_drive *, int);
/* geom_vinum_rename.c */
void gv_rename(struct g_geom *, struct gctl_req *);
+int gv_rename_drive(struct gv_softc *, struct gv_drive *, char *, int);
+int gv_rename_plex(struct gv_softc *, struct gv_plex *, char *, int);
+int gv_rename_sd(struct gv_softc *, struct gv_sd *, char *, int);
+int gv_rename_vol(struct gv_softc *, struct gv_volume *, char *, int);
/* geom_vinum_rm.c */
void gv_remove(struct g_geom *, struct gctl_req *);
-int gv_resetconfig(struct g_geom *, struct gctl_req *);
-int gv_rm_sd(struct gv_softc *sc, struct gctl_req *req,
- struct gv_sd *s, int flags);
+int gv_resetconfig(struct gv_softc *);
+void gv_rm_sd(struct gv_softc *sc, struct gv_sd *s);
+void gv_rm_drive(struct gv_softc *, struct gv_drive *, int);
+void gv_rm_plex(struct gv_softc *, struct gv_plex *);
+void gv_rm_vol(struct gv_softc *, struct gv_volume *);
+
/* geom_vinum_state.c */
int gv_sdstatemap(struct gv_plex *);
void gv_setstate(struct g_geom *, struct gctl_req *);
int gv_set_drive_state(struct gv_drive *, int, int);
int gv_set_sd_state(struct gv_sd *, int, int);
+int gv_set_vol_state(struct gv_volume *, int, int);
+int gv_set_plex_state(struct gv_plex *, int, int);
void gv_update_sd_state(struct gv_sd *);
void gv_update_plex_state(struct gv_plex *);
void gv_update_vol_state(struct gv_volume *);
/* geom_vinum_subr.c */
-void gv_adjust_freespace(struct gv_sd *, off_t);
-void gv_free_sd(struct gv_sd *);
-struct g_geom *find_vinum_geom(void);
-struct gv_drive *gv_find_drive(struct gv_softc *, char *);
-struct gv_plex *gv_find_plex(struct gv_softc *, char *);
-struct gv_sd *gv_find_sd(struct gv_softc *, char *);
-struct gv_volume *gv_find_vol(struct gv_softc *, char *);
-void gv_format_config(struct gv_softc *, struct sbuf *, int, char *);
-int gv_is_striped(struct gv_plex *);
-int gv_is_open(struct g_geom *);
-void gv_kill_drive_thread(struct gv_drive *);
-void gv_kill_plex_thread(struct gv_plex *);
-void gv_kill_vol_thread(struct gv_volume *);
-int gv_object_type(struct gv_softc *, char *);
-void gv_parse_config(struct gv_softc *, u_char *, int);
-int gv_sd_to_drive(struct gv_softc *, struct gv_drive *, struct gv_sd *,
- char *, int);
-int gv_sd_to_plex(struct gv_plex *, struct gv_sd *, int);
-void gv_update_plex_config(struct gv_plex *);
-void gv_update_vol_size(struct gv_volume *, off_t);
-off_t gv_vol_size(struct gv_volume *);
-off_t gv_plex_size(struct gv_plex *);
+void gv_adjust_freespace(struct gv_sd *, off_t);
+void gv_free_sd(struct gv_sd *);
+struct gv_drive *gv_find_drive(struct gv_softc *, char *);
+struct gv_drive *gv_find_drive_device(struct gv_softc *, char *);
+struct gv_plex *gv_find_plex(struct gv_softc *, char *);
+struct gv_sd *gv_find_sd(struct gv_softc *, char *);
+struct gv_volume *gv_find_vol(struct gv_softc *, char *);
+void gv_format_config(struct gv_softc *, struct sbuf *, int,
+ char *);
+int gv_is_striped(struct gv_plex *);
+int gv_consumer_is_open(struct g_consumer *);
+int gv_provider_is_open(struct g_provider *);
+int gv_object_type(struct gv_softc *, char *);
+void gv_parse_config(struct gv_softc *, char *,
+ struct gv_drive *);
+int gv_sd_to_drive(struct gv_sd *, struct gv_drive *);
+int gv_sd_to_plex(struct gv_sd *, struct gv_plex *);
+int gv_sdcount(struct gv_plex *, int);
+void gv_update_plex_config(struct gv_plex *);
+void gv_update_vol_size(struct gv_volume *, off_t);
+off_t gv_vol_size(struct gv_volume *);
+off_t gv_plex_size(struct gv_plex *);
+int gv_plexdown(struct gv_volume *);
+int gv_attach_plex(struct gv_plex *, struct gv_volume *,
+ int);
+int gv_attach_sd(struct gv_sd *, struct gv_plex *, off_t,
+ int);
+int gv_detach_plex(struct gv_plex *, int);
+int gv_detach_sd(struct gv_sd *, int);
+
+/* geom_vinum.c */
+void gv_worker(void *);
+void gv_post_event(struct gv_softc *, int, void *, void *, intmax_t,
+ intmax_t);
+void gv_drive_tasted(struct gv_softc *, struct g_provider *);
+void gv_drive_lost(struct gv_softc *, struct gv_drive *);
+void gv_setup_objects(struct gv_softc *);
+void gv_start(struct bio *);
+int gv_access(struct g_provider *, int, int, int);
+void gv_cleanup(struct gv_softc *);
+
+/* geom_vinum_volume.c */
+void gv_done(struct bio *);
+void gv_volume_start(struct gv_softc *, struct bio *);
+void gv_volume_flush(struct gv_volume *);
+void gv_bio_done(struct gv_softc *, struct bio *);
+
+/* geom_vinum_plex.c */
+void gv_plex_start(struct gv_plex *, struct bio *);
+void gv_plex_raid5_done(struct gv_plex *, struct bio *);
+void gv_plex_normal_done(struct gv_plex *, struct bio *);
+int gv_grow_request(struct gv_plex *, off_t, off_t, int, caddr_t);
+void gv_grow_complete(struct gv_plex *, struct bio *);
+void gv_init_request(struct gv_sd *, off_t, caddr_t, off_t);
+void gv_init_complete(struct gv_plex *, struct bio *);
+void gv_parity_request(struct gv_plex *, int, off_t);
+void gv_parity_complete(struct gv_plex *, struct bio *);
+void gv_rebuild_complete(struct gv_plex *, struct bio *);
+int gv_sync_request(struct gv_plex *, struct gv_plex *, off_t, off_t, int,
+ caddr_t);
+int gv_sync_complete(struct gv_plex *, struct bio *);
extern u_int g_vinum_debug;
diff --git a/sys/geom/vinum/geom_vinum_create.c b/sys/geom/vinum/geom_vinum_create.c
new file mode 100644
index 0000000..3f8212c
--- /dev/null
+++ b/sys/geom/vinum/geom_vinum_create.c
@@ -0,0 +1,614 @@
+/*-
+ * Copyright (c) 2007 Lukas Ertl
+ * Copyright (c) 2007, 2009 Ulf Lilleengen
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bio.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/systm.h>
+#include <sys/vimage.h>
+
+#include <geom/geom.h>
+#include <geom/vinum/geom_vinum_var.h>
+#include <geom/vinum/geom_vinum.h>
+
+#define DEFAULT_STRIPESIZE 262144
+
+/*
+ * Create a new drive object, either by user request, during taste of the drive
+ * itself, or because it was referenced by a subdisk during taste.
+ */
+int
+gv_create_drive(struct gv_softc *sc, struct gv_drive *d)
+{
+ struct g_geom *gp;
+ struct g_provider *pp;
+ struct g_consumer *cp, *cp2;
+ struct gv_drive *d2;
+ struct gv_hdr *hdr;
+ struct gv_freelist *fl;
+
+ KASSERT(d != NULL, ("gv_create_drive: NULL d"));
+
+ gp = sc->geom;
+
+ pp = NULL;
+ cp = cp2 = NULL;
+
+ /* The drive already has a consumer if it was tasted before. */
+ if (d->consumer != NULL) {
+ cp = d->consumer;
+ cp->private = d;
+ pp = cp->provider;
+ } else if (!(d->flags & GV_DRIVE_REFERENCED)) {
+ if (gv_find_drive(sc, d->name) != NULL) {
+ G_VINUM_DEBUG(0, "drive '%s' already exists", d->name);
+ g_free(d);
+ return (GV_ERR_CREATE);
+ }
+
+ if (gv_find_drive_device(sc, d->device) != NULL) {
+ G_VINUM_DEBUG(0, "provider '%s' already in use by "
+ "gvinum", d->device);
+ return (GV_ERR_CREATE);
+ }
+
+ pp = g_provider_by_name(d->device);
+ if (pp == NULL) {
+ G_VINUM_DEBUG(0, "create '%s': device '%s' disappeared",
+ d->name, d->device);
+ g_free(d);
+ return (GV_ERR_CREATE);
+ }
+
+ g_topology_lock();
+ cp = g_new_consumer(gp);
+ if (g_attach(cp, pp) != 0) {
+ g_destroy_consumer(cp);
+ g_topology_unlock();
+ G_VINUM_DEBUG(0, "create drive '%s': couldn't attach",
+ d->name);
+ g_free(d);
+ return (GV_ERR_CREATE);
+ }
+ g_topology_unlock();
+
+ d->consumer = cp;
+ cp->private = d;
+ }
+
+ /*
+ * If this was just a "referenced" drive, we're almost finished, but
+ * insert this drive not on the head of the drives list, as
+ * gv_drive_is_newer() expects a "real" drive from LIST_FIRST().
+ */
+ if (d->flags & GV_DRIVE_REFERENCED) {
+ snprintf(d->device, sizeof(d->device), "???");
+ d2 = LIST_FIRST(&sc->drives);
+ if (d2 == NULL)
+ LIST_INSERT_HEAD(&sc->drives, d, drive);
+ else
+ LIST_INSERT_AFTER(d2, d, drive);
+ return (0);
+ }
+
+ /*
+ * Update access counts of the new drive to those of an already
+ * existing drive.
+ */
+ LIST_FOREACH(d2, &sc->drives, drive) {
+ if ((d == d2) || (d2->consumer == NULL))
+ continue;
+
+ cp2 = d2->consumer;
+ g_topology_lock();
+ if ((cp2->acr || cp2->acw || cp2->ace) &&
+ (g_access(cp, cp2->acr, cp2->acw, cp2->ace) != 0)) {
+ g_detach(cp);
+ g_destroy_consumer(cp);
+ g_topology_unlock();
+ G_VINUM_DEBUG(0, "create drive '%s': couldn't update "
+ "access counts", d->name);
+ if (d->hdr != NULL)
+ g_free(d->hdr);
+ g_free(d);
+ return (GV_ERR_CREATE);
+ }
+ g_topology_unlock();
+ break;
+ }
+
+ d->size = pp->mediasize - GV_DATA_START;
+ d->avail = d->size;
+ d->vinumconf = sc;
+ LIST_INIT(&d->subdisks);
+ LIST_INIT(&d->freelist);
+
+ /* The header might have been set during taste. */
+ if (d->hdr == NULL) {
+ hdr = g_malloc(sizeof(*hdr), M_WAITOK | M_ZERO);
+ hdr->magic = GV_MAGIC;
+ hdr->config_length = GV_CFG_LEN;
+ mtx_lock(&hostname_mtx);
+ bcopy(G_hostname, hdr->label.sysname, GV_HOSTNAME_LEN);
+ mtx_unlock(&hostname_mtx);
+ strlcpy(hdr->label.name, d->name, sizeof(hdr->label.name));
+ microtime(&hdr->label.date_of_birth);
+ d->hdr = hdr;
+ }
+
+ /* We also need a freelist entry. */
+ fl = g_malloc(sizeof(struct gv_freelist), M_WAITOK | M_ZERO);
+ fl->offset = GV_DATA_START;
+ fl->size = d->avail;
+ LIST_INSERT_HEAD(&d->freelist, fl, freelist);
+ d->freelist_entries = 1;
+
+ if (gv_find_drive(sc, d->name) == NULL)
+ LIST_INSERT_HEAD(&sc->drives, d, drive);
+
+ gv_set_drive_state(d, GV_DRIVE_UP, 0);
+ return (0);
+}
+
+int
+gv_create_volume(struct gv_softc *sc, struct gv_volume *v)
+{
+ KASSERT(v != NULL, ("gv_create_volume: NULL v"));
+
+ v->vinumconf = sc;
+ v->flags |= GV_VOL_NEWBORN;
+ LIST_INIT(&v->plexes);
+ LIST_INSERT_HEAD(&sc->volumes, v, volume);
+ v->wqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
+ bioq_init(v->wqueue);
+ return (0);
+}
+
+int
+gv_create_plex(struct gv_softc *sc, struct gv_plex *p)
+{
+ struct gv_volume *v;
+
+ KASSERT(p != NULL, ("gv_create_plex: NULL p"));
+
+ /* Find the volume this plex should be attached to. */
+ v = gv_find_vol(sc, p->volume);
+ if (v == NULL) {
+ G_VINUM_DEBUG(0, "create plex '%s': volume '%s' not found",
+ p->name, p->volume);
+ g_free(p);
+ return (GV_ERR_CREATE);
+ }
+ if (!(v->flags & GV_VOL_NEWBORN))
+ p->flags |= GV_PLEX_ADDED;
+ p->vol_sc = v;
+ v->plexcount++;
+ p->vinumconf = sc;
+ p->synced = 0;
+ p->flags |= GV_PLEX_NEWBORN;
+ LIST_INSERT_HEAD(&v->plexes, p, in_volume);
+ LIST_INIT(&p->subdisks);
+ TAILQ_INIT(&p->packets);
+ LIST_INSERT_HEAD(&sc->plexes, p, plex);
+ p->bqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
+ bioq_init(p->bqueue);
+ p->wqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
+ bioq_init(p->wqueue);
+ p->rqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
+ bioq_init(p->rqueue);
+ return (0);
+}
+
+int
+gv_create_sd(struct gv_softc *sc, struct gv_sd *s)
+{
+ struct gv_plex *p;
+ struct gv_drive *d;
+
+ KASSERT(s != NULL, ("gv_create_sd: NULL s"));
+
+ /* Find the drive where this subdisk should be put on. */
+ d = gv_find_drive(sc, s->drive);
+ if (d == NULL) {
+ /*
+ * It's possible that the subdisk references a drive that
+ * doesn't exist yet (during the taste process), so create a
+ * practically empty "referenced" drive.
+ */
+ if (s->flags & GV_SD_TASTED) {
+ d = g_malloc(sizeof(struct gv_drive),
+ M_WAITOK | M_ZERO);
+ d->flags |= GV_DRIVE_REFERENCED;
+ strlcpy(d->name, s->drive, sizeof(d->name));
+ gv_create_drive(sc, d);
+ } else {
+ G_VINUM_DEBUG(0, "create sd '%s': drive '%s' not found",
+ s->name, s->drive);
+ g_free(s);
+ return (GV_ERR_CREATE);
+ }
+ }
+
+ /* Find the plex where this subdisk belongs to. */
+ p = gv_find_plex(sc, s->plex);
+ if (p == NULL) {
+ G_VINUM_DEBUG(0, "create sd '%s': plex '%s' not found",
+ s->name, s->plex);
+ g_free(s);
+ return (GV_ERR_CREATE);
+ }
+
+ /*
+ * First we give the subdisk to the drive, to handle autosized
+ * values ...
+ */
+ if (gv_sd_to_drive(s, d) != 0) {
+ g_free(s);
+ return (GV_ERR_CREATE);
+ }
+
+ /*
+ * Then, we give the subdisk to the plex; we check if the
+ * given values are correct and maybe adjust them.
+ */
+ if (gv_sd_to_plex(s, p) != 0) {
+ G_VINUM_DEBUG(0, "unable to give sd '%s' to plex '%s'",
+ s->name, p->name);
+ if (s->drive_sc && !(s->drive_sc->flags & GV_DRIVE_REFERENCED))
+ LIST_REMOVE(s, from_drive);
+ gv_free_sd(s);
+ g_free(s);
+ /*
+ * If this subdisk can't be created, we won't create
+ * the attached plex either, if it is also a new one.
+ */
+ if (!(p->flags & GV_PLEX_NEWBORN))
+ return (GV_ERR_CREATE);
+ gv_rm_plex(sc, p);
+ return (GV_ERR_CREATE);
+ }
+ s->flags |= GV_SD_NEWBORN;
+
+ s->vinumconf = sc;
+ LIST_INSERT_HEAD(&sc->subdisks, s, sd);
+
+ return (0);
+}
+
+/*
+ * Create a concatenated volume from specified drives or drivegroups.
+ */
+void
+gv_concat(struct g_geom *gp, struct gctl_req *req)
+{
+ struct gv_drive *d;
+ struct gv_sd *s;
+ struct gv_volume *v;
+ struct gv_plex *p;
+ struct gv_softc *sc;
+ char *drive, buf[30], *vol;
+ int *drives, *flags, dcount;
+
+ sc = gp->softc;
+ dcount = 0;
+ vol = gctl_get_param(req, "name", NULL);
+ if (vol == NULL) {
+ gctl_error(req, "volume names not given");
+ return;
+ }
+
+ flags = gctl_get_paraml(req, "flags", sizeof(*flags));
+ drives = gctl_get_paraml(req, "drives", sizeof(*drives));
+
+ if (drives == NULL) {
+ gctl_error(req, "drive names not given");
+ return;
+ }
+
+ /* First we create the volume. */
+ v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
+ strlcpy(v->name, vol, sizeof(v->name));
+ v->state = GV_VOL_UP;
+ gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
+
+ /* Then we create the plex. */
+ p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
+ snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
+ strlcpy(p->volume, v->name, sizeof(p->volume));
+ p->org = GV_PLEX_CONCAT;
+ p->stripesize = 0;
+ gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
+
+ /* Drives are first (right now) priority */
+ for (dcount = 0; dcount < *drives; dcount++) {
+ snprintf(buf, sizeof(buf), "drive%d", dcount);
+ drive = gctl_get_param(req, buf, NULL);
+ d = gv_find_drive(sc, drive);
+ if (d == NULL) {
+ gctl_error(req, "No such drive '%s'", drive);
+ continue;
+ }
+ s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
+ snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
+ strlcpy(s->plex, p->name, sizeof(s->plex));
+ strlcpy(s->drive, drive, sizeof(s->drive));
+ s->plex_offset = -1;
+ s->drive_offset = -1;
+ s->size = -1;
+ gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
+ }
+ gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
+}
+
+/*
+ * Create a mirrored volume from specified drives or drivegroups.
+ */
+void
+gv_mirror(struct g_geom *gp, struct gctl_req *req)
+{
+ struct gv_drive *d;
+ struct gv_sd *s;
+ struct gv_volume *v;
+ struct gv_plex *p;
+ struct gv_softc *sc;
+ char *drive, buf[30], *vol;
+ int *drives, *flags, dcount, pcount, scount;
+
+ sc = gp->softc;
+ dcount = 0;
+ scount = 0;
+ pcount = 0;
+ vol = gctl_get_param(req, "name", NULL);
+ if (vol == NULL) {
+ gctl_error(req, "volume's not given");
+ return;
+ }
+
+ flags = gctl_get_paraml(req, "flags", sizeof(*flags));
+ drives = gctl_get_paraml(req, "drives", sizeof(*drives));
+
+ if (drives == NULL) {
+ gctl_error(req, "drives not given");
+ return;
+ }
+
+ /* We must have an even number of drives. */
+ if (*drives % 2 != 0) {
+ gctl_error(req, "mirror organization must have an even number "
+ "of drives");
+ return;
+ }
+ if (*flags & GV_FLAG_S && *drives < 4) {
+ gctl_error(req, "must have at least 4 drives for striped plex");
+ return;
+ }
+
+ /* First we create the volume. */
+ v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
+ strlcpy(v->name, vol, sizeof(v->name));
+ v->state = GV_VOL_UP;
+ gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
+
+ /* Then we create the plexes. */
+ for (pcount = 0; pcount < 2; pcount++) {
+ p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
+ snprintf(p->name, sizeof(p->name), "%s.p%d", v->name,
+ pcount);
+ strlcpy(p->volume, v->name, sizeof(p->volume));
+ if (*flags & GV_FLAG_S) {
+ p->org = GV_PLEX_STRIPED;
+ p->stripesize = DEFAULT_STRIPESIZE;
+ } else {
+ p->org = GV_PLEX_CONCAT;
+ p->stripesize = -1;
+ }
+ gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
+
+ /*
+ * We just gives each even drive to plex one, and each odd to
+ * plex two.
+ */
+ scount = 0;
+ for (dcount = pcount; dcount < *drives; dcount += 2) {
+ snprintf(buf, sizeof(buf), "drive%d", dcount);
+ drive = gctl_get_param(req, buf, NULL);
+ d = gv_find_drive(sc, drive);
+ if (d == NULL) {
+ gctl_error(req, "No such drive '%s', aborting",
+ drive);
+ scount++;
+ break;
+ }
+ s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
+ snprintf(s->name, sizeof(s->name), "%s.s%d", p->name,
+ scount);
+ strlcpy(s->plex, p->name, sizeof(s->plex));
+ strlcpy(s->drive, drive, sizeof(s->drive));
+ s->plex_offset = -1;
+ s->drive_offset = -1;
+ s->size = -1;
+ gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
+ scount++;
+ }
+ }
+ gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
+}
+
+void
+gv_raid5(struct g_geom *gp, struct gctl_req *req)
+{
+ struct gv_softc *sc;
+ struct gv_drive *d;
+ struct gv_volume *v;
+ struct gv_plex *p;
+ struct gv_sd *s;
+ int *drives, *flags, dcount;
+ char *vol, *drive, buf[30];
+ off_t *stripesize;
+
+ dcount = 0;
+ sc = gp->softc;
+
+ vol = gctl_get_param(req, "name", NULL);
+ if (vol == NULL) {
+ gctl_error(req, "volume's not given");
+ return;
+ }
+ flags = gctl_get_paraml(req, "flags", sizeof(*flags));
+ drives = gctl_get_paraml(req, "drives", sizeof(*drives));
+ stripesize = gctl_get_paraml(req, "stripesize", sizeof(*stripesize));
+
+ if (stripesize == NULL) {
+ gctl_error(req, "no stripesize given");
+ return;
+ }
+
+ if (drives == NULL) {
+ gctl_error(req, "drives not given");
+ return;
+ }
+
+ /* We must have at least three drives. */
+ if (*drives < 3) {
+ gctl_error(req, "must have at least three drives for this "
+ "plex organisation");
+ return;
+ }
+ /* First we create the volume. */
+ v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
+ strlcpy(v->name, vol, sizeof(v->name));
+ v->state = GV_VOL_UP;
+ gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
+
+ /* Then we create the plex. */
+ p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
+ snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
+ strlcpy(p->volume, v->name, sizeof(p->volume));
+ p->org = GV_PLEX_RAID5;
+ p->stripesize = *stripesize;
+ gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
+
+ /* Create subdisks on drives. */
+ for (dcount = 0; dcount < *drives; dcount++) {
+ snprintf(buf, sizeof(buf), "drive%d", dcount);
+ drive = gctl_get_param(req, buf, NULL);
+ d = gv_find_drive(sc, drive);
+ if (d == NULL) {
+ gctl_error(req, "No such drive '%s'", drive);
+ continue;
+ }
+ s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
+ snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
+ strlcpy(s->plex, p->name, sizeof(s->plex));
+ strlcpy(s->drive, drive, sizeof(s->drive));
+ s->plex_offset = -1;
+ s->drive_offset = -1;
+ s->size = -1;
+ gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
+ }
+ gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
+}
+
+/*
+ * Create a striped volume from specified drives or drivegroups.
+ */
+void
+gv_stripe(struct g_geom *gp, struct gctl_req *req)
+{
+ struct gv_drive *d;
+ struct gv_sd *s;
+ struct gv_volume *v;
+ struct gv_plex *p;
+ struct gv_softc *sc;
+ char *drive, buf[30], *vol;
+ int *drives, *flags, dcount, pcount;
+
+ sc = gp->softc;
+ dcount = 0;
+ pcount = 0;
+ vol = gctl_get_param(req, "name", NULL);
+ if (vol == NULL) {
+ gctl_error(req, "volume's not given");
+ return;
+ }
+ flags = gctl_get_paraml(req, "flags", sizeof(*flags));
+ drives = gctl_get_paraml(req, "drives", sizeof(*drives));
+
+ if (drives == NULL) {
+ gctl_error(req, "drives not given");
+ return;
+ }
+
+ /* We must have at least two drives. */
+ if (*drives < 2) {
+ gctl_error(req, "must have at least 2 drives");
+ return;
+ }
+
+ /* First we create the volume. */
+ v = g_malloc(sizeof(*v), M_WAITOK | M_ZERO);
+ strlcpy(v->name, vol, sizeof(v->name));
+ v->state = GV_VOL_UP;
+ gv_post_event(sc, GV_EVENT_CREATE_VOLUME, v, NULL, 0, 0);
+
+ /* Then we create the plex. */
+ p = g_malloc(sizeof(*p), M_WAITOK | M_ZERO);
+ snprintf(p->name, sizeof(p->name), "%s.p%d", v->name, v->plexcount);
+ strlcpy(p->volume, v->name, sizeof(p->volume));
+ p->org = GV_PLEX_STRIPED;
+ p->stripesize = 262144;
+ gv_post_event(sc, GV_EVENT_CREATE_PLEX, p, NULL, 0, 0);
+
+ /* Create subdisks on drives. */
+ for (dcount = 0; dcount < *drives; dcount++) {
+ snprintf(buf, sizeof(buf), "drive%d", dcount);
+ drive = gctl_get_param(req, buf, NULL);
+ d = gv_find_drive(sc, drive);
+ if (d == NULL) {
+ gctl_error(req, "No such drive '%s'", drive);
+ continue;
+ }
+ s = g_malloc(sizeof(*s), M_WAITOK | M_ZERO);
+ snprintf(s->name, sizeof(s->name), "%s.s%d", p->name, dcount);
+ strlcpy(s->plex, p->name, sizeof(s->plex));
+ strlcpy(s->drive, drive, sizeof(s->drive));
+ s->plex_offset = -1;
+ s->drive_offset = -1;
+ s->size = -1;
+ gv_post_event(sc, GV_EVENT_CREATE_SD, s, NULL, 0, 0);
+ }
+ gv_post_event(sc, GV_EVENT_SETUP_OBJECTS, sc, NULL, 0, 0);
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
+}
diff --git a/sys/geom/vinum/geom_vinum_drive.c b/sys/geom/vinum/geom_vinum_drive.c
index 6f2f0fc..1e9dd0b 100644
--- a/sys/geom/vinum/geom_vinum_drive.c
+++ b/sys/geom/vinum/geom_vinum_drive.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004, 2005 Lukas Ertl
+ * Copyright (c) 2004, 2005, 2007 Lukas Ertl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,35 +27,20 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/param.h>
-#include <sys/bio.h>
-#include <sys/errno.h>
#include <sys/endian.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/kthread.h>
-#include <sys/libkern.h>
-#include <sys/lock.h>
#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/sbuf.h>
#include <sys/systm.h>
-#include <sys/time.h>
#include <sys/vimage.h>
#include <geom/geom.h>
#include <geom/vinum/geom_vinum_var.h>
#include <geom/vinum/geom_vinum.h>
-#include <geom/vinum/geom_vinum_share.h>
#define GV_LEGACY_I386 0
#define GV_LEGACY_AMD64 1
#define GV_LEGACY_SPARC64 2
#define GV_LEGACY_POWERPC 3
-static void gv_drive_dead(void *, int);
-static void gv_drive_worker(void *);
static int gv_legacy_header_type(uint8_t *, int);
/*
@@ -267,620 +252,96 @@ gv_write_header(struct g_consumer *cp, struct gv_hdr *m_hdr)
return (ret);
}
+/* Save the vinum configuration back to each involved disk. */
void
-gv_config_new_drive(struct gv_drive *d)
-{
- struct gv_hdr *vhdr;
- struct gv_freelist *fl;
-
- KASSERT(d != NULL, ("config_new_drive: NULL d"));
-
- vhdr = g_malloc(sizeof(*vhdr), M_WAITOK | M_ZERO);
- vhdr->magic = GV_MAGIC;
- vhdr->config_length = GV_CFG_LEN;
-
- mtx_lock(&hostname_mtx);
- bcopy(G_hostname, vhdr->label.sysname, GV_HOSTNAME_LEN);
- mtx_unlock(&hostname_mtx);
- strncpy(vhdr->label.name, d->name, GV_MAXDRIVENAME);
- microtime(&vhdr->label.date_of_birth);
-
- d->hdr = vhdr;
-
- LIST_INIT(&d->subdisks);
- LIST_INIT(&d->freelist);
-
- fl = g_malloc(sizeof(struct gv_freelist), M_WAITOK | M_ZERO);
- fl->offset = GV_DATA_START;
- fl->size = d->avail;
- LIST_INSERT_HEAD(&d->freelist, fl, freelist);
- d->freelist_entries = 1;
-
- d->bqueue = g_malloc(sizeof(struct bio_queue_head), M_WAITOK | M_ZERO);
- bioq_init(d->bqueue);
- mtx_init(&d->bqueue_mtx, "gv_drive", NULL, MTX_DEF);
- kproc_create(gv_drive_worker, d, NULL, 0, 0, "gv_d %s", d->name);
- d->flags |= GV_DRIVE_THREAD_ACTIVE;
-}
-
-void
-gv_save_config_all(struct gv_softc *sc)
+gv_save_config(struct gv_softc *sc)
{
+ struct g_consumer *cp;
struct gv_drive *d;
-
- g_topology_assert();
-
- LIST_FOREACH(d, &sc->drives, drive) {
- if (d->geom == NULL)
- continue;
- gv_save_config(NULL, d, sc);
- }
-}
-
-/* Save the vinum configuration back to disk. */
-void
-gv_save_config(struct g_consumer *cp, struct gv_drive *d, struct gv_softc *sc)
-{
- struct g_geom *gp;
- struct g_consumer *cp2;
struct gv_hdr *vhdr, *hdr;
struct sbuf *sb;
+ struct timeval last_update;
int error;
- g_topology_assert();
-
- KASSERT(d != NULL, ("gv_save_config: null d"));
KASSERT(sc != NULL, ("gv_save_config: null sc"));
- /*
- * We can't save the config on a drive that isn't up, but drives that
- * were just created aren't officially up yet, so we check a special
- * flag.
- */
- if ((d->state != GV_DRIVE_UP) && !(d->flags && GV_DRIVE_NEWBORN))
- return;
-
- if (cp == NULL) {
- gp = d->geom;
- KASSERT(gp != NULL, ("gv_save_config: null gp"));
- cp2 = LIST_FIRST(&gp->consumer);
- KASSERT(cp2 != NULL, ("gv_save_config: null cp2"));
- } else
- cp2 = cp;
-
vhdr = g_malloc(GV_HDR_LEN, M_WAITOK | M_ZERO);
vhdr->magic = GV_MAGIC;
vhdr->config_length = GV_CFG_LEN;
-
- hdr = d->hdr;
- if (hdr == NULL) {
- G_VINUM_DEBUG(0, "drive %s has NULL hdr", d->name);
- g_free(vhdr);
- return;
- }
- microtime(&hdr->label.last_update);
- bcopy(&hdr->label, &vhdr->label, sizeof(struct gv_label));
+ microtime(&last_update);
sb = sbuf_new(NULL, NULL, GV_CFG_LEN, SBUF_FIXEDLEN);
gv_format_config(sc, sb, 1, NULL);
sbuf_finish(sb);
- error = g_access(cp2, 0, 1, 0);
- if (error) {
- G_VINUM_DEBUG(0, "g_access failed on drive %s, errno %d",
- d->name, error);
- sbuf_delete(sb);
- g_free(vhdr);
- return;
- }
- g_topology_unlock();
-
- do {
- error = gv_write_header(cp2, vhdr);
- if (error) {
- G_VINUM_DEBUG(0, "writing vhdr failed on drive %s, "
- "errno %d", d->name, error);
- break;
- }
-
- error = g_write_data(cp2, GV_CFG_OFFSET, sbuf_data(sb),
- GV_CFG_LEN);
- if (error) {
- G_VINUM_DEBUG(0, "writing first config copy failed "
- "on drive %s, errno %d", d->name, error);
- break;
- }
-
- error = g_write_data(cp2, GV_CFG_OFFSET + GV_CFG_LEN,
- sbuf_data(sb), GV_CFG_LEN);
- if (error)
- G_VINUM_DEBUG(0, "writing second config copy failed "
- "on drive %s, errno %d", d->name, error);
- } while (0);
-
- g_topology_lock();
- g_access(cp2, 0, -1, 0);
- sbuf_delete(sb);
- g_free(vhdr);
-
- if (d->geom != NULL)
- gv_drive_modify(d);
-}
-
-/* This resembles g_slice_access(). */
-static int
-gv_drive_access(struct g_provider *pp, int dr, int dw, int de)
-{
- struct g_geom *gp;
- struct g_consumer *cp;
- struct g_provider *pp2;
- struct gv_drive *d;
- struct gv_sd *s, *s2;
- int error;
-
- gp = pp->geom;
- cp = LIST_FIRST(&gp->consumer);
- if (cp == NULL)
- return (0);
-
- d = gp->softc;
- if (d == NULL)
- return (0);
-
- s = pp->private;
- KASSERT(s != NULL, ("gv_drive_access: NULL s"));
-
- LIST_FOREACH(s2, &d->subdisks, from_drive) {
- if (s == s2)
- continue;
- if (s->drive_offset + s->size <= s2->drive_offset)
- continue;
- if (s2->drive_offset + s2->size <= s->drive_offset)
+ LIST_FOREACH(d, &sc->drives, drive) {
+ /*
+ * We can't save the config on a drive that isn't up, but
+ * drives that were just created aren't officially up yet, so
+ * we check a special flag.
+ */
+ if (d->state != GV_DRIVE_UP)
continue;
- /* Overlap. */
- pp2 = s2->provider;
- KASSERT(s2 != NULL, ("gv_drive_access: NULL s2"));
- if ((pp->acw + dw) > 0 && pp2->ace > 0)
- return (EPERM);
- if ((pp->ace + de) > 0 && pp2->acw > 0)
- return (EPERM);
- }
-
- error = g_access(cp, dr, dw, de);
- return (error);
-}
-
-static void
-gv_drive_done(struct bio *bp)
-{
- struct gv_drive *d;
-
- /* Put the BIO on the worker queue again. */
- d = bp->bio_from->geom->softc;
- bp->bio_cflags |= GV_BIO_DONE;
- mtx_lock(&d->bqueue_mtx);
- bioq_insert_tail(d->bqueue, bp);
- wakeup(d);
- mtx_unlock(&d->bqueue_mtx);
-}
-
-
-static void
-gv_drive_start(struct bio *bp)
-{
- struct gv_drive *d;
- struct gv_sd *s;
-
- switch (bp->bio_cmd) {
- case BIO_READ:
- case BIO_WRITE:
- case BIO_DELETE:
- break;
- case BIO_GETATTR:
- default:
- g_io_deliver(bp, EOPNOTSUPP);
- return;
- }
-
- s = bp->bio_to->private;
- if ((s->state == GV_SD_DOWN) || (s->state == GV_SD_STALE)) {
- g_io_deliver(bp, ENXIO);
- return;
- }
-
- d = bp->bio_to->geom->softc;
-
- /*
- * Put the BIO on the worker queue, where the worker thread will pick
- * it up.
- */
- mtx_lock(&d->bqueue_mtx);
- bioq_disksort(d->bqueue, bp);
- wakeup(d);
- mtx_unlock(&d->bqueue_mtx);
-
-}
-
-static void
-gv_drive_worker(void *arg)
-{
- struct bio *bp, *cbp;
- struct g_geom *gp;
- struct g_provider *pp;
- struct gv_drive *d;
- struct gv_sd *s;
- int error;
-
- d = arg;
-
- mtx_lock(&d->bqueue_mtx);
- for (;;) {
- /* We were signaled to exit. */
- if (d->flags & GV_DRIVE_THREAD_DIE)
- break;
-
- /* Take the first BIO from out queue. */
- bp = bioq_takefirst(d->bqueue);
- if (bp == NULL) {
- msleep(d, &d->bqueue_mtx, PRIBIO, "-", hz/10);
+ cp = d->consumer;
+ if (cp == NULL) {
+ G_VINUM_DEBUG(0, "drive '%s' has no consumer!",
+ d->name);
continue;
- }
- mtx_unlock(&d->bqueue_mtx);
-
- pp = bp->bio_to;
- gp = pp->geom;
-
- /* Completed request. */
- if (bp->bio_cflags & GV_BIO_DONE) {
- error = bp->bio_error;
-
- /* Deliver the original request. */
- g_std_done(bp);
-
- /* The request had an error, we need to clean up. */
- if (error != 0) {
- g_topology_lock();
- gv_set_drive_state(d, GV_DRIVE_DOWN,
- GV_SETSTATE_FORCE | GV_SETSTATE_CONFIG);
- g_topology_unlock();
- g_post_event(gv_drive_dead, d, M_WAITOK, d,
- NULL);
- }
-
- /* New request, needs to be sent downwards. */
- } else {
- s = pp->private;
-
- if ((s->state == GV_SD_DOWN) ||
- (s->state == GV_SD_STALE)) {
- g_io_deliver(bp, ENXIO);
- mtx_lock(&d->bqueue_mtx);
- continue;
- }
- if (bp->bio_offset > s->size) {
- g_io_deliver(bp, EINVAL);
- mtx_lock(&d->bqueue_mtx);
- continue;
- }
-
- cbp = g_clone_bio(bp);
- if (cbp == NULL) {
- g_io_deliver(bp, ENOMEM);
- mtx_lock(&d->bqueue_mtx);
- continue;
- }
- if (cbp->bio_offset + cbp->bio_length > s->size)
- cbp->bio_length = s->size -
- cbp->bio_offset;
- cbp->bio_done = gv_drive_done;
- cbp->bio_offset += s->drive_offset;
- g_io_request(cbp, LIST_FIRST(&gp->consumer));
- }
-
- mtx_lock(&d->bqueue_mtx);
- }
-
- while ((bp = bioq_takefirst(d->bqueue)) != NULL) {
- mtx_unlock(&d->bqueue_mtx);
- if (bp->bio_cflags & GV_BIO_DONE)
- g_std_done(bp);
- else
- g_io_deliver(bp, ENXIO);
- mtx_lock(&d->bqueue_mtx);
- }
- mtx_unlock(&d->bqueue_mtx);
- d->flags |= GV_DRIVE_THREAD_DEAD;
-
- kproc_exit(ENXIO);
-}
-
-
-static void
-gv_drive_orphan(struct g_consumer *cp)
-{
- struct g_geom *gp;
- struct gv_drive *d;
-
- g_topology_assert();
- gp = cp->geom;
- g_trace(G_T_TOPOLOGY, "gv_drive_orphan(%s)", gp->name);
- d = gp->softc;
- if (d != NULL) {
- gv_set_drive_state(d, GV_DRIVE_DOWN,
- GV_SETSTATE_FORCE | GV_SETSTATE_CONFIG);
- g_post_event(gv_drive_dead, d, M_WAITOK, d, NULL);
- } else
- g_wither_geom(gp, ENXIO);
-}
-
-static struct g_geom *
-gv_drive_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
-{
- struct g_geom *gp, *gp2;
- struct g_consumer *cp;
- struct gv_drive *d;
- struct gv_sd *s;
- struct gv_softc *sc;
- struct gv_freelist *fl;
- struct gv_hdr *vhdr;
- int error;
- char *buf, errstr[ERRBUFSIZ];
-
- vhdr = NULL;
- d = NULL;
-
- g_trace(G_T_TOPOLOGY, "gv_drive_taste(%s, %s)", mp->name, pp->name);
- g_topology_assert();
-
- /* Find the VINUM class and its associated geom. */
- gp2 = find_vinum_geom();
- if (gp2 == NULL)
- return (NULL);
- sc = gp2->softc;
-
- gp = g_new_geomf(mp, "%s.vinumdrive", pp->name);
- gp->start = gv_drive_start;
- gp->orphan = gv_drive_orphan;
- gp->access = gv_drive_access;
- gp->start = gv_drive_start;
-
- cp = g_new_consumer(gp);
- g_attach(cp, pp);
- error = g_access(cp, 1, 0, 0);
- if (error) {
- g_detach(cp);
- g_destroy_consumer(cp);
- g_destroy_geom(gp);
- return (NULL);
- }
-
- g_topology_unlock();
-
- /* Now check if the provided slice is a valid vinum drive. */
- do {
- vhdr = g_malloc(GV_HDR_LEN, M_WAITOK | M_ZERO);
- error = gv_read_header(cp, vhdr);
- if (error) {
- g_free(vhdr);
- break;
}
- /* A valid vinum drive, let's parse the on-disk information. */
- buf = g_read_data(cp, GV_CFG_OFFSET, GV_CFG_LEN, NULL);
- if (buf == NULL) {
+ hdr = d->hdr;
+ if (hdr == NULL) {
+ G_VINUM_DEBUG(0, "drive '%s' has no header",
+ d->name);
g_free(vhdr);
- break;
+ continue;
}
+ bcopy(&last_update, &hdr->label.last_update,
+ sizeof(struct timeval));
+ bcopy(&hdr->label, &vhdr->label, sizeof(struct gv_label));
g_topology_lock();
- gv_parse_config(sc, buf, 1);
- g_free(buf);
-
- /*
- * Let's see if this drive is already known in the
- * configuration.
- */
- d = gv_find_drive(sc, vhdr->label.name);
-
- /* We already know about this drive. */
- if (d != NULL) {
- /* Check if this drive already has a geom. */
- if (d->geom != NULL) {
- g_topology_unlock();
- g_free(vhdr);
- break;
- }
- bcopy(vhdr, d->hdr, sizeof(*vhdr));
- g_free(vhdr);
-
- /* This is a new drive. */
- } else {
- d = g_malloc(sizeof(*d), M_WAITOK | M_ZERO);
-
- /* Initialize all needed variables. */
- d->size = pp->mediasize - GV_DATA_START;
- d->avail = d->size;
- d->hdr = vhdr;
- strncpy(d->name, vhdr->label.name, GV_MAXDRIVENAME);
- LIST_INIT(&d->subdisks);
- LIST_INIT(&d->freelist);
-
- /* We also need a freelist entry. */
- fl = g_malloc(sizeof(*fl), M_WAITOK | M_ZERO);
- fl->offset = GV_DATA_START;
- fl->size = d->avail;
- LIST_INSERT_HEAD(&d->freelist, fl, freelist);
- d->freelist_entries = 1;
-
- /* Save it into the main configuration. */
- LIST_INSERT_HEAD(&sc->drives, d, drive);
- }
-
- /*
- * Create bio queue, queue mutex and a worker thread, if
- * necessary.
- */
- if (d->bqueue == NULL) {
- d->bqueue = g_malloc(sizeof(struct bio_queue_head),
- M_WAITOK | M_ZERO);
- bioq_init(d->bqueue);
- }
- if (mtx_initialized(&d->bqueue_mtx) == 0)
- mtx_init(&d->bqueue_mtx, "gv_drive", NULL, MTX_DEF);
-
- if (!(d->flags & GV_DRIVE_THREAD_ACTIVE)) {
- kproc_create(gv_drive_worker, d, NULL, 0, 0,
- "gv_d %s", d->name);
- d->flags |= GV_DRIVE_THREAD_ACTIVE;
+ error = g_access(cp, 0, 1, 0);
+ if (error) {
+ G_VINUM_DEBUG(0, "g_access failed on "
+ "drive %s, errno %d", d->name, error);
+ g_topology_unlock();
+ continue;
}
+ g_topology_unlock();
- g_access(cp, -1, 0, 0);
-
- gp->softc = d;
- d->geom = gp;
- d->vinumconf = sc;
- strncpy(d->device, pp->name, GV_MAXDRIVENAME);
-
- /*
- * Find out which subdisks belong to this drive and crosslink
- * them.
- */
- LIST_FOREACH(s, &sc->subdisks, sd) {
- if (!strncmp(s->drive, d->name, GV_MAXDRIVENAME))
- /* XXX: errors ignored */
- gv_sd_to_drive(sc, d, s, errstr,
- sizeof(errstr));
+ error = gv_write_header(cp, vhdr);
+ if (error) {
+ G_VINUM_DEBUG(0, "writing vhdr failed on drive %s, "
+ "errno %d", d->name, error);
+ g_topology_lock();
+ g_access(cp, 0, -1, 0);
+ g_topology_unlock();
+ continue;
}
-
- /* This drive is now up for sure. */
- gv_set_drive_state(d, GV_DRIVE_UP, 0);
-
- /*
- * If there are subdisks on this drive, we need to create
- * providers for them.
- */
- if (d->sdcount)
- gv_drive_modify(d);
-
- return (gp);
-
- } while (0);
-
- g_topology_lock();
- g_access(cp, -1, 0, 0);
-
- g_detach(cp);
- g_destroy_consumer(cp);
- g_destroy_geom(gp);
- return (NULL);
-}
-
-/*
- * Modify the providers for the given drive 'd'. It is assumed that the
- * subdisk list of 'd' is already correctly set up.
- */
-void
-gv_drive_modify(struct gv_drive *d)
-{
- struct g_geom *gp;
- struct g_consumer *cp;
- struct g_provider *pp, *pp2;
- struct gv_sd *s;
-
- KASSERT(d != NULL, ("gv_drive_modify: null d"));
- gp = d->geom;
- KASSERT(gp != NULL, ("gv_drive_modify: null gp"));
- cp = LIST_FIRST(&gp->consumer);
- KASSERT(cp != NULL, ("gv_drive_modify: null cp"));
- pp = cp->provider;
- KASSERT(pp != NULL, ("gv_drive_modify: null pp"));
-
- g_topology_assert();
-
- LIST_FOREACH(s, &d->subdisks, from_drive) {
- /* This subdisk already has a provider. */
- if (s->provider != NULL)
+ /* First config copy. */
+ error = g_write_data(cp, GV_CFG_OFFSET, sbuf_data(sb),
+ GV_CFG_LEN);
+ if (error) {
+ G_VINUM_DEBUG(0, "writing first config copy failed on "
+ "drive %s, errno %d", d->name, error);
+ g_topology_lock();
+ g_access(cp, 0, -1, 0);
+ g_topology_unlock();
continue;
- pp2 = g_new_providerf(gp, "gvinum/sd/%s", s->name);
- pp2->mediasize = s->size;
- pp2->sectorsize = pp->sectorsize;
- g_error_provider(pp2, 0);
- s->provider = pp2;
- pp2->private = s;
- }
-}
-
-static void
-gv_drive_dead(void *arg, int flag)
-{
- struct g_geom *gp;
- struct g_consumer *cp;
- struct gv_drive *d;
- struct gv_sd *s;
-
- g_topology_assert();
- KASSERT(arg != NULL, ("gv_drive_dead: NULL arg"));
-
- if (flag == EV_CANCEL)
- return;
-
- d = arg;
- if (d->state != GV_DRIVE_DOWN)
- return;
-
- g_trace(G_T_TOPOLOGY, "gv_drive_dead(%s)", d->name);
-
- gp = d->geom;
- if (gp == NULL)
- return;
-
- LIST_FOREACH(cp, &gp->consumer, consumer) {
- if (cp->nstart != cp->nend) {
- G_VINUM_DEBUG(0, "dead drive '%s' still has "
- "active requests, cannot detach consumer",
- d->name);
- g_post_event(gv_drive_dead, d, M_WAITOK, d,
- NULL);
- return;
}
- if (cp->acr != 0 || cp->acw != 0 || cp->ace != 0)
- g_access(cp, -cp->acr, -cp->acw, -cp->ace);
- }
+ /* Second config copy. */
+ error = g_write_data(cp, GV_CFG_OFFSET + GV_CFG_LEN,
+ sbuf_data(sb), GV_CFG_LEN);
+ if (error)
+ G_VINUM_DEBUG(0, "writing second config copy failed on "
+ "drive %s, errno %d", d->name, error);
- G_VINUM_DEBUG(1, "lost drive '%s'", d->name);
- d->geom = NULL;
- LIST_FOREACH(s, &d->subdisks, from_drive) {
- s->provider = NULL;
- s->consumer = NULL;
+ g_topology_lock();
+ g_access(cp, 0, -1, 0);
+ g_topology_unlock();
}
- gv_kill_drive_thread(d);
- gp->softc = NULL;
- g_wither_geom(gp, ENXIO);
-}
-static int
-gv_drive_destroy_geom(struct gctl_req *req, struct g_class *mp,
- struct g_geom *gp)
-{
- struct gv_drive *d;
-
- g_trace(G_T_TOPOLOGY, "gv_drive_destroy_geom: %s", gp->name);
- g_topology_assert();
-
- d = gp->softc;
- gv_kill_drive_thread(d);
-
- g_wither_geom(gp, ENXIO);
- return (0);
+ sbuf_delete(sb);
+ g_free(vhdr);
}
-
-#define VINUMDRIVE_CLASS_NAME "VINUMDRIVE"
-
-static struct g_class g_vinum_drive_class = {
- .name = VINUMDRIVE_CLASS_NAME,
- .version = G_VERSION,
- .taste = gv_drive_taste,
- .destroy_geom = gv_drive_destroy_geom
-};
-
-DECLARE_GEOM_CLASS(g_vinum_drive_class, g_vinum_drive);
diff --git a/sys/geom/vinum/geom_vinum_events.c b/sys/geom/vinum/geom_vinum_events.c
new file mode 100644
index 0000000..ce7fec0
--- /dev/null
+++ b/sys/geom/vinum/geom_vinum_events.c
@@ -0,0 +1,217 @@
+/*-
+ * Copyright (c) 2007 Lukas Ertl
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+
+#include <geom/geom.h>
+#include <geom/vinum/geom_vinum_var.h>
+#include <geom/vinum/geom_vinum.h>
+
+void
+gv_post_event(struct gv_softc *sc, int event, void *arg1, void *arg2,
+ intmax_t arg3, intmax_t arg4)
+{
+ struct gv_event *ev;
+
+ ev = g_malloc(sizeof(*ev), M_WAITOK | M_ZERO);
+ ev->type = event;
+ ev->arg1 = arg1;
+ ev->arg2 = arg2;
+ ev->arg3 = arg3;
+ ev->arg4 = arg4;
+
+ mtx_lock(&sc->queue_mtx);
+ TAILQ_INSERT_TAIL(&sc->equeue, ev, events);
+ wakeup(sc);
+ mtx_unlock(&sc->queue_mtx);
+}
+
+void
+gv_drive_tasted(struct gv_softc *sc, struct g_provider *pp)
+{
+ struct g_geom *gp;
+ struct g_consumer *cp;
+ struct gv_hdr *hdr;
+ struct gv_drive *d;
+ char *buf;
+ int error;
+
+ hdr = NULL;
+ buf = NULL;
+
+ G_VINUM_DEBUG(2, "tasted drive on '%s'", pp->name);
+
+ gp = sc->geom;
+ g_topology_lock();
+ cp = g_new_consumer(gp);
+ if (g_attach(cp, pp) != 0) {
+ g_destroy_consumer(cp);
+ g_topology_unlock();
+ G_VINUM_DEBUG(0, "failed to attach to provider on taste event");
+ return;
+ }
+ if (g_access(cp, 1, 0, 0) != 0) {
+ g_detach(cp);
+ g_destroy_consumer(cp);
+ g_topology_unlock();
+ G_VINUM_DEBUG(0, "failed to access consumer on taste event");
+ return;
+ }
+ g_topology_unlock();
+
+ hdr = g_malloc(GV_HDR_LEN, M_WAITOK | M_ZERO);
+ /* Read header and on-disk configuration. */
+ error = gv_read_header(cp, hdr);
+ if (error) {
+ G_VINUM_DEBUG(0, "failed to read header during taste");
+ goto failed;
+ }
+
+ /*
+ * Setup the drive before we parse the on-disk configuration, so that
+ * we already know about the drive then.
+ */
+ d = gv_find_drive(sc, hdr->label.name);
+ if (d == NULL) {
+ d = g_malloc(sizeof(*d), M_WAITOK | M_ZERO);
+ strlcpy(d->name, hdr->label.name, sizeof(d->name));
+ strlcpy(d->device, pp->name, sizeof(d->device));
+ } else if (d->flags & GV_DRIVE_REFERENCED) {
+ strlcpy(d->device, pp->name, sizeof(d->device));
+ d->flags &= ~GV_DRIVE_REFERENCED;
+ } else {
+ G_VINUM_DEBUG(2, "drive '%s' is already known", d->name);
+ goto failed;
+ }
+
+ /* Add the consumer and header to the new drive. */
+ d->consumer = cp;
+ d->hdr = hdr;
+ gv_create_drive(sc, d);
+
+ buf = g_read_data(cp, GV_CFG_OFFSET, GV_CFG_LEN, NULL);
+ if (buf == NULL) {
+ G_VINUM_DEBUG(0, "failed to read config during taste");
+ goto failed;
+ }
+ gv_parse_config(sc, buf, d);
+ g_free(buf);
+
+ g_topology_lock();
+ g_access(cp, -1, 0, 0);
+ g_topology_unlock();
+
+ gv_setup_objects(sc);
+ gv_set_drive_state(d, GV_DRIVE_UP, 0);
+
+ return;
+
+failed:
+ if (hdr != NULL)
+ g_free(hdr);
+ g_topology_lock();
+ g_access(cp, -1, 0, 0);
+ g_detach(cp);
+ g_destroy_consumer(cp);
+ g_topology_unlock();
+}
+
+/*
+ * When losing a drive (e.g. hardware failure), we cut down the consumer
+ * attached to the underlying device and bring the drive itself to a
+ * "referenced" state so that normal tasting could bring it up cleanly if it
+ * possibly arrives again.
+ */
+void
+gv_drive_lost(struct gv_softc *sc, struct gv_drive *d)
+{
+ struct g_consumer *cp;
+ struct gv_drive *d2;
+ struct gv_sd *s, *s2;
+ struct gv_freelist *fl, *fl2;
+
+ gv_set_drive_state(d, GV_DRIVE_DOWN,
+ GV_SETSTATE_FORCE | GV_SETSTATE_CONFIG);
+
+ cp = d->consumer;
+
+ if (cp != NULL) {
+ if (cp->nstart != cp->nend) {
+ G_VINUM_DEBUG(0, "dead drive '%s' has still active "
+ "requests, can't detach consumer", d->name);
+ gv_post_event(sc, GV_EVENT_DRIVE_LOST, d, NULL, 0, 0);
+ return;
+ }
+ g_topology_lock();
+ if (cp->acr != 0 || cp->acw != 0 || cp->ace != 0)
+ g_access(cp, -cp->acr, -cp->acw, -cp->ace);
+ g_detach(cp);
+ g_destroy_consumer(cp);
+ g_topology_unlock();
+ }
+
+ LIST_FOREACH_SAFE(fl, &d->freelist, freelist, fl2) {
+ LIST_REMOVE(fl, freelist);
+ g_free(fl);
+ }
+
+ d->consumer = NULL;
+ g_free(d->hdr);
+ d->hdr = NULL;
+ d->flags |= GV_DRIVE_REFERENCED;
+ snprintf(d->device, sizeof(d->device), "???");
+ d->size = 0;
+ d->avail = 0;
+ d->freelist_entries = 0;
+ d->sdcount = 0;
+
+ /* Put the subdisk in tasted mode, and remove from drive list. */
+ LIST_FOREACH_SAFE(s, &d->subdisks, from_drive, s2) {
+ LIST_REMOVE(s, from_drive);
+ s->flags |= GV_SD_TASTED;
+ }
+
+ /*
+ * Don't forget that gv_is_newer wants a "real" drive at the beginning
+ * of the list, so, just to be safe, we shuffle around.
+ */
+ LIST_REMOVE(d, drive);
+ d2 = LIST_FIRST(&sc->drives);
+ if (d2 == NULL)
+ LIST_INSERT_HEAD(&sc->drives, d, drive);
+ else
+ LIST_INSERT_AFTER(d2, d, drive);
+ gv_save_config(sc);
+}
diff --git a/sys/geom/vinum/geom_vinum_init.c b/sys/geom/vinum/geom_vinum_init.c
index fddc435..34f1156 100644
--- a/sys/geom/vinum/geom_vinum_init.c
+++ b/sys/geom/vinum/geom_vinum_init.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
+ * Copyright (c) 2007, 2009 Ulf Lilleengen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,158 +27,21 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-
#include <sys/param.h>
#include <sys/bio.h>
-#include <sys/kernel.h>
-#include <sys/kthread.h>
#include <sys/libkern.h>
#include <sys/malloc.h>
-#include <sys/queue.h>
#include <geom/geom.h>
#include <geom/vinum/geom_vinum_var.h>
#include <geom/vinum/geom_vinum.h>
-#include <geom/vinum/geom_vinum_share.h>
-
-static int gv_init_plex(struct gv_plex *);
-void gv_init_td(void *);
-static int gv_rebuild_plex(struct gv_plex *);
-void gv_rebuild_td(void *);
-static int gv_start_plex(struct gv_plex *);
-static int gv_start_vol(struct gv_volume *);
-static int gv_sync(struct gv_volume *);
-void gv_sync_td(void *);
-
-struct gv_sync_args {
- struct gv_volume *v;
- struct gv_plex *from;
- struct gv_plex *to;
- off_t syncsize;
-};
-
-void
-gv_parityop(struct g_geom *gp, struct gctl_req *req)
-{
- struct gv_softc *sc;
- struct gv_plex *p;
- struct bio *bp;
- struct g_consumer *cp;
- int error, *flags, type, *rebuild, rv;
- char *plex;
-
- rv = -1;
-
- plex = gctl_get_param(req, "plex", NULL);
- if (plex == NULL) {
- gctl_error(req, "no plex given");
- goto out;
- }
-
- flags = gctl_get_paraml(req, "flags", sizeof(*flags));
- if (flags == NULL) {
- gctl_error(req, "no flags given");
- goto out;
- }
-
- rebuild = gctl_get_paraml(req, "rebuild", sizeof(*rebuild));
- if (rebuild == NULL) {
- gctl_error(req, "no rebuild op given");
- goto out;
- }
-
- sc = gp->softc;
- type = gv_object_type(sc, plex);
- switch (type) {
- case GV_TYPE_PLEX:
- break;
- case GV_TYPE_VOL:
- case GV_TYPE_SD:
- case GV_TYPE_DRIVE:
- default:
- gctl_error(req, "'%s' is not a plex", plex);
- goto out;
- }
-
- p = gv_find_plex(sc, plex);
- if (p->state != GV_PLEX_UP) {
- gctl_error(req, "plex %s is not completely accessible",
- p->name);
- goto out;
- }
- if (p->org != GV_PLEX_RAID5) {
- gctl_error(req, "plex %s is not a RAID5 plex", p->name);
- goto out;
- }
-
- cp = p->consumer;
- error = g_access(cp, 1, 1, 0);
- if (error) {
- gctl_error(req, "cannot access consumer");
- goto out;
- }
- g_topology_unlock();
-
- /* Reset the check pointer when using -f. */
- if (*flags & GV_FLAG_F)
- p->synced = 0;
-
- bp = g_new_bio();
- if (bp == NULL) {
- gctl_error(req, "cannot create BIO - out of memory");
- g_topology_lock();
- error = g_access(cp, -1, -1, 0);
- goto out;
- }
- bp->bio_cmd = BIO_WRITE;
- bp->bio_done = NULL;
- bp->bio_data = g_malloc(p->stripesize, M_WAITOK | M_ZERO);
- bp->bio_cflags |= GV_BIO_CHECK;
- if (*rebuild)
- bp->bio_cflags |= GV_BIO_PARITY;
- bp->bio_offset = p->synced;
- bp->bio_length = p->stripesize;
-
- /* Schedule it down ... */
- g_io_request(bp, cp);
-
- /* ... and wait for the result. */
- error = biowait(bp, "gwrite");
- g_free(bp->bio_data);
- g_destroy_bio(bp);
-
- if (error) {
- /* Incorrect parity. */
- if (error == EAGAIN)
- rv = 1;
- /* Some other error happened. */
- else
- gctl_error(req, "Parity check failed at offset 0x%jx, "
- "errno %d", (intmax_t)p->synced, error);
-
- /* Correct parity. */
- } else
- rv = 0;
-
- gctl_set_param(req, "offset", &p->synced, sizeof(p->synced));
-
- /* Advance the checkpointer if there was no error. */
- if (rv == 0)
- p->synced += p->stripesize;
-
- /* End of plex; reset the check pointer and signal it to the caller. */
- if (p->synced >= p->size) {
- p->synced = 0;
- rv = -2;
- }
-
- g_topology_lock();
- error = g_access(cp, -1, -1, 0);
-
-out:
- gctl_set_param(req, "rv", &rv, sizeof(rv));
-}
+static int gv_sync(struct gv_volume *);
+static int gv_rebuild_plex(struct gv_plex *);
+static int gv_init_plex(struct gv_plex *);
+static int gv_grow_plex(struct gv_plex *);
+static int gv_sync_plex(struct gv_plex *, struct gv_plex *);
+static struct gv_plex *gv_find_good_plex(struct gv_volume *);
void
gv_start_obj(struct g_geom *gp, struct gctl_req *req)
@@ -187,7 +51,7 @@ gv_start_obj(struct g_geom *gp, struct gctl_req *req)
struct gv_plex *p;
int *argc, *initsize;
char *argv, buf[20];
- int err, i, type;
+ int i, type;
argc = gctl_get_paraml(req, "argc", sizeof(*argc));
initsize = gctl_get_paraml(req, "initsize", sizeof(*initsize));
@@ -208,37 +72,21 @@ gv_start_obj(struct g_geom *gp, struct gctl_req *req)
switch (type) {
case GV_TYPE_VOL:
v = gv_find_vol(sc, argv);
- err = gv_start_vol(v);
- if (err) {
- if (err == EINPROGRESS) {
- gctl_error(req, "cannot start volume "
- "'%s': already in progress", argv);
- } else {
- gctl_error(req, "cannot start volume "
- "'%s'; errno: %d", argv, err);
- }
- return;
- }
+ if (v != NULL)
+ gv_post_event(sc, GV_EVENT_START_VOLUME, v,
+ NULL, *initsize, 0);
break;
case GV_TYPE_PLEX:
p = gv_find_plex(sc, argv);
- err = gv_start_plex(p);
- if (err) {
- if (err == EINPROGRESS) {
- gctl_error(req, "cannot start plex "
- "'%s': already in progress", argv);
- } else {
- gctl_error(req, "cannot start plex "
- "'%s'; errno: %d", argv, err);
- }
- return;
- }
+ if (p != NULL)
+ gv_post_event(sc, GV_EVENT_START_PLEX, p, NULL,
+ *initsize, 0);
break;
case GV_TYPE_SD:
case GV_TYPE_DRIVE:
- /* XXX not yet */
+ /* XXX Not implemented, but what is the use? */
gctl_error(req, "cannot start '%s' - not yet supported",
argv);
return;
@@ -249,36 +97,73 @@ gv_start_obj(struct g_geom *gp, struct gctl_req *req)
}
}
-static int
+int
gv_start_plex(struct gv_plex *p)
{
struct gv_volume *v;
+ struct gv_plex *up;
+ struct gv_sd *s;
int error;
KASSERT(p != NULL, ("gv_start_plex: NULL p"));
- if (p->state == GV_PLEX_UP)
- return (0);
-
error = 0;
v = p->vol_sc;
- if ((v != NULL) && (v->plexcount > 1))
- error = gv_sync(v);
- else if (p->org == GV_PLEX_RAID5) {
- if (p->state == GV_PLEX_DEGRADED)
+
+ /* RAID5 plexes can either be init, rebuilt or grown. */
+ if (p->org == GV_PLEX_RAID5) {
+ if (p->state > GV_PLEX_DEGRADED) {
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ if (s->flags & GV_SD_GROW) {
+ error = gv_grow_plex(p);
+ return (error);
+ }
+ }
+ } else if (p->state == GV_PLEX_DEGRADED) {
error = gv_rebuild_plex(p);
- else
+ } else
error = gv_init_plex(p);
+ } else {
+ /* We want to sync from the other plex if we're down. */
+ if (p->state == GV_PLEX_DOWN && v->plexcount > 1) {
+ up = gv_find_good_plex(v);
+ if (up == NULL) {
+ G_VINUM_DEBUG(1, "unable to find a good plex");
+ return (ENXIO);
+ }
+ g_topology_lock();
+ error = gv_access(v->provider, 1, 1, 0);
+ if (error) {
+ g_topology_unlock();
+ G_VINUM_DEBUG(0, "sync from '%s' failed to "
+ "access volume: %d", up->name, error);
+ return (error);
+ }
+ g_topology_unlock();
+ error = gv_sync_plex(p, up);
+ if (error)
+ return (error);
+ /*
+ * In case we have a stripe that is up, check whether it can be
+ * grown.
+ */
+ } else if (p->org == GV_PLEX_STRIPED &&
+ p->state != GV_PLEX_DOWN) {
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ if (s->flags & GV_SD_GROW) {
+ error = gv_grow_plex(p);
+ break;
+ }
+ }
+ }
}
-
return (error);
}
-static int
+int
gv_start_vol(struct gv_volume *v)
{
struct gv_plex *p;
- struct gv_sd *s;
int error;
KASSERT(v != NULL, ("gv_start_vol: NULL v"));
@@ -291,39 +176,46 @@ gv_start_vol(struct gv_volume *v)
else if (v->plexcount == 1) {
p = LIST_FIRST(&v->plexes);
KASSERT(p != NULL, ("gv_start_vol: NULL p on %s", v->name));
- if (p->org == GV_PLEX_RAID5) {
- switch (p->state) {
- case GV_PLEX_DOWN:
- error = gv_init_plex(p);
- break;
- case GV_PLEX_DEGRADED:
- error = gv_rebuild_plex(p);
- break;
- default:
- return (0);
- }
- } else {
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- gv_set_sd_state(s, GV_SD_UP,
- GV_SETSTATE_CONFIG);
- }
- }
+ error = gv_start_plex(p);
} else
error = gv_sync(v);
return (error);
}
+/* Sync a plex p from the plex up. */
static int
-gv_sync(struct gv_volume *v)
+gv_sync_plex(struct gv_plex *p, struct gv_plex *up)
{
- struct gv_softc *sc;
- struct gv_plex *p, *up;
- struct gv_sync_args *sync;
+ int error;
- KASSERT(v != NULL, ("gv_sync: NULL v"));
- sc = v->vinumconf;
- KASSERT(sc != NULL, ("gv_sync: NULL sc on %s", v->name));
+ KASSERT(p != NULL, ("%s: NULL p", __func__));
+ KASSERT(up != NULL, ("%s: NULL up", __func__));
+ if ((p == up) || (p->state == GV_PLEX_UP))
+ return (0);
+ if (p->flags & GV_PLEX_SYNCING ||
+ p->flags & GV_PLEX_REBUILDING ||
+ p->flags & GV_PLEX_GROWING) {
+ return (EINPROGRESS);
+ }
+ p->synced = 0;
+ p->flags |= GV_PLEX_SYNCING;
+ G_VINUM_DEBUG(1, "starting sync of plex %s", p->name);
+ error = gv_sync_request(up, p, p->synced,
+ MIN(GV_DFLT_SYNCSIZE, up->size - p->synced),
+ BIO_READ, NULL);
+ if (error) {
+ G_VINUM_DEBUG(0, "error syncing plex %s", p->name);
+ return (error);
+ }
+ return (0);
+}
+
+/* Return a good plex from volume v. */
+static struct gv_plex *
+gv_find_good_plex(struct gv_volume *v)
+{
+ struct gv_plex *up;
/* Find the plex that's up. */
up = NULL;
@@ -331,341 +223,166 @@ gv_sync(struct gv_volume *v)
if (up->state == GV_PLEX_UP)
break;
}
-
/* Didn't find a good plex. */
- if (up == NULL)
- return (ENXIO);
-
- LIST_FOREACH(p, &v->plexes, in_volume) {
- if ((p == up) || (p->state == GV_PLEX_UP))
- continue;
- if (p->flags & GV_PLEX_SYNCING) {
- return (EINPROGRESS);
- }
- p->flags |= GV_PLEX_SYNCING;
- sync = g_malloc(sizeof(*sync), M_WAITOK | M_ZERO);
- sync->v = v;
- sync->from = up;
- sync->to = p;
- sync->syncsize = GV_DFLT_SYNCSIZE;
- kproc_create(gv_sync_td, sync, NULL, 0, 0, "gv_sync '%s'",
- p->name);
- }
-
- return (0);
+ return (up);
}
static int
-gv_rebuild_plex(struct gv_plex *p)
-{
- struct gv_sync_args *sync;
-
- if (gv_is_open(p->geom))
- return (EBUSY);
-
- if (p->flags & GV_PLEX_SYNCING)
- return (EINPROGRESS);
- p->flags |= GV_PLEX_SYNCING;
-
- sync = g_malloc(sizeof(*sync), M_WAITOK | M_ZERO);
- sync->to = p;
- sync->syncsize = GV_DFLT_SYNCSIZE;
-
- kproc_create(gv_rebuild_td, sync, NULL, 0, 0, "gv_rebuild %s",
- p->name);
-
- return (0);
-}
-
-static int
-gv_init_plex(struct gv_plex *p)
-{
- struct gv_sd *s;
-
- KASSERT(p != NULL, ("gv_init_plex: NULL p"));
-
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (s->state == GV_SD_INITIALIZING)
- return (EINPROGRESS);
- gv_set_sd_state(s, GV_SD_INITIALIZING, GV_SETSTATE_FORCE);
- s->init_size = GV_DFLT_SYNCSIZE;
- kproc_create(gv_init_td, s, NULL, 0, 0, "gv_init %s",
- s->name);
- }
-
- return (0);
-}
-
-/* This thread is responsible for rebuilding a degraded RAID5 plex. */
-void
-gv_rebuild_td(void *arg)
+gv_sync(struct gv_volume *v)
{
- struct bio *bp;
- struct gv_plex *p;
- struct g_consumer *cp;
- struct gv_sync_args *sync;
- u_char *buf;
- off_t i;
+ struct gv_softc *sc;
+ struct gv_plex *p, *up;
int error;
- buf = NULL;
- bp = NULL;
+ KASSERT(v != NULL, ("gv_sync: NULL v"));
+ sc = v->vinumconf;
+ KASSERT(sc != NULL, ("gv_sync: NULL sc on %s", v->name));
- sync = arg;
- p = sync->to;
- p->synced = 0;
- cp = p->consumer;
+ up = gv_find_good_plex(v);
+ if (up == NULL)
+ return (ENXIO);
g_topology_lock();
- error = g_access(cp, 1, 1, 0);
+ error = gv_access(v->provider, 1, 1, 0);
if (error) {
g_topology_unlock();
- G_VINUM_DEBUG(0, "rebuild of %s failed to access consumer: "
- "%d", p->name, error);
- kproc_exit(error);
+ G_VINUM_DEBUG(0, "sync from '%s' failed to access volume: %d",
+ up->name, error);
+ return (error);
}
g_topology_unlock();
- buf = g_malloc(sync->syncsize, M_WAITOK);
-
- G_VINUM_DEBUG(1, "rebuild of %s started", p->name);
- i = 0;
- for (i = 0; i < p->size; i += (p->stripesize * (p->sdcount - 1))) {
-/*
- if (i + sync->syncsize > p->size)
- sync->syncsize = p->size - i;
-*/
- bp = g_new_bio();
- if (bp == NULL) {
- G_VINUM_DEBUG(0, "rebuild of %s failed creating bio: "
- "out of memory", p->name);
- break;
- }
- bp->bio_cmd = BIO_WRITE;
- bp->bio_done = NULL;
- bp->bio_data = buf;
- bp->bio_cflags |= GV_BIO_REBUILD;
- bp->bio_offset = i;
- bp->bio_length = p->stripesize;
-
- /* Schedule it down ... */
- g_io_request(bp, cp);
-
- /* ... and wait for the result. */
- error = biowait(bp, "gwrite");
- if (error) {
- G_VINUM_DEBUG(0, "rebuild of %s failed at offset %jd "
- "errno: %d", p->name, i, error);
+ /* Go through the good plex, and issue BIO's to all other plexes. */
+ LIST_FOREACH(p, &v->plexes, in_volume) {
+ error = gv_sync_plex(p, up);
+ if (error)
break;
- }
- g_destroy_bio(bp);
- bp = NULL;
}
-
- if (bp != NULL)
- g_destroy_bio(bp);
- if (buf != NULL)
- g_free(buf);
-
- g_topology_lock();
- g_access(cp, -1, -1, 0);
- gv_save_config_all(p->vinumconf);
- g_topology_unlock();
-
- p->flags &= ~GV_PLEX_SYNCING;
- p->synced = 0;
-
- /* Successful initialization. */
- if (!error)
- G_VINUM_DEBUG(1, "rebuild of %s finished", p->name);
-
- g_free(sync);
- kproc_exit(error);
+ return (0);
}
-void
-gv_sync_td(void *arg)
+static int
+gv_rebuild_plex(struct gv_plex *p)
{
- struct bio *bp;
- struct gv_plex *p;
- struct g_consumer *from, *to;
- struct gv_sync_args *sync;
- u_char *buf;
- off_t i;
+ struct gv_drive *d;
+ struct gv_sd *s;
int error;
- sync = arg;
-
- from = sync->from->consumer;
- to = sync->to->consumer;
-
- p = sync->to;
+ if (p->flags & GV_PLEX_SYNCING ||
+ p->flags & GV_PLEX_REBUILDING ||
+ p->flags & GV_PLEX_GROWING)
+ return (EINPROGRESS);
+ /*
+ * Make sure that all subdisks have consumers. We won't allow a rebuild
+ * unless every subdisk have one.
+ */
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ d = s->drive_sc;
+ if (d == NULL || (d->flags & GV_DRIVE_REFERENCED)) {
+ G_VINUM_DEBUG(0, "can't rebuild %s, subdisk(s) have no "
+ "drives", p->name);
+ return (ENXIO);
+ }
+ }
+ p->flags |= GV_PLEX_REBUILDING;
p->synced = 0;
- error = 0;
-
+ g_topology_assert_not();
g_topology_lock();
- error = g_access(from, 1, 0, 0);
+ error = gv_access(p->vol_sc->provider, 1, 1, 0);
if (error) {
- g_topology_unlock();
- G_VINUM_DEBUG(0, "sync from '%s' failed to access "
- "consumer: %d", sync->from->name, error);
- g_free(sync);
- kproc_exit(error);
- }
- error = g_access(to, 0, 1, 0);
- if (error) {
- g_access(from, -1, 0, 0);
- g_topology_unlock();
- G_VINUM_DEBUG(0, "sync to '%s' failed to access "
- "consumer: %d", p->name, error);
- g_free(sync);
- kproc_exit(error);
+ G_VINUM_DEBUG(0, "unable to access provider");
+ return (0);
}
g_topology_unlock();
- G_VINUM_DEBUG(1, "plex sync %s -> %s started", sync->from->name,
- sync->to->name);
- for (i = 0; i < p->size; i+= sync->syncsize) {
- /* Read some bits from the good plex. */
- buf = g_read_data(from, i, sync->syncsize, &error);
- if (buf == NULL) {
- G_VINUM_DEBUG(0, "sync read from '%s' failed at "
- "offset %jd; errno: %d", sync->from->name, i,
- error);
- break;
- }
-
- /*
- * Create a bio and schedule it down on the 'bad' plex. We
- * cannot simply use g_write_data() because we have to let the
- * lower parts know that we are an initialization process and
- * not a 'normal' request.
- */
- bp = g_new_bio();
- if (bp == NULL) {
- G_VINUM_DEBUG(0, "sync write to '%s' failed at "
- "offset %jd; out of memory", p->name, i);
- g_free(buf);
- break;
- }
- bp->bio_cmd = BIO_WRITE;
- bp->bio_offset = i;
- bp->bio_length = sync->syncsize;
- bp->bio_data = buf;
- bp->bio_done = NULL;
-
- /*
- * This hack declare this bio as part of an initialization
- * process, so that the lower levels allow it to get through.
- */
- bp->bio_cflags |= GV_BIO_SYNCREQ;
-
- /* Schedule it down ... */
- g_io_request(bp, to);
+ gv_parity_request(p, GV_BIO_REBUILD, 0);
+ return (0);
+}
- /* ... and wait for the result. */
- error = biowait(bp, "gwrite");
- g_destroy_bio(bp);
- g_free(buf);
- if (error) {
- G_VINUM_DEBUG(0, "sync write to '%s' failed at "
- "offset %jd; errno: %d\n", p->name, i, error);
- break;
- }
+static int
+gv_grow_plex(struct gv_plex *p)
+{
+ struct gv_volume *v;
+ struct gv_sd *s;
+ off_t origsize, origlength;
+ int error, sdcount;
- /* Note that we have synced a little bit more. */
- p->synced += sync->syncsize;
- }
+ KASSERT(p != NULL, ("gv_grow_plex: NULL p"));
+ v = p->vol_sc;
+ KASSERT(v != NULL, ("gv_grow_plex: NULL v"));
+ if (p->flags & GV_PLEX_GROWING ||
+ p->flags & GV_PLEX_SYNCING ||
+ p->flags & GV_PLEX_REBUILDING)
+ return (EINPROGRESS);
g_topology_lock();
- g_access(from, -1, 0, 0);
- g_access(to, 0, -1, 0);
- gv_save_config_all(p->vinumconf);
+ error = gv_access(v->provider, 1, 1, 0);
g_topology_unlock();
+ if (error) {
+ G_VINUM_DEBUG(0, "unable to access provider");
+ return (error);
+ }
- /* Successful initialization. */
- if (!error)
- G_VINUM_DEBUG(1, "plex sync %s -> %s finished",
- sync->from->name, sync->to->name);
-
- p->flags &= ~GV_PLEX_SYNCING;
+ /* XXX: This routine with finding origsize is used two other places as
+ * well, so we should create a function for it. */
+ sdcount = p->sdcount;
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ if (s->flags & GV_SD_GROW)
+ sdcount--;
+ }
+ s = LIST_FIRST(&p->subdisks);
+ if (s == NULL) {
+ G_VINUM_DEBUG(0, "error growing plex without subdisks");
+ return (GV_ERR_NOTFOUND);
+ }
+ p->flags |= GV_PLEX_GROWING;
+ origsize = (sdcount - 1) * s->size;
+ origlength = (sdcount - 1) * p->stripesize;
p->synced = 0;
+ G_VINUM_DEBUG(1, "starting growing of plex %s", p->name);
+ gv_grow_request(p, 0, MIN(origlength, origsize), BIO_READ, NULL);
- g_free(sync);
- kproc_exit(error);
+ return (0);
}
-void
-gv_init_td(void *arg)
+static int
+gv_init_plex(struct gv_plex *p)
{
- struct gv_sd *s;
struct gv_drive *d;
- struct g_geom *gp;
- struct g_consumer *cp;
+ struct gv_sd *s;
int error;
- off_t i, init_size, start, offset, length;
- u_char *buf;
-
- s = arg;
- KASSERT(s != NULL, ("gv_init_td: NULL s"));
- d = s->drive_sc;
- KASSERT(d != NULL, ("gv_init_td: NULL d"));
- gp = d->geom;
- KASSERT(gp != NULL, ("gv_init_td: NULL gp"));
-
- cp = LIST_FIRST(&gp->consumer);
- KASSERT(cp != NULL, ("gv_init_td: NULL cp"));
+ off_t start;
+ caddr_t data;
- s->init_error = 0;
- init_size = s->init_size;
- start = s->drive_offset + s->initialized;
- offset = s->drive_offset;
- length = s->size;
-
- buf = g_malloc(s->init_size, M_WAITOK | M_ZERO);
-
- g_topology_lock();
- error = g_access(cp, 0, 1, 0);
- if (error) {
- s->init_error = error;
- g_topology_unlock();
- G_VINUM_DEBUG(0, "subdisk '%s' init: failed to access "
- "consumer; error: %d", s->name, error);
- kproc_exit(error);
- }
- g_topology_unlock();
+ KASSERT(p != NULL, ("gv_init_plex: NULL p"));
- for (i = start; i < offset + length; i += init_size) {
- error = g_write_data(cp, i, buf, init_size);
- if (error) {
- G_VINUM_DEBUG(0, "subdisk '%s' init: write failed"
- " at offset %jd (drive offset %jd); error %d",
- s->name, (intmax_t)s->initialized, (intmax_t)i,
- error);
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ if (s->state == GV_SD_INITIALIZING)
+ return (EINPROGRESS);
+ gv_set_sd_state(s, GV_SD_INITIALIZING, GV_SETSTATE_FORCE);
+ s->init_size = GV_DFLT_SYNCSIZE;
+ start = s->drive_offset + s->initialized;
+ d = s->drive_sc;
+ if (d == NULL) {
+ G_VINUM_DEBUG(0, "subdisk %s has no drive yet", s->name);
break;
}
- s->initialized += init_size;
- }
-
- g_free(buf);
-
- g_topology_lock();
- g_access(cp, 0, -1, 0);
- g_topology_unlock();
- if (error) {
- s->init_error = error;
- g_topology_lock();
- gv_set_sd_state(s, GV_SD_STALE,
- GV_SETSTATE_FORCE | GV_SETSTATE_CONFIG);
- g_topology_unlock();
- } else {
+ /*
+ * Take the lock here since we need to avoid a race in
+ * gv_init_request if the BIO is completed before the lock is
+ * released.
+ */
g_topology_lock();
- gv_set_sd_state(s, GV_SD_UP, GV_SETSTATE_CONFIG);
+ error = g_access(d->consumer, 0, 1, 0);
g_topology_unlock();
- s->initialized = 0;
- G_VINUM_DEBUG(1, "subdisk '%s' init: finished successfully",
- s->name);
+ if (error) {
+ G_VINUM_DEBUG(0, "error accessing consumer when "
+ "initializing %s", s->name);
+ break;
+ }
+ data = g_malloc(s->init_size, M_WAITOK | M_ZERO);
+ gv_init_request(s, start, data, s->init_size);
}
- kproc_exit(error);
+ return (0);
}
diff --git a/sys/geom/vinum/geom_vinum_list.c b/sys/geom/vinum/geom_vinum_list.c
index b1a668f..00b89495 100644
--- a/sys/geom/vinum/geom_vinum_list.c
+++ b/sys/geom/vinum/geom_vinum_list.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/param.h>
#include <sys/libkern.h>
#include <sys/malloc.h>
@@ -302,19 +301,37 @@ gv_lpi(struct gv_plex *p, struct sbuf *sb, int flags)
sbuf_printf(sb, "Plex %s:\tSize:\t%9jd bytes (%jd MB)\n",
p->name, (intmax_t)p->size, (intmax_t)p->size / MEGABYTE);
sbuf_printf(sb, "\t\tSubdisks: %8d\n", p->sdcount);
- sbuf_printf(sb, "\t\tState: %s\n\t\tOrganization: %s",
- gv_plexstate(p->state), gv_plexorg(p->org));
+ sbuf_printf(sb, "\t\tState: %s\n", gv_plexstate(p->state));
+ if ((p->flags & GV_PLEX_SYNCING) ||
+ (p->flags & GV_PLEX_GROWING) ||
+ (p->flags & GV_PLEX_REBUILDING)) {
+ sbuf_printf(sb, "\t\tSynced: ");
+ sbuf_printf(sb, "%16jd bytes (%d%%)\n",
+ (intmax_t)p->synced,
+ (p->size > 0) ? (int)((p->synced * 100) / p->size) :
+ 0);
+ }
+ sbuf_printf(sb, "\t\tOrganization: %s", gv_plexorg(p->org));
if (gv_is_striped(p)) {
sbuf_printf(sb, "\tStripe size: %s\n",
gv_roughlength(p->stripesize, 1));
}
+ sbuf_printf(sb, "\t\tFlags: %d\n", p->flags);
if (p->vol_sc != NULL) {
sbuf_printf(sb, "\t\tPart of volume %s\n", p->volume);
}
} else {
- sbuf_printf(sb, "P %-18s %2s State: %s\tSubdisks: %5d"
- "\tSize: %s\n", p->name, gv_plexorg_short(p->org),
- gv_plexstate(p->state), p->sdcount,
+ sbuf_printf(sb, "P %-18s %2s State: ", p->name,
+ gv_plexorg_short(p->org));
+ if ((p->flags & GV_PLEX_SYNCING) ||
+ (p->flags & GV_PLEX_GROWING) ||
+ (p->flags & GV_PLEX_REBUILDING)) {
+ sbuf_printf(sb, "S %d%%\t", (int)((p->synced * 100) /
+ p->size));
+ } else {
+ sbuf_printf(sb, "%s\t", gv_plexstate(p->state));
+ }
+ sbuf_printf(sb, "Subdisks: %5d\tSize: %s\n", p->sdcount,
gv_roughlength(p->size, 0));
}
@@ -396,6 +413,7 @@ gv_lsi(struct gv_sd *s, struct sbuf *sb, int flags)
s->drive_sc == NULL ? "*missing*" : s->drive_sc->name,
(intmax_t)s->drive_offset,
gv_roughlength(s->drive_offset, 1));
+ sbuf_printf(sb, "\t\tFlags: %d\n", s->flags);
} else {
sbuf_printf(sb, "S %-21s State: ", s->name);
if (s->state == GV_SD_INITIALIZING ||
@@ -455,6 +473,7 @@ gv_ldi(struct gv_drive *d, struct sbuf *sb, int flags)
sbuf_printf(sb, "\t\tAvailable: %11jd bytes (%jd MB)\n",
(intmax_t)d->avail, (intmax_t)d->avail / MEGABYTE);
sbuf_printf(sb, "\t\tState: %s\n", gv_drivestate(d->state));
+ sbuf_printf(sb, "\t\tFlags: %d\n", d->flags);
/* Be very verbose. */
if (flags & GV_FLAG_VV) {
@@ -469,7 +488,7 @@ gv_ldi(struct gv_drive *d, struct sbuf *sb, int flags)
sbuf_printf(sb, "D %-21s State: %s\t/dev/%s\tA: %jd/%jd MB "
"(%d%%)\n", d->name, gv_drivestate(d->state), d->device,
(intmax_t)d->avail / MEGABYTE, (intmax_t)d->size / MEGABYTE,
- (int)((d->avail * 100) / d->size));
+ d->size > 0 ? (int)((d->avail * 100) / d->size) : 0);
}
/* Recursive listing. */
diff --git a/sys/geom/vinum/geom_vinum_move.c b/sys/geom/vinum/geom_vinum_move.c
index 04822bc..e55a6a2 100644
--- a/sys/geom/vinum/geom_vinum_move.c
+++ b/sys/geom/vinum/geom_vinum_move.c
@@ -32,26 +32,21 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/param.h>
#include <sys/libkern.h>
-#include <sys/kernel.h>
#include <sys/malloc.h>
#include <geom/geom.h>
#include <geom/vinum/geom_vinum_var.h>
#include <geom/vinum/geom_vinum.h>
-#include <geom/vinum/geom_vinum_share.h>
-
-static int gv_move_sd(struct gv_softc *, struct gctl_req *,
- struct gv_sd *, char *, int);
void
gv_move(struct g_geom *gp, struct gctl_req *req)
{
struct gv_softc *sc;
struct gv_sd *s;
+ struct gv_drive *d;
char buf[20], *destination, *object;
- int *argc, err, *flags, i, type;
+ int *argc, *flags, i, type;
sc = gp->softc;
@@ -74,6 +69,7 @@ gv_move(struct g_geom *gp, struct gctl_req *req)
gctl_error(req, "destination '%s' is not a drive", destination);
return;
}
+ d = gv_find_drive(sc, destination);
/*
* We start with 1 here, because argv[0] on the command line is the
@@ -97,67 +93,59 @@ gv_move(struct g_geom *gp, struct gctl_req *req)
gctl_error(req, "unknown subdisk '%s'", object);
return;
}
- err = gv_move_sd(sc, req, s, destination, *flags);
- if (err)
- return;
+ gv_post_event(sc, GV_EVENT_MOVE_SD, s, d, *flags, 0);
}
-
- gv_save_config_all(sc);
}
/* Move a subdisk. */
-static int
-gv_move_sd(struct gv_softc *sc, struct gctl_req *req, struct gv_sd *cursd, char *destination, int flags)
+int
+gv_move_sd(struct gv_softc *sc, struct gv_sd *cursd,
+ struct gv_drive *destination, int flags)
{
struct gv_drive *d;
struct gv_sd *newsd, *s, *s2;
struct gv_plex *p;
- struct g_consumer *cp;
- char errstr[ERRBUFSIZ];
int err;
g_topology_assert();
KASSERT(cursd != NULL, ("gv_move_sd: NULL cursd"));
+ KASSERT(destination != NULL, ("gv_move_sd: NULL destination"));
- cp = cursd->consumer;
+ d = cursd->drive_sc;
- if (cp != NULL && (cp->acr || cp->acw || cp->ace)) {
- gctl_error(req, "subdisk '%s' is busy", cursd->name);
- return (-1);
+ if ((gv_consumer_is_open(d->consumer) ||
+ gv_consumer_is_open(destination->consumer)) &&
+ !(flags && GV_FLAG_F)) {
+ G_VINUM_DEBUG(0, "consumers on current and destination drive "
+ " still open");
+ return (GV_ERR_ISBUSY);
}
if (!(flags && GV_FLAG_F)) {
- gctl_error(req, "-f flag not passed; move would be "
+ G_VINUM_DEBUG(1, "-f flag not passed; move would be "
"destructive");
- return (-1);
+ return (GV_ERR_INVFLAG);
}
- d = gv_find_drive(sc, destination);
- if (d == NULL) {
- gctl_error(req, "destination drive '%s' not found",
- destination);
- return (-1);
- }
-
- if (d == cursd->drive_sc) {
- gctl_error(req, "subdisk '%s' already on drive '%s'",
- cursd->name, destination);
- return (-1);
+ if (destination == cursd->drive_sc) {
+ G_VINUM_DEBUG(1, "subdisk '%s' already on drive '%s'",
+ cursd->name, destination->name);
+ return (GV_ERR_ISATTACHED);
}
/* XXX: Does it have to be part of a plex? */
p = gv_find_plex(sc, cursd->plex);
if (p == NULL) {
- gctl_error(req, "subdisk '%s' is not part of a plex",
+ G_VINUM_DEBUG(0, "subdisk '%s' is not part of a plex",
cursd->name);
- return (-1);
+ return (GV_ERR_NOTFOUND);
}
-
+
/* Stale the old subdisk. */
err = gv_set_sd_state(cursd, GV_SD_STALE,
GV_SETSTATE_FORCE | GV_SETSTATE_CONFIG);
if (err) {
- gctl_error(req, "could not set the subdisk '%s' to state "
+ G_VINUM_DEBUG(0, "could not set the subdisk '%s' to state "
"'stale'", cursd->name);
return (err);
}
@@ -171,54 +159,30 @@ gv_move_sd(struct gv_softc *sc, struct gctl_req *req, struct gv_sd *cursd, char
newsd->plex_offset = cursd->plex_offset;
newsd->size = cursd->size;
newsd->drive_offset = -1;
- strncpy(newsd->name, cursd->name, GV_MAXSDNAME);
- strncpy(newsd->drive, destination, GV_MAXDRIVENAME);
- strncpy(newsd->plex, cursd->plex, GV_MAXPLEXNAME);
+ strlcpy(newsd->name, cursd->name, sizeof(newsd->name));
+ strlcpy(newsd->drive, destination->name, sizeof(newsd->drive));
+ strlcpy(newsd->plex, cursd->plex, sizeof(newsd->plex));
newsd->state = GV_SD_STALE;
newsd->vinumconf = cursd->vinumconf;
- err = gv_sd_to_drive(sc, d, newsd, errstr, ERRBUFSIZ);
+ err = gv_sd_to_drive(newsd, destination);
if (err) {
/* XXX not enough free space? */
- gctl_error(req, errstr);
g_free(newsd);
return (err);
}
/* Replace the old sd by the new one. */
- if (cp != NULL)
- g_detach(cp);
LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2) {
if (s == cursd) {
- p->sdcount--;
- p->size -= s->size;
- err = gv_rm_sd(sc, req, s, 0);
- if (err)
- return (err);
-
+ gv_rm_sd(sc, s);
}
}
-
- gv_sd_to_plex(p, newsd, 1);
-
- /* Creates the new providers.... */
- gv_drive_modify(d);
-
- /* And reconnect the consumer ... */
- if (cp != NULL) {
- newsd->consumer = cp;
- err = g_attach(cp, newsd->provider);
- if (err) {
- g_destroy_consumer(cp);
- gctl_error(req, "proposed move would create a loop "
- "in GEOM config");
- return (err);
- }
- }
-
+ gv_sd_to_plex(newsd, p);
LIST_INSERT_HEAD(&sc->subdisks, newsd, sd);
-
- gv_save_config_all(sc);
-
+ /* Update volume size of plex. */
+ if (p->vol_sc != NULL)
+ gv_update_vol_size(p->vol_sc, gv_vol_size(p->vol_sc));
+ gv_save_config(p->vinumconf);
return (0);
}
diff --git a/sys/geom/vinum/geom_vinum_plex.c b/sys/geom/vinum/geom_vinum_plex.c
index 8281cb2..f177068 100644
--- a/sys/geom/vinum/geom_vinum_plex.c
+++ b/sys/geom/vinum/geom_vinum_plex.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
+ * Copyright (c) 2007, 2009 Ulf Lilleengen
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,13 +30,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bio.h>
-#include <sys/kernel.h>
-#include <sys/kthread.h>
-#include <sys/libkern.h>
#include <sys/lock.h>
#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
#include <sys/systm.h>
#include <geom/geom.h>
@@ -43,329 +39,422 @@ __FBSDID("$FreeBSD$");
#include <geom/vinum/geom_vinum_raid5.h>
#include <geom/vinum/geom_vinum.h>
-static void gv_plex_completed_request(struct gv_plex *, struct bio *);
-static void gv_plex_normal_request(struct gv_plex *, struct bio *);
-static void gv_plex_worker(void *);
-static int gv_check_parity(struct gv_plex *, struct bio *,
- struct gv_raid5_packet *);
-static int gv_normal_parity(struct gv_plex *, struct bio *,
- struct gv_raid5_packet *);
-
-/* XXX: is this the place to catch dying subdisks? */
-static void
-gv_plex_orphan(struct g_consumer *cp)
+static int gv_check_parity(struct gv_plex *, struct bio *,
+ struct gv_raid5_packet *);
+static int gv_normal_parity(struct gv_plex *, struct bio *,
+ struct gv_raid5_packet *);
+static void gv_plex_flush(struct gv_plex *);
+static int gv_plex_offset(struct gv_plex *, off_t, off_t, off_t *, off_t *,
+ int *, int);
+static int gv_plex_normal_request(struct gv_plex *, struct bio *, off_t,
+ off_t, caddr_t);
+void
+gv_plex_start(struct gv_plex *p, struct bio *bp)
{
- struct g_geom *gp;
- struct gv_plex *p;
- int error;
+ struct bio *cbp;
+ struct gv_sd *s;
+ struct gv_raid5_packet *wp;
+ caddr_t addr;
+ off_t bcount, boff, len;
- g_topology_assert();
- gp = cp->geom;
- g_trace(G_T_TOPOLOGY, "gv_plex_orphan(%s)", gp->name);
-
- if (cp->acr != 0 || cp->acw != 0 || cp->ace != 0)
- g_access(cp, -cp->acr, -cp->acw, -cp->ace);
- error = cp->provider->error;
- if (error == 0)
- error = ENXIO;
- g_detach(cp);
- g_destroy_consumer(cp);
- if (!LIST_EMPTY(&gp->consumer))
- return;
+ bcount = bp->bio_length;
+ addr = bp->bio_data;
+ boff = bp->bio_offset;
+
+ /* Walk over the whole length of the request, we might split it up. */
+ while (bcount > 0) {
+ wp = NULL;
+
+ /*
+ * RAID5 plexes need special treatment, as a single request
+ * might involve several read/write sub-requests.
+ */
+ if (p->org == GV_PLEX_RAID5) {
+ wp = gv_raid5_start(p, bp, addr, boff, bcount);
+ if (wp == NULL)
+ return;
+
+ len = wp->length;
- p = gp->softc;
- if (p != NULL) {
- gv_kill_plex_thread(p);
- p->geom = NULL;
- p->provider = NULL;
- p->consumer = NULL;
+ if (TAILQ_EMPTY(&wp->bits))
+ g_free(wp);
+ else if (wp->lockbase != -1)
+ TAILQ_INSERT_TAIL(&p->packets, wp, list);
+
+ /*
+ * Requests to concatenated and striped plexes go straight
+ * through.
+ */
+ } else {
+ len = gv_plex_normal_request(p, bp, boff, bcount, addr);
+ }
+ if (len < 0)
+ return;
+
+ bcount -= len;
+ addr += len;
+ boff += len;
}
- gp->softc = NULL;
- g_wither_geom(gp, error);
-}
-void
-gv_plex_done(struct bio *bp)
-{
- struct gv_plex *p;
-
- p = bp->bio_from->geom->softc;
- bp->bio_cflags |= GV_BIO_DONE;
- mtx_lock(&p->bqueue_mtx);
- bioq_insert_tail(p->bqueue, bp);
- wakeup(p);
- mtx_unlock(&p->bqueue_mtx);
+ /*
+ * Fire off all sub-requests. We get the correct consumer (== drive)
+ * to send each request to via the subdisk that was stored in
+ * cbp->bio_caller1.
+ */
+ cbp = bioq_takefirst(p->bqueue);
+ while (cbp != NULL) {
+ /*
+ * RAID5 sub-requests need to come in correct order, otherwise
+ * we trip over the parity, as it might be overwritten by
+ * another sub-request. We abuse cbp->bio_caller2 to mark
+ * potential overlap situations.
+ */
+ if (cbp->bio_caller2 != NULL && gv_stripe_active(p, cbp)) {
+ /* Park the bio on the waiting queue. */
+ cbp->bio_cflags |= GV_BIO_ONHOLD;
+ bioq_disksort(p->wqueue, cbp);
+ } else {
+ s = cbp->bio_caller1;
+ g_io_request(cbp, s->drive_sc->consumer);
+ }
+ cbp = bioq_takefirst(p->bqueue);
+ }
}
-/* Find the correct subdisk to send the bio to and build a bio to send. */
static int
-gv_plexbuffer(struct gv_plex *p, struct bio *bp, caddr_t addr, off_t boff, off_t bcount)
+gv_plex_offset(struct gv_plex *p, off_t boff, off_t bcount, off_t *real_off,
+ off_t *real_len, int *sdno, int growing)
{
- struct g_geom *gp;
struct gv_sd *s;
- struct bio *cbp, *pbp;
- int i, sdno;
- off_t len_left, real_len, real_off;
- off_t stripeend, stripeno, stripestart;
-
- if (p == NULL || LIST_EMPTY(&p->subdisks))
- return (ENXIO);
-
- s = NULL;
- gp = bp->bio_to->geom;
+ int i, sdcount;
+ off_t len_left, stripeend, stripeno, stripestart;
- /*
- * We only handle concatenated and striped plexes here. RAID5 plexes
- * are handled in build_raid5_request().
- */
switch (p->org) {
case GV_PLEX_CONCAT:
/*
* Find the subdisk where this request starts. The subdisks in
* this list must be ordered by plex_offset.
*/
+ i = 0;
LIST_FOREACH(s, &p->subdisks, in_plex) {
if (s->plex_offset <= boff &&
- s->plex_offset + s->size > boff)
+ s->plex_offset + s->size > boff) {
+ *sdno = i;
break;
+ }
+ i++;
}
- /* Subdisk not found. */
- if (s == NULL)
- return (ENXIO);
+ if (s == NULL || s->drive_sc == NULL)
+ return (GV_ERR_NOTFOUND);
/* Calculate corresponding offsets on disk. */
- real_off = boff - s->plex_offset;
- len_left = s->size - real_off;
- real_len = (bcount > len_left) ? len_left : bcount;
+ *real_off = boff - s->plex_offset;
+ len_left = s->size - (*real_off);
+ KASSERT(len_left >= 0, ("gv_plex_offset: len_left < 0"));
+ *real_len = (bcount > len_left) ? len_left : bcount;
break;
case GV_PLEX_STRIPED:
/* The number of the stripe where the request starts. */
stripeno = boff / p->stripesize;
+ KASSERT(stripeno >= 0, ("gv_plex_offset: stripeno < 0"));
- /* The number of the subdisk where the stripe resides. */
- sdno = stripeno % p->sdcount;
-
- /* Find the right subdisk. */
- i = 0;
- LIST_FOREACH(s, &p->subdisks, in_plex) {
- if (i == sdno)
- break;
- i++;
- }
+ /* Take growing subdisks into account when calculating. */
+ sdcount = gv_sdcount(p, (boff >= p->synced));
- /* Subdisk not found. */
- if (s == NULL)
- return (ENXIO);
+ if (!(boff + bcount <= p->synced) &&
+ (p->flags & GV_PLEX_GROWING) &&
+ !growing)
+ return (GV_ERR_ISBUSY);
+ *sdno = stripeno % sdcount;
- /* The offset of the stripe from the start of the subdisk. */
- stripestart = (stripeno / p->sdcount) *
+ KASSERT(sdno >= 0, ("gv_plex_offset: sdno < 0"));
+ stripestart = (stripeno / sdcount) *
p->stripesize;
-
- /* The offset at the end of the stripe. */
+ KASSERT(stripestart >= 0, ("gv_plex_offset: stripestart < 0"));
stripeend = stripestart + p->stripesize;
-
- /* The offset of the request on this subdisk. */
- real_off = boff - (stripeno * p->stripesize) +
+ *real_off = boff - (stripeno * p->stripesize) +
stripestart;
+ len_left = stripeend - *real_off;
+ KASSERT(len_left >= 0, ("gv_plex_offset: len_left < 0"));
- /* The length left in this stripe. */
- len_left = stripeend - real_off;
-
- real_len = (bcount <= len_left) ? bcount : len_left;
+ *real_len = (bcount <= len_left) ? bcount : len_left;
break;
default:
- return (EINVAL);
+ return (GV_ERR_PLEXORG);
+ }
+ return (0);
+}
+
+/*
+ * Prepare a normal plex request.
+ */
+static int
+gv_plex_normal_request(struct gv_plex *p, struct bio *bp, off_t boff,
+ off_t bcount, caddr_t addr)
+{
+ struct gv_sd *s;
+ struct bio *cbp;
+ off_t real_len, real_off;
+ int i, err, sdno;
+
+ s = NULL;
+ sdno = -1;
+ real_len = real_off = 0;
+
+ err = ENXIO;
+
+ if (p == NULL || LIST_EMPTY(&p->subdisks))
+ goto bad;
+
+ err = gv_plex_offset(p, boff, bcount, &real_off,
+ &real_len, &sdno, (bp->bio_pflags & GV_BIO_SYNCREQ));
+ /* If the request was blocked, put it into wait. */
+ if (err == GV_ERR_ISBUSY) {
+ bioq_disksort(p->rqueue, bp);
+ return (-1); /* "Fail", and delay request. */
+ }
+ if (err) {
+ err = ENXIO;
+ goto bad;
}
+ err = ENXIO;
+
+ /* Find the right subdisk. */
+ i = 0;
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ if (i == sdno)
+ break;
+ i++;
+ }
+
+ /* Subdisk not found. */
+ if (s == NULL || s->drive_sc == NULL)
+ goto bad;
/* Now check if we can handle the request on this subdisk. */
switch (s->state) {
case GV_SD_UP:
/* If the subdisk is up, just continue. */
break;
-
+ case GV_SD_DOWN:
+ if (bp->bio_cflags & GV_BIO_INTERNAL)
+ G_VINUM_DEBUG(0, "subdisk must be in the stale state in"
+ " order to perform administrative requests");
+ goto bad;
case GV_SD_STALE:
- if (!(bp->bio_cflags & GV_BIO_SYNCREQ))
- return (ENXIO);
+ if (!(bp->bio_cflags & GV_BIO_SYNCREQ)) {
+ G_VINUM_DEBUG(0, "subdisk stale, unable to perform "
+ "regular requests");
+ goto bad;
+ }
G_VINUM_DEBUG(1, "sd %s is initializing", s->name);
gv_set_sd_state(s, GV_SD_INITIALIZING, GV_SETSTATE_FORCE);
break;
-
case GV_SD_INITIALIZING:
if (bp->bio_cmd == BIO_READ)
- return (ENXIO);
+ goto bad;
break;
-
default:
/* All other subdisk states mean it's not accessible. */
- return (ENXIO);
+ goto bad;
}
/* Clone the bio and adjust the offsets and sizes. */
cbp = g_clone_bio(bp);
- if (cbp == NULL)
- return (ENOMEM);
- cbp->bio_offset = real_off;
+ if (cbp == NULL) {
+ err = ENOMEM;
+ goto bad;
+ }
+ cbp->bio_offset = real_off + s->drive_offset;
cbp->bio_length = real_len;
cbp->bio_data = addr;
- cbp->bio_done = g_std_done;
- cbp->bio_caller2 = s->consumer;
- if ((bp->bio_cflags & GV_BIO_SYNCREQ)) {
+ cbp->bio_done = gv_done;
+ cbp->bio_caller1 = s;
+ if ((bp->bio_cflags & GV_BIO_SYNCREQ))
cbp->bio_cflags |= GV_BIO_SYNCREQ;
- cbp->bio_done = gv_plex_done;
- }
- if (bp->bio_driver1 == NULL) {
- bp->bio_driver1 = cbp;
- } else {
- pbp = bp->bio_driver1;
- while (pbp->bio_caller1 != NULL)
- pbp = pbp->bio_caller1;
- pbp->bio_caller1 = cbp;
+ /* Store the sub-requests now and let others issue them. */
+ bioq_insert_tail(p->bqueue, cbp);
+ return (real_len);
+bad:
+ G_VINUM_LOGREQ(0, bp, "plex request failed.");
+ /* Building the sub-request failed. If internal BIO, do not deliver. */
+ if (bp->bio_cflags & GV_BIO_INTERNAL) {
+ if (bp->bio_cflags & GV_BIO_MALLOC)
+ g_free(bp->bio_data);
+ g_destroy_bio(bp);
+ p->flags &= ~(GV_PLEX_SYNCING | GV_PLEX_REBUILDING |
+ GV_PLEX_GROWING);
+ return (-1);
}
-
- return (0);
+ g_io_deliver(bp, err);
+ return (-1);
}
-static void
-gv_plex_start(struct bio *bp)
+/*
+ * Handle a completed request to a striped or concatenated plex.
+ */
+void
+gv_plex_normal_done(struct gv_plex *p, struct bio *bp)
{
- struct gv_plex *p;
-
- switch(bp->bio_cmd) {
- case BIO_READ:
- case BIO_WRITE:
- case BIO_DELETE:
- break;
- case BIO_GETATTR:
- default:
- g_io_deliver(bp, EOPNOTSUPP);
- return;
- }
+ struct bio *pbp;
- /*
- * We cannot handle this request if too many of our subdisks are
- * inaccessible.
- */
- p = bp->bio_to->geom->softc;
- if ((p->state < GV_PLEX_DEGRADED) &&
- !(bp->bio_cflags & GV_BIO_SYNCREQ)) {
- g_io_deliver(bp, ENXIO);
- return;
+ pbp = bp->bio_parent;
+ if (pbp->bio_error == 0)
+ pbp->bio_error = bp->bio_error;
+ g_destroy_bio(bp);
+ pbp->bio_inbed++;
+ if (pbp->bio_children == pbp->bio_inbed) {
+ /* Just set it to length since multiple plexes will
+ * screw things up. */
+ pbp->bio_completed = pbp->bio_length;
+ if (pbp->bio_cflags & GV_BIO_SYNCREQ)
+ gv_sync_complete(p, pbp);
+ else if (pbp->bio_pflags & GV_BIO_SYNCREQ)
+ gv_grow_complete(p, pbp);
+ else
+ g_io_deliver(pbp, pbp->bio_error);
}
-
- mtx_lock(&p->bqueue_mtx);
- bioq_disksort(p->bqueue, bp);
- wakeup(p);
- mtx_unlock(&p->bqueue_mtx);
}
-static void
-gv_plex_worker(void *arg)
+/*
+ * Handle a completed request to a RAID-5 plex.
+ */
+void
+gv_plex_raid5_done(struct gv_plex *p, struct bio *bp)
{
- struct bio *bp;
- struct gv_plex *p;
- struct gv_sd *s;
+ struct gv_softc *sc;
+ struct bio *cbp, *pbp;
+ struct gv_bioq *bq, *bq2;
+ struct gv_raid5_packet *wp;
+ off_t completed;
+ int i;
- p = arg;
- KASSERT(p != NULL, ("NULL p"));
+ completed = 0;
+ sc = p->vinumconf;
+ wp = bp->bio_caller2;
- mtx_lock(&p->bqueue_mtx);
- for (;;) {
- /* We were signaled to exit. */
- if (p->flags & GV_PLEX_THREAD_DIE)
+ switch (bp->bio_parent->bio_cmd) {
+ case BIO_READ:
+ if (wp == NULL) {
+ completed = bp->bio_completed;
break;
+ }
- /* Take the first BIO from our queue. */
- bp = bioq_takefirst(p->bqueue);
- if (bp == NULL) {
- msleep(p, &p->bqueue_mtx, PRIBIO, "-", hz/10);
- continue;
+ TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
+ if (bq->bp != bp)
+ continue;
+ TAILQ_REMOVE(&wp->bits, bq, queue);
+ g_free(bq);
+ for (i = 0; i < wp->length; i++)
+ wp->data[i] ^= bp->bio_data[i];
+ break;
}
- mtx_unlock(&p->bqueue_mtx);
-
- /* A completed request. */
- if (bp->bio_cflags & GV_BIO_DONE) {
- if (bp->bio_cflags & GV_BIO_SYNCREQ ||
- bp->bio_cflags & GV_BIO_REBUILD) {
- s = bp->bio_to->private;
- if (bp->bio_error == 0)
- s->initialized += bp->bio_length;
- if (s->initialized >= s->size) {
- g_topology_lock();
- gv_set_sd_state(s, GV_SD_UP,
- GV_SETSTATE_CONFIG);
- g_topology_unlock();
- s->initialized = 0;
+ if (TAILQ_EMPTY(&wp->bits)) {
+ completed = wp->length;
+ if (wp->lockbase != -1) {
+ TAILQ_REMOVE(&p->packets, wp, list);
+ /* Bring the waiting bios back into the game. */
+ pbp = bioq_takefirst(p->wqueue);
+ while (pbp != NULL) {
+ mtx_lock(&sc->queue_mtx);
+ bioq_disksort(sc->bqueue, pbp);
+ mtx_unlock(&sc->queue_mtx);
+ pbp = bioq_takefirst(p->wqueue);
}
}
+ g_free(wp);
+ }
- if (bp->bio_cflags & GV_BIO_SYNCREQ)
- g_std_done(bp);
- else
- gv_plex_completed_request(p, bp);
- /*
- * A sub-request that was hold back because it interfered with
- * another sub-request.
- */
- } else if (bp->bio_cflags & GV_BIO_ONHOLD) {
- /* Is it still locked out? */
- if (gv_stripe_active(p, bp)) {
- /* Park the bio on the waiting queue. */
- mtx_lock(&p->bqueue_mtx);
- bioq_disksort(p->wqueue, bp);
- mtx_unlock(&p->bqueue_mtx);
- } else {
- bp->bio_cflags &= ~GV_BIO_ONHOLD;
- g_io_request(bp, bp->bio_caller2);
- }
+ break;
- /* A normal request to this plex. */
- } else
- gv_plex_normal_request(p, bp);
+ case BIO_WRITE:
+ /* XXX can this ever happen? */
+ if (wp == NULL) {
+ completed = bp->bio_completed;
+ break;
+ }
- mtx_lock(&p->bqueue_mtx);
- }
- mtx_unlock(&p->bqueue_mtx);
- p->flags |= GV_PLEX_THREAD_DEAD;
- wakeup(p);
+ /* Check if we need to handle parity data. */
+ TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
+ if (bq->bp != bp)
+ continue;
+ TAILQ_REMOVE(&wp->bits, bq, queue);
+ g_free(bq);
+ cbp = wp->parity;
+ if (cbp != NULL) {
+ for (i = 0; i < wp->length; i++)
+ cbp->bio_data[i] ^= bp->bio_data[i];
+ }
+ break;
+ }
- kproc_exit(ENXIO);
-}
+ /* Handle parity data. */
+ if (TAILQ_EMPTY(&wp->bits)) {
+ if (bp->bio_parent->bio_cflags & GV_BIO_CHECK)
+ i = gv_check_parity(p, bp, wp);
+ else
+ i = gv_normal_parity(p, bp, wp);
-static int
-gv_normal_parity(struct gv_plex *p, struct bio *bp, struct gv_raid5_packet *wp)
-{
- struct bio *cbp, *pbp;
- int finished, i;
+ /* All of our sub-requests have finished. */
+ if (i) {
+ completed = wp->length;
+ TAILQ_REMOVE(&p->packets, wp, list);
+ /* Bring the waiting bios back into the game. */
+ pbp = bioq_takefirst(p->wqueue);
+ while (pbp != NULL) {
+ mtx_lock(&sc->queue_mtx);
+ bioq_disksort(sc->bqueue, pbp);
+ mtx_unlock(&sc->queue_mtx);
+ pbp = bioq_takefirst(p->wqueue);
+ }
+ g_free(wp);
+ }
+ }
- finished = 1;
+ break;
+ }
- if (wp->waiting != NULL) {
- pbp = wp->waiting;
- wp->waiting = NULL;
- cbp = wp->parity;
- for (i = 0; i < wp->length; i++)
- cbp->bio_data[i] ^= pbp->bio_data[i];
- g_io_request(pbp, pbp->bio_caller2);
- finished = 0;
+ pbp = bp->bio_parent;
+ if (pbp->bio_error == 0)
+ pbp->bio_error = bp->bio_error;
+ pbp->bio_completed += completed;
- } else if (wp->parity != NULL) {
- cbp = wp->parity;
- wp->parity = NULL;
- g_io_request(cbp, cbp->bio_caller2);
- finished = 0;
+ /* When the original request is finished, we deliver it. */
+ pbp->bio_inbed++;
+ if (pbp->bio_inbed == pbp->bio_children) {
+ /* Hand it over for checking or delivery. */
+ if (pbp->bio_cmd == BIO_WRITE &&
+ (pbp->bio_cflags & GV_BIO_CHECK)) {
+ gv_parity_complete(p, pbp);
+ } else if (pbp->bio_cmd == BIO_WRITE &&
+ (pbp->bio_cflags & GV_BIO_REBUILD)) {
+ gv_rebuild_complete(p, pbp);
+ } else if (pbp->bio_cflags & GV_BIO_INIT) {
+ gv_init_complete(p, pbp);
+ } else if (pbp->bio_cflags & GV_BIO_SYNCREQ) {
+ gv_sync_complete(p, pbp);
+ } else if (pbp->bio_pflags & GV_BIO_SYNCREQ) {
+ gv_grow_complete(p, pbp);
+ } else {
+ g_io_deliver(pbp, pbp->bio_error);
+ }
}
- return (finished);
+ /* Clean up what we allocated. */
+ if (bp->bio_cflags & GV_BIO_MALLOC)
+ g_free(bp->bio_data);
+ g_destroy_bio(bp);
}
static int
gv_check_parity(struct gv_plex *p, struct bio *bp, struct gv_raid5_packet *wp)
{
struct bio *pbp;
+ struct gv_sd *s;
int err, finished, i;
err = 0;
@@ -374,7 +463,8 @@ gv_check_parity(struct gv_plex *p, struct bio *bp, struct gv_raid5_packet *wp)
if (wp->waiting != NULL) {
pbp = wp->waiting;
wp->waiting = NULL;
- g_io_request(pbp, pbp->bio_caller2);
+ s = pbp->bio_caller1;
+ g_io_request(pbp, s->drive_sc->consumer);
finished = 0;
} else if (wp->parity != NULL) {
@@ -395,7 +485,8 @@ gv_check_parity(struct gv_plex *p, struct bio *bp, struct gv_raid5_packet *wp)
/* ... but we rebuild it. */
if (bp->bio_parent->bio_cflags & GV_BIO_PARITY) {
- g_io_request(pbp, pbp->bio_caller2);
+ s = pbp->bio_caller1;
+ g_io_request(pbp, s->drive_sc->consumer);
finished = 0;
}
}
@@ -414,454 +505,542 @@ gv_check_parity(struct gv_plex *p, struct bio *bp, struct gv_raid5_packet *wp)
return (finished);
}
-void
-gv_plex_completed_request(struct gv_plex *p, struct bio *bp)
+static int
+gv_normal_parity(struct gv_plex *p, struct bio *bp, struct gv_raid5_packet *wp)
{
struct bio *cbp, *pbp;
- struct gv_bioq *bq, *bq2;
- struct gv_raid5_packet *wp;
- int i;
+ struct gv_sd *s;
+ int finished, i;
- wp = bp->bio_driver1;
+ finished = 1;
- switch (bp->bio_parent->bio_cmd) {
- case BIO_READ:
- if (wp == NULL)
- break;
+ if (wp->waiting != NULL) {
+ pbp = wp->waiting;
+ wp->waiting = NULL;
+ cbp = wp->parity;
+ for (i = 0; i < wp->length; i++)
+ cbp->bio_data[i] ^= pbp->bio_data[i];
+ s = pbp->bio_caller1;
+ g_io_request(pbp, s->drive_sc->consumer);
+ finished = 0;
- TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
- if (bq->bp == bp) {
- TAILQ_REMOVE(&wp->bits, bq, queue);
- g_free(bq);
- for (i = 0; i < wp->length; i++)
- wp->data[i] ^= bp->bio_data[i];
- break;
- }
- }
- if (TAILQ_EMPTY(&wp->bits)) {
- bp->bio_parent->bio_completed += wp->length;
- if (wp->lockbase != -1) {
- TAILQ_REMOVE(&p->packets, wp, list);
- /* Bring the waiting bios back into the game. */
- mtx_lock(&p->bqueue_mtx);
- pbp = bioq_takefirst(p->wqueue);
- while (pbp != NULL) {
- bioq_disksort(p->bqueue, pbp);
- pbp = bioq_takefirst(p->wqueue);
- }
- mtx_unlock(&p->bqueue_mtx);
- }
- g_free(wp);
- }
+ } else if (wp->parity != NULL) {
+ cbp = wp->parity;
+ wp->parity = NULL;
+ s = cbp->bio_caller1;
+ g_io_request(cbp, s->drive_sc->consumer);
+ finished = 0;
+ }
- break;
+ return (finished);
+}
- case BIO_WRITE:
- if (wp == NULL)
- break;
+/* Flush the queue with delayed requests. */
+static void
+gv_plex_flush(struct gv_plex *p)
+{
+ struct gv_softc *sc;
+ struct bio *bp;
- /* Check if we need to handle parity data. */
- TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
- if (bq->bp == bp) {
- TAILQ_REMOVE(&wp->bits, bq, queue);
- g_free(bq);
- cbp = wp->parity;
- if (cbp != NULL) {
- for (i = 0; i < wp->length; i++)
- cbp->bio_data[i] ^=
- bp->bio_data[i];
- }
- break;
- }
- }
+ sc = p->vinumconf;
+ bp = bioq_takefirst(p->rqueue);
+ while (bp != NULL) {
+ gv_plex_start(p, bp);
+ bp = bioq_takefirst(p->rqueue);
+ }
+}
- /* Handle parity data. */
- if (TAILQ_EMPTY(&wp->bits)) {
- if (bp->bio_parent->bio_cflags & GV_BIO_CHECK)
- i = gv_check_parity(p, bp, wp);
- else
- i = gv_normal_parity(p, bp, wp);
+int
+gv_sync_request(struct gv_plex *from, struct gv_plex *to, off_t offset,
+ off_t length, int type, caddr_t data)
+{
+ struct gv_softc *sc;
+ struct bio *bp;
- /* All of our sub-requests have finished. */
- if (i) {
- bp->bio_parent->bio_completed += wp->length;
- TAILQ_REMOVE(&p->packets, wp, list);
- /* Bring the waiting bios back into the game. */
- mtx_lock(&p->bqueue_mtx);
- pbp = bioq_takefirst(p->wqueue);
- while (pbp != NULL) {
- bioq_disksort(p->bqueue, pbp);
- pbp = bioq_takefirst(p->wqueue);
- }
- mtx_unlock(&p->bqueue_mtx);
- g_free(wp);
- }
- }
+ KASSERT(from != NULL, ("NULL from"));
+ KASSERT(to != NULL, ("NULL to"));
+ sc = from->vinumconf;
+ KASSERT(sc != NULL, ("NULL sc"));
- break;
+ bp = g_new_bio();
+ if (bp == NULL) {
+ G_VINUM_DEBUG(0, "sync from '%s' failed at offset "
+ " %jd; out of memory", from->name, offset);
+ return (ENOMEM);
}
+ bp->bio_length = length;
+ bp->bio_done = gv_done;
+ bp->bio_cflags |= GV_BIO_SYNCREQ;
+ bp->bio_offset = offset;
+ bp->bio_caller1 = from;
+ bp->bio_caller2 = to;
+ bp->bio_cmd = type;
+ if (data == NULL)
+ data = g_malloc(length, M_WAITOK);
+ bp->bio_cflags |= GV_BIO_MALLOC; /* Free on the next run. */
+ bp->bio_data = data;
+
+ /* Send down next. */
+ mtx_lock(&sc->queue_mtx);
+ bioq_disksort(sc->bqueue, bp);
+ mtx_unlock(&sc->queue_mtx);
+ //gv_plex_start(from, bp);
+ return (0);
+}
- pbp = bp->bio_parent;
- if (pbp->bio_error == 0)
- pbp->bio_error = bp->bio_error;
+/*
+ * Handle a finished plex sync bio.
+ */
+int
+gv_sync_complete(struct gv_plex *to, struct bio *bp)
+{
+ struct gv_plex *from, *p;
+ struct gv_sd *s;
+ struct gv_volume *v;
+ struct gv_softc *sc;
+ off_t offset;
+ int err;
- /* When the original request is finished, we deliver it. */
- pbp->bio_inbed++;
- if (pbp->bio_inbed == pbp->bio_children)
- g_io_deliver(pbp, pbp->bio_error);
+ g_topology_assert_not();
- /* Clean up what we allocated. */
- if (bp->bio_cflags & GV_BIO_MALLOC)
- g_free(bp->bio_data);
+ err = 0;
+ KASSERT(to != NULL, ("NULL to"));
+ KASSERT(bp != NULL, ("NULL bp"));
+ from = bp->bio_caller2;
+ KASSERT(from != NULL, ("NULL from"));
+ v = to->vol_sc;
+ KASSERT(v != NULL, ("NULL v"));
+ sc = v->vinumconf;
+ KASSERT(sc != NULL, ("NULL sc"));
+
+ /* If it was a read, write it. */
+ if (bp->bio_cmd == BIO_READ) {
+ err = gv_sync_request(from, to, bp->bio_offset, bp->bio_length,
+ BIO_WRITE, bp->bio_data);
+ /* If it was a write, read the next one. */
+ } else if (bp->bio_cmd == BIO_WRITE) {
+ if (bp->bio_cflags & GV_BIO_MALLOC)
+ g_free(bp->bio_data);
+ to->synced += bp->bio_length;
+ /* If we're finished, clean up. */
+ if (bp->bio_offset + bp->bio_length >= from->size) {
+ G_VINUM_DEBUG(1, "syncing of %s from %s completed",
+ to->name, from->name);
+ /* Update our state. */
+ LIST_FOREACH(s, &to->subdisks, in_plex)
+ gv_set_sd_state(s, GV_SD_UP, 0);
+ gv_update_plex_state(to);
+ to->flags &= ~GV_PLEX_SYNCING;
+ to->synced = 0;
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
+ } else {
+ offset = bp->bio_offset + bp->bio_length;
+ err = gv_sync_request(from, to, offset,
+ MIN(bp->bio_length, from->size - offset),
+ BIO_READ, NULL);
+ }
+ }
g_destroy_bio(bp);
+ /* Clean up if there was an error. */
+ if (err) {
+ to->flags &= ~GV_PLEX_SYNCING;
+ G_VINUM_DEBUG(0, "error syncing plexes: error code %d", err);
+ }
+
+ /* Check if all plexes are synced, and lower refcounts. */
+ g_topology_lock();
+ LIST_FOREACH(p, &v->plexes, in_volume) {
+ if (p->flags & GV_PLEX_SYNCING) {
+ g_topology_unlock();
+ return (-1);
+ }
+ }
+ /* If we came here, all plexes are synced, and we're free. */
+ gv_access(v->provider, -1, -1, 0);
+ g_topology_unlock();
+ G_VINUM_DEBUG(1, "plex sync completed");
+ gv_volume_flush(v);
+ return (0);
}
-void
-gv_plex_normal_request(struct gv_plex *p, struct bio *bp)
+/*
+ * Create a new bio struct for the next grow request.
+ */
+int
+gv_grow_request(struct gv_plex *p, off_t offset, off_t length, int type,
+ caddr_t data)
{
- struct bio *cbp, *pbp;
- struct gv_bioq *bq, *bq2;
- struct gv_raid5_packet *wp, *wp2;
- caddr_t addr;
- off_t bcount, boff;
- int err;
-
- bcount = bp->bio_length;
- addr = bp->bio_data;
- boff = bp->bio_offset;
+ struct gv_softc *sc;
+ struct bio *bp;
- /* Walk over the whole length of the request, we might split it up. */
- while (bcount > 0) {
- wp = NULL;
+ KASSERT(p != NULL, ("gv_grow_request: NULL p"));
+ sc = p->vinumconf;
+ KASSERT(sc != NULL, ("gv_grow_request: NULL sc"));
- /*
- * RAID5 plexes need special treatment, as a single write
- * request involves several read/write sub-requests.
- */
- if (p->org == GV_PLEX_RAID5) {
- wp = g_malloc(sizeof(*wp), M_WAITOK | M_ZERO);
- wp->bio = bp;
- TAILQ_INIT(&wp->bits);
-
- if (bp->bio_cflags & GV_BIO_REBUILD)
- err = gv_rebuild_raid5(p, wp, bp, addr,
- boff, bcount);
- else if (bp->bio_cflags & GV_BIO_CHECK)
- err = gv_check_raid5(p, wp, bp, addr,
- boff, bcount);
- else
- err = gv_build_raid5_req(p, wp, bp, addr,
- boff, bcount);
-
- /*
- * Building the sub-request failed, we probably need to
- * clean up a lot.
- */
- if (err) {
- G_VINUM_LOGREQ(0, bp, "plex request failed.");
- TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
- TAILQ_REMOVE(&wp->bits, bq, queue);
- g_free(bq);
- }
- if (wp->waiting != NULL) {
- if (wp->waiting->bio_cflags &
- GV_BIO_MALLOC)
- g_free(wp->waiting->bio_data);
- g_destroy_bio(wp->waiting);
- }
- if (wp->parity != NULL) {
- if (wp->parity->bio_cflags &
- GV_BIO_MALLOC)
- g_free(wp->parity->bio_data);
- g_destroy_bio(wp->parity);
- }
- g_free(wp);
-
- TAILQ_FOREACH_SAFE(wp, &p->packets, list, wp2) {
- if (wp->bio == bp) {
- TAILQ_REMOVE(&p->packets, wp,
- list);
- TAILQ_FOREACH_SAFE(bq,
- &wp->bits, queue, bq2) {
- TAILQ_REMOVE(&wp->bits,
- bq, queue);
- g_free(bq);
- }
- g_free(wp);
- }
- }
+ bp = g_new_bio();
+ if (bp == NULL) {
+ G_VINUM_DEBUG(0, "grow of %s failed creating bio: "
+ "out of memory", p->name);
+ return (ENOMEM);
+ }
- cbp = bp->bio_driver1;
- while (cbp != NULL) {
- pbp = cbp->bio_caller1;
- if (cbp->bio_cflags & GV_BIO_MALLOC)
- g_free(cbp->bio_data);
- g_destroy_bio(cbp);
- cbp = pbp;
- }
+ bp->bio_cmd = type;
+ bp->bio_done = gv_done;
+ bp->bio_error = 0;
+ bp->bio_caller1 = p;
+ bp->bio_offset = offset;
+ bp->bio_length = length;
+ bp->bio_pflags |= GV_BIO_SYNCREQ; /* XXX: misuse of pflags AND syncreq.*/
+ if (data == NULL)
+ data = g_malloc(length, M_WAITOK);
+ bp->bio_cflags |= GV_BIO_MALLOC;
+ bp->bio_data = data;
+
+ mtx_lock(&sc->queue_mtx);
+ bioq_disksort(sc->bqueue, bp);
+ mtx_unlock(&sc->queue_mtx);
+ //gv_plex_start(p, bp);
+ return (0);
+}
- g_io_deliver(bp, err);
- return;
- }
-
- if (TAILQ_EMPTY(&wp->bits))
- g_free(wp);
- else if (wp->lockbase != -1)
- TAILQ_INSERT_TAIL(&p->packets, wp, list);
+/*
+ * Finish handling of a bio to a growing plex.
+ */
+void
+gv_grow_complete(struct gv_plex *p, struct bio *bp)
+{
+ struct gv_softc *sc;
+ struct gv_sd *s;
+ struct gv_volume *v;
+ off_t origsize, offset;
+ int sdcount, err;
+
+ v = p->vol_sc;
+ KASSERT(v != NULL, ("gv_grow_complete: NULL v"));
+ sc = v->vinumconf;
+ KASSERT(sc != NULL, ("gv_grow_complete: NULL sc"));
+ err = 0;
- /*
- * Requests to concatenated and striped plexes go straight
- * through.
- */
- } else {
- err = gv_plexbuffer(p, bp, addr, boff, bcount);
-
- /* Building the sub-request failed. */
- if (err) {
- G_VINUM_LOGREQ(0, bp, "plex request failed.");
- cbp = bp->bio_driver1;
- while (cbp != NULL) {
- pbp = cbp->bio_caller1;
- g_destroy_bio(cbp);
- cbp = pbp;
- }
- g_io_deliver(bp, err);
- return;
+ /* If it was a read, write it. */
+ if (bp->bio_cmd == BIO_READ) {
+ p->synced += bp->bio_length;
+ err = gv_grow_request(p, bp->bio_offset, bp->bio_length,
+ BIO_WRITE, bp->bio_data);
+ /* If it was a write, read next. */
+ } else if (bp->bio_cmd == BIO_WRITE) {
+ if (bp->bio_cflags & GV_BIO_MALLOC)
+ g_free(bp->bio_data);
+
+ /* Find the real size of the plex. */
+ sdcount = gv_sdcount(p, 1);
+ s = LIST_FIRST(&p->subdisks);
+ KASSERT(s != NULL, ("NULL s"));
+ origsize = (s->size * (sdcount - 1));
+ if (bp->bio_offset + bp->bio_length >= origsize) {
+ G_VINUM_DEBUG(1, "growing of %s completed", p->name);
+ p->flags &= ~GV_PLEX_GROWING;
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ s->flags &= ~GV_SD_GROW;
+ gv_set_sd_state(s, GV_SD_UP, 0);
}
+ p->size = gv_plex_size(p);
+ gv_update_vol_size(v, gv_vol_size(v));
+ gv_set_plex_state(p, GV_PLEX_UP, 0);
+ g_topology_lock();
+ gv_access(v->provider, -1, -1, 0);
+ g_topology_unlock();
+ p->synced = 0;
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
+ /* Issue delayed requests. */
+ gv_plex_flush(p);
+ } else {
+ offset = bp->bio_offset + bp->bio_length;
+ err = gv_grow_request(p, offset,
+ MIN(bp->bio_length, origsize - offset),
+ BIO_READ, NULL);
}
-
- /* Abuse bio_caller1 as linked list. */
- pbp = bp->bio_driver1;
- while (pbp->bio_caller1 != NULL)
- pbp = pbp->bio_caller1;
- bcount -= pbp->bio_length;
- addr += pbp->bio_length;
- boff += pbp->bio_length;
- }
-
- /* Fire off all sub-requests. */
- pbp = bp->bio_driver1;
- while (pbp != NULL) {
- /*
- * RAID5 sub-requests need to come in correct order, otherwise
- * we trip over the parity, as it might be overwritten by
- * another sub-request.
- */
- if (pbp->bio_driver1 != NULL &&
- gv_stripe_active(p, pbp)) {
- /* Park the bio on the waiting queue. */
- pbp->bio_cflags |= GV_BIO_ONHOLD;
- mtx_lock(&p->bqueue_mtx);
- bioq_disksort(p->wqueue, pbp);
- mtx_unlock(&p->bqueue_mtx);
- } else
- g_io_request(pbp, pbp->bio_caller2);
- pbp = pbp->bio_caller1;
+ }
+ g_destroy_bio(bp);
+
+ if (err) {
+ p->flags &= ~GV_PLEX_GROWING;
+ G_VINUM_DEBUG(0, "error growing plex: error code %d", err);
}
}
-static int
-gv_plex_access(struct g_provider *pp, int dr, int dw, int de)
+
+/*
+ * Create an initialization BIO and send it off to the consumer. Assume that
+ * we're given initialization data as parameter.
+ */
+void
+gv_init_request(struct gv_sd *s, off_t start, caddr_t data, off_t length)
+{
+ struct gv_drive *d;
+ struct g_consumer *cp;
+ struct bio *bp, *cbp;
+
+ KASSERT(s != NULL, ("gv_init_request: NULL s"));
+ d = s->drive_sc;
+ KASSERT(d != NULL, ("gv_init_request: NULL d"));
+ cp = d->consumer;
+ KASSERT(cp != NULL, ("gv_init_request: NULL cp"));
+
+ bp = g_new_bio();
+ if (bp == NULL) {
+ G_VINUM_DEBUG(0, "subdisk '%s' init: write failed at offset %jd"
+ " (drive offset %jd); out of memory", s->name,
+ (intmax_t)s->initialized, (intmax_t)start);
+ return; /* XXX: Error codes. */
+ }
+ bp->bio_cmd = BIO_WRITE;
+ bp->bio_data = data;
+ bp->bio_done = gv_done;
+ bp->bio_error = 0;
+ bp->bio_length = length;
+ bp->bio_cflags |= GV_BIO_INIT;
+ bp->bio_offset = start;
+ bp->bio_caller1 = s;
+
+ /* Then ofcourse, we have to clone it. */
+ cbp = g_clone_bio(bp);
+ if (cbp == NULL) {
+ G_VINUM_DEBUG(0, "subdisk '%s' init: write failed at offset %jd"
+ " (drive offset %jd); out of memory", s->name,
+ (intmax_t)s->initialized, (intmax_t)start);
+ return; /* XXX: Error codes. */
+ }
+ cbp->bio_done = gv_done;
+ cbp->bio_caller1 = s;
+ /* Send it off to the consumer. */
+ g_io_request(cbp, cp);
+}
+
+/*
+ * Handle a finished initialization BIO.
+ */
+void
+gv_init_complete(struct gv_plex *p, struct bio *bp)
{
- struct gv_plex *p;
- struct g_geom *gp;
- struct g_consumer *cp, *cp2;
+ struct gv_softc *sc;
+ struct gv_drive *d;
+ struct g_consumer *cp;
+ struct gv_sd *s;
+ off_t start, length;
+ caddr_t data;
int error;
- gp = pp->geom;
- p = gp->softc;
- KASSERT(p != NULL, ("NULL p"));
+ s = bp->bio_caller1;
+ start = bp->bio_offset;
+ length = bp->bio_length;
+ error = bp->bio_error;
+ data = bp->bio_data;
- if (p->org == GV_PLEX_RAID5) {
- if (dw > 0 && dr == 0)
- dr = 1;
- else if (dw < 0 && dr == 0)
- dr = -1;
- }
+ KASSERT(s != NULL, ("gv_init_complete: NULL s"));
+ d = s->drive_sc;
+ KASSERT(d != NULL, ("gv_init_complete: NULL d"));
+ cp = d->consumer;
+ KASSERT(cp != NULL, ("gv_init_complete: NULL cp"));
+ sc = p->vinumconf;
+ KASSERT(sc != NULL, ("gv_init_complete: NULL sc"));
+
+ g_destroy_bio(bp);
- LIST_FOREACH(cp, &gp->consumer, consumer) {
- error = g_access(cp, dr, dw, de);
+ /*
+ * First we need to find out if it was okay, and abort if it's not.
+ * Then we need to free previous buffers, find out the correct subdisk,
+ * as well as getting the correct starting point and length of the BIO.
+ */
+ if (start >= s->drive_offset + s->size) {
+ /* Free the data we initialized. */
+ if (data != NULL)
+ g_free(data);
+ g_topology_assert_not();
+ g_topology_lock();
+ g_access(cp, 0, -1, 0);
+ g_topology_unlock();
if (error) {
- LIST_FOREACH(cp2, &gp->consumer, consumer) {
- if (cp == cp2)
- break;
- g_access(cp2, -dr, -dw, -de);
- }
- return (error);
+ gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE |
+ GV_SETSTATE_CONFIG);
+ } else {
+ gv_set_sd_state(s, GV_SD_UP, GV_SETSTATE_CONFIG);
+ s->initialized = 0;
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
+ G_VINUM_DEBUG(1, "subdisk '%s' init: finished "
+ "successfully", s->name);
}
+ return;
}
- return (0);
+ s->initialized += length;
+ start += length;
+ gv_init_request(s, start, data, length);
}
-static struct g_geom *
-gv_plex_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
+/*
+ * Create a new bio struct for the next parity rebuild. Used both by internal
+ * rebuild of degraded plexes as well as user initiated rebuilds/checks.
+ */
+void
+gv_parity_request(struct gv_plex *p, int flags, off_t offset)
{
- struct g_geom *gp;
- struct g_consumer *cp, *cp2;
- struct g_provider *pp2;
- struct gv_plex *p;
- struct gv_sd *s;
struct gv_softc *sc;
- int error;
-
- g_trace(G_T_TOPOLOGY, "gv_plex_taste(%s, %s)", mp->name, pp->name);
- g_topology_assert();
-
- /* We only want to attach to subdisks. */
- if (strcmp(pp->geom->class->name, "VINUMDRIVE"))
- return (NULL);
-
- /* Find the VINUM class and its associated geom. */
- gp = find_vinum_geom();
- if (gp == NULL)
- return (NULL);
- sc = gp->softc;
- KASSERT(sc != NULL, ("gv_plex_taste: NULL sc"));
+ struct bio *bp;
- /* Find out which subdisk the offered provider corresponds to. */
- s = pp->private;
- KASSERT(s != NULL, ("gv_plex_taste: NULL s"));
+ KASSERT(p != NULL, ("gv_parity_request: NULL p"));
+ sc = p->vinumconf;
+ KASSERT(sc != NULL, ("gv_parity_request: NULL sc"));
- /* Now find the correct plex where this subdisk belongs to. */
- p = gv_find_plex(sc, s->plex);
- if (p == NULL) {
- G_VINUM_DEBUG(0, "%s: NULL p for '%s'", __func__, s->name);
- return (NULL);
+ bp = g_new_bio();
+ if (bp == NULL) {
+ G_VINUM_DEBUG(0, "rebuild of %s failed creating bio: "
+ "out of memory", p->name);
+ return;
}
+ bp->bio_cmd = BIO_WRITE;
+ bp->bio_done = gv_done;
+ bp->bio_error = 0;
+ bp->bio_length = p->stripesize;
+ bp->bio_caller1 = p;
+
/*
- * Add this subdisk to this plex. Since we trust the on-disk
- * configuration, we don't check the given value (should we?).
- * XXX: shouldn't be done here
+ * Check if it's a rebuild of a degraded plex or a user request of
+ * parity rebuild.
*/
- gv_sd_to_plex(p, s, 0);
+ if (flags & GV_BIO_REBUILD)
+ bp->bio_data = g_malloc(GV_DFLT_SYNCSIZE, M_WAITOK);
+ else if (flags & GV_BIO_CHECK)
+ bp->bio_data = g_malloc(p->stripesize, M_WAITOK | M_ZERO);
+ else {
+ G_VINUM_DEBUG(0, "invalid flags given in rebuild");
+ return;
+ }
- /* Now check if there's already a geom for this plex. */
- gp = p->geom;
+ bp->bio_cflags = flags;
+ bp->bio_cflags |= GV_BIO_MALLOC;
- /* Yes, there is already a geom, so we just add the consumer. */
- if (gp != NULL) {
- cp2 = LIST_FIRST(&gp->consumer);
- /* Need to attach a new consumer to this subdisk. */
- cp = g_new_consumer(gp);
- error = g_attach(cp, pp);
- if (error) {
- G_VINUM_DEBUG(0, "unable to attach consumer to %s",
- pp->name);
- g_destroy_consumer(cp);
- return (NULL);
- }
- /* Adjust the access counts of the new consumer. */
- if ((cp2 != NULL) && (cp2->acr || cp2->acw || cp2->ace)) {
- error = g_access(cp, cp2->acr, cp2->acw, cp2->ace);
- if (error) {
- G_VINUM_DEBUG(0, "unable to set access counts"
- " for consumer on %s", pp->name);
- g_detach(cp);
- g_destroy_consumer(cp);
- return (NULL);
- }
- }
- s->consumer = cp;
+ /* We still have more parity to build. */
+ bp->bio_offset = offset;
+ mtx_lock(&sc->queue_mtx);
+ bioq_disksort(sc->bqueue, bp);
+ mtx_unlock(&sc->queue_mtx);
+ //gv_plex_start(p, bp); /* Send it down to the plex. */
+}
- /* Adjust the size of the providers this plex has. */
- LIST_FOREACH(pp2, &gp->provider, provider)
- pp2->mediasize = p->size;
+/*
+ * Handle a finished parity write.
+ */
+void
+gv_parity_complete(struct gv_plex *p, struct bio *bp)
+{
+ struct gv_softc *sc;
+ int error, flags;
- /* Update the size of the volume this plex is attached to. */
- if (p->vol_sc != NULL)
- gv_update_vol_size(p->vol_sc, p->size);
+ error = bp->bio_error;
+ flags = bp->bio_cflags;
+ flags &= ~GV_BIO_MALLOC;
- /*
- * If necessary, create bio queues, queue mutex and a worker
- * thread.
- */
- if (p->bqueue == NULL) {
- p->bqueue = g_malloc(sizeof(struct bio_queue_head),
- M_WAITOK | M_ZERO);
- bioq_init(p->bqueue);
- }
- if (p->wqueue == NULL) {
- p->wqueue = g_malloc(sizeof(struct bio_queue_head),
- M_WAITOK | M_ZERO);
- bioq_init(p->wqueue);
- }
- if (mtx_initialized(&p->bqueue_mtx) == 0)
- mtx_init(&p->bqueue_mtx, "gv_plex", NULL, MTX_DEF);
- if (!(p->flags & GV_PLEX_THREAD_ACTIVE)) {
- kproc_create(gv_plex_worker, p, NULL, 0, 0, "gv_p %s",
- p->name);
- p->flags |= GV_PLEX_THREAD_ACTIVE;
- }
+ sc = p->vinumconf;
+ KASSERT(sc != NULL, ("gv_parity_complete: NULL sc"));
+
+ /* Clean up what we allocated. */
+ if (bp->bio_cflags & GV_BIO_MALLOC)
+ g_free(bp->bio_data);
+ g_destroy_bio(bp);
- return (NULL);
+ if (error == EAGAIN) {
+ G_VINUM_DEBUG(0, "parity incorrect at offset 0x%jx",
+ (intmax_t)p->synced);
+ }
- /* We need to create a new geom. */
+ /* Any error is fatal, except EAGAIN when we're rebuilding. */
+ if (error && !(error == EAGAIN && (flags & GV_BIO_PARITY))) {
+ /* Make sure we don't have the lock. */
+ g_topology_assert_not();
+ g_topology_lock();
+ gv_access(p->vol_sc->provider, -1, -1, 0);
+ g_topology_unlock();
+ G_VINUM_DEBUG(0, "parity check on %s failed at 0x%jx "
+ "errno %d", p->name, (intmax_t)p->synced, error);
+ return;
} else {
- gp = g_new_geomf(mp, "%s", p->name);
- gp->start = gv_plex_start;
- gp->orphan = gv_plex_orphan;
- gp->access = gv_plex_access;
- gp->softc = p;
- p->geom = gp;
-
- TAILQ_INIT(&p->packets);
- p->bqueue = g_malloc(sizeof(struct bio_queue_head),
- M_WAITOK | M_ZERO);
- bioq_init(p->bqueue);
- p->wqueue = g_malloc(sizeof(struct bio_queue_head),
- M_WAITOK | M_ZERO);
- bioq_init(p->wqueue);
- mtx_init(&p->bqueue_mtx, "gv_plex", NULL, MTX_DEF);
- kproc_create(gv_plex_worker, p, NULL, 0, 0, "gv_p %s",
- p->name);
- p->flags |= GV_PLEX_THREAD_ACTIVE;
-
- /* Attach a consumer to this provider. */
- cp = g_new_consumer(gp);
- g_attach(cp, pp);
- s->consumer = cp;
-
- /* Create a provider for the outside world. */
- pp2 = g_new_providerf(gp, "gvinum/plex/%s", p->name);
- pp2->mediasize = p->size;
- pp2->sectorsize = pp->sectorsize;
- p->provider = pp2;
- g_error_provider(pp2, 0);
- return (gp);
+ p->synced += p->stripesize;
}
-}
-static int
-gv_plex_destroy_geom(struct gctl_req *req, struct g_class *mp,
- struct g_geom *gp)
-{
- struct gv_plex *p;
+ if (p->synced >= p->size) {
+ /* Make sure we don't have the lock. */
+ g_topology_assert_not();
+ g_topology_lock();
+ gv_access(p->vol_sc->provider, -1, -1, 0);
+ g_topology_unlock();
+ /* We're finished. */
+ G_VINUM_DEBUG(1, "parity operation on %s finished", p->name);
+ p->synced = 0;
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
+ return;
+ }
- g_trace(G_T_TOPOLOGY, "gv_plex_destroy_geom: %s", gp->name);
- g_topology_assert();
+ /* Send down next. It will determine if we need to itself. */
+ gv_parity_request(p, flags, p->synced);
+}
- p = gp->softc;
+/*
+ * Handle a finished plex rebuild bio.
+ */
+void
+gv_rebuild_complete(struct gv_plex *p, struct bio *bp)
+{
+ struct gv_softc *sc;
+ struct gv_sd *s;
+ int error, flags;
+ off_t offset;
- KASSERT(p != NULL, ("gv_plex_destroy_geom: null p of '%s'", gp->name));
+ error = bp->bio_error;
+ flags = bp->bio_cflags;
+ offset = bp->bio_offset;
+ flags &= ~GV_BIO_MALLOC;
+ sc = p->vinumconf;
+ KASSERT(sc != NULL, ("gv_rebuild_complete: NULL sc"));
- /*
- * If this is a RAID5 plex, check if its worker thread is still active
- * and signal it to self destruct.
- */
- gv_kill_plex_thread(p);
- /* g_free(sc); */
- g_wither_geom(gp, ENXIO);
- return (0);
-}
+ /* Clean up what we allocated. */
+ if (bp->bio_cflags & GV_BIO_MALLOC)
+ g_free(bp->bio_data);
+ g_destroy_bio(bp);
-#define VINUMPLEX_CLASS_NAME "VINUMPLEX"
+ if (error) {
+ g_topology_assert_not();
+ g_topology_lock();
+ gv_access(p->vol_sc->provider, -1, -1, 0);
+ g_topology_unlock();
+
+ G_VINUM_DEBUG(0, "rebuild of %s failed at offset %jd errno: %d",
+ p->name, (intmax_t)offset, error);
+ p->flags &= ~GV_PLEX_REBUILDING;
+ p->synced = 0;
+ gv_plex_flush(p); /* Flush out remaining rebuild BIOs. */
+ return;
+ }
-static struct g_class g_vinum_plex_class = {
- .name = VINUMPLEX_CLASS_NAME,
- .version = G_VERSION,
- .taste = gv_plex_taste,
- .destroy_geom = gv_plex_destroy_geom,
-};
+ offset += (p->stripesize * (gv_sdcount(p, 1) - 1));
+ if (offset >= p->size) {
+ /* We're finished. */
+ g_topology_assert_not();
+ g_topology_lock();
+ gv_access(p->vol_sc->provider, -1, -1, 0);
+ g_topology_unlock();
+
+ G_VINUM_DEBUG(1, "rebuild of %s finished", p->name);
+ gv_save_config(p->vinumconf);
+ p->flags &= ~GV_PLEX_REBUILDING;
+ p->synced = 0;
+ /* Try to up all subdisks. */
+ LIST_FOREACH(s, &p->subdisks, in_plex)
+ gv_update_sd_state(s);
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
+ gv_plex_flush(p); /* Flush out remaining rebuild BIOs. */
+ return;
+ }
-DECLARE_GEOM_CLASS(g_vinum_plex_class, g_vinum_plex);
+ /* Send down next. It will determine if we need to itself. */
+ gv_parity_request(p, flags, offset);
+}
diff --git a/sys/geom/vinum/geom_vinum_raid5.c b/sys/geom/vinum/geom_vinum_raid5.c
index abfed51..088162e 100644
--- a/sys/geom/vinum/geom_vinum_raid5.c
+++ b/sys/geom/vinum/geom_vinum_raid5.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,14 +29,8 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bio.h>
-#include <sys/conf.h>
-#include <sys/errno.h>
-#include <sys/kernel.h>
-#include <sys/kthread.h>
-#include <sys/libkern.h>
#include <sys/lock.h>
#include <sys/malloc.h>
-#include <sys/mutex.h>
#include <sys/systm.h>
#include <geom/geom.h>
@@ -44,8 +38,103 @@ __FBSDID("$FreeBSD$");
#include <geom/vinum/geom_vinum_raid5.h>
#include <geom/vinum/geom_vinum.h>
-int gv_raid5_offset(struct gv_plex *, off_t, off_t, off_t *, off_t *,
- int *, int *);
+static int gv_raid5_offset(struct gv_plex *, off_t, off_t,
+ off_t *, off_t *, int *, int *, int);
+static struct bio * gv_raid5_clone_bio(struct bio *, struct gv_sd *,
+ struct gv_raid5_packet *, caddr_t, int);
+static int gv_raid5_request(struct gv_plex *, struct gv_raid5_packet *,
+ struct bio *, caddr_t, off_t, off_t, int *);
+static int gv_raid5_check(struct gv_plex *, struct gv_raid5_packet *,
+ struct bio *, caddr_t, off_t, off_t);
+static int gv_raid5_rebuild(struct gv_plex *, struct gv_raid5_packet *,
+ struct bio *, caddr_t, off_t, off_t);
+
+struct gv_raid5_packet *
+gv_raid5_start(struct gv_plex *p, struct bio *bp, caddr_t addr, off_t boff,
+ off_t bcount)
+{
+ struct bio *cbp;
+ struct gv_raid5_packet *wp, *wp2;
+ struct gv_bioq *bq, *bq2;
+ int err, delay;
+
+ delay = 0;
+ wp = g_malloc(sizeof(*wp), M_WAITOK | M_ZERO);
+ wp->bio = bp;
+ wp->waiting = NULL;
+ wp->parity = NULL;
+ TAILQ_INIT(&wp->bits);
+
+ if (bp->bio_cflags & GV_BIO_REBUILD)
+ err = gv_raid5_rebuild(p, wp, bp, addr, boff, bcount);
+ else if (bp->bio_cflags & GV_BIO_CHECK)
+ err = gv_raid5_check(p, wp, bp, addr, boff, bcount);
+ else
+ err = gv_raid5_request(p, wp, bp, addr, boff, bcount, &delay);
+
+ /* Means we have a delayed request. */
+ if (delay) {
+ g_free(wp);
+ return (NULL);
+ }
+
+ /*
+ * Building the sub-request failed, we probably need to clean up a lot.
+ */
+ if (err) {
+ G_VINUM_LOGREQ(0, bp, "raid5 plex request failed.");
+ TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
+ TAILQ_REMOVE(&wp->bits, bq, queue);
+ g_free(bq);
+ }
+ if (wp->waiting != NULL) {
+ if (wp->waiting->bio_cflags & GV_BIO_MALLOC)
+ g_free(wp->waiting->bio_data);
+ g_destroy_bio(wp->waiting);
+ }
+ if (wp->parity != NULL) {
+ if (wp->parity->bio_cflags & GV_BIO_MALLOC)
+ g_free(wp->parity->bio_data);
+ g_destroy_bio(wp->parity);
+ }
+ g_free(wp);
+
+ TAILQ_FOREACH_SAFE(wp, &p->packets, list, wp2) {
+ if (wp->bio != bp)
+ continue;
+
+ TAILQ_REMOVE(&p->packets, wp, list);
+ TAILQ_FOREACH_SAFE(bq, &wp->bits, queue, bq2) {
+ TAILQ_REMOVE(&wp->bits, bq, queue);
+ g_free(bq);
+ }
+ g_free(wp);
+ }
+
+ cbp = bioq_takefirst(p->bqueue);
+ while (cbp != NULL) {
+ if (cbp->bio_cflags & GV_BIO_MALLOC)
+ g_free(cbp->bio_data);
+ g_destroy_bio(cbp);
+ cbp = bioq_takefirst(p->bqueue);
+ }
+
+ /* If internal, stop and reset state. */
+ if (bp->bio_cflags & GV_BIO_INTERNAL) {
+ if (bp->bio_cflags & GV_BIO_MALLOC)
+ g_free(cbp->bio_data);
+ g_destroy_bio(bp);
+ /* Reset flags. */
+ p->flags &= ~(GV_PLEX_SYNCING | GV_PLEX_REBUILDING |
+ GV_PLEX_GROWING);
+ return (NULL);
+ }
+ g_io_deliver(bp, err);
+ return (NULL);
+ }
+
+ return (wp);
+}
/*
* Check if the stripe that the work packet wants is already being used by
@@ -57,7 +146,7 @@ gv_stripe_active(struct gv_plex *p, struct bio *bp)
struct gv_raid5_packet *wp, *owp;
int overlap;
- wp = bp->bio_driver1;
+ wp = bp->bio_caller2;
if (wp->lockbase == -1)
return (0);
@@ -80,20 +169,20 @@ gv_stripe_active(struct gv_plex *p, struct bio *bp)
return (overlap);
}
-int
-gv_check_raid5(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
+static int
+gv_raid5_check(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
caddr_t addr, off_t boff, off_t bcount)
{
struct gv_sd *parity, *s;
struct gv_bioq *bq;
- struct bio *cbp, *pbp;
+ struct bio *cbp;
int i, psdno;
off_t real_len, real_off;
if (p == NULL || LIST_EMPTY(&p->subdisks))
return (ENXIO);
- gv_raid5_offset(p, boff, bcount, &real_off, &real_len, NULL, &psdno);
+ gv_raid5_offset(p, boff, bcount, &real_off, &real_len, NULL, &psdno, 1);
/* Find the right subdisk. */
parity = NULL;
@@ -122,20 +211,16 @@ gv_check_raid5(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
/* Skip the parity subdisk. */
if (s == parity)
continue;
+ /* Skip growing subdisks. */
+ if (s->flags & GV_SD_GROW)
+ continue;
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
if (cbp == NULL)
return (ENOMEM);
cbp->bio_cmd = BIO_READ;
- cbp->bio_data = g_malloc(real_len, M_WAITOK);
- cbp->bio_cflags |= GV_BIO_MALLOC;
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = s->consumer;
- cbp->bio_driver1 = wp;
- GV_ENQUEUE(bp, cbp, pbp);
+ bioq_insert_tail(p->bqueue, cbp);
bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
bq->bp = cbp;
@@ -143,51 +228,38 @@ gv_check_raid5(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
}
/* Read the parity data. */
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
if (cbp == NULL)
return (ENOMEM);
cbp->bio_cmd = BIO_READ;
- cbp->bio_data = g_malloc(real_len, M_WAITOK | M_ZERO);
- cbp->bio_cflags |= GV_BIO_MALLOC;
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = parity->consumer;
- cbp->bio_driver1 = wp;
wp->waiting = cbp;
/*
* In case we want to rebuild the parity, create an extra BIO to write
* it out. It also acts as buffer for the XOR operations.
*/
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, parity, wp, addr, 1);
if (cbp == NULL)
return (ENOMEM);
- cbp->bio_data = addr;
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = parity->consumer;
- cbp->bio_driver1 = wp;
wp->parity = cbp;
return (0);
}
/* Rebuild a degraded RAID5 plex. */
-int
-gv_rebuild_raid5(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
+static int
+gv_raid5_rebuild(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
caddr_t addr, off_t boff, off_t bcount)
{
struct gv_sd *broken, *s;
struct gv_bioq *bq;
- struct bio *cbp, *pbp;
+ struct bio *cbp;
off_t real_len, real_off;
if (p == NULL || LIST_EMPTY(&p->subdisks))
return (ENXIO);
- gv_raid5_offset(p, boff, bcount, &real_off, &real_len, NULL, NULL);
+ gv_raid5_offset(p, boff, bcount, &real_off, &real_len, NULL, NULL, 1);
/* Find the right subdisk. */
broken = NULL;
@@ -210,6 +282,8 @@ gv_rebuild_raid5(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
G_VINUM_DEBUG(1, "sd %s is reviving", broken->name);
gv_set_sd_state(broken, GV_SD_REVIVING, GV_SETSTATE_FORCE);
+ /* Set this bit now, but should be set at end. */
+ broken->flags |= GV_SD_CANGOUP;
break;
case GV_SD_REVIVING:
@@ -232,19 +306,16 @@ gv_rebuild_raid5(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
if (s == broken)
continue;
- cbp = g_clone_bio(bp);
+ /* Skip growing subdisks. */
+ if (s->flags & GV_SD_GROW)
+ continue;
+
+ cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
if (cbp == NULL)
return (ENOMEM);
cbp->bio_cmd = BIO_READ;
- cbp->bio_data = g_malloc(real_len, M_WAITOK);
- cbp->bio_cflags |= GV_BIO_MALLOC;
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = s->consumer;
- cbp->bio_driver1 = wp;
- GV_ENQUEUE(bp, cbp, pbp);
+ bioq_insert_tail(p->bqueue, cbp);
bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
bq->bp = cbp;
@@ -252,34 +323,28 @@ gv_rebuild_raid5(struct gv_plex *p, struct gv_raid5_packet *wp, struct bio *bp,
}
/* Write the parity data. */
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, broken, wp, NULL, 1);
if (cbp == NULL)
return (ENOMEM);
- cbp->bio_data = g_malloc(real_len, M_WAITOK | M_ZERO);
- cbp->bio_cflags |= GV_BIO_MALLOC;
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = broken->consumer;
- cbp->bio_driver1 = wp;
cbp->bio_cflags |= GV_BIO_REBUILD;
wp->parity = cbp;
p->synced = boff;
+ /* Post notification that we're finished. */
return (0);
}
/* Build a request group to perform (part of) a RAID5 request. */
-int
-gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
- struct bio *bp, caddr_t addr, off_t boff, off_t bcount)
+static int
+gv_raid5_request(struct gv_plex *p, struct gv_raid5_packet *wp,
+ struct bio *bp, caddr_t addr, off_t boff, off_t bcount, int *delay)
{
struct g_geom *gp;
struct gv_sd *broken, *original, *parity, *s;
struct gv_bioq *bq;
- struct bio *cbp, *pbp;
- int i, psdno, sdno, type;
+ struct bio *cbp;
+ int i, psdno, sdno, type, grow;
off_t real_len, real_off;
gp = bp->bio_to->geom;
@@ -295,7 +360,24 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
type = REQ_TYPE_NORMAL;
original = parity = broken = NULL;
- gv_raid5_offset(p, boff, bcount, &real_off, &real_len, &sdno, &psdno);
+ /* XXX: The resize won't crash with rebuild or sync, but we should still
+ * be aware of it. Also this should perhaps be done on rebuild/check as
+ * well?
+ */
+ /* If we're over, we must use the old. */
+ if (boff >= p->synced) {
+ grow = 1;
+ /* Or if over the resized offset, we use all drives. */
+ } else if (boff + bcount <= p->synced) {
+ grow = 0;
+ /* Else, we're in the middle, and must wait a bit. */
+ } else {
+ bioq_disksort(p->rqueue, bp);
+ *delay = 1;
+ return (0);
+ }
+ gv_raid5_offset(p, boff, bcount, &real_off, &real_len,
+ &sdno, &psdno, grow);
/* Find the right subdisks. */
i = 0;
@@ -315,8 +397,13 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
/* Our data stripe is missing. */
if (original->state != GV_SD_UP)
type = REQ_TYPE_DEGRADED;
+
+ /* If synchronizing request, just write it if disks are stale. */
+ if (original->state == GV_SD_STALE && parity->state == GV_SD_STALE &&
+ bp->bio_cflags & GV_BIO_SYNCREQ && bp->bio_cmd == BIO_WRITE) {
+ type = REQ_TYPE_NORMAL;
/* Our parity stripe is missing. */
- if (parity->state != GV_SD_UP) {
+ } else if (parity->state != GV_SD_UP) {
/* We cannot take another failure if we're already degraded. */
if (type != REQ_TYPE_NORMAL)
return (ENXIO);
@@ -330,9 +417,15 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
KASSERT(wp->length >= 0, ("gv_build_raid5_request: wp->length < 0"));
- if ((p->flags & GV_PLEX_SYNCING) && (boff + real_len < p->synced))
+ if ((p->flags & GV_PLEX_REBUILDING) && (boff + real_len < p->synced))
type = REQ_TYPE_NORMAL;
+ if ((p->flags & GV_PLEX_REBUILDING) && (boff + real_len >= p->synced)) {
+ bioq_disksort(p->rqueue, bp);
+ *delay = 1;
+ return (0);
+ }
+
switch (bp->bio_cmd) {
case BIO_READ:
/*
@@ -346,18 +439,14 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
/* Skip the broken subdisk. */
if (s == broken)
continue;
- cbp = g_clone_bio(bp);
+ /* Skip growing if within offset. */
+ if (grow && s->flags & GV_SD_GROW)
+ continue;
+ cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
if (cbp == NULL)
return (ENOMEM);
- cbp->bio_data = g_malloc(real_len, M_WAITOK);
- cbp->bio_cflags |= GV_BIO_MALLOC;
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = s->consumer;
- cbp->bio_driver1 = wp;
- GV_ENQUEUE(bp, cbp, pbp);
+ bioq_insert_tail(p->bqueue, cbp);
bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
bq->bp = cbp;
@@ -366,16 +455,11 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
/* A normal read can be fulfilled with the original subdisk. */
} else {
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, original, wp, addr, 0);
if (cbp == NULL)
return (ENOMEM);
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_data = addr;
- cbp->bio_done = g_std_done;
- cbp->bio_caller2 = original->consumer;
- GV_ENQUEUE(bp, cbp, pbp);
+ bioq_insert_tail(p->bqueue, cbp);
}
wp->lockbase = -1;
@@ -394,20 +478,16 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
/* Skip the broken and the parity subdisk. */
if ((s == broken) || (s == parity))
continue;
+ /* Skip growing if within offset. */
+ if (grow && s->flags & GV_SD_GROW)
+ continue;
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, s, wp, NULL, 1);
if (cbp == NULL)
return (ENOMEM);
cbp->bio_cmd = BIO_READ;
- cbp->bio_data = g_malloc(real_len, M_WAITOK);
- cbp->bio_cflags |= GV_BIO_MALLOC;
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = s->consumer;
- cbp->bio_driver1 = wp;
- GV_ENQUEUE(bp, cbp, pbp);
+ bioq_insert_tail(p->bqueue, cbp);
bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
bq->bp = cbp;
@@ -415,34 +495,21 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
}
/* Write the parity data. */
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
if (cbp == NULL)
return (ENOMEM);
- cbp->bio_data = g_malloc(real_len, M_WAITOK);
- cbp->bio_cflags |= GV_BIO_MALLOC;
- bcopy(addr, cbp->bio_data, real_len);
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = parity->consumer;
- cbp->bio_driver1 = wp;
+ bcopy(addr, cbp->bio_data, wp->length);
wp->parity = cbp;
/*
* When the parity stripe is missing we just write out the data.
*/
} else if (type == REQ_TYPE_NOPARITY) {
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, original, wp, addr, 1);
if (cbp == NULL)
return (ENOMEM);
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_data = addr;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = original->consumer;
- cbp->bio_driver1 = wp;
- GV_ENQUEUE(bp, cbp, pbp);
+ bioq_insert_tail(p->bqueue, cbp);
bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
bq->bp = cbp;
@@ -455,54 +522,33 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
*/
} else {
/* Read old parity. */
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
if (cbp == NULL)
return (ENOMEM);
cbp->bio_cmd = BIO_READ;
- cbp->bio_data = g_malloc(real_len, M_WAITOK);
- cbp->bio_cflags |= GV_BIO_MALLOC;
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = parity->consumer;
- cbp->bio_driver1 = wp;
- GV_ENQUEUE(bp, cbp, pbp);
+ bioq_insert_tail(p->bqueue, cbp);
bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
bq->bp = cbp;
TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
/* Read old data. */
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, original, wp, NULL, 1);
if (cbp == NULL)
return (ENOMEM);
cbp->bio_cmd = BIO_READ;
- cbp->bio_data = g_malloc(real_len, M_WAITOK);
- cbp->bio_cflags |= GV_BIO_MALLOC;
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = original->consumer;
- cbp->bio_driver1 = wp;
- GV_ENQUEUE(bp, cbp, pbp);
+ bioq_insert_tail(p->bqueue, cbp);
bq = g_malloc(sizeof(*bq), M_WAITOK | M_ZERO);
bq->bp = cbp;
TAILQ_INSERT_TAIL(&wp->bits, bq, queue);
/* Write new data. */
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, original, wp, addr, 1);
if (cbp == NULL)
return (ENOMEM);
- cbp->bio_data = addr;
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = original->consumer;
-
- cbp->bio_driver1 = wp;
/*
* We must not write the new data until the old data
@@ -512,16 +558,9 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
wp->waiting = cbp;
/* The final bio for the parity. */
- cbp = g_clone_bio(bp);
+ cbp = gv_raid5_clone_bio(bp, parity, wp, NULL, 1);
if (cbp == NULL)
return (ENOMEM);
- cbp->bio_data = g_malloc(real_len, M_WAITOK | M_ZERO);
- cbp->bio_cflags |= GV_BIO_MALLOC;
- cbp->bio_offset = real_off;
- cbp->bio_length = real_len;
- cbp->bio_done = gv_plex_done;
- cbp->bio_caller2 = parity->consumer;
- cbp->bio_driver1 = wp;
/* Remember that this is the BIO for the parity data. */
wp->parity = cbp;
@@ -535,21 +574,36 @@ gv_build_raid5_req(struct gv_plex *p, struct gv_raid5_packet *wp,
return (0);
}
-/* Calculate the offsets in the various subdisks for a RAID5 request. */
-int
+/*
+ * Calculate the offsets in the various subdisks for a RAID5 request. Also take
+ * care of new subdisks in an expanded RAID5 array.
+ * XXX: This assumes that the new subdisks are inserted after the others (which
+ * is okay as long as plex_offset is larger). If subdisks are inserted into the
+ * plexlist before, we get problems.
+ */
+static int
gv_raid5_offset(struct gv_plex *p, off_t boff, off_t bcount, off_t *real_off,
- off_t *real_len, int *sdno, int *psdno)
+ off_t *real_len, int *sdno, int *psdno, int growing)
{
- int sd, psd;
+ struct gv_sd *s;
+ int sd, psd, sdcount;
off_t len_left, stripeend, stripeoff, stripestart;
+ sdcount = p->sdcount;
+ if (growing) {
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ if (s->flags & GV_SD_GROW)
+ sdcount--;
+ }
+ }
+
/* The number of the subdisk containing the parity stripe. */
- psd = p->sdcount - 1 - ( boff / (p->stripesize * (p->sdcount - 1))) %
- p->sdcount;
+ psd = sdcount - 1 - ( boff / (p->stripesize * (sdcount - 1))) %
+ sdcount;
KASSERT(psdno >= 0, ("gv_raid5_offset: psdno < 0"));
/* Offset of the start address from the start of the stripe. */
- stripeoff = boff % (p->stripesize * (p->sdcount - 1));
+ stripeoff = boff % (p->stripesize * (sdcount - 1));
KASSERT(stripeoff >= 0, ("gv_raid5_offset: stripeoff < 0"));
/* The number of the subdisk where the stripe resides. */
@@ -561,7 +615,7 @@ gv_raid5_offset(struct gv_plex *p, off_t boff, off_t bcount, off_t *real_off,
sd++;
/* The offset of the stripe on this subdisk. */
- stripestart = (boff - stripeoff) / (p->sdcount - 1);
+ stripestart = (boff - stripeoff) / (sdcount - 1);
KASSERT(stripestart >= 0, ("gv_raid5_offset: stripestart < 0"));
stripeoff %= p->stripesize;
@@ -582,3 +636,27 @@ gv_raid5_offset(struct gv_plex *p, off_t boff, off_t bcount, off_t *real_off,
return (0);
}
+
+static struct bio *
+gv_raid5_clone_bio(struct bio *bp, struct gv_sd *s, struct gv_raid5_packet *wp,
+ caddr_t addr, int use_wp)
+{
+ struct bio *cbp;
+
+ cbp = g_clone_bio(bp);
+ if (cbp == NULL)
+ return (NULL);
+ if (addr == NULL) {
+ cbp->bio_data = g_malloc(wp->length, M_WAITOK | M_ZERO);
+ cbp->bio_cflags |= GV_BIO_MALLOC;
+ } else
+ cbp->bio_data = addr;
+ cbp->bio_offset = wp->lockbase + s->drive_offset;
+ cbp->bio_length = wp->length;
+ cbp->bio_done = gv_done;
+ cbp->bio_caller1 = s;
+ if (use_wp)
+ cbp->bio_caller2 = wp;
+
+ return (cbp);
+}
diff --git a/sys/geom/vinum/geom_vinum_raid5.h b/sys/geom/vinum/geom_vinum_raid5.h
index 804920e..d7d55b2 100644
--- a/sys/geom/vinum/geom_vinum_raid5.h
+++ b/sys/geom/vinum/geom_vinum_raid5.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,26 +35,10 @@
* transaction (read or write).
*/
-#define GV_ENQUEUE(bp, cbp, pbp) \
- do { \
- if (bp->bio_driver1 == NULL) { \
- bp->bio_driver1 = cbp; \
- } else { \
- pbp = bp->bio_driver1; \
- while (pbp->bio_caller1 != NULL) \
- pbp = pbp->bio_caller1; \
- pbp->bio_caller1 = cbp; \
- } \
- } while (0)
-
struct gv_raid5_packet {
caddr_t data; /* Data buffer of this sub-request- */
off_t length; /* Size of data buffer. */
off_t lockbase; /* Deny access to our plex offset. */
- off_t offset; /* The drive offset of the subdisk. */
- int bufmalloc; /* Flag if data buffer was malloced. */
- int active; /* Count of active subrequests. */
- int rqcount; /* Count of subrequests. */
struct bio *bio; /* Pointer to the original bio. */
struct bio *parity; /* The bio containing the parity data. */
@@ -64,14 +48,8 @@ struct gv_raid5_packet {
TAILQ_ENTRY(gv_raid5_packet) list; /* Entry in plex's packet list. */
};
+struct gv_raid5_packet * gv_raid5_start(struct gv_plex *, struct bio *,
+ caddr_t, off_t, off_t);
int gv_stripe_active(struct gv_plex *, struct bio *);
-int gv_build_raid5_req(struct gv_plex *, struct gv_raid5_packet *,
- struct bio *, caddr_t, off_t, off_t);
-int gv_check_raid5(struct gv_plex *, struct gv_raid5_packet *,
- struct bio *, caddr_t, off_t, off_t);
-int gv_rebuild_raid5(struct gv_plex *, struct gv_raid5_packet *,
- struct bio *, caddr_t, off_t, off_t);
-void gv_raid5_worker(void *);
-void gv_plex_done(struct bio *);
#endif /* !_GEOM_VINUM_RAID5_H_ */
diff --git a/sys/geom/vinum/geom_vinum_rename.c b/sys/geom/vinum/geom_vinum_rename.c
index ee5fc9c..53c173f 100644
--- a/sys/geom/vinum/geom_vinum_rename.c
+++ b/sys/geom/vinum/geom_vinum_rename.c
@@ -34,22 +34,11 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/libkern.h>
-#include <sys/kernel.h>
#include <sys/malloc.h>
#include <geom/geom.h>
#include <geom/vinum/geom_vinum_var.h>
#include <geom/vinum/geom_vinum.h>
-#include <geom/vinum/geom_vinum_share.h>
-
-static int gv_rename_drive(struct gv_softc *, struct gctl_req *,
- struct gv_drive *, char *, int);
-static int gv_rename_plex(struct gv_softc *, struct gctl_req *,
- struct gv_plex *, char *, int);
-static int gv_rename_sd(struct gv_softc *, struct gctl_req *,
- struct gv_sd *, char *, int);
-static int gv_rename_vol(struct gv_softc *, struct gctl_req *,
- struct gv_volume *, char *, int);
void
gv_rename(struct g_geom *gp, struct gctl_req *req)
@@ -59,8 +48,8 @@ gv_rename(struct g_geom *gp, struct gctl_req *req)
struct gv_plex *p;
struct gv_sd *s;
struct gv_drive *d;
- char *newname, *object;
- int err, *flags, type;
+ char *newname, *object, *name;
+ int *flags, type;
sc = gp->softc;
@@ -90,9 +79,9 @@ gv_rename(struct g_geom *gp, struct gctl_req *req)
gctl_error(req, "unknown volume '%s'", object);
return;
}
- err = gv_rename_vol(sc, req, v, newname, *flags);
- if (err)
- return;
+ name = g_malloc(GV_MAXVOLNAME, M_WAITOK | M_ZERO);
+ strlcpy(name, newname, GV_MAXVOLNAME);
+ gv_post_event(sc, GV_EVENT_RENAME_VOL, v, name, *flags, 0);
break;
case GV_TYPE_PLEX:
p = gv_find_plex(sc, object);
@@ -100,9 +89,9 @@ gv_rename(struct g_geom *gp, struct gctl_req *req)
gctl_error(req, "unknown plex '%s'", object);
return;
}
- err = gv_rename_plex(sc, req, p, newname, *flags);
- if (err)
- return;
+ name = g_malloc(GV_MAXPLEXNAME, M_WAITOK | M_ZERO);
+ strlcpy(name, newname, GV_MAXPLEXNAME);
+ gv_post_event(sc, GV_EVENT_RENAME_PLEX, p, name, *flags, 0);
break;
case GV_TYPE_SD:
s = gv_find_sd(sc, object);
@@ -110,9 +99,9 @@ gv_rename(struct g_geom *gp, struct gctl_req *req)
gctl_error(req, "unknown subdisk '%s'", object);
return;
}
- err = gv_rename_sd(sc, req, s, newname, *flags);
- if (err)
- return;
+ name = g_malloc(GV_MAXSDNAME, M_WAITOK | M_ZERO);
+ strlcpy(name, newname, GV_MAXSDNAME);
+ gv_post_event(sc, GV_EVENT_RENAME_SD, s, name, *flags, 0);
break;
case GV_TYPE_DRIVE:
d = gv_find_drive(sc, object);
@@ -120,122 +109,88 @@ gv_rename(struct g_geom *gp, struct gctl_req *req)
gctl_error(req, "unknown drive '%s'", object);
return;
}
- err = gv_rename_drive(sc, req, d, newname, *flags);
- if (err)
- return;
+ name = g_malloc(GV_MAXDRIVENAME, M_WAITOK | M_ZERO);
+ strlcpy(name, newname, GV_MAXDRIVENAME);
+ gv_post_event(sc, GV_EVENT_RENAME_DRIVE, d, name, *flags, 0);
break;
default:
gctl_error(req, "unknown object '%s'", object);
return;
}
-
- gv_save_config_all(sc);
}
-static int
-gv_rename_drive(struct gv_softc *sc, struct gctl_req *req, struct gv_drive *d, char *newname, int flags)
+int
+gv_rename_drive(struct gv_softc *sc, struct gv_drive *d, char *newname,
+ int flags)
{
struct gv_sd *s;
g_topology_assert();
KASSERT(d != NULL, ("gv_rename_drive: NULL d"));
- if (gv_object_type(sc, newname) != -1) {
- gctl_error(req, "drive name '%s' already in use", newname);
- return (-1);
+ if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) {
+ G_VINUM_DEBUG(1, "drive name '%s' already in use", newname);
+ return (GV_ERR_NAMETAKEN);
}
- strncpy(d->name, newname, GV_MAXDRIVENAME);
- strncpy(d->hdr->label.name, newname, GV_MAXDRIVENAME);
-
- /* XXX can we rename providers here? */
+ strlcpy(d->name, newname, sizeof(d->name));
+ if (d->hdr != NULL)
+ strlcpy(d->hdr->label.name, newname, sizeof(d->hdr->label.name));
LIST_FOREACH(s, &d->subdisks, from_drive)
- strncpy(s->drive, d->name, GV_MAXDRIVENAME);
+ strlcpy(s->drive, d->name, sizeof(s->drive));
return (0);
}
-static int
-gv_rename_plex(struct gv_softc *sc, struct gctl_req *req, struct gv_plex *p, char *newname, int flags)
+int
+gv_rename_plex(struct gv_softc *sc, struct gv_plex *p, char *newname, int flags)
{
+ char newsd[GV_MAXSDNAME];
struct gv_sd *s;
- char *plexnum, *plexnump, *oldplex, *oldplexp;
- char *newsd, *oldsd, *oldsdp;
+ char *ptr;
int err;
g_topology_assert();
KASSERT(p != NULL, ("gv_rename_plex: NULL p"));
- err = 0;
-
- if (gv_object_type(sc, newname) != -1) {
- gctl_error(req, "plex name '%s' already in use", newname);
- return (-1);
+ if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) {
+ G_VINUM_DEBUG(1, "plex name '%s' already in use", newname);
+ return (GV_ERR_NAMETAKEN);
}
- /* Needed for sanity checking. */
- plexnum = g_malloc(GV_MAXPLEXNAME, M_WAITOK | M_ZERO);
- strncpy(plexnum, newname, GV_MAXPLEXNAME);
- plexnump = plexnum;
-
- oldplex = g_malloc(GV_MAXPLEXNAME, M_WAITOK | M_ZERO);
- strncpy(oldplex, p->name, GV_MAXPLEXNAME);
- oldplexp = oldplex;
-
/*
* Locate the plex number part of the plex names.
- *
- * XXX: can we be sure that the current plex name has the format
- * 'foo.pX'?
+ * XXX: might be a good idea to sanitize input a bit more
*/
- strsep(&oldplexp, ".");
- strsep(&plexnump, ".");
- if (plexnump == NULL || *plexnump == '\0') {
- gctl_error(req, "proposed plex name '%s' is not a valid plex "
+ ptr = strrchr(newname, '.');
+ if (ptr == NULL) {
+ G_VINUM_DEBUG(0, "proposed plex name '%s' is not a valid plex "
"name", newname);
- err = -1;
- goto failure;
+ return (GV_ERR_INVNAME);
}
- if (strcmp(oldplexp, plexnump)) {
- gctl_error(req, "current and proposed plex numbers (%s, %s) "
- "do not match", plexnump, oldplexp);
- err = -1;
- goto failure;
- }
-
- strncpy(p->name, newname, GV_MAXPLEXNAME);
- /* XXX can we rename providers here? */
+ strlcpy(p->name, newname, sizeof(p->name));
/* Fix up references and potentially rename subdisks. */
LIST_FOREACH(s, &p->subdisks, in_plex) {
- strncpy(s->plex, p->name, GV_MAXPLEXNAME);
+ strlcpy(s->plex, p->name, sizeof(s->plex));
if (flags && GV_FLAG_R) {
- newsd = g_malloc(GV_MAXSDNAME, M_WAITOK | M_ZERO);
- oldsd = g_malloc(GV_MAXSDNAME, M_WAITOK | M_ZERO);
- oldsdp = oldsd;
- strncpy(oldsd, s->name, GV_MAXSDNAME);
/*
- * XXX: can we be sure that the current sd name has the
- * format 'foo.pX.sY'?
+ * Look for the two last dots in the string, and assume
+ * that the old value was ok.
*/
- strsep(&oldsdp, ".");
- strsep(&oldsdp, ".");
- snprintf(newsd, GV_MAXSDNAME, "%s.%s", p->name, oldsdp);
- err = gv_rename_sd(sc, req, s, newsd, flags);
- g_free(newsd);
- g_free(oldsd);
+ ptr = strrchr(s->name, '.');
+ if (ptr == NULL)
+ return (GV_ERR_INVNAME);
+ ptr++;
+ snprintf(newsd, sizeof(newsd), "%s.%s", p->name, ptr);
+ err = gv_rename_sd(sc, s, newsd, flags);
if (err)
- goto failure;
+ return (err);
}
}
-
-failure:
- g_free(plexnum);
- g_free(oldplex);
-
- return (err);
+ return (0);
}
/*
@@ -243,106 +198,64 @@ failure:
* since there are no structures below a subdisk. Similarly, we don't have to
* clean up any references elsewhere to the subdisk's name.
*/
-static int
-gv_rename_sd(struct gv_softc *sc, struct gctl_req *req, struct gv_sd *s, char * newname, int flags)
+int
+gv_rename_sd(struct gv_softc *sc, struct gv_sd *s, char *newname, int flags)
{
- char *new, *newp, *old, *oldp;
- int err;
+ char *dot1, *dot2;
g_topology_assert();
KASSERT(s != NULL, ("gv_rename_sd: NULL s"));
- err = 0;
-
- if (gv_object_type(sc, newname) != -1) {
- gctl_error(req, "subdisk name %s already in use", newname);
- return (-1);
+ if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) {
+ G_VINUM_DEBUG(1, "subdisk name %s already in use", newname);
+ return (GV_ERR_NAMETAKEN);
}
- /* Needed for sanity checking. */
- new = g_malloc(GV_MAXSDNAME, M_WAITOK | M_ZERO);
- strncpy(new, newname, GV_MAXSDNAME);
- newp = new;
-
- old = g_malloc(GV_MAXSDNAME, M_WAITOK | M_ZERO);
- strncpy(old, s->name, GV_MAXSDNAME);
- oldp = old;
-
- /*
- * Locate the sd number part of the sd names.
- *
- * XXX: can we be sure that the current sd name has the format
- * 'foo.pX.sY'?
- */
- strsep(&oldp, ".");
- strsep(&oldp, ".");
- strsep(&newp, ".");
- if (newp == NULL || *newp == '\0') {
- gctl_error(req, "proposed sd name '%s' is not a valid sd name",
+ /* Locate the sd number part of the sd names. */
+ dot1 = strchr(newname, '.');
+ if (dot1 == NULL || (dot2 = strchr(dot1 + 1, '.')) == NULL) {
+ G_VINUM_DEBUG(0, "proposed sd name '%s' is not a valid sd name",
newname);
- err = -1;
- goto fail;
+ return (GV_ERR_INVNAME);
}
- strsep(&newp, ".");
- if (newp == NULL || *newp == '\0') {
- gctl_error(req, "proposed sd name '%s' is not a valid sd name",
- newname);
- err = -1;
- goto fail;
- }
- if (strcmp(newp, oldp)) {
- gctl_error(req, "current and proposed sd numbers (%s, %s) do "
- "not match", oldp, newp);
- err = -1;
- goto fail;
- }
-
- strncpy(s->name, newname, GV_MAXSDNAME);
-
- /* XXX: can we rename providers here? */
-
-fail:
- g_free(new);
- g_free(old);
-
- return (err);
+ strlcpy(s->name, newname, sizeof(s->name));
+ return (0);
}
-static int
-gv_rename_vol(struct gv_softc *sc, struct gctl_req *req, struct gv_volume *v, char *newname, int flags)
+int
+gv_rename_vol(struct gv_softc *sc, struct gv_volume *v, char *newname,
+ int flags)
{
+ struct g_provider *pp;
struct gv_plex *p;
- char *new, *old, *oldp;
+ char newplex[GV_MAXPLEXNAME], *ptr;
int err;
g_topology_assert();
KASSERT(v != NULL, ("gv_rename_vol: NULL v"));
+ pp = v->provider;
+ KASSERT(pp != NULL, ("gv_rename_vol: NULL pp"));
- if (gv_object_type(sc, newname) != -1) {
- gctl_error(req, "volume name %s already in use", newname);
- return (-1);
+ if (gv_object_type(sc, newname) != GV_ERR_NOTFOUND) {
+ G_VINUM_DEBUG(1, "volume name %s already in use", newname);
+ return (GV_ERR_NAMETAKEN);
}
/* Rename the volume. */
- strncpy(v->name, newname, GV_MAXVOLNAME);
+ strlcpy(v->name, newname, sizeof(v->name));
/* Fix up references and potentially rename plexes. */
LIST_FOREACH(p, &v->plexes, in_volume) {
- strncpy(p->volume, v->name, GV_MAXVOLNAME);
+ strlcpy(p->volume, v->name, sizeof(p->volume));
if (flags && GV_FLAG_R) {
- new = g_malloc(GV_MAXPLEXNAME, M_WAITOK | M_ZERO);
- old = g_malloc(GV_MAXPLEXNAME, M_WAITOK | M_ZERO);
- oldp = old;
- strncpy(old, p->name, GV_MAXPLEXNAME);
/*
- * XXX: can we be sure that the current plex name has
- * the format 'foo.pX'?
+ * Look for the last dot in the string, and assume that
+ * the old value was ok.
*/
- strsep(&oldp, ".");
- snprintf(new, GV_MAXPLEXNAME, "%s.%s", v->name, oldp);
- err = gv_rename_plex(sc, req, p, new, flags);
- g_free(new);
- g_free(old);
+ ptr = strrchr(p->name, '.');
+ ptr++;
+ snprintf(newplex, sizeof(newplex), "%s.%s", v->name, ptr);
+ err = gv_rename_plex(sc, p, newplex, flags);
if (err)
return (err);
}
diff --git a/sys/geom/vinum/geom_vinum_rm.c b/sys/geom/vinum/geom_vinum_rm.c
index d7748da..2b1d36b 100644
--- a/sys/geom/vinum/geom_vinum_rm.c
+++ b/sys/geom/vinum/geom_vinum_rm.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,20 +30,11 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/libkern.h>
-#include <sys/kernel.h>
#include <sys/malloc.h>
#include <geom/geom.h>
#include <geom/vinum/geom_vinum_var.h>
#include <geom/vinum/geom_vinum.h>
-#include <geom/vinum/geom_vinum_share.h>
-
-static int gv_rm_drive(struct gv_softc *, struct gctl_req *,
- struct gv_drive *, int);
-static int gv_rm_plex(struct gv_softc *, struct gctl_req *,
- struct gv_plex *, int);
-static int gv_rm_vol(struct gv_softc *, struct gctl_req *,
- struct gv_volume *, int);
/* General 'remove' routine. */
void
@@ -56,7 +47,7 @@ gv_remove(struct g_geom *gp, struct gctl_req *req)
struct gv_drive *d;
int *argc, *flags;
char *argv, buf[20];
- int i, type, err;
+ int i, type;
argc = gctl_get_paraml(req, "argc", sizeof(*argc));
@@ -73,6 +64,8 @@ gv_remove(struct g_geom *gp, struct gctl_req *req)
sc = gp->softc;
+ /* XXX config locking */
+
for (i = 0; i < *argc; i++) {
snprintf(buf, sizeof(buf), "argv%d", i);
argv = gctl_get_param(req, buf, NULL);
@@ -82,184 +75,173 @@ gv_remove(struct g_geom *gp, struct gctl_req *req)
switch (type) {
case GV_TYPE_VOL:
v = gv_find_vol(sc, argv);
- if (v == NULL) {
- gctl_error(req, "unknown volume '%s'", argv);
+
+ /*
+ * If this volume has plexes, we want a recursive
+ * removal.
+ */
+ if (!LIST_EMPTY(&v->plexes) && !(*flags & GV_FLAG_R)) {
+ gctl_error(req, "volume '%s' has attached "
+ "plexes - need recursive removal", v->name);
return;
}
- err = gv_rm_vol(sc, req, v, *flags);
- if (err)
- return;
+
+ gv_post_event(sc, GV_EVENT_RM_VOLUME, v, NULL, 0, 0);
break;
+
case GV_TYPE_PLEX:
p = gv_find_plex(sc, argv);
- if (p == NULL) {
- gctl_error(req, "unknown plex '%s'", argv);
+
+ /*
+ * If this plex has subdisks, we want a recursive
+ * removal.
+ */
+ if (!LIST_EMPTY(&p->subdisks) &&
+ !(*flags & GV_FLAG_R)) {
+ gctl_error(req, "plex '%s' has attached "
+ "subdisks - need recursive removal",
+ p->name);
return;
}
- err = gv_rm_plex(sc, req, p, *flags);
- if (err)
+
+ /* Don't allow removal of the only plex of a volume. */
+ if (p->vol_sc != NULL && p->vol_sc->plexcount == 1) {
+ gctl_error(req, "plex '%s' is still attached "
+ "to volume '%s'", p->name, p->volume);
return;
+ }
+
+ gv_post_event(sc, GV_EVENT_RM_PLEX, p, NULL, 0, 0);
break;
+
case GV_TYPE_SD:
s = gv_find_sd(sc, argv);
- if (s == NULL) {
- gctl_error(req, "unknown subdisk '%s'", argv);
+
+ /* Don't allow removal if attached to a plex. */
+ if (s->plex_sc != NULL) {
+ gctl_error(req, "subdisk '%s' is still attached"
+ " to plex '%s'", s->name, s->plex_sc->name);
return;
}
- err = gv_rm_sd(sc, req, s, *flags);
- if (err)
- return;
+
+ gv_post_event(sc, GV_EVENT_RM_SD, s, NULL, 0, 0);
break;
+
case GV_TYPE_DRIVE:
d = gv_find_drive(sc, argv);
- if (d == NULL) {
- gctl_error(req, "unknown drive '%s'", argv);
+ /* We don't allow to remove open drives. */
+ if (gv_consumer_is_open(d->consumer) &&
+ !(*flags & GV_FLAG_F)) {
+ gctl_error(req, "drive '%s' is open", d->name);
return;
}
- err = gv_rm_drive(sc, req, d, *flags);
- if (err)
+
+ /* A drive with subdisks needs a recursive removal. */
+/* if (!LIST_EMPTY(&d->subdisks) &&
+ !(*flags & GV_FLAG_R)) {
+ gctl_error(req, "drive '%s' still has subdisks"
+ " - need recursive removal", d->name);
return;
+ }*/
+
+ gv_post_event(sc, GV_EVENT_RM_DRIVE, d, NULL, *flags,
+ 0);
break;
+
default:
gctl_error(req, "unknown object '%s'", argv);
return;
}
}
- gv_save_config_all(sc);
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
}
/* Resets configuration */
int
-gv_resetconfig(struct g_geom *gp, struct gctl_req *req)
+gv_resetconfig(struct gv_softc *sc)
{
- struct gv_softc *sc;
struct gv_drive *d, *d2;
struct gv_volume *v, *v2;
struct gv_plex *p, *p2;
struct gv_sd *s, *s2;
- int flags;
-
- d = NULL;
- d2 = NULL;
- p = NULL;
- p2 = NULL;
- s = NULL;
- s2 = NULL;
- flags = GV_FLAG_R;
- sc = gp->softc;
- /* First loop through to make sure no volumes are up */
- LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2) {
- if (gv_is_open(v->geom)) {
- gctl_error(req, "volume '%s' is busy", v->name);
- return (-1);
+
+ /* First make sure nothing is open. */
+ LIST_FOREACH_SAFE(d, &sc->drives, drive, d2) {
+ if (gv_consumer_is_open(d->consumer)) {
+ return (GV_ERR_ISBUSY);
}
}
/* Then if not, we remove everything. */
- LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2)
- gv_rm_vol(sc, req, v, flags);
- LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2)
- gv_rm_plex(sc, req, p, flags);
LIST_FOREACH_SAFE(s, &sc->subdisks, sd, s2)
- gv_rm_sd(sc, req, s, flags);
+ gv_rm_sd(sc, s);
LIST_FOREACH_SAFE(d, &sc->drives, drive, d2)
- gv_rm_drive(sc, req, d, flags);
- gv_save_config_all(sc);
+ gv_rm_drive(sc, d, 0);
+ LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2)
+ gv_rm_plex(sc, p);
+ LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2)
+ gv_rm_vol(sc, v);
+
+ gv_post_event(sc, GV_EVENT_SAVE_CONFIG, sc, NULL, 0, 0);
+
return (0);
}
/* Remove a volume. */
-static int
-gv_rm_vol(struct gv_softc *sc, struct gctl_req *req, struct gv_volume *v, int flags)
+void
+gv_rm_vol(struct gv_softc *sc, struct gv_volume *v)
{
- struct g_geom *gp;
+ struct g_provider *pp;
struct gv_plex *p, *p2;
- int err;
- g_topology_assert();
KASSERT(v != NULL, ("gv_rm_vol: NULL v"));
-
- /* If this volume has plexes, we want a recursive removal. */
- if (!LIST_EMPTY(&v->plexes) && !(flags & GV_FLAG_R)) {
- gctl_error(req, "volume '%s' has attached plexes", v->name);
- return (-1);
- }
-
- gp = v->geom;
+ pp = v->provider;
+ KASSERT(pp != NULL, ("gv_rm_vol: NULL pp"));
/* Check if any of our consumers is open. */
- if (gp != NULL && gv_is_open(gp)) {
- gctl_error(req, "volume '%s' is busy", v->name);
- return (-1);
+ if (gv_provider_is_open(pp)) {
+ G_VINUM_DEBUG(0, "Unable to remove %s: volume still in use",
+ v->name);
+ return;
}
/* Remove the plexes our volume has. */
- LIST_FOREACH_SAFE(p, &v->plexes, in_volume, p2) {
- v->plexcount--;
- LIST_REMOVE(p, in_volume);
- p->vol_sc = NULL;
-
- err = gv_rm_plex(sc, req, p, flags);
- if (err)
- return (err);
- }
+ LIST_FOREACH_SAFE(p, &v->plexes, in_volume, p2)
+ gv_rm_plex(sc, p);
- /* Clean up and let our geom fade away. */
+ /* Clean up. */
LIST_REMOVE(v, volume);
- gv_kill_vol_thread(v);
g_free(v);
- if (gp != NULL) {
- gp->softc = NULL;
- g_wither_geom(gp, ENXIO);
- }
- return (0);
+ /* Get rid of the volume's provider. */
+ if (pp != NULL) {
+ g_topology_lock();
+ pp->flags |= G_PF_WITHER;
+ g_orphan_provider(pp, ENXIO);
+ g_topology_unlock();
+ }
}
/* Remove a plex. */
-static int
-gv_rm_plex(struct gv_softc *sc, struct gctl_req *req, struct gv_plex *p, int flags)
+void
+gv_rm_plex(struct gv_softc *sc, struct gv_plex *p)
{
- struct g_geom *gp;
struct gv_volume *v;
struct gv_sd *s, *s2;
- int err;
-
- g_topology_assert();
KASSERT(p != NULL, ("gv_rm_plex: NULL p"));
-
- /* If this plex has subdisks, we want a recursive removal. */
- if (!LIST_EMPTY(&p->subdisks) && !(flags & GV_FLAG_R)) {
- gctl_error(req, "plex '%s' has attached subdisks", p->name);
- return (-1);
- }
-
- if (p->vol_sc != NULL && p->vol_sc->plexcount == 1) {
- gctl_error(req, "plex '%s' is still attached to volume '%s'",
- p->name, p->volume);
- return (-1);
- }
-
- gp = p->geom;
+ v = p->vol_sc;
/* Check if any of our consumers is open. */
- if (gp != NULL && gv_is_open(gp)) {
- gctl_error(req, "plex '%s' is busy", p->name);
- return (-1);
+ if (v != NULL && gv_provider_is_open(v->provider) && v->plexcount < 2) {
+ G_VINUM_DEBUG(0, "Unable to remove %s: volume still in use",
+ p->name);
+ return;
}
/* Remove the subdisks our plex has. */
- LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2) {
-#if 0
- LIST_REMOVE(s, in_plex);
- s->plex_sc = NULL;
-#endif
-
- err = gv_rm_sd(sc, req, s, flags);
- if (err)
- return (err);
- }
+ LIST_FOREACH_SAFE(s, &p->subdisks, in_plex, s2)
+ gv_rm_sd(sc, s);
v = p->vol_sc;
/* Clean up and let our geom fade away. */
@@ -272,35 +254,25 @@ gv_rm_plex(struct gv_softc *sc, struct gctl_req *req, struct gv_plex *p, int fla
gv_update_vol_size(v, gv_vol_size(v));
}
- gv_kill_plex_thread(p);
g_free(p);
-
- if (gp != NULL) {
- gp->softc = NULL;
- g_wither_geom(gp, ENXIO);
- }
-
- return (0);
}
/* Remove a subdisk. */
-int
-gv_rm_sd(struct gv_softc *sc, struct gctl_req *req, struct gv_sd *s, int flags)
+void
+gv_rm_sd(struct gv_softc *sc, struct gv_sd *s)
{
- struct g_provider *pp;
struct gv_plex *p;
struct gv_volume *v;
KASSERT(s != NULL, ("gv_rm_sd: NULL s"));
- pp = s->provider;
p = s->plex_sc;
v = NULL;
/* Clean up. */
if (p != NULL) {
LIST_REMOVE(s, in_plex);
-
+ s->plex_sc = NULL;
p->sdcount--;
/* Update the plexsize. */
p->size = gv_plex_size(p);
@@ -310,77 +282,64 @@ gv_rm_sd(struct gv_softc *sc, struct gctl_req *req, struct gv_sd *s, int flags)
gv_update_vol_size(v, gv_vol_size(v));
}
}
- if (s->drive_sc)
+ if (s->drive_sc && !(s->drive_sc->flags & GV_DRIVE_REFERENCED))
LIST_REMOVE(s, from_drive);
LIST_REMOVE(s, sd);
gv_free_sd(s);
g_free(s);
-
- /* If the subdisk has a provider we need to clean up this one too. */
- if (pp != NULL) {
- pp->flags |= G_PF_WITHER;
- g_orphan_provider(pp, ENXIO);
- }
-
- return (0);
}
/* Remove a drive. */
-static int
-gv_rm_drive(struct gv_softc *sc, struct gctl_req *req, struct gv_drive *d, int flags)
+void
+gv_rm_drive(struct gv_softc *sc, struct gv_drive *d, int flags)
{
- struct g_geom *gp;
struct g_consumer *cp;
struct gv_freelist *fl, *fl2;
struct gv_plex *p;
struct gv_sd *s, *s2;
struct gv_volume *v;
+ struct gv_drive *d2;
int err;
KASSERT(d != NULL, ("gv_rm_drive: NULL d"));
- gp = d->geom;
- KASSERT(gp != NULL, ("gv_rm_drive: NULL gp"));
- /* We don't allow to remove open drives. */
- if (gv_is_open(gp)) {
- gctl_error(req, "drive '%s' is open", d->name);
- return (-1);
- }
+ cp = d->consumer;
- /* A drive with subdisks needs a recursive removal. */
- if (!LIST_EMPTY(&d->subdisks) && !(flags & GV_FLAG_R)) {
- gctl_error(req, "drive '%s' still has subdisks", d->name);
- return (-1);
- }
+ if (cp != NULL) {
+ g_topology_lock();
+ err = g_access(cp, 0, 1, 0);
+ g_topology_unlock();
- cp = LIST_FIRST(&gp->consumer);
- err = g_access(cp, 0, 1, 0);
- if (err) {
- G_VINUM_DEBUG(0, "%s: unable to access '%s', errno: "
- "%d", __func__, cp->provider->name, err);
- return (err);
- }
+ if (err) {
+ G_VINUM_DEBUG(0, "%s: couldn't access '%s', "
+ "errno: %d", __func__, cp->provider->name, err);
+ return;
+ }
- /* Clear the Vinum Magic. */
- d->hdr->magic = GV_NOMAGIC;
- g_topology_unlock();
- err = gv_write_header(cp, d->hdr);
- if (err) {
- G_VINUM_DEBUG(0, "%s: unable to write header to '%s'"
- ", errno: %d", __func__, cp->provider->name, err);
- d->hdr->magic = GV_MAGIC;
+ /* Clear the Vinum Magic. */
+ d->hdr->magic = GV_NOMAGIC;
+ err = gv_write_header(cp, d->hdr);
+ if (err)
+ G_VINUM_DEBUG(0, "gv_rm_drive: couldn't write header to"
+ " '%s', errno: %d", cp->provider->name, err);
+
+ g_topology_lock();
+ g_access(cp, -cp->acr, -cp->acw, -cp->ace);
+ g_detach(cp);
+ g_destroy_consumer(cp);
+ g_topology_unlock();
}
- g_topology_lock();
- g_access(cp, 0, -1, 0);
/* Remove all associated subdisks, plexes, volumes. */
- if (!LIST_EMPTY(&d->subdisks)) {
- LIST_FOREACH_SAFE(s, &d->subdisks, from_drive, s2) {
- p = s->plex_sc;
- if (p != NULL) {
- v = p->vol_sc;
- if (v != NULL)
- gv_rm_vol(sc, req, v, flags);
+ if (flags & GV_FLAG_R) {
+ if (!LIST_EMPTY(&d->subdisks)) {
+ LIST_FOREACH_SAFE(s, &d->subdisks, from_drive, s2) {
+ p = s->plex_sc;
+ if (p != NULL) {
+ v = p->vol_sc;
+ if (v != NULL)
+ gv_rm_vol(sc, v);
+ }
}
}
}
@@ -390,15 +349,33 @@ gv_rm_drive(struct gv_softc *sc, struct gctl_req *req, struct gv_drive *d, int f
LIST_REMOVE(fl, freelist);
g_free(fl);
}
- LIST_REMOVE(d, drive);
- gv_kill_drive_thread(d);
- gp = d->geom;
- d->geom = NULL;
+ LIST_REMOVE(d, drive);
g_free(d->hdr);
+
+ /* Put ourself into referenced state if we have subdisks. */
+ if (d->sdcount > 0) {
+ d->consumer = NULL;
+ d->hdr = NULL;
+ d->flags |= GV_DRIVE_REFERENCED;
+ snprintf(d->device, sizeof(d->device), "???");
+ d->size = 0;
+ d->avail = 0;
+ d->freelist_entries = 0;
+ LIST_FOREACH(s, &d->subdisks, from_drive) {
+ s->flags |= GV_SD_TASTED;
+ gv_set_sd_state(s, GV_SD_DOWN, GV_SETSTATE_FORCE);
+ }
+ /* Shuffle around so we keep gv_is_newer happy. */
+ LIST_REMOVE(d, drive);
+ d2 = LIST_FIRST(&sc->drives);
+ if (d2 == NULL)
+ LIST_INSERT_HEAD(&sc->drives, d, drive);
+ else
+ LIST_INSERT_AFTER(d2, d, drive);
+ return;
+ }
g_free(d);
- gv_save_config_all(sc);
- g_wither_geom(gp, ENXIO);
- return (err);
+ gv_save_config(sc);
}
diff --git a/sys/geom/vinum/geom_vinum_share.c b/sys/geom/vinum/geom_vinum_share.c
index ec97c5e..eb70c28 100644
--- a/sys/geom/vinum/geom_vinum_share.c
+++ b/sys/geom/vinum/geom_vinum_share.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
* Copyright (c) 1997, 1998, 1999
* Nan Yang Computer Services Limited. All rights reserved.
*
@@ -45,10 +45,6 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#ifdef _KERNEL
-#include <sys/bio.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/kthread.h>
#include <sys/malloc.h>
#include <sys/systm.h>
@@ -63,7 +59,6 @@ __FBSDID("$FreeBSD$");
#define g_free free
#endif /* _KERNEL */
-#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/queue.h>
@@ -237,6 +232,8 @@ gv_sdstatei(char *buf)
return (GV_SD_UP);
else if (!strcmp(buf, "reviving"))
return (GV_SD_REVIVING);
+ else if (!strcmp(buf, "initializing"))
+ return (GV_SD_INITIALIZING);
else if (!strcmp(buf, "stale"))
return (GV_SD_STALE);
else
@@ -273,6 +270,8 @@ gv_plexstatei(char *buf)
return (GV_PLEX_INITIALIZING);
else if (!strcmp(buf, "degraded"))
return (GV_PLEX_DEGRADED);
+ else if (!strcmp(buf, "growable"))
+ return (GV_PLEX_GROWABLE);
else
return (GV_PLEX_DOWN);
}
@@ -288,6 +287,8 @@ gv_plexstate(int state)
return "initializing";
case GV_PLEX_DEGRADED:
return "degraded";
+ case GV_PLEX_GROWABLE:
+ return "growable";
case GV_PLEX_UP:
return "up";
default:
@@ -366,27 +367,86 @@ gv_plexorg_short(int org)
}
}
-/* Get a new drive object. */
-struct gv_drive *
-gv_new_drive(int max, char *token[])
+struct gv_sd *
+gv_alloc_sd(void)
{
- struct gv_drive *d;
- int j, errors;
- char *ptr;
+ struct gv_sd *s;
- if (token[1] == NULL || *token[1] == '\0')
+#ifdef _KERNEL
+ s = g_malloc(sizeof(struct gv_sd), M_NOWAIT);
+#else
+ s = malloc(sizeof(struct gv_sd));
+#endif
+ if (s == NULL)
return (NULL);
+ bzero(s, sizeof(struct gv_sd));
+ s->plex_offset = -1;
+ s->size = -1;
+ s->drive_offset = -1;
+ return (s);
+}
-#ifdef _KERNEL
- d = g_malloc(sizeof(struct gv_drive), M_WAITOK | M_ZERO);
+struct gv_drive *
+gv_alloc_drive(void)
+{
+ struct gv_drive *d;
+#ifdef _KERNEL
+ d = g_malloc(sizeof(struct gv_drive), M_NOWAIT);
#else
d = malloc(sizeof(struct gv_drive));
+#endif
if (d == NULL)
return (NULL);
bzero(d, sizeof(struct gv_drive));
+ return (d);
+}
+
+struct gv_volume *
+gv_alloc_volume(void)
+{
+ struct gv_volume *v;
+
+#ifdef _KERNEL
+ v = g_malloc(sizeof(struct gv_volume), M_NOWAIT);
+#else
+ v = malloc(sizeof(struct gv_volume));
#endif
+ if (v == NULL)
+ return (NULL);
+ bzero(v, sizeof(struct gv_volume));
+ return (v);
+}
+
+struct gv_plex *
+gv_alloc_plex(void)
+{
+ struct gv_plex *p;
+#ifdef _KERNEL
+ p = g_malloc(sizeof(struct gv_plex), M_NOWAIT);
+#else
+ p = malloc(sizeof(struct gv_plex));
+#endif
+ if (p == NULL)
+ return (NULL);
+ bzero(p, sizeof(struct gv_plex));
+ return (p);
+}
+
+/* Get a new drive object. */
+struct gv_drive *
+gv_new_drive(int max, char *token[])
+{
+ struct gv_drive *d;
+ int j, errors;
+ char *ptr;
+
+ if (token[1] == NULL || *token[1] == '\0')
+ return (NULL);
+ d = gv_alloc_drive();
+ if (d == NULL)
+ return (NULL);
errors = 0;
for (j = 1; j < max; j++) {
if (!strcmp(token[j], "state")) {
@@ -406,10 +466,10 @@ gv_new_drive(int max, char *token[])
if (strncmp(ptr, "/dev/", 5) == 0)
ptr += 5;
- strncpy(d->device, ptr, GV_MAXDRIVENAME);
+ strlcpy(d->device, ptr, sizeof(d->device));
} else {
/* We assume this is the drive name. */
- strncpy(d->name, token[j], GV_MAXDRIVENAME);
+ strlcpy(d->name, token[j], sizeof(d->name));
}
}
@@ -434,15 +494,9 @@ gv_new_volume(int max, char *token[])
if (token[1] == NULL || *token[1] == '\0')
return (NULL);
-#ifdef _KERNEL
- v = g_malloc(sizeof(struct gv_volume), M_WAITOK | M_ZERO);
-
-#else
- v = malloc(sizeof(struct gv_volume));
+ v = gv_alloc_volume();
if (v == NULL)
return (NULL);
- bzero(v, sizeof(struct gv_volume));
-#endif
errors = 0;
for (j = 1; j < max; j++) {
@@ -455,7 +509,7 @@ gv_new_volume(int max, char *token[])
v->state = gv_volstatei(token[j]);
} else {
/* We assume this is the volume name. */
- strncpy(v->name, token[j], GV_MAXVOLNAME);
+ strlcpy(v->name, token[j], sizeof(v->name));
}
}
@@ -480,14 +534,9 @@ gv_new_plex(int max, char *token[])
if (token[1] == NULL || *token[1] == '\0')
return (NULL);
-#ifdef _KERNEL
- p = g_malloc(sizeof(struct gv_plex), M_WAITOK | M_ZERO);
-#else
- p = malloc(sizeof(struct gv_plex));
+ p = gv_alloc_plex();
if (p == NULL)
return (NULL);
- bzero(p, sizeof(struct gv_plex));
-#endif
errors = 0;
for (j = 1; j < max; j++) {
@@ -497,7 +546,7 @@ gv_new_plex(int max, char *token[])
errors++;
break;
}
- strncpy(p->name, token[j], GV_MAXPLEXNAME);
+ strlcpy(p->name, token[j], sizeof(p->name));
} else if (!strcmp(token[j], "org")) {
j++;
if (j >= max) {
@@ -532,7 +581,7 @@ gv_new_plex(int max, char *token[])
errors++;
break;
}
- strncpy(p->volume, token[j], GV_MAXVOLNAME);
+ strlcpy(p->volume, token[j], sizeof(p->volume));
} else {
errors++;
break;
@@ -547,6 +596,8 @@ gv_new_plex(int max, char *token[])
return (p);
}
+
+
/* Get a new subdisk object. */
struct gv_sd *
gv_new_sd(int max, char *token[])
@@ -555,20 +606,12 @@ gv_new_sd(int max, char *token[])
int j, errors;
if (token[1] == NULL || *token[1] == '\0')
- return NULL;
+ return (NULL);
-#ifdef _KERNEL
- s = g_malloc(sizeof(struct gv_sd), M_WAITOK | M_ZERO);
-#else
- s = malloc(sizeof(struct gv_sd));
+ s = gv_alloc_sd();
if (s == NULL)
- return NULL;
- bzero(s, sizeof(struct gv_sd));
-#endif
+ return (NULL);
- s->plex_offset = -1;
- s->size = -1;
- s->drive_offset = -1;
errors = 0;
for (j = 1; j < max; j++) {
if (!strcmp(token[j], "name")) {
@@ -577,21 +620,21 @@ gv_new_sd(int max, char *token[])
errors++;
break;
}
- strncpy(s->name, token[j], GV_MAXSDNAME);
+ strlcpy(s->name, token[j], sizeof(s->name));
} else if (!strcmp(token[j], "drive")) {
j++;
if (j >= max) {
errors++;
break;
}
- strncpy(s->drive, token[j], GV_MAXDRIVENAME);
+ strlcpy(s->drive, token[j], sizeof(s->drive));
} else if (!strcmp(token[j], "plex")) {
j++;
if (j >= max) {
errors++;
break;
}
- strncpy(s->plex, token[j], GV_MAXPLEXNAME);
+ strlcpy(s->plex, token[j], sizeof(s->plex));
} else if (!strcmp(token[j], "state")) {
j++;
if (j >= max) {
diff --git a/sys/geom/vinum/geom_vinum_share.h b/sys/geom/vinum/geom_vinum_share.h
index f15f45d..5646d6b 100644
--- a/sys/geom/vinum/geom_vinum_share.h
+++ b/sys/geom/vinum/geom_vinum_share.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -41,6 +41,10 @@ enum {
off_t gv_sizespec(char *);
int gv_tokenize(char *, char **, int);
+struct gv_sd *gv_alloc_sd(void);
+struct gv_volume *gv_alloc_volume(void);
+struct gv_plex *gv_alloc_plex(void);
+struct gv_drive *gv_alloc_drive(void);
struct gv_drive *gv_new_drive(int, char **);
struct gv_plex *gv_new_plex(int, char **);
struct gv_sd *gv_new_sd(int, char **);
diff --git a/sys/geom/vinum/geom_vinum_state.c b/sys/geom/vinum/geom_vinum_state.c
index db40390..568c784 100644
--- a/sys/geom/vinum/geom_vinum_state.c
+++ b/sys/geom/vinum/geom_vinum_state.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,8 +27,6 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/param.h>
-#include <sys/kernel.h>
#include <sys/libkern.h>
#include <sys/malloc.h>
@@ -43,8 +41,10 @@ gv_setstate(struct g_geom *gp, struct gctl_req *req)
struct gv_softc *sc;
struct gv_sd *s;
struct gv_drive *d;
+ struct gv_volume *v;
+ struct gv_plex *p;
char *obj, *state;
- int err, f, *flags, newstate, type;
+ int f, *flags, type;
f = 0;
obj = gctl_get_param(req, "object", NULL);
@@ -72,43 +72,52 @@ gv_setstate(struct g_geom *gp, struct gctl_req *req)
type = gv_object_type(sc, obj);
switch (type) {
case GV_TYPE_VOL:
+ if (gv_volstatei(state) < 0) {
+ gctl_error(req, "invalid volume state '%s'", state);
+ break;
+ }
+ v = gv_find_vol(sc, obj);
+ gv_post_event(sc, GV_EVENT_SET_VOL_STATE, v, NULL,
+ gv_volstatei(state), f);
+ break;
+
case GV_TYPE_PLEX:
- gctl_error(req, "volume or plex state cannot be set currently");
+ if (gv_plexstatei(state) < 0) {
+ gctl_error(req, "invalid plex state '%s'", state);
+ break;
+ }
+ p = gv_find_plex(sc, obj);
+ gv_post_event(sc, GV_EVENT_SET_PLEX_STATE, p, NULL,
+ gv_plexstatei(state), f);
break;
case GV_TYPE_SD:
- newstate = gv_sdstatei(state);
- if (newstate < 0) {
+ if (gv_sdstatei(state) < 0) {
gctl_error(req, "invalid subdisk state '%s'", state);
break;
}
s = gv_find_sd(sc, obj);
- err = gv_set_sd_state(s, newstate, f);
- if (err)
- gctl_error(req, "cannot set subdisk state");
+ gv_post_event(sc, GV_EVENT_SET_SD_STATE, s, NULL,
+ gv_sdstatei(state), f);
break;
case GV_TYPE_DRIVE:
- newstate = gv_drivestatei(state);
- if (newstate < 0) {
+ if (gv_drivestatei(state) < 0) {
gctl_error(req, "invalid drive state '%s'", state);
break;
}
d = gv_find_drive(sc, obj);
- err = gv_set_drive_state(d, newstate, f);
- if (err)
- gctl_error(req, "cannot set drive state");
+ gv_post_event(sc, GV_EVENT_SET_DRIVE_STATE, d, NULL,
+ gv_drivestatei(state), f);
break;
default:
gctl_error(req, "unknown object '%s'", obj);
break;
}
-
- return;
}
-/* Update drive state; return 0 if the state changes, otherwise -1. */
+/* Update drive state; return 0 if the state changes, otherwise error. */
int
gv_set_drive_state(struct gv_drive *d, int newstate, int flags)
{
@@ -123,9 +132,9 @@ gv_set_drive_state(struct gv_drive *d, int newstate, int flags)
return (0);
/* We allow to take down an open drive only with force. */
- if ((newstate == GV_DRIVE_DOWN) && gv_is_open(d->geom) &&
+ if ((newstate == GV_DRIVE_DOWN) && gv_consumer_is_open(d->consumer) &&
(!(flags & GV_SETSTATE_FORCE)))
- return (-1);
+ return (GV_ERR_ISBUSY);
d->state = newstate;
@@ -136,7 +145,7 @@ gv_set_drive_state(struct gv_drive *d, int newstate, int flags)
/* Save the config back to disk. */
if (flags & GV_SETSTATE_CONFIG)
- gv_save_config_all(d->vinumconf);
+ gv_save_config(d->vinumconf);
return (0);
}
@@ -165,14 +174,24 @@ gv_set_sd_state(struct gv_sd *s, int newstate, int flags)
* force.
*/
if ((s->plex_sc != NULL) && !(flags & GV_SETSTATE_FORCE))
- return (-1);
+ return (GV_ERR_ISATTACHED);
+ break;
+
+ case GV_SD_REVIVING:
+ case GV_SD_INITIALIZING:
+ /*
+ * Only do this if we're forced, since it usually is done
+ * internally, and then we do use the force flag.
+ */
+ if (!flags & GV_SETSTATE_FORCE)
+ return (GV_ERR_SETSTATE);
break;
case GV_SD_UP:
/* We can't bring the subdisk up if our drive is dead. */
d = s->drive_sc;
if ((d == NULL) || (d->state != GV_DRIVE_UP))
- return (-1);
+ return (GV_ERR_SETSTATE);
/* Check from where we want to be brought up. */
switch (s->state) {
@@ -201,12 +220,15 @@ gv_set_sd_state(struct gv_sd *s, int newstate, int flags)
if (p->org != GV_PLEX_RAID5)
break;
- else if (flags & GV_SETSTATE_FORCE)
+ else if (s->flags & GV_SD_CANGOUP) {
+ s->flags &= ~GV_SD_CANGOUP;
+ break;
+ } else if (flags & GV_SETSTATE_FORCE)
break;
else
s->state = GV_SD_STALE;
- status = -1;
+ status = GV_ERR_SETSTATE;
break;
case GV_SD_STALE:
@@ -221,21 +243,24 @@ gv_set_sd_state(struct gv_sd *s, int newstate, int flags)
if (p == NULL || flags & GV_SETSTATE_FORCE)
break;
- if ((p->org != GV_PLEX_RAID5) &&
- (p->vol_sc->plexcount == 1))
+ if ((p->org != GV_PLEX_RAID5 &&
+ p->vol_sc->plexcount == 1) ||
+ (p->flags & GV_PLEX_SYNCING &&
+ p->synced > 0 &&
+ p->org == GV_PLEX_RAID5))
break;
else
- return (-1);
+ return (GV_ERR_SETSTATE);
default:
- return (-1);
+ return (GV_ERR_INVSTATE);
}
break;
/* Other state transitions are only possible with force. */
default:
if (!(flags & GV_SETSTATE_FORCE))
- return (-1);
+ return (GV_ERR_SETSTATE);
}
/* We can change the state and do it. */
@@ -248,11 +273,102 @@ gv_set_sd_state(struct gv_sd *s, int newstate, int flags)
/* Save the config back to disk. */
if (flags & GV_SETSTATE_CONFIG)
- gv_save_config_all(s->vinumconf);
+ gv_save_config(s->vinumconf);
return (status);
}
+int
+gv_set_plex_state(struct gv_plex *p, int newstate, int flags)
+{
+ struct gv_volume *v;
+ int oldstate, plexdown;
+
+ KASSERT(p != NULL, ("gv_set_plex_state: NULL p"));
+
+ oldstate = p->state;
+ v = p->vol_sc;
+ plexdown = 0;
+
+ if (newstate == oldstate)
+ return (0);
+
+ switch (newstate) {
+ case GV_PLEX_UP:
+ /* Let update_plex handle if the plex can come up */
+ gv_update_plex_state(p);
+ if (p->state != GV_PLEX_UP && !(flags & GV_SETSTATE_FORCE))
+ return (GV_ERR_SETSTATE);
+ p->state = newstate;
+ break;
+ case GV_PLEX_DOWN:
+ /*
+ * Set state to GV_PLEX_DOWN only if no-one is using the plex,
+ * or if the state is forced.
+ */
+ if (v != NULL) {
+ /* If the only one up, force is needed. */
+ plexdown = gv_plexdown(v);
+ if ((v->plexcount == 1 ||
+ (v->plexcount - plexdown == 1)) &&
+ ((flags & GV_SETSTATE_FORCE) == 0))
+ return (GV_ERR_SETSTATE);
+ }
+ p->state = newstate;
+ break;
+ case GV_PLEX_DEGRADED:
+ /* Only used internally, so we have to be forced. */
+ if (flags & GV_SETSTATE_FORCE)
+ p->state = newstate;
+ break;
+ }
+
+ /* Update our volume if we have one. */
+ if (v != NULL)
+ gv_update_vol_state(v);
+
+ /* Save config. */
+ if (flags & GV_SETSTATE_CONFIG)
+ gv_save_config(p->vinumconf);
+ return (0);
+}
+
+int
+gv_set_vol_state(struct gv_volume *v, int newstate, int flags)
+{
+ int oldstate;
+
+ KASSERT(v != NULL, ("gv_set_vol_state: NULL v"));
+
+ oldstate = v->state;
+
+ if (newstate == oldstate)
+ return (0);
+
+ switch (newstate) {
+ case GV_VOL_UP:
+ /* Let update handle if the volume can come up. */
+ gv_update_vol_state(v);
+ if (v->state != GV_VOL_UP && !(flags & GV_SETSTATE_FORCE))
+ return (GV_ERR_SETSTATE);
+ v->state = newstate;
+ break;
+ case GV_VOL_DOWN:
+ /*
+ * Set state to GV_VOL_DOWN only if no-one is using the volume,
+ * or if the state should be forced.
+ */
+ if (!gv_provider_is_open(v->provider) &&
+ !(flags & GV_SETSTATE_FORCE))
+ return (GV_ERR_ISBUSY);
+ v->state = newstate;
+ break;
+ }
+ /* Save config */
+ if (flags & GV_SETSTATE_CONFIG)
+ gv_save_config(v->vinumconf);
+ return (0);
+}
/* Update the state of a subdisk based on its environment. */
void
@@ -268,15 +384,19 @@ gv_update_sd_state(struct gv_sd *s)
oldstate = s->state;
/* If our drive isn't up we cannot be up either. */
- if (d->state != GV_DRIVE_UP)
+ if (d->state != GV_DRIVE_UP) {
s->state = GV_SD_DOWN;
/* If this subdisk was just created, we assume it is good.*/
- else if (s->flags & GV_SD_NEWBORN) {
+ } else if (s->flags & GV_SD_NEWBORN) {
s->state = GV_SD_UP;
s->flags &= ~GV_SD_NEWBORN;
- } else if (s->state != GV_SD_UP)
- s->state = GV_SD_STALE;
- else
+ } else if (s->state != GV_SD_UP) {
+ if (s->flags & GV_SD_CANGOUP) {
+ s->state = GV_SD_UP;
+ s->flags &= ~GV_SD_CANGOUP;
+ } else
+ s->state = GV_SD_STALE;
+ } else
s->state = GV_SD_UP;
if (s->state != oldstate)
@@ -292,6 +412,7 @@ gv_update_sd_state(struct gv_sd *s)
void
gv_update_plex_state(struct gv_plex *p)
{
+ struct gv_sd *s;
int sdstates;
int oldstate;
@@ -316,13 +437,24 @@ gv_update_plex_state(struct gv_plex *p)
/* Some of our subdisks are initializing. */
} else if (sdstates & GV_SD_INITSTATE) {
- if (p->flags & GV_PLEX_SYNCING)
+
+ if (p->flags & GV_PLEX_SYNCING ||
+ p->flags & GV_PLEX_REBUILDING)
p->state = GV_PLEX_DEGRADED;
else
p->state = GV_PLEX_DOWN;
} else
p->state = GV_PLEX_DOWN;
+ if (p->state == GV_PLEX_UP) {
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ if (s->flags & GV_SD_GROW) {
+ p->state = GV_PLEX_GROWABLE;
+ break;
+ }
+ }
+ }
+
if (p->state != oldstate)
G_VINUM_DEBUG(1, "plex %s state change: %s -> %s", p->name,
gv_plexstate(oldstate), gv_plexstate(p->state));
diff --git a/sys/geom/vinum/geom_vinum_subr.c b/sys/geom/vinum/geom_vinum_subr.c
index 848fbc7..70c7f3f 100644
--- a/sys/geom/vinum/geom_vinum_subr.c
+++ b/sys/geom/vinum/geom_vinum_subr.c
@@ -1,5 +1,6 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
+ * Copyright (c) 2007, 2009 Ulf Lilleengen
* Copyright (c) 1997, 1998, 1999
* Nan Yang Computer Services Limited. All rights reserved.
*
@@ -42,59 +43,28 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/libkern.h>
#include <sys/malloc.h>
#include <sys/systm.h>
#include <geom/geom.h>
-#include <geom/geom_int.h>
#include <geom/vinum/geom_vinum_var.h>
#include <geom/vinum/geom_vinum.h>
#include <geom/vinum/geom_vinum_share.h>
-static off_t gv_plex_smallest_sd(struct gv_plex *, off_t);
+int gv_drive_is_newer(struct gv_softc *, struct gv_drive *);
+static off_t gv_plex_smallest_sd(struct gv_plex *);
-/* Find the VINUM class and it's associated geom. */
-struct g_geom *
-find_vinum_geom(void)
-{
- struct g_class *mp;
- struct g_geom *gp;
-
- g_topology_assert();
-
- gp = NULL;
-
- LIST_FOREACH(mp, &g_classes, class) {
- if (!strcmp(mp->name, "VINUM")) {
- gp = LIST_FIRST(&mp->geom);
- break;
- }
- }
-
- return (gp);
-}
-
-/*
- * Parse the vinum config provided in *buf and store it in *gp's softc.
- * If parameter 'merge' is non-zero, then the given config is merged into
- * *gp.
- */
void
-gv_parse_config(struct gv_softc *sc, u_char *buf, int merge)
+gv_parse_config(struct gv_softc *sc, char *buf, struct gv_drive *d)
{
char *aptr, *bptr, *cptr;
struct gv_volume *v, *v2;
struct gv_plex *p, *p2;
struct gv_sd *s, *s2;
- int tokens;
+ int error, is_newer, tokens;
char *token[GV_MAXARGS];
- g_topology_assert();
-
- KASSERT(sc != NULL, ("gv_parse_config: NULL softc"));
+ is_newer = gv_drive_is_newer(sc, d);
/* Until the end of the string *buf. */
for (aptr = buf; *aptr != '\0'; aptr = bptr) {
@@ -109,64 +79,95 @@ gv_parse_config(struct gv_softc *sc, u_char *buf, int merge)
tokens = gv_tokenize(cptr, token, GV_MAXARGS);
- if (tokens > 0) {
- if (!strcmp(token[0], "volume")) {
- v = gv_new_volume(tokens, token);
- if (v == NULL) {
- G_VINUM_DEBUG(0, "failed volume");
- break;
- }
+ if (tokens <= 0)
+ continue;
- if (merge) {
- v2 = gv_find_vol(sc, v->name);
- if (v2 != NULL) {
- g_free(v);
- continue;
- }
+ if (!strcmp(token[0], "volume")) {
+ v = gv_new_volume(tokens, token);
+ if (v == NULL) {
+ G_VINUM_DEBUG(0, "config parse failed volume");
+ break;
+ }
+
+ v2 = gv_find_vol(sc, v->name);
+ if (v2 != NULL) {
+ if (is_newer) {
+ v2->state = v->state;
+ G_VINUM_DEBUG(2, "newer volume found!");
}
+ g_free(v);
+ continue;
+ }
- v->vinumconf = sc;
- LIST_INIT(&v->plexes);
- LIST_INSERT_HEAD(&sc->volumes, v, volume);
+ gv_create_volume(sc, v);
- } else if (!strcmp(token[0], "plex")) {
- p = gv_new_plex(tokens, token);
- if (p == NULL) {
- G_VINUM_DEBUG(0, "failed plex");
- break;
- }
+ } else if (!strcmp(token[0], "plex")) {
+ p = gv_new_plex(tokens, token);
+ if (p == NULL) {
+ G_VINUM_DEBUG(0, "config parse failed plex");
+ break;
+ }
- if (merge) {
- p2 = gv_find_plex(sc, p->name);
- if (p2 != NULL) {
- g_free(p);
- continue;
- }
+ p2 = gv_find_plex(sc, p->name);
+ if (p2 != NULL) {
+ /* XXX */
+ if (is_newer) {
+ p2->state = p->state;
+ G_VINUM_DEBUG(2, "newer plex found!");
}
+ g_free(p);
+ continue;
+ }
- p->vinumconf = sc;
- LIST_INIT(&p->subdisks);
- LIST_INSERT_HEAD(&sc->plexes, p, plex);
+ error = gv_create_plex(sc, p);
+ if (error)
+ continue;
+ /*
+ * These flags were set in gv_create_plex() and are not
+ * needed here (on-disk config parsing).
+ */
+ p->flags &= ~GV_PLEX_ADDED;
+ p->flags &= ~GV_PLEX_NEWBORN;
- } else if (!strcmp(token[0], "sd")) {
- s = gv_new_sd(tokens, token);
+ } else if (!strcmp(token[0], "sd")) {
+ s = gv_new_sd(tokens, token);
- if (s == NULL) {
- G_VINUM_DEBUG(0, "failed subdisk");
- break;
- }
+ if (s == NULL) {
+ G_VINUM_DEBUG(0, "config parse failed subdisk");
+ break;
+ }
- if (merge) {
- s2 = gv_find_sd(sc, s->name);
- if (s2 != NULL) {
- g_free(s);
- continue;
- }
+ s2 = gv_find_sd(sc, s->name);
+ if (s2 != NULL) {
+ /* XXX */
+ if (is_newer) {
+ s2->state = s->state;
+ G_VINUM_DEBUG(2, "newer subdisk found!");
}
-
- s->vinumconf = sc;
- LIST_INSERT_HEAD(&sc->subdisks, s, sd);
+ g_free(s);
+ continue;
}
+
+ /*
+ * Signal that this subdisk was tasted, and could
+ * possibly reference a drive that isn't in our config
+ * yet.
+ */
+ s->flags |= GV_SD_TASTED;
+
+ if (s->state == GV_SD_UP)
+ s->flags |= GV_SD_CANGOUP;
+
+ error = gv_create_sd(sc, s);
+ if (error)
+ continue;
+
+ /*
+ * This flag was set in gv_create_sd() and is not
+ * needed here (on-disk config parsing).
+ */
+ s->flags &= ~GV_SD_NEWBORN;
+ s->flags &= ~GV_SD_GROW;
}
}
}
@@ -183,8 +184,6 @@ gv_format_config(struct gv_softc *sc, struct sbuf *sb, int ondisk, char *prefix)
struct gv_plex *p;
struct gv_volume *v;
- g_topology_assert();
-
/*
* We don't need the drive configuration if we're not writing the
* config to disk.
@@ -233,17 +232,20 @@ gv_format_config(struct gv_softc *sc, struct sbuf *sb, int ondisk, char *prefix)
sbuf_printf(sb, " state %s", gv_sdstate(s->state));
sbuf_printf(sb, "\n");
}
-
- return;
}
static off_t
-gv_plex_smallest_sd(struct gv_plex *p, off_t smallest)
+gv_plex_smallest_sd(struct gv_plex *p)
{
struct gv_sd *s;
+ off_t smallest;
KASSERT(p != NULL, ("gv_plex_smallest_sd: NULL p"));
+ s = LIST_FIRST(&p->subdisks);
+ if (s == NULL)
+ return (-1);
+ smallest = s->size;
LIST_FOREACH(s, &p->subdisks, in_plex) {
if (s->size < smallest)
smallest = s->size;
@@ -251,12 +253,29 @@ gv_plex_smallest_sd(struct gv_plex *p, off_t smallest)
return (smallest);
}
+/* Walk over plexes in a volume and count how many are down. */
int
-gv_sd_to_plex(struct gv_plex *p, struct gv_sd *s, int check)
+gv_plexdown(struct gv_volume *v)
{
- struct gv_sd *s2;
+ int plexdown;
+ struct gv_plex *p;
- g_topology_assert();
+ KASSERT(v != NULL, ("gv_plexdown: NULL v"));
+
+ plexdown = 0;
+
+ LIST_FOREACH(p, &v->plexes, plex) {
+ if (p->state == GV_PLEX_DOWN)
+ plexdown++;
+ }
+ return (plexdown);
+}
+
+int
+gv_sd_to_plex(struct gv_sd *s, struct gv_plex *p)
+{
+ struct gv_sd *s2;
+ off_t psizeorig, remainder, smallest;
/* If this subdisk was already given to this plex, do nothing. */
if (s->plex_sc == p)
@@ -264,15 +283,56 @@ gv_sd_to_plex(struct gv_plex *p, struct gv_sd *s, int check)
/* Check correct size of this subdisk. */
s2 = LIST_FIRST(&p->subdisks);
- if (s2 != NULL && gv_is_striped(p) && (s2->size != s->size)) {
- G_VINUM_DEBUG(0, "need equal sized subdisks for "
- "this plex organisation - %s (%jd) <-> %s (%jd)",
- s2->name, s2->size, s->name, s->size);
- return (-1);
+ /* Adjust the subdisk-size if necessary. */
+ if (s2 != NULL && gv_is_striped(p)) {
+ /* First adjust to the stripesize. */
+ remainder = s->size % p->stripesize;
+
+ if (remainder) {
+ G_VINUM_DEBUG(1, "size of sd %s is not a "
+ "multiple of plex stripesize, taking off "
+ "%jd bytes", s->name,
+ (intmax_t)remainder);
+ gv_adjust_freespace(s, remainder);
+ }
+
+ smallest = gv_plex_smallest_sd(p);
+ /* Then take off extra if other subdisks are smaller. */
+ remainder = s->size - smallest;
+
+ /*
+ * Don't allow a remainder below zero for running plexes, it's too
+ * painful, and if someone were to accidentally do this, the
+ * resulting array might be smaller than the original... not god
+ */
+ if (remainder < 0) {
+ if (!(p->flags & GV_PLEX_NEWBORN)) {
+ G_VINUM_DEBUG(0, "sd %s too small for plex %s!",
+ s->name, p->name);
+ return (GV_ERR_BADSIZE);
+ }
+ /* Adjust other subdisks. */
+ LIST_FOREACH(s2, &p->subdisks, in_plex) {
+ G_VINUM_DEBUG(1, "size of sd %s is to big, "
+ "taking off %jd bytes", s->name,
+ (intmax_t)remainder);
+ gv_adjust_freespace(s2, (remainder * -1));
+ }
+ } else if (remainder > 0) {
+ G_VINUM_DEBUG(1, "size of sd %s is to big, "
+ "taking off %jd bytes", s->name,
+ (intmax_t)remainder);
+ gv_adjust_freespace(s, remainder);
+ }
}
/* Find the correct plex offset for this subdisk, if needed. */
if (s->plex_offset == -1) {
+ /*
+ * First set it to 0 to catch the case where we had a detached
+ * subdisk that didn't get any good offset.
+ */
+ s->plex_offset = 0;
if (p->sdcount) {
LIST_FOREACH(s2, &p->subdisks, in_plex) {
if (gv_is_striped(p))
@@ -282,25 +342,7 @@ gv_sd_to_plex(struct gv_plex *p, struct gv_sd *s, int check)
s->plex_offset = s2->plex_offset +
s2->size;
}
- } else
- s->plex_offset = 0;
- }
-
- p->sdcount++;
-
- /* Adjust the size of our plex. */
- switch (p->org) {
- case GV_PLEX_CONCAT:
- case GV_PLEX_STRIPED:
- p->size += s->size;
- break;
-
- case GV_PLEX_RAID5:
- p->size = (p->sdcount - 1) * gv_plex_smallest_sd(p, s->size);
- break;
-
- default:
- break;
+ }
}
/* There are no subdisks for this plex yet, just insert it. */
@@ -321,6 +363,29 @@ gv_sd_to_plex(struct gv_plex *p, struct gv_sd *s, int check)
}
s->plex_sc = p;
+ /* Adjust the size of our plex. We check if the plex misses a subdisk,
+ * so we don't make the plex smaller than it actually should be.
+ */
+ psizeorig = p->size;
+ p->size = gv_plex_size(p);
+ /* Make sure the size is not changed. */
+ if (p->sddetached > 0) {
+ if (p->size < psizeorig) {
+ p->size = psizeorig;
+ /* We make sure wee need another subdisk. */
+ if (p->sddetached == 1)
+ p->sddetached++;
+ }
+ p->sddetached--;
+ } else {
+ if ((p->org == GV_PLEX_RAID5 ||
+ p->org == GV_PLEX_STRIPED) &&
+ !(p->flags & GV_PLEX_NEWBORN) &&
+ p->state >= GV_PLEX_DEGRADED) {
+ s->flags |= GV_SD_GROW;
+ }
+ p->sdcount++;
+ }
return (0);
}
@@ -328,21 +393,32 @@ gv_sd_to_plex(struct gv_plex *p, struct gv_sd *s, int check)
void
gv_update_vol_size(struct gv_volume *v, off_t size)
{
- struct g_geom *gp;
- struct g_provider *pp;
-
if (v == NULL)
return;
+ if (v->provider != NULL) {
+ g_topology_lock();
+ v->provider->mediasize = size;
+ g_topology_unlock();
+ }
+ v->size = size;
+}
- gp = v->geom;
- if (gp == NULL)
- return;
+/* Return how many subdisks that constitute the original plex. */
+int
+gv_sdcount(struct gv_plex *p, int growing)
+{
+ struct gv_sd *s;
+ int sdcount;
- LIST_FOREACH(pp, &gp->provider, provider) {
- pp->mediasize = size;
+ sdcount = p->sdcount;
+ if (growing) {
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ if (s->flags & GV_SD_GROW)
+ sdcount--;
+ }
}
- v->size = size;
+ return (sdcount);
}
/* Calculates the plex size. */
@@ -351,14 +427,13 @@ gv_plex_size(struct gv_plex *p)
{
struct gv_sd *s;
off_t size;
+ int sdcount;
KASSERT(p != NULL, ("gv_plex_size: NULL p"));
- if (p->sdcount == 0)
- return (0);
-
/* Adjust the size of our plex. */
size = 0;
+ sdcount = gv_sdcount(p, 1);
switch (p->org) {
case GV_PLEX_CONCAT:
LIST_FOREACH(s, &p->subdisks, in_plex)
@@ -366,11 +441,11 @@ gv_plex_size(struct gv_plex *p)
break;
case GV_PLEX_STRIPED:
s = LIST_FIRST(&p->subdisks);
- size = p->sdcount * s->size;
+ size = ((s != NULL) ? (sdcount * s->size) : 0);
break;
case GV_PLEX_RAID5:
s = LIST_FIRST(&p->subdisks);
- size = (p->sdcount - 1) * s->size;
+ size = ((s != NULL) ? ((sdcount - 1) * s->size) : 0);
break;
}
@@ -391,7 +466,7 @@ gv_vol_size(struct gv_volume *v)
return (0);
minplexsize = p->size;
- LIST_FOREACH(p, &v->plexes, plex) {
+ LIST_FOREACH(p, &v->plexes, in_volume) {
if (p->size < minplexsize) {
minplexsize = p->size;
}
@@ -408,12 +483,9 @@ gv_update_plex_config(struct gv_plex *p)
KASSERT(p != NULL, ("gv_update_plex_config: NULL p"));
- /* This is what we want the plex to be. */
- state = GV_PLEX_UP;
-
/* The plex was added to an already running volume. */
if (p->flags & GV_PLEX_ADDED)
- state = GV_PLEX_DOWN;
+ gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE);
switch (p->org) {
case GV_PLEX_STRIPED:
@@ -430,7 +502,7 @@ gv_update_plex_config(struct gv_plex *p)
if (required_sds) {
if (p->sdcount < required_sds) {
- state = GV_PLEX_DOWN;
+ gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE);
}
/*
@@ -442,12 +514,13 @@ gv_update_plex_config(struct gv_plex *p)
G_VINUM_DEBUG(0, "subdisk size mismatch %s"
"(%jd) <> %s (%jd)", s->name, s->size,
s2->name, s2->size);
- state = GV_PLEX_DOWN;
+ gv_set_plex_state(p, GV_PLEX_DOWN,
+ GV_SETSTATE_FORCE);
}
}
- /* Trim subdisk sizes so that they match the stripe size. */
LIST_FOREACH(s, &p->subdisks, in_plex) {
+ /* Trim subdisk sizes to match the stripe size. */
remainder = s->size % p->stripesize;
if (remainder) {
G_VINUM_DEBUG(1, "size of sd %s is not a "
@@ -458,41 +531,32 @@ gv_update_plex_config(struct gv_plex *p)
}
}
- /* Adjust the size of our plex. */
- if (p->sdcount > 0) {
- p->size = 0;
- switch (p->org) {
- case GV_PLEX_CONCAT:
- LIST_FOREACH(s, &p->subdisks, in_plex)
- p->size += s->size;
- break;
-
- case GV_PLEX_STRIPED:
- s = LIST_FIRST(&p->subdisks);
- p->size = p->sdcount * s->size;
- break;
-
- case GV_PLEX_RAID5:
- s = LIST_FIRST(&p->subdisks);
- p->size = (p->sdcount - 1) * s->size;
- break;
-
- default:
- break;
- }
- }
-
+ p->size = gv_plex_size(p);
if (p->sdcount == 0)
- state = GV_PLEX_DOWN;
- else if ((p->flags & GV_PLEX_ADDED) ||
- ((p->org == GV_PLEX_RAID5) && (p->flags & GV_PLEX_NEWBORN))) {
+ gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE);
+ else if (p->org == GV_PLEX_RAID5 && p->flags & GV_PLEX_NEWBORN) {
+ LIST_FOREACH(s, &p->subdisks, in_plex)
+ gv_set_sd_state(s, GV_SD_UP, GV_SETSTATE_FORCE);
+ /* If added to a volume, we want the plex to be down. */
+ state = (p->flags & GV_PLEX_ADDED) ? GV_PLEX_DOWN : GV_PLEX_UP;
+ gv_set_plex_state(p, state, GV_SETSTATE_FORCE);
+ p->flags &= ~GV_PLEX_ADDED;
+ } else if (p->flags & GV_PLEX_ADDED) {
LIST_FOREACH(s, &p->subdisks, in_plex)
- s->state = GV_SD_STALE;
+ gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE);
+ gv_set_plex_state(p, GV_PLEX_DOWN, GV_SETSTATE_FORCE);
p->flags &= ~GV_PLEX_ADDED;
- p->flags &= ~GV_PLEX_NEWBORN;
- state = GV_PLEX_DOWN;
+ } else if (p->state == GV_PLEX_UP) {
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ if (s->flags & GV_SD_GROW) {
+ gv_set_plex_state(p, GV_PLEX_GROWABLE,
+ GV_SETSTATE_FORCE);
+ break;
+ }
+ }
}
- p->state = state;
+ /* Our plex is grown up now. */
+ p->flags &= ~GV_PLEX_NEWBORN;
}
/*
@@ -500,76 +564,82 @@ gv_update_plex_config(struct gv_plex *p)
* freelist.
*/
int
-gv_sd_to_drive(struct gv_softc *sc, struct gv_drive *d, struct gv_sd *s,
- char *errstr, int errlen)
+gv_sd_to_drive(struct gv_sd *s, struct gv_drive *d)
{
struct gv_sd *s2;
struct gv_freelist *fl, *fl2;
off_t tmp;
int i;
- g_topology_assert();
-
fl2 = NULL;
- KASSERT(sc != NULL, ("gv_sd_to_drive: NULL softc"));
- KASSERT(d != NULL, ("gv_sd_to_drive: NULL drive"));
- KASSERT(s != NULL, ("gv_sd_to_drive: NULL subdisk"));
- KASSERT(errstr != NULL, ("gv_sd_to_drive: NULL errstr"));
- KASSERT(errlen >= ERRBUFSIZ, ("gv_sd_to_drive: short errlen (%d)",
- errlen));
+ /* Shortcut for "referenced" drives. */
+ if (d->flags & GV_DRIVE_REFERENCED) {
+ s->drive_sc = d;
+ return (0);
+ }
/* Check if this subdisk was already given to this drive. */
- if (s->drive_sc == d)
- return (0);
+ if (s->drive_sc != NULL) {
+ if (s->drive_sc == d) {
+ if (!(s->flags & GV_SD_TASTED)) {
+ return (0);
+ }
+ } else {
+ G_VINUM_DEBUG(0, "can't give sd '%s' to '%s' "
+ "(already on '%s')", s->name, d->name,
+ s->drive_sc->name);
+ return (GV_ERR_ISATTACHED);
+ }
+ }
/* Preliminary checks. */
- if (s->size > d->avail || d->freelist_entries == 0) {
- snprintf(errstr, errlen, "not enough space on '%s' for '%s'",
- d->name, s->name);
- return (-1);
+ if ((s->size > d->avail) || (d->freelist_entries == 0)) {
+ G_VINUM_DEBUG(0, "not enough space on '%s' for '%s'", d->name,
+ s->name);
+ return (GV_ERR_NOSPACE);
}
- /* No size given, autosize it. */
+ /* If no size was given for this subdisk, try to auto-size it... */
if (s->size == -1) {
/* Find the largest available slot. */
LIST_FOREACH(fl, &d->freelist, freelist) {
- if (fl->size >= s->size) {
- s->size = fl->size;
- s->drive_offset = fl->offset;
- fl2 = fl;
- }
+ if (fl->size < s->size)
+ continue;
+ s->size = fl->size;
+ s->drive_offset = fl->offset;
+ fl2 = fl;
}
/* No good slot found? */
if (s->size == -1) {
- snprintf(errstr, errlen, "could not autosize '%s' on "
- "'%s'", s->name, d->name);
- return (-1);
+ G_VINUM_DEBUG(0, "couldn't autosize '%s' on '%s'",
+ s->name, d->name);
+ return (GV_ERR_BADSIZE);
}
/*
- * Check if we have a free slot that's large enough for the given size.
+ * ... or check if we have a free slot that's large enough for the
+ * given size.
*/
} else {
i = 0;
LIST_FOREACH(fl, &d->freelist, freelist) {
- /* Yes, this subdisk fits. */
- if (fl->size >= s->size) {
- i++;
- /* Assign drive offset, if not given. */
- if (s->drive_offset == -1)
- s->drive_offset = fl->offset;
- fl2 = fl;
- break;
- }
+ if (fl->size < s->size)
+ continue;
+ /* Assign drive offset, if not given. */
+ if (s->drive_offset == -1)
+ s->drive_offset = fl->offset;
+ fl2 = fl;
+ i++;
+ break;
}
/* Couldn't find a good free slot. */
if (i == 0) {
- snprintf(errstr, errlen, "free slots to small for '%s' "
- "on '%s'", s->name, d->name);
- return (-1);
+ G_VINUM_DEBUG(0, "free slots to small for '%s' on '%s'",
+ s->name, d->name);
+ return (GV_ERR_NOSPACE);
}
}
@@ -604,9 +674,9 @@ gv_sd_to_drive(struct gv_softc *sc, struct gv_drive *d, struct gv_sd *s,
/* Couldn't find a good free slot. */
if (i == 0) {
- snprintf(errstr, errlen, "given drive_offset for '%s' "
- "won't fit on '%s'", s->name, d->name);
- return (-1);
+ G_VINUM_DEBUG(0, "given drive_offset for '%s' won't fit "
+ "on '%s'", s->name, d->name);
+ return (GV_ERR_NOSPACE);
}
}
@@ -617,49 +687,41 @@ gv_sd_to_drive(struct gv_softc *sc, struct gv_drive *d, struct gv_sd *s,
/* First, adjust the freelist. */
LIST_FOREACH(fl, &d->freelist, freelist) {
+ /* Look for the free slot that we have found before. */
+ if (fl != fl2)
+ continue;
+
+ /* The subdisk starts at the beginning of the free slot. */
+ if (fl->offset == s->drive_offset) {
+ fl->offset += s->size;
+ fl->size -= s->size;
+
+ /* The subdisk uses the whole slot, so remove it. */
+ if (fl->size == 0) {
+ d->freelist_entries--;
+ LIST_REMOVE(fl, freelist);
+ }
+ /*
+ * The subdisk does not start at the beginning of the free
+ * slot.
+ */
+ } else {
+ tmp = fl->offset + fl->size;
+ fl->size = s->drive_offset - fl->offset;
- /* This is the free slot that we have found before. */
- if (fl == fl2) {
-
- /*
- * The subdisk starts at the beginning of the free
- * slot.
- */
- if (fl->offset == s->drive_offset) {
- fl->offset += s->size;
- fl->size -= s->size;
-
- /*
- * The subdisk uses the whole slot, so remove
- * it.
- */
- if (fl->size == 0) {
- d->freelist_entries--;
- LIST_REMOVE(fl, freelist);
- }
/*
- * The subdisk does not start at the beginning of the
- * free slot.
+ * The subdisk didn't use the complete rest of the free
+ * slot, so we need to split it.
*/
- } else {
- tmp = fl->offset + fl->size;
- fl->size = s->drive_offset - fl->offset;
-
- /*
- * The subdisk didn't use the complete rest of
- * the free slot, so we need to split it.
- */
- if (s->drive_offset + s->size != tmp) {
- fl2 = g_malloc(sizeof(*fl2),
- M_WAITOK | M_ZERO);
- fl2->offset = s->drive_offset + s->size;
- fl2->size = tmp - fl2->offset;
- LIST_INSERT_AFTER(fl, fl2, freelist);
- d->freelist_entries++;
- }
+ if (s->drive_offset + s->size != tmp) {
+ fl2 = g_malloc(sizeof(*fl2), M_WAITOK | M_ZERO);
+ fl2->offset = s->drive_offset + s->size;
+ fl2->size = tmp - fl2->offset;
+ LIST_INSERT_AFTER(fl, fl2, freelist);
+ d->freelist_entries++;
}
- break;
}
+ break;
}
/*
@@ -685,6 +747,8 @@ gv_sd_to_drive(struct gv_softc *sc, struct gv_drive *d, struct gv_sd *s,
d->sdcount++;
d->avail -= s->size;
+ s->flags &= ~GV_SD_TASTED;
+
/* Link back from the subdisk to this drive. */
s->drive_sc = d;
@@ -869,17 +933,65 @@ gv_find_drive(struct gv_softc *sc, char *name)
return (NULL);
}
+/* Find a drive given a device. */
+struct gv_drive *
+gv_find_drive_device(struct gv_softc *sc, char *device)
+{
+ struct gv_drive *d;
+
+ LIST_FOREACH(d, &sc->drives, drive) {
+ if(!strcmp(d->device, device))
+ return (d);
+ }
+
+ return (NULL);
+}
+
/* Check if any consumer of the given geom is open. */
int
-gv_is_open(struct g_geom *gp)
+gv_consumer_is_open(struct g_consumer *cp)
{
- struct g_consumer *cp;
+ if (cp == NULL)
+ return (0);
- if (gp == NULL)
+ if (cp->acr || cp->acw || cp->ace)
+ return (1);
+
+ return (0);
+}
+
+int
+gv_provider_is_open(struct g_provider *pp)
+{
+ if (pp == NULL)
return (0);
- LIST_FOREACH(cp, &gp->consumer, consumer) {
- if (cp->acr || cp->acw || cp->ace)
+ if (pp->acr || pp->acw || pp->ace)
+ return (1);
+
+ return (0);
+}
+
+/*
+ * Compare the modification dates of the drives.
+ * Return 1 if a > b, 0 otherwise.
+ */
+int
+gv_drive_is_newer(struct gv_softc *sc, struct gv_drive *d)
+{
+ struct gv_drive *d2;
+ struct timeval *a, *b;
+
+ KASSERT(!LIST_EMPTY(&sc->drives),
+ ("gv_is_drive_newer: empty drive list"));
+
+ a = &d->hdr->label.last_update;
+ LIST_FOREACH(d2, &sc->drives, drive) {
+ if ((d == d2) || (d2->state != GV_DRIVE_UP) ||
+ (d2->hdr == NULL))
+ continue;
+ b = &d2->hdr->label.last_update;
+ if (timevalcmp(a, b, >))
return (1);
}
@@ -915,58 +1027,255 @@ gv_object_type(struct gv_softc *sc, char *name)
return (GV_TYPE_DRIVE);
}
- return (-1);
+ return (GV_ERR_NOTFOUND);
}
void
-gv_kill_drive_thread(struct gv_drive *d)
+gv_setup_objects(struct gv_softc *sc)
{
- if (d->flags & GV_DRIVE_THREAD_ACTIVE) {
- d->flags |= GV_DRIVE_THREAD_DIE;
- wakeup(d);
- while (!(d->flags & GV_DRIVE_THREAD_DEAD))
- tsleep(d, PRIBIO, "gv_die", hz);
- d->flags &= ~GV_DRIVE_THREAD_ACTIVE;
- d->flags &= ~GV_DRIVE_THREAD_DIE;
- d->flags &= ~GV_DRIVE_THREAD_DEAD;
- g_free(d->bqueue);
- d->bqueue = NULL;
- mtx_destroy(&d->bqueue_mtx);
+ struct g_provider *pp;
+ struct gv_volume *v;
+ struct gv_plex *p;
+ struct gv_sd *s;
+ struct gv_drive *d;
+
+ LIST_FOREACH(s, &sc->subdisks, sd) {
+ d = gv_find_drive(sc, s->drive);
+ if (d != NULL)
+ gv_sd_to_drive(s, d);
+ p = gv_find_plex(sc, s->plex);
+ if (p != NULL)
+ gv_sd_to_plex(s, p);
+ gv_update_sd_state(s);
+ }
+
+ LIST_FOREACH(p, &sc->plexes, plex) {
+ gv_update_plex_config(p);
+ v = gv_find_vol(sc, p->volume);
+ if (v != NULL && p->vol_sc != v) {
+ p->vol_sc = v;
+ v->plexcount++;
+ LIST_INSERT_HEAD(&v->plexes, p, in_volume);
+ }
+ gv_update_plex_config(p);
+ }
+
+ LIST_FOREACH(v, &sc->volumes, volume) {
+ v->size = gv_vol_size(v);
+ if (v->provider == NULL) {
+ g_topology_lock();
+ pp = g_new_providerf(sc->geom, "gvinum/%s", v->name);
+ pp->mediasize = v->size;
+ pp->sectorsize = 512; /* XXX */
+ g_error_provider(pp, 0);
+ v->provider = pp;
+ pp->private = v;
+ g_topology_unlock();
+ } else if (v->provider->mediasize != v->size) {
+ g_topology_lock();
+ v->provider->mediasize = v->size;
+ g_topology_unlock();
+ }
+ v->flags &= ~GV_VOL_NEWBORN;
+ gv_update_vol_state(v);
}
}
void
-gv_kill_plex_thread(struct gv_plex *p)
+gv_cleanup(struct gv_softc *sc)
{
- if (p->flags & GV_PLEX_THREAD_ACTIVE) {
- p->flags |= GV_PLEX_THREAD_DIE;
- wakeup(p);
- while (!(p->flags & GV_PLEX_THREAD_DEAD))
- tsleep(p, PRIBIO, "gv_die", hz);
- p->flags &= ~GV_PLEX_THREAD_ACTIVE;
- p->flags &= ~GV_PLEX_THREAD_DIE;
- p->flags &= ~GV_PLEX_THREAD_DEAD;
+ struct gv_volume *v, *v2;
+ struct gv_plex *p, *p2;
+ struct gv_sd *s, *s2;
+ struct gv_drive *d, *d2;
+ struct gv_freelist *fl, *fl2;
+
+ mtx_lock(&sc->config_mtx);
+ LIST_FOREACH_SAFE(v, &sc->volumes, volume, v2) {
+ LIST_REMOVE(v, volume);
+ g_free(v->wqueue);
+ g_free(v);
+ }
+ LIST_FOREACH_SAFE(p, &sc->plexes, plex, p2) {
+ LIST_REMOVE(p, plex);
g_free(p->bqueue);
+ g_free(p->rqueue);
g_free(p->wqueue);
- p->bqueue = NULL;
- p->wqueue = NULL;
- mtx_destroy(&p->bqueue_mtx);
+ g_free(p);
+ }
+ LIST_FOREACH_SAFE(s, &sc->subdisks, sd, s2) {
+ LIST_REMOVE(s, sd);
+ g_free(s);
}
+ LIST_FOREACH_SAFE(d, &sc->drives, drive, d2) {
+ LIST_FOREACH_SAFE(fl, &d->freelist, freelist, fl2) {
+ LIST_REMOVE(fl, freelist);
+ g_free(fl);
+ }
+ LIST_REMOVE(d, drive);
+ g_free(d->hdr);
+ g_free(d);
+ }
+ mtx_destroy(&sc->config_mtx);
}
-void
-gv_kill_vol_thread(struct gv_volume *v)
+/* General 'attach' routine. */
+int
+gv_attach_plex(struct gv_plex *p, struct gv_volume *v, int rename)
+{
+ struct gv_sd *s;
+ struct gv_softc *sc;
+
+ g_topology_assert();
+
+ sc = p->vinumconf;
+ KASSERT(sc != NULL, ("NULL sc"));
+
+ if (p->vol_sc != NULL) {
+ G_VINUM_DEBUG(1, "unable to attach %s: already attached to %s",
+ p->name, p->volume);
+ return (GV_ERR_ISATTACHED);
+ }
+
+ /* Stale all subdisks of this plex. */
+ LIST_FOREACH(s, &p->subdisks, in_plex) {
+ if (s->state != GV_SD_STALE)
+ gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE);
+ }
+ /* Attach to volume. Make sure volume is not up and running. */
+ if (gv_provider_is_open(v->provider)) {
+ G_VINUM_DEBUG(1, "unable to attach %s: volume %s is busy",
+ p->name, v->name);
+ return (GV_ERR_ISBUSY);
+ }
+ p->vol_sc = v;
+ strlcpy(p->volume, v->name, sizeof(p->volume));
+ v->plexcount++;
+ if (rename) {
+ snprintf(p->name, sizeof(p->name), "%s.p%d", v->name,
+ v->plexcount);
+ }
+ LIST_INSERT_HEAD(&v->plexes, p, in_volume);
+
+ /* Get plex up again. */
+ gv_update_vol_size(v, gv_vol_size(v));
+ gv_set_plex_state(p, GV_PLEX_UP, 0);
+ gv_save_config(p->vinumconf);
+ return (0);
+}
+
+int
+gv_attach_sd(struct gv_sd *s, struct gv_plex *p, off_t offset, int rename)
+{
+ struct gv_sd *s2;
+ int error, sdcount;
+
+ g_topology_assert();
+
+ /* If subdisk is attached, don't do it. */
+ if (s->plex_sc != NULL) {
+ G_VINUM_DEBUG(1, "unable to attach %s: already attached to %s",
+ s->name, s->plex);
+ return (GV_ERR_ISATTACHED);
+ }
+
+ gv_set_sd_state(s, GV_SD_STALE, GV_SETSTATE_FORCE);
+ /* First check that this subdisk has a correct offset. If none other
+ * starts at the same, and it's correct module stripesize, it is */
+ if (offset != -1 && offset % p->stripesize != 0)
+ return (GV_ERR_BADOFFSET);
+ LIST_FOREACH(s2, &p->subdisks, in_plex) {
+ if (s2->plex_offset == offset)
+ return (GV_ERR_BADOFFSET);
+ }
+
+ /* Attach the subdisk to the plex at given offset. */
+ s->plex_offset = offset;
+ strlcpy(s->plex, p->name, sizeof(s->plex));
+
+ sdcount = p->sdcount;
+ error = gv_sd_to_plex(s, p);
+ if (error)
+ return (error);
+ gv_update_plex_config(p);
+
+ if (rename) {
+ snprintf(s->name, sizeof(s->name), "%s.s%d", s->plex,
+ p->sdcount);
+ }
+ if (p->vol_sc != NULL)
+ gv_update_vol_size(p->vol_sc, gv_vol_size(p->vol_sc));
+ gv_save_config(p->vinumconf);
+ /* We don't update the subdisk state since the user might have to
+ * initiate a rebuild/sync first. */
+ return (0);
+}
+
+/* Detach a plex from a volume. */
+int
+gv_detach_plex(struct gv_plex *p, int flags)
{
- if (v->flags & GV_VOL_THREAD_ACTIVE) {
- v->flags |= GV_VOL_THREAD_DIE;
- wakeup(v);
- while (!(v->flags & GV_VOL_THREAD_DEAD))
- tsleep(v, PRIBIO, "gv_die", hz);
- v->flags &= ~GV_VOL_THREAD_ACTIVE;
- v->flags &= ~GV_VOL_THREAD_DIE;
- v->flags &= ~GV_VOL_THREAD_DEAD;
- g_free(v->bqueue);
- v->bqueue = NULL;
- mtx_destroy(&v->bqueue_mtx);
+ struct gv_volume *v;
+
+ g_topology_assert();
+ v = p->vol_sc;
+
+ if (v == NULL) {
+ G_VINUM_DEBUG(1, "unable to detach %s: already detached",
+ p->name);
+ return (0); /* Not an error. */
+ }
+
+ /*
+ * Only proceed if forced or volume inactive.
+ */
+ if (!(flags & GV_FLAG_F) && (gv_provider_is_open(v->provider) ||
+ p->state == GV_PLEX_UP)) {
+ G_VINUM_DEBUG(1, "unable to detach %s: volume %s is busy",
+ p->name, p->volume);
+ return (GV_ERR_ISBUSY);
}
+ v->plexcount--;
+ /* Make sure someone don't read us when gone. */
+ v->last_read_plex = NULL;
+ LIST_REMOVE(p, in_volume);
+ p->vol_sc = NULL;
+ memset(p->volume, 0, GV_MAXVOLNAME);
+ gv_update_vol_size(v, gv_vol_size(v));
+ gv_save_config(p->vinumconf);
+ return (0);
+}
+
+/* Detach a subdisk from a plex. */
+int
+gv_detach_sd(struct gv_sd *s, int flags)
+{
+ struct gv_plex *p;
+
+ g_topology_assert();
+ p = s->plex_sc;
+
+ if (p == NULL) {
+ G_VINUM_DEBUG(1, "unable to detach %s: already detached",
+ s->name);
+ return (0); /* Not an error. */
+ }
+
+ /*
+ * Don't proceed if we're not forcing, and the plex is up, or degraded
+ * with this subdisk up.
+ */
+ if (!(flags & GV_FLAG_F) && ((p->state > GV_PLEX_DEGRADED) ||
+ ((p->state == GV_PLEX_DEGRADED) && (s->state == GV_SD_UP)))) {
+ G_VINUM_DEBUG(1, "unable to detach %s: plex %s is busy",
+ s->name, s->plex);
+ return (GV_ERR_ISBUSY);
+ }
+
+ LIST_REMOVE(s, in_plex);
+ s->plex_sc = NULL;
+ memset(s->plex, 0, GV_MAXPLEXNAME);
+ p->sddetached++;
+ gv_save_config(s->vinumconf);
+ return (0);
}
diff --git a/sys/geom/vinum/geom_vinum_var.h b/sys/geom/vinum/geom_vinum_var.h
index 5a86568..124944f 100644
--- a/sys/geom/vinum/geom_vinum_var.h
+++ b/sys/geom/vinum/geom_vinum_var.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2004, 2007 Lukas Ertl
* Copyright (c) 1997, 1998, 1999
* Nan Yang Computer Services Limited. All rights reserved.
*
@@ -112,11 +112,29 @@
#define GV_BIO_MALLOC 0x02
#define GV_BIO_ONHOLD 0x04
#define GV_BIO_SYNCREQ 0x08
-#define GV_BIO_SUCCEED 0x10
+#define GV_BIO_INIT 0x10
#define GV_BIO_REBUILD 0x20
#define GV_BIO_CHECK 0x40
#define GV_BIO_PARITY 0x80
#define GV_BIO_RETRY 0x100
+#define GV_BIO_INTERNAL \
+ (GV_BIO_SYNCREQ | GV_BIO_INIT | GV_BIO_REBUILD |GV_BIO_CHECK)
+
+/* Error codes to be used within gvinum. */
+#define GV_ERR_SETSTATE (-1) /* Error setting state. */
+#define GV_ERR_BADSIZE (-2) /* Object has wrong size. */
+#define GV_ERR_INVTYPE (-3) /* Invalid object type. */
+#define GV_ERR_CREATE (-4) /* Error creating gvinum object. */
+#define GV_ERR_ISBUSY (-5) /* Object is busy. */
+#define GV_ERR_ISATTACHED (-6) /* Object is attached to another. */
+#define GV_ERR_INVFLAG (-7) /* Invalid flag passed. */
+#define GV_ERR_INVSTATE (-8) /* Invalid state. */
+#define GV_ERR_NOTFOUND (-9) /* Object not found. */
+#define GV_ERR_NAMETAKEN (-10) /* Object name is taken. */
+#define GV_ERR_NOSPACE (-11) /* No space left on drive/subdisk. */
+#define GV_ERR_BADOFFSET (-12) /* Invalid offset specified. */
+#define GV_ERR_INVNAME (-13) /* Invalid object name. */
+#define GV_ERR_PLEXORG (-14) /* Invalid plex organization. */
/*
* hostname is 256 bytes long, but we don't need to shlep multiple copies in
@@ -162,16 +180,65 @@ struct gv_bioq {
TAILQ_ENTRY(gv_bioq) queue;
};
+#define GV_EVENT_DRIVE_TASTED 1
+#define GV_EVENT_DRIVE_LOST 2
+#define GV_EVENT_THREAD_EXIT 3
+#define GV_EVENT_CREATE_DRIVE 4
+#define GV_EVENT_CREATE_VOLUME 5
+#define GV_EVENT_CREATE_PLEX 6
+#define GV_EVENT_CREATE_SD 7
+#define GV_EVENT_SAVE_CONFIG 8
+#define GV_EVENT_RM_VOLUME 9
+#define GV_EVENT_RM_PLEX 10
+#define GV_EVENT_RM_SD 11
+#define GV_EVENT_RM_DRIVE 12
+#define GV_EVENT_SET_SD_STATE 13
+#define GV_EVENT_SET_DRIVE_STATE 14
+#define GV_EVENT_SET_VOL_STATE 15
+#define GV_EVENT_SET_PLEX_STATE 16
+#define GV_EVENT_RESET_CONFIG 17
+#define GV_EVENT_PARITY_REBUILD 18
+#define GV_EVENT_PARITY_CHECK 19
+#define GV_EVENT_START_PLEX 20
+#define GV_EVENT_START_VOLUME 21
+#define GV_EVENT_ATTACH_PLEX 22
+#define GV_EVENT_ATTACH_SD 23
+#define GV_EVENT_DETACH_PLEX 24
+#define GV_EVENT_DETACH_SD 25
+#define GV_EVENT_RENAME_VOL 26
+#define GV_EVENT_RENAME_PLEX 27
+#define GV_EVENT_RENAME_SD 28
+#define GV_EVENT_RENAME_DRIVE 29
+#define GV_EVENT_MOVE_SD 30
+#define GV_EVENT_SETUP_OBJECTS 31
+
+#ifdef _KERNEL
+struct gv_event {
+ int type;
+ void *arg1;
+ void *arg2;
+ intmax_t arg3;
+ intmax_t arg4;
+ TAILQ_ENTRY(gv_event) events;
+};
+#endif
+
/* This struct contains the main vinum config. */
struct gv_softc {
- /*struct mtx config_mtx; XXX not yet */
-
/* Linked lists of all objects in our setup. */
LIST_HEAD(,gv_drive) drives; /* All drives. */
LIST_HEAD(,gv_plex) plexes; /* All plexes. */
LIST_HEAD(,gv_sd) subdisks; /* All subdisks. */
LIST_HEAD(,gv_volume) volumes; /* All volumes. */
+ TAILQ_HEAD(,gv_event) equeue; /* Event queue. */
+ struct mtx queue_mtx; /* Queue lock. */
+ struct mtx config_mtx; /* Configuration lock. */
+#ifdef _KERNEL
+ struct bio_queue_head *bqueue; /* BIO queue. */
+#else
+ char *padding;
+#endif
struct g_geom *geom; /* Pointer to our VINUM geom. */
};
@@ -188,26 +255,19 @@ struct gv_drive {
int sdcount; /* Number of subdisks. */
int flags;
-#define GV_DRIVE_THREAD_ACTIVE 0x01 /* Drive has an active worker thread. */
-#define GV_DRIVE_THREAD_DIE 0x02 /* Signal the worker thread to die. */
-#define GV_DRIVE_THREAD_DEAD 0x04 /* The worker thread has died. */
-#define GV_DRIVE_NEWBORN 0x08 /* The drive was just created. */
+#define GV_DRIVE_REFERENCED 0x01 /* The drive isn't really existing,
+ but was referenced by a subdisk
+ during taste. */
+
+ struct gv_hdr *hdr; /* The drive header. */
- struct gv_hdr *hdr; /* The drive header. */
+ struct g_consumer *consumer; /* Consumer attached to this drive. */
int freelist_entries; /* Count of freelist entries. */
LIST_HEAD(,gv_freelist) freelist; /* List of freelist entries. */
LIST_HEAD(,gv_sd) subdisks; /* Subdisks on this drive. */
LIST_ENTRY(gv_drive) drive; /* Entry in the vinum config. */
-#ifdef _KERNEL
- struct bio_queue_head *bqueue; /* BIO queue of this drive. */
-#else
- char *padding;
-#endif
- struct mtx bqueue_mtx; /* Mtx. to protect the queue. */
-
- struct g_geom *geom; /* The geom of this drive. */
struct gv_softc *vinumconf; /* Pointer to the vinum conf. */
};
@@ -230,8 +290,10 @@ struct gv_sd {
int init_error; /* Flag error on initialization. */
int flags;
-#define GV_SD_NEWBORN 0x01 /* Subdisk was just created. */
-#define GV_SD_INITCANCEL 0x02 /* Cancel initialization process. */
+#define GV_SD_NEWBORN 0x01 /* Subdisk is created by user. */
+#define GV_SD_TASTED 0x02 /* Subdisk is created during taste. */
+#define GV_SD_CANGOUP 0x04 /* Subdisk can go up immediately. */
+#define GV_SD_GROW 0x08 /* Subdisk is added to striped plex. */
char drive[GV_MAXDRIVENAME]; /* Name of underlying drive. */
char plex[GV_MAXPLEXNAME]; /* Name of associated plex. */
@@ -239,9 +301,6 @@ struct gv_sd {
struct gv_drive *drive_sc; /* Pointer to underlying drive. */
struct gv_plex *plex_sc; /* Pointer to associated plex. */
- struct g_provider *provider; /* The provider this sd represents. */
- struct g_consumer *consumer; /* Consumer attached to our provider. */
-
LIST_ENTRY(gv_sd) from_drive; /* Subdisk list of underlying drive. */
LIST_ENTRY(gv_sd) in_plex; /* Subdisk list of associated plex. */
LIST_ENTRY(gv_sd) sd; /* Entry in the vinum config. */
@@ -257,7 +316,8 @@ struct gv_plex {
#define GV_PLEX_DOWN 0
#define GV_PLEX_INITIALIZING 1
#define GV_PLEX_DEGRADED 2
-#define GV_PLEX_UP 3
+#define GV_PLEX_GROWABLE 3
+#define GV_PLEX_UP 4
int org; /* The plex organisation. */
#define GV_PLEX_DISORG 0
@@ -270,6 +330,7 @@ struct gv_plex {
char volume[GV_MAXVOLNAME]; /* Name of associated volume. */
struct gv_volume *vol_sc; /* Pointer to associated volume. */
+ int sddetached; /* Number of detached subdisks. */
int sdcount; /* Number of subdisks in this plex. */
int sddown; /* Number of subdisks that are down. */
int flags;
@@ -279,26 +340,25 @@ struct gv_plex {
#define GV_PLEX_THREAD_DIE 0x08 /* Signal the RAID5 thread to die. */
#define GV_PLEX_THREAD_DEAD 0x10 /* The RAID5 thread has died. */
#define GV_PLEX_NEWBORN 0x20 /* The plex was just created. */
+#define GV_PLEX_REBUILDING 0x40 /* The plex is rebuilding. */
+#define GV_PLEX_GROWING 0x80 /* The plex is growing. */
off_t synced; /* Count of synced bytes. */
- struct mtx bqueue_mtx; /* Lock for the BIO queue. */
-#ifdef _KERNEL
- struct bio_queue_head *bqueue; /* BIO queue. */
- struct bio_queue_head *wqueue; /* Waiting BIO queue. */
-#else
- char *bpad, *wpad;
-#endif
TAILQ_HEAD(,gv_raid5_packet) packets; /* RAID5 sub-requests. */
LIST_HEAD(,gv_sd) subdisks; /* List of attached subdisks. */
LIST_ENTRY(gv_plex) in_volume; /* Plex list of associated volume. */
LIST_ENTRY(gv_plex) plex; /* Entry in the vinum config. */
- struct g_provider *provider; /* The provider this plex represents. */
- struct g_consumer *consumer; /* Consumer attached to our provider. */
+#ifdef _KERNEL
+ struct bio_queue_head *bqueue; /* BIO queue. */
+ struct bio_queue_head *wqueue; /* Waiting BIO queue. */
+ struct bio_queue_head *rqueue; /* Rebuild waiting BIO queue. */
+#else
+ char *bpad, *wpad, *rpad; /* Padding for userland. */
+#endif
- struct g_geom *geom; /* The geom of this plex. */
struct gv_softc *vinumconf; /* Pointer to the vinum config. */
};
@@ -315,19 +375,20 @@ struct gv_volume {
#define GV_VOL_THREAD_ACTIVE 0x01 /* Volume has an active thread. */
#define GV_VOL_THREAD_DIE 0x02 /* Signal the thread to die. */
#define GV_VOL_THREAD_DEAD 0x04 /* The thread has died. */
+#define GV_VOL_NEWBORN 0x08 /* The volume was just created. */
- struct mtx bqueue_mtx; /* Lock for the BIO queue. */
-#ifdef _KERNEL
- struct bio_queue_head *bqueue; /* BIO queue. */
+ LIST_HEAD(,gv_plex) plexes; /* List of attached plexes. */
+ LIST_ENTRY(gv_volume) volume; /* Entry in vinum config. */
+
+ struct g_provider *provider; /* Provider of this volume. */
+
+#ifdef _KERNEL
+ struct bio_queue_head *wqueue; /* BIO delayed request queue. */
#else
- char *padding;
+ char *wpad; /* Padding for userland. */
#endif
- LIST_HEAD(,gv_plex) plexes; /* List of attached plexes. */
- LIST_ENTRY(gv_volume) volume; /* Entry in vinum config. */
-
struct gv_plex *last_read_plex;
- struct g_geom *geom; /* The geom of this volume. */
struct gv_softc *vinumconf; /* Pointer to the vinum config. */
};
diff --git a/sys/geom/vinum/geom_vinum_volume.c b/sys/geom/vinum/geom_vinum_volume.c
index 88face2..32b353b 100644
--- a/sys/geom/vinum/geom_vinum_volume.c
+++ b/sys/geom/vinum/geom_vinum_volume.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2004 Lukas Ertl
+ * Copyright (c) 2007 Lukas Ertl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,416 +29,136 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bio.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/kthread.h>
-#include <sys/libkern.h>
#include <sys/lock.h>
#include <sys/malloc.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
#include <sys/systm.h>
#include <geom/geom.h>
#include <geom/vinum/geom_vinum_var.h>
#include <geom/vinum/geom_vinum.h>
-static void gv_vol_completed_request(struct gv_volume *, struct bio *);
-static void gv_vol_normal_request(struct gv_volume *, struct bio *);
-
-static void
-gv_volume_orphan(struct g_consumer *cp)
-{
- struct g_geom *gp;
- struct gv_volume *v;
- int error;
-
- g_topology_assert();
- gp = cp->geom;
- g_trace(G_T_TOPOLOGY, "gv_volume_orphan(%s)", gp->name);
- if (cp->acr != 0 || cp->acw != 0 || cp->ace != 0)
- g_access(cp, -cp->acr, -cp->acw, -cp->ace);
- error = cp->provider->error;
- if (error == 0)
- error = ENXIO;
- g_detach(cp);
- g_destroy_consumer(cp);
- if (!LIST_EMPTY(&gp->consumer))
- return;
- v = gp->softc;
- if (v != NULL) {
- gv_kill_vol_thread(v);
- v->geom = NULL;
- }
- gp->softc = NULL;
- g_wither_geom(gp, error);
-}
-
-/* We end up here after the requests to our plexes are done. */
-static void
-gv_volume_done(struct bio *bp)
-{
- struct gv_volume *v;
-
- v = bp->bio_from->geom->softc;
- bp->bio_cflags |= GV_BIO_DONE;
- mtx_lock(&v->bqueue_mtx);
- bioq_insert_tail(v->bqueue, bp);
- wakeup(v);
- mtx_unlock(&v->bqueue_mtx);
-}
-
-static void
-gv_volume_start(struct bio *bp)
-{
- struct gv_volume *v;
-
- switch(bp->bio_cmd) {
- case BIO_READ:
- case BIO_WRITE:
- case BIO_DELETE:
- break;
- case BIO_GETATTR:
- default:
- g_io_deliver(bp, EOPNOTSUPP);
- return;
- }
-
- v = bp->bio_to->geom->softc;
- if (v->state != GV_VOL_UP) {
- g_io_deliver(bp, ENXIO);
- return;
- }
-
- mtx_lock(&v->bqueue_mtx);
- bioq_disksort(v->bqueue, bp);
- wakeup(v);
- mtx_unlock(&v->bqueue_mtx);
-}
-
-static void
-gv_vol_worker(void *arg)
+void
+gv_volume_flush(struct gv_volume *v)
{
+ struct gv_softc *sc;
struct bio *bp;
- struct gv_volume *v;
- v = arg;
KASSERT(v != NULL, ("NULL v"));
- mtx_lock(&v->bqueue_mtx);
- for (;;) {
- /* We were signaled to exit. */
- if (v->flags & GV_VOL_THREAD_DIE)
- break;
-
- /* Take the first BIO from our queue. */
- bp = bioq_takefirst(v->bqueue);
- if (bp == NULL) {
- msleep(v, &v->bqueue_mtx, PRIBIO, "-", hz/10);
- continue;
- }
- mtx_unlock(&v->bqueue_mtx);
+ sc = v->vinumconf;
+ KASSERT(sc != NULL, ("NULL sc"));
- if (bp->bio_cflags & GV_BIO_DONE)
- gv_vol_completed_request(v, bp);
- else
- gv_vol_normal_request(v, bp);
-
- mtx_lock(&v->bqueue_mtx);
+ bp = bioq_takefirst(v->wqueue);
+ while (bp != NULL) {
+ gv_volume_start(sc, bp);
+ bp = bioq_takefirst(v->wqueue);
}
- mtx_unlock(&v->bqueue_mtx);
- v->flags |= GV_VOL_THREAD_DEAD;
- wakeup(v);
-
- kproc_exit(ENXIO);
}
-static void
-gv_vol_completed_request(struct gv_volume *v, struct bio *bp)
+void
+gv_volume_start(struct gv_softc *sc, struct bio *bp)
{
- struct bio *pbp;
struct g_geom *gp;
- struct g_consumer *cp, *cp2;
-
- pbp = bp->bio_parent;
-
- if (pbp->bio_error == 0)
- pbp->bio_error = bp->bio_error;
-
- switch (pbp->bio_cmd) {
- case BIO_READ:
- if (bp->bio_error == 0)
- break;
-
- if (pbp->bio_cflags & GV_BIO_RETRY)
- break;
-
- /* Check if we have another plex left. */
- cp = bp->bio_from;
- gp = cp->geom;
- cp2 = LIST_NEXT(cp, consumer);
- if (cp2 == NULL)
- break;
-
- if (LIST_NEXT(cp2, consumer) == NULL)
- pbp->bio_cflags |= GV_BIO_RETRY;
+ struct gv_volume *v;
+ struct gv_plex *p, *lp;
+ int numwrites;
- g_destroy_bio(bp);
- pbp->bio_children--;
- mtx_lock(&v->bqueue_mtx);
- bioq_disksort(v->bqueue, pbp);
- mtx_unlock(&v->bqueue_mtx);
+ gp = sc->geom;
+ v = bp->bio_to->private;
+ if (v == NULL || v->state != GV_VOL_UP) {
+ g_io_deliver(bp, ENXIO);
return;
-
- case BIO_WRITE:
- case BIO_DELETE:
- /* Remember if this write request succeeded. */
- if (bp->bio_error == 0)
- pbp->bio_cflags |= GV_BIO_SUCCEED;
- break;
}
- /* When the original request is finished, we deliver it. */
- pbp->bio_inbed++;
- if (pbp->bio_inbed == pbp->bio_children) {
- if (pbp->bio_cflags & GV_BIO_SUCCEED)
- pbp->bio_error = 0;
- pbp->bio_completed = bp->bio_length;
- g_io_deliver(pbp, pbp->bio_error);
- }
-
- g_destroy_bio(bp);
-}
-
-static void
-gv_vol_normal_request(struct gv_volume *v, struct bio *bp)
-{
- struct bio_queue_head queue;
- struct g_geom *gp;
- struct gv_plex *p, *lp;
- struct bio *cbp;
-
- gp = v->geom;
-
switch (bp->bio_cmd) {
case BIO_READ:
- cbp = g_clone_bio(bp);
- if (cbp == NULL) {
- g_io_deliver(bp, ENOMEM);
- return;
- }
- cbp->bio_done = gv_volume_done;
/*
- * Try to find a good plex where we can send the request to.
- * The plex either has to be up, or it's a degraded RAID5 plex.
+ * Try to find a good plex where we can send the request to,
+ * round-robin-style. The plex either has to be up, or it's a
+ * degraded RAID5 plex. Check if we have delayed requests. Put
+ * this request on the delayed queue if so. This makes sure that
+ * we don't read old values.
*/
+ if (bioq_first(v->wqueue) != NULL) {
+ bioq_insert_tail(v->wqueue, bp);
+ break;
+ }
lp = v->last_read_plex;
if (lp == NULL)
lp = LIST_FIRST(&v->plexes);
p = LIST_NEXT(lp, in_volume);
+ if (p == NULL)
+ p = LIST_FIRST(&v->plexes);
do {
- if (p == NULL)
- p = LIST_FIRST(&v->plexes);
+ if (p == NULL) {
+ p = lp;
+ break;
+ }
if ((p->state > GV_PLEX_DEGRADED) ||
(p->state >= GV_PLEX_DEGRADED &&
p->org == GV_PLEX_RAID5))
break;
p = LIST_NEXT(p, in_volume);
+ if (p == NULL)
+ p = LIST_FIRST(&v->plexes);
} while (p != lp);
- if (p == NULL ||
+ if ((p == NULL) ||
(p->org == GV_PLEX_RAID5 && p->state < GV_PLEX_DEGRADED) ||
(p->org != GV_PLEX_RAID5 && p->state <= GV_PLEX_DEGRADED)) {
- g_destroy_bio(cbp);
- bp->bio_children--;
g_io_deliver(bp, ENXIO);
return;
}
- g_io_request(cbp, p->consumer);
v->last_read_plex = p;
+ /* Hand it down to the plex logic. */
+ gv_plex_start(p, bp);
break;
case BIO_WRITE:
case BIO_DELETE:
- bioq_init(&queue);
+ /* Delay write-requests if any plex is synchronizing. */
LIST_FOREACH(p, &v->plexes, in_volume) {
- if (p->state < GV_PLEX_DEGRADED)
- continue;
- cbp = g_clone_bio(bp);
- if (cbp == NULL) {
- for (cbp = bioq_first(&queue); cbp != NULL;
- cbp = bioq_first(&queue)) {
- bioq_remove(&queue, cbp);
- g_destroy_bio(cbp);
- }
- if (bp->bio_error == 0)
- bp->bio_error = ENOMEM;
- g_io_deliver(bp, bp->bio_error);
+ if (p->flags & GV_PLEX_SYNCING) {
+ bioq_insert_tail(v->wqueue, bp);
return;
}
- bioq_insert_tail(&queue, cbp);
- cbp->bio_done = gv_volume_done;
- cbp->bio_caller1 = p->consumer;
- }
- /* Fire off all sub-requests. */
- for (cbp = bioq_first(&queue); cbp != NULL;
- cbp = bioq_first(&queue)) {
- bioq_remove(&queue, cbp);
- g_io_request(cbp, cbp->bio_caller1);
}
- break;
- }
-}
-
-static int
-gv_volume_access(struct g_provider *pp, int dr, int dw, int de)
-{
- struct g_geom *gp;
- struct g_consumer *cp, *cp2;
- int error;
- gp = pp->geom;
-
- error = ENXIO;
- LIST_FOREACH(cp, &gp->consumer, consumer) {
- error = g_access(cp, dr, dw, de);
- if (error) {
- LIST_FOREACH(cp2, &gp->consumer, consumer) {
- if (cp == cp2)
- break;
- g_access(cp2, -dr, -dw, -de);
- }
- return (error);
+ numwrites = 0;
+ /* Give the BIO to each plex of this volume. */
+ LIST_FOREACH(p, &v->plexes, in_volume) {
+ if (p->state < GV_PLEX_DEGRADED)
+ continue;
+ gv_plex_start(p, bp);
+ numwrites++;
}
+ if (numwrites == 0)
+ g_io_deliver(bp, ENXIO);
+ break;
}
- return (error);
}
-static struct g_geom *
-gv_volume_taste(struct g_class *mp, struct g_provider *pp, int flags __unused)
+void
+gv_bio_done(struct gv_softc *sc, struct bio *bp)
{
- struct g_geom *gp;
- struct g_provider *pp2;
- struct g_consumer *cp, *ocp;
- struct gv_softc *sc;
struct gv_volume *v;
struct gv_plex *p;
- int error, first;
-
- g_trace(G_T_TOPOLOGY, "gv_volume_taste(%s, %s)", mp->name, pp->name);
- g_topology_assert();
-
- /* First, find the VINUM class and its associated geom. */
- gp = find_vinum_geom();
- if (gp == NULL)
- return (NULL);
-
- sc = gp->softc;
- KASSERT(sc != NULL, ("gv_volume_taste: NULL sc"));
-
- gp = pp->geom;
-
- /* We only want to attach to plexes. */
- if (strcmp(gp->class->name, "VINUMPLEX"))
- return (NULL);
-
- first = 0;
- p = gp->softc;
-
- /* Let's see if the volume this plex wants is already configured. */
- v = gv_find_vol(sc, p->volume);
- if (v == NULL)
- return (NULL);
- if (v->geom == NULL) {
- gp = g_new_geomf(mp, "%s", p->volume);
- gp->start = gv_volume_start;
- gp->orphan = gv_volume_orphan;
- gp->access = gv_volume_access;
- gp->softc = v;
- first++;
- } else
- gp = v->geom;
-
- /* Create bio queue, queue mutex, and worker thread, if necessary. */
- if (v->bqueue == NULL) {
- v->bqueue = g_malloc(sizeof(struct bio_queue_head),
- M_WAITOK | M_ZERO);
- bioq_init(v->bqueue);
- }
- if (mtx_initialized(&v->bqueue_mtx) == 0)
- mtx_init(&v->bqueue_mtx, "gv_plex", NULL, MTX_DEF);
-
- if (!(v->flags & GV_VOL_THREAD_ACTIVE)) {
- kproc_create(gv_vol_worker, v, NULL, 0, 0, "gv_v %s",
- v->name);
- v->flags |= GV_VOL_THREAD_ACTIVE;
- }
-
- /*
- * Create a new consumer and attach it to the plex geom. Since this
- * volume might already have a plex attached, we need to adjust the
- * access counts of the new consumer.
- */
- ocp = LIST_FIRST(&gp->consumer);
- cp = g_new_consumer(gp);
- g_attach(cp, pp);
- if ((ocp != NULL) && (ocp->acr > 0 || ocp->acw > 0 || ocp->ace > 0)) {
- error = g_access(cp, ocp->acr, ocp->acw, ocp->ace);
- if (error) {
- G_VINUM_DEBUG(0, "failed g_access %s -> %s; "
- "errno %d", v->name, p->name, error);
- g_detach(cp);
- g_destroy_consumer(cp);
- if (first)
- g_destroy_geom(gp);
- return (NULL);
- }
- }
-
- p->consumer = cp;
-
- if (p->vol_sc != v) {
- p->vol_sc = v;
- v->plexcount++;
- LIST_INSERT_HEAD(&v->plexes, p, in_volume);
- }
-
- /* We need to setup a new VINUMVOLUME geom. */
- if (first) {
- pp2 = g_new_providerf(gp, "gvinum/%s", v->name);
- pp2->mediasize = pp->mediasize;
- pp2->sectorsize = pp->sectorsize;
- g_error_provider(pp2, 0);
- v->size = pp2->mediasize;
- v->geom = gp;
- return (gp);
+ struct gv_sd *s;
+
+ s = bp->bio_caller1;
+ KASSERT(s != NULL, ("gv_bio_done: NULL s"));
+ p = s->plex_sc;
+ KASSERT(p != NULL, ("gv_bio_done: NULL p"));
+ v = p->vol_sc;
+ KASSERT(v != NULL, ("gv_bio_done: NULL v"));
+
+ switch (p->org) {
+ case GV_PLEX_CONCAT:
+ case GV_PLEX_STRIPED:
+ gv_plex_normal_done(p, bp);
+ break;
+ case GV_PLEX_RAID5:
+ gv_plex_raid5_done(p, bp);
+ break;
}
-
- return (NULL);
}
-
-static int
-gv_volume_destroy_geom(struct gctl_req *req, struct g_class *mp,
- struct g_geom *gp)
-{
- struct gv_volume *v;
-
- g_trace(G_T_TOPOLOGY, "gv_volume_destroy_geom: %s", gp->name);
- g_topology_assert();
-
- v = gp->softc;
- gv_kill_vol_thread(v);
- g_wither_geom(gp, ENXIO);
- return (0);
-}
-
-#define VINUMVOLUME_CLASS_NAME "VINUMVOLUME"
-
-static struct g_class g_vinum_volume_class = {
- .name = VINUMVOLUME_CLASS_NAME,
- .version = G_VERSION,
- .taste = gv_volume_taste,
- .destroy_geom = gv_volume_destroy_geom,
-};
-
-DECLARE_GEOM_CLASS(g_vinum_volume_class, g_vinum_volume);
diff --git a/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c b/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c
index 9759d5a..ff06865 100644
--- a/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c
+++ b/sys/gnu/fs/xfs/FreeBSD/xfs_buf.c
@@ -81,7 +81,7 @@ xfs_buf_get_empty(size_t size, xfs_buftarg_t *target)
{
struct buf *bp;
- bp = geteblk(0);
+ bp = geteblk(0, 0);
if (bp != NULL) {
bp->b_bufsize = size;
bp->b_bcount = size;
@@ -100,7 +100,7 @@ xfs_buf_get_noaddr(size_t len, xfs_buftarg_t *target)
if (len >= MAXPHYS)
return (NULL);
- bp = geteblk(len);
+ bp = geteblk(len, 0);
if (bp != NULL) {
BUF_ASSERT_HELD(bp);
diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC
index 2915cc6..70aac72 100644
--- a/sys/i386/conf/GENERIC
+++ b/sys/i386/conf/GENERIC
@@ -309,7 +309,6 @@ device ural # Ralink Technology RT2500USB wireless NICs
device rum # Ralink Technology RT2501USB wireless NICs
device zyd # ZyDAS zb1211/zb1211b wireless NICs
device urio # Diamond Rio 500 MP3 player
-device uscanner # Scanners
# USB Serial devices
device u3g # USB-based 3G modems (Option, Huawei, Sierra)
device uark # Technologies ARK3116 based serial adapters
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 1f69960..b9c3fd1 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -528,8 +528,6 @@ hint.mse.0.irq="5"
# Network interfaces:
#
-# ar: Arnet SYNC/570i hdlc sync 2/4 port V.35/X.21 serial driver
-# (requires sppp)
# ath: Atheros a/b/g WiFi adapters (requires ath_hal and wlan)
# ce: Cronyx Tau-PCI/32 sync single/dual port G.703/E1 serial adaptor
# with 32 HDLC subchannels (requires sppp (default), or NETGRAPH if
@@ -554,17 +552,11 @@ hint.mse.0.irq="5"
# nve: nVidia nForce MCP on-board Ethernet Networking
# ral: Ralink Technology IEEE 802.11 wireless adapter
# sbni: Granch SBNI12-xx ISA and PCI adapters
-# sr: RISCom/N2 hdlc sync 1/2 port V.35/X.21 serial driver (requires sppp)
# wl: Lucent Wavelan (ISA card only).
# wpi: Intel 3945ABG Wireless LAN controller
# Order for ISA/EISA devices is important here
-device ar
-hint.ar.0.at="isa"
-hint.ar.0.port="0x300"
-hint.ar.0.irq="10"
-hint.ar.0.maddr="0xd0000"
device ath # Atheros pci/cardbus NIC's
device ath_hal # pci/cardbus chip support
#device ath_ar5210 # AR5210 chips
@@ -619,11 +611,6 @@ hint.sbni.0.at="isa"
hint.sbni.0.port="0x210"
hint.sbni.0.irq="0xefdead"
hint.sbni.0.flags="0"
-device sr
-hint.sr.0.at="isa"
-hint.sr.0.port="0x300"
-hint.sr.0.irq="5"
-hint.sr.0.maddr="0xd0000"
device wl
hint.wl.0.at="isa"
hint.wl.0.port="0x300"
diff --git a/sys/i386/conf/XBOX b/sys/i386/conf/XBOX
index 3867165..0a2e8c0 100644
--- a/sys/i386/conf/XBOX
+++ b/sys/i386/conf/XBOX
@@ -91,7 +91,6 @@ device ulpt # Printer
device umass # Disks/Mass storage - Requires scbus and da
device ums # Mouse
device urio # Diamond Rio 500 MP3 player
-device uscanner # Scanners
device miibus
device aue # ADMtek USB Ethernet
diff --git a/sys/i386/cpufreq/hwpstate.c b/sys/i386/cpufreq/hwpstate.c
new file mode 100644
index 0000000..cc5d03e
--- /dev/null
+++ b/sys/i386/cpufreq/hwpstate.c
@@ -0,0 +1,515 @@
+/*-
+ * Copyright (c) 2005 Nate Lawson
+ * Copyright (c) 2004 Colin Percival
+ * Copyright (c) 2004-2005 Bruno Durcot
+ * Copyright (c) 2004 FUKUDA Nobuhiko
+ * Copyright (c) 2009 Michael Reifenberger
+ * Copyright (c) 2009 Norikatsu Shigemura
+ * Copyright (c) 2008-2009 Gen Otsuji
+ *
+ * This code is depending on kern_cpu.c, est.c, powernow.c, p4tcc.c, smist.c
+ * in various parts. The authors of these files are Nate Lawson,
+ * Colin Percival, Bruno Durcot, and FUKUDA Nobuhiko.
+ * This code contains patches by Michael Reifenberger and Norikatsu Shigemura.
+ * Thank you.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted providing 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.
+ */
+
+/*
+ * For more info:
+ * BIOS and Kernel Developer's Guide(BKDG) for AMD Family 10h Processors
+ * 31116 Rev 3.20 February 04, 2009
+ * BIOS and Kernel Developer's Guide(BKDG) for AMD Family 11h Processors
+ * 41256 Rev 3.00 - July 07, 2008
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/pcpu.h>
+#include <sys/smp.h>
+#include <sys/sched.h>
+
+#include <machine/md_var.h>
+#include <machine/cputypes.h>
+#include <machine/specialreg.h>
+
+#include <contrib/dev/acpica/acpi.h>
+#include <dev/acpica/acpivar.h>
+
+#include "acpi_if.h"
+#include "cpufreq_if.h"
+
+#define MSR_AMD_10H_11H_LIMIT 0xc0010061
+#define MSR_AMD_10H_11H_CONTROL 0xc0010062
+#define MSR_AMD_10H_11H_STATUS 0xc0010063
+#define MSR_AMD_10H_11H_CONFIG 0xc0010064
+
+#define AMD_10H_11H_MAX_STATES 16
+
+/* for MSR_AMD_10H_11H_LIMIT C001_0061 */
+#define AMD_10H_11H_GET_PSTATE_MAX_VAL(msr) (((msr) >> 4) & 0x7)
+#define AMD_10H_11H_GET_PSTATE_LIMIT(msr) (((msr)) & 0x7)
+/* for MSR_AMD_10H_11H_CONFIG 10h:C001_0064:68 / 11h:C001_0064:6B */
+#define AMD_10H_11H_CUR_VID(msr) (((msr) >> 9) & 0x7F)
+#define AMD_10H_11H_CUR_DID(msr) (((msr) >> 6) & 0x07)
+#define AMD_10H_11H_CUR_FID(msr) ((msr) & 0x3F)
+
+#if defined(__amd64__)
+#define CPU_FAMILY(id) AMD64_CPU_FAMILY(id)
+#elif defined(__i386__)
+#define CPU_FAMILY(id) I386_CPU_FAMILY(id)
+#endif
+
+#define HWPSTATE_DEBUG(dev, msg...) \
+ do{ \
+ if(hwpstate_verbose) \
+ device_printf(dev, msg); \
+ }while(0)
+
+struct hwpstate_setting {
+ int freq; /* CPU clock in Mhz or 100ths of a percent. */
+ int volts; /* Voltage in mV. */
+ int power; /* Power consumed in mW. */
+ int lat; /* Transition latency in us. */
+ int pstate_id; /* P-State id */
+};
+
+struct hwpstate_softc {
+ device_t dev;
+ struct hwpstate_setting hwpstate_settings[AMD_10H_11H_MAX_STATES];
+ int cfnum;
+};
+
+static void hwpstate_identify(driver_t *driver, device_t parent);
+static int hwpstate_probe(device_t dev);
+static int hwpstate_attach(device_t dev);
+static int hwpstate_detach(device_t dev);
+static int hwpstate_set(device_t dev, const struct cf_setting *cf);
+static int hwpstate_get(device_t dev, struct cf_setting *cf);
+static int hwpstate_settings(device_t dev, struct cf_setting *sets, int *count);
+static int hwpstate_type(device_t dev, int *type);
+static int hwpstate_shutdown(device_t dev);
+static int hwpstate_features(driver_t *driver, u_int *features);
+static int hwpstate_get_info_from_acpi_perf(device_t dev, device_t perf_dev);
+static int hwpstate_get_info_from_msr(device_t dev);
+static int hwpstate_goto_pstate(device_t dev, int pstate_id);
+
+static int hwpstate_verbose = 0;
+SYSCTL_INT(_debug, OID_AUTO, hwpstate_verbose, CTLFLAG_RDTUN,
+ &hwpstate_verbose, 0, "Debug hwpstate");
+
+static device_method_t hwpstate_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, hwpstate_identify),
+ DEVMETHOD(device_probe, hwpstate_probe),
+ DEVMETHOD(device_attach, hwpstate_attach),
+ DEVMETHOD(device_detach, hwpstate_detach),
+ DEVMETHOD(device_shutdown, hwpstate_shutdown),
+
+ /* cpufreq interface */
+ DEVMETHOD(cpufreq_drv_set, hwpstate_set),
+ DEVMETHOD(cpufreq_drv_get, hwpstate_get),
+ DEVMETHOD(cpufreq_drv_settings, hwpstate_settings),
+ DEVMETHOD(cpufreq_drv_type, hwpstate_type),
+
+ /* ACPI interface */
+ DEVMETHOD(acpi_get_features, hwpstate_features),
+
+ {0, 0}
+};
+
+static devclass_t hwpstate_devclass;
+static driver_t hwpstate_driver = {
+ "hwpstate",
+ hwpstate_methods,
+ sizeof(struct hwpstate_softc),
+};
+
+DRIVER_MODULE(hwpstate, cpu, hwpstate_driver, hwpstate_devclass, 0, 0);
+
+/*
+ * Go to Px-state on all cpus considering the limit.
+ */
+static int
+hwpstate_goto_pstate(device_t dev, int pstate)
+{
+ struct hwpstate_softc *sc;
+ struct pcpu *pc;
+ int i;
+ uint64_t msr;
+ int j;
+ int limit;
+ int id = pstate;
+ int error;
+
+ sc = device_get_softc(dev);
+ /* get the current pstate limit */
+ msr = rdmsr(MSR_AMD_10H_11H_LIMIT);
+ limit = AMD_10H_11H_GET_PSTATE_LIMIT(msr);
+ if(limit > id)
+ id = limit;
+
+ error = 0;
+ /*
+ * We are going to the same Px-state on all cpus.
+ */
+ for (i = 0; i < mp_ncpus; i++) {
+ /* Find each cpu. */
+ pc = pcpu_find(i);
+ if (pc == NULL)
+ return (ENXIO);
+ thread_lock(curthread);
+ /* Bind to each cpu. */
+ sched_bind(curthread, pc->pc_cpuid);
+ thread_unlock(curthread);
+ HWPSTATE_DEBUG(dev, "setting P%d-state on cpu%d\n",
+ id, PCPU_GET(cpuid));
+ /* Go To Px-state */
+ wrmsr(MSR_AMD_10H_11H_CONTROL, id);
+ /* wait loop (100*100 usec is enough ?) */
+ for(j = 0; j < 100; j++){
+ msr = rdmsr(MSR_AMD_10H_11H_STATUS);
+ if(msr == id){
+ break;
+ }
+ DELAY(100);
+ }
+ /* get the result. not assure msr=id */
+ msr = rdmsr(MSR_AMD_10H_11H_STATUS);
+ HWPSTATE_DEBUG(dev, "result P%d-state on cpu%d\n",
+ (int)msr, PCPU_GET(cpuid));
+ if (msr != id) {
+ HWPSTATE_DEBUG(dev, "error: loop is not enough.\n");
+ error = ENXIO;
+ }
+ thread_lock(curthread);
+ sched_unbind(curthread);
+ thread_unlock(curthread);
+ }
+ return (error);
+}
+
+static int
+hwpstate_set(device_t dev, const struct cf_setting *cf)
+{
+ struct hwpstate_softc *sc;
+ struct hwpstate_setting *set;
+ int i;
+
+ if (cf == NULL)
+ return (EINVAL);
+ sc = device_get_softc(dev);
+ set = sc->hwpstate_settings;
+ for (i = 0; i < sc->cfnum; i++)
+ if (CPUFREQ_CMP(cf->freq, set[i].freq))
+ break;
+ if (i == sc->cfnum)
+ return (EINVAL);
+
+ return (hwpstate_goto_pstate(dev, set[i].pstate_id));
+}
+
+static int
+hwpstate_get(device_t dev, struct cf_setting *cf)
+{
+ struct hwpstate_softc *sc;
+ struct hwpstate_setting set;
+ uint64_t msr;
+
+ sc = device_get_softc(dev);
+ if (cf == NULL)
+ return (EINVAL);
+ msr = rdmsr(MSR_AMD_10H_11H_STATUS);
+ if(msr >= sc->cfnum)
+ return (EINVAL);
+ set = sc->hwpstate_settings[msr];
+
+ cf->freq = set.freq;
+ cf->volts = set.volts;
+ cf->power = set.power;
+ cf->lat = set.lat;
+ cf->dev = dev;
+ return (0);
+}
+
+static int
+hwpstate_settings(device_t dev, struct cf_setting *sets, int *count)
+{
+ struct hwpstate_softc *sc;
+ struct hwpstate_setting set;
+ int i;
+
+ if (sets == NULL || count == NULL)
+ return (EINVAL);
+ sc = device_get_softc(dev);
+ if (*count < sc->cfnum)
+ return (E2BIG);
+ for (i = 0; i < sc->cfnum; i++, sets++) {
+ set = sc->hwpstate_settings[i];
+ sets->freq = set.freq;
+ sets->volts = set.volts;
+ sets->power = set.power;
+ sets->lat = set.lat;
+ sets->dev = dev;
+ }
+ *count = sc->cfnum;
+
+ return (0);
+}
+
+static int
+hwpstate_type(device_t dev, int *type)
+{
+
+ if (type == NULL)
+ return (EINVAL);
+
+ *type = CPUFREQ_TYPE_ABSOLUTE;
+ return (0);
+}
+
+static void
+hwpstate_identify(driver_t *driver, device_t parent)
+{
+ device_t child;
+
+ if (device_find_child(parent, "hwpstate", -1) != NULL)
+ return;
+
+ if (cpu_vendor_id != CPU_VENDOR_AMD || CPU_FAMILY(cpu_id) < 0x10)
+ return;
+
+ /*
+ * Check if hardware pstate enable bit is set.
+ */
+ if ((amd_pminfo & AMDPM_HW_PSTATE) == 0) {
+ HWPSTATE_DEBUG(parent, "hwpstate enable bit is not set.\n");
+ return;
+ }
+
+ if (resource_disabled("hwpstate", 0))
+ return;
+
+ if ((child = BUS_ADD_CHILD(parent, 10, "hwpstate", -1)) == NULL)
+ device_printf(parent, "hwpstate: add child failed\n");
+}
+
+static int
+hwpstate_probe(device_t dev)
+{
+ struct hwpstate_softc *sc;
+ device_t perf_dev;
+ uint64_t msr;
+ int error, type;
+
+ /*
+ * Only hwpstate0.
+ * It goes well with acpi_throttle.
+ */
+ if (device_get_unit(dev) != 0)
+ return (ENXIO);
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ /*
+ * Check if acpi_perf has INFO only flag.
+ */
+ perf_dev = device_find_child(device_get_parent(dev), "acpi_perf", -1);
+ error = TRUE;
+ if (perf_dev && device_is_attached(perf_dev)) {
+ error = CPUFREQ_DRV_TYPE(perf_dev, &type);
+ if (error == 0) {
+ if ((type & CPUFREQ_FLAG_INFO_ONLY) == 0) {
+ /*
+ * If acpi_perf doesn't have INFO_ONLY flag,
+ * it will take care of pstate transitions.
+ */
+ HWPSTATE_DEBUG(dev, "acpi_perf will take care of pstate transitions.\n");
+ return (ENXIO);
+ } else {
+ /*
+ * If acpi_perf has INFO_ONLY flag, (_PCT has FFixedHW)
+ * we can get _PSS info from acpi_perf
+ * without going into ACPI.
+ */
+ HWPSTATE_DEBUG(dev, "going to fetch info from acpi_perf\n");
+ error = hwpstate_get_info_from_acpi_perf(dev, perf_dev);
+ }
+ }
+ }
+
+ if (error == 0) {
+ /*
+ * Now we get _PSS info from acpi_perf without error.
+ * Let's check it.
+ */
+ msr = rdmsr(MSR_AMD_10H_11H_LIMIT);
+ if (sc->cfnum != 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr)) {
+ HWPSTATE_DEBUG(dev, "msr and acpi _PSS count mismatch.\n");
+ error = TRUE;
+ }
+ }
+
+ /*
+ * If we cannot get info from acpi_perf,
+ * Let's get info from MSRs.
+ */
+ if (error)
+ error = hwpstate_get_info_from_msr(dev);
+ if (error)
+ return (error);
+
+ device_set_desc(dev, "Cool`n'Quiet 2.0");
+ return (0);
+}
+
+static int
+hwpstate_attach(device_t dev)
+{
+
+ return (cpufreq_register(dev));
+}
+
+static int
+hwpstate_get_info_from_msr(device_t dev)
+{
+ struct hwpstate_softc *sc;
+ struct hwpstate_setting *hwpstate_set;
+ uint64_t msr;
+ int family, i, fid, did;
+
+ family = CPU_FAMILY(cpu_id);
+ sc = device_get_softc(dev);
+ /* Get pstate count */
+ msr = rdmsr(MSR_AMD_10H_11H_LIMIT);
+ sc->cfnum = 1 + AMD_10H_11H_GET_PSTATE_MAX_VAL(msr);
+ hwpstate_set = sc->hwpstate_settings;
+ for (i = 0; i < sc->cfnum; i++) {
+ msr = rdmsr(MSR_AMD_10H_11H_CONFIG + i);
+ if ((msr & ((uint64_t)1 << 63)) != ((uint64_t)1 << 63)) {
+ HWPSTATE_DEBUG(dev, "msr is not valid.\n");
+ return (ENXIO);
+ }
+ did = AMD_10H_11H_CUR_DID(msr);
+ fid = AMD_10H_11H_CUR_FID(msr);
+ switch(family) {
+ case 0x11:
+ /* fid/did to frequency */
+ hwpstate_set[i].freq = 100 * (fid + 0x08) / (1 << did);
+ break;
+ case 0x10:
+ /* fid/did to frequency */
+ hwpstate_set[i].freq = 100 * (fid + 0x10) / (1 << did);
+ break;
+ default:
+ HWPSTATE_DEBUG(dev, "get_info_from_msr: AMD family %d CPU's are not implemented yet. sorry.\n", family);
+ return (ENXIO);
+ break;
+ }
+ hwpstate_set[i].pstate_id = i;
+ /* There was volts calculation, but deleted it. */
+ hwpstate_set[i].volts = CPUFREQ_VAL_UNKNOWN;
+ hwpstate_set[i].power = CPUFREQ_VAL_UNKNOWN;
+ hwpstate_set[i].lat = CPUFREQ_VAL_UNKNOWN;
+ }
+ return (0);
+}
+
+static int
+hwpstate_get_info_from_acpi_perf(device_t dev, device_t perf_dev)
+{
+ struct hwpstate_softc *sc;
+ struct cf_setting *perf_set;
+ struct hwpstate_setting *hwpstate_set;
+ int count, error, i;
+
+ perf_set = malloc(MAX_SETTINGS * sizeof(*perf_set), M_TEMP, M_NOWAIT);
+ if (perf_set == NULL) {
+ HWPSTATE_DEBUG(dev, "nomem\n");
+ return (ENOMEM);
+ }
+ /*
+ * Fetch settings from acpi_perf.
+ * Now it is attached, and has info only flag.
+ */
+ count = MAX_SETTINGS;
+ error = CPUFREQ_DRV_SETTINGS(perf_dev, perf_set, &count);
+ if (error) {
+ HWPSTATE_DEBUG(dev, "error: CPUFREQ_DRV_SETTINGS.\n");
+ goto out;
+ }
+ sc = device_get_softc(dev);
+ sc->cfnum = count;
+ hwpstate_set = sc->hwpstate_settings;
+ for (i = 0; i < count; i++) {
+ if (i == perf_set[i].spec[0]) {
+ hwpstate_set[i].pstate_id = i;
+ hwpstate_set[i].freq = perf_set[i].freq;
+ hwpstate_set[i].volts = perf_set[i].volts;
+ hwpstate_set[i].power = perf_set[i].power;
+ hwpstate_set[i].lat = perf_set[i].lat;
+ } else {
+ HWPSTATE_DEBUG(dev, "ACPI _PSS object mismatch.\n");
+ error = ENXIO;
+ goto out;
+ }
+ }
+out:
+ if (perf_set)
+ free(perf_set, M_TEMP);
+ return (error);
+}
+
+static int
+hwpstate_detach(device_t dev)
+{
+
+ hwpstate_goto_pstate(dev, 0);
+ return (cpufreq_unregister(dev));
+}
+
+static int
+hwpstate_shutdown(device_t dev)
+{
+
+ /* hwpstate_goto_pstate(dev, 0); */
+ return (0);
+}
+
+static int
+hwpstate_features(driver_t *driver, u_int *features)
+{
+
+ /* Notify the ACPI CPU that we support direct access to MSRs */
+ *features = ACPI_CAP_PERF_MSRS;
+ return (0);
+}
diff --git a/sys/i386/i386/elf_machdep.c b/sys/i386/i386/elf_machdep.c
index 19eddd0..9f5e3a4 100644
--- a/sys/i386/i386/elf_machdep.c
+++ b/sys/i386/i386/elf_machdep.c
@@ -84,7 +84,8 @@ static Elf32_Brandinfo freebsd_brand_info = {
.interp_path = "/libexec/ld-elf.so.1",
.sysvec = &elf32_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -99,7 +100,8 @@ static Elf32_Brandinfo freebsd_brand_oinfo = {
.interp_path = "/usr/libexec/ld-elf.so.1",
.sysvec = &elf32_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
diff --git a/sys/i386/i386/i686_mem.c b/sys/i386/i386/i686_mem.c
index fc88be1..fe229cc 100644
--- a/sys/i386/i386/i686_mem.c
+++ b/sys/i386/i386/i686_mem.c
@@ -73,11 +73,13 @@ static void i686_mrinit(struct mem_range_softc *sc);
static int i686_mrset(struct mem_range_softc *sc,
struct mem_range_desc *mrd, int *arg);
static void i686_mrAPinit(struct mem_range_softc *sc);
+static void i686_mrreinit(struct mem_range_softc *sc);
static struct mem_range_ops i686_mrops = {
i686_mrinit,
i686_mrset,
- i686_mrAPinit
+ i686_mrAPinit,
+ i686_mrreinit
};
/* XXX for AP startup hook */
@@ -668,6 +670,30 @@ i686_mrAPinit(struct mem_range_softc *sc)
wrmsr(MSR_MTRRdefType, mtrrdef);
}
+/*
+ * Re-initialise running CPU(s) MTRRs to match the ranges in the descriptor
+ * list.
+ *
+ * XXX Must be called with interrupts enabled.
+ */
+static void
+i686_mrreinit(struct mem_range_softc *sc)
+{
+#ifdef SMP
+ /*
+ * We should use ipi_all_but_self() to call other CPUs into a
+ * locking gate, then call a target function to do this work.
+ * The "proper" solution involves a generalised locking gate
+ * implementation, not ready yet.
+ */
+ smp_rendezvous(NULL, (void *)i686_mrAPinit, NULL, sc);
+#else
+ disable_intr(); /* disable interrupts */
+ i686_mrAPinit(sc);
+ enable_intr();
+#endif
+}
+
static void
i686_mem_drvinit(void *unused)
{
diff --git a/sys/i386/i386/k6_mem.c b/sys/i386/i386/k6_mem.c
index 9cbacfe..c99cf27 100644
--- a/sys/i386/i386/k6_mem.c
+++ b/sys/i386/i386/k6_mem.c
@@ -70,6 +70,7 @@ static struct mem_range_ops k6_mrops =
{
k6_mrinit,
k6_mrset,
+ NULL,
NULL
};
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index e10217a..3987907 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -243,6 +243,7 @@ static void
cpu_startup(dummy)
void *dummy;
{
+ uintmax_t memsize;
char *sysenv;
/*
@@ -273,8 +274,18 @@ cpu_startup(dummy)
#ifdef PERFMON
perfmon_init();
#endif
- printf("real memory = %ju (%ju MB)\n", ptoa((uintmax_t)Maxmem),
- ptoa((uintmax_t)Maxmem) / 1048576);
+ sysenv = getenv("smbios.memory.enabled");
+ if (sysenv != NULL) {
+ memsize = (uintmax_t)strtoul(sysenv, (char **)NULL, 10);
+ freeenv(sysenv);
+ } else
+ memsize = 0;
+ if (memsize > 0)
+ printf("real memory = %ju (%ju MB)\n", memsize << 10,
+ memsize >> 10);
+ else
+ printf("real memory = %ju (%ju MB)\n", ptoa((uintmax_t)Maxmem),
+ ptoa((uintmax_t)Maxmem) / 1048576);
realmem = Maxmem;
/*
* Display any holes after the first chunk of extended memory.
@@ -578,6 +589,7 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
struct sigacts *psp;
char *sp;
struct trapframe *regs;
+ struct segment_descriptor *sdp;
int sig;
int oonstack;
@@ -614,6 +626,15 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
get_fpcontext(td, &sf.sf_uc.uc_mcontext);
fpstate_drop(td);
+ /*
+ * Unconditionally fill the fsbase and gsbase into the mcontext.
+ */
+ sdp = &td->td_pcb->pcb_gsd;
+ sf.sf_uc.uc_mcontext.mc_fsbase = sdp->sd_hibase << 24 |
+ sdp->sd_lobase;
+ sdp = &td->td_pcb->pcb_fsd;
+ sf.sf_uc.uc_mcontext.mc_gsbase = sdp->sd_hibase << 24 |
+ sdp->sd_lobase;
/* Allocate space for the signal handler context. */
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
@@ -1515,236 +1536,236 @@ extern vm_offset_t proc0kstack;
*/
struct soft_segment_descriptor gdt_segs[] = {
/* GNULL_SEL 0 Null Descriptor */
-{ 0x0, /* segment base address */
- 0x0, /* length */
- 0, /* segment type */
- SEL_KPL, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = SEL_KPL,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* GPRIV_SEL 1 SMP Per-Processor Private Data Descriptor */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_KPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_KPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GUFS_SEL 2 %fs Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GUGS_SEL 3 %gs Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GCODE_SEL 4 Code Descriptor for kernel */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMERA, /* segment type */
- SEL_KPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = SEL_KPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GDATA_SEL 5 Data Descriptor for kernel */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_KPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_KPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GUCODE_SEL 6 Code Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMERA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GUDATA_SEL 7 Data Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GBIOSLOWMEM_SEL 8 BIOS access to realmode segment 0x40, must be #8 in GDT */
-{ 0x400, /* segment base address */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- SEL_KPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x400,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_KPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
#ifndef XEN
/* GPROC0_SEL 9 Proc 0 Tss Descriptor */
{
- 0x0, /* segment base address */
- sizeof(struct i386tss)-1,/* length */
- SDT_SYS386TSS, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+ .ssd_base = 0x0,
+ .ssd_limit = sizeof(struct i386tss)-1,
+ .ssd_type = SDT_SYS386TSS,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* GLDT_SEL 10 LDT Descriptor */
-{ (int) ldt, /* segment base address */
- sizeof(ldt)-1, /* length - all address space */
- SDT_SYSLDT, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = (int) ldt,
+ .ssd_limit = sizeof(ldt)-1,
+ .ssd_type = SDT_SYSLDT,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* GUSERLDT_SEL 11 User LDT Descriptor per process */
-{ (int) ldt, /* segment base address */
- (512 * sizeof(union descriptor)-1), /* length */
- SDT_SYSLDT, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = (int) ldt,
+ .ssd_limit = (512 * sizeof(union descriptor)-1),
+ .ssd_type = SDT_SYSLDT,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* GPANIC_SEL 12 Panic Tss Descriptor */
-{ (int) &dblfault_tss, /* segment base address */
- sizeof(struct i386tss)-1,/* length - all address space */
- SDT_SYS386TSS, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = (int) &dblfault_tss,
+ .ssd_limit = sizeof(struct i386tss)-1,
+ .ssd_type = SDT_SYS386TSS,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* GBIOSCODE32_SEL 13 BIOS 32-bit interface (32bit Code) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMERA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 1 },
/* GBIOSCODE16_SEL 14 BIOS 32-bit interface (16bit Code) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMERA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 1 },
/* GBIOSDATA_SEL 15 BIOS 32-bit interface (Data) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GBIOSUTIL_SEL 16 BIOS 16-bit interface (Utility) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 1 },
/* GBIOSARGS_SEL 17 BIOS 16-bit interface (Arguments) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 1 },
/* GNDIS_SEL 18 NDIS Descriptor */
-{ 0x0, /* segment base address */
- 0x0, /* length */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
#endif /* !XEN */
};
static struct soft_segment_descriptor ldt_segs[] = {
/* Null Descriptor - overwritten by call gate */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* Null Descriptor - overwritten by call gate */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* Null Descriptor - overwritten by call gate */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* Code Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMERA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* Null Descriptor - overwritten by call gate */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* Data Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
};
void
@@ -3067,6 +3088,7 @@ int
get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
{
struct trapframe *tp;
+ struct segment_descriptor *sdp;
tp = td->td_frame;
@@ -3098,6 +3120,11 @@ get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
mcp->mc_ss = tp->tf_ss;
mcp->mc_len = sizeof(*mcp);
get_fpcontext(td, mcp);
+ sdp = &td->td_pcb->pcb_gsd;
+ mcp->mc_fsbase = sdp->sd_hibase << 24 | sdp->sd_lobase;
+ sdp = &td->td_pcb->pcb_fsd;
+ mcp->mc_gsbase = sdp->sd_hibase << 24 | sdp->sd_lobase;
+
return (0);
}
@@ -3528,45 +3555,24 @@ lapic_set_lvt_triggermode(u_int apic_id, u_int lvt, enum intr_trigger trigger)
#ifdef KDB
/*
- * Provide inb() and outb() as functions. They are normally only
- * available as macros calling inlined functions, thus cannot be
- * called from the debugger.
- *
- * The actual code is stolen from <machine/cpufunc.h>, and de-inlined.
+ * Provide inb() and outb() as functions. They are normally only available as
+ * inline functions, thus cannot be called from the debugger.
*/
-#undef inb
-#undef outb
-
/* silence compiler warnings */
-u_char inb(u_int);
-void outb(u_int, u_char);
+u_char inb_(u_short);
+void outb_(u_short, u_char);
u_char
-inb(u_int port)
+inb_(u_short port)
{
- u_char data;
- /*
- * We use %%dx and not %1 here because i/o is done at %dx and not at
- * %edx, while gcc generates inferior code (movw instead of movl)
- * if we tell it to load (u_short) port.
- */
- __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
- return (data);
+ return inb(port);
}
void
-outb(u_int port, u_char data)
+outb_(u_short port, u_char data)
{
- u_char al;
- /*
- * Use an unnecessary assignment to help gcc's register allocator.
- * This make a large difference for gcc-1.40 and a tiny difference
- * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for
- * best results. gcc-2.6.0 can't handle this.
- */
- al = data;
- __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
+ outb(port, data);
}
#endif /* KDB */
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 83da708..7f6900d 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -2442,6 +2442,7 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva,
mpte = pmap_lookup_pt_page(pmap, sva);
if (mpte != NULL) {
pmap_remove_pt_page(pmap, mpte);
+ pmap->pm_stats.resident_count--;
KASSERT(mpte->wire_count == NPTEPG,
("pmap_remove_pde: pte page wire count error"));
mpte->wire_count = 0;
@@ -3990,6 +3991,7 @@ pmap_remove_pages(pmap_t pmap)
mpte = pmap_lookup_pt_page(pmap, pv->pv_va);
if (mpte != NULL) {
pmap_remove_pt_page(pmap, mpte);
+ pmap->pm_stats.resident_count--;
KASSERT(mpte->wire_count == NPTEPG,
("pmap_remove_pages: pte page wire count error"));
mpte->wire_count = 0;
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index 2a6ca0f..e06a9a2 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -424,11 +424,6 @@ cpu_set_upcall(struct thread *td, struct thread *td0)
* Set registers for trampoline to user mode. Leave space for the
* return address on stack. These are the kernel mode register values.
*/
-#ifdef PAE
- pcb2->pcb_cr3 = vtophys(vmspace_pmap(td->td_proc->p_vmspace)->pm_pdpt);
-#else
- pcb2->pcb_cr3 = vtophys(vmspace_pmap(td->td_proc->p_vmspace)->pm_pdir);
-#endif
pcb2->pcb_edi = 0;
pcb2->pcb_esi = (int)fork_return; /* trampoline arg */
pcb2->pcb_ebp = 0;
@@ -439,6 +434,7 @@ cpu_set_upcall(struct thread *td, struct thread *td0)
pcb2->pcb_gs = rgs();
/*
* If we didn't copy the pcb, we'd need to do the following registers:
+ * pcb2->pcb_cr3: cloned above.
* pcb2->pcb_dr*: cloned above.
* pcb2->pcb_savefpu: cloned above.
* pcb2->pcb_flags: cloned above.
diff --git a/sys/i386/include/cpufunc.h b/sys/i386/include/cpufunc.h
index ad5fc4c..98eb9ac 100644
--- a/sys/i386/include/cpufunc.h
+++ b/sys/i386/include/cpufunc.h
@@ -170,70 +170,12 @@ halt(void)
__asm __volatile("hlt");
}
-#if !defined(__GNUCLIKE_BUILTIN_CONSTANT_P) || __GNUCLIKE_ASM < 3
-
-#define inb(port) inbv(port)
-#define outb(port, data) outbv(port, data)
-
-#else /* __GNUCLIKE_BUILTIN_CONSTANT_P && __GNUCLIKE_ASM >= 3 */
-
-/*
- * The following complications are to get around gcc not having a
- * constraint letter for the range 0..255. We still put "d" in the
- * constraint because "i" isn't a valid constraint when the port
- * isn't constant. This only matters for -O0 because otherwise
- * the non-working version gets optimized away.
- *
- * Use an expression-statement instead of a conditional expression
- * because gcc-2.6.0 would promote the operands of the conditional
- * and produce poor code for "if ((inb(var) & const1) == const2)".
- *
- * The unnecessary test `(port) < 0x10000' is to generate a warning if
- * the `port' has type u_short or smaller. Such types are pessimal.
- * This actually only works for signed types. The range check is
- * careful to avoid generating warnings.
- */
-#define inb(port) __extension__ ({ \
- u_char _data; \
- if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \
- && (port) < 0x10000) \
- _data = inbc(port); \
- else \
- _data = inbv(port); \
- _data; })
-
-#define outb(port, data) ( \
- __builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \
- && (port) < 0x10000 \
- ? outbc(port, data) : outbv(port, data))
-
static __inline u_char
-inbc(u_int port)
+inb(u_int port)
{
u_char data;
- __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
- return (data);
-}
-
-static __inline void
-outbc(u_int port, u_char data)
-{
- __asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
-}
-
-#endif /* __GNUCLIKE_BUILTIN_CONSTANT_P && __GNUCLIKE_ASM >= 3*/
-
-static __inline u_char
-inbv(u_int port)
-{
- u_char data;
- /*
- * We use %%dx and not %1 here because i/o is done at %dx and not at
- * %edx, while gcc generates inferior code (movw instead of movl)
- * if we tell it to load (u_short) port.
- */
- __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
+ __asm volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
return (data);
}
@@ -242,7 +184,7 @@ inl(u_int port)
{
u_int data;
- __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
+ __asm volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
return (data);
}
@@ -284,33 +226,20 @@ inw(u_int port)
{
u_short data;
- __asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
+ __asm volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
return (data);
}
static __inline void
-outbv(u_int port, u_char data)
+outb(u_int port, u_char data)
{
- u_char al;
- /*
- * Use an unnecessary assignment to help gcc's register allocator.
- * This make a large difference for gcc-1.40 and a tiny difference
- * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for
- * best results. gcc-2.6.0 can't handle this.
- */
- al = data;
- __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
+ __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
}
static __inline void
outl(u_int port, u_int data)
{
- /*
- * outl() and outw() aren't used much so we haven't looked at
- * possible micro-optimizations such as the unnecessary
- * assignment for them.
- */
- __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
+ __asm volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
}
static __inline void
@@ -340,7 +269,7 @@ outsl(u_int port, const void *addr, size_t cnt)
static __inline void
outw(u_int port, u_short data)
{
- __asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
+ __asm volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
}
static __inline void
diff --git a/sys/i386/include/elf.h b/sys/i386/include/elf.h
index 1470173..af71ab8 100644
--- a/sys/i386/include/elf.h
+++ b/sys/i386/include/elf.h
@@ -84,16 +84,14 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-/*
- * The following non-standard values are used in Linux ELF binaries.
- */
#define AT_NOTELF 10 /* Program is not ELF ?? */
#define AT_UID 11 /* Real uid. */
#define AT_EUID 12 /* Effective uid. */
#define AT_GID 13 /* Real gid. */
#define AT_EGID 14 /* Effective gid. */
+#define AT_EXECPATH 15 /* Path to the executable. */
-#define AT_COUNT 15 /* Count of defined aux entry types. */
+#define AT_COUNT 16 /* Count of defined aux entry types. */
/*
* Relocation types.
diff --git a/sys/i386/include/endian.h b/sys/i386/include/endian.h
index 59fa4a5..6522ec4 100644
--- a/sys/i386/include/endian.h
+++ b/sys/i386/include/endian.h
@@ -69,25 +69,6 @@ extern "C" {
#if defined(__GNUCLIKE_ASM) && defined(__GNUCLIKE_BUILTIN_CONSTANT_P)
-#define __word_swap_int_var(x) \
-__extension__ ({ register __uint32_t __X = (x); \
- __asm ("rorl $16, %0" : "+r" (__X)); \
- __X; })
-
-#ifdef __OPTIMIZE__
-
-#define __word_swap_int_const(x) \
- ((((x) & 0xffff0000) >> 16) | \
- (((x) & 0x0000ffff) << 16))
-#define __word_swap_int(x) (__builtin_constant_p(x) ? \
- __word_swap_int_const(x) : __word_swap_int_var(x))
-
-#else /* __OPTIMIZE__ */
-
-#define __word_swap_int(x) __word_swap_int_var(x)
-
-#endif /* __OPTIMIZE__ */
-
#define __byte_swap_int_var(x) \
__extension__ ({ register __uint32_t __X = (x); \
__asm ("bswap %0" : "+r" (__X)); \
@@ -109,26 +90,6 @@ __extension__ ({ register __uint32_t __X = (x); \
#endif /* __OPTIMIZE__ */
-#define __byte_swap_word_var(x) \
-__extension__ ({ register __uint16_t __X = (x); \
- __asm ("xchgb %h0, %b0" : "+q" (__X)); \
- __X; })
-
-#ifdef __OPTIMIZE__
-
-#define __byte_swap_word_const(x) \
- ((((x) & 0xff00) >> 8) | \
- (((x) & 0x00ff) << 8))
-
-#define __byte_swap_word(x) (__builtin_constant_p(x) ? \
- __byte_swap_word_const(x) : __byte_swap_word_var(x))
-
-#else /* __OPTIMIZE__ */
-
-#define __byte_swap_word(x) __byte_swap_word_var(x)
-
-#endif /* __OPTIMIZE__ */
-
static __inline __uint64_t
__bswap64(__uint64_t _x)
{
@@ -149,8 +110,7 @@ __bswap32(__uint32_t _x)
static __inline __uint16_t
__bswap16(__uint16_t _x)
{
-
- return (__byte_swap_word(_x));
+ return (_x << 8 | _x >> 8);
}
#define __htonl(x) __bswap32(x)
diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h
index 00a3f7b..519ff6c 100644
--- a/sys/i386/include/pmap.h
+++ b/sys/i386/include/pmap.h
@@ -174,8 +174,7 @@ typedef uint32_t pt_entry_t;
#endif
/*
- * Address of current and alternate address space page table maps
- * and directories.
+ * Address of current address space page table maps and directories.
*/
#ifdef _KERNEL
extern pt_entry_t PTmap[];
diff --git a/sys/i386/include/signal.h b/sys/i386/include/signal.h
index 8d6b935..7a5f876 100644
--- a/sys/i386/include/signal.h
+++ b/sys/i386/include/signal.h
@@ -116,7 +116,11 @@ struct sigcontext {
int sc_ownedfp;
int sc_spare1[1];
int sc_fpstate[128] __aligned(16);
- int sc_spare2[8];
+
+ int sc_fsbase;
+ int sc_gsbase;
+
+ int sc_spare2[6];
};
#define sc_sp sc_esp
diff --git a/sys/i386/include/ucontext.h b/sys/i386/include/ucontext.h
index c992495..d8657d3 100644
--- a/sys/i386/include/ucontext.h
+++ b/sys/i386/include/ucontext.h
@@ -72,10 +72,15 @@ typedef struct __mcontext {
* See <machine/npx.h> for the internals of mc_fpstate[].
*/
int mc_fpstate[128] __aligned(16);
- int mc_spare2[8];
+
+ __register_t mc_fsbase;
+ __register_t mc_gsbase;
+
+ int mc_spare2[6];
} mcontext_t;
#if defined(_KERNEL) && defined(COMPAT_FREEBSD4)
+
struct mcontext4 {
__register_t mc_onstack; /* XXX - sigcontext compat. */
__register_t mc_gs; /* machine state (struct trapframe) */
diff --git a/sys/i386/include/vmparam.h b/sys/i386/include/vmparam.h
index f114232..e5f596c 100644
--- a/sys/i386/include/vmparam.h
+++ b/sys/i386/include/vmparam.h
@@ -43,10 +43,6 @@
* Machine dependent constants for 386.
*/
-#ifndef PAE
-#define VM_PROT_READ_IS_EXEC /* if you can read -- then you can exec */
-#endif
-
/*
* Virtual memory related constants, all in bytes
*/
diff --git a/sys/i386/include/xen/xenpmap.h b/sys/i386/include/xen/xenpmap.h
index 4bfd99e..b8a545e 100644
--- a/sys/i386/include/xen/xenpmap.h
+++ b/sys/i386/include/xen/xenpmap.h
@@ -45,6 +45,8 @@ void xen_pt_pin(vm_paddr_t);
void xen_pt_unpin(vm_paddr_t);
void xen_flush_queue(void);
void pmap_ref(pt_entry_t *pte, vm_paddr_t ma);
+void pmap_suspend(void);
+void pmap_resume(void);
void xen_check_queue(void);
#ifdef INVARIANTS
diff --git a/sys/i386/include/xen/xenvar.h b/sys/i386/include/xen/xenvar.h
index 402bc8a..cefbb05 100644
--- a/sys/i386/include/xen/xenvar.h
+++ b/sys/i386/include/xen/xenvar.h
@@ -40,6 +40,8 @@ extern int xendebug_flags;
#include <machine/xen/features.h>
extern xen_pfn_t *xen_phys_machine;
+extern xen_pfn_t *xen_pfn_to_mfn_frame_list[16];
+extern xen_pfn_t *xen_pfn_to_mfn_frame_list_list;
#if 0
#define TRACE_ENTER XENPRINTF("(file=%s, line=%d) entered %s\n", __FILE__, __LINE__, __FUNCTION__)
diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c
index a4f5b34..6da4b4c 100644
--- a/sys/i386/isa/npx.c
+++ b/sys/i386/isa/npx.c
@@ -181,7 +181,7 @@ SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD,
static volatile u_int npx_intrs_while_probing;
static volatile u_int npx_traps_while_probing;
-static union savefpu npx_cleanstate;
+static union savefpu npx_initialstate;
static bool_t npx_ex16;
static bool_t npx_exists;
static bool_t npx_irq13;
@@ -423,24 +423,24 @@ npx_attach(dev)
s = intr_disable();
stop_emulating();
- fpusave(&npx_cleanstate);
+ fpusave(&npx_initialstate);
start_emulating();
#ifdef CPU_ENABLE_SSE
if (cpu_fxsr) {
- if (npx_cleanstate.sv_xmm.sv_env.en_mxcsr_mask)
+ if (npx_initialstate.sv_xmm.sv_env.en_mxcsr_mask)
cpu_mxcsr_mask =
- npx_cleanstate.sv_xmm.sv_env.en_mxcsr_mask;
+ npx_initialstate.sv_xmm.sv_env.en_mxcsr_mask;
else
cpu_mxcsr_mask = 0xFFBF;
- bzero(npx_cleanstate.sv_xmm.sv_fp,
- sizeof(npx_cleanstate.sv_xmm.sv_fp));
- bzero(npx_cleanstate.sv_xmm.sv_xmm,
- sizeof(npx_cleanstate.sv_xmm.sv_xmm));
+ bzero(npx_initialstate.sv_xmm.sv_fp,
+ sizeof(npx_initialstate.sv_xmm.sv_fp));
+ bzero(npx_initialstate.sv_xmm.sv_xmm,
+ sizeof(npx_initialstate.sv_xmm.sv_xmm));
/* XXX might need even more zeroing. */
} else
#endif
- bzero(npx_cleanstate.sv_87.sv_ac,
- sizeof(npx_cleanstate.sv_87.sv_ac));
+ bzero(npx_initialstate.sv_87.sv_ac,
+ sizeof(npx_initialstate.sv_87.sv_ac));
intr_restore(s);
#ifdef I586_CPU_XXX
if (cpu_class == CPUCLASS_586 && npx_ex16 &&
@@ -794,13 +794,18 @@ npxdna(void)
PCPU_SET(fpcurthread, curthread);
pcb = PCPU_GET(curpcb);
+#ifdef CPU_ENABLE_SSE
+ if (cpu_fxsr)
+ fpu_clean_state();
+#endif
+
if ((pcb->pcb_flags & PCB_NPXINITDONE) == 0) {
/*
* This is the first time this thread has used the FPU or
* the PCB doesn't contain a clean FPU state. Explicitly
- * load sanitized registers.
+ * load an initial state.
*/
- fpurstor(&npx_cleanstate);
+ fpurstor(&npx_initialstate);
if (pcb->pcb_initial_npxcw != __INITIAL_NPXCW__)
fldcw(&pcb->pcb_initial_npxcw);
pcb->pcb_flags |= PCB_NPXINITDONE;
@@ -900,7 +905,7 @@ npxgetregs(td, addr)
return (_MC_FPOWNED_NONE);
if ((td->td_pcb->pcb_flags & PCB_NPXINITDONE) == 0) {
- bcopy(&npx_cleanstate, addr, sizeof(npx_cleanstate));
+ bcopy(&npx_initialstate, addr, sizeof(npx_initialstate));
SET_FPU_CW(addr, td->td_pcb->pcb_initial_npxcw);
return (_MC_FPOWNED_NONE);
}
@@ -976,10 +981,10 @@ fpusave(addr)
* In order to avoid leaking this information across processes, we clean
* these values by performing a dummy load before executing fxrstor().
*/
-static double dummy_variable = 0.0;
static void
fpu_clean_state(void)
{
+ static float dummy_variable = 0.0;
u_short status;
/*
@@ -1005,10 +1010,9 @@ fpurstor(addr)
{
#ifdef CPU_ENABLE_SSE
- if (cpu_fxsr) {
- fpu_clean_state();
+ if (cpu_fxsr)
fxrstor(addr);
- } else
+ else
#endif
frstor(addr);
}
diff --git a/sys/i386/linux/linux_sysvec.c b/sys/i386/linux/linux_sysvec.c
index 4efd496..707ffb3 100644
--- a/sys/i386/linux/linux_sysvec.c
+++ b/sys/i386/linux/linux_sysvec.c
@@ -1019,6 +1019,16 @@ struct sysentvec elf_linux_sysvec = {
.sv_flags = SV_ABI_LINUX | SV_IA32 | SV_ILP32
};
+static char GNULINUX_ABI_VENDOR[] = "GNU";
+
+static Elf_Brandnote linux_brandnote = {
+ .hdr.n_namesz = sizeof(GNULINUX_ABI_VENDOR),
+ .hdr.n_descsz = 16,
+ .hdr.n_type = 1,
+ .vendor = GNULINUX_ABI_VENDOR,
+ .flags = 0
+};
+
static Elf32_Brandinfo linux_brand = {
.brand = ELFOSABI_LINUX,
.machine = EM_386,
@@ -1027,7 +1037,8 @@ static Elf32_Brandinfo linux_brand = {
.interp_path = "/lib/ld-linux.so.1",
.sysvec = &elf_linux_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &linux_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
static Elf32_Brandinfo linux_glibc2brand = {
@@ -1038,7 +1049,8 @@ static Elf32_Brandinfo linux_glibc2brand = {
.interp_path = "/lib/ld-linux.so.2",
.sysvec = &elf_linux_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &linux_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
Elf32_Brandinfo *linux_brandlist[] = {
diff --git a/sys/i386/pci/pci_cfgreg.c b/sys/i386/pci/pci_cfgreg.c
index 3c41ba7..ecefa17 100644
--- a/sys/i386/pci/pci_cfgreg.c
+++ b/sys/i386/pci/pci_cfgreg.c
@@ -206,6 +206,7 @@ pci_docfgregread(int bus, int slot, int func, int reg, int bytes)
{
if (cfgmech == CFGMECH_PCIE &&
+ (bus >= pcie_minbus && bus <= pcie_maxbus) &&
(bus != 0 || !(1 << slot & pcie_badslots)))
return (pciereg_cfgread(bus, slot, func, reg, bytes));
else
@@ -240,6 +241,7 @@ pci_cfgregwrite(int bus, int slot, int func, int reg, u_int32_t data, int bytes)
{
if (cfgmech == CFGMECH_PCIE &&
+ (bus >= pcie_minbus && bus <= pcie_maxbus) &&
(bus != 0 || !(1 << slot & pcie_badslots)))
pciereg_cfgwrite(bus, slot, func, reg, data, bytes);
else
diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c
index 3725d0a..59947e8 100644
--- a/sys/i386/xen/pmap.c
+++ b/sys/i386/xen/pmap.c
@@ -4100,6 +4100,72 @@ pmap_align_superpage(vm_object_t object, vm_ooffset_t offset,
*addr = ((*addr + PDRMASK) & ~PDRMASK) + superpage_offset;
}
+#ifdef XEN
+
+void
+pmap_suspend()
+{
+ pmap_t pmap;
+ int i, pdir, offset;
+ vm_paddr_t pdirma;
+ mmu_update_t mu[4];
+
+ /*
+ * We need to remove the recursive mapping structure from all
+ * our pmaps so that Xen doesn't get confused when it restores
+ * the page tables. The recursive map lives at page directory
+ * index PTDPTDI. We assume that the suspend code has stopped
+ * the other vcpus (if any).
+ */
+ LIST_FOREACH(pmap, &allpmaps, pm_list) {
+ for (i = 0; i < 4; i++) {
+ /*
+ * Figure out which page directory (L2) page
+ * contains this bit of the recursive map and
+ * the offset within that page of the map
+ * entry
+ */
+ pdir = (PTDPTDI + i) / NPDEPG;
+ offset = (PTDPTDI + i) % NPDEPG;
+ pdirma = pmap->pm_pdpt[pdir] & PG_FRAME;
+ mu[i].ptr = pdirma + offset * sizeof(pd_entry_t);
+ mu[i].val = 0;
+ }
+ HYPERVISOR_mmu_update(mu, 4, NULL, DOMID_SELF);
+ }
+}
+
+void
+pmap_resume()
+{
+ pmap_t pmap;
+ int i, pdir, offset;
+ vm_paddr_t pdirma;
+ mmu_update_t mu[4];
+
+ /*
+ * Restore the recursive map that we removed on suspend.
+ */
+ LIST_FOREACH(pmap, &allpmaps, pm_list) {
+ for (i = 0; i < 4; i++) {
+ /*
+ * Figure out which page directory (L2) page
+ * contains this bit of the recursive map and
+ * the offset within that page of the map
+ * entry
+ */
+ pdir = (PTDPTDI + i) / NPDEPG;
+ offset = (PTDPTDI + i) % NPDEPG;
+ pdirma = pmap->pm_pdpt[pdir] & PG_FRAME;
+ mu[i].ptr = pdirma + offset * sizeof(pd_entry_t);
+ mu[i].val = (pmap->pm_pdpt[i] & PG_FRAME) | PG_V;
+ }
+ HYPERVISOR_mmu_update(mu, 4, NULL, DOMID_SELF);
+ }
+}
+
+#endif
+
#if defined(PMAP_DEBUG)
pmap_pid_dump(int pid)
{
diff --git a/sys/i386/xen/xen_machdep.c b/sys/i386/xen/xen_machdep.c
index c99d754..878f436 100644
--- a/sys/i386/xen/xen_machdep.c
+++ b/sys/i386/xen/xen_machdep.c
@@ -89,6 +89,8 @@ start_info_t *xen_start_info;
shared_info_t *HYPERVISOR_shared_info;
xen_pfn_t *xen_machine_phys = machine_to_phys_mapping;
xen_pfn_t *xen_phys_machine;
+xen_pfn_t *xen_pfn_to_mfn_frame_list[16];
+xen_pfn_t *xen_pfn_to_mfn_frame_list_list;
int preemptable, init_first;
extern unsigned int avail_space;
@@ -810,6 +812,39 @@ shift_phys_machine(unsigned long *phys_machine, int nr_pages)
}
#endif /* ADD_ISA_HOLE */
+/*
+ * Build a directory of the pages that make up our Physical to Machine
+ * mapping table. The Xen suspend/restore code uses this to find our
+ * mapping table.
+ */
+static void
+init_frame_list_list(void *arg)
+{
+ unsigned long nr_pages = xen_start_info->nr_pages;
+#define FPP (PAGE_SIZE/sizeof(xen_pfn_t))
+ int i, j, k;
+
+ xen_pfn_to_mfn_frame_list_list = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
+ for (i = 0, j = 0, k = -1; i < nr_pages;
+ i += FPP, j++) {
+ if ((j & (FPP - 1)) == 0) {
+ k++;
+ xen_pfn_to_mfn_frame_list[k] =
+ malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK);
+ xen_pfn_to_mfn_frame_list_list[k] =
+ VTOMFN(xen_pfn_to_mfn_frame_list[k]);
+ j = 0;
+ }
+ xen_pfn_to_mfn_frame_list[k][j] =
+ VTOMFN(&xen_phys_machine[i]);
+ }
+
+ HYPERVISOR_shared_info->arch.max_pfn = nr_pages;
+ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list
+ = VTOMFN(xen_pfn_to_mfn_frame_list_list);
+}
+SYSINIT(init_fll, SI_SUB_DEVFS, SI_ORDER_ANY, init_frame_list_list, NULL);
+
extern unsigned long physfree;
int pdir, curoffset;
@@ -1081,7 +1116,6 @@ initvalues(start_info_t *startinfo)
PT_SET_MA(console_page, console_page_ma | PG_KERNEL);
printk("#5\n");
- HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = (unsigned long)xen_phys_machine;
set_iopl.iopl = 1;
PANIC_IF(HYPERVISOR_physdev_op(PHYSDEVOP_SET_IOPL, &set_iopl));
diff --git a/sys/mips/alchemy/uart_cpu_alchemy.c b/sys/ia64/ia32/ia32_misc.c
index 931aed6..c85e31d 100644
--- a/sys/mips/alchemy/uart_cpu_alchemy.c
+++ b/sys/ia64/ia32/ia32_misc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2006 Wojciech A. Koszek <wkoszek@FreeBSD.org>
+ * Copyright (c) 2009 Konstantin Belousov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -22,58 +22,29 @@
* 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.
- *
- * $Id$
- */
-/*
- * Skeleton of this file was based on respective code for ARM
- * code written by Olivier Houchard.
*/
-#include "opt_uart.h"
-
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_compat.h"
+
#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/socket.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/cons.h>
-
-#include <machine/bus.h>
-
-#include <dev/uart/uart.h>
-#include <dev/uart/uart_cpu.h>
-
-#include <mips/alchemy/aureg.h>
+#include <sys/uio.h>
-bus_space_tag_t uart_bus_space_io;
-bus_space_tag_t uart_bus_space_mem;
+#include <compat/freebsd32/freebsd32_util.h>
+#include <compat/freebsd32/freebsd32.h>
+#include <compat/freebsd32/freebsd32_proto.h>
int
-uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
+freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
{
- return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
-}
-
-int
-uart_cpu_getdev(int devtype, struct uart_devinfo *di)
-{
-
- di->ops = uart_getops(&uart_ns8250_class);
- di->bas.chan = 0;
- di->bas.bst = 0;
- di->bas.regshft = 0;
- di->bas.rclk = 0;
- di->baudrate = 115200;
- di->databits = 8;
- di->stopbits = 1;
- di->parity = UART_PARITY_NONE;
-
- uart_bus_space_io = 0;
- uart_bus_space_mem = MIPS_PHYS_TO_KSEG1(UART0_BASE);
- di->bas.bsh = MIPS_PHYS_TO_KSEG1(UART0_BASE);
-
- return (0);
+ return (EOPNOTSUPP);
}
diff --git a/sys/ia64/ia64/elf_machdep.c b/sys/ia64/ia64/elf_machdep.c
index a3a6e57..3d3d214 100644
--- a/sys/ia64/ia64/elf_machdep.c
+++ b/sys/ia64/ia64/elf_machdep.c
@@ -92,7 +92,8 @@ static Elf64_Brandinfo freebsd_brand_info = {
.interp_path = "/libexec/ld-elf.so.1",
.sysvec = &elf64_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf64_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t)elf64_insert_brand_entry, &freebsd_brand_info);
@@ -105,7 +106,8 @@ static Elf64_Brandinfo freebsd_brand_oinfo = {
.interp_path = "/usr/libexec/ld-elf.so.1",
.sysvec = &elf64_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf64_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
(sysinit_cfunc_t)elf64_insert_brand_entry, &freebsd_brand_oinfo);
diff --git a/sys/ia64/include/elf.h b/sys/ia64/include/elf.h
index faab8d1..65802aa 100644
--- a/sys/ia64/include/elf.h
+++ b/sys/ia64/include/elf.h
@@ -82,16 +82,14 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-/*
- * The following non-standard values are used in Linux ELF binaries.
- */
#define AT_NOTELF 10 /* Program is not ELF ?? */
#define AT_UID 11 /* Real uid. */
#define AT_EUID 12 /* Effective uid. */
#define AT_GID 13 /* Real gid. */
#define AT_EGID 14 /* Effective gid. */
+#define AT_EXECPATH 15 /* Path to the executable. */
-#define AT_COUNT 15 /* Count of defined aux entry types. */
+#define AT_COUNT 16 /* Count of defined aux entry types. */
/*
* Values for e_flags.
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index ec96974..e2c0a12 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -78,14 +78,16 @@ __FBSDID("$FreeBSD$");
#define OLD_EI_BRAND 8
static int __elfN(check_header)(const Elf_Ehdr *hdr);
-static Elf_Brandinfo *__elfN(get_brandinfo)(const Elf_Ehdr *hdr,
- const char *interp);
+static Elf_Brandinfo *__elfN(get_brandinfo)(struct image_params *imgp,
+ const char *interp, int32_t *osrel);
static int __elfN(load_file)(struct proc *p, const char *file, u_long *addr,
u_long *entry, size_t pagesize);
static int __elfN(load_section)(struct vmspace *vmspace, vm_object_t object,
vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
vm_prot_t prot, size_t pagesize);
static int __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp);
+static boolean_t __elfN(check_note)(struct image_params *imgp,
+ Elf_Brandnote *checknote, int32_t *osrel);
SYSCTL_NODE(_kern, OID_AUTO, __CONCAT(elf, __ELF_WORD_SIZE), CTLFLAG_RW, 0,
"");
@@ -107,6 +109,16 @@ static Elf_Brandinfo *elf_brand_list[MAX_BRANDS];
#define round_page_ps(va, ps) (((va) + (ps - 1)) & ~(ps - 1))
#define aligned(a, t) (trunc_page_ps((u_long)(a), sizeof(t)) == (u_long)(a))
+static const char FREEBSD_ABI_VENDOR[] = "FreeBSD";
+
+Elf_Brandnote __elfN(freebsd_brandnote) = {
+ .hdr.n_namesz = sizeof(FREEBSD_ABI_VENDOR),
+ .hdr.n_descsz = sizeof(int32_t),
+ .hdr.n_type = 1,
+ .vendor = FREEBSD_ABI_VENDOR,
+ .flags = BN_CAN_FETCH_OSREL
+};
+
int
__elfN(insert_brand_entry)(Elf_Brandinfo *entry)
{
@@ -158,19 +170,32 @@ __elfN(brand_inuse)(Elf_Brandinfo *entry)
}
static Elf_Brandinfo *
-__elfN(get_brandinfo)(const Elf_Ehdr *hdr, const char *interp)
+__elfN(get_brandinfo)(struct image_params *imgp, const char *interp,
+ int32_t *osrel)
{
+ const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header;
Elf_Brandinfo *bi;
+ boolean_t ret;
int i;
/*
- * We support three types of branding -- (1) the ELF EI_OSABI field
+ * We support four types of branding -- (1) the ELF EI_OSABI field
* that SCO added to the ELF spec, (2) FreeBSD 3.x's traditional string
- * branding w/in the ELF header, and (3) path of the `interp_path'
- * field. We should also look for an ".note.ABI-tag" ELF section now
- * in all Linux ELF binaries, FreeBSD 4.1+, and some NetBSD ones.
+ * branding w/in the ELF header, (3) path of the `interp_path'
+ * field, and (4) the ".note.ABI-tag" ELF section.
*/
+ /* Look for an ".note.ABI-tag" ELF section */
+ for (i = 0; i < MAX_BRANDS; i++) {
+ bi = elf_brand_list[i];
+ if (bi != NULL && hdr->e_machine == bi->machine &&
+ (bi->flags & BI_BRAND_NOTE) != 0) {
+ ret = __elfN(check_note)(imgp, bi->brand_note, osrel);
+ if (ret)
+ return (bi);
+ }
+ }
+
/* If the executable has a brand, search for it in the brand list. */
for (i = 0; i < MAX_BRANDS; i++) {
bi = elf_brand_list[i];
@@ -590,13 +615,11 @@ fail:
return (error);
}
-static const char FREEBSD_ABI_VENDOR[] = "FreeBSD";
-
static int
__CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
{
const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header;
- const Elf_Phdr *phdr, *pnote = NULL;
+ const Elf_Phdr *phdr;
Elf_Auxargs *elf_auxargs;
struct vmspace *vmspace;
vm_prot_t prot;
@@ -604,12 +627,11 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
u_long text_addr = 0, data_addr = 0;
u_long seg_size, seg_addr;
u_long addr, entry = 0, proghdr = 0;
+ int32_t osrel = 0;
int error = 0, i;
const char *interp = NULL, *newinterp = NULL;
Elf_Brandinfo *brand_info;
- const Elf_Note *note, *note_end;
char *path;
- const char *note_name;
struct sysentvec *sv;
/*
@@ -646,7 +668,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
}
}
- brand_info = __elfN(get_brandinfo)(hdr, interp);
+ brand_info = __elfN(get_brandinfo)(imgp, interp, &osrel);
if (brand_info == NULL) {
uprintf("ELF binary type \"%u\" not known.\n",
hdr->e_ident[EI_OSABI]);
@@ -750,9 +772,6 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
case PT_PHDR: /* Program header table info */
proghdr = phdr[i].p_vaddr;
break;
- case PT_NOTE:
- pnote = &phdr[i];
- break;
default:
break;
}
@@ -840,41 +859,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp)
imgp->auxargs = elf_auxargs;
imgp->interpreted = 0;
-
- /*
- * Try to fetch the osreldate for FreeBSD binary from the ELF
- * OSABI-note. Only the first page of the image is searched,
- * the same as for headers.
- */
- if (pnote != NULL && pnote->p_offset < PAGE_SIZE &&
- pnote->p_offset + pnote->p_filesz < PAGE_SIZE ) {
- note = (const Elf_Note *)(imgp->image_header + pnote->p_offset);
- if (!aligned(note, Elf32_Addr)) {
- free(imgp->auxargs, M_TEMP);
- imgp->auxargs = NULL;
- return (ENOEXEC);
- }
- note_end = (const Elf_Note *)(imgp->image_header + pnote->p_offset +
- pnote->p_filesz);
- while (note < note_end) {
- if (note->n_namesz == sizeof(FREEBSD_ABI_VENDOR) &&
- note->n_descsz == sizeof(int32_t) &&
- note->n_type == 1 /* ABI_NOTETYPE */) {
- note_name = (const char *)(note + 1);
- if (strncmp(FREEBSD_ABI_VENDOR, note_name,
- sizeof(FREEBSD_ABI_VENDOR)) == 0) {
- imgp->proc->p_osrel = *(const int32_t *)
- (note_name +
- round_page_ps(sizeof(FREEBSD_ABI_VENDOR),
- sizeof(Elf32_Addr)));
- break;
- }
- }
- note = (const Elf_Note *)((const char *)(note + 1) +
- round_page_ps(note->n_namesz, sizeof(Elf32_Addr)) +
- round_page_ps(note->n_descsz, sizeof(Elf32_Addr)));
- }
- }
+ imgp->proc->p_osrel = osrel;
return (error);
}
@@ -900,6 +885,8 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp)
AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
AUXARGS_ENTRY(pos, AT_BASE, args->base);
+ if (imgp->execpathp != 0)
+ AUXARGS_ENTRY(pos, AT_EXECPATH, imgp->execpathp);
AUXARGS_ENTRY(pos, AT_NULL, 0);
free(imgp->auxargs, M_TEMP);
@@ -1336,6 +1323,71 @@ __elfN(putnote)(void *dst, size_t *off, const char *name, int type,
}
/*
+ * Try to find the appropriate ABI-note section for checknote,
+ * fetch the osreldate for binary from the ELF OSABI-note. Only the
+ * first page of the image is searched, the same as for headers.
+ */
+static boolean_t
+__elfN(check_note)(struct image_params *imgp, Elf_Brandnote *checknote,
+ int32_t *osrel)
+{
+ const Elf_Note *note, *note0, *note_end;
+ const Elf_Phdr *phdr, *pnote;
+ const Elf_Ehdr *hdr;
+ const char *note_name;
+ int i;
+
+ pnote = NULL;
+ hdr = (const Elf_Ehdr *)imgp->image_header;
+ phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff);
+
+ for (i = 0; i < hdr->e_phnum; i++) {
+ if (phdr[i].p_type == PT_NOTE) {
+ pnote = &phdr[i];
+ break;
+ }
+ }
+
+ if (pnote == NULL || pnote->p_offset >= PAGE_SIZE ||
+ pnote->p_offset + pnote->p_filesz >= PAGE_SIZE)
+ return (FALSE);
+
+ note = note0 = (const Elf_Note *)(imgp->image_header + pnote->p_offset);
+ note_end = (const Elf_Note *)(imgp->image_header +
+ pnote->p_offset + pnote->p_filesz);
+ for (i = 0; i < 100 && note >= note0 && note < note_end; i++) {
+ if (!aligned(note, Elf32_Addr))
+ return (FALSE);
+ if (note->n_namesz != checknote->hdr.n_namesz ||
+ note->n_descsz != checknote->hdr.n_descsz ||
+ note->n_type != checknote->hdr.n_type)
+ goto nextnote;
+ note_name = (const char *)(note + 1);
+ if (strncmp(checknote->vendor, note_name,
+ checknote->hdr.n_namesz) != 0)
+ goto nextnote;
+
+ /*
+ * Fetch the osreldate for binary
+ * from the ELF OSABI-note if necessary.
+ */
+ if ((checknote->flags & BN_CAN_FETCH_OSREL) != 0 &&
+ osrel != NULL)
+ *osrel = *(const int32_t *) (note_name +
+ roundup2(checknote->hdr.n_namesz,
+ sizeof(Elf32_Addr)));
+ return (TRUE);
+
+nextnote:
+ note = (const Elf_Note *)((const char *)(note + 1) +
+ roundup2(note->n_namesz, sizeof(Elf32_Addr)) +
+ roundup2(note->n_descsz, sizeof(Elf32_Addr)));
+ }
+
+ return (FALSE);
+}
+
+/*
* Tell kern_execve.c about it, with a little help from the linker.
*/
static struct execsw __elfN(execsw) = {
diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c
index d45e3b7..8355ca5 100644
--- a/sys/kern/kern_acct.c
+++ b/sys/kern/kern_acct.c
@@ -436,7 +436,6 @@ acct_process(struct thread *td)
* Write the accounting information to the file.
*/
vfslocked = VFS_LOCK_GIANT(acct_vp->v_mount);
- VOP_LEASE(acct_vp, td, acct_cred, LEASE_WRITE);
ret = vn_rdwr(UIO_WRITE, acct_vp, (caddr_t)&acct, sizeof (acct),
(off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT, acct_cred, NOCRED,
(int *)0, td);
diff --git a/sys/kern/kern_alq.c b/sys/kern/kern_alq.c
index 512f358..9f37244 100644
--- a/sys/kern/kern_alq.c
+++ b/sys/kern/kern_alq.c
@@ -293,7 +293,6 @@ alq_doio(struct alq *alq)
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
vn_start_write(vp, &mp, V_WAIT);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- VOP_LEASE(vp, td, alq->aq_cred, LEASE_WRITE);
/*
* XXX: VOP_WRITE error checks are ignored.
*/
diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c
index a5658ca..038515b 100644
--- a/sys/kern/kern_environment.c
+++ b/sys/kern/kern_environment.c
@@ -87,7 +87,7 @@ kenv(td, uap)
} */ *uap;
{
char *name, *value, *buffer = NULL;
- size_t len, done, needed;
+ size_t len, done, needed, buflen;
int error, i;
KASSERT(dynamic_kenv, ("kenv: dynamic_kenv = 0"));
@@ -100,13 +100,17 @@ kenv(td, uap)
return (error);
#endif
done = needed = 0;
+ buflen = uap->len;
+ if (buflen > KENV_SIZE * (KENV_MNAMELEN + KENV_MVALLEN + 2))
+ buflen = KENV_SIZE * (KENV_MNAMELEN +
+ KENV_MVALLEN + 2);
if (uap->len > 0 && uap->value != NULL)
- buffer = malloc(uap->len, M_TEMP, M_WAITOK|M_ZERO);
+ buffer = malloc(buflen, M_TEMP, M_WAITOK|M_ZERO);
mtx_lock(&kenv_lock);
for (i = 0; kenvp[i] != NULL; i++) {
len = strlen(kenvp[i]) + 1;
needed += len;
- len = min(len, uap->len - done);
+ len = min(len, buflen - done);
/*
* If called with a NULL or insufficiently large
* buffer, just keep computing the required size.
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index af6c9e4..f36f803 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -379,6 +379,8 @@ do_execve(td, args, mac_p)
imgp->ps_strings = 0;
imgp->auxarg_size = 0;
imgp->args = args;
+ imgp->execpath = imgp->freepath = NULL;
+ imgp->execpathp = 0;
#ifdef MAC
error = mac_execve_enter(imgp, mac_p);
@@ -519,6 +521,15 @@ interpret:
* of the sv_copyout_strings/sv_fixup operations require the vnode.
*/
VOP_UNLOCK(imgp->vp, 0);
+
+ /*
+ * Do the best to calculate the full path to the image file.
+ */
+ if (imgp->auxargs != NULL &&
+ ((args->fname != NULL && args->fname[0] == '/') ||
+ vn_fullpath(td, imgp->vp, &imgp->execpath, &imgp->freepath) != 0))
+ imgp->execpath = args->fname;
+
/*
* Copy out strings (args and env) and initialize stack base
*/
@@ -859,6 +870,8 @@ exec_fail_dealloc:
if (imgp->object != NULL)
vm_object_deallocate(imgp->object);
+ free(imgp->freepath, M_TEMP);
+
if (error == 0) {
/*
* Stop the process here if its stop event mask has
@@ -1164,18 +1177,24 @@ exec_copyout_strings(imgp)
register_t *stack_base;
struct ps_strings *arginfo;
struct proc *p;
+ size_t execpath_len;
int szsigcode;
/*
* Calculate string base and vector table pointers.
* Also deal with signal trampoline code for this exec type.
*/
+ if (imgp->execpath != NULL && imgp->auxargs != NULL)
+ execpath_len = strlen(imgp->execpath) + 1;
+ else
+ execpath_len = 0;
p = imgp->proc;
szsigcode = 0;
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
if (p->p_sysent->sv_szsigcode != NULL)
szsigcode = *(p->p_sysent->sv_szsigcode);
destp = (caddr_t)arginfo - szsigcode - SPARE_USRSPACE -
+ roundup(execpath_len, sizeof(char *)) -
roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
/*
@@ -1186,6 +1205,15 @@ exec_copyout_strings(imgp)
szsigcode), szsigcode);
/*
+ * Copy the image path for the rtld.
+ */
+ if (execpath_len != 0) {
+ imgp->execpathp = (uintptr_t)arginfo - szsigcode - execpath_len;
+ copyout(imgp->execpath, (void *)imgp->execpathp,
+ execpath_len);
+ }
+
+ /*
* If we have a valid auxargs ptr, prepare some room
* on the stack.
*/
@@ -1202,9 +1230,8 @@ exec_copyout_strings(imgp)
* for argument of Runtime loader.
*/
vectp = (char **)(destp - (imgp->args->argc +
- imgp->args->envc + 2 + imgp->auxarg_size) *
+ imgp->args->envc + 2 + imgp->auxarg_size + execpath_len) *
sizeof(char *));
-
} else {
/*
* The '+ 2' is for the null pointers at the end of each of
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index e802780..00be7aa 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -2,7 +2,7 @@
* Copyright (c) 1999 Poul-Henning Kamp.
* Copyright (c) 2008 Bjoern A. Zeeb.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -119,14 +119,14 @@ struct sx allprison_lock;
int lastprid = 0;
int prisoncount = 0;
-static void init_prison(void *);
-static void prison_complete(void *context, int pending);
-static int sysctl_jail_list(SYSCTL_HANDLER_ARGS);
+static void init_prison(void *);
+static void prison_complete(void *context, int pending);
+static int sysctl_jail_list(SYSCTL_HANDLER_ARGS);
#ifdef INET
-static int _prison_check_ip4(struct prison *, struct in_addr *);
+static int _prison_check_ip4(struct prison *pr, struct in_addr *ia);
#endif
#ifdef INET6
-static int _prison_check_ip6(struct prison *, struct in6_addr *);
+static int _prison_check_ip6(struct prison *pr, struct in6_addr *ia6);
#endif
static void
@@ -177,7 +177,7 @@ qcmp_v6(const void *ip1, const void *ip2)
ia6b = (const struct in6_addr *)ip2;
rc = 0;
- for (i=0; rc == 0 && i < sizeof(struct in6_addr); i++) {
+ for (i = 0; rc == 0 && i < sizeof(struct in6_addr); i++) {
if (ia6a->s6_addr[i] > ia6b->s6_addr[i])
rc = 1;
else if (ia6a->s6_addr[i] < ia6b->s6_addr[i])
@@ -240,7 +240,7 @@ static int
jail_copyin_ips(struct jail *j)
{
#ifdef INET
- struct in_addr *ip4;
+ struct in_addr *ip4;
#endif
#ifdef INET6
struct in6_addr *ip6;
@@ -348,7 +348,7 @@ jail_handle_ips(struct jail *j)
* Finish conversion for older versions, copyin and setup IPs.
*/
switch (j->version) {
- case 0:
+ case 0:
{
#ifdef INET
/* FreeBSD single IPv4 jails. */
@@ -594,6 +594,7 @@ e_killmtx:
return (error);
}
+
/*
* struct jail_attach_args {
* int jid;
@@ -807,7 +808,7 @@ prison_proc_free(struct prison *pr)
* Pass back primary IPv4 address of this jail.
*
* If not jailed return success but do not alter the address. Caller has to
- * make sure to intialize it correctly (e.g. INADDR_ANY).
+ * make sure to initialize it correctly (e.g. INADDR_ANY).
*
* Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv4.
* Address returned in NBO.
@@ -822,7 +823,6 @@ prison_get_ip4(struct ucred *cred, struct in_addr *ia)
if (!jailed(cred))
/* Do not change address passed in. */
return (0);
-
if (cred->cr_prison->pr_ip4 == NULL)
return (EAFNOSUPPORT);
@@ -956,7 +956,7 @@ prison_check_ip4(struct ucred *cred, struct in_addr *ia)
* Pass back primary IPv6 address for this jail.
*
* If not jailed return success but do not alter the address. Caller has to
- * make sure to intialize it correctly (e.g. IN6ADDR_ANY_INIT).
+ * make sure to initialize it correctly (e.g. IN6ADDR_ANY_INIT).
*
* Returns 0 on success, EAFNOSUPPORT if the jail doesn't allow IPv6.
*/
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index 6ccf2c0..6e680fb 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -992,7 +992,6 @@ ktr_writerequest(struct thread *td, struct ktr_request *req)
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
vn_start_write(vp, &mp, V_WAIT);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- (void)VOP_LEASE(vp, td, cred, LEASE_WRITE);
#ifdef MAC
error = mac_vnode_check_write(cred, NOCRED, vp);
if (error == 0)
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
index b2294f8..f19e249 100644
--- a/sys/kern/kern_lock.c
+++ b/sys/kern/kern_lock.c
@@ -333,16 +333,17 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
const char *wmesg, int pri, int timo, const char *file, int line)
{
GIANT_DECLARE;
- uint64_t waittime;
struct lock_class *class;
const char *iwmesg;
uintptr_t tid, v, x;
u_int op;
- int contested, error, ipri, itimo, queue, wakeup_swapper;
+ int error, ipri, itimo, queue, wakeup_swapper;
+#ifdef LOCK_PROFILING
+ uint64_t waittime = 0;
+ int contested = 0;
+#endif
- contested = 0;
error = 0;
- waittime = 0;
tid = (uintptr_t)curthread;
op = (flags & LK_TYPE_MASK);
iwmesg = (wmesg == LK_WMESG_DEFAULT) ? lk->lock_object.lo_name : wmesg;
@@ -686,7 +687,8 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
lk->lk_recurse--;
break;
}
- lock_profile_release_lock(&lk->lock_object);
+ if (tid != LK_KERNPROC)
+ lock_profile_release_lock(&lk->lock_object);
if (atomic_cmpset_rel_ptr(&lk->lk_lock, tid,
LK_UNLOCKED))
@@ -874,6 +876,7 @@ _lockmgr_disown(struct lock *lk, const char *file, int line)
*/
if (LK_HOLDER(lk->lk_lock) != tid)
return;
+ lock_profile_release_lock(&lk->lock_object);
LOCK_LOG_LOCK("XDISOWN", &lk->lock_object, 0, 0, file, line);
WITNESS_UNLOCK(&lk->lock_object, LOP_EXCLUSIVE, file, line);
TD_LOCKS_DEC(curthread);
diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c
index 523d911..c56e124 100644
--- a/sys/kern/kern_mutex.c
+++ b/sys/kern/kern_mutex.c
@@ -254,8 +254,11 @@ _mtx_unlock_spin_flags(struct mtx *m, int opts, const char *file, int line)
int
_mtx_trylock(struct mtx *m, int opts, const char *file, int line)
{
- int rval, contested = 0;
+#ifdef LOCK_PROFILING
uint64_t waittime = 0;
+ int contested = 0;
+#endif
+ int rval;
MPASS(curthread != NULL);
KASSERT(m->mtx_lock != MTX_DESTROYED,
@@ -296,15 +299,17 @@ _mtx_lock_sleep(struct mtx *m, uintptr_t tid, int opts, const char *file,
int line)
{
struct turnstile *ts;
+ uintptr_t v;
#ifdef ADAPTIVE_MUTEXES
volatile struct thread *owner;
#endif
#ifdef KTR
int cont_logged = 0;
#endif
+#ifdef LOCK_PROFILING
int contested = 0;
uint64_t waittime = 0;
- uintptr_t v;
+#endif
if (mtx_owned(m)) {
KASSERT((m->lock_object.lo_flags & LO_RECURSABLE) != 0,
@@ -448,8 +453,11 @@ void
_mtx_lock_spin(struct mtx *m, uintptr_t tid, int opts, const char *file,
int line)
{
- int i = 0, contested = 0;
+ int i = 0;
+#ifdef LOCK_PROFILING
+ int contested = 0;
uint64_t waittime = 0;
+#endif
if (LOCK_LOG_TEST(&m->lock_object, opts))
CTR1(KTR_LOCK, "_mtx_lock_spin: %p spinning", m);
@@ -486,11 +494,13 @@ _thread_lock_flags(struct thread *td, int opts, const char *file, int line)
{
struct mtx *m;
uintptr_t tid;
- int i, contested;
- uint64_t waittime;
+ int i;
+#ifdef LOCK_PROFILING
+ int contested = 0;
+ uint64_t waittime = 0;
+#endif
- contested = i = 0;
- waittime = 0;
+ i = 0;
tid = (uintptr_t)curthread;
for (;;) {
retry:
@@ -765,6 +775,7 @@ mtx_destroy(struct mtx *m)
else
curthread->td_locks--;
+ lock_profile_release_lock(&m->lock_object);
/* Tell witness this isn't locked to make it happy. */
WITNESS_UNLOCK(&m->lock_object, LOP_EXCLUSIVE, __FILE__,
__LINE__);
diff --git a/sys/kern/kern_poll.c b/sys/kern/kern_poll.c
index ca11177..8ca6b93 100644
--- a/sys/kern/kern_poll.c
+++ b/sys/kern/kern_poll.c
@@ -551,9 +551,7 @@ poll_switch(SYSCTL_HANDLER_ARGS)
else
ifr.ifr_reqcap =
ifp->if_capenable & ~IFCAP_POLLING;
- IFF_LOCKGIANT(ifp); /* LOR here */
(void) (*ifp->if_ioctl)(ifp, SIOCSIFCAP, (caddr_t)&ifr);
- IFF_UNLOCKGIANT(ifp);
}
}
IFNET_RUNLOCK();
diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c
index 531e145..ccaa690 100644
--- a/sys/kern/kern_rwlock.c
+++ b/sys/kern/kern_rwlock.c
@@ -282,8 +282,10 @@ _rw_rlock(struct rwlock *rw, const char *file, int line)
int spintries = 0;
int i;
#endif
+#ifdef LOCK_PROFILING
uint64_t waittime = 0;
int contested = 0;
+#endif
uintptr_t v;
KASSERT(rw->rw_lock != RW_DESTROYED,
@@ -584,9 +586,11 @@ _rw_wlock_hard(struct rwlock *rw, uintptr_t tid, const char *file, int line)
int spintries = 0;
int i;
#endif
- uint64_t waittime = 0;
uintptr_t v, x;
+#ifdef LOCK_PROFILING
+ uint64_t waittime = 0;
int contested = 0;
+#endif
if (rw_wlocked(rw)) {
KASSERT(rw->lock_object.lo_flags & RW_RECURSE,
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index 157da53..7702ad8 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -680,15 +680,6 @@ dump_write(struct dumperinfo *di, void *virtual, vm_offset_t physical,
return (di->dumper(di->priv, virtual, physical, offset, length));
}
-#if defined(__powerpc__)
-void
-dumpsys(struct dumperinfo *di __unused)
-{
-
- printf("Kernel dumps not implemented on this architecture\n");
-}
-#endif
-
void
mkdumpheader(struct kerneldumpheader *kdh, char *magic, uint32_t archver,
uint64_t dumplen, uint32_t blksz)
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 7460c13..5c1d553 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -2984,7 +2984,6 @@ restart:
if (set_core_nodump_flag)
vattr.va_flags = UF_NODUMP;
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- VOP_LEASE(vp, td, cred, LEASE_WRITE);
VOP_SETATTR(vp, &vattr, cred);
VOP_UNLOCK(vp, 0);
vn_finished_write(mp);
diff --git a/sys/kern/kern_sx.c b/sys/kern/kern_sx.c
index e1e34ec..9a2c9a2 100644
--- a/sys/kern/kern_sx.c
+++ b/sys/kern/kern_sx.c
@@ -431,9 +431,12 @@ _sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file,
#ifdef ADAPTIVE_SX
volatile struct thread *owner;
#endif
- uint64_t waittime = 0;
uintptr_t x;
- int contested = 0, error = 0;
+#ifdef LOCK_PROFILING
+ uint64_t waittime = 0;
+ int contested = 0;
+#endif
+ int error = 0;
/* If we already hold an exclusive lock, then recurse. */
if (sx_xlocked(sx)) {
@@ -652,8 +655,10 @@ _sx_slock_hard(struct sx *sx, int opts, const char *file, int line)
#ifdef ADAPTIVE_SX
volatile struct thread *owner;
#endif
+#ifdef LOCK_PROFILING
uint64_t waittime = 0;
int contested = 0;
+#endif
uintptr_t x;
int error = 0;
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 6409842..48dc4f8 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -103,24 +103,6 @@ static int timestepwarnings;
SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW,
&timestepwarnings, 0, "");
-#ifdef TC_COUNTERS
-#define TC_STATS(foo) \
- static u_int foo; \
- SYSCTL_UINT(_kern_timecounter, OID_AUTO, foo, CTLFLAG_RD, &foo, 0, "");\
- struct __hack
-
-TC_STATS(nbinuptime); TC_STATS(nnanouptime); TC_STATS(nmicrouptime);
-TC_STATS(nbintime); TC_STATS(nnanotime); TC_STATS(nmicrotime);
-TC_STATS(ngetbinuptime); TC_STATS(ngetnanouptime); TC_STATS(ngetmicrouptime);
-TC_STATS(ngetbintime); TC_STATS(ngetnanotime); TC_STATS(ngetmicrotime);
-TC_STATS(nsetclock);
-
-#define TC_COUNT(var) var++
-#undef TC_STATS
-#else
-#define TC_COUNT(var) /* nothing */
-#endif /* TC_COUNTERS */
-
static void tc_windup(void);
static void cpu_tick_calibrate(int);
@@ -185,7 +167,6 @@ binuptime(struct bintime *bt)
struct timehands *th;
u_int gen;
- TC_COUNT(nbinuptime);
do {
th = timehands;
gen = th->th_generation;
@@ -199,7 +180,6 @@ nanouptime(struct timespec *tsp)
{
struct bintime bt;
- TC_COUNT(nnanouptime);
binuptime(&bt);
bintime2timespec(&bt, tsp);
}
@@ -209,7 +189,6 @@ microuptime(struct timeval *tvp)
{
struct bintime bt;
- TC_COUNT(nmicrouptime);
binuptime(&bt);
bintime2timeval(&bt, tvp);
}
@@ -218,7 +197,6 @@ void
bintime(struct bintime *bt)
{
- TC_COUNT(nbintime);
binuptime(bt);
bintime_add(bt, &boottimebin);
}
@@ -228,7 +206,6 @@ nanotime(struct timespec *tsp)
{
struct bintime bt;
- TC_COUNT(nnanotime);
bintime(&bt);
bintime2timespec(&bt, tsp);
}
@@ -238,7 +215,6 @@ microtime(struct timeval *tvp)
{
struct bintime bt;
- TC_COUNT(nmicrotime);
bintime(&bt);
bintime2timeval(&bt, tvp);
}
@@ -249,7 +225,6 @@ getbinuptime(struct bintime *bt)
struct timehands *th;
u_int gen;
- TC_COUNT(ngetbinuptime);
do {
th = timehands;
gen = th->th_generation;
@@ -263,7 +238,6 @@ getnanouptime(struct timespec *tsp)
struct timehands *th;
u_int gen;
- TC_COUNT(ngetnanouptime);
do {
th = timehands;
gen = th->th_generation;
@@ -277,7 +251,6 @@ getmicrouptime(struct timeval *tvp)
struct timehands *th;
u_int gen;
- TC_COUNT(ngetmicrouptime);
do {
th = timehands;
gen = th->th_generation;
@@ -291,7 +264,6 @@ getbintime(struct bintime *bt)
struct timehands *th;
u_int gen;
- TC_COUNT(ngetbintime);
do {
th = timehands;
gen = th->th_generation;
@@ -306,7 +278,6 @@ getnanotime(struct timespec *tsp)
struct timehands *th;
u_int gen;
- TC_COUNT(ngetnanotime);
do {
th = timehands;
gen = th->th_generation;
@@ -320,7 +291,6 @@ getmicrotime(struct timeval *tvp)
struct timehands *th;
u_int gen;
- TC_COUNT(ngetmicrotime);
do {
th = timehands;
gen = th->th_generation;
@@ -411,7 +381,6 @@ tc_setclock(struct timespec *ts)
struct bintime bt, bt2;
cpu_tick_calibrate(1);
- TC_COUNT(nsetclock);
nanotime(&tbef);
timespec2bintime(ts, &bt);
binuptime(&bt2);
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
index 4606005..bb8779b 100644
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -306,6 +306,8 @@ thread_alloc(void)
void
thread_free(struct thread *td)
{
+
+ lock_profile_thread_exit(td);
if (td->td_cpuset)
cpuset_rel(td->td_cpuset);
td->td_cpuset = NULL;
@@ -439,6 +441,7 @@ thread_wait(struct proc *p)
/* Wait for any remaining threads to exit cpu_throw(). */
while (p->p_exitthreads)
sched_relinquish(curthread);
+ lock_profile_thread_exit(td);
cpuset_rel(td->td_cpuset);
td->td_cpuset = NULL;
cpu_thread_clean(td);
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index a8ecace..3aea2bd 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -74,7 +74,6 @@ static uma_zone_t itimer_zone = NULL;
static int settime(struct thread *, struct timeval *);
static void timevalfix(struct timeval *);
-static void no_lease_updatetime(int);
static void itimer_start(void);
static int itimer_init(void *, int, int);
@@ -106,14 +105,6 @@ int itimespecfix(struct timespec *ts);
SYSINIT(posix_timer, SI_SUB_P1003_1B, SI_ORDER_FIRST+4, itimer_start, NULL);
-static void
-no_lease_updatetime(deltat)
- int deltat;
-{
-}
-
-void (*lease_updatetime)(int) = no_lease_updatetime;
-
static int
settime(struct thread *td, struct timeval *tv)
{
@@ -168,9 +159,6 @@ settime(struct thread *td, struct timeval *tv)
ts.tv_nsec = tv->tv_usec * 1000;
mtx_lock(&Giant);
tc_setclock(&ts);
- (void) splsoftclock();
- lease_updatetime(delta.tv_sec);
- splx(s);
resettodr();
mtx_unlock(&Giant);
return (0);
@@ -1085,7 +1073,8 @@ itimer_find(struct proc *p, int timerid)
struct itimer *it;
PROC_LOCK_ASSERT(p, MA_OWNED);
- if ((p->p_itimers == NULL) || (timerid >= TIMER_MAX) ||
+ if ((p->p_itimers == NULL) ||
+ (timerid < 0) || (timerid >= TIMER_MAX) ||
(it = p->p_itimers->its_timers[timerid]) == NULL) {
return (NULL);
}
diff --git a/sys/kern/kern_umtx.c b/sys/kern/kern_umtx.c
index 09573ab..46e06c0 100644
--- a/sys/kern/kern_umtx.c
+++ b/sys/kern/kern_umtx.c
@@ -166,6 +166,7 @@ struct umtxq_chain {
};
#define UMTXQ_LOCKED_ASSERT(uc) mtx_assert(&(uc)->uc_lock, MA_OWNED)
+#define UMTXQ_BUSY_ASSERT(uc) KASSERT(&(uc)->uc_busy, ("umtx chain is not busy"))
/*
* Don't propagate time-sharing priority, there is a security reason,
@@ -1392,7 +1393,8 @@ umtx_unpropagate_priority(struct umtx_pi *pi)
oldpri = pi->pi_owner->td_user_pri;
sched_unlend_user_prio(pi->pi_owner, pri);
thread_unlock(pi->pi_owner);
- umtx_pi_adjust_locked(pi->pi_owner, oldpri);
+ if (uq_owner->uq_pi_blocked != NULL)
+ umtx_pi_adjust_locked(pi->pi_owner, oldpri);
pi = uq_owner->uq_pi_blocked;
}
}
@@ -1513,7 +1515,9 @@ umtxq_sleep_pi(struct umtx_q *uq, struct umtx_pi *pi,
KASSERT(td == curthread, ("inconsistent uq_thread"));
uc = umtxq_getchain(&uq->uq_key);
UMTXQ_LOCKED_ASSERT(uc);
+ UMTXQ_BUSY_ASSERT(uc);
umtxq_insert(uq);
+ mtx_lock_spin(&umtx_lock);
if (pi->pi_owner == NULL) {
/* XXX
* Current, We only support process private PI-mutex,
@@ -1524,6 +1528,7 @@ umtxq_sleep_pi(struct umtx_q *uq, struct umtx_pi *pi,
* For process private PI-mutex, we can find owner
* thread and boost its priority safely.
*/
+ mtx_unlock_spin(&umtx_lock);
PROC_LOCK(curproc);
td1 = thread_find(curproc, owner);
mtx_lock_spin(&umtx_lock);
@@ -1532,8 +1537,6 @@ umtxq_sleep_pi(struct umtx_q *uq, struct umtx_pi *pi,
umtx_pi_setowner(pi, td1);
}
PROC_UNLOCK(curproc);
- } else {
- mtx_lock_spin(&umtx_lock);
}
TAILQ_FOREACH(uq1, &pi->pi_blocked, uq_lockq) {
@@ -1551,26 +1554,18 @@ umtxq_sleep_pi(struct umtx_q *uq, struct umtx_pi *pi,
thread_lock(td);
td->td_flags |= TDF_UPIBLOCKED;
thread_unlock(td);
- mtx_unlock_spin(&umtx_lock);
- umtxq_unlock(&uq->uq_key);
-
- mtx_lock_spin(&umtx_lock);
umtx_propagate_priority(td);
mtx_unlock_spin(&umtx_lock);
+ umtxq_unbusy(&uq->uq_key);
- umtxq_lock(&uq->uq_key);
if (uq->uq_flags & UQF_UMTXQ) {
error = msleep(uq, &uc->uc_lock, PCATCH, wmesg, timo);
if (error == EWOULDBLOCK)
error = ETIMEDOUT;
if (uq->uq_flags & UQF_UMTXQ) {
- umtxq_busy(&uq->uq_key);
umtxq_remove(uq);
- umtxq_unbusy(&uq->uq_key);
}
}
- umtxq_unlock(&uq->uq_key);
-
mtx_lock_spin(&umtx_lock);
uq->uq_pi_blocked = NULL;
thread_lock(td);
@@ -1579,8 +1574,7 @@ umtxq_sleep_pi(struct umtx_q *uq, struct umtx_pi *pi,
TAILQ_REMOVE(&pi->pi_blocked, uq, uq_lockq);
umtx_unpropagate_priority(pi);
mtx_unlock_spin(&umtx_lock);
-
- umtxq_lock(&uq->uq_key);
+ umtxq_unlock(&uq->uq_key);
return (error);
}
@@ -1606,7 +1600,6 @@ static void
umtx_pi_unref(struct umtx_pi *pi)
{
struct umtxq_chain *uc;
- int free = 0;
uc = umtxq_getchain(&pi->pi_key);
UMTXQ_LOCKED_ASSERT(uc);
@@ -1622,10 +1615,8 @@ umtx_pi_unref(struct umtx_pi *pi)
("blocked queue not empty"));
mtx_unlock_spin(&umtx_lock);
TAILQ_REMOVE(&uc->uc_pi_list, pi, pi_hashlink);
- free = 1;
- }
- if (free)
umtx_pi_free(pi);
+ }
}
/*
@@ -1686,7 +1677,6 @@ _do_lock_pi(struct thread *td, struct umutex *m, uint32_t flags, int timo,
if (new_pi == NULL) {
umtxq_unlock(&uq->uq_key);
new_pi = umtx_pi_alloc(M_WAITOK);
- new_pi->pi_key = uq->uq_key;
umtxq_lock(&uq->uq_key);
pi = umtx_pi_lookup(&uq->uq_key);
if (pi != NULL) {
@@ -1732,7 +1722,9 @@ _do_lock_pi(struct thread *td, struct umutex *m, uint32_t flags, int timo,
if (owner == UMUTEX_CONTESTED) {
umtxq_lock(&uq->uq_key);
+ umtxq_busy(&uq->uq_key);
error = umtx_pi_claim(pi, td);
+ umtxq_unbusy(&uq->uq_key);
umtxq_unlock(&uq->uq_key);
break;
}
@@ -1787,7 +1779,6 @@ _do_lock_pi(struct thread *td, struct umutex *m, uint32_t flags, int timo,
}
umtxq_lock(&uq->uq_key);
- umtxq_unbusy(&uq->uq_key);
/*
* We set the contested bit, sleep. Otherwise the lock changed
* and we need to retry or we lost a race to the thread
@@ -1796,7 +1787,10 @@ _do_lock_pi(struct thread *td, struct umutex *m, uint32_t flags, int timo,
if (old == owner)
error = umtxq_sleep_pi(uq, pi, owner & ~UMUTEX_CONTESTED,
"umtxpi", timo);
- umtxq_unlock(&uq->uq_key);
+ else {
+ umtxq_unbusy(&uq->uq_key);
+ umtxq_unlock(&uq->uq_key);
+ }
}
umtxq_lock(&uq->uq_key);
@@ -1851,18 +1845,26 @@ do_unlock_pi(struct thread *td, struct umutex *m, uint32_t flags)
umtxq_busy(&key);
count = umtxq_count_pi(&key, &uq_first);
if (uq_first != NULL) {
+ mtx_lock_spin(&umtx_lock);
pi = uq_first->uq_pi_blocked;
+ KASSERT(pi != NULL, ("pi == NULL?"));
if (pi->pi_owner != curthread) {
+ mtx_unlock_spin(&umtx_lock);
umtxq_unbusy(&key);
umtxq_unlock(&key);
+ umtx_key_release(&key);
/* userland messed the mutex */
return (EPERM);
}
uq_me = curthread->td_umtxq;
- mtx_lock_spin(&umtx_lock);
pi->pi_owner = NULL;
TAILQ_REMOVE(&uq_me->uq_pi_contested, pi, pi_link);
+ /* get highest priority thread which is still sleeping. */
uq_first = TAILQ_FIRST(&pi->pi_blocked);
+ while (uq_first != NULL &&
+ (uq_first->uq_flags & UQF_UMTXQ) == 0) {
+ uq_first = TAILQ_NEXT(uq_first, uq_lockq);
+ }
pri = PRI_MAX;
TAILQ_FOREACH(pi2, &uq_me->uq_pi_contested, pi_link) {
uq_first2 = TAILQ_FIRST(&pi2->pi_blocked);
@@ -1875,6 +1877,8 @@ do_unlock_pi(struct thread *td, struct umutex *m, uint32_t flags)
sched_unlend_user_prio(curthread, pri);
thread_unlock(curthread);
mtx_unlock_spin(&umtx_lock);
+ if (uq_first)
+ umtxq_signal_thread(uq_first);
}
umtxq_unlock(&key);
@@ -1887,8 +1891,6 @@ do_unlock_pi(struct thread *td, struct umutex *m, uint32_t flags)
count <= 1 ? UMUTEX_UNOWNED : UMUTEX_CONTESTED);
umtxq_lock(&key);
- if (uq_first != NULL)
- umtxq_signal_thread(uq_first);
umtxq_unbusy(&key);
umtxq_unlock(&key);
umtx_key_release(&key);
diff --git a/sys/kern/kern_vimage.c b/sys/kern/kern_vimage.c
index 0cba35a..c426ee6 100644
--- a/sys/kern/kern_vimage.c
+++ b/sys/kern/kern_vimage.c
@@ -44,19 +44,136 @@ __FBSDID("$FreeBSD$");
MALLOC_DEFINE(M_VIMAGE, "vimage", "vimage resource container");
static TAILQ_HEAD(vnet_modlink_head, vnet_modlink) vnet_modlink_head;
+static TAILQ_HEAD(vnet_modpending_head, vnet_modlink) vnet_modpending_head;
+static void vnet_mod_complete_registration(struct vnet_modlink *);
+static int vnet_mod_constructor(struct vnet_modlink *);
void
vnet_mod_register(const struct vnet_modinfo *vmi)
{
+
+ vnet_mod_register_multi(vmi, NULL, NULL);
+}
+
+void
+vnet_mod_register_multi(const struct vnet_modinfo *vmi, void *iarg,
+ char *iname)
+{
struct vnet_modlink *vml, *vml_iter;
- /* Do not register the same module instance more than once. */
+ /* Do not register the same {module, iarg} pair more than once. */
TAILQ_FOREACH(vml_iter, &vnet_modlink_head, vml_mod_le)
- if (vml_iter->vml_modinfo == vmi)
- panic("%s: %s", __func__, vmi->vmi_name);
+ if (vml_iter->vml_modinfo == vmi && vml_iter->vml_iarg == iarg)
+ break;
+ if (vml_iter != NULL)
+ panic("registering an already registered vnet module: %s",
+ vml_iter->vml_modinfo->vmi_name);
vml = malloc(sizeof(struct vnet_modlink), M_VIMAGE, M_NOWAIT);
+
+ /*
+ * XXX we support only statically assigned module IDs at the time.
+ * In principle modules should be able to get a dynamically
+ * assigned ID at registration time.
+ *
+ * If a module is registered in multiple instances, then each
+ * instance must have both iarg and iname set.
+ */
+ if (vmi->vmi_id >= VNET_MOD_MAX)
+ panic("invalid vnet module ID: %d", vmi->vmi_id);
+ if (vmi->vmi_name == NULL)
+ panic("vnet module with no name: %d", vmi->vmi_id);
+ if ((iarg == NULL) ^ (iname == NULL))
+ panic("invalid vnet module instance: %s", vmi->vmi_name);
+
vml->vml_modinfo = vmi;
+ vml->vml_iarg = iarg;
+ vml->vml_iname = iname;
+
+ /* Check whether the module we depend on is already registered. */
+ if (vmi->vmi_dependson != vmi->vmi_id) {
+ TAILQ_FOREACH(vml_iter, &vnet_modlink_head, vml_mod_le)
+ if (vml_iter->vml_modinfo->vmi_id ==
+ vmi->vmi_dependson)
+ break; /* Depencency found, we are done. */
+ if (vml_iter == NULL) {
+#ifdef DEBUG_ORDERING
+ printf("dependency %d missing for vnet mod %s,"
+ "postponing registration\n",
+ vmi->vmi_dependson, vmi->vmi_name);
+#endif /* DEBUG_ORDERING */
+ TAILQ_INSERT_TAIL(&vnet_modpending_head, vml,
+ vml_mod_le);
+ return;
+ }
+ }
+
+ vnet_mod_complete_registration(vml);
+}
+
+void
+vnet_mod_complete_registration(struct vnet_modlink *vml)
+{
+ VNET_ITERATOR_DECL(vnet_iter);
+ struct vnet_modlink *vml_iter;
+
TAILQ_INSERT_TAIL(&vnet_modlink_head, vml, vml_mod_le);
+
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET_QUIET(vnet_iter);
+ vnet_mod_constructor(vml);
+ CURVNET_RESTORE();
+ }
+
+ /* Check for pending modules depending on us. */
+ do {
+ TAILQ_FOREACH(vml_iter, &vnet_modpending_head, vml_mod_le)
+ if (vml_iter->vml_modinfo->vmi_dependson ==
+ vml->vml_modinfo->vmi_id)
+ break;
+ if (vml_iter != NULL) {
+#ifdef DEBUG_ORDERING
+ printf("vnet mod %s now registering,"
+ "dependency %d loaded\n",
+ vml_iter->vml_modinfo->vmi_name,
+ vml->vml_modinfo->vmi_id);
+#endif /* DEBUG_ORDERING */
+ TAILQ_REMOVE(&vnet_modpending_head, vml_iter,
+ vml_mod_le);
+ vnet_mod_complete_registration(vml_iter);
+ }
+ } while (vml_iter != NULL);
+}
+
+static int vnet_mod_constructor(struct vnet_modlink *vml)
+{
+ const struct vnet_modinfo *vmi = vml->vml_modinfo;
+
+#ifdef DEBUG_ORDERING
+ printf("instantiating vnet_%s", vmi->vmi_name);
+ if (vml->vml_iarg)
+ printf("/%s", vml->vml_iname);
+ printf(": ");
+ if (vmi->vmi_struct_size)
+ printf("malloc(%zu); ", vmi->vmi_struct_size);
+ if (vmi->vmi_iattach != NULL)
+ printf("iattach()");
+ printf("\n");
+#endif
+
+#ifdef VIMAGE
+ if (vmi->vmi_struct_size) {
+ void *mem = malloc(vmi->vmi_struct_size, M_VNET,
+ M_NOWAIT | M_ZERO);
+ if (mem == NULL) /* XXX should return error, not panic. */
+ panic("vi_alloc: malloc for %s\n", vmi->vmi_name);
+ curvnet->mod_data[vmi->vmi_id] = mem;
+ }
+#endif
+
+ if (vmi->vmi_iattach != NULL)
+ vmi->vmi_iattach(vml->vml_iarg);
+
+ return (0);
}
/*
@@ -75,7 +192,7 @@ vi_symlookup(struct kld_sym_lookup *lookup, char *symstr)
if (vml->vml_modinfo->vmi_symmap == NULL)
continue;
for (mapentry = vml->vml_modinfo->vmi_symmap;
- mapentry->name != NULL; mapentry++) {
+ mapentry->name != NULL; mapentry++) {
if (strcmp(symstr, mapentry->name) == 0) {
lookup->symvalue = (u_long) mapentry->base;
lookup->symsize = mapentry->size;
@@ -91,8 +208,27 @@ vi_init(void *unused)
{
TAILQ_INIT(&vnet_modlink_head);
+ TAILQ_INIT(&vnet_modpending_head);
+}
+
+static void
+vi_init_done(void *unused)
+{
+ struct vnet_modlink *vml_iter;
+
+ if (TAILQ_EMPTY(&vnet_modpending_head))
+ return;
+
+ printf("vnet modules with unresolved dependencies:\n");
+ TAILQ_FOREACH(vml_iter, &vnet_modpending_head, vml_mod_le)
+ printf(" %d:%s depending on %d\n",
+ vml_iter->vml_modinfo->vmi_id,
+ vml_iter->vml_modinfo->vmi_name,
+ vml_iter->vml_modinfo->vmi_dependson);
+ panic("going nowhere without my vnet modules!");
}
SYSINIT(vimage, SI_SUB_VIMAGE, SI_ORDER_FIRST, vi_init, NULL);
+SYSINIT(vimage_done, SI_SUB_VIMAGE_DONE, SI_ORDER_FIRST, vi_init_done, NULL);
#endif /* !VIMAGE_GLOBALS */
diff --git a/sys/kern/sched_ule.c b/sys/kern/sched_ule.c
index 96f7280..a748b70 100644
--- a/sys/kern/sched_ule.c
+++ b/sys/kern/sched_ule.c
@@ -1337,11 +1337,11 @@ sched_initticks(void *dummy)
*/
balance_interval = realstathz;
/*
- * Set steal thresh to log2(mp_ncpu) but no greater than 4. This
- * prevents excess thrashing on large machines and excess idle on
- * smaller machines.
+ * Set steal thresh to roughly log2(mp_ncpu) but no greater than 4.
+ * This prevents excess thrashing on large machines and excess idle
+ * on smaller machines.
*/
- steal_thresh = min(ffs(mp_ncpus) - 1, 3);
+ steal_thresh = min(fls(mp_ncpus) - 1, 3);
affinity = SCHED_AFFINITY_DEFAULT;
#endif
}
@@ -2417,6 +2417,11 @@ sched_affinity(struct thread *td)
ts = td->td_sched;
if (THREAD_CAN_SCHED(td, ts->ts_cpu))
return;
+ if (TD_ON_RUNQ(td)) {
+ sched_rem(td);
+ sched_add(td, SRQ_BORING);
+ return;
+ }
if (!TD_IS_RUNNING(td))
return;
td->td_flags |= TDF_NEEDRESCHED;
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index 3c526a6..92a4038 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -532,6 +532,12 @@ devctl_queue_data(char *data)
struct dev_event_info *n1 = NULL;
struct proc *p;
+ /*
+ * Do not allow empty strings to be queued, as they
+ * cause devd to exit prematurely.
+ */
+ if (strlen(data) == 0)
+ return;
n1 = malloc(sizeof(*n1), M_BUS, M_NOWAIT);
if (n1 == NULL)
return;
@@ -814,7 +820,7 @@ devclass_find_internal(const char *classname, const char *parentname,
*/
if (parentname && dc && !dc->parent &&
strcmp(classname, parentname) != 0) {
- dc->parent = devclass_find_internal(parentname, NULL, FALSE);
+ dc->parent = devclass_find_internal(parentname, NULL, TRUE);
dc->parent->flags |= DC_HAS_CHILDREN;
}
diff --git a/sys/kern/subr_lock.c b/sys/kern/subr_lock.c
index 3e7c85d..977f9e5 100644
--- a/sys/kern/subr_lock.c
+++ b/sys/kern/subr_lock.c
@@ -46,9 +46,11 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/lock_profile.h>
#include <sys/malloc.h>
+#include <sys/mutex.h>
#include <sys/pcpu.h>
#include <sys/proc.h>
#include <sys/sbuf.h>
+#include <sys/sched.h>
#include <sys/smp.h>
#include <sys/sysctl.h>
@@ -186,7 +188,8 @@ struct lock_prof_cpu {
struct lock_prof_cpu *lp_cpu[MAXCPU];
-int lock_prof_enable = 0;
+volatile int lock_prof_enable = 0;
+static volatile int lock_prof_resetting;
/* SWAG: sbuf size = avg stat. line size * number of locks */
#define LPROF_SBUF_SIZE 256 * 400
@@ -239,25 +242,77 @@ lock_prof_init(void *arg)
}
SYSINIT(lockprof, SI_SUB_SMP, SI_ORDER_ANY, lock_prof_init, NULL);
+/*
+ * To be certain that lock profiling has idled on all cpus before we
+ * reset, we schedule the resetting thread on all active cpus. Since
+ * all operations happen within critical sections we can be sure that
+ * it is safe to zero the profiling structures.
+ */
+static void
+lock_prof_idle(void)
+{
+ struct thread *td;
+ int cpu;
+
+ td = curthread;
+ thread_lock(td);
+ for (cpu = 0; cpu <= mp_maxid; cpu++) {
+ if (CPU_ABSENT(cpu))
+ continue;
+ sched_bind(td, cpu);
+ }
+ sched_unbind(td);
+ thread_unlock(td);
+}
+
+static void
+lock_prof_reset_wait(void)
+{
+
+ /*
+ * Spin relinquishing our cpu so that lock_prof_idle may
+ * run on it.
+ */
+ while (lock_prof_resetting)
+ sched_relinquish(curthread);
+}
+
static void
lock_prof_reset(void)
{
struct lock_prof_cpu *lpc;
int enabled, i, cpu;
+ /*
+ * We not only race with acquiring and releasing locks but also
+ * thread exit. To be certain that threads exit without valid head
+ * pointers they must see resetting set before enabled is cleared.
+ * Otherwise a lock may not be removed from a per-thread list due
+ * to disabled being set but not wait for reset() to remove it below.
+ */
+ atomic_store_rel_int(&lock_prof_resetting, 1);
enabled = lock_prof_enable;
lock_prof_enable = 0;
- pause("lpreset", hz / 10);
+ lock_prof_idle();
+ /*
+ * Some objects may have migrated between CPUs. Clear all links
+ * before we zero the structures. Some items may still be linked
+ * into per-thread lists as well.
+ */
for (cpu = 0; cpu <= mp_maxid; cpu++) {
lpc = lp_cpu[cpu];
for (i = 0; i < LPROF_CACHE_SIZE; i++) {
LIST_REMOVE(&lpc->lpc_types[0].lpt_objs[i], lpo_link);
LIST_REMOVE(&lpc->lpc_types[1].lpt_objs[i], lpo_link);
}
+ }
+ for (cpu = 0; cpu <= mp_maxid; cpu++) {
+ lpc = lp_cpu[cpu];
bzero(lpc, sizeof(*lpc));
lock_prof_init_type(&lpc->lpc_types[0]);
lock_prof_init_type(&lpc->lpc_types[1]);
}
+ atomic_store_rel_int(&lock_prof_resetting, 0);
lock_prof_enable = enabled;
}
@@ -351,7 +406,7 @@ retry_sbufops:
"max", "wait_max", "total", "wait_total", "count", "avg", "wait_avg", "cnt_hold", "cnt_lock", "name");
enabled = lock_prof_enable;
lock_prof_enable = 0;
- pause("lpreset", hz / 10);
+ lock_prof_idle();
t = ticks;
for (cpu = 0; cpu <= mp_maxid; cpu++) {
if (lp_cpu[cpu] == NULL)
@@ -461,16 +516,13 @@ lock_profile_object_lookup(struct lock_object *lo, int spin, const char *file,
if (l->lpo_obj == lo && l->lpo_file == file &&
l->lpo_line == line)
return (l);
- critical_enter();
type = &lp_cpu[PCPU_GET(cpuid)]->lpc_types[spin];
l = LIST_FIRST(&type->lpt_lpoalloc);
if (l == NULL) {
lock_prof_rejected++;
- critical_exit();
return (NULL);
}
LIST_REMOVE(l, lpo_link);
- critical_exit();
l->lpo_obj = lo;
l->lpo_file = file;
l->lpo_line = line;
@@ -497,18 +549,49 @@ lock_profile_obtain_lock_success(struct lock_object *lo, int contested,
spin = (LOCK_CLASS(lo)->lc_flags & LC_SPINLOCK) ? 1 : 0;
if (spin && lock_prof_skipspin == 1)
return;
+ critical_enter();
+ /* Recheck enabled now that we're in a critical section. */
+ if (lock_prof_enable == 0)
+ goto out;
l = lock_profile_object_lookup(lo, spin, file, line);
if (l == NULL)
- return;
+ goto out;
l->lpo_cnt++;
if (++l->lpo_ref > 1)
- return;
+ goto out;
l->lpo_contest_locking = contested;
l->lpo_acqtime = nanoseconds();
if (waittime && (l->lpo_acqtime > waittime))
l->lpo_waittime = l->lpo_acqtime - waittime;
else
l->lpo_waittime = 0;
+out:
+ critical_exit();
+}
+
+void
+lock_profile_thread_exit(struct thread *td)
+{
+#ifdef INVARIANTS
+ struct lock_profile_object *l;
+
+ MPASS(curthread->td_critnest == 0);
+#endif
+ /*
+ * If lock profiling was disabled we have to wait for reset to
+ * clear our pointers before we can exit safely.
+ */
+ lock_prof_reset_wait();
+#ifdef INVARIANTS
+ LIST_FOREACH(l, &td->td_lprof[0], lpo_link)
+ printf("thread still holds lock acquired at %s:%d\n",
+ l->lpo_file, l->lpo_line);
+ LIST_FOREACH(l, &td->td_lprof[1], lpo_link)
+ printf("thread still holds lock acquired at %s:%d\n",
+ l->lpo_file, l->lpo_line);
+#endif
+ MPASS(LIST_FIRST(&td->td_lprof[0]) == NULL);
+ MPASS(LIST_FIRST(&td->td_lprof[1]) == NULL);
}
void
@@ -521,11 +604,20 @@ lock_profile_release_lock(struct lock_object *lo)
struct lpohead *head;
int spin;
- if (!lock_prof_enable || (lo->lo_flags & LO_NOPROFILE))
+ if (lo->lo_flags & LO_NOPROFILE)
return;
spin = (LOCK_CLASS(lo)->lc_flags & LC_SPINLOCK) ? 1 : 0;
head = &curthread->td_lprof[spin];
+ if (LIST_FIRST(head) == NULL)
+ return;
critical_enter();
+ /* Recheck enabled now that we're in a critical section. */
+ if (lock_prof_enable == 0 && lock_prof_resetting == 1)
+ goto out;
+ /*
+ * If lock profiling is not enabled we still want to remove the
+ * lpo from our queue.
+ */
LIST_FOREACH(l, head, lpo_link)
if (l->lpo_obj == lo)
break;
diff --git a/sys/kern/subr_param.c b/sys/kern/subr_param.c
index f45a64d..ed0437f 100644
--- a/sys/kern/subr_param.c
+++ b/sys/kern/subr_param.c
@@ -100,23 +100,30 @@ u_long dflssiz; /* initial stack size limit */
u_long maxssiz; /* max stack size */
u_long sgrowsiz; /* amount to grow stack */
-SYSCTL_INT(_kern, OID_AUTO, hz, CTLFLAG_RDTUN, &hz, 0, "ticks/second");
-SYSCTL_INT(_kern, OID_AUTO, maxswzone, CTLFLAG_RDTUN, &maxswzone, 0,
- "max swmeta KVA storage");
-SYSCTL_INT(_kern, OID_AUTO, maxbcache, CTLFLAG_RDTUN, &maxbcache, 0,
- "max buffer cache KVA storage");
+SYSCTL_INT(_kern, OID_AUTO, hz, CTLFLAG_RDTUN, &hz, 0,
+ "Number of clock ticks per second");
+SYSCTL_INT(_kern, OID_AUTO, ncallout, CTLFLAG_RDTUN, &ncallout, 0,
+ "Number of pre-allocated timer events");
+SYSCTL_INT(_kern, OID_AUTO, nbuf, CTLFLAG_RDTUN, &nbuf, 0,
+ "Number of buffers in the buffer cache");
+SYSCTL_INT(_kern, OID_AUTO, nswbuf, CTLFLAG_RDTUN, &nswbuf, 0,
+ "Number of swap buffers");
+SYSCTL_LONG(_kern, OID_AUTO, maxswzone, CTLFLAG_RDTUN, &maxswzone, 0,
+ "Maximum memory for swap metadata");
+SYSCTL_LONG(_kern, OID_AUTO, maxbcache, CTLFLAG_RDTUN, &maxbcache, 0,
+ "Maximum value of vfs.maxbufspace");
SYSCTL_ULONG(_kern, OID_AUTO, maxtsiz, CTLFLAG_RDTUN, &maxtsiz, 0,
- "max text size");
+ "Maximum text size");
SYSCTL_ULONG(_kern, OID_AUTO, dfldsiz, CTLFLAG_RDTUN, &dfldsiz, 0,
- "initial data size limit");
+ "Initial data size limit");
SYSCTL_ULONG(_kern, OID_AUTO, maxdsiz, CTLFLAG_RDTUN, &maxdsiz, 0,
- "max data size");
+ "Maximum data size");
SYSCTL_ULONG(_kern, OID_AUTO, dflssiz, CTLFLAG_RDTUN, &dflssiz, 0,
- "initial stack size limit");
+ "Initial stack size limit");
SYSCTL_ULONG(_kern, OID_AUTO, maxssiz, CTLFLAG_RDTUN, &maxssiz, 0,
- "max stack size");
+ "Maximum stack size");
SYSCTL_ULONG(_kern, OID_AUTO, sgrowsiz, CTLFLAG_RDTUN, &sgrowsiz, 0,
- "amount to grow stack");
+ "Amount to grow stack on a stack fault");
SYSCTL_PROC(_kern, OID_AUTO, vm_guest, CTLFLAG_RD | CTLTYPE_STRING,
NULL, 0, sysctl_kern_vm_guest, "A",
"Virtual machine detected? (none|generic|xen)");
diff --git a/sys/kern/subr_rtc.c b/sys/kern/subr_rtc.c
index 0f3ec17..e919bf0 100644
--- a/sys/kern/subr_rtc.c
+++ b/sys/kern/subr_rtc.c
@@ -109,44 +109,36 @@ clock_register(device_t dev, long res) /* res has units of microseconds */
void
inittodr(time_t base)
{
- struct timespec diff, ref, ts;
+ struct timespec ref, ts;
int error;
- if (base) {
- ref.tv_sec = base;
- ref.tv_nsec = 0;
- tc_setclock(&ref);
- }
-
if (clock_dev == NULL) {
printf("warning: no time-of-day clock registered, system time "
"will not be set accurately\n");
- return;
+ goto wrong_time;
}
/* XXX: We should poll all registered RTCs in case of failure */
error = CLOCK_GETTIME(clock_dev, &ts);
if (error != 0 && error != EINVAL) {
printf("warning: clock_gettime failed (%d), the system time "
"will not be set accurately\n", error);
- return;
+ goto wrong_time;
}
if (error == EINVAL || ts.tv_sec < 0) {
- printf("Invalid time in real time clock.\n");
- printf("Check and reset the date immediately!\n");
+ printf("Invalid time in real time clock.\n"
+ "Check and reset the date immediately!\n");
+ goto wrong_time;
}
ts.tv_sec += utc_offset();
+ tc_setclock(&ts);
+ return;
- if (timespeccmp(&ref, &ts, >)) {
- diff = ref;
- timespecsub(&ref, &ts);
- } else {
- diff = ts;
- timespecsub(&diff, &ref);
- }
- if (ts.tv_sec >= 2) {
- /* badly off, adjust it */
- tc_setclock(&ts);
+wrong_time:
+ if (base > 0) {
+ ref.tv_sec = base;
+ ref.tv_nsec = 0;
+ tc_setclock(&ref);
}
}
diff --git a/sys/kern/subr_smp.c b/sys/kern/subr_smp.c
index e807e48..1a3a6fa 100644
--- a/sys/kern/subr_smp.c
+++ b/sys/kern/subr_smp.c
@@ -262,6 +262,54 @@ stop_cpus(cpumask_t map)
return 1;
}
+#if defined(__amd64__)
+/*
+ * When called the executing CPU will send an IPI to all other CPUs
+ * requesting that they halt execution.
+ *
+ * Usually (but not necessarily) called with 'other_cpus' as its arg.
+ *
+ * - Signals all CPUs in map to suspend.
+ * - Waits for each to suspend.
+ *
+ * Returns:
+ * -1: error
+ * 0: NA
+ * 1: ok
+ *
+ * XXX FIXME: this is not MP-safe, needs a lock to prevent multiple CPUs
+ * from executing at same time.
+ */
+int
+suspend_cpus(cpumask_t map)
+{
+ int i;
+
+ if (!smp_started)
+ return (0);
+
+ CTR1(KTR_SMP, "suspend_cpus(%x)", map);
+
+ /* send the suspend IPI to all CPUs in map */
+ ipi_selected(map, IPI_SUSPEND);
+
+ i = 0;
+ while ((stopped_cpus & map) != map) {
+ /* spin */
+ cpu_spinwait();
+ i++;
+#ifdef DIAGNOSTIC
+ if (i == 100000) {
+ printf("timeout suspending cpus\n");
+ break;
+ }
+#endif
+ }
+
+ return (1);
+}
+#endif
+
/*
* Called by a CPU to restart stopped CPUs.
*
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index 0112a04..12a2c4e 100644
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -285,6 +285,7 @@ semunload(void)
free(semu, M_SEM);
for (i = 0; i < seminfo.semmni; i++)
mtx_destroy(&sema_mtx[i]);
+ free(sema_mtx, M_SEM);
mtx_destroy(&sem_mtx);
mtx_destroy(&sem_undo_mtx);
return (0);
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index e12f270..43c7f68 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -371,23 +371,31 @@ tty_wait_background(struct tty *tp, struct thread *td, int sig)
* exit
* - the signal to send to the process isn't masked
*/
- if (!tty_is_ctty(tp, p) ||
- p->p_pgrp == tp->t_pgrp || p->p_flag & P_PPWAIT ||
- SIGISMEMBER(p->p_sigacts->ps_sigignore, sig) ||
- SIGISMEMBER(td->td_sigmask, sig)) {
+ if (!tty_is_ctty(tp, p) || p->p_pgrp == tp->t_pgrp) {
/* Allow the action to happen. */
PROC_UNLOCK(p);
return (0);
}
+ if (SIGISMEMBER(p->p_sigacts->ps_sigignore, sig) ||
+ SIGISMEMBER(td->td_sigmask, sig)) {
+ /* Only allow them in write()/ioctl(). */
+ PROC_UNLOCK(p);
+ return (sig == SIGTTOU ? 0 : EIO);
+ }
+
+ pg = p->p_pgrp;
+ if (p->p_flag & P_PPWAIT || pg->pg_jobc == 0) {
+ /* Don't allow the action to happen. */
+ PROC_UNLOCK(p);
+ return (EIO);
+ }
+ PROC_UNLOCK(p);
+
/*
* Send the signal and sleep until we're the new
* foreground process group.
*/
- pg = p->p_pgrp;
- PROC_UNLOCK(p);
- if (pg->pg_jobc == 0)
- return (EIO);
PGRP_LOCK(pg);
pgsignal(pg, sig, 1);
PGRP_UNLOCK(pg);
diff --git a/sys/kern/uipc_domain.c b/sys/kern/uipc_domain.c
index 9c9b05f..df35bcb 100644
--- a/sys/kern/uipc_domain.c
+++ b/sys/kern/uipc_domain.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/socketvar.h>
#include <sys/systm.h>
+#include <sys/vimage.h>
#include <vm/uma.h>
/*
@@ -64,6 +65,8 @@ static void domainfinalize(void *);
SYSINIT(domainfin, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST, domainfinalize,
NULL);
+static vnet_attach_fn net_init_domain;
+
static struct callout pffast_callout;
static struct callout pfslow_callout;
@@ -100,6 +103,14 @@ struct pr_usrreqs nousrreqs = {
.pru_sopoll = pru_sopoll_notsupp,
};
+#ifndef VIMAGE_GLOBALS
+vnet_modinfo_t vnet_domain_modinfo = {
+ .vmi_id = VNET_MOD_DOMAIN,
+ .vmi_name = "domain",
+ .vmi_iattach = net_init_domain
+};
+#endif
+
static void
protosw_init(struct protosw *pr)
{
@@ -159,9 +170,10 @@ protosw_init(struct protosw *pr)
* Note: you cant unload it again because a socket may be using it.
* XXX can't fail at this time.
*/
-static void
-net_init_domain(struct domain *dp)
+static int
+net_init_domain(const void *arg)
{
+ const struct domain *dp = arg;
struct protosw *pr;
if (dp->dom_init)
@@ -175,6 +187,7 @@ net_init_domain(struct domain *dp)
max_datalen = MHLEN - max_hdr;
if (max_datalen < 1)
panic("%s: max_datalen < 1", __func__);
+ return (0);
}
/*
@@ -210,7 +223,11 @@ net_add_domain(void *data)
"domainfinalize()\n", dp->dom_name);
#endif
mtx_unlock(&dom_mtx);
+#ifndef VIMAGE_GLOBALS
+ vnet_mod_register_multi(&vnet_domain_modinfo, dp, dp->dom_name);
+#else
net_init_domain(dp);
+#endif
}
static void
diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c
index 47b711a..da233a6 100644
--- a/sys/kern/uipc_sem.c
+++ b/sys/kern/uipc_sem.c
@@ -548,6 +548,8 @@ int
ksem_open(struct thread *td, struct ksem_open_args *uap)
{
+ DP((">>> ksem_open start, pid=%d\n", (int)td->td_proc->p_pid));
+
if ((uap->oflag & ~(O_CREAT | O_EXCL)) != 0)
return (EINVAL);
return (ksem_create(td, uap->name, uap->idp, uap->mode, uap->value,
@@ -708,12 +710,14 @@ kern_sem_wait(struct thread *td, semid_t id, int tryflag,
struct ksem *ks;
int error;
- DP((">>> kern_sem_wait entered!\n"));
+ DP((">>> kern_sem_wait entered! pid=%d\n", (int)td->td_proc->p_pid));
error = ksem_get(td, id, &fp);
if (error)
return (error);
ks = fp->f_data;
mtx_lock(&sem_lock);
+ DP((">>> kern_sem_wait critical section entered! pid=%d\n",
+ (int)td->td_proc->p_pid));
#ifdef MAC
error = mac_posixsem_check_wait(td->td_ucred, fp->f_cred, ks);
if (error) {
@@ -723,7 +727,7 @@ kern_sem_wait(struct thread *td, semid_t id, int tryflag,
#endif
DP(("kern_sem_wait value = %d, tryflag %d\n", ks->ks_value, tryflag));
vfs_timestamp(&ks->ks_atime);
- if (ks->ks_value == 0) {
+ while (ks->ks_value == 0) {
ks->ks_waiters++;
if (tryflag != 0)
error = EAGAIN;
@@ -750,11 +754,13 @@ kern_sem_wait(struct thread *td, semid_t id, int tryflag,
goto err;
}
ks->ks_value--;
+ DP(("kern_sem_wait value post-decrement = %d\n", ks->ks_value));
error = 0;
err:
mtx_unlock(&sem_lock);
fdrop(fp, td);
- DP(("<<< kern_sem_wait leaving, error = %d\n", error));
+ DP(("<<< kern_sem_wait leaving, pid=%d, error = %d\n",
+ (int)td->td_proc->p_pid, error));
return (error);
}
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 2233e65..662b3abd 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -1811,7 +1811,7 @@ kern_sendfile(struct thread *td, struct sendfile_args *uap,
if ((error = fgetvp_read(td, uap->fd, &vp)) != 0)
goto out;
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ vn_lock(vp, LK_SHARED | LK_RETRY);
if (vp->v_type == VREG) {
obj = vp->v_object;
if (obj != NULL) {
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 517784a..6ddc837 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -457,10 +457,8 @@ restart:
error = mac_vnode_check_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd,
&vattr);
#endif
- if (error == 0) {
- VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
+ if (error == 0)
error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
- }
NDFREE(&nd, NDF_ONLY_PNBUF);
vput(nd.ni_dvp);
if (error) {
diff --git a/sys/kern/vfs_acl.c b/sys/kern/vfs_acl.c
index 760b0e7..6a7c461 100644
--- a/sys/kern/vfs_acl.c
+++ b/sys/kern/vfs_acl.c
@@ -91,7 +91,6 @@ vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type,
error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
if (error != 0)
return (error);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
#ifdef MAC
error = mac_vnode_check_setacl(td->td_ucred, vp, type, &inkernacl);
@@ -117,7 +116,6 @@ vacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type,
struct acl inkernelacl;
int error;
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
#ifdef MAC
error = mac_vnode_check_getacl(td->td_ucred, vp, type);
@@ -146,7 +144,6 @@ vacl_delete(struct thread *td, struct vnode *vp, acl_type_t type)
error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
if (error)
return (error);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
#ifdef MAC
error = mac_vnode_check_deleteacl(td->td_ucred, vp, type);
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 14c3569..0715e91 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -106,7 +106,8 @@ static void vfs_setdirty_locked_object(struct buf *bp);
static void vfs_vmio_release(struct buf *bp);
static int vfs_bio_clcheck(struct vnode *vp, int size,
daddr_t lblkno, daddr_t blkno);
-static int flushbufqueues(int, int);
+static int buf_do_flush(struct vnode *vp);
+static int flushbufqueues(struct vnode *, int, int);
static void buf_daemon(void);
static void bremfreel(struct buf *bp);
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
@@ -124,10 +125,10 @@ static long bufspace;
#if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \
defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD7)
SYSCTL_PROC(_vfs, OID_AUTO, bufspace, CTLTYPE_LONG|CTLFLAG_MPSAFE|CTLFLAG_RD,
- &bufspace, 0, sysctl_bufspace, "L", "KVA memory used for bufs");
+ &bufspace, 0, sysctl_bufspace, "L", "Virtual memory used for buffers");
#else
SYSCTL_LONG(_vfs, OID_AUTO, bufspace, CTLFLAG_RD, &bufspace, 0,
- "KVA memory used for bufs");
+ "Virtual memory used for buffers");
#endif
static long maxbufspace;
SYSCTL_LONG(_vfs, OID_AUTO, maxbufspace, CTLFLAG_RD, &maxbufspace, 0,
@@ -198,6 +199,9 @@ SYSCTL_INT(_vfs, OID_AUTO, getnewbufcalls, CTLFLAG_RW, &getnewbufcalls, 0,
static int getnewbufrestarts;
SYSCTL_INT(_vfs, OID_AUTO, getnewbufrestarts, CTLFLAG_RW, &getnewbufrestarts, 0,
"Number of times getnewbuf has had to restart a buffer aquisition");
+static int flushbufqtarget = 100;
+SYSCTL_INT(_vfs, OID_AUTO, flushbufqtarget, CTLFLAG_RW, &flushbufqtarget, 0,
+ "Amount of work to do in flushbufqueues when helping bufdaemon");
/*
* Wakeup point for bufdaemon, as well as indicator of whether it is already
@@ -258,6 +262,7 @@ static struct mtx nblock;
#define QUEUE_DIRTY_GIANT 3 /* B_DELWRI buffers that need giant */
#define QUEUE_EMPTYKVA 4 /* empty buffer headers w/KVA assignment */
#define QUEUE_EMPTY 5 /* empty buffer headers */
+#define QUEUE_SENTINEL 1024 /* not an queue index, but mark for sentinel */
/* Queues for free buffers with various properties */
static TAILQ_HEAD(bqueues, buf) bufqueues[BUFFER_QUEUES] = { { 0 } };
@@ -1364,9 +1369,23 @@ brelse(struct buf *bp)
if (bp->b_qindex != QUEUE_NONE)
panic("brelse: free buffer onto another queue???");
+ /*
+ * If the buffer has junk contents signal it and eventually
+ * clean up B_DELWRI and diassociate the vnode so that gbincore()
+ * doesn't find it.
+ */
+ if (bp->b_bufsize == 0 || (bp->b_ioflags & BIO_ERROR) != 0 ||
+ (bp->b_flags & (B_INVAL | B_NOCACHE | B_RELBUF)) != 0)
+ bp->b_flags |= B_INVAL;
+ if (bp->b_flags & B_INVAL) {
+ if (bp->b_flags & B_DELWRI)
+ bundirty(bp);
+ if (bp->b_vp)
+ brelvp(bp);
+ }
+
/* buffers with no memory */
if (bp->b_bufsize == 0) {
- bp->b_flags |= B_INVAL;
bp->b_xflags &= ~(BX_BKGRDWRITE | BX_ALTDATA);
if (bp->b_vflags & BV_BKGRDINPROG)
panic("losing buffer 1");
@@ -1379,7 +1398,6 @@ brelse(struct buf *bp)
/* buffers with junk contents */
} else if (bp->b_flags & (B_INVAL | B_NOCACHE | B_RELBUF) ||
(bp->b_ioflags & BIO_ERROR)) {
- bp->b_flags |= B_INVAL;
bp->b_xflags &= ~(BX_BKGRDWRITE | BX_ALTDATA);
if (bp->b_vflags & BV_BKGRDINPROG)
panic("losing buffer 2");
@@ -1402,19 +1420,6 @@ brelse(struct buf *bp)
mtx_unlock(&bqlock);
/*
- * If B_INVAL and B_DELWRI is set, clear B_DELWRI. We have already
- * placed the buffer on the correct queue. We must also disassociate
- * the device and vnode for a B_INVAL buffer so gbincore() doesn't
- * find it.
- */
- if (bp->b_flags & B_INVAL) {
- if (bp->b_flags & B_DELWRI)
- bundirty(bp);
- if (bp->b_vp)
- brelvp(bp);
- }
-
- /*
* Fixup numfreebuffers count. The bp is on an appropriate queue
* unless locked. We then bump numfreebuffers if it is not B_DELWRI.
* We've already handled the B_INVAL case ( B_DELWRI will be clear
@@ -1710,21 +1715,23 @@ vfs_bio_awrite(struct buf *bp)
*/
static struct buf *
-getnewbuf(int slpflag, int slptimeo, int size, int maxsize)
+getnewbuf(struct vnode *vp, int slpflag, int slptimeo, int size, int maxsize,
+ int gbflags)
{
+ struct thread *td;
struct buf *bp;
struct buf *nbp;
int defrag = 0;
int nqindex;
static int flushingbufs;
+ td = curthread;
/*
* We can't afford to block since we might be holding a vnode lock,
* which may prevent system daemons from running. We deal with
* low-memory situations by proactively returning memory and running
* async I/O rather then sync I/O.
*/
-
atomic_add_int(&getnewbufcalls, 1);
atomic_subtract_int(&getnewbufrestarts, 1);
restart:
@@ -1956,8 +1963,9 @@ restart:
*/
if (bp == NULL) {
- int flags;
+ int flags, norunbuf;
char *waitmsg;
+ int fl;
if (defrag) {
flags = VFS_BIO_NEED_BUFSPACE;
@@ -1975,9 +1983,35 @@ restart:
mtx_unlock(&bqlock);
bd_speedup(); /* heeeelp */
+ if (gbflags & GB_NOWAIT_BD)
+ return (NULL);
mtx_lock(&nblock);
while (needsbuffer & flags) {
+ if (vp != NULL && (td->td_pflags & TDP_BUFNEED) == 0) {
+ mtx_unlock(&nblock);
+ /*
+ * getblk() is called with a vnode
+ * locked, and some majority of the
+ * dirty buffers may as well belong to
+ * the vnode. Flushing the buffers
+ * there would make a progress that
+ * cannot be achieved by the
+ * buf_daemon, that cannot lock the
+ * vnode.
+ */
+ norunbuf = ~(TDP_BUFNEED | TDP_NORUNNINGBUF) |
+ (td->td_pflags & TDP_NORUNNINGBUF);
+ /* play bufdaemon */
+ td->td_pflags |= TDP_BUFNEED | TDP_NORUNNINGBUF;
+ fl = buf_do_flush(vp);
+ td->td_pflags &= norunbuf;
+ mtx_lock(&nblock);
+ if (fl != 0)
+ continue;
+ if ((needsbuffer & flags) == 0)
+ break;
+ }
if (msleep(&needsbuffer, &nblock,
(PRIBIO + 4) | slpflag, waitmsg, slptimeo)) {
mtx_unlock(&nblock);
@@ -2046,6 +2080,35 @@ static struct kproc_desc buf_kp = {
};
SYSINIT(bufdaemon, SI_SUB_KTHREAD_BUF, SI_ORDER_FIRST, kproc_start, &buf_kp);
+static int
+buf_do_flush(struct vnode *vp)
+{
+ int flushed;
+
+ flushed = flushbufqueues(vp, QUEUE_DIRTY, 0);
+ /* The list empty check here is slightly racy */
+ if (!TAILQ_EMPTY(&bufqueues[QUEUE_DIRTY_GIANT])) {
+ mtx_lock(&Giant);
+ flushed += flushbufqueues(vp, QUEUE_DIRTY_GIANT, 0);
+ mtx_unlock(&Giant);
+ }
+ if (flushed == 0) {
+ /*
+ * Could not find any buffers without rollback
+ * dependencies, so just write the first one
+ * in the hopes of eventually making progress.
+ */
+ flushbufqueues(vp, QUEUE_DIRTY, 1);
+ if (!TAILQ_EMPTY(
+ &bufqueues[QUEUE_DIRTY_GIANT])) {
+ mtx_lock(&Giant);
+ flushbufqueues(vp, QUEUE_DIRTY_GIANT, 1);
+ mtx_unlock(&Giant);
+ }
+ }
+ return (flushed);
+}
+
static void
buf_daemon()
{
@@ -2059,7 +2122,7 @@ buf_daemon()
/*
* This process is allowed to take the buffer cache to the limit
*/
- curthread->td_pflags |= TDP_NORUNNINGBUF;
+ curthread->td_pflags |= TDP_NORUNNINGBUF | TDP_BUFNEED;
mtx_lock(&bdlock);
for (;;) {
bd_request = 0;
@@ -2074,30 +2137,8 @@ buf_daemon()
* normally would so they can run in parallel with our drain.
*/
while (numdirtybuffers > lodirtybuffers) {
- int flushed;
-
- flushed = flushbufqueues(QUEUE_DIRTY, 0);
- /* The list empty check here is slightly racy */
- if (!TAILQ_EMPTY(&bufqueues[QUEUE_DIRTY_GIANT])) {
- mtx_lock(&Giant);
- flushed += flushbufqueues(QUEUE_DIRTY_GIANT, 0);
- mtx_unlock(&Giant);
- }
- if (flushed == 0) {
- /*
- * Could not find any buffers without rollback
- * dependencies, so just write the first one
- * in the hopes of eventually making progress.
- */
- flushbufqueues(QUEUE_DIRTY, 1);
- if (!TAILQ_EMPTY(
- &bufqueues[QUEUE_DIRTY_GIANT])) {
- mtx_lock(&Giant);
- flushbufqueues(QUEUE_DIRTY_GIANT, 1);
- mtx_unlock(&Giant);
- }
+ if (buf_do_flush(NULL) == 0)
break;
- }
uio_yield();
}
@@ -2143,7 +2184,7 @@ SYSCTL_INT(_vfs, OID_AUTO, flushwithdeps, CTLFLAG_RW, &flushwithdeps,
0, "Number of buffers flushed with dependecies that require rollbacks");
static int
-flushbufqueues(int queue, int flushdeps)
+flushbufqueues(struct vnode *lvp, int queue, int flushdeps)
{
struct buf sentinel;
struct vnode *vp;
@@ -2153,20 +2194,37 @@ flushbufqueues(int queue, int flushdeps)
int flushed;
int target;
- target = numdirtybuffers - lodirtybuffers;
- if (flushdeps && target > 2)
- target /= 2;
+ if (lvp == NULL) {
+ target = numdirtybuffers - lodirtybuffers;
+ if (flushdeps && target > 2)
+ target /= 2;
+ } else
+ target = flushbufqtarget;
flushed = 0;
bp = NULL;
+ sentinel.b_qindex = QUEUE_SENTINEL;
mtx_lock(&bqlock);
- TAILQ_INSERT_TAIL(&bufqueues[queue], &sentinel, b_freelist);
+ TAILQ_INSERT_HEAD(&bufqueues[queue], &sentinel, b_freelist);
while (flushed != target) {
- bp = TAILQ_FIRST(&bufqueues[queue]);
- if (bp == &sentinel)
+ bp = TAILQ_NEXT(&sentinel, b_freelist);
+ if (bp != NULL) {
+ TAILQ_REMOVE(&bufqueues[queue], &sentinel, b_freelist);
+ TAILQ_INSERT_AFTER(&bufqueues[queue], bp, &sentinel,
+ b_freelist);
+ } else
break;
- TAILQ_REMOVE(&bufqueues[queue], bp, b_freelist);
- TAILQ_INSERT_TAIL(&bufqueues[queue], bp, b_freelist);
-
+ /*
+ * Skip sentinels inserted by other invocations of the
+ * flushbufqueues(), taking care to not reorder them.
+ */
+ if (bp->b_qindex == QUEUE_SENTINEL)
+ continue;
+ /*
+ * Only flush the buffers that belong to the
+ * vnode locked by the curthread.
+ */
+ if (lvp != NULL && bp->b_vp != lvp)
+ continue;
if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL) != 0)
continue;
if (bp->b_pin_count > 0) {
@@ -2214,16 +2272,27 @@ flushbufqueues(int queue, int flushdeps)
BUF_UNLOCK(bp);
continue;
}
- if (vn_lock(vp, LK_EXCLUSIVE | LK_NOWAIT) == 0) {
+ if (vn_lock(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_CANRECURSE) == 0) {
mtx_unlock(&bqlock);
CTR3(KTR_BUF, "flushbufqueue(%p) vp %p flags %X",
bp, bp->b_vp, bp->b_flags);
- vfs_bio_awrite(bp);
+ if (curproc == bufdaemonproc)
+ vfs_bio_awrite(bp);
+ else {
+ bremfree(bp);
+ bwrite(bp);
+ }
vn_finished_write(mp);
VOP_UNLOCK(vp, 0);
flushwithdeps += hasdeps;
flushed++;
- waitrunningbufspace();
+
+ /*
+ * Sleeping on runningbufspace while holding
+ * vnode lock leads to deadlock.
+ */
+ if (curproc == bufdaemonproc)
+ waitrunningbufspace();
numdirtywakeup((lodirtybuffers + hidirtybuffers) / 2);
mtx_lock(&bqlock);
continue;
@@ -2605,7 +2674,7 @@ loop:
maxsize = vmio ? size + (offset & PAGE_MASK) : size;
maxsize = imax(maxsize, bsize);
- bp = getnewbuf(slpflag, slptimeo, size, maxsize);
+ bp = getnewbuf(vp, slpflag, slptimeo, size, maxsize, flags);
if (bp == NULL) {
if (slpflag || slptimeo)
return NULL;
@@ -2680,14 +2749,17 @@ loop:
* set to B_INVAL.
*/
struct buf *
-geteblk(int size)
+geteblk(int size, int flags)
{
struct buf *bp;
int maxsize;
maxsize = (size + BKVAMASK) & ~BKVAMASK;
- while ((bp = getnewbuf(0, 0, size, maxsize)) == 0)
- continue;
+ while ((bp = getnewbuf(NULL, 0, 0, size, maxsize, flags)) == NULL) {
+ if ((flags & GB_NOWAIT_BD) &&
+ (curthread->td_pflags & TDP_BUFNEED) != 0)
+ return (NULL);
+ }
allocbuf(bp, size);
bp->b_flags |= B_INVAL; /* b_dep cleared by getnewbuf() */
BUF_ASSERT_HELD(bp);
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index cec1e33..3c81b01 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -35,6 +35,9 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_kdtrace.h"
+#include "opt_ktrace.h"
+
#include <sys/param.h>
#include <sys/filedesc.h>
#include <sys/fnv_hash.h>
@@ -45,14 +48,43 @@ __FBSDID("$FreeBSD$");
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/rwlock.h>
+#include <sys/sdt.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/sysproto.h>
#include <sys/systm.h>
#include <sys/vnode.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
#include <vm/uma.h>
+SDT_PROVIDER_DECLARE(vfs);
+SDT_PROBE_DEFINE3(vfs, namecache, enter, done, "struct vnode *", "char *",
+ "struct vnode *");
+SDT_PROBE_DEFINE2(vfs, namecache, enter_negative, done, "struct vnode *",
+ "char *");
+SDT_PROBE_DEFINE1(vfs, namecache, fullpath, entry, "struct vnode *");
+SDT_PROBE_DEFINE3(vfs, namecache, fullpath, hit, "struct vnode *",
+ "struct char *", "struct vnode *");
+SDT_PROBE_DEFINE1(vfs, namecache, fullpath, miss, "struct vnode *");
+SDT_PROBE_DEFINE3(vfs, namecache, fullpath, return, "int", "struct vnode *",
+ "struct char *");
+SDT_PROBE_DEFINE3(vfs, namecache, lookup, hit, "struct vnode *", "char *",
+ "struct vnode *");
+SDT_PROBE_DEFINE2(vfs, namecache, lookup, hit_negative, "struct vnode *",
+ "char *");
+SDT_PROBE_DEFINE2(vfs, namecache, lookup, miss, "struct vnode *",
+ "char *");
+SDT_PROBE_DEFINE1(vfs, namecache, purge, done, "struct vnode *");
+SDT_PROBE_DEFINE1(vfs, namecache, purge_negative, done, "struct vnode *");
+SDT_PROBE_DEFINE1(vfs, namecache, purgevfs, done, "struct mount *");
+SDT_PROBE_DEFINE3(vfs, namecache, zap, done, "struct vnode *", "char *",
+ "struct vnode *");
+SDT_PROBE_DEFINE2(vfs, namecache, zap_negative, done, "struct vnode *",
+ "char *");
+
/*
* This structure describes the elements in the cache of recent
* names looked up by namei.
@@ -66,7 +98,7 @@ struct namecache {
struct vnode *nc_vp; /* vnode the name refers to */
u_char nc_flag; /* flag bits */
u_char nc_nlen; /* length of name */
- char nc_name[0]; /* segment name */
+ char nc_name[0]; /* segment name + nul */
};
/*
@@ -128,9 +160,10 @@ RW_SYSINIT(vfscache, &cache_lock, "Name Cache");
static uma_zone_t cache_zone_small;
static uma_zone_t cache_zone_large;
-#define CACHE_PATH_CUTOFF 32
-#define CACHE_ZONE_SMALL (sizeof(struct namecache) + CACHE_PATH_CUTOFF)
-#define CACHE_ZONE_LARGE (sizeof(struct namecache) + NAME_MAX)
+#define CACHE_PATH_CUTOFF 35
+#define CACHE_ZONE_SMALL (sizeof(struct namecache) + CACHE_PATH_CUTOFF \
+ + 1)
+#define CACHE_ZONE_LARGE (sizeof(struct namecache) + NAME_MAX + 1)
#define cache_alloc(len) uma_zalloc(((len) <= CACHE_PATH_CUTOFF) ? \
cache_zone_small : cache_zone_large, M_WAITOK)
@@ -182,7 +215,8 @@ static MALLOC_DEFINE(M_VFSCACHE, "vfscache", "VFS name cache entries");
/*
* Flags in namecache.nc_flag
*/
-#define NCF_WHITE 1
+#define NCF_WHITE 0x01
+#define NCF_ISDOTDOT 0x02
#ifdef DIAGNOSTIC
/*
@@ -285,16 +319,31 @@ cache_zap(ncp)
rw_assert(&cache_lock, RA_WLOCKED);
CTR2(KTR_VFS, "cache_zap(%p) vp %p", ncp, ncp->nc_vp);
+#ifdef KDTRACE_HOOKS
+ if (ncp->nc_vp != NULL) {
+ SDT_PROBE(vfs, namecache, zap, done, ncp->nc_dvp,
+ ncp->nc_name, ncp->nc_vp, 0, 0);
+ } else {
+ SDT_PROBE(vfs, namecache, zap_negative, done, ncp->nc_dvp,
+ ncp->nc_name, 0, 0, 0);
+ }
+#endif
vp = NULL;
LIST_REMOVE(ncp, nc_hash);
- LIST_REMOVE(ncp, nc_src);
- if (LIST_EMPTY(&ncp->nc_dvp->v_cache_src)) {
- vp = ncp->nc_dvp;
- numcachehv--;
+ if (ncp->nc_flag & NCF_ISDOTDOT) {
+ if (ncp == ncp->nc_dvp->v_cache_dd)
+ ncp->nc_dvp->v_cache_dd = NULL;
+ } else {
+ LIST_REMOVE(ncp, nc_src);
+ if (LIST_EMPTY(&ncp->nc_dvp->v_cache_src)) {
+ vp = ncp->nc_dvp;
+ numcachehv--;
+ }
}
if (ncp->nc_vp) {
TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst, ncp, nc_dst);
- ncp->nc_vp->v_dd = NULL;
+ if (ncp == ncp->nc_vp->v_cache_dd)
+ ncp->nc_vp->v_cache_dd = NULL;
} else {
TAILQ_REMOVE(&ncneg, ncp, nc_dst);
numneg--;
@@ -315,7 +364,7 @@ cache_zap(ncp)
* (negative cacheing), a status of ENOENT is returned. If the lookup
* fails, a status of zero is returned. If the directory vnode is
* recycled out from under us due to a forced unmount, a status of
- * EBADF is returned.
+ * ENOENT is returned.
*
* vpp is locked and ref'd on return. If we're looking up DOTDOT, dvp is
* unlocked. If we're looking up . an extra ref is taken, but the lock is
@@ -349,17 +398,33 @@ retry_wlocked:
CTR2(KTR_VFS, "cache_lookup(%p, %s) found via .",
dvp, cnp->cn_nameptr);
dothits++;
+ SDT_PROBE(vfs, namecache, lookup, hit, dvp, ".",
+ *vpp, 0, 0);
goto success;
}
if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
dotdothits++;
- if (dvp->v_dd == NULL ||
- (cnp->cn_flags & MAKEENTRY) == 0) {
+ if (dvp->v_cache_dd == NULL) {
+ SDT_PROBE(vfs, namecache, lookup, miss, dvp,
+ "..", NULL, 0, 0);
+ goto unlock;
+ }
+ if ((cnp->cn_flags & MAKEENTRY) == 0) {
+ if (!wlocked && !CACHE_UPGRADE_LOCK())
+ goto wlock;
+ if (dvp->v_cache_dd->nc_flag & NCF_ISDOTDOT)
+ cache_zap(dvp->v_cache_dd);
+ dvp->v_cache_dd = NULL;
goto unlock;
}
- *vpp = dvp->v_dd;
+ if (dvp->v_cache_dd->nc_flag & NCF_ISDOTDOT)
+ *vpp = dvp->v_cache_dd->nc_vp;
+ else
+ *vpp = dvp->v_cache_dd->nc_dvp;
CTR3(KTR_VFS, "cache_lookup(%p, %s) found %p via ..",
dvp, cnp->cn_nameptr, *vpp);
+ SDT_PROBE(vfs, namecache, lookup, hit, dvp, "..",
+ *vpp, 0, 0);
goto success;
}
}
@@ -375,6 +440,8 @@ retry_wlocked:
/* We failed to find an entry */
if (ncp == NULL) {
+ SDT_PROBE(vfs, namecache, lookup, miss, dvp, cnp->cn_nameptr,
+ NULL, 0, 0);
if ((cnp->cn_flags & MAKEENTRY) == 0) {
nummisszap++;
} else {
@@ -402,6 +469,8 @@ retry_wlocked:
*vpp = ncp->nc_vp;
CTR4(KTR_VFS, "cache_lookup(%p, %s) found %p via ncp %p",
dvp, cnp->cn_nameptr, *vpp, ncp);
+ SDT_PROBE(vfs, namecache, lookup, hit, dvp, ncp->nc_name,
+ *vpp, 0, 0);
goto success;
}
@@ -430,6 +499,8 @@ retry_wlocked:
nchstats.ncs_neghits++;
if (ncp->nc_flag & NCF_WHITE)
cnp->cn_flags |= ISWHITEOUT;
+ SDT_PROBE(vfs, namecache, lookup, hit_negative, dvp, ncp->nc_name,
+ 0, 0, 0);
CACHE_WUNLOCK();
return (ENOENT);
@@ -467,7 +538,7 @@ success:
/* forced unmount */
vrele(*vpp);
*vpp = NULL;
- return (EBADF);
+ return (ENOENT);
}
} else
vn_lock(*vpp, LK_DOWNGRADE | LK_RETRY);
@@ -485,8 +556,15 @@ success:
else
CACHE_RUNLOCK();
error = vget(*vpp, cnp->cn_lkflags | LK_INTERLOCK, cnp->cn_thread);
- if (cnp->cn_flags & ISDOTDOT)
+ if (cnp->cn_flags & ISDOTDOT) {
vn_lock(dvp, ltype | LK_RETRY);
+ if (dvp->v_iflag & VI_DOOMED) {
+ if (error == 0)
+ vput(*vpp);
+ *vpp = NULL;
+ return (ENOENT);
+ }
+ }
if (error) {
*vpp = NULL;
goto retry;
@@ -517,6 +595,7 @@ cache_enter(dvp, vp, cnp)
struct namecache *ncp, *n2;
struct nchashhead *ncpp;
u_int32_t hash;
+ int flag;
int hold;
int zap;
int len;
@@ -534,23 +613,35 @@ cache_enter(dvp, vp, cnp)
if (numcache >= desiredvnodes * 2)
return;
+ flag = 0;
if (cnp->cn_nameptr[0] == '.') {
- if (cnp->cn_namelen == 1) {
+ if (cnp->cn_namelen == 1)
return;
- }
- /*
- * For dotdot lookups only cache the v_dd pointer if the
- * directory has a link back to its parent via v_cache_dst.
- * Without this an unlinked directory would keep a soft
- * reference to its parent which could not be NULLd at
- * cache_purge() time.
- */
if (cnp->cn_namelen == 2 && cnp->cn_nameptr[1] == '.') {
CACHE_WLOCK();
- if (!TAILQ_EMPTY(&dvp->v_cache_dst))
- dvp->v_dd = vp;
+ /*
+ * If dotdot entry already exists, just retarget it
+ * to new parent vnode, otherwise continue with new
+ * namecache entry allocation.
+ */
+ if ((ncp = dvp->v_cache_dd) != NULL) {
+ if (ncp->nc_flag & NCF_ISDOTDOT) {
+ KASSERT(ncp->nc_dvp == dvp,
+ ("wrong isdotdot parent"));
+ TAILQ_REMOVE(&ncp->nc_vp->v_cache_dst,
+ ncp, nc_dst);
+ TAILQ_INSERT_HEAD(&vp->v_cache_dst,
+ ncp, nc_dst);
+ ncp->nc_vp = vp;
+ CACHE_WUNLOCK();
+ return;
+ }
+ }
+ dvp->v_cache_dd = NULL;
+ SDT_PROBE(vfs, namecache, enter, done, dvp, "..", vp,
+ 0, 0);
CACHE_WUNLOCK();
- return;
+ flag = NCF_ISDOTDOT;
}
}
@@ -564,9 +655,10 @@ cache_enter(dvp, vp, cnp)
ncp = cache_alloc(cnp->cn_namelen);
ncp->nc_vp = vp;
ncp->nc_dvp = dvp;
+ ncp->nc_flag = flag;
len = ncp->nc_nlen = cnp->cn_namelen;
hash = fnv_32_buf(cnp->cn_nameptr, len, FNV1_32_INIT);
- bcopy(cnp->cn_nameptr, ncp->nc_name, len);
+ strlcpy(ncp->nc_name, cnp->cn_nameptr, len + 1);
hash = fnv_32_buf(&dvp, sizeof(dvp), hash);
CACHE_WLOCK();
@@ -586,14 +678,35 @@ cache_enter(dvp, vp, cnp)
}
}
+ if (flag == NCF_ISDOTDOT) {
+ /*
+ * See if we are trying to add .. entry, but some other lookup
+ * has populated v_cache_dd pointer already.
+ */
+ if (dvp->v_cache_dd != NULL) {
+ CACHE_WUNLOCK();
+ cache_free(ncp);
+ return;
+ }
+ KASSERT(vp == NULL || vp->v_type == VDIR,
+ ("wrong vnode type %p", vp));
+ dvp->v_cache_dd = ncp;
+ }
+
numcache++;
if (!vp) {
numneg++;
- ncp->nc_flag = cnp->cn_flags & ISWHITEOUT ? NCF_WHITE : 0;
+ if (cnp->cn_flags & ISWHITEOUT)
+ ncp->nc_flag |= NCF_WHITE;
} else if (vp->v_type == VDIR) {
- vp->v_dd = dvp;
+ if (flag != NCF_ISDOTDOT) {
+ if ((n2 = vp->v_cache_dd) != NULL &&
+ (n2->nc_flag & NCF_ISDOTDOT) != 0)
+ cache_zap(n2);
+ vp->v_cache_dd = ncp;
+ }
} else {
- vp->v_dd = NULL;
+ vp->v_cache_dd = NULL;
}
/*
@@ -601,11 +714,14 @@ cache_enter(dvp, vp, cnp)
* within the cache entries table.
*/
LIST_INSERT_HEAD(ncpp, ncp, nc_hash);
- if (LIST_EMPTY(&dvp->v_cache_src)) {
- hold = 1;
- numcachehv++;
+ if (flag != NCF_ISDOTDOT) {
+ if (LIST_EMPTY(&dvp->v_cache_src)) {
+ hold = 1;
+ numcachehv++;
+ }
+ LIST_INSERT_HEAD(&dvp->v_cache_src, ncp, nc_src);
}
- LIST_INSERT_HEAD(&dvp->v_cache_src, ncp, nc_src);
+
/*
* If the entry is "negative", we place it into the
* "negative" cache queue, otherwise, we place it into the
@@ -613,8 +729,12 @@ cache_enter(dvp, vp, cnp)
*/
if (vp) {
TAILQ_INSERT_HEAD(&vp->v_cache_dst, ncp, nc_dst);
+ SDT_PROBE(vfs, namecache, enter, done, dvp, ncp->nc_name, vp,
+ 0, 0);
} else {
TAILQ_INSERT_TAIL(&ncneg, ncp, nc_dst);
+ SDT_PROBE(vfs, namecache, enter_negative, done, dvp,
+ ncp->nc_name, 0, 0, 0);
}
if (numneg * ncnegfactor > numcache) {
ncp = TAILQ_FIRST(&ncneg);
@@ -655,12 +775,18 @@ cache_purge(vp)
{
CTR1(KTR_VFS, "cache_purge(%p)", vp);
+ SDT_PROBE(vfs, namecache, purge, done, vp, 0, 0, 0, 0);
CACHE_WLOCK();
while (!LIST_EMPTY(&vp->v_cache_src))
cache_zap(LIST_FIRST(&vp->v_cache_src));
while (!TAILQ_EMPTY(&vp->v_cache_dst))
cache_zap(TAILQ_FIRST(&vp->v_cache_dst));
- vp->v_dd = NULL;
+ if (vp->v_cache_dd != NULL) {
+ KASSERT(vp->v_cache_dd->nc_flag & NCF_ISDOTDOT,
+ ("lost dotdot link"));
+ cache_zap(vp->v_cache_dd);
+ }
+ KASSERT(vp->v_cache_dd == NULL, ("incomplete purge"));
CACHE_WUNLOCK();
}
@@ -674,6 +800,7 @@ cache_purge_negative(vp)
struct namecache *cp, *ncp;
CTR1(KTR_VFS, "cache_purge_negative(%p)", vp);
+ SDT_PROBE(vfs, namecache, purge_negative, done, vp, 0, 0, 0, 0);
CACHE_WLOCK();
LIST_FOREACH_SAFE(cp, &vp->v_cache_src, nc_src, ncp) {
if (cp->nc_vp == NULL)
@@ -693,6 +820,7 @@ cache_purgevfs(mp)
struct namecache *ncp, *nnp;
/* Scan hash tables for applicable entries */
+ SDT_PROBE(vfs, namecache, purgevfs, done, mp, 0, 0, 0, 0);
CACHE_WLOCK();
for (ncpp = &nchashtbl[nchash]; ncpp >= nchashtbl; ncpp--) {
LIST_FOREACH_SAFE(ncp, ncpp, nc_hash, nnp) {
@@ -807,6 +935,10 @@ kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg, u_int buflen)
bcopy(bp, buf, strlen(bp) + 1);
else
error = copyout(bp, buf, strlen(bp) + 1);
+#ifdef KTRACE
+ if (KTRPOINT(curthread, KTR_NAMEI))
+ ktrnamei(bp);
+#endif
}
free(tmpbuf, M_TEMP);
return (error);
@@ -935,6 +1067,9 @@ vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
char *bp;
int error, i, slash_prefixed;
struct namecache *ncp;
+#ifdef KDTRACE_HOOKS
+ struct vnode *startvp = vp;
+#endif
buflen--;
bp = buf + buflen;
@@ -942,39 +1077,53 @@ vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
error = 0;
slash_prefixed = 0;
+ SDT_PROBE(vfs, namecache, fullpath, entry, vp, 0, 0, 0, 0);
CACHE_RLOCK();
numfullpathcalls++;
if (vp->v_type != VDIR) {
ncp = TAILQ_FIRST(&vp->v_cache_dst);
if (ncp != NULL) {
- for (i = ncp->nc_nlen - 1; i >= 0 && bp > buf; i--)
+ buflen -= ncp->nc_nlen;
+ for (i = ncp->nc_nlen - 1; i >= 0 && bp != buf; i--)
*--bp = ncp->nc_name[i];
if (bp == buf) {
numfullpathfail4++;
CACHE_RUNLOCK();
- return (ENOMEM);
+ error = ENOMEM;
+ SDT_PROBE(vfs, namecache, fullpath, return,
+ error, startvp, NULL, 0, 0);
+ return (error);
}
+ SDT_PROBE(vfs, namecache, fullpath, hit, ncp->nc_dvp,
+ ncp->nc_name, vp, 0, 0);
vp = ncp->nc_dvp;
} else {
+ SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0,
+ 0, 0);
error = vn_vptocnp(&vp, &bp, buf, &buflen);
if (error) {
+ SDT_PROBE(vfs, namecache, fullpath, return,
+ error, startvp, NULL, 0, 0);
return (error);
}
}
- *--bp = '/';
- buflen--;
- if (buflen < 0) {
+ if (buflen <= 0) {
numfullpathfail4++;
CACHE_RUNLOCK();
- return (ENOMEM);
+ error = ENOMEM;
+ SDT_PROBE(vfs, namecache, fullpath, return, error,
+ startvp, NULL, 0, 0);
+ return (error);
}
+ *--bp = '/';
+ buflen--;
slash_prefixed = 1;
}
while (vp != rdir && vp != rootvnode) {
if (vp->v_vflag & VV_ROOT) {
if (vp->v_iflag & VI_DOOMED) { /* forced unmount */
CACHE_RUNLOCK();
- error = EBADF;
+ error = ENOENT;
break;
}
vp = vp->v_mount->mnt_vnodecovered;
@@ -986,10 +1135,11 @@ vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
error = ENOTDIR;
break;
}
- ncp = TAILQ_FIRST(&vp->v_cache_dst);
+ TAILQ_FOREACH(ncp, &vp->v_cache_dst, nc_dst)
+ if ((ncp->nc_flag & NCF_ISDOTDOT) == 0)
+ break;
if (ncp != NULL) {
- MPASS(vp->v_dd == NULL || ncp->nc_dvp == vp->v_dd);
- buflen -= ncp->nc_nlen - 1;
+ buflen -= ncp->nc_nlen;
for (i = ncp->nc_nlen - 1; i >= 0 && bp != buf; i--)
*--bp = ncp->nc_name[i];
if (bp == buf) {
@@ -998,37 +1148,45 @@ vn_fullpath1(struct thread *td, struct vnode *vp, struct vnode *rdir,
error = ENOMEM;
break;
}
+ SDT_PROBE(vfs, namecache, fullpath, hit, ncp->nc_dvp,
+ ncp->nc_name, vp, 0, 0);
vp = ncp->nc_dvp;
} else {
+ SDT_PROBE(vfs, namecache, fullpath, miss, vp, 0, 0,
+ 0, 0);
error = vn_vptocnp(&vp, &bp, buf, &buflen);
- if (error) {
+ if (error)
break;
- }
}
- *--bp = '/';
- buflen--;
- if (buflen < 0) {
+ if (buflen <= 0) {
numfullpathfail4++;
CACHE_RUNLOCK();
error = ENOMEM;
break;
}
+ *--bp = '/';
+ buflen--;
slash_prefixed = 1;
}
- if (error)
+ if (error) {
+ SDT_PROBE(vfs, namecache, fullpath, return, error, startvp,
+ NULL, 0, 0);
return (error);
+ }
if (!slash_prefixed) {
if (bp == buf) {
numfullpathfail4++;
CACHE_RUNLOCK();
+ SDT_PROBE(vfs, namecache, fullpath, return, 0,
+ startvp, bp, 0, 0);
return (ENOMEM);
- } else {
+ } else
*--bp = '/';
- }
}
numfullpathfound++;
CACHE_RUNLOCK();
+ SDT_PROBE(vfs, namecache, fullpath, return, 0, startvp, bp, 0, 0);
*retbuf = bp;
return (0);
}
@@ -1040,8 +1198,10 @@ vn_commname(struct vnode *vp, char *buf, u_int buflen)
int l;
CACHE_RLOCK();
- ncp = TAILQ_FIRST(&vp->v_cache_dst);
- if (!ncp) {
+ TAILQ_FOREACH(ncp, &vp->v_cache_dst, nc_dst)
+ if ((ncp->nc_flag & NCF_ISDOTDOT) == 0)
+ break;
+ if (ncp == NULL) {
CACHE_RUNLOCK();
return (ENOENT);
}
diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c
index 1001497..2fe64b3 100644
--- a/sys/kern/vfs_default.c
+++ b/sys/kern/vfs_default.c
@@ -98,7 +98,6 @@ struct vop_vector default_vnodeops = {
.vop_ioctl = VOP_ENOTTY,
.vop_kqfilter = vop_stdkqfilter,
.vop_islocked = vop_stdislocked,
- .vop_lease = VOP_NULL,
.vop_lock1 = vop_stdlock,
.vop_lookup = vop_nolookup,
.vop_open = VOP_NULL,
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index c8b59d9..18890b7 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -175,7 +175,6 @@ extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
if (error)
return (error);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
aiov.iov_base = data;
@@ -341,7 +340,6 @@ extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
int error;
VFS_ASSERT_GIANT(vp->v_mount);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
/*
@@ -522,7 +520,6 @@ extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
if (error)
return (error);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
#ifdef MAC
@@ -664,7 +661,6 @@ extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
int error;
VFS_ASSERT_GIANT(vp->v_mount);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
auiop = NULL;
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index daecd6f..757e56e 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -37,6 +37,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_kdtrace.h"
#include "opt_ktrace.h"
#include "opt_mac.h"
@@ -51,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mount.h>
#include <sys/filedesc.h>
#include <sys/proc.h>
+#include <sys/sdt.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#ifdef KTRACE
@@ -65,6 +67,11 @@ __FBSDID("$FreeBSD$");
#define NAMEI_DIAGNOSTIC 1
#undef NAMEI_DIAGNOSTIC
+SDT_PROVIDER_DECLARE(vfs);
+SDT_PROBE_DEFINE3(vfs, namei, lookup, entry, "struct vnode *", "char *",
+ "unsigned long");
+SDT_PROBE_DEFINE2(vfs, namei, lookup, return, "int", "struct vnode *");
+
/*
* Allocation zone for namei
*/
@@ -181,7 +188,6 @@ namei(struct nameidata *ndp)
ktrnamei(cnp->cn_pnbuf);
}
#endif
-
/*
* Get starting point for the translation.
*/
@@ -224,6 +230,8 @@ namei(struct nameidata *ndp)
VFS_UNLOCK_GIANT(vfslocked);
}
}
+ SDT_PROBE(vfs, namei, lookup, entry, dp, cnp->cn_pnbuf,
+ cnp->cn_flags, 0, 0);
vfslocked = VFS_LOCK_GIANT(dp->v_mount);
for (;;) {
/*
@@ -252,6 +260,8 @@ namei(struct nameidata *ndp)
cnp->cn_pnbuf = NULL;
cnp->cn_nameptr = NULL;
#endif
+ SDT_PROBE(vfs, namei, lookup, return, error, NULL, 0,
+ 0, 0);
return (error);
}
vfslocked = (ndp->ni_cnd.cn_flags & GIANTHELD) != 0;
@@ -273,6 +283,8 @@ namei(struct nameidata *ndp)
VFS_UNLOCK_GIANT(vfslocked);
} else if (vfslocked)
ndp->ni_cnd.cn_flags |= GIANTHELD;
+ SDT_PROBE(vfs, namei, lookup, return, 0, ndp->ni_vp,
+ 0, 0, 0);
return (0);
}
if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
@@ -338,6 +350,7 @@ namei(struct nameidata *ndp)
ndp->ni_vp = NULL;
vrele(ndp->ni_dvp);
VFS_UNLOCK_GIANT(vfslocked);
+ SDT_PROBE(vfs, namei, lookup, return, error, NULL, 0, 0, 0);
return (error);
}
@@ -602,7 +615,7 @@ dirloop:
if ((dp->v_vflag & VV_ROOT) == 0)
break;
if (dp->v_iflag & VI_DOOMED) { /* forced unmount */
- error = EBADF;
+ error = ENOENT;
goto bad;
}
tdp = dp;
@@ -764,9 +777,11 @@ unionlookup:
*ndp->ni_next == '/')) {
cnp->cn_flags |= ISSYMLINK;
if (dp->v_iflag & VI_DOOMED) {
- /* We can't know whether the directory was mounted with
- * NOSYMFOLLOW, so we can't follow safely. */
- error = EBADF;
+ /*
+ * We can't know whether the directory was mounted with
+ * NOSYMFOLLOW, so we can't follow safely.
+ */
+ error = ENOENT;
goto bad2;
}
if (dp->v_mount->mnt_flag & MNT_NOSYMFOLLOW) {
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index e489d80..e4256c7 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -1357,6 +1357,9 @@ root_mount_hold(const char *identifier)
{
struct root_hold_token *h;
+ if (root_mounted())
+ return (NULL);
+
h = malloc(sizeof *h, M_DEVBUF, M_ZERO | M_WAITOK);
h->who = identifier;
mtx_lock(&mountlist_mtx);
@@ -1372,6 +1375,8 @@ void
root_mount_rel(struct root_hold_token *h)
{
+ if (h == NULL)
+ return;
mtx_lock(&mountlist_mtx);
LIST_REMOVE(h, list);
wakeup(&root_holds);
@@ -1386,6 +1391,8 @@ static void
root_mount_prepare(void)
{
struct root_hold_token *h;
+ struct timeval lastfail;
+ int curfail = 0;
for (;;) {
DROP_GIANT();
@@ -1396,10 +1403,12 @@ root_mount_prepare(void)
mtx_unlock(&mountlist_mtx);
break;
}
- printf("Root mount waiting for:");
- LIST_FOREACH(h, &root_holds, list)
- printf(" %s", h->who);
- printf("\n");
+ if (ppsratecheck(&lastfail, &curfail, 1)) {
+ printf("Root mount waiting for:");
+ LIST_FOREACH(h, &root_holds, list)
+ printf(" %s", h->who);
+ printf("\n");
+ }
msleep(&root_holds, &mountlist_mtx, PZERO | PDROP, "roothold",
hz);
}
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 9411e81..fcaf514 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -860,6 +860,7 @@ vdestroy(struct vnode *vp)
VNASSERT(bo->bo_dirty.bv_root == NULL, vp, ("dirtyblkroot not NULL"));
VNASSERT(TAILQ_EMPTY(&vp->v_cache_dst), vp, ("vp has namecache dst"));
VNASSERT(LIST_EMPTY(&vp->v_cache_src), vp, ("vp has namecache src"));
+ VNASSERT(vp->v_cache_dd == NULL, vp, ("vp has namecache for .."));
VI_UNLOCK(vp);
#ifdef MAC
mac_vnode_destroy(vp);
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index ad69698..202f2d1 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -1161,7 +1161,6 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
if (flags & O_TRUNC) {
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
goto bad;
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
VATTR_NULL(&vat);
vat.va_size = 0;
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
@@ -1353,7 +1352,6 @@ restart:
&nd.ni_cnd, &vattr);
#endif
if (!error) {
- VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
if (whiteout)
error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
else {
@@ -1460,7 +1458,6 @@ restart:
if (error)
goto out;
#endif
- VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
if (error == 0)
vput(nd.ni_vp);
@@ -1606,8 +1603,6 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2,
error = EEXIST;
} else if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY))
== 0) {
- VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
error = can_hardlink(vp, td->td_ucred);
if (error == 0)
#ifdef MAC
@@ -1727,7 +1722,6 @@ restart:
if (error)
goto out2;
#endif
- VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, syspath);
if (error == 0)
vput(nd.ni_vp);
@@ -1787,7 +1781,6 @@ restart:
return (error);
goto restart;
}
- VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE);
NDFREE(&nd, NDF_ONLY_PNBUF);
vput(nd.ni_dvp);
@@ -1893,7 +1886,6 @@ restart:
if (error)
goto out;
#endif
- VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
#ifdef MAC
out:
@@ -2667,7 +2659,6 @@ setfflags(td, vp, flags)
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
return (error);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
VATTR_NULL(&vattr);
vattr.va_flags = flags;
@@ -2795,7 +2786,6 @@ setfmode(td, vp, mode)
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
return (error);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
VATTR_NULL(&vattr);
vattr.va_mode = mode & ALLPERMS;
@@ -2958,7 +2948,6 @@ setfown(td, vp, uid, gid)
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
return (error);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
VATTR_NULL(&vattr);
vattr.va_uid = uid;
@@ -3172,7 +3161,6 @@ setutimes(td, vp, ts, numtimes, nullflag)
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
return (error);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
setbirthtime = 0;
if (numtimes < 3 && !VOP_GETATTR(vp, &vattr, td->td_ucred) &&
@@ -3403,7 +3391,6 @@ kern_truncate(struct thread *td, char *path, enum uio_seg pathseg, off_t length)
return (error);
}
NDFREE(&nd, NDF_ONLY_PNBUF);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
if (vp->v_type == VDIR)
error = EISDIR;
@@ -3647,13 +3634,6 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
#endif
out:
if (!error) {
- VOP_LEASE(tdvp, td, td->td_ucred, LEASE_WRITE);
- if (fromnd.ni_dvp != tdvp) {
- VOP_LEASE(fromnd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
- }
- if (tvp) {
- VOP_LEASE(tvp, td, td->td_ucred, LEASE_WRITE);
- }
error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
NDFREE(&fromnd, NDF_ONLY_PNBUF);
@@ -3779,7 +3759,6 @@ restart:
if (error)
goto out;
#endif
- VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
#ifdef MAC
out:
@@ -3872,8 +3851,6 @@ restart:
return (error);
goto restart;
}
- VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
vn_finished_write(mp);
out:
@@ -4462,7 +4439,6 @@ fhopen(td, uap)
vrele(vp);
goto out;
}
- VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */
#ifdef MAC
/*
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index 681c0eb..48a74ac 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -153,14 +153,10 @@ restart:
#ifdef MAC
error = mac_vnode_check_create(cred, ndp->ni_dvp,
&ndp->ni_cnd, vap);
- if (error == 0) {
+ if (error == 0)
#endif
- VOP_LEASE(ndp->ni_dvp, td, cred, LEASE_WRITE);
error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
&ndp->ni_cnd, vap);
-#ifdef MAC
- }
-#endif
vput(ndp->ni_dvp);
vn_finished_write(mp);
if (error) {
@@ -521,7 +517,6 @@ vn_read(fp, uio, active_cred, flags, td)
if (fp->f_flag & O_DIRECT)
ioflag |= IO_DIRECT;
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
- VOP_LEASE(vp, td, fp->f_cred, LEASE_READ);
/*
* According to McKusick the vn lock was protecting f_offset here.
* It is now protected by the FOFFSET_LOCKED flag.
@@ -598,7 +593,6 @@ vn_write(fp, uio, active_cred, flags, td)
if (vp->v_type != VCHR &&
(error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
goto unlock;
- VOP_LEASE(vp, td, fp->f_cred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
if ((flags & FOF_OFFSET) == 0)
uio->uio_offset = fp->f_offset;
@@ -642,7 +636,6 @@ vn_truncate(fp, length, active_cred, td)
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
- VOP_LEASE(vp, td, active_cred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
if (vp->v_type == VDIR) {
error = EISDIR;
diff --git a/sys/kern/vnode_if.src b/sys/kern/vnode_if.src
index 0e198bf..b7d9cb1 100644
--- a/sys/kern/vnode_if.src
+++ b/sys/kern/vnode_if.src
@@ -199,16 +199,6 @@ vop_write {
};
-%% lease vp = = =
-
-vop_lease {
- IN struct vnode *vp;
- IN struct thread *td;
- IN struct ucred *cred;
- IN int flag;
-};
-
-
%% ioctl vp U U U
vop_ioctl {
diff --git a/sys/mips/alchemy/alchemy_machdep.c b/sys/mips/alchemy/alchemy_machdep.c
deleted file mode 100644
index eca9b18..0000000
--- a/sys/mips/alchemy/alchemy_machdep.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*-
- * Copyright (C) 2007 by Oleksandr Tymoshenko. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES 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 MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
- * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "opt_ddb.h"
-
-#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/systm.h>
-#include <sys/imgact.h>
-#include <sys/bio.h>
-#include <sys/buf.h>
-#include <sys/bus.h>
-#include <sys/cpu.h>
-#include <sys/cons.h>
-#include <sys/exec.h>
-#include <sys/ucontext.h>
-#include <sys/proc.h>
-#include <sys/kdb.h>
-#include <sys/ptrace.h>
-#include <sys/reboot.h>
-#include <sys/signalvar.h>
-#include <sys/sysent.h>
-#include <sys/sysproto.h>
-#include <sys/user.h>
-
-#include <vm/vm.h>
-#include <vm/vm_object.h>
-#include <vm/vm_page.h>
-#include <vm/vm_pager.h>
-
-#include <machine/cache.h>
-#include <machine/clock.h>
-#include <machine/cpu.h>
-#include <machine/cpuinfo.h>
-#include <machine/cpufunc.h>
-#include <machine/cpuregs.h>
-#include <machine/hwfunc.h>
-#include <machine/intr_machdep.h>
-#include <machine/locore.h>
-#include <machine/md_var.h>
-#include <machine/pte.h>
-#include <machine/sigframe.h>
-#include <machine/trap.h>
-#include <machine/vmparam.h>
-
-extern int *edata;
-extern int *end;
-
-static void
-mips_init(void)
-{
- int i;
-
- printf("entry: mips_init()\n");
-
- bootverbose = 1;
- realmem = btoc(16 << 20);
-
- for (i = 0; i < 10; i++) {
- phys_avail[i] = 0;
- }
-
- /* phys_avail regions are in bytes */
- phys_avail[0] = MIPS_KSEG0_TO_PHYS((vm_offset_t)&end);
- phys_avail[1] = ctob(realmem);
-
- physmem = realmem;
-
- init_param1();
- init_param2(physmem);
- mips_cpu_init();
- pmap_bootstrap();
- mips_proc0_init();
- mutex_init();
-#ifdef DDB
- kdb_init();
-#endif
-}
-
-void
-platform_halt(void)
-{
-
-}
-
-
-void
-platform_identify(void)
-{
-
-}
-
-void
-platform_reset(void)
-{
-
- __asm __volatile("li $25, 0xbfc00000");
- __asm __volatile("j $25");
-}
-
-void
-platform_trap_enter(void)
-{
-
-}
-
-void
-platform_trap_exit(void)
-{
-
-}
-
-void
-platform_start(__register_t a0 __unused, __register_t a1 __unused,
- __register_t a2 __unused, __register_t a3 __unused)
-{
- vm_offset_t kernend;
- uint64_t platform_counter_freq = 175 * 1000 * 1000;
-
- /* clear the BSS and SBSS segments */
- kernend = round_page((vm_offset_t)&end);
- memset(&edata, 0, kernend - (vm_offset_t)(&edata));
-
- cninit();
- mips_init();
- /* Set counter_freq for tick_init_params() */
- platform_counter_freq = 175 * 1000 * 1000;
-
- mips_timer_init_params(platform_counter_freq, 0);
-}
diff --git a/sys/mips/alchemy/aureg.h b/sys/mips/alchemy/aureg.h
deleted file mode 100644
index dfa2103..0000000
--- a/sys/mips/alchemy/aureg.h
+++ /dev/null
@@ -1,373 +0,0 @@
-/* $NetBSD: aureg.h,v 1.18 2006/10/02 06:44:00 gdamore Exp $ */
-
-/*
- * Copyright 2002 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Simon Burge for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _MIPS_ALCHEMY_AUREG_H
-#define _MIPS_ALCHEMY_AUREG_H
-
-/************************************************************************/
-/******************** AC97 Controller registers *********************/
-/************************************************************************/
-#define AC97_BASE 0x10000000
-
-/************************************************************************/
-/*********************** USB Host registers *************************/
-/************************************************************************/
-#define USBH_BASE 0x10100000
-#define AU1550_USBH_BASE 0x14020000
-
-#define USBH_ENABLE 0x7fffc
-#define USBH_SIZE 0x100000
-
-#define AU1550_USBH_ENABLE 0x7ffc
-#define AU1550_USBH_SIZE 0x60000
-
-/************************************************************************/
-/********************** USB Device registers ************************/
-/************************************************************************/
-#define USBD_BASE 0x10200000
-
-/************************************************************************/
-/************************* IRDA registers ***************************/
-/************************************************************************/
-#define IRDA_BASE 0x10300000
-
-/************************************************************************/
-/****************** Interrupt Controller registers ******************/
-/************************************************************************/
-
-#define IC0_BASE 0x10400000
-#define IC1_BASE 0x11800000
-
-/*
- * The *_READ registers read the current value of the register
- * The *_SET registers set to 1 all bits that are written 1
- * The *_CLEAR registers clear to zero all bits that are written as 1
- */
-#define IC_CONFIG0_READ 0x40 /* See table below */
-#define IC_CONFIG0_SET 0x40
-#define IC_CONFIG0_CLEAR 0x44
-
-#define IC_CONFIG1_READ 0x48 /* See table below */
-#define IC_CONFIG1_SET 0x48
-#define IC_CONFIG1_CLEAR 0x4c
-
-#define IC_CONFIG2_READ 0x50 /* See table below */
-#define IC_CONFIG2_SET 0x50
-#define IC_CONFIG2_CLEAR 0x54
-
-#define IC_REQUEST0_INT 0x54 /* Show active interrupts on request 0 */
-
-#define IC_SOURCE_READ 0x58 /* Interrupt source */
-#define IC_SOURCE_SET 0x58 /* 0 - test bit used as source */
-#define IC_SOURCE_CLEAR 0x5c /* 1 - peripheral/GPIO used as source */
-
-#define IC_REQUEST1_INT 0x5c /* Show active interrupts on request 1 */
-
-#define IC_ASSIGN_REQUEST_READ 0x60 /* Assigns the interrupt to one of the */
-#define IC_ASSIGN_REQUEST_SET 0x60 /* CPU requests (0 - assign to request 1, */
-#define IC_ASSIGN_REQUEST_CLEAR 0x64 /* 1 - assign to request 0) */
-
-#define IC_WAKEUP_READ 0x68 /* Controls whether the interrupt can */
-#define IC_WAKEUP_SET 0x68 /* cause a wakeup from IDLE */
-#define IC_WAKEUP_CLEAR 0x6c
-
-#define IC_MASK_READ 0x70 /* Enables/Disables the interrupt */
-#define IC_MASK_SET 0x70
-#define IC_MASK_CLEAR 0x74
-
-#define IC_RISING_EDGE 0x78 /* Check/clear rising edge */
-
-#define IC_FALLING_EDGE 0x7c /* Check/clear falling edge */
-
-#define IC_TEST_BIT 0x80 /* single bit source select */
-
-/*
- * Interrupt Configuration Register Functions
- *
- * Cfg2[n] Cfg1[n] Cfg0[n] Function
- * 0 0 0 Interrupts Disabled
- * 0 0 1 Rising Edge Enabled
- * 0 1 0 Falling Edge Enabled
- * 0 1 1 Rising and Falling Edge Enabled
- * 1 0 0 Interrupts Disabled
- * 1 0 1 High Level Enabled
- * 1 1 0 Low Level Enabled
- * 1 1 1 Both Levels and Both Edges Enabled
- */
-
-/************************************************************************/
-/************* Programable Serial Controller registers **************/
-/************************************************************************/
-
-#define PSC0_BASE 0x11A00000
-#define PSC1_BASE 0x11B00000
-#define PSC2_BASE 0x10A00000
-#define PSC3_BASE 0x10B00000
-
-
-/************************************************************************/
-/********************** Ethernet MAC registers **********************/
-/************************************************************************/
-
-#define MAC0_BASE 0x10500000
-#define MAC1_BASE 0x10510000
-#define MACx_SIZE 0x28
-
-#define AU1500_MAC0_BASE 0x11500000 /* Grr, different on Au1500 */
-#define AU1500_MAC1_BASE 0x11510000 /* Grr, different on Au1500 */
-
-#define MAC0_ENABLE 0x10520000
-#define MAC1_ENABLE 0x10520004
-#define MACENx_SIZE 0x04
-
-#define AU1500_MAC0_ENABLE 0x11520000 /* Grr, different on Au1500 */
-#define AU1500_MAC1_ENABLE 0x11520004 /* Grr, different on Au1500 */
-
-#define MAC0_DMA_BASE 0x14004000
-#define MAC1_DMA_BASE 0x14004200
-#define MACx_DMA_SIZE 0x140
-
-/************************************************************************/
-/********************** Static Bus registers ************************/
-/************************************************************************/
-#define STATIC_BUS_BASE 0x14001000
-
-/************************************************************************/
-/******************** Secure Digital registers **********************/
-/************************************************************************/
-#define SD0_BASE 0x10600000
-#define SD1_BASE 0x10680000
-
-/************************************************************************/
-/************************* I^2S registers ***************************/
-/************************************************************************/
-#define I2S_BASE 0x11000000
-
-/************************************************************************/
-/************************** UART registers **************************/
-/************************************************************************/
-
-#define UART0_BASE 0x11100000
-#define UART1_BASE 0x11200000
-#define UART2_BASE 0x11300000
-#define UART3_BASE 0x11400000
-
-/************************************************************************/
-/************************* SSI registers ****************************/
-/************************************************************************/
-#define SSI0_BASE 0x11600000
-#define SSI1_BASE 0x11680000
-
-/************************************************************************/
-/************************ GPIO2 registers ***************************/
-/************************************************************************/
-#define GPIO_BASE 0x11900100
-
-/************************************************************************/
-/************************ GPIO2 registers ***************************/
-/************************************************************************/
-#define GPIO2_BASE 0x11700000
-
-/************************************************************************/
-/************************* PCI registers ****************************/
-/************************************************************************/
-#define PCI_BASE 0x14005000
-#define PCI_HEADER 0x14005100
-#define PCI_MEM_BASE 0x400000000ULL
-#define PCI_IO_BASE 0x500000000ULL
-#define PCI_CONFIG_BASE 0x600000000ULL
-
-/************************************************************************/
-/*********************** PCMCIA registers ***************************/
-/************************************************************************/
-#define PCMCIA_BASE 0xF00000000ULL
-
-/************************************************************************/
-/****************** Programmable Counter registers ******************/
-/************************************************************************/
-
-#define SYS_BASE 0x11900000
-
-#define PC_BASE SYS_BASE
-
-#define PC_TRIM0 0x00 /* PC0 Divide (16 bits) */
-#define PC_COUNTER_WRITE0 0x04 /* set PC0 */
-#define PC_MATCH0_0 0x08 /* match counter & interrupt */
-#define PC_MATCH1_0 0x0c /* match counter & interrupt */
-#define PC_MATCH2_0 0x10 /* match counter & interrupt */
-#define PC_COUNTER_CONTROL 0x14 /* Programmable Counter Control */
-#define CC_E1S 0x00800000 /* Enable PC1 write status */
-#define CC_T1S 0x00100000 /* Trim PC1 write status */
-#define CC_M21 0x00080000 /* Match 2 of PC1 write status */
-#define CC_M11 0x00040000 /* Match 1 of PC1 write status */
-#define CC_M01 0x00020000 /* Match 0 of PC1 write status */
-#define CC_C1S 0x00010000 /* PC1 write status */
-#define CC_BP 0x00004000 /* Bypass OSC (use GPIO1) */
-#define CC_EN1 0x00002000 /* Enable PC1 */
-#define CC_BT1 0x00001000 /* Bypass Trim on PC1 */
-#define CC_EN0 0x00000800 /* Enable PC0 */
-#define CC_BT0 0x00000400 /* Bypass Trim on PC0 */
-#define CC_EO 0x00000100 /* Enable Oscillator */
-#define CC_E0S 0x00000080 /* Enable PC0 write status */
-#define CC_32S 0x00000020 /* 32.768kHz OSC status */
-#define CC_T0S 0x00000010 /* Trim PC0 write status */
-#define CC_M20 0x00000008 /* Match 2 of PC0 write status */
-#define CC_M10 0x00000004 /* Match 1 of PC0 write status */
-#define CC_M00 0x00000002 /* Match 0 of PC0 write status */
-#define CC_C0S 0x00000001 /* PC0 write status */
-#define PC_COUNTER_READ_0 0x40 /* get PC0 */
-#define PC_TRIM1 0x44 /* PC1 Divide (16 bits) */
-#define PC_COUNTER_WRITE1 0x48 /* set PC1 */
-#define PC_MATCH0_1 0x4c /* match counter & interrupt */
-#define PC_MATCH1_1 0x50 /* match counter & interrupt */
-#define PC_MATCH2_1 0x54 /* match counter & interrupt */
-#define PC_COUNTER_READ_1 0x58 /* get PC1 */
-
-#define PC_SIZE 0x5c /* size of register set */
-#define PC_RATE 32768 /* counter rate is 32.768kHz */
-
-/************************************************************************/
-/******************* Frequency Generator Registers ******************/
-/************************************************************************/
-
-#define SYS_FREQCTRL0 (SYS_BASE + 0x20)
-#define SFC_FRDIV2(f) (f<<22) /* 29:22. Freq Divider 2 */
-#define SFC_FE2 (1<<21) /* Freq generator output enable 2 */
-#define SFC_FS2 (1<<20) /* Freq generator source 2 */
-#define SFC_FRDIV1(f) (f<<12) /* 19:12. Freq Divider 1 */
-#define SFC_FE1 (1<<11) /* Freq generator output enable 1 */
-#define SFC_FS1 (1<<10) /* Freq generator source 1 */
-#define SFC_FRDIV0(f) (f<<2) /* 9:2. Freq Divider 0 */
-#define SFC_FE0 2 /* Freq generator output enable 0 */
-#define SFC_FS0 1 /* Freq generator source 0 */
-
-#define SYS_FREQCTRL1 (SYS_BASE + 0x24)
-#define SFC_FRDIV5(f) (f<<22) /* 29:22. Freq Divider 5 */
-#define SFC_FE5 (1<<21) /* Freq generator output enable 5 */
-#define SFC_FS5 (1<<20) /* Freq generator source 5 */
-#define SFC_FRDIV4(f) (f<<12) /* 19:12. Freq Divider 4 */
-#define SFC_FE4 (1<<11) /* Freq generator output enable 4 */
-#define SFC_FS4 (1<<10) /* Freq generator source 4 */
-#define SFC_FRDIV3(f) (f<<2) /* 9:2. Freq Divider 3 */
-#define SFC_FE3 2 /* Freq generator output enable 3 */
-#define SFC_FS3 1 /* Freq generator source 3 */
-
-/************************************************************************/
-/****************** Clock Source Control Registers ******************/
-/************************************************************************/
-
-#define SYS_CLKSRC (SYS_BASE + 0x28)
-#define SCS_ME1(n) (n<<27) /* EXTCLK1 Clock Mux input select */
-#define SCS_ME0(n) (n<<22) /* EXTCLK0 Clock Mux input select */
-#define SCS_MPC(n) (n<<17) /* PCI clock mux input select */
-#define SCS_MUH(n) (n<<12) /* USB Host clock mux input select */
-#define SCS_MUD(n) (n<<7) /* USB Device clock mux input select */
-#define SCS_MEx_AUX 0x1 /* Aux clock */
-#define SCS_MEx_FREQ0 0x2 /* FREQ0 */
-#define SCS_MEx_FREQ1 0x3 /* FREQ1 */
-#define SCS_MEx_FREQ2 0x4 /* FREQ2 */
-#define SCS_MEx_FREQ3 0x5 /* FREQ3 */
-#define SCS_MEx_FREQ4 0x6 /* FREQ4 */
-#define SCS_MEx_FREQ5 0x7 /* FREQ5 */
-#define SCS_DE1 (1<<26) /* EXTCLK1 clock divider select */
-#define SCS_CE1 (1<<25) /* EXTCLK1 clock select */
-#define SCS_DE0 (1<<21) /* EXTCLK0 clock divider select */
-#define SCS_CE0 (1<<20) /* EXTCLK0 clock select */
-#define SCS_DPC (1<<16) /* PCI clock divider select */
-#define SCS_CPC (1<<15) /* PCI clock select */
-#define SCS_DUH (1<<11) /* USB Host clock divider select */
-#define SCS_CUH (1<<10) /* USB Host clock select */
-#define SCS_DUD (1<<6) /* USB Device clock divider select */
-#define SCS_CUD (1<<5) /* USB Device clock select */
-/*
- * Au1550 bits, needed for PSCs. Note that some bits collide with
- * earlier parts. On Au1550, USB clocks (both device and host) are
- * shared with PSC2, and must be configured for 48MHz. DBAU1550 YAMON
- * does this by default. Also, EXTCLK0 is shared with PSC3. DBAU1550
- * YAMON does not configure any clocks besides PSC2.
- */
-#define SCS_MP3(n) (n<<22) /* psc3_intclock mux */
-#define SCS_DP3 (1<<21) /* psc3_intclock divider */
-#define SCS_CP3 (1<<20) /* psc3_intclock select */
-#define SCS_MP1(n) (n<<12) /* psc1_intclock mux */
-#define SCS_DP1 (1<<11) /* psc1_intclock divider */
-#define SCS_CP1 (1<<10) /* psc1_intclock select */
-#define SCS_MP0(n) (n<<7) /* psc0_intclock mux */
-#define SCS_DP0 (1<<6) /* psc0_intclock divider */
-#define SCS_CP0 (1<<5) /* psc0_intclock seelct */
-#define SCS_MP2(n) (n<<2) /* psc2_intclock mux */
-#define SCS_DP2 (1<<1) /* psc2_intclock divider */
-#define SCS_CP2 (1<<0) /* psc2_intclock select */
-
-/************************************************************************/
-/*************************** PIN Function *****************************/
-/************************************************************************/
-
-#define SYS_PINFUNC (SYS_BASE + 0x2c)
-#define SPF_PSC3_MASK (7<<20)
-#define SPF_PSC3_AC97 (0<<17) /* select AC97/SPI */
-#define SPF_PSC3_I2S (1<<17) /* select I2S */
-#define SPF_PSC3_SMBUS (3<<17) /* select SMbus */
-#define SPF_PSC3_GPIO (7<<17) /* select gpio215:211 */
-#define SPF_PSC2_MASK (7<<17)
-#define SPF_PSC2_AC97 (0<<17) /* select AC97/SPI */
-#define SPF_PSC2_I2S (1<<17) /* select I2S */
-#define SPF_PSC2_SMBUS (3<<17) /* select SMbus */
-#define SPF_PSC2_GPIO (7<<17) /* select gpio210:206*/
-#define SPF_CS (1<<16) /* extclk0 or 32kHz osc */
-#define SPF_USB (1<<15) /* host or device usb otg */
-#define SPF_U3T (1<<14) /* uart3 tx or gpio23 */
-#define SPF_U1R (1<<13) /* uart1 rx or gpio22 */
-#define SPF_U1T (1<<12) /* uart1 tx or gpio21 */
-#define SPF_EX1 (1<<10) /* gpio3 or extclk1 */
-#define SPF_EX0 (1<<9) /* gpio2 or extclk0/32kHz osc*/
-#define SPF_U3 (1<<7) /* gpio14:9 or uart3 */
-#define SPF_MBSa (1<<5) /* must be set */
-#define SPF_NI2 (1<<4) /* enet1 or gpio28:24 */
-#define SPF_U0 (1<<3) /* uart0 or gpio20 */
-#define SPF_MBSb (1<<2) /* must be set */
-#define SPF_S1 (1<<1) /* gpio17 or psc1_sync1 */
-#define SPF_S0 (1<<0) /* gpio16 or psc0_sync1 */
-
-/************************************************************************/
-/*************************** PLL Control *****************************/
-/************************************************************************/
-
-#define SYS_CPUPLL (SYS_BASE + 0x60)
-#define SYS_AUXPLL (SYS_BASE + 0x64)
-
-#endif /* _MIPS_ALCHEMY_AUREG_H */
diff --git a/sys/mips/alchemy/files.alchemy b/sys/mips/alchemy/files.alchemy
deleted file mode 100644
index 8534431..0000000
--- a/sys/mips/alchemy/files.alchemy
+++ /dev/null
@@ -1,7 +0,0 @@
-# $FreeBSD$
-# Alchmy on-board devices
-# mips/alchemy/console.c standard
-mips/alchemy/alchemy_machdep.c standard
-mips/alchemy/obio.c standard
-mips/alchemy/uart_bus_alchemy.c optional uart
-mips/alchemy/uart_cpu_alchemy.c optional uart
diff --git a/sys/mips/alchemy/obio.c b/sys/mips/alchemy/obio.c
deleted file mode 100644
index 03e098d..0000000
--- a/sys/mips/alchemy/obio.c
+++ /dev/null
@@ -1,501 +0,0 @@
-/* $NetBSD: obio.c,v 1.11 2003/07/15 00:25:05 lukem Exp $ */
-
-/*-
- * Copyright (c) 2001, 2002, 2003 Wasabi Systems, Inc.
- * All rights reserved.
- *
- * Written by Jason R. Thorpe for Wasabi Systems, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed for the NetBSD Project by
- * Wasabi Systems, Inc.
- * 4. The name of Wasabi Systems, Inc. may not be used to endorse
- * or promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/interrupt.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/malloc.h>
-
-#include <machine/bus.h>
-
-#include <mips/adm5120/adm5120reg.h>
-#include <mips/adm5120/obiovar.h>
-
-/* MIPS HW interrupts of IRQ/FIQ respectively */
-#define ADM5120_INTR 0
-#define ADM5120_FAST_INTR 1
-
-/* Interrupt levels */
-#define INTR_IRQ 0
-#define INTR_FIQ 1
-
-int irq_priorities[NIRQS] = {
- INTR_IRQ, /* flash */
- INTR_FIQ, /* uart0 */
- INTR_FIQ, /* uart1 */
- INTR_IRQ, /* ahci */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* admsw */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
- INTR_IRQ, /* unknown */
-};
-
-
-#define REG_READ(o) *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1(ADM5120_BASE_ICU + (o)))
-#define REG_WRITE(o,v) (REG_READ(o)) = (v)
-
-static int obio_activate_resource(device_t, device_t, int, int,
- struct resource *);
-static device_t obio_add_child(device_t, int, const char *, int);
-static struct resource *
- obio_alloc_resource(device_t, device_t, int, int *, u_long,
- u_long, u_long, u_int);
-static int obio_attach(device_t);
-static int obio_deactivate_resource(device_t, device_t, int, int,
- struct resource *);
-static struct resource_list *
- obio_get_resource_list(device_t, device_t);
-static void obio_hinted_child(device_t, const char *, int);
-static int obio_intr(void *);
-static int obio_probe(device_t);
-static int obio_release_resource(device_t, device_t, int, int,
- struct resource *);
-static int obio_setup_intr(device_t, device_t, struct resource *, int,
- driver_filter_t *, driver_intr_t *, void *, void **);
-static int obio_teardown_intr(device_t, device_t, struct resource *,
- void *);
-
-static int
-obio_probe(device_t dev)
-{
-
- return (0);
-}
-
-static int
-obio_attach(device_t dev)
-{
- struct obio_softc *sc = device_get_softc(dev);
- int rid;
-
- sc->oba_mem_rman.rm_type = RMAN_ARRAY;
- sc->oba_mem_rman.rm_descr = "OBIO memeory";
- if (rman_init(&sc->oba_mem_rman) != 0 ||
- rman_manage_region(&sc->oba_mem_rman, OBIO_MEM_START,
- OBIO_MEM_START + OBIO_MEM_SIZE) != 0)
- panic("obio_attach: failed to set up I/O rman");
-
- sc->oba_irq_rman.rm_type = RMAN_ARRAY;
- sc->oba_irq_rman.rm_descr = "OBIO IRQ";
-
- if (rman_init(&sc->oba_irq_rman) != 0 ||
- rman_manage_region(&sc->oba_irq_rman, 0, NIRQS-1) != 0)
- panic("obio_attach: failed to set up IRQ rman");
-
- /* Hook up our interrupt handler. */
- if ((sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
- ADM5120_INTR, ADM5120_INTR, 1,
- RF_SHAREABLE | RF_ACTIVE)) == NULL) {
- device_printf(dev, "unable to allocate IRQ resource\n");
- return (ENXIO);
- }
-
- if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC, obio_intr, NULL,
- sc, &sc->sc_ih))) {
- device_printf(dev,
- "WARNING: unable to register interrupt handler\n");
- return (ENXIO);
- }
-
- /* Hook up our FAST interrupt handler. */
- if ((sc->sc_fast_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
- ADM5120_FAST_INTR, ADM5120_FAST_INTR, 1,
- RF_SHAREABLE | RF_ACTIVE)) == NULL) {
- device_printf(dev, "unable to allocate IRQ resource\n");
- return (ENXIO);
- }
-
- if ((bus_setup_intr(dev, sc->sc_fast_irq, INTR_TYPE_MISC, obio_intr,
- NULL, sc, &sc->sc_fast_ih))) {
- device_printf(dev,
- "WARNING: unable to register interrupt handler\n");
- return (ENXIO);
- }
-
- /* disable all interrupts */
- REG_WRITE(ICU_ENABLE_REG, ICU_INT_MASK);
-
- bus_generic_probe(dev);
- bus_enumerate_hinted_children(dev);
- bus_generic_attach(dev);
-
- return (0);
-}
-
-static struct resource *
-obio_alloc_resource(device_t bus, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
-{
- struct obio_softc *sc = device_get_softc(bus);
- struct obio_ivar *ivar = device_get_ivars(child);
- struct resource *rv;
- struct resource_list_entry *rle;
- struct rman *rm;
- int isdefault, needactivate, passthrough;
-
- isdefault = (start == 0UL && end == ~0UL && count == 1);
- needactivate = flags & RF_ACTIVE;
- passthrough = (device_get_parent(child) != bus);
- rle = NULL;
-
- if (passthrough)
- return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type,
- rid, start, end, count, flags));
-
- /*
- * If this is an allocation of the "default" range for a given RID,
- * and we know what the resources for this device are (ie. they aren't
- * maintained by a child bus), then work out the start/end values.
- */
- if (isdefault) {
- rle = resource_list_find(&ivar->resources, type, *rid);
- if (rle == NULL)
- return (NULL);
- if (rle->res != NULL) {
- panic("%s: resource entry is busy", __func__);
- }
- start = rle->start;
- end = rle->end;
- count = rle->count;
- }
-
- switch (type) {
- case SYS_RES_IRQ:
- rm = &sc->oba_irq_rman;
- break;
- case SYS_RES_MEMORY:
- rm = &sc->oba_mem_rman;
- break;
- default:
- printf("%s: unknown resource type %d\n", __func__, type);
- return (0);
- }
-
- rv = rman_reserve_resource(rm, start, end, count, flags, child);
- if (rv == 0) {
- printf("%s: could not reserve resource\n", __func__);
- return (0);
- }
-
- rman_set_rid(rv, *rid);
-
- if (needactivate) {
- if (bus_activate_resource(child, type, *rid, rv)) {
- printf("%s: could not activate resource\n", __func__);
- rman_release_resource(rv);
- return (0);
- }
- }
-
- return (rv);
-}
-
-static int
-obio_activate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
-{
-
- /*
- * If this is a memory resource, track the direct mapping
- * in the uncached MIPS KSEG1 segment.
- */
- if (type == SYS_RES_MEMORY) {
- void *vaddr;
-
- vaddr = (void *)MIPS_PHYS_TO_KSEG1((intptr_t)rman_get_start(r));
- rman_set_virtual(r, vaddr);
- rman_set_bustag(r, MIPS_BUS_SPACE_MEM);
- rman_set_bushandle(r, (bus_space_handle_t)vaddr);
- }
-
- return (rman_activate_resource(r));
-}
-
-static int
-obio_deactivate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
-{
-
- return (rman_deactivate_resource(r));
-}
-
-static int
-obio_release_resource(device_t dev, device_t child, int type,
- int rid, struct resource *r)
-{
- struct resource_list *rl;
- struct resource_list_entry *rle;
-
- rl = obio_get_resource_list(dev, child);
- if (rl == NULL)
- return (EINVAL);
- rle = resource_list_find(rl, type, rid);
- if (rle == NULL)
- return (EINVAL);
- rman_release_resource(r);
- rle->res = NULL;
-
- return (0);
-}
-
-static int
-obio_setup_intr(device_t dev, device_t child, struct resource *ires,
- int flags, driver_filter_t *filt, driver_intr_t *handler,
- void *arg, void **cookiep)
-{
- struct obio_softc *sc = device_get_softc(dev);
- struct intr_event *event;
- int irq, error, priority;
- uint32_t irqmask;
-
- irq = rman_get_start(ires);
-
- if (irq >= NIRQS)
- panic("%s: bad irq %d", __func__, irq);
-
- event = sc->sc_eventstab[irq];
- if (event == NULL) {
- error = intr_event_create(&event, (void *)irq, 0, irq,
- (mask_fn)mips_mask_irq, (mask_fn)mips_unmask_irq,
- NULL, NULL, "obio intr%d:", irq);
-
- sc->sc_eventstab[irq] = event;
- }
- else
- panic("obio: Can't share IRQs");
-
- intr_event_add_handler(event, device_get_nameunit(child), filt,
- handler, arg, intr_priority(flags), flags, cookiep);
-
- irqmask = 1 << irq;
- priority = irq_priorities[irq];
-
- if (priority == INTR_FIQ)
- REG_WRITE(ICU_MODE_REG, REG_READ(ICU_MODE_REG) | irqmask);
- else
- REG_WRITE(ICU_MODE_REG, REG_READ(ICU_MODE_REG) & ~irqmask);
-
- /* enable */
- REG_WRITE(ICU_ENABLE_REG, irqmask);
-
- return (0);
-}
-
-static int
-obio_teardown_intr(device_t dev, device_t child, struct resource *ires,
- void *cookie)
-{
- struct obio_softc *sc = device_get_softc(dev);
- int irq, result;
- uint32_t irqmask;
-
- irq = rman_get_start(ires);
- if (irq >= NIRQS)
- panic("%s: bad irq %d", __func__, irq);
-
- if (sc->sc_eventstab[irq] == NULL)
- panic("Trying to teardown unoccupied IRQ");
-
- irqmask = 1 << irq; /* only used as a mask from here on */
-
- /* disable this irq in HW */
- REG_WRITE(ICU_DISABLE_REG, irqmask);
-
- result = intr_event_remove_handler(cookie);
- if (!result) {
- sc->sc_eventstab[irq] = NULL;
- }
-
- return (result);
-}
-
-static int
-obio_intr(void *arg)
-{
- struct obio_softc *sc = arg;
- struct intr_event *event;
- uint32_t irqstat;
- int irq;
-
- irqstat = REG_READ(ICU_FIQ_STATUS_REG);
- irqstat |= REG_READ(ICU_STATUS_REG);
-
- irq = 0;
- while (irqstat != 0) {
- if ((irqstat & 1) == 1) {
- event = sc->sc_eventstab[irq];
- if (!event || TAILQ_EMPTY(&event->ie_handlers))
- continue;
-
- /* TODO: pass frame as an argument*/
- /* TODO: log stray interrupt */
- intr_event_handle(event, NULL);
- }
-
- irq++;
- irqstat >>= 1;
- }
-
- return (FILTER_HANDLED);
-}
-
-static void
-obio_hinted_child(device_t bus, const char *dname, int dunit)
-{
- device_t child;
- long maddr;
- int msize;
- int irq;
- int result;
-
- child = BUS_ADD_CHILD(bus, 0, dname, dunit);
-
- /*
- * Set hard-wired resources for hinted child using
- * specific RIDs.
- */
- resource_long_value(dname, dunit, "maddr", &maddr);
- resource_int_value(dname, dunit, "msize", &msize);
-
-
- result = bus_set_resource(child, SYS_RES_MEMORY, 0,
- maddr, msize);
- if (result != 0)
- device_printf(bus, "warning: bus_set_resource() failed\n");
-
- if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
- result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
- if (result != 0)
- device_printf(bus,
- "warning: bus_set_resource() failed\n");
- }
-}
-
-static device_t
-obio_add_child(device_t bus, int order, const char *name, int unit)
-{
- device_t child;
- struct obio_ivar *ivar;
-
- ivar = malloc(sizeof(struct obio_ivar), M_DEVBUF, M_WAITOK | M_ZERO);
- if (ivar == NULL) {
- printf("Failed to allocate ivar\n");
- return (0);
- }
- resource_list_init(&ivar->resources);
-
- child = device_add_child_ordered(bus, order, name, unit);
- if (child == NULL) {
- printf("Can't add child %s%d ordered\n", name, unit);
- return (0);
- }
-
- device_set_ivars(child, ivar);
-
- return (child);
-}
-
-/*
- * Helper routine for bus_generic_rl_get_resource/bus_generic_rl_set_resource
- * Provides pointer to resource_list for these routines
- */
-static struct resource_list *
-obio_get_resource_list(device_t dev, device_t child)
-{
- struct obio_ivar *ivar;
-
- ivar = device_get_ivars(child);
- return (&(ivar->resources));
-}
-
-static device_method_t obio_methods[] = {
- DEVMETHOD(bus_activate_resource, obio_activate_resource),
- DEVMETHOD(bus_add_child, obio_add_child),
- DEVMETHOD(bus_alloc_resource, obio_alloc_resource),
- DEVMETHOD(bus_deactivate_resource, obio_deactivate_resource),
- DEVMETHOD(bus_get_resource_list, obio_get_resource_list),
- DEVMETHOD(bus_hinted_child, obio_hinted_child),
- DEVMETHOD(bus_release_resource, obio_release_resource),
- DEVMETHOD(bus_setup_intr, obio_setup_intr),
- DEVMETHOD(bus_teardown_intr, obio_teardown_intr),
- DEVMETHOD(device_attach, obio_attach),
- DEVMETHOD(device_probe, obio_probe),
- DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
- DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
-
- {0, 0},
-};
-
-static driver_t obio_driver = {
- "obio",
- obio_methods,
- sizeof(struct obio_softc),
-};
-static devclass_t obio_devclass;
-
-DRIVER_MODULE(obio, nexus, obio_driver, obio_devclass, 0, 0);
diff --git a/sys/mips/alchemy/std.alchemy b/sys/mips/alchemy/std.alchemy
deleted file mode 100644
index a955b67..0000000
--- a/sys/mips/alchemy/std.alchemy
+++ /dev/null
@@ -1,8 +0,0 @@
-# $FreeBSD$
-# Standard include file for Alchemy Au1xxx CPUs:
-# Au1000, Au1200, Au1250, Au1500 and Au1550
-
-files "../alchemy/files.alchemy"
-
-cpu CPU_MIPS4KC
-options ISA_MIPS32
diff --git a/sys/mips/alchemy/uart_bus_alchemy.c b/sys/mips/alchemy/uart_bus_alchemy.c
deleted file mode 100644
index 5c2315b..0000000
--- a/sys/mips/alchemy/uart_bus_alchemy.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*-
- * Copyright (c) 2007 Bruce M. Simpson.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * $Id$
- */
-/*
- * Skeleton of this file was based on respective code for ARM
- * code written by Olivier Houchard.
- */
-
-#include "opt_uart.h"
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <machine/bus.h>
-#include <sys/rman.h>
-#include <machine/resource.h>
-
-#include <dev/pci/pcivar.h>
-
-#include <dev/uart/uart.h>
-#include <dev/uart/uart_bus.h>
-#include <dev/uart/uart_cpu.h>
-
-#include <mips/alchemy/aureg.h>
-
-#include "uart_if.h"
-
-static int uart_alchemy_probe(device_t dev);
-
-static device_method_t uart_alchemy_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, uart_alchemy_probe),
- DEVMETHOD(device_attach, uart_bus_attach),
- DEVMETHOD(device_detach, uart_bus_detach),
- { 0, 0 }
-};
-
-static driver_t uart_alchemy_driver = {
- uart_driver_name,
- uart_alchemy_methods,
- sizeof(struct uart_softc),
-};
-
-extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
-
-static int
-uart_alchemy_probe(device_t dev)
-{
- struct uart_softc *sc;
-
- sc = device_get_softc(dev);
- sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
- sc->sc_class = &uart_ns8250_class;
- bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
-
- return (uart_bus_probe(dev, 0, 0, 0, 0));
-}
-
-DRIVER_MODULE(uart, obio, uart_alchemy_driver, uart_devclass, 0, 0);
diff --git a/sys/mips/atheros/apb.c b/sys/mips/atheros/apb.c
deleted file mode 100644
index d53408c..0000000
--- a/sys/mips/atheros/apb.c
+++ /dev/null
@@ -1,433 +0,0 @@
-/*-
- * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice unmodified, 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/systm.h>
-#include <sys/bus.h>
-#include <sys/interrupt.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-#include <sys/malloc.h>
-
-#include <machine/bus.h>
-
-#include <mips/atheros/apbvar.h>
-#include <mips/atheros/ar71xxreg.h>
-
-#undef APB_DEBUG
-#ifdef APB_DEBUG
-#define dprintf printf
-#else
-#define dprintf(x, arg...)
-#endif /* APB_DEBUG */
-
-static int apb_activate_resource(device_t, device_t, int, int,
- struct resource *);
-static device_t apb_add_child(device_t, int, const char *, int);
-static struct resource *
- apb_alloc_resource(device_t, device_t, int, int *, u_long,
- u_long, u_long, u_int);
-static int apb_attach(device_t);
-static int apb_deactivate_resource(device_t, device_t, int, int,
- struct resource *);
-static struct resource_list *
- apb_get_resource_list(device_t, device_t);
-static void apb_hinted_child(device_t, const char *, int);
-static int apb_intr(void *);
-static int apb_probe(device_t);
-static int apb_release_resource(device_t, device_t, int, int,
- struct resource *);
-static int apb_setup_intr(device_t, device_t, struct resource *, int,
- driver_filter_t *, driver_intr_t *, void *, void **);
-static int apb_teardown_intr(device_t, device_t, struct resource *,
- void *);
-
-static void apb_mask_irq(unsigned int irq)
-{
- uint32_t reg;
-
- reg = ATH_READ_REG(AR71XX_MISC_INTR_MASK);
- ATH_WRITE_REG(AR71XX_MISC_INTR_MASK, reg & ~(1 << irq));
-
-}
-
-static void apb_unmask_irq(unsigned int irq)
-{
- uint32_t reg;
-
- reg = ATH_READ_REG(AR71XX_MISC_INTR_MASK);
- ATH_WRITE_REG(AR71XX_MISC_INTR_MASK, reg | (1 << irq));
-}
-
-static int
-apb_probe(device_t dev)
-{
-
- return (0);
-}
-
-static int
-apb_attach(device_t dev)
-{
- struct apb_softc *sc = device_get_softc(dev);
- int rid = 0;
-
- device_set_desc(dev, "APB Bus bridge");
- sc->apb_irq_rman.rm_type = RMAN_ARRAY;
- sc->apb_irq_rman.rm_descr = "APB IRQ";
-
- if (rman_init(&sc->apb_irq_rman) != 0 ||
- rman_manage_region(&sc->apb_irq_rman,
- APB_IRQ_BASE, APB_IRQ_END) != 0)
- panic("apb_attach: failed to set up IRQ rman");
-
- if ((sc->sc_misc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE)) == NULL) {
- device_printf(dev, "unable to allocate IRQ resource\n");
- return (ENXIO);
- }
-
- if ((bus_setup_intr(dev, sc->sc_misc_irq, INTR_TYPE_MISC,
- apb_intr, NULL, sc, &sc->sc_misc_ih))) {
- device_printf(dev,
- "WARNING: unable to register interrupt handler\n");
- return (ENXIO);
- }
-
- bus_generic_probe(dev);
- bus_enumerate_hinted_children(dev);
- bus_generic_attach(dev);
-
- return (0);
-}
-
-static struct resource *
-apb_alloc_resource(device_t bus, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
-{
- struct apb_softc *sc = device_get_softc(bus);
- struct apb_ivar *ivar = device_get_ivars(child);
- struct resource *rv;
- struct resource_list_entry *rle;
- struct rman *rm;
- int isdefault, needactivate, passthrough;
-
- isdefault = (start == 0UL && end == ~0UL);
- needactivate = flags & RF_ACTIVE;
- /*
- * Pass memory requests to nexus device
- */
- passthrough = (device_get_parent(child) != bus) ||
- (type == SYS_RES_MEMORY);
- rle = NULL;
-
- dprintf("%s: entry (%p, %p, %d, %p, %p, %p, %ld, %d)\n",
- __func__, bus, child, type, rid, (void *)(intptr_t)start,
- (void *)(intptr_t)end, count, flags);
-
- if (passthrough)
- return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type,
- rid, start, end, count, flags));
-
- /*
- * If this is an allocation of the "default" range for a given RID,
- * and we know what the resources for this device are (ie. they aren't
- * maintained by a child bus), then work out the start/end values.
- */
-
- if (isdefault) {
- rle = resource_list_find(&ivar->resources, type, *rid);
- if (rle == NULL) {
- return (NULL);
- }
-
- if (rle->res != NULL) {
- panic("%s: resource entry is busy", __func__);
- }
- start = rle->start;
- end = rle->end;
- count = rle->count;
-
- dprintf("%s: default resource (%p, %p, %ld)\n",
- __func__, (void *)(intptr_t)start,
- (void *)(intptr_t)end, count);
- }
-
- switch (type) {
- case SYS_RES_IRQ:
- rm = &sc->apb_irq_rman;
- break;
- default:
- printf("%s: unknown resource type %d\n", __func__, type);
- return (0);
- }
-
- rv = rman_reserve_resource(rm, start, end, count, flags, child);
- if (rv == 0) {
- printf("%s: could not reserve resource\n", __func__);
- return (0);
- }
-
- rman_set_rid(rv, *rid);
-
- if (needactivate) {
- if (bus_activate_resource(child, type, *rid, rv)) {
- printf("%s: could not activate resource\n", __func__);
- rman_release_resource(rv);
- return (0);
- }
- }
-
- return (rv);
-}
-
-static int
-apb_activate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
-{
-
- /* XXX: should we mask/unmask IRQ here? */
- return (BUS_ACTIVATE_RESOURCE(device_get_parent(bus), child,
- type, rid, r));
-}
-
-static int
-apb_deactivate_resource(device_t bus, device_t child, int type, int rid,
- struct resource *r)
-{
-
- /* XXX: should we mask/unmask IRQ here? */
- return (BUS_DEACTIVATE_RESOURCE(device_get_parent(bus), child,
- type, rid, r));
-}
-
-static int
-apb_release_resource(device_t dev, device_t child, int type,
- int rid, struct resource *r)
-{
- struct resource_list *rl;
- struct resource_list_entry *rle;
-
- rl = apb_get_resource_list(dev, child);
- if (rl == NULL)
- return (EINVAL);
- rle = resource_list_find(rl, type, rid);
- if (rle == NULL)
- return (EINVAL);
- rman_release_resource(r);
- rle->res = NULL;
-
- return (0);
-}
-
-static int
-apb_setup_intr(device_t bus, device_t child, struct resource *ires,
- int flags, driver_filter_t *filt, driver_intr_t *handler,
- void *arg, void **cookiep)
-{
- struct apb_softc *sc = device_get_softc(bus);
- struct intr_event *event;
- int irq, error;
-
- irq = rman_get_start(ires);
-
- if (irq > APB_IRQ_END)
- panic("%s: bad irq %d", __func__, irq);
-
- event = sc->sc_eventstab[irq];
- if (event == NULL) {
- error = intr_event_create(&event, (void *)irq, 0, irq,
- (mask_fn)apb_mask_irq, (mask_fn)apb_unmask_irq,
- NULL, NULL,
- "apb intr%d:", irq);
-
- sc->sc_eventstab[irq] = event;
- }
-
- intr_event_add_handler(event, device_get_nameunit(child), filt,
- handler, arg, intr_priority(flags), flags, cookiep);
-
- return (0);
-}
-
-static int
-apb_teardown_intr(device_t dev, device_t child, struct resource *ires,
- void *cookie)
-{
- struct apb_softc *sc = device_get_softc(dev);
- int irq, result;
-
- irq = rman_get_start(ires);
- if (irq > APB_IRQ_END)
- panic("%s: bad irq %d", __func__, irq);
-
- if (sc->sc_eventstab[irq] == NULL)
- panic("Trying to teardown unoccupied IRQ");
-
- apb_mask_irq(irq);
-
- result = intr_event_remove_handler(cookie);
- if (!result)
- sc->sc_eventstab[irq] = NULL;
-
- return (result);
-}
-
-static int
-apb_intr(void *arg)
-{
- struct apb_softc *sc = arg;
- struct intr_event *event;
- uint32_t reg, irq;
-
- reg = ATH_READ_REG(AR71XX_MISC_INTR_STATUS);
- for (irq = 0; irq < APB_NIRQS; irq++) {
- if (reg & (1 << irq)) {
- event = sc->sc_eventstab[irq];
- if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
- printf("Stray IRQ %d\n", irq);
- continue;
- }
-
- /* TODO: frame instead of NULL? */
- intr_event_handle(event, NULL);
- }
- }
-
- return (FILTER_HANDLED);
-}
-
-static void
-apb_hinted_child(device_t bus, const char *dname, int dunit)
-{
- device_t child;
- long maddr;
- int msize;
- int irq;
- int result;
- int mem_hints_count;
-
- child = BUS_ADD_CHILD(bus, 0, dname, dunit);
-
- /*
- * Set hard-wired resources for hinted child using
- * specific RIDs.
- */
- mem_hints_count = 0;
- if (resource_long_value(dname, dunit, "maddr", &maddr) == 0)
- mem_hints_count++;
- if (resource_int_value(dname, dunit, "msize", &msize) == 0)
- mem_hints_count++;
-
- /* check if all info for mem resource has been provided */
- if ((mem_hints_count > 0) && (mem_hints_count < 2)) {
- printf("Either maddr or msize hint is missing for %s%d\n",
- dname, dunit);
- } else if (mem_hints_count) {
- result = bus_set_resource(child, SYS_RES_MEMORY, 0,
- maddr, msize);
- if (result != 0)
- device_printf(bus,
- "warning: bus_set_resource() failed\n");
- }
-
- if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
- result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
- if (result != 0)
- device_printf(bus,
- "warning: bus_set_resource() failed\n");
- }
-}
-
-static device_t
-apb_add_child(device_t bus, int order, const char *name, int unit)
-{
- device_t child;
- struct apb_ivar *ivar;
-
- ivar = malloc(sizeof(struct apb_ivar), M_DEVBUF, M_WAITOK | M_ZERO);
- if (ivar == NULL) {
- printf("Failed to allocate ivar\n");
- return (0);
- }
- resource_list_init(&ivar->resources);
-
- child = device_add_child_ordered(bus, order, name, unit);
- if (child == NULL) {
- printf("Can't add child %s%d ordered\n", name, unit);
- return (0);
- }
-
- device_set_ivars(child, ivar);
-
- return (child);
-}
-
-/*
- * Helper routine for bus_generic_rl_get_resource/bus_generic_rl_set_resource
- * Provides pointer to resource_list for these routines
- */
-static struct resource_list *
-apb_get_resource_list(device_t dev, device_t child)
-{
- struct apb_ivar *ivar;
-
- ivar = device_get_ivars(child);
- return (&(ivar->resources));
-}
-
-static device_method_t apb_methods[] = {
- DEVMETHOD(bus_activate_resource, apb_activate_resource),
- DEVMETHOD(bus_add_child, apb_add_child),
- DEVMETHOD(bus_alloc_resource, apb_alloc_resource),
- DEVMETHOD(bus_deactivate_resource, apb_deactivate_resource),
- DEVMETHOD(bus_get_resource_list, apb_get_resource_list),
- DEVMETHOD(bus_hinted_child, apb_hinted_child),
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_release_resource, apb_release_resource),
- DEVMETHOD(bus_setup_intr, apb_setup_intr),
- DEVMETHOD(bus_teardown_intr, apb_teardown_intr),
- DEVMETHOD(device_attach, apb_attach),
- DEVMETHOD(device_probe, apb_probe),
- DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
- DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
-
- {0, 0},
-};
-
-static driver_t apb_driver = {
- "apb",
- apb_methods,
- sizeof(struct apb_softc),
-};
-static devclass_t apb_devclass;
-
-DRIVER_MODULE(apb, nexus, apb_driver, apb_devclass, 0, 0);
diff --git a/sys/mips/atheros/ar71xx_machdep.c b/sys/mips/atheros/ar71xx_machdep.c
deleted file mode 100644
index a5699ed..0000000
--- a/sys/mips/atheros/ar71xx_machdep.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/*-
- * Copyright (c) 2009 Oleksandr Tymoshenko
- * 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.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <machine/cpuregs.h>
-
-#include <mips/sentry5/s5reg.h>
-
-#include "opt_ddb.h"
-
-#include <sys/param.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/cons.h>
-#include <sys/kdb.h>
-
-#include <vm/vm.h>
-#include <vm/vm_page.h>
-
-#include <machine/clock.h>
-#include <machine/cpu.h>
-#include <machine/hwfunc.h>
-#include <machine/md_var.h>
-#include <machine/trap.h>
-#include <machine/vmparam.h>
-
-#include <mips/atheros/ar71xxreg.h>
-
-extern int *edata;
-extern int *end;
-
-void
-platform_halt(void)
-{
-
-}
-
-void
-platform_identify(void)
-{
-
-}
-
-void
-platform_reset(void)
-{
- uint32_t reg = ATH_READ_REG(AR71XX_RST_RESET);
-
- ATH_WRITE_REG(AR71XX_RST_RESET, reg | RST_RESET_FULL_CHIP);
- /* Wait for reset */
- while(1)
- ;
-}
-
-void
-platform_trap_enter(void)
-{
-
-}
-
-void
-platform_trap_exit(void)
-{
-
-}
-
-void
-platform_start(__register_t a0 __unused, __register_t a1 __unused,
- __register_t a2 __unused, __register_t a3 __unused)
-{
- vm_offset_t kernend;
- uint64_t platform_counter_freq;
- uint32_t reg;
-
- /* clear the BSS and SBSS segments */
- kernend = round_page((vm_offset_t)&end);
- memset(&edata, 0, kernend - (vm_offset_t)(&edata));
-
- /* TODO: Get available memory from RedBoot. Is it possible? */
- realmem = btoc(64*1024*1024);
- /* phys_avail regions are in bytes */
- phys_avail[0] = MIPS_KSEG0_TO_PHYS((vm_offset_t)&end);
- phys_avail[1] = ctob(realmem);
-
- physmem = realmem;
-
- /*
- * ns8250 uart code uses DELAY so ticker should be inititalized
- * before cninit. And tick_init_params refers to hz, so * init_param1
- * should be called first.
- */
- init_param1();
- /* TODO: Get CPU freq from RedBoot. Is it possible? */
- platform_counter_freq = 680000000UL;
- mips_timer_init_params(platform_counter_freq, 0);
- cninit();
-
- printf("arguments: \n");
- printf(" a0 = %08x\n", a0);
- printf(" a1 = %08x\n", a1);
- printf(" a2 = %08x\n", a2);
- printf(" a3 = %08x\n", a3);
-
- init_param2(physmem);
- mips_cpu_init();
- pmap_bootstrap();
- mips_proc0_init();
- mutex_init();
-
- /*
- * Reset USB devices
- */
- reg = ATH_READ_REG(AR71XX_RST_RESET);
- reg |=
- RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY;
- ATH_WRITE_REG(AR71XX_RST_RESET, reg);
- DELAY(1000);
- reg &=
- ~(RST_RESET_USB_OHCI_DLL | RST_RESET_USB_HOST | RST_RESET_USB_PHY);
- ATH_WRITE_REG(AR71XX_RST_RESET, reg);
-
- ATH_WRITE_REG(AR71XX_USB_CTRL_CONFIG,
- USB_CTRL_CONFIG_OHCI_DES_SWAP | USB_CTRL_CONFIG_OHCI_BUF_SWAP |
- USB_CTRL_CONFIG_EHCI_DES_SWAP | USB_CTRL_CONFIG_EHCI_BUF_SWAP);
-
- ATH_WRITE_REG(AR71XX_USB_CTRL_FLADJ,
- (32 << USB_CTRL_FLADJ_HOST_SHIFT) | (3 << USB_CTRL_FLADJ_A5_SHIFT));
- DELAY(1000);
-
-#ifdef DDB
- kdb_init();
-#endif
-}
diff --git a/sys/mips/atheros/ar71xx_ohci.c b/sys/mips/atheros/ar71xx_ohci.c
deleted file mode 100644
index b7adc61..0000000
--- a/sys/mips/atheros/ar71xx_ohci.c
+++ /dev/null
@@ -1,205 +0,0 @@
-/*-
- * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice unmodified, 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/systm.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-#include <sys/bus.h>
-#include <sys/queue.h>
-#include <machine/bus.h>
-#include <sys/rman.h>
-#include <machine/resource.h>
-
-#include <dev/usb/usb.h>
-#include <dev/usb/usbdi.h>
-#include <dev/usb/usbdivar.h>
-#include <dev/usb/usb_mem.h>
-
-#include <dev/usb/ohcireg.h>
-#include <dev/usb/ohcivar.h>
-
-static int ar71xx_ohci_attach(device_t dev);
-static int ar71xx_ohci_detach(device_t dev);
-static int ar71xx_ohci_probe(device_t dev);
-
-struct ar71xx_ohci_softc
-{
- struct ohci_softc sc_ohci;
-};
-
-static int
-ar71xx_ohci_probe(device_t dev)
-{
- device_set_desc(dev, "AR71XX integrated OHCI controller");
- return (BUS_PROBE_DEFAULT);
-}
-
-static int
-ar71xx_ohci_attach(device_t dev)
-{
- struct ar71xx_ohci_softc *sc = device_get_softc(dev);
- int err;
- int rid;
-
- rid = 0;
- sc->sc_ohci.io_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
- RF_ACTIVE);
- if (sc->sc_ohci.io_res == NULL) {
- err = ENOMEM;
- goto error;
- }
- sc->sc_ohci.iot = rman_get_bustag(sc->sc_ohci.io_res);
- sc->sc_ohci.ioh = rman_get_bushandle(sc->sc_ohci.io_res);
-
- rid = 0;
- sc->sc_ohci.irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_ACTIVE);
- if (sc->sc_ohci.irq_res == NULL) {
- err = ENOMEM;
- goto error;
- }
- sc->sc_ohci.sc_bus.bdev = device_add_child(dev, "usb", -1);
- if (sc->sc_ohci.sc_bus.bdev == NULL) {
- err = ENOMEM;
- goto error;
- }
- device_set_ivars(sc->sc_ohci.sc_bus.bdev, &sc->sc_ohci.sc_bus);
-
- /* Allocate a parent dma tag for DMA maps */
- err = bus_dma_tag_create(bus_get_dma_tag(dev), 1, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
- BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
- NULL, NULL, &sc->sc_ohci.sc_bus.parent_dmatag);
- if (err) {
- device_printf(dev, "Could not allocate parent DMA tag (%d)\n",
- err);
- err = ENXIO;
- goto error;
- }
-
- /* Allocate a dma tag for transfer buffers */
- err = bus_dma_tag_create(sc->sc_ohci.sc_bus.parent_dmatag, 1, 0,
- BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
- BUS_SPACE_MAXSIZE_32BIT, USB_DMA_NSEG, BUS_SPACE_MAXSIZE_32BIT, 0,
- busdma_lock_mutex, &Giant, &sc->sc_ohci.sc_bus.buffer_dmatag);
- if (err) {
- device_printf(dev, "Could not allocate transfer tag (%d)\n",
- err);
- err = ENXIO;
- goto error;
- }
-
- err = bus_setup_intr(dev, sc->sc_ohci.irq_res, INTR_TYPE_BIO, NULL,
- ohci_intr, sc, &sc->sc_ohci.ih);
- if (err) {
- err = ENXIO;
- goto error;
- }
- strlcpy(sc->sc_ohci.sc_vendor, "Atheros",
- sizeof(sc->sc_ohci.sc_vendor));
-
- bus_space_write_4(sc->sc_ohci.iot, sc->sc_ohci.ioh, OHCI_CONTROL, 0);
-
- err = ohci_init(&sc->sc_ohci);
- if (!err) {
- sc->sc_ohci.sc_flags |= OHCI_SCFLG_DONEINIT;
- err = device_probe_and_attach(sc->sc_ohci.sc_bus.bdev);
- }
-
-error:
- if (err) {
- ar71xx_ohci_detach(dev);
- return (err);
- }
- return (err);
-}
-
-static int
-ar71xx_ohci_detach(device_t dev)
-{
- struct ar71xx_ohci_softc *sc = device_get_softc(dev);
-
- if (sc->sc_ohci.sc_flags & OHCI_SCFLG_DONEINIT) {
- ohci_detach(&sc->sc_ohci, 0);
- sc->sc_ohci.sc_flags &= ~OHCI_SCFLG_DONEINIT;
- }
-
- if (sc->sc_ohci.ih) {
- bus_teardown_intr(dev, sc->sc_ohci.irq_res, sc->sc_ohci.ih);
- sc->sc_ohci.ih = NULL;
- }
-
- if (sc->sc_ohci.sc_bus.parent_dmatag != NULL)
- bus_dma_tag_destroy(sc->sc_ohci.sc_bus.parent_dmatag);
- if (sc->sc_ohci.sc_bus.buffer_dmatag != NULL)
- bus_dma_tag_destroy(sc->sc_ohci.sc_bus.buffer_dmatag);
-
- if (sc->sc_ohci.sc_bus.bdev) {
- device_delete_child(dev, sc->sc_ohci.sc_bus.bdev);
- sc->sc_ohci.sc_bus.bdev = NULL;
- }
- if (sc->sc_ohci.irq_res) {
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_ohci.irq_res);
- sc->sc_ohci.irq_res = NULL;
- }
- if (sc->sc_ohci.io_res) {
- bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_ohci.io_res);
- sc->sc_ohci.io_res = NULL;
- sc->sc_ohci.iot = 0;
- sc->sc_ohci.ioh = 0;
- }
- return (0);
-}
-
-static device_method_t ohci_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, ar71xx_ohci_probe),
- DEVMETHOD(device_attach, ar71xx_ohci_attach),
- DEVMETHOD(device_detach, ar71xx_ohci_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- {0, 0}
-};
-
-static driver_t ohci_driver = {
- "ohci",
- ohci_methods,
- sizeof(struct ar71xx_ohci_softc),
-};
-
-static devclass_t ohci_devclass;
-
-DRIVER_MODULE(ohci, apb, ohci_driver, ohci_devclass, 0, 0);
diff --git a/sys/mips/atheros/ar71xx_pci.c b/sys/mips/atheros/ar71xx_pci.c
deleted file mode 100644
index d3a9295..0000000
--- a/sys/mips/atheros/ar71xx_pci.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/*-
- * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice unmodified, 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/systm.h>
-
-#include <sys/bus.h>
-#include <sys/interrupt.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/rman.h>
-
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_extern.h>
-
-#include <machine/bus.h>
-#include <machine/cpu.h>
-#include <machine/pmap.h>
-
-#include <dev/pci/pcivar.h>
-#include <dev/pci/pcireg.h>
-
-#include <dev/pci/pcib_private.h>
-#include "pcib_if.h"
-
-#include "mips/atheros/ar71xxreg.h"
-
-#undef AR71XX_PCI_DEBUG
-#ifdef AR71XX_PCI_DEBUG
-#define dprintf printf
-#else
-#define dprintf(x, arg...)
-#endif
-
-struct ar71xx_pci_softc {
- device_t sc_dev;
-
- int sc_busno;
- struct rman sc_mem_rman;
- struct rman sc_irq_rman;
-
- struct resource *sc_irq;
- void *sc_ih;
-};
-
-/*
- * get bitmask for bytes of interest:
- * 0 - we want this byte, 1 - ignore it. e.g: we read 1 byte
- * from register 7. Bitmask would be: 0111
- */
-static uint32_t
-ar71xx_get_bytes_to_read(int reg, int bytes)
-{
- uint32_t bytes_to_read = 0;
- if ((bytes % 4) == 0)
- bytes_to_read = 0;
- else if ((bytes % 4) == 1)
- bytes_to_read = (~(1 << (reg % 4))) & 0xf;
- else if ((bytes % 4) == 2)
- bytes_to_read = (~(3 << (reg % 4))) & 0xf;
- else
- panic("%s: wrong combination", __func__);
-
- return (bytes_to_read);
-}
-
-static int
-ar71xx_pci_check_bus_error(void)
-{
- uint32_t error, addr, has_errors = 0;
- error = ATH_READ_REG(AR71XX_PCI_ERROR) & 0x3;
- dprintf("%s: PCI error = %02x\n", __func__, error);
- if (error) {
- addr = ATH_READ_REG(AR71XX_PCI_ERROR_ADDR);
-
- /* Do not report it yet */
-#if 0
- printf("PCI bus error %d at addr 0x%08x\n", error, addr);
-#endif
- ATH_WRITE_REG(AR71XX_PCI_ERROR, error);
- has_errors = 1;
- }
-
- error = ATH_READ_REG(AR71XX_PCI_AHB_ERROR) & 0x1;
- dprintf("%s: AHB error = %02x\n", __func__, error);
- if (error) {
- addr = ATH_READ_REG(AR71XX_PCI_AHB_ERROR_ADDR);
- /* Do not report it yet */
-#if 0
- printf("AHB bus error %d at addr 0x%08x\n", error, addr);
-#endif
- ATH_WRITE_REG(AR71XX_PCI_AHB_ERROR, error);
- has_errors = 1;
- }
-
- return (has_errors);
-}
-
-static uint32_t
-ar71xx_pci_make_addr(int bus, int slot, int func, int reg)
-{
- if (bus == 0) {
- return ((1 << slot) | (func << 8) | (reg & ~3));
- } else {
- return ((bus << 16) | (slot << 11) | (func << 8)
- | (reg & ~3) | 1);
- }
-}
-
-static int
-ar71xx_pci_conf_setup(int bus, int slot, int func, int reg, int bytes,
- uint32_t cmd)
-{
- uint32_t addr = ar71xx_pci_make_addr(bus, slot, func, (reg & ~3));
- cmd |= (ar71xx_get_bytes_to_read(reg, bytes) << 4);
-
- ATH_WRITE_REG(AR71XX_PCI_CONF_ADDR, addr);
- ATH_WRITE_REG(AR71XX_PCI_CONF_CMD, cmd);
-
- dprintf("%s: tag (%x, %x, %x) %d/%d addr=%08x, cmd=%08x\n", __func__,
- bus, slot, func, reg, bytes, addr, cmd);
-
- return ar71xx_pci_check_bus_error();
-}
-
-static uint32_t
-ar71xx_pci_read_config(device_t dev, int bus, int slot, int func, int reg,
- int bytes)
-{
- uint32_t data;
- uint32_t cmd, shift, mask;
-
- /* register access is 32-bit aligned */
- shift = (reg & 3) * 8;
- if (shift)
- mask = (1 << shift) - 1;
- else
- mask = 0xffffffff;
-
- dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot,
- func, reg, bytes);
-
- if ((bus == 0) && (slot == 0) && (func == 0)) {
- cmd = PCI_LCONF_CMD_READ | (reg & ~3);
- ATH_WRITE_REG(AR71XX_PCI_LCONF_CMD, cmd);
- data = ATH_READ_REG(AR71XX_PCI_LCONF_READ_DATA);
- } else {
- if (ar71xx_pci_conf_setup(bus, slot, func, reg, bytes,
- PCI_CONF_CMD_READ) == 0)
- data = ATH_READ_REG(AR71XX_PCI_CONF_READ_DATA);
- else
- data = -1;
- }
-
- /* get request bytes from 32-bit word */
- data = (data >> shift) & mask;
-
- dprintf("%s: read 0x%x\n", __func__, data);
-
- return (data);
-}
-
-static void
-ar71xx_pci_write_config(device_t dev, int bus, int slot, int func, int reg,
- uint32_t data, int bytes)
-{
- uint32_t cmd;
-
- dprintf("%s: tag (%x, %x, %x) reg %d(%d)\n", __func__, bus, slot,
- func, reg, bytes);
-
- data = data << (8*(reg % 4));
-
- if ((bus == 0) && (slot == 0) && (func == 0)) {
- cmd = PCI_LCONF_CMD_WRITE | (reg & ~3);
- cmd |= ar71xx_get_bytes_to_read(reg, bytes) << 20;
- ATH_WRITE_REG(AR71XX_PCI_LCONF_CMD, cmd);
- ATH_WRITE_REG(AR71XX_PCI_LCONF_WRITE_DATA, data);
- } else {
- if (ar71xx_pci_conf_setup(bus, slot, func, reg, bytes,
- PCI_CONF_CMD_WRITE) == 0)
- ATH_WRITE_REG(AR71XX_PCI_CONF_WRITE_DATA, data);
- }
-}
-
-static int
-at71xx_pci_intr(void *v)
-{
- panic("Implement me: %s\n", __func__);
- return FILTER_HANDLED;
-}
-
-static int
-ar71xx_pci_probe(device_t dev)
-{
-
- return (0);
-}
-
-static int
-ar71xx_pci_attach(device_t dev)
-{
- int busno = 0;
- int rid = 0;
- uint32_t reset;
- struct ar71xx_pci_softc *sc = device_get_softc(dev);
-
- sc->sc_mem_rman.rm_type = RMAN_ARRAY;
- sc->sc_mem_rman.rm_descr = "ar71xx PCI memory window";
- if (rman_init(&sc->sc_mem_rman) != 0 ||
- rman_manage_region(&sc->sc_mem_rman, AR71XX_PCI_MEM_BASE,
- AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1) != 0) {
- panic("ar71xx_pci_attach: failed to set up I/O rman");
- }
-
- sc->sc_irq_rman.rm_type = RMAN_ARRAY;
- sc->sc_irq_rman.rm_descr = "ar71xx PCI IRQs";
- if (rman_init(&sc->sc_irq_rman) != 0 ||
- rman_manage_region(&sc->sc_irq_rman, AR71XX_PCI_IRQ_START,
- AR71XX_PCI_IRQ_END) != 0)
- panic("ar71xx_pci_attach: failed to set up IRQ rman");
-
-
- ATH_WRITE_REG(AR71XX_PCI_INTR_STATUS, 0);
- ATH_WRITE_REG(AR71XX_PCI_INTR_MASK, 0);
-
- /* Hook up our interrupt handler. */
- if ((sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE)) == NULL) {
- device_printf(dev, "unable to allocate IRQ resource\n");
- return ENXIO;
- }
-
- if ((bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC,
- at71xx_pci_intr, NULL, sc, &sc->sc_ih))) {
- device_printf(dev,
- "WARNING: unable to register interrupt handler\n");
- return ENXIO;
- }
-
- /* reset PCI core and PCI bus */
- reset = ATH_READ_REG(AR71XX_RST_RESET);
- reset |= (RST_RESET_PCI_CORE | RST_RESET_PCI_BUS);
- ATH_WRITE_REG(AR71XX_RST_RESET, reset);
- DELAY(1000);
-
- reset &= ~(RST_RESET_PCI_CORE | RST_RESET_PCI_BUS);
- ATH_WRITE_REG(AR71XX_RST_RESET, reset);
- DELAY(1000);
-
- /* Init PCI windows */
- ATH_WRITE_REG(AR71XX_PCI_WINDOW0, PCI_WINDOW0_ADDR);
- ATH_WRITE_REG(AR71XX_PCI_WINDOW1, PCI_WINDOW1_ADDR);
- ATH_WRITE_REG(AR71XX_PCI_WINDOW2, PCI_WINDOW2_ADDR);
- ATH_WRITE_REG(AR71XX_PCI_WINDOW3, PCI_WINDOW3_ADDR);
- ATH_WRITE_REG(AR71XX_PCI_WINDOW4, PCI_WINDOW4_ADDR);
- ATH_WRITE_REG(AR71XX_PCI_WINDOW5, PCI_WINDOW5_ADDR);
- ATH_WRITE_REG(AR71XX_PCI_WINDOW6, PCI_WINDOW6_ADDR);
- ATH_WRITE_REG(AR71XX_PCI_WINDOW7, PCI_WINDOW7_CONF_ADDR);
- DELAY(1000);
-
- ar71xx_pci_check_bus_error();
-
- /* Fixup internal PCI bridge */
- ar71xx_pci_write_config(dev, 0, 0, 0, PCIR_COMMAND,
- PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN
- | PCIM_CMD_SERRESPEN | PCIM_CMD_BACKTOBACK
- | PCIM_CMD_PERRESPEN | PCIM_CMD_MWRICEN, 2);
-
- device_add_child(dev, "pci", busno);
- return (bus_generic_attach(dev));
-}
-
-static int
-ar71xx_pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
-{
- struct ar71xx_pci_softc *sc = device_get_softc(dev);
-
- switch (which) {
- case PCIB_IVAR_DOMAIN:
- *result = 0;
- return (0);
- case PCIB_IVAR_BUS:
- *result = sc->sc_busno;
- return (0);
- }
-
- return (ENOENT);
-}
-
-static int
-ar71xx_pci_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
-{
- struct ar71xx_pci_softc * sc = device_get_softc(dev);
-
- switch (which) {
- case PCIB_IVAR_BUS:
- sc->sc_busno = result;
- return (0);
- }
-
- return (ENOENT);
-}
-
-static struct resource *
-ar71xx_pci_alloc_resource(device_t bus, device_t child, int type, int *rid,
- u_long start, u_long end, u_long count, u_int flags)
-{
-
- struct ar71xx_pci_softc *sc = device_get_softc(bus);
- struct resource *rv = NULL;
- struct rman *rm;
-
- switch (type) {
- case SYS_RES_IRQ:
- rm = &sc->sc_irq_rman;
- break;
- case SYS_RES_MEMORY:
- rm = &sc->sc_mem_rman;
- break;
- default:
- return (NULL);
- }
-
- rv = rman_reserve_resource(rm, start, end, count, flags, child);
-
- if (rv == NULL)
- return (NULL);
-
- rman_set_rid(rv, *rid);
-
- if (flags & RF_ACTIVE) {
- if (bus_activate_resource(child, type, *rid, rv)) {
- rman_release_resource(rv);
- return (NULL);
- }
- }
-
- return (rv);
-}
-
-static int
-ar71xx_pci_teardown_intr(device_t dev, device_t child, struct resource *res,
- void *cookie)
-{
-
- return (intr_event_remove_handler(cookie));
-}
-
-static int
-ar71xx_pci_maxslots(device_t dev)
-{
-
- return (PCI_SLOTMAX);
-}
-
-static int
-ar71xx_pci_route_interrupt(device_t pcib, device_t device, int pin)
-{
-
- return (pin);
-}
-
-static device_method_t ar71xx_pci_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, ar71xx_pci_probe),
- DEVMETHOD(device_attach, ar71xx_pci_attach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
- DEVMETHOD(device_suspend, bus_generic_suspend),
- DEVMETHOD(device_resume, bus_generic_resume),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_read_ivar, ar71xx_pci_read_ivar),
- DEVMETHOD(bus_write_ivar, ar71xx_pci_write_ivar),
- DEVMETHOD(bus_alloc_resource, ar71xx_pci_alloc_resource),
- DEVMETHOD(bus_release_resource, bus_generic_release_resource),
- DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
- DEVMETHOD(bus_teardown_intr, ar71xx_pci_teardown_intr),
-
- /* pcib interface */
- DEVMETHOD(pcib_maxslots, ar71xx_pci_maxslots),
- DEVMETHOD(pcib_read_config, ar71xx_pci_read_config),
- DEVMETHOD(pcib_write_config, ar71xx_pci_write_config),
- DEVMETHOD(pcib_route_interrupt, ar71xx_pci_route_interrupt),
-
- {0, 0}
-};
-
-static driver_t ar71xx_pci_driver = {
- "pcib",
- ar71xx_pci_methods,
- sizeof(struct ar71xx_pci_softc),
-};
-
-static devclass_t ar71xx_pci_devclass;
-
-DRIVER_MODULE(ar71xx_pci, nexus, ar71xx_pci_driver, ar71xx_pci_devclass, 0, 0);
diff --git a/sys/mips/atheros/ar71xxreg.h b/sys/mips/atheros/ar71xxreg.h
deleted file mode 100644
index 9367792..0000000
--- a/sys/mips/atheros/ar71xxreg.h
+++ /dev/null
@@ -1,317 +0,0 @@
-/*-
- * Copyright (c) 2009 Oleksandr Tymoshenko
- * 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.
- */
-#ifndef _AR71XX_REG_H_
-#define _AR71XX_REG_H_
-
-#define ATH_READ_REG(reg) \
- *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg)))
-
-#define ATH_WRITE_REG(reg, val) \
- *((volatile uint32_t *)MIPS_PHYS_TO_KSEG1((reg))) = (val)
-
-/* PCI region */
-#define AR71XX_PCI_MEM_BASE 0x10000000
-/*
- * PCI mem windows is 0x08000000 bytes long but we exclude control
- * region from the resource manager
- */
-#define AR71XX_PCI_MEM_SIZE 0x07000000
-#define AR71XX_PCI_IRQ_START 0
-#define AR71XX_PCI_IRQ_END 2
-
-/* PCI config registers */
-#define AR71XX_PCI_LCONF_CMD 0x17010000
-#define PCI_LCONF_CMD_READ 0x00000000
-#define PCI_LCONF_CMD_WRITE 0x00010000
-#define AR71XX_PCI_LCONF_WRITE_DATA 0x17010004
-#define AR71XX_PCI_LCONF_READ_DATA 0x17010008
-#define AR71XX_PCI_CONF_ADDR 0x1701000C
-#define AR71XX_PCI_CONF_CMD 0x17010010
-#define PCI_CONF_CMD_READ 0x0000000A
-#define PCI_CONF_CMD_WRITE 0x0000000B
-#define AR71XX_PCI_CONF_WRITE_DATA 0x17010014
-#define AR71XX_PCI_CONF_READ_DATA 0x17010018
-#define AR71XX_PCI_ERROR 0x1701001C
-#define AR71XX_PCI_ERROR_ADDR 0x17010020
-#define AR71XX_PCI_AHB_ERROR 0x17010024
-#define AR71XX_PCI_AHB_ERROR_ADDR 0x17010028
-
-/* APB region */
-/* DDR registers */
-#define AR71XX_DDR_CONFIG 0x18000000
-#define AR71XX_DDR_CONFIG2 0x18000004
-#define AR71XX_DDR_MODE_REGISTER 0x18000008
-#define AR71XX_DDR_EXT_MODE_REGISTER 0x1800000C
-#define AR71XX_DDR_CONTROL 0x18000010
-#define AR71XX_DDR_REFRESH 0x18000014
-#define AR71XX_DDR_RD_DATA_THIS_CYCLE 0x18000018
-#define AR71XX_TAP_CONTROL0 0x1800001C
-#define AR71XX_TAP_CONTROL1 0x18000020
-#define AR71XX_TAP_CONTROL2 0x18000024
-#define AR71XX_TAP_CONTROL3 0x18000028
-#define AR71XX_PCI_WINDOW0 0x1800007C
-#define AR71XX_PCI_WINDOW1 0x18000080
-#define AR71XX_PCI_WINDOW2 0x18000084
-#define AR71XX_PCI_WINDOW3 0x18000088
-#define AR71XX_PCI_WINDOW4 0x1800008C
-#define AR71XX_PCI_WINDOW5 0x18000090
-#define AR71XX_PCI_WINDOW6 0x18000094
-#define AR71XX_PCI_WINDOW7 0x18000098
-#define AR71XX_WB_FLUSH_GE0 0x1800009C
-#define AR71XX_WB_FLUSH_GE1 0x180000A0
-#define AR71XX_WB_FLUSH_USB 0x180000A4
-#define AR71XX_WB_FLUSH_PCI 0x180000A8
-
-/*
- * Values for PCI_WINDOW_X registers
- */
-#define PCI_WINDOW0_ADDR 0x10000000
-#define PCI_WINDOW1_ADDR 0x11000000
-#define PCI_WINDOW2_ADDR 0x12000000
-#define PCI_WINDOW3_ADDR 0x13000000
-#define PCI_WINDOW4_ADDR 0x14000000
-#define PCI_WINDOW5_ADDR 0x15000000
-#define PCI_WINDOW6_ADDR 0x16000000
-#define PCI_WINDOW7_ADDR 0x17000000
-/* This value enables acces to PCI config registers */
-#define PCI_WINDOW7_CONF_ADDR 0x07000000
-
-#define AR71XX_UART_ADDR 0x18020000
-
-#define AR71XX_USB_CTRL_FLADJ 0x18030000
-#define USB_CTRL_FLADJ_HOST_SHIFT 12
-#define USB_CTRL_FLADJ_A5_SHIFT 10
-#define USB_CTRL_FLADJ_A4_SHIFT 8
-#define USB_CTRL_FLADJ_A3_SHIFT 6
-#define USB_CTRL_FLADJ_A2_SHIFT 4
-#define USB_CTRL_FLADJ_A1_SHIFT 2
-#define USB_CTRL_FLADJ_A0_SHIFT 0
-#define AR71XX_USB_CTRL_CONFIG 0x18030004
-#define USB_CTRL_CONFIG_OHCI_DES_SWAP (1 << 19)
-#define USB_CTRL_CONFIG_OHCI_BUF_SWAP (1 << 18)
-#define USB_CTRL_CONFIG_EHCI_DES_SWAP (1 << 17)
-#define USB_CTRL_CONFIG_EHCI_BUF_SWAP (1 << 16)
-#define USB_CTRL_CONFIG_DISABLE_XTL (1 << 13)
-#define USB_CTRL_CONFIG_OVERRIDE_XTL (1 << 12)
-#define USB_CTRL_CONFIG_CLK_SEL_SHIFT 4
-#define USB_CTRL_CONFIG_CLK_SEL_MASK 3
-#define USB_CTRL_CONFIG_CLK_SEL_12 0
-#define USB_CTRL_CONFIG_CLK_SEL_24 1
-#define USB_CTRL_CONFIG_CLK_SEL_48 2
-#define USB_CTRL_CONFIG_OVER_CURRENT_AS_GPIO (1 << 8)
-#define USB_CTRL_CONFIG_SS_SIMULATION_MODE (1 << 2)
-#define USB_CTRL_CONFIG_RESUME_UTMI_PLS_DIS (1 << 1)
-#define USB_CTRL_CONFIG_UTMI_BACKWARD_ENB (1 << 0)
-
-#define AR71XX_PLL_CPU_CONFIG 0x18050000
-#define AR71XX_PLL_SEC_CONFIG 0x18050004
-#define AR71XX_PLL_CPU_CLK_CTRL 0x18050008
-#define AR71XX_PLL_ETH_INT0_CLK 0x18050010
-#define AR71XX_PLL_ETH_INT1_CLK 0x18050014
-#define XPLL_ETH_INT_CLK_10 0x00991099
-#define XPLL_ETH_INT_CLK_100 0x00441011
-#define XPLL_ETH_INT_CLK_1000 0x13110000
-#define XPLL_ETH_INT_CLK_1000_GMII 0x14110000
-#define PLL_ETH_INT_CLK_10 0x00991099
-#define PLL_ETH_INT_CLK_100 0x00001099
-#define PLL_ETH_INT_CLK_1000 0x00110000
-#define AR71XX_PLL_ETH_EXT_CLK 0x18050018
-#define AR71XX_PLL_PCI_CLK 0x1805001C
-
-/*
- * APB interrupt status and mask register and interrupt bit numbers for
- */
-#define AR71XX_MISC_INTR_STATUS 0x18060010
-#define AR71XX_MISC_INTR_MASK 0x18060014
-#define MISC_INTR_TIMER 0
-#define MISC_INTR_ERROR 1
-#define MISC_INTR_GPIO 2
-#define MISC_INTR_UART 3
-#define MISC_INTR_WATCHDOG 4
-#define MISC_INTR_PERF 5
-#define MISC_INTR_OHCI 6
-#define MISC_INTR_DMA 7
-
-#define AR71XX_PCI_INTR_STATUS 0x18060018
-#define AR71XX_PCI_INTR_MASK 0x1806001C
-#define PCI_INTR_CORE (1 << 4)
-
-#define AR71XX_RST_RESET 0x18060024
-#define RST_RESET_FULL_CHIP (1 << 24) /* Same as pulling
- the reset pin */
-#define RST_RESET_CPU_COLD (1 << 20) /* Cold reset */
-#define RST_RESET_GE1_MAC (1 << 13)
-#define RST_RESET_GE1_PHY (1 << 12)
-#define RST_RESET_GE0_MAC (1 << 9)
-#define RST_RESET_GE0_PHY (1 << 8)
-#define RST_RESET_USB_OHCI_DLL (1 << 6)
-#define RST_RESET_USB_HOST (1 << 5)
-#define RST_RESET_USB_PHY (1 << 4)
-#define RST_RESET_PCI_BUS (1 << 1)
-#define RST_RESET_PCI_CORE (1 << 0)
-
-/*
- * GigE adapters region
- */
-#define AR71XX_MAC0_BASE 0x19000000
-#define AR71XX_MAC1_BASE 0x1A000000
-
-#define AR71XX_MAC_CFG1 0x00
-#define MAC_CFG1_SOFT_RESET (1 << 31)
-#define MAC_CFG1_SIMUL_RESET (1 << 30)
-#define MAC_CFG1_MAC_RX_BLOCK_RESET (1 << 19)
-#define MAC_CFG1_MAC_TX_BLOCK_RESET (1 << 18)
-#define MAC_CFG1_RX_FUNC_RESET (1 << 17)
-#define MAC_CFG1_TX_FUNC_RESET (1 << 16)
-#define MAC_CFG1_LOOPBACK (1 << 8)
-#define MAC_CFG1_RXFLOW_CTRL (1 << 5)
-#define MAC_CFG1_TXFLOW_CTRL (1 << 4)
-#define MAC_CFG1_SYNC_RX (1 << 3)
-#define MAC_CFG1_RX_ENABLE (1 << 2)
-#define MAC_CFG1_SYNC_TX (1 << 1)
-#define MAC_CFG1_TX_ENABLE (1 << 0)
-#define AR71XX_MAC_CFG2 0x04
-#define MAC_CFG2_PREAMBLE_LEN_MASK 0xf
-#define MAC_CFG2_PREAMBLE_LEN_SHIFT 12
-#define MAC_CFG2_IFACE_MODE_1000 (2 << 8)
-#define MAC_CFG2_IFACE_MODE_10_100 (1 << 8)
-#define MAC_CFG2_IFACE_MODE_SHIFT 8
-#define MAC_CFG2_IFACE_MODE_MASK 3
-#define MAC_CFG2_HUGE_FRAME (1 << 5)
-#define MAC_CFG2_LENGTH_FIELD (1 << 4)
-#define MAC_CFG2_ENABLE_PADCRC (1 << 2)
-#define MAC_CFG2_ENABLE_CRC (1 << 1)
-#define MAC_CFG2_FULL_DUPLEX (1 << 0)
-#define AR71XX_MAC_IFG 0x08
-#define AR71XX_MAC_HDUPLEX 0x0C
-#define AR71XX_MAC_MAX_FRAME_LEN 0x10
-#define AR71XX_MAC_MII_CFG 0x20
-#define MAC_MII_CFG_RESET (1 << 31)
-#define MAC_MII_CFG_SCAN_AUTO_INC (1 << 5)
-#define MAC_MII_CFG_PREAMBLE_SUP (1 << 4)
-#define MAC_MII_CFG_CLOCK_SELECT_MASK 0x7
-#define MAC_MII_CFG_CLOCK_DIV_4 0
-#define MAC_MII_CFG_CLOCK_DIV_6 2
-#define MAC_MII_CFG_CLOCK_DIV_8 3
-#define MAC_MII_CFG_CLOCK_DIV_10 4
-#define MAC_MII_CFG_CLOCK_DIV_14 5
-#define MAC_MII_CFG_CLOCK_DIV_20 6
-#define MAC_MII_CFG_CLOCK_DIV_28 7
-#define AR71XX_MAC_MII_CMD 0x24
-#define MAC_MII_CMD_SCAN_CYCLE (1 << 1)
-#define MAC_MII_CMD_READ 1
-#define MAC_MII_CMD_WRITE 0
-#define AR71XX_MAC_MII_ADDR 0x28
-#define MAC_MII_PHY_ADDR_SHIFT 8
-#define MAC_MII_PHY_ADDR_MASK 0xff
-#define MAC_MII_REG_MASK 0x1f
-#define AR71XX_MAC_MII_CONTROL 0x2C
-#define MAC_MII_CONTROL_MASK 0xffff
-#define AR71XX_MAC_MII_STATUS 0x30
-#define MAC_MII_STATUS_MASK 0xffff
-#define AR71XX_MAC_MII_INDICATOR 0x34
-#define MAC_MII_INDICATOR_NOT_VALID (1 << 2)
-#define MAC_MII_INDICATOR_SCANNING (1 << 1)
-#define MAC_MII_INDICATOR_BUSY (1 << 0)
-#define AR71XX_MAC_IFCONTROL 0x38
-#define MAC_IFCONTROL_SPEED (1 << 16)
-#define AR71XX_MAC_STA_ADDR1 0x40
-#define AR71XX_MAC_STA_ADDR2 0x44
-#define AR71XX_MAC_FIFO_CFG0 0x48
-#define FIFO_CFG0_TX_FABRIC (1 << 4)
-#define FIFO_CFG0_TX_SYSTEM (1 << 3)
-#define FIFO_CFG0_RX_FABRIC (1 << 2)
-#define FIFO_CFG0_RX_SYSTEM (1 << 1)
-#define FIFO_CFG0_WATERMARK (1 << 0)
-#define FIFO_CFG0_ALL ((1 << 5) - 1)
-#define FIFO_CFG0_ENABLE_SHIFT 8
-#define AR71XX_MAC_FIFO_CFG1 0x4C
-#define AR71XX_MAC_FIFO_CFG2 0x50
-#define AR71XX_MAC_FIFO_TX_THRESHOLD 0x54
-#define AR71XX_MAC_FIFO_RX_FILTMATCH 0x58
-#define FIFO_RX_FILTMATCH_ALL ((1 << 18) - 1)
-#define AR71XX_MAC_FIFO_RX_FILTMASK 0x5C
-#define FIFO_RX_FILTMASK_BYTE_MODE (1 << 19)
-#define FIFO_RX_FILTMASK_NO_SHORT_FRAME (1 << 18)
-#define FIFO_RX_FILTMASK_ALL ((1 << 20) - 1)
-/*
- * These flags applicable both to AR71XX_MAC_FIFO_RX_FILTMASK and
- * to AR71XX_MAC_FIFO_RX_FILTMATCH
- */
-#define FIFO_RX_FILT_UNICAST (1 << 17)
-#define FIFO_RX_FILT_TRUNC_FRAME (1 << 16)
-#define FIFO_RX_FILT_VLAN_TAG (1 << 15)
-#define FIFO_RX_FILT_UNSUP_OPCODE (1 << 14)
-#define FIFO_RX_FILT_PAUSE_FRAME (1 << 13)
-#define FIFO_RX_FILT_CTRL_FRAME (1 << 12)
-#define FIFO_RX_FILT_LONG_EVENT (1 << 11)
-#define FIFO_RX_FILT_DRIBBLE_NIBBLE (1 << 10)
-#define FIFO_RX_FILT_BCAST (1 << 9)
-#define FIFO_RX_FILT_MCAST (1 << 8)
-#define FIFO_RX_FILT_OK (1 << 7)
-#define FIFO_RX_FILT_OORANGE (1 << 6)
-#define FIFO_RX_FILT_LEN_MSMTCH (1 << 5)
-#define FIFO_RX_FILT_CRC_ERROR (1 << 4)
-#define FIFO_RX_FILT_CODE_ERROR (1 << 3)
-#define FIFO_RX_FILT_FALSE_CARRIER (1 << 2)
-#define FIFO_RX_FILT_RX_DV_EVENT (1 << 1)
-#define FIFO_RX_FILT_DROP_EVENT (1 << 0)
-#define AR71XX_MAC_FIFO_RAM0 0x60
-#define AR71XX_MAC_FIFO_RAM1 0x64
-#define AR71XX_MAC_FIFO_RAM2 0x68
-#define AR71XX_MAC_FIFO_RAM3 0x6C
-#define AR71XX_MAC_FIFO_RAM4 0x70
-#define AR71XX_MAC_FIFO_RAM5 0x74
-#define AR71XX_MAC_FIFO_RAM6 0x78
-#define AR71XX_DMA_TX_CONTROL 0x180
-#define DMA_TX_CONTROL_EN (1 << 0)
-#define AR71XX_DMA_TX_DESC 0x184
-#define AR71XX_DMA_TX_STATUS 0x188
-#define DMA_TX_STATUS_PCOUNT_MASK 0xff
-#define DMA_TX_STATUS_PCOUNT_SHIFT 16
-#define DMA_TX_STATUS_BUS_ERROR (1 << 3)
-#define DMA_TX_STATUS_UNDERRUN (1 << 1)
-#define DMA_TX_STATUS_PKT_SENT (1 << 0)
-#define AR71XX_DMA_RX_CONTROL 0x18C
-#define DMA_RX_CONTROL_EN (1 << 0)
-#define AR71XX_DMA_RX_DESC 0x190
-#define AR71XX_DMA_RX_STATUS 0x194
-#define DMA_RX_STATUS_PCOUNT_MASK 0xff
-#define DMA_RX_STATUS_PCOUNT_SHIFT 16
-#define DMA_RX_STATUS_BUS_ERROR (1 << 3)
-#define DMA_RX_STATUS_OVERFLOW (1 << 1)
-#define DMA_RX_STATUS_PKT_RECVD (1 << 0)
-#define AR71XX_DMA_INTR 0x198
-#define AR71XX_DMA_INTR_STATUS 0x19C
-#define DMA_INTR_ALL ((1 << 8) - 1)
-#define DMA_INTR_RX_BUS_ERROR (1 << 7)
-#define DMA_INTR_RX_OVERFLOW (1 << 6)
-#define DMA_INTR_RX_PKT_RCVD (1 << 4)
-#define DMA_INTR_TX_BUS_ERROR (1 << 3)
-#define DMA_INTR_TX_UNDERRUN (1 << 1)
-#define DMA_INTR_TX_PKT_SENT (1 << 0)
-
-#endif /* _AR71XX_REG_H_ */
diff --git a/sys/mips/atheros/files.ar71xx b/sys/mips/atheros/files.ar71xx
deleted file mode 100644
index 78e1d9c..0000000
--- a/sys/mips/atheros/files.ar71xx
+++ /dev/null
@@ -1,9 +0,0 @@
-# $FreeBSD$
-
-mips/atheros/apb.c standard
-mips/atheros/ar71xx_machdep.c standard
-mips/atheros/ar71xx_ohci.c optional ohci
-mips/atheros/ar71xx_pci.c optional pci
-mips/atheros/if_arge.c optional arge
-mips/atheros/uart_bus_ar71xx.c optional uart
-mips/atheros/uart_cpu_ar71xx.c optional uart
diff --git a/sys/mips/atheros/if_arge.c b/sys/mips/atheros/if_arge.c
deleted file mode 100644
index 7dbfe70..0000000
--- a/sys/mips/atheros/if_arge.c
+++ /dev/null
@@ -1,1657 +0,0 @@
-/*-
- * Copyright (c) 2009, Oleksandr Tymoshenko
- * 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 unmodified, 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$");
-
-/*
- * AR71XX gigabit ethernet driver
- */
-#include <sys/param.h>
-#include <sys/endian.h>
-#include <sys/systm.h>
-#include <sys/sockio.h>
-#include <sys/mbuf.h>
-#include <sys/malloc.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-#include <sys/socket.h>
-#include <sys/taskqueue.h>
-
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <net/ethernet.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <net/if_types.h>
-
-#include <net/bpf.h>
-
-#include <machine/bus.h>
-#include <machine/cache.h>
-#include <machine/resource.h>
-#include <vm/vm_param.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <machine/pmap.h>
-#include <sys/bus.h>
-#include <sys/rman.h>
-
-#include <dev/mii/mii.h>
-#include <dev/mii/miivar.h>
-
-#include <dev/pci/pcireg.h>
-#include <dev/pci/pcivar.h>
-
-MODULE_DEPEND(arge, ether, 1, 1, 1);
-MODULE_DEPEND(arge, miibus, 1, 1, 1);
-
-#include "miibus_if.h"
-
-#include <mips/atheros/ar71xxreg.h>
-#include <mips/atheros/if_argevar.h>
-
-#undef ARGE_DEBUG
-#ifdef ARGE_DEBUG
-#define dprintf printf
-#else
-#define dprintf(x, arg...)
-#endif
-
-static int arge_attach(device_t);
-static int arge_detach(device_t);
-static int arge_fix_chain(struct mbuf **mp);
-static void arge_flush_ddr(struct arge_softc *);
-static int arge_ifmedia_upd(struct ifnet *);
-static void arge_ifmedia_sts(struct ifnet *, struct ifmediareq *);
-static int arge_ioctl(struct ifnet *, u_long, caddr_t);
-static void arge_init(void *);
-static void arge_init_locked(struct arge_softc *);
-static void arge_link_task(void *, int);
-static int arge_miibus_readreg(device_t, int, int);
-static void arge_miibus_statchg(device_t);
-static int arge_miibus_writereg(device_t, int, int, int);
-static int arge_probe(device_t);
-static void arge_reset_dma(struct arge_softc *);
-static int arge_resume(device_t);
-static int arge_rx_ring_init(struct arge_softc *);
-static int arge_tx_ring_init(struct arge_softc *);
-static void arge_shutdown(device_t);
-static void arge_start(struct ifnet *);
-static void arge_start_locked(struct ifnet *);
-static void arge_stop(struct arge_softc *);
-static int arge_suspend(device_t);
-
-static void arge_rx_locked(struct arge_softc *);
-static void arge_tx_locked(struct arge_softc *);
-static void arge_intr(void *);
-static int arge_intr_filter(void *);
-static void arge_tx_intr(struct arge_softc *, uint32_t);
-static void arge_rx_intr(struct arge_softc *, uint32_t);
-static void arge_tick(void *);
-
-static void arge_dmamap_cb(void *, bus_dma_segment_t *, int, int);
-static int arge_dma_alloc(struct arge_softc *);
-static void arge_dma_free(struct arge_softc *);
-static int arge_newbuf(struct arge_softc *, int);
-static __inline void arge_fixup_rx(struct mbuf *);
-
-static device_method_t arge_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, arge_probe),
- DEVMETHOD(device_attach, arge_attach),
- DEVMETHOD(device_detach, arge_detach),
- DEVMETHOD(device_suspend, arge_suspend),
- DEVMETHOD(device_resume, arge_resume),
- DEVMETHOD(device_shutdown, arge_shutdown),
-
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
-
- /* MII interface */
- DEVMETHOD(miibus_readreg, arge_miibus_readreg),
- DEVMETHOD(miibus_writereg, arge_miibus_writereg),
- DEVMETHOD(miibus_statchg, arge_miibus_statchg),
-
- { 0, 0 }
-};
-
-static driver_t arge_driver = {
- "arge",
- arge_methods,
- sizeof(struct arge_softc)
-};
-
-static devclass_t arge_devclass;
-
-DRIVER_MODULE(arge, nexus, arge_driver, arge_devclass, 0, 0);
-DRIVER_MODULE(miibus, arge, miibus_driver, miibus_devclass, 0, 0);
-
-/*
- * Flushes all
- */
-static void
-arge_flush_ddr(struct arge_softc *sc)
-{
-
- ATH_WRITE_REG(sc->arge_ddr_flush_reg, 1);
- while (ATH_READ_REG(sc->arge_ddr_flush_reg) & 1)
- ;
-
- ATH_WRITE_REG(sc->arge_ddr_flush_reg, 1);
- while (ATH_READ_REG(sc->arge_ddr_flush_reg) & 1)
- ;
-}
-
-static int
-arge_probe(device_t dev)
-{
-
- device_set_desc(dev, "Atheros AR71xx built-in ethernet interface");
- return (0);
-}
-
-static int
-arge_attach(device_t dev)
-{
- uint8_t eaddr[ETHER_ADDR_LEN];
- struct ifnet *ifp;
- struct arge_softc *sc;
- int error = 0, rid, phynum;
- uint32_t reg;
-
- sc = device_get_softc(dev);
- sc->arge_dev = dev;
- sc->arge_mac_unit = device_get_unit(dev);
-
- KASSERT(((sc->arge_mac_unit == 0) || (sc->arge_mac_unit == 1)),
- ("if_arge: Only MAC0 and MAC1 supported"));
- if (sc->arge_mac_unit == 0) {
- sc->arge_ddr_flush_reg = AR71XX_WB_FLUSH_GE0;
- sc->arge_pll_reg = AR71XX_PLL_ETH_INT0_CLK;
- } else {
- sc->arge_ddr_flush_reg = AR71XX_WB_FLUSH_GE1;
- sc->arge_pll_reg = AR71XX_PLL_ETH_INT1_CLK;
- }
-
- /*
- * Get which PHY of 5 available we should use for this unit
- */
- if (resource_int_value(device_get_name(dev), device_get_unit(dev),
- "phy", &phynum) != 0) {
- /*
- * Use port 4 (WAN) for GE0. For any other port use
- * its PHY the same as its unit number
- */
- if (sc->arge_mac_unit == 0)
- phynum = 4;
- else
- phynum = sc->arge_mac_unit;
-
- device_printf(dev, "No PHY specified, using %d\n", phynum);
- }
-
- sc->arge_phy_num = phynum;
-
-
- mtx_init(&sc->arge_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
- MTX_DEF);
- callout_init_mtx(&sc->arge_stat_callout, &sc->arge_mtx, 0);
- TASK_INIT(&sc->arge_link_task, 0, arge_link_task, sc);
-
- /* Map control/status registers. */
- sc->arge_rid = 0;
- sc->arge_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &sc->arge_rid, RF_ACTIVE);
-
- if (sc->arge_res == NULL) {
- device_printf(dev, "couldn't map memory\n");
- error = ENXIO;
- goto fail;
- }
-
- /* Allocate interrupts */
- rid = 0;
- sc->arge_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
- RF_SHAREABLE | RF_ACTIVE);
-
- if (sc->arge_irq == NULL) {
- device_printf(dev, "couldn't map interrupt\n");
- error = ENXIO;
- goto fail;
- }
-
- /* Allocate ifnet structure. */
- ifp = sc->arge_ifp = if_alloc(IFT_ETHER);
-
- if (ifp == NULL) {
- device_printf(dev, "couldn't allocate ifnet structure\n");
- error = ENOSPC;
- goto fail;
- }
-
- ifp->if_softc = sc;
- if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = arge_ioctl;
- ifp->if_start = arge_start;
- ifp->if_init = arge_init;
-
- /* XXX: add real size */
- IFQ_SET_MAXLEN(&ifp->if_snd, 9);
- ifp->if_snd.ifq_maxlen = 9;
- IFQ_SET_READY(&ifp->if_snd);
-
- ifp->if_capenable = ifp->if_capabilities;
-
- eaddr[0] = 0x00;
- eaddr[1] = 0x15;
- eaddr[2] = 0x6d;
- eaddr[3] = 0xc1;
- eaddr[4] = 0x28;
- eaddr[5] = 0x2e;
-
- if (arge_dma_alloc(sc) != 0) {
- error = ENXIO;
- goto fail;
- }
-
- ARGE_WRITE(sc, AR71XX_MAC_CFG1,
- MAC_CFG1_SYNC_RX | MAC_CFG1_RX_ENABLE |
- MAC_CFG1_SYNC_TX | MAC_CFG1_TX_ENABLE);
-
- reg = ARGE_READ(sc, AR71XX_MAC_CFG2);
- reg |= MAC_CFG2_ENABLE_PADCRC | MAC_CFG2_LENGTH_FIELD ;
- ARGE_WRITE(sc, AR71XX_MAC_CFG2, reg);
-
- ARGE_WRITE(sc, AR71XX_MAC_MAX_FRAME_LEN, 1536);
-
- /* Reset MII bus */
- ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, MAC_MII_CFG_RESET);
- DELAY(100);
- ARGE_WRITE(sc, AR71XX_MAC_MII_CFG, MAC_MII_CFG_CLOCK_DIV_28);
- DELAY(100);
-
- /*
- * Set all Ethernet address registers to the same initial values
- * set all four addresses to 66-88-aa-cc-dd-ee
- */
- ARGE_WRITE(sc, AR71XX_MAC_STA_ADDR1, 0x6dc1282e);
- ARGE_WRITE(sc, AR71XX_MAC_STA_ADDR2, 0x00000015);
-
- ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG0,
- FIFO_CFG0_ALL << FIFO_CFG0_ENABLE_SHIFT);
- ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG1, 0x0fff0000);
- ARGE_WRITE(sc, AR71XX_MAC_FIFO_CFG2, 0x00001fff);
-
- reg = FIFO_RX_FILTMATCH_ALL;
- ARGE_WRITE(sc, AR71XX_MAC_FIFO_RX_FILTMATCH, reg);
-
- reg = FIFO_RX_FILTMASK_ALL;
- reg &= ~FIFO_RX_FILTMASK_BYTE_MODE;
- ARGE_WRITE(sc, AR71XX_MAC_FIFO_RX_FILTMASK, reg);
-
- /* Do MII setup. */
- if (mii_phy_probe(dev, &sc->arge_miibus,
- arge_ifmedia_upd, arge_ifmedia_sts)) {
- device_printf(dev, "MII without any phy!\n");
- error = ENXIO;
- goto fail;
- }
-
- /* Call MI attach routine. */
- ether_ifattach(ifp, eaddr);
-
- /* Hook interrupt last to avoid having to lock softc */
- error = bus_setup_intr(dev, sc->arge_irq, INTR_TYPE_NET | INTR_MPSAFE,
- arge_intr_filter, arge_intr, sc, &sc->arge_intrhand);
-
- if (error) {
- device_printf(dev, "couldn't set up irq\n");
- ether_ifdetach(ifp);
- goto fail;
- }
-
-fail:
- if (error)
- arge_detach(dev);
-
- return (error);
-}
-
-static int
-arge_detach(device_t dev)
-{
- struct arge_softc *sc = device_get_softc(dev);
- struct ifnet *ifp = sc->arge_ifp;
-
- KASSERT(mtx_initialized(&sc->arge_mtx), ("arge mutex not initialized"));
-
- /* These should only be active if attach succeeded */
- if (device_is_attached(dev)) {
- ARGE_LOCK(sc);
- sc->arge_detach = 1;
- arge_stop(sc);
- ARGE_UNLOCK(sc);
- taskqueue_drain(taskqueue_swi, &sc->arge_link_task);
- ether_ifdetach(ifp);
- }
-
- if (sc->arge_miibus)
- device_delete_child(dev, sc->arge_miibus);
- bus_generic_detach(dev);
-
- if (sc->arge_intrhand)
- bus_teardown_intr(dev, sc->arge_irq, sc->arge_intrhand);
-
- if (sc->arge_res)
- bus_release_resource(dev, SYS_RES_MEMORY, sc->arge_rid,
- sc->arge_res);
-
- if (ifp)
- if_free(ifp);
-
- arge_dma_free(sc);
-
- mtx_destroy(&sc->arge_mtx);
-
- return (0);
-
-}
-
-static int
-arge_suspend(device_t dev)
-{
-
- panic("%s", __func__);
- return 0;
-}
-
-static int
-arge_resume(device_t dev)
-{
-
- panic("%s", __func__);
- return 0;
-}
-
-static void
-arge_shutdown(device_t dev)
-{
- struct arge_softc *sc;
-
- sc = device_get_softc(dev);
-
- ARGE_LOCK(sc);
- arge_stop(sc);
- ARGE_UNLOCK(sc);
-}
-
-static int
-arge_miibus_readreg(device_t dev, int phy, int reg)
-{
- struct arge_softc * sc = device_get_softc(dev);
- int i, result;
- uint32_t addr = 0x1000 | (phy << MAC_MII_PHY_ADDR_SHIFT)
- | (reg & MAC_MII_REG_MASK);
-
- if (phy != sc->arge_phy_num)
- return (0);
-
- ARGE_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE);
- ARGE_WRITE(sc, AR71XX_MAC_MII_ADDR, addr);
- ARGE_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_READ);
-
- i = ARGE_MII_TIMEOUT;
- while ((ARGE_READ(sc, AR71XX_MAC_MII_INDICATOR) &
- MAC_MII_INDICATOR_BUSY) && (i--))
- DELAY(5);
-
- if (i < 0) {
- dprintf("%s timedout\n", __func__);
- /* XXX: return ERRNO istead? */
- return (-1);
- }
-
- result = ARGE_READ(sc, AR71XX_MAC_MII_STATUS) & MAC_MII_STATUS_MASK;
- ARGE_WRITE(sc, AR71XX_MAC_MII_CMD, MAC_MII_CMD_WRITE);
- dprintf("%s: phy=%d, reg=%02x, value[%08x]=%04x\n", __func__,
- phy, reg, addr, result);
-
- return (result);
-}
-
-static int
-arge_miibus_writereg(device_t dev, int phy, int reg, int data)
-{
- struct arge_softc * sc = device_get_softc(dev);
- int i;
- uint32_t addr = 0x1000
- | (phy << MAC_MII_PHY_ADDR_SHIFT) | (reg & MAC_MII_REG_MASK);
-
- dprintf("%s: phy=%d, reg=%02x, value=%04x\n", __func__,
- phy, reg, data);
-
- ARGE_WRITE(sc, AR71XX_MAC_MII_ADDR, addr);
- ARGE_WRITE(sc, AR71XX_MAC_MII_CONTROL, data);
-
- i = ARGE_MII_TIMEOUT;
- while ((ARGE_READ(sc, AR71XX_MAC_MII_INDICATOR) &
- MAC_MII_INDICATOR_BUSY) && (i--))
- DELAY(5);
-
- if (i < 0) {
- dprintf("%s timedout\n", __func__);
- /* XXX: return ERRNO istead? */
- return (-1);
- }
-
- return (0);
-}
-
-static void
-arge_miibus_statchg(device_t dev)
-{
- struct arge_softc *sc;
-
- sc = device_get_softc(dev);
- taskqueue_enqueue(taskqueue_swi, &sc->arge_link_task);
-}
-
-static void
-arge_link_task(void *arg, int pending)
-{
- struct arge_softc *sc;
- struct mii_data *mii;
- struct ifnet *ifp;
- uint32_t media;
- uint32_t cfg, ifcontrol, rx_filtmask, pll, sec_cfg;
-
- sc = (struct arge_softc *)arg;
-
- ARGE_LOCK(sc);
- mii = device_get_softc(sc->arge_miibus);
- ifp = sc->arge_ifp;
- if (mii == NULL || ifp == NULL ||
- (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- ARGE_UNLOCK(sc);
- return;
- }
-
- if (mii->mii_media_status & IFM_ACTIVE) {
-
- media = IFM_SUBTYPE(mii->mii_media_active);
-
- if (media != IFM_NONE) {
- sc->arge_link_status = 1;
-
- cfg = ARGE_READ(sc, AR71XX_MAC_CFG2);
- ifcontrol = ARGE_READ(sc, AR71XX_MAC_IFCONTROL);
- rx_filtmask =
- ARGE_READ(sc, AR71XX_MAC_FIFO_RX_FILTMASK);
-
- cfg &= ~(MAC_CFG2_IFACE_MODE_1000
- | MAC_CFG2_IFACE_MODE_10_100
- | MAC_CFG2_FULL_DUPLEX);
- ifcontrol &= ~MAC_IFCONTROL_SPEED;
- rx_filtmask &= ~FIFO_RX_FILTMASK_BYTE_MODE;
-
- switch(media) {
- case IFM_10_T:
- cfg |= MAC_CFG2_IFACE_MODE_10_100;
- pll = PLL_ETH_INT_CLK_10;
- break;
- case IFM_100_TX:
- cfg |= MAC_CFG2_IFACE_MODE_10_100;
- ifcontrol |= MAC_IFCONTROL_SPEED;
- pll = PLL_ETH_INT_CLK_100;
- break;
- case IFM_1000_T:
- case IFM_1000_SX:
- cfg |= MAC_CFG2_IFACE_MODE_1000;
- rx_filtmask |= FIFO_RX_FILTMASK_BYTE_MODE;
- pll = PLL_ETH_INT_CLK_1000;
- break;
- default:
- pll = PLL_ETH_INT_CLK_100;
- device_printf(sc->arge_dev,
- "Unknown media %d\n", media);
- }
-
- ARGE_WRITE(sc, AR71XX_MAC_FIFO_TX_THRESHOLD,
- 0x008001ff);
-
- ARGE_WRITE(sc, AR71XX_MAC_CFG2, cfg);
- ARGE_WRITE(sc, AR71XX_MAC_IFCONTROL, ifcontrol);
- ARGE_WRITE(sc, AR71XX_MAC_FIFO_RX_FILTMASK,
- rx_filtmask);
-
- /* set PLL registers */
- sec_cfg = ATH_READ_REG(AR71XX_PLL_CPU_CONFIG);
- sec_cfg &= ~(3 << 17);
- sec_cfg |= (2 << 17);
-
- ATH_WRITE_REG(AR71XX_PLL_CPU_CONFIG, sec_cfg);
- DELAY(100);
-
- ATH_WRITE_REG(sc->arge_pll_reg, pll);
-
- sec_cfg |= (3 << 17);
- ATH_WRITE_REG(AR71XX_PLL_CPU_CONFIG, sec_cfg);
- DELAY(100);
-
- sec_cfg &= ~(3 << 17);
- ATH_WRITE_REG(AR71XX_PLL_CPU_CONFIG, sec_cfg);
- DELAY(100);
- }
- } else
- sc->arge_link_status = 0;
-
- ARGE_UNLOCK(sc);
-}
-
-static void
-arge_reset_dma(struct arge_softc *sc)
-{
- unsigned int i;
-
- ARGE_WRITE(sc, AR71XX_DMA_RX_CONTROL, 0);
- ARGE_WRITE(sc, AR71XX_DMA_TX_CONTROL, 0);
-
- ARGE_WRITE(sc, AR71XX_DMA_RX_DESC, 0);
- ARGE_WRITE(sc, AR71XX_DMA_TX_DESC, 0);
-
- /* Clear all possible RX interrupts */
- for (i = 0; i < ARGE_RX_RING_COUNT; i++)
- ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_PKT_RECVD);
-
- /*
- * Clear all possible TX interrupts
- */
- for (i = 0; i < ARGE_TX_RING_COUNT; i++)
- ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_PKT_SENT);
-
- /*
- * Now Rx/Tx errors
- */
- ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS,
- DMA_RX_STATUS_BUS_ERROR | DMA_RX_STATUS_OVERFLOW);
- ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS,
- DMA_TX_STATUS_BUS_ERROR | DMA_TX_STATUS_UNDERRUN);
-}
-
-
-
-static void
-arge_init(void *xsc)
-{
- struct arge_softc *sc = xsc;
-
- ARGE_LOCK(sc);
- arge_init_locked(sc);
- ARGE_UNLOCK(sc);
-}
-
-static void
-arge_init_locked(struct arge_softc *sc)
-{
- struct ifnet *ifp = sc->arge_ifp;
- struct mii_data *mii;
-
- ARGE_LOCK_ASSERT(sc);
-
- mii = device_get_softc(sc->arge_miibus);
-
- arge_stop(sc);
-
- /* Init circular RX list. */
- if (arge_rx_ring_init(sc) != 0) {
- device_printf(sc->arge_dev,
- "initialization failed: no memory for rx buffers\n");
- arge_stop(sc);
- return;
- }
-
- /* Init tx descriptors. */
- arge_tx_ring_init(sc);
-
- arge_reset_dma(sc);
-
- sc->arge_link_status = 0;
- mii_mediachg(mii);
-
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
- callout_reset(&sc->arge_stat_callout, hz, arge_tick, sc);
- ARGE_WRITE(sc, AR71XX_DMA_TX_DESC, ARGE_TX_RING_ADDR(sc, 0));
- ARGE_WRITE(sc, AR71XX_DMA_RX_DESC, ARGE_RX_RING_ADDR(sc, 0));
-
- /* Start listening */
- ARGE_WRITE(sc, AR71XX_DMA_RX_CONTROL, DMA_RX_CONTROL_EN);
-
- /* Enable interrupts */
- ARGE_WRITE(sc, AR71XX_DMA_INTR, DMA_INTR_ALL);
-}
-
-/*
- * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
- * pointers to the fragment pointers.
- */
-static int
-arge_encap(struct arge_softc *sc, struct mbuf **m_head)
-{
- struct arge_txdesc *txd;
- struct arge_desc *desc, *prev_desc;
- bus_dma_segment_t txsegs[ARGE_MAXFRAGS];
- int error, i, nsegs, prod, si, prev_prod;
-
- ARGE_LOCK_ASSERT(sc);
-
- prod = sc->arge_cdata.arge_tx_prod;
- txd = &sc->arge_cdata.arge_txdesc[prod];
- error = bus_dmamap_load_mbuf_sg(sc->arge_cdata.arge_tx_tag,
- txd->tx_dmamap, *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT);
-
- if (error == EFBIG) {
- panic("EFBIG");
- } else if (error != 0)
- return (error);
-
- if (nsegs == 0) {
- m_freem(*m_head);
- *m_head = NULL;
- return (EIO);
- }
-
- /* Check number of available descriptors. */
- if (sc->arge_cdata.arge_tx_cnt + nsegs >= (ARGE_TX_RING_COUNT - 1)) {
- bus_dmamap_unload(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap);
- return (ENOBUFS);
- }
-
- txd->tx_m = *m_head;
- bus_dmamap_sync(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap,
- BUS_DMASYNC_PREWRITE);
-
- si = prod;
-
- /*
- * Make a list of descriptors for this packet. DMA controller will
- * walk through it while arge_link is not zero.
- */
- prev_prod = prod;
- desc = prev_desc = NULL;
- for (i = 0; i < nsegs; i++) {
- desc = &sc->arge_rdata.arge_tx_ring[prod];
- desc->packet_ctrl = ARGE_DMASIZE(txsegs[i].ds_len);
-
- desc->packet_addr = txsegs[i].ds_addr;
- /* link with previous descriptor */
- if (prev_desc)
- prev_desc->packet_ctrl |= ARGE_DESC_MORE;
-
- sc->arge_cdata.arge_tx_cnt++;
- prev_desc = desc;
- ARGE_INC(prod, ARGE_TX_RING_COUNT);
- }
-
- /* Update producer index. */
- sc->arge_cdata.arge_tx_prod = prod;
-
- /* Sync descriptors. */
- bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag,
- sc->arge_cdata.arge_tx_ring_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- /* Start transmitting */
- ARGE_WRITE(sc, AR71XX_DMA_TX_CONTROL, DMA_TX_CONTROL_EN);
- return (0);
-}
-
-static void
-arge_start(struct ifnet *ifp)
-{
- struct arge_softc *sc;
-
- sc = ifp->if_softc;
-
- ARGE_LOCK(sc);
- arge_start_locked(ifp);
- ARGE_UNLOCK(sc);
-}
-
-static void
-arge_start_locked(struct ifnet *ifp)
-{
- struct arge_softc *sc;
- struct mbuf *m_head;
- int enq;
-
- sc = ifp->if_softc;
-
- ARGE_LOCK_ASSERT(sc);
-
- if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
- IFF_DRV_RUNNING || sc->arge_link_status == 0 )
- return;
-
- arge_flush_ddr(sc);
-
- for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
- sc->arge_cdata.arge_tx_cnt < ARGE_TX_RING_COUNT - 2; ) {
- IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
- if (m_head == NULL)
- break;
-
- /*
- * Fix mbuf chain, all fragments should be 4 bytes aligned and
- * even 4 bytes
- */
- arge_fix_chain(&m_head);
-
- if (m_head == NULL) {
- dprintf("failed to adjust mbuf chain\n");
- }
-
- /*
- * Pack the data into the transmit ring.
- */
- if (arge_encap(sc, &m_head)) {
- if (m_head == NULL)
- break;
- IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- break;
- }
-
- enq++;
- /*
- * If there's a BPF listener, bounce a copy of this frame
- * to him.
- */
- ETHER_BPF_MTAP(ifp, m_head);
- }
-}
-
-static void
-arge_stop(struct arge_softc *sc)
-{
- struct ifnet *ifp;
-
- ARGE_LOCK_ASSERT(sc);
-
- ifp = sc->arge_ifp;
- ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
- callout_stop(&sc->arge_stat_callout);
-
- /* mask out interrupts */
- ARGE_WRITE(sc, AR71XX_DMA_INTR, 0);
-
- arge_reset_dma(sc);
-}
-
-
-static int
-arge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
-{
- struct arge_softc *sc = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *) data;
- struct mii_data *mii;
- int error;
-
- switch (command) {
- case SIOCSIFFLAGS:
- printf("Implement me: SIOCSIFFLAGS\n");
- error = 0;
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- printf("Implement me: SIOCDELMULTI\n");
- error = 0;
- break;
- case SIOCGIFMEDIA:
- case SIOCSIFMEDIA:
- printf("Implement me: SIOCSIFMEDIA\n");
- mii = device_get_softc(sc->arge_miibus);
- error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
- break;
- case SIOCSIFCAP:
- error = 0;
- ifp->if_hwassist = 0;
- printf("Implement me: SIOCSIFCAP\n");
- break;
- default:
- error = ether_ioctl(ifp, command, data);
- break;
- }
-
- return (error);
-}
-
-/*
- * Set media options.
- */
-static int
-arge_ifmedia_upd(struct ifnet *ifp)
-{
- struct arge_softc *sc;
- struct mii_data *mii;
- struct mii_softc *miisc;
- int error;
-
- sc = ifp->if_softc;
- ARGE_LOCK(sc);
- mii = device_get_softc(sc->arge_miibus);
- if (mii->mii_instance) {
- LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
- mii_phy_reset(miisc);
- }
- error = mii_mediachg(mii);
- ARGE_UNLOCK(sc);
-
- return (error);
-}
-
-/*
- * Report current media status.
- */
-static void
-arge_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
-{
- struct arge_softc *sc = ifp->if_softc;
- struct mii_data *mii;
-
- mii = device_get_softc(sc->arge_miibus);
- ARGE_LOCK(sc);
- mii_pollstat(mii);
- ARGE_UNLOCK(sc);
- ifmr->ifm_active = mii->mii_media_active;
- ifmr->ifm_status = mii->mii_media_status;
-}
-
-struct arge_dmamap_arg {
- bus_addr_t arge_busaddr;
-};
-
-static void
-arge_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
-{
- struct arge_dmamap_arg *ctx;
-
- if (error != 0)
- return;
- ctx = arg;
- ctx->arge_busaddr = segs[0].ds_addr;
-}
-
-static int
-arge_dma_alloc(struct arge_softc *sc)
-{
- struct arge_dmamap_arg ctx;
- struct arge_txdesc *txd;
- struct arge_rxdesc *rxd;
- int error, i;
-
- /* Create parent DMA tag. */
- error = bus_dma_tag_create(
- bus_get_dma_tag(sc->arge_dev), /* parent */
- 1, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
- 0, /* nsegments */
- BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->arge_cdata.arge_parent_tag);
- if (error != 0) {
- device_printf(sc->arge_dev, "failed to create parent DMA tag\n");
- goto fail;
- }
- /* Create tag for Tx ring. */
- error = bus_dma_tag_create(
- sc->arge_cdata.arge_parent_tag, /* parent */
- ARGE_RING_ALIGN, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- ARGE_TX_DMA_SIZE, /* maxsize */
- 1, /* nsegments */
- ARGE_TX_DMA_SIZE, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->arge_cdata.arge_tx_ring_tag);
- if (error != 0) {
- device_printf(sc->arge_dev, "failed to create Tx ring DMA tag\n");
- goto fail;
- }
-
- /* Create tag for Rx ring. */
- error = bus_dma_tag_create(
- sc->arge_cdata.arge_parent_tag, /* parent */
- ARGE_RING_ALIGN, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- ARGE_RX_DMA_SIZE, /* maxsize */
- 1, /* nsegments */
- ARGE_RX_DMA_SIZE, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->arge_cdata.arge_rx_ring_tag);
- if (error != 0) {
- device_printf(sc->arge_dev, "failed to create Rx ring DMA tag\n");
- goto fail;
- }
-
- /* Create tag for Tx buffers. */
- error = bus_dma_tag_create(
- sc->arge_cdata.arge_parent_tag, /* parent */
- sizeof(uint32_t), 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MCLBYTES * ARGE_MAXFRAGS, /* maxsize */
- ARGE_MAXFRAGS, /* nsegments */
- MCLBYTES, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->arge_cdata.arge_tx_tag);
- if (error != 0) {
- device_printf(sc->arge_dev, "failed to create Tx DMA tag\n");
- goto fail;
- }
-
- /* Create tag for Rx buffers. */
- error = bus_dma_tag_create(
- sc->arge_cdata.arge_parent_tag, /* parent */
- ARGE_RX_ALIGN, 0, /* alignment, boundary */
- BUS_SPACE_MAXADDR, /* lowaddr */
- BUS_SPACE_MAXADDR, /* highaddr */
- NULL, NULL, /* filter, filterarg */
- MCLBYTES, /* maxsize */
- 1, /* nsegments */
- MCLBYTES, /* maxsegsize */
- 0, /* flags */
- NULL, NULL, /* lockfunc, lockarg */
- &sc->arge_cdata.arge_rx_tag);
- if (error != 0) {
- device_printf(sc->arge_dev, "failed to create Rx DMA tag\n");
- goto fail;
- }
-
- /* Allocate DMA'able memory and load the DMA map for Tx ring. */
- error = bus_dmamem_alloc(sc->arge_cdata.arge_tx_ring_tag,
- (void **)&sc->arge_rdata.arge_tx_ring, BUS_DMA_WAITOK |
- BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->arge_cdata.arge_tx_ring_map);
- if (error != 0) {
- device_printf(sc->arge_dev,
- "failed to allocate DMA'able memory for Tx ring\n");
- goto fail;
- }
-
- ctx.arge_busaddr = 0;
- error = bus_dmamap_load(sc->arge_cdata.arge_tx_ring_tag,
- sc->arge_cdata.arge_tx_ring_map, sc->arge_rdata.arge_tx_ring,
- ARGE_TX_DMA_SIZE, arge_dmamap_cb, &ctx, 0);
- if (error != 0 || ctx.arge_busaddr == 0) {
- device_printf(sc->arge_dev,
- "failed to load DMA'able memory for Tx ring\n");
- goto fail;
- }
- sc->arge_rdata.arge_tx_ring_paddr = ctx.arge_busaddr;
-
- /* Allocate DMA'able memory and load the DMA map for Rx ring. */
- error = bus_dmamem_alloc(sc->arge_cdata.arge_rx_ring_tag,
- (void **)&sc->arge_rdata.arge_rx_ring, BUS_DMA_WAITOK |
- BUS_DMA_COHERENT | BUS_DMA_ZERO, &sc->arge_cdata.arge_rx_ring_map);
- if (error != 0) {
- device_printf(sc->arge_dev,
- "failed to allocate DMA'able memory for Rx ring\n");
- goto fail;
- }
-
- ctx.arge_busaddr = 0;
- error = bus_dmamap_load(sc->arge_cdata.arge_rx_ring_tag,
- sc->arge_cdata.arge_rx_ring_map, sc->arge_rdata.arge_rx_ring,
- ARGE_RX_DMA_SIZE, arge_dmamap_cb, &ctx, 0);
- if (error != 0 || ctx.arge_busaddr == 0) {
- device_printf(sc->arge_dev,
- "failed to load DMA'able memory for Rx ring\n");
- goto fail;
- }
- sc->arge_rdata.arge_rx_ring_paddr = ctx.arge_busaddr;
-
- /* Create DMA maps for Tx buffers. */
- for (i = 0; i < ARGE_TX_RING_COUNT; i++) {
- txd = &sc->arge_cdata.arge_txdesc[i];
- txd->tx_m = NULL;
- txd->tx_dmamap = NULL;
- error = bus_dmamap_create(sc->arge_cdata.arge_tx_tag, 0,
- &txd->tx_dmamap);
- if (error != 0) {
- device_printf(sc->arge_dev,
- "failed to create Tx dmamap\n");
- goto fail;
- }
- }
- /* Create DMA maps for Rx buffers. */
- if ((error = bus_dmamap_create(sc->arge_cdata.arge_rx_tag, 0,
- &sc->arge_cdata.arge_rx_sparemap)) != 0) {
- device_printf(sc->arge_dev,
- "failed to create spare Rx dmamap\n");
- goto fail;
- }
- for (i = 0; i < ARGE_RX_RING_COUNT; i++) {
- rxd = &sc->arge_cdata.arge_rxdesc[i];
- rxd->rx_m = NULL;
- rxd->rx_dmamap = NULL;
- error = bus_dmamap_create(sc->arge_cdata.arge_rx_tag, 0,
- &rxd->rx_dmamap);
- if (error != 0) {
- device_printf(sc->arge_dev,
- "failed to create Rx dmamap\n");
- goto fail;
- }
- }
-
-fail:
- return (error);
-}
-
-static void
-arge_dma_free(struct arge_softc *sc)
-{
- struct arge_txdesc *txd;
- struct arge_rxdesc *rxd;
- int i;
-
- /* Tx ring. */
- if (sc->arge_cdata.arge_tx_ring_tag) {
- if (sc->arge_cdata.arge_tx_ring_map)
- bus_dmamap_unload(sc->arge_cdata.arge_tx_ring_tag,
- sc->arge_cdata.arge_tx_ring_map);
- if (sc->arge_cdata.arge_tx_ring_map &&
- sc->arge_rdata.arge_tx_ring)
- bus_dmamem_free(sc->arge_cdata.arge_tx_ring_tag,
- sc->arge_rdata.arge_tx_ring,
- sc->arge_cdata.arge_tx_ring_map);
- sc->arge_rdata.arge_tx_ring = NULL;
- sc->arge_cdata.arge_tx_ring_map = NULL;
- bus_dma_tag_destroy(sc->arge_cdata.arge_tx_ring_tag);
- sc->arge_cdata.arge_tx_ring_tag = NULL;
- }
- /* Rx ring. */
- if (sc->arge_cdata.arge_rx_ring_tag) {
- if (sc->arge_cdata.arge_rx_ring_map)
- bus_dmamap_unload(sc->arge_cdata.arge_rx_ring_tag,
- sc->arge_cdata.arge_rx_ring_map);
- if (sc->arge_cdata.arge_rx_ring_map &&
- sc->arge_rdata.arge_rx_ring)
- bus_dmamem_free(sc->arge_cdata.arge_rx_ring_tag,
- sc->arge_rdata.arge_rx_ring,
- sc->arge_cdata.arge_rx_ring_map);
- sc->arge_rdata.arge_rx_ring = NULL;
- sc->arge_cdata.arge_rx_ring_map = NULL;
- bus_dma_tag_destroy(sc->arge_cdata.arge_rx_ring_tag);
- sc->arge_cdata.arge_rx_ring_tag = NULL;
- }
- /* Tx buffers. */
- if (sc->arge_cdata.arge_tx_tag) {
- for (i = 0; i < ARGE_TX_RING_COUNT; i++) {
- txd = &sc->arge_cdata.arge_txdesc[i];
- if (txd->tx_dmamap) {
- bus_dmamap_destroy(sc->arge_cdata.arge_tx_tag,
- txd->tx_dmamap);
- txd->tx_dmamap = NULL;
- }
- }
- bus_dma_tag_destroy(sc->arge_cdata.arge_tx_tag);
- sc->arge_cdata.arge_tx_tag = NULL;
- }
- /* Rx buffers. */
- if (sc->arge_cdata.arge_rx_tag) {
- for (i = 0; i < ARGE_RX_RING_COUNT; i++) {
- rxd = &sc->arge_cdata.arge_rxdesc[i];
- if (rxd->rx_dmamap) {
- bus_dmamap_destroy(sc->arge_cdata.arge_rx_tag,
- rxd->rx_dmamap);
- rxd->rx_dmamap = NULL;
- }
- }
- if (sc->arge_cdata.arge_rx_sparemap) {
- bus_dmamap_destroy(sc->arge_cdata.arge_rx_tag,
- sc->arge_cdata.arge_rx_sparemap);
- sc->arge_cdata.arge_rx_sparemap = 0;
- }
- bus_dma_tag_destroy(sc->arge_cdata.arge_rx_tag);
- sc->arge_cdata.arge_rx_tag = NULL;
- }
-
- if (sc->arge_cdata.arge_parent_tag) {
- bus_dma_tag_destroy(sc->arge_cdata.arge_parent_tag);
- sc->arge_cdata.arge_parent_tag = NULL;
- }
-}
-
-/*
- * Initialize the transmit descriptors.
- */
-static int
-arge_tx_ring_init(struct arge_softc *sc)
-{
- struct arge_ring_data *rd;
- struct arge_txdesc *txd;
- bus_addr_t addr;
- int i;
-
- sc->arge_cdata.arge_tx_prod = 0;
- sc->arge_cdata.arge_tx_cons = 0;
- sc->arge_cdata.arge_tx_cnt = 0;
- sc->arge_cdata.arge_tx_pkts = 0;
-
- rd = &sc->arge_rdata;
- bzero(rd->arge_tx_ring, sizeof(rd->arge_tx_ring));
- for (i = 0; i < ARGE_TX_RING_COUNT; i++) {
- if (i == ARGE_TX_RING_COUNT - 1)
- addr = ARGE_TX_RING_ADDR(sc, 0);
- else
- addr = ARGE_TX_RING_ADDR(sc, i + 1);
- rd->arge_tx_ring[i].packet_ctrl = ARGE_DESC_EMPTY;
- rd->arge_tx_ring[i].next_desc = addr;
- txd = &sc->arge_cdata.arge_txdesc[i];
- txd->tx_m = NULL;
- }
-
- bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag,
- sc->arge_cdata.arge_tx_ring_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- return (0);
-}
-
-/*
- * Initialize the RX descriptors and allocate mbufs for them. Note that
- * we arrange the descriptors in a closed ring, so that the last descriptor
- * points back to the first.
- */
-static int
-arge_rx_ring_init(struct arge_softc *sc)
-{
- struct arge_ring_data *rd;
- struct arge_rxdesc *rxd;
- bus_addr_t addr;
- int i;
-
- sc->arge_cdata.arge_rx_cons = 0;
-
- rd = &sc->arge_rdata;
- bzero(rd->arge_rx_ring, sizeof(rd->arge_rx_ring));
- for (i = 0; i < ARGE_RX_RING_COUNT; i++) {
- rxd = &sc->arge_cdata.arge_rxdesc[i];
- rxd->rx_m = NULL;
- rxd->desc = &rd->arge_rx_ring[i];
- if (i == ARGE_RX_RING_COUNT - 1)
- addr = ARGE_RX_RING_ADDR(sc, 0);
- else
- addr = ARGE_RX_RING_ADDR(sc, i + 1);
- rd->arge_rx_ring[i].packet_ctrl = ARGE_DESC_EMPTY;
- rd->arge_rx_ring[i].next_desc = addr;
- if (arge_newbuf(sc, i) != 0)
- return (ENOBUFS);
- }
-
- bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag,
- sc->arge_cdata.arge_rx_ring_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
-
- return (0);
-}
-
-/*
- * Initialize an RX descriptor and attach an MBUF cluster.
- */
-static int
-arge_newbuf(struct arge_softc *sc, int idx)
-{
- struct arge_desc *desc;
- struct arge_rxdesc *rxd;
- struct mbuf *m;
- bus_dma_segment_t segs[1];
- bus_dmamap_t map;
- int nsegs;
-
- m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
- if (m == NULL)
- return (ENOBUFS);
- m->m_len = m->m_pkthdr.len = MCLBYTES;
- m_adj(m, sizeof(uint64_t));
-
- if (bus_dmamap_load_mbuf_sg(sc->arge_cdata.arge_rx_tag,
- sc->arge_cdata.arge_rx_sparemap, m, segs, &nsegs, 0) != 0) {
- m_freem(m);
- return (ENOBUFS);
- }
- KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
-
- rxd = &sc->arge_cdata.arge_rxdesc[idx];
- if (rxd->rx_m != NULL) {
- bus_dmamap_sync(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap,
- BUS_DMASYNC_POSTREAD);
- bus_dmamap_unload(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap);
- }
- map = rxd->rx_dmamap;
- rxd->rx_dmamap = sc->arge_cdata.arge_rx_sparemap;
- sc->arge_cdata.arge_rx_sparemap = map;
- bus_dmamap_sync(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap,
- BUS_DMASYNC_PREREAD);
- rxd->rx_m = m;
- desc = rxd->desc;
- desc->packet_addr = segs[0].ds_addr;
- desc->packet_ctrl = (desc->packet_ctrl & ~ARGE_DESC_SIZE_MASK)
- | ARGE_DMASIZE(segs[0].ds_len);
-
- return (0);
-}
-
-static __inline void
-arge_fixup_rx(struct mbuf *m)
-{
- int i;
- uint16_t *src, *dst;
-
- src = mtod(m, uint16_t *);
- dst = src - 1;
-
- for (i = 0; i < (m->m_len / sizeof(uint16_t) + 1); i++)
- *dst++ = *src++;
-
- m->m_data -= ETHER_ALIGN;
-}
-
-
-static void
-arge_tx_locked(struct arge_softc *sc)
-{
- struct arge_txdesc *txd;
- struct arge_desc *cur_tx;
- struct ifnet *ifp;
- uint32_t ctrl;
- int cons, prod;
-
- ARGE_LOCK_ASSERT(sc);
-
- cons = sc->arge_cdata.arge_tx_cons;
- prod = sc->arge_cdata.arge_tx_prod;
- if (cons == prod)
- return;
-
- bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag,
- sc->arge_cdata.arge_tx_ring_map,
- BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
-
- ifp = sc->arge_ifp;
- /*
- * Go through our tx list and free mbufs for those
- * frames that have been transmitted.
- */
- for (; cons != prod; ARGE_INC(cons, ARGE_TX_RING_COUNT)) {
- cur_tx = &sc->arge_rdata.arge_tx_ring[cons];
- ctrl = cur_tx->packet_ctrl;
- /* Check if descriptor has "finished" flag */
- if ((ctrl & ARGE_DESC_EMPTY) == 0)
- break;
-
- ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_PKT_SENT);
-
- sc->arge_cdata.arge_tx_cnt--;
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-
- txd = &sc->arge_cdata.arge_txdesc[cons];
-
- cur_tx->packet_ctrl = ARGE_DESC_EMPTY;
-
- ifp->if_opackets++;
-
- bus_dmamap_sync(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap,
- BUS_DMASYNC_POSTWRITE);
- bus_dmamap_unload(sc->arge_cdata.arge_tx_tag, txd->tx_dmamap);
-
- /* Free only if it's first descriptor in list */
- if (txd->tx_m)
- m_freem(txd->tx_m);
- txd->tx_m = NULL;
-
- /* reset descriptor */
- cur_tx->packet_ctrl = ARGE_DESC_EMPTY;
- cur_tx->packet_addr = 0;
- }
-
- sc->arge_cdata.arge_tx_cons = cons;
-
- bus_dmamap_sync(sc->arge_cdata.arge_tx_ring_tag,
- sc->arge_cdata.arge_tx_ring_map, BUS_DMASYNC_PREWRITE);
-}
-
-
-static void
-arge_rx_locked(struct arge_softc *sc)
-{
- struct arge_rxdesc *rxd;
- struct ifnet *ifp = sc->arge_ifp;
- int cons, prog, packet_len;
- struct arge_desc *cur_rx;
- struct mbuf *m;
-
- ARGE_LOCK_ASSERT(sc);
-
- cons = sc->arge_cdata.arge_rx_cons;
-
- bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag,
- sc->arge_cdata.arge_rx_ring_map,
- BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
-
- for (prog = 0; prog < ARGE_RX_RING_COUNT;
- ARGE_INC(cons, ARGE_RX_RING_COUNT)) {
- cur_rx = &sc->arge_rdata.arge_rx_ring[cons];
- rxd = &sc->arge_cdata.arge_rxdesc[cons];
- m = rxd->rx_m;
-
- if ((cur_rx->packet_ctrl & ARGE_DESC_EMPTY) != 0)
- break;
-
- ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_PKT_RECVD);
-
- prog++;
-
- packet_len = ARGE_DMASIZE(cur_rx->packet_ctrl);
- bus_dmamap_sync(sc->arge_cdata.arge_rx_tag, rxd->rx_dmamap,
- BUS_DMASYNC_PREREAD);
- m = rxd->rx_m;
-
- arge_fixup_rx(m);
- m->m_pkthdr.rcvif = ifp;
- /* Skip 4 bytes of CRC */
- m->m_pkthdr.len = m->m_len = packet_len - ETHER_CRC_LEN;
- ifp->if_ipackets++;
-
- ARGE_UNLOCK(sc);
- (*ifp->if_input)(ifp, m);
- ARGE_LOCK(sc);
-
- /* Reinit descriptor */
- cur_rx->packet_ctrl = ARGE_DESC_EMPTY;
- cur_rx->packet_addr = 0;
- if (arge_newbuf(sc, cons) != 0) {
- device_printf(sc->arge_dev,
- "Failed to allocate buffer\n");
- break;
- }
-
- bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag,
- sc->arge_cdata.arge_rx_ring_map,
- BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
-
- }
-
- if (prog > 0) {
- sc->arge_cdata.arge_rx_cons = cons;
-
- bus_dmamap_sync(sc->arge_cdata.arge_rx_ring_tag,
- sc->arge_cdata.arge_rx_ring_map,
- BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
- }
-}
-
-static void
-arge_rx_intr(struct arge_softc *sc, uint32_t status)
-{
-
- ARGE_LOCK(sc);
- /* interrupts are masked by filter */
- arge_rx_locked(sc);
-
- /* unmask interrupts */
- ARGE_SET_BITS(sc,
- AR71XX_DMA_INTR, DMA_INTR_RX_OVERFLOW | DMA_INTR_RX_PKT_RCVD);
- ARGE_UNLOCK(sc);
-}
-
-static int
-arge_intr_filter(void *arg)
-{
- struct arge_softc *sc = arg;
- uint32_t status, ints;
-
- status = ARGE_READ(sc, AR71XX_DMA_INTR_STATUS);
- ints = ARGE_READ(sc, AR71XX_DMA_INTR);
-
-#if 0
- dprintf("int mask(filter) = %b\n", ints,
- "\20\10RX_BUS_ERROR\7RX_OVERFLOW\5RX_PKT_RCVD"
- "\4TX_BUS_ERROR\2TX_UNDERRUN\1TX_PKT_SENT");
- dprintf("status(filter) = %b\n", status,
- "\20\10RX_BUS_ERROR\7RX_OVERFLOW\5RX_PKT_RCVD"
- "\4TX_BUS_ERROR\2TX_UNDERRUN\1TX_PKT_SENT");
-#endif
-
- if (status & DMA_INTR_ALL) {
- if (status & (DMA_INTR_RX_PKT_RCVD | DMA_INTR_RX_OVERFLOW))
- ARGE_CLEAR_BITS(sc, AR71XX_DMA_INTR,
- DMA_INTR_RX_OVERFLOW | DMA_INTR_RX_PKT_RCVD);
-
- if (status & (DMA_INTR_TX_PKT_SENT | DMA_INTR_TX_UNDERRUN))
- ARGE_CLEAR_BITS(sc, AR71XX_DMA_INTR,
- DMA_INTR_TX_UNDERRUN | DMA_INTR_TX_PKT_SENT);
-
- sc->arge_intr_status = status;
- return (FILTER_SCHEDULE_THREAD);
- }
-
- sc->arge_intr_status = 0;
- return (FILTER_STRAY);
-}
-
-static void
-arge_intr(void *arg)
-{
- struct arge_softc *sc = arg;
- uint32_t status;
-
- status = sc->arge_intr_status;
-
-#if 0
- dprintf("int status(intr) = %b\n", status,
- "\20\10\7RX_OVERFLOW\5RX_PKT_RCVD"
- "\4TX_BUS_ERROR\2TX_UNDERRUN\1TX_PKT_SENT");
-#endif
-
- /*
- * Is it our interrupt at all?
- */
- if (status == 0)
- return;
-
- if (status & DMA_INTR_RX_BUS_ERROR) {
- ARGE_WRITE(sc, AR71XX_DMA_RX_STATUS, DMA_RX_STATUS_BUS_ERROR);
- device_printf(sc->arge_dev, "RX bus error");
- return;
- }
-
- if (status & DMA_INTR_TX_BUS_ERROR) {
- ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS, DMA_TX_STATUS_BUS_ERROR);
- device_printf(sc->arge_dev, "TX bus error");
- return;
- }
-
- if (status & (DMA_INTR_RX_PKT_RCVD | DMA_INTR_RX_OVERFLOW))
- arge_rx_intr(sc, status);
-
- if (status & (DMA_INTR_TX_PKT_SENT | DMA_INTR_TX_UNDERRUN))
- arge_tx_intr(sc, status);
-}
-
-static void
-arge_tx_intr(struct arge_softc *sc, uint32_t status)
-{
- ARGE_LOCK(sc);
-
- /* Interrupts are masked by filter */
- arge_tx_locked(sc);
-
- ARGE_UNLOCK(sc);
-}
-
-static void
-arge_tick(void *xsc)
-{
- struct arge_softc *sc = xsc;
- struct mii_data *mii;
-
- ARGE_LOCK_ASSERT(sc);
-
- mii = device_get_softc(sc->arge_miibus);
- mii_tick(mii);
- callout_reset(&sc->arge_stat_callout, hz, arge_tick, sc);
-}
-
-/*
- * Create a copy of a single mbuf. It can have either internal or
- * external data, it may have a packet header. External data is really
- * copied, so the new buffer is writeable.
- */
-static struct mbuf *
-copy_mbuf(struct mbuf *m)
-{
- struct mbuf *new;
-
- MGET(new, M_DONTWAIT, MT_DATA);
- if (new == NULL)
- return (NULL);
-
- if (m->m_flags & M_PKTHDR) {
- M_MOVE_PKTHDR(new, m);
- if (m->m_len > MHLEN)
- MCLGET(new, M_WAIT);
- } else {
- if (m->m_len > MLEN)
- MCLGET(new, M_WAIT);
- }
-
- bcopy(m->m_data, new->m_data, m->m_len);
- new->m_len = m->m_len;
- new->m_flags &= ~M_RDONLY;
-
- return (new);
-}
-
-
-
-static int
-arge_fix_chain(struct mbuf **mp)
-{
- struct mbuf *m = *mp, *prev = NULL, *next, *new;
- u_int mlen = 0, fill = 0;
- int first, off;
- u_char *d, *cp;
-
- do {
- next = m->m_next;
-
- if ((uintptr_t)mtod(m, void *) % 4 != 0 ||
- (m->m_len % 4 != 0 && next)) {
- /*
- * Needs fixing
- */
- first = (m == *mp);
-
- d = mtod(m, u_char *);
- if ((off = (uintptr_t)(void *)d % 4) != 0) {
- if (M_WRITABLE(m)) {
- bcopy(d, d - off, m->m_len);
- m->m_data = (caddr_t)(d - off);
- } else {
- if ((new = copy_mbuf(m)) == NULL) {
- goto fail;
- }
- if (prev)
- prev->m_next = new;
- new->m_next = next;
- m_free(m);
- m = new;
- }
- }
-
- if ((off = m->m_len % 4) != 0) {
- if (!M_WRITABLE(m)) {
- if ((new = copy_mbuf(m)) == NULL) {
- goto fail;
- }
- if (prev)
- prev->m_next = new;
- new->m_next = next;
- m_free(m);
- m = new;
- }
- d = mtod(m, u_char *) + m->m_len;
- off = 4 - off;
- while (off) {
- if (next == NULL) {
- *d++ = 0;
- fill++;
- } else if (next->m_len == 0) {
- next = m_free(next);
- continue;
- } else {
- cp = mtod(next, u_char *);
- *d++ = *cp++;
- next->m_len--;
- next->m_data = (caddr_t)cp;
- }
- off--;
- m->m_len++;
- }
- }
-
- if (first)
- *mp = m;
- }
-
- mlen += m->m_len;
- prev = m;
- } while ((m = next) != NULL);
-
- return (mlen - fill);
-
- fail:
- m_freem(*mp);
- *mp = NULL;
- return (0);
-}
diff --git a/sys/mips/atheros/if_argevar.h b/sys/mips/atheros/if_argevar.h
deleted file mode 100644
index 1966e61..0000000
--- a/sys/mips/atheros/if_argevar.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*-
- * Copyright (c) 2009, Oleksandr Tymoshenko
- * 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 unmodified, 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.
- */
-
-#ifndef __IF_ARGEVAR_H__
-#define __IF_ARGEVAR_H__
-
-#define ARGE_TX_RING_COUNT 128
-#define ARGE_RX_RING_COUNT 128
-#define ARGE_RX_DMA_SIZE ARGE_RX_RING_COUNT * sizeof(struct arge_desc)
-#define ARGE_TX_DMA_SIZE ARGE_TX_RING_COUNT * sizeof(struct arge_desc)
-#define ARGE_MAXFRAGS 8
-#define ARGE_RING_ALIGN sizeof(struct arge_desc)
-#define ARGE_RX_ALIGN sizeof(uint32_t)
-#define ARGE_MAXFRAGS 8
-#define ARGE_TX_RING_ADDR(sc, i) \
- ((sc)->arge_rdata.arge_tx_ring_paddr + sizeof(struct arge_desc) * (i))
-#define ARGE_RX_RING_ADDR(sc, i) \
- ((sc)->arge_rdata.arge_rx_ring_paddr + sizeof(struct arge_desc) * (i))
-#define ARGE_INC(x,y) (x) = (((x) + 1) % y)
-
-
-#define ARGE_MII_TIMEOUT 1000
-
-#define ARGE_LOCK(_sc) mtx_lock(&(_sc)->arge_mtx)
-#define ARGE_UNLOCK(_sc) mtx_unlock(&(_sc)->arge_mtx)
-#define ARGE_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->arge_mtx, MA_OWNED)
-
-/*
- * register space access macros
- */
-#define ARGE_WRITE(sc, reg, val) do { \
- bus_write_4(sc->arge_res, (reg), (val)); \
- } while (0)
-
-#define ARGE_READ(sc, reg) bus_read_4(sc->arge_res, (reg))
-
-#define ARGE_SET_BITS(sc, reg, bits) \
- ARGE_WRITE(sc, reg, ARGE_READ(sc, (reg)) | (bits))
-
-#define ARGE_CLEAR_BITS(sc, reg, bits) \
- ARGE_WRITE(sc, reg, ARGE_READ(sc, (reg)) & ~(bits))
-
-#define ARGE_DESC_EMPTY (1 << 31)
-#define ARGE_DESC_MORE (1 << 24)
-#define ARGE_DESC_SIZE_MASK ((1 << 12) - 1)
-#define ARGE_DMASIZE(len) ((len) & ARGE_DESC_SIZE_MASK)
-struct arge_desc {
- uint32_t packet_addr;
- uint32_t packet_ctrl;
- uint32_t next_desc;
- uint32_t padding;
-};
-
-struct arge_txdesc {
- struct mbuf *tx_m;
- bus_dmamap_t tx_dmamap;
-};
-
-struct arge_rxdesc {
- struct mbuf *rx_m;
- bus_dmamap_t rx_dmamap;
- struct arge_desc *desc;
-};
-
-struct arge_chain_data {
- bus_dma_tag_t arge_parent_tag;
- bus_dma_tag_t arge_tx_tag;
- struct arge_txdesc arge_txdesc[ARGE_TX_RING_COUNT];
- bus_dma_tag_t arge_rx_tag;
- struct arge_rxdesc arge_rxdesc[ARGE_RX_RING_COUNT];
- bus_dma_tag_t arge_tx_ring_tag;
- bus_dma_tag_t arge_rx_ring_tag;
- bus_dmamap_t arge_tx_ring_map;
- bus_dmamap_t arge_rx_ring_map;
- bus_dmamap_t arge_rx_sparemap;
- int arge_tx_pkts;
- int arge_tx_prod;
- int arge_tx_cons;
- int arge_tx_cnt;
- int arge_rx_cons;
-};
-
-struct arge_ring_data {
- struct arge_desc *arge_rx_ring;
- struct arge_desc *arge_tx_ring;
- bus_addr_t arge_rx_ring_paddr;
- bus_addr_t arge_tx_ring_paddr;
-};
-
-struct arge_softc {
- struct ifnet *arge_ifp; /* interface info */
- device_t arge_dev;
- struct resource *arge_res;
- int arge_rid;
- struct resource *arge_irq;
- void *arge_intrhand;
- device_t arge_miibus;
- bus_dma_tag_t arge_parent_tag;
- bus_dma_tag_t arge_tag;
- struct mtx arge_mtx;
- struct callout arge_stat_callout;
- struct task arge_link_task;
- struct arge_chain_data arge_cdata;
- struct arge_ring_data arge_rdata;
- int arge_link_status;
- int arge_detach;
- uint32_t arge_intr_status;
- int arge_mac_unit;
- int arge_phy_num;
- uint32_t arge_ddr_flush_reg;
- uint32_t arge_pll_reg;
-};
-
-#endif /* __IF_ARGEVAR_H__ */
diff --git a/sys/mips/atheros/uart_bus_ar71xx.c b/sys/mips/atheros/uart_bus_ar71xx.c
deleted file mode 100644
index 1cb611c..0000000
--- a/sys/mips/atheros/uart_bus_ar71xx.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/*-
- * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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
- */
-#include "opt_uart.h"
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/kernel.h>
-#include <sys/module.h>
-
-#include <machine/bus.h>
-
-#include <dev/uart/uart.h>
-#include <dev/uart/uart_cpu.h>
-#include <dev/uart/uart_bus.h>
-
-#include <mips/atheros/ar71xxreg.h>
-
-#include "uart_if.h"
-
-static int uart_ar71xx_probe(device_t dev);
-extern struct uart_class uart_ar71xx_uart_class;
-
-static device_method_t uart_ar71xx_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, uart_ar71xx_probe),
- DEVMETHOD(device_attach, uart_bus_attach),
- DEVMETHOD(device_detach, uart_bus_detach),
- { 0, 0 }
-};
-
-static driver_t uart_ar71xx_driver = {
- uart_driver_name,
- uart_ar71xx_methods,
- sizeof(struct uart_softc),
-};
-
-extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
-
-static int
-uart_ar71xx_probe(device_t dev)
-{
- struct uart_softc *sc;
-
- sc = device_get_softc(dev);
- sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs);
- sc->sc_class = &uart_ns8250_class;
- bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas));
-
- return (uart_bus_probe(dev, 2, 85000000, 0, 0));
-}
-
-DRIVER_MODULE(uart, apb, uart_ar71xx_driver, uart_devclass, 0, 0);
diff --git a/sys/mips/conf/ADM5120 b/sys/mips/conf/ADM5120
index 7a47abe..a03d102 100644
--- a/sys/mips/conf/ADM5120
+++ b/sys/mips/conf/ADM5120
@@ -25,6 +25,7 @@ makeoptions MIPS_LITTLE_ENDIAN=defined
# Don't build any modules yet.
makeoptions MODULES_OVERRIDE=""
+options KERNVIRTADDR=0x80100000
include "../adm5120/std.adm5120"
hints "ADM5120.hints" #Default places to look for devices.
diff --git a/sys/mips/conf/ALCHEMY b/sys/mips/conf/ALCHEMY
deleted file mode 100644
index c1fb59a..0000000
--- a/sys/mips/conf/ALCHEMY
+++ /dev/null
@@ -1,66 +0,0 @@
-# ALCHEMY -- Generic kernel for Alchemy Au1xxx CPUs.
-#
-# For more information on this file, please read the handbook section on
-# Kernel Configuration Files:
-#
-# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
-#
-# The handbook is also available locally in /usr/share/doc/handbook
-# if you've installed the doc distribution, otherwise always see the
-# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
-# latest information.
-#
-# An exhaustive list of options and more detailed explanations of the
-# device lines is also present in the ../../conf/NOTES and NOTES files.
-# If you are in doubt as to the purpose or necessity of a line, check first
-# in NOTES.
-#
-# $FreeBSD$
-
-ident ALCHEMY
-
-makeoptions ARCH_FLAGS=-march=mips32
-makeoptions MIPS_LITTLE_ENDIAN=defined
-
-# Don't build any modules yet.
-makeoptions MODULES_OVERRIDE=""
-
-include "../alchemy/std.alchemy"
-
-hints "ALCHEMY.hints" #Default places to look for devices.
-
-makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
-
-options DDB
-options KDB
-
-options SCHED_4BSD #4BSD scheduler
-options INET #InterNETworking
-options NFSCLIENT #Network Filesystem Client
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
-options PSEUDOFS #Pseudo-filesystem framework
-# options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
-
-options BOOTP
-options BOOTP_NFSROOT
-options BOOTP_NFSV3
-options BOOTP_WIRED_TO=admsw0
-options BOOTP_COMPAT
-
-# options FFS #Berkeley Fast Filesystem
-# options SOFTUPDATES #Enable FFS soft updates support
-# options UFS_ACL #Support for access control lists
-# options UFS_DIRHASH #Improve performance on big directories
-options ROOTDEVNAME=\"nfs:10.0.0.1:/mnt/bsd\"
-
-
-# Debugging for use in -current
-options INVARIANTS #Enable calls of extra sanity checking
-options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS
-#options WITNESS #Enable checks to detect deadlocks and cycles
-#options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed
-
-device loop
-device ether
-device uart
-# device md
diff --git a/sys/mips/conf/AR71XX b/sys/mips/conf/AR71XX
deleted file mode 100644
index 936d0f1..0000000
--- a/sys/mips/conf/AR71XX
+++ /dev/null
@@ -1,37 +0,0 @@
-#
-# $FreeBSD$
-#
-
-ident AR71XX
-cpu CPU_MIPS4KC
-options CPU_NOFPU
-options ISA_MIPS32
-makeoptions TARGET_BIG_ENDIAN
-makeoptions KERNLOADADDR=0x80050000
-
-files "../atheros/files.ar71xx"
-hints "AR71XX.hints"
-
-makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
-makeoptions MODULES_OVERRIDE=""
-
-options DDB
-options KDB
-
-options SCHED_4BSD #4BSD scheduler
-options INET #InterNETworking
-options NFSCLIENT #Network Filesystem Client
-options NFS_ROOT #NFS usable as /, requires NFSCLIENT
-options PSEUDOFS #Pseudo-filesystem framework
-options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions
-
-# Debugging for use in -current
-options INVARIANTS
-options INVARIANT_SUPPORT
-
-device pci
-device uart
-
-device loop
-device ether
-device md
diff --git a/sys/mips/conf/AR71XX.hints b/sys/mips/conf/AR71XX.hints
deleted file mode 100644
index 58fbdde..0000000
--- a/sys/mips/conf/AR71XX.hints
+++ /dev/null
@@ -1,25 +0,0 @@
-# $FreeBSD$
-hint.apb.0.at="nexus0"
-hint.apb.0.maddr=0x18000000
-hint.apb.0.msize=0x01000000
-hint.apb.0.irq=4
-
-# uart0
-hint.uart.0.at="apb0"
-# see atheros/uart_cpu_ar71xx.c why +3
-hint.uart.0.maddr=0x18020003
-hint.uart.0.msize=0x18
-hint.uart.0.irq=3
-
-# pci
-hint.pcib.0.at="nexus0"
-hint.pcib.0.irq=0
-
-hint.arge.0.at="nexus0"
-hint.arge.0.maddr=0x19000000
-hint.arge.0.msize=0x1000
-hint.arge.0.irq=2
-# hint.arge.1.at="nexus0"
-# hint.arge.1.maddr=0x1A000000
-# hint.arge.1.msize=0x1000
-# hint.arge.1.irq=3
diff --git a/sys/mips/conf/MALTA b/sys/mips/conf/MALTA
index 022cc52..9771c55 100644
--- a/sys/mips/conf/MALTA
+++ b/sys/mips/conf/MALTA
@@ -27,6 +27,7 @@ options YAMON
# Don't build any modules yet.
makeoptions MODULES_OVERRIDE=""
+options KERNVIRTADDR=0x80100000
options TICK_USE_YAMON_FREQ=defined
#options TICK_USE_MALTA_RTC=defined
diff --git a/sys/mips/conf/QEMU b/sys/mips/conf/QEMU
index bc7d649..0a2b122 100644
--- a/sys/mips/conf/QEMU
+++ b/sys/mips/conf/QEMU
@@ -27,6 +27,7 @@ makeoptions ARCH_FLAGS=-march=mips32
# Don't build any modules yet.
makeoptions MODULES_OVERRIDE=""
+options KERNVIRTADDR=0x80100000
include "../adm5120/std.adm5120"
#hints "GENERIC.hints" #Default places to look for devices.
diff --git a/sys/mips/conf/SENTRY5 b/sys/mips/conf/SENTRY5
index c3918e2..7611e44 100644
--- a/sys/mips/conf/SENTRY5
+++ b/sys/mips/conf/SENTRY5
@@ -41,6 +41,13 @@ options CFE
options CFE_CONSOLE
options ALT_BREAK_TO_DEBUGGER
+# cfe loader expects kernel at 0x80001000 for mips32 w/o backwards
+# offsets in the linked elf image (see ldscript hack)
+# XXX can we conditionalize the linker stuff on options CFE?
+options KERNVIRTADDR=0x80001000
+
+makeoptions LDSCRIPT_NAME= ldscript.mips.cfe
+
#makeoptions ARCH_FLAGS=-march=mips32
makeoptions MIPS_LITTLE_ENDIAN=defined
makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols
@@ -66,8 +73,8 @@ options INVARIANT_SUPPORT
device siba # Sonics SiliconBackplane
device pci # siba_pcib
-# device bfe # XXX will build both pci and siba
-# device miibus # attachments
+device bfe # XXX will build both pci and siba
+device miibus # attachments
# pci devices
# notyet:
diff --git a/sys/mips/include/bus.h b/sys/mips/include/bus.h
index 42ac1df..92557d7 100644
--- a/sys/mips/include/bus.h
+++ b/sys/mips/include/bus.h
@@ -101,8 +101,9 @@
* Map a region of device bus space into CPU virtual address space.
*/
-__inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
- bus_size_t size, int flags, bus_space_handle_t *bshp);
+static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
+ bus_size_t size, int flags,
+ bus_space_handle_t *bshp);
static __inline int
bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr,
diff --git a/sys/mips/include/elf.h b/sys/mips/include/elf.h
index 6e48ec1..3a31daa 100644
--- a/sys/mips/include/elf.h
+++ b/sys/mips/include/elf.h
@@ -241,15 +241,13 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused for i386). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-/*
- * The following non-standard values are used in Linux ELF binaries.
- */
#define AT_NOTELF 10 /* Program is not ELF ?? */
#define AT_UID 11 /* Real uid. */
#define AT_EUID 12 /* Effective uid. */
#define AT_GID 13 /* Real gid. */
#define AT_EGID 14 /* Effective gid. */
+#define AT_EXECPATH 15 /* Path to the executable. */
-#define AT_COUNT 15 /* Count of defined aux entry types. */
+#define AT_COUNT 16 /* Count of defined aux entry types. */
#endif /* !_MACHINE_ELF_H_ */
diff --git a/sys/mips/mips/elf64_machdep.c b/sys/mips/mips/elf64_machdep.c
index e5a2f5d..c10fb5f 100644
--- a/sys/mips/mips/elf64_machdep.c
+++ b/sys/mips/mips/elf64_machdep.c
@@ -88,7 +88,8 @@ static Elf64_Brandinfo freebsd_brand_gnutools_info64 = {
.interp_path = "/libexec/ld-elf.so.1",
.sysvec = &elf64_freebsd_sysvec,
.interp_path = "/libexec/ld-elf.so.1",
- .flags = BI_CAN_EXEC_DYN
+ .brand_note = &elf64_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(gnu_mips_elf64, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -103,7 +104,8 @@ static Elf64_Brandinfo freebsd_brand_info64 = {
.interp_path = "/libexec/ld-elf.so.1",
.sysvec = &elf64_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = 0
+ .brand_note = &elf64_freebsd_brandnote,
+ .flags = BI_BRAND_NOTE
};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
diff --git a/sys/mips/mips/elf_machdep.c b/sys/mips/mips/elf_machdep.c
index 163d0ee..19cb1a1 100644
--- a/sys/mips/mips/elf_machdep.c
+++ b/sys/mips/mips/elf_machdep.c
@@ -86,7 +86,8 @@ static Elf32_Brandinfo freebsd_brand_info = {
.interp_path = "/libexec/ld-elf.so.1",
.sysvec = &elf32_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = 0
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_BRAND_NOTE
};
SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
diff --git a/sys/mips/mips/elf_trampoline.c b/sys/mips/mips/elf_trampoline.c
deleted file mode 100644
index 0f2ccc9..0000000
--- a/sys/mips/mips/elf_trampoline.c
+++ /dev/null
@@ -1,133 +0,0 @@
-/*-
- * Copyright (c) 2005 Olivier Houchard. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR 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 <machine/asm.h>
-#include <sys/param.h>
-#include <sys/elf32.h>
-#include <sys/inflate.h>
-#include <machine/elf.h>
-#include <machine/cpufunc.h>
-#include <machine/stdarg.h>
-
-/*
- * Since we are compiled outside of the normal kernel build process, we
- * need to include opt_global.h manually.
- */
-#include "opt_global.h"
-#include "opt_kernname.h"
-
-extern char kernel_start[];
-extern char kernel_end[];
-
-static __inline void *
-memcpy(void *dst, const void *src, int len)
-{
- const char *s = src;
- char *d = dst;
-
- while (len) {
- if (0 && len >= 4 && !((vm_offset_t)d & 3) &&
- !((vm_offset_t)s & 3)) {
- *(uint32_t *)d = *(uint32_t *)s;
- s += 4;
- d += 4;
- len -= 4;
- } else {
- *d++ = *s++;
- len--;
- }
- }
- return (dst);
-}
-
-static __inline void
-bzero(void *addr, int count)
-{
- char *tmp = (char *)addr;
-
- while (count > 0) {
- if (count >= 4 && !((vm_offset_t)tmp & 3)) {
- *(uint32_t *)tmp = 0;
- tmp += 4;
- count -= 4;
- } else {
- *tmp = 0;
- tmp++;
- count--;
- }
- }
-}
-
-/*
- * Relocate PT_LOAD segements of kernel ELF image to their respective
- * virtual addresses and return entry point
- */
-void *
-load_kernel(void * kstart)
-{
- Elf32_Ehdr *eh;
- Elf32_Phdr phdr[64] /* XXX */;
- int i;
- void *entry_point;
-
- eh = (Elf32_Ehdr *)kstart;
- entry_point = (void*)eh->e_entry;
- memcpy(phdr, (void *)(kstart + eh->e_phoff ),
- eh->e_phnum * sizeof(phdr[0]));
-
- for (i = 0; i < eh->e_phnum; i++) {
- volatile char c;
-
- if (phdr[i].p_type != PT_LOAD)
- continue;
-
- memcpy((void *)(phdr[i].p_vaddr),
- (void*)(kstart + phdr[i].p_offset), phdr[i].p_filesz);
- /* Clean space from oversized segments, eg: bss. */
- if (phdr[i].p_filesz < phdr[i].p_memsz)
- bzero((void *)(phdr[i].p_vaddr + phdr[i].p_filesz),
- phdr[i].p_memsz - phdr[i].p_filesz);
- }
-
- return entry_point;
-}
-
-void
-_startC(register_t a0, register_t a1, register_t a2, register_t a3)
-{
- unsigned int * code;
- int i;
- void (*entry_point)(register_t, register_t, register_t, register_t);
-
- /*
- * Relocate segment to the predefined memory location
- * Most likely it will be KSEG0/KSEG1 address
- */
- entry_point = load_kernel(kernel_start);
-
- /* Pass saved registers to original _start */
- entry_point(a0, a1, a2, a3);
-}
diff --git a/sys/mips/mips/inckern.S b/sys/mips/mips/inckern.S
deleted file mode 100644
index 8610196..0000000
--- a/sys/mips/mips/inckern.S
+++ /dev/null
@@ -1,34 +0,0 @@
-/*-
- * Copyright (c) 2005 Olivier Houchard. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR 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 "opt_kernname.h"
-
-#include <machine/asm.h>
-__FBSDID("$FreeBSD$")
-.section ".real_kernel","aw"
-.globl kernel_start;
-kernel_start:
-.incbin KERNNAME
-.globl kernel_end;
-kernel_end:
diff --git a/sys/mips/mips/nexus.c b/sys/mips/mips/nexus.c
index e96eeab..64cba66 100644
--- a/sys/mips/mips/nexus.c
+++ b/sys/mips/mips/nexus.c
@@ -249,8 +249,6 @@ nexus_hinted_child(device_t bus, const char *dname, int dunit)
long maddr;
int msize;
int result;
- int irq;
- int mem_hints_count;
child = BUS_ADD_CHILD(bus, 0, dname, dunit);
@@ -258,34 +256,17 @@ nexus_hinted_child(device_t bus, const char *dname, int dunit)
* Set hard-wired resources for hinted child using
* specific RIDs.
*/
- mem_hints_count = 0;
- if (resource_long_value(dname, dunit, "maddr", &maddr) == 0)
- mem_hints_count++;
- if (resource_int_value(dname, dunit, "msize", &msize) == 0)
- mem_hints_count++;
-
- /* check if all info for mem resource has been provided */
- if ((mem_hints_count > 0) && (mem_hints_count < 2)) {
- printf("Either maddr or msize hint is missing for %s%d\n",
- dname, dunit);
- } else if (mem_hints_count) {
- dprintf("%s: discovered hinted child %s at maddr %p(%d)\n",
- __func__, device_get_nameunit(child),
- (void *)(intptr_t)maddr, msize);
-
- result = bus_set_resource(child, SYS_RES_MEMORY, MIPS_MEM_RID,
- maddr, msize);
- if (result != 0) {
- device_printf(bus,
- "warning: bus_set_resource() failed\n");
- }
- }
+ resource_long_value(dname, dunit, "maddr", &maddr);
+ resource_int_value(dname, dunit, "msize", &msize);
+
+ dprintf("%s: discovered hinted child %s at maddr %p(%d)\n",
+ __func__, device_get_nameunit(child),
+ (void *)(intptr_t)maddr, msize);
- if (resource_int_value(dname, dunit, "irq", &irq) == 0) {
- result = bus_set_resource(child, SYS_RES_IRQ, 0, irq, 1);
- if (result != 0)
- device_printf(bus,
- "warning: bus_set_resource() failed\n");
+ result = bus_set_resource(child, SYS_RES_MEMORY, MIPS_MEM_RID,
+ maddr, msize);
+ if (result != 0) {
+ device_printf(bus, "warning: bus_set_resource() failed\n");
}
}
diff --git a/sys/mips/sentry5/files.sentry5 b/sys/mips/sentry5/files.sentry5
index 7992509..61038e0 100644
--- a/sys/mips/sentry5/files.sentry5
+++ b/sys/mips/sentry5/files.sentry5
@@ -4,4 +4,11 @@
# for USB 1.1 OHCI, Ethernet and IPSEC cores
# which are believed to be devices we have drivers for
# which just need to be tweaked for attachment to an SSB system bus.
+
mips/sentry5/s5_machdep.c standard
+dev/siba/siba.c optional siba
+dev/siba/siba_pcib.c optional siba pci
+mips/sentry5/siba_cc.c optional siba
+
+# notyet
+#mips/sentry5/siba_mips.c optional siba
diff --git a/sys/dev/siba/siba_cc.c b/sys/mips/sentry5/siba_cc.c
index cd78f0b..cd78f0b 100644
--- a/sys/dev/siba/siba_cc.c
+++ b/sys/mips/sentry5/siba_cc.c
diff --git a/sys/dev/siba/siba_mips.c b/sys/mips/sentry5/siba_mips.c
index 676da83..676da83 100644
--- a/sys/dev/siba/siba_mips.c
+++ b/sys/mips/sentry5/siba_mips.c
diff --git a/sys/dev/siba/siba_sdram.c b/sys/mips/sentry5/siba_sdram.c
index 8e74e53..8e74e53 100644
--- a/sys/dev/siba/siba_sdram.c
+++ b/sys/mips/sentry5/siba_sdram.c
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index bb46b9c..969f704 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -18,12 +18,12 @@ SUBDIR= ${_3dfx} \
aic7xxx \
aio \
${_amd} \
+ ${_amdtemp} \
ale \
amr \
${_an} \
${_aout} \
${_apm} \
- ${_ar} \
${_arcmsr} \
${_arcnet} \
${_asmc} \
@@ -137,7 +137,6 @@ SUBDIR= ${_3dfx} \
${_ixgb} \
jme \
joy \
- ${_k8temp} \
kbdmux \
krpc \
le \
@@ -188,6 +187,7 @@ SUBDIR= ${_3dfx} \
nfsclient \
nfslockd \
nfsserver \
+ nfssvc \
nge \
nmdm \
${_nsp} \
@@ -219,7 +219,6 @@ SUBDIR= ${_3dfx} \
puc \
ral \
${_random} \
- ${_ray} \
rc4 \
${_rdma} \
re \
@@ -244,7 +243,6 @@ SUBDIR= ${_3dfx} \
${_speaker} \
${_splash} \
${_sppp} \
- ${_sr} \
ste \
${_stg} \
stge \
@@ -332,7 +330,6 @@ _amd= amd
_an= an
_aout= aout
_apm= apm
-_ar= ar
_arcnet= arcnet
_bktr= bktr
_cardbus= cardbus
@@ -385,7 +382,6 @@ _opensolaris= opensolaris
_pccard= pccard
_pcfclock= pcfclock
_pst= pst
-_ray= ray
_rdma= rdma
_safe= safe
_sbni= sbni
@@ -395,7 +391,6 @@ _sound= sound
_speaker= speaker
_splash= splash
_sppp= sppp
-_sr= sr
_stg= stg
_streams= streams
_svr4= svr4
@@ -409,6 +404,7 @@ _zfs= zfs
_aac= aac
_acpi= acpi
_ahb= ahb
+_amdtemp= amdtemp
_arcmsr= arcmsr
_asmc= asmc
_asr= asr
@@ -435,7 +431,6 @@ _iwifw= iwifw
_iwn= iwn
_iwnfw= iwnfw
_ixgb= ixgb
-_k8temp= k8temp
_mly= mly
_nfe= nfe
_nve= nve
@@ -464,6 +459,7 @@ _aac= aac
_acpi= acpi
_agp= agp
_an= an
+_amdtemp= amdtemp
_arcmsr= arcmsr
_asmc= asmc
_cardbus= cardbus
@@ -502,7 +498,6 @@ _ipwfw= ipwfw
_iwn= iwn
_iwnfw= iwnfw
_ixgb= ixgb
-_k8temp= k8temp
_linprocfs= linprocfs
_linsysfs= linsysfs
_linux= linux
@@ -587,6 +582,9 @@ _auxio= auxio
_em= em
_i2c= i2c
_igb= igb
+.if ${MK_CDDL} != "no" || defined(ALL_MODULES)
+_opensolaris= opensolaris
+.endif
_sound= sound
.if ${MK_ZFS} != "no" || defined(ALL_MODULES)
_zfs= zfs
diff --git a/sys/modules/amdtemp/Makefile b/sys/modules/amdtemp/Makefile
new file mode 100644
index 0000000..1f7cff5
--- /dev/null
+++ b/sys/modules/amdtemp/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/amdtemp
+
+KMOD= amdtemp
+SRCS= amdtemp.c bus_if.h device_if.h pci_if.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ath/Makefile b/sys/modules/ath/Makefile
index 068d337..d494c45 100644
--- a/sys/modules/ath/Makefile
+++ b/sys/modules/ath/Makefile
@@ -38,7 +38,7 @@ KMOD= if_ath
SRCS= if_ath.c if_ath_pci.c
# NB: v3 eeprom support used by both AR5211 and AR5212; just include it
SRCS+= ah_osdep.c ah.c ah_regdomain.c ah_eeprom_v3.c
-SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ath.h opt_ah.h
+SRCS+= device_if.h bus_if.h pci_if.h opt_inet.h opt_ath.h opt_ah.h opt_wlan.h
#
# AR5210 support; these are first generation 11a-only devices.
@@ -95,7 +95,7 @@ SRCS+= ar2133.c
# NB: rate control is bound to the driver by symbol names so only pick one
.if ${ATH_RATE} == "sample"
.PATH: ${.CURDIR}/../../dev/ath/ath_rate/sample
-SRCS+= sample.c opt_wlan.h
+SRCS+= sample.c
.elif ${ATH_RATE} == "onoe"
.PATH: ${.CURDIR}/../../dev/ath/ath_rate/onoe
SRCS+= onoe.c
diff --git a/sys/modules/cpufreq/Makefile b/sys/modules/cpufreq/Makefile
index 4e82008..108c2b1 100644
--- a/sys/modules/cpufreq/Makefile
+++ b/sys/modules/cpufreq/Makefile
@@ -12,7 +12,7 @@ SRCS+= bus_if.h cpufreq_if.h device_if.h pci_if.h
CFLAGS+= -I${.CURDIR}/../../contrib/dev/acpica
SRCS+= acpi_if.h opt_acpi.h
-SRCS+= est.c p4tcc.c powernow.c
+SRCS+= est.c hwpstate.c p4tcc.c powernow.c
.endif
.if ${MACHINE} == "i386"
diff --git a/sys/modules/dtrace/Makefile b/sys/modules/dtrace/Makefile
index 45c2b2f..671ccc9 100644
--- a/sys/modules/dtrace/Makefile
+++ b/sys/modules/dtrace/Makefile
@@ -4,6 +4,7 @@
.include "Makefile.inc"
SUBDIR= dtmalloc \
+ dtnfsclient \
dtrace \
dtraceall \
dtrace_test \
diff --git a/sys/modules/dtrace/dtnfsclient/Makefile b/sys/modules/dtrace/dtnfsclient/Makefile
new file mode 100644
index 0000000..5e26bba
--- /dev/null
+++ b/sys/modules/dtrace/dtnfsclient/Makefile
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../nfsclient
+
+KMOD= dtnfsclient
+SRCS= nfs_kdtrace.c
+SRCS+= vnode_if.h
+
+CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris \
+ -I${.CURDIR}/../../../cddl/contrib/opensolaris/uts/common \
+ -I${.CURDIR}/../../..
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/dtrace/dtraceall/dtraceall.c b/sys/modules/dtrace/dtraceall/dtraceall.c
index 4f7bdfe..6a71797 100644
--- a/sys/modules/dtrace/dtraceall/dtraceall.c
+++ b/sys/modules/dtrace/dtraceall/dtraceall.c
@@ -65,6 +65,7 @@ MODULE_DEPEND(dtraceall, cyclic, 1, 1, 1);
MODULE_DEPEND(dtraceall, opensolaris, 1, 1, 1);
MODULE_DEPEND(dtraceall, dtrace, 1, 1, 1);
MODULE_DEPEND(dtraceall, dtmalloc, 1, 1, 1);
+MODULE_DEPEND(dtraceall, dtnfsclient, 1, 1, 1);
#if defined(__amd64__) || defined(__i386__)
MODULE_DEPEND(dtraceall, fbt, 1, 1, 1);
#endif
diff --git a/sys/modules/geom/geom_vinum/Makefile b/sys/modules/geom/geom_vinum/Makefile
index fe14515..48ac962 100644
--- a/sys/modules/geom/geom_vinum/Makefile
+++ b/sys/modules/geom/geom_vinum/Makefile
@@ -3,10 +3,10 @@
.PATH: ${.CURDIR}/../../../geom/vinum
KMOD= geom_vinum
-SRCS= geom_vinum.c geom_vinum_drive.c geom_vinum_plex.c \
+SRCS= geom_vinum.c geom_vinum_create.c geom_vinum_drive.c geom_vinum_plex.c \
geom_vinum_volume.c geom_vinum_subr.c geom_vinum_raid5.c \
geom_vinum_share.c geom_vinum_list.c geom_vinum_rm.c \
geom_vinum_init.c geom_vinum_state.c geom_vinum_rename.c \
- geom_vinum_move.c
+ geom_vinum_move.c geom_vinum_events.c
.include <bsd.kmod.mk>
diff --git a/sys/modules/ip6_mroute_mod/Makefile b/sys/modules/ip6_mroute_mod/Makefile
new file mode 100644
index 0000000..f361c9d
--- /dev/null
+++ b/sys/modules/ip6_mroute_mod/Makefile
@@ -0,0 +1,19 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+.PATH: ${.CURDIR}/../../netinet6
+
+KMOD= ip6_mroute
+
+SRCS= ip6_mroute.c
+SRCS+= opt_inet6.h opt_mac.h opt_mrouting.h
+
+.if !defined(KERNBUILDDIR)
+opt_inet6.h:
+ echo "#define INET6 1" > ${.TARGET}
+opt_mrouting.h:
+ echo "#define MROUTING 1" > ${.TARGET}
+.endif
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ip_mroute_mod/Makefile b/sys/modules/ip_mroute_mod/Makefile
index 3ca0a3dc..141eceb 100644
--- a/sys/modules/ip_mroute_mod/Makefile
+++ b/sys/modules/ip_mroute_mod/Makefile
@@ -8,21 +8,12 @@ KMOD= ip_mroute
SRCS= ip_mroute.c
SRCS+= opt_inet.h opt_mac.h opt_mrouting.h opt_route.h
-SRCS+= opt_inet6.h
-
-.if ${MK_INET6_SUPPORT} != "no"
-SRCS+= ip6_mroute.c
-.endif
.if !defined(KERNBUILDDIR)
opt_inet.h:
echo "#define INET 1" > ${.TARGET}
opt_mrouting.h:
echo "#define MROUTING 1" > ${.TARGET}
-.if ${MK_INET6_SUPPORT} != "no"
-opt_inet6.h:
- echo "#define INET6 1" > ${.TARGET}
-.endif
.endif
.include <bsd.kmod.mk>
diff --git a/sys/modules/ipmi/Makefile b/sys/modules/ipmi/Makefile
index 3f45c73..7493b23 100644
--- a/sys/modules/ipmi/Makefile
+++ b/sys/modules/ipmi/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
+SUBDIR+= ipmi_linux
+
.PATH: ${.CURDIR}/../../dev/ipmi
# XXX - ipmi_smbus and ipmi_ssif depend on smbus
diff --git a/sys/modules/ipmi/ipmi_linux/Makefile b/sys/modules/ipmi/ipmi_linux/Makefile
new file mode 100644
index 0000000..bbdef1b
--- /dev/null
+++ b/sys/modules/ipmi/ipmi_linux/Makefile
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/ipmi
+
+KMOD= ipmi_linux
+SRCS= ipmi_linux.c
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/ixgbe/Makefile b/sys/modules/ixgbe/Makefile
index a40a909..e159f46 100644
--- a/sys/modules/ixgbe/Makefile
+++ b/sys/modules/ixgbe/Makefile
@@ -4,7 +4,8 @@ KMOD = ixgbe
SRCS = device_if.h bus_if.h pci_if.h
SRCS += ixgbe.c
# Shared source
-SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c ixgbe_82598.c
+SRCS += ixgbe_common.c ixgbe_api.c ixgbe_phy.c
+SRCS += ixgbe_82599.c ixgbe_82598.c
CFLAGS+= -I${.CURDIR}/../../dev/ixgbe
clean:
diff --git a/sys/modules/k8temp/Makefile b/sys/modules/k8temp/Makefile
deleted file mode 100644
index 32909ad..0000000
--- a/sys/modules/k8temp/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# $FreeBSD$
-
-.PATH: ${.CURDIR}/../../dev/k8temp
-
-KMOD= k8temp
-SRCS= k8temp.c bus_if.h device_if.h pci_if.h
-
-.include <bsd.kmod.mk>
diff --git a/sys/modules/linprocfs/Makefile b/sys/modules/linprocfs/Makefile
index a7cb129..62af13e 100644
--- a/sys/modules/linprocfs/Makefile
+++ b/sys/modules/linprocfs/Makefile
@@ -4,6 +4,7 @@
KMOD= linprocfs
SRCS= vnode_if.h \
+ device_if.h bus_if.h \
linprocfs.c \
opt_compat.h \
opt_route.h
diff --git a/sys/modules/mii/Makefile b/sys/modules/mii/Makefile
index 57647ea..6232b5e 100644
--- a/sys/modules/mii/Makefile
+++ b/sys/modules/mii/Makefile
@@ -3,7 +3,8 @@
.PATH: ${.CURDIR}/../../dev/mii
KMOD= miibus
-SRCS= acphy.c amphy.c atphy.c bmtphy.c brgphy.c bus_if.h ciphy.c device_if.h
+SRCS= acphy.c amphy.c atphy.c axphy.c bmtphy.c brgphy.c bus_if.h
+SRCS+= ciphy.c device_if.h
SRCS+= e1000phy.c exphy.c gentbi.c icsphy.c inphy.c ip1000phy.c jmphy.c
SRCS+= lxtphy.c miibus_if.c miibus_if.h mii.c miidevs.h mii_physubr.c
SRCS+= mlphy.c nsgphy.c nsphy.c nsphyter.c pci_if.h pnaphy.c qsphy.c
diff --git a/sys/modules/netgraph/Makefile b/sys/modules/netgraph/Makefile
index 760604d..2bae5ef 100644
--- a/sys/modules/netgraph/Makefile
+++ b/sys/modules/netgraph/Makefile
@@ -44,8 +44,6 @@ SUBDIR= async \
source \
split \
sppp \
- ${_sync_ar} \
- ${_sync_sr} \
tag \
tcpmss \
tee \
@@ -54,11 +52,6 @@ SUBDIR= async \
vjc \
vlan
-.if ${MACHINE_ARCH} == "i386"
-_sync_ar= sync_ar
-_sync_sr= sync_sr
-.endif
-
.if ${MK_BLUETOOTH} != "no" || defined(ALL_MODULES)
_bluetooth= bluetooth
.endif
diff --git a/sys/modules/nfsclient/Makefile b/sys/modules/nfsclient/Makefile
index 11742f5..a420502 100644
--- a/sys/modules/nfsclient/Makefile
+++ b/sys/modules/nfsclient/Makefile
@@ -10,7 +10,7 @@ SRCS= vnode_if.h \
opt_inet.h opt_nfs.h opt_bootp.h opt_nfsroot.h
SRCS+= nfs4_dev.c nfs4_idmap.c nfs4_socket.c nfs4_subs.c \
nfs4_vfs_subs.c nfs4_vfsops.c nfs4_vn_subs.c nfs4_vnops.c
-SRCS+= opt_inet6.h opt_kgssapi.h opt_route.h
+SRCS+= opt_inet6.h opt_kdtrace.h opt_kgssapi.h opt_route.h
# USE THE RPCCLNT:
CFLAGS+= -DRPCCLNT_DEBUG
diff --git a/sys/modules/nfssvc/Makefile b/sys/modules/nfssvc/Makefile
new file mode 100644
index 0000000..0073d13
--- /dev/null
+++ b/sys/modules/nfssvc/Makefile
@@ -0,0 +1,9 @@
+
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../nfs
+KMOD= nfssvc
+SRCS= nfs_nfssvc.c \
+ opt_nfs.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/opensolaris/Makefile b/sys/modules/opensolaris/Makefile
index 5e2195a..a1df2a8 100644
--- a/sys/modules/opensolaris/Makefile
+++ b/sys/modules/opensolaris/Makefile
@@ -7,7 +7,7 @@ SRCS= opensolaris.c \
opensolaris_cmn_err.c \
opensolaris_kmem.c
-.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "ia64"
+.if ${MACHINE_ARCH} == "i386" || ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "ia64" || ${MACHINE_ARCH} == "sparc64"
.PATH: ${.CURDIR}/../../cddl/contrib/opensolaris/common/atomic/${MACHINE_ARCH}
SRCS+= atomic.S
.else
diff --git a/sys/modules/usb/Makefile b/sys/modules/usb/Makefile
index a002111..44f55c6 100644
--- a/sys/modules/usb/Makefile
+++ b/sys/modules/usb/Makefile
@@ -28,8 +28,8 @@
SUBDIR = usb
#SUBDIR += ubt bluetooth_ng ubtfw
SUBDIR += ehci musb ohci uhci uss820dci ${_at91dci} ${_atmegadci}
-SUBDIR += rum ural zyd
-SUBDIR += uhid ukbd ums udbp ufm uscanner
+SUBDIR += rum uath ural zyd
+SUBDIR += uhid ukbd ums udbp ufm
SUBDIR += ucom u3g uark ubsa ubser uchcom ucycom ufoma uftdi ugensa uipaq ulpt \
umct umodem umoscom uplcom uslcom uvisor uvscom
SUBDIR += uether aue axe cdce cue kue rue udav
diff --git a/sys/modules/usb/uath/Makefile b/sys/modules/usb/uath/Makefile
new file mode 100644
index 0000000..a734dfc
--- /dev/null
+++ b/sys/modules/usb/uath/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../../dev/usb/wlan
+
+KMOD = if_uath
+SRCS = if_uath.c if_uathvar.h if_uathreg.h \
+ bus_if.h device_if.h \
+ opt_bus.h opt_usb.h usb_if.h usbdevs.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/modules/usb/usb/Makefile b/sys/modules/usb/usb/Makefile
index 39b8a99..5b0104e 100644
--- a/sys/modules/usb/usb/Makefile
+++ b/sys/modules/usb/usb/Makefile
@@ -36,7 +36,7 @@ SRCS= bus_if.h device_if.h usb_if.h usb_if.c vnode_if.h \
usb_busdma.c usb_controller.c usb_compat_linux.c usb_core.c usb_debug.c \
usb_dev.c usb_device.c usb_dynamic.c usb_error.c usb_generic.c \
usb_handle_request.c usb_hid.c usb_hub.c usb_lookup.c usb_mbuf.c \
- usb_msctest.c usb_parse.c usb_process.c usb_request.c usb_sw_transfer.c \
+ usb_msctest.c usb_parse.c usb_process.c usb_request.c \
usb_transfer.c usb_util.c
.include <bsd.kmod.mk>
diff --git a/sys/modules/usb/uscanner/Makefile b/sys/modules/usb/uscanner/Makefile
deleted file mode 100644
index 4534a3e..0000000
--- a/sys/modules/usb/uscanner/Makefile
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# $FreeBSD$
-#
-# Copyright (c) 2008 Hans Petter Selasky. 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.
-#
-
-S= ${.CURDIR}/../../..
-
-.PATH: $S/dev/usb/image
-
-KMOD= uscanner
-SRCS= opt_bus.h opt_usb.h device_if.h bus_if.h usb_if.h vnode_if.h usbdevs.h \
- uscanner.c
-
-.include <bsd.kmod.mk>
diff --git a/sys/net/bpf.h b/sys/net/bpf.h
index 3d3d079..726483a 100644
--- a/sys/net/bpf.h
+++ b/sys/net/bpf.h
@@ -726,6 +726,94 @@ struct bpf_zbuf_header {
#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ * http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
+ */
+#define DLT_AX25_KISS 202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <varunax@gmail.com>.
+ */
+#define DLT_LAPD 203
+
+/*
+ * Variants of various link-layer headers, with a one-byte direction
+ * pseudo-header prepended - zero means "received by this host",
+ * non-zero (any non-zero value) means "sent by this host" - as per
+ * Will Barker <w.barker@zen.co.uk>.
+ */
+#define DLT_PPP_WITH_DIR 204 /* PPP - don't confuse with DLT_PPP_WITH_DIRECTION */
+#define DLT_C_HDLC_WITH_DIR 205 /* Cisco HDLC */
+#define DLT_FRELAY_WITH_DIR 206 /* Frame Relay */
+#define DLT_LAPB_WITH_DIR 207 /* LAPB */
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ * <avn@pigeonpoint.com>.
+ */
+#define DLT_IPMB_LINUX 209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_FLEXRAY 210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_MOST 211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ * <hannes.kaelber@x2e.de>.
+ */
+#define DLT_LIN 212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_SERIAL 213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_XORAYA 214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <jcmvbkbc@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NONASK_PHY 215
+
+/*
+ * DLT and savefile link type values are split into a class and
+ * a member of that class. A class value of 0 indicates a regular
+ * DLT_/LINKTYPE_ value.
+ */
+#define DLT_CLASS(x) ((x) & 0x03ff0000)
+
+/*
* The instruction encodings.
*/
/* instruction classes */
diff --git a/sys/net/bsd_comp.c b/sys/net/bsd_comp.c
deleted file mode 100644
index 462567b..0000000
--- a/sys/net/bsd_comp.c
+++ /dev/null
@@ -1,1117 +0,0 @@
-/*-
- * Because this code is derived from the 4.3BSD compress source:
- *
- *
- * Copyright (c) 1985, 1986 The Regents of the University of California.
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * James A. Woods, derived from original work by Spencer Thomas
- * and Joseph Orost.
- *
- * 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.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * This version is for use with mbufs on BSD-derived systems.
- *
- * $FreeBSD$
- */
-
-#include "opt_mac.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/mutex.h>
-
-#include <net/ppp_defs.h>
-
-#define PACKETPTR struct mbuf *
-#include <net/ppp_comp.h>
-
-#include <security/mac/mac_framework.h>
-
-/*
- * PPP "BSD compress" compression
- * The differences between this compression and the classic BSD LZW
- * source are obvious from the requirement that the classic code worked
- * with files while this handles arbitrarily long streams that
- * are broken into packets. They are:
- *
- * When the code size expands, a block of junk is not emitted by
- * the compressor and not expected by the decompressor.
- *
- * New codes are not necessarily assigned every time an old
- * code is output by the compressor. This is because a packet
- * end forces a code to be emitted, but does not imply that a
- * new sequence has been seen.
- *
- * The compression ratio is checked at the first end of a packet
- * after the appropriate gap. Besides simplifying and speeding
- * things up, this makes it more likely that the transmitter
- * and receiver will agree when the dictionary is cleared when
- * compression is not going well.
- */
-
-/*
- * A dictionary for doing BSD compress.
- */
-struct bsd_db {
- int totlen; /* length of this structure */
- u_int hsize; /* size of the hash table */
- u_char hshift; /* used in hash function */
- u_char n_bits; /* current bits/code */
- u_char maxbits;
- u_char debug;
- u_char unit;
- u_int16_t seqno; /* sequence # of next packet */
- u_int hdrlen; /* header length to preallocate */
- u_int mru;
- u_int maxmaxcode; /* largest valid code */
- u_int max_ent; /* largest code in use */
- u_int in_count; /* uncompressed bytes, aged */
- u_int bytes_out; /* compressed bytes, aged */
- u_int ratio; /* recent compression ratio */
- u_int checkpoint; /* when to next check the ratio */
- u_int clear_count; /* times dictionary cleared */
- u_int incomp_count; /* incompressible packets */
- u_int incomp_bytes; /* incompressible bytes */
- u_int uncomp_count; /* uncompressed packets */
- u_int uncomp_bytes; /* uncompressed bytes */
- u_int comp_count; /* compressed packets */
- u_int comp_bytes; /* compressed bytes */
- u_int16_t *lens; /* array of lengths of codes */
- struct bsd_dict {
- union { /* hash value */
- u_int32_t fcode;
- struct {
-#if BYTE_ORDER == LITTLE_ENDIAN
- u_int16_t prefix; /* preceding code */
- u_char suffix; /* last character of new code */
- u_char pad;
-#else
- u_char pad;
- u_char suffix; /* last character of new code */
- u_int16_t prefix; /* preceding code */
-#endif
- } hs;
- } f;
- u_int16_t codem1; /* output of hash table -1 */
- u_int16_t cptr; /* map code to hash table entry */
- } dict[1];
-};
-
-#define BSD_OVHD 2 /* BSD compress overhead/packet */
-#define BSD_INIT_BITS BSD_MIN_BITS
-
-static void bsd_clear(struct bsd_db *db);
-static int bsd_check(struct bsd_db *db);
-static void *bsd_alloc(u_char *options, int opt_len, int decomp);
-static int bsd_init(struct bsd_db *db, u_char *options, int opt_len,
- int unit, int hdrlen, int mru, int debug, int decomp);
-static void *bsd_comp_alloc(u_char *options, int opt_len);
-static void *bsd_decomp_alloc(u_char *options, int opt_len);
-static void bsd_free(void *state);
-static int bsd_comp_init(void *state, u_char *options, int opt_len,
- int unit, int hdrlen, int debug);
-static int bsd_decomp_init(void *state, u_char *options, int opt_len,
- int unit, int hdrlen, int mru, int debug);
-static int bsd_compress(void *state, struct mbuf **mret, struct mbuf *mp,
- int slen, int maxolen);
-static void bsd_incomp(void *state, struct mbuf *dmsg);
-static int bsd_decompress(void *state, struct mbuf *cmp,
- struct mbuf **dmpp);
-static void bsd_reset(void *state);
-static void bsd_comp_stats(void *state, struct compstat *stats);
-
-/*
- * Procedures exported to if_ppp.c.
- */
-struct compressor ppp_bsd_compress = {
- CI_BSD_COMPRESS, /* compress_proto */
- bsd_comp_alloc, /* comp_alloc */
- bsd_free, /* comp_free */
- bsd_comp_init, /* comp_init */
- bsd_reset, /* comp_reset */
- bsd_compress, /* compress */
- bsd_comp_stats, /* comp_stat */
- bsd_decomp_alloc, /* decomp_alloc */
- bsd_free, /* decomp_free */
- bsd_decomp_init, /* decomp_init */
- bsd_reset, /* decomp_reset */
- bsd_decompress, /* decompress */
- bsd_incomp, /* incomp */
- bsd_comp_stats, /* decomp_stat */
-};
-
-/*
- * the next two codes should not be changed lightly, as they must not
- * lie within the contiguous general code space.
- */
-#define CLEAR 256 /* table clear output code */
-#define FIRST 257 /* first free entry */
-#define LAST 255
-
-#define MAXCODE(b) ((1 << (b)) - 1)
-#define BADCODEM1 MAXCODE(BSD_MAX_BITS)
-
-#define BSD_HASH(prefix,suffix,hshift) ((((u_int32_t)(suffix)) << (hshift)) \
- ^ (u_int32_t)(prefix))
-#define BSD_KEY(prefix,suffix) ((((u_int32_t)(suffix)) << 16) \
- + (u_int32_t)(prefix))
-
-#define CHECK_GAP 10000 /* Ratio check interval */
-
-#define RATIO_SCALE_LOG 8
-#define RATIO_SCALE (1<<RATIO_SCALE_LOG)
-#define RATIO_MAX (0x7fffffff>>RATIO_SCALE_LOG)
-
-/*
- * clear the dictionary
- */
-static void
-bsd_clear(db)
- struct bsd_db *db;
-{
- db->clear_count++;
- db->max_ent = FIRST-1;
- db->n_bits = BSD_INIT_BITS;
- db->ratio = 0;
- db->bytes_out = 0;
- db->in_count = 0;
- db->checkpoint = CHECK_GAP;
-}
-
-/*
- * If the dictionary is full, then see if it is time to reset it.
- *
- * Compute the compression ratio using fixed-point arithmetic
- * with 8 fractional bits.
- *
- * Since we have an infinite stream instead of a single file,
- * watch only the local compression ratio.
- *
- * Since both peers must reset the dictionary at the same time even in
- * the absence of CLEAR codes (while packets are incompressible), they
- * must compute the same ratio.
- */
-static int /* 1=output CLEAR */
-bsd_check(db)
- struct bsd_db *db;
-{
- u_int new_ratio;
-
- if (db->in_count >= db->checkpoint) {
- /* age the ratio by limiting the size of the counts */
- if (db->in_count >= RATIO_MAX
- || db->bytes_out >= RATIO_MAX) {
- db->in_count -= db->in_count/4;
- db->bytes_out -= db->bytes_out/4;
- }
-
- db->checkpoint = db->in_count + CHECK_GAP;
-
- if (db->max_ent >= db->maxmaxcode) {
- /* Reset the dictionary only if the ratio is worse,
- * or if it looks as if it has been poisoned
- * by incompressible data.
- *
- * This does not overflow, because
- * db->in_count <= RATIO_MAX.
- */
- new_ratio = db->in_count << RATIO_SCALE_LOG;
- if (db->bytes_out != 0)
- new_ratio /= db->bytes_out;
-
- if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE) {
- bsd_clear(db);
- return 1;
- }
- db->ratio = new_ratio;
- }
- }
- return 0;
-}
-
-/*
- * Return statistics.
- */
-static void
-bsd_comp_stats(state, stats)
- void *state;
- struct compstat *stats;
-{
- struct bsd_db *db = (struct bsd_db *) state;
- u_int out;
-
- stats->unc_bytes = db->uncomp_bytes;
- stats->unc_packets = db->uncomp_count;
- stats->comp_bytes = db->comp_bytes;
- stats->comp_packets = db->comp_count;
- stats->inc_bytes = db->incomp_bytes;
- stats->inc_packets = db->incomp_count;
- stats->ratio = db->in_count;
- out = db->bytes_out;
- if (stats->ratio <= 0x7fffff)
- stats->ratio <<= 8;
- else
- out >>= 8;
- if (out != 0)
- stats->ratio /= out;
-}
-
-/*
- * Reset state, as on a CCP ResetReq.
- */
-static void
-bsd_reset(state)
- void *state;
-{
- struct bsd_db *db = (struct bsd_db *) state;
-
- db->seqno = 0;
- bsd_clear(db);
- db->clear_count = 0;
-}
-
-/*
- * Allocate space for a (de) compressor.
- */
-static void *
-bsd_alloc(options, opt_len, decomp)
- u_char *options;
- int opt_len, decomp;
-{
- int bits;
- u_int newlen, hsize, hshift, maxmaxcode;
- struct bsd_db *db;
-
- if (opt_len < CILEN_BSD_COMPRESS || options[0] != CI_BSD_COMPRESS
- || options[1] != CILEN_BSD_COMPRESS
- || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
- return NULL;
- bits = BSD_NBITS(options[2]);
- switch (bits) {
- case 9: /* needs 82152 for both directions */
- case 10: /* needs 84144 */
- case 11: /* needs 88240 */
- case 12: /* needs 96432 */
- hsize = 5003;
- hshift = 4;
- break;
- case 13: /* needs 176784 */
- hsize = 9001;
- hshift = 5;
- break;
- case 14: /* needs 353744 */
- hsize = 18013;
- hshift = 6;
- break;
- case 15: /* needs 691440 */
- hsize = 35023;
- hshift = 7;
- break;
- case 16: /* needs 1366160--far too much, */
- /* hsize = 69001; */ /* and 69001 is too big for cptr */
- /* hshift = 8; */ /* in struct bsd_db */
- /* break; */
- default:
- return NULL;
- }
-
- maxmaxcode = MAXCODE(bits);
- newlen = sizeof(*db) + (hsize-1) * (sizeof(db->dict[0]));
- db = malloc(newlen, M_DEVBUF, M_NOWAIT);
- if (!db)
- return NULL;
- bzero(db, sizeof(*db) - sizeof(db->dict));
-
- if (!decomp) {
- db->lens = NULL;
- } else {
- db->lens = malloc((maxmaxcode+1) * sizeof(db->lens[0]),
- M_DEVBUF, M_NOWAIT);
- if (!db->lens) {
- free(db, M_DEVBUF);
- return NULL;
- }
- }
-
- db->totlen = newlen;
- db->hsize = hsize;
- db->hshift = hshift;
- db->maxmaxcode = maxmaxcode;
- db->maxbits = bits;
-
- return (void *) db;
-}
-
-static void
-bsd_free(state)
- void *state;
-{
- struct bsd_db *db = (struct bsd_db *) state;
-
- if (db->lens)
- free(db->lens, M_DEVBUF);
- free(db, M_DEVBUF);
-}
-
-static void *
-bsd_comp_alloc(options, opt_len)
- u_char *options;
- int opt_len;
-{
- return bsd_alloc(options, opt_len, 0);
-}
-
-static void *
-bsd_decomp_alloc(options, opt_len)
- u_char *options;
- int opt_len;
-{
- return bsd_alloc(options, opt_len, 1);
-}
-
-/*
- * Initialize the database.
- */
-static int
-bsd_init(db, options, opt_len, unit, hdrlen, mru, debug, decomp)
- struct bsd_db *db;
- u_char *options;
- int opt_len, unit, hdrlen, mru, debug, decomp;
-{
- int i;
-
- if (opt_len < CILEN_BSD_COMPRESS || options[0] != CI_BSD_COMPRESS
- || options[1] != CILEN_BSD_COMPRESS
- || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION
- || BSD_NBITS(options[2]) != db->maxbits
- || (decomp && db->lens == NULL))
- return 0;
-
- if (decomp) {
- i = LAST+1;
- while (i != 0)
- db->lens[--i] = 1;
- }
- i = db->hsize;
- while (i != 0) {
- db->dict[--i].codem1 = BADCODEM1;
- db->dict[i].cptr = 0;
- }
-
- db->unit = unit;
- db->hdrlen = hdrlen;
- db->mru = mru;
-#ifndef DEBUG
- if (debug)
-#endif
- db->debug = 1;
-
- bsd_reset(db);
-
- return 1;
-}
-
-static int
-bsd_comp_init(state, options, opt_len, unit, hdrlen, debug)
- void *state;
- u_char *options;
- int opt_len, unit, hdrlen, debug;
-{
- return bsd_init((struct bsd_db *) state, options, opt_len,
- unit, hdrlen, 0, debug, 0);
-}
-
-static int
-bsd_decomp_init(state, options, opt_len, unit, hdrlen, mru, debug)
- void *state;
- u_char *options;
- int opt_len, unit, hdrlen, mru, debug;
-{
- return bsd_init((struct bsd_db *) state, options, opt_len,
- unit, hdrlen, mru, debug, 1);
-}
-
-
-/*
- * compress a packet
- * One change from the BSD compress command is that when the
- * code size expands, we do not output a bunch of padding.
- */
-static int /* new slen */
-bsd_compress(state, mret, mp, slen, maxolen)
- void *state;
- struct mbuf **mret; /* return compressed mbuf chain here */
- struct mbuf *mp; /* from here */
- int slen; /* uncompressed length */
- int maxolen; /* max compressed length */
-{
- struct bsd_db *db = (struct bsd_db *) state;
- int hshift = db->hshift;
- u_int max_ent = db->max_ent;
- u_int n_bits = db->n_bits;
- u_int bitno = 32;
- u_int32_t accm = 0, fcode;
- struct bsd_dict *dictp;
- u_char c;
- int hval, disp, ent, ilen;
- u_char *rptr, *wptr;
- u_char *cp_end;
- int olen;
- struct mbuf *m;
-
-#define PUTBYTE(v) { \
- ++olen; \
- if (wptr) { \
- *wptr++ = (v); \
- if (wptr >= cp_end) { \
- m->m_len = wptr - mtod(m, u_char *); \
- MGET(m->m_next, M_DONTWAIT, MT_DATA); \
- m = m->m_next; \
- if (m) { \
- m->m_len = 0; \
- if (maxolen - olen > MLEN) \
- MCLGET(m, M_DONTWAIT); \
- wptr = mtod(m, u_char *); \
- cp_end = wptr + M_TRAILINGSPACE(m); \
- } else \
- wptr = NULL; \
- } \
- } \
-}
-
-#define OUTPUT(ent) { \
- bitno -= n_bits; \
- accm |= ((ent) << bitno); \
- do { \
- PUTBYTE(accm >> 24); \
- accm <<= 8; \
- bitno += 8; \
- } while (bitno <= 24); \
-}
-
- /*
- * If the protocol is not in the range we're interested in,
- * just return without compressing the packet. If it is,
- * the protocol becomes the first byte to compress.
- */
- rptr = mtod(mp, u_char *);
- ent = PPP_PROTOCOL(rptr);
- if (ent < 0x21 || ent > 0xf9) {
- *mret = NULL;
- return slen;
- }
-
- /* Don't generate compressed packets which are larger than
- the uncompressed packet. */
- if (maxolen > slen)
- maxolen = slen;
-
- /* Allocate one mbuf to start with. */
- MGET(m, M_DONTWAIT, MT_DATA);
- *mret = m;
- if (m != NULL) {
- m->m_len = 0;
- if (maxolen + db->hdrlen > MLEN)
- MCLGET(m, M_DONTWAIT);
- m->m_data += db->hdrlen;
- wptr = mtod(m, u_char *);
- cp_end = wptr + M_TRAILINGSPACE(m);
- } else
- wptr = cp_end = NULL;
-
- /*
- * Copy the PPP header over, changing the protocol,
- * and install the 2-byte packet sequence number.
- */
- if (wptr) {
- *wptr++ = PPP_ADDRESS(rptr); /* assumes the ppp header is */
- *wptr++ = PPP_CONTROL(rptr); /* all in one mbuf */
- *wptr++ = 0; /* change the protocol */
- *wptr++ = PPP_COMP;
- *wptr++ = db->seqno >> 8;
- *wptr++ = db->seqno;
- }
- ++db->seqno;
-
- olen = 0;
- rptr += PPP_HDRLEN;
- slen = mp->m_len - PPP_HDRLEN;
- ilen = slen + 1;
- for (;;) {
- if (slen <= 0) {
- mp = mp->m_next;
- if (!mp)
- break;
- rptr = mtod(mp, u_char *);
- slen = mp->m_len;
- if (!slen)
- continue; /* handle 0-length buffers */
- ilen += slen;
- }
-
- slen--;
- c = *rptr++;
- fcode = BSD_KEY(ent, c);
- hval = BSD_HASH(ent, c, hshift);
- dictp = &db->dict[hval];
-
- /* Validate and then check the entry. */
- if (dictp->codem1 >= max_ent)
- goto nomatch;
- if (dictp->f.fcode == fcode) {
- ent = dictp->codem1+1;
- continue; /* found (prefix,suffix) */
- }
-
- /* continue probing until a match or invalid entry */
- disp = (hval == 0) ? 1 : hval;
- do {
- hval += disp;
- if (hval >= db->hsize)
- hval -= db->hsize;
- dictp = &db->dict[hval];
- if (dictp->codem1 >= max_ent)
- goto nomatch;
- } while (dictp->f.fcode != fcode);
- ent = dictp->codem1 + 1; /* finally found (prefix,suffix) */
- continue;
-
- nomatch:
- OUTPUT(ent); /* output the prefix */
-
- /* code -> hashtable */
- if (max_ent < db->maxmaxcode) {
- struct bsd_dict *dictp2;
- /* expand code size if needed */
- if (max_ent >= MAXCODE(n_bits))
- db->n_bits = ++n_bits;
-
- /* Invalidate old hash table entry using
- * this code, and then take it over.
- */
- dictp2 = &db->dict[max_ent+1];
- if (db->dict[dictp2->cptr].codem1 == max_ent)
- db->dict[dictp2->cptr].codem1 = BADCODEM1;
- dictp2->cptr = hval;
- dictp->codem1 = max_ent;
- dictp->f.fcode = fcode;
-
- db->max_ent = ++max_ent;
- }
- ent = c;
- }
-
- OUTPUT(ent); /* output the last code */
- db->bytes_out += olen;
- db->in_count += ilen;
- if (bitno < 32)
- ++db->bytes_out; /* count complete bytes */
-
- if (bsd_check(db))
- OUTPUT(CLEAR); /* do not count the CLEAR */
-
- /*
- * Pad dribble bits of last code with ones.
- * Do not emit a completely useless byte of ones.
- */
- if (bitno != 32)
- PUTBYTE((accm | (0xff << (bitno-8))) >> 24);
-
- if (m != NULL) {
- m->m_len = wptr - mtod(m, u_char *);
- m->m_next = NULL;
- }
-
- /*
- * Increase code size if we would have without the packet
- * boundary and as the decompressor will.
- */
- if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
- db->n_bits++;
-
- db->uncomp_bytes += ilen;
- ++db->uncomp_count;
- if (olen + PPP_HDRLEN + BSD_OVHD > maxolen) {
- /* throw away the compressed stuff if it is longer than uncompressed */
- if (*mret != NULL) {
- m_freem(*mret);
- *mret = NULL;
- }
- ++db->incomp_count;
- db->incomp_bytes += ilen;
- } else {
- ++db->comp_count;
- db->comp_bytes += olen + BSD_OVHD;
- }
-
- return olen + PPP_HDRLEN + BSD_OVHD;
-#undef OUTPUT
-#undef PUTBYTE
-}
-
-
-/*
- * Update the "BSD Compress" dictionary on the receiver for
- * incompressible data by pretending to compress the incoming data.
- */
-static void
-bsd_incomp(state, dmsg)
- void *state;
- struct mbuf *dmsg;
-{
- struct bsd_db *db = (struct bsd_db *) state;
- u_int hshift = db->hshift;
- u_int max_ent = db->max_ent;
- u_int n_bits = db->n_bits;
- struct bsd_dict *dictp;
- u_int32_t fcode;
- u_char c;
- u_int32_t hval, disp;
- int slen, ilen;
- u_int bitno = 7;
- u_char *rptr;
- u_int ent;
-
- /*
- * If the protocol is not in the range we're interested in,
- * just return without looking at the packet. If it is,
- * the protocol becomes the first byte to "compress".
- */
- rptr = mtod(dmsg, u_char *);
- ent = PPP_PROTOCOL(rptr);
- if (ent < 0x21 || ent > 0xf9)
- return;
-
- db->seqno++;
- ilen = 1; /* count the protocol as 1 byte */
- rptr += PPP_HDRLEN;
- slen = dmsg->m_len - PPP_HDRLEN;
- for (;;) {
- if (slen <= 0) {
- dmsg = dmsg->m_next;
- if (!dmsg)
- break;
- rptr = mtod(dmsg, u_char *);
- slen = dmsg->m_len;
- continue;
- }
- ilen += slen;
-
- do {
- c = *rptr++;
- fcode = BSD_KEY(ent, c);
- hval = BSD_HASH(ent, c, hshift);
- dictp = &db->dict[hval];
-
- /* validate and then check the entry */
- if (dictp->codem1 >= max_ent)
- goto nomatch;
- if (dictp->f.fcode == fcode) {
- ent = dictp->codem1+1;
- continue; /* found (prefix,suffix) */
- }
-
- /* continue probing until a match or invalid entry */
- disp = (hval == 0) ? 1 : hval;
- do {
- hval += disp;
- if (hval >= db->hsize)
- hval -= db->hsize;
- dictp = &db->dict[hval];
- if (dictp->codem1 >= max_ent)
- goto nomatch;
- } while (dictp->f.fcode != fcode);
- ent = dictp->codem1+1;
- continue; /* finally found (prefix,suffix) */
-
- nomatch: /* output (count) the prefix */
- bitno += n_bits;
-
- /* code -> hashtable */
- if (max_ent < db->maxmaxcode) {
- struct bsd_dict *dictp2;
- /* expand code size if needed */
- if (max_ent >= MAXCODE(n_bits))
- db->n_bits = ++n_bits;
-
- /* Invalidate previous hash table entry
- * assigned this code, and then take it over.
- */
- dictp2 = &db->dict[max_ent+1];
- if (db->dict[dictp2->cptr].codem1 == max_ent)
- db->dict[dictp2->cptr].codem1 = BADCODEM1;
- dictp2->cptr = hval;
- dictp->codem1 = max_ent;
- dictp->f.fcode = fcode;
-
- db->max_ent = ++max_ent;
- db->lens[max_ent] = db->lens[ent]+1;
- }
- ent = c;
- } while (--slen != 0);
- }
- bitno += n_bits; /* output (count) the last code */
- db->bytes_out += bitno/8;
- db->in_count += ilen;
- (void)bsd_check(db);
-
- ++db->incomp_count;
- db->incomp_bytes += ilen;
- ++db->uncomp_count;
- db->uncomp_bytes += ilen;
-
- /* Increase code size if we would have without the packet
- * boundary and as the decompressor will.
- */
- if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
- db->n_bits++;
-}
-
-
-/*
- * Decompress "BSD Compress".
- *
- * Because of patent problems, we return DECOMP_ERROR for errors
- * found by inspecting the input data and for system problems, but
- * DECOMP_FATALERROR for any errors which could possibly be said to
- * be being detected "after" decompression. For DECOMP_ERROR,
- * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
- * infringing a patent of Motorola's if we do, so we take CCP down
- * instead.
- *
- * Given that the frame has the correct sequence number and a good FCS,
- * errors such as invalid codes in the input most likely indicate a
- * bug, so we return DECOMP_FATALERROR for them in order to turn off
- * compression, even though they are detected by inspecting the input.
- */
-static int
-bsd_decompress(state, cmp, dmpp)
- void *state;
- struct mbuf *cmp, **dmpp;
-{
- struct bsd_db *db = (struct bsd_db *) state;
- u_int max_ent = db->max_ent;
- u_int32_t accm = 0;
- u_int bitno = 32; /* 1st valid bit in accm */
- u_int n_bits = db->n_bits;
- u_int tgtbitno = 32-n_bits; /* bitno when we have a code */
- struct bsd_dict *dictp;
- int explen, i, seq, len;
- u_int incode, oldcode, finchar;
- u_char *p, *rptr, *wptr;
- struct mbuf *m, *dmp, *mret;
- int adrs, ctrl, ilen;
- int space, codelen, extra;
-
- /*
- * Save the address/control from the PPP header
- * and then get the sequence number.
- */
- *dmpp = NULL;
- rptr = mtod(cmp, u_char *);
- adrs = PPP_ADDRESS(rptr);
- ctrl = PPP_CONTROL(rptr);
- rptr += PPP_HDRLEN;
- len = cmp->m_len - PPP_HDRLEN;
- seq = 0;
- for (i = 0; i < 2; ++i) {
- while (len <= 0) {
- cmp = cmp->m_next;
- if (cmp == NULL)
- return DECOMP_ERROR;
- rptr = mtod(cmp, u_char *);
- len = cmp->m_len;
- }
- seq = (seq << 8) + *rptr++;
- --len;
- }
-
- /*
- * Check the sequence number and give up if it differs from
- * the value we're expecting.
- */
- if (seq != db->seqno) {
- if (db->debug)
- printf("bsd_decomp%d: bad sequence # %d, expected %d\n",
- db->unit, seq, db->seqno - 1);
- return DECOMP_ERROR;
- }
- ++db->seqno;
-
- /*
- * Allocate one mbuf to start with.
- */
- MGETHDR(dmp, M_DONTWAIT, MT_DATA);
- if (dmp == NULL)
- return DECOMP_ERROR;
- mret = dmp;
- dmp->m_len = 0;
- dmp->m_next = NULL;
- MCLGET(dmp, M_DONTWAIT);
- dmp->m_data += db->hdrlen;
- wptr = mtod(dmp, u_char *);
- space = M_TRAILINGSPACE(dmp) - PPP_HDRLEN + 1;
-#ifdef MAC
- mac_mbuf_copy(cmp, dmp);
-#endif
-
- /*
- * Fill in the ppp header, but not the last byte of the protocol
- * (that comes from the decompressed data).
- */
- wptr[0] = adrs;
- wptr[1] = ctrl;
- wptr[2] = 0;
- wptr += PPP_HDRLEN - 1;
-
- ilen = len;
- oldcode = CLEAR;
- explen = 0;
- for (;;) {
- if (len == 0) {
- cmp = cmp->m_next;
- if (!cmp) /* quit at end of message */
- break;
- rptr = mtod(cmp, u_char *);
- len = cmp->m_len;
- ilen += len;
- continue; /* handle 0-length buffers */
- }
-
- /*
- * Accumulate bytes until we have a complete code.
- * Then get the next code, relying on the 32-bit,
- * unsigned accm to mask the result.
- */
- bitno -= 8;
- accm |= *rptr++ << bitno;
- --len;
- if (tgtbitno < bitno)
- continue;
- incode = accm >> tgtbitno;
- accm <<= n_bits;
- bitno += n_bits;
-
- if (incode == CLEAR) {
- /*
- * The dictionary must only be cleared at
- * the end of a packet. But there could be an
- * empty mbuf at the end.
- */
- if (len > 0 || cmp->m_next != NULL) {
- while ((cmp = cmp->m_next) != NULL)
- len += cmp->m_len;
- if (len > 0) {
- m_freem(mret);
- if (db->debug)
- printf("bsd_decomp%d: bad CLEAR\n", db->unit);
- return DECOMP_FATALERROR; /* probably a bug */
- }
- }
- bsd_clear(db);
- explen = ilen = 0;
- break;
- }
-
- if (incode > max_ent + 2 || incode > db->maxmaxcode
- || (incode > max_ent && oldcode == CLEAR)) {
- m_freem(mret);
- if (db->debug) {
- printf("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
- db->unit, incode, oldcode);
- printf("max_ent=0x%x explen=%d seqno=%d\n",
- max_ent, explen, db->seqno);
- }
- return DECOMP_FATALERROR; /* probably a bug */
- }
-
- /* Special case for KwKwK string. */
- if (incode > max_ent) {
- finchar = oldcode;
- extra = 1;
- } else {
- finchar = incode;
- extra = 0;
- }
-
- codelen = db->lens[finchar];
- explen += codelen + extra;
- if (explen > db->mru + 1) {
- m_freem(mret);
- if (db->debug) {
- printf("bsd_decomp%d: ran out of mru\n", db->unit);
-#ifdef DEBUG
- while ((cmp = cmp->m_next) != NULL)
- len += cmp->m_len;
- printf(" len=%d, finchar=0x%x, codelen=%d, explen=%d\n",
- len, finchar, codelen, explen);
-#endif
- }
- return DECOMP_FATALERROR;
- }
-
- /*
- * For simplicity, the decoded characters go in a single mbuf,
- * so we allocate a single extra cluster mbuf if necessary.
- */
- if ((space -= codelen + extra) < 0) {
- dmp->m_len = wptr - mtod(dmp, u_char *);
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m == NULL) {
- m_freem(mret);
- return DECOMP_ERROR;
- }
- m->m_len = 0;
- m->m_next = NULL;
- dmp->m_next = m;
- MCLGET(m, M_DONTWAIT);
- space = M_TRAILINGSPACE(m) - (codelen + extra);
- if (space < 0) {
- /* now that's what I call *compression*. */
- m_freem(mret);
- return DECOMP_ERROR;
- }
- dmp = m;
- wptr = mtod(dmp, u_char *);
- }
-
- /*
- * Decode this code and install it in the decompressed buffer.
- */
- p = (wptr += codelen);
- while (finchar > LAST) {
- dictp = &db->dict[db->dict[finchar].cptr];
-#ifdef DEBUG
- if (--codelen <= 0 || dictp->codem1 != finchar-1)
- goto bad;
-#endif
- *--p = dictp->f.hs.suffix;
- finchar = dictp->f.hs.prefix;
- }
- *--p = finchar;
-
-#ifdef DEBUG
- if (--codelen != 0)
- printf("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
- db->unit, codelen, incode, max_ent);
-#endif
-
- if (extra) /* the KwKwK case again */
- *wptr++ = finchar;
-
- /*
- * If not first code in a packet, and
- * if not out of code space, then allocate a new code.
- *
- * Keep the hash table correct so it can be used
- * with uncompressed packets.
- */
- if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
- struct bsd_dict *dictp2;
- u_int32_t fcode;
- u_int32_t hval, disp;
-
- fcode = BSD_KEY(oldcode,finchar);
- hval = BSD_HASH(oldcode,finchar,db->hshift);
- dictp = &db->dict[hval];
-
- /* look for a free hash table entry */
- if (dictp->codem1 < max_ent) {
- disp = (hval == 0) ? 1 : hval;
- do {
- hval += disp;
- if (hval >= db->hsize)
- hval -= db->hsize;
- dictp = &db->dict[hval];
- } while (dictp->codem1 < max_ent);
- }
-
- /*
- * Invalidate previous hash table entry
- * assigned this code, and then take it over
- */
- dictp2 = &db->dict[max_ent+1];
- if (db->dict[dictp2->cptr].codem1 == max_ent) {
- db->dict[dictp2->cptr].codem1 = BADCODEM1;
- }
- dictp2->cptr = hval;
- dictp->codem1 = max_ent;
- dictp->f.fcode = fcode;
-
- db->max_ent = ++max_ent;
- db->lens[max_ent] = db->lens[oldcode]+1;
-
- /* Expand code size if needed. */
- if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
- db->n_bits = ++n_bits;
- tgtbitno = 32-n_bits;
- }
- }
- oldcode = incode;
- }
- dmp->m_len = wptr - mtod(dmp, u_char *);
-
- /*
- * Keep the checkpoint right so that incompressible packets
- * clear the dictionary at the right times.
- */
- db->bytes_out += ilen;
- db->in_count += explen;
- if (bsd_check(db) && db->debug) {
- printf("bsd_decomp%d: peer should have cleared dictionary\n",
- db->unit);
- }
-
- ++db->comp_count;
- db->comp_bytes += ilen + BSD_OVHD;
- ++db->uncomp_count;
- db->uncomp_bytes += explen;
-
- *dmpp = mret;
- return DECOMP_OK;
-
-#ifdef DEBUG
- bad:
- if (codelen <= 0) {
- printf("bsd_decomp%d: fell off end of chain ", db->unit);
- printf("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
- incode, finchar, db->dict[finchar].cptr, max_ent);
- } else if (dictp->codem1 != finchar-1) {
- printf("bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",
- db->unit, incode, finchar);
- printf("oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode,
- db->dict[finchar].cptr, dictp->codem1);
- }
- m_freem(mret);
- return DECOMP_FATALERROR;
-#endif /* DEBUG */
-}
diff --git a/sys/net/if.c b/sys/net/if.c
index 7e8d90b..da3c041 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -138,10 +138,10 @@ static void link_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
static int if_rtdel(struct radix_node *, void *);
static int ifhwioctl(u_long, struct ifnet *, caddr_t, struct thread *);
static int if_delmulti_locked(struct ifnet *, struct ifmultiaddr *, int);
-static void if_start_deferred(void *context, int pending);
static void do_link_state_change(void *, int);
static int if_getgroup(struct ifgroupreq *, struct ifnet *);
static int if_getgroupmembers(struct ifgroupreq *);
+static void if_delgroups(struct ifnet *);
#ifdef INET6
/*
@@ -151,6 +151,8 @@ static int if_getgroupmembers(struct ifgroupreq *);
extern void nd6_setmtu(struct ifnet *);
#endif
+static int vnet_net_iattach(const void *);
+
#ifdef VIMAGE_GLOBALS
struct ifnethead ifnet; /* depend on static init XXX */
struct ifgrouphead ifg_head;
@@ -181,9 +183,13 @@ static struct vnet_symmap vnet_net_symmap[] = {
VNET_SYMMAP_END
};
-VNET_MOD_DECLARE(NET, net, vnet_net_iattach, vnet_net_idetach,
- NONE, vnet_net_symmap)
-#endif
+static const vnet_modinfo_t vnet_net_modinfo = {
+ .vmi_id = VNET_MOD_NET,
+ .vmi_name = "net",
+ .vmi_symmap = vnet_net_symmap,
+ .vmi_iattach = vnet_net_iattach
+};
+#endif /* !VIMAGE_GLOBALS */
/*
* System initialization
@@ -392,24 +398,33 @@ filt_netdev(struct knote *kn, long hint)
static void
if_init(void *dummy __unused)
{
- INIT_VNET_NET(curvnet);
#ifndef VIMAGE_GLOBALS
vnet_mod_register(&vnet_net_modinfo);
#endif
+ vnet_net_iattach(NULL);
+
+ IFNET_LOCK_INIT();
+ ifdev_setbyindex(0, make_dev(&net_cdevsw, 0, UID_ROOT, GID_WHEEL,
+ 0600, "network"));
+ if_clone_init();
+}
+
+static int
+vnet_net_iattach(const void *unused __unused)
+{
+ INIT_VNET_NET(curvnet);
V_if_index = 0;
V_ifindex_table = NULL;
V_if_indexlim = 8;
- IFNET_LOCK_INIT();
TAILQ_INIT(&V_ifnet);
TAILQ_INIT(&V_ifg_head);
knlist_init(&V_ifklist, NULL, NULL, NULL, NULL);
if_grow(); /* create initial table */
- ifdev_setbyindex(0, make_dev(&net_cdevsw, 0, UID_ROOT, GID_WHEEL,
- 0600, "network"));
- if_clone_init();
+
+ return (0);
}
static void
@@ -533,7 +548,7 @@ if_free_type(struct ifnet *ifp, u_char type)
IF_ADDR_LOCK_DESTROY(ifp);
free(ifp, M_IFNET);
-};
+}
void
ifq_attach(struct ifaltq *ifq, struct ifnet *ifp)
@@ -582,7 +597,6 @@ if_attach(struct ifnet *ifp)
panic ("%s: BUG: if_attach called without if_alloc'd input()\n",
ifp->if_xname);
- TASK_INIT(&ifp->if_starttask, 0, if_start_deferred, ifp);
TASK_INIT(&ifp->if_linktask, 0, do_link_state_change, ifp);
IF_AFDATA_LOCK_INIT(ifp);
ifp->if_afdata_initialized = 0;
@@ -674,9 +688,6 @@ if_attach(struct ifnet *ifp)
if (atomic_cmpset_int(&slowtimo_started, 0, 1) && !cold)
if_slowtimo(0);
}
- if (ifp->if_flags & IFF_NEEDSGIANT)
- if_printf(ifp,
- "WARNING: using obsoleted IFF_NEEDSGIANT flag\n");
}
static void
@@ -881,6 +892,7 @@ if_detach(struct ifnet *ifp)
rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
EVENTHANDLER_INVOKE(ifnet_departure_event, ifp);
devctl_notify("IFNET", ifp->if_xname, "DETACH", NULL);
+ if_delgroups(ifp);
IF_AFDATA_LOCK(ifp);
for (dp = domains; dp; dp = dp->dom_next) {
@@ -1018,6 +1030,54 @@ if_delgroup(struct ifnet *ifp, const char *groupname)
}
/*
+ * Remove an interface from all groups
+ */
+static void
+if_delgroups(struct ifnet *ifp)
+{
+ INIT_VNET_NET(ifp->if_vnet);
+ struct ifg_list *ifgl;
+ struct ifg_member *ifgm;
+ char groupname[IFNAMSIZ];
+
+ IFNET_WLOCK();
+ while (!TAILQ_EMPTY(&ifp->if_groups)) {
+ ifgl = TAILQ_FIRST(&ifp->if_groups);
+
+ strlcpy(groupname, ifgl->ifgl_group->ifg_group, IFNAMSIZ);
+
+ IF_ADDR_LOCK(ifp);
+ TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
+ IF_ADDR_UNLOCK(ifp);
+
+ TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
+ if (ifgm->ifgm_ifp == ifp)
+ break;
+
+ if (ifgm != NULL) {
+ TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm,
+ ifgm_next);
+ free(ifgm, M_TEMP);
+ }
+
+ if (--ifgl->ifgl_group->ifg_refcnt == 0) {
+ TAILQ_REMOVE(&V_ifg_head, ifgl->ifgl_group, ifg_next);
+ EVENTHANDLER_INVOKE(group_detach_event,
+ ifgl->ifgl_group);
+ free(ifgl->ifgl_group, M_TEMP);
+ }
+ IFNET_WUNLOCK();
+
+ free(ifgl, M_TEMP);
+
+ EVENTHANDLER_INVOKE(group_change_event, groupname);
+
+ IFNET_WLOCK();
+ }
+ IFNET_WUNLOCK();
+}
+
+/*
* Stores all groups from an interface in memory pointed
* to by data
*/
@@ -1607,8 +1667,7 @@ if_qflush(struct ifnet *ifp)
* call the appropriate interface routine on expiration.
*
* XXXRW: Note that because timeouts run with Giant, if_watchdog() is called
- * holding Giant. If we switch to an MPSAFE callout, we likely need to grab
- * Giant before entering if_watchdog() on an IFF_NEEDSGIANT interface.
+ * holding Giant.
*/
static void
if_slowtimo(void *arg)
@@ -1741,9 +1800,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
(new_flags &~ IFF_CANTCHANGE);
if (ifp->if_ioctl) {
- IFF_LOCKGIANT(ifp);
(void) (*ifp->if_ioctl)(ifp, cmd, data);
- IFF_UNLOCKGIANT(ifp);
}
getmicrotime(&ifp->if_lastchange);
break;
@@ -1756,9 +1813,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
return (EOPNOTSUPP);
if (ifr->ifr_reqcap & ~ifp->if_capabilities)
return (EINVAL);
- IFF_LOCKGIANT(ifp);
error = (*ifp->if_ioctl)(ifp, cmd, data);
- IFF_UNLOCKGIANT(ifp);
if (error == 0)
getmicrotime(&ifp->if_lastchange);
break;
@@ -1830,9 +1885,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
return (error);
if (ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
- IFF_LOCKGIANT(ifp);
error = (*ifp->if_ioctl)(ifp, cmd, data);
- IFF_UNLOCKGIANT(ifp);
if (error == 0)
getmicrotime(&ifp->if_lastchange);
break;
@@ -1848,9 +1901,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
return (EINVAL);
if (ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
- IFF_LOCKGIANT(ifp);
error = (*ifp->if_ioctl)(ifp, cmd, data);
- IFF_UNLOCKGIANT(ifp);
if (error == 0) {
getmicrotime(&ifp->if_lastchange);
rt_ifmsg(ifp);
@@ -1920,9 +1971,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
return (error);
if (ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
- IFF_LOCKGIANT(ifp);
error = (*ifp->if_ioctl)(ifp, cmd, data);
- IFF_UNLOCKGIANT(ifp);
if (error == 0)
getmicrotime(&ifp->if_lastchange);
break;
@@ -1938,9 +1987,7 @@ ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
case SIOCGIFGENERIC:
if (ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
- IFF_LOCKGIANT(ifp);
error = (*ifp->if_ioctl)(ifp, cmd, data);
- IFF_UNLOCKGIANT(ifp);
break;
case SIOCSIFLLADDR:
@@ -2043,6 +2090,8 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
error = ((*so->so_proto->pr_usrreqs->pru_control)(so, cmd,
data,
ifp, td));
+ if (error == EOPNOTSUPP && ifp != NULL && ifp->if_ioctl != NULL)
+ error = (*ifp->if_ioctl)(ifp, cmd, data);
#else
{
int ocmd = cmd;
@@ -2084,6 +2133,9 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
cmd,
data,
ifp, td));
+ if (error == EOPNOTSUPP && ifp != NULL &&
+ ifp->if_ioctl != NULL)
+ error = (*ifp->if_ioctl)(ifp, cmd, data);
switch (ocmd) {
case OSIOCGIFADDR:
@@ -2168,9 +2220,7 @@ if_setflag(struct ifnet *ifp, int flag, int pflag, int *refcount, int onswitch)
}
ifr.ifr_flags = ifp->if_flags & 0xffff;
ifr.ifr_flagshigh = ifp->if_flags >> 16;
- IFF_LOCKGIANT(ifp);
error = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
- IFF_UNLOCKGIANT(ifp);
if (error)
goto recover;
/* Notify userland that interface flags have changed */
@@ -2540,9 +2590,7 @@ if_addmulti(struct ifnet *ifp, struct sockaddr *sa,
* interface to let them know about it.
*/
if (ifp->if_ioctl != NULL) {
- IFF_LOCKGIANT(ifp);
(void) (*ifp->if_ioctl)(ifp, SIOCADDMULTI, 0);
- IFF_UNLOCKGIANT(ifp);
}
if (llsa != NULL)
@@ -2601,9 +2649,7 @@ if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
return (ENOENT);
if (lastref && ifp->if_ioctl != NULL) {
- IFF_LOCKGIANT(ifp);
(void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0);
- IFF_UNLOCKGIANT(ifp);
}
return (0);
@@ -2613,9 +2659,7 @@ if_delmulti(struct ifnet *ifp, struct sockaddr *sa)
* Delete a multicast group membership by group membership pointer.
* Network-layer protocol domains must use this routine.
*
- * It is safe to call this routine if the ifp disappeared. Callers should
- * hold IFF_LOCKGIANT() to avoid a LOR in case the hardware needs to be
- * reconfigured.
+ * It is safe to call this routine if the ifp disappeared.
*/
void
if_delmulti_ifma(struct ifmultiaddr *ifma)
@@ -2660,9 +2704,7 @@ if_delmulti_ifma(struct ifmultiaddr *ifma)
*/
IF_ADDR_UNLOCK(ifp);
if (lastref && ifp->if_ioctl != NULL) {
- IFF_LOCKGIANT(ifp);
(void)(*ifp->if_ioctl)(ifp, SIOCDELMULTI, 0);
- IFF_UNLOCKGIANT(ifp);
}
}
}
@@ -2772,6 +2814,7 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
case IFT_BRIDGE:
case IFT_ARCNET:
case IFT_IEEE8023ADLAG:
+ case IFT_IEEE80211:
bcopy(lladdr, LLADDR(sdl), len);
break;
default:
@@ -2784,7 +2827,6 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
*/
if ((ifp->if_flags & IFF_UP) != 0) {
if (ifp->if_ioctl) {
- IFF_LOCKGIANT(ifp);
ifp->if_flags &= ~IFF_UP;
ifr.ifr_flags = ifp->if_flags & 0xffff;
ifr.ifr_flagshigh = ifp->if_flags >> 16;
@@ -2793,7 +2835,6 @@ if_setlladdr(struct ifnet *ifp, const u_char *lladdr, int len)
ifr.ifr_flags = ifp->if_flags & 0xffff;
ifr.ifr_flagshigh = ifp->if_flags >> 16;
(*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr);
- IFF_UNLOCKGIANT(ifp);
}
#ifdef INET
/*
@@ -2839,39 +2880,11 @@ if_printf(struct ifnet *ifp, const char * fmt, ...)
return (retval);
}
-/*
- * When an interface is marked IFF_NEEDSGIANT, its if_start() routine cannot
- * be called without Giant. However, we often can't acquire the Giant lock
- * at those points; instead, we run it via a task queue that holds Giant via
- * if_start_deferred.
- *
- * XXXRW: We need to make sure that the ifnet isn't fully detached until any
- * outstanding if_start_deferred() tasks that will run after the free. This
- * probably means waiting in if_detach().
- */
void
if_start(struct ifnet *ifp)
{
- if (ifp->if_flags & IFF_NEEDSGIANT) {
- if (mtx_owned(&Giant))
- (*(ifp)->if_start)(ifp);
- else
- taskqueue_enqueue(taskqueue_swi_giant,
- &ifp->if_starttask);
- } else
- (*(ifp)->if_start)(ifp);
-}
-
-static void
-if_start_deferred(void *context, int pending)
-{
- struct ifnet *ifp;
-
- GIANT_REQUIRED;
-
- ifp = context;
- (ifp->if_start)(ifp);
+ (*(ifp)->if_start)(ifp);
}
/*
@@ -2908,7 +2921,7 @@ if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp, int adjust)
_IF_ENQUEUE(ifq, m);
IF_UNLOCK(ifq);
if (ifp != NULL && !active)
- if_start(ifp);
+ (*(ifp)->if_start)(ifp);
return (1);
}
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index da73543..ef8cf5b 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -829,9 +829,7 @@ bridge_set_ifcap(struct bridge_softc *sc, struct bridge_iflist *bif, int set)
ifr.ifr_reqcap = set;
if (ifp->if_capenable != set) {
- IFF_LOCKGIANT(ifp);
error = (*ifp->if_ioctl)(ifp, SIOCSIFCAP, (caddr_t)&ifr);
- IFF_UNLOCKGIANT(ifp);
if (error)
if_printf(sc->sc_ifp,
"error setting interface capabilities on %s\n",
@@ -3245,12 +3243,12 @@ bridge_ip_checkbasic(struct mbuf **mp)
if ((m = m_copyup(m, sizeof(struct ip),
(max_linkhdr + 3) & ~3)) == NULL) {
/* XXXJRT new stat, please */
- V_ipstat.ips_toosmall++;
+ IPSTAT_INC(ips_toosmall);
goto bad;
}
} else if (__predict_false(m->m_len < sizeof (struct ip))) {
if ((m = m_pullup(m, sizeof (struct ip))) == NULL) {
- V_ipstat.ips_toosmall++;
+ IPSTAT_INC(ips_toosmall);
goto bad;
}
}
@@ -3258,17 +3256,17 @@ bridge_ip_checkbasic(struct mbuf **mp)
if (ip == NULL) goto bad;
if (ip->ip_v != IPVERSION) {
- V_ipstat.ips_badvers++;
+ IPSTAT_INC(ips_badvers);
goto bad;
}
hlen = ip->ip_hl << 2;
if (hlen < sizeof(struct ip)) { /* minimum header length */
- V_ipstat.ips_badhlen++;
+ IPSTAT_INC(ips_badhlen);
goto bad;
}
if (hlen > m->m_len) {
if ((m = m_pullup(m, hlen)) == 0) {
- V_ipstat.ips_badhlen++;
+ IPSTAT_INC(ips_badhlen);
goto bad;
}
ip = mtod(m, struct ip *);
@@ -3285,7 +3283,7 @@ bridge_ip_checkbasic(struct mbuf **mp)
}
}
if (sum) {
- V_ipstat.ips_badsum++;
+ IPSTAT_INC(ips_badsum);
goto bad;
}
@@ -3296,7 +3294,7 @@ bridge_ip_checkbasic(struct mbuf **mp)
* Check for additional length bogosity
*/
if (len < hlen) {
- V_ipstat.ips_badlen++;
+ IPSTAT_INC(ips_badlen);
goto bad;
}
@@ -3306,7 +3304,7 @@ bridge_ip_checkbasic(struct mbuf **mp)
* Drop packet if shorter than we expect.
*/
if (m->m_pkthdr.len < len) {
- V_ipstat.ips_tooshort++;
+ IPSTAT_INC(ips_tooshort);
goto bad;
}
@@ -3421,7 +3419,7 @@ bridge_fragment(struct ifnet *ifp, struct mbuf *m, struct ether_header *eh,
}
if (error == 0)
- V_ipstat.ips_fragmented++;
+ IPSTAT_INC(ips_fragmented);
return (error);
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index be7fa9f..1c10f17 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -121,6 +121,16 @@ void (*ng_gif_detach_p)(struct ifnet *ifp);
static void gif_start(struct ifnet *);
static int gif_clone_create(struct if_clone *, int, caddr_t);
static void gif_clone_destroy(struct ifnet *);
+static int vnet_gif_iattach(const void *);
+
+#ifndef VIMAGE_GLOBALS
+static const vnet_modinfo_t vnet_gif_modinfo = {
+ .vmi_id = VNET_MOD_GIF,
+ .vmi_name = "gif",
+ .vmi_dependson = VNET_MOD_NET,
+ .vmi_iattach = vnet_gif_iattach
+};
+#endif
IFC_SIMPLE_DECLARE(gif, 0);
@@ -251,6 +261,26 @@ gif_clone_destroy(ifp)
}
static int
+vnet_gif_iattach(const void *unused __unused)
+{
+ INIT_VNET_GIF(curvnet);
+
+ LIST_INIT(&V_gif_softc_list);
+ V_max_gif_nesting = MAX_GIF_NEST;
+#ifdef XBONEHACK
+ V_parallel_tunnels = 1;
+#else
+ V_parallel_tunnels = 0;
+#endif
+ V_ip_gif_ttl = GIF_TTL;
+#ifdef INET6
+ V_ip6_gif_hlim = GIF_HLIM;
+#endif
+
+ return (0);
+}
+
+static int
gifmodevent(mod, type, data)
module_t mod;
int type;
@@ -261,18 +291,10 @@ gifmodevent(mod, type, data)
case MOD_LOAD:
mtx_init(&gif_mtx, "gif_mtx", NULL, MTX_DEF);
- LIST_INIT(&V_gif_softc_list);
- V_max_gif_nesting = MAX_GIF_NEST;
-#ifdef XBONEHACK
- V_parallel_tunnels = 1;
+#ifndef VIMAGE_GLOBALS
+ vnet_mod_register(&vnet_gif_modinfo);
#else
- V_parallel_tunnels = 0;
-#endif
-#ifdef INET
- V_ip_gif_ttl = GIF_TTL;
-#endif
-#ifdef INET6
- V_ip6_gif_hlim = GIF_HLIM;
+ vnet_gif_iattach(NULL);
#endif
if_clone_attach(&gif_cloner);
@@ -281,7 +303,7 @@ gifmodevent(mod, type, data)
if_clone_detach(&gif_cloner);
mtx_destroy(&gif_mtx);
#ifdef INET6
- V_ip6_gif_hlim = 0;
+ V_ip6_gif_hlim = 0; /* XXX -> vnet_gif_idetach() */
#endif
break;
default:
diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
index d5548fc..c31acef 100644
--- a/sys/net/if_loop.c
+++ b/sys/net/if_loop.c
@@ -94,17 +94,31 @@
#define LOMTU 16384
#endif
+#define LO_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_SCTP)
+#define LO_CSUM_SET (CSUM_DATA_VALID | CSUM_PSEUDO_HDR | \
+ CSUM_IP_CHECKED | CSUM_IP_VALID | \
+ CSUM_SCTP_VALID)
+
int loioctl(struct ifnet *, u_long, caddr_t);
static void lortrequest(int, struct rtentry *, struct rt_addrinfo *);
int looutput(struct ifnet *ifp, struct mbuf *m,
struct sockaddr *dst, struct rtentry *rt);
static int lo_clone_create(struct if_clone *, int, caddr_t);
static void lo_clone_destroy(struct ifnet *);
+static int vnet_loif_iattach(const void *);
#ifdef VIMAGE_GLOBALS
struct ifnet *loif; /* Used externally */
#endif
+#ifndef VIMAGE_GLOBALS
+static const vnet_modinfo_t vnet_loif_modinfo = {
+ .vmi_id = VNET_MOD_LOIF,
+ .vmi_name = "loif",
+ .vmi_iattach = vnet_loif_iattach
+};
+#endif /* !VIMAGE_GLOBALS */
+
IFC_SIMPLE_DECLARE(lo, 1);
static void
@@ -138,6 +152,8 @@ lo_clone_create(struct if_clone *ifc, int unit, caddr_t params)
ifp->if_ioctl = loioctl;
ifp->if_output = looutput;
ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ ifp->if_capabilities = ifp->if_capenable = IFCAP_HWCSUM;
+ ifp->if_hwassist = LO_CSUM_FEATURES;
if_attach(ifp);
bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
if (V_loif == NULL)
@@ -146,6 +162,15 @@ lo_clone_create(struct if_clone *ifc, int unit, caddr_t params)
return (0);
}
+static int vnet_loif_iattach(const void *unused __unused)
+{
+ INIT_VNET_NET(curvnet);
+
+ V_loif = NULL;
+ if_clone_attach(&lo_cloner);
+ return (0);
+}
+
static int
loop_modevent(module_t mod, int type, void *data)
{
@@ -153,8 +178,11 @@ loop_modevent(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
- V_loif = NULL;
- if_clone_attach(&lo_cloner);
+#ifndef VIMAGE_GLOBALS
+ vnet_mod_register(&vnet_loif_modinfo);
+#else
+ vnet_loif_iattach(NULL);
+#endif
break;
case MOD_UNLOAD:
@@ -212,6 +240,11 @@ looutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
#if 1 /* XXX */
switch (dst->sa_family) {
case AF_INET:
+ if (ifp->if_capenable & IFCAP_RXCSUM) {
+ m->m_pkthdr.csum_data = 0xffff;
+ m->m_pkthdr.csum_flags = LO_CSUM_SET;
+ }
+ m->m_pkthdr.csum_flags &= ~LO_CSUM_FEATURES;
case AF_INET6:
case AF_IPX:
case AF_APPLETALK:
@@ -348,7 +381,7 @@ loioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct ifaddr *ifa;
struct ifreq *ifr = (struct ifreq *)data;
- int error = 0;
+ int error = 0, mask;
switch (cmd) {
case SIOCSIFADDR:
@@ -391,6 +424,18 @@ loioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCSIFFLAGS:
break;
+ case SIOCSIFCAP:
+ mask = ifp->if_capenable ^ ifr->ifr_reqcap;
+ if ((mask & IFCAP_RXCSUM) != 0)
+ ifp->if_capenable ^= IFCAP_RXCSUM;
+ if ((mask & IFCAP_TXCSUM) != 0)
+ ifp->if_capenable ^= IFCAP_TXCSUM;
+ if (ifp->if_capenable & IFCAP_TXCSUM)
+ ifp->if_hwassist = LO_CSUM_FEATURES;
+ else
+ ifp->if_hwassist = 0;
+ break;
+
default:
error = EINVAL;
}
diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c
deleted file mode 100644
index 753adf9..0000000
--- a/sys/net/if_ppp.c
+++ /dev/null
@@ -1,1733 +0,0 @@
-/*
- * if_ppp.c - Point-to-Point Protocol (PPP) Asynchronous driver.
- */
-
-/*-
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Drew D. Perkins
- * Carnegie Mellon University
- * 4910 Forbes Ave.
- * Pittsburgh, PA 15213
- * (412) 268-8576
- * ddp@andrew.cmu.edu
- *
- * Based on:
- * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
- *
- * Copyright (c) 1987 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Serial Line interface
- *
- * Rick Adams
- * Center for Seismic Studies
- * 1300 N 17th Street, Suite 1450
- * Arlington, Virginia 22209
- * (703)276-7900
- * rick@seismo.ARPA
- * seismo!rick
- *
- * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
- * Converted to 4.3BSD Beta by Chris Torek.
- * Other changes made at Berkeley, based in part on code by Kirk Smith.
- *
- * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
- * Added VJ tcp header compression; more unified ioctls
- *
- * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
- * Cleaned up a lot of the mbuf-related code to fix bugs that
- * caused system crashes and packet corruption. Changed pppstart
- * so that it doesn't just give up with a collision if the whole
- * packet doesn't fit in the output ring buffer.
- *
- * Added priority queueing for interactive IP packets, following
- * the model of if_sl.c, plus hooks for bpf.
- * Paul Mackerras (paulus@cs.anu.edu.au).
- */
-
-/* $FreeBSD$ */
-/* from if_sl.c,v 1.11 84/10/04 12:54:47 rick Exp */
-/* from NetBSD: if_ppp.c,v 1.15.2.2 1994/07/28 05:17:58 cgd Exp */
-
-#include "opt_inet.h"
-#include "opt_inet6.h"
-#include "opt_ipx.h"
-#include "opt_mac.h"
-#include "opt_ppp.h"
-
-#ifdef INET
-#define VJC
-#endif
-#define PPP_COMPRESS
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/priv.h>
-#include <sys/proc.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/filio.h>
-#include <sys/sockio.h>
-#include <sys/kernel.h>
-#include <sys/time.h>
-#include <sys/malloc.h>
-#include <sys/module.h>
-
-#include <net/if.h>
-#include <net/if_clone.h>
-#include <net/if_types.h>
-#include <net/netisr.h>
-#include <net/bpf.h>
-
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#endif
-
-#ifdef IPX
-#include <netipx/ipx.h>
-#include <netipx/ipx_if.h>
-#endif
-
-#ifdef VJC
-#include <net/slcompress.h>
-#endif
-
-#include <net/if_ppp.h>
-#include <net/if_pppvar.h>
-
-#include <security/mac/mac_framework.h>
-
-/* minimise diffs */
-#ifndef splsoftnet
-#define splsoftnet splnet
-#endif
-
-#ifdef PPP_COMPRESS
-#define PACKETPTR struct mbuf *
-#include <net/ppp_comp.h>
-#endif
-
-#define PPPNAME "ppp"
-static MALLOC_DEFINE(M_PPP, PPPNAME, "PPP interface");
-
-static struct mtx ppp_softc_list_mtx;
-static LIST_HEAD(, ppp_softc) ppp_softc_list;
-
-#define PPP_LIST_LOCK_INIT() mtx_init(&ppp_softc_list_mtx, \
- "ppp_softc_list_mtx", NULL, MTX_DEF)
-#define PPP_LIST_LOCK_DESTROY() mtx_destroy(&ppp_softc_list_mtx)
-#define PPP_LIST_LOCK() mtx_lock(&ppp_softc_list_mtx)
-#define PPP_LIST_UNLOCK() mtx_unlock(&ppp_softc_list_mtx)
-
-/* XXX layering violation */
-extern void pppasyncattach(void *);
-extern void pppasyncdetach(void);
-
-static int pppsioctl(struct ifnet *ifp, u_long cmd, caddr_t data);
-static void pppintr(void);
-
-static void ppp_requeue(struct ppp_softc *);
-static void ppp_ccp(struct ppp_softc *, struct mbuf *m, int rcvd);
-static void ppp_ccp_closed(struct ppp_softc *);
-static void ppp_inproc(struct ppp_softc *, struct mbuf *);
-static void pppdumpm(struct mbuf *m0);
-static int ppp_clone_create(struct if_clone *, int, caddr_t);
-static void ppp_clone_destroy(struct ifnet *);
-
-IFC_SIMPLE_DECLARE(ppp, 0);
-
-/*
- * Some useful mbuf macros not in mbuf.h.
- */
-#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
-
-#define M_DATASTART(m) \
- (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
- (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
-
-#define M_DATASIZE(m) \
- (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
- (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
-
-/*
- * We steal two bits in the mbuf m_flags, to mark high-priority packets
- * for output, and received packets following lost/corrupted packets.
- */
-#define M_HIGHPRI 0x2000 /* output packet for sc_fastq */
-#define M_ERRMARK 0x4000 /* steal a bit in mbuf m_flags */
-
-
-#ifdef PPP_COMPRESS
-/*
- * List of compressors we know about.
- * We leave some space so maybe we can modload compressors.
- */
-
-extern struct compressor ppp_bsd_compress;
-extern struct compressor ppp_deflate, ppp_deflate_draft;
-
-static struct compressor *ppp_compressors[8] = {
-#if defined(PPP_BSDCOMP)
- &ppp_bsd_compress,
-#endif
-#if defined(PPP_DEFLATE)
- &ppp_deflate,
- &ppp_deflate_draft,
-#endif
- NULL
-};
-#endif /* PPP_COMPRESS */
-
-static int
-ppp_clone_create(struct if_clone *ifc, int unit, caddr_t params)
-{
- struct ifnet *ifp;
- struct ppp_softc *sc;
-
- sc = malloc(sizeof(struct ppp_softc), M_PPP, M_WAITOK | M_ZERO);
- ifp = sc->sc_ifp = if_alloc(IFT_PPP);
- if (ifp == NULL) {
- free(sc, M_PPP);
- return (ENOSPC);
- }
-
- callout_init(&sc->sc_timo_ch, 0);
- ifp->if_softc = sc;
- if_initname(ifp, ifc->ifc_name, unit);
- ifp->if_mtu = PPP_MTU;
- ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST | IFF_NEEDSGIANT;
- ifp->if_hdrlen = PPP_HDRLEN;
- ifp->if_ioctl = pppsioctl;
- ifp->if_output = pppoutput;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
- sc->sc_inq.ifq_maxlen = IFQ_MAXLEN;
- sc->sc_fastq.ifq_maxlen = IFQ_MAXLEN;
- sc->sc_rawq.ifq_maxlen = IFQ_MAXLEN;
- mtx_init(&sc->sc_inq.ifq_mtx, "ppp_inq", NULL, MTX_DEF);
- mtx_init(&sc->sc_fastq.ifq_mtx, "ppp_fastq", NULL, MTX_DEF);
- mtx_init(&sc->sc_rawq.ifq_mtx, "ppp_rawq", NULL, MTX_DEF);
- if_attach(ifp);
- bpfattach(ifp, DLT_PPP, PPP_HDRLEN);
-
- PPP_LIST_LOCK();
- LIST_INSERT_HEAD(&ppp_softc_list, sc, sc_list);
- PPP_LIST_UNLOCK();
-
- return (0);
-}
-
-static void
-ppp_clone_destroy(struct ifnet *ifp)
-{
- struct ppp_softc *sc;
-
- sc = ifp->if_softc;
- PPP_LIST_LOCK();
- LIST_REMOVE(sc, sc_list);
- PPP_LIST_UNLOCK();
-
- bpfdetach(ifp);
- if_detach(ifp);
- if_free(ifp);
- mtx_destroy(&sc->sc_rawq.ifq_mtx);
- mtx_destroy(&sc->sc_fastq.ifq_mtx);
- mtx_destroy(&sc->sc_inq.ifq_mtx);
- free(sc, M_PPP);
-}
-
-static int
-ppp_modevent(module_t mod, int type, void *data)
-{
-
- switch (type) {
- case MOD_LOAD:
- PPP_LIST_LOCK_INIT();
- LIST_INIT(&ppp_softc_list);
- if_clone_attach(&ppp_cloner);
-
- netisr_register(NETISR_PPP, (netisr_t *)pppintr, NULL,
- NETISR_FORCEQUEUE);
- /*
- * XXX layering violation - if_ppp can work over any lower
- * level transport that cares to attach to it.
- */
- pppasyncattach(NULL);
- break;
- case MOD_UNLOAD:
- /* XXX: layering violation */
- pppasyncdetach();
-
- netisr_unregister(NETISR_PPP);
-
- if_clone_detach(&ppp_cloner);
- PPP_LIST_LOCK_DESTROY();
- break;
- default:
- return EOPNOTSUPP;
- }
- return 0;
-}
-
-static moduledata_t ppp_mod = {
- "if_ppp",
- ppp_modevent,
- 0
-};
-
-DECLARE_MODULE(if_ppp, ppp_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
-
-/*
- * Allocate a ppp interface unit and initialize it.
- */
-struct ppp_softc *
-pppalloc(pid)
- pid_t pid;
-{
- int i;
- char tmpname[IFNAMSIZ];
- struct ifnet *ifp;
- struct ppp_softc *sc;
-
- PPP_LIST_LOCK();
- LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
- if (sc->sc_xfer == pid) {
- sc->sc_xfer = 0;
- PPP_LIST_UNLOCK();
- return sc;
- }
- }
- LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
- if (sc->sc_devp == NULL)
- break;
- }
- PPP_LIST_UNLOCK();
- /* Try to clone an interface if we don't have a free one */
- if (sc == NULL) {
- strcpy(tmpname, PPPNAME);
- if (if_clone_create(tmpname, sizeof(tmpname), (caddr_t) 0) != 0)
- return NULL;
- ifp = ifunit(tmpname);
- if (ifp == NULL)
- return NULL;
- sc = ifp->if_softc;
- }
- if (sc == NULL || sc->sc_devp != NULL)
- return NULL;
-
- sc->sc_flags = 0;
- sc->sc_mru = PPP_MRU;
- sc->sc_relinq = NULL;
- bzero((char *)&sc->sc_stats, sizeof(sc->sc_stats));
-#ifdef VJC
- sc->sc_comp = malloc(sizeof(struct slcompress),
- M_DEVBUF, M_NOWAIT);
- if (sc->sc_comp)
- sl_compress_init(sc->sc_comp, -1);
-#endif
-#ifdef PPP_COMPRESS
- sc->sc_xc_state = NULL;
- sc->sc_rc_state = NULL;
-#endif /* PPP_COMPRESS */
- for (i = 0; i < NUM_NP; ++i)
- sc->sc_npmode[i] = NPMODE_ERROR;
- sc->sc_npqueue = NULL;
- sc->sc_npqtail = &sc->sc_npqueue;
- sc->sc_last_sent = sc->sc_last_recv = time_uptime;
-
- return sc;
-}
-
-/*
- * Deallocate a ppp unit. Must be called at splsoftnet or higher.
- */
-void
-pppdealloc(sc)
- struct ppp_softc *sc;
-{
- struct mbuf *m;
-
- if_down(PPP2IFP(sc));
- PPP2IFP(sc)->if_flags &= ~IFF_UP;
- PPP2IFP(sc)->if_drv_flags &= ~IFF_DRV_RUNNING;
- getmicrotime(&PPP2IFP(sc)->if_lastchange);
- sc->sc_devp = NULL;
- sc->sc_xfer = 0;
- IF_DRAIN(&sc->sc_rawq);
- IF_DRAIN(&sc->sc_inq);
- IF_DRAIN(&sc->sc_fastq);
- while ((m = sc->sc_npqueue) != NULL) {
- sc->sc_npqueue = m->m_nextpkt;
- m_freem(m);
- }
-#ifdef PPP_COMPRESS
- ppp_ccp_closed(sc);
- sc->sc_xc_state = NULL;
- sc->sc_rc_state = NULL;
-#endif /* PPP_COMPRESS */
-#ifdef PPP_FILTER
- if (sc->sc_pass_filt.bf_insns != 0) {
- free(sc->sc_pass_filt.bf_insns, M_DEVBUF);
- sc->sc_pass_filt.bf_insns = 0;
- sc->sc_pass_filt.bf_len = 0;
- }
- if (sc->sc_active_filt.bf_insns != 0) {
- free(sc->sc_active_filt.bf_insns, M_DEVBUF);
- sc->sc_active_filt.bf_insns = 0;
- sc->sc_active_filt.bf_len = 0;
- }
-#endif /* PPP_FILTER */
-#ifdef VJC
- if (sc->sc_comp != 0) {
- free(sc->sc_comp, M_DEVBUF);
- sc->sc_comp = 0;
- }
-#endif
-}
-
-/*
- * Ioctl routine for generic ppp devices.
- */
-int
-pppioctl(sc, cmd, data, flag, td)
- struct ppp_softc *sc;
- u_long cmd;
- caddr_t data;
- int flag;
- struct thread *td;
-{
- struct proc *p = td->td_proc;
- int s, flags, mru, npx;
- u_int nb;
- int error = 0;
- struct ppp_option_data *odp;
- struct compressor **cp;
- struct npioctl *npi;
- time_t t;
-#ifdef PPP_FILTER
- struct bpf_program *bp, *nbp;
- struct bpf_insn *newcode, *oldcode;
- int newcodelen;
-#endif /* PPP_FILTER */
-#ifdef PPP_COMPRESS
- u_char ccp_option[CCP_MAX_OPTION_LENGTH];
-#endif
-
- switch (cmd) {
- case FIONREAD:
- *(int *)data = sc->sc_inq.ifq_len;
- break;
-
- case PPPIOCGUNIT:
- *(int *)data = PPP2IFP(sc)->if_dunit;
- break;
-
- case PPPIOCGFLAGS:
- *(u_int *)data = sc->sc_flags;
- break;
-
- case PPPIOCSFLAGS:
- error = priv_check(td, PRIV_NET_PPP);
- if (error)
- break;
- flags = *(int *)data & SC_MASK;
- s = splsoftnet();
-#ifdef PPP_COMPRESS
- if (sc->sc_flags & SC_CCP_OPEN && !(flags & SC_CCP_OPEN))
- ppp_ccp_closed(sc);
-#endif
- splimp();
- sc->sc_flags = (sc->sc_flags & ~SC_MASK) | flags;
- splx(s);
- break;
-
- case PPPIOCSMRU:
- error = priv_check(td, PRIV_NET_PPP);
- if (error)
- return (error);
- mru = *(int *)data;
- if (mru >= PPP_MRU && mru <= PPP_MAXMRU)
- sc->sc_mru = mru;
- break;
-
- case PPPIOCGMRU:
- *(int *)data = sc->sc_mru;
- break;
-
-#ifdef VJC
- case PPPIOCSMAXCID:
- error = priv_check(td, PRIV_NET_PPP);
- if (error)
- break;
- if (sc->sc_comp) {
- s = splsoftnet();
- sl_compress_init(sc->sc_comp, *(int *)data);
- splx(s);
- }
- break;
-#endif
-
- case PPPIOCXFERUNIT:
- error = priv_check(td, PRIV_NET_PPP);
- if (error)
- break;
- sc->sc_xfer = p->p_pid;
- break;
-
-#ifdef PPP_COMPRESS
- case PPPIOCSCOMPRESS:
- error = priv_check(td, PRIV_NET_PPP);
- if (error)
- break;
- odp = (struct ppp_option_data *) data;
- nb = odp->length;
- if (nb > sizeof(ccp_option))
- nb = sizeof(ccp_option);
- if ((error = copyin(odp->ptr, ccp_option, nb)) != 0)
- break;
- if (ccp_option[1] < 2) { /* preliminary check on the length byte */
- error = EINVAL;
- break;
- }
- for (cp = ppp_compressors; *cp != NULL; ++cp)
- if ((*cp)->compress_proto == ccp_option[0]) {
- /*
- * Found a handler for the protocol - try to allocate
- * a compressor or decompressor.
- */
- error = 0;
- if (odp->transmit) {
- s = splsoftnet();
- if (sc->sc_xc_state != NULL)
- (*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
- sc->sc_xcomp = *cp;
- sc->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb);
- if (sc->sc_xc_state == NULL) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "comp_alloc failed\n");
- error = ENOBUFS;
- }
- splimp();
- sc->sc_flags &= ~SC_COMP_RUN;
- splx(s);
- } else {
- s = splsoftnet();
- if (sc->sc_rc_state != NULL)
- (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
- sc->sc_rcomp = *cp;
- sc->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb);
- if (sc->sc_rc_state == NULL) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "decomp_alloc failed\n");
- error = ENOBUFS;
- }
- splimp();
- sc->sc_flags &= ~SC_DECOMP_RUN;
- splx(s);
- }
- return (error);
- }
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "no compressor for [%x %x %x], %x\n",
- ccp_option[0], ccp_option[1], ccp_option[2], nb);
- error = EINVAL; /* no handler found */
- break;
-#endif /* PPP_COMPRESS */
-
- case PPPIOCGNPMODE:
- case PPPIOCSNPMODE:
- npi = (struct npioctl *) data;
- npx = 0; /* XXX: quiet gcc */
- switch (npi->protocol) {
- case PPP_IP:
- npx = NP_IP;
- break;
- case PPP_IPV6:
- npx = NP_IPV6;
- break;
- default:
- error = EINVAL;
- }
- if (error)
- break;
- if (cmd == PPPIOCGNPMODE) {
- npi->mode = sc->sc_npmode[npx];
- } else {
- error = priv_check(td, PRIV_NET_PPP);
- if (error)
- break;
- if (npi->mode != sc->sc_npmode[npx]) {
- s = splsoftnet();
- sc->sc_npmode[npx] = npi->mode;
- if (npi->mode != NPMODE_QUEUE) {
- ppp_requeue(sc);
- (*sc->sc_start)(sc);
- }
- splx(s);
- }
- }
- break;
-
- case PPPIOCGIDLE:
- s = splsoftnet();
- t = time_uptime;
- ((struct ppp_idle *)data)->xmit_idle = t - sc->sc_last_sent;
- ((struct ppp_idle *)data)->recv_idle = t - sc->sc_last_recv;
- splx(s);
- break;
-
-#ifdef PPP_FILTER
- case PPPIOCSPASS:
- case PPPIOCSACTIVE:
- nbp = (struct bpf_program *) data;
- if ((unsigned) nbp->bf_len > BPF_MAXINSNS) {
- error = EINVAL;
- break;
- }
- newcodelen = nbp->bf_len * sizeof(struct bpf_insn);
- if (newcodelen != 0) {
- newcode = malloc(newcodelen, M_DEVBUF, M_WAITOK);
- if (newcode == 0) {
- error = EINVAL; /* or sumpin */
- break;
- }
- if ((error = copyin((caddr_t)nbp->bf_insns, (caddr_t)newcode,
- newcodelen)) != 0) {
- free(newcode, M_DEVBUF);
- break;
- }
- if (!bpf_validate(newcode, nbp->bf_len)) {
- free(newcode, M_DEVBUF);
- error = EINVAL;
- break;
- }
- } else
- newcode = 0;
- bp = (cmd == PPPIOCSPASS)? &sc->sc_pass_filt: &sc->sc_active_filt;
- oldcode = bp->bf_insns;
- s = splimp();
- bp->bf_len = nbp->bf_len;
- bp->bf_insns = newcode;
- splx(s);
- if (oldcode != 0)
- free(oldcode, M_DEVBUF);
- break;
-#endif
-
- default:
- error = ENOIOCTL;
- break;
- }
- return (error);
-}
-
-/*
- * Process an ioctl request to the ppp network interface.
- */
-static int
-pppsioctl(ifp, cmd, data)
- register struct ifnet *ifp;
- u_long cmd;
- caddr_t data;
-{
- struct thread *td = curthread; /* XXX */
- register struct ppp_softc *sc = ifp->if_softc;
- register struct ifaddr *ifa = (struct ifaddr *)data;
- register struct ifreq *ifr = (struct ifreq *)data;
- struct ppp_stats *psp;
-#ifdef PPP_COMPRESS
- struct ppp_comp_stats *pcp;
-#endif
- int s = splimp(), error = 0;
-
- switch (cmd) {
- case SIOCSIFFLAGS:
- if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
- ifp->if_flags &= ~IFF_UP;
- break;
-
- case SIOCSIFADDR:
- case SIOCAIFADDR:
- switch(ifa->ifa_addr->sa_family) {
-#ifdef INET
- case AF_INET:
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- break;
-#endif
-#ifdef IPX
- case AF_IPX:
- break;
-#endif
- default:
- error = EAFNOSUPPORT;
- break;
- }
- break;
-
- case SIOCSIFDSTADDR:
- switch(ifa->ifa_addr->sa_family) {
-#ifdef INET
- case AF_INET:
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- break;
-#endif
-#ifdef IPX
- case AF_IPX:
- break;
-#endif
- default:
- error = EAFNOSUPPORT;
- break;
- }
- break;
-
- case SIOCSIFMTU:
- /*
- * XXXRW: Isn't this priv_check() check redundant to the one at the
- * ifnet layer?
- */
- error = priv_check(td, PRIV_NET_SETIFMTU);
- if (error)
- break;
- if (ifr->ifr_mtu > PPP_MAXMTU)
- error = EINVAL;
- else {
- PPP2IFP(sc)->if_mtu = ifr->ifr_mtu;
- if (sc->sc_setmtu)
- (*sc->sc_setmtu)(sc);
- }
- break;
-
- case SIOCGIFMTU:
- ifr->ifr_mtu = PPP2IFP(sc)->if_mtu;
- break;
-
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- if (ifr == 0) {
- error = EAFNOSUPPORT;
- break;
- }
- switch(ifr->ifr_addr.sa_family) {
-#ifdef INET
- case AF_INET:
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- break;
-#endif
- default:
- error = EAFNOSUPPORT;
- break;
- }
- break;
-
- case SIOCGPPPSTATS:
- psp = &((struct ifpppstatsreq *) data)->stats;
- bzero(psp, sizeof(*psp));
- psp->p = sc->sc_stats;
-#if defined(VJC) && !defined(SL_NO_STATS)
- if (sc->sc_comp) {
- psp->vj.vjs_packets = sc->sc_comp->sls_packets;
- psp->vj.vjs_compressed = sc->sc_comp->sls_compressed;
- psp->vj.vjs_searches = sc->sc_comp->sls_searches;
- psp->vj.vjs_misses = sc->sc_comp->sls_misses;
- psp->vj.vjs_uncompressedin = sc->sc_comp->sls_uncompressedin;
- psp->vj.vjs_compressedin = sc->sc_comp->sls_compressedin;
- psp->vj.vjs_errorin = sc->sc_comp->sls_errorin;
- psp->vj.vjs_tossed = sc->sc_comp->sls_tossed;
- }
-#endif /* VJC */
- break;
-
-#ifdef PPP_COMPRESS
- case SIOCGPPPCSTATS:
- pcp = &((struct ifpppcstatsreq *) data)->stats;
- bzero(pcp, sizeof(*pcp));
- if (sc->sc_xc_state != NULL)
- (*sc->sc_xcomp->comp_stat)(sc->sc_xc_state, &pcp->c);
- if (sc->sc_rc_state != NULL)
- (*sc->sc_rcomp->decomp_stat)(sc->sc_rc_state, &pcp->d);
- break;
-#endif /* PPP_COMPRESS */
-
- default:
- error = ENOTTY;
- }
- splx(s);
- return (error);
-}
-
-/*
- * Queue a packet. Start transmission if not active.
- * Packet is placed in Information field of PPP frame.
- * Called at splnet as the if->if_output handler.
- * Called at splnet from pppwrite().
- */
-int
-pppoutput(ifp, m0, dst, rtp)
- struct ifnet *ifp;
- struct mbuf *m0;
- struct sockaddr *dst;
- struct rtentry *rtp;
-{
- register struct ppp_softc *sc = ifp->if_softc;
- int protocol, address, control;
- u_char *cp;
- int s, error;
- struct ip *ip;
- struct ifqueue *ifq;
- enum NPmode mode;
- int len;
-
-#ifdef MAC
- error = mac_ifnet_check_transmit(ifp, m0);
- if (error)
- goto bad;
-#endif
-
- if (sc->sc_devp == NULL || (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0
- || ((ifp->if_flags & IFF_UP) == 0 && dst->sa_family != AF_UNSPEC)) {
- error = ENETDOWN; /* sort of */
- goto bad;
- }
-
- /*
- * Compute PPP header.
- */
- m0->m_flags &= ~M_HIGHPRI;
- switch (dst->sa_family) {
-#ifdef INET
- case AF_INET:
- address = PPP_ALLSTATIONS;
- control = PPP_UI;
- protocol = PPP_IP;
- mode = sc->sc_npmode[NP_IP];
-
- /*
- * If this packet has the "low delay" bit set in the IP header,
- * put it on the fastq instead.
- */
- ip = mtod(m0, struct ip *);
- if (ip->ip_tos & IPTOS_LOWDELAY)
- m0->m_flags |= M_HIGHPRI;
- break;
-#endif
-#ifdef INET6
- case AF_INET6:
- address = PPP_ALLSTATIONS; /*XXX*/
- control = PPP_UI; /*XXX*/
- protocol = PPP_IPV6;
- mode = sc->sc_npmode[NP_IPV6];
-
-#if 0 /* XXX flowinfo/traffic class, maybe? */
- /*
- * If this packet has the "low delay" bit set in the IP header,
- * put it on the fastq instead.
- */
- ip = mtod(m0, struct ip *);
- if (ip->ip_tos & IPTOS_LOWDELAY)
- m0->m_flags |= M_HIGHPRI;
-#endif
- break;
-#endif
-#ifdef IPX
- case AF_IPX:
- /*
- * This is pretty bogus.. We dont have an ipxcp module in pppd
- * yet to configure the link parameters. Sigh. I guess a
- * manual ifconfig would do.... -Peter
- */
- address = PPP_ALLSTATIONS;
- control = PPP_UI;
- protocol = PPP_IPX;
- mode = NPMODE_PASS;
- break;
-#endif
- case AF_UNSPEC:
- address = PPP_ADDRESS(dst->sa_data);
- control = PPP_CONTROL(dst->sa_data);
- protocol = PPP_PROTOCOL(dst->sa_data);
- mode = NPMODE_PASS;
- break;
- default:
- if_printf(ifp, "af%d not supported\n", dst->sa_family);
- error = EAFNOSUPPORT;
- goto bad;
- }
-
- /*
- * Drop this packet, or return an error, if necessary.
- */
- if (mode == NPMODE_ERROR) {
- error = ENETDOWN;
- goto bad;
- }
- if (mode == NPMODE_DROP) {
- error = 0;
- goto bad;
- }
-
- /*
- * Add PPP header. If no space in first mbuf, allocate another.
- * (This assumes M_LEADINGSPACE is always 0 for a cluster mbuf.)
- */
- if (M_LEADINGSPACE(m0) < PPP_HDRLEN) {
- m0 = m_prepend(m0, PPP_HDRLEN, M_DONTWAIT);
- if (m0 == 0) {
- error = ENOBUFS;
- goto bad;
- }
- m0->m_len = 0;
- } else
- m0->m_data -= PPP_HDRLEN;
-
- cp = mtod(m0, u_char *);
- *cp++ = address;
- *cp++ = control;
- *cp++ = protocol >> 8;
- *cp++ = protocol & 0xff;
- m0->m_len += PPP_HDRLEN;
-
- len = m_length(m0, NULL);
-
- if (sc->sc_flags & SC_LOG_OUTPKT) {
- printf("%s output: ", ifp->if_xname);
- pppdumpm(m0);
- }
-
- if ((protocol & 0x8000) == 0) {
-#ifdef PPP_FILTER
- /*
- * Apply the pass and active filters to the packet,
- * but only if it is a data packet.
- */
- *mtod(m0, u_char *) = 1; /* indicates outbound */
- if (sc->sc_pass_filt.bf_insns != 0
- && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m0,
- len, 0) == 0) {
- error = 0; /* drop this packet */
- goto bad;
- }
-
- /*
- * Update the time we sent the most recent packet.
- */
- if (sc->sc_active_filt.bf_insns == 0
- || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m0, len, 0))
- sc->sc_last_sent = time_uptime;
-
- *mtod(m0, u_char *) = address;
-#else
- /*
- * Update the time we sent the most recent data packet.
- */
- sc->sc_last_sent = time_uptime;
-#endif /* PPP_FILTER */
- }
-
- /*
- * See if bpf wants to look at the packet.
- */
- BPF_MTAP(ifp, m0);
-
- /*
- * Put the packet on the appropriate queue.
- */
- s = splsoftnet(); /* redundant */
- if (mode == NPMODE_QUEUE) {
- /* XXX we should limit the number of packets on this queue */
- *sc->sc_npqtail = m0;
- m0->m_nextpkt = NULL;
- sc->sc_npqtail = &m0->m_nextpkt;
- } else {
- /* fastq and if_snd are emptied at spl[soft]net now */
- ifq = (m0->m_flags & M_HIGHPRI)? &sc->sc_fastq:
- (struct ifqueue *)&ifp->if_snd;
- IF_LOCK(ifq);
- if (_IF_QFULL(ifq) && dst->sa_family != AF_UNSPEC) {
- _IF_DROP(ifq);
- IF_UNLOCK(ifq);
- PPP2IFP(sc)->if_oerrors++;
- sc->sc_stats.ppp_oerrors++;
- error = ENOBUFS;
- goto bad;
- }
- _IF_ENQUEUE(ifq, m0);
- IF_UNLOCK(ifq);
- (*sc->sc_start)(sc);
- }
- getmicrotime(&ifp->if_lastchange);
- ifp->if_opackets++;
- ifp->if_obytes += len;
-
- splx(s);
- return (0);
-
-bad:
- m_freem(m0);
- return (error);
-}
-
-/*
- * After a change in the NPmode for some NP, move packets from the
- * npqueue to the send queue or the fast queue as appropriate.
- * Should be called at spl[soft]net.
- */
-static void
-ppp_requeue(sc)
- struct ppp_softc *sc;
-{
- struct mbuf *m, **mpp;
- struct ifqueue *ifq;
- enum NPmode mode;
-
- for (mpp = &sc->sc_npqueue; (m = *mpp) != NULL; ) {
- switch (PPP_PROTOCOL(mtod(m, u_char *))) {
- case PPP_IP:
- mode = sc->sc_npmode[NP_IP];
- break;
- case PPP_IPV6:
- mode = sc->sc_npmode[NP_IPV6];
- break;
- default:
- mode = NPMODE_PASS;
- }
-
- switch (mode) {
- case NPMODE_PASS:
- /*
- * This packet can now go on one of the queues to be sent.
- */
- *mpp = m->m_nextpkt;
- m->m_nextpkt = NULL;
- ifq = (m->m_flags & M_HIGHPRI)? &sc->sc_fastq:
- (struct ifqueue *)&PPP2IFP(sc)->if_snd;
- if (! IF_HANDOFF(ifq, m, NULL)) {
- PPP2IFP(sc)->if_oerrors++;
- sc->sc_stats.ppp_oerrors++;
- }
- break;
-
- case NPMODE_DROP:
- case NPMODE_ERROR:
- *mpp = m->m_nextpkt;
- m_freem(m);
- break;
-
- case NPMODE_QUEUE:
- mpp = &m->m_nextpkt;
- break;
- }
- }
- sc->sc_npqtail = mpp;
-}
-
-/*
- * Transmitter has finished outputting some stuff;
- * remember to call sc->sc_start later at splsoftnet.
- */
-void
-ppp_restart(sc)
- struct ppp_softc *sc;
-{
- int s = splimp();
-
- sc->sc_flags &= ~SC_TBUSY;
- schednetisr(NETISR_PPP);
- splx(s);
-}
-
-
-/*
- * Get a packet to send. This procedure is intended to be called at
- * splsoftnet, since it may involve time-consuming operations such as
- * applying VJ compression, packet compression, address/control and/or
- * protocol field compression to the packet.
- */
-struct mbuf *
-ppp_dequeue(sc)
- struct ppp_softc *sc;
-{
- struct mbuf *m, *mp;
- u_char *cp;
- int address, control, protocol;
-
- /*
- * Grab a packet to send: first try the fast queue, then the
- * normal queue.
- */
- IF_DEQUEUE(&sc->sc_fastq, m);
- if (m == NULL)
- IF_DEQUEUE(&PPP2IFP(sc)->if_snd, m);
- if (m == NULL)
- return NULL;
-
- ++sc->sc_stats.ppp_opackets;
-
- /*
- * Extract the ppp header of the new packet.
- * The ppp header will be in one mbuf.
- */
- cp = mtod(m, u_char *);
- address = PPP_ADDRESS(cp);
- control = PPP_CONTROL(cp);
- protocol = PPP_PROTOCOL(cp);
-
- switch (protocol) {
- case PPP_IP:
-#ifdef VJC
- /*
- * If the packet is a TCP/IP packet, see if we can compress it.
- */
- if ((sc->sc_flags & SC_COMP_TCP) && sc->sc_comp != NULL) {
- struct ip *ip;
- int type;
-
- mp = m;
- ip = (struct ip *) (cp + PPP_HDRLEN);
- if (mp->m_len <= PPP_HDRLEN) {
- mp = mp->m_next;
- if (mp == NULL)
- break;
- ip = mtod(mp, struct ip *);
- }
- /* this code assumes the IP/TCP header is in one non-shared mbuf */
- if (ip->ip_p == IPPROTO_TCP) {
- type = sl_compress_tcp(mp, ip, sc->sc_comp,
- !(sc->sc_flags & SC_NO_TCP_CCID));
- switch (type) {
- case TYPE_UNCOMPRESSED_TCP:
- protocol = PPP_VJC_UNCOMP;
- break;
- case TYPE_COMPRESSED_TCP:
- protocol = PPP_VJC_COMP;
- cp = mtod(m, u_char *);
- cp[0] = address; /* header has moved */
- cp[1] = control;
- cp[2] = 0;
- break;
- }
- cp[3] = protocol; /* update protocol in PPP header */
- }
- }
-#endif /* VJC */
- break;
-
-#ifdef PPP_COMPRESS
- case PPP_CCP:
- ppp_ccp(sc, m, 0);
- break;
-#endif /* PPP_COMPRESS */
- }
-
-#ifdef PPP_COMPRESS
- if (protocol != PPP_LCP && protocol != PPP_CCP
- && sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN)) {
- struct mbuf *mcomp = NULL;
- int slen, clen;
-
- slen = m_length(m, NULL);
- clen = (*sc->sc_xcomp->compress)
- (sc->sc_xc_state, &mcomp, m, slen, PPP2IFP(sc)->if_mtu + PPP_HDRLEN);
- if (mcomp != NULL) {
- if (sc->sc_flags & SC_CCP_UP) {
- /* Send the compressed packet instead of the original. */
- m_freem(m);
- m = mcomp;
- cp = mtod(m, u_char *);
- protocol = cp[3];
- } else {
- /* Can't transmit compressed packets until CCP is up. */
- m_freem(mcomp);
- }
- }
- }
-#endif /* PPP_COMPRESS */
-
- /*
- * Compress the address/control and protocol, if possible.
- */
- if (sc->sc_flags & SC_COMP_AC && address == PPP_ALLSTATIONS &&
- control == PPP_UI && protocol != PPP_ALLSTATIONS &&
- protocol != PPP_LCP) {
- /* can compress address/control */
- m->m_data += 2;
- m->m_len -= 2;
- }
- if (sc->sc_flags & SC_COMP_PROT && protocol < 0xFF) {
- /* can compress protocol */
- if (mtod(m, u_char *) == cp) {
- cp[2] = cp[1]; /* move address/control up */
- cp[1] = cp[0];
- }
- ++m->m_data;
- --m->m_len;
- }
-
- return m;
-}
-
-/*
- * Software interrupt routine, called at spl[soft]net.
- */
-static void
-pppintr()
-{
- struct ppp_softc *sc;
- int s;
- struct mbuf *m;
-
- mtx_lock(&Giant);
- PPP_LIST_LOCK();
- LIST_FOREACH(sc, &ppp_softc_list, sc_list) {
- s = splimp();
- if (!(sc->sc_flags & SC_TBUSY)
- && (PPP2IFP(sc)->if_snd.ifq_head || sc->sc_fastq.ifq_head)) {
- sc->sc_flags |= SC_TBUSY;
- splx(s);
- (*sc->sc_start)(sc);
- } else
- splx(s);
- for (;;) {
- s = splimp();
- IF_DEQUEUE(&sc->sc_rawq, m);
- splx(s);
- if (m == NULL)
- break;
-#ifdef MAC
- mac_ifnet_create_mbuf(PPP2IFP(sc), m);
-#endif
- ppp_inproc(sc, m);
- }
- }
- PPP_LIST_UNLOCK();
- mtx_unlock(&Giant);
-}
-
-#ifdef PPP_COMPRESS
-/*
- * Handle a CCP packet. `rcvd' is 1 if the packet was received,
- * 0 if it is about to be transmitted.
- */
-static void
-ppp_ccp(sc, m, rcvd)
- struct ppp_softc *sc;
- struct mbuf *m;
- int rcvd;
-{
- u_char *dp, *ep;
- struct mbuf *mp;
- int slen, s;
-
- /*
- * Get a pointer to the data after the PPP header.
- */
- if (m->m_len <= PPP_HDRLEN) {
- mp = m->m_next;
- if (mp == NULL)
- return;
- dp = (mp != NULL)? mtod(mp, u_char *): NULL;
- } else {
- mp = m;
- dp = mtod(mp, u_char *) + PPP_HDRLEN;
- }
-
- ep = mtod(mp, u_char *) + mp->m_len;
- if (dp + CCP_HDRLEN > ep)
- return;
- slen = CCP_LENGTH(dp);
- if (dp + slen > ep) {
- if (sc->sc_flags & SC_DEBUG)
- printf("if_ppp/ccp: not enough data in mbuf (%p+%x > %p+%x)\n",
- dp, slen, mtod(mp, u_char *), mp->m_len);
- return;
- }
-
- switch (CCP_CODE(dp)) {
- case CCP_CONFREQ:
- case CCP_TERMREQ:
- case CCP_TERMACK:
- /* CCP must be going down - disable compression */
- if (sc->sc_flags & SC_CCP_UP) {
- s = splimp();
- sc->sc_flags &= ~(SC_CCP_UP | SC_COMP_RUN | SC_DECOMP_RUN);
- splx(s);
- }
- break;
-
- case CCP_CONFACK:
- if (sc->sc_flags & SC_CCP_OPEN && !(sc->sc_flags & SC_CCP_UP)
- && slen >= CCP_HDRLEN + CCP_OPT_MINLEN
- && slen >= CCP_OPT_LENGTH(dp + CCP_HDRLEN) + CCP_HDRLEN) {
- if (!rcvd) {
- /* we're agreeing to send compressed packets. */
- if (sc->sc_xc_state != NULL
- && (*sc->sc_xcomp->comp_init)
- (sc->sc_xc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
- PPP2IFP(sc)->if_dunit, 0, sc->sc_flags & SC_DEBUG)) {
- s = splimp();
- sc->sc_flags |= SC_COMP_RUN;
- splx(s);
- }
- } else {
- /* peer is agreeing to send compressed packets. */
- if (sc->sc_rc_state != NULL
- && (*sc->sc_rcomp->decomp_init)
- (sc->sc_rc_state, dp + CCP_HDRLEN, slen - CCP_HDRLEN,
- PPP2IFP(sc)->if_dunit, 0, sc->sc_mru,
- sc->sc_flags & SC_DEBUG)) {
- s = splimp();
- sc->sc_flags |= SC_DECOMP_RUN;
- sc->sc_flags &= ~(SC_DC_ERROR | SC_DC_FERROR);
- splx(s);
- }
- }
- }
- break;
-
- case CCP_RESETACK:
- if (sc->sc_flags & SC_CCP_UP) {
- if (!rcvd) {
- if (sc->sc_xc_state && (sc->sc_flags & SC_COMP_RUN))
- (*sc->sc_xcomp->comp_reset)(sc->sc_xc_state);
- } else {
- if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
- (*sc->sc_rcomp->decomp_reset)(sc->sc_rc_state);
- s = splimp();
- sc->sc_flags &= ~SC_DC_ERROR;
- splx(s);
- }
- }
- }
- break;
- }
-}
-
-/*
- * CCP is down; free (de)compressor state if necessary.
- */
-static void
-ppp_ccp_closed(sc)
- struct ppp_softc *sc;
-{
- if (sc->sc_xc_state) {
- (*sc->sc_xcomp->comp_free)(sc->sc_xc_state);
- sc->sc_xc_state = NULL;
- }
- if (sc->sc_rc_state) {
- (*sc->sc_rcomp->decomp_free)(sc->sc_rc_state);
- sc->sc_rc_state = NULL;
- }
-}
-#endif /* PPP_COMPRESS */
-
-/*
- * PPP packet input routine.
- * The caller has checked and removed the FCS and has inserted
- * the address/control bytes and the protocol high byte if they
- * were omitted.
- */
-void
-ppppktin(sc, m, lost)
- struct ppp_softc *sc;
- struct mbuf *m;
- int lost;
-{
- int s = splimp();
-
- if (lost)
- m->m_flags |= M_ERRMARK;
- IF_ENQUEUE(&sc->sc_rawq, m);
- schednetisr(NETISR_PPP);
- splx(s);
-}
-
-/*
- * Process a received PPP packet, doing decompression as necessary.
- * Should be called at splsoftnet.
- */
-#define COMPTYPE(proto) ((proto) == PPP_VJC_COMP? TYPE_COMPRESSED_TCP: \
- TYPE_UNCOMPRESSED_TCP)
-
-static void
-ppp_inproc(sc, m)
- struct ppp_softc *sc;
- struct mbuf *m;
-{
- struct ifnet *ifp = PPP2IFP(sc);
- int isr;
- int s, ilen = 0, xlen, proto, rv;
- u_char *cp, adrs, ctrl;
- struct mbuf *mp, *dmp = NULL;
- u_char *iphdr;
- u_int hlen;
-
- sc->sc_stats.ppp_ipackets++;
-
- if (sc->sc_flags & SC_LOG_INPKT) {
- ilen = m_length(m, NULL);
- if_printf(ifp, "got %d bytes\n", ilen);
- pppdumpm(m);
- }
-
- cp = mtod(m, u_char *);
- adrs = PPP_ADDRESS(cp);
- ctrl = PPP_CONTROL(cp);
- proto = PPP_PROTOCOL(cp);
-
- if (m->m_flags & M_ERRMARK) {
- m->m_flags &= ~M_ERRMARK;
- s = splimp();
- sc->sc_flags |= SC_VJ_RESET;
- splx(s);
- }
-
-#ifdef PPP_COMPRESS
- /*
- * Decompress this packet if necessary, update the receiver's
- * dictionary, or take appropriate action on a CCP packet.
- */
- if (proto == PPP_COMP && sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)
- && !(sc->sc_flags & SC_DC_ERROR) && !(sc->sc_flags & SC_DC_FERROR)) {
- /* decompress this packet */
- rv = (*sc->sc_rcomp->decompress)(sc->sc_rc_state, m, &dmp);
- if (rv == DECOMP_OK) {
- m_freem(m);
- if (dmp == NULL) {
- /* no error, but no decompressed packet produced */
- return;
- }
- m = dmp;
- cp = mtod(m, u_char *);
- proto = PPP_PROTOCOL(cp);
-
- } else {
- /*
- * An error has occurred in decompression.
- * Pass the compressed packet up to pppd, which may take
- * CCP down or issue a Reset-Req.
- */
- if (sc->sc_flags & SC_DEBUG)
- if_printf(ifp, "decompress failed %d\n", rv);
- s = splimp();
- sc->sc_flags |= SC_VJ_RESET;
- if (rv == DECOMP_ERROR)
- sc->sc_flags |= SC_DC_ERROR;
- else
- sc->sc_flags |= SC_DC_FERROR;
- splx(s);
- }
-
- } else {
- if (sc->sc_rc_state && (sc->sc_flags & SC_DECOMP_RUN)) {
- (*sc->sc_rcomp->incomp)(sc->sc_rc_state, m);
- }
- if (proto == PPP_CCP) {
- ppp_ccp(sc, m, 1);
- }
- }
-#endif
-
- ilen = m_length(m, NULL);
-
-#ifdef VJC
- if (sc->sc_flags & SC_VJ_RESET) {
- /*
- * If we've missed a packet, we must toss subsequent compressed
- * packets which don't have an explicit connection ID.
- */
- if (sc->sc_comp)
- sl_uncompress_tcp(NULL, 0, TYPE_ERROR, sc->sc_comp);
- s = splimp();
- sc->sc_flags &= ~SC_VJ_RESET;
- splx(s);
- }
-
- /*
- * See if we have a VJ-compressed packet to uncompress.
- */
- if (proto == PPP_VJC_COMP) {
- if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
- goto bad;
-
- xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
- ilen - PPP_HDRLEN, TYPE_COMPRESSED_TCP,
- sc->sc_comp, &iphdr, &hlen);
-
- if (xlen <= 0) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(ifp, "VJ uncompress failed on type comp\n");
- goto bad;
- }
-
- /* Copy the PPP and IP headers into a new mbuf. */
- MGETHDR(mp, M_DONTWAIT, MT_DATA);
- if (mp == NULL)
- goto bad;
- mp->m_len = 0;
- mp->m_next = NULL;
- if (hlen + PPP_HDRLEN > MHLEN) {
- MCLGET(mp, M_DONTWAIT);
- if (M_TRAILINGSPACE(mp) < hlen + PPP_HDRLEN) {
- m_freem(mp);
- goto bad; /* lose if big headers and no clusters */
- }
- }
-#ifdef MAC
- mac_mbuf_copy(m, mp);
-#endif
- cp = mtod(mp, u_char *);
- cp[0] = adrs;
- cp[1] = ctrl;
- cp[2] = 0;
- cp[3] = PPP_IP;
- proto = PPP_IP;
- bcopy(iphdr, cp + PPP_HDRLEN, hlen);
- mp->m_len = hlen + PPP_HDRLEN;
-
- /*
- * Trim the PPP and VJ headers off the old mbuf
- * and stick the new and old mbufs together.
- */
- m->m_data += PPP_HDRLEN + xlen;
- m->m_len -= PPP_HDRLEN + xlen;
- if (m->m_len <= M_TRAILINGSPACE(mp)) {
- bcopy(mtod(m, u_char *), mtod(mp, u_char *) + mp->m_len, m->m_len);
- mp->m_len += m->m_len;
- mp->m_next = m_free(m);
- } else {
- mp->m_next = m;
- }
- m = mp;
- ilen += hlen - xlen;
-
- } else if (proto == PPP_VJC_UNCOMP) {
- if ((sc->sc_flags & SC_REJ_COMP_TCP) || sc->sc_comp == 0)
- goto bad;
-
- xlen = sl_uncompress_tcp_core(cp + PPP_HDRLEN, m->m_len - PPP_HDRLEN,
- ilen - PPP_HDRLEN, TYPE_UNCOMPRESSED_TCP,
- sc->sc_comp, &iphdr, &hlen);
-
- if (xlen < 0) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(ifp, "VJ uncompress failed on type uncomp\n");
- goto bad;
- }
-
- proto = PPP_IP;
- cp[3] = PPP_IP;
- }
-#endif /* VJC */
-
- /*
- * If the packet will fit in a header mbuf, don't waste a
- * whole cluster on it.
- */
- if (ilen <= MHLEN && M_IS_CLUSTER(m)) {
- MGETHDR(mp, M_DONTWAIT, MT_DATA);
- if (mp != NULL) {
-#ifdef MAC
- mac_mbuf_copy(m, mp);
-#endif
- m_copydata(m, 0, ilen, mtod(mp, caddr_t));
- m_freem(m);
- m = mp;
- m->m_len = ilen;
- }
- }
- m->m_pkthdr.len = ilen;
- m->m_pkthdr.rcvif = ifp;
-
- if ((proto & 0x8000) == 0) {
-#ifdef PPP_FILTER
- /*
- * See whether we want to pass this packet, and
- * if it counts as link activity.
- */
- adrs = *mtod(m, u_char *); /* save address field */
- *mtod(m, u_char *) = 0; /* indicate inbound */
- if (sc->sc_pass_filt.bf_insns != 0
- && bpf_filter(sc->sc_pass_filt.bf_insns, (u_char *) m,
- ilen, 0) == 0) {
- /* drop this packet */
- m_freem(m);
- return;
- }
- if (sc->sc_active_filt.bf_insns == 0
- || bpf_filter(sc->sc_active_filt.bf_insns, (u_char *) m, ilen, 0))
- sc->sc_last_recv = time_uptime;
-
- *mtod(m, u_char *) = adrs;
-#else
- /*
- * Record the time that we received this packet.
- */
- sc->sc_last_recv = time_uptime;
-#endif /* PPP_FILTER */
- }
-
- /* See if bpf wants to look at the packet. */
- BPF_MTAP(PPP2IFP(sc), m);
-
- isr = -1;
- switch (proto) {
-#ifdef INET
- case PPP_IP:
- /*
- * IP packet - take off the ppp header and pass it up to IP.
- */
- if ((ifp->if_flags & IFF_UP) == 0
- || sc->sc_npmode[NP_IP] != NPMODE_PASS) {
- /* interface is down - drop the packet. */
- m_freem(m);
- return;
- }
- m->m_pkthdr.len -= PPP_HDRLEN;
- m->m_data += PPP_HDRLEN;
- m->m_len -= PPP_HDRLEN;
- if ((m = ip_fastforward(m)) == NULL)
- return;
- isr = NETISR_IP;
- break;
-#endif
-#ifdef INET6
- case PPP_IPV6:
- /*
- * IPv6 packet - take off the ppp header and pass it up to IPv6.
- */
- if ((ifp->if_flags & IFF_UP) == 0
- || sc->sc_npmode[NP_IPV6] != NPMODE_PASS) {
- /* interface is down - drop the packet. */
- m_freem(m);
- return;
- }
- m->m_pkthdr.len -= PPP_HDRLEN;
- m->m_data += PPP_HDRLEN;
- m->m_len -= PPP_HDRLEN;
- isr = NETISR_IPV6;
- break;
-#endif
-#ifdef IPX
- case PPP_IPX:
- /*
- * IPX packet - take off the ppp header and pass it up to IPX.
- */
- if ((PPP2IFP(sc)->if_flags & IFF_UP) == 0
- /* XXX: || sc->sc_npmode[NP_IPX] != NPMODE_PASS*/) {
- /* interface is down - drop the packet. */
- m_freem(m);
- return;
- }
- m->m_pkthdr.len -= PPP_HDRLEN;
- m->m_data += PPP_HDRLEN;
- m->m_len -= PPP_HDRLEN;
- isr = NETISR_IPX;
- sc->sc_last_recv = time_uptime; /* update time of last pkt rcvd */
- break;
-#endif
-
- default:
- /*
- * Some other protocol - place on input queue for read().
- */
- break;
- }
-
- if (isr == -1)
- rv = IF_HANDOFF(&sc->sc_inq, m, NULL);
- else
- rv = netisr_queue(isr, m); /* (0) on success. */
- if ((isr == -1 && !rv) || (isr != -1 && rv)) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(ifp, "input queue full\n");
- ifp->if_iqdrops++;
- m = NULL;
- goto bad;
- }
- ifp->if_ipackets++;
- ifp->if_ibytes += ilen;
- getmicrotime(&ifp->if_lastchange);
-
- if (isr == -1)
- (*sc->sc_ctlp)(sc);
-
- return;
-
- bad:
- if (m)
- m_freem(m);
- PPP2IFP(sc)->if_ierrors++;
- sc->sc_stats.ppp_ierrors++;
-}
-
-#define MAX_DUMP_BYTES 128
-
-static void
-pppdumpm(m0)
- struct mbuf *m0;
-{
- char buf[3*MAX_DUMP_BYTES+4];
- char *bp = buf;
- struct mbuf *m;
-
- for (m = m0; m; m = m->m_next) {
- int l = m->m_len;
- u_char *rptr = (u_char *)m->m_data;
-
- while (l--) {
- if (bp > buf + (sizeof(buf) - 4))
- goto done;
- *bp++ = hex2ascii(*rptr >> 4);
- *bp++ = hex2ascii(*rptr++ & 0xf);
- }
-
- if (m->m_next) {
- if (bp > buf + (sizeof(buf) - 3))
- goto done;
- *bp++ = '|';
- } else
- *bp++ = ' ';
- }
-done:
- if (m)
- *bp++ = '>';
- *bp = 0;
- printf("%s\n", buf);
-}
diff --git a/sys/net/if_ppp.h b/sys/net/if_ppp.h
deleted file mode 100644
index d23255b..0000000
--- a/sys/net/if_ppp.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * if_ppp.h - Point-to-Point Protocol definitions.
- */
-
-/*-
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
- */
-
-#ifndef _IF_PPP_H_
-#define _IF_PPP_H_
-
-/* XXX this used to be self-contained. */
-#include <net/ppp_defs.h>
-#include <net/if.h>
-
-/*
- * Packet sizes
- */
-#define PPP_MTU 1500 /* Default MTU (size of Info field) */
-#define PPP_MAXMRU 65000 /* Largest MRU we allow */
-#define PPP_MAXMTU 16384 /* Largest MTU we allow */
-
-/*
- * Bit definitions for flags.
- */
-#define SC_COMP_PROT 0x00000001 /* protocol compression (output) */
-#define SC_COMP_AC 0x00000002 /* header compression (output) */
-#define SC_COMP_TCP 0x00000004 /* TCP (VJ) compression (output) */
-#define SC_NO_TCP_CCID 0x00000008 /* disable VJ connection-id comp. */
-#define SC_REJ_COMP_AC 0x00000010 /* reject adrs/ctrl comp. on input */
-#define SC_REJ_COMP_TCP 0x00000020 /* reject TCP (VJ) comp. on input */
-#define SC_CCP_OPEN 0x00000040 /* Look at CCP packets */
-#define SC_CCP_UP 0x00000080 /* May send/recv compressed packets */
-#define SC_DEBUG 0x00010000 /* enable debug messages */
-#define SC_LOG_INPKT 0x00020000 /* log contents of good pkts recvd */
-#define SC_LOG_OUTPKT 0x00040000 /* log contents of pkts sent */
-#define SC_LOG_RAWIN 0x00080000 /* log all chars received */
-#define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */
-#define SC_RCV_B7_0 0x01000000 /* have rcvd char with bit 7 = 0 */
-#define SC_RCV_B7_1 0x02000000 /* have rcvd char with bit 7 = 1 */
-#define SC_RCV_EVNP 0x04000000 /* have rcvd char with even parity */
-#define SC_RCV_ODDP 0x08000000 /* have rcvd char with odd parity */
-#define SC_MASK 0x0fff00ff /* bits that user can change */
-
-/*
- * State bits in sc_flags, not changeable by user.
- */
-#define SC_TIMEOUT 0x00000400 /* timeout is currently pending */
-#define SC_VJ_RESET 0x00000800 /* need to reset VJ decomp */
-#define SC_COMP_RUN 0x00001000 /* compressor has been initiated */
-#define SC_DECOMP_RUN 0x00002000 /* decompressor has been initiated */
-#define SC_DC_ERROR 0x00004000 /* non-fatal decomp error detected */
-#define SC_DC_FERROR 0x00008000 /* fatal decomp error detected */
-#define SC_TBUSY 0x10000000 /* xmitter doesn't need a packet yet */
-#define SC_PKTLOST 0x20000000 /* have lost or dropped a packet */
-#define SC_FLUSH 0x40000000 /* flush input until next PPP_FLAG */
-#define SC_ESCAPED 0x80000000 /* saw a PPP_ESCAPE */
-
-/*
- * Ioctl definitions.
- */
-
-struct npioctl {
- int protocol; /* PPP procotol, e.g. PPP_IP */
- enum NPmode mode;
-};
-
-/* Structure describing a CCP configuration option, for PPPIOCSCOMPRESS */
-struct ppp_option_data {
- u_char *ptr;
- u_int length;
- int transmit;
-};
-
-struct ifpppstatsreq {
- char ifr_name[IFNAMSIZ];
- struct ppp_stats stats;
-};
-
-struct ifpppcstatsreq {
- char ifr_name[IFNAMSIZ];
- struct ppp_comp_stats stats;
-};
-
-/*
- * Ioctl definitions.
- */
-
-#define PPPIOCGFLAGS _IOR('t', 90, int) /* get configuration flags */
-#define PPPIOCSFLAGS _IOW('t', 89, int) /* set configuration flags */
-#define PPPIOCGASYNCMAP _IOR('t', 88, int) /* get async map */
-#define PPPIOCSASYNCMAP _IOW('t', 87, int) /* set async map */
-#define PPPIOCGUNIT _IOR('t', 86, int) /* get ppp unit number */
-#define PPPIOCGRASYNCMAP _IOR('t', 85, int) /* get receive async map */
-#define PPPIOCSRASYNCMAP _IOW('t', 84, int) /* set receive async map */
-#define PPPIOCGMRU _IOR('t', 83, int) /* get max receive unit */
-#define PPPIOCSMRU _IOW('t', 82, int) /* set max receive unit */
-#define PPPIOCSMAXCID _IOW('t', 81, int) /* set VJ max slot ID */
-#define PPPIOCGXASYNCMAP _IOR('t', 80, ext_accm) /* get extended ACCM */
-#define PPPIOCSXASYNCMAP _IOW('t', 79, ext_accm) /* set extended ACCM */
-#define PPPIOCXFERUNIT _IO('t', 78) /* transfer PPP unit */
-#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data)
-#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */
-#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */
-#define PPPIOCGIDLE _IOR('t', 74, struct ppp_idle) /* get idle time */
-#define PPPIOCSPASS _IOW('t', 71, struct bpf_program) /* set pass filter */
-#define PPPIOCSACTIVE _IOW('t', 70, struct bpf_program) /* set active filt */
-
-/* PPPIOC[GS]MTU are alternatives to SIOC[GS]IFMTU, used under Ultrix */
-#define PPPIOCGMTU _IOR('t', 73, int) /* get interface MTU */
-#define PPPIOCSMTU _IOW('t', 72, int) /* set interface MTU */
-
-/*
- * These two are interface ioctls so that pppstats can do them on
- * a socket without having to open the serial device.
- */
-#define SIOCGPPPSTATS _IOWR('i', 123, struct ifpppstatsreq)
-#define SIOCGPPPCSTATS _IOWR('i', 122, struct ifpppcstatsreq)
-
-#if !defined(ifr_mtu)
-#define ifr_mtu ifr_ifru.ifru_metric
-#endif
-
-#endif /* _IF_PPP_H_ */
diff --git a/sys/net/if_pppvar.h b/sys/net/if_pppvar.h
deleted file mode 100644
index 77e1ade..0000000
--- a/sys/net/if_pppvar.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * if_pppvar.h - private structures and declarations for PPP.
- */
-/*-
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies. This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
- *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
- */
-
-/*
- * Supported network protocols. These values are used for
- * indexing sc_npmode.
- */
-#define NP_IP 0 /* Internet Protocol */
-#define NP_IPV6 1 /* Internet Protocol version 6 */
-#define NUM_NP 2 /* Number of NPs. */
-
-/*
- * Structure describing each ppp unit.
- */
-struct ppp_softc {
- struct ifnet *sc_ifp; /* network-visible interface */
-/*hi*/ u_int sc_flags; /* control/status bits; see if_ppp.h */
- struct callout sc_timo_ch; /* Used for scheduling timeouts */
- void *sc_devp; /* pointer to device-dep structure */
- void (*sc_start)(struct ppp_softc *); /* start output proc */
- void (*sc_ctlp)(struct ppp_softc *); /* rcvd control pkt */
- void (*sc_relinq)(struct ppp_softc *); /* relinquish ifunit */
- void (*sc_setmtu)(struct ppp_softc *); /* set mtu */
- short sc_mru; /* max receive unit */
- pid_t sc_xfer; /* used in transferring unit */
-/*hi*/ struct ifqueue sc_rawq; /* received packets */
-/*net*/ struct ifqueue sc_inq; /* queue of input packets for daemon */
-/*net*/ struct ifqueue sc_fastq; /* interactive output packet q */
- struct mbuf *sc_npqueue; /* output packets not to be sent yet */
- struct mbuf **sc_npqtail; /* ptr to last next ptr in npqueue */
- struct pppstat sc_stats; /* count of bytes/pkts sent/rcvd */
- enum NPmode sc_npmode[NUM_NP]; /* what to do with each NP */
- struct compressor *sc_xcomp; /* transmit compressor */
- void *sc_xc_state; /* transmit compressor state */
- struct compressor *sc_rcomp; /* receive decompressor */
- void *sc_rc_state; /* receive decompressor state */
- time_t sc_last_sent; /* time (secs) last NP pkt sent */
- time_t sc_last_recv; /* time (secs) last NP pkt rcvd */
-#ifdef PPP_FILTER
- struct bpf_program sc_pass_filt; /* filter for packets to pass */
- struct bpf_program sc_active_filt; /* filter for "non-idle" packets */
-#endif /* PPP_FILTER */
-#ifdef VJC
- struct slcompress *sc_comp; /* vjc control buffer */
-#endif
-
- /* Device-dependent part for async lines. */
- ext_accm sc_asyncmap; /* async control character map */
- u_long sc_rasyncmap; /* receive async control char map */
- struct mbuf *sc_outm; /* mbuf chain currently being output */
- struct mbuf *sc_m; /* pointer to input mbuf chain */
- struct mbuf *sc_mc; /* pointer to current input mbuf */
- char *sc_mp; /* ptr to next char in input mbuf */
- short sc_ilen; /* length of input packet so far */
- u_short sc_fcs; /* FCS so far (input) */
- u_short sc_outfcs; /* FCS so far for output packet */
- u_char sc_rawin[16]; /* chars as received */
- int sc_rawin_count; /* # in sc_rawin */
- LIST_ENTRY(ppp_softc) sc_list;
-};
-#define PPP2IFP(sc) ((sc)->sc_ifp)
-
-struct ppp_softc *pppalloc(pid_t pid);
-void pppdealloc(struct ppp_softc *sc);
-int pppioctl(struct ppp_softc *sc, u_long cmd, caddr_t data, int flag,
- struct thread *td);
-int pppoutput(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
- struct rtentry *rtp);
-void ppp_restart(struct ppp_softc *sc);
-void ppppktin(struct ppp_softc *sc, struct mbuf *m, int lost);
-struct mbuf *ppp_dequeue(struct ppp_softc *sc);
diff --git a/sys/net/if_sl.c b/sys/net/if_sl.c
deleted file mode 100644
index 10853e9..0000000
--- a/sys/net/if_sl.c
+++ /dev/null
@@ -1,1110 +0,0 @@
-/*-
- * Copyright (c) 1987, 1989, 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)if_sl.c 8.6 (Berkeley) 2/1/94
- * $FreeBSD$
- */
-
-/*
- * Serial Line interface
- *
- * Rick Adams
- * Center for Seismic Studies
- * 1300 N 17th Street, Suite 1450
- * Arlington, Virginia 22209
- * (703)276-7900
- * rick@seismo.ARPA
- * seismo!rick
- *
- * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
- * N.B.: this belongs in netinet, not net, the way it stands now.
- * Should have a link-layer type designation, but wouldn't be
- * backwards-compatible.
- *
- * Converted to 4.3BSD Beta by Chris Torek.
- * Other changes made at Berkeley, based in part on code by Kirk Smith.
- * W. Jolitz added slip abort.
- *
- * Hacked almost beyond recognition by Van Jacobson (van@helios.ee.lbl.gov).
- * Added priority queuing for "interactive" traffic; hooks for TCP
- * header compression; ICMP filtering (at 2400 baud, some cretin
- * pinging you can use up all your bandwidth). Made low clist behavior
- * more robust and slightly less likely to hang serial line.
- * Sped up a bunch of things.
- *
- * Note that splimp() is used throughout to block both (tty) input
- * interrupts and network activity; thus, splimp must be >= spltty.
- */
-
-#include "opt_inet.h"
-#include "opt_slip.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/priv.h>
-#include <sys/proc.h>
-#include <sys/socket.h>
-#include <sys/sockio.h>
-#include <sys/fcntl.h>
-#include <sys/signalvar.h>
-#include <sys/tty.h>
-#include <sys/clist.h>
-#include <sys/kernel.h>
-#include <sys/conf.h>
-#include <sys/module.h>
-#include <sys/proc.h>
-
-#include <net/if.h>
-#include <net/if_types.h>
-#include <net/netisr.h>
-
-#if INET
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#else
-#error "Huh? Slip without inet?"
-#endif
-
-#include <net/slcompress.h>
-#include <net/if_slvar.h>
-#include <net/slip.h>
-
-#include <net/bpf.h>
-
-static MALLOC_DEFINE(M_SL, "sl", "SLIP Interface");
-
-/*
- * SLRMAX is a hard limit on input packet size. To simplify the code
- * and improve performance, we require that packets fit in an mbuf
- * cluster, and if we get a compressed packet, there's enough extra
- * room to expand the header into a max length tcp/ip header (128
- * bytes). So, SLRMAX can be at most
- * MCLBYTES - 128
- *
- * SLMTU is the default transmit MTU. The transmit MTU should be kept
- * small enough so that interactive use doesn't suffer, but large
- * enough to provide good performance. 552 is a good choice for SLMTU
- * because it is high enough to not fragment TCP packets being routed
- * through this host. Packet fragmentation is bad with SLIP because
- * fragment headers aren't compressed. The previous assumptions about
- * the best MTU value don't really hold when using modern modems with
- * BTLZ data compression because the modem buffers play a much larger
- * role in interactive performance than the MTU. The MTU can be changed
- * at any time to suit the specific environment with ifconfig(8), and
- * its maximum value is defined as SLTMAX. SLTMAX must not be so large
- * that it would overflow the stack if BPF is configured (XXX; if_ppp.c
- * handles this better).
- *
- * SLIP_HIWAT is the amount of data that will be queued 'downstream'
- * of us (i.e., in clists waiting to be picked up by the tty output
- * interrupt). If we queue a lot of data downstream, it's immune to
- * our t.o.s. queuing.
- * E.g., if SLIP_HIWAT is 1024, the interactive traffic in mixed
- * telnet/ftp will see a 1 sec wait, independent of the mtu (the
- * wait is dependent on the ftp window size but that's typically
- * 1k - 4k). So, we want SLIP_HIWAT just big enough to amortize
- * the cost (in idle time on the wire) of the tty driver running
- * off the end of its clists & having to call back slstart for a
- * new packet. For a tty interface with any buffering at all, this
- * cost will be zero. Even with a totally brain dead interface (like
- * the one on a typical workstation), the cost will be <= 1 character
- * time. So, setting SLIP_HIWAT to ~100 guarantees that we'll lose
- * at most 1% while maintaining good interactive response.
- */
-#define BUFOFFSET (128+sizeof(struct ifnet **)+SLIP_HDRLEN)
-#define SLRMAX (MCLBYTES - BUFOFFSET)
-#define SLBUFSIZE (SLRMAX + BUFOFFSET)
-#ifndef SLMTU
-#define SLMTU 552 /* default MTU */
-#endif
-#define SLTMAX 1500 /* maximum MTU */
-#define SLIP_HIWAT roundup(50,CBSIZE)
-#define CLISTRESERVE 1024 /* Can't let clists get too low */
-
-/*
- * SLIP ABORT ESCAPE MECHANISM:
- * (inspired by HAYES modem escape arrangement)
- * 1sec escape 1sec escape 1sec escape { 1sec escape 1sec escape }
- * within window time signals a "soft" exit from slip mode by remote end
- * if the IFF_DEBUG flag is on.
- */
-#define ABT_ESC '\033' /* can't be t_intr - distant host must know it*/
-#define ABT_IDLE 1 /* in seconds - idle before an escape */
-#define ABT_COUNT 3 /* count of escapes for abort */
-#define ABT_WINDOW (ABT_COUNT*2+2) /* in seconds - time to count */
-
-static LIST_HEAD(sl_list, sl_softc) sl_list;
-
-#define FRAME_END 0xc0 /* Frame End */
-#define FRAME_ESCAPE 0xdb /* Frame Esc */
-#define TRANS_FRAME_END 0xdc /* transposed frame end */
-#define TRANS_FRAME_ESCAPE 0xdd /* transposed frame esc */
-
-static int slisstatic(int);
-static void slmarkstatic(int);
-static struct sl_softc *slcreate(void);
-static void sldestroy(struct sl_softc *sc);
-static struct mbuf *sl_btom(struct sl_softc *, int);
-static timeout_t sl_keepalive;
-static timeout_t sl_outfill;
-static l_close_t slclose;
-static l_rint_t slinput;
-static l_ioctl_t sltioctl;
-static l_start_t sltstart;
-static int slioctl(struct ifnet *, u_long, caddr_t);
-static int slopen(struct cdev *, struct tty *);
-static int sloutput(struct ifnet *,
- struct mbuf *, struct sockaddr *, struct rtentry *);
-static void slstart(struct ifnet *);
-
-static struct linesw slipdisc = {
- .l_open = slopen,
- .l_close = slclose,
- .l_read = l_noread,
- .l_write = l_nowrite,
- .l_ioctl = sltioctl,
- .l_rint = slinput,
- .l_start = sltstart,
- .l_modem = ttymodem
-};
-
-/*
- * Called from boot code to establish sl interfaces.
- */
-static int
-sl_modevent(module_t mod, int type, void *data)
-{
- switch (type) {
- case MOD_LOAD:
- ldisc_register(SLIPDISC, &slipdisc);
- LIST_INIT(&sl_list);
- break;
- case MOD_UNLOAD:
- ldisc_deregister(SLIPDISC);
- printf("if_sl module unload - not possible for this module type\n");
- return EINVAL;
- default:
- return EOPNOTSUPP;
- }
- return 0;
-}
-
-static moduledata_t sl_mod = {
- "if_sl",
- sl_modevent,
- 0
-};
-
-DECLARE_MODULE(if_sl, sl_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
-
-static int *st_unit_list;
-static size_t st_unit_max = 0;
-
-static int
-slisunitfree(int unit)
-{
- struct sl_softc *sc;
-
- LIST_FOREACH(sc, &sl_list, sl_next) {
- if (SL2IFP(sc)->if_dunit == unit)
- return (0);
- }
- return (1);
-}
-
-static struct sl_softc *
-sl_for_tty(struct tty *tp)
-{
- struct sl_softc *nc;
-
- LIST_FOREACH(nc, &sl_list, sl_next) {
- if (nc->sc_ttyp == tp)
- return (nc);
- }
- return (NULL);
-}
-static int
-slisstatic(int unit)
-{
- size_t i;
-
- for (i = 0; i < st_unit_max; i++)
- if (st_unit_list[i] == unit)
- return 1;
- return 0;
-}
-
-static void
-slmarkstatic(int unit)
-{
- int *t;
-
- if (slisstatic(unit))
- return;
-
- t = malloc(sizeof(int) * (st_unit_max+1), M_SL, M_NOWAIT);
- if (t == NULL)
- return;
-
- if (st_unit_list) {
- bcopy(st_unit_list, t, sizeof(int) * st_unit_max);
- free(st_unit_list, M_SL);
- }
- st_unit_list = t;
- st_unit_list[st_unit_max] = unit;
- st_unit_max++;
-}
-
-static struct sl_softc *
-slcreate(void)
-{
- struct sl_softc *sc;
- int unit;
- struct mbuf *m;
-
- sc = malloc(sizeof(*sc), M_SL, M_WAITOK | M_ZERO);
- sc->sc_ifp = if_alloc(IFT_SLIP);
- if (sc->sc_ifp == NULL) {
- free(sc, M_SL);
- return (NULL);
- }
-
- m = m_gethdr(M_WAIT, MT_DATA);
- MCLGET(m, M_WAIT);
-
- sc->sc_ep = mtod(m, u_char *) + SLBUFSIZE;
- sc->sc_mbuf = m;
- sc->sc_buf = sc->sc_ep - SLRMAX;
- sc->sc_mp = sc->sc_buf;
- sl_compress_init(&sc->sc_comp, -1);
-
- SL2IFP(sc)->if_softc = sc;
- SL2IFP(sc)->if_mtu = SLMTU;
- SL2IFP(sc)->if_flags =
-#ifdef SLIP_IFF_OPTS
- SLIP_IFF_OPTS;
-#else
- IFF_POINTOPOINT | SC_AUTOCOMP | IFF_MULTICAST | IFF_NEEDSGIANT;
-#endif
- SL2IFP(sc)->if_ioctl = slioctl;
- SL2IFP(sc)->if_output = sloutput;
- SL2IFP(sc)->if_start = slstart;
- SL2IFP(sc)->if_snd.ifq_maxlen = 50;
- sc->sc_fastq.ifq_maxlen = 32;
- SL2IFP(sc)->if_linkmib = sc;
- SL2IFP(sc)->if_linkmiblen = sizeof *sc;
- mtx_init(&sc->sc_fastq.ifq_mtx, "sl_fastq", NULL, MTX_DEF);
-
- /*
- * Find a suitable unit number.
- */
- for (unit=0; ; unit++) {
- if (slisstatic(unit))
- continue;
- if (!slisunitfree(unit))
- continue;
- break;
- }
- if_initname(SL2IFP(sc), "sl", unit);
- LIST_INSERT_HEAD(&sl_list, sc, sl_next);
-
- if_attach(SL2IFP(sc));
- bpfattach(SL2IFP(sc), DLT_SLIP, SLIP_HDRLEN);
-
- return sc;
-}
-
-
-/*
- * Line specific open routine.
- * Attach the given tty to the first available sl unit.
- */
-/* ARGSUSED */
-static int
-slopen(struct cdev *dev, register struct tty *tp)
-{
- register struct sl_softc *sc;
- int s, error;
-
- error = priv_check(curthread, PRIV_NET_SLIP);
- if (error)
- return (error);
-
- if ((sc = slcreate()) == NULL)
- return (ENOBUFS);
-
- tp->t_hotchar = FRAME_END;
- sc->sc_ttyp = tp;
- SL2IFP(sc)->if_baudrate = tp->t_ospeed;
- ttyflush(tp, FREAD | FWRITE);
-
- /*
- * We don't use t_canq or t_rawq, so reduce their
- * cblock resources to 0. Reserve enough cblocks
- * for t_outq to guarantee that we can fit a full
- * packet if the SLIP_HIWAT check allows slstart()
- * to loop. Use the same value for the cblock
- * limit since the reserved blocks should always
- * be enough. Reserving cblocks probably makes
- * the CLISTRESERVE check unnecessary and wasteful.
- */
- clist_alloc_cblocks(&tp->t_canq, 0, 0);
- clist_alloc_cblocks(&tp->t_outq,
- SLIP_HIWAT + 2 * SL2IFP(sc)->if_mtu + 1,
- SLIP_HIWAT + 2 * SL2IFP(sc)->if_mtu + 1);
- clist_alloc_cblocks(&tp->t_rawq, 0, 0);
-
- s = splnet();
- if_up(SL2IFP(sc));
- splx(s);
- return (0);
-}
-
-static void
-sldestroy(struct sl_softc *sc)
-{
- bpfdetach(SL2IFP(sc));
- if_detach(SL2IFP(sc));
- if_free(SL2IFP(sc));
- LIST_REMOVE(sc, sl_next);
- m_free(sc->sc_mbuf);
- mtx_destroy(&sc->sc_fastq.ifq_mtx);
- if (sc->bpfbuf)
- free(sc->bpfbuf, M_SL);
- free(sc, M_SL);
-}
-
-/*
- * Line specific close routine.
- * Detach the tty from the sl unit.
- */
-static int
-slclose(struct tty *tp, int flag)
-{
- register struct sl_softc *sc;
- int s;
-
- ttyflush(tp, FREAD | FWRITE);
- /*
- * XXX the placement of the following spl is misleading. tty
- * interrupts must be blocked across line discipline switches
- * and throughout closes to avoid races.
- */
- s = splimp(); /* actually, max(spltty, splnet) */
- clist_free_cblocks(&tp->t_outq);
- sc = sl_for_tty(tp);
- if (sc != NULL) {
- if (sc->sc_outfill) {
- sc->sc_outfill = 0;
- untimeout(sl_outfill, sc, sc->sc_ofhandle);
- }
- if (sc->sc_keepalive) {
- sc->sc_keepalive = 0;
- untimeout(sl_keepalive, sc, sc->sc_kahandle);
- }
- if_down(SL2IFP(sc));
- sc->sc_ttyp = NULL;
- sldestroy(sc);
- }
- splx(s);
- return 0;
-}
-
-/*
- * Line specific (tty) ioctl routine.
- * Provide a way to get the sl unit number.
- */
-/* ARGSUSED */
-static int
-sltioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
- struct thread *td)
-{
- struct sl_softc *sc = sl_for_tty(tp);
- int s, unit, wasup;
-
- s = splimp();
- switch (cmd) {
- case SLIOCGUNIT:
- *(int *)data = SL2IFP(sc)->if_dunit;
- break;
-
- case SLIOCSUNIT:
- unit = *(u_int *)data;
- if (unit < 0) {
- splx(s);
- return (ENXIO);
- }
- if (SL2IFP(sc)->if_dunit != unit) {
- if (!slisunitfree(unit)) {
- splx(s);
- return (ENXIO);
- }
-
- wasup = SL2IFP(sc)->if_flags & IFF_UP;
- bpfdetach(SL2IFP(sc));
- if_detach(SL2IFP(sc));
- LIST_REMOVE(sc, sl_next);
- if_initname(SL2IFP(sc), "sl", unit);
- LIST_INSERT_HEAD(&sl_list, sc, sl_next);
- if_attach(SL2IFP(sc));
- bpfattach(SL2IFP(sc), DLT_SLIP, SLIP_HDRLEN);
- if (wasup)
- if_up(SL2IFP(sc));
- else
- if_down(SL2IFP(sc));
- clist_alloc_cblocks(&tp->t_outq,
- SLIP_HIWAT + 2 * SL2IFP(sc)->if_mtu + 1,
- SLIP_HIWAT + 2 * SL2IFP(sc)->if_mtu + 1);
- }
- slmarkstatic(unit);
- break;
-
- case SLIOCSKEEPAL:
- sc->sc_keepalive = *(u_int *)data * hz;
- if (sc->sc_keepalive) {
- sc->sc_flags |= SC_KEEPALIVE;
- sc->sc_kahandle = timeout(sl_keepalive, sc,
- sc->sc_keepalive);
- } else {
- if ((sc->sc_flags & SC_KEEPALIVE) != 0) {
- untimeout(sl_keepalive, sc, sc->sc_kahandle);
- sc->sc_flags &= ~SC_KEEPALIVE;
- }
- }
- break;
-
- case SLIOCGKEEPAL:
- *(int *)data = sc->sc_keepalive / hz;
- break;
-
- case SLIOCSOUTFILL:
- sc->sc_outfill = *(u_int *)data * hz;
- if (sc->sc_outfill) {
- sc->sc_flags |= SC_OUTWAIT;
- sc->sc_ofhandle = timeout(sl_outfill, sc,
- sc->sc_outfill);
- } else {
- if ((sc->sc_flags & SC_OUTWAIT) != 0) {
- untimeout(sl_outfill, sc, sc->sc_ofhandle);
- sc->sc_flags &= ~SC_OUTWAIT;
- }
- }
- break;
-
- case SLIOCGOUTFILL:
- *(int *)data = sc->sc_outfill / hz;
- break;
-
- default:
- splx(s);
- return (ENOIOCTL);
- }
- splx(s);
- return (0);
-}
-
-/*
- * Queue a packet. Start transmission if not active.
- * Compression happens in slstart; if we do it here, IP TOS
- * will cause us to not compress "background" packets, because
- * ordering gets trashed. It can be done for all packets in slstart.
- */
-static int
-sloutput(struct ifnet *ifp, register struct mbuf *m, struct sockaddr *dst,
- struct rtentry *rtp)
-{
- register struct sl_softc *sc = ifp->if_softc;
- register struct ip *ip;
- int error;
-
- /*
- * `Cannot happen' (see slioctl). Someday we will extend
- * the line protocol to support other address families.
- */
- if (dst->sa_family != AF_INET) {
- if_printf(ifp, "af%d not supported\n", dst->sa_family);
- m_freem(m);
- SL2IFP(sc)->if_noproto++;
- return (EAFNOSUPPORT);
- }
-
- if (sc->sc_ttyp == NULL || !(ifp->if_flags & IFF_UP)) {
- m_freem(m);
- return (ENETDOWN);
- }
- if ((sc->sc_ttyp->t_state & TS_CONNECTED) == 0) {
- m_freem(m);
- return (EHOSTUNREACH);
- }
- ip = mtod(m, struct ip *);
- if (SL2IFP(sc)->if_flags & SC_NOICMP && ip->ip_p == IPPROTO_ICMP) {
- m_freem(m);
- return (ENETRESET); /* XXX ? */
- }
- if (ip->ip_tos & IPTOS_LOWDELAY &&
- !ALTQ_IS_ENABLED(&SL2IFP(sc)->if_snd))
- error = !(IF_HANDOFF(&sc->sc_fastq, m, SL2IFP(sc)));
- else
- IFQ_HANDOFF(SL2IFP(sc), m, error);
- if (error) {
- SL2IFP(sc)->if_oerrors++;
- return (ENOBUFS);
- }
- return (0);
-}
-
-static void
-slstart(struct ifnet *ifp)
-{
- struct sl_softc *sc = ifp->if_softc;
- int s;
-
- s = splimp();
- if (sc->sc_ttyp->t_outq.c_cc == 0)
- sltstart(sc->sc_ttyp);
- splx(s);
-}
-
-/*
- * Start output on interface. Get another datagram
- * to send from the interface queue and map it to
- * the interface before starting output.
- */
-static int
-sltstart(struct tty *tp)
-{
- register struct sl_softc *sc = sl_for_tty(tp);
- register struct mbuf *m;
- register u_char *cp;
- register struct ip *ip;
- int s;
- register int len = 0;
-
- GIANT_REQUIRED; /* tty */
-
- for (;;) {
- /*
- * Call output process whether or not there is more in the
- * output queue. We are being called in lieu of ttstart
- * and must do what it would.
- */
- tt_oproc(tp);
-
- if (tp->t_outq.c_cc != 0) {
- if (sc != NULL)
- sc->sc_flags &= ~SC_OUTWAIT;
- if (tp->t_outq.c_cc > SLIP_HIWAT)
- return 0;
- }
-
- /*
- * This happens briefly when the line shuts down.
- */
- if (sc == NULL)
- return 0;
-
- /*
- * Get a packet and send it to the interface.
- */
- s = splimp();
- IF_DEQUEUE(&sc->sc_fastq, m);
- if (m)
- SL2IFP(sc)->if_omcasts++; /* XXX */
- else
- IF_DEQUEUE(&SL2IFP(sc)->if_snd, m);
- splx(s);
- if (m == NULL)
- return 0;
-
- /*
- * We do the header compression here rather than in sloutput
- * because the packets will be out of order if we are using TOS
- * queueing, and the connection id compression will get
- * munged when this happens.
- */
- if (bpf_peers_present(SL2IFP(sc)->if_bpf)) {
- /*
- * We need to save the TCP/IP header before it's
- * compressed. To avoid complicated code, we just
- * copy the entire packet into a stack buffer (since
- * this is a serial line, packets should be short
- * and/or the copy should be negligible cost compared
- * to the packet transmission time).
- */
- register struct mbuf *m1 = m;
- register u_char *cp;
-
- if (sc->bpfbuf == NULL)
- sc->bpfbuf = malloc(SLTMAX + SLIP_HDRLEN,
- M_SL, M_NOWAIT);
-
- if (sc->bpfbuf) {
- cp = sc->bpfbuf + SLIP_HDRLEN;
- len = 0;
- do {
- register int mlen = m1->m_len;
-
- bcopy(mtod(m1, caddr_t), cp, mlen);
- cp += mlen;
- len += mlen;
- } while ((m1 = m1->m_next) != NULL);
- }
- }
- ip = mtod(m, struct ip *);
- if (ip->ip_v == IPVERSION && ip->ip_p == IPPROTO_TCP) {
- if (SL2IFP(sc)->if_flags & SC_COMPRESS)
- *mtod(m, u_char *) |= sl_compress_tcp(m, ip,
- &sc->sc_comp, 1);
- }
- if (bpf_peers_present(SL2IFP(sc)->if_bpf) && sc->bpfbuf) {
- /*
- * Put the SLIP pseudo-"link header" in place. The
- * compressed header is now at the beginning of the
- * mbuf.
- */
- sc->bpfbuf[SLX_DIR] = SLIPDIR_OUT;
- bcopy(mtod(m, caddr_t), &sc->bpfbuf[SLX_CHDR], CHDR_LEN);
- BPF_TAP(SL2IFP(sc), sc->bpfbuf, len + SLIP_HDRLEN);
- }
-
- /*
- * If system is getting low on clists, just flush our
- * output queue (if the stuff was important, it'll get
- * retransmitted). Note that SLTMAX is used instead of
- * the current if_mtu setting because connections that
- * have already been established still use the original
- * (possibly larger) mss.
- */
- if (cfreecount < CLISTRESERVE + SLTMAX) {
- m_freem(m);
- SL2IFP(sc)->if_collisions++;
- continue;
- }
-
- sc->sc_flags &= ~SC_OUTWAIT;
- /*
- * The extra FRAME_END will start up a new packet, and thus
- * will flush any accumulated garbage. We do this whenever
- * the line may have been idle for some time.
- */
- if (tp->t_outq.c_cc == 0) {
- ++SL2IFP(sc)->if_obytes;
- (void) putc(FRAME_END, &tp->t_outq);
- }
-
- while (m) {
- register u_char *ep;
-
- cp = mtod(m, u_char *); ep = cp + m->m_len;
- while (cp < ep) {
- /*
- * Find out how many bytes in the string we can
- * handle without doing something special.
- */
- register u_char *bp = cp;
-
- while (cp < ep) {
- switch (*cp++) {
- case FRAME_ESCAPE:
- case FRAME_END:
- --cp;
- goto out;
- }
- }
- out:
- if (cp > bp) {
- /*
- * Put n characters at once
- * into the tty output queue.
- */
- if (b_to_q((char *)bp, cp - bp,
- &tp->t_outq))
- break;
- SL2IFP(sc)->if_obytes += cp - bp;
- }
- /*
- * If there are characters left in the mbuf,
- * the first one must be special..
- * Put it out in a different form.
- */
- if (cp < ep) {
- if (putc(FRAME_ESCAPE, &tp->t_outq))
- break;
- if (putc(*cp++ == FRAME_ESCAPE ?
- TRANS_FRAME_ESCAPE : TRANS_FRAME_END,
- &tp->t_outq)) {
- (void) unputc(&tp->t_outq);
- break;
- }
- SL2IFP(sc)->if_obytes += 2;
- }
- }
- m = m_free(m);
- }
-
- if (putc(FRAME_END, &tp->t_outq)) {
- /*
- * Not enough room. Remove a char to make room
- * and end the packet normally.
- * If you get many collisions (more than one or two
- * a day) you probably do not have enough clists
- * and you should increase "nclist" in param.c.
- */
- (void) unputc(&tp->t_outq);
- (void) putc(FRAME_END, &tp->t_outq);
- SL2IFP(sc)->if_collisions++;
- } else {
- ++SL2IFP(sc)->if_obytes;
- SL2IFP(sc)->if_opackets++;
- }
- }
- return 0;
-}
-
-/*
- * Copy data buffer to mbuf chain; add ifnet pointer.
- */
-static struct mbuf *
-sl_btom(struct sl_softc *sc, register int len)
-{
- struct mbuf *m, *newm;
-
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- return (NULL);
-
- /*
- * If we have more than MHLEN bytes, it's cheaper to
- * queue the cluster we just filled & allocate a new one
- * for the input buffer. Otherwise, fill the mbuf we
- * allocated above. Note that code in the input routine
- * guarantees that packet will fit in a cluster.
- */
- if (len >= MHLEN) {
- MCLGET(m, M_DONTWAIT);
- if ((m->m_flags & M_EXT) == 0) {
- /*
- * we couldn't get a cluster - if memory's this
- * low, it's time to start dropping packets.
- */
- (void) m_free(m);
- return (NULL);
- }
- /* Swap the new and old clusters */
- newm = m;
- m = sc->sc_mbuf;
- sc->sc_mbuf = newm;
- sc->sc_ep = mtod(newm, u_char *) + SLBUFSIZE;
-
- m->m_data = (caddr_t)sc->sc_buf;
- } else
- bcopy((caddr_t)sc->sc_buf, mtod(m, caddr_t), len);
-
- m->m_len = len;
- m->m_pkthdr.len = len;
- m->m_pkthdr.rcvif = SL2IFP(sc);
- return (m);
-}
-
-/*
- * tty interface receiver interrupt.
- */
-static int
-slinput(int c, struct tty *tp)
-{
- register struct sl_softc *sc;
- register struct mbuf *m;
- register int len;
- u_char chdr[CHDR_LEN];
-
- tk_nin++;
- sc = sl_for_tty(tp);
- if (sc == NULL)
- return 0;
- if (c & TTY_ERRORMASK || (tp->t_state & TS_CONNECTED) == 0) {
- sc->sc_flags |= SC_ERROR;
- return 0;
- }
- c &= TTY_CHARMASK;
-
- ++SL2IFP(sc)->if_ibytes;
-
- if (SL2IFP(sc)->if_flags & IFF_DEBUG) {
- if (c == ABT_ESC) {
- /*
- * If we have a previous abort, see whether
- * this one is within the time limit.
- */
- if (sc->sc_abortcount &&
- time_uptime >= sc->sc_starttime + ABT_WINDOW)
- sc->sc_abortcount = 0;
- /*
- * If we see an abort after "idle" time, count it;
- * record when the first abort escape arrived.
- */
- if (time_uptime >= sc->sc_lasttime + ABT_IDLE) {
- if (++sc->sc_abortcount == 1)
- sc->sc_starttime = time_uptime;
- if (sc->sc_abortcount >= ABT_COUNT) {
- slclose(tp,0);
- return 0;
- }
- }
- } else
- sc->sc_abortcount = 0;
- sc->sc_lasttime = time_uptime;
- }
-
- switch (c) {
-
- case TRANS_FRAME_ESCAPE:
- if (sc->sc_escape)
- c = FRAME_ESCAPE;
- break;
-
- case TRANS_FRAME_END:
- if (sc->sc_escape)
- c = FRAME_END;
- break;
-
- case FRAME_ESCAPE:
- sc->sc_escape = 1;
- return 0;
-
- case FRAME_END:
- sc->sc_flags &= ~SC_KEEPALIVE;
- if(sc->sc_flags & SC_ERROR) {
- sc->sc_flags &= ~SC_ERROR;
- goto newpack;
- }
- len = sc->sc_mp - sc->sc_buf;
- if (len < 3)
- /* less than min length packet - ignore */
- goto newpack;
-
- if (bpf_peers_present(SL2IFP(sc)->if_bpf)) {
- /*
- * Save the compressed header, so we
- * can tack it on later. Note that we
- * will end up copying garbage in some
- * cases but this is okay. We remember
- * where the buffer started so we can
- * compute the new header length.
- */
- bcopy(sc->sc_buf, chdr, CHDR_LEN);
- }
-
- if ((c = (*sc->sc_buf & 0xf0)) != (IPVERSION << 4)) {
- if (c & 0x80)
- c = TYPE_COMPRESSED_TCP;
- else if (c == TYPE_UNCOMPRESSED_TCP)
- *sc->sc_buf &= 0x4f; /* XXX */
- /*
- * We've got something that's not an IP packet.
- * If compression is enabled, try to decompress it.
- * Otherwise, if `auto-enable' compression is on and
- * it's a reasonable packet, decompress it and then
- * enable compression. Otherwise, drop it.
- */
- if (SL2IFP(sc)->if_flags & SC_COMPRESS) {
- len = sl_uncompress_tcp(&sc->sc_buf, len,
- (u_int)c, &sc->sc_comp);
- if (len <= 0)
- goto error;
- } else if ((SL2IFP(sc)->if_flags & SC_AUTOCOMP) &&
- c == TYPE_UNCOMPRESSED_TCP && len >= 40) {
- len = sl_uncompress_tcp(&sc->sc_buf, len,
- (u_int)c, &sc->sc_comp);
- if (len <= 0)
- goto error;
- SL2IFP(sc)->if_flags |= SC_COMPRESS;
- } else
- goto error;
- }
- if (bpf_peers_present(SL2IFP(sc)->if_bpf)) {
- /*
- * Put the SLIP pseudo-"link header" in place.
- * We couldn't do this any earlier since
- * decompression probably moved the buffer
- * pointer. Then, invoke BPF.
- */
- register u_char *hp = sc->sc_buf - SLIP_HDRLEN;
-
- hp[SLX_DIR] = SLIPDIR_IN;
- bcopy(chdr, &hp[SLX_CHDR], CHDR_LEN);
- BPF_TAP(SL2IFP(sc), hp, len + SLIP_HDRLEN);
- }
- m = sl_btom(sc, len);
- if (m == NULL)
- goto error;
-
- SL2IFP(sc)->if_ipackets++;
-
- if ((SL2IFP(sc)->if_flags & IFF_UP) == 0) {
- m_freem(m);
- goto newpack;
- }
- if (netisr_queue(NETISR_IP, m)) { /* (0) on success. */
- SL2IFP(sc)->if_ierrors++;
- SL2IFP(sc)->if_iqdrops++;
- }
- goto newpack;
- }
- if (sc->sc_mp < sc->sc_ep) {
- *sc->sc_mp++ = c;
- sc->sc_escape = 0;
- return 0;
- }
-
- /* can't put lower; would miss an extra frame */
- sc->sc_flags |= SC_ERROR;
-
-error:
- SL2IFP(sc)->if_ierrors++;
-newpack:
- sc->sc_mp = sc->sc_buf = sc->sc_ep - SLRMAX;
- sc->sc_escape = 0;
- return 0;
-}
-
-/*
- * Process an ioctl request.
- */
-static int
-slioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
-{
- register struct ifaddr *ifa = (struct ifaddr *)data;
- register struct ifreq *ifr = (struct ifreq *)data;
- register int s, error = 0;
- struct sl_softc *sc = ifp->if_softc;
-
- s = splimp();
-
- switch (cmd) {
-
- case SIOCSIFFLAGS:
- /*
- * if.c will set the interface up even if we
- * don't want it to.
- */
- if (sc->sc_ttyp == NULL) {
- ifp->if_flags &= ~IFF_UP;
- }
- break;
- case SIOCSIFADDR:
- /*
- * This is "historical" - set the interface up when
- * setting the address.
- */
- if (ifa->ifa_addr->sa_family == AF_INET) {
- if (sc->sc_ttyp != NULL)
- ifp->if_flags |= IFF_UP;
- } else {
- error = EAFNOSUPPORT;
- }
- break;
-
- case SIOCSIFDSTADDR:
- if (ifa->ifa_addr->sa_family != AF_INET)
- error = EAFNOSUPPORT;
- break;
-
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- break;
-
- case SIOCSIFMTU:
- /*
- * Set the interface MTU.
- */
- if (ifr->ifr_mtu > SLTMAX)
- error = EINVAL;
- else {
- struct tty *tp;
-
- ifp->if_mtu = ifr->ifr_mtu;
- tp = sc->sc_ttyp;
- if (tp != NULL)
- clist_alloc_cblocks(&tp->t_outq,
- SLIP_HIWAT + 2 * ifp->if_mtu + 1,
- SLIP_HIWAT + 2 * ifp->if_mtu + 1);
- }
- break;
-
- default:
- error = EINVAL;
- }
- splx(s);
- return (error);
-}
-
-static void
-sl_keepalive(void *chan)
-{
- struct sl_softc *sc = chan;
-
- if (sc->sc_keepalive) {
- if (sc->sc_flags & SC_KEEPALIVE) {
- if (sc->sc_ttyp->t_pgrp != NULL) {
- PGRP_LOCK(sc->sc_ttyp->t_pgrp);
- pgsignal (sc->sc_ttyp->t_pgrp, SIGURG, 1);
- PGRP_UNLOCK(sc->sc_ttyp->t_pgrp);
- }
- } else
- sc->sc_flags |= SC_KEEPALIVE;
- sc->sc_kahandle = timeout(sl_keepalive, sc, sc->sc_keepalive);
- } else {
- sc->sc_flags &= ~SC_KEEPALIVE;
- }
-}
-
-static void
-sl_outfill(void *chan)
-{
- struct sl_softc *sc = chan;
- register struct tty *tp = sc->sc_ttyp;
- int s;
-
- if (sc->sc_outfill && tp != NULL) {
- if (sc->sc_flags & SC_OUTWAIT) {
- s = splimp ();
- ++SL2IFP(sc)->if_obytes;
- (void) putc(FRAME_END, &tp->t_outq);
- tt_oproc(tp);
- splx (s);
- } else
- sc->sc_flags |= SC_OUTWAIT;
- sc->sc_ofhandle = timeout(sl_outfill, sc, sc->sc_outfill);
- } else {
- sc->sc_flags &= ~SC_OUTWAIT;
- }
-}
diff --git a/sys/net/if_slvar.h b/sys/net/if_slvar.h
deleted file mode 100644
index e6b6d2c..0000000
--- a/sys/net/if_slvar.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*-
- * Copyright (c) 1991, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)if_slvar.h 8.3 (Berkeley) 2/1/94
- *
- * $FreeBSD$
- */
-
-#ifndef _NET_IF_SLVAR_H_
-#define _NET_IF_SLVAR_H_
-
-#include <sys/callout.h>
-
-/*
- * Definitions for SLIP interface data structures
- *
- * (This exists so programs like slstats can get at the definition
- * of sl_softc.)
- */
-struct sl_softc {
- struct ifnet *sc_ifp; /* network-visible interface */
- struct ifqueue sc_fastq; /* interactive output queue */
- struct tty *sc_ttyp; /* pointer to tty structure */
- struct mbuf *sc_mbuf; /* pointer to mbuf containing buffer */
- u_char *sc_mp; /* pointer to next available buf char */
- u_char *sc_ep; /* pointer to last available buf char */
- u_char *sc_buf; /* input buffer */
- u_int sc_flags; /* see below */
- u_int sc_escape; /* =1 if last char input was FRAME_ESCAPE */
- time_t sc_lasttime; /* last time a char arrived */
- long sc_abortcount; /* number of abort escape chars */
- time_t sc_starttime; /* time of first abort in window */
- u_int sc_keepalive; /* time to decide link hang */
- u_int sc_outfill; /* time to send FRAME_END when output idle */
- /*
- * Handles for scheduling outfill and
- * keepalive timeouts.
- */
- struct callout_handle sc_ofhandle;
- struct callout_handle sc_kahandle;
- struct slcompress sc_comp; /* tcp compression data */
- LIST_ENTRY(sl_softc) sl_next;
- u_char *bpfbuf; /* hang buffer for bpf here */
-};
-#define SL2IFP(sc) ((sc)->sc_ifp)
-
-/* internal flags */
-#define SC_ERROR 0x0001 /* had an input error */
-#define SC_OUTWAIT 0x0002 /* waiting for output fill */
-#define SC_KEEPALIVE 0x0004 /* input keepalive */
-
-/* visible flags */
-#define SC_COMPRESS IFF_LINK0 /* compress TCP traffic */
-#define SC_NOICMP IFF_LINK1 /* suppress ICMP traffic */
-#define SC_AUTOCOMP IFF_LINK2 /* auto-enable TCP compression */
-
-
-#endif
diff --git a/sys/net/if_spppsubr.c b/sys/net/if_spppsubr.c
index 9a5a11d..b1c7125 100644
--- a/sys/net/if_spppsubr.c
+++ b/sys/net/if_spppsubr.c
@@ -239,7 +239,7 @@ struct cp {
#define SPPP_LOCK(sp) mtx_lock (&(sp)->mtx)
#define SPPP_UNLOCK(sp) mtx_unlock (&(sp)->mtx)
#define SPPP_LOCK_ASSERT(sp) mtx_assert (&(sp)->mtx, MA_OWNED)
-#define SPPP_LOCK_OWNED(sp) mtx_owned (&sp->mtx)
+#define SPPP_LOCK_OWNED(sp) mtx_owned (&(sp)->mtx)
#ifdef INET
/*
diff --git a/sys/net/if_tap.c b/sys/net/if_tap.c
index b4ee7e1..9256301 100644
--- a/sys/net/if_tap.c
+++ b/sys/net/if_tap.c
@@ -600,6 +600,7 @@ static int
tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
struct tap_softc *tp = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
struct ifstat *ifs = NULL;
int s, dummy;
@@ -609,6 +610,10 @@ tapifioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCDELMULTI:
break;
+ case SIOCSIFMTU:
+ ifp->if_mtu = ifr->ifr_mtu;
+ break;
+
case SIOCGIFSTATUS:
s = splimp();
ifs = (struct ifstat *)data;
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
index 3ff019f2..7640d78 100644
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -181,7 +181,6 @@ struct ifnet {
void *if_afdata[AF_MAX];
int if_afdata_initialized;
struct rwlock if_afdata_lock;
- struct task if_starttask; /* task for IFF_NEEDSGIANT */
struct task if_linktask; /* task for link change events */
struct mtx if_addr_mtx; /* mutex to protect address lists */
@@ -379,16 +378,6 @@ EVENTHANDLER_DECLARE(group_change_event, group_change_event_handler_t);
#define IF_AFDATA_LOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_LOCKED)
#define IF_AFDATA_UNLOCK_ASSERT(ifp) rw_assert(&(ifp)->if_afdata_lock, RA_UNLOCKED)
-#define IFF_LOCKGIANT(ifp) do { \
- if ((ifp)->if_flags & IFF_NEEDSGIANT) \
- mtx_lock(&Giant); \
-} while (0)
-
-#define IFF_UNLOCKGIANT(ifp) do { \
- if ((ifp)->if_flags & IFF_NEEDSGIANT) \
- mtx_unlock(&Giant); \
-} while (0)
-
int if_handoff(struct ifqueue *ifq, struct mbuf *m, struct ifnet *ifp,
int adjust);
#define IF_HANDOFF(ifq, m, ifp) \
diff --git a/sys/net/ppp_comp.h b/sys/net/ppp_comp.h
deleted file mode 100644
index 00591ef..0000000
--- a/sys/net/ppp_comp.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * ppp_comp.h - Definitions for doing PPP packet compression.
- */
-
-/*-
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies. This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
- *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- *
- * $FreeBSD$
- */
-
-#ifndef _NET_PPP_COMP_H
-#define _NET_PPP_COMP_H
-
-/*
- * Structure giving methods for compression/decompression.
- */
-#ifdef PACKETPTR
-struct compressor {
- int compress_proto; /* CCP compression protocol number */
-
- /* Allocate space for a compressor (transmit side) */
- void *(*comp_alloc)(u_char *options, int opt_len);
- /* Free space used by a compressor */
- void (*comp_free)(void *state);
- /* Initialize a compressor */
- int (*comp_init)(void *state, u_char *options, int opt_len,
- int unit, int hdrlen, int debug);
- /* Reset a compressor */
- void (*comp_reset)(void *state);
- /* Compress a packet */
- int (*compress)(void *state, PACKETPTR *mret, PACKETPTR mp,
- int orig_len, int max_len);
- /* Return compression statistics */
- void (*comp_stat)(void *state, struct compstat *stats);
-
- /* Allocate space for a decompressor (receive side) */
- void *(*decomp_alloc)(u_char *options, int opt_len);
- /* Free space used by a decompressor */
- void (*decomp_free)(void *state);
- /* Initialize a decompressor */
- int (*decomp_init)(void *state, u_char *options, int opt_len,
- int unit, int hdrlen, int mru, int debug);
- /* Reset a decompressor */
- void (*decomp_reset)(void *state);
- /* Decompress a packet. */
- int (*decompress)(void *state, PACKETPTR mp, PACKETPTR *dmpp);
- /* Update state for an incompressible packet received */
- void (*incomp)(void *state, PACKETPTR mp);
- /* Return decompression statistics */
- void (*decomp_stat)(void *state, struct compstat *stats);
-};
-#endif /* PACKETPTR */
-
-/*
- * Return values for decompress routine.
- * We need to make these distinctions so that we can disable certain
- * useful functionality, namely sending a CCP reset-request as a result
- * of an error detected after decompression. This is to avoid infringing
- * a patent held by Motorola.
- * Don't you just lurve software patents.
- */
-#define DECOMP_OK 0 /* everything went OK */
-#define DECOMP_ERROR 1 /* error detected before decomp. */
-#define DECOMP_FATALERROR 2 /* error detected after decomp. */
-
-/*
- * CCP codes.
- */
-#define CCP_CONFREQ 1
-#define CCP_CONFACK 2
-#define CCP_TERMREQ 5
-#define CCP_TERMACK 6
-#define CCP_RESETREQ 14
-#define CCP_RESETACK 15
-
-/*
- * Max # bytes for a CCP option
- */
-#define CCP_MAX_OPTION_LENGTH 32
-
-/*
- * Parts of a CCP packet.
- */
-#define CCP_CODE(dp) ((dp)[0])
-#define CCP_ID(dp) ((dp)[1])
-#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3])
-#define CCP_HDRLEN 4
-
-#define CCP_OPT_CODE(dp) ((dp)[0])
-#define CCP_OPT_LENGTH(dp) ((dp)[1])
-#define CCP_OPT_MINLEN 2
-
-/*
- * Definitions for BSD-Compress.
- */
-#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */
-#define CILEN_BSD_COMPRESS 3 /* length of config. option */
-
-/* Macros for handling the 3rd byte of the BSD-Compress config option. */
-#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */
-#define BSD_VERSION(x) ((x) >> 5) /* version of option format */
-#define BSD_CURRENT_VERSION 1 /* current version number */
-#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n))
-
-#define BSD_MIN_BITS 9 /* smallest code size supported */
-#define BSD_MAX_BITS 15 /* largest code size supported */
-
-/*
- * Definitions for Deflate.
- */
-#define CI_DEFLATE 26 /* config option for Deflate */
-#define CI_DEFLATE_DRAFT 24 /* value used in original draft RFC */
-#define CILEN_DEFLATE 4 /* length of its config option */
-
-#define DEFLATE_MIN_SIZE 8
-#define DEFLATE_MAX_SIZE 15
-#define DEFLATE_METHOD_VAL 8
-#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE)
-#define DEFLATE_METHOD(x) ((x) & 0x0F)
-#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \
- + DEFLATE_METHOD_VAL)
-#define DEFLATE_CHK_SEQUENCE 0
-
-/*
- * Definitions for other, as yet unsupported, compression methods.
- */
-#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */
-#define CILEN_PREDICTOR_1 2 /* length of its config option */
-#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */
-#define CILEN_PREDICTOR_2 2 /* length of its config option */
-
-#endif /* _NET_PPP_COMP_H */
diff --git a/sys/net/ppp_deflate.c b/sys/net/ppp_deflate.c
deleted file mode 100644
index e3015bd..0000000
--- a/sys/net/ppp_deflate.c
+++ /dev/null
@@ -1,680 +0,0 @@
-/* $FreeBSD$ */
-
-/*-
- * ppp_deflate.c - interface the zlib procedures for Deflate compression
- * and decompression (as used by gzip) to the PPP code.
- * This version is for use with mbufs on BSD-derived systems.
- *
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies. This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
- *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/lock.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
-#include <sys/module.h>
-#include <sys/mutex.h>
-
-#include <net/ppp_defs.h>
-#include <net/zlib.h>
-
-#define PACKETPTR struct mbuf *
-#include <net/ppp_comp.h>
-
-#define DEFLATE_DEBUG 1
-
-/*
- * State for a Deflate (de)compressor.
- */
-struct deflate_state {
- int seqno;
- int w_size;
- int unit;
- int hdrlen;
- int mru;
- int debug;
- z_stream strm;
- struct compstat stats;
-};
-
-#define DEFLATE_OVHD 2 /* Deflate overhead/packet */
-
-static void *z_alloc(void *, u_int items, u_int size);
-static void z_free(void *, void *ptr);
-static void *z_comp_alloc(u_char *options, int opt_len);
-static void *z_decomp_alloc(u_char *options, int opt_len);
-static void z_comp_free(void *state);
-static void z_decomp_free(void *state);
-static int z_comp_init(void *state, u_char *options, int opt_len,
- int unit, int hdrlen, int debug);
-static int z_decomp_init(void *state, u_char *options, int opt_len,
- int unit, int hdrlen, int mru, int debug);
-static int z_compress(void *state, struct mbuf **mret, struct mbuf *mp,
- int slen, int maxolen);
-static void z_incomp(void *state, struct mbuf *dmsg);
-static int z_decompress(void *state, struct mbuf *cmp, struct mbuf **dmpp);
-static void z_comp_reset(void *state);
-static void z_decomp_reset(void *state);
-static void z_comp_stats(void *state, struct compstat *stats);
-
-/*
- * Procedures exported to if_ppp.c.
- */
-struct compressor ppp_deflate = {
- CI_DEFLATE, /* compress_proto */
- z_comp_alloc, /* comp_alloc */
- z_comp_free, /* comp_free */
- z_comp_init, /* comp_init */
- z_comp_reset, /* comp_reset */
- z_compress, /* compress */
- z_comp_stats, /* comp_stat */
- z_decomp_alloc, /* decomp_alloc */
- z_decomp_free, /* decomp_free */
- z_decomp_init, /* decomp_init */
- z_decomp_reset, /* decomp_reset */
- z_decompress, /* decompress */
- z_incomp, /* incomp */
- z_comp_stats, /* decomp_stat */
-};
-
-struct compressor ppp_deflate_draft = {
- CI_DEFLATE_DRAFT, /* compress_proto */
- z_comp_alloc, /* comp_alloc */
- z_comp_free, /* comp_free */
- z_comp_init, /* comp_init */
- z_comp_reset, /* comp_reset */
- z_compress, /* compress */
- z_comp_stats, /* comp_stat */
- z_decomp_alloc, /* decomp_alloc */
- z_decomp_free, /* decomp_free */
- z_decomp_init, /* decomp_init */
- z_decomp_reset, /* decomp_reset */
- z_decompress, /* decompress */
- z_incomp, /* incomp */
- z_comp_stats, /* decomp_stat */
-};
-
-/*
- * Space allocation and freeing routines for use by zlib routines.
- */
-static void *
-z_alloc(notused, items, size)
- void *notused;
- u_int items, size;
-{
- void *ptr;
-
- ptr = malloc(items * size, M_DEVBUF, M_NOWAIT);
- return ptr;
-}
-
-static void
-z_free(notused, ptr)
- void *notused;
- void *ptr;
-{
- free(ptr, M_DEVBUF);
-}
-
-/*
- * Allocate space for a compressor.
- */
-static void *
-z_comp_alloc(options, opt_len)
- u_char *options;
- int opt_len;
-{
- struct deflate_state *state;
- int w_size;
-
- if (opt_len != CILEN_DEFLATE
- || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
- || options[1] != CILEN_DEFLATE
- || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
- || options[3] != DEFLATE_CHK_SEQUENCE)
- return NULL;
- w_size = DEFLATE_SIZE(options[2]);
- if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
- return NULL;
-
- state = malloc(sizeof(struct deflate_state),
- M_DEVBUF, M_NOWAIT);
- if (state == NULL)
- return NULL;
-
- state->strm.next_in = NULL;
- state->strm.zalloc = z_alloc;
- state->strm.zfree = z_free;
- if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, DEFLATE_METHOD_VAL,
- -w_size, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
- free(state, M_DEVBUF);
- return NULL;
- }
-
- state->w_size = w_size;
- bzero(&state->stats, sizeof(state->stats));
- return (void *) state;
-}
-
-static void
-z_comp_free(arg)
- void *arg;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- deflateEnd(&state->strm);
- free(state, M_DEVBUF);
-}
-
-static int
-z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
- void *arg;
- u_char *options;
- int opt_len, unit, hdrlen, debug;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- if (opt_len < CILEN_DEFLATE
- || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
- || options[1] != CILEN_DEFLATE
- || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
- || DEFLATE_SIZE(options[2]) != state->w_size
- || options[3] != DEFLATE_CHK_SEQUENCE)
- return 0;
-
- state->seqno = 0;
- state->unit = unit;
- state->hdrlen = hdrlen;
- state->debug = debug;
-
- deflateReset(&state->strm);
-
- return 1;
-}
-
-static void
-z_comp_reset(arg)
- void *arg;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- state->seqno = 0;
- deflateReset(&state->strm);
-}
-
-static int
-z_compress(arg, mret, mp, orig_len, maxolen)
- void *arg;
- struct mbuf **mret; /* compressed packet (out) */
- struct mbuf *mp; /* uncompressed packet (in) */
- int orig_len, maxolen;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
- u_char *rptr, *wptr;
- int proto, olen, wspace, r, flush;
- struct mbuf *m;
-
- /*
- * Check that the protocol is in the range we handle.
- */
- rptr = mtod(mp, u_char *);
- proto = PPP_PROTOCOL(rptr);
- if (proto > 0x3fff || proto == 0xfd || proto == 0xfb) {
- *mret = NULL;
- return orig_len;
- }
-
- /* Allocate one mbuf initially. */
- if (maxolen > orig_len)
- maxolen = orig_len;
- MGET(m, M_DONTWAIT, MT_DATA);
- *mret = m;
- if (m != NULL) {
- m->m_len = 0;
- if (maxolen + state->hdrlen > MLEN)
- MCLGET(m, M_DONTWAIT);
- wspace = M_TRAILINGSPACE(m);
- if (state->hdrlen + PPP_HDRLEN + 2 < wspace) {
- m->m_data += state->hdrlen;
- wspace -= state->hdrlen;
- }
- wptr = mtod(m, u_char *);
-
- /*
- * Copy over the PPP header and store the 2-byte sequence number.
- */
- wptr[0] = PPP_ADDRESS(rptr);
- wptr[1] = PPP_CONTROL(rptr);
- wptr[2] = PPP_COMP >> 8;
- wptr[3] = PPP_COMP;
- wptr += PPP_HDRLEN;
- wptr[0] = state->seqno >> 8;
- wptr[1] = state->seqno;
- wptr += 2;
- state->strm.next_out = wptr;
- state->strm.avail_out = wspace - (PPP_HDRLEN + 2);
- } else {
- state->strm.next_out = NULL;
- state->strm.avail_out = 1000000;
- wptr = NULL;
- wspace = 0;
- }
- ++state->seqno;
-
- rptr += (proto > 0xff)? 2: 3; /* skip 1st proto byte if 0 */
- state->strm.next_in = rptr;
- state->strm.avail_in = mtod(mp, u_char *) + mp->m_len - rptr;
- mp = mp->m_next;
- flush = (mp == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
- olen = 0;
- for (;;) {
- r = deflate(&state->strm, flush);
- if (r != Z_OK) {
- printf("z_compress: deflate returned %d (%s)\n",
- r, (state->strm.msg? state->strm.msg: ""));
- break;
- }
- if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
- break; /* all done */
- if (state->strm.avail_in == 0 && mp != NULL) {
- state->strm.next_in = mtod(mp, u_char *);
- state->strm.avail_in = mp->m_len;
- mp = mp->m_next;
- if (mp == NULL)
- flush = Z_PACKET_FLUSH;
- }
- if (state->strm.avail_out == 0) {
- if (m != NULL) {
- m->m_len = wspace;
- olen += wspace;
- MGET(m->m_next, M_DONTWAIT, MT_DATA);
- m = m->m_next;
- if (m != NULL) {
- m->m_len = 0;
- if (maxolen - olen > MLEN)
- MCLGET(m, M_DONTWAIT);
- state->strm.next_out = mtod(m, u_char *);
- state->strm.avail_out = wspace = M_TRAILINGSPACE(m);
- }
- }
- if (m == NULL) {
- state->strm.next_out = NULL;
- state->strm.avail_out = 1000000;
- }
- }
- }
- if (m != NULL)
- olen += (m->m_len = wspace - state->strm.avail_out);
-
- /*
- * See if we managed to reduce the size of the packet.
- */
- if (m != NULL && olen < orig_len) {
- state->stats.comp_bytes += olen;
- state->stats.comp_packets++;
- } else {
- if (*mret != NULL) {
- m_freem(*mret);
- *mret = NULL;
- }
- state->stats.inc_bytes += orig_len;
- state->stats.inc_packets++;
- olen = orig_len;
- }
- state->stats.unc_bytes += orig_len;
- state->stats.unc_packets++;
-
- return olen;
-}
-
-static void
-z_comp_stats(arg, stats)
- void *arg;
- struct compstat *stats;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
- u_int out;
-
- *stats = state->stats;
- stats->ratio = stats->unc_bytes;
- out = stats->comp_bytes + stats->inc_bytes;
- if (stats->ratio <= 0x7ffffff)
- stats->ratio <<= 8;
- else
- out >>= 8;
- if (out != 0)
- stats->ratio /= out;
-}
-
-/*
- * Allocate space for a decompressor.
- */
-static void *
-z_decomp_alloc(options, opt_len)
- u_char *options;
- int opt_len;
-{
- struct deflate_state *state;
- int w_size;
-
- if (opt_len != CILEN_DEFLATE
- || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
- || options[1] != CILEN_DEFLATE
- || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
- || options[3] != DEFLATE_CHK_SEQUENCE)
- return NULL;
- w_size = DEFLATE_SIZE(options[2]);
- if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
- return NULL;
-
- state = malloc(sizeof(struct deflate_state),
- M_DEVBUF, M_NOWAIT);
- if (state == NULL)
- return NULL;
-
- state->strm.next_out = NULL;
- state->strm.zalloc = z_alloc;
- state->strm.zfree = z_free;
- if (inflateInit2(&state->strm, -w_size) != Z_OK) {
- free(state, M_DEVBUF);
- return NULL;
- }
-
- state->w_size = w_size;
- bzero(&state->stats, sizeof(state->stats));
- return (void *) state;
-}
-
-static void
-z_decomp_free(arg)
- void *arg;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- inflateEnd(&state->strm);
- free(state, M_DEVBUF);
-}
-
-static int
-z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
- void *arg;
- u_char *options;
- int opt_len, unit, hdrlen, mru, debug;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- if (opt_len < CILEN_DEFLATE
- || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
- || options[1] != CILEN_DEFLATE
- || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
- || DEFLATE_SIZE(options[2]) != state->w_size
- || options[3] != DEFLATE_CHK_SEQUENCE)
- return 0;
-
- state->seqno = 0;
- state->unit = unit;
- state->hdrlen = hdrlen;
- state->debug = debug;
- state->mru = mru;
-
- inflateReset(&state->strm);
-
- return 1;
-}
-
-static void
-z_decomp_reset(arg)
- void *arg;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
-
- state->seqno = 0;
- inflateReset(&state->strm);
-}
-
-/*
- * Decompress a Deflate-compressed packet.
- *
- * Because of patent problems, we return DECOMP_ERROR for errors
- * found by inspecting the input data and for system problems, but
- * DECOMP_FATALERROR for any errors which could possibly be said to
- * be being detected "after" decompression. For DECOMP_ERROR,
- * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
- * infringing a patent of Motorola's if we do, so we take CCP down
- * instead.
- *
- * Given that the frame has the correct sequence number and a good FCS,
- * errors such as invalid codes in the input most likely indicate a
- * bug, so we return DECOMP_FATALERROR for them in order to turn off
- * compression, even though they are detected by inspecting the input.
- */
-static int
-z_decompress(arg, mi, mop)
- void *arg;
- struct mbuf *mi, **mop;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
- struct mbuf *mo, *mo_head;
- u_char *rptr, *wptr;
- int rlen, olen, ospace;
- int seq, i, flush, r, decode_proto;
- u_char hdr[PPP_HDRLEN + DEFLATE_OVHD];
-
- *mop = NULL;
- rptr = mtod(mi, u_char *);
- rlen = mi->m_len;
- for (i = 0; i < PPP_HDRLEN + DEFLATE_OVHD; ++i) {
- while (rlen <= 0) {
- mi = mi->m_next;
- if (mi == NULL)
- return DECOMP_ERROR;
- rptr = mtod(mi, u_char *);
- rlen = mi->m_len;
- }
- hdr[i] = *rptr++;
- --rlen;
- }
-
- /* Check the sequence number. */
- seq = (hdr[PPP_HDRLEN] << 8) + hdr[PPP_HDRLEN+1];
- if (seq != state->seqno) {
- if (state->debug)
- printf("z_decompress%d: bad seq # %d, expected %d\n",
- state->unit, seq, state->seqno);
- return DECOMP_ERROR;
- }
- ++state->seqno;
-
- /* Allocate an output mbuf. */
- MGETHDR(mo, M_DONTWAIT, MT_DATA);
- if (mo == NULL)
- return DECOMP_ERROR;
- mo_head = mo;
- mo->m_len = 0;
- mo->m_next = NULL;
- MCLGET(mo, M_DONTWAIT);
- ospace = M_TRAILINGSPACE(mo);
- if (state->hdrlen + PPP_HDRLEN < ospace) {
- mo->m_data += state->hdrlen;
- ospace -= state->hdrlen;
- }
-
- /*
- * Fill in the first part of the PPP header. The protocol field
- * comes from the decompressed data.
- */
- wptr = mtod(mo, u_char *);
- wptr[0] = PPP_ADDRESS(hdr);
- wptr[1] = PPP_CONTROL(hdr);
- wptr[2] = 0;
-
- /*
- * Set up to call inflate. We set avail_out to 1 initially so we can
- * look at the first byte of the output and decide whether we have
- * a 1-byte or 2-byte protocol field.
- */
- state->strm.next_in = rptr;
- state->strm.avail_in = rlen;
- mi = mi->m_next;
- flush = (mi == NULL)? Z_PACKET_FLUSH: Z_NO_FLUSH;
- rlen += PPP_HDRLEN + DEFLATE_OVHD;
- state->strm.next_out = wptr + 3;
- state->strm.avail_out = 1;
- decode_proto = 1;
- olen = PPP_HDRLEN;
-
- /*
- * Call inflate, supplying more input or output as needed.
- */
- for (;;) {
- r = inflate(&state->strm, flush);
- if (r != Z_OK) {
-#if !DEFLATE_DEBUG
- if (state->debug)
-#endif
- printf("z_decompress%d: inflate returned %d (%s)\n",
- state->unit, r, (state->strm.msg? state->strm.msg: ""));
- m_freem(mo_head);
- return DECOMP_FATALERROR;
- }
- if (flush != Z_NO_FLUSH && state->strm.avail_out != 0)
- break; /* all done */
- if (state->strm.avail_in == 0 && mi != NULL) {
- state->strm.next_in = mtod(mi, u_char *);
- state->strm.avail_in = mi->m_len;
- rlen += mi->m_len;
- mi = mi->m_next;
- if (mi == NULL)
- flush = Z_PACKET_FLUSH;
- }
- if (state->strm.avail_out == 0) {
- if (decode_proto) {
- state->strm.avail_out = ospace - PPP_HDRLEN;
- if ((wptr[3] & 1) == 0) {
- /* 2-byte protocol field */
- wptr[2] = wptr[3];
- --state->strm.next_out;
- ++state->strm.avail_out;
- --olen;
- }
- decode_proto = 0;
- } else {
- mo->m_len = ospace;
- olen += ospace;
- MGET(mo->m_next, M_DONTWAIT, MT_DATA);
- mo = mo->m_next;
- if (mo == NULL) {
- m_freem(mo_head);
- return DECOMP_ERROR;
- }
- MCLGET(mo, M_DONTWAIT);
- state->strm.next_out = mtod(mo, u_char *);
- state->strm.avail_out = ospace = M_TRAILINGSPACE(mo);
- }
- }
- }
- if (decode_proto) {
- m_freem(mo_head);
- return DECOMP_ERROR;
- }
- olen += (mo->m_len = ospace - state->strm.avail_out);
-#if DEFLATE_DEBUG
- if (state->debug && olen > state->mru + PPP_HDRLEN)
- printf("ppp_deflate%d: exceeded mru (%d > %d)\n",
- state->unit, olen, state->mru + PPP_HDRLEN);
-#endif
-
- state->stats.unc_bytes += olen;
- state->stats.unc_packets++;
- state->stats.comp_bytes += rlen;
- state->stats.comp_packets++;
-
- *mop = mo_head;
- return DECOMP_OK;
-}
-
-/*
- * Incompressible data has arrived - add it to the history.
- */
-static void
-z_incomp(arg, mi)
- void *arg;
- struct mbuf *mi;
-{
- struct deflate_state *state = (struct deflate_state *) arg;
- u_char *rptr;
- int rlen, proto, r;
-
- /*
- * Check that the protocol is one we handle.
- */
- rptr = mtod(mi, u_char *);
- proto = PPP_PROTOCOL(rptr);
- if (proto > 0x3fff || proto == 0xfd || proto == 0xfb)
- return;
-
- ++state->seqno;
-
- /*
- * Iterate through the mbufs, adding the characters in them
- * to the decompressor's history. For the first mbuf, we start
- * at the either the 1st or 2nd byte of the protocol field,
- * depending on whether the protocol value is compressible.
- */
- rlen = mi->m_len;
- state->strm.next_in = rptr + 3;
- state->strm.avail_in = rlen - 3;
- if (proto > 0xff) {
- --state->strm.next_in;
- ++state->strm.avail_in;
- }
- for (;;) {
- r = inflateIncomp(&state->strm);
- if (r != Z_OK) {
- /* gak! */
-#if !DEFLATE_DEBUG
- if (state->debug)
-#endif
- printf("z_incomp%d: inflateIncomp returned %d (%s)\n",
- state->unit, r, (state->strm.msg? state->strm.msg: ""));
- return;
- }
- mi = mi->m_next;
- if (mi == NULL)
- break;
- state->strm.next_in = mtod(mi, u_char *);
- state->strm.avail_in = mi->m_len;
- rlen += mi->m_len;
- }
-
- /*
- * Update stats.
- */
- state->stats.inc_bytes += rlen;
- state->stats.inc_packets++;
- state->stats.unc_bytes += rlen;
- state->stats.unc_packets++;
-}
-MODULE_DEPEND(ppp_deflate, zlib, 1, 1, 1);
diff --git a/sys/net/ppp_tty.c b/sys/net/ppp_tty.c
deleted file mode 100644
index ae37bd7..0000000
--- a/sys/net/ppp_tty.c
+++ /dev/null
@@ -1,1076 +0,0 @@
-/*
- * ppp_tty.c - Point-to-Point Protocol (PPP) driver for asynchronous
- * tty devices.
- */
-/*-
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Drew D. Perkins
- * Carnegie Mellon University
- * 4910 Forbes Ave.
- * Pittsburgh, PA 15213
- * (412) 268-8576
- * ddp@andrew.cmu.edu
- *
- * Based on:
- * @(#)if_sl.c 7.6.1.2 (Berkeley) 2/15/89
- *
- * Copyright (c) 1987 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Serial Line interface
- *
- * Rick Adams
- * Center for Seismic Studies
- * 1300 N 17th Street, Suite 1450
- * Arlington, Virginia 22209
- * (703)276-7900
- * rick@seismo.ARPA
- * seismo!rick
- *
- * Pounded on heavily by Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
- * Converted to 4.3BSD Beta by Chris Torek.
- * Other changes made at Berkeley, based in part on code by Kirk Smith.
- *
- * Converted to 4.3BSD+ 386BSD by Brad Parker (brad@cayman.com)
- * Added VJ tcp header compression; more unified ioctls
- *
- * Extensively modified by Paul Mackerras (paulus@cs.anu.edu.au).
- * Cleaned up a lot of the mbuf-related code to fix bugs that
- * caused system crashes and packet corruption. Changed pppstart
- * so that it doesn't just give up with a "collision" if the whole
- * packet doesn't fit in the output ring buffer.
- *
- * Added priority queueing for interactive IP packets, following
- * the model of if_sl.c, plus hooks for bpf.
- * Paul Mackerras (paulus@cs.anu.edu.au).
- */
-
-/* $FreeBSD$ */
-
-#include "opt_ppp.h" /* XXX for ppp_defs.h */
-
-#define VJC /* XXX for ppp_defs.h */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/priv.h>
-#include <sys/proc.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/fcntl.h>
-#include <sys/tty.h>
-#include <sys/conf.h>
-#include <sys/uio.h>
-
-#ifdef PPP_FILTER
-#include <net/bpf.h>
-#endif
-#include <net/if_ppp.h>
-#include <net/if_pppvar.h>
-
-static int pppopen(struct cdev *dev, struct tty *tp);
-static int pppclose(struct tty *tp, int flag);
-static int pppread(struct tty *tp, struct uio *uio, int flag);
-static int pppwrite(struct tty *tp, struct uio *uio, int flag);
-static int ppptioctl(struct tty *tp, u_long cmd, caddr_t data,
- int flag, struct thread *td);
-static int pppinput(int c, struct tty *tp);
-static int pppstart(struct tty *tp);
-
-static u_short pppfcs(u_short fcs, u_char *cp, int len);
-static void pppasyncstart(struct ppp_softc *);
-static void pppasyncctlp(struct ppp_softc *);
-static void pppasyncrelinq(struct ppp_softc *);
-static void pppasyncsetmtu(struct ppp_softc *);
-static void ppp_timeout(void *);
-static void pppgetm(struct ppp_softc *sc);
-static void ppplogchar(struct ppp_softc *, int);
-
-/* XXX called from if_ppp.c - layering violation */
-void pppasyncattach(void *);
-void pppasyncdetach(void);
-
-/*
- * Some useful mbuf macros not in mbuf.h.
- */
-#define M_IS_CLUSTER(m) ((m)->m_flags & M_EXT)
-
-#define M_DATASTART(m) \
- (M_IS_CLUSTER(m) ? (m)->m_ext.ext_buf : \
- (m)->m_flags & M_PKTHDR ? (m)->m_pktdat : (m)->m_dat)
-
-#define M_DATASIZE(m) \
- (M_IS_CLUSTER(m) ? (m)->m_ext.ext_size : \
- (m)->m_flags & M_PKTHDR ? MHLEN: MLEN)
-
-/*
- * Does c need to be escaped?
- */
-#define ESCAPE_P(c) (sc->sc_asyncmap[(c) >> 5] & (1 << ((c) & 0x1F)))
-
-/*
- * Procedures for using an async tty interface for PPP.
- */
-
-/* This is a FreeBSD-2.X kernel. */
-#define CCOUNT(q) ((q)->c_cc)
-#define PPP_LOWAT 100 /* Process more output when < LOWAT on queue */
-#define PPP_HIWAT 400 /* Don't start a new packet if HIWAT on que */
-
-/*
- * Define the PPP line discipline.
- */
-
-static struct linesw pppdisc = {
- pppopen, pppclose, pppread, pppwrite,
- ppptioctl, pppinput, pppstart, ttymodem
-};
-
-void
-pppasyncattach(dummy)
- void *dummy;
-{
- ldisc_register(PPPDISC, &pppdisc);
-}
-
-void
-pppasyncdetach()
-{
- ldisc_deregister(PPPDISC);
-}
-
-/*
- * Line specific open routine for async tty devices.
- * Attach the given tty to the first available ppp unit.
- * Called from device open routine or ttioctl() at >= splsofttty()
- */
-/* ARGSUSED */
-static int
-pppopen(dev, tp)
- struct cdev *dev;
- register struct tty *tp;
-{
- struct thread *td = curthread; /* XXX */
- register struct ppp_softc *sc;
- int error, s;
-
- error = priv_check(td, PRIV_NET_PPP);
- if (error)
- return (error);
-
- s = spltty();
-
- tp->t_hotchar = PPP_FLAG;
-
- if ((sc = pppalloc(td->td_proc->p_pid)) == NULL) {
- splx(s);
- return ENXIO;
- }
-
- if (sc->sc_relinq)
- (*sc->sc_relinq)(sc); /* get previous owner to relinquish the unit */
-
- sc->sc_ilen = 0;
- sc->sc_m = NULL;
- bzero(sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
- sc->sc_asyncmap[0] = 0xffffffff;
- sc->sc_asyncmap[3] = 0x60000000;
- sc->sc_rasyncmap = 0;
- sc->sc_devp = (void *) tp;
- sc->sc_start = pppasyncstart;
- sc->sc_ctlp = pppasyncctlp;
- sc->sc_relinq = pppasyncrelinq;
- sc->sc_setmtu = pppasyncsetmtu;
- sc->sc_outm = NULL;
- pppgetm(sc);
- PPP2IFP(sc)->if_drv_flags |= IFF_DRV_RUNNING;
- getmicrotime(&PPP2IFP(sc)->if_lastchange);
- PPP2IFP(sc)->if_baudrate = tp->t_ospeed;
-
- tp->t_hotchar = PPP_FLAG;
- tp->t_lsc = sc;
- ttyflush(tp, FREAD | FWRITE);
-
- /*
- * Pre-allocate cblocks to the "just right" amount. The 1 byte t_canq
- * allocation helps avoid the need for select and/or FIONREAD.
- * We also pass 1 byte tokens through t_canq...
- */
- clist_alloc_cblocks(&tp->t_canq, 1, 1);
- clist_alloc_cblocks(&tp->t_outq, PPP2IFP(sc)->if_mtu + PPP_HIWAT,
- PPP2IFP(sc)->if_mtu + PPP_HIWAT);
- clist_alloc_cblocks(&tp->t_rawq, 0, 0);
-
- splx(s);
-
- return (0);
-}
-
-/*
- * Line specific close routine, called from device close routine
- * and from ttioctl at >= splsofttty().
- * Detach the tty from the ppp unit.
- * Mimics part of tty_close().
- */
-static int
-pppclose(tp, flag)
- struct tty *tp;
- int flag;
-{
- register struct ppp_softc *sc = (struct ppp_softc *)tp->t_lsc;
- int s;
-
- s = spltty();
- ttyflush(tp, FREAD | FWRITE);
- clist_free_cblocks(&tp->t_canq);
- clist_free_cblocks(&tp->t_outq);
- if (sc != NULL) {
- pppasyncrelinq(sc);
- pppdealloc(sc);
- }
- splx(s);
- return 0;
-}
-
-/*
- * Relinquish the interface unit to another device.
- */
-static void
-pppasyncrelinq(sc)
- struct ppp_softc *sc;
-{
- int s;
-
- s = spltty();
- if (sc->sc_outm) {
- m_freem(sc->sc_outm);
- sc->sc_outm = NULL;
- }
- if (sc->sc_m) {
- m_freem(sc->sc_m);
- sc->sc_m = NULL;
- }
- if (sc->sc_flags & SC_TIMEOUT) {
- callout_stop(&sc->sc_timo_ch);
- sc->sc_flags &= ~SC_TIMEOUT;
- }
- splx(s);
-}
-
-/*
- * This gets called from the upper layer to notify a mtu change
- */
-static void
-pppasyncsetmtu(sc)
-register struct ppp_softc *sc;
-{
- register struct tty *tp = (struct tty *) sc->sc_devp;
- int s;
-
- s = spltty();
- if (tp != NULL)
- clist_alloc_cblocks(&tp->t_outq, PPP2IFP(sc)->if_mtu + PPP_HIWAT,
- PPP2IFP(sc)->if_mtu + PPP_HIWAT);
- splx(s);
-}
-
-/*
- * Line specific (tty) read routine.
- * called at zero spl from the device driver in the response to user-level
- * reads on the tty file descriptor (ie: pppd).
- */
-static int
-pppread(tp, uio, flag)
- register struct tty *tp;
- struct uio *uio;
- int flag;
-{
- register struct ppp_softc *sc = (struct ppp_softc *)tp->t_lsc;
- struct mbuf *m, *m0;
- register int s;
- int error = 0;
-
- if (sc == NULL)
- return 0;
- /*
- * Loop waiting for input, checking that nothing disasterous
- * happens in the meantime.
- */
- s = spltty();
- for (;;) {
- if (tp != (struct tty *) sc->sc_devp || tp->t_line != PPPDISC) {
- splx(s);
- return 0;
- }
- if (sc->sc_inq.ifq_head != NULL)
- break;
- if ((tp->t_state & TS_CONNECTED) == 0) {
- splx(s);
- return 0; /* end of file */
- }
- if (tp->t_state & TS_ASYNC || flag & O_NONBLOCK) {
- splx(s);
- return (EWOULDBLOCK);
- }
- error = ttysleep(tp, TSA_HUP_OR_INPUT(tp), TTIPRI | PCATCH, "pppin", 0);
- if (error) {
- splx(s);
- return error;
- }
- }
-
- /* Pull place-holder byte out of canonical queue */
- getc(&tp->t_canq);
-
- /* Get the packet from the input queue */
- IF_DEQUEUE(&sc->sc_inq, m0);
- splx(s);
-
- for (m = m0; m && uio->uio_resid; m = m->m_next)
- if ((error = uiomove(mtod(m, u_char *), m->m_len, uio)) != 0)
- break;
- m_freem(m0);
- return (error);
-}
-
-/*
- * Line specific (tty) write routine.
- * called at zero spl from the device driver in the response to user-level
- * writes on the tty file descriptor (ie: pppd).
- */
-static int
-pppwrite(tp, uio, flag)
- register struct tty *tp;
- struct uio *uio;
- int flag;
-{
- register struct ppp_softc *sc = (struct ppp_softc *)tp->t_lsc;
- struct mbuf *m;
- struct sockaddr dst;
- int error, s;
-
- if ((tp->t_state & TS_CONNECTED) == 0)
- return 0; /* wrote 0 bytes */
- if (tp->t_line != PPPDISC)
- return (EINVAL);
- if (sc == NULL)
- return EIO;
- if (uio->uio_resid > PPP2IFP(sc)->if_mtu + PPP_HDRLEN ||
- uio->uio_resid < PPP_HDRLEN)
- return (EMSGSIZE);
-
- s = spltty();
- if ((m = m_uiotombuf(uio, M_DONTWAIT, 0, 0, M_PKTHDR)) == NULL) {
- splx(s);
- return (ENOBUFS);
- }
-
- dst.sa_family = AF_UNSPEC;
- bcopy(mtod(m, u_char *), dst.sa_data, PPP_HDRLEN);
- m->m_data += PPP_HDRLEN;
- m->m_len -= PPP_HDRLEN;
-
- /* call the upper layer to "transmit" it... */
- error = pppoutput(PPP2IFP(sc), m, &dst, NULL);
- splx(s);
- return (error);
-}
-
-/*
- * Line specific (tty) ioctl routine.
- * This discipline requires that tty device drivers call
- * the line specific l_ioctl routine from their ioctl routines.
- */
-/* ARGSUSED */
-static int
-ppptioctl(tp, cmd, data, flag, td)
- struct tty *tp;
- u_long cmd;
- caddr_t data;
- int flag;
- struct thread *td;
-{
- struct ppp_softc *sc = (struct ppp_softc *)tp->t_lsc;
- int error, s;
-
- if (sc == NULL || tp != (struct tty *) sc->sc_devp)
- return (ENOIOCTL);
-
- error = 0;
- switch (cmd) {
- case PPPIOCSASYNCMAP:
- error = priv_check(td, PRIV_NET_PPP);
- if (error)
- break;
- sc->sc_asyncmap[0] = *(u_int *)data;
- break;
-
- case PPPIOCGASYNCMAP:
- *(u_int *)data = sc->sc_asyncmap[0];
- break;
-
- case PPPIOCSRASYNCMAP:
- error = priv_check(td, PRIV_NET_PPP);
- if (error)
- break;
- sc->sc_rasyncmap = *(u_int *)data;
- break;
-
- case PPPIOCGRASYNCMAP:
- *(u_int *)data = sc->sc_rasyncmap;
- break;
-
- case PPPIOCSXASYNCMAP:
- error = priv_check(td, PRIV_NET_PPP);
- if (error)
- break;
- s = spltty();
- bcopy(data, sc->sc_asyncmap, sizeof(sc->sc_asyncmap));
- sc->sc_asyncmap[1] = 0; /* mustn't escape 0x20 - 0x3f */
- sc->sc_asyncmap[2] &= ~0x40000000; /* mustn't escape 0x5e */
- sc->sc_asyncmap[3] |= 0x60000000; /* must escape 0x7d, 0x7e */
- splx(s);
- break;
-
- case PPPIOCGXASYNCMAP:
- bcopy(sc->sc_asyncmap, data, sizeof(sc->sc_asyncmap));
- break;
-
- default:
- error = pppioctl(sc, cmd, data, flag, td);
- if (error == 0 && cmd == PPPIOCSMRU)
- pppgetm(sc);
- }
-
- return error;
-}
-
-/*
- * FCS lookup table as calculated by genfcstab.
- */
-static u_short fcstab[256] = {
- 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
- 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
- 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
- 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
- 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
- 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
- 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
- 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
- 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
- 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
- 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
- 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
- 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
- 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
- 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
- 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
- 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
- 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
- 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
- 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
- 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
- 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
- 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
- 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
- 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
- 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
- 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
- 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
- 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
- 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
- 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
- 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-};
-
-/*
- * Calculate a new FCS given the current FCS and the new data.
- */
-static u_short
-pppfcs(u_short fcs, u_char *cp, int len)
-{
- while (len--)
- fcs = PPP_FCS(fcs, *cp++);
- return (fcs);
-}
-
-/*
- * This gets called at splsoftnet from if_ppp.c at various times
- * when there is data ready to be sent.
- */
-static void
-pppasyncstart(sc)
- register struct ppp_softc *sc;
-{
- register struct tty *tp = (struct tty *) sc->sc_devp;
- register struct mbuf *m;
- register int len;
- register u_char *start, *stop, *cp;
- int n, ndone, done, idle;
- int s;
-
- idle = 0;
- /* XXX assumes atomic access to *tp although we're not at spltty(). */
- while (CCOUNT(&tp->t_outq) < PPP_HIWAT) {
- /*
- * See if we have an existing packet partly sent.
- * If not, get a new packet and start sending it.
- */
- m = sc->sc_outm;
- if (m == NULL) {
- /*
- * Get another packet to be sent.
- */
- m = ppp_dequeue(sc);
- if (m == NULL) {
- idle = 1;
- break;
- }
-
- /*
- * The extra PPP_FLAG will start up a new packet, and thus
- * will flush any accumulated garbage. We do this whenever
- * the line may have been idle for some time.
- */
- /* XXX as above. */
- if (CCOUNT(&tp->t_outq) == 0) {
- ++sc->sc_stats.ppp_obytes;
- (void) putc(PPP_FLAG, &tp->t_outq);
- }
-
- /* Calculate the FCS for the first mbuf's worth. */
- sc->sc_outfcs = pppfcs(PPP_INITFCS, mtod(m, u_char *), m->m_len);
- getmicrotime(&PPP2IFP(sc)->if_lastchange);
- }
-
- for (;;) {
- start = mtod(m, u_char *);
- len = m->m_len;
- stop = start + len;
- while (len > 0) {
- /*
- * Find out how many bytes in the string we can
- * handle without doing something special.
- */
- for (cp = start; cp < stop; cp++)
- if (ESCAPE_P(*cp))
- break;
- n = cp - start;
- if (n) {
- /* NetBSD (0.9 or later), 4.3-Reno or similar. */
- ndone = n - b_to_q(start, n, &tp->t_outq);
- len -= ndone;
- start += ndone;
- sc->sc_stats.ppp_obytes += ndone;
-
- if (ndone < n)
- break; /* packet doesn't fit */
- }
- /*
- * If there are characters left in the mbuf,
- * the first one must be special.
- * Put it out in a different form.
- */
- if (len) {
- s = spltty();
- if (putc(PPP_ESCAPE, &tp->t_outq)) {
- splx(s);
- break;
- }
- if (putc(*start ^ PPP_TRANS, &tp->t_outq)) {
- (void) unputc(&tp->t_outq);
- splx(s);
- break;
- }
- splx(s);
- sc->sc_stats.ppp_obytes += 2;
- start++;
- len--;
- }
- }
-
- /*
- * If we didn't empty this mbuf, remember where we're up to.
- * If we emptied the last mbuf, try to add the FCS and closing
- * flag, and if we can't, leave sc_outm pointing to m, but with
- * m->m_len == 0, to remind us to output the FCS and flag later.
- */
- done = len == 0;
- if (done && m->m_next == NULL) {
- u_char *p, *q;
- int c;
- u_char endseq[8];
-
- /*
- * We may have to escape the bytes in the FCS.
- */
- p = endseq;
- c = ~sc->sc_outfcs & 0xFF;
- if (ESCAPE_P(c)) {
- *p++ = PPP_ESCAPE;
- *p++ = c ^ PPP_TRANS;
- } else
- *p++ = c;
- c = (~sc->sc_outfcs >> 8) & 0xFF;
- if (ESCAPE_P(c)) {
- *p++ = PPP_ESCAPE;
- *p++ = c ^ PPP_TRANS;
- } else
- *p++ = c;
- *p++ = PPP_FLAG;
-
- /*
- * Try to output the FCS and flag. If the bytes
- * don't all fit, back out.
- */
- s = spltty();
- for (q = endseq; q < p; ++q)
- if (putc(*q, &tp->t_outq)) {
- done = 0;
- for (; q > endseq; --q)
- unputc(&tp->t_outq);
- break;
- }
- splx(s);
- if (done)
- sc->sc_stats.ppp_obytes += q - endseq;
- }
-
- if (!done) {
- /* remember where we got to */
- m->m_data = start;
- m->m_len = len;
- break;
- }
-
- /* Finished with this mbuf; free it and move on. */
- m = m_free(m);
- if (m == NULL) {
- /* Finished a packet */
- break;
- }
- sc->sc_outfcs = pppfcs(sc->sc_outfcs, mtod(m, u_char *), m->m_len);
- }
-
- /*
- * If m == NULL, we have finished a packet.
- * If m != NULL, we've either done as much work this time
- * as we need to, or else we've filled up the output queue.
- */
- sc->sc_outm = m;
- if (m)
- break;
- }
-
- /* Call pppstart to start output again if necessary. */
- s = spltty();
- pppstart(tp);
-
- /*
- * This timeout is needed for operation on a pseudo-tty,
- * because the pty code doesn't call pppstart after it has
- * drained the t_outq.
- */
- if (!idle && (sc->sc_flags & SC_TIMEOUT) == 0) {
- callout_reset(&sc->sc_timo_ch, 1, ppp_timeout, sc);
- sc->sc_flags |= SC_TIMEOUT;
- }
-
- splx(s);
-}
-
-/*
- * This gets called when a received packet is placed on
- * the inq, at splsoftnet. The pppd daemon is to be woken up to do a read().
- */
-static void
-pppasyncctlp(sc)
- struct ppp_softc *sc;
-{
- struct tty *tp;
- int s;
-
- /* Put a placeholder byte in canq for ttselect()/ttnread(). */
- s = spltty();
- tp = (struct tty *) sc->sc_devp;
- putc(0, &tp->t_canq);
- ttwakeup(tp);
- splx(s);
-}
-
-/*
- * Start output on async tty interface. If the transmit queue
- * has drained sufficiently, arrange for pppasyncstart to be
- * called later at splsoftnet.
- * Called at spltty or higher.
- */
-static int
-pppstart(tp)
- register struct tty *tp;
-{
- register struct ppp_softc *sc = (struct ppp_softc *)tp->t_lsc;
-
- /*
- * Call output process whether or not there is any output.
- * We are being called in lieu of ttstart and must do what it would.
- */
- tt_oproc(tp);
-
- /*
- * If the transmit queue has drained and the tty has not hung up
- * or been disconnected from the ppp unit, then tell if_ppp.c that
- * we need more output.
- */
- if (CCOUNT(&tp->t_outq) < PPP_LOWAT
- && !((tp->t_state & TS_CONNECTED) == 0)
- && sc != NULL) {
- ppp_restart(sc);
- }
-
- return 0;
-}
-
-/*
- * Timeout routine - try to start some more output.
- */
-static void
-ppp_timeout(x)
- void *x;
-{
- struct ppp_softc *sc = (struct ppp_softc *) x;
- struct tty *tp = (struct tty *) sc->sc_devp;
- int s;
-
- s = spltty();
- sc->sc_flags &= ~SC_TIMEOUT;
- pppstart(tp);
- splx(s);
-}
-
-/*
- * Allocate enough mbuf to handle current MRU.
- */
-static void
-pppgetm(sc)
- register struct ppp_softc *sc;
-{
- struct mbuf *m, **mp;
- int len;
-
- mp = &sc->sc_m;
- for (len = sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN; len > 0; ){
- if ((m = *mp) == NULL) {
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- break;
- *mp = m;
- MCLGET(m, M_DONTWAIT);
- }
- len -= M_DATASIZE(m);
- mp = &m->m_next;
- }
-}
-
-/*
- * tty interface receiver interrupt.
- */
-static unsigned paritytab[8] = {
- 0x96696996, 0x69969669, 0x69969669, 0x96696996,
- 0x69969669, 0x96696996, 0x96696996, 0x69969669
-};
-
-/*
- * Called when character is available from device driver.
- * Only guaranteed to be at splsofttty() or spltty()
- * This is safe to be called while the upper half's netisr is preempted.
- */
-static int
-pppinput(c, tp)
- int c;
- register struct tty *tp;
-{
- register struct ppp_softc *sc;
- struct mbuf *m;
- int ilen, s;
-
- sc = (struct ppp_softc *)tp->t_lsc;
- if (sc == NULL)
- return 0;
-
- ++tk_nin;
- ++sc->sc_stats.ppp_ibytes;
-
- if ((tp->t_state & TS_CONNECTED) == 0) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "no carrier\n");
- goto flush;
- }
-
- if (c & TTY_ERRORMASK) {
- /* framing error or overrun on this char - abort packet */
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "line error %x\n", c & TTY_ERRORMASK);
- goto flush;
- }
-
- c &= TTY_CHARMASK;
-
- /*
- * Handle software flow control of output.
- */
- if (tp->t_iflag & IXON) {
- if (c == tp->t_cc[VSTOP] && tp->t_cc[VSTOP] != _POSIX_VDISABLE) {
- if ((tp->t_state & TS_TTSTOP) == 0) {
- tp->t_state |= TS_TTSTOP;
- tt_stop(tp, 0);
- }
- return 0;
- }
- if (c == tp->t_cc[VSTART] && tp->t_cc[VSTART] != _POSIX_VDISABLE) {
- tp->t_state &= ~TS_TTSTOP;
- tt_oproc(tp);
- return 0;
- }
- }
-
- s = spltty();
- if (c & 0x80)
- sc->sc_flags |= SC_RCV_B7_1;
- else
- sc->sc_flags |= SC_RCV_B7_0;
- if (paritytab[c >> 5] & (1 << (c & 0x1F)))
- sc->sc_flags |= SC_RCV_ODDP;
- else
- sc->sc_flags |= SC_RCV_EVNP;
- splx(s);
-
- if (sc->sc_flags & SC_LOG_RAWIN)
- ppplogchar(sc, c);
-
- if (c == PPP_FLAG) {
- ilen = sc->sc_ilen;
- sc->sc_ilen = 0;
-
- if (sc->sc_rawin_count > 0)
- ppplogchar(sc, -1);
-
- /*
- * If SC_ESCAPED is set, then we've seen the packet
- * abort sequence "}~".
- */
- if (sc->sc_flags & (SC_FLUSH | SC_ESCAPED)
- || (ilen > 0 && sc->sc_fcs != PPP_GOODFCS)) {
- s = spltty();
- sc->sc_flags |= SC_PKTLOST; /* note the dropped packet */
- if ((sc->sc_flags & (SC_FLUSH | SC_ESCAPED)) == 0){
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "bad fcs %x, pkt len %d\n",
- sc->sc_fcs, ilen);
- PPP2IFP(sc)->if_ierrors++;
- sc->sc_stats.ppp_ierrors++;
- } else
- sc->sc_flags &= ~(SC_FLUSH | SC_ESCAPED);
- splx(s);
- return 0;
- }
-
- if (ilen < PPP_HDRLEN + PPP_FCSLEN) {
- if (ilen) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "too short (%d)\n", ilen);
- s = spltty();
- PPP2IFP(sc)->if_ierrors++;
- sc->sc_stats.ppp_ierrors++;
- sc->sc_flags |= SC_PKTLOST;
- splx(s);
- }
- return 0;
- }
-
- /*
- * Remove FCS trailer. Somewhat painful...
- */
- ilen -= 2;
- if (--sc->sc_mc->m_len == 0) {
- for (m = sc->sc_m; m->m_next != sc->sc_mc; m = m->m_next)
- ;
- sc->sc_mc = m;
- }
- sc->sc_mc->m_len--;
-
- /* excise this mbuf chain */
- m = sc->sc_m;
- sc->sc_m = sc->sc_mc->m_next;
- sc->sc_mc->m_next = NULL;
-
- ppppktin(sc, m, sc->sc_flags & SC_PKTLOST);
- if (sc->sc_flags & SC_PKTLOST) {
- s = spltty();
- sc->sc_flags &= ~SC_PKTLOST;
- splx(s);
- }
-
- pppgetm(sc);
- return 0;
- }
-
- if (sc->sc_flags & SC_FLUSH) {
- if (sc->sc_flags & SC_LOG_FLUSH)
- ppplogchar(sc, c);
- return 0;
- }
-
- if (c < 0x20 && (sc->sc_rasyncmap & (1 << c)))
- return 0;
-
- s = spltty();
- if (sc->sc_flags & SC_ESCAPED) {
- sc->sc_flags &= ~SC_ESCAPED;
- c ^= PPP_TRANS;
- } else if (c == PPP_ESCAPE) {
- sc->sc_flags |= SC_ESCAPED;
- splx(s);
- return 0;
- }
- splx(s);
-
- /*
- * Initialize buffer on first octet received.
- * First octet could be address or protocol (when compressing
- * address/control).
- * Second octet is control.
- * Third octet is first or second (when compressing protocol)
- * octet of protocol.
- * Fourth octet is second octet of protocol.
- */
- if (sc->sc_ilen == 0) {
- /* reset the first input mbuf */
- if (sc->sc_m == NULL) {
- pppgetm(sc);
- if (sc->sc_m == NULL) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "no input mbufs!\n");
- goto flush;
- }
- }
- m = sc->sc_m;
- m->m_len = 0;
- m->m_data = M_DATASTART(sc->sc_m);
- sc->sc_mc = m;
- sc->sc_mp = mtod(m, char *);
- sc->sc_fcs = PPP_INITFCS;
- if (c != PPP_ALLSTATIONS) {
- if (sc->sc_flags & SC_REJ_COMP_AC) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc),
- "garbage received: 0x%x (need 0xFF)\n", c);
- goto flush;
- }
- *sc->sc_mp++ = PPP_ALLSTATIONS;
- *sc->sc_mp++ = PPP_UI;
- sc->sc_ilen += 2;
- m->m_len += 2;
- }
- }
- if (sc->sc_ilen == 1 && c != PPP_UI) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "missing UI (0x3), got 0x%x\n", c);
- goto flush;
- }
- if (sc->sc_ilen == 2 && (c & 1) == 1) {
- /* a compressed protocol */
- *sc->sc_mp++ = 0;
- sc->sc_ilen++;
- sc->sc_mc->m_len++;
- }
- if (sc->sc_ilen == 3 && (c & 1) == 0) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "bad protocol %x\n",
- (sc->sc_mp[-1] << 8) + c);
- goto flush;
- }
-
- /* packet beyond configured mru? */
- if (++sc->sc_ilen > sc->sc_mru + PPP_HDRLEN + PPP_FCSLEN) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "packet too big\n");
- goto flush;
- }
-
- /* is this mbuf full? */
- m = sc->sc_mc;
- if (M_TRAILINGSPACE(m) <= 0) {
- if (m->m_next == NULL) {
- pppgetm(sc);
- if (m->m_next == NULL) {
- if (sc->sc_flags & SC_DEBUG)
- if_printf(PPP2IFP(sc), "too few input mbufs!\n");
- goto flush;
- }
- }
- sc->sc_mc = m = m->m_next;
- m->m_len = 0;
- m->m_data = M_DATASTART(m);
- sc->sc_mp = mtod(m, char *);
- }
-
- ++m->m_len;
- *sc->sc_mp++ = c;
- sc->sc_fcs = PPP_FCS(sc->sc_fcs, c);
- return 0;
-
- flush:
- if (!(sc->sc_flags & SC_FLUSH)) {
- s = spltty();
- PPP2IFP(sc)->if_ierrors++;
- sc->sc_stats.ppp_ierrors++;
- sc->sc_flags |= SC_FLUSH;
- splx(s);
- if (sc->sc_flags & SC_LOG_FLUSH)
- ppplogchar(sc, c);
- }
- return 0;
-}
-
-#define MAX_DUMP_BYTES 128
-
-static void
-ppplogchar(sc, c)
- struct ppp_softc *sc;
- int c;
-{
- if (c >= 0)
- sc->sc_rawin[sc->sc_rawin_count++] = c;
- if (sc->sc_rawin_count >= sizeof(sc->sc_rawin)
- || (c < 0 && sc->sc_rawin_count > 0)) {
- printf("%s input: %*D", PPP2IFP(sc)->if_xname,
- sc->sc_rawin_count, sc->sc_rawin, " ");
- sc->sc_rawin_count = 0;
- }
-}
diff --git a/sys/net/route.c b/sys/net/route.c
index e06c059..f1e13ad 100644
--- a/sys/net/route.c
+++ b/sys/net/route.c
@@ -106,6 +106,15 @@ static int rttrash; /* routes not in table but not freed */
static void rt_maskedcopy(struct sockaddr *,
struct sockaddr *, struct sockaddr *);
+static int vnet_route_iattach(const void *);
+
+#ifndef VIMAGE_GLOBALS
+static const vnet_modinfo_t vnet_rtable_modinfo = {
+ .vmi_id = VNET_MOD_RTABLE,
+ .vmi_name = "rtable",
+ .vmi_iattach = vnet_route_iattach
+};
+#endif /* !VIMAGE_GLOBALS */
/* compare two sockaddr structures */
#define sa_equal(a1, a2) (bcmp((a1), (a2), (a1)->sa_len) == 0)
@@ -122,7 +131,9 @@ static void rt_maskedcopy(struct sockaddr *,
*/
#define RNTORT(p) ((struct rtentry *)(p))
+#ifdef VIMAGE_GLOBALS
static uma_zone_t rtzone; /* Routing table UMA zone. */
+#endif
#if 0
/* default fib for tunnels to use */
@@ -150,20 +161,30 @@ SYSCTL_PROC(_net, OID_AUTO, my_fibnum, CTLTYPE_INT|CTLFLAG_RD,
static void
route_init(void)
{
- INIT_VNET_INET(curvnet);
- int table;
- struct domain *dom;
- int fam;
/* whack the tunable ints into line. */
if (rt_numfibs > RT_MAXFIBS)
rt_numfibs = RT_MAXFIBS;
if (rt_numfibs == 0)
rt_numfibs = 1;
- rtzone = uma_zcreate("rtentry", sizeof(struct rtentry), NULL, NULL,
- NULL, NULL, UMA_ALIGN_PTR, 0);
rn_init(); /* initialize all zeroes, all ones, mask table */
+#ifndef VIMAGE_GLOBALS
+ vnet_mod_register(&vnet_rtable_modinfo);
+#else
+ vnet_route_iattach(NULL);
+#endif
+}
+
+static int vnet_route_iattach(const void *unused __unused)
+{
+ INIT_VNET_INET(curvnet);
+ int table;
+ struct domain *dom;
+ int fam;
+
+ V_rtzone = uma_zcreate("rtentry", sizeof(struct rtentry), NULL, NULL,
+ NULL, NULL, UMA_ALIGN_PTR, 0);
for (dom = domains; dom; dom = dom->dom_next) {
if (dom->dom_rtattach) {
for (table = 0; table < rt_numfibs; table++) {
@@ -186,6 +207,8 @@ route_init(void)
}
}
}
+
+ return (0);
}
#ifndef _SYS_SYSPROTO_H_
@@ -402,7 +425,7 @@ rtfree(struct rtentry *rt)
* and the rtentry itself of course
*/
RT_LOCK_DESTROY(rt);
- uma_zfree(rtzone, rt);
+ uma_zfree(V_rtzone, rt);
return;
}
done:
@@ -958,7 +981,7 @@ deldone:
if (info->rti_ifa == NULL && (error = rt_getifa_fib(info, fibnum)))
senderr(error);
ifa = info->rti_ifa;
- rt = uma_zalloc(rtzone, M_NOWAIT | M_ZERO);
+ rt = uma_zalloc(V_rtzone, M_NOWAIT | M_ZERO);
if (rt == NULL)
senderr(ENOBUFS);
RT_LOCK_INIT(rt);
@@ -971,7 +994,7 @@ deldone:
RT_LOCK(rt);
if ((error = rt_setgate(rt, dst, gateway)) != 0) {
RT_LOCK_DESTROY(rt);
- uma_zfree(rtzone, rt);
+ uma_zfree(V_rtzone, rt);
senderr(error);
}
@@ -1006,7 +1029,7 @@ deldone:
}
Free(rt_key(rt));
RT_LOCK_DESTROY(rt);
- uma_zfree(rtzone, rt);
+ uma_zfree(V_rtzone, rt);
senderr(EEXIST);
}
#endif
@@ -1022,7 +1045,7 @@ deldone:
IFAFREE(rt->rt_ifa);
Free(rt_key(rt));
RT_LOCK_DESTROY(rt);
- uma_zfree(rtzone, rt);
+ uma_zfree(V_rtzone, rt);
senderr(EEXIST);
}
diff --git a/sys/net/vnet.h b/sys/net/vnet.h
index 9354610..0b3ef8e 100644
--- a/sys/net/vnet.h
+++ b/sys/net/vnet.h
@@ -47,6 +47,7 @@ struct vnet_net {
struct rtstat _rtstat;
struct radix_node_head *_rt_tables[RT_MAXFIBS][AF_MAX+1];
int _rttrash;
+ uma_zone_t _rtzone;
struct ifnet *_loif;
LIST_HEAD(, lo_softc) _lo_list;
@@ -86,5 +87,6 @@ extern struct vnet_net vnet_net_0;
#define V_rt_tables VNET_NET(rt_tables)
#define V_rtstat VNET_NET(rtstat)
#define V_rttrash VNET_NET(rttrash)
+#define V_rtzone VNET_NET(rtzone)
#endif /* !_NET_VNET_H_ */
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
index 217f04d..bd3c1ae 100644
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -46,6 +46,9 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
#include <net/bpf.h>
@@ -183,6 +186,7 @@ ieee80211_chan_init(struct ieee80211com *ic)
ic->ic_csa_newchan = NULL;
/* arbitrarily pick the first channel */
ic->ic_curchan = &ic->ic_channels[0];
+ ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan);
/* fillin well-known rate sets if driver has not specified */
DEFAULTRATES(IEEE80211_MODE_11B, ieee80211_rateset_11b);
@@ -236,7 +240,8 @@ null_input(struct ifnet *ifp, struct mbuf *m)
* the driver on attach to prior to creating any vap's.
*/
void
-ieee80211_ifattach(struct ieee80211com *ic)
+ieee80211_ifattach(struct ieee80211com *ic,
+ const uint8_t macaddr[IEEE80211_ADDR_LEN])
{
struct ifnet *ifp = ic->ic_ifp;
struct sockaddr_dl *sdl;
@@ -264,6 +269,9 @@ ieee80211_ifattach(struct ieee80211com *ic)
ieee80211_node_attach(ic);
ieee80211_power_attach(ic);
ieee80211_proto_attach(ic);
+#ifdef IEEE80211_SUPPORT_SUPERG
+ ieee80211_superg_attach(ic);
+#endif
ieee80211_ht_attach(ic);
ieee80211_scan_attach(ic);
ieee80211_regdomain_attach(ic);
@@ -284,7 +292,7 @@ ieee80211_ifattach(struct ieee80211com *ic)
sdl = (struct sockaddr_dl *)ifa->ifa_addr;
sdl->sdl_type = IFT_ETHER; /* XXX IFT_IEEE80211? */
sdl->sdl_alen = IEEE80211_ADDR_LEN;
- IEEE80211_ADDR_COPY(LLADDR(sdl), ic->ic_myaddr);
+ IEEE80211_ADDR_COPY(LLADDR(sdl), macaddr);
}
/*
@@ -306,6 +314,9 @@ ieee80211_ifdetach(struct ieee80211com *ic)
ieee80211_sysctl_detach(ic);
ieee80211_regdomain_detach(ic);
ieee80211_scan_detach(ic);
+#ifdef IEEE80211_SUPPORT_SUPERG
+ ieee80211_superg_detach(ic);
+#endif
ieee80211_ht_detach(ic);
/* NB: must be called before ieee80211_node_detach */
ieee80211_proto_detach(ic);
@@ -415,10 +426,6 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
vap->iv_flags |= IEEE80211_F_WME;
if (vap->iv_caps & IEEE80211_C_BURST)
vap->iv_flags |= IEEE80211_F_BURST;
- if (vap->iv_caps & IEEE80211_C_FF)
- vap->iv_flags |= IEEE80211_F_FF;
- if (vap->iv_caps & IEEE80211_C_TURBOP)
- vap->iv_flags |= IEEE80211_F_TURBOP;
/* NB: bg scanning only makes sense for station mode right now */
if (vap->iv_opmode == IEEE80211_M_STA &&
(vap->iv_caps & IEEE80211_C_BGSCAN))
@@ -445,6 +452,9 @@ ieee80211_vap_setup(struct ieee80211com *ic, struct ieee80211vap *vap,
ieee80211_node_vattach(vap);
ieee80211_power_vattach(vap);
ieee80211_proto_vattach(vap);
+#ifdef IEEE80211_SUPPORT_SUPERG
+ ieee80211_superg_vattach(vap);
+#endif
ieee80211_ht_vattach(vap);
ieee80211_scan_vattach(vap);
ieee80211_regdomain_vattach(vap);
@@ -497,7 +507,9 @@ ieee80211_vap_attach(struct ieee80211vap *vap,
IEEE80211_LOCK(ic);
TAILQ_INSERT_TAIL(&ic->ic_vaps, vap, iv_next);
ieee80211_syncflag_locked(ic, IEEE80211_F_WME);
+#ifdef IEEE80211_SUPPORT_SUPERG
ieee80211_syncflag_locked(ic, IEEE80211_F_TURBOP);
+#endif
ieee80211_syncflag_locked(ic, IEEE80211_F_PCF);
ieee80211_syncflag_locked(ic, IEEE80211_F_BURST);
ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_HT);
@@ -545,7 +557,9 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next);
ieee80211_syncflag_locked(ic, IEEE80211_F_WME);
+#ifdef IEEE80211_SUPPORT_SUPERG
ieee80211_syncflag_locked(ic, IEEE80211_F_TURBOP);
+#endif
ieee80211_syncflag_locked(ic, IEEE80211_F_PCF);
ieee80211_syncflag_locked(ic, IEEE80211_F_BURST);
ieee80211_syncflag_ext_locked(ic, IEEE80211_FEXT_HT);
@@ -562,6 +576,9 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
ieee80211_regdomain_vdetach(vap);
ieee80211_scan_vdetach(vap);
+#ifdef IEEE80211_SUPPORT_SUPERG
+ ieee80211_superg_vdetach(vap);
+#endif
ieee80211_ht_vdetach(vap);
/* NB: must be before ieee80211_node_vdetach */
ieee80211_proto_vdetach(vap);
diff --git a/sys/net80211/ieee80211.h b/sys/net80211/ieee80211.h
index fb63507..226fb05 100644
--- a/sys/net80211/ieee80211.h
+++ b/sys/net80211/ieee80211.h
@@ -733,28 +733,6 @@ struct ieee80211_csa_ie {
uint8_t csa_count; /* Channel Switch Count */
} __packed;
-/*
- * Atheros advanced capability information element.
- */
-struct ieee80211_ath_ie {
- uint8_t ath_id; /* IEEE80211_ELEMID_VENDOR */
- uint8_t ath_len; /* length in bytes */
- uint8_t ath_oui[3]; /* 0x00, 0x03, 0x7f */
- uint8_t ath_oui_type; /* OUI type */
- uint8_t ath_oui_subtype; /* OUI subtype */
- uint8_t ath_version; /* spec revision */
- uint8_t ath_capability; /* capability info */
-#define ATHEROS_CAP_TURBO_PRIME 0x01 /* dynamic turbo--aka Turbo' */
-#define ATHEROS_CAP_COMPRESSION 0x02 /* data compression */
-#define ATHEROS_CAP_FAST_FRAME 0x04 /* fast (jumbo) frames */
-#define ATHEROS_CAP_XR 0x08 /* Xtended Range support */
-#define ATHEROS_CAP_AR 0x10 /* Advanded Radar support */
-#define ATHEROS_CAP_BURST 0x20 /* Bursting - not negotiated */
-#define ATHEROS_CAP_WME 0x40 /* CWMin tuning */
-#define ATHEROS_CAP_BOOST 0x80 /* use turbo/!turbo mode */
- uint8_t ath_defkeyix[2];
-} __packed;
-
/* rate set entries are in .5 Mb/s units, and potentially marked as basic */
#define IEEE80211_RATE_BASIC 0x80
#define IEEE80211_RATE_VAL 0x7f
@@ -768,9 +746,11 @@ struct ieee80211_ath_ie {
"\20\1NON_ERP_PRESENT\2USE_PROTECTION\3LONG_PREAMBLE"
#define ATH_OUI 0x7f0300 /* Atheros OUI */
-#define ATH_OUI_TYPE 0x01
-#define ATH_OUI_SUBTYPE 0x01
-#define ATH_OUI_VERSION 0x00
+#define ATH_OUI_TYPE 0x01 /* Atheros protocol ie */
+
+/* NB: Atheros allocated the OUI for this purpose ~2005 but beware ... */
+#define TDMA_OUI ATH_OUI
+#define TDMA_OUI_TYPE 0x02 /* TDMA protocol ie */
#define BCM_OUI 0x4c9000 /* Broadcom OUI */
#define BCM_OUI_HTCAP 51 /* pre-draft HTCAP ie */
@@ -1048,55 +1028,4 @@ struct ieee80211_duration {
IEEE80211_DUR_DS_SLOW_PLCPHDR + \
IEEE80211_DUR_DIFS)
-/*
- * Atheros fast-frame encapsulation format.
- * FF max payload:
- * 802.2 + FFHDR + HPAD + 802.3 + 802.2 + 1500 + SPAD + 802.3 + 802.2 + 1500:
- * 8 + 4 + 4 + 14 + 8 + 1500 + 6 + 14 + 8 + 1500
- * = 3066
- */
-/* fast frame header is 32-bits */
-#define ATH_FF_PROTO 0x0000003f /* protocol */
-#define ATH_FF_PROTO_S 0
-#define ATH_FF_FTYPE 0x000000c0 /* frame type */
-#define ATH_FF_FTYPE_S 6
-#define ATH_FF_HLEN32 0x00000300 /* optional hdr length */
-#define ATH_FF_HLEN32_S 8
-#define ATH_FF_SEQNUM 0x001ffc00 /* sequence number */
-#define ATH_FF_SEQNUM_S 10
-#define ATH_FF_OFFSET 0xffe00000 /* offset to 2nd payload */
-#define ATH_FF_OFFSET_S 21
-
-#define ATH_FF_MAX_HDR_PAD 4
-#define ATH_FF_MAX_SEP_PAD 6
-#define ATH_FF_MAX_HDR 30
-
-#define ATH_FF_PROTO_L2TUNNEL 0 /* L2 tunnel protocol */
-#define ATH_FF_ETH_TYPE 0x88bd /* Ether type for encapsulated frames */
-#define ATH_FF_SNAP_ORGCODE_0 0x00
-#define ATH_FF_SNAP_ORGCODE_1 0x03
-#define ATH_FF_SNAP_ORGCODE_2 0x7f
-
-struct ieee80211_tdma_param {
- u_int8_t tdma_id; /* IEEE80211_ELEMID_VENDOR */
- u_int8_t tdma_len;
- u_int8_t tdma_oui[3]; /* 0x00, 0x03, 0x7f */
- u_int8_t tdma_type; /* OUI type */
- u_int8_t tdma_subtype; /* OUI subtype */
- u_int8_t tdma_version; /* spec revision */
- u_int8_t tdma_slot; /* station slot # */
- u_int8_t tdma_slotcnt; /* bss slot count */
- u_int16_t tdma_slotlen; /* bss slot len (100us) */
- u_int8_t tdma_bintval; /* beacon interval (superframes) */
- u_int8_t tdma_inuse[1]; /* slot occupancy map */
- u_int8_t tdma_pad[2];
- u_int8_t tdma_tstamp[8]; /* timestamp from last beacon */
-} __packed;
-
-/* NB: Atheros allocated the OUI for this purpose ~3 years ago but beware ... */
-#define TDMA_OUI ATH_OUI
-#define TDMA_OUI_TYPE 0x02
-#define TDMA_SUBTYPE_PARAM 0x01
-#define TDMA_VERSION 2
-
#endif /* _NET80211_IEEE80211_H_ */
diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c
index e72aef1..445b1bb 100644
--- a/sys/net80211/ieee80211_adhoc.c
+++ b/sys/net80211/ieee80211_adhoc.c
@@ -57,6 +57,9 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_adhoc.h>
#include <net80211/ieee80211_input.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
#ifdef IEEE80211_SUPPORT_TDMA
#include <net80211/ieee80211_tdma.h>
#endif
@@ -590,32 +593,13 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
m = ieee80211_decap_amsdu(ni, m);
if (m == NULL)
return IEEE80211_FC0_TYPE_DATA;
- } else if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF) &&
-#define FF_LLC_SIZE (sizeof(struct ether_header) + sizeof(struct llc))
- m->m_pkthdr.len >= 3*FF_LLC_SIZE) {
- struct llc *llc;
-
- /*
- * Check for fast-frame tunnel encapsulation.
- */
- if (m->m_len < FF_LLC_SIZE &&
- (m = m_pullup(m, FF_LLC_SIZE)) == NULL) {
- IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
- ni->ni_macaddr, "fast-frame",
- "%s", "m_pullup(llc) failed");
- vap->iv_stats.is_rx_tooshort++;
+ } else {
+#ifdef IEEE80211_SUPPORT_SUPERG
+ m = ieee80211_decap_fastframe(vap, ni, m);
+ if (m == NULL)
return IEEE80211_FC0_TYPE_DATA;
- }
- llc = (struct llc *)(mtod(m, uint8_t *) +
- sizeof(struct ether_header));
- if (llc->llc_snap.ether_type == htons(ATH_FF_ETH_TYPE)) {
- m_adj(m, FF_LLC_SIZE);
- m = ieee80211_decap_fastframe(ni, m);
- if (m == NULL)
- return IEEE80211_FC0_TYPE_DATA;
- }
+#endif
}
-#undef FF_LLC_SIZE
if (dir == IEEE80211_FC1_DIR_DSTODS && ni->ni_wdsvap != NULL)
ieee80211_deliver_data(ni->ni_wdsvap, ni, m);
else
diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c
index 09ea89c..0dd27b1 100644
--- a/sys/net80211/ieee80211_ddb.c
+++ b/sys/net80211/ieee80211_ddb.c
@@ -445,7 +445,6 @@ _db_show_com(const struct ieee80211com *ic, int showvaps, int showsta, int showp
db_printf(" opmode %s", ieee80211_opmode_name[ic->ic_opmode]);
db_printf("\n");
db_printf("\tmedia %p", &ic->ic_media);
- db_printf(" myaddr %s", ether_sprintf(ic->ic_myaddr));
db_printf(" inact %p", &ic->ic_inact);
db_printf("\n");
diff --git a/sys/net80211/ieee80211_freebsd.c b/sys/net80211/ieee80211_freebsd.c
index 5f44f1c..8d38614 100644
--- a/sys/net80211/ieee80211_freebsd.c
+++ b/sys/net80211/ieee80211_freebsd.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/if_clone.h>
#include <net/if_media.h>
#include <net/if_types.h>
@@ -137,7 +138,7 @@ wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
vap = ic->ic_vap_create(ic, ifc->ifc_name, unit,
cp.icp_opmode, cp.icp_flags, cp.icp_bssid,
cp.icp_flags & IEEE80211_CLONE_MACADDR ?
- cp.icp_macaddr : ic->ic_myaddr);
+ cp.icp_macaddr : (const uint8_t *)IF_LLADDR(ifp));
return (vap == NULL ? EIO : 0);
}
@@ -188,6 +189,15 @@ SYSCTL_PROC(_net_wlan, OID_AUTO, addba_backoff, CTLFLAG_RW,
extern int ieee80211_addba_maxtries;
SYSCTL_INT(_net_wlan, OID_AUTO, addba_maxtries, CTLFLAG_RW,
&ieee80211_addba_maxtries, 0, "max ADDBA requests sent before backoff");
+#ifdef IEEE80211_SUPPORT_SUPERG
+extern int ieee80211_ffppsmin;
+SYSCTL_INT(_net_wlan, OID_AUTO, ffppsmin, CTLFLAG_RW,
+ &ieee80211_ffppsmin, 0, "min packet rate before fast-frame staging");
+extern int ieee80211_ffagemax;
+SYSCTL_PROC(_net_wlan, OID_AUTO, ffagemax, CTLFLAG_RW,
+ &ieee80211_ffagemax, 0, ieee80211_sysctl_msecs_ticks, "I",
+ "max hold time for fast-frame staging (ms)");
+#endif /* IEEE80211_SUPPORT_SUPERG */
static int
ieee80211_sysctl_inact(SYSCTL_HANDLER_ARGS)
diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h
index 519e37d..db6648d 100644
--- a/sys/net80211/ieee80211_freebsd.h
+++ b/sys/net80211/ieee80211_freebsd.h
@@ -211,7 +211,6 @@ struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen);
/* tx path usage */
#define M_ENCAP M_PROTO1 /* 802.11 encap done */
-#define M_WDS M_PROTO2 /* WDS frame */
#define M_EAPOL M_PROTO3 /* PAE/EAPOL frame */
#define M_PWR_SAV M_PROTO4 /* bypass PS handling */
#define M_MORE_DATA M_PROTO5 /* more data frames to follow */
@@ -219,7 +218,7 @@ struct mbuf *ieee80211_getmgtframe(uint8_t **frm, int headroom, int pktlen);
#define M_TXCB M_PROTO7 /* do tx complete callback */
#define M_AMPDU_MPDU M_PROTO8 /* ok for A-MPDU aggregation */
#define M_80211_TX \
- (M_FRAG|M_FIRSTFRAG|M_LASTFRAG|M_ENCAP|M_WDS|M_EAPOL|M_PWR_SAV|\
+ (M_FRAG|M_FIRSTFRAG|M_LASTFRAG|M_ENCAP|M_EAPOL|M_PWR_SAV|\
M_MORE_DATA|M_FF|M_TXCB|M_AMPDU_MPDU)
/* rx path usage */
@@ -391,6 +390,17 @@ alg##_modevent(int type) \
/* XXX nothing to do until the rate control framework arrives */\
} \
TEXT_SET(rate##_set, alg##_modevent)
+
+struct ieee80211req;
+typedef int ieee80211_ioctl_getfunc(struct ieee80211vap *,
+ struct ieee80211req *);
+SET_DECLARE(ieee80211_ioctl_getset, ieee80211_ioctl_getfunc);
+#define IEEE80211_IOCTL_GET(_name, _get) TEXT_SET(ieee80211_ioctl_getset, _get)
+
+typedef int ieee80211_ioctl_setfunc(struct ieee80211vap *,
+ struct ieee80211req *);
+SET_DECLARE(ieee80211_ioctl_setset, ieee80211_ioctl_setfunc);
+#define IEEE80211_IOCTL_SET(_name, _set) TEXT_SET(ieee80211_ioctl_setset, _set)
#endif /* _KERNEL */
/* XXX this stuff belongs elsewhere */
diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c
index e0f831b..5b16a8d 100644
--- a/sys/net80211/ieee80211_hostap.c
+++ b/sys/net80211/ieee80211_hostap.c
@@ -57,6 +57,9 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_hostap.h>
#include <net80211/ieee80211_input.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
#include <net80211/ieee80211_wds.h>
#define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2)
@@ -752,32 +755,13 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
m = ieee80211_decap_amsdu(ni, m);
if (m == NULL)
return IEEE80211_FC0_TYPE_DATA;
- } else if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF) &&
-#define FF_LLC_SIZE (sizeof(struct ether_header) + sizeof(struct llc))
- m->m_pkthdr.len >= 3*FF_LLC_SIZE) {
- struct llc *llc;
-
- /*
- * Check for fast-frame tunnel encapsulation.
- */
- if (m->m_len < FF_LLC_SIZE &&
- (m = m_pullup(m, FF_LLC_SIZE)) == NULL) {
- IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
- ni->ni_macaddr, "fast-frame",
- "%s", "m_pullup(llc) failed");
- vap->iv_stats.is_rx_tooshort++;
+ } else {
+#ifdef IEEE80211_SUPPORT_SUPERG
+ m = ieee80211_decap_fastframe(vap, ni, m);
+ if (m == NULL)
return IEEE80211_FC0_TYPE_DATA;
- }
- llc = (struct llc *)(mtod(m, uint8_t *) +
- sizeof(struct ether_header));
- if (llc->llc_snap.ether_type == htons(ATH_FF_ETH_TYPE)) {
- m_adj(m, FF_LLC_SIZE);
- m = ieee80211_decap_fastframe(ni, m);
- if (m == NULL)
- return IEEE80211_FC0_TYPE_DATA;
- }
+#endif
}
-#undef FF_LLC_SIZE
if (dir == IEEE80211_FC1_DIR_DSTODS && ni->ni_wdsvap != NULL)
ieee80211_deliver_data(ni->ni_wdsvap, ni, m);
else
@@ -1967,8 +1951,10 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
wpa = frm;
else if (iswmeinfo(frm))
wme = frm;
+#ifdef IEEE80211_SUPPORT_SUPERG
else if (isatherosoui(frm))
ath = frm;
+#endif
else if (vap->iv_flags_ext & IEEE80211_FEXT_HTCOMPAT) {
if (ishtcapoui(frm) && htcap == NULL)
htcap = frm;
@@ -2052,6 +2038,10 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
ieee80211_ht_updatehtcap(ni, htcap);
} else if (ni->ni_flags & IEEE80211_NODE_HT)
ieee80211_ht_node_cleanup(ni);
+#ifdef IEEE80211_SUPPORT_SUPERG
+ else if (ni->ni_ath_flags & IEEE80211_NODE_ATH)
+ ieee80211_ff_node_cleanup(ni);
+#endif
/*
* Allow AMPDU operation only with unencrypted traffic
* or AES-CCM; the 11n spec only specifies these ciphers
@@ -2106,6 +2096,7 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
ni->ni_flags |= IEEE80211_NODE_QOS;
} else
ni->ni_flags &= ~IEEE80211_NODE_QOS;
+#ifdef IEEE80211_SUPPORT_SUPERG
if (ath != NULL) {
setie(ath_ie, ath - sfrm);
/*
@@ -2113,6 +2104,7 @@ hostap_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
*/
ieee80211_parse_ath(ni, ni->ni_ies.ath_ie);
} else
+#endif
ni->ni_ath_flags = 0;
#undef setie
} else {
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 23f770b..2134e29d 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -98,7 +98,7 @@ ieee80211_input_all(struct ieee80211com *ic,
}
/*
- * This function reassemble fragments.
+ * This function reassembles fragments.
*
* XXX should handle 3 concurrent reassemblies per-spec.
*/
@@ -358,73 +358,6 @@ ieee80211_decap1(struct mbuf *m, int *framelen)
}
/*
- * Decap the encapsulated frame pair and dispatch the first
- * for delivery. The second frame is returned for delivery
- * via the normal path.
- */
-struct mbuf *
-ieee80211_decap_fastframe(struct ieee80211_node *ni, struct mbuf *m)
-{
-#define MS(x,f) (((x) & f) >> f##_S)
- struct ieee80211vap *vap = ni->ni_vap;
- uint32_t ath;
- struct mbuf *n;
- int framelen;
-
- m_copydata(m, 0, sizeof(uint32_t), (caddr_t) &ath);
- if (MS(ath, ATH_FF_PROTO) != ATH_FF_PROTO_L2TUNNEL) {
- IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
- ni->ni_macaddr, "fast-frame",
- "unsupport tunnel protocol, header 0x%x", ath);
- vap->iv_stats.is_ff_badhdr++;
- m_freem(m);
- return NULL;
- }
- /* NB: skip header and alignment padding */
- m_adj(m, roundup(sizeof(uint32_t) - 2, 4) + 2);
-
- vap->iv_stats.is_ff_decap++;
-
- /*
- * Decap the first frame, bust it apart from the
- * second and deliver; then decap the second frame
- * and return it to the caller for normal delivery.
- */
- m = ieee80211_decap1(m, &framelen);
- if (m == NULL) {
- IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
- ni->ni_macaddr, "fast-frame", "%s", "first decap failed");
- vap->iv_stats.is_ff_tooshort++;
- return NULL;
- }
- n = m_split(m, framelen, M_NOWAIT);
- if (n == NULL) {
- IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
- ni->ni_macaddr, "fast-frame",
- "%s", "unable to split encapsulated frames");
- vap->iv_stats.is_ff_split++;
- m_freem(m); /* NB: must reclaim */
- return NULL;
- }
- /* XXX not right for WDS */
- vap->iv_deliver_data(vap, ni, m); /* 1st of pair */
-
- /*
- * Decap second frame.
- */
- m_adj(n, roundup2(framelen, 4) - framelen); /* padding */
- n = ieee80211_decap1(n, &framelen);
- if (n == NULL) {
- IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
- ni->ni_macaddr, "fast-frame", "%s", "second decap failed");
- vap->iv_stats.is_ff_tooshort++;
- }
- /* XXX verify framelen against mbuf contents */
- return n; /* 2nd delivered by caller */
-#undef MS
-}
-
-/*
* Install received rate set information in the node's state block.
*/
int
@@ -510,16 +443,6 @@ ieee80211_alloc_challenge(struct ieee80211_node *ni)
return (ni->ni_challenge != NULL);
}
-void
-ieee80211_parse_ath(struct ieee80211_node *ni, uint8_t *ie)
-{
- const struct ieee80211_ath_ie *ath =
- (const struct ieee80211_ath_ie *) ie;
-
- ni->ni_ath_flags = ath->ath_capability;
- ni->ni_ath_defkeyix = LE_READ_2(&ath->ath_defkeyix);
-}
-
/*
* Parse a Beacon or ProbeResponse frame and return the
* useful information in an ieee80211_scanparams structure.
@@ -633,8 +556,10 @@ ieee80211_parse_beacon(struct ieee80211_node *ni, struct mbuf *m,
scan->wpa = frm;
else if (iswmeparam(frm) || iswmeinfo(frm))
scan->wme = frm;
+#ifdef IEEE80211_SUPPORT_SUPERG
else if (isatherosoui(frm))
scan->ath = frm;
+#endif
#ifdef IEEE80211_SUPPORT_TDMA
else if (istdmaoui(frm))
scan->tdma = frm;
diff --git a/sys/net80211/ieee80211_input.h b/sys/net80211/ieee80211_input.h
index b656c55..f19b934 100644
--- a/sys/net80211/ieee80211_input.h
+++ b/sys/net80211/ieee80211_input.h
@@ -148,14 +148,11 @@ struct mbuf *ieee80211_defrag(struct ieee80211_node *,
struct mbuf *, int);
struct mbuf *ieee80211_decap(struct ieee80211vap *, struct mbuf *, int);
struct mbuf *ieee80211_decap1(struct mbuf *, int *);
-struct mbuf *ieee80211_decap_fastframe(struct ieee80211_node *,
- struct mbuf *);
int ieee80211_setup_rates(struct ieee80211_node *ni,
const uint8_t *rates, const uint8_t *xrates, int flags);
void ieee80211_send_error(struct ieee80211_node *,
const uint8_t mac[IEEE80211_ADDR_LEN], int subtype, int arg);
int ieee80211_alloc_challenge(struct ieee80211_node *);
-void ieee80211_parse_ath(struct ieee80211_node *, uint8_t *);
int ieee80211_parse_beacon(struct ieee80211_node *, struct mbuf *,
struct ieee80211_scanparams *);
int ieee80211_parse_action(struct ieee80211_node *, struct mbuf *);
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index 21d5637..c148214 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -63,9 +63,6 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_ioctl.h>
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_input.h>
-#ifdef IEEE80211_SUPPORT_TDMA
-#include <net80211/ieee80211_tdma.h>
-#endif
#define IS_UP_AUTO(_vap) \
(IFNET_IS_UP_RUNNING(vap->iv_ifp) && \
@@ -587,21 +584,6 @@ ieee80211_ioctl_getmaccmd(struct ieee80211vap *vap, struct ieee80211req *ireq)
return (acl == NULL ? EINVAL : acl->iac_getioctl(vap, ireq));
}
-/*
- * Return the current ``state'' of an Atheros capbility.
- * If associated in station mode report the negotiated
- * setting. Otherwise report the current setting.
- */
-static int
-getathcap(struct ieee80211vap *vap, int cap)
-{
- if (vap->iv_opmode == IEEE80211_M_STA &&
- vap->iv_state == IEEE80211_S_RUN)
- return IEEE80211_ATH_CAP(vap, vap->iv_bss, cap) != 0;
- else
- return (vap->iv_flags & cap) != 0;
-}
-
static __noinline int
ieee80211_ioctl_getcurchan(struct ieee80211vap *vap, struct ieee80211req *ireq)
{
@@ -752,6 +734,30 @@ ieee80211_ioctl_getstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
}
/*
+ * Dummy ioctl get handler so the linker set is defined.
+ */
+static int
+dummy_ioctl_get(struct ieee80211vap *vap, struct ieee80211req *ireq)
+{
+ return ENOSYS;
+}
+IEEE80211_IOCTL_GET(dummy, dummy_ioctl_get);
+
+static int
+ieee80211_ioctl_getdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
+{
+ ieee80211_ioctl_getfunc * const *get;
+ int error;
+
+ SET_FOREACH(get, ieee80211_ioctl_getset) {
+ error = (*get)(vap, ireq);
+ if (error != ENOSYS)
+ return error;
+ }
+ return EINVAL;
+}
+
+/*
* When building the kernel with -O2 on the i386 architecture, gcc
* seems to want to inline this function into ieee80211_ioctl()
* (which is the only routine that calls it). When this happens,
@@ -953,12 +959,6 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
case IEEE80211_IOC_PUREG:
ireq->i_val = (vap->iv_flags & IEEE80211_F_PUREG) != 0;
break;
- case IEEE80211_IOC_FF:
- ireq->i_val = getathcap(vap, IEEE80211_F_FF);
- break;
- case IEEE80211_IOC_TURBOP:
- ireq->i_val = getathcap(vap, IEEE80211_F_TURBOP);
- break;
case IEEE80211_IOC_BGSCAN:
ireq->i_val = (vap->iv_flags & IEEE80211_F_BGSCAN) != 0;
break;
@@ -1104,16 +1104,8 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
ireq->i_val =
(vap->iv_flags_ext & IEEE80211_FEXT_RIFS) != 0;
break;
-#ifdef IEEE80211_SUPPORT_TDMA
- case IEEE80211_IOC_TDMA_SLOT:
- case IEEE80211_IOC_TDMA_SLOTCNT:
- case IEEE80211_IOC_TDMA_SLOTLEN:
- case IEEE80211_IOC_TDMA_BINTERVAL:
- error = ieee80211_tdma_ioctl_get80211(vap, ireq);
- break;
-#endif
default:
- error = EINVAL;
+ error = ieee80211_ioctl_getdefault(vap, ireq);
break;
}
return error;
@@ -1879,6 +1871,7 @@ setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c)
vap->iv_bss->ni_chan = ic->ic_curchan;
} else
ic->ic_curchan = vap->iv_des_chan;
+ ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan);
} else {
/*
* Need to go through the state machine in case we
@@ -1894,6 +1887,7 @@ setcurchan(struct ieee80211vap *vap, struct ieee80211_channel *c)
* there is immediate feedback; e.g. via ifconfig.
*/
ic->ic_curchan = vap->iv_des_chan;
+ ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan);
}
}
return error;
@@ -2476,6 +2470,30 @@ isvapht(const struct ieee80211vap *vap)
IEEE80211_IS_CHAN_HT(bss->ni_chan);
}
+/*
+ * Dummy ioctl set handler so the linker set is defined.
+ */
+static int
+dummy_ioctl_set(struct ieee80211vap *vap, struct ieee80211req *ireq)
+{
+ return ENOSYS;
+}
+IEEE80211_IOCTL_SET(dummy, dummy_ioctl_set);
+
+static int
+ieee80211_ioctl_setdefault(struct ieee80211vap *vap, struct ieee80211req *ireq)
+{
+ ieee80211_ioctl_setfunc * const *set;
+ int error;
+
+ SET_FOREACH(set, ieee80211_ioctl_setset) {
+ error = (*set)(vap, ireq);
+ if (error != ENOSYS)
+ return error;
+ }
+ return EINVAL;
+}
+
static __noinline int
ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211req *ireq)
{
@@ -2852,24 +2870,6 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
if (isvap11g(vap))
error = ENETRESET;
break;
- case IEEE80211_IOC_FF:
- if (ireq->i_val) {
- if ((vap->iv_caps & IEEE80211_C_FF) == 0)
- return EOPNOTSUPP;
- vap->iv_flags |= IEEE80211_F_FF;
- } else
- vap->iv_flags &= ~IEEE80211_F_FF;
- error = ERESTART;
- break;
- case IEEE80211_IOC_TURBOP:
- if (ireq->i_val) {
- if ((vap->iv_caps & IEEE80211_C_TURBOP) == 0)
- return EOPNOTSUPP;
- vap->iv_flags |= IEEE80211_F_TURBOP;
- } else
- vap->iv_flags &= ~IEEE80211_F_TURBOP;
- error = ENETRESET;
- break;
case IEEE80211_IOC_BGSCAN:
if (ireq->i_val) {
if ((vap->iv_caps & IEEE80211_C_BGSCAN) == 0)
@@ -3131,16 +3131,8 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
if (isvapht(vap))
error = ERESTART;
break;
-#ifdef IEEE80211_SUPPORT_TDMA
- case IEEE80211_IOC_TDMA_SLOT:
- case IEEE80211_IOC_TDMA_SLOTCNT:
- case IEEE80211_IOC_TDMA_SLOTLEN:
- case IEEE80211_IOC_TDMA_BINTERVAL:
- error = ieee80211_tdma_ioctl_set80211(vap, ireq);
- break;
-#endif
default:
- error = EINVAL;
+ error = ieee80211_ioctl_setdefault(vap, ireq);
break;
}
/*
diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h
index 367f505..6a81375 100644
--- a/sys/net80211/ieee80211_ioctl.h
+++ b/sys/net80211/ieee80211_ioctl.h
@@ -217,7 +217,8 @@ struct ieee80211_stats {
uint8_t is_rx_authfail_code; /* last rx'd auth fail reason */
uint32_t is_beacon_miss; /* beacon miss notification */
uint32_t is_rx_badstate; /* rx discard state != RUN */
- uint32_t is_spare[12];
+ uint32_t is_ff_flush; /* ff's flush'd from stageq */
+ uint32_t is_spare[11];
};
/*
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 761c969..1632b19 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -43,6 +43,9 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_input.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
#ifdef IEEE80211_SUPPORT_TDMA
#include <net80211/ieee80211_tdma.h>
#endif
@@ -624,6 +627,7 @@ ieee80211_sync_curchan(struct ieee80211com *ic)
if (c != ic->ic_curchan) {
ic->ic_curchan = c;
ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
+ ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan);
ic->ic_set_channel(ic);
}
}
@@ -648,6 +652,7 @@ ieee80211_setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
}
ic->ic_bsschan = ic->ic_curchan = c;
ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
+ ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan);
ic->ic_set_channel(ic);
}
@@ -754,8 +759,10 @@ ieee80211_sta_join(struct ieee80211vap *vap, struct ieee80211_channel *chan,
if (ieee80211_ies_init(&ni->ni_ies, se->se_ies.data, se->se_ies.len)) {
ieee80211_ies_expand(&ni->ni_ies);
+#ifdef IEEE80211_SUPPORT_SUPERG
if (ni->ni_ies.ath_ie != NULL)
ieee80211_parse_ath(ni, ni->ni_ies.ath_ie);
+#endif
if (ni->ni_ies.htcap_ie != NULL)
ieee80211_parse_htcap(ni, ni->ni_ies.htcap_ie);
if (ni->ni_ies.htinfo_ie != NULL)
@@ -875,8 +882,10 @@ ieee80211_ies_expand(struct ieee80211_ies *ies)
ies->wpa_ie = ie;
else if (iswmeoui(ie))
ies->wme_ie = ie;
+#ifdef IEEE80211_SUPPORT_SUPERG
else if (isatherosoui(ie))
ies->ath_ie = ie;
+#endif
#ifdef IEEE80211_SUPPORT_TDMA
else if (istdmaoui(ie))
ies->tdma_ie = ie;
@@ -920,6 +929,10 @@ node_cleanup(struct ieee80211_node *ni)
*/
if (ni->ni_flags & IEEE80211_NODE_HT)
ieee80211_ht_node_cleanup(ni);
+#ifdef IEEE80211_SUPPORT_SUPERG
+ else if (ni->ni_ath_flags & IEEE80211_NODE_ATH)
+ ieee80211_ff_node_cleanup(ni);
+#endif
/*
* Clear AREF flag that marks the authorization refcnt bump
* has happened. This is probably not needed as the node
@@ -1173,8 +1186,10 @@ ieee80211_node_create_wds(struct ieee80211vap *vap,
*/
if (vap->iv_flags & IEEE80211_F_WME)
ni->ni_flags |= IEEE80211_NODE_QOS;
+#ifdef IEEE80211_SUPPORT_SUPERG
if (vap->iv_flags & IEEE80211_F_FF)
ni->ni_flags |= IEEE80211_NODE_FF;
+#endif
if ((ic->ic_htcaps & IEEE80211_HTC_HT) &&
(vap->iv_flags_ext & IEEE80211_FEXT_HT)) {
/*
@@ -1331,8 +1346,10 @@ ieee80211_fakeup_adhoc_node(struct ieee80211vap *vap,
*/
if (vap->iv_flags & IEEE80211_F_WME)
ni->ni_flags |= IEEE80211_NODE_QOS;
+#ifdef IEEE80211_SUPPORT_SUPERG
if (vap->iv_flags & IEEE80211_F_FF)
ni->ni_flags |= IEEE80211_NODE_FF;
+#endif
}
node_setuptxparms(ni);
if (ic->ic_newassoc != NULL)
@@ -1366,8 +1383,10 @@ ieee80211_init_neighbor(struct ieee80211_node *ni,
ni->ni_flags |= IEEE80211_NODE_QOS;
else
ni->ni_flags &= ~IEEE80211_NODE_QOS;
+#ifdef IEEE80211_SUPPORT_SUPERG
if (ni->ni_ies.ath_ie != NULL)
ieee80211_parse_ath(ni, ni->ni_ies.ath_ie);
+#endif
}
/* NB: must be after ni_chan is setup */
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index 589ad52..9e9d254 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -69,7 +69,7 @@ struct ieee80211vap;
/*
* Information element ``blob''. We use this structure
* to capture management frame payloads that need to be
- * retained. Information elemnts within the payload that
+ * retained. Information elements within the payload that
* we need to consult have references recorded.
*/
struct ieee80211_ies {
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index f471c5c..21e0370 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -47,6 +47,9 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_regdomain.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
#ifdef IEEE80211_SUPPORT_TDMA
#include <net80211/ieee80211_tdma.h>
#endif
@@ -62,9 +65,6 @@ __FBSDID("$FreeBSD$");
#define ETHER_HEADER_COPY(dst, src) \
memcpy(dst, src, sizeof(struct ether_header))
-static struct mbuf *ieee80211_encap_fastframe(struct ieee80211vap *,
- struct mbuf *m1, const struct ether_header *eh1,
- struct mbuf *m2, const struct ether_header *eh2);
static int ieee80211_fragment(struct ieee80211vap *, struct mbuf *,
u_int hdrsize, u_int ciphdrsize, u_int mtu);
static void ieee80211_tx_mgt_cb(struct ieee80211_node *, void *, int);
@@ -205,7 +205,6 @@ ieee80211_start(struct ifnet *ifp)
m_freem(m);
continue;
}
- /* XXX AUTH'd */
if (ni->ni_associd == 0 &&
(ni->ni_flags & IEEE80211_NODE_ASSOCID)) {
IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_OUTPUT,
@@ -218,6 +217,7 @@ ieee80211_start(struct ifnet *ifp)
ieee80211_free_node(ni);
continue;
}
+
if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) &&
(m->m_flags & M_PWR_SAV) == 0) {
/*
@@ -242,23 +242,28 @@ ieee80211_start(struct ifnet *ifp)
continue;
}
- BPF_MTAP(ifp, m); /* 802.11 tx path */
-
- /*
- * XXX When ni is associated with a WDS link then
- * the vap will be the WDS vap but ni_vap will point
- * to the ap vap the station associated to. Once
- * we handoff the packet to the driver the callback
- * to ieee80211_encap won't be able to tell if the
- * packet should be encapsulated for WDS or not (e.g.
- * multicast frames will not be handled correctly).
- * We hack this by marking the mbuf so ieee80211_encap
- * can do the right thing.
- */
- if (vap->iv_opmode == IEEE80211_M_WDS)
- m->m_flags |= M_WDS;
- else
- m->m_flags &= ~M_WDS;
+ BPF_MTAP(ifp, m); /* 802.3 tx */
+
+#ifdef IEEE80211_SUPPORT_SUPERG
+ if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF)) {
+ m = ieee80211_ff_check(ni, m);
+ if (m == NULL) {
+ /* NB: any ni ref held on stageq */
+ continue;
+ }
+ }
+#endif /* IEEE80211_SUPPORT_SUPERG */
+ if (__predict_true((vap->iv_caps & IEEE80211_C_8023ENCAP) == 0)) {
+ /*
+ * Encapsulate the packet in prep for transmission.
+ */
+ m = ieee80211_encap(vap, ni, m);
+ if (m == NULL) {
+ /* NB: stat+msg handled in ieee80211_encap */
+ ieee80211_free_node(ni);
+ continue;
+ }
+ }
/*
* Stash the node pointer and hand the frame off to
@@ -268,7 +273,6 @@ ieee80211_start(struct ifnet *ifp)
*/
m->m_pkthdr.rcvif = (void *)ni;
- /* XXX defer if_start calls? */
error = parent->if_transmit(parent, m);
if (error != 0) {
/* NB: IFQ_HANDOFF reclaims mbuf */
@@ -732,7 +736,7 @@ done:
* Drivers and cipher modules assume we have done the necessary work
* and fail rudely if they don't find the space they need.
*/
-static struct mbuf *
+struct mbuf *
ieee80211_mbuf_adjust(struct ieee80211vap *vap, int hdrsize,
struct ieee80211_key *key, struct mbuf *m)
{
@@ -853,16 +857,16 @@ ieee80211_crypto_getmcastkey(struct ieee80211vap *vap,
* marked EAPOL frames w/ M_EAPOL.
*/
struct mbuf *
-ieee80211_encap(struct ieee80211_node *ni, struct mbuf *m)
+ieee80211_encap(struct ieee80211vap *vap, struct ieee80211_node *ni,
+ struct mbuf *m)
{
#define WH4(wh) ((struct ieee80211_frame_addr4 *)(wh))
- struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
struct ether_header eh;
struct ieee80211_frame *wh;
struct ieee80211_key *key;
struct llc *llc;
- int hdrsize, hdrspace, datalen, addqos, txfrag, isff, is4addr;
+ int hdrsize, hdrspace, datalen, addqos, txfrag, is4addr;
/*
* Copy existing Ethernet header to a safe place. The
@@ -917,12 +921,11 @@ ieee80211_encap(struct ieee80211_node *ni, struct mbuf *m)
hdrsize = sizeof(struct ieee80211_frame);
/*
* 4-address frames need to be generated for:
- * o packets sent through a WDS vap (M_WDS || IEEE80211_M_WDS)
+ * o packets sent through a WDS vap (IEEE80211_M_WDS)
* o packets relayed by a station operating with dynamic WDS
* (IEEE80211_M_STA+IEEE80211_F_DWDS and src address)
*/
- is4addr = (m->m_flags & M_WDS) ||
- vap->iv_opmode == IEEE80211_M_WDS || /* XXX redundant? */
+ is4addr = vap->iv_opmode == IEEE80211_M_WDS ||
(vap->iv_opmode == IEEE80211_M_STA &&
(vap->iv_flags & IEEE80211_F_DWDS) &&
!IEEE80211_ADDR_EQ(eh.ether_shost, vap->iv_myaddr));
@@ -936,56 +939,7 @@ ieee80211_encap(struct ieee80211_node *ni, struct mbuf *m)
else
hdrspace = hdrsize;
- if ((isff = m->m_flags & M_FF) != 0) {
- struct mbuf *m2;
- struct ether_header eh2;
-
- /*
- * Fast frame encapsulation. There must be two packets
- * chained with m_nextpkt. We do header adjustment for
- * each, add the tunnel encapsulation, and then concatenate
- * the mbuf chains to form a single frame for transmission.
- */
- m2 = m->m_nextpkt;
- if (m2 == NULL) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
- "%s: only one frame\n", __func__);
- goto bad;
- }
- m->m_nextpkt = NULL;
- /*
- * Include fast frame headers in adjusting header
- * layout; this allocates space according to what
- * ieee80211_encap_fastframe will do.
- */
- m = ieee80211_mbuf_adjust(vap,
- hdrspace + sizeof(struct llc) + sizeof(uint32_t) + 2 +
- sizeof(struct ether_header),
- key, m);
- if (m == NULL) {
- /* NB: ieee80211_mbuf_adjust handles msgs+statistics */
- m_freem(m2);
- goto bad;
- }
- /*
- * Copy second frame's Ethernet header out of line
- * and adjust for encapsulation headers. Note that
- * we make room for padding in case there isn't room
- * at the end of first frame.
- */
- KASSERT(m2->m_len >= sizeof(eh2), ("no ethernet header!"));
- ETHER_HEADER_COPY(&eh2, mtod(m2, caddr_t));
- m2 = ieee80211_mbuf_adjust(vap,
- ATH_FF_MAX_HDR_PAD + sizeof(struct ether_header),
- NULL, m2);
- if (m2 == NULL) {
- /* NB: ieee80211_mbuf_adjust handles msgs+statistics */
- goto bad;
- }
- m = ieee80211_encap_fastframe(vap, m, &eh, m2, &eh2);
- if (m == NULL)
- goto bad;
- } else {
+ if (__predict_true((m->m_flags & M_FF) == 0)) {
/*
* Normal frame.
*/
@@ -1003,6 +957,15 @@ ieee80211_encap(struct ieee80211_node *ni, struct mbuf *m)
llc->llc_snap.org_code[1] = 0;
llc->llc_snap.org_code[2] = 0;
llc->llc_snap.ether_type = eh.ether_type;
+ } else {
+#ifdef IEEE80211_SUPPORT_SUPERG
+ /*
+ * Aggregated frame.
+ */
+ m = ieee80211_ff_encap(vap, m, hdrspace, key);
+ if (m == NULL)
+#endif
+ goto bad;
}
datalen = m->m_pkthdr.len; /* NB: w/o 802.11 header */
@@ -1129,7 +1092,7 @@ ieee80211_encap(struct ieee80211_node *ni, struct mbuf *m)
txfrag = (m->m_pkthdr.len > vap->iv_fragthreshold &&
!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
(vap->iv_caps & IEEE80211_C_TXFRAG) &&
- !isff); /* NB: don't fragment ff's */
+ (m->m_flags & M_FF) == 0); /* NB: don't fragment ff's */
if (key != NULL) {
/*
* IEEE 802.1X: send EAPOL frames always in the clear.
@@ -1176,135 +1139,6 @@ bad:
}
/*
- * Do Ethernet-LLC encapsulation for each payload in a fast frame
- * tunnel encapsulation. The frame is assumed to have an Ethernet
- * header at the front that must be stripped before prepending the
- * LLC followed by the Ethernet header passed in (with an Ethernet
- * type that specifies the payload size).
- */
-static struct mbuf *
-ieee80211_encap1(struct ieee80211vap *vap, struct mbuf *m,
- const struct ether_header *eh)
-{
- struct llc *llc;
- uint16_t payload;
-
- /* XXX optimize by combining m_adj+M_PREPEND */
- m_adj(m, sizeof(struct ether_header) - sizeof(struct llc));
- llc = mtod(m, struct llc *);
- llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
- llc->llc_control = LLC_UI;
- llc->llc_snap.org_code[0] = 0;
- llc->llc_snap.org_code[1] = 0;
- llc->llc_snap.org_code[2] = 0;
- llc->llc_snap.ether_type = eh->ether_type;
- payload = m->m_pkthdr.len; /* NB: w/o Ethernet header */
-
- M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
- if (m == NULL) { /* XXX cannot happen */
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
- "%s: no space for ether_header\n", __func__);
- vap->iv_stats.is_tx_nobuf++;
- return NULL;
- }
- ETHER_HEADER_COPY(mtod(m, void *), eh);
- mtod(m, struct ether_header *)->ether_type = htons(payload);
- return m;
-}
-
-/*
- * Do fast frame tunnel encapsulation. The two frames and
- * Ethernet headers are supplied. The caller is assumed to
- * have arrange for space in the mbuf chains for encapsulating
- * headers (to avoid major mbuf fragmentation).
- *
- * The encapsulated frame is returned or NULL if there is a
- * problem (should not happen).
- */
-static struct mbuf *
-ieee80211_encap_fastframe(struct ieee80211vap *vap,
- struct mbuf *m1, const struct ether_header *eh1,
- struct mbuf *m2, const struct ether_header *eh2)
-{
- struct llc *llc;
- struct mbuf *m;
- int pad;
-
- /*
- * First, each frame gets a standard encapsulation.
- */
- m1 = ieee80211_encap1(vap, m1, eh1);
- if (m1 == NULL) {
- m_freem(m2);
- return NULL;
- }
- m2 = ieee80211_encap1(vap, m2, eh2);
- if (m2 == NULL) {
- m_freem(m1);
- return NULL;
- }
-
- /*
- * Pad leading frame to a 4-byte boundary. If there
- * is space at the end of the first frame, put it
- * there; otherwise prepend to the front of the second
- * frame. We know doing the second will always work
- * because we reserve space above. We prefer appending
- * as this typically has better DMA alignment properties.
- */
- for (m = m1; m->m_next != NULL; m = m->m_next)
- ;
- pad = roundup2(m1->m_pkthdr.len, 4) - m1->m_pkthdr.len;
- if (pad) {
- if (M_TRAILINGSPACE(m) < pad) { /* prepend to second */
- m2->m_data -= pad;
- m2->m_len += pad;
- m2->m_pkthdr.len += pad;
- } else { /* append to first */
- m->m_len += pad;
- m1->m_pkthdr.len += pad;
- }
- }
-
- /*
- * Now, stick 'em together and prepend the tunnel headers;
- * first the Atheros tunnel header (all zero for now) and
- * then a special fast frame LLC.
- *
- * XXX optimize by prepending together
- */
- m->m_next = m2; /* NB: last mbuf from above */
- m1->m_pkthdr.len += m2->m_pkthdr.len;
- M_PREPEND(m1, sizeof(uint32_t)+2, M_DONTWAIT);
- if (m1 == NULL) { /* XXX cannot happen */
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
- "%s: no space for tunnel header\n", __func__);
- vap->iv_stats.is_tx_nobuf++;
- return NULL;
- }
- memset(mtod(m1, void *), 0, sizeof(uint32_t)+2);
-
- M_PREPEND(m1, sizeof(struct llc), M_DONTWAIT);
- if (m1 == NULL) { /* XXX cannot happen */
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
- "%s: no space for llc header\n", __func__);
- vap->iv_stats.is_tx_nobuf++;
- return NULL;
- }
- llc = mtod(m1, struct llc *);
- llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
- llc->llc_control = LLC_UI;
- llc->llc_snap.org_code[0] = ATH_FF_SNAP_ORGCODE_0;
- llc->llc_snap.org_code[1] = ATH_FF_SNAP_ORGCODE_1;
- llc->llc_snap.org_code[2] = ATH_FF_SNAP_ORGCODE_2;
- llc->llc_snap.ether_type = htons(ATH_FF_ETH_TYPE);
-
- vap->iv_stats.is_ff_encap++;
-
- return m1;
-}
-
-/*
* Fragment the frame according to the specified mtu.
* The size of the 802.11 header (w/o padding) is provided
* so we don't need to recalculate it. We create a new
@@ -1569,31 +1403,6 @@ ieee80211_add_wme_param(uint8_t *frm, struct ieee80211_wme_state *wme)
}
#undef WME_OUI_BYTES
-#define ATH_OUI_BYTES 0x00, 0x03, 0x7f
-/*
- * Add a WME information element to a frame.
- */
-static uint8_t *
-ieee80211_add_ath(uint8_t *frm, uint8_t caps, uint16_t defkeyix)
-{
- static const struct ieee80211_ath_ie info = {
- .ath_id = IEEE80211_ELEMID_VENDOR,
- .ath_len = sizeof(struct ieee80211_ath_ie) - 2,
- .ath_oui = { ATH_OUI_BYTES },
- .ath_oui_type = ATH_OUI_TYPE,
- .ath_oui_subtype= ATH_OUI_SUBTYPE,
- .ath_version = ATH_OUI_VERSION,
- };
- struct ieee80211_ath_ie *ath = (struct ieee80211_ath_ie *) frm;
-
- memcpy(frm, &info, sizeof(info));
- ath->ath_capability = caps;
- ath->ath_defkeyix[0] = (defkeyix & 0xff);
- ath->ath_defkeyix[1] = ((defkeyix >> 8) & 0xff);
- return frm + sizeof(info);
-}
-#undef ATH_OUI_BYTES
-
/*
* Add an 11h Power Constraint element to a frame.
*/
@@ -1978,7 +1787,9 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg)
+ sizeof(struct ieee80211_wme_info)
+ sizeof(struct ieee80211_ie_htcap)
+ 4 + sizeof(struct ieee80211_ie_htcap)
+#ifdef IEEE80211_SUPPORT_SUPERG
+ sizeof(struct ieee80211_ath_ie)
+#endif
+ (vap->iv_appie_wpa != NULL ?
vap->iv_appie_wpa->ie_len : 0)
+ (vap->iv_appie_assocreq != NULL ?
@@ -2047,13 +1858,15 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg)
ni->ni_ies.htcap_ie != NULL &&
ni->ni_ies.htcap_ie[0] == IEEE80211_ELEMID_VENDOR)
frm = ieee80211_add_htcap_vendor(frm, ni);
- if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_F_ATHEROS))
- frm = ieee80211_add_ath(frm,
+#ifdef IEEE80211_SUPPORT_SUPERG
+ if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_F_ATHEROS)) {
+ frm = ieee80211_add_ath(frm,
IEEE80211_ATH_CAP(vap, ni, IEEE80211_F_ATHEROS),
- (vap->iv_flags & IEEE80211_F_WPA) == 0 &&
- ni->ni_authmode != IEEE80211_AUTH_8021X &&
- vap->iv_def_txkey != IEEE80211_KEYIX_NONE ?
- vap->iv_def_txkey : 0x7fff);
+ ((vap->iv_flags & IEEE80211_F_WPA) == 0 &&
+ ni->ni_authmode != IEEE80211_AUTH_8021X) ?
+ vap->iv_def_txkey : IEEE80211_KEYIX_NONE);
+ }
+#endif /* IEEE80211_SUPPORT_SUPERG */
if (vap->iv_appie_assocreq != NULL)
frm = add_appie(frm, vap->iv_appie_assocreq);
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
@@ -2089,7 +1902,9 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg)
+ sizeof(struct ieee80211_ie_htcap) + 4
+ sizeof(struct ieee80211_ie_htinfo) + 4
+ sizeof(struct ieee80211_wme_param)
+#ifdef IEEE80211_SUPPORT_SUPERG
+ sizeof(struct ieee80211_ath_ie)
+#endif
+ (vap->iv_appie_assocresp != NULL ?
vap->iv_appie_assocresp->ie_len : 0)
);
@@ -2124,10 +1939,14 @@ ieee80211_send_mgmt(struct ieee80211_node *ni, int type, int arg)
frm = ieee80211_add_htcap_vendor(frm, ni);
frm = ieee80211_add_htinfo_vendor(frm, ni);
}
+#ifdef IEEE80211_SUPPORT_SUPERG
if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_F_ATHEROS))
- frm = ieee80211_add_ath(frm,
+ frm = ieee80211_add_ath(frm,
IEEE80211_ATH_CAP(vap, ni, IEEE80211_F_ATHEROS),
- ni->ni_ath_defkeyix);
+ ((vap->iv_flags & IEEE80211_F_WPA) == 0 &&
+ ni->ni_authmode != IEEE80211_AUTH_8021X) ?
+ vap->iv_def_txkey : IEEE80211_KEYIX_NONE);
+#endif /* IEEE80211_SUPPORT_SUPERG */
if (vap->iv_appie_assocresp != NULL)
frm = add_appie(frm, vap->iv_appie_assocresp);
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
@@ -2228,7 +2047,9 @@ ieee80211_alloc_proberesp(struct ieee80211_node *bss, int legacy)
+ sizeof(struct ieee80211_wme_param)
+ 4 + sizeof(struct ieee80211_ie_htcap)
+ 4 + sizeof(struct ieee80211_ie_htinfo)
+#ifdef IEEE80211_SUPPORT_SUPERG
+ sizeof(struct ieee80211_ath_ie)
+#endif
+ (vap->iv_appie_proberesp != NULL ?
vap->iv_appie_proberesp->ie_len : 0)
);
@@ -2311,9 +2132,11 @@ ieee80211_alloc_proberesp(struct ieee80211_node *bss, int legacy)
frm = ieee80211_add_htcap_vendor(frm, bss);
frm = ieee80211_add_htinfo_vendor(frm, bss);
}
- if (bss->ni_ies.ath_ie != NULL && legacy != IEEE80211_SEND_LEGACY_11B)
- frm = ieee80211_add_ath(frm, bss->ni_ath_flags,
- bss->ni_ath_defkeyix);
+#ifdef IEEE80211_SUPPORT_SUPERG
+ if ((vap->iv_flags & IEEE80211_F_ATHEROS) &&
+ legacy != IEEE80211_SEND_LEGACY_11B)
+ frm = ieee80211_add_athcaps(frm, bss);
+#endif
if (vap->iv_appie_proberesp != NULL)
frm = add_appie(frm, vap->iv_appie_proberesp);
m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *);
@@ -2506,6 +2329,7 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm,
* [tlv] WME parameters
* [tlv] Vendor OUI HT capabilities (optional)
* [tlv] Vendor OUI HT information (optional)
+ * [tlv] Atheros capabilities (optional)
* [tlv] TDMA parameters (optional)
* [tlv] application data (optional)
*/
@@ -2596,6 +2420,12 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm,
frm = ieee80211_add_htcap_vendor(frm, ni);
frm = ieee80211_add_htinfo_vendor(frm, ni);
}
+#ifdef IEEE80211_SUPPORT_SUPERG
+ if (vap->iv_flags & IEEE80211_F_ATHEROS) {
+ bo->bo_ath = frm;
+ frm = ieee80211_add_athcaps(frm, ni);
+ }
+#endif
#ifdef IEEE80211_SUPPORT_TDMA
if (vap->iv_caps & IEEE80211_C_TDMA) {
bo->bo_tdma = frm;
@@ -2675,6 +2505,9 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni,
+ 4+2*sizeof(struct ieee80211_ie_htinfo)/* HT info */
+ (vap->iv_caps & IEEE80211_C_WME ? /* WME */
sizeof(struct ieee80211_wme_param) : 0)
+#ifdef IEEE80211_SUPPORT_SUPERG
+ + sizeof(struct ieee80211_ath_ie) /* ATH */
+#endif
#ifdef IEEE80211_SUPPORT_TDMA
+ (vap->iv_caps & IEEE80211_C_TDMA ? /* TDMA */
sizeof(struct ieee80211_tdma_param) : 0)
@@ -2852,6 +2685,12 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
bo->bo_tim_trailer += adjust;
bo->bo_erp += adjust;
bo->bo_htinfo += adjust;
+#ifdef IEEE80211_SUPERG_SUPPORT
+ bo->bo_ath += adjust;
+#endif
+#ifdef IEEE80211_TDMA_SUPPORT
+ bo->bo_tdma += adjust;
+#endif
bo->bo_appie += adjust;
bo->bo_wme += adjust;
bo->bo_csa += adjust;
@@ -2895,7 +2734,14 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
if (vap->iv_csa_count == 0) {
memmove(&csa[1], csa, bo->bo_csa_trailer_len);
bo->bo_erp += sizeof(*csa);
+ bo->bo_htinfo += sizeof(*csa);
bo->bo_wme += sizeof(*csa);
+#ifdef IEEE80211_SUPERG_SUPPORT
+ bo->bo_ath += sizeof(*csa);
+#endif
+#ifdef IEEE80211_TDMA_SUPPORT
+ bo->bo_tdma += sizeof(*csa);
+#endif
bo->bo_appie += sizeof(*csa);
bo->bo_csa_trailer_len += sizeof(*csa);
bo->bo_tim_trailer_len += sizeof(*csa);
@@ -2915,6 +2761,12 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
(void) ieee80211_add_erp(bo->bo_erp, ic);
clrbit(bo->bo_flags, IEEE80211_BEACON_ERP);
}
+#ifdef IEEE80211_SUPPORT_SUPERG
+ if (isset(bo->bo_flags, IEEE80211_BEACON_ATH)) {
+ ieee80211_add_athcaps(bo->bo_ath, ni);
+ clrbit(bo->bo_flags, IEEE80211_BEACON_ATH);
+ }
+#endif
}
if (isset(bo->bo_flags, IEEE80211_BEACON_APPIE)) {
const struct ieee80211_appie *aie = vap->iv_appie_beacon;
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index f870c3c..572580f 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -1316,39 +1316,6 @@ ieee80211_resume_all(struct ieee80211com *ic)
IEEE80211_UNLOCK(ic);
}
-/*
- * Switch between turbo and non-turbo operating modes.
- * Use the specified channel flags to locate the new
- * channel, update 802.11 state, and then call back into
- * the driver to effect the change.
- */
-void
-ieee80211_dturbo_switch(struct ieee80211vap *vap, int newflags)
-{
- struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_channel *chan;
-
- chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags);
- if (chan == NULL) { /* XXX should not happen */
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
- "%s: no channel with freq %u flags 0x%x\n",
- __func__, ic->ic_bsschan->ic_freq, newflags);
- return;
- }
-
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
- "%s: %s -> %s (freq %u flags 0x%x)\n", __func__,
- ieee80211_phymode_name[ieee80211_chan2mode(ic->ic_bsschan)],
- ieee80211_phymode_name[ieee80211_chan2mode(chan)],
- chan->ic_freq, chan->ic_flags);
-
- ic->ic_bsschan = chan;
- ic->ic_prevchan = ic->ic_curchan;
- ic->ic_curchan = chan;
- ic->ic_set_channel(ic);
- /* NB: do not need to reset ERP state 'cuz we're in sta mode */
-}
-
void
ieee80211_beacon_miss(struct ieee80211com *ic)
{
diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
index fa50758..2d32d1e 100644
--- a/sys/net80211/ieee80211_proto.h
+++ b/sys/net80211/ieee80211_proto.h
@@ -74,7 +74,10 @@ int ieee80211_output(struct ifnet *, struct mbuf *,
void ieee80211_start(struct ifnet *);
int ieee80211_send_nulldata(struct ieee80211_node *);
int ieee80211_classify(struct ieee80211_node *, struct mbuf *m);
-struct mbuf *ieee80211_encap(struct ieee80211_node *, struct mbuf *);
+struct mbuf *ieee80211_mbuf_adjust(struct ieee80211vap *, int,
+ struct ieee80211_key *, struct mbuf *);
+struct mbuf *ieee80211_encap(struct ieee80211vap *, struct ieee80211_node *,
+ struct mbuf *);
int ieee80211_send_mgmt(struct ieee80211_node *, int, int);
struct ieee80211_appie;
int ieee80211_send_probereq(struct ieee80211_node *ni,
@@ -298,6 +301,7 @@ struct ieee80211_beacon_offsets {
uint16_t bo_tim_trailer_len;/* tim trailer length in bytes */
uint8_t *bo_erp; /* start of ERP element */
uint8_t *bo_htinfo; /* start of HT info element */
+ uint8_t *bo_ath; /* start of ATH parameters */
uint8_t *bo_appie; /* start of AppIE element */
uint16_t bo_appie_len; /* AppIE length in bytes */
uint16_t bo_csa_trailer_len;;
@@ -328,6 +332,7 @@ enum {
IEEE80211_BEACON_CFP = 6, /* CFParms */
IEEE80211_BEACON_CSA = 7, /* Channel Switch Announcement */
IEEE80211_BEACON_TDMA = 9, /* TDMA Info */
+ IEEE80211_BEACON_ATH = 10, /* ATH parameters */
};
int ieee80211_beacon_update(struct ieee80211_node *,
struct ieee80211_beacon_offsets *, struct mbuf *, int mcast);
diff --git a/sys/net80211/ieee80211_scan.c b/sys/net80211/ieee80211_scan.c
index be3c08a..7ce2d31 100644
--- a/sys/net80211/ieee80211_scan.c
+++ b/sys/net80211/ieee80211_scan.c
@@ -298,6 +298,7 @@ change_channel(struct ieee80211com *ic,
struct ieee80211_channel *chan)
{
ic->ic_curchan = chan;
+ ic->ic_rt = ieee80211_get_ratetable(chan);
ic->ic_set_channel(ic);
}
diff --git a/sys/net80211/ieee80211_scan.h b/sys/net80211/ieee80211_scan.h
index 3b58cff..78e5fe4 100644
--- a/sys/net80211/ieee80211_scan.h
+++ b/sys/net80211/ieee80211_scan.h
@@ -42,7 +42,7 @@
* a callback when scanning on a ``passive channel'' when the
* IEEE80211_FEXT_PROBECHAN flag is set.
*
- * A scan operation involves constructing a set of channels to inspec
+ * A scan operation involves constructing a set of channels to inspect
* (the scan set), visiting each channel and collecting information
* (e.g. what bss are present), and then analyzing the results to make
* decisions like which bss to join. This process needs to be as fast
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index bc99817..607c36d 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -126,6 +126,7 @@ static void sta_flush_table(struct sta_table *);
#define MATCH_TDMA_NOTMASTER 0x0800 /* not TDMA master */
#define MATCH_TDMA_NOSLOT 0x1000 /* all TDMA slots occupied */
#define MATCH_TDMA_LOCAL 0x2000 /* local address */
+#define MATCH_TDMA_VERSION 0x4000 /* protocol version mismatch */
static int match_bss(struct ieee80211vap *,
const struct ieee80211_scan_state *, struct sta_entry *, int);
static void adhoc_age(struct ieee80211_scan_state *);
@@ -970,9 +971,12 @@ match_bss(struct ieee80211vap *vap,
if (vap->iv_caps & IEEE80211_C_TDMA) {
const struct ieee80211_tdma_param *tdma =
(const struct ieee80211_tdma_param *)se->se_ies.tdma_ie;
+ const struct ieee80211_tdma_state *ts = vap->iv_tdma;
if (tdma == NULL)
fail |= MATCH_TDMA_NOIE;
+ else if (tdma->tdma_version != ts->tdma_version)
+ fail |= MATCH_TDMA_VERSION;
else if (tdma->tdma_slot != 0)
fail |= MATCH_TDMA_NOTMASTER;
else if (tdma_isfull(tdma))
@@ -1062,9 +1066,10 @@ match_bss(struct ieee80211vap *vap,
fail & MATCH_CC ? '$' :
#ifdef IEEE80211_SUPPORT_TDMA
fail & MATCH_TDMA_NOIE ? '&' :
- fail & MATCH_TDMA_NOTMASTER ? ':' :
- fail & MATCH_TDMA_NOSLOT ? '@' :
- fail & MATCH_TDMA_LOCAL ? '#' :
+ fail & MATCH_TDMA_VERSION ? 'v' :
+ fail & MATCH_TDMA_NOTMASTER ? 's' :
+ fail & MATCH_TDMA_NOSLOT ? 'f' :
+ fail & MATCH_TDMA_LOCAL ? 'l' :
#endif
fail ? '-' : '+', ether_sprintf(se->se_macaddr));
printf(" %s%c", ether_sprintf(se->se_bssid),
@@ -1076,8 +1081,7 @@ match_bss(struct ieee80211vap *vap,
fail & MATCH_RATE ? '!' : ' ');
printf(" %4s%c",
(se->se_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
- (se->se_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
- "????",
+ (se->se_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" : "",
fail & MATCH_CAPINFO ? '!' : ' ');
printf(" %3s%c ",
(se->se_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index 54733c9..ff3365f 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -57,6 +57,9 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_sta.h>
#include <net80211/ieee80211_input.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
#define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2)
@@ -102,9 +105,7 @@ sta_vattach(struct ieee80211vap *vap)
static void
sta_beacon_miss(struct ieee80211vap *vap)
{
- struct ieee80211com *ic = vap->iv_ic;
-
- KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0, ("scanning"));
+ KASSERT((vap->iv_ic->ic_flags & IEEE80211_F_SCAN) == 0, ("scanning"));
KASSERT(vap->iv_state == IEEE80211_S_RUN,
("wrong state %d", vap->iv_state));
@@ -129,6 +130,9 @@ sta_beacon_miss(struct ieee80211vap *vap)
vap->iv_bmiss_count = 0;
vap->iv_stats.is_beacon_miss++;
if (vap->iv_roaming == IEEE80211_ROAMING_AUTO) {
+#ifdef IEEE80211_SUPPORT_SUPERG
+ struct ieee80211com *ic = vap->iv_ic;
+
/*
* If we receive a beacon miss interrupt when using
* dynamic turbo, attempt to switch modes before
@@ -137,6 +141,7 @@ sta_beacon_miss(struct ieee80211vap *vap)
if (IEEE80211_ATH_CAP(vap, vap->iv_bss, IEEE80211_NODE_TURBOP))
ieee80211_dturbo_switch(vap,
ic->ic_bsschan->ic_flags ^ IEEE80211_CHAN_TURBO);
+#endif
/*
* Try to reassociate before scanning for a new ap.
*/
@@ -795,32 +800,13 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
m = ieee80211_decap_amsdu(ni, m);
if (m == NULL)
return IEEE80211_FC0_TYPE_DATA;
- } else if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF) &&
-#define FF_LLC_SIZE (sizeof(struct ether_header) + sizeof(struct llc))
- m->m_pkthdr.len >= 3*FF_LLC_SIZE) {
- struct llc *llc;
-
- /*
- * Check for fast-frame tunnel encapsulation.
- */
- if (m->m_len < FF_LLC_SIZE &&
- (m = m_pullup(m, FF_LLC_SIZE)) == NULL) {
- IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
- ni->ni_macaddr, "fast-frame",
- "%s", "m_pullup(llc) failed");
- vap->iv_stats.is_rx_tooshort++;
+ } else {
+#ifdef IEEE80211_SUPPORT_SUPERG
+ m = ieee80211_decap_fastframe(vap, ni, m);
+ if (m == NULL)
return IEEE80211_FC0_TYPE_DATA;
- }
- llc = (struct llc *)(mtod(m, uint8_t *) +
- sizeof(struct ether_header));
- if (llc->llc_snap.ether_type == htons(ATH_FF_ETH_TYPE)) {
- m_adj(m, FF_LLC_SIZE);
- m = ieee80211_decap_fastframe(ni, m);
- if (m == NULL)
- return IEEE80211_FC0_TYPE_DATA;
- }
+#endif
}
-#undef FF_LLC_SIZE
ieee80211_deliver_data(vap, ni, m);
return IEEE80211_FC0_TYPE_DATA;
@@ -1094,51 +1080,6 @@ ieee80211_parse_wmeparams(struct ieee80211vap *vap, uint8_t *frm,
#undef MS
}
-static int
-ieee80211_parse_athparams(struct ieee80211_node *ni, uint8_t *frm,
- const struct ieee80211_frame *wh)
-{
- struct ieee80211vap *vap = ni->ni_vap;
- const struct ieee80211_ath_ie *ath;
- u_int len = frm[1];
- int capschanged;
- uint16_t defkeyix;
-
- if (len < sizeof(struct ieee80211_ath_ie)-2) {
- IEEE80211_DISCARD_IE(vap,
- IEEE80211_MSG_ELEMID | IEEE80211_MSG_SUPERG,
- wh, "Atheros", "too short, len %u", len);
- return -1;
- }
- ath = (const struct ieee80211_ath_ie *)frm;
- capschanged = (ni->ni_ath_flags != ath->ath_capability);
- defkeyix = LE_READ_2(ath->ath_defkeyix);
- if (capschanged || defkeyix != ni->ni_ath_defkeyix) {
- ni->ni_ath_flags = ath->ath_capability;
- ni->ni_ath_defkeyix = defkeyix;
- IEEE80211_NOTE(vap, IEEE80211_MSG_SUPERG, ni,
- "ath ie change: new caps 0x%x defkeyix 0x%x",
- ni->ni_ath_flags, ni->ni_ath_defkeyix);
- }
- if (IEEE80211_ATH_CAP(vap, ni, ATHEROS_CAP_TURBO_PRIME)) {
- uint16_t curflags, newflags;
-
- /*
- * Check for turbo mode switch. Calculate flags
- * for the new mode and effect the switch.
- */
- newflags = curflags = vap->iv_ic->ic_bsschan->ic_flags;
- /* NB: BOOST is not in ic_flags, so get it from the ie */
- if (ath->ath_capability & ATHEROS_CAP_BOOST)
- newflags |= IEEE80211_CHAN_TURBO;
- else
- newflags &= ~IEEE80211_CHAN_TURBO;
- if (newflags != curflags)
- ieee80211_dturbo_switch(vap, newflags);
- }
- return capschanged;
-}
-
/*
* Return non-zero if a background scan may be continued:
* o bg scan is active
@@ -1176,7 +1117,9 @@ startbgscan(struct ieee80211vap *vap)
return ((vap->iv_flags & IEEE80211_F_BGSCAN) &&
(ic->ic_flags & IEEE80211_F_CSAPENDING) == 0 &&
+#ifdef IEEE80211_SUPPORT_SUPERG
!IEEE80211_IS_CHAN_DTURBO(ic->ic_curchan) &&
+#endif
time_after(ticks, ic->ic_lastscan + vap->iv_bgscanintvl) &&
time_after(ticks, ic->ic_lastdata + vap->iv_bgscanidle));
}
@@ -1271,8 +1214,10 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
(ni->ni_flags & IEEE80211_NODE_QOS) &&
ieee80211_parse_wmeparams(vap, scan.wme, wh) > 0)
ieee80211_wme_updateparams(vap);
+#ifdef IEEE80211_SUPPORT_SUPERG
if (scan.ath != NULL)
ieee80211_parse_athparams(ni, scan.ath, wh);
+#endif
if (scan.htcap != NULL && scan.htinfo != NULL &&
(vap->iv_flags_ext & IEEE80211_FEXT_HT)) {
ieee80211_ht_updateparams(ni,
@@ -1514,6 +1459,11 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
ieee80211_setup_htrates(ni, htcap,
IEEE80211_F_JOIN | IEEE80211_F_DOBRS);
ieee80211_setup_basic_htrates(ni, htinfo);
+ } else {
+#ifdef IEEE80211_SUPPORT_SUPERG
+ if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_ATH))
+ ieee80211_ff_node_init(ni);
+#endif
}
/*
* Configure state now that we are associated.
diff --git a/sys/net80211/ieee80211_superg.c b/sys/net80211/ieee80211_superg.c
new file mode 100644
index 0000000..4bae885
--- /dev/null
+++ b/sys/net80211/ieee80211_superg.c
@@ -0,0 +1,872 @@
+/*-
+ * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_wlan.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/endian.h>
+
+#include <sys/socket.h>
+
+#include <net/bpf.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_llc.h>
+#include <net/if_media.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_input.h>
+#include <net80211/ieee80211_phy.h>
+#include <net80211/ieee80211_superg.h>
+
+/*
+ * Atheros fast-frame encapsulation format.
+ * FF max payload:
+ * 802.2 + FFHDR + HPAD + 802.3 + 802.2 + 1500 + SPAD + 802.3 + 802.2 + 1500:
+ * 8 + 4 + 4 + 14 + 8 + 1500 + 6 + 14 + 8 + 1500
+ * = 3066
+ */
+/* fast frame header is 32-bits */
+#define ATH_FF_PROTO 0x0000003f /* protocol */
+#define ATH_FF_PROTO_S 0
+#define ATH_FF_FTYPE 0x000000c0 /* frame type */
+#define ATH_FF_FTYPE_S 6
+#define ATH_FF_HLEN32 0x00000300 /* optional hdr length */
+#define ATH_FF_HLEN32_S 8
+#define ATH_FF_SEQNUM 0x001ffc00 /* sequence number */
+#define ATH_FF_SEQNUM_S 10
+#define ATH_FF_OFFSET 0xffe00000 /* offset to 2nd payload */
+#define ATH_FF_OFFSET_S 21
+
+#define ATH_FF_MAX_HDR_PAD 4
+#define ATH_FF_MAX_SEP_PAD 6
+#define ATH_FF_MAX_HDR 30
+
+#define ATH_FF_PROTO_L2TUNNEL 0 /* L2 tunnel protocol */
+#define ATH_FF_ETH_TYPE 0x88bd /* Ether type for encapsulated frames */
+#define ATH_FF_SNAP_ORGCODE_0 0x00
+#define ATH_FF_SNAP_ORGCODE_1 0x03
+#define ATH_FF_SNAP_ORGCODE_2 0x7f
+
+#define ATH_FF_TXQMIN 2 /* min txq depth for staging */
+#define ATH_FF_TXQMAX 50 /* maximum # of queued frames allowed */
+#define ATH_FF_STAGEMAX 5 /* max waiting period for staged frame*/
+
+#define ETHER_HEADER_COPY(dst, src) \
+ memcpy(dst, src, sizeof(struct ether_header))
+
+/* XXX public for sysctl hookup */
+int ieee80211_ffppsmin = 2; /* pps threshold for ff aggregation */
+int ieee80211_ffagemax = -1; /* max time frames held on stage q */
+
+void
+ieee80211_superg_attach(struct ieee80211com *ic)
+{
+ ieee80211_ffagemax = msecs_to_ticks(150);
+}
+
+void
+ieee80211_superg_detach(struct ieee80211com *ic)
+{
+}
+
+void
+ieee80211_superg_vattach(struct ieee80211vap *vap)
+{
+ if (vap->iv_caps & IEEE80211_C_FF)
+ vap->iv_flags |= IEEE80211_F_FF;
+ /* NB: we only implement sta mode */
+ if (vap->iv_opmode == IEEE80211_M_STA &&
+ (vap->iv_caps & IEEE80211_C_TURBOP))
+ vap->iv_flags |= IEEE80211_F_TURBOP;
+}
+
+void
+ieee80211_superg_vdetach(struct ieee80211vap *vap)
+{
+}
+
+#define ATH_OUI_BYTES 0x00, 0x03, 0x7f
+/*
+ * Add a WME information element to a frame.
+ */
+uint8_t *
+ieee80211_add_ath(uint8_t *frm, uint8_t caps, ieee80211_keyix defkeyix)
+{
+ static const struct ieee80211_ath_ie info = {
+ .ath_id = IEEE80211_ELEMID_VENDOR,
+ .ath_len = sizeof(struct ieee80211_ath_ie) - 2,
+ .ath_oui = { ATH_OUI_BYTES },
+ .ath_oui_type = ATH_OUI_TYPE,
+ .ath_oui_subtype= ATH_OUI_SUBTYPE,
+ .ath_version = ATH_OUI_VERSION,
+ };
+ struct ieee80211_ath_ie *ath = (struct ieee80211_ath_ie *) frm;
+
+ memcpy(frm, &info, sizeof(info));
+ ath->ath_capability = caps;
+ if (defkeyix != IEEE80211_KEYIX_NONE) {
+ ath->ath_defkeyix[0] = (defkeyix & 0xff);
+ ath->ath_defkeyix[1] = ((defkeyix >> 8) & 0xff);
+ } else {
+ ath->ath_defkeyix[0] = 0xff;
+ ath->ath_defkeyix[1] = 0x7f;
+ }
+ return frm + sizeof(info);
+}
+#undef ATH_OUI_BYTES
+
+uint8_t *
+ieee80211_add_athcaps(uint8_t *frm, const struct ieee80211_node *bss)
+{
+ const struct ieee80211vap *vap = bss->ni_vap;
+
+ return ieee80211_add_ath(frm,
+ vap->iv_flags & IEEE80211_F_ATHEROS,
+ ((vap->iv_flags & IEEE80211_F_WPA) == 0 &&
+ bss->ni_authmode != IEEE80211_AUTH_8021X) ?
+ vap->iv_def_txkey : IEEE80211_KEYIX_NONE);
+}
+
+void
+ieee80211_parse_ath(struct ieee80211_node *ni, uint8_t *ie)
+{
+ const struct ieee80211_ath_ie *ath =
+ (const struct ieee80211_ath_ie *) ie;
+
+ ni->ni_ath_flags = ath->ath_capability;
+ ni->ni_ath_defkeyix = LE_READ_2(&ath->ath_defkeyix);
+}
+
+int
+ieee80211_parse_athparams(struct ieee80211_node *ni, uint8_t *frm,
+ const struct ieee80211_frame *wh)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+ const struct ieee80211_ath_ie *ath;
+ u_int len = frm[1];
+ int capschanged;
+ uint16_t defkeyix;
+
+ if (len < sizeof(struct ieee80211_ath_ie)-2) {
+ IEEE80211_DISCARD_IE(vap,
+ IEEE80211_MSG_ELEMID | IEEE80211_MSG_SUPERG,
+ wh, "Atheros", "too short, len %u", len);
+ return -1;
+ }
+ ath = (const struct ieee80211_ath_ie *)frm;
+ capschanged = (ni->ni_ath_flags != ath->ath_capability);
+ defkeyix = LE_READ_2(ath->ath_defkeyix);
+ if (capschanged || defkeyix != ni->ni_ath_defkeyix) {
+ ni->ni_ath_flags = ath->ath_capability;
+ ni->ni_ath_defkeyix = defkeyix;
+ IEEE80211_NOTE(vap, IEEE80211_MSG_SUPERG, ni,
+ "ath ie change: new caps 0x%x defkeyix 0x%x",
+ ni->ni_ath_flags, ni->ni_ath_defkeyix);
+ }
+ if (IEEE80211_ATH_CAP(vap, ni, ATHEROS_CAP_TURBO_PRIME)) {
+ uint16_t curflags, newflags;
+
+ /*
+ * Check for turbo mode switch. Calculate flags
+ * for the new mode and effect the switch.
+ */
+ newflags = curflags = vap->iv_ic->ic_bsschan->ic_flags;
+ /* NB: BOOST is not in ic_flags, so get it from the ie */
+ if (ath->ath_capability & ATHEROS_CAP_BOOST)
+ newflags |= IEEE80211_CHAN_TURBO;
+ else
+ newflags &= ~IEEE80211_CHAN_TURBO;
+ if (newflags != curflags)
+ ieee80211_dturbo_switch(vap, newflags);
+ }
+ return capschanged;
+}
+
+/*
+ * Decap the encapsulated frame pair and dispatch the first
+ * for delivery. The second frame is returned for delivery
+ * via the normal path.
+ */
+struct mbuf *
+ieee80211_ff_decap(struct ieee80211_node *ni, struct mbuf *m)
+{
+#define FF_LLC_SIZE (sizeof(struct ether_header) + sizeof(struct llc))
+#define MS(x,f) (((x) & f) >> f##_S)
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct llc *llc;
+ uint32_t ath;
+ struct mbuf *n;
+ int framelen;
+
+ /* NB: we assume caller does this check for us */
+ KASSERT(IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF),
+ ("ff not negotiated"));
+ /*
+ * Check for fast-frame tunnel encapsulation.
+ */
+ if (m->m_pkthdr.len < 3*FF_LLC_SIZE)
+ return m;
+ if (m->m_len < FF_LLC_SIZE &&
+ (m = m_pullup(m, FF_LLC_SIZE)) == NULL) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+ ni->ni_macaddr, "fast-frame",
+ "%s", "m_pullup(llc) failed");
+ vap->iv_stats.is_rx_tooshort++;
+ return NULL;
+ }
+ llc = (struct llc *)(mtod(m, uint8_t *) +
+ sizeof(struct ether_header));
+ if (llc->llc_snap.ether_type != htons(ATH_FF_ETH_TYPE))
+ return m;
+ m_adj(m, FF_LLC_SIZE);
+ m_copydata(m, 0, sizeof(uint32_t), (caddr_t) &ath);
+ if (MS(ath, ATH_FF_PROTO) != ATH_FF_PROTO_L2TUNNEL) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+ ni->ni_macaddr, "fast-frame",
+ "unsupport tunnel protocol, header 0x%x", ath);
+ vap->iv_stats.is_ff_badhdr++;
+ m_freem(m);
+ return NULL;
+ }
+ /* NB: skip header and alignment padding */
+ m_adj(m, roundup(sizeof(uint32_t) - 2, 4) + 2);
+
+ vap->iv_stats.is_ff_decap++;
+
+ /*
+ * Decap the first frame, bust it apart from the
+ * second and deliver; then decap the second frame
+ * and return it to the caller for normal delivery.
+ */
+ m = ieee80211_decap1(m, &framelen);
+ if (m == NULL) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+ ni->ni_macaddr, "fast-frame", "%s", "first decap failed");
+ vap->iv_stats.is_ff_tooshort++;
+ return NULL;
+ }
+ n = m_split(m, framelen, M_NOWAIT);
+ if (n == NULL) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+ ni->ni_macaddr, "fast-frame",
+ "%s", "unable to split encapsulated frames");
+ vap->iv_stats.is_ff_split++;
+ m_freem(m); /* NB: must reclaim */
+ return NULL;
+ }
+ /* XXX not right for WDS */
+ vap->iv_deliver_data(vap, ni, m); /* 1st of pair */
+
+ /*
+ * Decap second frame.
+ */
+ m_adj(n, roundup2(framelen, 4) - framelen); /* padding */
+ n = ieee80211_decap1(n, &framelen);
+ if (n == NULL) {
+ IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
+ ni->ni_macaddr, "fast-frame", "%s", "second decap failed");
+ vap->iv_stats.is_ff_tooshort++;
+ }
+ /* XXX verify framelen against mbuf contents */
+ return n; /* 2nd delivered by caller */
+#undef MS
+#undef FF_LLC_SIZE
+}
+
+/*
+ * Do Ethernet-LLC encapsulation for each payload in a fast frame
+ * tunnel encapsulation. The frame is assumed to have an Ethernet
+ * header at the front that must be stripped before prepending the
+ * LLC followed by the Ethernet header passed in (with an Ethernet
+ * type that specifies the payload size).
+ */
+static struct mbuf *
+ff_encap1(struct ieee80211vap *vap, struct mbuf *m,
+ const struct ether_header *eh)
+{
+ struct llc *llc;
+ uint16_t payload;
+
+ /* XXX optimize by combining m_adj+M_PREPEND */
+ m_adj(m, sizeof(struct ether_header) - sizeof(struct llc));
+ llc = mtod(m, struct llc *);
+ llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
+ llc->llc_control = LLC_UI;
+ llc->llc_snap.org_code[0] = 0;
+ llc->llc_snap.org_code[1] = 0;
+ llc->llc_snap.org_code[2] = 0;
+ llc->llc_snap.ether_type = eh->ether_type;
+ payload = m->m_pkthdr.len; /* NB: w/o Ethernet header */
+
+ M_PREPEND(m, sizeof(struct ether_header), M_DONTWAIT);
+ if (m == NULL) { /* XXX cannot happen */
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
+ "%s: no space for ether_header\n", __func__);
+ vap->iv_stats.is_tx_nobuf++;
+ return NULL;
+ }
+ ETHER_HEADER_COPY(mtod(m, void *), eh);
+ mtod(m, struct ether_header *)->ether_type = htons(payload);
+ return m;
+}
+
+/*
+ * Fast frame encapsulation. There must be two packets
+ * chained with m_nextpkt. We do header adjustment for
+ * each, add the tunnel encapsulation, and then concatenate
+ * the mbuf chains to form a single frame for transmission.
+ */
+struct mbuf *
+ieee80211_ff_encap(struct ieee80211vap *vap, struct mbuf *m1, int hdrspace,
+ struct ieee80211_key *key)
+{
+ struct mbuf *m2;
+ struct ether_header eh1, eh2;
+ struct llc *llc;
+ struct mbuf *m;
+ int pad;
+
+ m2 = m1->m_nextpkt;
+ if (m2 == NULL) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
+ "%s: only one frame\n", __func__);
+ goto bad;
+ }
+ m1->m_nextpkt = NULL;
+ /*
+ * Include fast frame headers in adjusting header layout.
+ */
+ KASSERT(m1->m_len >= sizeof(eh1), ("no ethernet header!"));
+ ETHER_HEADER_COPY(&eh1, mtod(m1, caddr_t));
+ m1 = ieee80211_mbuf_adjust(vap,
+ hdrspace + sizeof(struct llc) + sizeof(uint32_t) + 2 +
+ sizeof(struct ether_header),
+ key, m1);
+ if (m1 == NULL) {
+ /* NB: ieee80211_mbuf_adjust handles msgs+statistics */
+ m_freem(m2);
+ goto bad;
+ }
+
+ /*
+ * Copy second frame's Ethernet header out of line
+ * and adjust for encapsulation headers. Note that
+ * we make room for padding in case there isn't room
+ * at the end of first frame.
+ */
+ KASSERT(m2->m_len >= sizeof(eh2), ("no ethernet header!"));
+ ETHER_HEADER_COPY(&eh2, mtod(m2, caddr_t));
+ m2 = ieee80211_mbuf_adjust(vap,
+ ATH_FF_MAX_HDR_PAD + sizeof(struct ether_header),
+ NULL, m2);
+ if (m2 == NULL) {
+ /* NB: ieee80211_mbuf_adjust handles msgs+statistics */
+ goto bad;
+ }
+
+ /*
+ * Now do tunnel encapsulation. First, each
+ * frame gets a standard encapsulation.
+ */
+ m1 = ff_encap1(vap, m1, &eh1);
+ if (m1 == NULL)
+ goto bad;
+ m2 = ff_encap1(vap, m2, &eh2);
+ if (m2 == NULL)
+ goto bad;
+
+ /*
+ * Pad leading frame to a 4-byte boundary. If there
+ * is space at the end of the first frame, put it
+ * there; otherwise prepend to the front of the second
+ * frame. We know doing the second will always work
+ * because we reserve space above. We prefer appending
+ * as this typically has better DMA alignment properties.
+ */
+ for (m = m1; m->m_next != NULL; m = m->m_next)
+ ;
+ pad = roundup2(m1->m_pkthdr.len, 4) - m1->m_pkthdr.len;
+ if (pad) {
+ if (M_TRAILINGSPACE(m) < pad) { /* prepend to second */
+ m2->m_data -= pad;
+ m2->m_len += pad;
+ m2->m_pkthdr.len += pad;
+ } else { /* append to first */
+ m->m_len += pad;
+ m1->m_pkthdr.len += pad;
+ }
+ }
+
+ /*
+ * Now, stick 'em together and prepend the tunnel headers;
+ * first the Atheros tunnel header (all zero for now) and
+ * then a special fast frame LLC.
+ *
+ * XXX optimize by prepending together
+ */
+ m->m_next = m2; /* NB: last mbuf from above */
+ m1->m_pkthdr.len += m2->m_pkthdr.len;
+ M_PREPEND(m1, sizeof(uint32_t)+2, M_DONTWAIT);
+ if (m1 == NULL) { /* XXX cannot happen */
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
+ "%s: no space for tunnel header\n", __func__);
+ vap->iv_stats.is_tx_nobuf++;
+ return NULL;
+ }
+ memset(mtod(m1, void *), 0, sizeof(uint32_t)+2);
+
+ M_PREPEND(m1, sizeof(struct llc), M_DONTWAIT);
+ if (m1 == NULL) { /* XXX cannot happen */
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
+ "%s: no space for llc header\n", __func__);
+ vap->iv_stats.is_tx_nobuf++;
+ return NULL;
+ }
+ llc = mtod(m1, struct llc *);
+ llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP;
+ llc->llc_control = LLC_UI;
+ llc->llc_snap.org_code[0] = ATH_FF_SNAP_ORGCODE_0;
+ llc->llc_snap.org_code[1] = ATH_FF_SNAP_ORGCODE_1;
+ llc->llc_snap.org_code[2] = ATH_FF_SNAP_ORGCODE_2;
+ llc->llc_snap.ether_type = htons(ATH_FF_ETH_TYPE);
+
+ vap->iv_stats.is_ff_encap++;
+
+ return m1;
+bad:
+ if (m1 != NULL)
+ m_freem(m1);
+ if (m2 != NULL)
+ m_freem(m2);
+ return NULL;
+}
+
+static void
+ff_transmit(struct ieee80211_node *ni, struct mbuf *m)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+ int error;
+
+ /* encap and xmit */
+ m = ieee80211_encap(vap, ni, m);
+ if (m != NULL) {
+ struct ifnet *ifp = vap->iv_ifp;
+ struct ifnet *parent = ni->ni_ic->ic_ifp;
+
+ error = parent->if_transmit(parent, m);
+ if (error != 0) {
+ /* NB: IFQ_HANDOFF reclaims mbuf */
+ ieee80211_free_node(ni);
+ } else {
+ ifp->if_opackets++;
+ }
+ } else
+ ieee80211_free_node(ni);
+}
+
+/*
+ * Flush frames to device; note we re-use the linked list
+ * the frames were stored on and use the sentinel (unchanged)
+ * which may be non-NULL.
+ */
+static void
+ff_flush(struct mbuf *head, struct mbuf *last)
+{
+ struct mbuf *m, *next;
+ struct ieee80211_node *ni;
+ struct ieee80211vap *vap;
+
+ for (m = head; m != last; m = next) {
+ next = m->m_nextpkt;
+ m->m_nextpkt = NULL;
+
+ ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
+ vap = ni->ni_vap;
+
+ IEEE80211_NOTE(vap, IEEE80211_MSG_SUPERG, ni,
+ "%s: flush frame, age %u", __func__, M_AGE_GET(m));
+ vap->iv_stats.is_ff_flush++;
+
+ ff_transmit(ni, m);
+ }
+}
+
+/*
+ * Age frames on the staging queue.
+ */
+void
+ieee80211_ff_age(struct ieee80211com *ic, struct ieee80211_stageq *sq, int quanta)
+{
+ struct mbuf *m, *head;
+ struct ieee80211_node *ni;
+ struct ieee80211_tx_ampdu *tap;
+
+ KASSERT(sq->head != NULL, ("stageq empty"));
+
+ IEEE80211_LOCK(ic);
+ head = sq->head;
+ while ((m = sq->head) != NULL && M_AGE_GET(m) < quanta) {
+ /* clear tap ref to frame */
+ ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
+ tap = &ni->ni_tx_ampdu[M_WME_GETAC(m)];
+ KASSERT(tap->txa_private == m, ("staging queue empty"));
+ tap->txa_private = NULL;
+
+ sq->head = m->m_nextpkt;
+ sq->depth--;
+ ic->ic_stageqdepth--;
+ }
+ if (m == NULL)
+ sq->tail = NULL;
+ else
+ M_AGE_SUB(m, quanta);
+ IEEE80211_UNLOCK(ic);
+
+ ff_flush(head, m);
+}
+
+static void
+stageq_add(struct ieee80211_stageq *sq, struct mbuf *m)
+{
+ int age = ieee80211_ffagemax;
+ if (sq->tail != NULL) {
+ sq->tail->m_nextpkt = m;
+ age -= M_AGE_GET(sq->head);
+ } else
+ sq->head = m;
+ KASSERT(age >= 0, ("age %d", age));
+ M_AGE_SET(m, age);
+ m->m_nextpkt = NULL;
+ sq->tail = m;
+ sq->depth++;
+}
+
+static void
+stageq_remove(struct ieee80211_stageq *sq, struct mbuf *mstaged)
+{
+ struct mbuf *m, *mprev;
+
+ mprev = NULL;
+ for (m = sq->head; m != NULL; m = m->m_nextpkt) {
+ if (m == mstaged) {
+ if (mprev == NULL)
+ sq->head = m->m_nextpkt;
+ else
+ mprev->m_nextpkt = m->m_nextpkt;
+ if (sq->tail == m)
+ sq->tail = mprev;
+ sq->depth--;
+ return;
+ }
+ mprev = m;
+ }
+ printf("%s: packet not found\n", __func__);
+}
+
+static uint32_t
+ff_approx_txtime(struct ieee80211_node *ni,
+ const struct mbuf *m1, const struct mbuf *m2)
+{
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ieee80211vap *vap = ni->ni_vap;
+ uint32_t framelen;
+
+ /*
+ * Approximate the frame length to be transmitted. A swag to add
+ * the following maximal values to the skb payload:
+ * - 32: 802.11 encap + CRC
+ * - 24: encryption overhead (if wep bit)
+ * - 4 + 6: fast-frame header and padding
+ * - 16: 2 LLC FF tunnel headers
+ * - 14: 1 802.3 FF tunnel header (mbuf already accounts for 2nd)
+ */
+ framelen = m1->m_pkthdr.len + 32 +
+ ATH_FF_MAX_HDR_PAD + ATH_FF_MAX_SEP_PAD + ATH_FF_MAX_HDR;
+ if (vap->iv_flags & IEEE80211_F_PRIVACY)
+ framelen += 24;
+ if (m2 != NULL)
+ framelen += m2->m_pkthdr.len;
+ return ieee80211_compute_duration(ic->ic_rt, framelen, ni->ni_txrate, 0);
+}
+
+/*
+ * Check if the supplied frame can be partnered with an existing
+ * or pending frame. Return a reference to any frame that should be
+ * sent on return; otherwise return NULL.
+ */
+struct mbuf *
+ieee80211_ff_check(struct ieee80211_node *ni, struct mbuf *m)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211com *ic = ni->ni_ic;
+ const int pri = M_WME_GETAC(m);
+ struct ieee80211_stageq *sq;
+ struct ieee80211_tx_ampdu *tap;
+ struct mbuf *mstaged;
+ uint32_t txtime, limit;
+
+ /*
+ * Check if the supplied frame can be aggregated.
+ *
+ * NB: we allow EAPOL frames to be aggregated with other ucast traffic.
+ * Do 802.1x EAPOL frames proceed in the clear? Then they couldn't
+ * be aggregated with other types of frames when encryption is on?
+ */
+ IEEE80211_LOCK(ic);
+ tap = &ni->ni_tx_ampdu[pri];
+ mstaged = tap->txa_private; /* NB: we reuse AMPDU state */
+ ieee80211_txampdu_count_packet(tap);
+
+ /*
+ * When not in station mode never aggregate a multicast
+ * frame; this insures, for example, that a combined frame
+ * does not require multiple encryption keys.
+ */
+ if (vap->iv_opmode != IEEE80211_M_STA &&
+ ETHER_IS_MULTICAST(mtod(m, struct ether_header *)->ether_dhost)) {
+ /* XXX flush staged frame? */
+ IEEE80211_UNLOCK(ic);
+ return m;
+ }
+ /*
+ * If there is no frame to combine with and the pps is
+ * too low; then do not attempt to aggregate this frame.
+ */
+ if (mstaged == NULL &&
+ ieee80211_txampdu_getpps(tap) < ieee80211_ffppsmin) {
+ IEEE80211_UNLOCK(ic);
+ return m;
+ }
+ sq = &ic->ic_ff_stageq[pri];
+ /*
+ * Check the txop limit to insure the aggregate fits.
+ */
+ limit = IEEE80211_TXOP_TO_US(
+ ic->ic_wme.wme_chanParams.cap_wmeParams[pri].wmep_txopLimit);
+ if (limit != 0 &&
+ (txtime = ff_approx_txtime(ni, m, mstaged)) > limit) {
+ /*
+ * Aggregate too long, return to the caller for direct
+ * transmission. In addition, flush any pending frame
+ * before sending this one.
+ */
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
+ "%s: txtime %u exceeds txop limit %u\n",
+ __func__, txtime, limit);
+
+ tap->txa_private = NULL;
+ if (mstaged != NULL)
+ stageq_remove(sq, mstaged);
+ IEEE80211_UNLOCK(ic);
+
+ if (mstaged != NULL) {
+ IEEE80211_NOTE(vap, IEEE80211_MSG_SUPERG, ni,
+ "%s: flush staged frame", __func__);
+ /* encap and xmit */
+ ff_transmit(ni, mstaged);
+ }
+ return m; /* NB: original frame */
+ }
+ /*
+ * An aggregation candidate. If there's a frame to partner
+ * with then combine and return for processing. Otherwise
+ * save this frame and wait for a partner to show up (or
+ * the frame to be flushed). Note that staged frames also
+ * hold their node reference.
+ */
+ if (mstaged != NULL) {
+ tap->txa_private = NULL;
+ stageq_remove(sq, mstaged);
+ IEEE80211_UNLOCK(ic);
+
+ IEEE80211_NOTE(vap, IEEE80211_MSG_SUPERG, ni,
+ "%s: aggregate fast-frame", __func__);
+ /*
+ * Release the node reference; we only need
+ * the one already in mstaged.
+ */
+ KASSERT(mstaged->m_pkthdr.rcvif == (void *)ni,
+ ("rcvif %p ni %p", mstaged->m_pkthdr.rcvif, ni));
+ ieee80211_free_node(ni);
+
+ m->m_nextpkt = NULL;
+ mstaged->m_nextpkt = m;
+ mstaged->m_flags |= M_FF; /* NB: mark for encap work */
+ } else {
+ m->m_pkthdr.rcvif = (void *)ni; /* NB: hold node reference */
+
+ KASSERT(tap->txa_private == NULL,
+ ("txa_private %p", tap->txa_private));
+ tap->txa_private = m;
+
+ stageq_add(sq, m);
+ ic->ic_stageqdepth++;
+ IEEE80211_UNLOCK(ic);
+
+ IEEE80211_NOTE(vap, IEEE80211_MSG_SUPERG, ni,
+ "%s: stage frame, %u queued", __func__, sq->depth);
+ /* NB: mstaged is NULL */
+ }
+ return mstaged;
+}
+
+void
+ieee80211_ff_node_init(struct ieee80211_node *ni)
+{
+ /*
+ * Clean FF state on re-associate. This handles the case
+ * where a station leaves w/o notifying us and then returns
+ * before node is reaped for inactivity.
+ */
+ ieee80211_ff_node_cleanup(ni);
+}
+
+void
+ieee80211_ff_node_cleanup(struct ieee80211_node *ni)
+{
+ struct ieee80211com *ic = ni->ni_ic;
+ struct ieee80211_tx_ampdu *tap;
+ struct mbuf *m, *head;
+ int ac;
+
+ IEEE80211_LOCK(ic);
+ head = NULL;
+ for (ac = 0; ac < WME_NUM_AC; ac++) {
+ tap = &ni->ni_tx_ampdu[ac];
+ m = tap->txa_private;
+ if (m != NULL) {
+ tap->txa_private = NULL;
+ stageq_remove(&ic->ic_ff_stageq[ac], m);
+ m->m_nextpkt = head;
+ head = m;
+ }
+ }
+ IEEE80211_UNLOCK(ic);
+
+ for (m = head; m != NULL; m = m->m_nextpkt) {
+ m_freem(m);
+ ieee80211_free_node(ni);
+ }
+}
+
+/*
+ * Switch between turbo and non-turbo operating modes.
+ * Use the specified channel flags to locate the new
+ * channel, update 802.11 state, and then call back into
+ * the driver to effect the change.
+ */
+void
+ieee80211_dturbo_switch(struct ieee80211vap *vap, int newflags)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211_channel *chan;
+
+ chan = ieee80211_find_channel(ic, ic->ic_bsschan->ic_freq, newflags);
+ if (chan == NULL) { /* XXX should not happen */
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
+ "%s: no channel with freq %u flags 0x%x\n",
+ __func__, ic->ic_bsschan->ic_freq, newflags);
+ return;
+ }
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SUPERG,
+ "%s: %s -> %s (freq %u flags 0x%x)\n", __func__,
+ ieee80211_phymode_name[ieee80211_chan2mode(ic->ic_bsschan)],
+ ieee80211_phymode_name[ieee80211_chan2mode(chan)],
+ chan->ic_freq, chan->ic_flags);
+
+ ic->ic_bsschan = chan;
+ ic->ic_prevchan = ic->ic_curchan;
+ ic->ic_curchan = chan;
+ ic->ic_rt = ieee80211_get_ratetable(chan);
+ ic->ic_set_channel(ic);
+ /* NB: do not need to reset ERP state 'cuz we're in sta mode */
+}
+
+/*
+ * Return the current ``state'' of an Atheros capbility.
+ * If associated in station mode report the negotiated
+ * setting. Otherwise report the current setting.
+ */
+static int
+getathcap(struct ieee80211vap *vap, int cap)
+{
+ if (vap->iv_opmode == IEEE80211_M_STA &&
+ vap->iv_state == IEEE80211_S_RUN)
+ return IEEE80211_ATH_CAP(vap, vap->iv_bss, cap) != 0;
+ else
+ return (vap->iv_flags & cap) != 0;
+}
+
+static int
+superg_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
+{
+ switch (ireq->i_type) {
+ case IEEE80211_IOC_FF:
+ ireq->i_val = getathcap(vap, IEEE80211_F_FF);
+ break;
+ case IEEE80211_IOC_TURBOP:
+ ireq->i_val = getathcap(vap, IEEE80211_F_TURBOP);
+ break;
+ default:
+ return ENOSYS;
+ }
+ return 0;
+}
+IEEE80211_IOCTL_GET(superg, superg_ioctl_get80211);
+
+static int
+superg_ioctl_set80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
+{
+ switch (ireq->i_type) {
+ case IEEE80211_IOC_FF:
+ if (ireq->i_val) {
+ if ((vap->iv_caps & IEEE80211_C_FF) == 0)
+ return EOPNOTSUPP;
+ vap->iv_flags |= IEEE80211_F_FF;
+ } else
+ vap->iv_flags &= ~IEEE80211_F_FF;
+ return ENETRESET;
+ case IEEE80211_IOC_TURBOP:
+ if (ireq->i_val) {
+ if ((vap->iv_caps & IEEE80211_C_TURBOP) == 0)
+ return EOPNOTSUPP;
+ vap->iv_flags |= IEEE80211_F_TURBOP;
+ } else
+ vap->iv_flags &= ~IEEE80211_F_TURBOP;
+ return ENETRESET;
+ default:
+ return ENOSYS;
+ }
+ return 0;
+}
+IEEE80211_IOCTL_SET(superg, superg_ioctl_set80211);
diff --git a/sys/net80211/ieee80211_superg.h b/sys/net80211/ieee80211_superg.h
new file mode 100644
index 0000000..d627ab0
--- /dev/null
+++ b/sys/net80211/ieee80211_superg.h
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 2009 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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$
+ */
+#ifndef _NET80211_IEEE80211_SUPERG_H_
+#define _NET80211_IEEE80211_SUPERG_H_
+
+/*
+ * Atheros' 802.11 SuperG protocol support.
+ */
+
+/*
+ * Atheros advanced capability information element.
+ */
+struct ieee80211_ath_ie {
+ uint8_t ath_id; /* IEEE80211_ELEMID_VENDOR */
+ uint8_t ath_len; /* length in bytes */
+ uint8_t ath_oui[3]; /* ATH_OUI */
+ uint8_t ath_oui_type; /* ATH_OUI_TYPE */
+ uint8_t ath_oui_subtype; /* ATH_OUI_SUBTYPE */
+ uint8_t ath_version; /* spec revision */
+ uint8_t ath_capability; /* capability info */
+#define ATHEROS_CAP_TURBO_PRIME 0x01 /* dynamic turbo--aka Turbo' */
+#define ATHEROS_CAP_COMPRESSION 0x02 /* data compression */
+#define ATHEROS_CAP_FAST_FRAME 0x04 /* fast (jumbo) frames */
+#define ATHEROS_CAP_XR 0x08 /* Xtended Range support */
+#define ATHEROS_CAP_AR 0x10 /* Advanded Radar support */
+#define ATHEROS_CAP_BURST 0x20 /* Bursting - not negotiated */
+#define ATHEROS_CAP_WME 0x40 /* CWMin tuning */
+#define ATHEROS_CAP_BOOST 0x80 /* use turbo/!turbo mode */
+ uint8_t ath_defkeyix[2];
+} __packed;
+
+#define ATH_OUI_VERSION 0x00
+#define ATH_OUI_SUBTYPE 0x01
+
+#ifdef _KERNEL
+void ieee80211_superg_attach(struct ieee80211com *);
+void ieee80211_superg_detach(struct ieee80211com *);
+void ieee80211_superg_vattach(struct ieee80211vap *);
+void ieee80211_superg_vdetach(struct ieee80211vap *);
+
+uint8_t *ieee80211_add_ath(uint8_t *, uint8_t, ieee80211_keyix);
+uint8_t *ieee80211_add_athcaps(uint8_t *, const struct ieee80211_node *);
+void ieee80211_parse_ath(struct ieee80211_node *, uint8_t *);
+int ieee80211_parse_athparams(struct ieee80211_node *, uint8_t *,
+ const struct ieee80211_frame *);
+
+void ieee80211_ff_node_init(struct ieee80211_node *);
+void ieee80211_ff_node_cleanup(struct ieee80211_node *);
+
+struct mbuf *ieee80211_ff_check(struct ieee80211_node *, struct mbuf *);
+void ieee80211_ff_age(struct ieee80211com *, struct ieee80211_stageq *, int);
+
+static __inline void
+ieee80211_flush_stageq(struct ieee80211com *ic, int ac)
+{
+ if (ic->ic_ff_stageq[ac].depth)
+ ieee80211_ff_age(ic, &ic->ic_ff_stageq[ac], 0x7fffffff);
+}
+
+static __inline void
+ieee80211_age_stageq(struct ieee80211com *ic, int ac, int quanta)
+{
+ if (ic->ic_ff_stageq[ac].depth)
+ ieee80211_ff_age(ic, &ic->ic_ff_stageq[ac], quanta);
+}
+
+struct mbuf *ieee80211_ff_encap(struct ieee80211vap *, struct mbuf *,
+ int, struct ieee80211_key *);
+
+struct mbuf *ieee80211_ff_decap(struct ieee80211_node *, struct mbuf *);
+
+static __inline struct mbuf *
+ieee80211_decap_fastframe(struct ieee80211vap *vap, struct ieee80211_node *ni,
+ struct mbuf *m)
+{
+ return IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF) ?
+ ieee80211_ff_decap(ni, m) : m;
+}
+#endif /* _KERNEL */
+#endif /* _NET80211_IEEE80211_SUPERG_H_ */
diff --git a/sys/net80211/ieee80211_tdma.c b/sys/net80211/ieee80211_tdma.c
index 82ba29e..88c52e0 100644
--- a/sys/net80211/ieee80211_tdma.c
+++ b/sys/net80211/ieee80211_tdma.c
@@ -33,9 +33,9 @@ __FBSDID("$FreeBSD$");
* IEEE 802.11 TDMA mode support.
*/
#include "opt_inet.h"
+#include "opt_tdma.h"
#include "opt_wlan.h"
-#ifdef IEEE80211_SUPPORT_TDMA
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/mbuf.h>
@@ -60,7 +60,6 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_tdma.h>
#include <net80211/ieee80211_input.h>
-#include "opt_tdma.h"
#ifndef TDMA_SLOTLEN_DEFAULT
#define TDMA_SLOTLEN_DEFAULT 10*1000 /* 10ms */
#endif
@@ -95,6 +94,16 @@ __FBSDID("$FreeBSD$");
#define TDMA_TXRATE_11NG_DEFAULT (4 | IEEE80211_RATE_MCS)
#endif
+#define TDMA_VERSION_VALID(_version) \
+ (TDMA_VERSION_V2 <= (_version) && (_version) <= TDMA_VERSION)
+#define TDMA_SLOTCNT_VALID(_slotcnt) \
+ (2 <= (_slotcnt) && (_slotcnt) <= TDMA_MAXSLOTS)
+/* XXX magic constants */
+#define TDMA_SLOTLEN_VALID(_slotlen) \
+ (2*100 <= (_slotlen) && (unsigned)(_slotlen) <= 0xfffff)
+/* XXX probably should set a max */
+#define TDMA_BINTVAL_VALID(_bintval) (1 <= (_bintval))
+
static void tdma_vdetach(struct ieee80211vap *vap);
static int tdma_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static void tdma_beacon_miss(struct ieee80211vap *vap);
@@ -142,6 +151,7 @@ ieee80211_tdma_vattach(struct ieee80211vap *vap)
return;
}
/* NB: default configuration is passive so no beacons */
+ ts->tdma_version = TDMA_VERSION;
ts->tdma_slotlen = TDMA_SLOTLEN_DEFAULT;
ts->tdma_slotcnt = TDMA_SLOTCNT_DEFAULT;
ts->tdma_bintval = TDMA_BINTVAL_DEFAULT;
@@ -371,71 +381,93 @@ tdma_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
* a TDMA information element. The sender's identity
* is provided so we can track who our peer is. If pickslot
* is non-zero we scan the slot allocation state in the ie
- * locate a free slot for our use.
+ * to locate a free slot for our use.
*/
static int
tdma_update(struct ieee80211vap *vap, const struct ieee80211_tdma_param *tdma,
struct ieee80211_node *ni, int pickslot)
{
struct ieee80211_tdma_state *ts = vap->iv_tdma;
- int slotlen, slotcnt, slot, bintval;
+ int slot, slotlen, update;
KASSERT(vap->iv_caps & IEEE80211_C_TDMA,
("not a tdma vap, caps 0x%x", vap->iv_caps));
- slotlen = le16toh(tdma->tdma_slotlen);
- slotcnt = tdma->tdma_slotcnt;
- bintval = tdma->tdma_bintval;
-
- /* XXX rate-limit printf's */
- if (!(2 <= slotcnt && slotcnt <= IEEE80211_TDMA_MAXSLOTS)) {
- printf("%s: bogus slot cnt %u\n", __func__, slotcnt);
- return 0;
- }
- /* XXX magic constants */
- if (slotlen < 2 || slotlen > (0xfffff/100)) {
- printf("%s: bogus slot len %u\n", __func__, slotlen);
- return 0;
- }
- if (bintval < 1) {
- printf("%s: bogus beacon interval %u\n", __func__, bintval);
- return 0;
- }
+ update = 0;
+ if (tdma->tdma_slotcnt != ts->tdma_slotcnt) {
+ if (!TDMA_SLOTCNT_VALID(tdma->tdma_slotcnt)) {
+ if (ppsratecheck(&ts->tdma_lastprint, &ts->tdma_fails, 1))
+ printf("%s: bad slot cnt %u\n",
+ __func__, tdma->tdma_slotcnt);
+ return 0;
+ }
+ update |= TDMA_UPDATE_SLOTCNT;
+ }
+ slotlen = le16toh(tdma->tdma_slotlen) * 100;
+ if (slotlen != ts->tdma_slotlen) {
+ if (!TDMA_SLOTLEN_VALID(slotlen)) {
+ if (ppsratecheck(&ts->tdma_lastprint, &ts->tdma_fails, 1))
+ printf("%s: bad slot len %u\n",
+ __func__, slotlen);
+ return 0;
+ }
+ update |= TDMA_UPDATE_SLOTLEN;
+ }
+ if (tdma->tdma_bintval != ts->tdma_bintval) {
+ if (!TDMA_BINTVAL_VALID(tdma->tdma_bintval)) {
+ if (ppsratecheck(&ts->tdma_lastprint, &ts->tdma_fails, 1))
+ printf("%s: bad beacon interval %u\n",
+ __func__, tdma->tdma_bintval);
+ return 0;
+ }
+ update |= TDMA_UPDATE_BINTVAL;
+ }
+ slot = ts->tdma_slot;
if (pickslot) {
/*
* Pick unoccupied slot. Note we never choose slot 0.
*/
- for (slot = slotcnt-1; slot > 0; slot--)
+ for (slot = tdma->tdma_slotcnt-1; slot > 0; slot--)
if (isclr(tdma->tdma_inuse, slot))
break;
if (slot <= 0) {
printf("%s: no free slot, slotcnt %u inuse: 0x%x\n",
- __func__, slotcnt, tdma->tdma_inuse[0]);
+ __func__, tdma->tdma_slotcnt,
+ tdma->tdma_inuse[0]);
/* XXX need to do something better */
return 0;
}
- } else
- slot = ts->tdma_slot;
+ if (slot != ts->tdma_slot)
+ update |= TDMA_UPDATE_SLOT;
+ }
+ if (ni != ts->tdma_peer) {
+ /* update everything */
+ update = TDMA_UPDATE_SLOT
+ | TDMA_UPDATE_SLOTCNT
+ | TDMA_UPDATE_SLOTLEN
+ | TDMA_UPDATE_BINTVAL;
+ }
- if (slotcnt != ts->tdma_slotcnt ||
- 100*slotlen != ts->tdma_slotlen ||
- bintval != ts->tdma_bintval ||
- slot != ts->tdma_slot ||
- ts->tdma_peer != ni) {
+ if (update) {
/*
* New/changed parameters; update runtime state.
*/
/* XXX overwrites user parameters */
- ts->tdma_slotcnt = slotcnt;
- ts->tdma_slotlen = 100*slotlen;
- ts->tdma_slot = slot;
- ts->tdma_bintval = bintval;
+ if (update & TDMA_UPDATE_SLOTCNT)
+ ts->tdma_slotcnt = tdma->tdma_slotcnt;
+ if (update & TDMA_UPDATE_SLOTLEN)
+ ts->tdma_slotlen = slotlen;
+ if (update & TDMA_UPDATE_SLOT)
+ ts->tdma_slot = slot;
+ if (update & TDMA_UPDATE_BINTVAL)
+ ts->tdma_bintval = tdma->tdma_bintval;
/* mark beacon to be updated before next xmit */
ieee80211_beacon_notify(vap, IEEE80211_BEACON_TDMA);
IEEE80211_DPRINTF(vap, IEEE80211_MSG_TDMA,
"%s: slot %u slotcnt %u slotlen %u us bintval %u\n",
- __func__, slot, slotcnt, 100*slotlen, tdma->tdma_bintval);
+ __func__, ts->tdma_slot, ts->tdma_slotcnt,
+ 100*ts->tdma_slotlen, ts->tdma_bintval);
}
/*
* Notify driver. Note we can be called before
@@ -445,7 +477,7 @@ tdma_update(struct ieee80211vap *vap, const struct ieee80211_tdma_param *tdma,
* has been setup. The next beacon will dtrt.
*/
if (vap->iv_state == IEEE80211_S_RUN)
- vap->iv_ic->ic_tdma_update(ni, tdma);
+ vap->iv_ic->ic_tdma_update(ni, tdma, update);
/*
* Dispatch join event on first beacon from new master.
*/
@@ -481,10 +513,23 @@ tdma_process_params(struct ieee80211_node *ni,
wh, "tdma", "too short, len %u", len);
return IEEE80211_REASON_IE_INVALID;
}
- if (tdma->tdma_version != TDMA_VERSION) {
+ if (tdma->tdma_version != ts->tdma_version) {
+ IEEE80211_DISCARD_IE(vap,
+ IEEE80211_MSG_ELEMID | IEEE80211_MSG_TDMA,
+ wh, "tdma", "bad version %u (ours %u)",
+ tdma->tdma_version, ts->tdma_version);
+ return IEEE80211_REASON_IE_INVALID;
+ }
+ /*
+ * NB: ideally we'd check against tdma_slotcnt, but that
+ * would require extra effort so do this easy check that
+ * covers the work below; more stringent checks are done
+ * before we make more extensive use of the ie contents.
+ */
+ if (tdma->tdma_slot >= TDMA_MAXSLOTS) {
IEEE80211_DISCARD_IE(vap,
IEEE80211_MSG_ELEMID | IEEE80211_MSG_TDMA,
- wh, "tdma", "bad version %u", tdma->tdma_version);
+ wh, "tdma", "invalid slot %u", tdma->tdma_slot);
return IEEE80211_REASON_IE_INVALID;
}
/*
@@ -612,7 +657,7 @@ ieee80211_add_tdma(uint8_t *frm, struct ieee80211vap *vap)
.tdma_subtype = TDMA_SUBTYPE_PARAM,
.tdma_version = TDMA_VERSION,
};
- const struct ieee80211_tdma_state *tdma = vap->iv_tdma;
+ const struct ieee80211_tdma_state *ts = vap->iv_tdma;
uint16_t slotlen;
KASSERT(vap->iv_caps & IEEE80211_C_TDMA,
@@ -620,13 +665,13 @@ ieee80211_add_tdma(uint8_t *frm, struct ieee80211vap *vap)
memcpy(frm, &param, sizeof(param));
frm += __offsetof(struct ieee80211_tdma_param, tdma_slot);
- *frm++ = tdma->tdma_slot;
- *frm++ = tdma->tdma_slotcnt;
+ *frm++ = ts->tdma_slot;
+ *frm++ = ts->tdma_slotcnt;
/* NB: convert units to fit in 16-bits */
- slotlen = tdma->tdma_slotlen / 100; /* 100us units */
+ slotlen = ts->tdma_slotlen / 100; /* 100us units */
ADDSHORT(frm, slotlen);
- *frm++ = tdma->tdma_bintval;
- *frm++ = tdma->tdma_inuse[0];
+ *frm++ = ts->tdma_bintval;
+ *frm++ = ts->tdma_inuse[0];
frm += 10; /* pad+timestamp */
return frm;
#undef ADDSHORT
@@ -670,9 +715,8 @@ ieee80211_tdma_update_beacon(struct ieee80211vap *vap,
ts->tdma_count--;
}
-int
-ieee80211_tdma_ioctl_get80211(struct ieee80211vap *vap,
- struct ieee80211req *ireq)
+static int
+tdma_ioctl_get80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
{
struct ieee80211_tdma_state *ts = vap->iv_tdma;
@@ -693,14 +737,14 @@ ieee80211_tdma_ioctl_get80211(struct ieee80211vap *vap,
ireq->i_val = ts->tdma_bintval;
break;
default:
- return EINVAL;
+ return ENOSYS;
}
return 0;
}
+IEEE80211_IOCTL_GET(tdma, tdma_ioctl_get80211);
-int
-ieee80211_tdma_ioctl_set80211(struct ieee80211vap *vap,
- struct ieee80211req *ireq)
+static int
+tdma_ioctl_set80211(struct ieee80211vap *vap, struct ieee80211req *ireq)
{
struct ieee80211_tdma_state *ts = vap->iv_tdma;
@@ -717,8 +761,7 @@ ieee80211_tdma_ioctl_set80211(struct ieee80211vap *vap,
}
break;
case IEEE80211_IOC_TDMA_SLOTCNT:
- if (!(2 <= ireq->i_val &&
- ireq->i_val <= IEEE80211_TDMA_MAXSLOTS))
+ if (!TDMA_SLOTCNT_VALID(ireq->i_val))
return EINVAL;
if (ireq->i_val != ts->tdma_slotcnt) {
ts->tdma_slotcnt = ireq->i_val;
@@ -732,7 +775,7 @@ ieee80211_tdma_ioctl_set80211(struct ieee80211vap *vap,
* 0xfffff is the max duration for bursting
* (implict by way of 16-bit data type for i_val)
*/
- if (ireq->i_val < 150)
+ if (!TDMA_SLOTLEN_VALID(ireq->i_val))
return EINVAL;
if (ireq->i_val != ts->tdma_slotlen) {
ts->tdma_slotlen = ireq->i_val;
@@ -740,7 +783,7 @@ ieee80211_tdma_ioctl_set80211(struct ieee80211vap *vap,
}
break;
case IEEE80211_IOC_TDMA_BINTERVAL:
- if (ireq->i_val < 1)
+ if (!TDMA_BINTVAL_VALID(ireq->i_val))
return EINVAL;
if (ireq->i_val != ts->tdma_bintval) {
ts->tdma_bintval = ireq->i_val;
@@ -748,8 +791,8 @@ ieee80211_tdma_ioctl_set80211(struct ieee80211vap *vap,
}
break;
default:
- return EINVAL;
+ return ENOSYS;
}
return 0;
}
-#endif /* IEEE80211_SUPPORT_TDMA */
+IEEE80211_IOCTL_SET(tdma, tdma_ioctl_set80211);
diff --git a/sys/net80211/ieee80211_tdma.h b/sys/net80211/ieee80211_tdma.h
index c5ac3a2..41ca09e 100644
--- a/sys/net80211/ieee80211_tdma.h
+++ b/sys/net80211/ieee80211_tdma.h
@@ -31,16 +31,51 @@
/*
* TDMA-mode implementation definitions.
*/
+
+#define TDMA_SUBTYPE_PARAM 0x01
+#define TDMA_VERSION_V2 2
+#define TDMA_VERSION TDMA_VERSION_V2
+
+/* NB: we only support 2 right now but protocol handles up to 8 */
+#define TDMA_MAXSLOTS 2 /* max slots/sta's */
+
+#define TDMA_PARAM_LEN_V2 sizeof(struct ieee80211_tdma_param)
+
+/*
+ * TDMA information element.
+ */
+struct ieee80211_tdma_param {
+ u_int8_t tdma_id; /* IEEE80211_ELEMID_VENDOR */
+ u_int8_t tdma_len;
+ u_int8_t tdma_oui[3]; /* TDMA_OUI */
+ u_int8_t tdma_type; /* TDMA_OUI_TYPE */
+ u_int8_t tdma_subtype; /* TDMA_SUBTYPE_PARAM */
+ u_int8_t tdma_version; /* spec revision */
+ u_int8_t tdma_slot; /* station slot # [0..7] */
+ u_int8_t tdma_slotcnt; /* bss slot count [1..8] */
+ u_int16_t tdma_slotlen; /* bss slot len (100us) */
+ u_int8_t tdma_bintval; /* beacon interval (superframes) */
+ u_int8_t tdma_inuse[1]; /* slot occupancy map */
+ u_int8_t tdma_pad[2];
+ u_int8_t tdma_tstamp[8]; /* timestamp from last beacon */
+} __packed;
+
+#ifdef _KERNEL
+/*
+ * Implementation state.
+ */
struct ieee80211_tdma_state {
u_int tdma_slotlen; /* bss slot length (us) */
+ uint8_t tdma_version; /* protocol version to use */
uint8_t tdma_slotcnt; /* bss slot count */
uint8_t tdma_bintval; /* beacon interval (slots) */
uint8_t tdma_slot; /* station slot # */
uint8_t tdma_inuse[1]; /* mask of slots in use */
-#define IEEE80211_TDMA_MAXSLOTS 8
- void *tdma_peer; /* peer station cookie */
uint8_t tdma_active[1]; /* mask of active slots */
int tdma_count; /* active/inuse countdown */
+ void *tdma_peer; /* peer station cookie */
+ struct timeval tdma_lastprint; /* time of last rate-limited printf */
+ int tdma_fails; /* fail count for rate-limiting */
/* parent method pointers */
int (*tdma_newstate)(struct ieee80211vap *, enum ieee80211_state,
@@ -49,6 +84,11 @@ struct ieee80211_tdma_state {
struct mbuf *, int, int, int, uint32_t);
void (*tdma_opdetach)(struct ieee80211vap *);
};
+
+#define TDMA_UPDATE_SLOT 0x0001 /* tdma_slot changed */
+#define TDMA_UPDATE_SLOTCNT 0x0002 /* tdma_slotcnt changed */
+#define TDMA_UPDATE_SLOTLEN 0x0004 /* tdma_slotlen changed */
+#define TDMA_UPDATE_BINTVAL 0x0008 /* tdma_bintval changed */
void ieee80211_tdma_vattach(struct ieee80211vap *);
@@ -58,9 +98,5 @@ uint8_t *ieee80211_add_tdma(uint8_t *frm, struct ieee80211vap *vap);
struct ieee80211_beacon_offsets;
void ieee80211_tdma_update_beacon(struct ieee80211vap *vap,
struct ieee80211_beacon_offsets *bo);
-struct ieee80211req;
-int ieee80211_tdma_ioctl_get80211(struct ieee80211vap *vap,
- struct ieee80211req *ireq);
-int ieee80211_tdma_ioctl_set80211(struct ieee80211vap *vap,
- struct ieee80211req *ireq);
+#endif /* _KERNEL */
#endif /* !_NET80211_IEEE80211_TDMA_H_ */
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index ace2c2f..4705047 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -47,6 +47,7 @@
#include <net80211/ieee80211_crypto.h>
#include <net80211/ieee80211_dfs.h>
#include <net80211/ieee80211_ioctl.h> /* for ieee80211_stats */
+#include <net80211/ieee80211_phy.h>
#include <net80211/ieee80211_power.h>
#include <net80211/ieee80211_node.h>
#include <net80211/ieee80211_proto.h>
@@ -106,6 +107,13 @@ struct ieee80211_appie {
};
struct ieee80211_tdma_param;
+struct ieee80211_rate_table;
+
+struct ieee80211_stageq {
+ struct mbuf *head; /* frames linked w/ m_nextpkt */
+ struct mbuf *tail; /* last frame in queue */
+ int depth; /* # items on head */
+};
struct ieee80211com {
struct ifnet *ic_ifp; /* associated device */
@@ -115,7 +123,6 @@ struct ieee80211com {
enum ieee80211_phytype ic_phytype; /* XXX wrong for multi-mode */
enum ieee80211_opmode ic_opmode; /* operation mode */
struct ifmedia ic_media; /* interface media config */
- uint8_t ic_myaddr[IEEE80211_ADDR_LEN];
struct callout ic_inact; /* inactivity processing */
struct task ic_parent_task; /* deferred parent processing */
@@ -162,6 +169,7 @@ struct ieee80211com {
uint8_t ic_chan_active[IEEE80211_CHAN_BYTES];
uint8_t ic_chan_scan[IEEE80211_CHAN_BYTES];
struct ieee80211_channel *ic_curchan; /* current channel */
+ const struct ieee80211_rate_table *ic_rt; /* table for ic_curchan */
struct ieee80211_channel *ic_bsschan; /* bss channel */
struct ieee80211_channel *ic_prevchan; /* previous channel */
struct ieee80211_regdomain ic_regdomain;/* regulatory data */
@@ -196,6 +204,10 @@ struct ieee80211com {
int ic_lastnonerp; /* last time non-ERP sta noted*/
int ic_lastnonht; /* last time non-HT sta noted */
+ /* fast-frames staging q */
+ struct ieee80211_stageq ic_ff_stageq[WME_NUM_AC];
+ int ic_stageqdepth; /* cumulative depth */
+
/* virtual ap create/delete */
struct ieee80211vap* (*ic_vap_create)(struct ieee80211com *,
const char name[IFNAMSIZ], int unit,
@@ -229,7 +241,7 @@ struct ieee80211com {
void (*ic_newassoc)(struct ieee80211_node *, int);
/* TDMA update notification */
void (*ic_tdma_update)(struct ieee80211_node *,
- const struct ieee80211_tdma_param *);
+ const struct ieee80211_tdma_param *, int);
/* node state management */
struct ieee80211_node* (*ic_node_alloc)(struct ieee80211vap *,
const uint8_t [IEEE80211_ADDR_LEN]);
@@ -520,8 +532,9 @@ MALLOC_DECLARE(M_80211_VAP);
#define IEEE80211_FVEN_BITS "\20"
/* ic_caps/iv_caps: device driver capabilities */
-/* 0x2f available */
+/* 0x2e available */
#define IEEE80211_C_STA 0x00000001 /* CAPABILITY: STA available */
+#define IEEE80211_C_8023ENCAP 0x00000002 /* CAPABILITY: 802.3 encap */
#define IEEE80211_C_FF 0x00000040 /* CAPABILITY: ATH FF avail */
#define IEEE80211_C_TURBOP 0x00000080 /* CAPABILITY: ATH Turbo avail*/
#define IEEE80211_C_IBSS 0x00000100 /* CAPABILITY: IBSS available */
@@ -553,7 +566,7 @@ MALLOC_DECLARE(M_80211_VAP);
IEEE80211_C_TDMA)
#define IEEE80211_C_BITS \
- "\20\1STA\7FF\10TURBOP\11IBSS\12PMGT" \
+ "\20\1STA\002803ENCAP\7FF\10TURBOP\11IBSS\12PMGT" \
"\13HOSTAP\14AHDEMO\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE" \
"\21MONITOR\22DFS\30WPA1\31WPA2\32BURST\33WME\34WDS\36BGSCAN" \
"\37TXFRAG\40TDMA"
@@ -575,7 +588,8 @@ MALLOC_DECLARE(M_80211_VAP);
"\20\1LDPC\2CHWIDTH40\5GREENFIELD\6SHORTGI20\7SHORTGI40\10TXSTBC" \
"\21AMPDU\22AMSDU\23HT\24SMPS\25RIFS"
-void ieee80211_ifattach(struct ieee80211com *);
+void ieee80211_ifattach(struct ieee80211com *,
+ const uint8_t macaddr[IEEE80211_ADDR_LEN]);
void ieee80211_ifdetach(struct ieee80211com *);
int ieee80211_vap_setup(struct ieee80211com *, struct ieee80211vap *,
const char name[IFNAMSIZ], int unit, int opmode, int flags,
@@ -702,7 +716,7 @@ ieee80211_htchanflags(const struct ieee80211_channel *c)
#define IEEE80211_MSG_DOT1XSM 0x00010000 /* 802.1x state machine */
#define IEEE80211_MSG_RADIUS 0x00008000 /* 802.1x radius client */
#define IEEE80211_MSG_RADDUMP 0x00004000 /* dump 802.1x radius packets */
-#define IEEE80211_MSG_RADKEYS 0x00002000 /* dump 802.1x keys */
+#define IEEE80211_MSG_MESH 0x00002000 /* mesh networking */
#define IEEE80211_MSG_WPA 0x00001000 /* WPA/RSN protocol */
#define IEEE80211_MSG_ACL 0x00000800 /* ACL handling */
#define IEEE80211_MSG_WME 0x00000400 /* WME protocol */
diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c
index 2501cb50..27b995a 100644
--- a/sys/net80211/ieee80211_wds.c
+++ b/sys/net80211/ieee80211_wds.c
@@ -57,6 +57,9 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_var.h>
#include <net80211/ieee80211_wds.h>
#include <net80211/ieee80211_input.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
static void wds_vattach(struct ieee80211vap *);
static int wds_newstate(struct ieee80211vap *, enum ieee80211_state, int);
@@ -247,9 +250,7 @@ ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m)
if (ifp == m->m_pkthdr.rcvif)
continue;
/*
- * Duplicate the frame and send it. We don't need
- * to classify or lookup the tx node; this was already
- * done by the caller so we can just re-use the info.
+ * Duplicate the frame and send it.
*/
mcopy = m_copypacket(m, M_DONTWAIT);
if (mcopy == NULL) {
@@ -264,6 +265,7 @@ ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m)
m_freem(mcopy);
continue;
}
+ /* calculate priority so drivers can find the tx queue */
if (ieee80211_classify(ni, mcopy)) {
IEEE80211_DISCARD_MAC(vap,
IEEE80211_MSG_OUTPUT | IEEE80211_MSG_WDS,
@@ -275,7 +277,16 @@ ieee80211_dwds_mcast(struct ieee80211vap *vap0, struct mbuf *m)
ieee80211_free_node(ni);
continue;
}
- mcopy->m_flags |= M_MCAST | M_WDS;
+ /*
+ * Encapsulate the packet in prep for transmission.
+ */
+ mcopy = ieee80211_encap(vap, ni, mcopy);
+ if (m == NULL) {
+ /* NB: stat+msg handled in ieee80211_encap */
+ ieee80211_free_node(ni);
+ continue;
+ }
+ mcopy->m_flags |= M_MCAST;
mcopy->m_pkthdr.rcvif = (void *) ni;
err = parent->if_transmit(parent, mcopy);
@@ -728,32 +739,13 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m,
m = ieee80211_decap_amsdu(ni, m);
if (m == NULL)
return IEEE80211_FC0_TYPE_DATA;
- } else if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF) &&
-#define FF_LLC_SIZE (sizeof(struct ether_header) + sizeof(struct llc))
- m->m_pkthdr.len >= 3*FF_LLC_SIZE) {
- struct llc *llc;
-
- /*
- * Check for fast-frame tunnel encapsulation.
- */
- if (m->m_len < FF_LLC_SIZE &&
- (m = m_pullup(m, FF_LLC_SIZE)) == NULL) {
- IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
- ni->ni_macaddr, "fast-frame",
- "%s", "m_pullup(llc) failed");
- vap->iv_stats.is_rx_tooshort++;
+ } else {
+#ifdef IEEE80211_SUPPORT_SUPERG
+ m = ieee80211_decap_fastframe(vap, ni, m);
+ if (m == NULL)
return IEEE80211_FC0_TYPE_DATA;
- }
- llc = (struct llc *)(mtod(m, uint8_t *) +
- sizeof(struct ether_header));
- if (llc->llc_snap.ether_type == htons(ATH_FF_ETH_TYPE)) {
- m_adj(m, FF_LLC_SIZE);
- m = ieee80211_decap_fastframe(ni, m);
- if (m == NULL)
- return IEEE80211_FC0_TYPE_DATA;
- }
+#endif
}
-#undef FF_LLC_SIZE
ieee80211_deliver_data(vap, ni, m);
return IEEE80211_FC0_TYPE_DATA;
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h
index fcdc9ce..ad5f7bc 100644
--- a/sys/netinet/icmp6.h
+++ b/sys/netinet/icmp6.h
@@ -596,6 +596,11 @@ struct icmp6stat {
u_quad_t icp6s_badredirect; /* bad redirect message */
};
+#ifdef _KERNEL
+#define ICMP6STAT_ADD(name, val) V_icmp6stat.name += (val)
+#define ICMP6STAT_INC(name) ICMP6STAT_ADD(name, 1)
+#endif
+
/*
* Names for ICMP sysctl objects
*/
diff --git a/sys/netinet/icmp_var.h b/sys/netinet/icmp_var.h
index cd9ee00..8d7b9de 100644
--- a/sys/netinet/icmp_var.h
+++ b/sys/netinet/icmp_var.h
@@ -57,6 +57,11 @@ struct icmpstat {
u_long icps_noroute; /* no route back */
};
+#ifdef _KERNEL
+#define ICMPSTAT_ADD(name, val) V_icmpstat.name += (val)
+#define ICMPSTAT_INC(name) ICMPSTAT_ADD(name, 1)
+#endif
+
/*
* Names for ICMP sysctl objects
*/
diff --git a/sys/netinet/if_ether.c b/sys/netinet/if_ether.c
index a918415..4aae7d3 100644
--- a/sys/netinet/if_ether.c
+++ b/sys/netinet/if_ether.c
@@ -111,6 +111,7 @@ SYSCTL_V_INT(V_NET, vnet_inet, _net_link_ether_inet, OID_AUTO, proxyall,
"Enable proxy ARP for all suitable requests");
static void arp_init(void);
+static int arp_iattach(const void *);
void arprequest(struct ifnet *,
struct in_addr *, struct in_addr *, u_char *);
static void arpintr(struct mbuf *);
@@ -119,6 +120,15 @@ static void arptimer(void *);
static void in_arpinput(struct mbuf *);
#endif
+#ifndef VIMAGE_GLOBALS
+static const vnet_modinfo_t vnet_arp_modinfo = {
+ .vmi_id = VNET_MOD_ARP,
+ .vmi_name = "arp",
+ .vmi_dependson = VNET_MOD_INET,
+ .vmi_iattach = arp_iattach
+};
+#endif /* !VIMAGE_GLOBALS */
+
#ifdef AF_INET
void arp_ifscrub(struct ifnet *ifp, uint32_t addr);
@@ -790,8 +800,8 @@ arp_ifinit2(struct ifnet *ifp, struct ifaddr *ifa, u_char *enaddr)
ifa->ifa_rtrequest = NULL;
}
-static void
-arp_init(void)
+static int
+arp_iattach(const void *unused __unused)
{
INIT_VNET_INET(curvnet);
@@ -800,6 +810,19 @@ arp_init(void)
V_useloopback = 1; /* use loopback interface for local traffic */
V_arp_proxyall = 0;
+ return (0);
+}
+
+static void
+arp_init(void)
+{
+
+#ifndef VIMAGE_GLOBALS
+ vnet_mod_register(&vnet_arp_modinfo);
+#else
+ arp_iattach(NULL);
+#endif
+
arpintrq.ifq_maxlen = 50;
mtx_init(&arpintrq.ifq_mtx, "arp_inq", NULL, MTX_DEF);
netisr_register(NETISR_ARP, arpintr, &arpintrq, 0);
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c
index 31e8306..6f3286f 100644
--- a/sys/netinet/igmp.c
+++ b/sys/netinet/igmp.c
@@ -183,6 +183,11 @@ static int vnet_igmp_idetach(const void *);
* VIMAGE: Each in_multi corresponds to an ifp, and each ifp corresponds
* to a vnet in ifp->if_vnet.
*
+ * SMPng: XXX We may potentially race operations on ifma_protospec.
+ * The problem is that we currently lack a clean way of taking the
+ * IF_ADDR_LOCK() between the ifnet and in layers w/o recursing,
+ * as anything which modifies ifma needs to be covered by that lock.
+ * So check for ifma_protospec being NULL before proceeding.
*/
struct mtx igmp_mtx;
int mpsafe_igmp = 0;
@@ -601,6 +606,7 @@ out:
* is detached, but also before the link layer does its cleanup.
*
* SMPNG: igmp_ifdetach() needs to take IF_ADDR_LOCK().
+ * XXX This is also bitten by unlocked ifma_protospec access.
*
* VIMAGE: curvnet should have been set by caller, but let's not assume
* that for now.
@@ -623,8 +629,13 @@ igmp_ifdetach(struct ifnet *ifp)
if (igi->igi_version == IGMP_VERSION_3) {
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_INET)
+ if (ifma->ifma_addr->sa_family != AF_INET ||
+ ifma->ifma_protospec == NULL)
continue;
+#if 0
+ KASSERT(ifma->ifma_protospec != NULL,
+ ("%s: ifma_protospec is NULL", __func__));
+#endif
inm = (struct in_multi *)ifma->ifma_protospec;
if (inm->inm_state == IGMP_LEAVING_MEMBER) {
SLIST_INSERT_HEAD(&igi->igi_relinmhead,
@@ -751,11 +762,11 @@ igmp_input_v1_query(struct ifnet *ifp, const struct ip *ip)
* daemon may wish to see it.
*/
if (!in_allhosts(ip->ip_dst)) {
- ++V_igmpstat.igps_rcv_badqueries;
+ IGMPSTAT_INC(igps_rcv_badqueries);
return (0);
}
- ++V_igmpstat.igps_rcv_gen_queries;
+ IGMPSTAT_INC(igps_rcv_gen_queries);
/*
* Switch to IGMPv1 host compatibility mode.
@@ -783,7 +794,8 @@ igmp_input_v1_query(struct ifnet *ifp, const struct ip *ip)
*/
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_INET)
+ if (ifma->ifma_addr->sa_family != AF_INET ||
+ ifma->ifma_protospec == NULL)
continue;
inm = (struct in_multi *)ifma->ifma_protospec;
if (inm->inm_timer != 0)
@@ -863,7 +875,7 @@ igmp_input_v2_query(struct ifnet *ifp, const struct ip *ip,
inet_ntoa(igmp->igmp_group), ifp, ifp->if_xname);
igmp_v2_update_group(inm, timer);
}
- ++V_igmpstat.igps_rcv_group_queries;
+ IGMPSTAT_INC(igps_rcv_group_queries);
} else {
/*
* IGMPv2 General Query.
@@ -880,14 +892,15 @@ igmp_input_v2_query(struct ifnet *ifp, const struct ip *ip,
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_INET)
+ if (ifma->ifma_addr->sa_family != AF_INET ||
+ ifma->ifma_protospec == NULL)
continue;
inm = (struct in_multi *)ifma->ifma_protospec;
igmp_v2_update_group(inm, timer);
}
IF_ADDR_UNLOCK(ifp);
}
- ++V_igmpstat.igps_rcv_gen_queries;
+ IGMPSTAT_INC(igps_rcv_gen_queries);
}
out_locked:
@@ -991,8 +1004,8 @@ igmp_input_v3_query(struct ifnet *ifp, const struct ip *ip,
qqi = igmpv3->igmp_qqi;
if (qqi >= 128) {
- maxresp = IGMP_MANT(igmpv3->igmp_qqi) <<
- (IGMP_EXP(igmpv3->igmp_qqi) + 3);
+ qqi = IGMP_MANT(igmpv3->igmp_qqi) <<
+ (IGMP_EXP(igmpv3->igmp_qqi) + 3);
}
timer = maxresp * PR_FASTHZ / IGMP_TIMER_SCALE;
@@ -1028,7 +1041,7 @@ igmp_input_v3_query(struct ifnet *ifp, const struct ip *ip,
* Schedule a current-state report on this ifp for
* all groups, possibly containing source lists.
*/
- ++V_igmpstat.igps_rcv_gen_queries;
+ IGMPSTAT_INC(igps_rcv_gen_queries);
if (!in_allhosts(ip->ip_dst) || nsrc > 0) {
/*
@@ -1036,7 +1049,7 @@ igmp_input_v3_query(struct ifnet *ifp, const struct ip *ip,
* A general query with a source list has undefined
* behaviour; discard it.
*/
- ++V_igmpstat.igps_rcv_badqueries;
+ IGMPSTAT_INC(igps_rcv_badqueries);
goto out_locked;
}
@@ -1066,16 +1079,16 @@ igmp_input_v3_query(struct ifnet *ifp, const struct ip *ip,
if (inm == NULL)
goto out_locked;
if (nsrc > 0) {
- ++V_igmpstat.igps_rcv_gsr_queries;
+ IGMPSTAT_INC(igps_rcv_gsr_queries);
if (!ratecheck(&inm->inm_lastgsrtv,
&V_igmp_gsrdelay)) {
CTR1(KTR_IGMPV3, "%s: GS query throttled.",
__func__);
- ++V_igmpstat.igps_drop_gsr_queries;
+ IGMPSTAT_INC(igps_drop_gsr_queries);
goto out_locked;
}
} else {
- ++V_igmpstat.igps_rcv_group_queries;
+ IGMPSTAT_INC(igps_rcv_group_queries);
}
CTR3(KTR_IGMPV3, "process v3 %s query on ifp %p(%s)",
inet_ntoa(igmpv3->igmp_group), ifp, ifp->if_xname);
@@ -1211,14 +1224,14 @@ igmp_input_v1_report(struct ifnet *ifp, /*const*/ struct ip *ip,
struct in_ifaddr *ia;
struct in_multi *inm;
- ++V_igmpstat.igps_rcv_reports;
+ IGMPSTAT_INC(igps_rcv_reports);
if (ifp->if_flags & IFF_LOOPBACK)
return (0);
if (!IN_MULTICAST(ntohl(igmp->igmp_group.s_addr) ||
!in_hosteq(igmp->igmp_group, ip->ip_dst))) {
- ++V_igmpstat.igps_rcv_badreports;
+ IGMPSTAT_INC(igps_rcv_badreports);
return (EINVAL);
}
@@ -1255,7 +1268,7 @@ igmp_input_v1_report(struct ifnet *ifp, /*const*/ struct ip *ip,
goto out_locked;
}
- ++V_igmpstat.igps_rcv_ourreports;
+ IGMPSTAT_INC(igps_rcv_ourreports);
/*
* If we are in IGMPv3 host mode, do not allow the
@@ -1326,14 +1339,14 @@ igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip,
if (ia != NULL && in_hosteq(ip->ip_src, IA_SIN(ia)->sin_addr))
return (0);
- ++V_igmpstat.igps_rcv_reports;
+ IGMPSTAT_INC(igps_rcv_reports);
if (ifp->if_flags & IFF_LOOPBACK)
return (0);
if (!IN_MULTICAST(ntohl(igmp->igmp_group.s_addr)) ||
!in_hosteq(igmp->igmp_group, ip->ip_dst)) {
- ++V_igmpstat.igps_rcv_badreports;
+ IGMPSTAT_INC(igps_rcv_badreports);
return (EINVAL);
}
@@ -1366,7 +1379,7 @@ igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip,
igi = inm->inm_igi;
KASSERT(igi != NULL, ("%s: no igi for ifp %p", __func__, ifp));
- ++V_igmpstat.igps_rcv_ourreports;
+ IGMPSTAT_INC(igps_rcv_ourreports);
/*
* If we are in IGMPv3 host mode, do not allow the
@@ -1424,7 +1437,7 @@ igmp_input(struct mbuf *m, int off)
ifp = m->m_pkthdr.rcvif;
INIT_VNET_INET(ifp->if_vnet);
- ++V_igmpstat.igps_rcv_total;
+ IGMPSTAT_INC(igps_rcv_total);
ip = mtod(m, struct ip *);
iphlen = off;
@@ -1434,7 +1447,7 @@ igmp_input(struct mbuf *m, int off)
* Validate lengths.
*/
if (igmplen < IGMP_MINLEN) {
- ++V_igmpstat.igps_rcv_tooshort;
+ IGMPSTAT_INC(igps_rcv_tooshort);
m_freem(m);
return;
}
@@ -1450,13 +1463,13 @@ igmp_input(struct mbuf *m, int off)
minlen += IGMP_MINLEN;
if ((m->m_flags & M_EXT || m->m_len < minlen) &&
(m = m_pullup(m, minlen)) == 0) {
- ++V_igmpstat.igps_rcv_tooshort;
+ IGMPSTAT_INC(igps_rcv_tooshort);
return;
}
ip = mtod(m, struct ip *);
if (ip->ip_ttl != 1) {
- ++V_igmpstat.igps_rcv_badttl;
+ IGMPSTAT_INC(igps_rcv_badttl);
m_freem(m);
return;
}
@@ -1468,7 +1481,7 @@ igmp_input(struct mbuf *m, int off)
m->m_len -= iphlen;
igmp = mtod(m, struct igmp *);
if (in_cksum(m, igmplen)) {
- ++V_igmpstat.igps_rcv_badsum;
+ IGMPSTAT_INC(igps_rcv_badsum);
m_freem(m);
return;
}
@@ -1485,14 +1498,14 @@ igmp_input(struct mbuf *m, int off)
} else if (igmplen >= IGMP_V3_QUERY_MINLEN) {
queryver = IGMP_VERSION_3;
} else {
- ++V_igmpstat.igps_rcv_tooshort;
+ IGMPSTAT_INC(igps_rcv_tooshort);
m_freem(m);
return;
}
switch (queryver) {
case IGMP_VERSION_1:
- ++V_igmpstat.igps_rcv_v1v2_queries;
+ IGMPSTAT_INC(igps_rcv_v1v2_queries);
if (!V_igmp_v1enable)
break;
if (igmp_input_v1_query(ifp, ip) != 0) {
@@ -1502,7 +1515,7 @@ igmp_input(struct mbuf *m, int off)
break;
case IGMP_VERSION_2:
- ++V_igmpstat.igps_rcv_v1v2_queries;
+ IGMPSTAT_INC(igps_rcv_v1v2_queries);
if (!V_igmp_v2enable)
break;
if (igmp_input_v2_query(ifp, ip, igmp) != 0) {
@@ -1517,7 +1530,7 @@ igmp_input(struct mbuf *m, int off)
uint16_t srclen;
int nsrc;
- ++V_igmpstat.igps_rcv_v3_queries;
+ IGMPSTAT_INC(igps_rcv_v3_queries);
igmpv3 = (struct igmpv3 *)igmp;
/*
* Validate length based on source count.
@@ -1525,7 +1538,7 @@ igmp_input(struct mbuf *m, int off)
nsrc = ntohs(igmpv3->igmp_numsrc);
srclen = sizeof(struct in_addr) * nsrc;
if (nsrc * sizeof(in_addr_t) > srclen) {
- ++V_igmpstat.igps_rcv_tooshort;
+ IGMPSTAT_INC(igps_rcv_tooshort);
return;
}
/*
@@ -1537,7 +1550,7 @@ igmp_input(struct mbuf *m, int off)
if ((m->m_flags & M_EXT ||
m->m_len < igmpv3len) &&
(m = m_pullup(m, igmpv3len)) == NULL) {
- ++V_igmpstat.igps_rcv_tooshort;
+ IGMPSTAT_INC(igps_rcv_tooshort);
return;
}
igmpv3 = (struct igmpv3 *)(mtod(m, uint8_t *)
@@ -1564,7 +1577,7 @@ igmp_input(struct mbuf *m, int off)
if (!V_igmp_v2enable)
break;
if (!ip_checkrouteralert(m))
- ++V_igmpstat.igps_rcv_nora;
+ IGMPSTAT_INC(igps_rcv_nora);
if (igmp_input_v2_report(ifp, ip, igmp) != 0) {
m_freem(m);
return;
@@ -1577,7 +1590,7 @@ igmp_input(struct mbuf *m, int off)
* as report suppression is no longer required.
*/
if (!ip_checkrouteralert(m))
- ++V_igmpstat.igps_rcv_nora;
+ IGMPSTAT_INC(igps_rcv_nora);
break;
default:
@@ -1701,7 +1714,8 @@ igmp_fasttimo_vnet(void)
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link,
tifma) {
- if (ifma->ifma_addr->sa_family != AF_INET)
+ if (ifma->ifma_addr->sa_family != AF_INET ||
+ ifma->ifma_protospec == NULL)
continue;
inm = (struct in_multi *)ifma->ifma_protospec;
switch (igi->igi_version) {
@@ -2770,8 +2784,11 @@ igmp_v3_enqueue_group_record(struct ifqueue *ifq, struct in_multi *inm,
m = NULL;
m0srcs = (ifp->if_mtu - IGMP_LEADINGSPACE -
sizeof(struct igmp_grouprec)) / sizeof(in_addr_t);
- if (!is_state_change && !is_group_query)
+ if (!is_state_change && !is_group_query) {
m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (m)
+ m->m_data += IGMP_LEADINGSPACE;
+ }
if (m == NULL) {
m = m_gethdr(M_DONTWAIT, MT_DATA);
if (m)
@@ -2779,7 +2796,6 @@ igmp_v3_enqueue_group_record(struct ifqueue *ifq, struct in_multi *inm,
}
if (m == NULL)
return (-ENOMEM);
- m->m_data += IGMP_LEADINGSPACE;
igmp_save_context(m, ifp);
@@ -2895,6 +2911,8 @@ igmp_v3_enqueue_group_record(struct ifqueue *ifq, struct in_multi *inm,
return (-ENOMEM);
}
m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (m)
+ m->m_data += IGMP_LEADINGSPACE;
if (m == NULL) {
m = m_gethdr(M_DONTWAIT, MT_DATA);
if (m)
@@ -2903,7 +2921,6 @@ igmp_v3_enqueue_group_record(struct ifqueue *ifq, struct in_multi *inm,
if (m == NULL)
return (-ENOMEM);
igmp_save_context(m, ifp);
- m->m_data += IGMP_LEADINGSPACE;
md = m_getptr(m, 0, &off);
pig = (struct igmp_grouprec *)(mtod(md, uint8_t *) + off);
CTR1(KTR_IGMPV3, "%s: allocated next packet", __func__);
@@ -3049,6 +3066,8 @@ igmp_v3_enqueue_filter_change(struct ifqueue *ifq, struct in_multi *inm)
"%s: use previous packet", __func__);
} else {
m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
+ if (m)
+ m->m_data += IGMP_LEADINGSPACE;
if (m == NULL) {
m = m_gethdr(M_DONTWAIT, MT_DATA);
if (m)
@@ -3061,7 +3080,6 @@ igmp_v3_enqueue_filter_change(struct ifqueue *ifq, struct in_multi *inm)
}
m->m_pkthdr.PH_vt.vt_nrecs = 0;
igmp_save_context(m, ifp);
- m->m_data += IGMP_LEADINGSPACE;
m0srcs = (ifp->if_mtu - IGMP_LEADINGSPACE -
sizeof(struct igmp_grouprec)) /
sizeof(in_addr_t);
@@ -3311,7 +3329,8 @@ igmp_v3_dispatch_general_query(struct igmp_ifinfo *igi)
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, tifma) {
- if (ifma->ifma_addr->sa_family != AF_INET)
+ if (ifma->ifma_addr->sa_family != AF_INET ||
+ ifma->ifma_protospec == NULL)
continue;
inm = (struct in_multi *)ifma->ifma_protospec;
@@ -3394,7 +3413,7 @@ igmp_intr(struct mbuf *m)
CTR3(KTR_IGMPV3, "%s: dropped %p as ifindex %u went away.",
__func__, m, ifindex);
m_freem(m);
- V_ipstat.ips_noroute++;
+ IPSTAT_INC(ips_noroute);
goto out;
}
@@ -3422,7 +3441,7 @@ igmp_intr(struct mbuf *m)
if (m0 == NULL) {
CTR2(KTR_IGMPV3, "%s: dropped %p", __func__, m);
m_freem(m);
- V_ipstat.ips_odropped++;
+ IPSTAT_INC(ips_odropped);
goto out;
}
}
@@ -3436,11 +3455,10 @@ igmp_intr(struct mbuf *m)
error = ip_output(m0, ipopts, NULL, 0, &imo, NULL);
if (error) {
CTR3(KTR_IGMPV3, "%s: ip_output(%p) = %d", __func__, m0, error);
- m_freem(m0);
goto out;
}
- ++V_igmpstat.igps_snd_reports;
+ IGMPSTAT_INC(igps_snd_reports);
out:
/*
diff --git a/sys/netinet/igmp.h b/sys/netinet/igmp.h
index 186142d..ab5d4cf 100644
--- a/sys/netinet/igmp.h
+++ b/sys/netinet/igmp.h
@@ -108,7 +108,7 @@ struct igmp_report {
#define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* membership query */
#define IGMP_v1_HOST_MEMBERSHIP_REPORT 0x12 /* Ver. 1 membership report */
#define IGMP_DVMRP 0x13 /* DVMRP routing message */
-#define IGMP_PIM 0x14 /* PIM routing message */
+#define IGMP_PIM 0x14 /* PIMv1 message (historic) */
#define IGMP_v2_HOST_MEMBERSHIP_REPORT 0x16 /* Ver. 2 membership report */
#define IGMP_HOST_LEAVE_MESSAGE 0x17 /* Leave-group message */
#define IGMP_MTRACE_REPLY 0x1e /* mtrace(8) reply */
diff --git a/sys/netinet/igmp_var.h b/sys/netinet/igmp_var.h
index 9c9c7d4..ca17158 100644
--- a/sys/netinet/igmp_var.h
+++ b/sys/netinet/igmp_var.h
@@ -106,6 +106,11 @@ struct igmpstat {
#define IGPS_VERSION_3 3 /* as of FreeBSD 8.x */
#define IGPS_VERSION3_LEN 168
+#ifdef _KERNEL
+#define IGMPSTAT_ADD(name, val) V_igmpstat.name += (val)
+#define IGMPSTAT_INC(name) IGMPSTAT_ADD(name, 1)
+#endif
+
#ifdef CTASSERT
CTASSERT(sizeof(struct igmpstat) == 168);
#endif
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index e2834bf..1423e81 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -397,10 +397,8 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
oldaddr = ia->ia_dstaddr;
ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
if (ifp->if_ioctl != NULL) {
- IFF_LOCKGIANT(ifp);
error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR,
(caddr_t)ia);
- IFF_UNLOCKGIANT(ifp);
if (error) {
ia->ia_dstaddr = oldaddr;
return (error);
@@ -507,10 +505,7 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
default:
if (ifp == NULL || ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
- IFF_LOCKGIANT(ifp);
- error = (*ifp->if_ioctl)(ifp, cmd, data);
- IFF_UNLOCKGIANT(ifp);
- return (error);
+ return ((*ifp->if_ioctl)(ifp, cmd, data));
}
/*
@@ -531,7 +526,6 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
IFP_TO_IA(ifp, oia);
if (oia == NULL) {
ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]);
- IFF_LOCKGIANT(ifp);
IN_MULTI_LOCK();
if (ii->ii_allhosts) {
(void)in_leavegroup_locked(ii->ii_allhosts,
@@ -539,7 +533,6 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
ii->ii_allhosts = NULL;
}
IN_MULTI_UNLOCK();
- IFF_UNLOCKGIANT(ifp);
}
}
IFAFREE(&ia->ia_ifa);
@@ -753,9 +746,7 @@ in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia, struct sockaddr_in *sin,
* and to validate the address if necessary.
*/
if (ifp->if_ioctl != NULL) {
- IFF_LOCKGIANT(ifp);
error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
- IFF_UNLOCKGIANT(ifp);
if (error) {
splx(s);
/* LIST_REMOVE(ia, ia_hash) is done in in_control */
@@ -1020,6 +1011,8 @@ in_ifdetach(struct ifnet *ifp)
* Delete all IPv4 multicast address records, and associated link-layer
* multicast address records, associated with ifp.
* XXX It looks like domifdetach runs AFTER the link layer cleanup.
+ * XXX This should not race with ifma_protospec being set during
+ * a new allocation, if it does, we have bigger problems.
*/
static void
in_purgemaddrs(struct ifnet *ifp)
@@ -1040,8 +1033,13 @@ in_purgemaddrs(struct ifnet *ifp)
*/
IF_ADDR_LOCK(ifp);
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
- if (ifma->ifma_addr->sa_family != AF_INET)
+ if (ifma->ifma_addr->sa_family != AF_INET ||
+ ifma->ifma_protospec == NULL)
continue;
+#if 0
+ KASSERT(ifma->ifma_protospec != NULL,
+ ("%s: ifma_protospec is NULL", __func__));
+#endif
inm = (struct in_multi *)ifma->ifma_protospec;
LIST_INSERT_HEAD(&purgeinms, inm, inm_link);
}
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index 4b2c827..dd302a5 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -120,7 +120,7 @@ struct sockaddr_in {
char sin_zero[8];
};
-#ifndef _KERNEL
+#if !defined(_KERNEL) && __BSD_VISIBLE
#ifndef _BYTEORDER_PROTOTYPED
#define _BYTEORDER_PROTOTYPED
@@ -140,7 +140,7 @@ __END_DECLS
#define ntohs(x) __ntohs(x)
#endif
-#endif /* !_KERNEL */
+#endif /* !_KERNEL && __BSD_VISIBLE */
#if __POSIX_VISIBLE >= 200112
#define IPPROTO_RAW 255 /* raw IP packet */
diff --git a/sys/netinet/in_gif.c b/sys/netinet/in_gif.c
index a05c04b..bc62f5f 100644
--- a/sys/netinet/in_gif.c
+++ b/sys/netinet/in_gif.c
@@ -273,14 +273,14 @@ in_gif_input(struct mbuf *m, int off)
sc = (struct gif_softc *)encap_getarg(m);
if (sc == NULL) {
m_freem(m);
- V_ipstat.ips_nogif++;
+ IPSTAT_INC(ips_nogif);
return;
}
gifp = GIF2IFP(sc);
if (gifp == NULL || (gifp->if_flags & IFF_UP) == 0) {
m_freem(m);
- V_ipstat.ips_nogif++;
+ IPSTAT_INC(ips_nogif);
return;
}
@@ -340,7 +340,7 @@ in_gif_input(struct mbuf *m, int off)
break;
default:
- V_ipstat.ips_nogif++;
+ IPSTAT_INC(ips_nogif);
m_freem(m);
return;
}
diff --git a/sys/netinet/in_mcast.c b/sys/netinet/in_mcast.c
index 0c7e7e1..9c04916 100644
--- a/sys/netinet/in_mcast.c
+++ b/sys/netinet/in_mcast.c
@@ -432,6 +432,9 @@ in_getmulti(struct ifnet *ifp, const struct in_addr *group,
if (error != 0)
return (error);
+ /* XXX ifma_protospec must be covered by IF_ADDR_LOCK */
+ IF_ADDR_LOCK(ifp);
+
/*
* If something other than netinet is occupying the link-layer
* group, print a meaningful error message and back out of
@@ -454,9 +457,12 @@ in_getmulti(struct ifnet *ifp, const struct in_addr *group,
#endif
++inm->inm_refcount;
*pinm = inm;
+ IF_ADDR_UNLOCK(ifp);
return (0);
}
+ IF_ADDR_LOCK_ASSERT(ifp);
+
/*
* A new in_multi record is needed; allocate and initialize it.
* We DO NOT perform an IGMP join as the in_ layer may need to
@@ -467,6 +473,7 @@ in_getmulti(struct ifnet *ifp, const struct in_addr *group,
inm = malloc(sizeof(*inm), M_IPMADDR, M_NOWAIT | M_ZERO);
if (inm == NULL) {
if_delmulti_ifma(ifma);
+ IF_ADDR_UNLOCK(ifp);
return (ENOMEM);
}
inm->inm_addr = *group;
@@ -489,6 +496,7 @@ in_getmulti(struct ifnet *ifp, const struct in_addr *group,
*pinm = inm;
+ IF_ADDR_UNLOCK(ifp);
return (0);
}
@@ -522,6 +530,7 @@ inm_release_locked(struct in_multi *inm)
ifma = inm->inm_ifma;
+ /* XXX this access is not covered by IF_ADDR_LOCK */
CTR2(KTR_IGMPV3, "%s: purging ifma %p", __func__, ifma);
KASSERT(ifma->ifma_protospec == inm,
("%s: ifma_protospec != inm", __func__));
@@ -1100,11 +1109,9 @@ in_joingroup(struct ifnet *ifp, const struct in_addr *gina,
{
int error;
- IFF_LOCKGIANT(ifp);
IN_MULTI_LOCK();
error = in_joingroup_locked(ifp, gina, imf, pinm);
IN_MULTI_UNLOCK();
- IFF_UNLOCKGIANT(ifp);
return (error);
}
@@ -1181,20 +1188,14 @@ int
in_leavegroup(struct in_multi *inm, /*const*/ struct in_mfilter *imf)
{
struct ifnet *ifp;
- int detached, error;
+ int error;
- detached = inm_is_ifp_detached(inm);
ifp = inm->inm_ifp;
- if (!detached)
- IFF_LOCKGIANT(ifp);
IN_MULTI_LOCK();
error = in_leavegroup_locked(inm, imf);
IN_MULTI_UNLOCK();
- if (!detached)
- IFF_UNLOCKGIANT(ifp);
-
return (error);
}
@@ -1396,8 +1397,6 @@ inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt)
if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
return (EINVAL);
- IFF_LOCKGIANT(ifp);
-
/*
* Check if we are actually a member of this group.
*/
@@ -1486,7 +1485,6 @@ out_imf_rollback:
out_inp_locked:
INP_WUNLOCK(inp);
- IFF_UNLOCKGIANT(ifp);
return (error);
}
@@ -1978,8 +1976,6 @@ inp_join_group(struct inpcb *inp, struct sockopt *sopt)
if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0)
return (EADDRNOTAVAIL);
- IFF_LOCKGIANT(ifp);
-
/*
* MCAST_JOIN_SOURCE on an exclusive membership is an error.
* On an existing inclusive membership, it just adds the
@@ -2102,7 +2098,6 @@ out_imo_free:
out_inp_locked:
INP_WUNLOCK(inp);
- IFF_UNLOCKGIANT(ifp);
return (error);
}
@@ -2215,9 +2210,6 @@ inp_leave_group(struct inpcb *inp, struct sockopt *sopt)
if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
return (EINVAL);
- if (ifp)
- IFF_LOCKGIANT(ifp);
-
/*
* Find the membership in the membership array.
*/
@@ -2312,8 +2304,6 @@ out_imf_rollback:
out_inp_locked:
INP_WUNLOCK(inp);
- if (ifp)
- IFF_UNLOCKGIANT(ifp);
return (error);
}
@@ -2432,8 +2422,6 @@ inp_set_source_filters(struct inpcb *inp, struct sockopt *sopt)
if (ifp == NULL)
return (EADDRNOTAVAIL);
- IFF_LOCKGIANT(ifp);
-
/*
* Take the INP write lock.
* Check if this socket is a member of this group.
@@ -2551,7 +2539,6 @@ out_imf_rollback:
out_inp_locked:
INP_WUNLOCK(inp);
- IFF_UNLOCKGIANT(ifp);
return (error);
}
@@ -2851,7 +2838,7 @@ inm_print(const struct in_multi *inm)
{
int t;
- if ((KTR_COMPILE & KTR_IGMPV3) == 0)
+ if ((ktr_mask & KTR_IGMPV3) == 0)
return;
printf("%s: --- begin inm %p ---\n", __func__, inm);
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 6703c88..a10da084 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -384,7 +384,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
* This entire block sorely needs a rewrite.
*/
if (t &&
- ((t->inp_vflag & INP_TIMEWAIT) == 0) &&
+ ((t->inp_flags & INP_TIMEWAIT) == 0) &&
(so->so_type != SOCK_STREAM ||
ntohl(t->inp_faddr.s_addr) == INADDR_ANY) &&
(ntohl(sin->sin_addr.s_addr) != INADDR_ANY ||
@@ -397,7 +397,7 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
}
t = in_pcblookup_local(pcbinfo, sin->sin_addr,
lport, wild, cred);
- if (t && (t->inp_vflag & INP_TIMEWAIT)) {
+ if (t && (t->inp_flags & INP_TIMEWAIT)) {
/*
* XXXRW: If an incpb has had its timewait
* state recycled, we treat the address as
@@ -1031,7 +1031,7 @@ in_pcbdrop(struct inpcb *inp)
INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
INP_WLOCK_ASSERT(inp);
- inp->inp_vflag |= INP_DROPPED;
+ inp->inp_flags |= INP_DROPPED;
if (inp->inp_flags & INP_INHASHLIST) {
struct inpcbport *phd = inp->inp_phd;
@@ -1818,6 +1818,22 @@ db_print_inpflags(int inp_flags)
db_printf("%sIN6P_AUTOFLOWLABEL", comma ? ", " : "");
comma = 1;
}
+ if (inp_flags & INP_TIMEWAIT) {
+ db_printf("%sINP_TIMEWAIT", comma ? ", " : "");
+ comma = 1;
+ }
+ if (inp_flags & INP_ONESBCAST) {
+ db_printf("%sINP_ONESBCAST", comma ? ", " : "");
+ comma = 1;
+ }
+ if (inp_flags & INP_DROPPED) {
+ db_printf("%sINP_DROPPED", comma ? ", " : "");
+ comma = 1;
+ }
+ if (inp_flags & INP_SOCKREF) {
+ db_printf("%sINP_SOCKREF", comma ? ", " : "");
+ comma = 1;
+ }
if (inp_flags & IN6P_RFC2292) {
db_printf("%sIN6P_RFC2292", comma ? ", " : "");
comma = 1;
@@ -1846,22 +1862,6 @@ db_print_inpvflag(u_char inp_vflag)
db_printf("%sINP_IPV6PROTO", comma ? ", " : "");
comma = 1;
}
- if (inp_vflag & INP_TIMEWAIT) {
- db_printf("%sINP_TIMEWAIT", comma ? ", " : "");
- comma = 1;
- }
- if (inp_vflag & INP_ONESBCAST) {
- db_printf("%sINP_ONESBCAST", comma ? ", " : "");
- comma = 1;
- }
- if (inp_vflag & INP_DROPPED) {
- db_printf("%sINP_DROPPED", comma ? ", " : "");
- comma = 1;
- }
- if (inp_vflag & INP_SOCKREF) {
- db_printf("%sINP_SOCKREF", comma ? ", " : "");
- comma = 1;
- }
}
void
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index 677b974..aada126 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -167,7 +167,7 @@ struct inpcb {
u_char inp_ip_ttl; /* (i) time to live proto */
u_char inp_ip_p; /* (c) protocol proto */
u_char inp_ip_minttl; /* (i) minimum TTL or drop */
- uint32_t inp_ispare1; /* (x) connection id / queue id */
+ uint32_t inp_flowid; /* (x) flow id / queue id */
u_int inp_refcount; /* (i) refcount */
void *inp_pspare[2]; /* (x) rtentry / general use */
@@ -384,40 +384,40 @@ void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
#define INP_IPV4 0x1
#define INP_IPV6 0x2
#define INP_IPV6PROTO 0x4 /* opened under IPv6 protocol */
-#define INP_TIMEWAIT 0x8 /* inpcb in TIMEWAIT, ppcb is tcptw */
-#define INP_ONESBCAST 0x10 /* send all-ones broadcast */
-#define INP_DROPPED 0x20 /* protocol drop flag */
-#define INP_SOCKREF 0x40 /* strong socket reference */
/*
* Flags for inp_flag.
*/
-#define INP_RECVOPTS 0x01 /* receive incoming IP options */
-#define INP_RECVRETOPTS 0x02 /* receive IP options for reply */
-#define INP_RECVDSTADDR 0x04 /* receive IP dst address */
-#define INP_HDRINCL 0x08 /* user supplies entire IP header */
-#define INP_HIGHPORT 0x10 /* user wants "high" port binding */
-#define INP_LOWPORT 0x20 /* user wants "low" port binding */
-#define INP_ANONPORT 0x40 /* port chosen for user */
-#define INP_RECVIF 0x80 /* receive incoming interface */
-#define INP_MTUDISC 0x100 /* user can do MTU discovery */
-#define INP_FAITH 0x200 /* accept FAITH'ed connections */
-#define INP_RECVTTL 0x400 /* receive incoming IP TTL */
-#define INP_DONTFRAG 0x800 /* don't fragment packet */
-#define INP_NONLOCALOK 0x1000 /* Allow bind to spoof any address */
+#define INP_RECVOPTS 0x00000001 /* receive incoming IP options */
+#define INP_RECVRETOPTS 0x00000002 /* receive IP options for reply */
+#define INP_RECVDSTADDR 0x00000004 /* receive IP dst address */
+#define INP_HDRINCL 0x00000008 /* user supplies entire IP header */
+#define INP_HIGHPORT 0x00000010 /* user wants "high" port binding */
+#define INP_LOWPORT 0x00000020 /* user wants "low" port binding */
+#define INP_ANONPORT 0x00000040 /* port chosen for user */
+#define INP_RECVIF 0x00000080 /* receive incoming interface */
+#define INP_MTUDISC 0x00000100 /* user can do MTU discovery */
+#define INP_FAITH 0x00000200 /* accept FAITH'ed connections */
+#define INP_RECVTTL 0x00000400 /* receive incoming IP TTL */
+#define INP_DONTFRAG 0x00000800 /* don't fragment packet */
+#define INP_NONLOCALOK 0x00001000 /* Allow bind to spoof any address */
/* - requires options IP_NONLOCALBIND */
-#define INP_INHASHLIST 0x2000 /* in_pcbinshash() has been called */
-
-#define IN6P_IPV6_V6ONLY 0x008000 /* restrict AF_INET6 socket for v6 */
-
-#define IN6P_PKTINFO 0x010000 /* receive IP6 dst and I/F */
-#define IN6P_HOPLIMIT 0x020000 /* receive hoplimit */
-#define IN6P_HOPOPTS 0x040000 /* receive hop-by-hop options */
-#define IN6P_DSTOPTS 0x080000 /* receive dst options after rthdr */
-#define IN6P_RTHDR 0x100000 /* receive routing header */
-#define IN6P_RTHDRDSTOPTS 0x200000 /* receive dstoptions before rthdr */
-#define IN6P_TCLASS 0x400000 /* receive traffic class value */
-#define IN6P_AUTOFLOWLABEL 0x800000 /* attach flowlabel automatically */
+#define INP_INHASHLIST 0x00002000 /* in_pcbinshash() has been called */
+#define IN6P_IPV6_V6ONLY 0x00008000 /* restrict AF_INET6 socket for v6 */
+#define IN6P_PKTINFO 0x00010000 /* receive IP6 dst and I/F */
+#define IN6P_HOPLIMIT 0x00020000 /* receive hoplimit */
+#define IN6P_HOPOPTS 0x00040000 /* receive hop-by-hop options */
+#define IN6P_DSTOPTS 0x00080000 /* receive dst options after rthdr */
+#define IN6P_RTHDR 0x00100000 /* receive routing header */
+#define IN6P_RTHDRDSTOPTS 0x00200000 /* receive dstoptions before rthdr */
+#define IN6P_TCLASS 0x00400000 /* receive traffic class value */
+#define IN6P_AUTOFLOWLABEL 0x00800000 /* attach flowlabel automatically */
+#define INP_TIMEWAIT 0x01000000 /* in TIMEWAIT, ppcb is tcptw */
+#define INP_ONESBCAST 0x02000000 /* send all-ones broadcast */
+#define INP_DROPPED 0x04000000 /* protocol drop flag */
+#define INP_SOCKREF 0x08000000 /* strong socket reference */
+#define INP_SW_FLOWID 0x10000000 /* software generated flow id */
+#define INP_HW_FLOWID 0x20000000 /* hardware generated flow id */
#define IN6P_RFC2292 0x40000000 /* used RFC2292 API on the socket */
#define IN6P_MTU 0x80000000 /* receive path MTU */
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 6d96163..cc74580 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -530,7 +530,7 @@ carp_input(struct mbuf *m, int hlen)
struct carp_header *ch;
int iplen, len;
- carpstats.carps_ipackets++;
+ CARPSTATS_INC(carps_ipackets);
if (!carp_opts[CARPCTL_ALLOW]) {
m_freem(m);
@@ -539,7 +539,7 @@ carp_input(struct mbuf *m, int hlen)
/* check if received on a valid carp interface */
if (m->m_pkthdr.rcvif->if_carp == NULL) {
- carpstats.carps_badif++;
+ CARPSTATS_INC(carps_badif);
CARP_LOG("carp_input: packet received on non-carp "
"interface: %s\n",
m->m_pkthdr.rcvif->if_xname);
@@ -549,7 +549,7 @@ carp_input(struct mbuf *m, int hlen)
/* verify that the IP TTL is 255. */
if (ip->ip_ttl != CARP_DFLTTL) {
- carpstats.carps_badttl++;
+ CARPSTATS_INC(carps_badttl);
CARP_LOG("carp_input: received ttl %d != 255i on %s\n",
ip->ip_ttl,
m->m_pkthdr.rcvif->if_xname);
@@ -560,7 +560,7 @@ carp_input(struct mbuf *m, int hlen)
iplen = ip->ip_hl << 2;
if (m->m_pkthdr.len < iplen + sizeof(*ch)) {
- carpstats.carps_badlen++;
+ CARPSTATS_INC(carps_badlen);
CARP_LOG("carp_input: received len %zd < "
"sizeof(struct carp_header)\n",
m->m_len - sizeof(struct ip));
@@ -570,7 +570,7 @@ carp_input(struct mbuf *m, int hlen)
if (iplen + sizeof(*ch) < m->m_len) {
if ((m = m_pullup(m, iplen + sizeof(*ch))) == NULL) {
- carpstats.carps_hdrops++;
+ CARPSTATS_INC(carps_hdrops);
CARP_LOG("carp_input: pullup failed\n");
return;
}
@@ -584,7 +584,7 @@ carp_input(struct mbuf *m, int hlen)
*/
len = iplen + sizeof(*ch);
if (len > m->m_pkthdr.len) {
- carpstats.carps_badlen++;
+ CARPSTATS_INC(carps_badlen);
CARP_LOG("carp_input: packet too short %d on %s\n",
m->m_pkthdr.len,
m->m_pkthdr.rcvif->if_xname);
@@ -593,7 +593,7 @@ carp_input(struct mbuf *m, int hlen)
}
if ((m = m_pullup(m, len)) == NULL) {
- carpstats.carps_hdrops++;
+ CARPSTATS_INC(carps_hdrops);
return;
}
ip = mtod(m, struct ip *);
@@ -602,7 +602,7 @@ carp_input(struct mbuf *m, int hlen)
/* verify the CARP checksum */
m->m_data += iplen;
if (carp_cksum(m, len - iplen)) {
- carpstats.carps_badsum++;
+ CARPSTATS_INC(carps_badsum);
CARP_LOG("carp_input: checksum failed on %s\n",
m->m_pkthdr.rcvif->if_xname);
m_freem(m);
@@ -622,7 +622,7 @@ carp6_input(struct mbuf **mp, int *offp, int proto)
struct carp_header *ch;
u_int len;
- carpstats.carps_ipackets6++;
+ CARPSTATS_INC(carps_ipackets6);
if (!carp_opts[CARPCTL_ALLOW]) {
m_freem(m);
@@ -631,7 +631,7 @@ carp6_input(struct mbuf **mp, int *offp, int proto)
/* check if received on a valid carp interface */
if (m->m_pkthdr.rcvif->if_carp == NULL) {
- carpstats.carps_badif++;
+ CARPSTATS_INC(carps_badif);
CARP_LOG("carp6_input: packet received on non-carp "
"interface: %s\n",
m->m_pkthdr.rcvif->if_xname);
@@ -641,7 +641,7 @@ carp6_input(struct mbuf **mp, int *offp, int proto)
/* verify that the IP TTL is 255 */
if (ip6->ip6_hlim != CARP_DFLTTL) {
- carpstats.carps_badttl++;
+ CARPSTATS_INC(carps_badttl);
CARP_LOG("carp6_input: received ttl %d != 255 on %s\n",
ip6->ip6_hlim,
m->m_pkthdr.rcvif->if_xname);
@@ -653,7 +653,7 @@ carp6_input(struct mbuf **mp, int *offp, int proto)
len = m->m_len;
IP6_EXTHDR_GET(ch, struct carp_header *, m, *offp, sizeof(*ch));
if (ch == NULL) {
- carpstats.carps_badlen++;
+ CARPSTATS_INC(carps_badlen);
CARP_LOG("carp6_input: packet size %u too small\n", len);
return (IPPROTO_DONE);
}
@@ -662,7 +662,7 @@ carp6_input(struct mbuf **mp, int *offp, int proto)
/* verify the CARP checksum */
m->m_data += *offp;
if (carp_cksum(m, sizeof(*ch))) {
- carpstats.carps_badsum++;
+ CARPSTATS_INC(carps_badsum);
CARP_LOG("carp6_input: checksum failed, on %s\n",
m->m_pkthdr.rcvif->if_xname);
m_freem(m);
@@ -691,7 +691,7 @@ carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af)
if (!sc || !((SC2IFP(sc)->if_flags & IFF_UP) &&
(SC2IFP(sc)->if_drv_flags & IFF_DRV_RUNNING))) {
- carpstats.carps_badvhid++;
+ CARPSTATS_INC(carps_badvhid);
CARP_UNLOCK(ifp->if_carp);
m_freem(m);
return;
@@ -713,7 +713,7 @@ carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af)
/* verify the CARP version. */
if (ch->carp_version != CARP_VERSION) {
- carpstats.carps_badver++;
+ CARPSTATS_INC(carps_badver);
SC2IFP(sc)->if_ierrors++;
CARP_UNLOCK(ifp->if_carp);
CARP_LOG("%s; invalid version %d\n",
@@ -725,7 +725,7 @@ carp_input_c(struct mbuf *m, struct carp_header *ch, sa_family_t af)
/* verify the hash */
if (carp_hmac_verify(sc, ch->carp_counter, ch->carp_md)) {
- carpstats.carps_badauth++;
+ CARPSTATS_INC(carps_badauth);
SC2IFP(sc)->if_ierrors++;
CARP_UNLOCK(ifp->if_carp);
CARP_LOG("%s: incorrect hash\n", SC2IFP(sc)->if_xname);
@@ -915,7 +915,7 @@ carp_send_ad_locked(struct carp_softc *sc)
MGETHDR(m, M_DONTWAIT, MT_HEADER);
if (m == NULL) {
SC2IFP(sc)->if_oerrors++;
- carpstats.carps_onomem++;
+ CARPSTATS_INC(carps_onomem);
/* XXX maybe less ? */
if (advbase != 255 || advskew != 255)
callout_reset(&sc->sc_ad_tmo, tvtohz(&tv),
@@ -953,7 +953,7 @@ carp_send_ad_locked(struct carp_softc *sc)
getmicrotime(&SC2IFP(sc)->if_lastchange);
SC2IFP(sc)->if_opackets++;
SC2IFP(sc)->if_obytes += len;
- carpstats.carps_opackets++;
+ CARPSTATS_INC(carps_opackets);
if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL)) {
SC2IFP(sc)->if_oerrors++;
@@ -987,7 +987,7 @@ carp_send_ad_locked(struct carp_softc *sc)
MGETHDR(m, M_DONTWAIT, MT_HEADER);
if (m == NULL) {
SC2IFP(sc)->if_oerrors++;
- carpstats.carps_onomem++;
+ CARPSTATS_INC(carps_onomem);
/* XXX maybe less ? */
if (advbase != 255 || advskew != 255)
callout_reset(&sc->sc_ad_tmo, tvtohz(&tv),
@@ -1030,7 +1030,7 @@ carp_send_ad_locked(struct carp_softc *sc)
getmicrotime(&SC2IFP(sc)->if_lastchange);
SC2IFP(sc)->if_opackets++;
SC2IFP(sc)->if_obytes += len;
- carpstats.carps_opackets6++;
+ CARPSTATS_INC(carps_opackets6);
if (ip6_output(m, NULL, NULL, 0, &sc->sc_im6o, NULL, NULL)) {
SC2IFP(sc)->if_oerrors++;
diff --git a/sys/netinet/ip_carp.h b/sys/netinet/ip_carp.h
index 2dd9544..47bb494 100644
--- a/sys/netinet/ip_carp.h
+++ b/sys/netinet/ip_carp.h
@@ -117,6 +117,11 @@ struct carpstats {
uint64_t carps_preempt; /* if enabled, preemptions */
};
+#ifdef _KERNEL
+#define CARPSTATS_ADD(name, val) carpstats.name += (val)
+#define CARPSTATS_INC(name) CARPSTATS_ADD(name, 1)
+#endif
+
/*
* Configuration structure for SIOCSVH SIOCGVH
*/
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index c2e3191..f39c655 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -186,7 +186,7 @@ div_input(struct mbuf *m, int off)
{
INIT_VNET_INET(curvnet);
- V_ipstat.ips_noproto++;
+ IPSTAT_INC(ips_noproto);
m_freem(m);
}
@@ -307,8 +307,8 @@ divert_packet(struct mbuf *m, int incoming)
INP_INFO_RUNLOCK(&V_divcbinfo);
if (sa == NULL) {
m_freem(m);
- V_ipstat.ips_noproto++;
- V_ipstat.ips_delivered--;
+ IPSTAT_INC(ips_noproto);
+ IPSTAT_DEC(ips_delivered);
}
}
@@ -394,7 +394,7 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin,
ip->ip_off = ntohs(ip->ip_off);
/* Send packet to output processing */
- V_ipstat.ips_rawout++; /* XXX */
+ IPSTAT_INC(ips_rawout); /* XXX */
#ifdef MAC
mac_inpcb_create_mbuf(inp, m);
@@ -570,7 +570,7 @@ div_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
/* Packet must have a header (but that's about it) */
if (m->m_len < sizeof (struct ip) &&
(m = m_pullup(m, sizeof (struct ip))) == 0) {
- V_ipstat.ips_toosmall++;
+ IPSTAT_INC(ips_toosmall);
m_freem(m);
return EINVAL;
}
diff --git a/sys/netinet/ip_dummynet.c b/sys/netinet/ip_dummynet.c
index 4c7f60a..5816be9 100644
--- a/sys/netinet/ip_dummynet.c
+++ b/sys/netinet/ip_dummynet.c
@@ -519,14 +519,64 @@ transmit_event(struct dn_pipe *pipe, struct mbuf **head, struct mbuf **tail)
}
}
+#define div64(a, b) ((int64_t)(a) / (int64_t)(b))
+#define DN_TO_DROP 0xffff
/*
- * the following macro computes how many ticks we have to wait
- * before being able to transmit a packet. The credit is taken from
- * either a pipe (WF2Q) or a flow_queue (per-flow queueing)
+ * Compute how many ticks we have to wait before being able to send
+ * a packet. This is computed as the "wire time" for the packet
+ * (length + extra bits), minus the credit available, scaled to ticks.
+ * Check that the result is not be negative (it could be if we have
+ * too much leftover credit in q->numbytes).
*/
-#define SET_TICKS(_m, q, p) \
- ((_m)->m_pkthdr.len * 8 * hz - (q)->numbytes + p->bandwidth - 1) / \
- p->bandwidth;
+static inline dn_key
+set_ticks(struct mbuf *m, struct dn_flow_queue *q, struct dn_pipe *p)
+{
+ int64_t ret;
+
+ ret = div64( (m->m_pkthdr.len * 8 + q->extra_bits) * hz
+ - q->numbytes + p->bandwidth - 1 , p->bandwidth);
+#if 0
+ printf("%s %d extra_bits %d numb %d ret %d\n",
+ __FUNCTION__, __LINE__,
+ (int)(q->extra_bits & 0xffffffff),
+ (int)(q->numbytes & 0xffffffff),
+ (int)(ret & 0xffffffff));
+#endif
+ if (ret < 0)
+ ret = 0;
+ return ret;
+}
+
+/*
+ * Convert the additional MAC overheads/delays into an equivalent
+ * number of bits for the given data rate. The samples are in milliseconds
+ * so we need to divide by 1000.
+ */
+static dn_key
+compute_extra_bits(struct mbuf *pkt, struct dn_pipe *p)
+{
+ int index;
+ dn_key extra_bits;
+
+ if (!p->samples || p->samples_no == 0)
+ return 0;
+ index = random() % p->samples_no;
+ extra_bits = ((dn_key)p->samples[index] * p->bandwidth) / 1000;
+ if (index >= p->loss_level) {
+ struct dn_pkt_tag *dt = dn_tag_get(pkt);
+ if (dt)
+ dt->dn_dir = DN_TO_DROP;
+ }
+ return extra_bits;
+}
+
+static void
+free_pipe(struct dn_pipe *p)
+{
+ if (p->samples)
+ free(p->samples, M_DUMMYNET);
+ free(p, M_DUMMYNET);
+}
/*
* extract pkt from queue, compute output time (could be now)
@@ -585,12 +635,16 @@ ready_event(struct dn_flow_queue *q, struct mbuf **head, struct mbuf **tail)
q->numbytes += (curr_time - q->sched_time) * p->bandwidth;
while ((pkt = q->head) != NULL) {
int len = pkt->m_pkthdr.len;
- int len_scaled = p->bandwidth ? len * 8 * hz : 0;
+ dn_key len_scaled = p->bandwidth ? len*8*hz
+ + q->extra_bits*hz
+ : 0;
- if (len_scaled > q->numbytes)
+ if (DN_KEY_GT(len_scaled, q->numbytes))
break;
q->numbytes -= len_scaled;
move_pkt(pkt, q, p, len);
+ if (q->head)
+ q->extra_bits = compute_extra_bits(q->head, p);
}
/*
* If we have more packets queued, schedule next ready event
@@ -600,7 +654,7 @@ ready_event(struct dn_flow_queue *q, struct mbuf **head, struct mbuf **tail)
* ticks to go for the finish time of the packet.
*/
if ((pkt = q->head) != NULL) { /* this implies bandwidth != 0 */
- dn_key t = SET_TICKS(pkt, q, p); /* ticks i have to wait */
+ dn_key t = set_ticks(pkt, q, p); /* ticks i have to wait */
q->sched_time = curr_time;
heap_insert(&ready_heap, curr_time + t, (void *)q);
@@ -933,6 +987,12 @@ dummynet_send(struct mbuf *m)
case DN_TO_ETH_OUT:
ether_output_frame(pkt->ifp, m);
break;
+
+ case DN_TO_DROP:
+ /* drop the packet after some time */
+ m_freem(m);
+ break;
+
default:
printf("dummynet: bad switch %d!\n", pkt->dn_dir);
m_freem(m);
@@ -1367,8 +1427,10 @@ dummynet_io(struct mbuf **m0, int dir, struct ip_fw_args *fwa)
/* Fixed-rate queue: just insert into the ready_heap. */
dn_key t = 0;
- if (pipe->bandwidth && m->m_pkthdr.len * 8 * hz > q->numbytes)
- t = SET_TICKS(m, q, pipe);
+ if (pipe->bandwidth) {
+ q->extra_bits = compute_extra_bits(m, pipe);
+ t = set_ticks(m, q, pipe);
+ }
q->sched_time = curr_time;
if (t == 0) /* Must process it now. */
ready_event(q, &head, &tail);
@@ -1555,7 +1617,7 @@ dummynet_flush(void)
SLIST_FOREACH_SAFE(pipe, &pipehash[i], next, pipe1) {
SLIST_REMOVE(&pipehash[i], pipe, dn_pipe, next);
purge_pipe(pipe);
- free(pipe, M_DUMMYNET);
+ free_pipe(pipe);
}
DUMMYNET_UNLOCK();
}
@@ -1775,11 +1837,38 @@ config_pipe(struct dn_pipe *p)
pipe->delay = p->delay;
set_fs_parms(&(pipe->fs), pfs);
+ /* Handle changes in the delay profile. */
+ if (p->samples_no > 0) {
+ if (pipe->samples_no != p->samples_no) {
+ if (pipe->samples != NULL)
+ free(pipe->samples, M_DUMMYNET);
+ pipe->samples =
+ malloc(p->samples_no*sizeof(dn_key),
+ M_DUMMYNET, M_NOWAIT | M_ZERO);
+ if (pipe->samples == NULL) {
+ DUMMYNET_UNLOCK();
+ printf("dummynet: no memory "
+ "for new samples\n");
+ return (ENOMEM);
+ }
+ pipe->samples_no = p->samples_no;
+ }
+
+ strncpy(pipe->name,p->name,sizeof(pipe->name));
+ pipe->loss_level = p->loss_level;
+ for (i = 0; i<pipe->samples_no; ++i)
+ pipe->samples[i] = p->samples[i];
+ } else if (pipe->samples != NULL) {
+ free(pipe->samples, M_DUMMYNET);
+ pipe->samples = NULL;
+ pipe->samples_no = 0;
+ }
+
if (pipe->fs.rq == NULL) { /* a new pipe */
error = alloc_hash(&(pipe->fs), pfs);
if (error) {
DUMMYNET_UNLOCK();
- free(pipe, M_DUMMYNET);
+ free_pipe(pipe);
return (error);
}
SLIST_INSERT_HEAD(&pipehash[HASH(pipe->pipe_nr)],
@@ -1957,7 +2046,7 @@ delete_pipe(struct dn_pipe *p)
pipe_remove_from_heap(&wfq_ready_heap, pipe);
DUMMYNET_UNLOCK();
- free(pipe, M_DUMMYNET);
+ free_pipe(pipe);
} else { /* this is a WF2Q queue (dn_flow_set) */
struct dn_flow_set *fs;
@@ -2095,6 +2184,7 @@ dummynet_get(struct sockopt *sopt)
pipe_bp->fs.next.sle_next = NULL;
pipe_bp->fs.pipe = NULL;
pipe_bp->fs.rq = NULL;
+ pipe_bp->samples = NULL;
bp += sizeof(*pipe) ;
bp = dn_copy_set(&(pipe->fs), bp);
@@ -2127,7 +2217,8 @@ static int
ip_dn_ctl(struct sockopt *sopt)
{
int error = 0 ;
- struct dn_pipe *p, tmp_pipe;
+ struct dn_pipe *p;
+ struct dn_pipe_max tmp_pipe; /* pipe + large buffer */
error = priv_check(sopt->sopt_td, PRIV_NETINET_DUMMYNET);
if (error)
@@ -2159,15 +2250,18 @@ ip_dn_ctl(struct sockopt *sopt)
break ;
case IP_DUMMYNET_CONFIGURE :
- p = &tmp_pipe ;
- error = sooptcopyin(sopt, p, sizeof *p, sizeof *p);
+ p = (struct dn_pipe *)&tmp_pipe ;
+ error = sooptcopyin(sopt, p, sizeof(tmp_pipe), sizeof *p);
if (error)
break ;
+ if (p->samples_no > 0)
+ p->samples = &tmp_pipe.samples[0];
+
error = config_pipe(p);
break ;
case IP_DUMMYNET_DEL : /* remove a pipe or queue */
- p = &tmp_pipe ;
+ p = (struct dn_pipe *)&tmp_pipe ;
error = sooptcopyin(sopt, p, sizeof *p, sizeof *p);
if (error)
break ;
diff --git a/sys/netinet/ip_dummynet.h b/sys/netinet/ip_dummynet.h
index 0a37e6c..6e102f4 100644
--- a/sys/netinet/ip_dummynet.h
+++ b/sys/netinet/ip_dummynet.h
@@ -204,7 +204,18 @@ struct dn_flow_queue {
struct mbuf *head, *tail ; /* queue of packets */
u_int len ;
u_int len_bytes ;
- u_long numbytes ; /* credit for transmission (dynamic queues) */
+
+ /*
+ * When we emulate MAC overheads, or channel unavailability due
+ * to other traffic on a shared medium, we augment the packet at
+ * the head of the queue with an 'extra_bits' field representsing
+ * the additional delay the packet will be subject to:
+ * extra_bits = bw*unavailable_time.
+ * With large bandwidth and large delays, extra_bits (and also numbytes)
+ * can become very large, so better play safe and use 64 bit
+ */
+ dn_key numbytes ; /* credit for transmission (dynamic queues) */
+ dn_key extra_bits; /* extra bits simulating unavailable channel */
u_int64_t tot_pkts ; /* statistics counters */
u_int64_t tot_bytes ;
@@ -252,6 +263,7 @@ struct dn_flow_set {
#define DN_IS_GENTLE_RED 0x0004
#define DN_QSIZE_IS_BYTES 0x0008 /* queue size is measured in bytes */
#define DN_NOERROR 0x0010 /* do not report ENOBUFS on drops */
+#define DN_HAS_PROFILE 0x0020 /* the pipe has a delay profile. */
#define DN_IS_PIPE 0x4000
#define DN_IS_QUEUE 0x8000
@@ -324,7 +336,9 @@ struct dn_pipe { /* a pipe */
dn_key V ; /* virtual time */
int sum; /* sum of weights of all active sessions */
- int numbytes; /* bits I can transmit (more or less). */
+
+ /* Same as in dn_flow_queue, numbytes can become large */
+ dn_key numbytes; /* bits I can transmit (more or less). */
dn_key sched_time ; /* time pipe was scheduled in ready_heap */
@@ -337,7 +351,25 @@ struct dn_pipe { /* a pipe */
int ready ; /* set if ifp != NULL and we got a signal from it */
struct dn_flow_set fs ; /* used with fixed-rate flows */
+
+ /* fields to simulate a delay profile */
+
+#define ED_MAX_NAME_LEN 32
+ char name[ED_MAX_NAME_LEN];
+ int loss_level;
+ int samples_no;
+ int *samples;
};
+
+/* dn_pipe_max is used to pass pipe configuration from userland onto
+ * kernel space and back
+ */
+#define ED_MAX_SAMPLES_NO 1024
+struct dn_pipe_max {
+ struct dn_pipe pipe;
+ int samples[ED_MAX_SAMPLES_NO];
+};
+
SLIST_HEAD(dn_pipe_head, dn_pipe);
#ifdef _KERNEL
diff --git a/sys/netinet/ip_fastfwd.c b/sys/netinet/ip_fastfwd.c
index ea106df..0479064 100644
--- a/sys/netinet/ip_fastfwd.c
+++ b/sys/netinet/ip_fastfwd.c
@@ -140,8 +140,8 @@ ip_findroute(struct route *ro, struct in_addr dest, struct mbuf *m)
if (rt->rt_flags & RTF_GATEWAY)
dst = (struct sockaddr_in *)rt->rt_gateway;
} else {
- V_ipstat.ips_noroute++;
- V_ipstat.ips_cantforward++;
+ IPSTAT_INC(ips_noroute);
+ IPSTAT_INC(ips_cantforward);
if (rt)
RTFREE(rt);
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0);
@@ -193,7 +193,7 @@ ip_fastforward(struct mbuf *m)
* Is entire packet big enough?
*/
if (m->m_pkthdr.len < sizeof(struct ip)) {
- V_ipstat.ips_tooshort++;
+ IPSTAT_INC(ips_tooshort);
goto drop;
}
@@ -202,7 +202,7 @@ ip_fastforward(struct mbuf *m)
*/
if (m->m_len < sizeof (struct ip) &&
(m = m_pullup(m, sizeof (struct ip))) == NULL) {
- V_ipstat.ips_toosmall++;
+ IPSTAT_INC(ips_toosmall);
return NULL; /* mbuf already free'd */
}
@@ -212,7 +212,7 @@ ip_fastforward(struct mbuf *m)
* Is it IPv4?
*/
if (ip->ip_v != IPVERSION) {
- V_ipstat.ips_badvers++;
+ IPSTAT_INC(ips_badvers);
goto drop;
}
@@ -221,12 +221,12 @@ ip_fastforward(struct mbuf *m)
*/
hlen = ip->ip_hl << 2;
if (hlen < sizeof(struct ip)) { /* minimum header length */
- V_ipstat.ips_badlen++;
+ IPSTAT_INC(ips_badlen);
goto drop;
}
if (hlen > m->m_len) {
if ((m = m_pullup(m, hlen)) == NULL) {
- V_ipstat.ips_badhlen++;
+ IPSTAT_INC(ips_badhlen);
return NULL; /* mbuf already free'd */
}
ip = mtod(m, struct ip *);
@@ -244,7 +244,7 @@ ip_fastforward(struct mbuf *m)
sum = in_cksum(m, hlen);
}
if (sum) {
- V_ipstat.ips_badsum++;
+ IPSTAT_INC(ips_badsum);
goto drop;
}
@@ -259,7 +259,7 @@ ip_fastforward(struct mbuf *m)
* Is IP length longer than packet we have got?
*/
if (m->m_pkthdr.len < ip_len) {
- V_ipstat.ips_tooshort++;
+ IPSTAT_INC(ips_tooshort);
goto drop;
}
@@ -279,7 +279,7 @@ ip_fastforward(struct mbuf *m)
*/
if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
(ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
- V_ipstat.ips_badaddr++;
+ IPSTAT_INC(ips_badaddr);
goto drop;
}
@@ -337,7 +337,7 @@ ip_fastforward(struct mbuf *m)
if (in_localip(ip->ip_dst))
return m;
- V_ipstat.ips_total++;
+ IPSTAT_INC(ips_total);
/*
* Step 3: incoming packet firewall processing
@@ -519,7 +519,7 @@ passout:
*/
if ((ifp->if_snd.ifq_len + ip->ip_len / ifp->if_mtu + 1) >=
ifp->if_snd.ifq_maxlen) {
- V_ipstat.ips_odropped++;
+ IPSTAT_INC(ips_odropped);
/* would send source quench here but that is depreciated */
goto drop;
}
@@ -558,7 +558,7 @@ passout:
* Handle EMSGSIZE with icmp reply needfrag for TCP MTU discovery
*/
if (ip->ip_off & IP_DF) {
- V_ipstat.ips_cantfrag++;
+ IPSTAT_INC(ips_cantfrag);
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG,
0, mtu);
goto consumed;
@@ -596,16 +596,16 @@ passout:
m_freem(m);
}
} else
- V_ipstat.ips_fragmented++;
+ IPSTAT_INC(ips_fragmented);
}
}
if (error != 0)
- V_ipstat.ips_odropped++;
+ IPSTAT_INC(ips_odropped);
else {
ro.ro_rt->rt_rmx.rmx_pksent++;
- V_ipstat.ips_forward++;
- V_ipstat.ips_fastforward++;
+ IPSTAT_INC(ips_forward);
+ IPSTAT_INC(ips_fastforward);
}
consumed:
RTFREE(ro.ro_rt);
diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h
index 0cf1a52..fa37a73 100644
--- a/sys/netinet/ip_fw.h
+++ b/sys/netinet/ip_fw.h
@@ -139,7 +139,8 @@ enum ipfw_opcodes { /* arguments (4 byte each) */
O_FORWARD_IP, /* fwd sockaddr */
O_FORWARD_MAC, /* fwd mac */
O_NAT, /* nope */
-
+ O_REASS, /* none */
+
/*
* More opcodes.
*/
@@ -574,6 +575,7 @@ enum {
IP_FW_NETGRAPH,
IP_FW_NGTEE,
IP_FW_NAT,
+ IP_FW_REASS,
};
/* flags for divert mtag */
@@ -696,6 +698,7 @@ struct vnet_ipfw {
int _fw_debug; /* actually unused */
int _autoinc_step;
ipfw_dyn_rule **_ipfw_dyn_v;
+ uma_zone_t _ipfw_dyn_rule_zone;
struct ip_fw_chain _layer3_chain;
u_int32_t _dyn_buckets;
u_int32_t _curr_dyn_buckets;
@@ -740,6 +743,7 @@ extern struct vnet_ipfw vnet_ipfw_0;
#define V_fw_debug VNET_IPFW(fw_debug)
#define V_autoinc_step VNET_IPFW(autoinc_step)
#define V_ipfw_dyn_v VNET_IPFW(ipfw_dyn_v)
+#define V_ipfw_dyn_rule_zone VNET_IPFW(ipfw_dyn_rule_zone)
#define V_layer3_chain VNET_IPFW(layer3_chain)
#define V_dyn_buckets VNET_IPFW(dyn_buckets)
#define V_curr_dyn_buckets VNET_IPFW(curr_dyn_buckets)
diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c
index 1405a27..fa6e6f1 100644
--- a/sys/netinet/ip_fw2.c
+++ b/sys/netinet/ip_fw2.c
@@ -898,6 +898,9 @@ ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args,
case O_NAT:
action = "Nat";
break;
+ case O_REASS:
+ action = "Reass";
+ break;
default:
action = "UNKNOWN";
break;
@@ -3375,6 +3378,55 @@ check_body:
goto done;
}
+ case O_REASS: {
+ int ip_off;
+
+ f->pcnt++;
+ f->bcnt += pktlen;
+ ip_off = (args->eh != NULL) ? ntohs(ip->ip_off) : ip->ip_off;
+ if (ip_off & (IP_MF | IP_OFFMASK)) {
+ /*
+ * ip_reass() expects len & off in host
+ * byte order: fix them in case we come
+ * from layer2.
+ */
+ if (args->eh != NULL) {
+ ip->ip_len = ntohs(ip->ip_len);
+ ip->ip_off = ntohs(ip->ip_off);
+ }
+
+ m = ip_reass(m);
+ args->m = m;
+
+ /*
+ * IP header checksum fixup after
+ * reassembly and leave header
+ * in network byte order.
+ */
+ if (m != NULL) {
+ int hlen;
+
+ ip = mtod(m, struct ip *);
+ hlen = ip->ip_hl << 2;
+ /* revert len & off for layer2 pkts */
+ if (args->eh != NULL)
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_sum = 0;
+ if (hlen == sizeof(struct ip))
+ ip->ip_sum = in_cksum_hdr(ip);
+ else
+ ip->ip_sum = in_cksum(m, hlen);
+ retval = IP_FW_REASS;
+ args->rule = f;
+ goto done;
+ } else {
+ retval = IP_FW_DENY;
+ goto done;
+ }
+ }
+ goto next_rule;
+ }
+
default:
panic("-- unknown opcode %d\n", cmd->opcode);
} /* end of switch() on opcodes */
@@ -4024,6 +4076,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
case O_UNREACH6:
#endif
case O_SKIPTO:
+ case O_REASS:
check_size:
if (cmdlen != F_INSN_SIZE(ipfw_insn))
goto bad_size;
diff --git a/sys/netinet/ip_fw_pfil.c b/sys/netinet/ip_fw_pfil.c
index 1e6d2b0..11560a7 100644
--- a/sys/netinet/ip_fw_pfil.c
+++ b/sys/netinet/ip_fw_pfil.c
@@ -200,6 +200,9 @@ again:
case IP_FW_NAT:
goto again; /* continue with packet */
+ case IP_FW_REASS:
+ goto again;
+
default:
KASSERT(0, ("%s: unknown retval", __func__));
}
@@ -329,6 +332,9 @@ again:
case IP_FW_NAT:
goto again; /* continue with packet */
+ case IP_FW_REASS:
+ goto again;
+
default:
KASSERT(0, ("%s: unknown retval", __func__));
}
diff --git a/sys/netinet/ip_icmp.c b/sys/netinet/ip_icmp.c
index baf07d3..fe06b9a 100644
--- a/sys/netinet/ip_icmp.c
+++ b/sys/netinet/ip_icmp.c
@@ -180,7 +180,7 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
printf("icmp_error(%p, %x, %d)\n", oip, type, code);
#endif
if (type != ICMP_REDIRECT)
- V_icmpstat.icps_error++;
+ ICMPSTAT_INC(icps_error);
/*
* Don't send error:
* if the original packet was encrypted.
@@ -197,7 +197,7 @@ icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
n->m_len >= oiphlen + ICMP_MINLEN &&
!ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiphlen))->icmp_type)) {
- V_icmpstat.icps_oldicmp++;
+ ICMPSTAT_INC(icps_oldicmp);
goto freeit;
}
/* Drop if IP header plus 8 bytes is not contignous in first mbuf. */
@@ -257,7 +257,7 @@ stdreply: icmpelen = max(8, min(V_icmp_quotelen, oip->ip_len - oiphlen));
*/
M_SETFIB(m, M_GETFIB(n));
icp = mtod(m, struct icmp *);
- V_icmpstat.icps_outhist[type]++;
+ ICMPSTAT_INC(icps_outhist[type]);
icp->icmp_type = type;
if (type == ICMP_REDIRECT)
icp->icmp_gwaddr.s_addr = dest;
@@ -340,12 +340,12 @@ icmp_input(struct mbuf *m, int off)
}
#endif
if (icmplen < ICMP_MINLEN) {
- V_icmpstat.icps_tooshort++;
+ ICMPSTAT_INC(icps_tooshort);
goto freeit;
}
i = hlen + min(icmplen, ICMP_ADVLENMIN);
if (m->m_len < i && (m = m_pullup(m, i)) == 0) {
- V_icmpstat.icps_tooshort++;
+ ICMPSTAT_INC(icps_tooshort);
return;
}
ip = mtod(m, struct ip *);
@@ -353,7 +353,7 @@ icmp_input(struct mbuf *m, int off)
m->m_data += hlen;
icp = mtod(m, struct icmp *);
if (in_cksum(m, icmplen)) {
- V_icmpstat.icps_checksum++;
+ ICMPSTAT_INC(icps_checksum);
goto freeit;
}
m->m_len += hlen;
@@ -395,7 +395,7 @@ icmp_input(struct mbuf *m, int off)
icmpgw.sin_len = sizeof(struct sockaddr_in);
icmpgw.sin_family = AF_INET;
- V_icmpstat.icps_inhist[icp->icmp_type]++;
+ ICMPSTAT_INC(icps_inhist[icp->icmp_type]);
code = icp->icmp_code;
switch (icp->icmp_type) {
@@ -460,7 +460,7 @@ icmp_input(struct mbuf *m, int off)
*/
if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
- V_icmpstat.icps_badlen++;
+ ICMPSTAT_INC(icps_badlen);
goto freeit;
}
icp->icmp_ip.ip_len = ntohs(icp->icmp_ip.ip_len);
@@ -483,13 +483,13 @@ icmp_input(struct mbuf *m, int off)
break;
badcode:
- V_icmpstat.icps_badcode++;
+ ICMPSTAT_INC(icps_badcode);
break;
case ICMP_ECHO:
if (!V_icmpbmcastecho
&& (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
- V_icmpstat.icps_bmcastecho++;
+ ICMPSTAT_INC(icps_bmcastecho);
break;
}
icp->icmp_type = ICMP_ECHOREPLY;
@@ -501,11 +501,11 @@ icmp_input(struct mbuf *m, int off)
case ICMP_TSTAMP:
if (!V_icmpbmcastecho
&& (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
- V_icmpstat.icps_bmcasttstamp++;
+ ICMPSTAT_INC(icps_bmcasttstamp);
break;
}
if (icmplen < ICMP_TSLEN) {
- V_icmpstat.icps_badlen++;
+ ICMPSTAT_INC(icps_badlen);
break;
}
icp->icmp_type = ICMP_TSTAMPREPLY;
@@ -554,8 +554,8 @@ icmp_input(struct mbuf *m, int off)
}
reflect:
ip->ip_len += hlen; /* since ip_input deducts this */
- V_icmpstat.icps_reflect++;
- V_icmpstat.icps_outhist[icp->icmp_type]++;
+ ICMPSTAT_INC(icps_reflect);
+ ICMPSTAT_INC(icps_outhist[icp->icmp_type]);
icmp_reflect(m);
return;
@@ -585,7 +585,7 @@ reflect:
goto badcode;
if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
- V_icmpstat.icps_badlen++;
+ ICMPSTAT_INC(icps_badlen);
break;
}
/*
@@ -660,7 +660,7 @@ icmp_reflect(struct mbuf *m)
IN_EXPERIMENTAL(ntohl(ip->ip_src.s_addr)) ||
IN_ZERONET(ntohl(ip->ip_src.s_addr)) ) {
m_freem(m); /* Bad return address */
- V_icmpstat.icps_badaddr++;
+ ICMPSTAT_INC(icps_badaddr);
goto done; /* Ip_output() will check for broadcast */
}
@@ -729,7 +729,7 @@ icmp_reflect(struct mbuf *m)
ia = ip_rtaddr(ip->ip_dst, M_GETFIB(m));
if (ia == NULL) {
m_freem(m);
- V_icmpstat.icps_noroute++;
+ ICMPSTAT_INC(icps_noroute);
goto done;
}
match:
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index a75ee72..920d741 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -224,6 +224,23 @@ int fw_one_pass;
static void ip_freef(struct ipqhead *, struct ipq *);
+#ifndef VIMAGE_GLOBALS
+static void vnet_inet_register(void);
+
+static const vnet_modinfo_t vnet_inet_modinfo = {
+ .vmi_id = VNET_MOD_INET,
+ .vmi_name = "inet",
+};
+
+static void vnet_inet_register()
+{
+
+ vnet_mod_register(&vnet_inet_modinfo);
+}
+
+SYSINIT(inet, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, vnet_inet_register, 0);
+#endif
+
/*
* IP initialization: fill in IP protocol switch table.
* All protocols not implemented in kernel go to raw IP protocol handler.
@@ -242,6 +259,7 @@ ip_init(void)
V_rsvp_on = 0;
V_ip_defttl = IPDEFTTL;
V_ip_do_randomid = 0;
+ V_ip_id = time_second & 0xffff;
V_ipforwarding = 0;
V_ipstealth = 0;
V_nipq = 0; /* Total # of reass queues */
@@ -270,6 +288,20 @@ ip_init(void)
TAILQ_INIT(&V_in_ifaddrhead);
V_in_ifaddrhashtbl = hashinit(INADDR_NHASH, M_IFADDR, &V_in_ifaddrhmask);
+
+ /* Initialize IP reassembly queue. */
+ for (i = 0; i < IPREASS_NHASH; i++)
+ TAILQ_INIT(&V_ipq[i]);
+ V_maxnipq = nmbclusters / 32;
+ V_maxfragsperpacket = 16;
+ V_ipq_zone = uma_zcreate("ipq", sizeof(struct ipq), NULL, NULL, NULL,
+ NULL, UMA_ALIGN_PTR, 0);
+ maxnipq_update();
+
+ /* Skip initialization of globals for non-default instances. */
+ if (!IS_DEFAULT_VNET(curvnet))
+ return;
+
pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW);
if (pr == NULL)
panic("ip_init: PF_INET not found");
@@ -297,16 +329,6 @@ ip_init(void)
printf("%s: WARNING: unable to register pfil hook, "
"error %d\n", __func__, i);
- /* Initialize IP reassembly queue. */
- IPQ_LOCK_INIT();
- for (i = 0; i < IPREASS_NHASH; i++)
- TAILQ_INIT(&V_ipq[i]);
- V_maxnipq = nmbclusters / 32;
- V_maxfragsperpacket = 16;
- V_ipq_zone = uma_zcreate("ipq", sizeof(struct ipq), NULL, NULL, NULL,
- NULL, UMA_ALIGN_PTR, 0);
- maxnipq_update();
-
/* Start ipport_tick. */
callout_init(&ipport_tick_callout, CALLOUT_MPSAFE);
ipport_tick(NULL);
@@ -316,7 +338,7 @@ ip_init(void)
NULL, EVENTHANDLER_PRI_ANY);
/* Initialize various other remaining things. */
- V_ip_id = time_second & 0xffff;
+ IPQ_LOCK_INIT();
ipintrq.ifq_maxlen = ipqmaxlen;
mtx_init(&ipintrq.ifq_mtx, "ip_inq", NULL, MTX_DEF);
netisr_register(NETISR_IP, ip_input, &ipintrq, 0);
@@ -359,31 +381,31 @@ ip_input(struct mbuf *m)
goto ours;
}
- V_ipstat.ips_total++;
+ IPSTAT_INC(ips_total);
if (m->m_pkthdr.len < sizeof(struct ip))
goto tooshort;
if (m->m_len < sizeof (struct ip) &&
(m = m_pullup(m, sizeof (struct ip))) == NULL) {
- V_ipstat.ips_toosmall++;
+ IPSTAT_INC(ips_toosmall);
return;
}
ip = mtod(m, struct ip *);
if (ip->ip_v != IPVERSION) {
- V_ipstat.ips_badvers++;
+ IPSTAT_INC(ips_badvers);
goto bad;
}
hlen = ip->ip_hl << 2;
if (hlen < sizeof(struct ip)) { /* minimum header length */
- V_ipstat.ips_badhlen++;
+ IPSTAT_INC(ips_badhlen);
goto bad;
}
if (hlen > m->m_len) {
if ((m = m_pullup(m, hlen)) == NULL) {
- V_ipstat.ips_badhlen++;
+ IPSTAT_INC(ips_badhlen);
return;
}
ip = mtod(m, struct ip *);
@@ -393,7 +415,7 @@ ip_input(struct mbuf *m)
if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
(ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) {
- V_ipstat.ips_badaddr++;
+ IPSTAT_INC(ips_badaddr);
goto bad;
}
}
@@ -408,7 +430,7 @@ ip_input(struct mbuf *m)
}
}
if (sum) {
- V_ipstat.ips_badsum++;
+ IPSTAT_INC(ips_badsum);
goto bad;
}
@@ -423,7 +445,7 @@ ip_input(struct mbuf *m)
*/
ip->ip_len = ntohs(ip->ip_len);
if (ip->ip_len < hlen) {
- V_ipstat.ips_badlen++;
+ IPSTAT_INC(ips_badlen);
goto bad;
}
ip->ip_off = ntohs(ip->ip_off);
@@ -436,7 +458,7 @@ ip_input(struct mbuf *m)
*/
if (m->m_pkthdr.len < ip->ip_len) {
tooshort:
- V_ipstat.ips_tooshort++;
+ IPSTAT_INC(ips_tooshort);
goto bad;
}
if (m->m_pkthdr.len > ip->ip_len) {
@@ -587,7 +609,7 @@ passin:
}
/* RFC 3927 2.7: Do not forward datagrams for 169.254.0.0/16. */
if (IN_LINKLOCAL(ntohl(ip->ip_dst.s_addr))) {
- V_ipstat.ips_cantforward++;
+ IPSTAT_INC(ips_cantforward);
m_freem(m);
return;
}
@@ -603,7 +625,7 @@ passin:
*/
if (ip_mforward &&
ip_mforward(ip, m->m_pkthdr.rcvif, m, 0) != 0) {
- V_ipstat.ips_cantforward++;
+ IPSTAT_INC(ips_cantforward);
m_freem(m);
return;
}
@@ -615,7 +637,7 @@ passin:
*/
if (ip->ip_p == IPPROTO_IGMP)
goto ours;
- V_ipstat.ips_forward++;
+ IPSTAT_INC(ips_forward);
}
/*
* Assume the packet is for us, to avoid prematurely taking
@@ -645,7 +667,7 @@ passin:
* Not for us; forward if possible and desirable.
*/
if (V_ipforwarding == 0) {
- V_ipstat.ips_cantforward++;
+ IPSTAT_INC(ips_cantforward);
m_freem(m);
} else {
#ifdef IPSEC
@@ -705,7 +727,7 @@ ours:
/*
* Switch out to protocol's input routine.
*/
- V_ipstat.ips_delivered++;
+ IPSTAT_INC(ips_delivered);
(*inetsw[ip_protox[ip->ip_p]].pr_input)(m, hlen);
return;
@@ -803,8 +825,8 @@ ip_reass(struct mbuf *m)
/* If maxnipq or maxfragsperpacket are 0, never accept fragments. */
if (V_maxnipq == 0 || V_maxfragsperpacket == 0) {
- V_ipstat.ips_fragments++;
- V_ipstat.ips_fragdropped++;
+ IPSTAT_INC(ips_fragments);
+ IPSTAT_INC(ips_fragdropped);
m_freem(m);
return (NULL);
}
@@ -846,14 +868,14 @@ ip_reass(struct mbuf *m)
for (i = 0; i < IPREASS_NHASH; i++) {
struct ipq *r = TAILQ_LAST(&V_ipq[i], ipqhead);
if (r) {
- V_ipstat.ips_fragtimeout +=
- r->ipq_nfrags;
+ IPSTAT_ADD(ips_fragtimeout,
+ r->ipq_nfrags);
ip_freef(&V_ipq[i], r);
break;
}
}
} else {
- V_ipstat.ips_fragtimeout += q->ipq_nfrags;
+ IPSTAT_ADD(ips_fragtimeout, q->ipq_nfrags);
ip_freef(head, q);
}
}
@@ -870,7 +892,7 @@ found:
* that's a non-zero multiple of 8 bytes.
*/
if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) {
- V_ipstat.ips_toosmall++; /* XXX */
+ IPSTAT_INC(ips_toosmall); /* XXX */
goto dropfrag;
}
m->m_flags |= M_FRAG;
@@ -883,7 +905,7 @@ found:
* Attempt reassembly; if it succeeds, proceed.
* ip_reass() will return a different mbuf.
*/
- V_ipstat.ips_fragments++;
+ IPSTAT_INC(ips_fragments);
m->m_pkthdr.header = ip;
/* Previous ip_reass() started here. */
@@ -994,7 +1016,7 @@ found:
}
nq = q->m_nextpkt;
m->m_nextpkt = nq;
- V_ipstat.ips_fragdropped++;
+ IPSTAT_INC(ips_fragdropped);
fp->ipq_nfrags--;
m_freem(q);
}
@@ -1013,7 +1035,7 @@ found:
for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt) {
if (GETIP(q)->ip_off != next) {
if (fp->ipq_nfrags > V_maxfragsperpacket) {
- V_ipstat.ips_fragdropped += fp->ipq_nfrags;
+ IPSTAT_ADD(ips_fragdropped, fp->ipq_nfrags);
ip_freef(head, fp);
}
goto done;
@@ -1023,7 +1045,7 @@ found:
/* Make sure the last packet didn't have the IP_MF flag */
if (p->m_flags & M_FRAG) {
if (fp->ipq_nfrags > V_maxfragsperpacket) {
- V_ipstat.ips_fragdropped += fp->ipq_nfrags;
+ IPSTAT_ADD(ips_fragdropped, fp->ipq_nfrags);
ip_freef(head, fp);
}
goto done;
@@ -1035,8 +1057,8 @@ found:
q = fp->ipq_frags;
ip = GETIP(q);
if (next + (ip->ip_hl << 2) > IP_MAXPACKET) {
- V_ipstat.ips_toolong++;
- V_ipstat.ips_fragdropped += fp->ipq_nfrags;
+ IPSTAT_INC(ips_toolong);
+ IPSTAT_ADD(ips_fragdropped, fp->ipq_nfrags);
ip_freef(head, fp);
goto done;
}
@@ -1085,12 +1107,12 @@ found:
/* some debugging cruft by sklower, below, will go away soon */
if (m->m_flags & M_PKTHDR) /* XXX this should be done elsewhere */
m_fixhdr(m);
- V_ipstat.ips_reassembled++;
+ IPSTAT_INC(ips_reassembled);
IPQ_UNLOCK();
return (m);
dropfrag:
- V_ipstat.ips_fragdropped++;
+ IPSTAT_INC(ips_fragdropped);
if (fp != NULL)
fp->ipq_nfrags--;
m_freem(m);
@@ -1147,8 +1169,8 @@ ip_slowtimo(void)
fpp = fp;
fp = TAILQ_NEXT(fp, ipq_list);
if(--fpp->ipq_ttl == 0) {
- V_ipstat.ips_fragtimeout +=
- fpp->ipq_nfrags;
+ IPSTAT_ADD(ips_fragtimeout,
+ fpp->ipq_nfrags);
ip_freef(&V_ipq[i], fpp);
}
}
@@ -1162,8 +1184,8 @@ ip_slowtimo(void)
for (i = 0; i < IPREASS_NHASH; i++) {
while (V_nipq > V_maxnipq &&
!TAILQ_EMPTY(&V_ipq[i])) {
- V_ipstat.ips_fragdropped +=
- TAILQ_FIRST(&V_ipq[i])->ipq_nfrags;
+ IPSTAT_ADD(ips_fragdropped,
+ TAILQ_FIRST(&V_ipq[i])->ipq_nfrags);
ip_freef(&V_ipq[i],
TAILQ_FIRST(&V_ipq[i]));
}
@@ -1191,8 +1213,8 @@ ip_drain(void)
INIT_VNET_INET(vnet_iter);
for (i = 0; i < IPREASS_NHASH; i++) {
while(!TAILQ_EMPTY(&V_ipq[i])) {
- V_ipstat.ips_fragdropped +=
- TAILQ_FIRST(&V_ipq[i])->ipq_nfrags;
+ IPSTAT_ADD(ips_fragdropped,
+ TAILQ_FIRST(&V_ipq[i])->ipq_nfrags);
ip_freef(&V_ipq[i], TAILQ_FIRST(&V_ipq[i]));
}
}
@@ -1324,7 +1346,7 @@ ip_forward(struct mbuf *m, int srcrt)
int error, type = 0, code = 0, mtu = 0;
if (m->m_flags & (M_BCAST|M_MCAST) || in_canforward(ip->ip_dst) == 0) {
- V_ipstat.ips_cantforward++;
+ IPSTAT_INC(ips_cantforward);
m_freem(m);
return;
}
@@ -1443,11 +1465,11 @@ ip_forward(struct mbuf *m, int srcrt)
RTFREE(ro.ro_rt);
if (error)
- V_ipstat.ips_cantforward++;
+ IPSTAT_INC(ips_cantforward);
else {
- V_ipstat.ips_forward++;
+ IPSTAT_INC(ips_forward);
if (type)
- V_ipstat.ips_redirectsent++;
+ IPSTAT_INC(ips_redirectsent);
else {
if (mcopy)
m_freem(mcopy);
@@ -1499,7 +1521,7 @@ ip_forward(struct mbuf *m, int srcrt)
else
mtu = ip_next_mtu(ip->ip_len, 0);
}
- V_ipstat.ips_cantfrag++;
+ IPSTAT_INC(ips_cantfrag);
break;
case ENOBUFS:
diff --git a/sys/netinet/ip_ipsec.c b/sys/netinet/ip_ipsec.c
index 4e23a2b..b9dc483 100644
--- a/sys/netinet/ip_ipsec.c
+++ b/sys/netinet/ip_ipsec.c
@@ -129,7 +129,7 @@ ip_ipsec_fwd(struct mbuf *m)
KEY_FREESP(&sp);
splx(s);
if (error) {
- V_ipstat.ips_cantforward++;
+ IPSTAT_INC(ips_cantforward);
return 1;
}
#endif /* IPSEC */
diff --git a/sys/netinet/ip_mroute.c b/sys/netinet/ip_mroute.c
index 36a5efd..476ad20 100644
--- a/sys/netinet/ip_mroute.c
+++ b/sys/netinet/ip_mroute.c
@@ -53,11 +53,23 @@
* bandwidth metering and signaling
*/
+/*
+ * TODO: Prefix functions with ipmf_.
+ * TODO: Maintain a refcount on if_allmulti() in ifnet or in the protocol
+ * domain attachment (if_afdata) so we can track consumers of that service.
+ * TODO: Deprecate routing socket path for SIOCGETSGCNT and SIOCGETVIFCNT,
+ * move it to socket options.
+ * TODO: Cleanup LSRR removal further.
+ * TODO: Push RSVP stubs into raw_ip.c.
+ * TODO: Use bitstring.h for vif set.
+ * TODO: Fix mrt6_ioctl dangling ref when dynamically loaded.
+ * TODO: Sync ip6_mroute.c with this file.
+ */
+
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include "opt_inet.h"
-#include "opt_inet6.h"
#include "opt_mac.h"
#include "opt_mrouting.h"
@@ -65,7 +77,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/stddef.h>
#include <sys/lock.h>
+#include <sys/ktr.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/module.h>
@@ -81,9 +95,11 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/time.h>
#include <sys/vimage.h>
+
#include <net/if.h>
#include <net/netisr.h>
#include <net/route.h>
+
#include <netinet/in.h>
#include <netinet/igmp.h>
#include <netinet/in_systm.h>
@@ -98,96 +114,79 @@ __FBSDID("$FreeBSD$");
#include <netinet/udp.h>
#include <netinet/vinet.h>
-#ifdef INET6
-#include <netinet/ip6.h>
-#include <netinet6/in6_var.h>
-#include <netinet6/ip6_mroute.h>
-#include <netinet6/ip6_var.h>
-#endif
#include <machine/in_cksum.h>
#include <security/mac/mac_framework.h>
-/*
- * Control debugging code for rsvp and multicast routing code.
- * Can only set them with the debugger.
- */
-static u_int rsvpdebug; /* non-zero enables debugging */
-
-static u_int mrtdebug; /* any set of the flags below */
-#define DEBUG_MFC 0x02
-#define DEBUG_FORWARD 0x04
-#define DEBUG_EXPIRE 0x08
-#define DEBUG_XMIT 0x10
-#define DEBUG_PIM 0x20
+#ifndef KTR_IPMF
+#define KTR_IPMF KTR_SUBSYS
+#endif
#define VIFI_INVALID ((vifi_t) -1)
+#define M_HASCL(m) ((m)->m_flags & M_EXT)
-#define M_HASCL(m) ((m)->m_flags & M_EXT)
-
-static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast routing tables");
+static MALLOC_DEFINE(M_MRTABLE, "mroutetbl", "multicast forwarding cache");
/*
* Locking. We use two locks: one for the virtual interface table and
* one for the forwarding table. These locks may be nested in which case
* the VIF lock must always be taken first. Note that each lock is used
* to cover not only the specific data structure but also related data
- * structures. It may be better to add more fine-grained locking later;
- * it's not clear how performance-critical this code is.
- *
- * XXX: This module could particularly benefit from being cleaned
- * up to use the <sys/queue.h> macros.
- *
+ * structures.
*/
-static struct mrtstat mrtstat;
-SYSCTL_STRUCT(_net_inet_ip, OID_AUTO, mrtstat, CTLFLAG_RW,
- &mrtstat, mrtstat,
- "Multicast Routing Statistics (struct mrtstat, netinet/ip_mroute.h)");
-
-static struct mfc *mfctable[MFCTBLSIZ];
-SYSCTL_OPAQUE(_net_inet_ip, OID_AUTO, mfctable, CTLFLAG_RD,
- &mfctable, sizeof(mfctable), "S,*mfc[MFCTBLSIZ]",
- "Multicast Forwarding Table (struct *mfc[MFCTBLSIZ], netinet/ip_mroute.h)");
-
static struct mtx mrouter_mtx;
#define MROUTER_LOCK() mtx_lock(&mrouter_mtx)
#define MROUTER_UNLOCK() mtx_unlock(&mrouter_mtx)
#define MROUTER_LOCK_ASSERT() mtx_assert(&mrouter_mtx, MA_OWNED)
-#define MROUTER_LOCK_INIT() \
+#define MROUTER_LOCK_INIT() \
mtx_init(&mrouter_mtx, "IPv4 multicast forwarding", NULL, MTX_DEF)
#define MROUTER_LOCK_DESTROY() mtx_destroy(&mrouter_mtx)
+static struct mrtstat mrtstat;
+SYSCTL_STRUCT(_net_inet_ip, OID_AUTO, mrtstat, CTLFLAG_RW,
+ &mrtstat, mrtstat,
+ "IPv4 Multicast Forwarding Statistics (struct mrtstat, "
+ "netinet/ip_mroute.h)");
+
+static u_long mfchash;
+#define MFCHASH(a, g) \
+ ((((a).s_addr >> 20) ^ ((a).s_addr >> 10) ^ (a).s_addr ^ \
+ ((g).s_addr >> 20) ^ ((g).s_addr >> 10) ^ (g).s_addr) & mfchash)
+#define MFCHASHSIZE 256
+
+static u_char *nexpire; /* 0..mfchashsize-1 */
+static u_long mfchashsize; /* Hash size */
+LIST_HEAD(mfchashhdr, mfc) *mfchashtbl;
+
static struct mtx mfc_mtx;
-#define MFC_LOCK() mtx_lock(&mfc_mtx)
-#define MFC_UNLOCK() mtx_unlock(&mfc_mtx)
+#define MFC_LOCK() mtx_lock(&mfc_mtx)
+#define MFC_UNLOCK() mtx_unlock(&mfc_mtx)
#define MFC_LOCK_ASSERT() mtx_assert(&mfc_mtx, MA_OWNED)
-#define MFC_LOCK_INIT() mtx_init(&mfc_mtx, "mroute mfc table", NULL, MTX_DEF)
+#define MFC_LOCK_INIT() \
+ mtx_init(&mfc_mtx, "IPv4 multicast forwarding cache", NULL, MTX_DEF)
#define MFC_LOCK_DESTROY() mtx_destroy(&mfc_mtx)
+static vifi_t numvifs;
static struct vif viftable[MAXVIFS];
SYSCTL_OPAQUE(_net_inet_ip, OID_AUTO, viftable, CTLFLAG_RD,
&viftable, sizeof(viftable), "S,vif[MAXVIFS]",
- "Multicast Virtual Interfaces (struct vif[MAXVIFS], netinet/ip_mroute.h)");
+ "IPv4 Multicast Interfaces (struct vif[MAXVIFS], netinet/ip_mroute.h)");
static struct mtx vif_mtx;
-#define VIF_LOCK() mtx_lock(&vif_mtx)
-#define VIF_UNLOCK() mtx_unlock(&vif_mtx)
+#define VIF_LOCK() mtx_lock(&vif_mtx)
+#define VIF_UNLOCK() mtx_unlock(&vif_mtx)
#define VIF_LOCK_ASSERT() mtx_assert(&vif_mtx, MA_OWNED)
-#define VIF_LOCK_INIT() mtx_init(&vif_mtx, "mroute vif table", NULL, MTX_DEF)
+#define VIF_LOCK_INIT() \
+ mtx_init(&vif_mtx, "IPv4 multicast interfaces", NULL, MTX_DEF)
#define VIF_LOCK_DESTROY() mtx_destroy(&vif_mtx)
-static u_char nexpire[MFCTBLSIZ];
-
static eventhandler_tag if_detach_event_tag = NULL;
static struct callout expire_upcalls_ch;
-
#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
#define UPCALL_EXPIRE 6 /* number of timeouts */
-#define ENCAP_TTL 64
-
/*
* Bandwidth meter variables and constants
*/
@@ -223,7 +222,7 @@ SYSCTL_ULONG(_net_inet_pim, OID_AUTO, squelch_wholepkt, CTLFLAG_RW,
"Disable IGMP_WHOLEPKT notifications if rendezvous point is unspecified");
extern struct domain inetdomain;
-struct protosw in_pim_protosw = {
+static const struct protosw in_pim_protosw = {
.pr_type = SOCK_RAW,
.pr_domain = &inetdomain,
.pr_protocol = IPPROTO_PIM,
@@ -235,18 +234,6 @@ struct protosw in_pim_protosw = {
};
static const struct encaptab *pim_encap_cookie;
-#ifdef INET6
-/* ip6_mroute.c glue */
-extern struct in6_protosw in6_pim_protosw;
-static const struct encaptab *pim6_encap_cookie;
-
-extern int X_ip6_mrouter_set(struct socket *, struct sockopt *);
-extern int X_ip6_mrouter_get(struct socket *, struct sockopt *);
-extern int X_ip6_mrouter_done(void);
-extern int X_ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *);
-extern int X_mrt6_ioctl(int, caddr_t);
-#endif
-
static int pim_encapcheck(const struct mbuf *, int, int, void *);
/*
@@ -264,6 +251,7 @@ struct pim_encap_pimhdr {
struct pim pim;
uint32_t flags;
};
+#define PIM_ENCAP_TTL 64
static struct ip pim_encap_iphdr = {
#if BYTE_ORDER == LITTLE_ENDIAN
@@ -277,7 +265,7 @@ static struct ip pim_encap_iphdr = {
sizeof(struct ip), /* total length */
0, /* id */
0, /* frag offset */
- ENCAP_TTL,
+ PIM_ENCAP_TTL,
IPPROTO_PIM,
0, /* checksum */
};
@@ -297,129 +285,97 @@ static vifi_t reg_vif_num = VIFI_INVALID;
/*
* Private variables.
*/
-static vifi_t numvifs;
-static u_long X_ip_mcast_src(int vifi);
-static int X_ip_mforward(struct ip *ip, struct ifnet *ifp,
- struct mbuf *m, struct ip_moptions *imo);
+static u_long X_ip_mcast_src(int);
+static int X_ip_mforward(struct ip *, struct ifnet *, struct mbuf *,
+ struct ip_moptions *);
static int X_ip_mrouter_done(void);
-static int X_ip_mrouter_get(struct socket *so, struct sockopt *m);
-static int X_ip_mrouter_set(struct socket *so, struct sockopt *m);
-static int X_legal_vif_num(int vif);
-static int X_mrt_ioctl(int cmd, caddr_t data, int fibnum);
-
-static int get_sg_cnt(struct sioc_sg_req *);
-static int get_vif_cnt(struct sioc_vif_req *);
-static void if_detached_event(void *arg __unused, struct ifnet *);
-static int ip_mrouter_init(struct socket *, int);
-static int add_vif(struct vifctl *);
-static int del_vif_locked(vifi_t);
-static int del_vif(vifi_t);
-static int add_mfc(struct mfcctl2 *);
-static int del_mfc(struct mfcctl2 *);
-static int set_api_config(uint32_t *); /* chose API capabilities */
-static int socket_send(struct socket *, struct mbuf *, struct sockaddr_in *);
-static int set_assert(int);
-static void expire_upcalls(void *);
-static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, vifi_t);
-static void phyint_send(struct ip *, struct vif *, struct mbuf *);
-static void send_packet(struct vif *, struct mbuf *);
-
-/*
- * Bandwidth monitoring
- */
-static void free_bw_list(struct bw_meter *list);
-static int add_bw_upcall(struct bw_upcall *);
-static int del_bw_upcall(struct bw_upcall *);
-static void bw_meter_receive_packet(struct bw_meter *x, int plen,
- struct timeval *nowp);
-static void bw_meter_prepare_upcall(struct bw_meter *x, struct timeval *nowp);
-static void bw_upcalls_send(void);
-static void schedule_bw_meter(struct bw_meter *x, struct timeval *nowp);
-static void unschedule_bw_meter(struct bw_meter *x);
-static void bw_meter_process(void);
-static void expire_bw_upcalls_send(void *);
-static void expire_bw_meter_process(void *);
-
-static int pim_register_send(struct ip *, struct vif *,
- struct mbuf *, struct mfc *);
-static int pim_register_send_rp(struct ip *, struct vif *,
- struct mbuf *, struct mfc *);
-static int pim_register_send_upcall(struct ip *, struct vif *,
- struct mbuf *, struct mfc *);
-static struct mbuf *pim_register_prepare(struct ip *, struct mbuf *);
-
-/*
- * whether or not special PIM assert processing is enabled.
- */
-static int pim_assert;
-/*
- * Rate limit for assert notification messages, in usec
- */
-#define ASSERT_MSG_TIME 3000000
+static int X_ip_mrouter_get(struct socket *, struct sockopt *);
+static int X_ip_mrouter_set(struct socket *, struct sockopt *);
+static int X_legal_vif_num(int);
+static int X_mrt_ioctl(int, caddr_t, int);
+
+static int add_bw_upcall(struct bw_upcall *);
+static int add_mfc(struct mfcctl2 *);
+static int add_vif(struct vifctl *);
+static void bw_meter_prepare_upcall(struct bw_meter *, struct timeval *);
+static void bw_meter_process(void);
+static void bw_meter_receive_packet(struct bw_meter *, int,
+ struct timeval *);
+static void bw_upcalls_send(void);
+static int del_bw_upcall(struct bw_upcall *);
+static int del_mfc(struct mfcctl2 *);
+static int del_vif(vifi_t);
+static int del_vif_locked(vifi_t);
+static void expire_bw_meter_process(void *);
+static void expire_bw_upcalls_send(void *);
+static void expire_mfc(struct mfc *);
+static void expire_upcalls(void *);
+static void free_bw_list(struct bw_meter *);
+static int get_sg_cnt(struct sioc_sg_req *);
+static int get_vif_cnt(struct sioc_vif_req *);
+static void if_detached_event(void *, struct ifnet *);
+static int ip_mdq(struct mbuf *, struct ifnet *, struct mfc *, vifi_t);
+static int ip_mrouter_init(struct socket *, int);
+static __inline struct mfc *
+ mfc_find(struct in_addr *, struct in_addr *);
+static void phyint_send(struct ip *, struct vif *, struct mbuf *);
+static struct mbuf *
+ pim_register_prepare(struct ip *, struct mbuf *);
+static int pim_register_send(struct ip *, struct vif *,
+ struct mbuf *, struct mfc *);
+static int pim_register_send_rp(struct ip *, struct vif *,
+ struct mbuf *, struct mfc *);
+static int pim_register_send_upcall(struct ip *, struct vif *,
+ struct mbuf *, struct mfc *);
+static void schedule_bw_meter(struct bw_meter *, struct timeval *);
+static void send_packet(struct vif *, struct mbuf *);
+static int set_api_config(uint32_t *);
+static int set_assert(int);
+static int socket_send(struct socket *, struct mbuf *,
+ struct sockaddr_in *);
+static void unschedule_bw_meter(struct bw_meter *);
/*
- * Kernel multicast routing API capabilities and setup.
+ * Kernel multicast forwarding API capabilities and setup.
* If more API capabilities are added to the kernel, they should be
* recorded in `mrt_api_support'.
*/
+#define MRT_API_VERSION 0x0305
+
+static const int mrt_api_version = MRT_API_VERSION;
static const uint32_t mrt_api_support = (MRT_MFC_FLAGS_DISABLE_WRONGVIF |
MRT_MFC_FLAGS_BORDER_VIF |
MRT_MFC_RP |
MRT_MFC_BW_UPCALL);
static uint32_t mrt_api_config = 0;
-/*
- * Hash function for a source, group entry
- */
-#define MFCHASH(a, g) MFCHASHMOD(((a) >> 20) ^ ((a) >> 10) ^ (a) ^ \
- ((g) >> 20) ^ ((g) >> 10) ^ (g))
+static int pim_assert_enabled;
+static struct timeval pim_assert_interval = { 3, 0 }; /* Rate limit */
/*
- * Find a route for a given origin IP address and Multicast group address
- * Statistics are updated by the caller if needed
- * (mrtstat.mrts_mfc_lookups and mrtstat.mrts_mfc_misses)
+ * Find a route for a given origin IP address and multicast group address.
+ * Statistics must be updated by the caller.
*/
-static struct mfc *
-mfc_find(in_addr_t o, in_addr_t g)
+static __inline struct mfc *
+mfc_find(struct in_addr *o, struct in_addr *g)
{
- struct mfc *rt;
+ struct mfc *rt;
- MFC_LOCK_ASSERT();
+ MFC_LOCK_ASSERT();
- for (rt = mfctable[MFCHASH(o,g)]; rt; rt = rt->mfc_next)
- if ((rt->mfc_origin.s_addr == o) &&
- (rt->mfc_mcastgrp.s_addr == g) && (rt->mfc_stall == NULL))
- break;
- return rt;
-}
+ LIST_FOREACH(rt, &mfchashtbl[MFCHASH(*o, *g)], mfc_hash) {
+ if (in_hosteq(rt->mfc_origin, *o) &&
+ in_hosteq(rt->mfc_mcastgrp, *g) &&
+ TAILQ_EMPTY(&rt->mfc_stall))
+ break;
+ }
-/*
- * Macros to compute elapsed time efficiently
- * Borrowed from Van Jacobson's scheduling code
- */
-#define TV_DELTA(a, b, delta) { \
- int xxs; \
- delta = (a).tv_usec - (b).tv_usec; \
- if ((xxs = (a).tv_sec - (b).tv_sec)) { \
- switch (xxs) { \
- case 2: \
- delta += 1000000; \
- /* FALLTHROUGH */ \
- case 1: \
- delta += 1000000; \
- break; \
- default: \
- delta += (1000000 * xxs); \
- } \
- } \
+ return (rt);
}
-#define TV_LT(a, b) (((a).tv_usec < (b).tv_usec && \
- (a).tv_sec <= (b).tv_sec) || (a).tv_sec < (b).tv_sec)
-
/*
- * Handle MRT setsockopt commands to modify the multicast routing tables.
+ * Handle MRT setsockopt commands to modify the multicast forwarding tables.
*/
static int
X_ip_mrouter_set(struct socket *so, struct sockopt *sopt)
@@ -526,15 +482,15 @@ static int
X_ip_mrouter_get(struct socket *so, struct sockopt *sopt)
{
int error;
- static int version = 0x0305; /* !!! why is this here? XXX */
switch (sopt->sopt_name) {
case MRT_VERSION:
- error = sooptcopyout(sopt, &version, sizeof version);
+ error = sooptcopyout(sopt, &mrt_api_version, sizeof mrt_api_version);
break;
case MRT_ASSERT:
- error = sooptcopyout(sopt, &pim_assert, sizeof pim_assert);
+ error = sooptcopyout(sopt, &pim_assert_enabled,
+ sizeof pim_assert_enabled);
break;
case MRT_API_SUPPORT:
@@ -556,7 +512,7 @@ X_ip_mrouter_get(struct socket *so, struct sockopt *sopt)
* Handle ioctl commands to obtain information from the cache
*/
static int
-X_mrt_ioctl(int cmd, caddr_t data, int fibnum)
+X_mrt_ioctl(int cmd, caddr_t data, int fibnum __unused)
{
int error = 0;
@@ -593,7 +549,7 @@ get_sg_cnt(struct sioc_sg_req *req)
struct mfc *rt;
MFC_LOCK();
- rt = mfc_find(req->src.s_addr, req->grp.s_addr);
+ rt = mfc_find(&req->src, &req->grp);
if (rt == NULL) {
MFC_UNLOCK();
req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
@@ -632,10 +588,8 @@ get_vif_cnt(struct sioc_vif_req *req)
static void
ip_mrouter_reset(void)
{
- bzero((caddr_t)mfctable, sizeof(mfctable));
- bzero((caddr_t)nexpire, sizeof(nexpire));
- pim_assert = 0;
+ pim_assert_enabled = 0;
mrt_api_config = 0;
callout_init(&expire_upcalls_ch, CALLOUT_MPSAFE);
@@ -652,55 +606,40 @@ if_detached_event(void *arg __unused, struct ifnet *ifp)
INIT_VNET_INET(curvnet);
vifi_t vifi;
int i;
- struct mfc *mfc;
- struct mfc *nmfc;
- struct mfc **ppmfc; /* Pointer to previous node's next-pointer */
- struct rtdetq *pq;
- struct rtdetq *npq;
MROUTER_LOCK();
+
if (V_ip_mrouter == NULL) {
MROUTER_UNLOCK();
+ return;
}
+ VIF_LOCK();
+ MFC_LOCK();
+
/*
* Tear down multicast forwarder state associated with this ifnet.
* 1. Walk the vif list, matching vifs against this ifnet.
* 2. Walk the multicast forwarding cache (mfc) looking for
* inner matches with this vif's index.
- * 3. Free any pending mbufs for this mfc.
- * 4. Free the associated mfc entry and state associated with this vif.
- * Be very careful about unlinking from a singly-linked list whose
- * "head node" is a pointer in a simple array.
- * 5. Free vif state. This should disable ALLMULTI on the interface.
+ * 3. Expire any matching multicast forwarding cache entries.
+ * 4. Free vif state. This should disable ALLMULTI on the interface.
*/
- VIF_LOCK();
- MFC_LOCK();
for (vifi = 0; vifi < numvifs; vifi++) {
if (viftable[vifi].v_ifp != ifp)
continue;
- for (i = 0; i < MFCTBLSIZ; i++) {
- ppmfc = &mfctable[i];
- for (mfc = mfctable[i]; mfc != NULL; ) {
- nmfc = mfc->mfc_next;
- if (mfc->mfc_parent == vifi) {
- for (pq = mfc->mfc_stall; pq != NULL; ) {
- npq = pq->next;
- m_freem(pq->m);
- free(pq, M_MRTABLE);
- pq = npq;
- }
- free_bw_list(mfc->mfc_bw_meter);
- free(mfc, M_MRTABLE);
- *ppmfc = nmfc;
- } else {
- ppmfc = &mfc->mfc_next;
+ for (i = 0; i < mfchashsize; i++) {
+ struct mfc *rt, *nrt;
+ for (rt = LIST_FIRST(&mfchashtbl[i]); rt; rt = nrt) {
+ nrt = LIST_NEXT(rt, mfc_hash);
+ if (rt->mfc_parent == vifi) {
+ expire_mfc(rt);
+ }
}
- mfc = nmfc;
- }
}
del_vif_locked(vifi);
}
+
MFC_UNLOCK();
VIF_UNLOCK();
@@ -708,16 +647,15 @@ if_detached_event(void *arg __unused, struct ifnet *ifp)
}
/*
- * Enable multicast routing
+ * Enable multicast forwarding.
*/
static int
ip_mrouter_init(struct socket *so, int version)
{
INIT_VNET_INET(curvnet);
- if (mrtdebug)
- log(LOG_DEBUG, "ip_mrouter_init: so_type = %d, pr_protocol = %d\n",
- so->so_type, so->so_proto->pr_protocol);
+ CTR3(KTR_IPMF, "%s: so_type %d, pr_protocol %d", __func__,
+ so->so_type, so->so_proto->pr_protocol);
if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_IGMP)
return EOPNOTSUPP;
@@ -739,6 +677,8 @@ ip_mrouter_init(struct socket *so, int version)
return (ENOMEM);
}
+ mfchashtbl = hashinit_flags(mfchashsize, M_MRTABLE, &mfchash, HASH_NOWAIT);
+
callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, NULL);
callout_reset(&bw_upcalls_ch, BW_UPCALLS_PERIOD,
@@ -749,14 +689,13 @@ ip_mrouter_init(struct socket *so, int version)
MROUTER_UNLOCK();
- if (mrtdebug)
- log(LOG_DEBUG, "ip_mrouter_init\n");
+ CTR1(KTR_IPMF, "%s: done", __func__);
return 0;
}
/*
- * Disable multicast routing
+ * Disable multicast forwarding.
*/
static int
X_ip_mrouter_done(void)
@@ -766,8 +705,6 @@ X_ip_mrouter_done(void)
int i;
struct ifnet *ifp;
struct ifreq ifr;
- struct mfc *rt;
- struct rtdetq *rte;
MROUTER_LOCK();
@@ -783,12 +720,13 @@ X_ip_mrouter_done(void)
mrt_api_config = 0;
VIF_LOCK();
+
/*
* For each phyint in use, disable promiscuous reception of all IP
* multicasts.
*/
for (vifi = 0; vifi < numvifs; vifi++) {
- if (viftable[vifi].v_lcl_addr.s_addr != 0 &&
+ if (!in_nullhost(viftable[vifi].v_lcl_addr) &&
!(viftable[vifi].v_flags & (VIFF_TUNNEL | VIFF_REGISTER))) {
struct sockaddr_in *so = (struct sockaddr_in *)&(ifr.ifr_addr);
@@ -801,46 +739,44 @@ X_ip_mrouter_done(void)
}
bzero((caddr_t)viftable, sizeof(viftable));
numvifs = 0;
- pim_assert = 0;
+ pim_assert_enabled = 0;
+
VIF_UNLOCK();
+
EVENTHANDLER_DEREGISTER(ifnet_departure_event, if_detach_event_tag);
- /*
- * Free all multicast forwarding cache entries.
- */
callout_stop(&expire_upcalls_ch);
callout_stop(&bw_upcalls_ch);
callout_stop(&bw_meter_ch);
MFC_LOCK();
- for (i = 0; i < MFCTBLSIZ; i++) {
- for (rt = mfctable[i]; rt != NULL; ) {
- struct mfc *nr = rt->mfc_next;
- for (rte = rt->mfc_stall; rte != NULL; ) {
- struct rtdetq *n = rte->next;
-
- m_freem(rte->m);
- free(rte, M_MRTABLE);
- rte = n;
- }
- free_bw_list(rt->mfc_bw_meter);
- free(rt, M_MRTABLE);
- rt = nr;
+ /*
+ * Free all multicast forwarding cache entries.
+ * Do not use hashdestroy(), as we must perform other cleanup.
+ */
+ for (i = 0; i < mfchashsize; i++) {
+ struct mfc *rt, *nrt;
+ for (rt = LIST_FIRST(&mfchashtbl[i]); rt; rt = nrt) {
+ nrt = LIST_NEXT(rt, mfc_hash);
+ expire_mfc(rt);
}
}
- bzero((caddr_t)mfctable, sizeof(mfctable));
- bzero((caddr_t)nexpire, sizeof(nexpire));
+ free(mfchashtbl, M_MRTABLE);
+ mfchashtbl = NULL;
+
+ bzero(nexpire, sizeof(nexpire[0]) * mfchashsize);
+
bw_upcalls_n = 0;
bzero(bw_meter_timers, sizeof(bw_meter_timers));
+
MFC_UNLOCK();
reg_vif_num = VIFI_INVALID;
MROUTER_UNLOCK();
- if (mrtdebug)
- log(LOG_DEBUG, "ip_mrouter_done\n");
+ CTR1(KTR_IPMF, "%s: done", __func__);
return 0;
}
@@ -854,7 +790,7 @@ set_assert(int i)
if ((i != 1) && (i != 0))
return EINVAL;
- pim_assert = i;
+ pim_assert_enabled = i;
return 0;
}
@@ -878,17 +814,22 @@ set_api_config(uint32_t *apival)
*apival = 0;
return EPERM;
}
- if (pim_assert) {
+ if (pim_assert_enabled) {
*apival = 0;
return EPERM;
}
- for (i = 0; i < MFCTBLSIZ; i++) {
- if (mfctable[i] != NULL) {
+
+ MFC_LOCK();
+
+ for (i = 0; i < mfchashsize; i++) {
+ if (LIST_FIRST(&mfchashtbl[i]) != NULL) {
*apival = 0;
return EPERM;
}
}
+ MFC_UNLOCK();
+
mrt_api_config = *apival & mrt_api_support;
*apival = mrt_api_config;
@@ -918,11 +859,11 @@ add_vif(struct vifctl *vifcp)
VIF_UNLOCK();
return EINVAL;
}
- if (vifp->v_lcl_addr.s_addr != INADDR_ANY) {
+ if (!in_nullhost(vifp->v_lcl_addr)) {
VIF_UNLOCK();
return EADDRINUSE;
}
- if (vifcp->vifc_lcl_addr.s_addr == INADDR_ANY) {
+ if (in_nullhost(vifcp->vifc_lcl_addr)) {
VIF_UNLOCK();
return EADDRNOTAVAIL;
}
@@ -946,14 +887,12 @@ add_vif(struct vifctl *vifcp)
}
if ((vifcp->vifc_flags & VIFF_TUNNEL) != 0) {
- log(LOG_ERR, "tunnels are no longer supported\n");
+ CTR1(KTR_IPMF, "%s: tunnels are no longer supported", __func__);
VIF_UNLOCK();
return EOPNOTSUPP;
} else if (vifcp->vifc_flags & VIFF_REGISTER) {
ifp = &multicast_register_if;
- if (mrtdebug)
- log(LOG_DEBUG, "Adding a register vif, ifp: %p\n",
- (void *)&multicast_register_if);
+ CTR2(KTR_IPMF, "%s: add register vif for ifp %p", __func__, ifp);
if (reg_vif_num == VIFI_INVALID) {
if_initname(&multicast_register_if, "register_vif", 0);
multicast_register_if.if_flags = IFF_LOOPBACK;
@@ -978,8 +917,6 @@ add_vif(struct vifctl *vifcp)
vifp->v_lcl_addr = vifcp->vifc_lcl_addr;
vifp->v_rmt_addr = vifcp->vifc_rmt_addr;
vifp->v_ifp = ifp;
- vifp->v_rsvp_on = 0;
- vifp->v_rsvpd = NULL;
/* initialize per vif pkt counters */
vifp->v_pkt_in = 0;
vifp->v_pkt_out = 0;
@@ -988,17 +925,14 @@ add_vif(struct vifctl *vifcp)
bzero(&vifp->v_route, sizeof(vifp->v_route));
/* Adjust numvifs up if the vifi is higher than numvifs */
- if (numvifs <= vifcp->vifc_vifi) numvifs = vifcp->vifc_vifi + 1;
+ if (numvifs <= vifcp->vifc_vifi)
+ numvifs = vifcp->vifc_vifi + 1;
VIF_UNLOCK();
- if (mrtdebug)
- log(LOG_DEBUG, "add_vif #%d, lcladdr %lx, %s %lx, thresh %x\n",
- vifcp->vifc_vifi,
- (u_long)ntohl(vifcp->vifc_lcl_addr.s_addr),
- (vifcp->vifc_flags & VIFF_TUNNEL) ? "rmtaddr" : "mask",
- (u_long)ntohl(vifcp->vifc_rmt_addr.s_addr),
- vifcp->vifc_threshold);
+ CTR4(KTR_IPMF, "%s: add vif %d laddr %s thresh %x", __func__,
+ (int)vifcp->vifc_vifi, inet_ntoa(vifcp->vifc_lcl_addr),
+ (int)vifcp->vifc_threshold);
return 0;
}
@@ -1017,7 +951,7 @@ del_vif_locked(vifi_t vifi)
return EINVAL;
}
vifp = &viftable[vifi];
- if (vifp->v_lcl_addr.s_addr == INADDR_ANY) {
+ if (in_nullhost(vifp->v_lcl_addr)) {
return EADDRNOTAVAIL;
}
@@ -1029,12 +963,11 @@ del_vif_locked(vifi_t vifi)
bzero((caddr_t)vifp, sizeof (*vifp));
- if (mrtdebug)
- log(LOG_DEBUG, "del_vif %d, numvifs %d\n", vifi, numvifs);
+ CTR2(KTR_IPMF, "%s: delete vif %d", __func__, (int)vifi);
/* Adjust numvifs down */
for (vifi = numvifs; vifi > 0; vifi--)
- if (viftable[vifi-1].v_lcl_addr.s_addr != INADDR_ANY)
+ if (!in_nullhost(viftable[vifi-1].v_lcl_addr))
break;
numvifs = vifi;
@@ -1089,9 +1022,25 @@ init_mfc_params(struct mfc *rt, struct mfcctl2 *mfccp)
rt->mfc_pkt_cnt = 0;
rt->mfc_byte_cnt = 0;
rt->mfc_wrong_if = 0;
- rt->mfc_last_assert.tv_sec = rt->mfc_last_assert.tv_usec = 0;
+ timevalclear(&rt->mfc_last_assert);
}
+static void
+expire_mfc(struct mfc *rt)
+{
+ struct rtdetq *rte, *nrte;
+
+ free_bw_list(rt->mfc_bw_meter);
+
+ TAILQ_FOREACH_SAFE(rte, &rt->mfc_stall, rte_link, nrte) {
+ m_freem(rte->m);
+ TAILQ_REMOVE(&rt->mfc_stall, rte, rte_link);
+ free(rte, M_MRTABLE);
+ }
+
+ LIST_REMOVE(rt, mfc_hash);
+ free(rt, M_MRTABLE);
+}
/*
* Add an mfc entry
@@ -1100,67 +1049,58 @@ static int
add_mfc(struct mfcctl2 *mfccp)
{
struct mfc *rt;
- u_long hash;
- struct rtdetq *rte;
+ struct rtdetq *rte, *nrte;
+ u_long hash = 0;
u_short nstl;
VIF_LOCK();
MFC_LOCK();
- rt = mfc_find(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr);
+ rt = mfc_find(&mfccp->mfcc_origin, &mfccp->mfcc_mcastgrp);
/* If an entry already exists, just update the fields */
if (rt) {
- if (mrtdebug & DEBUG_MFC)
- log(LOG_DEBUG,"add_mfc update o %lx g %lx p %x\n",
- (u_long)ntohl(mfccp->mfcc_origin.s_addr),
- (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
- mfccp->mfcc_parent);
-
+ CTR4(KTR_IPMF, "%s: update mfc orig %s group %lx parent %x",
+ __func__, inet_ntoa(mfccp->mfcc_origin),
+ (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
+ mfccp->mfcc_parent);
update_mfc_params(rt, mfccp);
MFC_UNLOCK();
VIF_UNLOCK();
- return 0;
+ return (0);
}
/*
* Find the entry for which the upcall was made and update
*/
- hash = MFCHASH(mfccp->mfcc_origin.s_addr, mfccp->mfcc_mcastgrp.s_addr);
- for (rt = mfctable[hash], nstl = 0; rt; rt = rt->mfc_next) {
-
- if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
- (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr) &&
- (rt->mfc_stall != NULL)) {
-
- if (nstl++)
- log(LOG_ERR, "add_mfc %s o %lx g %lx p %x dbx %p\n",
- "multiple kernel entries",
- (u_long)ntohl(mfccp->mfcc_origin.s_addr),
- (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
- mfccp->mfcc_parent, (void *)rt->mfc_stall);
-
- if (mrtdebug & DEBUG_MFC)
- log(LOG_DEBUG,"add_mfc o %lx g %lx p %x dbg %p\n",
- (u_long)ntohl(mfccp->mfcc_origin.s_addr),
+ nstl = 0;
+ hash = MFCHASH(mfccp->mfcc_origin, mfccp->mfcc_mcastgrp);
+ LIST_FOREACH(rt, &mfchashtbl[hash], mfc_hash) {
+ if (in_hosteq(rt->mfc_origin, mfccp->mfcc_origin) &&
+ in_hosteq(rt->mfc_mcastgrp, mfccp->mfcc_mcastgrp) &&
+ !TAILQ_EMPTY(&rt->mfc_stall)) {
+ CTR5(KTR_IPMF,
+ "%s: add mfc orig %s group %lx parent %x qh %p",
+ __func__, inet_ntoa(mfccp->mfcc_origin),
(u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
- mfccp->mfcc_parent, (void *)rt->mfc_stall);
-
- init_mfc_params(rt, mfccp);
-
- rt->mfc_expire = 0; /* Don't clean this guy up */
- nexpire[hash]--;
-
- /* free packets Qed at the end of this entry */
- for (rte = rt->mfc_stall; rte != NULL; ) {
- struct rtdetq *n = rte->next;
+ mfccp->mfcc_parent,
+ TAILQ_FIRST(&rt->mfc_stall));
+ if (nstl++)
+ CTR1(KTR_IPMF, "%s: multiple matches", __func__);
- ip_mdq(rte->m, rte->ifp, rt, -1);
- m_freem(rte->m);
- free(rte, M_MRTABLE);
- rte = n;
- }
- rt->mfc_stall = NULL;
+ init_mfc_params(rt, mfccp);
+ rt->mfc_expire = 0; /* Don't clean this guy up */
+ nexpire[hash]--;
+
+ /* Free queued packets, but attempt to forward them first. */
+ TAILQ_FOREACH_SAFE(rte, &rt->mfc_stall, rte_link, nrte) {
+ if (rte->ifp != NULL)
+ ip_mdq(rte->m, rte->ifp, rt, -1);
+ m_freem(rte->m);
+ TAILQ_REMOVE(&rt->mfc_stall, rte, rte_link);
+ rt->mfc_nstall--;
+ free(rte, M_MRTABLE);
+ }
}
}
@@ -1168,43 +1108,42 @@ add_mfc(struct mfcctl2 *mfccp)
* It is possible that an entry is being inserted without an upcall
*/
if (nstl == 0) {
- if (mrtdebug & DEBUG_MFC)
- log(LOG_DEBUG,"add_mfc no upcall h %lu o %lx g %lx p %x\n",
- hash, (u_long)ntohl(mfccp->mfcc_origin.s_addr),
- (u_long)ntohl(mfccp->mfcc_mcastgrp.s_addr),
- mfccp->mfcc_parent);
-
- for (rt = mfctable[hash]; rt != NULL; rt = rt->mfc_next) {
- if ((rt->mfc_origin.s_addr == mfccp->mfcc_origin.s_addr) &&
- (rt->mfc_mcastgrp.s_addr == mfccp->mfcc_mcastgrp.s_addr)) {
- init_mfc_params(rt, mfccp);
- if (rt->mfc_expire)
- nexpire[hash]--;
- rt->mfc_expire = 0;
- break; /* XXX */
- }
+ CTR1(KTR_IPMF, "%s: adding mfc w/o upcall", __func__);
+ LIST_FOREACH(rt, &mfchashtbl[hash], mfc_hash) {
+ if (in_hosteq(rt->mfc_origin, mfccp->mfcc_origin) &&
+ in_hosteq(rt->mfc_mcastgrp, mfccp->mfcc_mcastgrp)) {
+ init_mfc_params(rt, mfccp);
+ if (rt->mfc_expire)
+ nexpire[hash]--;
+ rt->mfc_expire = 0;
+ break; /* XXX */
+ }
}
+
if (rt == NULL) { /* no upcall, so make a new entry */
rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
if (rt == NULL) {
MFC_UNLOCK();
VIF_UNLOCK();
- return ENOBUFS;
+ return (ENOBUFS);
}
init_mfc_params(rt, mfccp);
- rt->mfc_expire = 0;
- rt->mfc_stall = NULL;
+ TAILQ_INIT(&rt->mfc_stall);
+ rt->mfc_nstall = 0;
+ rt->mfc_expire = 0;
rt->mfc_bw_meter = NULL;
+
/* insert new entry at head of hash chain */
- rt->mfc_next = mfctable[hash];
- mfctable[hash] = rt;
+ LIST_INSERT_HEAD(&mfchashtbl[hash], rt, mfc_hash);
}
}
+
MFC_UNLOCK();
VIF_UNLOCK();
- return 0;
+
+ return (0);
}
/*
@@ -1216,49 +1155,37 @@ del_mfc(struct mfcctl2 *mfccp)
struct in_addr origin;
struct in_addr mcastgrp;
struct mfc *rt;
- struct mfc **nptr;
- u_long hash;
- struct bw_meter *list;
origin = mfccp->mfcc_origin;
mcastgrp = mfccp->mfcc_mcastgrp;
- if (mrtdebug & DEBUG_MFC)
- log(LOG_DEBUG,"del_mfc orig %lx mcastgrp %lx\n",
- (u_long)ntohl(origin.s_addr), (u_long)ntohl(mcastgrp.s_addr));
+ CTR3(KTR_IPMF, "%s: delete mfc orig %s group %lx", __func__,
+ inet_ntoa(origin), (u_long)ntohl(mcastgrp.s_addr));
MFC_LOCK();
- hash = MFCHASH(origin.s_addr, mcastgrp.s_addr);
- for (nptr = &mfctable[hash]; (rt = *nptr) != NULL; nptr = &rt->mfc_next)
- if (origin.s_addr == rt->mfc_origin.s_addr &&
- mcastgrp.s_addr == rt->mfc_mcastgrp.s_addr &&
- rt->mfc_stall == NULL)
- break;
+ rt = mfc_find(&origin, &mcastgrp);
if (rt == NULL) {
MFC_UNLOCK();
return EADDRNOTAVAIL;
}
- *nptr = rt->mfc_next;
-
/*
* free the bw_meter entries
*/
- list = rt->mfc_bw_meter;
+ free_bw_list(rt->mfc_bw_meter);
rt->mfc_bw_meter = NULL;
+ LIST_REMOVE(rt, mfc_hash);
free(rt, M_MRTABLE);
- free_bw_list(list);
-
MFC_UNLOCK();
- return 0;
+ return (0);
}
/*
- * Send a message to the routing daemon on the multicast routing socket
+ * Send a message to the routing daemon on the multicast routing socket.
*/
static int
socket_send(struct socket *s, struct mbuf *mm, struct sockaddr_in *src)
@@ -1298,10 +1225,8 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
int error;
vifi_t vifi;
- if (mrtdebug & DEBUG_FORWARD)
- log(LOG_DEBUG, "ip_mforward: src %lx, dst %lx, ifp %p\n",
- (u_long)ntohl(ip->ip_src.s_addr), (u_long)ntohl(ip->ip_dst.s_addr),
- (void *)ifp);
+ CTR3(KTR_IPMF, "ip_mforward: delete mfc orig %s group %lx ifp %p",
+ inet_ntoa(ip->ip_src), (u_long)ntohl(ip->ip_dst.s_addr), ifp);
if (ip->ip_hl < (sizeof(struct ip) + TUNNEL_LEN) >> 2 ||
((u_char *)(ip + 1))[1] != IPOPT_LSRR ) {
@@ -1314,14 +1239,7 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
* Packet arrived through a source-route tunnel.
* Source-route tunnels are no longer supported.
*/
- static int last_log;
- if (last_log != time_uptime) {
- last_log = time_uptime;
- log(LOG_ERR,
- "ip_mforward: received source-routed packet from %lx\n",
- (u_long)ntohl(ip->ip_src.s_addr));
- }
- return 1;
+ return (1);
}
VIF_LOCK();
@@ -1329,26 +1247,11 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
if (imo && ((vifi = imo->imo_multicast_vif) < numvifs)) {
if (ip->ip_ttl < MAXTTL)
ip->ip_ttl++; /* compensate for -1 in *_send routines */
- if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
- struct vif *vifp = viftable + vifi;
-
- printf("Sending IPPROTO_RSVP from %lx to %lx on vif %d (%s%s)\n",
- (long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr),
- vifi,
- (vifp->v_flags & VIFF_TUNNEL) ? "tunnel on " : "",
- vifp->v_ifp->if_xname);
- }
error = ip_mdq(m, ifp, NULL, vifi);
MFC_UNLOCK();
VIF_UNLOCK();
return error;
}
- if (rsvpdebug && ip->ip_p == IPPROTO_RSVP) {
- printf("Warning: IPPROTO_RSVP from %lx to %lx without vif option\n",
- (long)ntohl(ip->ip_src.s_addr), (long)ntohl(ip->ip_dst.s_addr));
- if (!imo)
- printf("In fact, no options were specified at all\n");
- }
/*
* Don't forward a packet with time-to-live of zero or one,
@@ -1363,8 +1266,8 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
/*
* Determine forwarding vifs from the forwarding cache table
*/
- ++mrtstat.mrts_mfc_lookups;
- rt = mfc_find(ip->ip_src.s_addr, ip->ip_dst.s_addr);
+ MRTSTAT_INC(mrts_mfc_lookups);
+ rt = mfc_find(&ip->ip_src, &ip->ip_dst);
/* Entry exists, so forward if necessary */
if (rt != NULL) {
@@ -1383,25 +1286,24 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
u_long hash;
int hlen = ip->ip_hl << 2;
- ++mrtstat.mrts_mfc_misses;
-
- mrtstat.mrts_no_route++;
- if (mrtdebug & (DEBUG_FORWARD | DEBUG_MFC))
- log(LOG_DEBUG, "ip_mforward: no rte s %lx g %lx\n",
- (u_long)ntohl(ip->ip_src.s_addr),
- (u_long)ntohl(ip->ip_dst.s_addr));
+ MRTSTAT_INC(mrts_mfc_misses);
+ MRTSTAT_INC(mrts_no_route);
+ CTR2(KTR_IPMF, "ip_mforward: no mfc for (%s,%lx)",
+ inet_ntoa(ip->ip_src), (u_long)ntohl(ip->ip_dst.s_addr));
/*
* Allocate mbufs early so that we don't do extra work if we are
* just going to fail anyway. Make sure to pullup the header so
* that other people can't step on it.
*/
- rte = (struct rtdetq *)malloc((sizeof *rte), M_MRTABLE, M_NOWAIT);
+ rte = (struct rtdetq *)malloc((sizeof *rte), M_MRTABLE,
+ M_NOWAIT|M_ZERO);
if (rte == NULL) {
MFC_UNLOCK();
VIF_UNLOCK();
return ENOBUFS;
}
+
mb0 = m_copypacket(m, M_DONTWAIT);
if (mb0 && (M_HASCL(mb0) || mb0->m_len < hlen))
mb0 = m_pullup(mb0, hlen);
@@ -1413,12 +1315,12 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
}
/* is there an upcall waiting for this flow ? */
- hash = MFCHASH(ip->ip_src.s_addr, ip->ip_dst.s_addr);
- for (rt = mfctable[hash]; rt; rt = rt->mfc_next) {
- if ((ip->ip_src.s_addr == rt->mfc_origin.s_addr) &&
- (ip->ip_dst.s_addr == rt->mfc_mcastgrp.s_addr) &&
- (rt->mfc_stall != NULL))
- break;
+ hash = MFCHASH(ip->ip_src, ip->ip_dst);
+ LIST_FOREACH(rt, &mfchashtbl[hash], mfc_hash) {
+ if (in_hosteq(ip->ip_src, rt->mfc_origin) &&
+ in_hosteq(ip->ip_dst, rt->mfc_mcastgrp) &&
+ !TAILQ_EMPTY(&rt->mfc_stall))
+ break;
}
if (rt == NULL) {
@@ -1431,7 +1333,8 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
* Locate the vifi for the incoming interface for this packet.
* If none found, drop packet.
*/
- for (vifi=0; vifi < numvifs && viftable[vifi].v_ifp != ifp; vifi++)
+ for (vifi = 0; vifi < numvifs &&
+ viftable[vifi].v_ifp != ifp; vifi++)
;
if (vifi >= numvifs) /* vif not found, drop packet */
goto non_fatal;
@@ -1440,6 +1343,7 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
rt = (struct mfc *)malloc(sizeof(*rt), M_MRTABLE, M_NOWAIT);
if (rt == NULL)
goto fail;
+
/* Make a copy of the header to send to the user level process */
mm = m_copy(mb0, 0, hlen);
if (mm == NULL)
@@ -1455,12 +1359,12 @@ X_ip_mforward(struct ip *ip, struct ifnet *ifp, struct mbuf *m,
im->im_mbz = 0;
im->im_vif = vifi;
- mrtstat.mrts_upcalls++;
+ MRTSTAT_INC(mrts_upcalls);
k_igmpsrc.sin_addr = ip->ip_src;
if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) {
- log(LOG_WARNING, "ip_mforward: ip_mrouter socket queue full\n");
- ++mrtstat.mrts_upq_sockfull;
+ CTR0(KTR_IPMF, "ip_mforward: socket queue full");
+ MRTSTAT_INC(mrts_upq_sockfull);
fail1:
free(rt, M_MRTABLE);
fail:
@@ -1482,45 +1386,32 @@ fail:
}
rt->mfc_parent = -1;
- rt->mfc_rp.s_addr = INADDR_ANY; /* clear the RP address */
-
+ /* clear the RP address */
+ rt->mfc_rp.s_addr = INADDR_ANY;
rt->mfc_bw_meter = NULL;
/* link into table */
- rt->mfc_next = mfctable[hash];
- mfctable[hash] = rt;
- rt->mfc_stall = rte;
+ LIST_INSERT_HEAD(&mfchashtbl[hash], rt, mfc_hash);
+ TAILQ_INSERT_HEAD(&rt->mfc_stall, rte, rte_link);
+ rt->mfc_nstall++;
} else {
- /* determine if q has overflowed */
- int npkts = 0;
- struct rtdetq **p;
-
- /*
- * XXX ouch! we need to append to the list, but we
- * only have a pointer to the front, so we have to
- * scan the entire list every time.
- */
- for (p = &rt->mfc_stall; *p != NULL; p = &(*p)->next)
- npkts++;
-
- if (npkts > MAX_UPQ) {
- mrtstat.mrts_upq_ovflw++;
+ /* determine if queue has overflowed */
+ if (rt->mfc_nstall > MAX_UPQ) {
+ MRTSTAT_INC(mrts_upq_ovflw);
non_fatal:
free(rte, M_MRTABLE);
m_freem(mb0);
MFC_UNLOCK();
VIF_UNLOCK();
- return 0;
+ return (0);
}
-
- /* Add this entry to the end of the queue */
- *p = rte;
+ TAILQ_INSERT_TAIL(&rt->mfc_stall, rte, rte_link);
+ rt->mfc_nstall++;
}
rte->m = mb0;
rte->ifp = ifp;
- rte->next = NULL;
MFC_UNLOCK();
VIF_UNLOCK();
@@ -1535,58 +1426,44 @@ non_fatal:
static void
expire_upcalls(void *unused)
{
- struct rtdetq *rte;
- struct mfc *mfc, **nptr;
int i;
MFC_LOCK();
- for (i = 0; i < MFCTBLSIZ; i++) {
+
+ for (i = 0; i < mfchashsize; i++) {
+ struct mfc *rt, *nrt;
+
if (nexpire[i] == 0)
continue;
- nptr = &mfctable[i];
- for (mfc = *nptr; mfc != NULL; mfc = *nptr) {
- /*
- * Skip real cache entries
- * Make sure it wasn't marked to not expire (shouldn't happen)
- * If it expires now
- */
- if (mfc->mfc_stall != NULL && mfc->mfc_expire != 0 &&
- --mfc->mfc_expire == 0) {
- if (mrtdebug & DEBUG_EXPIRE)
- log(LOG_DEBUG, "expire_upcalls: expiring (%lx %lx)\n",
- (u_long)ntohl(mfc->mfc_origin.s_addr),
- (u_long)ntohl(mfc->mfc_mcastgrp.s_addr));
- /*
- * drop all the packets
- * free the mbuf with the pkt, if, timing info
- */
- for (rte = mfc->mfc_stall; rte; ) {
- struct rtdetq *n = rte->next;
- m_freem(rte->m);
- free(rte, M_MRTABLE);
- rte = n;
- }
- ++mrtstat.mrts_cache_cleanups;
- nexpire[i]--;
+ for (rt = LIST_FIRST(&mfchashtbl[i]); rt; rt = nrt) {
+ nrt = LIST_NEXT(rt, mfc_hash);
+
+ if (TAILQ_EMPTY(&rt->mfc_stall))
+ continue;
+
+ if (rt->mfc_expire == 0 || --rt->mfc_expire > 0)
+ continue;
/*
* free the bw_meter entries
*/
- while (mfc->mfc_bw_meter != NULL) {
- struct bw_meter *x = mfc->mfc_bw_meter;
+ while (rt->mfc_bw_meter != NULL) {
+ struct bw_meter *x = rt->mfc_bw_meter;
- mfc->mfc_bw_meter = x->bm_mfc_next;
+ rt->mfc_bw_meter = x->bm_mfc_next;
free(x, M_BWMETER);
}
- *nptr = mfc->mfc_next;
- free(mfc, M_MRTABLE);
- } else {
- nptr = &mfc->mfc_next;
+ MRTSTAT_INC(mrts_cache_cleanups);
+ CTR3(KTR_IPMF, "%s: expire (%lx, %lx)", __func__,
+ (u_long)ntohl(rt->mfc_origin.s_addr),
+ (u_long)ntohl(rt->mfc_mcastgrp.s_addr));
+
+ expire_mfc(rt);
}
- }
}
+
MFC_UNLOCK();
callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT, expire_upcalls, NULL);
@@ -1623,11 +1500,9 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif)
*/
vifi = rt->mfc_parent;
if ((vifi >= numvifs) || (viftable[vifi].v_ifp != ifp)) {
- /* came in the wrong interface */
- if (mrtdebug & DEBUG_FORWARD)
- log(LOG_DEBUG, "wrong if: ifp %p vifi %d vififp %p\n",
- (void *)ifp, vifi, (void *)viftable[vifi].v_ifp);
- ++mrtstat.mrts_wrong_if;
+ CTR4(KTR_IPMF, "%s: rx on wrong ifp %p (vifi %d, v_ifp %p)",
+ __func__, ifp, (int)vifi, viftable[vifi].v_ifp);
+ MRTSTAT_INC(mrts_wrong_if);
++rt->mfc_wrong_if;
/*
* If we are doing PIM assert processing, send a message
@@ -1637,12 +1512,10 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif)
* can complete the SPT switch, regardless of the type
* of the iif (broadcast media, GRE tunnel, etc).
*/
- if (pim_assert && (vifi < numvifs) && viftable[vifi].v_ifp) {
- struct timeval now;
- u_long delta;
+ if (pim_assert_enabled && (vifi < numvifs) && viftable[vifi].v_ifp) {
if (ifp == &multicast_register_if)
- pimstat.pims_rcv_registers_wrongiif++;
+ PIMSTAT_INC(pims_rcv_registers_wrongiif);
/* Get vifi for the incoming packet */
for (vifi=0; vifi < numvifs && viftable[vifi].v_ifp != ifp; vifi++)
@@ -1653,11 +1526,7 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif)
if (rt->mfc_flags[vifi] & MRT_MFC_FLAGS_DISABLE_WRONGVIF)
return 0; /* WRONGVIF disabled: ignore the packet */
- GET_TIME(now);
-
- TV_DELTA(now, rt->mfc_last_assert, delta);
-
- if (delta > ASSERT_MSG_TIME) {
+ if (ratecheck(&rt->mfc_last_assert, &pim_assert_interval)) {
struct sockaddr_in k_igmpsrc = { sizeof k_igmpsrc, AF_INET };
struct igmpmsg *im;
int hlen = ip->ip_hl << 2;
@@ -1668,20 +1537,17 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif)
if (mm == NULL)
return ENOBUFS;
- rt->mfc_last_assert = now;
-
im = mtod(mm, struct igmpmsg *);
im->im_msgtype = IGMPMSG_WRONGVIF;
im->im_mbz = 0;
im->im_vif = vifi;
- mrtstat.mrts_upcalls++;
+ MRTSTAT_INC(mrts_upcalls);
k_igmpsrc.sin_addr = im->im_src;
if (socket_send(V_ip_mrouter, mm, &k_igmpsrc) < 0) {
- log(LOG_WARNING,
- "ip_mforward: ip_mrouter socket queue full\n");
- ++mrtstat.mrts_upq_sockfull;
+ CTR1(KTR_IPMF, "%s: socket queue full", __func__);
+ MRTSTAT_INC(mrts_upq_sockfull);
return ENOBUFS;
}
}
@@ -1689,8 +1555,9 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif)
return 0;
}
+
/* If I sourced this packet, it counts as output, else it was input. */
- if (ip->ip_src.s_addr == viftable[vifi].v_lcl_addr.s_addr) {
+ if (in_hosteq(ip->ip_src, viftable[vifi].v_lcl_addr)) {
viftable[vifi].v_pkt_out++;
viftable[vifi].v_bytes_out += plen;
} else {
@@ -1723,7 +1590,7 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif)
struct bw_meter *x;
struct timeval now;
- GET_TIME(now);
+ microtime(&now);
MFC_LOCK_ASSERT();
for (x = rt->mfc_bw_meter; x != NULL; x = x->bm_mfc_next)
bw_meter_receive_packet(x, plen, &now);
@@ -1733,13 +1600,23 @@ ip_mdq(struct mbuf *m, struct ifnet *ifp, struct mfc *rt, vifi_t xmt_vif)
}
/*
- * check if a vif number is legal/ok. This is used by ip_output.
+ * Check if a vif number is legal/ok. This is used by in_mcast.c.
*/
static int
X_legal_vif_num(int vif)
{
- /* XXX unlocked, matter? */
- return (vif >= 0 && vif < numvifs);
+ int ret;
+
+ ret = 0;
+ if (vif < 0)
+ return (ret);
+
+ VIF_LOCK();
+ if (vif < numvifs)
+ ret = 1;
+ VIF_UNLOCK();
+
+ return (ret);
}
/*
@@ -1748,11 +1625,18 @@ X_legal_vif_num(int vif)
static u_long
X_ip_mcast_src(int vifi)
{
- /* XXX unlocked, matter? */
- if (vifi >= 0 && vifi < numvifs)
- return viftable[vifi].v_lcl_addr.s_addr;
- else
- return INADDR_ANY;
+ in_addr_t addr;
+
+ addr = INADDR_ANY;
+ if (vifi < 0)
+ return (addr);
+
+ VIF_LOCK();
+ if (vifi < numvifs)
+ addr = viftable[vifi].v_lcl_addr.s_addr;
+ VIF_UNLOCK();
+
+ return (addr);
}
static void
@@ -1801,173 +1685,33 @@ send_packet(struct vif *vifp, struct mbuf *m)
* the loopback interface, thus preventing looping.
*/
error = ip_output(m, NULL, &vifp->v_route, IP_FORWARDING, &imo, NULL);
- if (mrtdebug & DEBUG_XMIT) {
- log(LOG_DEBUG, "phyint_send on vif %td err %d\n",
- vifp - viftable, error);
- }
+ CTR3(KTR_IPMF, "%s: vif %td err %d", __func__,
+ (ptrdiff_t)(vifp - viftable), error);
}
+/*
+ * Stubs for old RSVP socket shim implementation.
+ */
+
static int
-X_ip_rsvp_vif(struct socket *so, struct sockopt *sopt)
+X_ip_rsvp_vif(struct socket *so __unused, struct sockopt *sopt __unused)
{
- INIT_VNET_INET(curvnet);
- int error, vifi;
-
- if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
- return EOPNOTSUPP;
-
- error = sooptcopyin(sopt, &vifi, sizeof vifi, sizeof vifi);
- if (error)
- return error;
-
- VIF_LOCK();
- if (vifi < 0 || vifi >= numvifs) { /* Error if vif is invalid */
- VIF_UNLOCK();
- return EADDRNOTAVAIL;
- }
-
- if (sopt->sopt_name == IP_RSVP_VIF_ON) {
- /* Check if socket is available. */
- if (viftable[vifi].v_rsvpd != NULL) {
- VIF_UNLOCK();
- return EADDRINUSE;
- }
-
- viftable[vifi].v_rsvpd = so;
- /* This may seem silly, but we need to be sure we don't over-increment
- * the RSVP counter, in case something slips up.
- */
- if (!viftable[vifi].v_rsvp_on) {
- viftable[vifi].v_rsvp_on = 1;
- V_rsvp_on++;
- }
- } else { /* must be VIF_OFF */
- /*
- * XXX as an additional consistency check, one could make sure
- * that viftable[vifi].v_rsvpd == so, otherwise passing so as
- * first parameter is pretty useless.
- */
- viftable[vifi].v_rsvpd = NULL;
- /*
- * This may seem silly, but we need to be sure we don't over-decrement
- * the RSVP counter, in case something slips up.
- */
- if (viftable[vifi].v_rsvp_on) {
- viftable[vifi].v_rsvp_on = 0;
- V_rsvp_on--;
- }
- }
- VIF_UNLOCK();
- return 0;
+ return (EOPNOTSUPP);
}
static void
-X_ip_rsvp_force_done(struct socket *so)
+X_ip_rsvp_force_done(struct socket *so __unused)
{
- INIT_VNET_INET(curvnet);
- int vifi;
- /* Don't bother if it is not the right type of socket. */
- if (so->so_type != SOCK_RAW || so->so_proto->pr_protocol != IPPROTO_RSVP)
- return;
-
- VIF_LOCK();
-
- /* The socket may be attached to more than one vif...this
- * is perfectly legal.
- */
- for (vifi = 0; vifi < numvifs; vifi++) {
- if (viftable[vifi].v_rsvpd == so) {
- viftable[vifi].v_rsvpd = NULL;
- /* This may seem silly, but we need to be sure we don't
- * over-decrement the RSVP counter, in case something slips up.
- */
- if (viftable[vifi].v_rsvp_on) {
- viftable[vifi].v_rsvp_on = 0;
- V_rsvp_on--;
- }
- }
- }
-
- VIF_UNLOCK();
}
static void
-X_rsvp_input(struct mbuf *m, int off)
+X_rsvp_input(struct mbuf *m, int off __unused)
{
- INIT_VNET_INET(curvnet);
- int vifi;
- struct ip *ip = mtod(m, struct ip *);
- struct sockaddr_in rsvp_src = { sizeof rsvp_src, AF_INET };
- struct ifnet *ifp;
- if (rsvpdebug)
- printf("rsvp_input: rsvp_on %d\n", V_rsvp_on);
-
- /* Can still get packets with rsvp_on = 0 if there is a local member
- * of the group to which the RSVP packet is addressed. But in this
- * case we want to throw the packet away.
- */
- if (!V_rsvp_on) {
- m_freem(m);
- return;
- }
-
- if (rsvpdebug)
- printf("rsvp_input: check vifs\n");
-
-#ifdef DIAGNOSTIC
- M_ASSERTPKTHDR(m);
-#endif
-
- ifp = m->m_pkthdr.rcvif;
-
- VIF_LOCK();
- /* Find which vif the packet arrived on. */
- for (vifi = 0; vifi < numvifs; vifi++)
- if (viftable[vifi].v_ifp == ifp)
- break;
-
- if (vifi == numvifs || viftable[vifi].v_rsvpd == NULL) {
- /*
- * Drop the lock here to avoid holding it across rip_input.
- * This could make rsvpdebug printfs wrong. If you care,
- * record the state of stuff before dropping the lock.
- */
- VIF_UNLOCK();
- /*
- * If the old-style non-vif-associated socket is set,
- * then use it. Otherwise, drop packet since there
- * is no specific socket for this vif.
- */
- if (V_ip_rsvpd != NULL) {
- if (rsvpdebug)
- printf("rsvp_input: Sending packet up old-style socket\n");
- rip_input(m, off); /* xxx */
- } else {
- if (rsvpdebug && vifi == numvifs)
- printf("rsvp_input: Can't find vif for packet.\n");
- else if (rsvpdebug && viftable[vifi].v_rsvpd == NULL)
- printf("rsvp_input: No socket defined for vif %d\n",vifi);
- m_freem(m);
- }
- return;
- }
- rsvp_src.sin_addr = ip->ip_src;
-
- if (rsvpdebug && m)
- printf("rsvp_input: m->m_len = %d, sbspace() = %ld\n",
- m->m_len,sbspace(&(viftable[vifi].v_rsvpd->so_rcv)));
-
- if (socket_send(viftable[vifi].v_rsvpd, m, &rsvp_src) < 0) {
- if (rsvpdebug)
- printf("rsvp_input: Failed to append to socket\n");
- } else {
- if (rsvpdebug)
- printf("rsvp_input: send packet up\n");
- }
- VIF_UNLOCK();
+ if (!V_rsvp_on)
+ m_freem(m);
}
/*
@@ -2033,7 +1777,7 @@ add_bw_upcall(struct bw_upcall *req)
* Find if we have already same bw_meter entry
*/
MFC_LOCK();
- mfc = mfc_find(req->bu_src.s_addr, req->bu_dst.s_addr);
+ mfc = mfc_find(&req->bu_src, &req->bu_dst);
if (mfc == NULL) {
MFC_UNLOCK();
return EADDRNOTAVAIL;
@@ -2058,7 +1802,7 @@ add_bw_upcall(struct bw_upcall *req)
/* Set the new bw_meter entry */
x->bm_threshold.b_time = req->bu_threshold.b_time;
- GET_TIME(now);
+ microtime(&now);
x->bm_start_time = now;
x->bm_threshold.b_packets = req->bu_threshold.b_packets;
x->bm_threshold.b_bytes = req->bu_threshold.b_bytes;
@@ -2103,8 +1847,9 @@ del_bw_upcall(struct bw_upcall *req)
return EOPNOTSUPP;
MFC_LOCK();
+
/* Find the corresponding MFC entry */
- mfc = mfc_find(req->bu_src.s_addr, req->bu_dst.s_addr);
+ mfc = mfc_find(&req->bu_src, &req->bu_dst);
if (mfc == NULL) {
MFC_UNLOCK();
return EADDRNOTAVAIL;
@@ -2336,10 +2081,10 @@ bw_upcalls_send(void)
* Send the upcalls
* XXX do we need to set the address in k_igmpsrc ?
*/
- mrtstat.mrts_upcalls++;
+ MRTSTAT_INC(mrts_upcalls);
if (socket_send(V_ip_mrouter, m, &k_igmpsrc) < 0) {
log(LOG_WARNING, "bw_upcalls_send: ip_mrouter socket queue full\n");
- ++mrtstat.mrts_upq_sockfull;
+ MRTSTAT_INC(mrts_upq_sockfull);
}
}
@@ -2446,7 +2191,7 @@ bw_meter_process()
int i;
struct timeval now, process_endtime;
- GET_TIME(now);
+ microtime(&now);
if (last_tv_sec == now.tv_sec)
return; /* nothing to do */
@@ -2564,15 +2309,12 @@ pim_register_send(struct ip *ip, struct vif *vifp, struct mbuf *m,
{
struct mbuf *mb_copy, *mm;
- if (mrtdebug & DEBUG_PIM)
- log(LOG_DEBUG, "pim_register_send: ");
-
/*
* Do not send IGMP_WHOLEPKT notifications to userland, if the
* rendezvous point was unspecified, and we were told not to.
*/
if (pim_squelch_wholepkt != 0 && (mrt_api_config & MRT_MFC_RP) &&
- (rt->mfc_rp.s_addr == INADDR_ANY))
+ in_nullhost(rt->mfc_rp))
return 0;
mb_copy = pim_register_prepare(ip, m);
@@ -2589,8 +2331,7 @@ pim_register_send(struct ip *ip, struct vif *vifp, struct mbuf *m,
mm = m_pullup(mm, sizeof(struct ip));
if (mm != NULL) {
ip = mtod(mm, struct ip *);
- if ((mrt_api_config & MRT_MFC_RP) &&
- (rt->mfc_rp.s_addr != INADDR_ANY)) {
+ if ((mrt_api_config & MRT_MFC_RP) && !in_nullhost(rt->mfc_rp)) {
pim_register_send_rp(ip, vifp, mm, rt);
} else {
pim_register_send_upcall(ip, vifp, mm, rt);
@@ -2690,19 +2431,17 @@ pim_register_send_upcall(struct ip *ip, struct vif *vifp,
k_igmpsrc.sin_addr = ip->ip_src;
- mrtstat.mrts_upcalls++;
+ MRTSTAT_INC(mrts_upcalls);
if (socket_send(V_ip_mrouter, mb_first, &k_igmpsrc) < 0) {
- if (mrtdebug & DEBUG_PIM)
- log(LOG_WARNING,
- "mcast: pim_register_send_upcall: ip_mrouter socket queue full");
- ++mrtstat.mrts_upq_sockfull;
+ CTR1(KTR_IPMF, "%s: socket queue full", __func__);
+ MRTSTAT_INC(mrts_upq_sockfull);
return ENOBUFS;
}
/* Keep statistics */
- pimstat.pims_snd_registers_msgs++;
- pimstat.pims_snd_registers_bytes += len;
+ PIMSTAT_INC(pims_snd_registers_msgs);
+ PIMSTAT_ADD(pims_snd_registers_bytes, len);
return 0;
}
@@ -2723,7 +2462,7 @@ pim_register_send_rp(struct ip *ip, struct vif *vifp, struct mbuf *mb_copy,
VIF_LOCK_ASSERT();
- if ((vifi >= numvifs) || (viftable[vifi].v_lcl_addr.s_addr == 0)) {
+ if ((vifi >= numvifs) || in_nullhost(viftable[vifi].v_lcl_addr)) {
m_freem(mb_copy);
return EADDRNOTAVAIL; /* The iif vif is invalid */
}
@@ -2772,14 +2511,14 @@ pim_register_send_rp(struct ip *ip, struct vif *vifp, struct mbuf *mb_copy,
send_packet(vifp, mb_first);
/* Keep statistics */
- pimstat.pims_snd_registers_msgs++;
- pimstat.pims_snd_registers_bytes += len;
+ PIMSTAT_INC(pims_snd_registers_msgs);
+ PIMSTAT_ADD(pims_snd_registers_bytes, len);
return 0;
}
/*
- * pim_encapcheck() is called by the encap[46]_input() path at runtime to
+ * pim_encapcheck() is called by the encap4_input() path at runtime to
* determine if a packet is for PIM; allowing PIM to be dynamically loaded
* into the kernel.
*/
@@ -2815,16 +2554,16 @@ pim_input(struct mbuf *m, int off)
int iphlen = off;
/* Keep statistics */
- pimstat.pims_rcv_total_msgs++;
- pimstat.pims_rcv_total_bytes += datalen;
+ PIMSTAT_INC(pims_rcv_total_msgs);
+ PIMSTAT_ADD(pims_rcv_total_bytes, datalen);
/*
* Validate lengths
*/
if (datalen < PIM_MINLEN) {
- pimstat.pims_rcv_tooshort++;
- log(LOG_ERR, "pim_input: packet size too small %d from %lx\n",
- datalen, (u_long)ip->ip_src.s_addr);
+ PIMSTAT_INC(pims_rcv_tooshort);
+ CTR3(KTR_IPMF, "%s: short packet (%d) from %s",
+ __func__, datalen, inet_ntoa(ip->ip_src));
m_freem(m);
return;
}
@@ -2844,9 +2583,10 @@ pim_input(struct mbuf *m, int off)
*/
if ((m->m_flags & M_EXT || m->m_len < minlen) &&
(m = m_pullup(m, minlen)) == 0) {
- log(LOG_ERR, "pim_input: m_pullup failure\n");
+ CTR1(KTR_IPMF, "%s: m_pullup() failed", __func__);
return;
}
+
/* m_pullup() may have given us a new mbuf so reset ip. */
ip = mtod(m, struct ip *);
ip_tos = ip->ip_tos;
@@ -2866,18 +2606,17 @@ pim_input(struct mbuf *m, int off)
if (PIM_VT_T(pim->pim_vt) == PIM_REGISTER && in_cksum(m, PIM_MINLEN) == 0) {
/* do nothing, checksum okay */
} else if (in_cksum(m, datalen)) {
- pimstat.pims_rcv_badsum++;
- if (mrtdebug & DEBUG_PIM)
- log(LOG_DEBUG, "pim_input: invalid checksum");
+ PIMSTAT_INC(pims_rcv_badsum);
+ CTR1(KTR_IPMF, "%s: invalid checksum", __func__);
m_freem(m);
return;
}
/* PIM version check */
if (PIM_VT_V(pim->pim_vt) < PIM_VERSION) {
- pimstat.pims_rcv_badversion++;
- log(LOG_ERR, "pim_input: incorrect version %d, expecting %d\n",
- PIM_VT_V(pim->pim_vt), PIM_VERSION);
+ PIMSTAT_INC(pims_rcv_badversion);
+ CTR3(KTR_IPMF, "%s: bad version %d expect %d", __func__,
+ (int)PIM_VT_V(pim->pim_vt), PIM_VERSION);
m_freem(m);
return;
}
@@ -2901,9 +2640,8 @@ pim_input(struct mbuf *m, int off)
VIF_LOCK();
if ((reg_vif_num >= numvifs) || (reg_vif_num == VIFI_INVALID)) {
VIF_UNLOCK();
- if (mrtdebug & DEBUG_PIM)
- log(LOG_DEBUG,
- "pim_input: register vif not set: %d\n", reg_vif_num);
+ CTR2(KTR_IPMF, "%s: register vif not set: %d", __func__,
+ (int)reg_vif_num);
m_freem(m);
return;
}
@@ -2915,11 +2653,9 @@ pim_input(struct mbuf *m, int off)
* Validate length
*/
if (datalen < PIM_REG_MINLEN) {
- pimstat.pims_rcv_tooshort++;
- pimstat.pims_rcv_badregisters++;
- log(LOG_ERR,
- "pim_input: register packet size too small %d from %lx\n",
- datalen, (u_long)ip->ip_src.s_addr);
+ PIMSTAT_INC(pims_rcv_tooshort);
+ PIMSTAT_INC(pims_rcv_badregisters);
+ CTR1(KTR_IPMF, "%s: register packet size too small", __func__);
m_freem(m);
return;
}
@@ -2927,33 +2663,22 @@ pim_input(struct mbuf *m, int off)
reghdr = (u_int32_t *)(pim + 1);
encap_ip = (struct ip *)(reghdr + 1);
- if (mrtdebug & DEBUG_PIM) {
- log(LOG_DEBUG,
- "pim_input[register], encap_ip: %lx -> %lx, encap_ip len %d\n",
- (u_long)ntohl(encap_ip->ip_src.s_addr),
- (u_long)ntohl(encap_ip->ip_dst.s_addr),
- ntohs(encap_ip->ip_len));
- }
+ CTR3(KTR_IPMF, "%s: register: encap ip src %s len %d",
+ __func__, inet_ntoa(encap_ip->ip_src), ntohs(encap_ip->ip_len));
/* verify the version number of the inner packet */
if (encap_ip->ip_v != IPVERSION) {
- pimstat.pims_rcv_badregisters++;
- if (mrtdebug & DEBUG_PIM) {
- log(LOG_DEBUG, "pim_input: invalid IP version (%d) "
- "of the inner packet\n", encap_ip->ip_v);
- }
+ PIMSTAT_INC(pims_rcv_badregisters);
+ CTR1(KTR_IPMF, "%s: bad encap ip version", __func__);
m_freem(m);
return;
}
/* verify the inner packet is destined to a mcast group */
if (!IN_MULTICAST(ntohl(encap_ip->ip_dst.s_addr))) {
- pimstat.pims_rcv_badregisters++;
- if (mrtdebug & DEBUG_PIM)
- log(LOG_DEBUG,
- "pim_input: inner packet of register is not "
- "multicast %lx\n",
- (u_long)ntohl(encap_ip->ip_dst.s_addr));
+ PIMSTAT_INC(pims_rcv_badregisters);
+ CTR2(KTR_IPMF, "%s: bad encap ip dest %s", __func__,
+ inet_ntoa(encap_ip->ip_dst));
m_freem(m);
return;
}
@@ -2992,30 +2717,28 @@ pim_input(struct mbuf *m, int off)
*/
mcp = m_copy(m, 0, iphlen + PIM_REG_MINLEN);
if (mcp == NULL) {
- log(LOG_ERR,
- "pim_input: pim register: could not copy register head\n");
+ CTR1(KTR_IPMF, "%s: m_copy() failed", __func__);
m_freem(m);
return;
}
/* Keep statistics */
/* XXX: registers_bytes include only the encap. mcast pkt */
- pimstat.pims_rcv_registers_msgs++;
- pimstat.pims_rcv_registers_bytes += ntohs(encap_ip->ip_len);
+ PIMSTAT_INC(pims_rcv_registers_msgs);
+ PIMSTAT_ADD(pims_rcv_registers_bytes, ntohs(encap_ip->ip_len));
/*
* forward the inner ip packet; point m_data at the inner ip.
*/
m_adj(m, iphlen + PIM_MINLEN);
- if (mrtdebug & DEBUG_PIM) {
- log(LOG_DEBUG,
- "pim_input: forwarding decapsulated register: "
- "src %lx, dst %lx, vif %d\n",
- (u_long)ntohl(encap_ip->ip_src.s_addr),
- (u_long)ntohl(encap_ip->ip_dst.s_addr),
- reg_vif_num);
- }
+ CTR4(KTR_IPMF,
+ "%s: forward decap'd REGISTER: src %lx dst %lx vif %d",
+ __func__,
+ (u_long)ntohl(encap_ip->ip_src.s_addr),
+ (u_long)ntohl(encap_ip->ip_dst.s_addr),
+ (int)reg_vif_num);
+
/* NB: vifp was collected above; can it change on us? */
if_simloop(vifp, m, dst.sin_family, 0);
@@ -3037,10 +2760,37 @@ pim_input_to_daemon:
return;
}
-/*
- * XXX: This is common code for dealing with initialization for both
- * the IPv4 and IPv6 multicast forwarding paths. It could do with cleanup.
- */
+static int
+sysctl_mfctable(SYSCTL_HANDLER_ARGS)
+{
+ struct mfc *rt;
+ int error, i;
+
+ if (req->newptr)
+ return (EPERM);
+ if (mfchashtbl == NULL) /* XXX unlocked */
+ return (0);
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error)
+ return (error);
+
+ MFC_LOCK();
+ for (i = 0; i < mfchashsize; i++) {
+ LIST_FOREACH(rt, &mfchashtbl[i], mfc_hash) {
+ error = SYSCTL_OUT(req, rt, sizeof(struct mfc));
+ if (error)
+ goto out_locked;
+ }
+ }
+out_locked:
+ MFC_UNLOCK();
+ return (error);
+}
+
+SYSCTL_NODE(_net_inet_ip, OID_AUTO, mfctable, CTLFLAG_RD, sysctl_mfctable,
+ "IPv4 Multicast Forwarding Table (struct *mfc[mfchashsize], "
+ "netinet/ip_mroute.h)");
+
static int
ip_mroute_modevent(module_t mod, int type, void *unused)
{
@@ -3051,9 +2801,20 @@ ip_mroute_modevent(module_t mod, int type, void *unused)
MROUTER_LOCK_INIT();
MFC_LOCK_INIT();
VIF_LOCK_INIT();
- ip_mrouter_reset();
+
+ mfchashsize = MFCHASHSIZE;
+ if (TUNABLE_ULONG_FETCH("net.inet.ip.mfchashsize", &mfchashsize) &&
+ !powerof2(mfchashsize)) {
+ printf("WARNING: %s not a power of 2; using default\n",
+ "net.inet.ip.mfchashsize");
+ mfchashsize = MFCHASHSIZE;
+ }
+ MALLOC(nexpire, u_char *, mfchashsize, M_MRTABLE, M_WAITOK|M_ZERO);
+
+ pim_squelch_wholepkt = 0;
TUNABLE_ULONG_FETCH("net.inet.pim.squelch_wholepkt",
&pim_squelch_wholepkt);
+ ip_mrouter_reset();
pim_encap_cookie = encap_attach_func(AF_INET, IPPROTO_PIM,
pim_encapcheck, &in_pim_protosw, NULL);
@@ -3065,36 +2826,12 @@ ip_mroute_modevent(module_t mod, int type, void *unused)
return (EINVAL);
}
-#ifdef INET6
- pim6_encap_cookie = encap_attach_func(AF_INET6, IPPROTO_PIM,
- pim_encapcheck, (struct protosw *)&in6_pim_protosw, NULL);
- if (pim6_encap_cookie == NULL) {
- printf("ip_mroute: unable to attach pim6 encap\n");
- if (pim_encap_cookie) {
- encap_detach(pim_encap_cookie);
- pim_encap_cookie = NULL;
- }
- VIF_LOCK_DESTROY();
- MFC_LOCK_DESTROY();
- MROUTER_LOCK_DESTROY();
- return (EINVAL);
- }
-#endif
-
ip_mcast_src = X_ip_mcast_src;
ip_mforward = X_ip_mforward;
ip_mrouter_done = X_ip_mrouter_done;
ip_mrouter_get = X_ip_mrouter_get;
ip_mrouter_set = X_ip_mrouter_set;
-#ifdef INET6
- ip6_mforward = X_ip6_mforward;
- ip6_mrouter_done = X_ip6_mrouter_done;
- ip6_mrouter_get = X_ip6_mrouter_get;
- ip6_mrouter_set = X_ip6_mrouter_set;
- mrt6_ioctl = X_mrt6_ioctl;
-#endif
-
ip_rsvp_force_done = X_ip_rsvp_force_done;
ip_rsvp_vif = X_ip_rsvp_vif;
@@ -3112,31 +2849,18 @@ ip_mroute_modevent(module_t mod, int type, void *unused)
* just loaded and then unloaded w/o starting up a user
* process we still need to cleanup.
*/
- if (V_ip_mrouter
-#ifdef INET6
- || ip6_mrouter
-#endif
- )
- return EINVAL;
-
-#ifdef INET6
- if (pim6_encap_cookie) {
- encap_detach(pim6_encap_cookie);
- pim6_encap_cookie = NULL;
- }
- X_ip6_mrouter_done();
- ip6_mforward = NULL;
- ip6_mrouter_done = NULL;
- ip6_mrouter_get = NULL;
- ip6_mrouter_set = NULL;
- mrt6_ioctl = NULL;
-#endif
+ if (V_ip_mrouter != NULL)
+ return (EINVAL);
if (pim_encap_cookie) {
encap_detach(pim_encap_cookie);
pim_encap_cookie = NULL;
}
X_ip_mrouter_done();
+
+ FREE(nexpire, M_MRTABLE);
+ nexpire = NULL;
+
ip_mcast_src = NULL;
ip_mforward = NULL;
ip_mrouter_done = NULL;
@@ -3166,4 +2890,5 @@ static moduledata_t ip_mroutemod = {
ip_mroute_modevent,
0
};
+
DECLARE_MODULE(ip_mroute, ip_mroutemod, SI_SUB_PSEUDO, SI_ORDER_ANY);
diff --git a/sys/netinet/ip_mroute.h b/sys/netinet/ip_mroute.h
index 4043e44..d5ef5e0 100644
--- a/sys/netinet/ip_mroute.h
+++ b/sys/netinet/ip_mroute.h
@@ -70,9 +70,6 @@
#define MRT_ADD_BW_UPCALL 111 /* create bandwidth monitor */
#define MRT_DEL_BW_UPCALL 112 /* delete bandwidth monitor */
-
-#define GET_TIME(t) microtime(&t)
-
/*
* Types and macros for handling bitmaps with one bit per virtual interface.
*/
@@ -224,6 +221,11 @@ struct mrtstat {
u_long mrts_upq_sockfull; /* upcalls dropped - socket full */
};
+#ifdef _KERNEL
+#define MRTSTAT_ADD(name, val) mrtstat.name += (val)
+#define MRTSTAT_INC(name) MRTSTAT_ADD(name, 1)
+#endif
+
/*
* Argument structure used by mrouted to get src-grp pkt counts
*/
@@ -253,8 +255,6 @@ struct sioc_vif_req {
struct vif {
u_char v_flags; /* VIFF_ flags defined above */
u_char v_threshold; /* min ttl required to forward on vif*/
- u_int v_rate_limit; /* ignored; kept for compatibility */
- struct tbf *v_tbf; /* ignored; kept for compatibility */
struct in_addr v_lcl_addr; /* local interface address */
struct in_addr v_rmt_addr; /* remote address (tunnels only) */
struct ifnet *v_ifp; /* pointer to interface */
@@ -263,16 +263,13 @@ struct vif {
u_long v_bytes_in; /* # bytes in on interface */
u_long v_bytes_out; /* # bytes out on interface */
struct route v_route; /* cached route */
- u_int v_rsvp_on; /* RSVP listening on this vif */
- struct socket *v_rsvpd; /* RSVP daemon socket */
};
/*
* The kernel's multicast forwarding cache entry structure
- * (A field for the type of service (mfc_tos) is to be added
- * at a future point)
*/
struct mfc {
+ LIST_ENTRY(mfc) mfc_hash;
struct in_addr mfc_origin; /* IP origin of mcasts */
struct in_addr mfc_mcastgrp; /* multicast group associated*/
vifi_t mfc_parent; /* incoming vif */
@@ -282,11 +279,11 @@ struct mfc {
u_long mfc_wrong_if; /* wrong if for src-grp */
int mfc_expire; /* time to clean entry up */
struct timeval mfc_last_assert; /* last time I sent an assert*/
- struct rtdetq *mfc_stall; /* q of packets awaiting mfc */
- struct mfc *mfc_next; /* next mfc entry */
uint8_t mfc_flags[MAXVIFS]; /* the MRT_MFC_FLAGS_* flags */
struct in_addr mfc_rp; /* the RP address */
struct bw_meter *mfc_bw_meter; /* list of bandwidth meters */
+ u_long mfc_nstall; /* # of packets awaiting mfc */
+ TAILQ_HEAD(, rtdetq) mfc_stall; /* q of packets awaiting mfc */
};
/*
@@ -311,19 +308,11 @@ struct igmpmsg {
* Argument structure used for pkt info. while upcall is made
*/
struct rtdetq {
+ TAILQ_ENTRY(rtdetq) rte_link;
struct mbuf *m; /* A copy of the packet */
struct ifnet *ifp; /* Interface pkt came in on */
vifi_t xmt_vif; /* Saved copy of imo_multicast_vif */
- struct rtdetq *next; /* Next in list of packets */
};
-
-#define MFCTBLSIZ 256
-#if (MFCTBLSIZ & (MFCTBLSIZ - 1)) == 0 /* from sys:route.h */
-#define MFCHASHMOD(h) ((h) & (MFCTBLSIZ - 1))
-#else
-#define MFCHASHMOD(h) ((h) % MFCTBLSIZ)
-#endif
-
#define MAX_UPQ 4 /* max. no of pkts in upcall Q */
/*
diff --git a/sys/netinet/ip_options.c b/sys/netinet/ip_options.c
index 74d54f2..dbb7d81 100644
--- a/sys/netinet/ip_options.c
+++ b/sys/netinet/ip_options.c
@@ -218,7 +218,7 @@ nosourcerouting:
#ifdef IPSTEALTH
dropit:
#endif
- V_ipstat.ips_cantforward++;
+ IPSTAT_INC(ips_cantforward);
m_freem(m);
return (1);
}
@@ -366,7 +366,7 @@ dropit:
return (0);
bad:
icmp_error(m, type, code, 0, 0);
- V_ipstat.ips_badoptions++;
+ IPSTAT_INC(ips_badoptions);
return (1);
}
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 90df601..16dba61 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -153,6 +153,10 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
if (inp != NULL) {
M_SETFIB(m, inp->inp_inc.inc_fibnum);
INP_LOCK_ASSERT(inp);
+ if (inp->inp_flags & (INP_HW_FLOWID|INP_SW_FLOWID)) {
+ m->m_pkthdr.flowid = inp->inp_flowid;
+ m->m_flags |= M_FLOWID;
+ }
}
if (opt) {
@@ -178,7 +182,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags,
ip->ip_v = IPVERSION;
ip->ip_hl = hlen >> 2;
ip->ip_id = ip_newid();
- V_ipstat.ips_localout++;
+ IPSTAT_INC(ips_localout);
} else {
hlen = ip->ip_hl << 2;
}
@@ -217,7 +221,7 @@ again:
if (flags & IP_SENDONES) {
if ((ia = ifatoia(ifa_ifwithbroadaddr(sintosa(dst)))) == NULL &&
(ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL) {
- V_ipstat.ips_noroute++;
+ IPSTAT_INC(ips_noroute);
error = ENETUNREACH;
goto bad;
}
@@ -229,7 +233,7 @@ again:
} else if (flags & IP_ROUTETOIF) {
if ((ia = ifatoia(ifa_ifwithdstaddr(sintosa(dst)))) == NULL &&
(ia = ifatoia(ifa_ifwithnet(sintosa(dst)))) == NULL) {
- V_ipstat.ips_noroute++;
+ IPSTAT_INC(ips_noroute);
error = ENETUNREACH;
goto bad;
}
@@ -261,7 +265,7 @@ again:
inp ? inp->inp_inc.inc_fibnum : M_GETFIB(m));
#endif
if (ro->ro_rt == NULL) {
- V_ipstat.ips_noroute++;
+ IPSTAT_INC(ips_noroute);
error = EHOSTUNREACH;
goto bad;
}
@@ -318,7 +322,7 @@ again:
*/
if ((imo == NULL) || (imo->imo_multicast_vif == -1)) {
if ((ifp->if_flags & IFF_MULTICAST) == 0) {
- V_ipstat.ips_noroute++;
+ IPSTAT_INC(ips_noroute);
error = ENETUNREACH;
goto bad;
}
@@ -416,7 +420,7 @@ again:
#endif /* ALTQ */
{
error = ENOBUFS;
- V_ipstat.ips_odropped++;
+ IPSTAT_INC(ips_odropped);
ifp->if_snd.ifq_drops += (ip->ip_len / ifp->if_mtu + 1);
goto bad;
}
@@ -534,7 +538,7 @@ passout:
if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET ||
(ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) {
if ((ifp->if_flags & IFF_LOOPBACK) == 0) {
- V_ipstat.ips_badaddr++;
+ IPSTAT_INC(ips_badaddr);
error = EADDRNOTAVAIL;
goto bad;
}
@@ -598,7 +602,7 @@ passout:
/* Balk when DF bit is set or the interface didn't support TSO. */
if ((ip->ip_off & IP_DF) || (m->m_pkthdr.csum_flags & CSUM_TSO)) {
error = EMSGSIZE;
- V_ipstat.ips_cantfrag++;
+ IPSTAT_INC(ips_cantfrag);
goto bad;
}
@@ -631,7 +635,7 @@ passout:
}
if (error == 0)
- V_ipstat.ips_fragmented++;
+ IPSTAT_INC(ips_fragmented);
done:
if (ro == &iproute && ro->ro_rt) {
@@ -667,7 +671,7 @@ ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
int nfrags;
if (ip->ip_off & IP_DF) { /* Fragmentation not allowed */
- V_ipstat.ips_cantfrag++;
+ IPSTAT_INC(ips_cantfrag);
return EMSGSIZE;
}
@@ -748,7 +752,7 @@ smart_frag_failure:
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
error = ENOBUFS;
- V_ipstat.ips_odropped++;
+ IPSTAT_INC(ips_odropped);
goto done;
}
m->m_flags |= (m0->m_flags & M_MCAST) | M_FRAG;
@@ -778,7 +782,7 @@ smart_frag_failure:
if (m->m_next == NULL) { /* copy failed */
m_free(m);
error = ENOBUFS; /* ??? */
- V_ipstat.ips_odropped++;
+ IPSTAT_INC(ips_odropped);
goto done;
}
m->m_pkthdr.len = mhlen + len;
@@ -794,7 +798,7 @@ smart_frag_failure:
*mnext = m;
mnext = &m->m_nextpkt;
}
- V_ipstat.ips_ofragments += nfrags;
+ IPSTAT_ADD(ips_ofragments, nfrags);
/* set first marker for fragment chain */
m0->m_flags |= M_FIRSTFRAG | M_FRAG;
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index b68f481..472a458 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -132,6 +132,11 @@ struct ipstat {
#ifdef _KERNEL
+#define IPSTAT_ADD(name, val) V_ipstat.name += (val)
+#define IPSTAT_SUB(name, val) V_ipstat.name -= (val)
+#define IPSTAT_INC(name) IPSTAT_ADD(name, 1)
+#define IPSTAT_DEC(name) IPSTAT_SUB(name, 1)
+
/* flags passed to ip_output as last parameter */
#define IP_FORWARDING 0x1 /* most of ip header exists */
#define IP_RAWOUTPUT 0x2 /* raw ip header exists */
diff --git a/sys/netinet/libalias/alias.c b/sys/netinet/libalias/alias.c
index 9d80da9..2e469d7 100644
--- a/sys/netinet/libalias/alias.c
+++ b/sys/netinet/libalias/alias.c
@@ -742,7 +742,7 @@ UdpAliasIn(struct libalias *la, struct ip *pip)
u_short alias_port;
u_short proxy_port;
int accumulate;
- int r = 0, error;
+ int error;
struct alias_data ad = {
.lnk = lnk,
.oaddr = &original_address,
@@ -762,6 +762,9 @@ UdpAliasIn(struct libalias *la, struct ip *pip)
/* Walk out chain. */
error = find_handler(IN, UDP, la, pip, &ad);
+ /* If we cannot figure out the packet, ignore it. */
+ if (error < 0)
+ return (PKT_ALIAS_IGNORED);
/* If UDP checksum is not zero, then adjust since destination port */
/* is being unaliased and destination address is being altered. */
@@ -801,13 +804,7 @@ UdpAliasIn(struct libalias *la, struct ip *pip)
&original_address, &pip->ip_dst, 2);
pip->ip_dst = original_address;
- /*
- * If we cannot figure out the packet, ignore it.
- */
- if (r < 0)
- return (PKT_ALIAS_IGNORED);
- else
- return (PKT_ALIAS_OK);
+ return (PKT_ALIAS_OK);
}
return (PKT_ALIAS_IGNORED);
}
@@ -1226,7 +1223,6 @@ FragmentOut(struct libalias *la, struct in_addr *ip_src, u_short *ip_sum)
(prototypes in alias.h)
*/
-// XXX ip free
int
LibAliasSaveFragment(struct libalias *la, char *ptr)
{
@@ -1246,7 +1242,6 @@ LibAliasSaveFragment(struct libalias *la, char *ptr)
return (iresult);
}
-// XXX ip free
char *
LibAliasGetFragment(struct libalias *la, char *ptr)
{
@@ -1268,7 +1263,6 @@ LibAliasGetFragment(struct libalias *la, char *ptr)
return (fptr);
}
-// XXX ip free
void
LibAliasFragmentIn(struct libalias *la, char *ptr, /* Points to correctly
* de-aliased header
diff --git a/sys/netinet/libalias/alias_cuseeme.c b/sys/netinet/libalias/alias_cuseeme.c
index f255942..28f5e93 100644
--- a/sys/netinet/libalias/alias_cuseeme.c
+++ b/sys/netinet/libalias/alias_cuseeme.c
@@ -64,7 +64,7 @@ AliasHandleCUSeeMeIn(struct libalias *la, struct ip *pip,
struct in_addr original_addr);
static int
-fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
+fingerprint(struct libalias *la, struct alias_data *ah)
{
if (ah->dport == NULL || ah->oaddr == NULL)
diff --git a/sys/netinet/libalias/alias_dummy.c b/sys/netinet/libalias/alias_dummy.c
index fc6a0f9..4283aaf 100644
--- a/sys/netinet/libalias/alias_dummy.c
+++ b/sys/netinet/libalias/alias_dummy.c
@@ -60,7 +60,7 @@ static void
AliasHandleDummy(struct libalias *la, struct ip *ip, struct alias_data *ah);
static int
-fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
+fingerprint(struct libalias *la, struct alias_data *ah)
{
/*
diff --git a/sys/netinet/libalias/alias_ftp.c b/sys/netinet/libalias/alias_ftp.c
index 50fa8d0..ef0e52c 100644
--- a/sys/netinet/libalias/alias_ftp.c
+++ b/sys/netinet/libalias/alias_ftp.c
@@ -104,7 +104,7 @@ AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *,
int maxpacketsize);
static int
-fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
+fingerprint(struct libalias *la, struct alias_data *ah)
{
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
diff --git a/sys/netinet/libalias/alias_irc.c b/sys/netinet/libalias/alias_irc.c
index 8197fb8..c01e8e6 100644
--- a/sys/netinet/libalias/alias_irc.c
+++ b/sys/netinet/libalias/alias_irc.c
@@ -93,7 +93,7 @@ AliasHandleIrcOut(struct libalias *, struct ip *, struct alias_link *,
int maxpacketsize);
static int
-fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
+fingerprint(struct libalias *la, struct alias_data *ah)
{
if (ah->dport == NULL || ah->dport == NULL || ah->lnk == NULL ||
diff --git a/sys/netinet/libalias/alias_mod.c b/sys/netinet/libalias/alias_mod.c
index 643fe5f..2713137 100644
--- a/sys/netinet/libalias/alias_mod.c
+++ b/sys/netinet/libalias/alias_mod.c
@@ -133,9 +133,10 @@ handler_chain_destroy(void)
static int
_attach_handler(struct proto_handler *p)
{
- struct proto_handler *b = NULL;
+ struct proto_handler *b;
- LIBALIAS_WLOCK_ASSERT();
+ LIBALIAS_WLOCK_ASSERT();
+ b = NULL;
LIST_FOREACH(b, &handler_chain, entries) {
if ((b->pri == p->pri) &&
(b->dir == p->dir) &&
@@ -172,10 +173,11 @@ _detach_handler(struct proto_handler *p)
int
LibAliasAttachHandlers(struct proto_handler *_p)
{
- int i, error = -1;
+ int i, error;
LIBALIAS_WLOCK();
- for (i=0; 1; i++) {
+ error = -1;
+ for (i = 0; 1; i++) {
if (*((int *)&_p[i]) == EOH)
break;
error = _attach_handler(&_p[i]);
@@ -189,10 +191,11 @@ LibAliasAttachHandlers(struct proto_handler *_p)
int
LibAliasDetachHandlers(struct proto_handler *_p)
{
- int i, error = -1;
+ int i, error;
LIBALIAS_WLOCK();
- for (i=0; 1; i++) {
+ error = -1;
+ for (i = 0; 1; i++) {
if (*((int *)&_p[i]) == EOH)
break;
error = _detach_handler(&_p[i]);
@@ -206,26 +209,27 @@ LibAliasDetachHandlers(struct proto_handler *_p)
int
detach_handler(struct proto_handler *_p)
{
- int error = -1;
+ int error;
LIBALIAS_WLOCK();
+ error = -1;
error = _detach_handler(_p);
LIBALIAS_WUNLOCK();
return (error);
}
int
-find_handler(int8_t dir, int8_t proto, struct libalias *la, struct ip *pip,
- struct alias_data *ad)
+find_handler(int8_t dir, int8_t proto, struct libalias *la, __unused struct ip *pip,
+ struct alias_data *ad)
{
struct proto_handler *p;
- int error = ENOENT;
+ int error;
LIBALIAS_RLOCK();
-
+ error = ENOENT;
LIST_FOREACH(p, &handler_chain, entries) {
if ((p->dir & dir) && (p->proto & proto))
- if (p->fingerprint(la, pip, ad) == 0) {
+ if (p->fingerprint(la, ad) == 0) {
error = p->protohandler(la, pip, ad);
break;
}
@@ -259,9 +263,11 @@ attach_dll(struct dll *p)
void *
detach_dll(char *p)
{
- struct dll *b = NULL, *b_tmp;
- void *error = NULL;
+ struct dll *b, *b_tmp;
+ void *error;
+ b = NULL;
+ error = NULL;
SLIST_FOREACH_SAFE(b, &dll_chain, next, b_tmp)
if (!strncmp(b->name, p, DLL_LEN)) {
SLIST_REMOVE(&dll_chain, b, dll, next);
diff --git a/sys/netinet/libalias/alias_mod.h b/sys/netinet/libalias/alias_mod.h
index 5e193e9..f2f679d 100644
--- a/sys/netinet/libalias/alias_mod.h
+++ b/sys/netinet/libalias/alias_mod.h
@@ -80,10 +80,10 @@ struct proto_handler {
u_int pri; /* Handler priority. */
int16_t dir; /* Flow direction. */
uint8_t proto; /* Working protocol. */
- int (*fingerprint)(struct libalias *la, /* Fingerprint * function. */
- struct ip *pip, struct alias_data *ah);
- int (*protohandler)(struct libalias *la, /* Aliasing * function. */
- struct ip *pip, struct alias_data *ah);
+ int (*fingerprint)(struct libalias *, /* Fingerprint * function. */
+ struct alias_data *);
+ int (*protohandler)(struct libalias *, /* Aliasing * function. */
+ struct ip *, struct alias_data *);
LIST_ENTRY(proto_handler) entries;
};
diff --git a/sys/netinet/libalias/alias_nbt.c b/sys/netinet/libalias/alias_nbt.c
index 924ee6a..6fcf727 100644
--- a/sys/netinet/libalias/alias_nbt.c
+++ b/sys/netinet/libalias/alias_nbt.c
@@ -77,7 +77,7 @@ static int
AliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *,
struct in_addr *, u_short *, struct in_addr *, u_short *);
static int
-fingerprint1(struct libalias *la, struct ip *pip, struct alias_data *ah)
+fingerprint1(struct libalias *la, struct alias_data *ah)
{
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
@@ -93,12 +93,11 @@ static int
protohandler1(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
- AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport);
- return (0);
+ return (AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport));
}
static int
-fingerprint2(struct libalias *la, struct ip *pip, struct alias_data *ah)
+fingerprint2(struct libalias *la, struct alias_data *ah)
{
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
@@ -123,9 +122,8 @@ static int
protohandler2out(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
- AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport,
- ah->aaddr, ah->aport);
- return (0);
+ return (AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport,
+ ah->aaddr, ah->aport));
}
/* Kernel module definition. */
diff --git a/sys/netinet/libalias/alias_pptp.c b/sys/netinet/libalias/alias_pptp.c
index b4fd9d0..3465c78 100644
--- a/sys/netinet/libalias/alias_pptp.c
+++ b/sys/netinet/libalias/alias_pptp.c
@@ -79,7 +79,7 @@ static int
AliasHandlePptpGreIn(struct libalias *, struct ip *);
static int
-fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
+fingerprint(struct libalias *la, struct alias_data *ah)
{
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL)
@@ -91,7 +91,7 @@ fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
}
static int
-fingerprintgre(struct libalias *la, struct ip *pip, struct alias_data *ah)
+fingerprintgre(struct libalias *la, struct alias_data *ah)
{
return (0);
diff --git a/sys/netinet/libalias/alias_skinny.c b/sys/netinet/libalias/alias_skinny.c
index e726e55..12be97a 100644
--- a/sys/netinet/libalias/alias_skinny.c
+++ b/sys/netinet/libalias/alias_skinny.c
@@ -57,7 +57,7 @@ static void
AliasHandleSkinny(struct libalias *, struct ip *, struct alias_link *);
static int
-fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
+fingerprint(struct libalias *la, struct alias_data *ah)
{
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL)
diff --git a/sys/netinet/libalias/alias_smedia.c b/sys/netinet/libalias/alias_smedia.c
index e748ad7..2e1b17e 100644
--- a/sys/netinet/libalias/alias_smedia.c
+++ b/sys/netinet/libalias/alias_smedia.c
@@ -132,7 +132,7 @@ static void
AliasHandleRtspOut(struct libalias *, struct ip *, struct alias_link *,
int maxpacketsize);
static int
-fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
+fingerprint(struct libalias *la, struct alias_data *ah)
{
if (ah->dport != NULL && ah->aport != NULL && ah->sport != NULL &&
diff --git a/sys/netinet/pim_var.h b/sys/netinet/pim_var.h
index f79edde..aecb673 100644
--- a/sys/netinet/pim_var.h
+++ b/sys/netinet/pim_var.h
@@ -59,6 +59,11 @@ struct pimstat {
u_quad_t pims_snd_registers_bytes; /* sent regs. bytes (data only) */
};
+#ifdef _KERNEL
+#define PIMSTAT_ADD(name, val) pimstat.name += (val)
+#define PIMSTAT_INC(name) PIMSTAT_ADD(name, 1)
+#endif
+
/*
* Names for PIM sysctl objects
*/
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index b536eb7..0775168 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -345,7 +345,7 @@ rip_input(struct mbuf *m, int off)
(struct sockaddr *)&group,
(struct sockaddr *)&ripsrc);
if (blocked != MCAST_PASS) {
- V_ipstat.ips_notmember++;
+ IPSTAT_INC(ips_notmember);
continue;
}
}
@@ -364,12 +364,12 @@ rip_input(struct mbuf *m, int off)
INP_INFO_RUNLOCK(&V_ripcbinfo);
if (last != NULL) {
if (rip_append(last, ip, m, &ripsrc) != 0)
- V_ipstat.ips_delivered--;
+ IPSTAT_INC(ips_delivered);
INP_RUNLOCK(last);
} else {
m_freem(m);
- V_ipstat.ips_noproto++;
- V_ipstat.ips_delivered--;
+ IPSTAT_INC(ips_noproto);
+ IPSTAT_DEC(ips_delivered);
}
}
@@ -450,7 +450,7 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst)
* XXX prevent ip_output from overwriting header fields.
*/
flags |= IP_RAWOUTPUT;
- V_ipstat.ips_rawout++;
+ IPSTAT_INC(ips_rawout);
}
if (inp->inp_flags & INP_ONESBCAST)
diff --git a/sys/netinet/sctp.h b/sys/netinet/sctp.h
index afbf5ea..83b939a 100644
--- a/sys/netinet/sctp.h
+++ b/sys/netinet/sctp.h
@@ -544,7 +544,7 @@ struct sctp_error_unrecognized_chunk {
#define SCTP_THRESHOLD_LOGGING 0x02000000
#define SCTP_LOG_AT_SEND_2_SCTP 0x04000000
#define SCTP_LOG_AT_SEND_2_OUTQ 0x08000000
-
+#define SCTP_LOG_TRY_ADVANCE 0x10000000
#undef SCTP_PACKED
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index bdd1849..8df3490 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -229,8 +229,8 @@ __FBSDID("$FreeBSD$");
#define SCTP_THRESHOLD_CLEAR 120
#define SCTP_THRESHOLD_INCR 121
#define SCTP_FLIGHT_LOG_DWN_WP_FWD 122
-
-#define SCTP_LOG_MAX_TYPES 123
+#define SCTP_FWD_TSN_CHECK 123
+#define SCTP_LOG_MAX_TYPES 124
/*
* To turn on various logging, you must first enable 'options KTR' and
* you might want to bump the entires 'options KTR_ENTRIES=80000'.
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index f9fd08f..98dc28e 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -423,12 +423,13 @@ abandon:
if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) {
nr_tsn = chk->rec.data.TSN_seq;
- if (nr_tsn >= asoc->nr_mapping_array_base_tsn) {
+ if ((compare_with_wrap(nr_tsn, asoc->nr_mapping_array_base_tsn, MAX_TSN)) ||
+ (nr_tsn == asoc->nr_mapping_array_base_tsn)) {
nr_gap = nr_tsn - asoc->nr_mapping_array_base_tsn;
} else {
nr_gap = (MAX_TSN - asoc->nr_mapping_array_base_tsn) + nr_tsn + 1;
}
- if ((nr_gap >= (SCTP_NR_MAPPING_ARRAY << 3)) ||
+ if ((nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3)) ||
(nr_gap >= (uint32_t) (asoc->nr_mapping_array_size << 3))) {
/*
* EY The 1st should never happen, as in
@@ -440,10 +441,11 @@ abandon:
* nr_mapping_array is always expanded when
* mapping_array is expanded
*/
+ printf("Impossible nr_gap ack range failed\n");
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
}
@@ -550,7 +552,9 @@ abandon:
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn,
+ asoc->highest_tsn_inside_nr_map,
+ MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
}
@@ -699,7 +703,7 @@ protocol_error:
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
}
@@ -760,7 +764,8 @@ protocol_error:
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map,
+ MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
}
@@ -2390,6 +2395,15 @@ finish_express_del:
}
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->mapping_array, gap);
+
+ if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) &&
+ asoc->peer_supports_nr_sack &&
+ (SCTP_BASE_SYSCTL(sctp_do_drain) == 0)) {
+ SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, gap);
+ if (compare_with_wrap(tsn, asoc->highest_tsn_inside_nr_map, MAX_TSN)) {
+ asoc->highest_tsn_inside_nr_map = tsn;
+ }
+ }
/* check the special flag for stream resets */
if (((liste = TAILQ_FIRST(&asoc->resetHead)) != NULL) &&
((compare_with_wrap(asoc->cumulative_tsn, liste->tsn, MAX_TSN)) ||
@@ -2498,9 +2512,9 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
int slide_from, slide_end, lgap, distance;
/* EY nr_mapping array variables */
- int nr_at;
- int nr_last_all_ones = 0;
- int nr_slide_from, nr_slide_end, nr_lgap, nr_distance;
+ /* int nr_at; */
+ /* int nr_last_all_ones = 0; */
+ /* int nr_slide_from, nr_slide_end, nr_lgap, nr_distance; */
uint32_t old_cumack, old_base, old_highest;
unsigned char aux_array[64];
@@ -2683,102 +2697,19 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
asoc->cumulative_tsn, asoc->highest_tsn_inside_map,
SCTP_MAP_SLIDE_RESULT);
}
- }
- }
- /*
- * EY if doing nr_sacks then slide the nr_mapping_array accordingly
- * please
- */
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) {
-
- nr_at = 0;
- for (nr_slide_from = 0; nr_slide_from < stcb->asoc.nr_mapping_array_size; nr_slide_from++) {
-
- if (asoc->nr_mapping_array[nr_slide_from] == 0xff) {
- nr_at += 8;
- nr_last_all_ones = 1;
- } else {
- /* there is a 0 bit */
- nr_at += sctp_map_lookup_tab[asoc->nr_mapping_array[nr_slide_from]];
- nr_last_all_ones = 0;
- break;
- }
- }
-
- nr_at++;
-
- if (compare_with_wrap(asoc->cumulative_tsn,
- asoc->highest_tsn_inside_nr_map, MAX_TSN) && (at >= 8)) {
- /* The complete array was completed by a single FR */
- /* higest becomes the cum-ack */
- int clr;
-
- clr = (nr_at >> 3) + 1;
-
- if (clr > asoc->nr_mapping_array_size)
- clr = asoc->nr_mapping_array_size;
-
- memset(asoc->nr_mapping_array, 0, clr);
- /* base becomes one ahead of the cum-ack */
- asoc->nr_mapping_array_base_tsn = asoc->cumulative_tsn + 1;
- asoc->highest_tsn_inside_nr_map = asoc->cumulative_tsn;
-
- } else if (nr_at >= 8) {
- /* we can slide the mapping array down */
- /* Calculate the new byte postion we can move down */
-
/*
- * now calculate the ceiling of the move using our
- * highest TSN value
+ * EY if doing nr_sacks then slide the
+ * nr_mapping_array accordingly please
*/
- if (asoc->highest_tsn_inside_nr_map >= asoc->nr_mapping_array_base_tsn) {
- nr_lgap = asoc->highest_tsn_inside_nr_map -
- asoc->nr_mapping_array_base_tsn;
- } else {
- nr_lgap = (MAX_TSN - asoc->nr_mapping_array_base_tsn) +
- asoc->highest_tsn_inside_nr_map + 1;
- }
- nr_slide_end = nr_lgap >> 3;
- if (nr_slide_end < nr_slide_from) {
-#ifdef INVARIANTS
- panic("impossible slide");
-#else
- printf("impossible slide?\n");
- return;
-#endif
- }
- if (nr_slide_end > asoc->nr_mapping_array_size) {
-#ifdef INVARIANTS
- panic("would overrun buffer");
-#else
- printf("Gak, would have overrun map end:%d nr_slide_end:%d\n",
- asoc->nr_mapping_array_size, nr_slide_end);
- nr_slide_end = asoc->nr_mapping_array_size;
-#endif
- }
- nr_distance = (nr_slide_end - nr_slide_from) + 1;
-
- if (nr_distance + nr_slide_from > asoc->nr_mapping_array_size ||
- nr_distance < 0) {
- /*
- * Here we do NOT slide forward the array so
- * that hopefully when more data comes in to
- * fill it up we will be able to slide it
- * forward. Really I don't think this should
- * happen :-0
- */
- ;
- } else {
- int ii;
-
- for (ii = 0; ii < nr_distance; ii++) {
+ if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack) {
+ for (ii = 0; ii < distance; ii++) {
asoc->nr_mapping_array[ii] =
- asoc->nr_mapping_array[nr_slide_from + ii];
+ asoc->nr_mapping_array[slide_from + ii];
}
- for (ii = nr_distance; ii <= nr_slide_end; ii++) {
+ for (ii = distance; ii <= slide_end; ii++) {
asoc->nr_mapping_array[ii] = 0;
}
- asoc->nr_mapping_array_base_tsn += (nr_slide_from << 3);
+ asoc->nr_mapping_array_base_tsn += (slide_from << 3);
}
}
}
@@ -2802,7 +2733,7 @@ sctp_sack_check(struct sctp_tcb *stcb, int ok_to_sack, int was_a_gap, int *abort
* EY if nr_sacks used then send an nr-sack , a sack
* otherwise
*/
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack)
+ if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && stcb->asoc.peer_supports_nr_sack)
sctp_send_nr_sack(stcb);
else
sctp_send_sack(stcb);
@@ -3496,9 +3427,13 @@ sctp_handle_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb, struct
/*
* All chunks NOT UNSENT
* fall through here and are
- * marked
+ * marked (leave PR-SCTP
+ * ones that are to skip
+ * alone though)
*/
- tp1->sent = SCTP_DATAGRAM_MARKED;
+ if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
+ tp1->sent = SCTP_DATAGRAM_MARKED;
+
if (tp1->rec.data.chunk_was_revoked) {
/* deflate the cwnd */
tp1->whoTo->cwnd -= tp1->book_size;
@@ -3680,20 +3615,7 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
if (tp1->data != NULL) {
(void)sctp_release_pr_sctp_chunk(stcb, tp1,
(SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
- &asoc->sent_queue, SCTP_SO_NOT_LOCKED);
- }
- tp1 = TAILQ_NEXT(tp1, sctp_next);
- continue;
- }
- }
- if ((PR_SCTP_RTX_ENABLED(tp1->flags)) && tp1->sent < SCTP_DATAGRAM_ACKED) {
- /* Has it been retransmitted tv_sec times? */
- if (tp1->snd_count > tp1->rec.data.timetodrop.tv_sec) {
- /* Yes, so drop it */
- if (tp1->data != NULL) {
- (void)sctp_release_pr_sctp_chunk(stcb, tp1,
- (SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
- &asoc->sent_queue, SCTP_SO_NOT_LOCKED);
+ SCTP_SO_NOT_LOCKED);
}
tp1 = TAILQ_NEXT(tp1, sctp_next);
continue;
@@ -3914,6 +3836,25 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
/* Increment the count to resend */
struct sctp_nets *alt;
+ if ((stcb->asoc.peer_supports_prsctp) &&
+ (PR_SCTP_RTX_ENABLED(tp1->flags))) {
+ /*
+ * Has it been retransmitted tv_sec times? -
+ * we store the retran count there.
+ */
+ if (tp1->snd_count > tp1->rec.data.timetodrop.tv_sec) {
+ /* Yes, so drop it */
+ if (tp1->data != NULL) {
+ (void)sctp_release_pr_sctp_chunk(stcb, tp1,
+ (SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
+ SCTP_SO_NOT_LOCKED);
+ }
+ /* Make sure to flag we had a FR */
+ tp1->whoTo->net_ack++;
+ tp1 = TAILQ_NEXT(tp1, sctp_next);
+ continue;
+ }
+ }
/* printf("OK, we are now ready to FR this guy\n"); */
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FR_LOGGING_ENABLE) {
sctp_log_fr(tp1->rec.data.TSN_seq, tp1->snd_count,
@@ -4078,6 +4019,13 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
/* no chance to advance, out of here */
break;
}
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
+ if (tp1->sent == SCTP_FORWARD_TSN_SKIP) {
+ sctp_misc_ints(SCTP_FWD_TSN_CHECK,
+ asoc->advanced_peer_ack_point,
+ tp1->rec.data.TSN_seq, 0, 0);
+ }
+ }
if (!PR_SCTP_ENABLED(tp1->flags)) {
/*
* We can't fwd-tsn past any that are reliable aka
@@ -4107,7 +4055,7 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
if (tp1->data) {
(void)sctp_release_pr_sctp_chunk(stcb, tp1,
(SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
- &asoc->sent_queue, SCTP_SO_NOT_LOCKED);
+ SCTP_SO_NOT_LOCKED);
}
} else {
/*
@@ -4124,8 +4072,16 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
*/
if (tp1->sent == SCTP_FORWARD_TSN_SKIP) {
/* advance PeerAckPoint goes forward */
- asoc->advanced_peer_ack_point = tp1->rec.data.TSN_seq;
- a_adv = tp1;
+ if (compare_with_wrap(tp1->rec.data.TSN_seq,
+ asoc->advanced_peer_ack_point,
+ MAX_TSN)) {
+
+ asoc->advanced_peer_ack_point = tp1->rec.data.TSN_seq;
+ a_adv = tp1;
+ } else if (tp1->rec.data.TSN_seq == asoc->advanced_peer_ack_point) {
+ /* No update but we do save the chk */
+ a_adv = tp1;
+ }
} else {
/*
* If it is still in RESEND we can advance no
@@ -4142,14 +4098,27 @@ sctp_try_advance_peer_ack_point(struct sctp_tcb *stcb,
return (a_adv);
}
-static void
+static int
sctp_fs_audit(struct sctp_association *asoc)
{
struct sctp_tmit_chunk *chk;
int inflight = 0, resend = 0, inbetween = 0, acked = 0, above = 0;
+ int entry_flight, entry_cnt, ret;
+
+ entry_flight = asoc->total_flight;
+ entry_cnt = asoc->total_flight_count;
+ ret = 0;
+
+ if (asoc->pr_sctp_cnt >= asoc->sent_queue_cnt)
+ return (0);
TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
if (chk->sent < SCTP_DATAGRAM_RESEND) {
+ printf("Chk TSN:%u size:%d inflight cnt:%d\n",
+ chk->rec.data.TSN_seq,
+ chk->send_size,
+ chk->snd_count
+ );
inflight++;
} else if (chk->sent == SCTP_DATAGRAM_RESEND) {
resend++;
@@ -4166,10 +4135,15 @@ sctp_fs_audit(struct sctp_association *asoc)
#ifdef INVARIANTS
panic("Flight size-express incorrect? \n");
#else
- SCTP_PRINTF("Flight size-express incorrect inflight:%d inbetween:%d\n",
- inflight, inbetween);
+ printf("asoc->total_flight:%d cnt:%d\n",
+ entry_flight, entry_cnt);
+
+ SCTP_PRINTF("Flight size-express incorrect F:%d I:%d R:%d Ab:%d ACK:%d\n",
+ inflight, inbetween, resend, above, acked);
+ ret = 1;
#endif
}
+ return (ret);
}
@@ -4590,20 +4564,26 @@ again:
(asoc->sent_queue_retran_cnt == 0) &&
(win_probe_recovered == 0) &&
(done_once == 0)) {
- /* huh, this should not happen */
- sctp_fs_audit(asoc);
- TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- net->flight_size = 0;
- }
- asoc->total_flight = 0;
- asoc->total_flight_count = 0;
- asoc->sent_queue_retran_cnt = 0;
- TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
- if (tp1->sent < SCTP_DATAGRAM_RESEND) {
- sctp_flight_size_increase(tp1);
- sctp_total_flight_increase(stcb, tp1);
- } else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
- asoc->sent_queue_retran_cnt++;
+ /*
+ * huh, this should not happen unless all packets are
+ * PR-SCTP and marked to skip of course.
+ */
+ if (sctp_fs_audit(asoc)) {
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ if (net->flight_size) {
+ net->flight_size = 0;
+ }
+ }
+ asoc->total_flight = 0;
+ asoc->total_flight_count = 0;
+ asoc->sent_queue_retran_cnt = 0;
+ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
+ if (tp1->sent < SCTP_DATAGRAM_RESEND) {
+ sctp_flight_size_increase(tp1);
+ sctp_total_flight_increase(stcb, tp1);
+ } else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
+ asoc->sent_queue_retran_cnt++;
+ }
}
}
done_once = 1;
@@ -4728,6 +4708,13 @@ again:
*/
asoc->nonce_sum_check = 0;
asoc->nonce_resync_tsn = asoc->advanced_peer_ack_point;
+ } else if (lchk) {
+ /* try to FR fwd-tsn's that get lost too */
+ lchk->rec.data.fwd_tsn_cnt++;
+ if (lchk->rec.data.fwd_tsn_cnt > 3) {
+ send_forward_tsn(stcb, asoc);
+ lchk->rec.data.fwd_tsn_cnt = 0;
+ }
}
}
if (lchk) {
@@ -4813,10 +4800,6 @@ sctp_handle_sack(struct mbuf *m, int offset,
num_seg = ntohs(sack->num_gap_ack_blks);
a_rwnd = rwnd;
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_SACK_ARRIVALS_ENABLE) {
- sctp_misc_ints(SCTP_SACK_LOG_NORMAL, cum_ack,
- rwnd, stcb->asoc.last_acked_seq, stcb->asoc.peers_rwnd);
- }
/* CMT DAC algo */
cmt_dac_flag = ch->ch.chunk_flags & SCTP_SACK_CMT_DAC;
num_dup = ntohs(sack->num_dup_tsns);
@@ -5605,20 +5588,24 @@ again:
(asoc->sent_queue_retran_cnt == 0) &&
(win_probe_recovered == 0) &&
(done_once == 0)) {
- /* huh, this should not happen */
- sctp_fs_audit(asoc);
- TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- net->flight_size = 0;
- }
- asoc->total_flight = 0;
- asoc->total_flight_count = 0;
- asoc->sent_queue_retran_cnt = 0;
- TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
- if (tp1->sent < SCTP_DATAGRAM_RESEND) {
- sctp_flight_size_increase(tp1);
- sctp_total_flight_increase(stcb, tp1);
- } else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
- asoc->sent_queue_retran_cnt++;
+ /*
+ * huh, this should not happen unless all packets are
+ * PR-SCTP and marked to skip of course.
+ */
+ if (sctp_fs_audit(asoc)) {
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ net->flight_size = 0;
+ }
+ asoc->total_flight = 0;
+ asoc->total_flight_count = 0;
+ asoc->sent_queue_retran_cnt = 0;
+ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
+ if (tp1->sent < SCTP_DATAGRAM_RESEND) {
+ sctp_flight_size_increase(tp1);
+ sctp_total_flight_increase(stcb, tp1);
+ } else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
+ asoc->sent_queue_retran_cnt++;
+ }
}
}
done_once = 1;
@@ -5643,6 +5630,11 @@ again:
* on issues that will occur when the ECN NONCE
* stuff is put into SCTP for cross checking.
*/
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
+ sctp_misc_ints(SCTP_FWD_TSN_CHECK,
+ 0xee, cum_ack, asoc->advanced_peer_ack_point,
+ old_adv_peer_ack_point);
+ }
if (compare_with_wrap(asoc->advanced_peer_ack_point, old_adv_peer_ack_point,
MAX_TSN)) {
send_forward_tsn(stcb, asoc);
@@ -5652,6 +5644,13 @@ again:
*/
asoc->nonce_sum_check = 0;
asoc->nonce_resync_tsn = asoc->advanced_peer_ack_point;
+ } else if (lchk) {
+ /* try to FR fwd-tsn's that get lost too */
+ lchk->rec.data.fwd_tsn_cnt++;
+ if (lchk->rec.data.fwd_tsn_cnt > 3) {
+ send_forward_tsn(stcb, asoc);
+ lchk->rec.data.fwd_tsn_cnt = 0;
+ }
}
}
if (lchk) {
@@ -5740,7 +5739,9 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn,
+ asoc->highest_tsn_inside_nr_map,
+ MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
@@ -5843,7 +5844,8 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, nr_gap);
- if (nr_tsn > asoc->highest_tsn_inside_nr_map)
+ if (compare_with_wrap(nr_tsn, asoc->highest_tsn_inside_nr_map,
+ MAX_TSN))
asoc->highest_tsn_inside_nr_map = nr_tsn;
}
@@ -5905,6 +5907,91 @@ sctp_kick_prsctp_reorder_queue(struct sctp_tcb *stcb,
}
}
+static void
+sctp_flush_reassm_for_str_seq(struct sctp_tcb *stcb,
+ struct sctp_association *asoc,
+ uint16_t stream, uint16_t seq)
+{
+ struct sctp_tmit_chunk *chk, *at;
+
+ if (!TAILQ_EMPTY(&asoc->reasmqueue)) {
+ /* For each one on here see if we need to toss it */
+ /*
+ * For now large messages held on the reasmqueue that are
+ * complete will be tossed too. We could in theory do more
+ * work to spin through and stop after dumping one msg aka
+ * seeing the start of a new msg at the head, and call the
+ * delivery function... to see if it can be delivered... But
+ * for now we just dump everything on the queue.
+ */
+ chk = TAILQ_FIRST(&asoc->reasmqueue);
+ while (chk) {
+ at = TAILQ_NEXT(chk, sctp_next);
+ if (chk->rec.data.stream_number != stream) {
+ chk = at;
+ continue;
+ }
+ if (chk->rec.data.stream_seq == seq) {
+ /* It needs to be tossed */
+ TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
+ if (compare_with_wrap(chk->rec.data.TSN_seq,
+ asoc->tsn_last_delivered, MAX_TSN)) {
+ asoc->tsn_last_delivered =
+ chk->rec.data.TSN_seq;
+ asoc->str_of_pdapi =
+ chk->rec.data.stream_number;
+ asoc->ssn_of_pdapi =
+ chk->rec.data.stream_seq;
+ asoc->fragment_flags =
+ chk->rec.data.rcv_flags;
+ }
+ asoc->size_on_reasm_queue -= chk->send_size;
+ sctp_ucount_decr(asoc->cnt_on_reasm_queue);
+
+ /* Clear up any stream problem */
+ if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
+ SCTP_DATA_UNORDERED &&
+ (compare_with_wrap(chk->rec.data.stream_seq,
+ asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered,
+ MAX_SEQ))) {
+ /*
+ * We must dump forward this streams
+ * sequence number if the chunk is
+ * not unordered that is being
+ * skipped. There is a chance that
+ * if the peer does not include the
+ * last fragment in its FWD-TSN we
+ * WILL have a problem here since
+ * you would have a partial chunk in
+ * queue that may not be
+ * deliverable. Also if a Partial
+ * delivery API as started the user
+ * may get a partial chunk. The next
+ * read returning a new chunk...
+ * really ugly but I see no way
+ * around it! Maybe a notify??
+ */
+ asoc->strmin[chk->rec.data.stream_number].last_sequence_delivered =
+ chk->rec.data.stream_seq;
+ }
+ if (chk->data) {
+ sctp_m_freem(chk->data);
+ chk->data = NULL;
+ }
+ sctp_free_a_chunk(stcb, chk);
+ } else if (compare_with_wrap(chk->rec.data.stream_seq, seq, MAX_SEQ)) {
+ /*
+ * If the stream_seq is > than the purging
+ * one, we are done
+ */
+ break;
+ }
+ chk = at;
+ }
+ }
+}
+
+
void
sctp_handle_forward_tsn(struct sctp_tcb *stcb,
struct sctp_forward_tsn_chunk *fwd, int *abort_flag, struct mbuf *m, int offset)
@@ -5934,13 +6021,14 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
*/
struct sctp_association *asoc;
uint32_t new_cum_tsn, gap;
- unsigned int i, cnt_gone, fwd_sz, cumack_set_flag, m_size;
+ unsigned int i, fwd_sz, cumack_set_flag, m_size;
+ uint32_t str_seq;
struct sctp_stream_in *strm;
struct sctp_tmit_chunk *chk, *at;
+ struct sctp_queued_to_read *ctl, *sv;
cumack_set_flag = 0;
asoc = &stcb->asoc;
- cnt_gone = 0;
if ((fwd_sz = ntohs(fwd->ch.chunk_length)) < sizeof(struct sctp_forward_tsn_chunk)) {
SCTPDBG(SCTP_DEBUG_INDATA1,
"Bad size too small/big fwd-tsn\n");
@@ -6019,7 +6107,6 @@ sctp_handle_forward_tsn(struct sctp_tcb *stcb,
return;
}
SCTP_STAT_INCR(sctps_fwdtsn_map_over);
-slide_out:
memset(stcb->asoc.mapping_array, 0, stcb->asoc.mapping_array_size);
cumack_set_flag = 1;
asoc->mapping_array_base_tsn = new_cum_tsn + 1;
@@ -6043,12 +6130,15 @@ slide_out:
asoc->last_echo_tsn = asoc->highest_tsn_inside_map;
} else {
SCTP_TCB_LOCK_ASSERT(stcb);
- if ((compare_with_wrap(((uint32_t) asoc->cumulative_tsn + gap), asoc->highest_tsn_inside_map, MAX_TSN)) ||
- (((uint32_t) asoc->cumulative_tsn + gap) == asoc->highest_tsn_inside_map)) {
- goto slide_out;
- } else {
- for (i = 0; i <= gap; i++) {
- SCTP_SET_TSN_PRESENT(asoc->mapping_array, i);
+ for (i = 0; i <= gap; i++) {
+ SCTP_SET_TSN_PRESENT(asoc->mapping_array, i);
+ /*
+ * EY if drain is off then every gap-ack is an
+ * nr-gap-ack
+ */
+ if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off) && asoc->peer_supports_nr_sack
+ && SCTP_BASE_SYSCTL(sctp_do_drain) == 0) {
+ SCTP_SET_TSN_PRESENT(asoc->nr_mapping_array, i);
}
}
/*
@@ -6059,7 +6149,6 @@ slide_out:
if (*abort_flag)
return;
}
-
/*************************************************************/
/* 2. Clear up re-assembly queue */
/*************************************************************/
@@ -6083,9 +6172,9 @@ slide_out:
chk = TAILQ_FIRST(&asoc->reasmqueue);
while (chk) {
at = TAILQ_NEXT(chk, sctp_next);
- if (compare_with_wrap(asoc->cumulative_tsn,
- chk->rec.data.TSN_seq, MAX_TSN) ||
- asoc->cumulative_tsn == chk->rec.data.TSN_seq) {
+ if ((compare_with_wrap(new_cum_tsn,
+ chk->rec.data.TSN_seq, MAX_TSN)) ||
+ (new_cum_tsn == chk->rec.data.TSN_seq)) {
/* It needs to be tossed */
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
if (compare_with_wrap(chk->rec.data.TSN_seq,
@@ -6101,7 +6190,6 @@ slide_out:
}
asoc->size_on_reasm_queue -= chk->send_size;
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
- cnt_gone++;
/* Clear up any stream problem */
if ((chk->rec.data.rcv_flags & SCTP_DATA_UNORDERED) !=
@@ -6137,45 +6225,17 @@ slide_out:
} else {
/*
* Ok we have gone beyond the end of the
- * fwd-tsn's mark. Some checks...
+ * fwd-tsn's mark.
*/
- if ((asoc->fragmented_delivery_inprogress) &&
- (chk->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG)) {
- uint32_t str_seq;
-
- /*
- * Special case PD-API is up and
- * what we fwd-tsn' over includes
- * one that had the LAST_FRAG. We no
- * longer need to do the PD-API.
- */
- asoc->fragmented_delivery_inprogress = 0;
-
- str_seq = (asoc->str_of_pdapi << 16) | asoc->ssn_of_pdapi;
- sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
- stcb, SCTP_PARTIAL_DELIVERY_ABORTED, (void *)&str_seq, SCTP_SO_NOT_LOCKED);
-
- }
break;
}
chk = at;
}
}
- if (asoc->fragmented_delivery_inprogress) {
- /*
- * Ok we removed cnt_gone chunks in the PD-API queue that
- * were being delivered. So now we must turn off the flag.
- */
- uint32_t str_seq;
-
- str_seq = (asoc->str_of_pdapi << 16) | asoc->ssn_of_pdapi;
- sctp_ulp_notify(SCTP_NOTIFY_PARTIAL_DELVIERY_INDICATION,
- stcb, SCTP_PARTIAL_DELIVERY_ABORTED, (void *)&str_seq, SCTP_SO_NOT_LOCKED);
- asoc->fragmented_delivery_inprogress = 0;
- }
- /*************************************************************/
- /* 3. Update the PR-stream re-ordering queues */
- /*************************************************************/
+ /*******************************************************/
+ /* 3. Update the PR-stream re-ordering queues and fix */
+ /* delivery issues as needed. */
+ /*******************************************************/
fwd_sz -= sizeof(*fwd);
if (m && fwd_sz) {
/* New method. */
@@ -6184,6 +6244,7 @@ slide_out:
offset += sizeof(*fwd);
+ SCTP_INP_READ_LOCK(stcb->sctp_ep);
num_str = fwd_sz / sizeof(struct sctp_strseq);
for (i = 0; i < num_str; i++) {
uint16_t st;
@@ -6200,11 +6261,49 @@ slide_out:
stseq->stream = st;
st = ntohs(stseq->sequence);
stseq->sequence = st;
+
/* now process */
+
+ /*
+ * Ok we now look for the stream/seq on the read
+ * queue where its not all delivered. If we find it
+ * we transmute the read entry into a PDI_ABORTED.
+ */
if (stseq->stream >= asoc->streamincnt) {
/* screwed up streams, stop! */
break;
}
+ if ((asoc->str_of_pdapi == stseq->stream) &&
+ (asoc->ssn_of_pdapi == stseq->sequence)) {
+ /*
+ * If this is the one we were partially
+ * delivering now then we no longer are.
+ * Note this will change with the reassembly
+ * re-write.
+ */
+ asoc->fragmented_delivery_inprogress = 0;
+ }
+ sctp_flush_reassm_for_str_seq(stcb, asoc, stseq->stream, stseq->sequence);
+ TAILQ_FOREACH(ctl, &stcb->sctp_ep->read_queue, next) {
+ if ((ctl->sinfo_stream == stseq->stream) &&
+ (ctl->sinfo_ssn == stseq->sequence)) {
+ str_seq = (stseq->stream << 16) | stseq->sequence;
+ ctl->end_added = 1;
+ ctl->pdapi_aborted = 1;
+ sv = stcb->asoc.control_pdapi;
+ stcb->asoc.control_pdapi = ctl;
+ sctp_notify_partial_delivery_indication(stcb,
+ SCTP_PARTIAL_DELIVERY_ABORTED,
+ SCTP_HOLDS_LOCK,
+ str_seq);
+ stcb->asoc.control_pdapi = sv;
+ break;
+ } else if ((ctl->sinfo_stream == stseq->stream) &&
+ (compare_with_wrap(ctl->sinfo_ssn, stseq->sequence, MAX_SEQ))) {
+ /* We are past our victim SSN */
+ break;
+ }
+ }
strm = &asoc->strmin[stseq->stream];
if (compare_with_wrap(stseq->sequence,
strm->last_sequence_delivered, MAX_SEQ)) {
@@ -6216,6 +6315,7 @@ slide_out:
/* sa_ignore NO_NULL_CHK */
sctp_kick_prsctp_reorder_queue(stcb, strm);
}
+ SCTP_INP_READ_UNLOCK(stcb->sctp_ep);
}
if (TAILQ_FIRST(&asoc->reasmqueue)) {
/* now lets kick out and check for more fragmented delivery */
@@ -6614,20 +6714,24 @@ again:
(asoc->sent_queue_retran_cnt == 0) &&
(win_probe_recovered == 0) &&
(done_once == 0)) {
- /* huh, this should not happen */
- sctp_fs_audit(asoc);
- TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- net->flight_size = 0;
- }
- asoc->total_flight = 0;
- asoc->total_flight_count = 0;
- asoc->sent_queue_retran_cnt = 0;
- TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
- if (tp1->sent < SCTP_DATAGRAM_RESEND) {
- sctp_flight_size_increase(tp1);
- sctp_total_flight_increase(stcb, tp1);
- } else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
- asoc->sent_queue_retran_cnt++;
+ /*
+ * huh, this should not happen unless all packets are
+ * PR-SCTP and marked to skip of course.
+ */
+ if (sctp_fs_audit(asoc)) {
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ net->flight_size = 0;
+ }
+ asoc->total_flight = 0;
+ asoc->total_flight_count = 0;
+ asoc->sent_queue_retran_cnt = 0;
+ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
+ if (tp1->sent < SCTP_DATAGRAM_RESEND) {
+ sctp_flight_size_increase(tp1);
+ sctp_total_flight_increase(stcb, tp1);
+ } else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
+ asoc->sent_queue_retran_cnt++;
+ }
}
}
done_once = 1;
@@ -7012,7 +7116,8 @@ sctp_handle_nr_sack_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb,
* fall through here and are
* marked
*/
- tp1->sent = SCTP_DATAGRAM_MARKED;
+ if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
+ tp1->sent = SCTP_DATAGRAM_NR_MARKED;
if (tp1->rec.data.chunk_was_revoked) {
/* deflate the cwnd */
tp1->whoTo->cwnd -= tp1->book_size;
@@ -7024,7 +7129,8 @@ sctp_handle_nr_sack_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb,
* nr_marked
*/
if (all_bit) {
- tp1->sent = SCTP_DATAGRAM_NR_MARKED;
+ if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
+ tp1->sent = SCTP_DATAGRAM_NR_MARKED;
/*
* TAILQ_REMOVE(&asoc
* ->sent_queue,
@@ -7143,7 +7249,8 @@ sctp_handle_nr_sack_segments(struct mbuf *m, int *offset, struct sctp_tcb *stcb,
while (tp1) {
if (tp1->rec.data.TSN_seq == j) {
if (tp1->sent != SCTP_DATAGRAM_UNSENT) {
- tp1->sent = SCTP_DATAGRAM_NR_MARKED;
+ if (tp1->sent != SCTP_FORWARD_TSN_SKIP)
+ tp1->sent = SCTP_DATAGRAM_NR_MARKED;
/*
* TAILQ_REMOVE(&asoc
* ->sent_queue,
@@ -8170,20 +8277,24 @@ again:
(asoc->sent_queue_retran_cnt == 0) &&
(win_probe_recovered == 0) &&
(done_once == 0)) {
- /* huh, this should not happen */
- sctp_fs_audit(asoc);
- TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
- net->flight_size = 0;
- }
- asoc->total_flight = 0;
- asoc->total_flight_count = 0;
- asoc->sent_queue_retran_cnt = 0;
- TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
- if (tp1->sent < SCTP_DATAGRAM_RESEND) {
- sctp_flight_size_increase(tp1);
- sctp_total_flight_increase(stcb, tp1);
- } else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
- asoc->sent_queue_retran_cnt++;
+ /*
+ * huh, this should not happen unless all packets are
+ * PR-SCTP and marked to skip of course.
+ */
+ if (sctp_fs_audit(asoc)) {
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
+ net->flight_size = 0;
+ }
+ asoc->total_flight = 0;
+ asoc->total_flight_count = 0;
+ asoc->sent_queue_retran_cnt = 0;
+ TAILQ_FOREACH(tp1, &asoc->sent_queue, sctp_next) {
+ if (tp1->sent < SCTP_DATAGRAM_RESEND) {
+ sctp_flight_size_increase(tp1);
+ sctp_total_flight_increase(stcb, tp1);
+ } else if (tp1->sent == SCTP_DATAGRAM_RESEND) {
+ asoc->sent_queue_retran_cnt++;
+ }
}
}
done_once = 1;
@@ -8221,6 +8332,13 @@ again:
*/
asoc->nonce_sum_check = 0;
asoc->nonce_resync_tsn = asoc->advanced_peer_ack_point;
+ } else if (lchk) {
+ /* try to FR fwd-tsn's that get lost too */
+ lchk->rec.data.fwd_tsn_cnt++;
+ if (lchk->rec.data.fwd_tsn_cnt > 3) {
+ send_forward_tsn(stcb, asoc);
+ lchk->rec.data.fwd_tsn_cnt = 0;
+ }
}
}
if (lchk) {
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 494929b..c962e4d 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -3150,8 +3150,10 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
(uintptr_t) stcb,
tp1->rec.data.TSN_seq);
}
- sctp_flight_size_decrease(tp1);
- sctp_total_flight_decrease(stcb, tp1);
+ if (tp1->sent < SCTP_DATAGRAM_RESEND) {
+ sctp_flight_size_decrease(tp1);
+ sctp_total_flight_decrease(stcb, tp1);
+ }
} {
/* audit code */
unsigned int audit;
@@ -5606,11 +5608,14 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset,
/* there was a gap before this data was processed */
was_a_gap = 1;
}
+ stcb->asoc.send_sack = 1;
sctp_sack_check(stcb, 1, was_a_gap, &abort_flag);
if (abort_flag) {
/* Again, we aborted so NO UNLOCK needed */
goto out_now;
}
+ } else if (fwd_tsn_seen) {
+ stcb->asoc.send_sack = 1;
}
/* trigger send of any chunks in queue... */
trigger_send:
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 3729616..5885474 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -1859,1812 +1859,6 @@ struct sack_track sack_array[256] = {
}
};
-/* EY below are nr_sacks version of the preceeding two data structures, identical except their names */
-#define SCTP_MAX_NR_GAPS_INARRAY 4
-struct nr_sack_track {
- uint8_t right_edge; /* mergable on the right edge */
- uint8_t left_edge; /* mergable on the left edge */
- uint8_t num_entries;
- uint8_t spare;
- struct sctp_nr_gap_ack_block nr_gaps[SCTP_MAX_NR_GAPS_INARRAY];
-};
-
-struct nr_sack_track nr_sack_array[256] = {
- {0, 0, 0, 0, /* 0x00 */
- {{0, 0},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x01 */
- {{0, 0},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x02 */
- {{1, 1},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x03 */
- {{0, 1},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x04 */
- {{2, 2},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x05 */
- {{0, 0},
- {2, 2},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x06 */
- {{1, 2},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x07 */
- {{0, 2},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x08 */
- {{3, 3},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x09 */
- {{0, 0},
- {3, 3},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x0a */
- {{1, 1},
- {3, 3},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x0b */
- {{0, 1},
- {3, 3},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x0c */
- {{2, 3},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x0d */
- {{0, 0},
- {2, 3},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x0e */
- {{1, 3},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x0f */
- {{0, 3},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x10 */
- {{4, 4},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x11 */
- {{0, 0},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x12 */
- {{1, 1},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x13 */
- {{0, 1},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x14 */
- {{2, 2},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x15 */
- {{0, 0},
- {2, 2},
- {4, 4},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x16 */
- {{1, 2},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x17 */
- {{0, 2},
- {4, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x18 */
- {{3, 4},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x19 */
- {{0, 0},
- {3, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x1a */
- {{1, 1},
- {3, 4},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x1b */
- {{0, 1},
- {3, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x1c */
- {{2, 4},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x1d */
- {{0, 0},
- {2, 4},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x1e */
- {{1, 4},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x1f */
- {{0, 4},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x20 */
- {{5, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x21 */
- {{0, 0},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x22 */
- {{1, 1},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x23 */
- {{0, 1},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x24 */
- {{2, 2},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x25 */
- {{0, 0},
- {2, 2},
- {5, 5},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x26 */
- {{1, 2},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x27 */
- {{0, 2},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x28 */
- {{3, 3},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x29 */
- {{0, 0},
- {3, 3},
- {5, 5},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x2a */
- {{1, 1},
- {3, 3},
- {5, 5},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x2b */
- {{0, 1},
- {3, 3},
- {5, 5},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x2c */
- {{2, 3},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x2d */
- {{0, 0},
- {2, 3},
- {5, 5},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x2e */
- {{1, 3},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x2f */
- {{0, 3},
- {5, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x30 */
- {{4, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x31 */
- {{0, 0},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x32 */
- {{1, 1},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x33 */
- {{0, 1},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x34 */
- {{2, 2},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x35 */
- {{0, 0},
- {2, 2},
- {4, 5},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x36 */
- {{1, 2},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x37 */
- {{0, 2},
- {4, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x38 */
- {{3, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x39 */
- {{0, 0},
- {3, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x3a */
- {{1, 1},
- {3, 5},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x3b */
- {{0, 1},
- {3, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x3c */
- {{2, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x3d */
- {{0, 0},
- {2, 5},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x3e */
- {{1, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x3f */
- {{0, 5},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x40 */
- {{6, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x41 */
- {{0, 0},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x42 */
- {{1, 1},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x43 */
- {{0, 1},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x44 */
- {{2, 2},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x45 */
- {{0, 0},
- {2, 2},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x46 */
- {{1, 2},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x47 */
- {{0, 2},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x48 */
- {{3, 3},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x49 */
- {{0, 0},
- {3, 3},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x4a */
- {{1, 1},
- {3, 3},
- {6, 6},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x4b */
- {{0, 1},
- {3, 3},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x4c */
- {{2, 3},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x4d */
- {{0, 0},
- {2, 3},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x4e */
- {{1, 3},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x4f */
- {{0, 3},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x50 */
- {{4, 4},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x51 */
- {{0, 0},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x52 */
- {{1, 1},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x53 */
- {{0, 1},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x54 */
- {{2, 2},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {1, 0, 4, 0, /* 0x55 */
- {{0, 0},
- {2, 2},
- {4, 4},
- {6, 6}
- }
- },
- {0, 0, 3, 0, /* 0x56 */
- {{1, 2},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x57 */
- {{0, 2},
- {4, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x58 */
- {{3, 4},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x59 */
- {{0, 0},
- {3, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x5a */
- {{1, 1},
- {3, 4},
- {6, 6},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x5b */
- {{0, 1},
- {3, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x5c */
- {{2, 4},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x5d */
- {{0, 0},
- {2, 4},
- {6, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x5e */
- {{1, 4},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x5f */
- {{0, 4},
- {6, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x60 */
- {{5, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x61 */
- {{0, 0},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x62 */
- {{1, 1},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x63 */
- {{0, 1},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x64 */
- {{2, 2},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x65 */
- {{0, 0},
- {2, 2},
- {5, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x66 */
- {{1, 2},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x67 */
- {{0, 2},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x68 */
- {{3, 3},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x69 */
- {{0, 0},
- {3, 3},
- {5, 6},
- {0, 0}
- }
- },
- {0, 0, 3, 0, /* 0x6a */
- {{1, 1},
- {3, 3},
- {5, 6},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x6b */
- {{0, 1},
- {3, 3},
- {5, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x6c */
- {{2, 3},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x6d */
- {{0, 0},
- {2, 3},
- {5, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x6e */
- {{1, 3},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x6f */
- {{0, 3},
- {5, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x70 */
- {{4, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x71 */
- {{0, 0},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x72 */
- {{1, 1},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x73 */
- {{0, 1},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x74 */
- {{2, 2},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 3, 0, /* 0x75 */
- {{0, 0},
- {2, 2},
- {4, 6},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x76 */
- {{1, 2},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x77 */
- {{0, 2},
- {4, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x78 */
- {{3, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x79 */
- {{0, 0},
- {3, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 2, 0, /* 0x7a */
- {{1, 1},
- {3, 6},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x7b */
- {{0, 1},
- {3, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x7c */
- {{2, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 2, 0, /* 0x7d */
- {{0, 0},
- {2, 6},
- {0, 0},
- {0, 0}
- }
- },
- {0, 0, 1, 0, /* 0x7e */
- {{1, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 0, 1, 0, /* 0x7f */
- {{0, 6},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0x80 */
- {{7, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0x81 */
- {{0, 0},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x82 */
- {{1, 1},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0x83 */
- {{0, 1},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x84 */
- {{2, 2},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x85 */
- {{0, 0},
- {2, 2},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x86 */
- {{1, 2},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0x87 */
- {{0, 2},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x88 */
- {{3, 3},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x89 */
- {{0, 0},
- {3, 3},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0x8a */
- {{1, 1},
- {3, 3},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x8b */
- {{0, 1},
- {3, 3},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x8c */
- {{2, 3},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x8d */
- {{0, 0},
- {2, 3},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x8e */
- {{1, 3},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0x8f */
- {{0, 3},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x90 */
- {{4, 4},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x91 */
- {{0, 0},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0x92 */
- {{1, 1},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x93 */
- {{0, 1},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0x94 */
- {{2, 2},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0x95 */
- {{0, 0},
- {2, 2},
- {4, 4},
- {7, 7}
- }
- },
- {0, 1, 3, 0, /* 0x96 */
- {{1, 2},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x97 */
- {{0, 2},
- {4, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x98 */
- {{3, 4},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x99 */
- {{0, 0},
- {3, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0x9a */
- {{1, 1},
- {3, 4},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x9b */
- {{0, 1},
- {3, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x9c */
- {{2, 4},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0x9d */
- {{0, 0},
- {2, 4},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0x9e */
- {{1, 4},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0x9f */
- {{0, 4},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xa0 */
- {{5, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xa1 */
- {{0, 0},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xa2 */
- {{1, 1},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xa3 */
- {{0, 1},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xa4 */
- {{2, 2},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0xa5 */
- {{0, 0},
- {2, 2},
- {5, 5},
- {7, 7}
- }
- },
- {0, 1, 3, 0, /* 0xa6 */
- {{1, 2},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xa7 */
- {{0, 2},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xa8 */
- {{3, 3},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0xa9 */
- {{0, 0},
- {3, 3},
- {5, 5},
- {7, 7}
- }
- },
- {0, 1, 4, 0, /* 0xaa */
- {{1, 1},
- {3, 3},
- {5, 5},
- {7, 7}
- }
- },
- {1, 1, 4, 0, /* 0xab */
- {{0, 1},
- {3, 3},
- {5, 5},
- {7, 7}
- }
- },
- {0, 1, 3, 0, /* 0xac */
- {{2, 3},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0xad */
- {{0, 0},
- {2, 3},
- {5, 5},
- {7, 7}
- }
- },
- {0, 1, 3, 0, /* 0xae */
- {{1, 3},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xaf */
- {{0, 3},
- {5, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xb0 */
- {{4, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xb1 */
- {{0, 0},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xb2 */
- {{1, 1},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xb3 */
- {{0, 1},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xb4 */
- {{2, 2},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0xb5 */
- {{0, 0},
- {2, 2},
- {4, 5},
- {7, 7}
- }
- },
- {0, 1, 3, 0, /* 0xb6 */
- {{1, 2},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xb7 */
- {{0, 2},
- {4, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xb8 */
- {{3, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xb9 */
- {{0, 0},
- {3, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xba */
- {{1, 1},
- {3, 5},
- {7, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xbb */
- {{0, 1},
- {3, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xbc */
- {{2, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xbd */
- {{0, 0},
- {2, 5},
- {7, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xbe */
- {{1, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xbf */
- {{0, 5},
- {7, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xc0 */
- {{6, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xc1 */
- {{0, 0},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xc2 */
- {{1, 1},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xc3 */
- {{0, 1},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xc4 */
- {{2, 2},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xc5 */
- {{0, 0},
- {2, 2},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xc6 */
- {{1, 2},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xc7 */
- {{0, 2},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xc8 */
- {{3, 3},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xc9 */
- {{0, 0},
- {3, 3},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xca */
- {{1, 1},
- {3, 3},
- {6, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xcb */
- {{0, 1},
- {3, 3},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xcc */
- {{2, 3},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xcd */
- {{0, 0},
- {2, 3},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xce */
- {{1, 3},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xcf */
- {{0, 3},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xd0 */
- {{4, 4},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xd1 */
- {{0, 0},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xd2 */
- {{1, 1},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xd3 */
- {{0, 1},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xd4 */
- {{2, 2},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {1, 1, 4, 0, /* 0xd5 */
- {{0, 0},
- {2, 2},
- {4, 4},
- {6, 7}
- }
- },
- {0, 1, 3, 0, /* 0xd6 */
- {{1, 2},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xd7 */
- {{0, 2},
- {4, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xd8 */
- {{3, 4},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xd9 */
- {{0, 0},
- {3, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xda */
- {{1, 1},
- {3, 4},
- {6, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xdb */
- {{0, 1},
- {3, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xdc */
- {{2, 4},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xdd */
- {{0, 0},
- {2, 4},
- {6, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xde */
- {{1, 4},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xdf */
- {{0, 4},
- {6, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xe0 */
- {{5, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xe1 */
- {{0, 0},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xe2 */
- {{1, 1},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xe3 */
- {{0, 1},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xe4 */
- {{2, 2},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xe5 */
- {{0, 0},
- {2, 2},
- {5, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xe6 */
- {{1, 2},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xe7 */
- {{0, 2},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xe8 */
- {{3, 3},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xe9 */
- {{0, 0},
- {3, 3},
- {5, 7},
- {0, 0}
- }
- },
- {0, 1, 3, 0, /* 0xea */
- {{1, 1},
- {3, 3},
- {5, 7},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xeb */
- {{0, 1},
- {3, 3},
- {5, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xec */
- {{2, 3},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xed */
- {{0, 0},
- {2, 3},
- {5, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xee */
- {{1, 3},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xef */
- {{0, 3},
- {5, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xf0 */
- {{4, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xf1 */
- {{0, 0},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xf2 */
- {{1, 1},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xf3 */
- {{0, 1},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xf4 */
- {{2, 2},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 3, 0, /* 0xf5 */
- {{0, 0},
- {2, 2},
- {4, 7},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xf6 */
- {{1, 2},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xf7 */
- {{0, 2},
- {4, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xf8 */
- {{3, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xf9 */
- {{0, 0},
- {3, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 2, 0, /* 0xfa */
- {{1, 1},
- {3, 7},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xfb */
- {{0, 1},
- {3, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xfc */
- {{2, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 2, 0, /* 0xfd */
- {{0, 0},
- {2, 7},
- {0, 0},
- {0, 0}
- }
- },
- {0, 1, 1, 0, /* 0xfe */
- {{1, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- },
- {1, 1, 1, 0, /* 0xff */
- {{0, 7},
- {0, 0},
- {0, 0},
- {0, 0}
- }
- }
-};
-
-
int
sctp_is_address_in_scope(struct sctp_ifa *ifa,
@@ -7513,7 +5707,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
cause = SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_UNSENT;
ret_spc = sctp_release_pr_sctp_chunk(stcb, chk,
cause,
- &asoc->sent_queue, SCTP_SO_LOCKED);
+ SCTP_SO_LOCKED);
freed_spc += ret_spc;
if (freed_spc >= dataout) {
return;
@@ -7538,7 +5732,7 @@ sctp_prune_prsctp(struct sctp_tcb *stcb,
ret_spc = sctp_release_pr_sctp_chunk(stcb, chk,
SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_UNSENT,
- &asoc->send_queue, SCTP_SO_LOCKED);
+ SCTP_SO_LOCKED);
freed_spc += ret_spc;
if (freed_spc >= dataout) {
@@ -7920,7 +6114,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
struct sctp_association *asoc,
int *num_out,
int *reason_code,
- int control_only, int *cwnd_full, int from_where,
+ int control_only, int from_where,
struct timeval *now, int *now_filled, int frag_point, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
@@ -8106,13 +6300,13 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
if (do_chunk_output)
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_NOT_LOCKED);
else if (added_control) {
- int num_out = 0, reason = 0, cwnd_full = 0, now_filled = 0;
+ int num_out = 0, reason = 0, now_filled = 0;
struct timeval now;
int frag_point;
frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
(void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out,
- &reason, 1, &cwnd_full, 1, &now, &now_filled, frag_point, SCTP_SO_NOT_LOCKED);
+ &reason, 1, 1, &now, &now_filled, frag_point, SCTP_SO_NOT_LOCKED);
}
no_chunk_output:
if (ret) {
@@ -8405,6 +6599,7 @@ sctp_clean_up_ctl(struct sctp_tcb *stcb, struct sctp_association *asoc)
(chk->rec.chunk_id.id == SCTP_NR_SELECTIVE_ACK) || /* EY */
(chk->rec.chunk_id.id == SCTP_HEARTBEAT_REQUEST) ||
(chk->rec.chunk_id.id == SCTP_HEARTBEAT_ACK) ||
+ (chk->rec.chunk_id.id == SCTP_FORWARD_CUM_TSN) ||
(chk->rec.chunk_id.id == SCTP_SHUTDOWN) ||
(chk->rec.chunk_id.id == SCTP_SHUTDOWN_ACK) ||
(chk->rec.chunk_id.id == SCTP_OPERATION_ERROR) ||
@@ -8547,7 +6742,7 @@ one_more_time:
* when we took all the data the sender_all_done was
* not set.
*/
- if (sp->put_last_out == 0) {
+ if ((sp->put_last_out == 0) && (sp->discard_rest == 0)) {
SCTP_PRINTF("Gak, put out entire msg with NO end!-1\n");
SCTP_PRINTF("sender_done:%d len:%d msg_comp:%d put_last_out:%d send_lock:%d\n",
sp->sender_all_done,
@@ -8568,7 +6763,6 @@ one_more_time:
sp->data = NULL;
}
sctp_free_a_strmoq(stcb, sp);
-
/* we can't be locked to it */
*locked = 0;
stcb->asoc.locked_on_sending = NULL;
@@ -8596,6 +6790,29 @@ one_more_time:
*giveup = 1;
to_move = 0;
goto out_of;
+ } else if (sp->discard_rest) {
+ if (send_lock_up == 0) {
+ SCTP_TCB_SEND_LOCK(stcb);
+ send_lock_up = 1;
+ }
+ /* Whack down the size */
+ atomic_subtract_int(&stcb->asoc.total_output_queue_size, sp->length);
+ if ((stcb->sctp_socket != NULL) && \
+ ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
+ atomic_subtract_int(&stcb->sctp_socket->so_snd.sb_cc, sp->length);
+ }
+ if (sp->data) {
+ sctp_m_freem(sp->data);
+ sp->data = NULL;
+ sp->tail_mbuf = NULL;
+ }
+ sp->length = 0;
+ sp->some_taken = 1;
+ *locked = 1;
+ *giveup = 1;
+ to_move = 0;
+ goto out_of;
}
}
some_taken = sp->some_taken;
@@ -9172,7 +7389,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
struct sctp_association *asoc,
int *num_out,
int *reason_code,
- int control_only, int *cwnd_full, int from_where,
+ int control_only, int from_where,
struct timeval *now, int *now_filled, int frag_point, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
@@ -9188,18 +7405,18 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
* fomulate and send the low level chunks. Making sure to combine
* any control in the control chunk queue also.
*/
- struct sctp_nets *net;
+ struct sctp_nets *net, *start_at, *old_start_at = NULL;
struct mbuf *outchain, *endoutchain;
struct sctp_tmit_chunk *chk, *nchk;
/* temp arrays for unlinking */
struct sctp_tmit_chunk *data_list[SCTP_MAX_DATA_BUNDLING];
int no_fragmentflg, error;
+ unsigned int max_rwnd_per_dest;
int one_chunk, hbflag, skip_data_for_this_net;
int asconf, cookie, no_out_cnt;
- int bundle_at, ctl_cnt, no_data_chunks, cwnd_full_ind, eeor_mode;
+ int bundle_at, ctl_cnt, no_data_chunks, eeor_mode;
unsigned int mtu, r_mtu, omtu, mx_mtu, to_out;
- struct sctp_nets *start_at, *old_startat = NULL, *send_start_at;
int tsns_sent = 0;
uint32_t auth_offset = 0;
struct sctp_auth_chunk *auth = NULL;
@@ -9215,7 +7432,6 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
int quit_now = 0;
*num_out = 0;
- cwnd_full_ind = 0;
auth_keyid = stcb->asoc.authinfo.active_keyid;
if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
@@ -9251,112 +7467,61 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
}
if (asoc->peers_rwnd == 0) {
/* No room in peers rwnd */
- *cwnd_full = 1;
*reason_code = 1;
if (asoc->total_flight > 0) {
/* we are allowed one chunk in flight */
no_data_chunks = 1;
}
}
+ max_rwnd_per_dest = ((asoc->peers_rwnd + asoc->total_flight) / asoc->numnets);
if ((no_data_chunks == 0) && (!TAILQ_EMPTY(&asoc->out_wheel))) {
- if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
- /*
- * for CMT we start at the next one past the one we
- * last added data to.
- */
- if (TAILQ_FIRST(&asoc->send_queue) != NULL) {
- goto skip_the_fill_from_streams;
- }
- if (asoc->last_net_data_came_from) {
- net = TAILQ_NEXT(asoc->last_net_data_came_from, sctp_next);
- if (net == NULL) {
- net = TAILQ_FIRST(&asoc->nets);
- }
- } else {
- /* back to start */
- net = TAILQ_FIRST(&asoc->nets);
- }
-
+ TAILQ_FOREACH(net, &asoc->nets, sctp_next) {
/*
- * JRI-TODO: CMT-MPI. Simply set the first
- * destination (net) to be optimized for the next
- * message to be pulled out of the outwheel. 1. peek
- * at outwheel 2. If large message, set net =
- * highest_cwnd 3. If small message, set net =
- * lowest rtt
+ * This for loop we are in takes in each net, if
+ * its's got space in cwnd and has data sent to it
+ * (when CMT is off) then it calls
+ * sctp_fill_outqueue for the net. This gets data on
+ * the send queue for that network.
+ *
+ * In sctp_fill_outqueue TSN's are assigned and data is
+ * copied out of the stream buffers. Note mostly
+ * copy by reference (we hope).
*/
- } else {
- net = asoc->primary_destination;
- if (net == NULL) {
- /* TSNH */
- net = TAILQ_FIRST(&asoc->nets);
- }
- }
- start_at = net;
-
-one_more_time:
- for (; net != NULL; net = TAILQ_NEXT(net, sctp_next)) {
net->window_probe = 0;
- if (old_startat && (old_startat == net)) {
- break;
- }
- /*
- * JRI: if dest is unreachable or unconfirmed, do
- * not send data to it
- */
if ((net->dest_state & SCTP_ADDR_NOT_REACHABLE) || (net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
- continue;
- }
- /*
- * JRI: if dest is in PF state, do not send data to
- * it
- */
- if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) &&
- SCTP_BASE_SYSCTL(sctp_cmt_pf) &&
- (net->dest_state & SCTP_ADDR_PF)) {
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
+ sctp_log_cwnd(stcb, net, 1,
+ SCTP_CWND_LOG_FILL_OUTQ_CALLED);
+ }
continue;
}
if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0) && (net->ref_count < 2)) {
/* nothing can be in queue for this guy */
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
+ sctp_log_cwnd(stcb, net, 2,
+ SCTP_CWND_LOG_FILL_OUTQ_CALLED);
+ }
continue;
}
if (net->flight_size >= net->cwnd) {
- /* skip this network, no room */
- cwnd_full_ind++;
+ /* skip this network, no room - can't fill */
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
+ sctp_log_cwnd(stcb, net, 3,
+ SCTP_CWND_LOG_FILL_OUTQ_CALLED);
+ }
continue;
}
- /*
- * JRI : this for loop we are in takes in each net,
- * if its's got space in cwnd and has data sent to
- * it (when CMT is off) then it calls
- * sctp_fill_outqueue for the net. This gets data on
- * the send queue for that network.
- *
- * In sctp_fill_outqueue TSN's are assigned and data is
- * copied out of the stream buffers. Note mostly
- * copy by reference (we hope).
- */
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_LOGGING_ENABLE) {
- sctp_log_cwnd(stcb, net, 0, SCTP_CWND_LOG_FILL_OUTQ_CALLED);
+ sctp_log_cwnd(stcb, net, 4, SCTP_CWND_LOG_FILL_OUTQ_CALLED);
}
sctp_fill_outqueue(stcb, net, frag_point, eeor_mode, &quit_now);
if (quit_now) {
/* memory alloc failure */
no_data_chunks = 1;
- goto skip_the_fill_from_streams;
+ break;
}
}
- if (start_at != TAILQ_FIRST(&asoc->nets)) {
- /* got to pick up the beginning stuff. */
- old_startat = start_at;
- start_at = net = TAILQ_FIRST(&asoc->nets);
- if (old_startat)
- goto one_more_time;
- }
}
-skip_the_fill_from_streams:
- *cwnd_full = cwnd_full_ind;
-
/* now service each destination and send out what we can for it */
/* Nothing to send? */
if ((TAILQ_FIRST(&asoc->control_send_queue) == NULL) &&
@@ -9365,32 +7530,45 @@ skip_the_fill_from_streams:
*reason_code = 8;
return (0);
}
- if (no_data_chunks) {
- chk = TAILQ_FIRST(&asoc->asconf_send_queue);
- if (chk == NULL)
- chk = TAILQ_FIRST(&asoc->control_send_queue);
- } else {
- chk = TAILQ_FIRST(&asoc->send_queue);
- }
- if (chk) {
- send_start_at = chk->whoTo;
+ if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
+ /* get the last start point */
+ start_at = asoc->last_net_cmt_send_started;
+ if (start_at == NULL) {
+ /* null so to beginning */
+ start_at = TAILQ_FIRST(&asoc->nets);
+ } else {
+ start_at = TAILQ_NEXT(asoc->last_net_cmt_send_started, sctp_next);
+ if (start_at == NULL) {
+ start_at = TAILQ_FIRST(&asoc->nets);
+ }
+ }
+ asoc->last_net_cmt_send_started = start_at;
} else {
- send_start_at = TAILQ_FIRST(&asoc->nets);
+ start_at = TAILQ_FIRST(&asoc->nets);
}
- old_startat = NULL;
+ old_start_at = NULL;
again_one_more_time:
- for (net = send_start_at; net != NULL; net = TAILQ_NEXT(net, sctp_next)) {
+ for (net = start_at; net != NULL; net = TAILQ_NEXT(net, sctp_next)) {
/* how much can we send? */
/* SCTPDBG("Examine for sending net:%x\n", (uint32_t)net); */
- if (old_startat && (old_startat == net)) {
+ if (old_start_at && (old_start_at == net)) {
/* through list ocmpletely. */
break;
}
- tsns_sent = 0;
- if (net->ref_count < 2) {
+ tsns_sent = 0xa;
+ if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off) == 0) && (net->ref_count < 2)) {
/*
* Ref-count of 1 so we cannot have data or control
- * queued to this address. Skip it.
+ * queued to this address. Skip it (non-CMT).
+ */
+ continue;
+ }
+ if ((TAILQ_FIRST(&asoc->control_send_queue) == NULL) &&
+ (TAILQ_FIRST(&asoc->asconf_send_queue) == NULL) &&
+ (net->flight_size >= net->cwnd)) {
+ /*
+ * Nothing on control or asconf and flight is full,
+ * we can skip even in the CMT case.
*/
continue;
}
@@ -9862,6 +8040,19 @@ again_one_more_time:
}
}
}
+ /* JRI: if dest is in PF state, do not send data to it */
+ if (SCTP_BASE_SYSCTL(sctp_cmt_on_off) &&
+ SCTP_BASE_SYSCTL(sctp_cmt_pf) &&
+ (net->dest_state & SCTP_ADDR_PF)) {
+ goto no_data_fill;
+ }
+ if (net->flight_size >= net->cwnd) {
+ goto no_data_fill;
+ }
+ if ((SCTP_BASE_SYSCTL(sctp_cmt_on_off)) &&
+ (net->flight_size > max_rwnd_per_dest)) {
+ goto no_data_fill;
+ }
/*********************/
/* Data transmission */
/*********************/
@@ -9897,7 +8088,8 @@ again_one_more_time:
omtu = 0;
break;
}
- if ((((asoc->state & SCTP_STATE_OPEN) == SCTP_STATE_OPEN) && (skip_data_for_this_net == 0)) ||
+ if ((((asoc->state & SCTP_STATE_OPEN) == SCTP_STATE_OPEN) &&
+ (skip_data_for_this_net == 0)) ||
(cookie)) {
for (chk = TAILQ_FIRST(&asoc->send_queue); chk; chk = nchk) {
if (no_data_chunks) {
@@ -9911,7 +8103,18 @@ again_one_more_time:
break;
}
nchk = TAILQ_NEXT(chk, sctp_next);
- if (chk->whoTo != net) {
+ if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
+ if (chk->whoTo != net) {
+ /*
+ * For CMT, steal the data
+ * to this network if its
+ * not set here.
+ */
+ sctp_free_remote_addr(chk->whoTo);
+ chk->whoTo = net;
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ }
+ } else if (chk->whoTo != net) {
/* No, not sent to this net */
continue;
}
@@ -10051,6 +8254,7 @@ again_one_more_time:
}
} /* for (chunk gather loop for this net) */
} /* if asoc.state OPEN */
+no_data_fill:
/* Is there something to send for this destination? */
if (outchain) {
/* We may need to start a control timer or two */
@@ -10199,10 +8403,10 @@ again_one_more_time:
sctp_log_cwnd(stcb, net, tsns_sent, SCTP_CWND_LOG_FROM_SEND);
}
}
- if (old_startat == NULL) {
- old_startat = send_start_at;
- send_start_at = TAILQ_FIRST(&asoc->nets);
- if (old_startat)
+ if (old_start_at == NULL) {
+ old_start_at = start_at;
+ start_at = TAILQ_FIRST(&asoc->nets);
+ if (old_start_at)
goto again_one_more_time;
}
/*
@@ -11247,7 +9451,6 @@ sctp_chunk_output(struct sctp_inpcb *inp,
burst_cnt = 0, burst_limit = 0;
struct timeval now;
int now_filled = 0;
- int cwnd_full = 0;
int nagle_on = 0;
int frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
int un_sent = 0;
@@ -11298,7 +9501,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
* and then the next call with get the retran's.
*/
(void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1,
- &cwnd_full, from_where,
+ from_where,
&now, &now_filled, frag_point, so_locked);
return;
} else if (from_where != SCTP_OUTPUT_FROM_HB_TMR) {
@@ -11323,7 +9526,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
* if queued too.
*/
(void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1,
- &cwnd_full, from_where,
+ from_where,
&now, &now_filled, frag_point, so_locked);
#ifdef SCTP_AUDITING_ENABLED
sctp_auditing(8, inp, stcb, NULL);
@@ -11350,7 +9553,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
sctp_auditing(10, inp, stcb, NULL);
#endif
/* Push out any control */
- (void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1, &cwnd_full, from_where,
+ (void)sctp_med_chunk_output(inp, stcb, asoc, &num_out, &reason_code, 1, from_where,
&now, &now_filled, frag_point, so_locked);
return;
}
@@ -11421,10 +9624,9 @@ sctp_chunk_output(struct sctp_inpcb *inp,
}
burst_cnt = 0;
- cwnd_full = 0;
do {
error = sctp_med_chunk_output(inp, stcb, asoc, &num_out,
- &reason_code, 0, &cwnd_full, from_where,
+ &reason_code, 0, from_where,
&now, &now_filled, frag_point, so_locked);
if (error) {
SCTPDBG(SCTP_DEBUG_OUTPUT1, "Error %d was returned from med-c-op\n", error);
@@ -11533,6 +9735,7 @@ send_forward_tsn(struct sctp_tcb *stcb,
{
struct sctp_tmit_chunk *chk;
struct sctp_forward_tsn_chunk *fwdtsn;
+ uint32_t advance_peer_ack_point;
SCTP_TCB_LOCK_ASSERT(stcb);
TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
@@ -11610,11 +9813,23 @@ sctp_fill_in_rest:
/* trim to a mtu size */
cnt_of_space = asoc->smallest_mtu - ovh;
}
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
+ sctp_misc_ints(SCTP_FWD_TSN_CHECK,
+ 0xff, 0, cnt_of_skipped,
+ asoc->advanced_peer_ack_point);
+
+ }
+ advance_peer_ack_point = asoc->advanced_peer_ack_point;
if (cnt_of_space < space_needed) {
/*-
* ok we must trim down the chunk by lowering the
* advance peer ack point.
*/
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
+ sctp_misc_ints(SCTP_FWD_TSN_CHECK,
+ 0xff, 0xff, cnt_of_space,
+ space_needed);
+ }
cnt_of_skipped = (cnt_of_space -
((sizeof(struct sctp_forward_tsn_chunk)) /
sizeof(struct sctp_strseq)));
@@ -11627,12 +9842,17 @@ sctp_fill_in_rest:
tp1 = TAILQ_NEXT(at, sctp_next);
at = tp1;
}
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOG_TRY_ADVANCE) {
+ sctp_misc_ints(SCTP_FWD_TSN_CHECK,
+ 0xff, cnt_of_skipped, at->rec.data.TSN_seq,
+ asoc->advanced_peer_ack_point);
+ }
last = at;
/*-
* last now points to last one I can report, update
* peer ack point
*/
- asoc->advanced_peer_ack_point = last->rec.data.TSN_seq;
+ advance_peer_ack_point = last->rec.data.TSN_seq;
space_needed -= (cnt_of_skipped * sizeof(struct sctp_strseq));
}
chk->send_size = space_needed;
@@ -11641,7 +9861,7 @@ sctp_fill_in_rest:
fwdtsn->ch.chunk_length = htons(chk->send_size);
fwdtsn->ch.chunk_flags = 0;
fwdtsn->ch.chunk_type = SCTP_FORWARD_CUM_TSN;
- fwdtsn->new_cumulative_tsn = htonl(asoc->advanced_peer_ack_point);
+ fwdtsn->new_cumulative_tsn = htonl(advance_peer_ack_point);
chk->send_size = (sizeof(struct sctp_forward_tsn_chunk) +
(cnt_of_skipped * sizeof(struct sctp_strseq)));
SCTP_BUF_LEN(chk->data) = chk->send_size;
@@ -11672,6 +9892,9 @@ sctp_fill_in_rest:
at = tp1;
continue;
}
+ if (at->rec.data.TSN_seq == advance_peer_ack_point) {
+ at->rec.data.fwd_tsn_cnt = 0;
+ }
strseq->stream = ntohs(at->rec.data.stream_number);
strseq->sequence = ntohs(at->rec.data.stream_seq);
strseq++;
@@ -11862,7 +10085,11 @@ sctp_send_sack(struct sctp_tcb *stcb)
gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)sack + sizeof(struct sctp_sack_chunk));
- siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
+ if (asoc->highest_tsn_inside_map > asoc->mapping_array_base_tsn)
+ siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
+ else
+ siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_map + 7) / 8;
+
if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
offset = 1;
/*-
@@ -11990,7 +10217,7 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
struct sctp_nr_gap_ack_block *nr_gap_descriptor;
struct sack_track *selector;
- struct nr_sack_track *nr_selector;
+ struct sack_track *nr_selector;
/* EY do we need nr_mergeable, NO */
int mergeable = 0;
@@ -12170,9 +10397,12 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
stcb->freed_by_sorcv_sincelast = 0;
gap_descriptor = (struct sctp_gap_ack_block *)((caddr_t)nr_sack + sizeof(struct sctp_nr_sack_chunk));
- nr_gap_descriptor = (struct sctp_nr_gap_ack_block *)((caddr_t)nr_sack + sizeof(struct sctp_nr_sack_chunk));
- siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
+ if (asoc->highest_tsn_inside_map > asoc->mapping_array_base_tsn)
+ siz = (((asoc->highest_tsn_inside_map - asoc->mapping_array_base_tsn) + 1) + 7) / 8;
+ else
+ siz = (((MAX_TSN - asoc->mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_map + 7) / 8;
+
if (compare_with_wrap(asoc->mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
offset = 1;
/*-
@@ -12255,11 +10485,15 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
nr_gap_descriptor = (struct sctp_nr_gap_ack_block *)gap_descriptor;
/* EY - there will be gaps + nr_gaps if draining is possible */
- if (SCTP_BASE_SYSCTL(sctp_do_drain)) {
+ if ((SCTP_BASE_SYSCTL(sctp_do_drain)) && (limit_reached == 0)) {
mergeable = 0;
- siz = (((asoc->highest_tsn_inside_nr_map - asoc->nr_mapping_array_base_tsn) + 1) + 7) / 8;
+ if (asoc->highest_tsn_inside_nr_map > asoc->nr_mapping_array_base_tsn)
+ siz = (((asoc->highest_tsn_inside_nr_map - asoc->nr_mapping_array_base_tsn) + 1) + 7) / 8;
+ else
+ siz = (((MAX_TSN - asoc->nr_mapping_array_base_tsn) + 1) + asoc->highest_tsn_inside_nr_map + 7) / 8;
+
if (compare_with_wrap(asoc->nr_mapping_array_base_tsn, asoc->cumulative_tsn, MAX_TSN)) {
offset = 1;
/*-
@@ -12278,7 +10512,7 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
if (compare_with_wrap(asoc->highest_tsn_inside_nr_map, asoc->cumulative_tsn, MAX_TSN)) {
/* we have a gap .. maybe */
for (i = 0; i < siz; i++) {
- nr_selector = &nr_sack_array[asoc->nr_mapping_array[i]];
+ nr_selector = &sack_array[asoc->nr_mapping_array[i]];
if (mergeable && nr_selector->right_edge) {
/*
* Backup, left and right edges were
@@ -12304,9 +10538,9 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
* left side
*/
mergeable = 0;
- nr_gap_descriptor->start = htons((nr_selector->nr_gaps[j].start + offset));
+ nr_gap_descriptor->start = htons((nr_selector->gaps[j].start + offset));
}
- nr_gap_descriptor->end = htons((nr_selector->nr_gaps[j].end + offset));
+ nr_gap_descriptor->end = htons((nr_selector->gaps[j].end + offset));
num_nr_gap_blocks++;
nr_gap_descriptor++;
if (((caddr_t)nr_gap_descriptor + sizeof(struct sctp_nr_gap_ack_block)) > limit) {
@@ -12328,7 +10562,7 @@ sctp_send_nr_sack(struct sctp_tcb *stcb)
}
}
}
- /*---------------------------------------------------End of---filling the nr_gap_ack blocks----------------------------------------------------*/
+ /*---------------------------------------------End of---filling the nr_gap_ack blocks----------------------------------------------------*/
/* now we must add any dups we are going to report. */
if ((limit_reached == 0) && (asoc->numduptsns)) {
@@ -15401,7 +13635,7 @@ skip_out_eof:
}
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED);
} else if (some_on_control) {
- int num_out, reason, cwnd_full, frag_point;
+ int num_out, reason, frag_point;
/* Here we do control only */
if (hold_tcblock == 0) {
@@ -15410,7 +13644,7 @@ skip_out_eof:
}
frag_point = sctp_get_frag_point(stcb, &stcb->asoc);
(void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out,
- &reason, 1, &cwnd_full, 1, &now, &now_filled, frag_point, SCTP_SO_LOCKED);
+ &reason, 1, 1, &now, &now_filled, frag_point, SCTP_SO_LOCKED);
}
SCTPDBG(SCTP_DEBUG_OUTPUT1, "USR Send complete qo:%d prw:%d unsent:%d tf:%d cooq:%d toqs:%d err:%d\n",
queue_only, stcb->asoc.peers_rwnd, un_sent,
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index d98e760..df519cc 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -3157,8 +3157,9 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
SCTP_TCB_UNLOCK(asoc);
continue;
}
- if ((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_WAIT) ||
- (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_ECHOED)) {
+ if (((SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_WAIT) ||
+ (SCTP_GET_STATE(&asoc->asoc) == SCTP_STATE_COOKIE_ECHOED)) &&
+ (asoc->asoc.total_output_queue_size == 0)) {
/*
* If we have data in queue, we don't want
* to just free since the app may have done,
@@ -6029,6 +6030,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
stcb->asoc.peer_supports_prsctp = 0;
stcb->asoc.peer_supports_pktdrop = 0;
stcb->asoc.peer_supports_strreset = 0;
+ stcb->asoc.peer_supports_nr_sack = 0;
stcb->asoc.peer_supports_auth = 0;
pr_supported = (struct sctp_supported_chunk_types_param *)phdr;
num_ent = plen - sizeof(struct sctp_paramhdr);
@@ -6044,6 +6046,12 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
case SCTP_PACKET_DROPPED:
stcb->asoc.peer_supports_pktdrop = 1;
break;
+ case SCTP_NR_SELECTIVE_ACK:
+ if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off))
+ stcb->asoc.peer_supports_nr_sack = 1;
+ else
+ stcb->asoc.peer_supports_nr_sack = 0;
+ break;
case SCTP_STREAM_RESET:
stcb->asoc.peer_supports_strreset = 1;
break;
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index a03ae94..24ae10f 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -196,6 +196,7 @@ struct sctp_nets {
/* smoothed average things for RTT and RTO itself */
int lastsa;
int lastsv;
+ int rtt; /* last measured rtt value in ms */
unsigned int RTO;
/* This is used for SHUTDOWN/SHUTDOWN-ACK/SEND or INIT timers */
@@ -309,7 +310,7 @@ struct sctp_data_chunkrec {
/* ECN Nonce: Nonce Value for this chunk */
uint8_t ect_nonce;
-
+ uint8_t fwd_tsn_cnt;
/*
* part of the Highest sacked algorithm to be able to stroke counts
* on ones that are FR'd.
@@ -445,6 +446,7 @@ struct sctp_stream_queue_pending {
uint8_t pr_sctp_on;
uint8_t sender_all_done;
uint8_t put_last_out;
+ uint8_t discard_rest;
};
/*
@@ -676,7 +678,7 @@ struct sctp_association {
/* primary destination to use */
struct sctp_nets *primary_destination;
/* For CMT */
- struct sctp_nets *last_net_data_came_from;
+ struct sctp_nets *last_net_cmt_send_started;
/* last place I got a data chunk from */
struct sctp_nets *last_data_chunk_from;
/* last place I got a control from */
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index a64aec4..969ffdd 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -463,6 +463,7 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
xraddr.cwnd = net->cwnd;
xraddr.flight_size = net->flight_size;
xraddr.mtu = net->mtu;
+ xraddr.rtt = net->rtt;
xraddr.start_time.tv_sec = (uint32_t) net->start_time.tv_sec;
xraddr.start_time.tv_usec = (uint32_t) net->start_time.tv_usec;
SCTP_INP_RUNLOCK(inp);
diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h
index dd42d41..7419568 100644
--- a/sys/netinet/sctp_sysctl.h
+++ b/sys/netinet/sctp_sysctl.h
@@ -74,7 +74,7 @@ struct sctp_sysctl {
uint32_t sctp_nr_outgoing_streams_default;
uint32_t sctp_cmt_on_off;
uint32_t sctp_cmt_use_dac;
-/* EY 5/5/08 - nr_sack flag variable */
+ /* EY 5/5/08 - nr_sack flag variable */
uint32_t sctp_nr_sack_on_off;
uint32_t sctp_cmt_pf;
uint32_t sctp_use_cwnd_based_maxburst;
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index 1d2d5f2..477c0b1 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -767,7 +767,7 @@ start_again:
(void)sctp_release_pr_sctp_chunk(stcb,
chk,
(SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
- &stcb->asoc.sent_queue, SCTP_SO_NOT_LOCKED);
+ SCTP_SO_NOT_LOCKED);
}
continue;
}
@@ -779,7 +779,7 @@ start_again:
(void)sctp_release_pr_sctp_chunk(stcb,
chk,
(SCTP_RESPONSE_TO_USER_REQ | SCTP_NOTIFY_DATAGRAM_SENT),
- &stcb->asoc.sent_queue, SCTP_SO_NOT_LOCKED);
+ SCTP_SO_NOT_LOCKED);
}
continue;
}
diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h
index b8d2ecd..efcd2c4 100644
--- a/sys/netinet/sctp_uio.h
+++ b/sys/netinet/sctp_uio.h
@@ -565,9 +565,9 @@ struct sctp_sack_info {
struct sctp_cwnd_args {
struct sctp_nets *net; /* network to *//* FIXME: LP64 issue */
uint32_t cwnd_new_value;/* cwnd in k */
- uint32_t inflight; /* flightsize in k */
uint32_t pseudo_cumack;
- uint32_t cwnd_augment; /* increment to it */
+ uint16_t inflight; /* flightsize in k */
+ uint16_t cwnd_augment; /* increment to it */
uint8_t meets_pseudo_cumack;
uint8_t need_new_pseudo_cumack;
uint8_t cnt_in_send;
@@ -986,7 +986,7 @@ struct xsctp_inpcb {
uint16_t local_port;
uint16_t qlen;
uint16_t maxqlen;
- uint32_t extra_padding[8]; /* future */
+ uint32_t extra_padding[32]; /* future */
};
struct xsctp_tcb {
@@ -1017,14 +1017,14 @@ struct xsctp_tcb {
struct sctp_timeval discontinuity_time; /* sctpAssocEntry 17 */
uint32_t peers_rwnd;
sctp_assoc_t assoc_id; /* sctpAssocEntry 1 */
- uint32_t extra_padding[8]; /* future */
+ uint32_t extra_padding[32]; /* future */
};
struct xsctp_laddr {
union sctp_sockstore address; /* sctpAssocLocalAddrEntry 1/2 */
uint32_t last;
struct sctp_timeval start_time; /* sctpAssocLocalAddrEntry 3 */
- uint32_t extra_padding[8]; /* future */
+ uint32_t extra_padding[32]; /* future */
};
struct xsctp_raddr {
@@ -1041,7 +1041,8 @@ struct xsctp_raddr {
uint8_t confirmed; /* */
uint8_t heartbeat_enabled; /* sctpAssocLocalRemEntry 4 */
struct sctp_timeval start_time; /* sctpAssocLocalRemEntry 8 */
- uint32_t extra_padding[8]; /* future */
+ uint32_t rtt;
+ uint32_t extra_padding[32]; /* future */
};
#define SCTP_MAX_LOGGING_SIZE 30000
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index b3bfea5..c80cca0 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -126,6 +126,10 @@ sctp_pathmtu_adjustment(struct sctp_inpcb *inp,
* since we sent to big of chunk
*/
chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
+ if (chk->sent < SCTP_DATAGRAM_RESEND) {
+ sctp_flight_size_decrease(chk);
+ sctp_total_flight_decrease(stcb, chk);
+ }
if (chk->sent != SCTP_DATAGRAM_RESEND) {
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
}
@@ -140,8 +144,6 @@ sctp_pathmtu_adjustment(struct sctp_inpcb *inp,
}
/* Clear any time so NO RTT is being done */
chk->do_rtt = 0;
- sctp_flight_size_decrease(chk);
- sctp_total_flight_decrease(stcb, chk);
}
}
}
diff --git a/sys/netinet/sctp_var.h b/sys/netinet/sctp_var.h
index 934af00..1ccccf3 100644
--- a/sys/netinet/sctp_var.h
+++ b/sys/netinet/sctp_var.h
@@ -96,7 +96,8 @@ extern struct pr_usrreqs sctp_usrreqs;
#define sctp_alloc_a_strmoq(_stcb, _strmoq) { \
(_strmoq) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_strmoq), struct sctp_stream_queue_pending); \
- if ((_strmoq)) { \
+ if ((_strmoq)) { \
+ memset(_strmoq, 0, sizeof(struct sctp_stream_queue_pending)); \
SCTP_INCR_STRMOQ_COUNT(); \
(_strmoq)->holds_key_ref = 0; \
} \
@@ -267,6 +268,7 @@ extern struct pr_usrreqs sctp_usrreqs;
#else
#define sctp_total_flight_decrease(stcb, tp1) do { \
+ tp1->window_probe = 0; \
if (stcb->asoc.total_flight >= tp1->book_size) { \
stcb->asoc.total_flight -= tp1->book_size; \
if (stcb->asoc.total_flight_count > 0) \
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 1eac98a..aea7376 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -970,7 +970,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
asoc->sent_queue_retran_cnt = 0;
/* for CMT */
- asoc->last_net_data_came_from = NULL;
+ asoc->last_net_cmt_send_started = NULL;
/* This will need to be adjusted */
asoc->last_cwr_tsn = asoc->init_seq_number - 1;
@@ -1222,33 +1222,25 @@ sctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed)
SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
asoc->mapping_array = new_array;
asoc->mapping_array_size = new_size;
- return (0);
-}
-
-/* EY - nr_sack version of the above method */
-int
-sctp_expand_nr_mapping_array(struct sctp_association *asoc, uint32_t needed)
-{
- /* nr mapping array needs to grow */
- uint8_t *new_array;
- uint32_t new_size;
-
- new_size = asoc->nr_mapping_array_size + ((needed + 7) / 8 + SCTP_NR_MAPPING_ARRAY_INCR);
- SCTP_MALLOC(new_array, uint8_t *, new_size, SCTP_M_MAP);
- if (new_array == NULL) {
- /* can't get more, forget it */
- SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n",
- new_size);
- return (-1);
+ if (asoc->peer_supports_nr_sack) {
+ new_size = asoc->nr_mapping_array_size + ((needed + 7) / 8 + SCTP_NR_MAPPING_ARRAY_INCR);
+ SCTP_MALLOC(new_array, uint8_t *, new_size, SCTP_M_MAP);
+ if (new_array == NULL) {
+ /* can't get more, forget it */
+ SCTP_PRINTF("No memory for expansion of SCTP mapping array %d\n",
+ new_size);
+ return (-1);
+ }
+ memset(new_array, 0, new_size);
+ memcpy(new_array, asoc->nr_mapping_array, asoc->nr_mapping_array_size);
+ SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP);
+ asoc->nr_mapping_array = new_array;
+ asoc->nr_mapping_array_size = new_size;
}
- memset(new_array, 0, new_size);
- memcpy(new_array, asoc->nr_mapping_array, asoc->nr_mapping_array_size);
- SCTP_FREE(asoc->nr_mapping_array, SCTP_M_MAP);
- asoc->nr_mapping_array = new_array;
- asoc->nr_mapping_array_size = new_size;
return (0);
}
+
#if defined(SCTP_USE_THREAD_BASED_ITERATOR)
static void
sctp_iterator_work(struct sctp_iterator *it)
@@ -2589,7 +2581,7 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
/***************************/
/* 2. update RTTVAR & SRTT */
/***************************/
- o_calctime = calc_time;
+ net->rtt = o_calctime = calc_time;
/* this is Van Jacobson's integer version */
if (net->RTO_measured) {
calc_time -= (net->lastsa >> SCTP_RTT_SHIFT); /* take away 1/8th when
@@ -3686,10 +3678,10 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
while (chk) {
TAILQ_REMOVE(&asoc->sent_queue, chk, sctp_next);
asoc->sent_queue_cnt--;
- sctp_free_bufspace(stcb, asoc, chk, 1);
- sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
- SCTP_NOTIFY_DATAGRAM_SENT, chk, so_locked);
- if (chk->data) {
+ if (chk->data != NULL) {
+ sctp_free_bufspace(stcb, asoc, chk, 1);
+ sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
+ SCTP_NOTIFY_DATAGRAM_SENT, chk, so_locked);
sctp_m_freem(chk->data);
chk->data = NULL;
}
@@ -3704,9 +3696,10 @@ sctp_report_all_outbound(struct sctp_tcb *stcb, int holds_lock, int so_locked
while (chk) {
TAILQ_REMOVE(&asoc->send_queue, chk, sctp_next);
asoc->send_queue_cnt--;
- sctp_free_bufspace(stcb, asoc, chk, 1);
- sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, SCTP_NOTIFY_DATAGRAM_UNSENT, chk, so_locked);
- if (chk->data) {
+ if (chk->data != NULL) {
+ sctp_free_bufspace(stcb, asoc, chk, 1);
+ sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb,
+ SCTP_NOTIFY_DATAGRAM_UNSENT, chk, so_locked);
sctp_m_freem(chk->data);
chk->data = NULL;
}
@@ -4630,65 +4623,42 @@ sctp_free_bufspace(struct sctp_tcb *stcb, struct sctp_association *asoc,
int
sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
- int reason, struct sctpchunk_listhead *queue, int so_locked
+ int reason, int so_locked
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
)
{
+ struct sctp_stream_out *strq;
+ struct sctp_tmit_chunk *chk = NULL;
+ struct sctp_stream_queue_pending *sp;
+ uint16_t stream = 0, seq = 0;
+ uint8_t foundeom = 0;
int ret_sz = 0;
int notdone;
- uint8_t foundeom = 0;
+ int do_wakeup_routine = 0;
+ stream = tp1->rec.data.stream_number;
+ seq = tp1->rec.data.stream_seq;
do {
ret_sz += tp1->book_size;
- tp1->sent = SCTP_FORWARD_TSN_SKIP;
- if (tp1->data) {
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- struct socket *so;
-
-#endif
+ if (tp1->data != NULL) {
+ if (tp1->sent < SCTP_DATAGRAM_RESEND) {
+ sctp_flight_size_decrease(tp1);
+ sctp_total_flight_decrease(stcb, tp1);
+ }
sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
- sctp_flight_size_decrease(tp1);
- sctp_total_flight_decrease(stcb, tp1);
+ stcb->asoc.peers_rwnd += tp1->send_size;
+ stcb->asoc.peers_rwnd += SCTP_BASE_SYSCTL(sctp_peer_chunk_oh);
sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1, so_locked);
sctp_m_freem(tp1->data);
tp1->data = NULL;
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- so = SCTP_INP_SO(stcb->sctp_ep);
- if (!so_locked) {
- atomic_add_int(&stcb->asoc.refcnt, 1);
- SCTP_TCB_UNLOCK(stcb);
- SCTP_SOCKET_LOCK(so, 1);
- SCTP_TCB_LOCK(stcb);
- atomic_subtract_int(&stcb->asoc.refcnt, 1);
- if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
- /*
- * assoc was freed while we were
- * unlocked
- */
- SCTP_SOCKET_UNLOCK(so, 1);
- return (ret_sz);
- }
- }
-#endif
- sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
-#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
- if (!so_locked) {
- SCTP_SOCKET_UNLOCK(so, 1);
+ do_wakeup_routine = 1;
+ if (PR_SCTP_BUF_ENABLED(tp1->flags)) {
+ stcb->asoc.sent_queue_cnt_removeable--;
}
-#endif
- }
- if (PR_SCTP_BUF_ENABLED(tp1->flags)) {
- stcb->asoc.sent_queue_cnt_removeable--;
- }
- if (queue == &stcb->asoc.send_queue) {
- TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next);
- /* on to the sent queue */
- TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1,
- sctp_next);
- stcb->asoc.sent_queue_cnt++;
}
+ tp1->sent = SCTP_FORWARD_TSN_SKIP;
if ((tp1->rec.data.rcv_flags & SCTP_DATA_NOT_FRAG) ==
SCTP_DATA_NOT_FRAG) {
/* not frag'ed we ae done */
@@ -4707,22 +4677,151 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
tp1 = TAILQ_NEXT(tp1, sctp_next);
}
} while (tp1 && notdone);
- if ((foundeom == 0) && (queue == &stcb->asoc.sent_queue)) {
+ if (foundeom == 0) {
/*
* The multi-part message was scattered across the send and
* sent queue.
*/
+next_on_sent:
tp1 = TAILQ_FIRST(&stcb->asoc.send_queue);
/*
* recurse throught the send_queue too, starting at the
* beginning.
*/
- if (tp1) {
- ret_sz += sctp_release_pr_sctp_chunk(stcb, tp1, reason,
- &stcb->asoc.send_queue, so_locked);
- } else {
- SCTP_PRINTF("hmm, nothing on the send queue and no EOM?\n");
+ if ((tp1) &&
+ (tp1->rec.data.stream_number == stream) &&
+ (tp1->rec.data.stream_seq == seq)
+ ) {
+ /*
+ * save to chk in case we have some on stream out
+ * queue. If so and we have an un-transmitted one we
+ * don't have to fudge the TSN.
+ */
+ chk = tp1;
+ ret_sz += tp1->book_size;
+ sctp_ulp_notify(SCTP_NOTIFY_DG_FAIL, stcb, reason, tp1, so_locked);
+ sctp_free_bufspace(stcb, &stcb->asoc, tp1, 1);
+ sctp_m_freem(tp1->data);
+ /* No flight involved here book the size to 0 */
+ tp1->book_size = 0;
+ tp1->data = NULL;
+ if (tp1->rec.data.rcv_flags & SCTP_DATA_LAST_FRAG) {
+ foundeom = 1;
+ }
+ do_wakeup_routine = 1;
+ tp1->sent = SCTP_FORWARD_TSN_SKIP;
+ TAILQ_REMOVE(&stcb->asoc.send_queue, tp1, sctp_next);
+ /*
+ * on to the sent queue so we can wait for it to be
+ * passed by.
+ */
+ TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, tp1,
+ sctp_next);
+ stcb->asoc.send_queue_cnt--;
+ stcb->asoc.sent_queue_cnt++;
+ goto next_on_sent;
+ }
+ }
+ if (foundeom == 0) {
+ /*
+ * Still no eom found. That means there is stuff left on the
+ * stream out queue.. yuck.
+ */
+ strq = &stcb->asoc.strmout[stream];
+ SCTP_TCB_SEND_LOCK(stcb);
+ sp = TAILQ_FIRST(&strq->outqueue);
+ while (sp->strseq <= seq) {
+ /* Check if its our SEQ */
+ if (sp->strseq == seq) {
+ sp->discard_rest = 1;
+ /*
+ * We may need to put a chunk on the queue
+ * that holds the TSN that would have been
+ * sent with the LAST bit.
+ */
+ if (chk == NULL) {
+ /* Yep, we have to */
+ sctp_alloc_a_chunk(stcb, chk);
+ if (chk == NULL) {
+ /*
+ * we are hosed. All we can
+ * do is nothing.. which
+ * will cause an abort if
+ * the peer is paying
+ * attention.
+ */
+ goto oh_well;
+ }
+ memset(chk, 0, sizeof(*chk));
+ chk->rec.data.rcv_flags = SCTP_DATA_LAST_FRAG;
+ chk->sent = SCTP_FORWARD_TSN_SKIP;
+ chk->asoc = &stcb->asoc;
+ chk->rec.data.stream_seq = sp->strseq;
+ chk->rec.data.stream_number = sp->stream;
+ chk->rec.data.payloadtype = sp->ppid;
+ chk->rec.data.context = sp->context;
+ chk->flags = sp->act_flags;
+ chk->addr_over = sp->addr_over;
+ chk->whoTo = sp->net;
+ atomic_add_int(&chk->whoTo->ref_count, 1);
+ chk->rec.data.TSN_seq = atomic_fetchadd_int(&stcb->asoc.sending_seq, 1);
+ stcb->asoc.pr_sctp_cnt++;
+ chk->pr_sctp_on = 1;
+ TAILQ_INSERT_TAIL(&stcb->asoc.sent_queue, chk, sctp_next);
+ stcb->asoc.sent_queue_cnt++;
+ stcb->asoc.pr_sctp_cnt++;
+ } else {
+ chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
+ }
+ oh_well:
+ if (sp->data) {
+ /*
+ * Pull any data to free up the SB
+ * and allow sender to "add more"
+ * whilc we will throw away :-)
+ */
+ sctp_free_spbufspace(stcb, &stcb->asoc,
+ sp);
+ ret_sz += sp->length;
+ do_wakeup_routine = 1;
+ sp->some_taken = 1;
+ sctp_m_freem(sp->data);
+ sp->length = 0;
+ sp->data = NULL;
+ sp->tail_mbuf = NULL;
+ }
+ break;
+ } else {
+ /* Next one please */
+ sp = TAILQ_NEXT(sp, next);
+ }
+ } /* End while */
+ SCTP_TCB_SEND_UNLOCK(stcb);
+ }
+ if (do_wakeup_routine) {
+#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ struct socket *so;
+
+ so = SCTP_INP_SO(stcb->sctp_ep);
+ if (!so_locked) {
+ atomic_add_int(&stcb->asoc.refcnt, 1);
+ SCTP_TCB_UNLOCK(stcb);
+ SCTP_SOCKET_LOCK(so, 1);
+ SCTP_TCB_LOCK(stcb);
+ atomic_subtract_int(&stcb->asoc.refcnt, 1);
+ if (stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET) {
+ /* assoc was freed while we were unlocked */
+ SCTP_SOCKET_UNLOCK(so, 1);
+ return (ret_sz);
+ }
}
+#endif
+ sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);
+#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
+ if (!so_locked) {
+ SCTP_SOCKET_UNLOCK(so, 1);
+ }
+#endif
}
return (ret_sz);
}
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index 56c6729..c5a2ad9 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -237,7 +237,7 @@ sctp_notify_partial_delivery_indication(struct sctp_tcb *stcb,
int
sctp_release_pr_sctp_chunk(struct sctp_tcb *, struct sctp_tmit_chunk *,
- int, struct sctpchunk_listhead *, int
+ int, int
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
SCTP_UNUSED
#endif
@@ -287,7 +287,6 @@ do { \
#define sctp_free_spbufspace(stcb, asoc, sp) \
do { \
if (sp->data != NULL) { \
- atomic_subtract_int(&(asoc)->chunks_on_out_queue, 1); \
if ((asoc)->total_output_queue_size >= sp->length) { \
atomic_subtract_int(&(asoc)->total_output_queue_size, sp->length); \
} else { \
diff --git a/sys/netinet/tcp_hostcache.c b/sys/netinet/tcp_hostcache.c
index c9b5b8c..71f4626 100644
--- a/sys/netinet/tcp_hostcache.c
+++ b/sys/netinet/tcp_hostcache.c
@@ -341,7 +341,7 @@ tcp_hc_insert(struct in_conninfo *inc)
TAILQ_REMOVE(&hc_head->hch_bucket, hc_entry, rmx_q);
V_tcp_hostcache.hashbase[hash].hch_length--;
V_tcp_hostcache.cache_count--;
- V_tcpstat.tcps_hc_bucketoverflow++;
+ TCPSTAT_INC(tcps_hc_bucketoverflow);
#if 0
uma_zfree(V_tcp_hostcache.zone, hc_entry);
#endif
@@ -373,7 +373,7 @@ tcp_hc_insert(struct in_conninfo *inc)
TAILQ_INSERT_HEAD(&hc_head->hch_bucket, hc_entry, rmx_q);
V_tcp_hostcache.hashbase[hash].hch_length++;
V_tcp_hostcache.cache_count++;
- V_tcpstat.tcps_hc_added++;
+ TCPSTAT_INC(tcps_hc_added);
return hc_entry;
}
@@ -508,7 +508,7 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml)
else
hc_entry->rmx_rtt =
(hc_entry->rmx_rtt + hcml->rmx_rtt) / 2;
- V_tcpstat.tcps_cachedrtt++;
+ TCPSTAT_INC(tcps_cachedrtt);
}
if (hcml->rmx_rttvar != 0) {
if (hc_entry->rmx_rttvar == 0)
@@ -516,7 +516,7 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml)
else
hc_entry->rmx_rttvar =
(hc_entry->rmx_rttvar + hcml->rmx_rttvar) / 2;
- V_tcpstat.tcps_cachedrttvar++;
+ TCPSTAT_INC(tcps_cachedrttvar);
}
if (hcml->rmx_ssthresh != 0) {
if (hc_entry->rmx_ssthresh == 0)
@@ -524,7 +524,7 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml)
else
hc_entry->rmx_ssthresh =
(hc_entry->rmx_ssthresh + hcml->rmx_ssthresh) / 2;
- V_tcpstat.tcps_cachedssthresh++;
+ TCPSTAT_INC(tcps_cachedssthresh);
}
if (hcml->rmx_bandwidth != 0) {
if (hc_entry->rmx_bandwidth == 0)
@@ -532,7 +532,7 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml)
else
hc_entry->rmx_bandwidth =
(hc_entry->rmx_bandwidth + hcml->rmx_bandwidth) / 2;
- /* V_tcpstat.tcps_cachedbandwidth++; */
+ /* TCPSTAT_INC(tcps_cachedbandwidth); */
}
if (hcml->rmx_cwnd != 0) {
if (hc_entry->rmx_cwnd == 0)
@@ -540,7 +540,7 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml)
else
hc_entry->rmx_cwnd =
(hc_entry->rmx_cwnd + hcml->rmx_cwnd) / 2;
- /* V_tcpstat.tcps_cachedcwnd++; */
+ /* TCPSTAT_INC(tcps_cachedcwnd); */
}
if (hcml->rmx_sendpipe != 0) {
if (hc_entry->rmx_sendpipe == 0)
@@ -548,7 +548,7 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml)
else
hc_entry->rmx_sendpipe =
(hc_entry->rmx_sendpipe + hcml->rmx_sendpipe) /2;
- /* V_tcpstat.tcps_cachedsendpipe++; */
+ /* TCPSTAT_INC(tcps_cachedsendpipe); */
}
if (hcml->rmx_recvpipe != 0) {
if (hc_entry->rmx_recvpipe == 0)
@@ -556,7 +556,7 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml)
else
hc_entry->rmx_recvpipe =
(hc_entry->rmx_recvpipe + hcml->rmx_recvpipe) /2;
- /* V_tcpstat.tcps_cachedrecvpipe++; */
+ /* TCPSTAT_INC(tcps_cachedrecvpipe); */
}
TAILQ_REMOVE(&hc_entry->rmx_head->hch_bucket, hc_entry, rmx_q);
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index d3b91b6..d4a9f70 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -352,7 +352,7 @@ tcp_input(struct mbuf *m, int off0)
#endif
to.to_flags = 0;
- V_tcpstat.tcps_rcvtotal++;
+ TCPSTAT_INC(tcps_rcvtotal);
if (isipv6) {
#ifdef INET6
@@ -360,7 +360,7 @@ tcp_input(struct mbuf *m, int off0)
ip6 = mtod(m, struct ip6_hdr *);
tlen = sizeof(*ip6) + ntohs(ip6->ip6_plen) - off0;
if (in6_cksum(m, IPPROTO_TCP, off0, tlen)) {
- V_tcpstat.tcps_rcvbadsum++;
+ TCPSTAT_INC(tcps_rcvbadsum);
goto drop;
}
th = (struct tcphdr *)((caddr_t)ip6 + off0);
@@ -392,7 +392,7 @@ tcp_input(struct mbuf *m, int off0)
if (m->m_len < sizeof (struct tcpiphdr)) {
if ((m = m_pullup(m, sizeof (struct tcpiphdr)))
== NULL) {
- V_tcpstat.tcps_rcvshort++;
+ TCPSTAT_INC(tcps_rcvshort);
return;
}
}
@@ -426,7 +426,7 @@ tcp_input(struct mbuf *m, int off0)
th->th_sum = in_cksum(m, len);
}
if (th->th_sum) {
- V_tcpstat.tcps_rcvbadsum++;
+ TCPSTAT_INC(tcps_rcvbadsum);
goto drop;
}
/* Re-initialization for later version check */
@@ -446,7 +446,7 @@ tcp_input(struct mbuf *m, int off0)
*/
off = th->th_off << 2;
if (off < sizeof (struct tcphdr) || off > tlen) {
- V_tcpstat.tcps_rcvbadoff++;
+ TCPSTAT_INC(tcps_rcvbadoff);
goto drop;
}
tlen -= off; /* tlen is used instead of ti->ti_len */
@@ -461,7 +461,7 @@ tcp_input(struct mbuf *m, int off0)
if (m->m_len < sizeof(struct ip) + off) {
if ((m = m_pullup(m, sizeof (struct ip) + off))
== NULL) {
- V_tcpstat.tcps_rcvshort++;
+ TCPSTAT_INC(tcps_rcvshort);
return;
}
ip = mtod(m, struct ip *);
@@ -594,7 +594,14 @@ findpcb:
goto dropwithreset;
}
INP_WLOCK(inp);
-
+ if (!(inp->inp_flags & INP_HW_FLOWID)
+ && (m->m_flags & M_FLOWID)
+ && ((inp->inp_socket == NULL)
+ || !(inp->inp_socket->so_options & SO_ACCEPTCONN))) {
+ inp->inp_flags |= INP_HW_FLOWID;
+ inp->inp_flags &= ~INP_SW_FLOWID;
+ inp->inp_flowid = m->m_pkthdr.flowid;
+ }
#ifdef IPSEC
#ifdef INET6
if (isipv6 && ipsec6_in_reject(m, inp)) {
@@ -635,7 +642,7 @@ findpcb:
* tried to free the inpcb, in which case we need to loop back and
* try to find a new inpcb to deliver to.
*/
- if (inp->inp_vflag & INP_TIMEWAIT) {
+ if (inp->inp_flags & INP_TIMEWAIT) {
KASSERT(ti_locked == TI_RLOCKED || ti_locked == TI_WLOCKED,
("%s: INP_TIMEWAIT ti_locked %d", __func__, ti_locked));
@@ -853,7 +860,7 @@ findpcb:
log(LOG_DEBUG, "%s; %s: Listen socket: "
"SYN is missing, segment ignored\n",
s, __func__);
- V_tcpstat.tcps_badsyn++;
+ TCPSTAT_INC(tcps_badsyn);
goto dropunlock;
}
/*
@@ -865,7 +872,7 @@ findpcb:
"SYN|ACK invalid, segment rejected\n",
s, __func__);
syncache_badack(&inc); /* XXX: Not needed! */
- V_tcpstat.tcps_badsyn++;
+ TCPSTAT_INC(tcps_badsyn);
rstreason = BANDLIM_RST_OPENPORT;
goto dropwithreset;
}
@@ -885,7 +892,7 @@ findpcb:
log(LOG_DEBUG, "%s; %s: Listen socket: "
"SYN|FIN segment ignored (based on "
"sysctl setting)\n", s, __func__);
- V_tcpstat.tcps_badsyn++;
+ TCPSTAT_INC(tcps_badsyn);
goto dropunlock;
}
/*
@@ -1148,13 +1155,13 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
switch (iptos & IPTOS_ECN_MASK) {
case IPTOS_ECN_CE:
tp->t_flags |= TF_ECN_SND_ECE;
- V_tcpstat.tcps_ecn_ce++;
+ TCPSTAT_INC(tcps_ecn_ce);
break;
case IPTOS_ECN_ECT0:
- V_tcpstat.tcps_ecn_ect0++;
+ TCPSTAT_INC(tcps_ecn_ect0);
break;
case IPTOS_ECN_ECT1:
- V_tcpstat.tcps_ecn_ect1++;
+ TCPSTAT_INC(tcps_ecn_ect1);
break;
}
@@ -1167,7 +1174,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if ((thflags & TH_ECE) &&
SEQ_LEQ(th->th_ack, tp->snd_recover)) {
- V_tcpstat.tcps_ecn_rcwnd++;
+ TCPSTAT_INC(tcps_ecn_rcwnd);
tcp_congestion_exp(tp);
}
}
@@ -1284,14 +1291,14 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
__func__, ti_locked);
ti_locked = TI_UNLOCKED;
- ++V_tcpstat.tcps_predack;
+ TCPSTAT_INC(tcps_predack);
/*
* "bad retransmit" recovery.
*/
if (tp->t_rxtshift == 1 &&
ticks < tp->t_badrxtwin) {
- ++V_tcpstat.tcps_sndrexmitbad;
+ TCPSTAT_INC(tcps_sndrexmitbad);
tp->snd_cwnd = tp->snd_cwnd_prev;
tp->snd_ssthresh =
tp->snd_ssthresh_prev;
@@ -1327,8 +1334,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
}
tcp_xmit_bandwidth_limit(tp, th->th_ack);
acked = th->th_ack - tp->snd_una;
- V_tcpstat.tcps_rcvackpack++;
- V_tcpstat.tcps_rcvackbyte += acked;
+ TCPSTAT_INC(tcps_rcvackpack);
+ TCPSTAT_ADD(tcps_rcvackbyte, acked);
sbdrop(&so->so_snd, acked);
if (SEQ_GT(tp->snd_una, tp->snd_recover) &&
SEQ_LEQ(th->th_ack, tp->snd_recover))
@@ -1389,7 +1396,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
/* Clean receiver SACK report if present */
if ((tp->t_flags & TF_SACK_PERMIT) && tp->rcv_numsacks)
tcp_clean_sackreport(tp);
- ++V_tcpstat.tcps_preddat;
+ TCPSTAT_INC(tcps_preddat);
tp->rcv_nxt += tlen;
/*
* Pull snd_wl1 up to prevent seq wrap relative to
@@ -1401,8 +1408,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
* rcv_nxt.
*/
tp->rcv_up = tp->rcv_nxt;
- V_tcpstat.tcps_rcvpack++;
- V_tcpstat.tcps_rcvbyte += tlen;
+ TCPSTAT_INC(tcps_rcvpack);
+ TCPSTAT_ADD(tcps_rcvbyte, tlen);
ND6_HINT(tp); /* Some progress has been made */
#ifdef TCPDEBUG
if (so->so_options & SO_DEBUG)
@@ -1552,7 +1559,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tp->irs = th->th_seq;
tcp_rcvseqinit(tp);
if (thflags & TH_ACK) {
- V_tcpstat.tcps_connects++;
+ TCPSTAT_INC(tcps_connects);
soisconnected(so);
#ifdef MAC
SOCK_LOCK(so);
@@ -1578,7 +1585,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
if ((thflags & TH_ECE) && V_tcp_do_ecn) {
tp->t_flags |= TF_ECN_PERMIT;
- V_tcpstat.tcps_ecn_shs++;
+ TCPSTAT_INC(tcps_ecn_shs);
}
/*
@@ -1628,8 +1635,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
m_adj(m, -todrop);
tlen = tp->rcv_wnd;
thflags &= ~TH_FIN;
- V_tcpstat.tcps_rcvpackafterwin++;
- V_tcpstat.tcps_rcvbyteafterwin += todrop;
+ TCPSTAT_INC(tcps_rcvpackafterwin);
+ TCPSTAT_ADD(tcps_rcvbyteafterwin, todrop);
}
tp->snd_wl1 = th->th_seq - 1;
tp->rcv_up = th->th_seq;
@@ -1733,7 +1740,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
SEQ_LEQ(th->th_seq, tp->rcv_nxt + 1)) &&
!(SEQ_GEQ(th->th_seq, tp->last_ack_sent - 1) &&
SEQ_LEQ(th->th_seq, tp->last_ack_sent + 1))) {
- V_tcpstat.tcps_badrst++;
+ TCPSTAT_INC(tcps_badrst);
goto drop;
}
/* FALLTHROUGH */
@@ -1748,7 +1755,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
tp->t_state = TCPS_CLOSED;
- V_tcpstat.tcps_drops++;
+ TCPSTAT_INC(tcps_drops);
tp = tcp_close(tp);
break;
@@ -1788,9 +1795,9 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
tp->ts_recent = 0;
} else {
- V_tcpstat.tcps_rcvduppack++;
- V_tcpstat.tcps_rcvdupbyte += tlen;
- V_tcpstat.tcps_pawsdrop++;
+ TCPSTAT_INC(tcps_rcvduppack);
+ TCPSTAT_ADD(tcps_rcvdupbyte, tlen);
+ TCPSTAT_INC(tcps_pawsdrop);
if (tlen)
goto dropafterack;
goto drop;
@@ -1838,11 +1845,11 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
tp->t_flags |= TF_ACKNOW;
todrop = tlen;
- V_tcpstat.tcps_rcvduppack++;
- V_tcpstat.tcps_rcvdupbyte += todrop;
+ TCPSTAT_INC(tcps_rcvduppack);
+ TCPSTAT_ADD(tcps_rcvdupbyte, todrop);
} else {
- V_tcpstat.tcps_rcvpartduppack++;
- V_tcpstat.tcps_rcvpartdupbyte += todrop;
+ TCPSTAT_INC(tcps_rcvpartduppack);
+ TCPSTAT_ADD(tcps_rcvpartdupbyte, todrop);
}
drop_hdrlen += todrop; /* drop from the top afterwards */
th->th_seq += todrop;
@@ -1874,7 +1881,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
free(s, M_TCPLOG);
}
tp = tcp_close(tp);
- V_tcpstat.tcps_rcvafterclose++;
+ TCPSTAT_INC(tcps_rcvafterclose);
rstreason = BANDLIM_UNLIMITED;
goto dropwithreset;
}
@@ -1885,9 +1892,9 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
todrop = (th->th_seq + tlen) - (tp->rcv_nxt + tp->rcv_wnd);
if (todrop > 0) {
- V_tcpstat.tcps_rcvpackafterwin++;
+ TCPSTAT_INC(tcps_rcvpackafterwin);
if (todrop >= tlen) {
- V_tcpstat.tcps_rcvbyteafterwin += tlen;
+ TCPSTAT_ADD(tcps_rcvbyteafterwin, tlen);
/*
* If window is closed can only take segments at
* window edge, and have to drop data and PUSH from
@@ -1897,11 +1904,11 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
if (tp->rcv_wnd == 0 && th->th_seq == tp->rcv_nxt) {
tp->t_flags |= TF_ACKNOW;
- V_tcpstat.tcps_rcvwinprobe++;
+ TCPSTAT_INC(tcps_rcvwinprobe);
} else
goto dropafterack;
} else
- V_tcpstat.tcps_rcvbyteafterwin += todrop;
+ TCPSTAT_ADD(tcps_rcvbyteafterwin, todrop);
m_adj(m, -todrop);
tlen -= todrop;
thflags &= ~(TH_PUSH|TH_FIN);
@@ -1974,7 +1981,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
*/
case TCPS_SYN_RECEIVED:
- V_tcpstat.tcps_connects++;
+ TCPSTAT_INC(tcps_connects);
soisconnected(so);
/* Do window scaling? */
if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) ==
@@ -2020,7 +2027,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
case TCPS_CLOSING:
case TCPS_LAST_ACK:
if (SEQ_GT(th->th_ack, tp->snd_max)) {
- V_tcpstat.tcps_rcvacktoomuch++;
+ TCPSTAT_INC(tcps_rcvacktoomuch);
goto dropafterack;
}
if ((tp->t_flags & TF_SACK_PERMIT) &&
@@ -2029,7 +2036,7 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tcp_sack_doack(tp, &to, th->th_ack);
if (SEQ_LEQ(th->th_ack, tp->snd_una)) {
if (tlen == 0 && tiwin == tp->snd_wnd) {
- V_tcpstat.tcps_rcvdupack++;
+ TCPSTAT_INC(tcps_rcvdupack);
/*
* If we have outstanding data (other than
* a window probe), this is a completely
@@ -2112,7 +2119,8 @@ tcp_do_segment(struct mbuf *m, struct tcphdr *th, struct socket *so,
tcp_timer_activate(tp, TT_REXMT, 0);
tp->t_rtttime = 0;
if (tp->t_flags & TF_SACK_PERMIT) {
- V_tcpstat.tcps_sack_recovery_episode++;
+ TCPSTAT_INC(
+ tcps_sack_recovery_episode);
tp->sack_newdata = tp->snd_nxt;
tp->snd_cwnd = tp->t_maxseg;
(void) tcp_output(tp);
@@ -2234,8 +2242,8 @@ process_ACK:
INP_WLOCK_ASSERT(tp->t_inpcb);
acked = th->th_ack - tp->snd_una;
- V_tcpstat.tcps_rcvackpack++;
- V_tcpstat.tcps_rcvackbyte += acked;
+ TCPSTAT_INC(tcps_rcvackpack);
+ TCPSTAT_ADD(tcps_rcvackbyte, acked);
/*
* If we just performed our first retransmit, and the ACK
@@ -2245,7 +2253,7 @@ process_ACK:
* we left off.
*/
if (tp->t_rxtshift == 1 && ticks < tp->t_badrxtwin) {
- ++V_tcpstat.tcps_sndrexmitbad;
+ TCPSTAT_INC(tcps_sndrexmitbad);
tp->snd_cwnd = tp->snd_cwnd_prev;
tp->snd_ssthresh = tp->snd_ssthresh_prev;
tp->snd_recover = tp->snd_recover_prev;
@@ -2469,7 +2477,7 @@ step6:
/* keep track of pure window updates */
if (tlen == 0 &&
tp->snd_wl2 == th->th_ack && tiwin > tp->snd_wnd)
- V_tcpstat.tcps_rcvwinupd++;
+ TCPSTAT_INC(tcps_rcvwinupd);
tp->snd_wnd = tiwin;
tp->snd_wl1 = th->th_seq;
tp->snd_wl2 = th->th_ack;
@@ -2579,8 +2587,8 @@ dodata: /* XXX */
tp->t_flags |= TF_ACKNOW;
tp->rcv_nxt += tlen;
thflags = th->th_flags & TH_FIN;
- V_tcpstat.tcps_rcvpack++;
- V_tcpstat.tcps_rcvbyte += tlen;
+ TCPSTAT_INC(tcps_rcvpack);
+ TCPSTAT_ADD(tcps_rcvbyte, tlen);
ND6_HINT(tp);
SOCKBUF_LOCK(&so->so_rcv);
if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
@@ -2933,7 +2941,7 @@ tcp_dooptions(struct tcpopt *to, u_char *cp, int cnt, int flags)
to->to_flags |= TOF_SACK;
to->to_nsacks = (optlen - 2) / TCPOLEN_SACK;
to->to_sacks = cp + 2;
- V_tcpstat.tcps_sack_rcv_blocks++;
+ TCPSTAT_INC(tcps_sack_rcv_blocks);
break;
default:
continue;
@@ -2988,7 +2996,7 @@ tcp_xmit_timer(struct tcpcb *tp, int rtt)
INP_WLOCK_ASSERT(tp->t_inpcb);
- V_tcpstat.tcps_rttupdated++;
+ TCPSTAT_INC(tcps_rttupdated);
tp->t_rttupdated++;
if (tp->t_srtt != 0) {
/*
@@ -3310,10 +3318,10 @@ tcp_mss(struct tcpcb *tp, int offer)
if (tp->t_srtt == 0 && (rtt = metrics.rmx_rtt)) {
tp->t_srtt = rtt;
tp->t_rttbest = tp->t_srtt + TCP_RTT_SCALE;
- V_tcpstat.tcps_usedrtt++;
+ TCPSTAT_INC(tcps_usedrtt);
if (metrics.rmx_rttvar) {
tp->t_rttvar = metrics.rmx_rttvar;
- V_tcpstat.tcps_usedrttvar++;
+ TCPSTAT_INC(tcps_usedrttvar);
} else {
/* default variation is +- 1 rtt */
tp->t_rttvar =
@@ -3331,7 +3339,7 @@ tcp_mss(struct tcpcb *tp, int offer)
* threshold to no less than 2*mss.
*/
tp->snd_ssthresh = max(2 * mss, metrics.rmx_ssthresh);
- V_tcpstat.tcps_usedssthresh++;
+ TCPSTAT_INC(tcps_usedssthresh);
}
if (metrics.rmx_bandwidth)
tp->snd_bandwidth = metrics.rmx_bandwidth;
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index 2347305..d014fdd 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -264,9 +264,9 @@ again:
if (len > 0) {
sack_rxmit = 1;
sendalot = 1;
- V_tcpstat.tcps_sack_rexmits++;
- V_tcpstat.tcps_sack_rexmit_bytes +=
- min(len, tp->t_maxseg);
+ TCPSTAT_INC(tcps_sack_rexmits);
+ TCPSTAT_ADD(tcps_sack_rexmit_bytes,
+ min(len, tp->t_maxseg));
}
}
after_sack_rexmit:
@@ -768,13 +768,13 @@ send:
u_int moff;
if ((tp->t_flags & TF_FORCEDATA) && len == 1)
- V_tcpstat.tcps_sndprobe++;
+ TCPSTAT_INC(tcps_sndprobe);
else if (SEQ_LT(tp->snd_nxt, tp->snd_max) || sack_rxmit) {
- V_tcpstat.tcps_sndrexmitpack++;
- V_tcpstat.tcps_sndrexmitbyte += len;
+ TCPSTAT_INC(tcps_sndrexmitpack);
+ TCPSTAT_ADD(tcps_sndrexmitbyte, len);
} else {
- V_tcpstat.tcps_sndpack++;
- V_tcpstat.tcps_sndbyte += len;
+ TCPSTAT_INC(tcps_sndpack);
+ TCPSTAT_ADD(tcps_sndbyte, len);
}
#ifdef notyet
if ((m = m_copypack(so->so_snd.sb_mb, off,
@@ -841,13 +841,13 @@ send:
} else {
SOCKBUF_UNLOCK(&so->so_snd);
if (tp->t_flags & TF_ACKNOW)
- V_tcpstat.tcps_sndacks++;
+ TCPSTAT_INC(tcps_sndacks);
else if (flags & (TH_SYN|TH_FIN|TH_RST))
- V_tcpstat.tcps_sndctrl++;
+ TCPSTAT_INC(tcps_sndctrl);
else if (SEQ_GT(tp->snd_up, tp->snd_una))
- V_tcpstat.tcps_sndurg++;
+ TCPSTAT_INC(tcps_sndurg);
else
- V_tcpstat.tcps_sndwinup++;
+ TCPSTAT_INC(tcps_sndwinup);
MGETHDR(m, M_DONTWAIT, MT_DATA);
if (m == NULL) {
@@ -919,7 +919,7 @@ send:
else
#endif
ip->ip_tos |= IPTOS_ECN_ECT0;
- V_tcpstat.tcps_ecn_ect0++;
+ TCPSTAT_INC(tcps_ecn_ect0);
}
/*
@@ -1085,7 +1085,7 @@ send:
if (tp->t_rtttime == 0) {
tp->t_rtttime = ticks;
tp->t_rtseq = startseq;
- V_tcpstat.tcps_segstimed++;
+ TCPSTAT_INC(tcps_segstimed);
}
}
@@ -1262,7 +1262,7 @@ out:
return (error);
}
}
- V_tcpstat.tcps_sndtotal++;
+ TCPSTAT_INC(tcps_sndtotal);
/*
* Data sent (as far as we can tell).
@@ -1437,7 +1437,7 @@ tcp_addoptions(struct tcpopt *to, u_char *optp)
optlen += TCPOLEN_SACK;
sack++;
}
- V_tcpstat.tcps_sack_send_blocks++;
+ TCPSTAT_INC(tcps_sack_send_blocks);
break;
}
default:
diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c
index 172abc5..080bb02 100644
--- a/sys/netinet/tcp_reass.c
+++ b/sys/netinet/tcp_reass.c
@@ -108,10 +108,12 @@ tcp_reass_zone_change(void *tag)
INIT_VNET_INET(curvnet);
V_tcp_reass_maxseg = nmbclusters / 16;
- uma_zone_set_max(tcp_reass_zone, V_tcp_reass_maxseg);
+ uma_zone_set_max(V_tcp_reass_zone, V_tcp_reass_maxseg);
}
+#ifdef VIMAGE_GLOBALS
uma_zone_t tcp_reass_zone;
+#endif
void
tcp_reass_init(void)
@@ -126,9 +128,9 @@ tcp_reass_init(void)
V_tcp_reass_maxseg = nmbclusters / 16;
TUNABLE_INT_FETCH("net.inet.tcp.reass.maxsegments",
&V_tcp_reass_maxseg);
- tcp_reass_zone = uma_zcreate("tcpreass", sizeof (struct tseg_qent),
+ V_tcp_reass_zone = uma_zcreate("tcpreass", sizeof (struct tseg_qent),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
- uma_zone_set_max(tcp_reass_zone, V_tcp_reass_maxseg);
+ uma_zone_set_max(V_tcp_reass_zone, V_tcp_reass_maxseg);
EVENTHANDLER_REGISTER(nmbclusters_change,
tcp_reass_zone_change, NULL, EVENTHANDLER_PRI_ANY);
}
@@ -170,7 +172,7 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
(V_tcp_reass_qsize + 1 >= V_tcp_reass_maxseg ||
tp->t_segqlen >= V_tcp_reass_maxqlen)) {
V_tcp_reass_overflows++;
- V_tcpstat.tcps_rcvmemdrop++;
+ TCPSTAT_INC(tcps_rcvmemdrop);
m_freem(m);
*tlenp = 0;
return (0);
@@ -180,9 +182,9 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
* Allocate a new queue entry. If we can't, or hit the zone limit
* just drop the pkt.
*/
- te = uma_zalloc(tcp_reass_zone, M_NOWAIT);
+ te = uma_zalloc(V_tcp_reass_zone, M_NOWAIT);
if (te == NULL) {
- V_tcpstat.tcps_rcvmemdrop++;
+ TCPSTAT_INC(tcps_rcvmemdrop);
m_freem(m);
*tlenp = 0;
return (0);
@@ -210,10 +212,10 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
i = p->tqe_th->th_seq + p->tqe_len - th->th_seq;
if (i > 0) {
if (i >= *tlenp) {
- V_tcpstat.tcps_rcvduppack++;
- V_tcpstat.tcps_rcvdupbyte += *tlenp;
+ TCPSTAT_INC(tcps_rcvduppack);
+ TCPSTAT_ADD(tcps_rcvdupbyte, *tlenp);
m_freem(m);
- uma_zfree(tcp_reass_zone, te);
+ uma_zfree(V_tcp_reass_zone, te);
tp->t_segqlen--;
V_tcp_reass_qsize--;
/*
@@ -229,8 +231,8 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
th->th_seq += i;
}
}
- V_tcpstat.tcps_rcvoopack++;
- V_tcpstat.tcps_rcvoobyte += *tlenp;
+ TCPSTAT_INC(tcps_rcvoopack);
+ TCPSTAT_ADD(tcps_rcvoobyte, *tlenp);
/*
* While we overlap succeeding segments trim them or,
@@ -250,7 +252,7 @@ tcp_reass(struct tcpcb *tp, struct tcphdr *th, int *tlenp, struct mbuf *m)
nq = LIST_NEXT(q, tqe_q);
LIST_REMOVE(q, tqe_q);
m_freem(q->tqe_m);
- uma_zfree(tcp_reass_zone, q);
+ uma_zfree(V_tcp_reass_zone, q);
tp->t_segqlen--;
V_tcp_reass_qsize--;
q = nq;
@@ -287,7 +289,7 @@ present:
m_freem(q->tqe_m);
else
sbappendstream_locked(&so->so_rcv, q->tqe_m);
- uma_zfree(tcp_reass_zone, q);
+ uma_zfree(V_tcp_reass_zone, q);
tp->t_segqlen--;
V_tcp_reass_qsize--;
q = nq;
diff --git a/sys/netinet/tcp_sack.c b/sys/netinet/tcp_sack.c
index 4ca10af..29bf50c 100644
--- a/sys/netinet/tcp_sack.c
+++ b/sys/netinet/tcp_sack.c
@@ -123,9 +123,8 @@ __FBSDID("$FreeBSD$");
#include <machine/in_cksum.h>
-extern struct uma_zone *sack_hole_zone;
-
#ifdef VIMAGE_GLOBALS
+extern struct uma_zone *sack_hole_zone;
int tcp_do_sack;
int tcp_sack_maxholes;
int tcp_sack_globalmaxholes;
@@ -261,11 +260,11 @@ tcp_sackhole_alloc(struct tcpcb *tp, tcp_seq start, tcp_seq end)
if (tp->snd_numholes >= V_tcp_sack_maxholes ||
V_tcp_sack_globalholes >= V_tcp_sack_globalmaxholes) {
- V_tcpstat.tcps_sack_sboverflow++;
+ TCPSTAT_INC(tcps_sack_sboverflow);
return NULL;
}
- hole = (struct sackhole *)uma_zalloc(sack_hole_zone, M_NOWAIT);
+ hole = (struct sackhole *)uma_zalloc(V_sack_hole_zone, M_NOWAIT);
if (hole == NULL)
return NULL;
@@ -287,7 +286,7 @@ tcp_sackhole_free(struct tcpcb *tp, struct sackhole *hole)
{
INIT_VNET_INET(tp->t_vnet);
- uma_zfree(sack_hole_zone, hole);
+ uma_zfree(V_sack_hole_zone, hole);
tp->snd_numholes--;
V_tcp_sack_globalholes--;
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 11f4a81..d2d38a0 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -243,7 +243,9 @@ SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_tcp_inflight, OID_AUTO, stab,
CTLFLAG_RW, tcp_inflight_stab, 0,
"Inflight Algorithm Stabilization 20 = 2 packets");
+#ifdef VIMAGE_GLOBALS
uma_zone_t sack_hole_zone;
+#endif
static struct inpcb *tcp_notify(struct inpcb *, int);
static void tcp_isn_tick(void *);
@@ -269,7 +271,9 @@ struct tcpcb_mem {
struct tcp_timer tt;
};
+#ifdef VIMAGE_GLOBALS
static uma_zone_t tcpcb_zone;
+#endif
MALLOC_DEFINE(M_TCPLOG, "tcplog", "TCP address and flags print buffers");
struct callout isn_callout;
static struct mtx isn_mtx;
@@ -286,7 +290,7 @@ tcp_zone_change(void *tag)
{
uma_zone_set_max(V_tcbinfo.ipi_zone, maxsockets);
- uma_zone_set_max(tcpcb_zone, maxsockets);
+ uma_zone_set_max(V_tcpcb_zone, maxsockets);
tcp_tw_zone_change();
}
@@ -348,18 +352,7 @@ tcp_init(void)
V_tcp_sack_globalmaxholes = 65536;
V_tcp_sack_globalholes = 0;
- tcp_delacktime = TCPTV_DELACK;
- tcp_keepinit = TCPTV_KEEP_INIT;
- tcp_keepidle = TCPTV_KEEP_IDLE;
- tcp_keepintvl = TCPTV_KEEPINTVL;
- tcp_maxpersistidle = TCPTV_KEEP_IDLE;
- tcp_msl = TCPTV_MSL;
- tcp_rexmit_min = TCPTV_MIN;
- if (tcp_rexmit_min < 1)
- tcp_rexmit_min = 1;
- tcp_rexmit_slop = TCPTV_CPU_VAR;
V_tcp_inflight_rttthresh = TCPTV_INFLIGHT_RTTTHRESH;
- tcp_finwait2_timeout = TCPTV_FINWAIT2_TIMEOUT;
TUNABLE_INT_FETCH("net.inet.tcp.sack.enable", &V_tcp_do_sack);
@@ -372,7 +365,6 @@ tcp_init(void)
printf("WARNING: TCB hash size not a power of 2\n");
hashsize = 512; /* safe default */
}
- tcp_tcbhashsize = hashsize;
V_tcbinfo.ipi_hashbase = hashinit(hashsize, M_PCB,
&V_tcbinfo.ipi_hashmask);
V_tcbinfo.ipi_porthashbase = hashinit(hashsize, M_PCB,
@@ -380,6 +372,37 @@ tcp_init(void)
V_tcbinfo.ipi_zone = uma_zcreate("inpcb", sizeof(struct inpcb),
NULL, NULL, tcp_inpcb_init, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
uma_zone_set_max(V_tcbinfo.ipi_zone, maxsockets);
+ /*
+ * These have to be type stable for the benefit of the timers.
+ */
+ V_tcpcb_zone = uma_zcreate("tcpcb", sizeof(struct tcpcb_mem),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
+ uma_zone_set_max(V_tcpcb_zone, maxsockets);
+ tcp_tw_init();
+ syncache_init();
+ tcp_hc_init();
+ tcp_reass_init();
+ V_sack_hole_zone = uma_zcreate("sackhole", sizeof(struct sackhole),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
+
+ /* Skip initialization of globals for non-default instances. */
+ if (!IS_DEFAULT_VNET(curvnet))
+ return;
+
+ /* XXX virtualize those bellow? */
+ tcp_delacktime = TCPTV_DELACK;
+ tcp_keepinit = TCPTV_KEEP_INIT;
+ tcp_keepidle = TCPTV_KEEP_IDLE;
+ tcp_keepintvl = TCPTV_KEEPINTVL;
+ tcp_maxpersistidle = TCPTV_KEEP_IDLE;
+ tcp_msl = TCPTV_MSL;
+ tcp_rexmit_min = TCPTV_MIN;
+ if (tcp_rexmit_min < 1)
+ tcp_rexmit_min = 1;
+ tcp_rexmit_slop = TCPTV_CPU_VAR;
+ tcp_finwait2_timeout = TCPTV_FINWAIT2_TIMEOUT;
+ tcp_tcbhashsize = hashsize;
+
#ifdef INET6
#define TCP_MINPROTOHDR (sizeof(struct ip6_hdr) + sizeof(struct tcphdr))
#else /* INET6 */
@@ -390,23 +413,12 @@ tcp_init(void)
if (max_linkhdr + TCP_MINPROTOHDR > MHLEN)
panic("tcp_init");
#undef TCP_MINPROTOHDR
- /*
- * These have to be type stable for the benefit of the timers.
- */
- tcpcb_zone = uma_zcreate("tcpcb", sizeof(struct tcpcb_mem),
- NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
- uma_zone_set_max(tcpcb_zone, maxsockets);
- tcp_tw_init();
- syncache_init();
- tcp_hc_init();
- tcp_reass_init();
+
ISN_LOCK_INIT();
callout_init(&isn_callout, CALLOUT_MPSAFE);
- tcp_isn_tick(NULL);
+ callout_reset(&isn_callout, hz/100, tcp_isn_tick, NULL);
EVENTHANDLER_REGISTER(shutdown_pre_sync, tcp_fini, NULL,
SHUTDOWN_PRI_DEFAULT);
- sack_hole_zone = uma_zcreate("sackhole", sizeof(struct sackhole),
- NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
EVENTHANDLER_REGISTER(maxsockets_change, tcp_zone_change, NULL,
EVENTHANDLER_PRI_ANY);
}
@@ -686,7 +698,7 @@ tcp_newtcpcb(struct inpcb *inp)
int isipv6 = (inp->inp_vflag & INP_IPV6) != 0;
#endif /* INET6 */
- tm = uma_zalloc(tcpcb_zone, M_NOWAIT | M_ZERO);
+ tm = uma_zalloc(V_tcpcb_zone, M_NOWAIT | M_ZERO);
if (tm == NULL)
return (NULL);
tp = &tm->tcb;
@@ -752,9 +764,9 @@ tcp_drop(struct tcpcb *tp, int errno)
if (TCPS_HAVERCVDSYN(tp->t_state)) {
tp->t_state = TCPS_CLOSED;
(void) tcp_output_reset(tp);
- V_tcpstat.tcps_drops++;
+ TCPSTAT_INC(tcps_drops);
} else
- V_tcpstat.tcps_conndrops++;
+ TCPSTAT_INC(tcps_conndrops);
if (errno == ETIMEDOUT && tp->t_softerror)
errno = tp->t_softerror;
so->so_error = errno;
@@ -846,7 +858,7 @@ tcp_discardcb(struct tcpcb *tp)
while ((q = LIST_FIRST(&tp->t_segq)) != NULL) {
LIST_REMOVE(q, tqe_q);
m_freem(q->tqe_m);
- uma_zfree(tcp_reass_zone, q);
+ uma_zfree(V_tcp_reass_zone, q);
tp->t_segqlen--;
V_tcp_reass_qsize--;
}
@@ -856,7 +868,7 @@ tcp_discardcb(struct tcpcb *tp)
tcp_free_sackholes(tp);
inp->inp_ppcb = NULL;
tp->t_inpcb = NULL;
- uma_zfree(tcpcb_zone, tp);
+ uma_zfree(V_tcpcb_zone, tp);
}
/*
@@ -877,14 +889,14 @@ tcp_close(struct tcpcb *tp)
if (tp->t_state == TCPS_LISTEN)
tcp_offload_listen_close(tp);
in_pcbdrop(inp);
- V_tcpstat.tcps_closed++;
+ TCPSTAT_INC(tcps_closed);
KASSERT(inp->inp_socket != NULL, ("tcp_close: inp_socket NULL"));
so = inp->inp_socket;
soisdisconnected(so);
- if (inp->inp_vflag & INP_SOCKREF) {
+ if (inp->inp_flags & INP_SOCKREF) {
KASSERT(so->so_state & SS_PROTOREF,
("tcp_close: !SS_PROTOREF"));
- inp->inp_vflag &= ~INP_SOCKREF;
+ inp->inp_flags &= ~INP_SOCKREF;
INP_WUNLOCK(inp);
ACCEPT_LOCK();
SOCK_LOCK(so);
@@ -921,7 +933,7 @@ tcp_drain(void)
*/
INP_INFO_RLOCK(&V_tcbinfo);
LIST_FOREACH(inpb, V_tcbinfo.ipi_listhead, inp_list) {
- if (inpb->inp_vflag & INP_TIMEWAIT)
+ if (inpb->inp_flags & INP_TIMEWAIT)
continue;
INP_WLOCK(inpb);
if ((tcpb = intotcpcb(inpb)) != NULL) {
@@ -929,7 +941,7 @@ tcp_drain(void)
!= NULL) {
LIST_REMOVE(te, tqe_q);
m_freem(te->tqe_m);
- uma_zfree(tcp_reass_zone, te);
+ uma_zfree(V_tcp_reass_zone, te);
tcpb->t_segqlen--;
V_tcp_reass_qsize--;
}
@@ -962,8 +974,8 @@ tcp_notify(struct inpcb *inp, int error)
INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
- if ((inp->inp_vflag & INP_TIMEWAIT) ||
- (inp->inp_vflag & INP_DROPPED))
+ if ((inp->inp_flags & INP_TIMEWAIT) ||
+ (inp->inp_flags & INP_DROPPED))
return (inp);
tp = intotcpcb(inp);
@@ -1063,7 +1075,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
* TCP state changes, is not quite right, but for
* now, better than nothing.
*/
- if (inp->inp_vflag & INP_TIMEWAIT) {
+ if (inp->inp_flags & INP_TIMEWAIT) {
if (intotw(inp) != NULL)
error = cr_cansee(req->td->td_ucred,
intotw(inp)->tw_cred);
@@ -1094,7 +1106,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS)
inp_ppcb = inp->inp_ppcb;
if (inp_ppcb == NULL)
bzero((char *) &xt.xt_tp, sizeof xt.xt_tp);
- else if (inp->inp_vflag & INP_TIMEWAIT) {
+ else if (inp->inp_flags & INP_TIMEWAIT) {
bzero((char *) &xt.xt_tp, sizeof xt.xt_tp);
xt.xt_tp.t_state = TCPS_TIME_WAIT;
} else
@@ -1293,8 +1305,8 @@ tcp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
ip->ip_src, th->th_sport, 0, NULL);
if (inp != NULL) {
INP_WLOCK(inp);
- if (!(inp->inp_vflag & INP_TIMEWAIT) &&
- !(inp->inp_vflag & INP_DROPPED) &&
+ if (!(inp->inp_flags & INP_TIMEWAIT) &&
+ !(inp->inp_flags & INP_DROPPED) &&
!(inp->inp_socket == NULL)) {
icmp_tcp_seq = htonl(th->th_seq);
tp = intotcpcb(inp);
@@ -1546,8 +1558,8 @@ tcp_isn_tick(void *xtp)
VNET_ITERATOR_DECL(vnet_iter);
u_int32_t projected_offset;
- ISN_LOCK();
VNET_LIST_RLOCK();
+ ISN_LOCK();
VNET_FOREACH(vnet_iter) {
CURVNET_SET(vnet_iter); /* XXX appease INVARIANTS */
INIT_VNET_INET(curvnet);
@@ -1560,9 +1572,9 @@ tcp_isn_tick(void *xtp)
V_isn_offset_old = V_isn_offset;
CURVNET_RESTORE();
}
+ ISN_UNLOCK();
VNET_LIST_RUNLOCK();
callout_reset(&isn_callout, hz/100, tcp_isn_tick, NULL);
- ISN_UNLOCK();
}
/*
@@ -1581,8 +1593,8 @@ tcp_drop_syn_sent(struct inpcb *inp, int errno)
INP_INFO_WLOCK_ASSERT(&V_tcbinfo);
INP_WLOCK_ASSERT(inp);
- if ((inp->inp_vflag & INP_TIMEWAIT) ||
- (inp->inp_vflag & INP_DROPPED))
+ if ((inp->inp_flags & INP_TIMEWAIT) ||
+ (inp->inp_flags & INP_DROPPED))
return (inp);
tp = intotcpcb(inp);
@@ -1610,8 +1622,8 @@ tcp_mtudisc(struct inpcb *inp, int errno)
struct socket *so;
INP_WLOCK_ASSERT(inp);
- if ((inp->inp_vflag & INP_TIMEWAIT) ||
- (inp->inp_vflag & INP_DROPPED))
+ if ((inp->inp_flags & INP_TIMEWAIT) ||
+ (inp->inp_flags & INP_DROPPED))
return (inp);
tp = intotcpcb(inp);
@@ -1626,7 +1638,7 @@ tcp_mtudisc(struct inpcb *inp, int errno)
tp->t_maxseg = so->so_snd.sb_hiwat;
SOCKBUF_UNLOCK(&so->so_snd);
- V_tcpstat.tcps_mturesent++;
+ TCPSTAT_INC(tcps_mturesent);
tp->t_rtttime = 0;
tp->snd_nxt = tp->snd_una;
tcp_free_sackholes(tp);
@@ -2114,7 +2126,6 @@ sysctl_drop(SYSCTL_HANDLER_ARGS)
struct sockaddr_in *fin, *lin;
#ifdef INET6
struct sockaddr_in6 *fin6, *lin6;
- struct in6_addr f6, l6;
#endif
int error;
@@ -2174,8 +2185,9 @@ sysctl_drop(SYSCTL_HANDLER_ARGS)
switch (addrs[0].ss_family) {
#ifdef INET6
case AF_INET6:
- inp = in6_pcblookup_hash(&V_tcbinfo, &f6, fin6->sin6_port,
- &l6, lin6->sin6_port, 0, NULL);
+ inp = in6_pcblookup_hash(&V_tcbinfo, &fin6->sin6_addr,
+ fin6->sin6_port, &lin6->sin6_addr, lin6->sin6_port, 0,
+ NULL);
break;
#endif
case AF_INET:
@@ -2185,7 +2197,7 @@ sysctl_drop(SYSCTL_HANDLER_ARGS)
}
if (inp != NULL) {
INP_WLOCK(inp);
- if (inp->inp_vflag & INP_TIMEWAIT) {
+ if (inp->inp_flags & INP_TIMEWAIT) {
/*
* XXXRW: There currently exists a state where an
* inpcb is present, but its timewait state has been
@@ -2197,7 +2209,7 @@ sysctl_drop(SYSCTL_HANDLER_ARGS)
tcp_twclose(tw, 0);
else
INP_WUNLOCK(inp);
- } else if (!(inp->inp_vflag & INP_DROPPED) &&
+ } else if (!(inp->inp_flags & INP_DROPPED) &&
!(inp->inp_socket->so_options & SO_ACCEPTCONN)) {
tp = intotcpcb(inp);
tp = tcp_drop(tp, ECONNABORTED);
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 9faca96..18f3fb4 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -294,7 +294,7 @@ syncache_insert(struct syncache *sc, struct syncache_head *sch)
("sch->sch_length incorrect"));
sc2 = TAILQ_LAST(&sch->sch_bucket, sch_head);
syncache_drop(sc2, sch);
- V_tcpstat.tcps_sc_bucketoverflow++;
+ TCPSTAT_INC(tcps_sc_bucketoverflow);
}
/* Put it into the bucket. */
@@ -309,7 +309,7 @@ syncache_insert(struct syncache *sc, struct syncache_head *sch)
SCH_UNLOCK(sch);
V_tcp_syncache.cache_count++;
- V_tcpstat.tcps_sc_added++;
+ TCPSTAT_INC(tcps_sc_added);
}
/*
@@ -398,7 +398,7 @@ syncache_timer(void *xsch)
free(s, M_TCPLOG);
}
syncache_drop(sc, sch);
- V_tcpstat.tcps_sc_stale++;
+ TCPSTAT_INC(tcps_sc_stale);
continue;
}
if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) {
@@ -409,7 +409,7 @@ syncache_timer(void *xsch)
}
(void) syncache_respond(sc);
- V_tcpstat.tcps_sc_retransmitted++;
+ TCPSTAT_INC(tcps_sc_retransmitted);
syncache_timeout(sc, sch, 0);
}
if (!TAILQ_EMPTY(&(sch)->sch_bucket))
@@ -489,7 +489,7 @@ syncache_chkrst(struct in_conninfo *inc, struct tcphdr *th)
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
log(LOG_DEBUG, "%s; %s: Spurious RST with ACK, SYN or "
"FIN flag set, segment ignored\n", s, __func__);
- V_tcpstat.tcps_badrst++;
+ TCPSTAT_INC(tcps_badrst);
goto done;
}
@@ -506,7 +506,7 @@ syncache_chkrst(struct in_conninfo *inc, struct tcphdr *th)
log(LOG_DEBUG, "%s; %s: Spurious RST without matching "
"syncache entry (possibly syncookie only), "
"segment ignored\n", s, __func__);
- V_tcpstat.tcps_badrst++;
+ TCPSTAT_INC(tcps_badrst);
goto done;
}
@@ -530,13 +530,13 @@ syncache_chkrst(struct in_conninfo *inc, struct tcphdr *th)
log(LOG_DEBUG, "%s; %s: Our SYN|ACK was rejected, "
"connection attempt aborted by remote endpoint\n",
s, __func__);
- V_tcpstat.tcps_sc_reset++;
+ TCPSTAT_INC(tcps_sc_reset);
} else {
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
log(LOG_DEBUG, "%s; %s: RST with invalid SEQ %u != "
"IRS %u (+WND %u), segment ignored\n",
s, __func__, th->th_seq, sc->sc_irs, sc->sc_wnd);
- V_tcpstat.tcps_badrst++;
+ TCPSTAT_INC(tcps_badrst);
}
done:
@@ -556,7 +556,7 @@ syncache_badack(struct in_conninfo *inc)
SCH_LOCK_ASSERT(sch);
if (sc != NULL) {
syncache_drop(sc, sch);
- V_tcpstat.tcps_sc_badack++;
+ TCPSTAT_INC(tcps_sc_badack);
}
SCH_UNLOCK(sch);
}
@@ -590,7 +590,7 @@ syncache_unreach(struct in_conninfo *inc, struct tcphdr *th)
goto done;
}
syncache_drop(sc, sch);
- V_tcpstat.tcps_sc_unreach++;
+ TCPSTAT_INC(tcps_sc_unreach);
done:
SCH_UNLOCK(sch);
}
@@ -622,7 +622,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
* have the peer retransmit its SYN again after its
* RTO and try again.
*/
- V_tcpstat.tcps_listendrop++;
+ TCPSTAT_INC(tcps_listendrop);
if ((s = tcp_log_addrs(&sc->sc_inc, NULL, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Socket create failed "
"due to limits or memory shortage\n",
@@ -792,7 +792,7 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
INP_WUNLOCK(inp);
- V_tcpstat.tcps_accepts++;
+ TCPSTAT_INC(tcps_accepts);
return (so);
abort:
@@ -912,9 +912,9 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
*lsop = syncache_socket(sc, *lsop, m);
if (*lsop == NULL)
- V_tcpstat.tcps_sc_aborted++;
+ TCPSTAT_INC(tcps_sc_aborted);
else
- V_tcpstat.tcps_sc_completed++;
+ TCPSTAT_INC(tcps_sc_completed);
/* how do we find the inp for the new socket? */
if (sc != &scs)
@@ -1046,7 +1046,7 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
sc->sc_tu->tu_syncache_event(TOE_SC_ENTRY_PRESENT,
sc->sc_toepcb);
#endif
- V_tcpstat.tcps_sc_dupsyn++;
+ TCPSTAT_INC(tcps_sc_dupsyn);
if (ipopts) {
/*
* If we were remembering a previous source route,
@@ -1081,8 +1081,8 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
if (!TOEPCB_ISSET(sc) && syncache_respond(sc) == 0) {
sc->sc_rxmits = 0;
syncache_timeout(sc, sch, 1);
- V_tcpstat.tcps_sndacks++;
- V_tcpstat.tcps_sndtotal++;
+ TCPSTAT_INC(tcps_sndacks);
+ TCPSTAT_INC(tcps_sndtotal);
}
SCH_UNLOCK(sch);
goto done;
@@ -1095,7 +1095,7 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* Treat this as if the cache was full; drop the oldest
* entry and insert the new one.
*/
- V_tcpstat.tcps_sc_zonefail++;
+ TCPSTAT_INC(tcps_sc_zonefail);
if ((sc = TAILQ_LAST(&sch->sch_bucket, sch_head)) != NULL)
syncache_drop(sc, sch);
sc = uma_zalloc(V_tcp_syncache.zone, M_NOWAIT | M_ZERO);
@@ -1233,12 +1233,12 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
syncache_free(sc);
else if (sc != &scs)
syncache_insert(sc, sch); /* locks and unlocks sch */
- V_tcpstat.tcps_sndacks++;
- V_tcpstat.tcps_sndtotal++;
+ TCPSTAT_INC(tcps_sndacks);
+ TCPSTAT_INC(tcps_sndtotal);
} else {
if (sc != &scs)
syncache_free(sc);
- V_tcpstat.tcps_sc_dropped++;
+ TCPSTAT_INC(tcps_sc_dropped);
}
done:
@@ -1351,7 +1351,7 @@ syncache_respond(struct syncache *sc)
if (sc->sc_flags & SCF_ECN) {
th->th_flags |= TH_ECE;
- V_tcpstat.tcps_ecn_shs++;
+ TCPSTAT_INC(tcps_ecn_shs);
}
/* Tack on the TCP options. */
@@ -1584,7 +1584,7 @@ syncookie_generate(struct syncache_head *sch, struct syncache *sc,
sc->sc_tsoff = data - ticks; /* after XOR */
}
- V_tcpstat.tcps_sc_sendcookie++;
+ TCPSTAT_INC(tcps_sc_sendcookie);
}
static struct syncache *
@@ -1687,7 +1687,7 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
sc->sc_rxmits = 0;
sc->sc_peer_mss = tcp_sc_msstab[mss];
- V_tcpstat.tcps_sc_recvcookie++;
+ TCPSTAT_INC(tcps_sc_recvcookie);
return (sc);
}
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index 6963d9c..67fc23f 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -182,7 +182,7 @@ tcp_timer_delack(void *xtp)
}
INP_WLOCK(inp);
INP_INFO_RUNLOCK(&V_tcbinfo);
- if ((inp->inp_vflag & INP_DROPPED) || callout_pending(&tp->t_timers->tt_delack)
+ if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_delack)
|| !callout_active(&tp->t_timers->tt_delack)) {
INP_WUNLOCK(inp);
CURVNET_RESTORE();
@@ -191,7 +191,7 @@ tcp_timer_delack(void *xtp)
callout_deactivate(&tp->t_timers->tt_delack);
tp->t_flags |= TF_ACKNOW;
- V_tcpstat.tcps_delack++;
+ TCPSTAT_INC(tcps_delack);
(void) tcp_output(tp);
INP_WUNLOCK(inp);
CURVNET_RESTORE();
@@ -229,7 +229,7 @@ tcp_timer_2msl(void *xtp)
}
INP_WLOCK(inp);
tcp_free_sackholes(tp);
- if ((inp->inp_vflag & INP_DROPPED) || callout_pending(&tp->t_timers->tt_2msl) ||
+ if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_2msl) ||
!callout_active(&tp->t_timers->tt_2msl)) {
INP_WUNLOCK(tp->t_inpcb);
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -250,7 +250,7 @@ tcp_timer_2msl(void *xtp)
if (tcp_fast_finwait2_recycle && tp->t_state == TCPS_FIN_WAIT_2 &&
tp->t_inpcb && tp->t_inpcb->inp_socket &&
(tp->t_inpcb->inp_socket->so_rcv.sb_state & SBS_CANTRCVMORE)) {
- V_tcpstat.tcps_finwait2_drops++;
+ TCPSTAT_INC(tcps_finwait2_drops);
tp = tcp_close(tp);
} else {
if (tp->t_state != TCPS_TIME_WAIT &&
@@ -301,7 +301,7 @@ tcp_timer_keep(void *xtp)
return;
}
INP_WLOCK(inp);
- if ((inp->inp_vflag & INP_DROPPED) || callout_pending(&tp->t_timers->tt_keep)
+ if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_keep)
|| !callout_active(&tp->t_timers->tt_keep)) {
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -313,7 +313,7 @@ tcp_timer_keep(void *xtp)
* Keep-alive timer went off; send something
* or drop connection if idle for too long.
*/
- V_tcpstat.tcps_keeptimeo++;
+ TCPSTAT_INC(tcps_keeptimeo);
if (tp->t_state < TCPS_ESTABLISHED)
goto dropit;
if ((always_keepalive || inp->inp_socket->so_options & SO_KEEPALIVE) &&
@@ -332,7 +332,7 @@ tcp_timer_keep(void *xtp)
* by the protocol spec, this requires the
* correspondent TCP to respond.
*/
- V_tcpstat.tcps_keepprobe++;
+ TCPSTAT_INC(tcps_keepprobe);
t_template = tcpip_maketemplate(inp);
if (t_template) {
tcp_respond(tp, t_template->tt_ipgen,
@@ -355,7 +355,7 @@ tcp_timer_keep(void *xtp)
return;
dropit:
- V_tcpstat.tcps_keepdrops++;
+ TCPSTAT_INC(tcps_keepdrops);
tp = tcp_drop(tp, ETIMEDOUT);
#ifdef TCPDEBUG
@@ -397,7 +397,7 @@ tcp_timer_persist(void *xtp)
return;
}
INP_WLOCK(inp);
- if ((inp->inp_vflag & INP_DROPPED) || callout_pending(&tp->t_timers->tt_persist)
+ if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_persist)
|| !callout_active(&tp->t_timers->tt_persist)) {
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -409,7 +409,7 @@ tcp_timer_persist(void *xtp)
* Persistance timer into zero window.
* Force a byte to be output, if possible.
*/
- V_tcpstat.tcps_persisttimeo++;
+ TCPSTAT_INC(tcps_persisttimeo);
/*
* Hack: if the peer is dead/unreachable, we do not
* time out if the window is closed. After a full
@@ -420,7 +420,7 @@ tcp_timer_persist(void *xtp)
if (tp->t_rxtshift == TCP_MAXRXTSHIFT &&
((ticks - tp->t_rcvtime) >= tcp_maxpersistidle ||
(ticks - tp->t_rcvtime) >= TCP_REXMTVAL(tp) * tcp_totbackoff)) {
- V_tcpstat.tcps_persistdrop++;
+ TCPSTAT_INC(tcps_persistdrop);
tp = tcp_drop(tp, ETIMEDOUT);
goto out;
}
@@ -471,7 +471,7 @@ tcp_timer_rexmt(void * xtp)
return;
}
INP_WLOCK(inp);
- if ((inp->inp_vflag & INP_DROPPED) || callout_pending(&tp->t_timers->tt_rexmt)
+ if ((inp->inp_flags & INP_DROPPED) || callout_pending(&tp->t_timers->tt_rexmt)
|| !callout_active(&tp->t_timers->tt_rexmt)) {
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -487,7 +487,7 @@ tcp_timer_rexmt(void * xtp)
*/
if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
tp->t_rxtshift = TCP_MAXRXTSHIFT;
- V_tcpstat.tcps_timeoutdrop++;
+ TCPSTAT_INC(tcps_timeoutdrop);
tp = tcp_drop(tp, tp->t_softerror ?
tp->t_softerror : ETIMEDOUT);
goto out;
@@ -513,7 +513,7 @@ tcp_timer_rexmt(void * xtp)
tp->t_flags &= ~TF_WASFRECOVERY;
tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1));
}
- V_tcpstat.tcps_rexmttimeo++;
+ TCPSTAT_INC(tcps_rexmttimeo);
if (tp->t_state == TCPS_SYN_SENT)
rexmt = TCP_REXMTVAL(tp) * tcp_syn_backoff[tp->t_rxtshift];
else
diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c
index cc3170c..839b25d 100644
--- a/sys/netinet/tcp_timewait.c
+++ b/sys/netinet/tcp_timewait.c
@@ -94,7 +94,6 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
-static uma_zone_t tcptw_zone;
static int maxtcptw;
/*
@@ -104,6 +103,7 @@ static int maxtcptw;
* tcbinfo lock, which must be held over queue iteration and modification.
*/
#ifdef VIMAGE_GLOBALS
+static uma_zone_t tcptw_zone;
static TAILQ_HEAD(, tcptw) twq_2msl;
int nolocaltimewait;
#endif
@@ -142,7 +142,7 @@ sysctl_maxtcptw(SYSCTL_HANDLER_ARGS)
if (error == 0 && req->newptr)
if (new >= 32) {
maxtcptw = new;
- uma_zone_set_max(tcptw_zone, maxtcptw);
+ uma_zone_set_max(V_tcptw_zone, maxtcptw);
}
return (error);
}
@@ -160,7 +160,7 @@ tcp_tw_zone_change(void)
{
if (maxtcptw == 0)
- uma_zone_set_max(tcptw_zone, tcptw_auto_size());
+ uma_zone_set_max(V_tcptw_zone, tcptw_auto_size());
}
void
@@ -168,13 +168,13 @@ tcp_tw_init(void)
{
INIT_VNET_INET(curvnet);
- tcptw_zone = uma_zcreate("tcptw", sizeof(struct tcptw),
+ V_tcptw_zone = uma_zcreate("tcptw", sizeof(struct tcptw),
NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
TUNABLE_INT_FETCH("net.inet.tcp.maxtcptw", &maxtcptw);
if (maxtcptw == 0)
- uma_zone_set_max(tcptw_zone, tcptw_auto_size());
+ uma_zone_set_max(V_tcptw_zone, tcptw_auto_size());
else
- uma_zone_set_max(tcptw_zone, maxtcptw);
+ uma_zone_set_max(V_tcptw_zone, maxtcptw);
TAILQ_INIT(&V_twq_2msl);
}
@@ -204,7 +204,7 @@ tcp_twstart(struct tcpcb *tp)
return;
}
- tw = uma_zalloc(tcptw_zone, M_NOWAIT);
+ tw = uma_zalloc(V_tcptw_zone, M_NOWAIT);
if (tw == NULL) {
tw = tcp_tw_2msl_scan(1);
if (tw == NULL) {
@@ -265,17 +265,17 @@ tcp_twstart(struct tcpcb *tp)
if (acknow)
tcp_twrespond(tw, TH_ACK);
inp->inp_ppcb = tw;
- inp->inp_vflag |= INP_TIMEWAIT;
+ inp->inp_flags |= INP_TIMEWAIT;
tcp_tw_2msl_reset(tw, 0);
/*
* If the inpcb owns the sole reference to the socket, then we can
* detach and free the socket as it is not needed in time wait.
*/
- if (inp->inp_vflag & INP_SOCKREF) {
+ if (inp->inp_flags & INP_SOCKREF) {
KASSERT(so->so_state & SS_PROTOREF,
("tcp_twstart: !SS_PROTOREF"));
- inp->inp_vflag &= ~INP_SOCKREF;
+ inp->inp_flags &= ~INP_SOCKREF;
INP_WUNLOCK(inp);
ACCEPT_LOCK();
SOCK_LOCK(so);
@@ -435,7 +435,7 @@ tcp_twclose(struct tcptw *tw, int reuse)
* notify the socket layer.
*/
inp = tw->tw_inpcb;
- KASSERT((inp->inp_vflag & INP_TIMEWAIT), ("tcp_twclose: !timewait"));
+ KASSERT((inp->inp_flags & INP_TIMEWAIT), ("tcp_twclose: !timewait"));
KASSERT(intotw(inp) == tw, ("tcp_twclose: inp_ppcb != tw"));
INP_INFO_WLOCK_ASSERT(&V_tcbinfo); /* tcp_tw_2msl_stop(). */
INP_WLOCK_ASSERT(inp);
@@ -453,8 +453,8 @@ tcp_twclose(struct tcptw *tw, int reuse)
* in which case another reference exists (XXXRW: think
* about this more), and we don't need to take action.
*/
- if (inp->inp_vflag & INP_SOCKREF) {
- inp->inp_vflag &= ~INP_SOCKREF;
+ if (inp->inp_flags & INP_SOCKREF) {
+ inp->inp_flags &= ~INP_SOCKREF;
INP_WUNLOCK(inp);
ACCEPT_LOCK();
SOCK_LOCK(so);
@@ -472,12 +472,12 @@ tcp_twclose(struct tcptw *tw, int reuse)
}
} else
in_pcbfree(inp);
- V_tcpstat.tcps_closed++;
+ TCPSTAT_INC(tcps_closed);
crfree(tw->tw_cred);
tw->tw_cred = NULL;
if (reuse)
return;
- uma_zfree(tcptw_zone, tw);
+ uma_zfree(V_tcptw_zone, tw);
}
int
@@ -567,10 +567,10 @@ tcp_twrespond(struct tcptw *tw, int flags)
NULL, inp);
}
if (flags & TH_ACK)
- V_tcpstat.tcps_sndacks++;
+ TCPSTAT_INC(tcps_sndacks);
else
- V_tcpstat.tcps_sndctrl++;
- V_tcpstat.tcps_sndtotal++;
+ TCPSTAT_INC(tcps_sndctrl);
+ TCPSTAT_INC(tcps_sndtotal);
return (error);
}
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index 05e22be..089ef1f 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -169,7 +169,7 @@ tcp_detach(struct socket *so, struct inpcb *inp)
tp = intotcpcb(inp);
- if (inp->inp_vflag & INP_TIMEWAIT) {
+ if (inp->inp_flags & INP_TIMEWAIT) {
/*
* There are two cases to handle: one in which the time wait
* state is being discarded (INP_DROPPED), and one in which
@@ -182,7 +182,7 @@ tcp_detach(struct socket *so, struct inpcb *inp)
*
* XXXRW: Would it be cleaner to free the tcptw here?
*/
- if (inp->inp_vflag & INP_DROPPED) {
+ if (inp->inp_flags & INP_DROPPED) {
KASSERT(tp == NULL, ("tcp_detach: INP_TIMEWAIT && "
"INP_DROPPED && tp != NULL"));
in_pcbdetach(inp);
@@ -201,7 +201,7 @@ tcp_detach(struct socket *so, struct inpcb *inp)
*
* XXXRW: Does the second case still occur?
*/
- if (inp->inp_vflag & INP_DROPPED ||
+ if (inp->inp_flags & INP_DROPPED ||
tp->t_state < TCPS_SYN_SENT) {
tcp_discardcb(tp);
in_pcbdetach(inp);
@@ -262,7 +262,7 @@ tcp_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_bind: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = EINVAL;
goto out;
}
@@ -303,7 +303,7 @@ tcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp6_usr_bind: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = EINVAL;
goto out;
}
@@ -350,7 +350,7 @@ tcp_usr_listen(struct socket *so, int backlog, struct thread *td)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_listen: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = EINVAL;
goto out;
}
@@ -388,7 +388,7 @@ tcp6_usr_listen(struct socket *so, int backlog, struct thread *td)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp6_usr_listen: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = EINVAL;
goto out;
}
@@ -449,7 +449,7 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_connect: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = EINVAL;
goto out;
}
@@ -491,7 +491,7 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp6_usr_connect: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = EINVAL;
goto out;
}
@@ -557,7 +557,7 @@ tcp_usr_disconnect(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_disconnect: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = ECONNRESET;
goto out;
}
@@ -594,7 +594,7 @@ tcp_usr_accept(struct socket *so, struct sockaddr **nam)
KASSERT(inp != NULL, ("tcp_usr_accept: inp == NULL"));
INP_INFO_RLOCK(&V_tcbinfo);
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = ECONNABORTED;
goto out;
}
@@ -637,7 +637,7 @@ tcp6_usr_accept(struct socket *so, struct sockaddr **nam)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp6_usr_accept: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = ECONNABORTED;
goto out;
}
@@ -687,7 +687,7 @@ tcp_usr_shutdown(struct socket *so)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = ECONNRESET;
goto out;
}
@@ -695,7 +695,7 @@ tcp_usr_shutdown(struct socket *so)
TCPDEBUG1();
socantsendmore(so);
tcp_usrclosed(tp);
- if (!(inp->inp_vflag & INP_DROPPED))
+ if (!(inp->inp_flags & INP_DROPPED))
error = tcp_output_disconnect(tp);
out:
@@ -720,7 +720,7 @@ tcp_usr_rcvd(struct socket *so, int flags)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_rcvd: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = ECONNRESET;
goto out;
}
@@ -771,7 +771,7 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_send: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
if (control)
m_freem(control);
if (m)
@@ -829,7 +829,7 @@ tcp_usr_send(struct socket *so, int flags, struct mbuf *m,
INP_INFO_WUNLOCK(&V_tcbinfo);
headlocked = 0;
}
- if (!(inp->inp_vflag & INP_DROPPED)) {
+ if (!(inp->inp_flags & INP_DROPPED)) {
if (flags & PRUS_MORETOCOME)
tp->t_flags |= TF_MORETOCOME;
error = tcp_output_send(tp);
@@ -917,18 +917,18 @@ tcp_usr_abort(struct socket *so)
/*
* If we still have full TCP state, and we're not dropped, drop.
*/
- if (!(inp->inp_vflag & INP_TIMEWAIT) &&
- !(inp->inp_vflag & INP_DROPPED)) {
+ if (!(inp->inp_flags & INP_TIMEWAIT) &&
+ !(inp->inp_flags & INP_DROPPED)) {
tp = intotcpcb(inp);
TCPDEBUG1();
tcp_drop(tp, ECONNABORTED);
TCPDEBUG2(PRU_ABORT);
}
- if (!(inp->inp_vflag & INP_DROPPED)) {
+ if (!(inp->inp_flags & INP_DROPPED)) {
SOCK_LOCK(so);
so->so_state |= SS_PROTOREF;
SOCK_UNLOCK(so);
- inp->inp_vflag |= INP_SOCKREF;
+ inp->inp_flags |= INP_SOCKREF;
}
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -957,18 +957,18 @@ tcp_usr_close(struct socket *so)
* If we still have full TCP state, and we're not dropped, initiate
* a disconnect.
*/
- if (!(inp->inp_vflag & INP_TIMEWAIT) &&
- !(inp->inp_vflag & INP_DROPPED)) {
+ if (!(inp->inp_flags & INP_TIMEWAIT) &&
+ !(inp->inp_flags & INP_DROPPED)) {
tp = intotcpcb(inp);
TCPDEBUG1();
tcp_disconnect(tp);
TCPDEBUG2(PRU_CLOSE);
}
- if (!(inp->inp_vflag & INP_DROPPED)) {
+ if (!(inp->inp_flags & INP_DROPPED)) {
SOCK_LOCK(so);
so->so_state |= SS_PROTOREF;
SOCK_UNLOCK(so);
- inp->inp_vflag |= INP_SOCKREF;
+ inp->inp_flags |= INP_SOCKREF;
}
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_tcbinfo);
@@ -988,7 +988,7 @@ tcp_usr_rcvoob(struct socket *so, struct mbuf *m, int flags)
inp = sotoinpcb(so);
KASSERT(inp != NULL, ("tcp_usr_rcvoob: inp == NULL"));
INP_WLOCK(inp);
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
error = ECONNRESET;
goto out;
}
@@ -1113,7 +1113,7 @@ tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
tp->request_r_scale++;
soisconnecting(so);
- V_tcpstat.tcps_connattempt++;
+ TCPSTAT_INC(tcps_connattempt);
tp->t_state = TCPS_SYN_SENT;
tcp_timer_activate(tp, TT_KEEP, tcp_keepinit);
tp->iss = tcp_new_isn(tp);
@@ -1173,11 +1173,11 @@ tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td)
/* Compute window scaling to request. */
while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
- (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat)
+ (TCP_MAXWIN << tp->request_r_scale) < sb_max)
tp->request_r_scale++;
soisconnecting(so);
- V_tcpstat.tcps_connattempt++;
+ TCPSTAT_INC(tcps_connattempt);
tp->t_state = TCPS_SYN_SENT;
tcp_timer_activate(tp, TT_KEEP, tcp_keepinit);
tp->iss = tcp_new_isn(tp);
@@ -1241,7 +1241,7 @@ tcp_fill_info(struct tcpcb *tp, struct tcp_info *ti)
*/
#define INP_WLOCK_RECHECK(inp) do { \
INP_WLOCK(inp); \
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { \
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) { \
INP_WUNLOCK(inp); \
return (ECONNRESET); \
} \
@@ -1275,7 +1275,7 @@ tcp_ctloutput(struct socket *so, struct sockopt *sopt)
#endif
return (error);
}
- if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) {
+ if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
INP_WUNLOCK(inp);
return (ECONNRESET);
}
@@ -1515,7 +1515,7 @@ tcp_disconnect(struct tcpcb *tp)
soisdisconnecting(so);
sbflush(&so->so_rcv);
tcp_usrclosed(tp);
- if (!(inp->inp_vflag & INP_DROPPED))
+ if (!(inp->inp_flags & INP_DROPPED))
tcp_output_disconnect(tp);
}
}
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index c52506e..268db7c 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -458,6 +458,11 @@ struct tcpstat {
u_long tcps_ecn_rcwnd; /* # times ECN reduced the cwnd */
};
+#ifdef _KERNEL
+#define TCPSTAT_ADD(name, val) V_tcpstat.name += (val)
+#define TCPSTAT_INC(name) TCPSTAT_ADD(name, 1)
+#endif
+
/*
* TCB structure exported to user-land via sysctl(3).
* Evil hack: declare only if in_pcb.h and sys/socketvar.h have been
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 33df73e..084b485 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -254,7 +254,7 @@ udp_append(struct inpcb *inp, struct ip *ip, struct mbuf *n, int off,
m_freem(n);
if (opts)
m_freem(opts);
- V_udpstat.udps_fullsock++;
+ UDPSTAT_INC(udps_fullsock);
} else
sorwakeup_locked(so);
}
@@ -276,7 +276,7 @@ udp_input(struct mbuf *m, int off)
#endif
ifp = m->m_pkthdr.rcvif;
- V_udpstat.udps_ipackets++;
+ UDPSTAT_INC(udps_ipackets);
/*
* Strip IP options, if any; should skip this, make available to
@@ -294,7 +294,7 @@ udp_input(struct mbuf *m, int off)
ip = mtod(m, struct ip *);
if (m->m_len < iphlen + sizeof(struct udphdr)) {
if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
- V_udpstat.udps_hdrops++;
+ UDPSTAT_INC(udps_hdrops);
return;
}
ip = mtod(m, struct ip *);
@@ -324,7 +324,7 @@ udp_input(struct mbuf *m, int off)
len = ntohs((u_short)uh->uh_ulen);
if (ip->ip_len != len) {
if (len > ip->ip_len || len < sizeof(struct udphdr)) {
- V_udpstat.udps_badlen++;
+ UDPSTAT_INC(udps_badlen);
goto badunlocked;
}
m_adj(m, len - ip->ip_len);
@@ -364,12 +364,12 @@ udp_input(struct mbuf *m, int off)
bcopy(b, ((struct ipovly *)ip)->ih_x1, 9);
}
if (uh_sum) {
- V_udpstat.udps_badsum++;
+ UDPSTAT_INC(udps_badsum);
m_freem(m);
return;
}
} else
- V_udpstat.udps_nosum++;
+ UDPSTAT_INC(udps_nosum);
#ifdef IPFIREWALL_FORWARD
/*
@@ -439,10 +439,10 @@ udp_input(struct mbuf *m, int off)
(struct sockaddr *)&udp_in);
if (blocked != MCAST_PASS) {
if (blocked == MCAST_NOTGMEMBER)
- V_ipstat.ips_notmember++;
+ IPSTAT_INC(ips_notmember);
if (blocked == MCAST_NOTSMEMBER ||
blocked == MCAST_MUTED)
- V_udpstat.udps_filtermcast++;
+ UDPSTAT_INC(udps_filtermcast);
INP_RUNLOCK(inp);
continue;
}
@@ -494,7 +494,7 @@ udp_input(struct mbuf *m, int off)
* to send an ICMP Port Unreachable for a broadcast
* or multicast datgram.)
*/
- V_udpstat.udps_noportbcast++;
+ UDPSTAT_INC(udps_noportbcast);
goto badheadlocked;
}
if (last->inp_ppcb == NULL) {
@@ -531,9 +531,9 @@ udp_input(struct mbuf *m, int off)
buf, ntohs(uh->uh_dport), inet_ntoa(ip->ip_src),
ntohs(uh->uh_sport));
}
- V_udpstat.udps_noport++;
+ UDPSTAT_INC(udps_noport);
if (m->m_flags & (M_BCAST | M_MCAST)) {
- V_udpstat.udps_noportbcast++;
+ UDPSTAT_INC(udps_noportbcast);
goto badheadlocked;
}
if (V_udp_blackhole)
@@ -1072,7 +1072,7 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
((struct ip *)ui)->ip_ttl = inp->inp_ip_ttl; /* XXX */
((struct ip *)ui)->ip_tos = inp->inp_ip_tos; /* XXX */
- V_udpstat.udps_opackets++;
+ UDPSTAT_INC(udps_opackets);
if (unlock_udbinfo == 2)
INP_INFO_WUNLOCK(&V_udbinfo);
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index 76a31b8..d83f705 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -71,6 +71,11 @@ struct udpstat {
u_long udps_filtermcast; /* blocked by multicast filter */
};
+#ifdef _KERNEL
+#define UDPSTAT_ADD(name, val) V_udpstat.name += (val)
+#define UDPSTAT_INC(name) UDPSTAT_ADD(name, 1)
+#endif
+
/*
* Names for UDP sysctl objects.
*/
diff --git a/sys/netinet/vinet.h b/sys/netinet/vinet.h
index e5b0bab..b65acc1 100644
--- a/sys/netinet/vinet.h
+++ b/sys/netinet/vinet.h
@@ -86,6 +86,11 @@ struct vnet_inet {
struct tcp_hostcache _tcp_hostcache;
struct callout _tcp_hc_callout;
+ uma_zone_t _tcp_reass_zone;
+ uma_zone_t _tcpcb_zone;
+ uma_zone_t _tcptw_zone;
+ uma_zone_t _sack_hole_zone;
+
struct tcp_syncache _tcp_syncache;
int _tcp_syncookies;
int _tcp_syncookiesonly;
@@ -315,12 +320,15 @@ extern struct vnet_inet vnet_inet_0;
#define V_rtq_timeout VNET_INET(rtq_timeout)
#define V_rtq_timer VNET_INET(rtq_timer)
#define V_rtq_toomany VNET_INET(rtq_toomany)
+#define V_sack_hole_zone VNET_INET(sack_hole_zone)
#define V_sameprefixcarponly VNET_INET(sameprefixcarponly)
#define V_ss_fltsz VNET_INET(ss_fltsz)
#define V_ss_fltsz_local VNET_INET(ss_fltsz_local)
#define V_subnetsarelocal VNET_INET(subnetsarelocal)
#define V_tcb VNET_INET(tcb)
#define V_tcbinfo VNET_INET(tcbinfo)
+#define V_tcpcb_zone VNET_INET(tcpcb_zone)
+#define V_tcptw_zone VNET_INET(tcptw_zone)
#define V_tcp_abc_l_var VNET_INET(tcp_abc_l_var)
#define V_tcp_autorcvbuf_inc VNET_INET(tcp_autorcvbuf_inc)
#define V_tcp_autorcvbuf_max VNET_INET(tcp_autorcvbuf_max)
@@ -353,6 +361,7 @@ extern struct vnet_inet vnet_inet_0;
#define V_tcp_reass_maxseg VNET_INET(tcp_reass_maxseg)
#define V_tcp_reass_overflows VNET_INET(tcp_reass_overflows)
#define V_tcp_reass_qsize VNET_INET(tcp_reass_qsize)
+#define V_tcp_reass_zone VNET_INET(tcp_reass_zone)
#define V_tcp_sack_globalholes VNET_INET(tcp_sack_globalholes)
#define V_tcp_sack_globalmaxholes VNET_INET(tcp_sack_globalmaxholes)
#define V_tcp_sack_maxholes VNET_INET(tcp_sack_maxholes)
diff --git a/sys/netinet6/frag6.c b/sys/netinet6/frag6.c
index e2eda6f..d0f333d 100644
--- a/sys/netinet6/frag6.c
+++ b/sys/netinet6/frag6.c
@@ -109,14 +109,16 @@ frag6_init(void)
{
INIT_VNET_INET6(curvnet);
+ V_ip6q.ip6q_next = V_ip6q.ip6q_prev = &V_ip6q;
V_ip6_maxfragpackets = nmbclusters / 4;
V_ip6_maxfrags = nmbclusters / 4;
- EVENTHANDLER_REGISTER(nmbclusters_change,
- frag6_change, NULL, EVENTHANDLER_PRI_ANY);
- IP6Q_LOCK_INIT();
+ if (!IS_DEFAULT_VNET(curvnet))
+ return;
- V_ip6q.ip6q_next = V_ip6q.ip6q_prev = &V_ip6q;
+ IP6Q_LOCK_INIT();
+ EVENTHANDLER_REGISTER(nmbclusters_change,
+ frag6_change, NULL, EVENTHANDLER_PRI_ANY);
}
/*
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
index 27159db..277e313 100644
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -254,14 +254,14 @@ icmp6_error(struct mbuf *m, int type, int code, int param)
int off;
int nxt;
- V_icmp6stat.icp6s_error++;
+ ICMP6STAT_INC(icp6s_error);
/* count per-type-code statistics */
icmp6_errcount(&V_icmp6stat.icp6s_outerrhist, type, code);
#ifdef M_DECRYPTED /*not openbsd*/
if (m->m_flags & M_DECRYPTED) {
- V_icmp6stat.icp6s_canterror++;
+ ICMP6STAT_INC(icp6s_canterror);
goto freeit;
}
#endif
@@ -319,7 +319,7 @@ icmp6_error(struct mbuf *m, int type, int code, int param)
IP6_EXTHDR_GET(icp, struct icmp6_hdr *, m, off,
sizeof(*icp));
if (icp == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return;
}
#endif
@@ -330,7 +330,7 @@ icmp6_error(struct mbuf *m, int type, int code, int param)
* Special case: for redirect (which is
* informational) we must not send icmp6 error.
*/
- V_icmp6stat.icp6s_canterror++;
+ ICMP6STAT_INC(icp6s_canterror);
goto freeit;
} else {
/* ICMPv6 informational - send the error */
@@ -343,7 +343,7 @@ icmp6_error(struct mbuf *m, int type, int code, int param)
/* Finally, do rate limitation check. */
if (icmp6_ratelimit(&oip6->ip6_src, type, code)) {
- V_icmp6stat.icp6s_toofreq++;
+ ICMP6STAT_INC(icp6s_toofreq);
goto freeit;
}
@@ -384,7 +384,7 @@ icmp6_error(struct mbuf *m, int type, int code, int param)
*/
m->m_pkthdr.rcvif = NULL;
- V_icmp6stat.icp6s_outhist[type]++;
+ ICMP6STAT_INC(icp6s_outhist[type]);
icmp6_reflect(m, sizeof(struct ip6_hdr)); /* header order: IPv6 - ICMPv6 */
return;
@@ -424,7 +424,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
ip6 = mtod(m, struct ip6_hdr *);
if (icmp6len < sizeof(struct icmp6_hdr)) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
goto freeit;
}
@@ -436,7 +436,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
#else
IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off, sizeof(*icmp6));
if (icmp6 == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return IPPROTO_DONE;
}
#endif
@@ -447,7 +447,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
"ICMP6 checksum error(%d|%x) %s\n",
icmp6->icmp6_type, sum,
ip6_sprintf(ip6bufs, &ip6->ip6_src)));
- V_icmp6stat.icp6s_checksum++;
+ ICMP6STAT_INC(icp6s_checksum);
goto freeit;
}
@@ -467,7 +467,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
}
}
- V_icmp6stat.icp6s_inhist[icmp6->icmp6_type]++;
+ ICMP6STAT_INC(icp6s_inhist[icmp6->icmp6_type]);
icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_msg);
if (icmp6->icmp6_type < ICMP6_INFOMSG_MASK)
icmp6_ifstat_inc(m->m_pkthdr.rcvif, ifs6_in_error);
@@ -601,8 +601,8 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
nicmp6->icmp6_type = ICMP6_ECHO_REPLY;
nicmp6->icmp6_code = 0;
if (n) {
- V_icmp6stat.icp6s_reflect++;
- V_icmp6stat.icp6s_outhist[ICMP6_ECHO_REPLY]++;
+ ICMP6STAT_INC(icp6s_reflect);
+ ICMP6STAT_INC(icp6s_outhist[ICMP6_ECHO_REPLY]);
icmp6_reflect(n, noff);
}
break;
@@ -734,8 +734,8 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
}
#undef hostnamelen
if (n) {
- V_icmp6stat.icp6s_reflect++;
- V_icmp6stat.icp6s_outhist[ICMP6_WRUREPLY]++;
+ ICMP6STAT_INC(icp6s_reflect);
+ ICMP6STAT_INC(icp6s_outhist[ICMP6_WRUREPLY]);
icmp6_reflect(n, noff);
}
break;
@@ -856,11 +856,11 @@ icmp6_input(struct mbuf **mp, int *offp, int proto)
break;
badcode:
- V_icmp6stat.icp6s_badcode++;
+ ICMP6STAT_INC(icp6s_badcode);
break;
badlen:
- V_icmp6stat.icp6s_badlen++;
+ ICMP6STAT_INC(icp6s_badlen);
break;
}
@@ -885,7 +885,7 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len, int code)
struct sockaddr_in6 icmp6src, icmp6dst;
if (icmp6len < sizeof(struct icmp6_hdr) + sizeof(struct ip6_hdr)) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
goto freeit;
}
#ifndef PULLDOWN_TEST
@@ -896,7 +896,7 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len, int code)
IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
sizeof(*icmp6) + sizeof(struct ip6_hdr));
if (icmp6 == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return (-1);
}
#endif
@@ -931,7 +931,7 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len, int code)
IP6_EXTHDR_GET(eh, struct ip6_ext *, m,
eoff, sizeof(*eh));
if (eh == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return (-1);
}
#endif
@@ -959,7 +959,7 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len, int code)
IP6_EXTHDR_GET(rth, struct ip6_rthdr *, m,
eoff, sizeof(*rth));
if (rth == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return (-1);
}
#endif
@@ -985,7 +985,7 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len, int code)
struct ip6_rthdr0 *, m,
eoff, rthlen);
if (rth0 == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return (-1);
}
#endif
@@ -1007,7 +1007,7 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len, int code)
IP6_EXTHDR_GET(fh, struct ip6_frag *, m,
eoff, sizeof(*fh));
if (fh == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return (-1);
}
#endif
@@ -1042,7 +1042,7 @@ icmp6_notify_error(struct mbuf **mp, int off, int icmp6len, int code)
IP6_EXTHDR_GET(icmp6, struct icmp6_hdr *, m, off,
sizeof(*icmp6) + sizeof(struct ip6_hdr));
if (icmp6 == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return (-1);
}
#endif
@@ -1156,7 +1156,7 @@ icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated)
if (mtu < tcp_maxmtu6(&inc, NULL)) {
tcp_hc_updatemtu(&inc, mtu);
- V_icmp6stat.icp6s_pmtuchg++;
+ ICMP6STAT_INC(icp6s_pmtuchg);
}
}
@@ -2276,7 +2276,7 @@ icmp6_redirect_input(struct mbuf *m, int off)
#else
IP6_EXTHDR_GET(nd_rd, struct nd_redirect *, m, off, icmp6len);
if (nd_rd == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return;
}
#endif
@@ -2439,7 +2439,7 @@ icmp6_redirect_input(struct mbuf *m, int off)
return;
bad:
- V_icmp6stat.icp6s_badredirect++;
+ ICMP6STAT_INC(icp6s_badredirect);
m_freem(m);
}
@@ -2715,7 +2715,7 @@ noredhdropt:;
icmp6_ifstat_inc(outif, ifs6_out_msg);
icmp6_ifstat_inc(outif, ifs6_out_redirect);
}
- V_icmp6stat.icp6s_outhist[ND_REDIRECT]++;
+ ICMP6STAT_INC(icp6s_outhist[ND_REDIRECT]);
return;
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index b75ffc5..d8a11d0 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -1516,9 +1516,7 @@ in6_ifinit(struct ifnet *ifp, struct in6_ifaddr *ia,
ia->ia_addr = *sin6;
if (ifacount <= 1 && ifp->if_ioctl) {
- IFF_LOCKGIANT(ifp);
error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (caddr_t)ia);
- IFF_UNLOCKGIANT(ifp);
if (error) {
splx(s);
return (error);
diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c
index 4950549..68b3542 100644
--- a/sys/netinet6/in6_ifattach.c
+++ b/sys/netinet6/in6_ifattach.c
@@ -906,10 +906,8 @@ in6_purgemaddrs(struct ifnet *ifp)
struct in6_multi *in6m;
struct in6_multi *oin6m;
- IFF_LOCKGIANT(ifp);
LIST_FOREACH_SAFE(in6m, &in6_multihead, in6m_entry, oin6m) {
if (in6m->in6m_ifp == ifp)
in6_delmulti(in6m);
}
- IFF_UNLOCKGIANT(ifp);
}
diff --git a/sys/netinet6/in6_pcb.c b/sys/netinet6/in6_pcb.c
index 79cb213..79e79cb 100644
--- a/sys/netinet6/in6_pcb.c
+++ b/sys/netinet6/in6_pcb.c
@@ -197,7 +197,7 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
&sin6->sin6_addr, lport,
INPLOOKUP_WILDCARD, cred);
if (t &&
- ((t->inp_vflag & INP_TIMEWAIT) == 0) &&
+ ((t->inp_flags & INP_TIMEWAIT) == 0) &&
(so->so_type != SOCK_STREAM ||
IN6_IS_ADDR_UNSPECIFIED(&t->in6p_faddr)) &&
(!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
@@ -215,7 +215,7 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
sin.sin_addr, lport,
INPLOOKUP_WILDCARD, cred);
if (t &&
- ((t->inp_vflag &
+ ((t->inp_flags &
INP_TIMEWAIT) == 0) &&
(so->so_type != SOCK_STREAM ||
ntohl(t->inp_faddr.s_addr) ==
@@ -227,7 +227,7 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
}
t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
lport, wild, cred);
- if (t && (reuseport & ((t->inp_vflag & INP_TIMEWAIT) ?
+ if (t && (reuseport & ((t->inp_flags & INP_TIMEWAIT) ?
intotw(t)->tw_so_options :
t->inp_socket->so_options)) == 0)
return (EADDRINUSE);
@@ -238,7 +238,7 @@ in6_pcbbind(register struct inpcb *inp, struct sockaddr *nam,
in6_sin6_2_sin(&sin, sin6);
t = in_pcblookup_local(pcbinfo, sin.sin_addr,
lport, wild, cred);
- if (t && t->inp_vflag & INP_TIMEWAIT) {
+ if (t && t->inp_flags & INP_TIMEWAIT) {
if ((reuseport &
intotw(t)->tw_so_options) == 0 &&
(ntohl(t->inp_laddr.s_addr) !=
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index 8030416..7ae30387 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -920,8 +920,6 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred)
void
addrsel_policy_init(void)
{
- ADDRSEL_LOCK_INIT();
- ADDRSEL_SXLOCK_INIT();
INIT_VNET_INET6(curvnet);
V_ip6_prefer_tempaddr = 0;
@@ -931,6 +929,12 @@ addrsel_policy_init(void)
/* initialize the "last resort" policy */
bzero(&V_defaultaddrpolicy, sizeof(V_defaultaddrpolicy));
V_defaultaddrpolicy.label = ADDR_LABEL_NOTAPP;
+
+ if (!IS_DEFAULT_VNET(curvnet))
+ return;
+
+ ADDRSEL_LOCK_INIT();
+ ADDRSEL_SXLOCK_INIT();
}
static struct in6_addrpolicy *
diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
index f094683..27c8e89 100644
--- a/sys/netinet6/ip6_input.c
+++ b/sys/netinet6/ip6_input.c
@@ -155,6 +155,25 @@ static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *);
static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int);
#endif
+#ifndef VIMAGE_GLOBALS
+static void vnet_inet6_register(void);
+
+static const vnet_modinfo_t vnet_inet6_modinfo = {
+ .vmi_id = VNET_MOD_INET6,
+ .vmi_name = "inet6",
+ .vmi_dependson = VNET_MOD_INET /* XXX revisit - TCP/UDP needs this? */
+};
+
+static void
+vnet_inet6_register(void)
+{
+
+ vnet_mod_register(&vnet_inet6_modinfo);
+}
+
+SYSINIT(inet6, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, vnet_inet6_register, 0);
+#endif
+
/*
* IP6 initialization: fill in IP6 protocol switch table.
* All protocols not implemented in kernel go to raw IP6 protocol handler.
@@ -234,6 +253,17 @@ ip6_init(void)
/* 40 1K datagrams */
V_dad_init = 0;
+ scope6_init();
+ addrsel_policy_init();
+ nd6_init();
+ frag6_init();
+
+ V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
+
+ /* Skip global initialization stuff for non-default instances. */
+ if (!IS_DEFAULT_VNET(curvnet))
+ return;
+
#ifdef DIAGNOSTIC
if (sizeof(struct protosw) != sizeof(struct ip6protosw))
panic("sizeof(protosw) != sizeof(ip6protosw)");
@@ -265,18 +295,13 @@ ip6_init(void)
printf("%s: WARNING: unable to register pfil hook, "
"error %d\n", __func__, i);
- ip6intrq.ifq_maxlen = V_ip6qmaxlen;
+ ip6intrq.ifq_maxlen = V_ip6qmaxlen; /* XXX */
mtx_init(&ip6intrq.ifq_mtx, "ip6_inq", NULL, MTX_DEF);
netisr_register(NETISR_IPV6, ip6_input, &ip6intrq, 0);
- scope6_init();
- addrsel_policy_init();
- nd6_init();
- frag6_init();
- V_ip6_desync_factor = arc4random() % MAX_TEMP_DESYNC_FACTOR;
}
-static void
-ip6_init2(void *dummy)
+static int
+ip6_init2_vnet(const void *unused __unused)
{
INIT_VNET_INET6(curvnet);
@@ -290,6 +315,15 @@ ip6_init2(void *dummy)
(V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
V_ip6_temp_regen_advance) * hz,
in6_tmpaddrtimer, NULL);
+
+ return (0);
+}
+
+static void
+ip6_init2(void *dummy)
+{
+
+ ip6_init2_vnet(NULL);
}
/* cheat */
diff --git a/sys/netinet6/ip6_mroute.c b/sys/netinet6/ip6_mroute.c
index 18e7aca..29201d6 100644
--- a/sys/netinet6/ip6_mroute.c
+++ b/sys/netinet6/ip6_mroute.c
@@ -92,6 +92,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
+#include <sys/module.h>
#include <sys/protosw.h>
#include <sys/signalvar.h>
#include <sys/socket.h>
@@ -114,6 +115,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_var.h>
#include <netinet/icmp6.h>
#include <netinet/vinet.h>
+#include <netinet/ip_encap.h>
#include <netinet/ip6.h>
#include <netinet6/ip6_var.h>
@@ -130,20 +132,18 @@ static MALLOC_DEFINE(M_MRTABLE6, "mf6c", "multicast forwarding cache entry");
/* XXX: this is a very common idiom; move to <sys/mbuf.h> ? */
#define M_HASCL(m) ((m)->m_flags & M_EXT)
-static int ip6_mdq(struct mbuf *, struct ifnet *, struct mf6c *);
-static void phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
-
-static void pim6_init(void);
-static int set_pim6(int *);
-static int socket_send __P((struct socket *, struct mbuf *,
- struct sockaddr_in6 *));
-static int register_send __P((struct ip6_hdr *, struct mif6 *,
- struct mbuf *));
+static int ip6_mdq(struct mbuf *, struct ifnet *, struct mf6c *);
+static void phyint_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
+static void pim6_init(void);
+static int register_send(struct ip6_hdr *, struct mif6 *, struct mbuf *);
+static int set_pim6(int *);
+static int socket_send(struct socket *, struct mbuf *,
+ struct sockaddr_in6 *);
extern struct domain inet6domain;
-/* XXX: referenced from ip_mroute.c for dynamically loading this code. */
-struct ip6protosw in6_pim_protosw = {
+static const struct encaptab *pim6_encap_cookie;
+static const struct ip6protosw in6_pim_protosw = {
.pr_type = SOCK_RAW,
.pr_domain = &inet6domain,
.pr_protocol = IPPROTO_PIM,
@@ -154,6 +154,7 @@ struct ip6protosw in6_pim_protosw = {
.pr_init = pim6_init,
.pr_usrreqs = &rip6_usrreqs
};
+static int pim6_encapcheck(const struct mbuf *, int, int, void *);
#ifdef VIMAGE_GLOBALS
static int ip6_mrouter_ver;
@@ -171,18 +172,48 @@ SYSCTL_STRUCT(_net_inet6_ip6, OID_AUTO, mrt6stat, CTLFLAG_RW,
#define NO_RTE_FOUND 0x1
#define RTE_FOUND 0x2
+static struct mtx mrouter6_mtx;
+#define MROUTER6_LOCK() mtx_lock(&mrouter6_mtx)
+#define MROUTER6_UNLOCK() mtx_unlock(&mrouter6_mtx)
+#define MROUTER6_LOCK_ASSERT() do { \
+ mtx_assert(&mrouter6_mtx, MA_OWNED); \
+ NET_ASSERT_GIANT(); \
+} while (0)
+#define MROUTER6_LOCK_INIT() \
+ mtx_init(&mrouter6_mtx, "IPv6 multicast forwarding", NULL, MTX_DEF)
+#define MROUTER6_LOCK_DESTROY() mtx_destroy(&mrouter6_mtx)
+
static struct mf6c *mf6ctable[MF6CTBLSIZ];
SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mf6ctable, CTLFLAG_RD,
&mf6ctable, sizeof(mf6ctable), "S,*mf6ctable[MF6CTBLSIZ]",
- "Multicast Forwarding Table (struct *mf6ctable[MF6CTBLSIZ], "
+ "IPv6 Multicast Forwarding Table (struct *mf6ctable[MF6CTBLSIZ], "
"netinet6/ip6_mroute.h)");
+static struct mtx mfc6_mtx;
+#define MFC6_LOCK() mtx_lock(&mfc6_mtx)
+#define MFC6_UNLOCK() mtx_unlock(&mfc6_mtx)
+#define MFC6_LOCK_ASSERT() do { \
+ mtx_assert(&mfc6_mtx, MA_OWNED); \
+ NET_ASSERT_GIANT(); \
+} while (0)
+#define MFC6_LOCK_INIT() \
+ mtx_init(&mfc6_mtx, "IPv6 multicast forwarding cache", NULL, MTX_DEF)
+#define MFC6_LOCK_DESTROY() mtx_destroy(&mfc6_mtx)
+
static u_char n6expire[MF6CTBLSIZ];
static struct mif6 mif6table[MAXMIFS];
SYSCTL_OPAQUE(_net_inet6_ip6, OID_AUTO, mif6table, CTLFLAG_RD,
- &mif6table, sizeof(mif6table), "S,vif[MAXMIFS]",
- "Multicast Interfaces (struct mif[MAXMIFS], netinet6/ip6_mroute.h)");
+ &mif6table, sizeof(mif6table), "S,mif6[MAXMIFS]",
+ "IPv6 Multicast Interfaces (struct mif6[MAXMIFS], netinet6/ip6_mroute.h)");
+
+static struct mtx mif6_mtx;
+#define MIF6_LOCK() mtx_lock(&mif6_mtx)
+#define MIF6_UNLOCK() mtx_unlock(&mif6_mtx)
+#define MIF6_LOCK_ASSERT() mtx_assert(&mif6_mtx, MA_OWNED)
+#define MIF6_LOCK_INIT() \
+ mtx_init(&mif6_mtx, "IPv6 multicast interfaces", NULL, MTX_DEF)
+#define MIF6_LOCK_DESTROY() mtx_destroy(&mif6_mtx)
#ifdef MRT6DEBUG
#ifdef VIMAGE_GLOBALS
@@ -200,11 +231,9 @@ static void expire_upcalls(void *);
#define EXPIRE_TIMEOUT (hz / 4) /* 4x / second */
#define UPCALL_EXPIRE 6 /* number of timeouts */
-#ifdef INET
-#ifdef MROUTING
-extern struct socket *ip_mrouter;
-#endif
-#endif
+/*
+ * XXX TODO: maintain a count to if_allmulti() calls in struct ifnet.
+ */
/*
* 'Interfaces' associated with decapsulator (so we can tell
@@ -298,21 +327,22 @@ static u_long upcall_data[UPCALL_MAX + 1];
static void collate();
#endif /* UPCALL_TIMING */
-static int get_sg_cnt(struct sioc_sg_req6 *);
-static int get_mif6_cnt(struct sioc_mif_req6 *);
static int ip6_mrouter_init(struct socket *, int, int);
-static int add_m6if(struct mif6ctl *);
-static int del_m6if(mifi_t *);
static int add_m6fc(struct mf6cctl *);
+static int add_m6if(struct mif6ctl *);
static int del_m6fc(struct mf6cctl *);
+static int del_m6if(mifi_t *);
+static int del_m6if_locked(mifi_t *);
+static int get_mif6_cnt(struct sioc_mif_req6 *);
+static int get_sg_cnt(struct sioc_sg_req6 *);
static struct callout expire_upcalls_ch;
-int X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m);
+int X_ip6_mforward(struct ip6_hdr *, struct ifnet *, struct mbuf *);
int X_ip6_mrouter_done(void);
-int X_ip6_mrouter_set(struct socket *so, struct sockopt *sopt);
-int X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt);
-int X_mrt6_ioctl(int cmd, caddr_t data);
+int X_ip6_mrouter_set(struct socket *, struct sockopt *);
+int X_ip6_mrouter_get(struct socket *, struct sockopt *);
+int X_mrt6_ioctl(int, caddr_t);
static void
pim6_init(void)
@@ -419,14 +449,24 @@ X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt)
int
X_mrt6_ioctl(int cmd, caddr_t data)
{
+ int ret;
+
+ ret = EINVAL;
+
switch (cmd) {
case SIOCGETSGCNT_IN6:
- return (get_sg_cnt((struct sioc_sg_req6 *)data));
+ ret = get_sg_cnt((struct sioc_sg_req6 *)data);
+ break;
+
case SIOCGETMIFCNT_IN6:
- return (get_mif6_cnt((struct sioc_mif_req6 *)data));
+ ret = get_mif6_cnt((struct sioc_mif_req6 *)data);
+ break;
+
default:
- return (EINVAL);
+ break;
}
+
+ return (ret);
}
/*
@@ -436,22 +476,24 @@ static int
get_sg_cnt(struct sioc_sg_req6 *req)
{
struct mf6c *rt;
- int s;
+ int ret;
+
+ ret = 0;
+
+ MFC6_LOCK();
- s = splnet();
MF6CFIND(req->src.sin6_addr, req->grp.sin6_addr, rt);
- splx(s);
- if (rt != NULL) {
+ if (rt == NULL) {
+ ret = ESRCH;
+ } else {
req->pktcnt = rt->mf6c_pkt_cnt;
req->bytecnt = rt->mf6c_byte_cnt;
req->wrong_if = rt->mf6c_wrong_if;
- } else
- return (ESRCH);
-#if 0
- req->pktcnt = req->bytecnt = req->wrong_if = 0xffffffff;
-#endif
+ }
- return (0);
+ MFC6_UNLOCK();
+
+ return (ret);
}
/*
@@ -460,17 +502,26 @@ get_sg_cnt(struct sioc_sg_req6 *req)
static int
get_mif6_cnt(struct sioc_mif_req6 *req)
{
- mifi_t mifi = req->mifi;
+ mifi_t mifi;
+ int ret;
- if (mifi >= nummifs)
- return (EINVAL);
+ ret = 0;
+ mifi = req->mifi;
- req->icount = mif6table[mifi].m6_pkt_in;
- req->ocount = mif6table[mifi].m6_pkt_out;
- req->ibytes = mif6table[mifi].m6_bytes_in;
- req->obytes = mif6table[mifi].m6_bytes_out;
+ MIF6_LOCK();
- return (0);
+ if (mifi >= nummifs) {
+ ret = EINVAL;
+ } else {
+ req->icount = mif6table[mifi].m6_pkt_in;
+ req->ocount = mif6table[mifi].m6_pkt_out;
+ req->ibytes = mif6table[mifi].m6_bytes_in;
+ req->obytes = mif6table[mifi].m6_bytes_out;
+ }
+
+ MIF6_UNLOCK();
+
+ return (ret);
}
static int
@@ -507,8 +558,12 @@ ip6_mrouter_init(struct socket *so, int v, int cmd)
if (v != 1)
return (ENOPROTOOPT);
- if (ip6_mrouter != NULL)
+ MROUTER6_LOCK();
+
+ if (ip6_mrouter != NULL) {
+ MROUTER6_UNLOCK();
return (EADDRINUSE);
+ }
ip6_mrouter = so;
V_ip6_mrouter_ver = cmd;
@@ -522,6 +577,8 @@ ip6_mrouter_init(struct socket *so, int v, int cmd)
callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
expire_upcalls, NULL);
+ MROUTER6_UNLOCK();
+
#ifdef MRT6DEBUG
if (V_mrt6debug)
log(LOG_DEBUG, "ip6_mrouter_init\n");
@@ -531,7 +588,7 @@ ip6_mrouter_init(struct socket *so, int v, int cmd)
}
/*
- * Disable multicast routing
+ * Disable IPv6 multicast forwarding.
*/
int
X_ip6_mrouter_done(void)
@@ -541,31 +598,22 @@ X_ip6_mrouter_done(void)
int i;
struct mf6c *rt;
struct rtdetq *rte;
- int s;
- s = splnet();
+ MROUTER6_LOCK();
+
+ if (ip6_mrouter == NULL) {
+ MROUTER6_UNLOCK();
+ return (EINVAL);
+ }
/*
* For each phyint in use, disable promiscuous reception of all IPv6
* multicasts.
*/
-#ifdef INET
-#ifdef MROUTING
- /*
- * If there is still IPv4 multicast routing daemon,
- * we remain interfaces to receive all muliticasted packets.
- * XXX: there may be an interface in which the IPv4 multicast
- * daemon is not interested...
- */
- if (!V_ip_mrouter)
-#endif
-#endif
- {
- for (mifi = 0; mifi < nummifs; mifi++) {
- if (mif6table[mifi].m6_ifp &&
- !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
- if_allmulti(mif6table[mifi].m6_ifp, 0);
- }
+ for (mifi = 0; mifi < nummifs; mifi++) {
+ if (mif6table[mifi].m6_ifp &&
+ !(mif6table[mifi].m6_flags & MIFF_REGISTER)) {
+ if_allmulti(mif6table[mifi].m6_ifp, 0);
}
}
bzero((caddr_t)mif6table, sizeof(mif6table));
@@ -578,6 +626,7 @@ X_ip6_mrouter_done(void)
/*
* Free all multicast forwarding cache entries.
*/
+ MFC6_LOCK();
for (i = 0; i < MF6CTBLSIZ; i++) {
rt = mf6ctable[i];
while (rt) {
@@ -595,8 +644,8 @@ X_ip6_mrouter_done(void)
free(frt, M_MRTABLE6);
}
}
-
bzero((caddr_t)mf6ctable, sizeof(mf6ctable));
+ MFC6_UNLOCK();
/*
* Reset register interface
@@ -611,7 +660,7 @@ X_ip6_mrouter_done(void)
ip6_mrouter = NULL;
V_ip6_mrouter_ver = 0;
- splx(s);
+ MROUTER6_UNLOCK();
#ifdef MRT6DEBUG
if (V_mrt6debug)
@@ -632,15 +681,24 @@ add_m6if(struct mif6ctl *mifcp)
INIT_VNET_NET(curvnet);
struct mif6 *mifp;
struct ifnet *ifp;
- int error, s;
+ int error;
- if (mifcp->mif6c_mifi >= MAXMIFS)
+ MIF6_LOCK();
+
+ if (mifcp->mif6c_mifi >= MAXMIFS) {
+ MIF6_UNLOCK();
return (EINVAL);
+ }
mifp = mif6table + mifcp->mif6c_mifi;
- if (mifp->m6_ifp)
+ if (mifp->m6_ifp != NULL) {
+ MIF6_UNLOCK();
return (EADDRINUSE); /* XXX: is it appropriate? */
- if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > V_if_index)
+ }
+ if (mifcp->mif6c_pifi == 0 || mifcp->mif6c_pifi > V_if_index) {
+ MIF6_UNLOCK();
return (ENXIO);
+ }
+
ifp = ifnet_byindex(mifcp->mif6c_pifi);
if (mifcp->mif6c_flags & MIFF_REGISTER) {
@@ -661,21 +719,20 @@ add_m6if(struct mif6ctl *mifcp)
} else {
ifp = multicast_register_if6;
}
-
- } /* if REGISTER */
- else {
+ } else {
/* Make sure the interface supports multicast */
- if ((ifp->if_flags & IFF_MULTICAST) == 0)
+ if ((ifp->if_flags & IFF_MULTICAST) == 0) {
+ MIF6_UNLOCK();
return (EOPNOTSUPP);
+ }
- s = splnet();
error = if_allmulti(ifp, 1);
- splx(s);
- if (error)
+ if (error) {
+ MIF6_UNLOCK();
return (error);
+ }
}
- s = splnet();
mifp->m6_flags = mifcp->mif6c_flags;
mifp->m6_ifp = ifp;
@@ -684,12 +741,14 @@ add_m6if(struct mif6ctl *mifcp)
mifp->m6_pkt_out = 0;
mifp->m6_bytes_in = 0;
mifp->m6_bytes_out = 0;
- splx(s);
+ bzero(&mifp->m6_route, sizeof(mifp->m6_route));
/* Adjust nummifs up if the mifi is higher than nummifs */
if (nummifs <= mifcp->mif6c_mifi)
nummifs = mifcp->mif6c_mifi + 1;
+ MIF6_UNLOCK();
+
#ifdef MRT6DEBUG
if (V_mrt6debug)
log(LOG_DEBUG,
@@ -705,27 +764,22 @@ add_m6if(struct mif6ctl *mifcp)
* Delete a mif from the mif table
*/
static int
-del_m6if(mifi_t *mifip)
+del_m6if_locked(mifi_t *mifip)
{
struct mif6 *mifp = mif6table + *mifip;
mifi_t mifi;
struct ifnet *ifp;
- int s;
+
+ MIF6_LOCK_ASSERT();
if (*mifip >= nummifs)
return (EINVAL);
if (mifp->m6_ifp == NULL)
return (EINVAL);
- s = splnet();
-
if (!(mifp->m6_flags & MIFF_REGISTER)) {
- /*
- * XXX: what if there is yet IPv4 multicast daemon
- * using the interface?
- */
+ /* XXX: TODO: Maintain an ALLMULTI refcount in struct ifnet. */
ifp = mifp->m6_ifp;
-
if_allmulti(ifp, 0);
} else {
if (reg_mif_num != (mifi_t)-1 &&
@@ -745,8 +799,6 @@ del_m6if(mifi_t *mifip)
break;
nummifs = mifi;
- splx(s);
-
#ifdef MRT6DEBUG
if (V_mrt6debug)
log(LOG_DEBUG, "del_m6if %d, nummifs %d\n", *mifip, nummifs);
@@ -755,6 +807,18 @@ del_m6if(mifi_t *mifip)
return (0);
}
+static int
+del_m6if(mifi_t *mifip)
+{
+ int cc;
+
+ MIF6_LOCK();
+ cc = del_m6if_locked(mifip);
+ MIF6_UNLOCK();
+
+ return (cc);
+}
+
/*
* Add an mfc entry
*/
@@ -765,9 +829,10 @@ add_m6fc(struct mf6cctl *mfccp)
u_long hash;
struct rtdetq *rte;
u_short nstl;
- int s;
char ip6bufo[INET6_ADDRSTRLEN], ip6bufg[INET6_ADDRSTRLEN];
+ MFC6_LOCK();
+
MF6CFIND(mfccp->mf6cc_origin.sin6_addr,
mfccp->mf6cc_mcastgrp.sin6_addr, rt);
@@ -783,17 +848,16 @@ add_m6fc(struct mf6cctl *mfccp)
}
#endif
- s = splnet();
rt->mf6c_parent = mfccp->mf6cc_parent;
rt->mf6c_ifset = mfccp->mf6cc_ifset;
- splx(s);
+
+ MFC6_UNLOCK();
return (0);
}
/*
* Find the entry for which the upcall was made and update
*/
- s = splnet();
hash = MF6CHASH(mfccp->mf6cc_origin.sin6_addr,
mfccp->mf6cc_mcastgrp.sin6_addr);
for (rt = mf6ctable[hash], nstl = 0; rt; rt = rt->mf6c_next) {
@@ -891,7 +955,7 @@ add_m6fc(struct mf6cctl *mfccp)
rt = (struct mf6c *)malloc(sizeof(*rt), M_MRTABLE6,
M_NOWAIT);
if (rt == NULL) {
- splx(s);
+ MFC6_UNLOCK();
return (ENOBUFS);
}
@@ -912,7 +976,8 @@ add_m6fc(struct mf6cctl *mfccp)
mf6ctable[hash] = rt;
}
}
- splx(s);
+
+ MFC6_UNLOCK();
return (0);
}
@@ -953,7 +1018,6 @@ del_m6fc(struct mf6cctl *mfccp)
struct mf6c *rt;
struct mf6c **nptr;
u_long hash;
- int s;
origin = mfccp->mf6cc_origin;
mcastgrp = mfccp->mf6cc_mcastgrp;
@@ -968,7 +1032,7 @@ del_m6fc(struct mf6cctl *mfccp)
}
#endif
- s = splnet();
+ MFC6_LOCK();
nptr = &mf6ctable[hash];
while ((rt = *nptr) != NULL) {
@@ -982,14 +1046,14 @@ del_m6fc(struct mf6cctl *mfccp)
nptr = &rt->mf6c_next;
}
if (rt == NULL) {
- splx(s);
+ MFC6_UNLOCK();
return (EADDRNOTAVAIL);
}
*nptr = rt->mf6c_next;
free(rt, M_MRTABLE6);
- splx(s);
+ MFC6_UNLOCK();
return (0);
}
@@ -1035,7 +1099,6 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
struct mf6c *rt;
struct mif6 *mifp;
struct mbuf *mm;
- int s;
mifi_t mifi;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
@@ -1078,15 +1141,16 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
return (0);
}
+ MFC6_LOCK();
+
/*
* Determine forwarding mifs from the forwarding cache table
*/
- s = splnet();
MF6CFIND(ip6->ip6_src, ip6->ip6_dst, rt);
/* Entry exists, so forward if necessary */
if (rt) {
- splx(s);
+ MFC6_UNLOCK();
return (ip6_mdq(m, ifp, rt));
} else {
/*
@@ -1120,7 +1184,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
rte = (struct rtdetq *)malloc(sizeof(*rte), M_MRTABLE6,
M_NOWAIT);
if (rte == NULL) {
- splx(s);
+ MFC6_UNLOCK();
return (ENOBUFS);
}
mb0 = m_copy(m, 0, M_COPYALL);
@@ -1133,7 +1197,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
mb0 = m_pullup(mb0, sizeof(struct ip6_hdr));
if (mb0 == NULL) {
free(rte, M_MRTABLE6);
- splx(s);
+ MFC6_UNLOCK();
return (ENOBUFS);
}
@@ -1160,7 +1224,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
if (rt == NULL) {
free(rte, M_MRTABLE6);
m_freem(mb0);
- splx(s);
+ MFC6_UNLOCK();
return (ENOBUFS);
}
/*
@@ -1173,7 +1237,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
free(rte, M_MRTABLE6);
m_freem(mb0);
free(rt, M_MRTABLE6);
- splx(s);
+ MFC6_UNLOCK();
return (ENOBUFS);
}
@@ -1203,7 +1267,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
free(rte, M_MRTABLE6);
m_freem(mb0);
free(rt, M_MRTABLE6);
- splx(s);
+ MFC6_UNLOCK();
return (EINVAL);
}
@@ -1236,7 +1300,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
free(rte, M_MRTABLE6);
m_freem(mb0);
free(rt, M_MRTABLE6);
- splx(s);
+ MFC6_UNLOCK();
return (ENOBUFS);
}
@@ -1269,7 +1333,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
mrt6stat.mrt6s_upq_ovflw++;
free(rte, M_MRTABLE6);
m_freem(mb0);
- splx(s);
+ MFC6_UNLOCK();
return (0);
}
@@ -1284,7 +1348,7 @@ X_ip6_mforward(struct ip6_hdr *ip6, struct ifnet *ifp, struct mbuf *m)
rte->t = tp;
#endif /* UPCALL_TIMING */
- splx(s);
+ MFC6_UNLOCK();
return (0);
}
@@ -1300,9 +1364,8 @@ expire_upcalls(void *unused)
struct rtdetq *rte;
struct mf6c *mfc, **nptr;
int i;
- int s;
- s = splnet();
+ MFC6_LOCK();
for (i = 0; i < MF6CTBLSIZ; i++) {
if (n6expire[i] == 0)
continue;
@@ -1346,7 +1409,7 @@ expire_upcalls(void *unused)
}
}
}
- splx(s);
+ MFC6_UNLOCK();
callout_reset(&expire_upcalls_ch, EXPIRE_TIMEOUT,
expire_upcalls, NULL);
}
@@ -1540,8 +1603,6 @@ phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m)
struct mbuf *mb_copy;
struct ifnet *ifp = mifp->m6_ifp;
int error = 0;
- int s = splnet(); /* needs to protect static "ro" below. */
- static struct route_in6 ro;
struct in6_multi *in6m;
struct sockaddr_in6 *dst6;
u_long linkmtu;
@@ -1556,7 +1617,6 @@ phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m)
(M_HASCL(mb_copy) || mb_copy->m_len < sizeof(struct ip6_hdr)))
mb_copy = m_pullup(mb_copy, sizeof(struct ip6_hdr));
if (mb_copy == NULL) {
- splx(s);
return;
}
/* set MCAST flag to the outgoing packet */
@@ -1576,7 +1636,7 @@ phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m)
/* XXX: ip6_output will override ip6->ip6_hlim */
im6o.im6o_multicast_hlim = ip6->ip6_hlim;
im6o.im6o_multicast_loop = 1;
- error = ip6_output(mb_copy, NULL, &ro,
+ error = ip6_output(mb_copy, NULL, &mifp->m6_route,
IPV6_FORWARDING, &im6o, NULL, NULL);
#ifdef MRT6DEBUG
@@ -1584,7 +1644,6 @@ phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m)
log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
mifp - mif6table, error);
#endif
- splx(s);
return;
}
@@ -1592,13 +1651,13 @@ phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m)
* If we belong to the destination multicast group
* on the outgoing interface, loop back a copy.
*/
- dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
+ dst6 = &mifp->m6_route.ro_dst;
IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
if (in6m != NULL) {
dst6->sin6_len = sizeof(struct sockaddr_in6);
dst6->sin6_family = AF_INET6;
dst6->sin6_addr = ip6->ip6_dst;
- ip6_mloopback(ifp, m, (struct sockaddr_in6 *)&ro.ro_dst);
+ ip6_mloopback(ifp, m, &mifp->m6_route.ro_dst);
}
/*
* Put the packet into the sending queue of the outgoing interface
@@ -1614,7 +1673,7 @@ phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m)
* we need no ND for a multicast forwarded packet...right?
*/
error = (*ifp->if_output)(ifp, mb_copy,
- (struct sockaddr *)&ro.ro_dst, NULL);
+ (struct sockaddr *)&mifp->m6_route.ro_dst, NULL);
#ifdef MRT6DEBUG
if (V_mrt6debug & DEBUG_XMIT)
log(LOG_DEBUG, "phyint_send on mif %d err %d\n",
@@ -1645,8 +1704,6 @@ phyint_send(struct ip6_hdr *ip6, struct mif6 *mifp, struct mbuf *m)
m_freem(mb_copy); /* simply discard the packet */
}
}
-
- splx(s);
}
static int
@@ -1715,6 +1772,24 @@ register_send(struct ip6_hdr *ip6, struct mif6 *mif, struct mbuf *m)
}
/*
+ * pim6_encapcheck() is called by the encap6_input() path at runtime to
+ * determine if a packet is for PIM; allowing PIM to be dynamically loaded
+ * into the kernel.
+ */
+static int
+pim6_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
+{
+
+#ifdef DIAGNOSTIC
+ KASSERT(proto == IPPROTO_PIM, ("not for IPPROTO_PIM"));
+#endif
+ if (proto != IPPROTO_PIM)
+ return 0; /* not for us; reject the datagram. */
+
+ return 64; /* claim the datagram. */
+}
+
+/*
* PIM sparse mode hook
* Receives the pim control messages, and passes them up to the listening
* socket, using rip6_input.
@@ -1951,3 +2026,66 @@ pim6_input(struct mbuf **mp, int *offp, int proto)
rip6_input(&m, offp, proto);
return (IPPROTO_DONE);
}
+
+static int
+ip6_mroute_modevent(module_t mod, int type, void *unused)
+{
+
+ switch (type) {
+ case MOD_LOAD:
+ MROUTER6_LOCK_INIT();
+ MFC6_LOCK_INIT();
+ MIF6_LOCK_INIT();
+
+ pim6_encap_cookie = encap_attach_func(AF_INET6, IPPROTO_PIM,
+ pim6_encapcheck,
+ (const struct protosw *)&in6_pim_protosw, NULL);
+ if (pim6_encap_cookie == NULL) {
+ printf("ip6_mroute: unable to attach pim6 encap\n");
+ MIF6_LOCK_DESTROY();
+ MFC6_LOCK_DESTROY();
+ MROUTER6_LOCK_DESTROY();
+ return (EINVAL);
+ }
+
+ ip6_mforward = X_ip6_mforward;
+ ip6_mrouter_done = X_ip6_mrouter_done;
+ ip6_mrouter_get = X_ip6_mrouter_get;
+ ip6_mrouter_set = X_ip6_mrouter_set;
+ mrt6_ioctl = X_mrt6_ioctl;
+ break;
+
+ case MOD_UNLOAD:
+ if (ip6_mrouter != NULL)
+ return EINVAL;
+
+ if (pim6_encap_cookie) {
+ encap_detach(pim6_encap_cookie);
+ pim6_encap_cookie = NULL;
+ }
+ X_ip6_mrouter_done();
+ ip6_mforward = NULL;
+ ip6_mrouter_done = NULL;
+ ip6_mrouter_get = NULL;
+ ip6_mrouter_set = NULL;
+ mrt6_ioctl = NULL;
+
+ MIF6_LOCK_DESTROY();
+ MFC6_LOCK_DESTROY();
+ MROUTER6_LOCK_DESTROY();
+ break;
+
+ default:
+ return (EOPNOTSUPP);
+ }
+
+ return (0);
+}
+
+static moduledata_t ip6_mroutemod = {
+ "ip6_mroute",
+ ip6_mroute_modevent,
+ 0
+};
+
+DECLARE_MODULE(ip6_mroute, ip6_mroutemod, SI_SUB_PSEUDO, SI_ORDER_ANY);
diff --git a/sys/netinet6/ip6_mroute.h b/sys/netinet6/ip6_mroute.h
index 0e35e62..a0a5e4a 100644
--- a/sys/netinet6/ip6_mroute.h
+++ b/sys/netinet6/ip6_mroute.h
@@ -212,7 +212,7 @@ struct mif6 {
u_quad_t m6_pkt_out; /* # pkts out on interface */
u_quad_t m6_bytes_in; /* # bytes in on interface */
u_quad_t m6_bytes_out; /* # bytes out on interface */
- struct route_in6 m6_route;/* cached route if this is a tunnel */
+ struct route_in6 m6_route; /* cached route */
#ifdef notyet
u_int m6_rsvp_on; /* RSVP listening on this vif */
struct socket *m6_rsvpd; /* RSVP daemon socket */
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c
index 3e0f921..29b71be 100644
--- a/sys/netinet6/mld6.c
+++ b/sys/netinet6/mld6.c
@@ -288,7 +288,7 @@ mld6_input(struct mbuf *m, int off)
#else
IP6_EXTHDR_GET(mldh, struct mld_hdr *, m, off, sizeof(*mldh));
if (mldh == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return;
}
#endif
@@ -517,7 +517,7 @@ mld6_sendpkt(struct in6_multi *in6m, int type, const struct in6_addr *dst)
im6o.im6o_multicast_loop = (ip6_mrouter != NULL);
/* increment output statictics */
- V_icmp6stat.icp6s_outhist[type]++;
+ ICMP6STAT_INC(icp6s_outhist[type]);
ip6_output(mh, &V_ip6_opts, NULL, 0, &im6o, &outif, NULL);
if (outif) {
@@ -550,7 +550,6 @@ in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp,
*errorp = 0;
in6m = NULL;
- IFF_LOCKGIANT(ifp);
/*IN6_MULTI_LOCK();*/
IN6_LOOKUP_MULTI(*maddr6, ifp, in6m);
@@ -622,7 +621,6 @@ in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp,
} while (0);
/*IN6_MULTI_UNLOCK();*/
- IFF_UNLOCKGIANT(ifp);
return (in6m);
}
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 535f329..857d3fc 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -374,7 +374,7 @@ nd6_options(union nd_opts *ndopts)
* Message validation requires that all included
* options have a length that is greater than zero.
*/
- V_icmp6stat.icp6s_nd_badopt++;
+ ICMP6STAT_INC(icp6s_nd_badopt);
bzero(ndopts, sizeof(*ndopts));
return -1;
}
@@ -418,7 +418,7 @@ nd6_options(union nd_opts *ndopts)
skip1:
i++;
if (i > V_nd6_maxndopt) {
- V_icmp6stat.icp6s_nd_toomanyopt++;
+ ICMP6STAT_INC(icp6s_nd_toomanyopt);
nd6log((LOG_INFO, "too many loop in nd opt\n"));
break;
}
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index 1f88fb1..c83a245 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -128,7 +128,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
#else
IP6_EXTHDR_GET(nd_ns, struct nd_neighbor_solicit *, m, off, icmp6len);
if (nd_ns == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return;
}
#endif
@@ -365,7 +365,7 @@ nd6_ns_input(struct mbuf *m, int off, int icmp6len)
ip6_sprintf(ip6bufs, &daddr6)));
nd6log((LOG_ERR, "nd6_ns_input: tgt=%s\n",
ip6_sprintf(ip6bufs, &taddr6)));
- V_icmp6stat.icp6s_badns++;
+ ICMP6STAT_INC(icp6s_badns);
m_freem(m);
}
@@ -563,7 +563,7 @@ nd6_ns_output(struct ifnet *ifp, const struct in6_addr *daddr6,
ip6_output(m, NULL, &ro, dad ? IPV6_UNSPECSRC : 0, &im6o, NULL, NULL);
icmp6_ifstat_inc(ifp, ifs6_out_msg);
icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit);
- V_icmp6stat.icp6s_outhist[ND_NEIGHBOR_SOLICIT]++;
+ ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_SOLICIT]);
if (ro.ro_rt) { /* we don't cache this route. */
RTFREE(ro.ro_rt);
@@ -625,7 +625,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
#else
IP6_EXTHDR_GET(nd_na, struct nd_neighbor_advert *, m, off, icmp6len);
if (nd_na == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return;
}
#endif
@@ -897,7 +897,7 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len)
if (ln != NULL)
LLE_WUNLOCK(ln);
- V_icmp6stat.icp6s_badna++;
+ ICMP6STAT_INC(icp6s_badna);
m_freem(m);
}
@@ -1065,7 +1065,7 @@ nd6_na_output(struct ifnet *ifp, const struct in6_addr *daddr6_0,
ip6_output(m, NULL, &ro, 0, &im6o, NULL, NULL);
icmp6_ifstat_inc(ifp, ifs6_out_msg);
icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert);
- V_icmp6stat.icp6s_outhist[ND_NEIGHBOR_ADVERT]++;
+ ICMP6STAT_INC(icp6s_outhist[ND_NEIGHBOR_ADVERT]);
if (ro.ro_rt) { /* we don't cache this route. */
RTFREE(ro.ro_rt);
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
index e71f025..1b59db7 100644
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -155,7 +155,7 @@ nd6_rs_input(struct mbuf *m, int off, int icmp6len)
#else
IP6_EXTHDR_GET(nd_rs, struct nd_router_solicit *, m, off, icmp6len);
if (nd_rs == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return;
}
#endif
@@ -190,7 +190,7 @@ nd6_rs_input(struct mbuf *m, int off, int icmp6len)
return;
bad:
- V_icmp6stat.icp6s_badrs++;
+ ICMP6STAT_INC(icp6s_badrs);
m_freem(m);
}
@@ -246,7 +246,7 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
#else
IP6_EXTHDR_GET(nd_ra, struct nd_router_advert *, m, off, icmp6len);
if (nd_ra == NULL) {
- V_icmp6stat.icp6s_tooshort++;
+ ICMP6STAT_INC(icp6s_tooshort);
return;
}
#endif
@@ -422,7 +422,7 @@ nd6_ra_input(struct mbuf *m, int off, int icmp6len)
return;
bad:
- V_icmp6stat.icp6s_badra++;
+ ICMP6STAT_INC(icp6s_badra);
m_freem(m);
}
diff --git a/sys/netinet6/raw_ip6.c b/sys/netinet6/raw_ip6.c
index bce1b14..2ac95e5 100644
--- a/sys/netinet6/raw_ip6.c
+++ b/sys/netinet6/raw_ip6.c
@@ -477,7 +477,7 @@ rip6_output(m, va_alist)
if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) {
if (oifp)
icmp6_ifoutstat_inc(oifp, type, code);
- V_icmp6stat.icp6s_outhist[type]++;
+ ICMP6STAT_INC(icp6s_outhist[type]);
} else
V_rip6stat.rip6s_opackets++;
diff --git a/sys/netinet6/scope6.c b/sys/netinet6/scope6.c
index 9611deb..b866cd9 100644
--- a/sys/netinet6/scope6.c
+++ b/sys/netinet6/scope6.c
@@ -83,8 +83,12 @@ scope6_init(void)
#else
V_ip6_use_defzone = 0;
#endif
- SCOPE6_LOCK_INIT();
bzero(&V_sid_default, sizeof(V_sid_default));
+
+ if (!IS_DEFAULT_VNET(curvnet))
+ return;
+
+ SCOPE6_LOCK_INIT();
}
struct scope6_id *
diff --git a/sys/netinet6/udp6_usrreq.c b/sys/netinet6/udp6_usrreq.c
index 05d48f5..566cf92 100644
--- a/sys/netinet6/udp6_usrreq.c
+++ b/sys/netinet6/udp6_usrreq.c
@@ -166,7 +166,7 @@ udp6_append(struct inpcb *inp, struct mbuf *n, int off,
m_freem(n);
if (opts)
m_freem(opts);
- V_udpstat.udps_fullsock++;
+ UDPSTAT_INC(udps_fullsock);
} else
sorwakeup_locked(so);
}
@@ -202,7 +202,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
return (IPPROTO_DONE);
#endif
- V_udpstat.udps_ipackets++;
+ UDPSTAT_INC(udps_ipackets);
/*
* Destination port of 0 is illegal, based on RFC768.
@@ -214,7 +214,7 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
ulen = ntohs((u_short)uh->uh_ulen);
if (plen != ulen) {
- V_udpstat.udps_badlen++;
+ UDPSTAT_INC(udps_badlen);
goto badunlocked;
}
@@ -222,11 +222,11 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
* Checksum extended UDP header and data.
*/
if (uh->uh_sum == 0) {
- V_udpstat.udps_nosum++;
+ UDPSTAT_INC(udps_nosum);
goto badunlocked;
}
if (in6_cksum(m, IPPROTO_UDP, off, ulen) != 0) {
- V_udpstat.udps_badsum++;
+ UDPSTAT_INC(udps_badsum);
goto badunlocked;
}
@@ -327,8 +327,8 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
* to send an ICMP Port Unreachable for a broadcast
* or multicast datgram.)
*/
- V_udpstat.udps_noport++;
- V_udpstat.udps_noportmcast++;
+ UDPSTAT_INC(udps_noport);
+ UDPSTAT_INC(udps_noportmcast);
goto badheadlocked;
}
INP_RLOCK(last);
@@ -365,10 +365,10 @@ udp6_input(struct mbuf **mp, int *offp, int proto)
ip6_sprintf(ip6bufs, &ip6->ip6_src),
ntohs(uh->uh_sport));
}
- V_udpstat.udps_noport++;
+ UDPSTAT_INC(udps_noport);
if (m->m_flags & M_MCAST) {
printf("UDP6: M_MCAST is set in a unicast packet.\n");
- V_udpstat.udps_noportmcast++;
+ UDPSTAT_INC(udps_noportmcast);
goto badheadlocked;
}
INP_INFO_RUNLOCK(&V_udbinfo);
@@ -719,7 +719,7 @@ udp6_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr6,
flags = 0;
- V_udpstat.udps_opackets++;
+ UDPSTAT_INC(udps_opackets);
error = ip6_output(m, optp, NULL, flags, inp->in6p_moptions,
NULL, inp);
break;
diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c
index 00ce8de..a76afd2 100644
--- a/sys/netipsec/ipsec.c
+++ b/sys/netipsec/ipsec.c
@@ -103,6 +103,8 @@ struct vnet_ipsec vnet_ipsec_0;
#endif
#endif
+static int ipsec_iattach(const void *);
+
#ifdef VIMAGE_GLOBALS
/* NB: name changed so netstat doesn't use it. */
struct ipsecstat ipsec4stat;
@@ -242,6 +244,15 @@ static void vshiftl __P((unsigned char *, int, int));
MALLOC_DEFINE(M_IPSEC_INPCB, "inpcbpolicy", "inpcb-resident ipsec policy");
+#ifndef VIMAGE_GLOBALS
+static const vnet_modinfo_t vnet_ipsec_modinfo = {
+ .vmi_id = VNET_MOD_IPSEC,
+ .vmi_name = "ipsec",
+ .vmi_dependson = VNET_MOD_INET, /* XXX revisit - INET6 ? */
+ .vmi_iattach = ipsec_iattach
+};
+#endif /* !VIMAGE_GLOBALS */
+
void
ipsec_init(void)
{
@@ -1758,8 +1769,23 @@ static void
ipsec_attach(void)
{
+#ifndef VIMAGE_GLOBALS
+ vnet_mod_register(&vnet_ipsec_modinfo);
+#else
+ ipsec_iattach(NULL);
+#endif
+
+}
+
+static int
+ipsec_iattach(const void *unused __unused)
+{
+ INIT_VNET_IPSEC(curvnet);
+
SECPOLICY_LOCK_INIT(&V_ip4_def_policy);
V_ip4_def_policy.refcnt = 1; /* NB: disallow free. */
+
+ return (0);
}
SYSINIT(ipsec, SI_SUB_PROTO_DOMAIN, SI_ORDER_FIRST, ipsec_attach, NULL);
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index 74d31dd..70b68a8 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -2687,7 +2687,12 @@ key_delsah(sah)
if (sav->refcnt == 0) {
/* sanity check */
KEY_CHKSASTATE(state, sav->state, __func__);
- KEY_FREESAV(&sav);
+ /*
+ * do NOT call KEY_FREESAV here:
+ * it will only delete the sav if refcnt == 1,
+ * where we already know that refcnt == 0
+ */
+ key_delsav(sav);
} else {
/* give up to delete this sa */
zombie++;
@@ -4131,6 +4136,7 @@ key_flush_sad(time_t now)
/* if LARVAL entry doesn't become MATURE, delete it. */
LIST_FOREACH_SAFE(sav, &sah->savtree[SADB_SASTATE_LARVAL], chain, nextsav) {
+ /* Need to also check refcnt for a larval SA ??? */
if (now - sav->created > V_key_larval_lifetime)
KEY_FREESAV(&sav);
}
@@ -4155,11 +4161,16 @@ key_flush_sad(time_t now)
if (sav->lft_s->addtime != 0 &&
now - sav->created > sav->lft_s->addtime) {
key_sa_chgstate(sav, SADB_SASTATE_DYING);
- /* Actually, only send expire message if SA has been used, as it
- * was done before, but should we always send such message, and let IKE
- * daemon decide if it should be renegociated or not ?
- * XXX expire message will actually NOT be sent if SA is only used
- * after soft lifetime has been reached, see below (DYING state)
+ /*
+ * Actually, only send expire message if
+ * SA has been used, as it was done before,
+ * but should we always send such message,
+ * and let IKE daemon decide if it should be
+ * renegotiated or not ?
+ * XXX expire message will actually NOT be
+ * sent if SA is only used after soft
+ * lifetime has been reached, see below
+ * (DYING state)
*/
if (sav->lft_c->usetime != 0)
key_expire(sav);
@@ -7160,12 +7171,6 @@ key_init(void)
V_ipsec_esp_auth = 0;
V_ipsec_ah_keymin = 128;
- SPTREE_LOCK_INIT();
- REGTREE_LOCK_INIT();
- SAHTREE_LOCK_INIT();
- ACQ_LOCK_INIT();
- SPACQ_LOCK_INIT();
-
for (i = 0; i < IPSEC_DIR_MAX; i++)
LIST_INIT(&V_sptree[i]);
@@ -7181,6 +7186,15 @@ key_init(void)
V_ip4_def_policy.policy = IPSEC_POLICY_NONE;
V_ip4_def_policy.refcnt++; /*never reclaim this*/
+ if (!IS_DEFAULT_VNET(curvnet))
+ return;
+
+ SPTREE_LOCK_INIT();
+ REGTREE_LOCK_INIT();
+ SAHTREE_LOCK_INIT();
+ ACQ_LOCK_INIT();
+ SPACQ_LOCK_INIT();
+
#ifndef IPSEC_DEBUG2
timeout((void *)key_timehandler, (void *)0, hz);
#endif /*IPSEC_DEBUG2*/
diff --git a/sys/netipsec/xform_ah.c b/sys/netipsec/xform_ah.c
index 3a4c7dc..07d7001 100644
--- a/sys/netipsec/xform_ah.c
+++ b/sys/netipsec/xform_ah.c
@@ -73,6 +73,17 @@
#include <opencrypto/cryptodev.h>
+static int ah_iattach(const void *);
+
+#ifndef VIMAGE_GLOBALS
+static const vnet_modinfo_t vnet_ah_modinfo = {
+ .vmi_id = VNET_MOD_AH,
+ .vmi_name = "ipsec_ah",
+ .vmi_dependson = VNET_MOD_IPSEC,
+ .vmi_iattach = ah_iattach
+};
+#endif /* !VIMAGE_GLOBALS */
+
/*
* Return header size in bytes. The old protocol did not support
* the replay counter; the new protocol always includes the counter.
@@ -1220,9 +1231,22 @@ static void
ah_attach(void)
{
+ xform_register(&ah_xformsw);
+#ifndef VIMAGE_GLOBALS
+ vnet_mod_register(&vnet_ah_modinfo);
+#else
+ ah_iattach(NULL);
+#endif
+}
+
+static int
+ah_iattach(const void *unused __unused)
+{
+ INIT_VNET_IPSEC(curvnet);
+
V_ah_enable = 1; /* control flow of packets with AH */
V_ah_cleartos = 1; /* clear ip_tos when doing AH calc */
- xform_register(&ah_xformsw);
+ return (0);
}
SYSINIT(ah_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ah_attach, NULL);
diff --git a/sys/netipsec/xform_esp.c b/sys/netipsec/xform_esp.c
index 98a2240..6508c14 100644
--- a/sys/netipsec/xform_esp.c
+++ b/sys/netipsec/xform_esp.c
@@ -90,6 +90,16 @@ SYSCTL_V_STRUCT(V_NET, vnet_ipsec, _net_inet_esp, IPSECCTL_STATS,
static int esp_input_cb(struct cryptop *op);
static int esp_output_cb(struct cryptop *crp);
+static int esp_iattach(const void *);
+
+#ifndef VIMAGE_GLOBALS
+static const vnet_modinfo_t vnet_esp_modinfo = {
+ .vmi_id = VNET_MOD_ESP,
+ .vmi_name = "ipsec_esp",
+ .vmi_dependson = VNET_MOD_IPSEC,
+ .vmi_iattach = esp_iattach
+};
+#endif /* !VIMAGE_GLOBALS */
/*
* NB: this is public for use by the PF_KEY support.
@@ -990,9 +1000,23 @@ static struct xformsw esp_xformsw = {
static void
esp_attach(void)
{
+
+ xform_register(&esp_xformsw);
+#ifndef VIMAGE_GLOBALS
+ vnet_mod_register(&vnet_esp_modinfo);
+#else
+ esp_iattach(NULL);
+#endif
+}
+
+static int
+esp_iattach(const void *unused __unused)
+{
+ INIT_VNET_IPSEC(curvnet);
+
#define MAXIV(xform) \
if (xform.blocksize > V_esp_max_ivlen) \
- V_esp_max_ivlen = xform.blocksize \
+ V_esp_max_ivlen = xform.blocksize \
V_esp_enable = 1;
V_esp_max_ivlen = 0;
@@ -1005,8 +1029,8 @@ esp_attach(void)
MAXIV(enc_xform_skipjack); /* SADB_X_EALG_SKIPJACK */
MAXIV(enc_xform_null); /* SADB_EALG_NULL */
MAXIV(enc_xform_camellia); /* SADB_X_EALG_CAMELLIACBC */
-
- xform_register(&esp_xformsw);
#undef MAXIV
+
+ return (0);
}
SYSINIT(esp_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, esp_attach, NULL);
diff --git a/sys/netipsec/xform_ipcomp.c b/sys/netipsec/xform_ipcomp.c
index d64abf0f..8e2f1c4 100644
--- a/sys/netipsec/xform_ipcomp.c
+++ b/sys/netipsec/xform_ipcomp.c
@@ -80,6 +80,16 @@ SYSCTL_V_STRUCT(V_NET, vnet_ipsec, _net_inet_ipcomp, IPSECCTL_STATS,
static int ipcomp_input_cb(struct cryptop *crp);
static int ipcomp_output_cb(struct cryptop *crp);
+static int ipcomp_iattach(const void *);
+
+#ifndef VIMAGE_GLOBALS
+static const vnet_modinfo_t vnet_ipcomp_modinfo = {
+ .vmi_id = VNET_MOD_IPCOMP,
+ .vmi_name = "ipsec_ipcomp",
+ .vmi_dependson = VNET_MOD_IPSEC,
+ .vmi_iattach = ipcomp_iattach
+};
+#endif /* !VIMAGE_GLOBALS */
struct comp_algo *
ipcomp_algorithm_lookup(int alg)
@@ -600,7 +610,20 @@ static void
ipcomp_attach(void)
{
- V_ipcomp_enable = 0;
xform_register(&ipcomp_xformsw);
+#ifndef VIMAGE_GLOBALS
+ vnet_mod_register(&vnet_ipcomp_modinfo);
+#else
+ ipcomp_iattach(NULL);
+#endif
+}
+
+static int
+ipcomp_iattach(const void *unused __unused)
+{
+ INIT_VNET_IPSEC(curvnet);
+
+ V_ipcomp_enable = 0;
+ return (0);
}
SYSINIT(ipcomp_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipcomp_attach, NULL);
diff --git a/sys/netipsec/xform_ipip.c b/sys/netipsec/xform_ipip.c
index cbc447c..4d97168 100644
--- a/sys/netipsec/xform_ipip.c
+++ b/sys/netipsec/xform_ipip.c
@@ -108,6 +108,16 @@ SYSCTL_V_STRUCT(V_NET, vnet_ipsec, _net_inet_ipip, IPSECCTL_STATS,
#define M_IPSEC (M_AUTHIPHDR|M_AUTHIPDGM|M_DECRYPTED)
static void _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp);
+static int ipe4_iattach(const void *);
+
+#ifndef VIMAGE_GLOBALS
+static const vnet_modinfo_t vnet_ipip_modinfo = {
+ .vmi_id = VNET_MOD_IPIP,
+ .vmi_name = "ipsec_ipip",
+ .vmi_dependson = VNET_MOD_IPSEC,
+ .vmi_iattach = ipe4_iattach
+};
+#endif /* !VIMAGE_GLOBALS */
#ifdef INET6
/*
@@ -697,11 +707,18 @@ ipe4_encapcheck(const struct mbuf *m, int off, int proto, void *arg)
return ((m->m_flags & M_IPSEC) != 0 ? 1 : 0);
}
-static void
-ipe4_attach(void)
+static int
+ipe4_iattach(const void *unused __unused)
{
+ INIT_VNET_IPSEC(curvnet);
V_ipip_allow = 0;
+ return (0);
+}
+
+static void
+ipe4_attach(void)
+{
xform_register(&ipe4_xformsw);
/* attach to encapsulation framework */
@@ -712,6 +729,11 @@ ipe4_attach(void)
(void) encap_attach_func(AF_INET6, -1,
ipe4_encapcheck, (struct protosw *)&ipe6_protosw, NULL);
#endif
+#ifndef VIMAGE_GLOBALS
+ vnet_mod_register(&vnet_ipip_modinfo);
+#else
+ ipe4_iattach(NULL);
+#endif
}
SYSINIT(ipe4_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, ipe4_attach, NULL);
#endif /* IPSEC */
diff --git a/sys/netnatm/natm.c b/sys/netnatm/natm.c
index b9705db..baa596e 100644
--- a/sys/netnatm/natm.c
+++ b/sys/netnatm/natm.c
@@ -221,13 +221,9 @@ natm_usr_connect(struct socket *so, struct sockaddr *nam, d_thread_t *p)
op.param.traffic = ATMIO_TRAFFIC_UBR;
NATM_UNLOCK();
- IFF_LOCKGIANT(ifp);
if (ifp->if_ioctl == NULL ||
- ifp->if_ioctl(ifp, SIOCATMOPENVCC, (caddr_t)&op) != 0) {
- IFF_UNLOCKGIANT(ifp);
+ ifp->if_ioctl(ifp, SIOCATMOPENVCC, (caddr_t)&op) != 0)
return (EIO);
- }
- IFF_UNLOCKGIANT(ifp);
soisconnected(so);
return (error);
}
@@ -259,11 +255,8 @@ natm_usr_disconnect(struct socket *so)
cl.vpi = npcb->npcb_vpi;
cl.vci = npcb->npcb_vci;
NATM_UNLOCK();
- if (ifp->if_ioctl != NULL) {
- IFF_LOCKGIANT(ifp);
+ if (ifp->if_ioctl != NULL)
ifp->if_ioctl(ifp, SIOCATMCLOSEVCC, (caddr_t)&cl);
- IFF_UNLOCKGIANT(ifp);
- }
soisdisconnected(so);
return (error);
}
@@ -342,17 +335,13 @@ natm_usr_control(struct socket *so, u_long cmd, caddr_t arg,
struct ifnet *ifp, d_thread_t *p)
{
struct natmpcb *npcb;
- int error;
npcb = (struct natmpcb *)so->so_pcb;
KASSERT(npcb != NULL, ("natm_usr_control: npcb == NULL"));
if (ifp == NULL || ifp->if_ioctl == NULL)
return (EOPNOTSUPP);
- IFF_LOCKGIANT(ifp);
- error = ((*ifp->if_ioctl)(ifp, cmd, arg));
- IFF_UNLOCKGIANT(ifp);
- return (error);
+ return ((*ifp->if_ioctl)(ifp, cmd, arg));
}
static void
diff --git a/sys/nfs/nfs_nfssvc.c b/sys/nfs/nfs_nfssvc.c
new file mode 100644
index 0000000..9379fbe
--- /dev/null
+++ b/sys/nfs/nfs_nfssvc.c
@@ -0,0 +1,153 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_nfs.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/sysproto.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/priv.h>
+#include <sys/proc.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <sys/sysent.h>
+#include <sys/syscall.h>
+#include <sys/sysproto.h>
+
+#include <security/audit/audit.h>
+
+#include <nfs/nfssvc.h>
+
+static int nfssvc_offset = SYS_nfssvc;
+static struct sysent nfssvc_prev_sysent;
+MAKE_SYSENT(nfssvc);
+
+/*
+ * This tiny module simply handles the nfssvc() system call. The other
+ * nfs modules that use the system call register themselves by setting
+ * the nfsd_call_xxx function pointers non-NULL.
+ */
+
+int (*nfsd_call_nfsserver)(struct thread *, struct nfssvc_args *) = NULL;
+int (*nfsd_call_nfscommon)(struct thread *, struct nfssvc_args *) = NULL;
+int (*nfsd_call_nfscl)(struct thread *, struct nfssvc_args *) = NULL;
+int (*nfsd_call_nfsd)(struct thread *, struct nfssvc_args *) = NULL;
+
+/*
+ * Nfs server psuedo system call for the nfsd's
+ */
+int
+nfssvc(struct thread *td, struct nfssvc_args *uap)
+{
+ int error;
+
+ KASSERT(!mtx_owned(&Giant), ("nfssvc(): called with Giant"));
+
+ AUDIT_ARG(cmd, uap->flag);
+
+ error = priv_check(td, PRIV_NFS_DAEMON);
+ if (error)
+ return (error);
+ error = EINVAL;
+ if ((uap->flag & (NFSSVC_ADDSOCK | NFSSVC_OLDNFSD | NFSSVC_NFSD)) &&
+ nfsd_call_nfsserver != NULL)
+ error = (*nfsd_call_nfsserver)(td, uap);
+ else if ((uap->flag & (NFSSVC_CBADDSOCK | NFSSVC_NFSCBD)) &&
+ nfsd_call_nfscl != NULL)
+ error = (*nfsd_call_nfscl)(td, uap);
+ else if ((uap->flag & (NFSSVC_IDNAME | NFSSVC_GETSTATS |
+ NFSSVC_GSSDADDPORT | NFSSVC_GSSDADDFIRST | NFSSVC_GSSDDELETEALL |
+ NFSSVC_NFSUSERDPORT | NFSSVC_NFSUSERDDELPORT)) &&
+ nfsd_call_nfscommon != NULL)
+ error = (*nfsd_call_nfscommon)(td, uap);
+ else if ((uap->flag & (NFSSVC_NFSDNFSD | NFSSVC_NFSDADDSOCK |
+ NFSSVC_PUBLICFH | NFSSVC_V4ROOTEXPORT | NFSSVC_NOPUBLICFH |
+ NFSSVC_STABLERESTART | NFSSVC_ADMINREVOKE |
+ NFSSVC_DUMPCLIENTS | NFSSVC_DUMPLOCKS)) &&
+ nfsd_call_nfsd != NULL)
+ error = (*nfsd_call_nfsd)(td, uap);
+ if (error == EINTR || error == ERESTART)
+ error = 0;
+ return (error);
+}
+
+/*
+ * Called once to initialize data structures...
+ */
+static int
+nfssvc_modevent(module_t mod, int type, void *data)
+{
+ static int registered;
+ int error = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+ error = syscall_register(&nfssvc_offset, &nfssvc_sysent,
+ &nfssvc_prev_sysent);
+ if (error)
+ break;
+ registered = 1;
+ break;
+
+ case MOD_UNLOAD:
+ if (nfsd_call_nfsserver != NULL || nfsd_call_nfscommon != NULL
+ || nfsd_call_nfscl != NULL || nfsd_call_nfsd != NULL) {
+ error = EBUSY;
+ break;
+ }
+ if (registered)
+ syscall_deregister(&nfssvc_offset, &nfssvc_prev_sysent);
+ registered = 0;
+ break;
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+ return error;
+}
+static moduledata_t nfssvc_mod = {
+ "nfssvc",
+ nfssvc_modevent,
+ NULL,
+};
+DECLARE_MODULE(nfssvc, nfssvc_mod, SI_SUB_VFS, SI_ORDER_ANY);
+
+/* So that loader and kldload(2) can find us, wherever we are.. */
+MODULE_VERSION(nfssvc, 1);
+
diff --git a/sys/net/slip.h b/sys/nfs/nfssvc.h
index 7b4164e..5578240 100644
--- a/sys/net/slip.h
+++ b/sys/nfs/nfssvc.h
@@ -1,7 +1,10 @@
/*-
- * Copyright (c) 1994
+ * Copyright (c) 1989, 1993, 1995
* The Regents of the University of California. All rights reserved.
*
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -26,33 +29,39 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)slip.h 8.1 (Berkeley) 2/12/94
* $FreeBSD$
*/
-#ifndef _NET_SLIP_H_
-#define _NET_SLIP_H_
-
-/* Ioctls operating on SLIP ttys. */
-#define SLIOCGUNIT _IOR('t', 88, int) /* get slip unit number */
-#define SLIOCSKEEPAL _IOW('t', 84, int) /* set keepalive */
-#define SLIOCSOUTFILL _IOW('t', 83, int) /* set out fill time */
-#define SLIOCGKEEPAL _IOR('t', 82, int) /* get keepalive time */
-#define SLIOCGOUTFILL _IOR('t', 81, int) /* get out fill time */
-#define SLIOCSUNIT _IOW('t', 80, int) /* set slip unit number */
+#ifndef _NFS_NFSSVC_H_
+#define _NFS_NFSSVC_H_
/*
- * Definitions of the pseudo-link-level header attached to slip
- * packets grabbed by the packet filter (bpf) traffic monitor.
+ * Flags for nfssvc() system call.
*/
-#define SLIP_HDRLEN 16 /* BPF SLIP header length */
-
-/* Offsets into BPF SLIP header. */
-#define SLX_DIR 0 /* direction; see below */
-#define SLX_CHDR 1 /* compressed header data */
-#define CHDR_LEN 15 /* length of compressed header data */
+#define NFSSVC_OLDNFSD 0x004
+#define NFSSVC_ADDSOCK 0x008
+#define NFSSVC_NFSD 0x010
-#define SLIPDIR_IN 0 /* incoming */
-#define SLIPDIR_OUT 1 /* outgoing */
+/*
+ * and ones for nfsv4.
+ */
+#define NFSSVC_NOPUBLICFH 0x00000020
+#define NFSSVC_STABLERESTART 0x00000040
+#define NFSSVC_NFSDNFSD 0x00000080
+#define NFSSVC_NFSDADDSOCK 0x00000100
+#define NFSSVC_IDNAME 0x00000200
+#define NFSSVC_GSSDDELETEALL 0x00000400
+#define NFSSVC_GSSDADDPORT 0x00000800
+#define NFSSVC_NFSUSERDPORT 0x00001000
+#define NFSSVC_NFSUSERDDELPORT 0x00002000
+#define NFSSVC_V4ROOTEXPORT 0x00004000
+#define NFSSVC_ADMINREVOKE 0x00008000
+#define NFSSVC_DUMPCLIENTS 0x00010000
+#define NFSSVC_DUMPLOCKS 0x00020000
+#define NFSSVC_GSSDADDFIRST 0x00040000
+#define NFSSVC_PUBLICFH 0x00080000
+#define NFSSVC_NFSCBD 0x00100000
+#define NFSSVC_CBADDSOCK 0x00200000
+#define NFSSVC_GETSTATS 0x00400000
-#endif /* !_NET_SLIP_H */
+#endif /* _NFS_NFSSVC_H */
diff --git a/sys/nfs4client/nfs4_socket.c b/sys/nfs4client/nfs4_socket.c
index 754ba47..c1fe154 100644
--- a/sys/nfs4client/nfs4_socket.c
+++ b/sys/nfs4client/nfs4_socket.c
@@ -259,7 +259,7 @@ nfs4_request(struct vnode *vp, struct mbuf *mrest, int procnum,
** lookup cache, just in case.
**/
if (error == ESTALE)
- cache_purge(vp);
+ nfs_purgecache(vp);
return (error);
}
diff --git a/sys/nfs4client/nfs4_vnops.c b/sys/nfs4client/nfs4_vnops.c
index 4dd7316..af85494 100644
--- a/sys/nfs4client/nfs4_vnops.c
+++ b/sys/nfs4client/nfs4_vnops.c
@@ -173,7 +173,6 @@ struct vop_vector nfs4_vnodeops = {
.vop_getpages = nfs_getpages,
.vop_putpages = nfs_putpages,
.vop_inactive = nfs_inactive,
- .vop_lease = VOP_NULL,
.vop_link = nfs4_link,
.vop_lookup = nfs4_lookup,
.vop_mkdir = nfs4_mkdir,
@@ -241,11 +240,11 @@ SYSCTL_INT(_vfs_nfs4, OID_AUTO, access_cache_misses, CTLFLAG_RD,
| NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP)
static int
nfs4_v3_access_otw(struct vnode *vp, int wmode, struct thread *td,
- struct ucred *cred)
+ struct ucred *cred, uint32_t *retmode)
{
const int v3 = 1;
u_int32_t *tl;
- int error = 0, attrflag;
+ int error = 0, attrflag, i, lrupos;
return (0);
@@ -264,11 +263,26 @@ nfs4_v3_access_otw(struct vnode *vp, int wmode, struct thread *td,
nfsm_request(vp, NFSPROC_ACCESS, td, cred);
nfsm_postop_attr(vp, attrflag);
if (!error) {
+ lrupos = 0;
tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
rmode = fxdr_unsigned(u_int32_t, *tl);
- np->n_mode = rmode;
- np->n_modeuid = cred->cr_uid;
- np->n_modestamp = time_second;
+ for (i = 0; i < NFS_ACCESSCACHESIZE; i++) {
+ if (np->n_accesscache[i].uid == cred->cr_uid) {
+ np->n_accesscache[i].mode = rmode;
+ np->n_accesscache[i].stamp = time_second;
+ break;
+ }
+ if (i > 0 && np->n_accesscache[i].stamp <
+ np->n_accesscache[lrupos].stamp)
+ lrupos = i;
+ }
+ if (i == NFS_ACCESSCACHESIZE) {
+ np->n_accesscache[lrupos].uid = cred->cr_uid;
+ np->n_accesscache[lrupos].mode = rmode;
+ np->n_accesscache[lrupos].stamp = time_second;
+ }
+ if (retmode != NULL)
+ *retmode = rmode;
}
m_freem(mrep);
nfsmout:
@@ -285,8 +299,8 @@ static int
nfs4_access(struct vop_access_args *ap)
{
struct vnode *vp = ap->a_vp;
- int error = 0;
- u_int32_t mode, wmode;
+ int error = 0, i, gotahit;
+ u_int32_t mode, rmode, wmode;
int v3 = NFS_ISV3(vp); /* v3 \in v4 */
struct nfsnode *np = VTONFS(vp);
caddr_t bpos, dpos;
@@ -350,19 +364,27 @@ nfs4_access(struct vop_access_args *ap)
* Does our cached result allow us to give a definite yes to
* this request?
*/
- if (time_second < np->n_modestamp + nfs4_access_cache_timeout &&
- ap->a_cred->cr_uid == np->n_modeuid &&
- (np->n_mode & mode) == mode) {
- nfsstats.accesscache_hits++;
- } else {
+ gotahit = 0;
+ for (i = 0; i < NFS_ACCESSCACHESIZE; i++) {
+ if (ap->a_cred->cr_uid == np->n_accesscache[i].uid) {
+ if (time_second < (np->n_accesscache[i].stamp +
+ nfs4_access_cache_timeout) &&
+ (np->n_accesscache[i].mode & mode) == mode) {
+ nfsstats.accesscache_hits++;
+ gotahit = 1;
+ }
+ break;
+ }
+ }
+ if (gotahit == 0) {
/*
* Either a no, or a don't know. Go to the wire.
*/
nfsstats.accesscache_misses++;
error = nfs4_v3_access_otw(vp, wmode, ap->a_td,
- ap->a_cred);
+ ap->a_cred, &rmode);
if (error == 0) {
- if ((np->n_mode & mode) != mode)
+ if ((rmode & mode) != mode)
error = EACCES;
}
}
diff --git a/sys/nfsclient/nfs.h b/sys/nfsclient/nfs.h
index c5b1c51..4dce2fe 100644
--- a/sys/nfsclient/nfs.h
+++ b/sys/nfsclient/nfs.h
@@ -63,11 +63,14 @@
#define NFS_MAXATTRTIMO 60
#endif
#ifndef NFS_MINDIRATTRTIMO
-#define NFS_MINDIRATTRTIMO 30 /* VDIR attrib cache timeout in sec */
+#define NFS_MINDIRATTRTIMO 3 /* VDIR attrib cache timeout in sec */
#endif
#ifndef NFS_MAXDIRATTRTIMO
#define NFS_MAXDIRATTRTIMO 60
#endif
+#ifndef NFS_ACCESSCACHESIZE
+#define NFS_ACCESSCACHESIZE 8 /* Per-node access cache entries */
+#endif
#define NFS_WSIZE 8192 /* Def. write data size <= 8192 */
#define NFS_RSIZE 8192 /* Def. read data size <= 8192 */
#define NFS_READDIRSIZE 8192 /* Def. readdir size */
@@ -319,6 +322,7 @@ void nfs_down(struct nfsreq *, struct nfsmount *, struct thread *,
#endif /* ! NFS4_USE_RPCCLNT */
#endif
+void nfs_purgecache(struct vnode *);
int nfs_vinvalbuf(struct vnode *, int, struct thread *, int);
int nfs_readrpc(struct vnode *, struct uio *, struct ucred *);
int nfs_writerpc(struct vnode *, struct uio *, struct ucred *, int *,
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c
index ef863e5..97820f0 100644
--- a/sys/nfsclient/nfs_bio.c
+++ b/sys/nfsclient/nfs_bio.c
@@ -35,6 +35,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_kdtrace.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
@@ -61,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <nfsclient/nfs.h>
#include <nfsclient/nfsmount.h>
#include <nfsclient/nfsnode.h>
+#include <nfsclient/nfs_kdtrace.h>
#include <nfs4client/nfs4.h>
@@ -403,6 +406,7 @@ nfs_bioread_check_cons(struct vnode *vp, struct thread *td, struct ucred *cred)
goto out;
}
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
error = VOP_GETATTR(vp, &vattr, cred);
if (error)
goto out;
@@ -915,6 +919,7 @@ nfs_write(struct vop_write_args *ap)
#endif
flush_and_restart:
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
error = nfs_vinvalbuf(vp, V_SAVE, td, 1);
if (error)
return (error);
@@ -928,6 +933,7 @@ flush_and_restart:
*/
if (ioflag & IO_APPEND) {
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
error = VOP_GETATTR(vp, &vattr, cred);
if (error)
return (error);
@@ -1756,6 +1762,7 @@ nfs_doio(struct vnode *vp, struct buf *bp, struct ucred *cr, struct thread *td)
mtx_lock(&np->n_mtx);
np->n_flag |= NWRITEERR;
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
mtx_unlock(&np->n_mtx);
}
bp->b_dirtyoff = bp->b_dirtyend = 0;
diff --git a/sys/nfsclient/nfs_kdtrace.c b/sys/nfsclient/nfs_kdtrace.c
new file mode 100644
index 0000000..8444ae2
--- /dev/null
+++ b/sys/nfsclient/nfs_kdtrace.c
@@ -0,0 +1,545 @@
+/*-
+ * Copyright (c) 2009 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, 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/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+
+#include <sys/dtrace.h>
+#include <sys/dtrace_bsd.h>
+
+#include <nfs/nfsproto.h>
+
+/*
+ * dtnfsclient is a DTrace provider that tracks the intent to perform RPCs
+ * in the NFS client, as well as acess to and maintenance of the access and
+ * attribute caches. This is not quite the same as RPCs, because NFS may
+ * issue multiple RPC transactions in the event that authentication fails,
+ * there's a jukebox error, or none at all if the access or attribute cache
+ * hits. However, it cleanly represents the logical layer between RPC
+ * transmission and vnode/vfs operations, providing access to state linking
+ * the two.
+ */
+
+static int dtnfsclient_unload(void);
+static void dtnfsclient_getargdesc(void *, dtrace_id_t, void *,
+ dtrace_argdesc_t *);
+static void dtnfsclient_provide(void *, dtrace_probedesc_t *);
+static void dtnfsclient_destroy(void *, dtrace_id_t, void *);
+static void dtnfsclient_enable(void *, dtrace_id_t, void *);
+static void dtnfsclient_disable(void *, dtrace_id_t, void *);
+static void dtnfsclient_load(void *);
+
+static dtrace_pattr_t dtnfsclient_attr = {
+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
+{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_STABLE, DTRACE_CLASS_COMMON },
+};
+
+/*
+ * Descrition of NFSv3 and (optional) NFSv2 probes for a procedure.
+ */
+struct dtnfsclient_rpc {
+ char *nr_v3_name;
+ char *nr_v2_name; /* Or NULL if none. */
+
+ /*
+ * IDs for the start and done cases, for both NFSv2 and NFSv3.
+ */
+ uint32_t nr_v2_id_start, nr_v2_id_done;
+ uint32_t nr_v3_id_start, nr_v3_id_done;
+};
+
+/*
+ * This table is indexed by NFSv3 procedure number, but also used for NFSv2
+ * procedure names.
+ */
+static struct dtnfsclient_rpc dtnfsclient_rpcs[NFS_NPROCS] = {
+ { "null", "null" },
+ { "getattr", "getattr" },
+ { "setattr", "setattr" },
+ { "lookup", "lookup" },
+ { "access" },
+ { "readlink", "readlink" },
+ { "read", "read" },
+ { "write", "write" },
+ { "create", "create" },
+ { "mkdir", "mkdir" },
+ { "symlink", "symlink" },
+ { "mknod" },
+ { "remove", "remove" },
+ { "rmdir", "rmdir" },
+ { "rename", "rename" },
+ { "link", "link" },
+ { "readdir", "readdir" },
+ { "readdirplus" },
+ { "fsstat", "statfs" },
+ { "fsinfo" },
+ { "pathconf" },
+ { "commit" },
+ { "noop" },
+};
+
+/*
+ * Module name strings.
+ */
+static char *dtnfsclient_accesscache_str = "accesscache";
+static char *dtnfsclient_attrcache_str = "attrcache";
+static char *dtnfsclient_nfs2_str = "nfs2";
+static char *dtnfsclient_nfs3_str = "nfs3";
+
+/*
+ * Function name strings.
+ */
+static char *dtnfsclient_flush_str = "flush";
+static char *dtnfsclient_load_str = "load";
+static char *dtnfsclient_get_str = "get";
+
+/*
+ * Name strings.
+ */
+static char *dtnfsclient_done_str = "done";
+static char *dtnfsclient_hit_str = "hit";
+static char *dtnfsclient_miss_str = "miss";
+static char *dtnfsclient_start_str = "start";
+
+static dtrace_pops_t dtnfsclient_pops = {
+ dtnfsclient_provide,
+ NULL,
+ dtnfsclient_enable,
+ dtnfsclient_disable,
+ NULL,
+ NULL,
+ dtnfsclient_getargdesc,
+ NULL,
+ NULL,
+ dtnfsclient_destroy
+};
+
+static dtrace_provider_id_t dtnfsclient_id;
+
+/*
+ * Most probes are generated from the above RPC table, but for access and
+ * attribute caches, we have specific IDs we recognize and handle specially
+ * in various spots.
+ */
+extern uint32_t nfsclient_accesscache_flush_done_id;
+extern uint32_t nfsclient_accesscache_get_hit_id;
+extern uint32_t nfsclient_accesscache_get_miss_id;
+extern uint32_t nfsclient_accesscache_load_done_id;
+
+extern uint32_t nfsclient_attrcache_flush_done_id;
+extern uint32_t nfsclient_attrcache_get_hit_id;
+extern uint32_t nfsclient_attrcache_get_miss_id;
+extern uint32_t nfsclient_attrcache_load_done_id;
+
+/*
+ * When tracing on a procedure is enabled, the DTrace ID for an RPC event is
+ * stored in one of these two NFS client-allocated arrays; 0 indicates that
+ * the event is not being traced so probes should not be called.
+ *
+ * For simplicity, we allocate both v2 and v3 arrays as NFS_NPROCS, and the
+ * v2 array is simply sparse.
+ */
+extern uint32_t nfsclient_nfs2_start_probes[NFS_NPROCS];
+extern uint32_t nfsclient_nfs2_done_probes[NFS_NPROCS];
+
+extern uint32_t nfsclient_nfs3_start_probes[NFS_NPROCS];
+extern uint32_t nfsclient_nfs3_done_probes[NFS_NPROCS];
+
+/*
+ * Look up a DTrace probe ID to see if it's associated with a "done" event --
+ * if so, we will return a fourth argument type of "int".
+ */
+static int
+dtnfs23_isdoneprobe(dtrace_id_t id)
+{
+ int i;
+
+ for (i = 0; i < NFS_NPROCS; i++) {
+ if (dtnfsclient_rpcs[i].nr_v3_id_done == id ||
+ dtnfsclient_rpcs[i].nr_v2_id_done == id)
+ return (1);
+ }
+ return (0);
+}
+
+static void
+dtnfsclient_getargdesc(void *arg, dtrace_id_t id, void *parg,
+ dtrace_argdesc_t *desc)
+{
+ const char *p = NULL;
+
+ if (id == nfsclient_accesscache_flush_done_id ||
+ id == nfsclient_attrcache_flush_done_id ||
+ id == nfsclient_attrcache_get_miss_id) {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ } else if (id == nfsclient_accesscache_get_hit_id ||
+ id == nfsclient_accesscache_get_miss_id) {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ case 1:
+ p = "uid_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ } else if (id == nfsclient_accesscache_load_done_id) {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ case 1:
+ p = "uid_t";
+ break;
+ case 2:
+ p = "uint32_t";
+ break;
+ case 3:
+ p = "int";
+ break;
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ } else if (id == nfsclient_attrcache_get_hit_id) {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ case 1:
+ p = "struct vattr *";
+ break;
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ } else if (id == nfsclient_attrcache_load_done_id) {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ case 1:
+ p = "struct vattr *";
+ break;
+ case 2:
+ p = "int";
+ break;
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ } else {
+ switch (desc->dtargd_ndx) {
+ case 0:
+ p = "struct vnode *";
+ break;
+ case 1:
+ p = "struct mbuf *";
+ break;
+ case 2:
+ p = "struct ucred *";
+ break;
+ case 3:
+ p = "int";
+ break;
+ case 4:
+ if (dtnfs23_isdoneprobe(id)) {
+ p = "int";
+ break;
+ }
+ /* FALLSTHROUGH */
+ default:
+ desc->dtargd_ndx = DTRACE_ARGNONE;
+ break;
+ }
+ }
+ if (p != NULL)
+ strlcpy(desc->dtargd_native, p, sizeof(desc->dtargd_native));
+}
+
+static void
+dtnfsclient_provide(void *arg, dtrace_probedesc_t *desc)
+{
+ int i;
+
+ if (desc != NULL)
+ return;
+
+ /*
+ * Register access cache probes.
+ */
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
+ nfsclient_accesscache_flush_done_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
+ nfsclient_accesscache_get_hit_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
+ nfsclient_accesscache_get_miss_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
+ nfsclient_accesscache_load_done_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_accesscache_str,
+ dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
+ }
+
+ /*
+ * Register attribute cache probes.
+ */
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_flush_str, dtnfsclient_done_str) == 0) {
+ nfsclient_attrcache_flush_done_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_flush_str, dtnfsclient_done_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_get_str, dtnfsclient_hit_str) == 0) {
+ nfsclient_attrcache_get_hit_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_get_str, dtnfsclient_hit_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_get_str, dtnfsclient_miss_str) == 0) {
+ nfsclient_attrcache_get_miss_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_get_str, dtnfsclient_miss_str, 0, NULL);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_load_str, dtnfsclient_done_str) == 0) {
+ nfsclient_attrcache_load_done_id = dtrace_probe_create(
+ dtnfsclient_id, dtnfsclient_attrcache_str,
+ dtnfsclient_load_str, dtnfsclient_done_str, 0, NULL);
+ }
+
+ /*
+ * Register NFSv2 RPC procedures; note sparseness check for each slot
+ * in the NFSv3 procnum-indexed array.
+ */
+ for (i = 0; i < NFS_NPROCS; i++) {
+ if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
+ dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
+ dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_start_str) ==
+ 0) {
+ dtnfsclient_rpcs[i].nr_v2_id_start =
+ dtrace_probe_create(dtnfsclient_id,
+ dtnfsclient_nfs2_str,
+ dtnfsclient_rpcs[i].nr_v2_name,
+ dtnfsclient_start_str, 0,
+ &nfsclient_nfs2_start_probes[i]);
+ }
+ if (dtnfsclient_rpcs[i].nr_v2_name != NULL &&
+ dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs2_str,
+ dtnfsclient_rpcs[i].nr_v2_name, dtnfsclient_done_str) ==
+ 0) {
+ dtnfsclient_rpcs[i].nr_v2_id_done =
+ dtrace_probe_create(dtnfsclient_id,
+ dtnfsclient_nfs2_str,
+ dtnfsclient_rpcs[i].nr_v2_name,
+ dtnfsclient_done_str, 0,
+ &nfsclient_nfs2_done_probes[i]);
+ }
+ }
+
+ /*
+ * Register NFSv3 RPC procedures.
+ */
+ for (i = 0; i < NFS_NPROCS; i++) {
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
+ dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_start_str) ==
+ 0) {
+ dtnfsclient_rpcs[i].nr_v3_id_start =
+ dtrace_probe_create(dtnfsclient_id,
+ dtnfsclient_nfs3_str,
+ dtnfsclient_rpcs[i].nr_v3_name,
+ dtnfsclient_start_str, 0,
+ &nfsclient_nfs3_start_probes[i]);
+ }
+ if (dtrace_probe_lookup(dtnfsclient_id, dtnfsclient_nfs3_str,
+ dtnfsclient_rpcs[i].nr_v3_name, dtnfsclient_done_str) ==
+ 0) {
+ dtnfsclient_rpcs[i].nr_v3_id_done =
+ dtrace_probe_create(dtnfsclient_id,
+ dtnfsclient_nfs3_str,
+ dtnfsclient_rpcs[i].nr_v3_name,
+ dtnfsclient_done_str, 0,
+ &nfsclient_nfs3_done_probes[i]);
+ }
+ }
+}
+
+static void
+dtnfsclient_destroy(void *arg, dtrace_id_t id, void *parg)
+{
+}
+
+static void
+dtnfsclient_enable(void *arg, dtrace_id_t id, void *parg)
+{
+ uint32_t *p = parg;
+ void *f = dtrace_probe;
+
+ if (id == nfsclient_accesscache_flush_done_id)
+ dtrace_nfsclient_accesscache_flush_done_probe = f;
+ else if (id == nfsclient_accesscache_get_hit_id)
+ dtrace_nfsclient_accesscache_get_hit_probe = f;
+ else if (id == nfsclient_accesscache_get_miss_id)
+ dtrace_nfsclient_accesscache_get_miss_probe = f;
+ else if (id == nfsclient_accesscache_load_done_id)
+ dtrace_nfsclient_accesscache_load_done_probe = f;
+ else if (id == nfsclient_attrcache_flush_done_id)
+ dtrace_nfsclient_attrcache_flush_done_probe = f;
+ else if (id == nfsclient_attrcache_get_hit_id)
+ dtrace_nfsclient_attrcache_get_hit_probe = f;
+ else if (id == nfsclient_attrcache_get_miss_id)
+ dtrace_nfsclient_attrcache_get_miss_probe = f;
+ else if (id == nfsclient_attrcache_load_done_id)
+ dtrace_nfsclient_attrcache_load_done_probe = f;
+ else
+ *p = id;
+}
+
+static void
+dtnfsclient_disable(void *arg, dtrace_id_t id, void *parg)
+{
+ uint32_t *p = parg;
+
+ if (id == nfsclient_accesscache_flush_done_id)
+ dtrace_nfsclient_accesscache_flush_done_probe = NULL;
+ else if (id == nfsclient_accesscache_get_hit_id)
+ dtrace_nfsclient_accesscache_get_hit_probe = NULL;
+ else if (id == nfsclient_accesscache_get_miss_id)
+ dtrace_nfsclient_accesscache_get_miss_probe = NULL;
+ else if (id == nfsclient_accesscache_load_done_id)
+ dtrace_nfsclient_accesscache_load_done_probe = NULL;
+ else if (id == nfsclient_attrcache_flush_done_id)
+ dtrace_nfsclient_attrcache_flush_done_probe = NULL;
+ else if (id == nfsclient_attrcache_get_hit_id)
+ dtrace_nfsclient_attrcache_get_hit_probe = NULL;
+ else if (id == nfsclient_attrcache_get_miss_id)
+ dtrace_nfsclient_attrcache_get_miss_probe = NULL;
+ else if (id == nfsclient_attrcache_load_done_id)
+ dtrace_nfsclient_attrcache_load_done_probe = NULL;
+ else
+ *p = 0;
+}
+
+static void
+dtnfsclient_load(void *dummy)
+{
+
+ if (dtrace_register("nfsclient", &dtnfsclient_attr,
+ DTRACE_PRIV_USER, NULL, &dtnfsclient_pops, NULL,
+ &dtnfsclient_id) != 0)
+ return;
+
+ dtrace_nfsclient_nfs23_start_probe =
+ (dtrace_nfsclient_nfs23_start_probe_func_t)dtrace_probe;
+ dtrace_nfsclient_nfs23_done_probe =
+ (dtrace_nfsclient_nfs23_done_probe_func_t)dtrace_probe;
+}
+
+
+static int
+dtnfsclient_unload()
+{
+ int error = 0;
+
+ dtrace_nfsclient_nfs23_start_probe = NULL;
+ dtrace_nfsclient_nfs23_done_probe = NULL;
+
+ if ((error = dtrace_unregister(dtnfsclient_id)) != 0)
+ return (error);
+
+ return (error);
+}
+
+static int
+dtnfsclient_modevent(module_t mod __unused, int type, void *data __unused)
+{
+ int error = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+ break;
+
+ case MOD_UNLOAD:
+ break;
+
+ case MOD_SHUTDOWN:
+ break;
+
+ default:
+ error = EOPNOTSUPP;
+ break;
+ }
+
+ return (error);
+}
+
+SYSINIT(dtnfsclient_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
+ dtnfsclient_load, NULL);
+SYSUNINIT(dtnfsclient_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
+ dtnfsclient_unload, NULL);
+
+DEV_MODULE(dtnfsclient, dtnfsclient_modevent, NULL);
+MODULE_VERSION(dtnfsclient, 1);
+MODULE_DEPEND(dtnfsclient, dtrace, 1, 1, 1);
+MODULE_DEPEND(dtnfsclient, opensolaris, 1, 1, 1);
diff --git a/sys/nfsclient/nfs_kdtrace.h b/sys/nfsclient/nfs_kdtrace.h
new file mode 100644
index 0000000..d29aa68
--- /dev/null
+++ b/sys/nfsclient/nfs_kdtrace.h
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 2009 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NFSCLIENT_NFS_KDTRACE_H_
+#define _NFSCLIENT_NFS_KDTRACE_H_
+
+#ifdef KDTRACE_HOOKS
+#include <sys/dtrace_bsd.h>
+
+/*
+ * Definitions for NFS access cache probes.
+ */
+extern uint32_t nfsclient_accesscache_flush_done_id;
+extern uint32_t nfsclient_accesscache_get_hit_id;
+extern uint32_t nfsclient_accesscache_get_miss_id;
+extern uint32_t nfsclient_accesscache_load_done_id;
+
+#define KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp) do { \
+ if (dtrace_nfsclient_accesscache_flush_done_probe != NULL) \
+ (dtrace_nfsclient_accesscache_flush_done_probe)( \
+ nfsclient_accesscache_flush_done_id, (vp)); \
+} while (0)
+
+#define KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp, uid, mode) do { \
+ if (dtrace_nfsclient_accesscache_get_hit_probe != NULL) \
+ (dtrace_nfsclient_accesscache_get_hit_probe)( \
+ nfsclient_accesscache_get_hit_id, (vp), (uid), \
+ (mode)); \
+} while (0)
+
+#define KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp, uid, mode) do { \
+ if (dtrace_nfsclient_accesscache_get_miss_probe != NULL) \
+ (dtrace_nfsclient_accesscache_get_miss_probe)( \
+ nfsclient_accesscache_get_miss_id, (vp), (uid), \
+ (mode)); \
+} while (0)
+
+#define KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, uid, rmode, error) do { \
+ if (dtrace_nfsclient_accesscache_load_done_probe != NULL) \
+ (dtrace_nfsclient_accesscache_load_done_probe)( \
+ nfsclient_accesscache_load_done_id, (vp), (uid), \
+ (rmode), (error)); \
+} while (0)
+
+/*
+ * Definitions for NFS attribute cache probes.
+ */
+extern uint32_t nfsclient_attrcache_flush_done_id;
+extern uint32_t nfsclient_attrcache_get_hit_id;
+extern uint32_t nfsclient_attrcache_get_miss_id;
+extern uint32_t nfsclient_attrcache_load_done_id;
+
+#define KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp) do { \
+ if (dtrace_nfsclient_attrcache_flush_done_probe != NULL) \
+ (dtrace_nfsclient_attrcache_flush_done_probe)( \
+ nfsclient_attrcache_flush_done_id, (vp)); \
+} while (0)
+
+#define KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap) do { \
+ if (dtrace_nfsclient_attrcache_get_hit_probe != NULL) \
+ (dtrace_nfsclient_attrcache_get_hit_probe)( \
+ nfsclient_attrcache_get_hit_id, (vp), (vap)); \
+} while (0)
+
+#define KDTRACE_NFS_ATTRCACHE_GET_MISS(vp) do { \
+ if (dtrace_nfsclient_attrcache_get_miss_probe != NULL) \
+ (dtrace_nfsclient_attrcache_get_miss_probe)( \
+ nfsclient_attrcache_get_miss_id, (vp)); \
+} while (0)
+
+#define KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, error) do { \
+ if (dtrace_nfsclient_attrcache_load_done_probe != NULL) \
+ (dtrace_nfsclient_attrcache_load_done_probe)( \
+ nfsclient_attrcache_load_done_id, (vp), (vap), \
+ (error)); \
+} while (0)
+
+#else /* !KDTRACE_HOOKS */
+
+#define KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp)
+#define KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp, uid, mode)
+#define KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp, uid, mode)
+#define KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, uid, rmode, error)
+
+#define KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp)
+#define KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap)
+#define KDTRACE_NFS_ATTRCACHE_GET_MISS(vp)
+#define KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, vap, error)
+
+#endif /* KDTRACE_HOOKS */
+
+#endif /* !_NFSCLIENT_NFS_KDTRACE_H_ */
diff --git a/sys/nfsclient/nfs_krpc.c b/sys/nfsclient/nfs_krpc.c
index 8a5f805..767dc0f 100644
--- a/sys/nfsclient/nfs_krpc.c
+++ b/sys/nfsclient/nfs_krpc.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
*/
#include "opt_inet6.h"
+#include "opt_kdtrace.h"
#include "opt_kgssapi.h"
#include <sys/param.h>
@@ -73,6 +74,25 @@ __FBSDID("$FreeBSD$");
#ifndef NFS_LEGACYRPC
+#ifdef KDTRACE_HOOKS
+#include <sys/dtrace_bsd.h>
+
+dtrace_nfsclient_nfs23_start_probe_func_t
+ dtrace_nfsclient_nfs23_start_probe;
+
+dtrace_nfsclient_nfs23_done_probe_func_t
+ dtrace_nfsclient_nfs23_done_probe;
+
+/*
+ * Registered probes by RPC type.
+ */
+uint32_t nfsclient_nfs2_start_probes[NFS_NPROCS];
+uint32_t nfsclient_nfs2_done_probes[NFS_NPROCS];
+
+uint32_t nfsclient_nfs3_start_probes[NFS_NPROCS];
+uint32_t nfsclient_nfs3_done_probes[NFS_NPROCS];
+#endif
+
static int nfs_realign_test;
static int nfs_realign_count;
static int nfs_bufpackets = 4;
@@ -468,6 +488,25 @@ nfs_request(struct vnode *vp, struct mbuf *mreq, int procnum,
ext.rc_timers = NULL;
}
+#ifdef KDTRACE_HOOKS
+ if (dtrace_nfsclient_nfs23_start_probe != NULL) {
+ uint32_t probe_id;
+ int probe_procnum;
+
+ if (nmp->nm_flag & NFSMNT_NFSV3) {
+ probe_id = nfsclient_nfs3_start_probes[procnum];
+ probe_procnum = procnum;
+ } else {
+ probe_id = nfsclient_nfs2_start_probes[procnum];
+ probe_procnum = (nmp->nm_flag & NFSMNT_NFSV3) ?
+ procnum : nfsv2_procid[procnum];
+ }
+ if (probe_id != 0)
+ (dtrace_nfsclient_nfs23_start_probe)(probe_id, vp,
+ mreq, cred, probe_procnum);
+ }
+#endif
+
nfsstats.rpcrequests++;
tryagain:
timo.tv_sec = nmp->nm_timeo / NFS_HZ;
@@ -493,11 +532,8 @@ tryagain:
error = EACCES;
}
md = mrep;
- if (error) {
- m_freem(mreq);
- AUTH_DESTROY(auth);
- return (error);
- }
+ if (error)
+ goto nfsmout;
KASSERT(mrep != NULL, ("mrep shouldn't be NULL if no error\n"));
@@ -521,7 +557,7 @@ tryagain:
* cache, just in case.
*/
if (error == ESTALE)
- cache_purge(vp);
+ nfs_purgecache(vp);
/*
* Skip wcc data on NFS errors for now. NetApp filers
* return corrupt postop attrs in the wcc data for NFS
@@ -535,11 +571,27 @@ tryagain:
error |= NFSERR_RETERR;
} else
m_freem(mrep);
- m_freem(mreq);
- AUTH_DESTROY(auth);
- return (error);
+ goto nfsmout;
}
+#ifdef KDTRACE_HOOKS
+ if (dtrace_nfsclient_nfs23_done_probe != NULL) {
+ uint32_t probe_id;
+ int probe_procnum;
+
+ if (nmp->nm_flag & NFSMNT_NFSV3) {
+ probe_id = nfsclient_nfs3_done_probes[procnum];
+ probe_procnum = procnum;
+ } else {
+ probe_id = nfsclient_nfs2_done_probes[procnum];
+ probe_procnum = (nmp->nm_flag & NFSMNT_NFSV3) ?
+ procnum : nfsv2_procid[procnum];
+ }
+ if (probe_id != 0)
+ (dtrace_nfsclient_nfs23_done_probe)(probe_id, vp,
+ mreq, cred, probe_procnum, 0);
+ }
+#endif
m_freem(mreq);
*mrp = mrep;
*mdp = md;
@@ -548,6 +600,24 @@ tryagain:
return (0);
nfsmout:
+#ifdef KDTRACE_HOOKS
+ if (dtrace_nfsclient_nfs23_done_probe != NULL) {
+ uint32_t probe_id;
+ int probe_procnum;
+
+ if (nmp->nm_flag & NFSMNT_NFSV3) {
+ probe_id = nfsclient_nfs3_done_probes[procnum];
+ probe_procnum = procnum;
+ } else {
+ probe_id = nfsclient_nfs2_done_probes[procnum];
+ probe_procnum = (nmp->nm_flag & NFSMNT_NFSV3) ?
+ procnum : nfsv2_procid[procnum];
+ }
+ if (probe_id != 0)
+ (dtrace_nfsclient_nfs23_done_probe)(probe_id, vp,
+ mreq, cred, probe_procnum, error);
+ }
+#endif
m_freem(mreq);
if (auth)
AUTH_DESTROY(auth);
diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c
index a61962f..8057604 100644
--- a/sys/nfsclient/nfs_socket.c
+++ b/sys/nfsclient/nfs_socket.c
@@ -1364,7 +1364,7 @@ wait_for_pinned_req:
* lookup cache, just in case.
*/
if (error == ESTALE)
- cache_purge(vp);
+ nfs_purgecache(vp);
/*
* Skip wcc data on NFS errors for now. NetApp filers return corrupt
* postop attrs in the wcc data for NFS err EROFS. Not sure if they
diff --git a/sys/nfsclient/nfs_subs.c b/sys/nfsclient/nfs_subs.c
index be6ab92..1453dbf 100644
--- a/sys/nfsclient/nfs_subs.c
+++ b/sys/nfsclient/nfs_subs.c
@@ -41,6 +41,8 @@ __FBSDID("$FreeBSD$");
* copy data between mbuf chains and uio lists.
*/
+#include "opt_kdtrace.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -69,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <nfs/nfsproto.h>
#include <nfsclient/nfs.h>
#include <nfsclient/nfsnode.h>
+#include <nfsclient/nfs_kdtrace.h>
#include <nfs/xdr_subs.h>
#include <nfsclient/nfsm_subs.h>
#include <nfsclient/nfsmount.h>
@@ -81,6 +84,24 @@ __FBSDID("$FreeBSD$");
*/
#include <machine/stdarg.h>
+#ifdef KDTRACE_HOOKS
+dtrace_nfsclient_attrcache_flush_probe_func_t
+ dtrace_nfsclient_attrcache_flush_done_probe;
+uint32_t nfsclient_attrcache_flush_done_id;
+
+dtrace_nfsclient_attrcache_get_hit_probe_func_t
+ dtrace_nfsclient_attrcache_get_hit_probe;
+uint32_t nfsclient_attrcache_get_hit_id;
+
+dtrace_nfsclient_attrcache_get_miss_probe_func_t
+ dtrace_nfsclient_attrcache_get_miss_probe;
+uint32_t nfsclient_attrcache_get_miss_id;
+
+dtrace_nfsclient_attrcache_load_probe_func_t
+ dtrace_nfsclient_attrcache_load_done_probe;
+uint32_t nfsclient_attrcache_load_done_id;
+#endif /* !KDTRACE_HOOKS */
+
/*
* Data items converted to xdr at startup, since they are constant
* This is kinda hokey, but may save a little time doing byte swaps
@@ -556,7 +577,7 @@ nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
struct vnode *vp = *vpp;
struct vattr *vap;
struct nfs_fattr *fp;
- struct nfsnode *np;
+ struct nfsnode *np = NULL;
int32_t t1;
caddr_t cp2;
int rdev;
@@ -566,12 +587,15 @@ nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
struct timespec mtime, mtime_save;
int v3 = NFS_ISV3(vp);
struct thread *td = curthread;
+ int error = 0;
md = *mdp;
t1 = (mtod(md, caddr_t) + md->m_len) - *dposp;
cp2 = nfsm_disct(mdp, dposp, NFSX_FATTR(v3), t1, M_WAIT);
- if (cp2 == NULL)
- return EBADRPC;
+ if (cp2 == NULL) {
+ error = EBADRPC;
+ goto out;
+ }
fp = (struct nfs_fattr *)cp2;
if (v3) {
vtyp = nfsv3tov_type(fp->fa_type);
@@ -684,6 +708,7 @@ nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
*/
vap->va_size = np->n_size;
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
} else if (np->n_flag & NMODIFIED) {
/*
* We've modified the file: Use the larger
@@ -716,9 +741,11 @@ nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
* We detect this by for the mtime moving back. We invalidate the
* attrcache when this happens.
*/
- if (timespeccmp(&mtime_save, &vap->va_mtime, >))
+ if (timespeccmp(&mtime_save, &vap->va_mtime, >)) {
/* Size changed or mtime went backwards */
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
+ }
if (vaper != NULL) {
bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
if (np->n_flag & NCHG) {
@@ -728,8 +755,18 @@ nfs_loadattrcache(struct vnode **vpp, struct mbuf **mdp, caddr_t *dposp,
vaper->va_mtime = np->n_mtim;
}
}
+
+#ifdef KDTRACE_HOOKS
+ if (np->n_attrstamp != 0)
+ KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, &np->n_vattr, 0);
+#endif
mtx_unlock(&np->n_mtx);
- return (0);
+out:
+#ifdef KDTRACE_HOOKS
+ if (error)
+ KDTRACE_NFS_ATTRCACHE_LOAD_DONE(vp, NULL, error);
+#endif
+ return (error);
}
#ifdef NFS_ACDEBUG
@@ -794,7 +831,8 @@ nfs_getattrcache(struct vnode *vp, struct vattr *vaper)
if ((time_second - np->n_attrstamp) >= timeo) {
nfsstats.attrcache_misses++;
mtx_unlock(&np->n_mtx);
- return( ENOENT);
+ KDTRACE_NFS_ATTRCACHE_GET_MISS(vp);
+ return (ENOENT);
}
nfsstats.attrcache_hits++;
if (vap->va_size != np->n_size) {
@@ -823,9 +861,33 @@ nfs_getattrcache(struct vnode *vp, struct vattr *vaper)
#ifdef NFS_ACDEBUG
mtx_unlock(&Giant); /* nfs_printf() */
#endif
+ KDTRACE_NFS_ATTRCACHE_GET_HIT(vp, vap);
return (0);
}
+/*
+ * Purge all cached information about an NFS vnode including name
+ * cache entries, the attribute cache, and the access cache. This is
+ * called when an NFS request for a node fails with a stale
+ * filehandle.
+ */
+void
+nfs_purgecache(struct vnode *vp)
+{
+ struct nfsnode *np;
+ int i;
+
+ np = VTONFS(vp);
+ cache_purge(vp);
+ mtx_lock(&np->n_mtx);
+ np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
+ for (i = 0; i < NFS_ACCESSCACHESIZE; i++)
+ np->n_accesscache[i].stamp = 0;
+ KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp);
+ mtx_unlock(&np->n_mtx);
+}
+
static nfsuint64 nfs_nullcookie = { { 0, 0 } };
/*
* This function finds the directory cookie that corresponds to the
diff --git a/sys/nfsclient/nfs_vnops.c b/sys/nfsclient/nfs_vnops.c
index fd44c1a..2093b3f 100644
--- a/sys/nfsclient/nfs_vnops.c
+++ b/sys/nfsclient/nfs_vnops.c
@@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$");
*/
#include "opt_inet.h"
+#include "opt_kdtrace.h"
#include <sys/param.h>
#include <sys/kernel.h>
@@ -76,6 +77,7 @@ __FBSDID("$FreeBSD$");
#include <nfsclient/nfs.h>
#include <nfsclient/nfsnode.h>
#include <nfsclient/nfsmount.h>
+#include <nfsclient/nfs_kdtrace.h>
#include <nfsclient/nfs_lock.h>
#include <nfs/xdr_subs.h>
#include <nfsclient/nfsm_subs.h>
@@ -85,6 +87,26 @@ __FBSDID("$FreeBSD$");
#include <netinet/in_var.h>
#include <netinet/vinet.h>
+#include <machine/stdarg.h>
+
+#ifdef KDTRACE_HOOKS
+#include <sys/dtrace_bsd.h>
+
+dtrace_nfsclient_accesscache_flush_probe_func_t
+ dtrace_nfsclient_accesscache_flush_done_probe;
+uint32_t nfsclient_accesscache_flush_done_id;
+
+dtrace_nfsclient_accesscache_get_probe_func_t
+ dtrace_nfsclient_accesscache_get_hit_probe,
+ dtrace_nfsclient_accesscache_get_miss_probe;
+uint32_t nfsclient_accesscache_get_hit_id;
+uint32_t nfsclient_accesscache_get_miss_id;
+
+dtrace_nfsclient_accesscache_load_probe_func_t
+ dtrace_nfsclient_accesscache_load_done_probe;
+uint32_t nfsclient_accesscache_load_done_id;
+#endif /* !KDTRACE_HOOKS */
+
/* Defs */
#define TRUE 1
#define FALSE 0
@@ -146,7 +168,6 @@ struct vop_vector nfs_vnodeops = {
.vop_getpages = nfs_getpages,
.vop_putpages = nfs_putpages,
.vop_inactive = nfs_inactive,
- .vop_lease = VOP_NULL,
.vop_link = nfs_link,
.vop_lookup = nfs_lookup,
.vop_mkdir = nfs_mkdir,
@@ -270,11 +291,11 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_misses, CTLFLAG_RD,
static int
nfs3_access_otw(struct vnode *vp, int wmode, struct thread *td,
- struct ucred *cred)
+ struct ucred *cred, uint32_t *retmode)
{
const int v3 = 1;
u_int32_t *tl;
- int error = 0, attrflag;
+ int error = 0, attrflag, i, lrupos;
struct mbuf *mreq, *mrep, *md, *mb;
caddr_t bpos, dpos;
@@ -291,16 +312,38 @@ nfs3_access_otw(struct vnode *vp, int wmode, struct thread *td,
nfsm_request(vp, NFSPROC_ACCESS, td, cred);
nfsm_postop_attr(vp, attrflag);
if (!error) {
+ lrupos = 0;
tl = nfsm_dissect(u_int32_t *, NFSX_UNSIGNED);
rmode = fxdr_unsigned(u_int32_t, *tl);
mtx_lock(&np->n_mtx);
- np->n_mode = rmode;
- np->n_modeuid = cred->cr_uid;
- np->n_modestamp = time_second;
+ for (i = 0; i < NFS_ACCESSCACHESIZE; i++) {
+ if (np->n_accesscache[i].uid == cred->cr_uid) {
+ np->n_accesscache[i].mode = rmode;
+ np->n_accesscache[i].stamp = time_second;
+ break;
+ }
+ if (i > 0 && np->n_accesscache[i].stamp <
+ np->n_accesscache[lrupos].stamp)
+ lrupos = i;
+ }
+ if (i == NFS_ACCESSCACHESIZE) {
+ np->n_accesscache[lrupos].uid = cred->cr_uid;
+ np->n_accesscache[lrupos].mode = rmode;
+ np->n_accesscache[lrupos].stamp = time_second;
+ }
mtx_unlock(&np->n_mtx);
+ if (retmode != NULL)
+ *retmode = rmode;
+ KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, rmode, 0);
}
m_freem(mrep);
nfsmout:
+#ifdef KDTRACE_HOOKS
+ if (error) {
+ KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, 0,
+ error);
+ }
+#endif
return (error);
}
@@ -314,8 +357,8 @@ static int
nfs_access(struct vop_access_args *ap)
{
struct vnode *vp = ap->a_vp;
- int error = 0;
- u_int32_t mode, wmode;
+ int error = 0, i, gotahit;
+ u_int32_t mode, rmode, wmode;
int v3 = NFS_ISV3(vp);
struct nfsnode *np = VTONFS(vp);
@@ -372,26 +415,40 @@ nfs_access(struct vop_access_args *ap)
* Does our cached result allow us to give a definite yes to
* this request?
*/
+ gotahit = 0;
mtx_lock(&np->n_mtx);
- if ((time_second < (np->n_modestamp + nfsaccess_cache_timeout)) &&
- (ap->a_cred->cr_uid == np->n_modeuid) &&
- ((np->n_mode & mode) == mode)) {
- nfsstats.accesscache_hits++;
- } else {
+ for (i = 0; i < NFS_ACCESSCACHESIZE; i++) {
+ if (ap->a_cred->cr_uid == np->n_accesscache[i].uid) {
+ if (time_second < (np->n_accesscache[i].stamp +
+ nfsaccess_cache_timeout) &&
+ (np->n_accesscache[i].mode & mode) == mode) {
+ nfsstats.accesscache_hits++;
+ gotahit = 1;
+ }
+ break;
+ }
+ }
+ mtx_unlock(&np->n_mtx);
+#ifdef KDTRACE_HOOKS
+ if (gotahit)
+ KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp,
+ ap->a_cred->cr_uid, mode);
+ else
+ KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp,
+ ap->a_cred->cr_uid, mode);
+#endif
+ if (gotahit == 0) {
/*
* Either a no, or a don't know. Go to the wire.
*/
nfsstats.accesscache_misses++;
- mtx_unlock(&np->n_mtx);
- error = nfs3_access_otw(vp, wmode, ap->a_td,ap->a_cred);
- mtx_lock(&np->n_mtx);
+ error = nfs3_access_otw(vp, wmode, ap->a_td, ap->a_cred,
+ &rmode);
if (!error) {
- if ((np->n_mode & mode) != mode) {
+ if ((rmode & mode) != mode)
error = EACCES;
- }
}
}
- mtx_unlock(&np->n_mtx);
return (error);
} else {
if ((error = nfsspec_access(ap)) != 0) {
@@ -473,6 +530,7 @@ nfs_open(struct vop_open_args *ap)
if (error == EINTR || error == EIO)
return (error);
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
if (vp->v_type == VDIR)
np->n_direofoffset = 0;
error = VOP_GETATTR(vp, &vattr, ap->a_cred);
@@ -489,6 +547,7 @@ nfs_open(struct vop_open_args *ap)
td->td_proc == NULL ||
np->n_ac_ts_pid != td->td_proc->p_pid) {
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
}
mtx_unlock(&np->n_mtx);
error = VOP_GETATTR(vp, &vattr, ap->a_cred);
@@ -651,7 +710,7 @@ nfs_getattr(struct vop_getattr_args *ap)
goto nfsmout;
if (v3 && nfs_prime_access_cache && nfsaccess_cache_timeout > 0) {
nfsstats.accesscache_misses++;
- nfs3_access_otw(vp, NFSV3ACCESS_ALL, td, ap->a_cred);
+ nfs3_access_otw(vp, NFSV3ACCESS_ALL, td, ap->a_cred, NULL);
if (nfs_getattrcache(vp, &vattr) == 0)
goto nfsmout;
}
@@ -810,7 +869,7 @@ nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred)
struct nfsnode *np = VTONFS(vp);
caddr_t bpos, dpos;
u_int32_t *tl;
- int error = 0, wccflag = NFSV3_WCCRATTR;
+ int error = 0, i, wccflag = NFSV3_WCCRATTR;
struct mbuf *mreq, *mrep, *md, *mb;
int v3 = NFS_ISV3(vp);
@@ -843,7 +902,11 @@ nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred)
}
nfsm_request(vp, NFSPROC_SETATTR, curthread, cred);
if (v3) {
- np->n_modestamp = 0;
+ mtx_lock(&np->n_mtx);
+ for (i = 0; i < NFS_ACCESSCACHESIZE; i++)
+ np->n_accesscache[i].stamp = 0;
+ mtx_unlock(&np->n_mtx);
+ KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp);
nfsm_wcc_data(vp, wccflag);
} else
nfsm_loadattr(vp, NULL);
@@ -914,6 +977,8 @@ nfs_lookup(struct vop_lookup_args *ap)
vrele(newvp);
*vpp = NULLVP;
} else if (error == ENOENT) {
+ if (dvp->v_iflag & VI_DOOMED)
+ return (ENOENT);
/*
* We only accept a negative hit in the cache if the
* modification time of the parent directory matches
@@ -1397,8 +1462,10 @@ nfsmout:
}
mtx_lock(&(VTONFS(dvp))->n_mtx);
VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag)
+ if (!wccflag) {
VTONFS(dvp)->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
+ }
mtx_unlock(&(VTONFS(dvp))->n_mtx);
return (error);
}
@@ -1529,8 +1596,10 @@ nfsmout:
}
mtx_lock(&(VTONFS(dvp))->n_mtx);
VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag)
+ if (!wccflag) {
VTONFS(dvp)->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
+ }
mtx_unlock(&(VTONFS(dvp))->n_mtx);
return (error);
}
@@ -1594,6 +1663,7 @@ nfs_remove(struct vop_remove_args *ap)
} else if (!np->n_sillyrename)
error = nfs_sillyrename(dvp, vp, cnp);
np->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
return (error);
}
@@ -1639,8 +1709,10 @@ nfs_removerpc(struct vnode *dvp, const char *name, int namelen,
nfsmout:
mtx_lock(&(VTONFS(dvp))->n_mtx);
VTONFS(dvp)->n_flag |= NMODIFIED;
- if (!wccflag)
+ if (!wccflag) {
VTONFS(dvp)->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
+ }
mtx_unlock(&(VTONFS(dvp))->n_mtx);
return (error);
}
@@ -1785,10 +1857,14 @@ nfsmout:
mtx_lock(&(VTONFS(tdvp))->n_mtx);
VTONFS(tdvp)->n_flag |= NMODIFIED;
mtx_unlock(&(VTONFS(tdvp))->n_mtx);
- if (!fwccflag)
+ if (!fwccflag) {
VTONFS(fdvp)->n_attrstamp = 0;
- if (!twccflag)
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(fdvp);
+ }
+ if (!twccflag) {
VTONFS(tdvp)->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp);
+ }
return (error);
}
@@ -1836,10 +1912,14 @@ nfsmout:
mtx_lock(&(VTONFS(tdvp))->n_mtx);
VTONFS(tdvp)->n_flag |= NMODIFIED;
mtx_unlock(&(VTONFS(tdvp))->n_mtx);
- if (!attrflag)
+ if (!attrflag) {
VTONFS(vp)->n_attrstamp = 0;
- if (!wccflag)
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
+ }
+ if (!wccflag) {
VTONFS(tdvp)->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp);
+ }
return (error);
}
@@ -1924,8 +2004,10 @@ nfsmout:
mtx_lock(&(VTONFS(dvp))->n_mtx);
VTONFS(dvp)->n_flag |= NMODIFIED;
mtx_unlock(&(VTONFS(dvp))->n_mtx);
- if (!wccflag)
+ if (!wccflag) {
VTONFS(dvp)->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
+ }
return (error);
}
@@ -1980,8 +2062,10 @@ nfsmout:
mtx_lock(&(VTONFS(dvp))->n_mtx);
VTONFS(dvp)->n_flag |= NMODIFIED;
mtx_unlock(&(VTONFS(dvp))->n_mtx);
- if (!wccflag)
+ if (!wccflag) {
VTONFS(dvp)->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
+ }
if (error == 0 && newvp == NULL) {
error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
cnp->cn_thread, &np);
@@ -2030,8 +2114,10 @@ nfsmout:
mtx_lock(&(VTONFS(dvp))->n_mtx);
VTONFS(dvp)->n_flag |= NMODIFIED;
mtx_unlock(&(VTONFS(dvp))->n_mtx);
- if (!wccflag)
+ if (!wccflag) {
VTONFS(dvp)->n_attrstamp = 0;
+ KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
+ }
cache_purge(dvp);
cache_purge(vp);
/*
diff --git a/sys/nfsclient/nfsnode.h b/sys/nfsclient/nfsnode.h
index 7781ae6..6f10d79 100644
--- a/sys/nfsclient/nfsnode.h
+++ b/sys/nfsclient/nfsnode.h
@@ -84,6 +84,12 @@ struct nfs_attrcache_timestamp {
unsigned long nfs_ac_ts_syscalls;
};
+struct nfs_accesscache {
+ u_int32_t mode; /* ACCESS mode cache */
+ uid_t uid; /* credentials having mode */
+ time_t stamp; /* mode cache timestamp */
+};
+
/*
* The nfsnode is the nfs equivalent to ufs's inode. Any similarity
* is purely coincidental.
@@ -104,9 +110,7 @@ struct nfsnode {
u_quad_t n_lrev; /* Modify rev for lease */
struct vattr n_vattr; /* Vnode attribute cache */
time_t n_attrstamp; /* Attr. cache timestamp */
- u_int32_t n_mode; /* ACCESS mode cache */
- uid_t n_modeuid; /* credentials having mode */
- time_t n_modestamp; /* mode cache timestamp */
+ struct nfs_accesscache n_accesscache[NFS_ACCESSCACHESIZE];
struct timespec n_mtime; /* Prev modify time. */
time_t n_ctime; /* Prev create time. */
time_t n_dmtime; /* Prev dir modify time. */
diff --git a/sys/nfsserver/nfs.h b/sys/nfsserver/nfs.h
index 2709377..b47ffea 100644
--- a/sys/nfsserver/nfs.h
+++ b/sys/nfsserver/nfs.h
@@ -40,6 +40,8 @@
#include "opt_nfs.h"
#endif
+#include <nfs/nfssvc.h>
+
/*
* Tunable constants for nfs
*/
@@ -116,13 +118,6 @@ struct nfsd_nfsd_args {
#endif
/*
- * Flags for nfssvc() system call.
- */
-#define NFSSVC_OLDNFSD 0x004
-#define NFSSVC_ADDSOCK 0x008
-#define NFSSVC_NFSD 0x010
-
-/*
* vfs.nfsrv sysctl(3) identifiers
*/
#define NFS_NFSRVSTATS 1 /* struct: struct nfsrvstats */
@@ -447,6 +442,13 @@ int nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct mbuf **mrq);
int nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
struct mbuf **mrq);
+/*
+ * #ifdef _SYS_SYSPROTO_H_ so that it is only defined when sysproto.h
+ * has been included, so that "struct nfssvc_args" is defined.
+ */
+#ifdef _SYS_SYSPROTO_H_
+int nfssvc_nfsserver(struct thread *, struct nfssvc_args *);
+#endif
#endif /* _KERNEL */
#endif
diff --git a/sys/nfsserver/nfs_srvkrpc.c b/sys/nfsserver/nfs_srvkrpc.c
index e52ac03..77bdec8 100644
--- a/sys/nfsserver/nfs_srvkrpc.c
+++ b/sys/nfsserver/nfs_srvkrpc.c
@@ -151,6 +151,9 @@ int32_t (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *nd,
/*
* NFS server system calls
*/
+/*
+ * This is now called from nfssvc() in nfs/nfs_nfssvc.c.
+ */
/*
* Nfs server psuedo system call for the nfsd's
@@ -163,25 +166,14 @@ int32_t (*nfsrv3_procs[NFS_NPROCS])(struct nfsrv_descript *nd,
* - sockaddr with no IPv4-mapped addresses
* - mask for both INET and INET6 families if there is IPv4-mapped overlap
*/
-#ifndef _SYS_SYSPROTO_H_
-struct nfssvc_args {
- int flag;
- caddr_t argp;
-};
-#endif
int
-nfssvc(struct thread *td, struct nfssvc_args *uap)
+nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap)
{
struct file *fp;
struct nfsd_addsock_args addsockarg;
struct nfsd_nfsd_args nfsdarg;
int error;
- KASSERT(!mtx_owned(&Giant), ("nfssvc(): called with Giant"));
-
- error = priv_check(td, PRIV_NFS_DAEMON);
- if (error)
- return (error);
if (uap->flag & NFSSVC_ADDSOCK) {
error = copyin(uap->argp, (caddr_t)&addsockarg,
sizeof(addsockarg));
@@ -208,8 +200,6 @@ nfssvc(struct thread *td, struct nfssvc_args *uap)
} else {
error = ENXIO;
}
- if (error == EINTR || error == ERESTART)
- error = 0;
return (error);
}
@@ -397,6 +387,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
#endif
#endif
inet_ntoa(sin->sin_addr), port);
+ m_freem(mreq);
svcerr_weakauth(rqst);
svc_freereq(rqst);
return;
@@ -405,6 +396,7 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
if (proc != nfsrv_null) {
if (!svc_getcred(rqst, &nd.nd_cr, &nd.nd_credflavor)) {
+ m_freem(mreq);
svcerr_weakauth(rqst);
svc_freereq(rqst);
return;
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index 00e5216..d154463 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.c
@@ -100,10 +100,6 @@ struct nfsd_head nfsd_head;
int nfsd_head_flag;
#endif
-static int nfssvc_offset = SYS_nfssvc;
-static struct sysent nfssvc_prev_sysent;
-MAKE_SYSENT(nfssvc);
-
struct mtx nfsd_mtx;
/*
@@ -519,13 +515,14 @@ static const short *nfsrv_v3errmap[] = {
nfsv3err_commit,
};
+extern int (*nfsd_call_nfsserver)(struct thread *, struct nfssvc_args *);
+
/*
* Called once to initialize data structures...
*/
static int
nfsrv_modevent(module_t mod, int type, void *data)
{
- static int registered;
int error = 0;
switch (type) {
@@ -560,11 +557,7 @@ nfsrv_modevent(module_t mod, int type, void *data)
NFSD_UNLOCK();
#endif
- error = syscall_register(&nfssvc_offset, &nfssvc_sysent,
- &nfssvc_prev_sysent);
- if (error)
- break;
- registered = 1;
+ nfsd_call_nfsserver = nfssvc_nfsserver;
break;
case MOD_UNLOAD:
@@ -573,8 +566,7 @@ nfsrv_modevent(module_t mod, int type, void *data)
break;
}
- if (registered)
- syscall_deregister(&nfssvc_offset, &nfssvc_prev_sysent);
+ nfsd_call_nfsserver = NULL;
callout_drain(&nfsrv_callout);
#ifdef NFS_LEGACYRPC
nfsrv_destroycache(); /* Free the server request cache */
@@ -596,6 +588,7 @@ DECLARE_MODULE(nfsserver, nfsserver_mod, SI_SUB_VFS, SI_ORDER_ANY);
/* So that loader and kldload(2) can find us, wherever we are.. */
MODULE_VERSION(nfsserver, 1);
+MODULE_DEPEND(nfsserver, nfssvc, 1, 1, 1);
#ifndef NFS_LEGACYRPC
MODULE_DEPEND(nfsserver, krpc, 1, 1, 1);
#endif
diff --git a/sys/nfsserver/nfs_syscalls.c b/sys/nfsserver/nfs_syscalls.c
index 326d623..59a30a3 100644
--- a/sys/nfsserver/nfs_syscalls.c
+++ b/sys/nfsserver/nfs_syscalls.c
@@ -113,6 +113,9 @@ extern u_long sb_max_adj;
*/
/*
+ * This is now called from nfssvc() in nfs/nfs_nfssvc.c.
+ */
+/*
* Nfs server psuedo system call for the nfsd's
* Based on the flag value it either:
* - adds a socket to the selection list
@@ -123,27 +126,14 @@ extern u_long sb_max_adj;
* - sockaddr with no IPv4-mapped addresses
* - mask for both INET and INET6 families if there is IPv4-mapped overlap
*/
-#ifndef _SYS_SYSPROTO_H_
-struct nfssvc_args {
- int flag;
- caddr_t argp;
-};
-#endif
int
-nfssvc(struct thread *td, struct nfssvc_args *uap)
+nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap)
{
struct file *fp;
struct sockaddr *nam;
struct nfsd_addsock_args nfsdarg;
int error;
- KASSERT(!mtx_owned(&Giant), ("nfssvc(): called with Giant"));
-
- AUDIT_ARG(cmd, uap->flag);
-
- error = priv_check(td, PRIV_NFS_DAEMON);
- if (error)
- return (error);
NFSD_LOCK();
while (nfssvc_sockhead_flag & SLP_INIT) {
nfssvc_sockhead_flag |= SLP_WANTINIT;
@@ -181,8 +171,6 @@ nfssvc(struct thread *td, struct nfssvc_args *uap)
} else {
error = ENXIO;
}
- if (error == EINTR || error == ERESTART)
- error = 0;
return (error);
}
diff --git a/sys/pc98/conf/GENERIC b/sys/pc98/conf/GENERIC
index a393748..b6adce6 100644
--- a/sys/pc98/conf/GENERIC
+++ b/sys/pc98/conf/GENERIC
@@ -265,7 +265,6 @@ device bpf # Berkeley packet filter
#device rum # Ralink Technology RT2501USB wireless NICs
#device zyd # ZyDAS zb1211/zb1211b wireless NICs
#device urio # Diamond Rio 500 MP3 player
-#device uscanner # Scanners
# USB Serial devices
#device uark # Technologies ARK3116 based serial adapters
#device ubsa # Belkin F5U103 and compatible serial adapters
diff --git a/sys/pc98/conf/NOTES b/sys/pc98/conf/NOTES
index e9d5af5..34823da 100644
--- a/sys/pc98/conf/NOTES
+++ b/sys/pc98/conf/NOTES
@@ -372,8 +372,6 @@ hint.mse.0.irq="13"
# Network interfaces:
#
-# ar: Arnet SYNC/570i hdlc sync 2/4 port V.35/X.21 serial driver
-# (requires sppp)
# ce: Cronyx Tau-PCI/32 sync single/dual port G.703/E1 serial adaptor
# with 32 HDLC subchannels (requires sppp (default), or NETGRAPH if
# NETGRAPH_CRONYX is configured)
@@ -391,13 +389,11 @@ hint.mse.0.irq="13"
# ral: Ralink Technology IEEE 802.11 wireless adapter
# sbni: Granch SBNI12-xx ISA and PCI adapters
# snc: National Semiconductor DP8393X SONIC Ethernet adapter driver
-# sr: RISCom/N2 hdlc sync 1/2 port V.35/X.21 serial driver (requires sppp)
# ural: Ralink Technology RT2500USB IEEE 802.11 wireless adapter
# ath: Atheros a/b/g WiFi adapters (requires ath_hal and wlan)
# Order for ISA/EISA devices is important here
-device ar
device ce
device cp
device cs
@@ -427,7 +423,6 @@ hint.snc.0.at="isa"
hint.snc.0.port="0x888"
hint.snc.0.irq="6"
hint.snc.0.maddr="0xc0000"
-device sr
device ural
device ath # Atheros pci/cardbus NIC's
diff --git a/sys/pc98/pc98/machdep.c b/sys/pc98/pc98/machdep.c
index 3623519..a42b903 100644
--- a/sys/pc98/pc98/machdep.c
+++ b/sys/pc98/pc98/machdep.c
@@ -525,6 +525,7 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
struct sigacts *psp;
char *sp;
struct trapframe *regs;
+ struct segment_descriptor *sdp;
int sig;
int oonstack;
@@ -561,6 +562,15 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
get_fpcontext(td, &sf.sf_uc.uc_mcontext);
fpstate_drop(td);
+ /*
+ * Unconditionally fill the fsbase and gsbase into the mcontext.
+ */
+ sdp = &td->td_pcb->pcb_gsd;
+ sf.sf_uc.uc_mcontext.mc_fsbase = sdp->sd_hibase << 24 |
+ sdp->sd_lobase;
+ sdp = &td->td_pcb->pcb_fsd;
+ sf.sf_uc.uc_mcontext.mc_gsbase = sdp->sd_hibase << 24 |
+ sdp->sd_lobase;
/* Allocate space for the signal handler context. */
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
@@ -1308,234 +1318,234 @@ extern vm_offset_t proc0kstack;
*/
struct soft_segment_descriptor gdt_segs[] = {
/* GNULL_SEL 0 Null Descriptor */
-{ 0x0, /* segment base address */
- 0x0, /* length */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* GPRIV_SEL 1 SMP Per-Processor Private Data Descriptor */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GUFS_SEL 2 %fs Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GUGS_SEL 3 %gs Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GCODE_SEL 4 Code Descriptor for kernel */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMERA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GDATA_SEL 5 Data Descriptor for kernel */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GUCODE_SEL 6 Code Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMERA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GUDATA_SEL 7 Data Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GBIOSLOWMEM_SEL 8 BIOS access to realmode segment 0x40, must be #8 in GDT */
-{ 0x400, /* segment base address */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x400,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GPROC0_SEL 9 Proc 0 Tss Descriptor */
{
- 0x0, /* segment base address */
- sizeof(struct i386tss)-1,/* length */
- SDT_SYS386TSS, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+ .ssd_base = 0x0,
+ .ssd_limit = sizeof(struct i386tss)-1,
+ .ssd_type = SDT_SYS386TSS,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* GLDT_SEL 10 LDT Descriptor */
-{ (int) ldt, /* segment base address */
- sizeof(ldt)-1, /* length - all address space */
- SDT_SYSLDT, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = (int) ldt,
+ .ssd_limit = sizeof(ldt)-1,
+ .ssd_type = SDT_SYSLDT,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* GUSERLDT_SEL 11 User LDT Descriptor per process */
-{ (int) ldt, /* segment base address */
- (512 * sizeof(union descriptor)-1), /* length */
- SDT_SYSLDT, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = (int) ldt,
+ .ssd_limit = (512 * sizeof(union descriptor)-1),
+ .ssd_type = SDT_SYSLDT,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* GPANIC_SEL 12 Panic Tss Descriptor */
-{ (int) &dblfault_tss, /* segment base address */
- sizeof(struct i386tss)-1,/* length - all address space */
- SDT_SYS386TSS, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* unused - default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = (int) &dblfault_tss,
+ .ssd_limit = sizeof(struct i386tss)-1,
+ .ssd_type = SDT_SYS386TSS,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* GBIOSCODE32_SEL 13 BIOS 32-bit interface (32bit Code) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMERA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 1 },
/* GBIOSCODE16_SEL 14 BIOS 32-bit interface (16bit Code) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMERA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 1 },
/* GBIOSDATA_SEL 15 BIOS 32-bit interface (Data) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* GBIOSUTIL_SEL 16 BIOS 16-bit interface (Utility) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 1 },
/* GBIOSARGS_SEL 17 BIOS 16-bit interface (Arguments) */
-{ 0, /* segment base address (overwritten) */
- 0xfffff, /* length */
- SDT_MEMRWA, /* segment type */
- 0, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = 0,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 1 },
/* GNDIS_SEL 18 NDIS Descriptor */
-{ 0x0, /* segment base address */
- 0x0, /* length */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
};
static struct soft_segment_descriptor ldt_segs[] = {
/* Null Descriptor - overwritten by call gate */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* Null Descriptor - overwritten by call gate */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* Null Descriptor - overwritten by call gate */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* Code Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMERA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMERA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
/* Null Descriptor - overwritten by call gate */
-{ 0x0, /* segment base address */
- 0x0, /* length - all address space */
- 0, /* segment type */
- 0, /* segment descriptor priority level */
- 0, /* segment descriptor present */
- 0, 0,
- 0, /* default 32 vs 16 bit size */
- 0 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0x0,
+ .ssd_type = 0,
+ .ssd_dpl = 0,
+ .ssd_p = 0,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 0,
+ .ssd_gran = 0 },
/* Data Descriptor for user */
-{ 0x0, /* segment base address */
- 0xfffff, /* length - all address space */
- SDT_MEMRWA, /* segment type */
- SEL_UPL, /* segment descriptor priority level */
- 1, /* segment descriptor present */
- 0, 0,
- 1, /* default 32 vs 16 bit size */
- 1 /* limit granularity (byte/page units)*/ },
+{ .ssd_base = 0x0,
+ .ssd_limit = 0xfffff,
+ .ssd_type = SDT_MEMRWA,
+ .ssd_dpl = SEL_UPL,
+ .ssd_p = 1,
+ .ssd_xx = 0, .ssd_xx1 = 0,
+ .ssd_def32 = 1,
+ .ssd_gran = 1 },
};
void
@@ -2410,6 +2420,7 @@ int
get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
{
struct trapframe *tp;
+ struct segment_descriptor *sdp;
tp = td->td_frame;
@@ -2441,6 +2452,11 @@ get_mcontext(struct thread *td, mcontext_t *mcp, int flags)
mcp->mc_ss = tp->tf_ss;
mcp->mc_len = sizeof(*mcp);
get_fpcontext(td, mcp);
+ sdp = &td->td_pcb->pcb_gsd;
+ mcp->mc_fsbase = sdp->sd_hibase << 24 | sdp->sd_lobase;
+ sdp = &td->td_pcb->pcb_fsd;
+ mcp->mc_gsbase = sdp->sd_hibase << 24 | sdp->sd_lobase;
+
return (0);
}
@@ -2775,45 +2791,24 @@ user_dbreg_trap(void)
#ifdef KDB
/*
- * Provide inb() and outb() as functions. They are normally only
- * available as macros calling inlined functions, thus cannot be
- * called from the debugger.
- *
- * The actual code is stolen from <machine/cpufunc.h>, and de-inlined.
+ * Provide inb() and outb() as functions. They are normally only available as
+ * inline functions, thus cannot be called from the debugger.
*/
-#undef inb
-#undef outb
-
/* silence compiler warnings */
-u_char inb(u_int);
-void outb(u_int, u_char);
+u_char inb_(u_short);
+void outb_(u_short, u_char);
u_char
-inb(u_int port)
+inb_(u_short port)
{
- u_char data;
- /*
- * We use %%dx and not %1 here because i/o is done at %dx and not at
- * %edx, while gcc generates inferior code (movw instead of movl)
- * if we tell it to load (u_short) port.
- */
- __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
- return (data);
+ return inb(port);
}
void
-outb(u_int port, u_char data)
+outb_(u_short port, u_char data)
{
- u_char al;
- /*
- * Use an unnecessary assignment to help gcc's register allocator.
- * This make a large difference for gcc-1.40 and a tiny difference
- * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for
- * best results. gcc-2.6.0 can't handle this.
- */
- al = data;
- __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
+ outb(port, data);
}
#endif /* KDB */
diff --git a/sys/pci/intpm.c b/sys/pci/intpm.c
index 6b71183..63eb4c4 100644
--- a/sys/pci/intpm.c
+++ b/sys/pci/intpm.c
@@ -167,10 +167,6 @@ intsmb_attach(device_t dev)
goto fail;
}
- value = pci_read_config(dev, PCI_BASE_ADDR_PM, 4);
- device_printf(dev, "PM %s %x\n", (value & 1) ? "I/O mapped" : "Memory",
- value & 0xfffe);
-
sc->isbusy = 0;
sc->smbus = device_add_child(dev, "smbus", -1);
if (sc->smbus == NULL) {
@@ -365,13 +361,13 @@ intsmb_start(struct intsmb_softc *sc, unsigned char cmd, int nointr)
tmp |= PIIX4_SMBHSTCNT_START;
/* While not in autoconfiguration enable interrupts. */
- if (!cold || !nointr)
+ if (!cold && !nointr)
tmp |= PIIX4_SMBHSTCNT_INTREN;
bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp);
}
static int
-intsmb_error(int status)
+intsmb_error(device_t dev, int status)
{
int error = 0;
@@ -381,6 +377,10 @@ intsmb_error(int status)
error |= SMB_ECOLLI;
if (status & PIIX4_SMBHSTSTAT_FAIL)
error |= SMB_ENOACK;
+
+ if (error != 0 && bootverbose)
+ device_printf(dev, "error = %d, status = %#x\n", error, status);
+
return (error);
}
@@ -410,7 +410,7 @@ intsmb_stop_poll(struct intsmb_softc *sc)
status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS);
if (!(status & PIIX4_SMBHSTSTAT_BUSY)) {
sc->isbusy = 0;
- error = intsmb_error(status);
+ error = intsmb_error(sc->dev, status);
if (error == 0 && !(status & PIIX4_SMBHSTSTAT_INTR))
device_printf(sc->dev, "unknown cause why?\n");
return (error);
@@ -442,7 +442,7 @@ intsmb_stop(struct intsmb_softc *sc)
if (error == 0) {
status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS);
if (!(status & PIIX4_SMBHSTSTAT_BUSY)) {
- error = intsmb_error(status);
+ error = intsmb_error(sc->dev, status);
if (error == 0 && !(status & PIIX4_SMBHSTSTAT_INTR))
device_printf(sc->dev, "unknown cause why?\n");
#ifdef ENABLE_ALART
diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c
index da8f35f..fb83e3a 100644
--- a/sys/powerpc/aim/machdep.c
+++ b/sys/powerpc/aim/machdep.c
@@ -117,6 +117,7 @@ __FBSDID("$FreeBSD$");
#include <machine/powerpc.h>
#include <machine/reg.h>
#include <machine/sigframe.h>
+#include <machine/spr.h>
#include <machine/trap.h>
#include <machine/vmparam.h>
@@ -130,6 +131,8 @@ extern vm_offset_t ksym_start, ksym_end;
int cold = 1;
int cacheline_size = 32;
+int ppc64 = 0;
+int hw_direct_map = 1;
struct pcpu __pcpu[MAXCPU];
@@ -230,10 +233,13 @@ cpu_startup(void *dummy)
extern char kernel_text[], _end[];
+extern void *testppc64, *testppc64size;
+extern void *restorebridge, *restorebridgesize;
+extern void *rfid_patch, *rfi_patch1, *rfi_patch2;
#ifdef SMP
extern void *rstcode, *rstsize;
#endif
-extern void *trapcode, *trapsize;
+extern void *trapcode, *trapcode64, *trapsize;
extern void *alitrap, *alisize;
extern void *dsitrap, *dsisize;
extern void *decrint, *decrsize;
@@ -245,11 +251,16 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
{
struct pcpu *pc;
vm_offset_t end;
+ void *generictrap;
+ size_t trap_offset;
void *kmdp;
char *env;
+ uint32_t msr, scratch;
+ uint8_t *cache_check;
end = 0;
kmdp = NULL;
+ trap_offset = 0;
/*
* Parse metadata if present and fetch parameters. Must be done
@@ -315,54 +326,164 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, void *mdp)
printf("powerpc_init: no loader metadata.\n");
}
+ /*
+ * Init KDB
+ */
+
kdb_init();
/*
- * XXX: Initialize the interrupt tables.
- * Disable translation in case the vector area
- * hasn't been mapped (G5)
+ * PowerPC 970 CPUs have a misfeature requested by Apple that makes
+ * them pretend they have a 32-byte cacheline. Turn this off
+ * before we measure the cacheline size.
*/
- mtmsr(mfmsr() & ~(PSL_IR | PSL_DR));
+
+ switch (mfpvr() >> 16) {
+ case IBM970:
+ case IBM970FX:
+ case IBM970MP:
+ case IBM970GX:
+ scratch = mfspr64upper(SPR_HID5,msr);
+ scratch &= ~HID5_970_DCBZ_SIZE_HI;
+ mtspr64(SPR_HID5, scratch, mfspr(SPR_HID5), msr);
+ break;
+ }
+
+ /*
+ * Initialize the interrupt tables and figure out our cache line
+ * size and whether or not we need the 64-bit bridge code.
+ */
+
+ /*
+ * Disable translation in case the vector area hasn't been
+ * mapped (G5).
+ */
+
+ msr = mfmsr();
+ mtmsr(msr & ~(PSL_IR | PSL_DR));
isync();
+
+ /*
+ * Measure the cacheline size using dcbz
+ *
+ * Use EXC_PGM as a playground. We are about to overwrite it
+ * anyway, we know it exists, and we know it is cache-aligned.
+ */
+
+ cache_check = (void *)EXC_PGM;
+
+ for (cacheline_size = 0; cacheline_size < 0x100; cacheline_size++)
+ cache_check[cacheline_size] = 0xff;
+
+ __asm __volatile("dcbz %0,0":: "r" (cache_check) : "memory");
+
+ /* Find the first byte dcbz did not zero to get the cache line size */
+ for (cacheline_size = 0; cacheline_size < 0x100 &&
+ cache_check[cacheline_size] == 0; cacheline_size++);
+
+ /*
+ * Figure out whether we need to use the 64 bit PMAP. This works by
+ * executing an instruction that is only legal on 64-bit PPC (mtmsrd),
+ * and setting ppc64 = 0 if that causes a trap.
+ */
+
+ ppc64 = 1;
+
+ bcopy(&testppc64, (void *)EXC_PGM, (size_t)&testppc64size);
+ __syncicache((void *)EXC_PGM, (size_t)&testppc64size);
+
+ __asm __volatile("\
+ mfmsr %0; \
+ mtsprg2 %1; \
+ \
+ mtmsrd %0; \
+ mfsprg2 %1;"
+ : "=r"(scratch), "=r"(ppc64));
+
+ /*
+ * Now copy restorebridge into all the handlers, if necessary,
+ * and set up the trap tables.
+ */
+
+ if (ppc64) {
+ /* Patch the two instances of rfi -> rfid */
+ bcopy(&rfid_patch,&rfi_patch1,4);
+ #ifdef KDB
+ /* rfi_patch2 is at the end of dbleave */
+ bcopy(&rfid_patch,&rfi_patch2,4);
+ #endif
+
+ /*
+ * Copy a code snippet to restore 32-bit bridge mode
+ * to the top of every non-generic trap handler
+ */
+
+ trap_offset += (size_t)&restorebridgesize;
+ bcopy(&restorebridge, (void *)EXC_RST, trap_offset);
+ bcopy(&restorebridge, (void *)EXC_DSI, trap_offset);
+ bcopy(&restorebridge, (void *)EXC_ALI, trap_offset);
+ bcopy(&restorebridge, (void *)EXC_PGM, trap_offset);
+ bcopy(&restorebridge, (void *)EXC_MCHK, trap_offset);
+ bcopy(&restorebridge, (void *)EXC_TRC, trap_offset);
+ bcopy(&restorebridge, (void *)EXC_BPT, trap_offset);
+
+ /*
+ * Set the common trap entry point to the one that
+ * knows to restore 32-bit operation on execution.
+ */
+
+ generictrap = &trapcode64;
+ } else {
+ generictrap = &trapcode;
+ }
+
#ifdef SMP
- bcopy(&rstcode, (void *)EXC_RST, (size_t)&rstsize);
+ bcopy(&rstcode, (void *)(EXC_RST + trap_offset), (size_t)&rstsize);
#else
- bcopy(&trapcode, (void *)EXC_RST, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_RST, (size_t)&trapsize);
#endif
- bcopy(&trapcode, (void *)EXC_MCHK, (size_t)&trapsize);
- bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize);
- bcopy(&trapcode, (void *)EXC_ISI, (size_t)&trapsize);
- bcopy(&trapcode, (void *)EXC_EXI, (size_t)&trapsize);
- bcopy(&alitrap, (void *)EXC_ALI, (size_t)&alisize);
- bcopy(&trapcode, (void *)EXC_PGM, (size_t)&trapsize);
- bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize);
- bcopy(&trapcode, (void *)EXC_DECR, (size_t)&trapsize);
- bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize);
- bcopy(&trapcode, (void *)EXC_TRC, (size_t)&trapsize);
- bcopy(&trapcode, (void *)EXC_FPA, (size_t)&trapsize);
- bcopy(&trapcode, (void *)EXC_VEC, (size_t)&trapsize);
- bcopy(&trapcode, (void *)EXC_VECAST, (size_t)&trapsize);
- bcopy(&trapcode, (void *)EXC_THRM, (size_t)&trapsize);
- bcopy(&trapcode, (void *)EXC_BPT, (size_t)&trapsize);
+
#ifdef KDB
- bcopy(&dblow, (void *)EXC_MCHK, (size_t)&dbsize);
- bcopy(&dblow, (void *)EXC_PGM, (size_t)&dbsize);
- bcopy(&dblow, (void *)EXC_TRC, (size_t)&dbsize);
- bcopy(&dblow, (void *)EXC_BPT, (size_t)&dbsize);
+ bcopy(&dblow, (void *)(EXC_MCHK + trap_offset), (size_t)&dbsize);
+ bcopy(&dblow, (void *)(EXC_PGM + trap_offset), (size_t)&dbsize);
+ bcopy(&dblow, (void *)(EXC_TRC + trap_offset), (size_t)&dbsize);
+ bcopy(&dblow, (void *)(EXC_BPT + trap_offset), (size_t)&dbsize);
+#else
+ bcopy(generictrap, (void *)EXC_MCHK, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_PGM, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_TRC, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_BPT, (size_t)&trapsize);
#endif
+ bcopy(&dsitrap, (void *)(EXC_DSI + trap_offset), (size_t)&dsisize);
+ bcopy(&alitrap, (void *)(EXC_ALI + trap_offset), (size_t)&alisize);
+ bcopy(generictrap, (void *)EXC_ISI, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_EXI, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_FPU, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_DECR, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_SC, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_FPA, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_VEC, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_VECAST, (size_t)&trapsize);
+ bcopy(generictrap, (void *)EXC_THRM, (size_t)&trapsize);
__syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
/*
- * Make sure translation has been enabled
+ * Restore MSR
*/
- mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI);
+ mtmsr(msr);
isync();
/*
* Initialise virtual memory.
*/
- pmap_mmu_install(MMU_TYPE_OEA, 0); /* XXX temporary */
+ if (ppc64)
+ pmap_mmu_install(MMU_TYPE_G5, 0);
+ else
+ pmap_mmu_install(MMU_TYPE_OEA, 0);
+
pmap_bootstrap(startkernel, endkernel);
+ mtmsr(mfmsr() | PSL_IR|PSL_DR|PSL_ME|PSL_RI);
+ isync();
/*
* Initialize params/tunables that are derived from memsize
diff --git a/sys/powerpc/aim/mmu_oea.c b/sys/powerpc/aim/mmu_oea.c
index 158b2ab..71947fa 100644
--- a/sys/powerpc/aim/mmu_oea.c
+++ b/sys/powerpc/aim/mmu_oea.c
@@ -323,6 +323,7 @@ void moea_zero_page_area(mmu_t, vm_page_t, int, int);
void moea_zero_page_idle(mmu_t, vm_page_t);
void moea_activate(mmu_t, struct thread *);
void moea_deactivate(mmu_t, struct thread *);
+void moea_cpu_bootstrap(mmu_t, int);
void moea_bootstrap(mmu_t, vm_offset_t, vm_offset_t);
void *moea_mapdev(mmu_t, vm_offset_t, vm_size_t);
void moea_unmapdev(mmu_t, vm_offset_t, vm_size_t);
@@ -364,6 +365,7 @@ static mmu_method_t moea_methods[] = {
/* Internal interfaces */
MMUMETHOD(mmu_bootstrap, moea_bootstrap),
+ MMUMETHOD(mmu_cpu_bootstrap, moea_cpu_bootstrap),
MMUMETHOD(mmu_mapdev, moea_mapdev),
MMUMETHOD(mmu_unmapdev, moea_unmapdev),
MMUMETHOD(mmu_kextract, moea_kextract),
@@ -617,7 +619,7 @@ om_cmp(const void *a, const void *b)
}
void
-pmap_cpu_bootstrap(int ap)
+moea_cpu_bootstrap(mmu_t mmup, int ap)
{
u_int sdr;
int i;
@@ -709,6 +711,9 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
__asm __volatile("mtdbatl 1,%0" :: "r"(battable[8].batl));
isync();
+ /* set global direct map flag */
+ hw_direct_map = 1;
+
mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
CTR0(KTR_PMAP, "moea_bootstrap: physical memory");
@@ -895,7 +900,7 @@ moea_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
kernel_pmap->pm_sr[KERNEL2_SR] = KERNEL2_SEGMENT;
kernel_pmap->pm_active = ~0;
- pmap_cpu_bootstrap(0);
+ moea_cpu_bootstrap(mmup,0);
pmap_bootstrapped++;
diff --git a/sys/powerpc/aim/mmu_oea64.c b/sys/powerpc/aim/mmu_oea64.c
new file mode 100644
index 0000000..64e8c75
--- /dev/null
+++ b/sys/powerpc/aim/mmu_oea64.c
@@ -0,0 +1,2443 @@
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas <matt@3am-software.com> of Allegro Networks, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: pmap.c,v 1.28 2000/03/26 20:42:36 kleink Exp $
+ */
+/*-
+ * Copyright (C) 2001 Benno Rice.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Manages physical address maps.
+ *
+ * In addition to hardware address maps, this module is called upon to
+ * provide software-use-only maps which may or may not be stored in the
+ * same form as hardware maps. These pseudo-maps are used to store
+ * intermediate results from copy operations to and from address spaces.
+ *
+ * Since the information managed by this module is also stored by the
+ * logical address mapping module, this module may throw away valid virtual
+ * to physical mappings at almost any time. However, invalidations of
+ * mappings must be done as requested.
+ *
+ * In order to cope with hardware architectures which make virtual to
+ * physical map invalidates expensive, this module may delay invalidate
+ * reduced protection operations until such time as they are actually
+ * necessary. This module is given full information as to which processors
+ * are currently using which maps, and to when physical maps must be made
+ * correct.
+ */
+
+#include "opt_kstack_pages.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/ktr.h>
+#include <sys/lock.h>
+#include <sys/msgbuf.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/vmmeter.h>
+
+#include <sys/kdb.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/vm_kern.h>
+#include <vm/vm_page.h>
+#include <vm/vm_map.h>
+#include <vm/vm_object.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_pageout.h>
+#include <vm/vm_pager.h>
+#include <vm/uma.h>
+
+#include <machine/cpu.h>
+#include <machine/powerpc.h>
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/psl.h>
+#include <machine/bat.h>
+#include <machine/pte.h>
+#include <machine/sr.h>
+#include <machine/trap.h>
+#include <machine/mmuvar.h>
+
+#include "mmu_if.h"
+
+#define MOEA_DEBUG
+
+#define TODO panic("%s: not implemented", __func__);
+
+static __inline u_int32_t
+cntlzw(volatile u_int32_t a) {
+ u_int32_t b;
+ __asm ("cntlzw %0, %1" : "=r"(b) : "r"(a));
+ return b;
+}
+
+static __inline uint64_t
+va_to_vsid(pmap_t pm, vm_offset_t va)
+{
+ return ((pm->pm_sr[(uintptr_t)va >> ADDR_SR_SHFT]) & SR_VSID_MASK);
+}
+
+#define TLBSYNC() __asm __volatile("tlbsync; ptesync");
+#define SYNC() __asm __volatile("sync");
+#define EIEIO() __asm __volatile("eieio");
+
+/*
+ * The tlbie instruction must be executed in 64-bit mode
+ * so we have to twiddle MSR[SF] around every invocation.
+ * Just to add to the fun, exceptions must be off as well
+ * so that we can't trap in 64-bit mode. What a pain.
+ */
+
+static __inline void
+TLBIE(pmap_t pmap, vm_offset_t va) {
+ register_t msr;
+ register_t scratch;
+
+ uint64_t vpn;
+ register_t vpn_hi, vpn_lo;
+
+#if 1
+ /*
+ * CPU documentation says that tlbie takes the VPN, not the
+ * VA. I think the code below does this correctly. We will see.
+ */
+
+ vpn = (uint64_t)(va & ADDR_PIDX);
+ if (pmap != NULL)
+ vpn |= (va_to_vsid(pmap,va) << 28);
+#else
+ vpn = va;
+#endif
+
+ vpn_hi = (uint32_t)(vpn >> 32);
+ vpn_lo = (uint32_t)vpn;
+
+ __asm __volatile("\
+ mfmsr %0; \
+ clrldi %1,%0,49; \
+ insrdi %1,1,1,0; \
+ mtmsrd %1; \
+ ptesync; \
+ \
+ sld %1,%2,%4; \
+ or %1,%1,%3; \
+ tlbie %1; \
+ \
+ mtmsrd %0; \
+ eieio; \
+ tlbsync; \
+ ptesync;"
+ : "=r"(msr), "=r"(scratch) : "r"(vpn_hi), "r"(vpn_lo), "r"(32));
+}
+
+#define DISABLE_TRANS(msr) msr = mfmsr(); mtmsr(msr & ~PSL_DR); isync()
+#define ENABLE_TRANS(msr) mtmsr(msr); isync()
+
+#define VSID_MAKE(sr, hash) ((sr) | (((hash) & 0xfffff) << 4))
+#define VSID_TO_SR(vsid) ((vsid) & 0xf)
+#define VSID_TO_HASH(vsid) (((vsid) >> 4) & 0xfffff)
+
+#define PVO_PTEGIDX_MASK 0x007 /* which PTEG slot */
+#define PVO_PTEGIDX_VALID 0x008 /* slot is valid */
+#define PVO_WIRED 0x010 /* PVO entry is wired */
+#define PVO_MANAGED 0x020 /* PVO entry is managed */
+#define PVO_BOOTSTRAP 0x080 /* PVO entry allocated during
+ bootstrap */
+#define PVO_FAKE 0x100 /* fictitious phys page */
+#define PVO_VADDR(pvo) ((pvo)->pvo_vaddr & ~ADDR_POFF)
+#define PVO_ISFAKE(pvo) ((pvo)->pvo_vaddr & PVO_FAKE)
+#define PVO_PTEGIDX_GET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_MASK)
+#define PVO_PTEGIDX_ISSET(pvo) ((pvo)->pvo_vaddr & PVO_PTEGIDX_VALID)
+#define PVO_PTEGIDX_CLR(pvo) \
+ ((void)((pvo)->pvo_vaddr &= ~(PVO_PTEGIDX_VALID|PVO_PTEGIDX_MASK)))
+#define PVO_PTEGIDX_SET(pvo, i) \
+ ((void)((pvo)->pvo_vaddr |= (i)|PVO_PTEGIDX_VALID))
+
+#define MOEA_PVO_CHECK(pvo)
+
+#define LOCK_TABLE() mtx_lock(&moea64_table_mutex)
+#define UNLOCK_TABLE() mtx_unlock(&moea64_table_mutex);
+#define ASSERT_TABLE_LOCK() mtx_assert(&moea64_table_mutex, MA_OWNED)
+
+struct ofw_map {
+ vm_offset_t om_va;
+ vm_size_t om_len;
+ vm_offset_t om_pa_hi;
+ vm_offset_t om_pa_lo;
+ u_int om_mode;
+};
+
+/*
+ * Map of physical memory regions.
+ */
+static struct mem_region *regions;
+static struct mem_region *pregions;
+extern u_int phys_avail_count;
+extern int regions_sz, pregions_sz;
+extern int ofw_real_mode;
+static struct ofw_map translations[64];
+
+extern struct pmap ofw_pmap;
+
+extern void bs_remap_earlyboot(void);
+
+
+/*
+ * Lock for the pteg and pvo tables.
+ */
+struct mtx moea64_table_mutex;
+
+/*
+ * PTEG data.
+ */
+static struct lpteg *moea64_pteg_table;
+u_int moea64_pteg_count;
+u_int moea64_pteg_mask;
+
+/*
+ * PVO data.
+ */
+struct pvo_head *moea64_pvo_table; /* pvo entries by pteg index */
+/* lists of unmanaged pages */
+struct pvo_head moea64_pvo_kunmanaged =
+ LIST_HEAD_INITIALIZER(moea64_pvo_kunmanaged);
+struct pvo_head moea64_pvo_unmanaged =
+ LIST_HEAD_INITIALIZER(moea64_pvo_unmanaged);
+
+uma_zone_t moea64_upvo_zone; /* zone for pvo entries for unmanaged pages */
+uma_zone_t moea64_mpvo_zone; /* zone for pvo entries for managed pages */
+
+vm_offset_t pvo_allocator_start;
+vm_offset_t pvo_allocator_end;
+
+#define BPVO_POOL_SIZE 327680
+static struct pvo_entry *moea64_bpvo_pool;
+static int moea64_bpvo_pool_index = 0;
+
+#define VSID_NBPW (sizeof(u_int32_t) * 8)
+static u_int moea64_vsid_bitmap[NPMAPS / VSID_NBPW];
+
+static boolean_t moea64_initialized = FALSE;
+
+/*
+ * Statistics.
+ */
+u_int moea64_pte_valid = 0;
+u_int moea64_pte_overflow = 0;
+u_int moea64_pvo_entries = 0;
+u_int moea64_pvo_enter_calls = 0;
+u_int moea64_pvo_remove_calls = 0;
+SYSCTL_INT(_machdep, OID_AUTO, moea64_pte_valid, CTLFLAG_RD,
+ &moea64_pte_valid, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea64_pte_overflow, CTLFLAG_RD,
+ &moea64_pte_overflow, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea64_pvo_entries, CTLFLAG_RD,
+ &moea64_pvo_entries, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea64_pvo_enter_calls, CTLFLAG_RD,
+ &moea64_pvo_enter_calls, 0, "");
+SYSCTL_INT(_machdep, OID_AUTO, moea64_pvo_remove_calls, CTLFLAG_RD,
+ &moea64_pvo_remove_calls, 0, "");
+
+vm_offset_t moea64_scratchpage_va[2];
+struct pvo_entry *moea64_scratchpage_pvo[2];
+struct lpte *moea64_scratchpage_pte[2];
+struct mtx moea64_scratchpage_mtx;
+
+/*
+ * Allocate physical memory for use in moea64_bootstrap.
+ */
+static vm_offset_t moea64_bootstrap_alloc(vm_size_t, u_int);
+
+/*
+ * PTE calls.
+ */
+static int moea64_pte_insert(u_int, struct lpte *);
+
+/*
+ * PVO calls.
+ */
+static int moea64_pvo_enter(pmap_t, uma_zone_t, struct pvo_head *,
+ vm_offset_t, vm_offset_t, uint64_t, int, int);
+static void moea64_pvo_remove(struct pvo_entry *, int);
+static struct pvo_entry *moea64_pvo_find_va(pmap_t, vm_offset_t, int *);
+static struct lpte *moea64_pvo_to_pte(const struct pvo_entry *, int);
+
+/*
+ * Utility routines.
+ */
+static void moea64_bridge_bootstrap(mmu_t mmup,
+ vm_offset_t kernelstart, vm_offset_t kernelend);
+static void moea64_bridge_cpu_bootstrap(mmu_t, int ap);
+static void moea64_enter_locked(pmap_t, vm_offset_t, vm_page_t,
+ vm_prot_t, boolean_t);
+static boolean_t moea64_query_bit(vm_page_t, u_int64_t);
+static u_int moea64_clear_bit(vm_page_t, u_int64_t, u_int64_t *);
+static void moea64_kremove(mmu_t, vm_offset_t);
+static void moea64_syncicache(pmap_t pmap, vm_offset_t va,
+ vm_offset_t pa);
+static void tlbia(void);
+
+/*
+ * Kernel MMU interface
+ */
+void moea64_change_wiring(mmu_t, pmap_t, vm_offset_t, boolean_t);
+void moea64_clear_modify(mmu_t, vm_page_t);
+void moea64_clear_reference(mmu_t, vm_page_t);
+void moea64_copy_page(mmu_t, vm_page_t, vm_page_t);
+void moea64_enter(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t, boolean_t);
+void moea64_enter_object(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_page_t,
+ vm_prot_t);
+void moea64_enter_quick(mmu_t, pmap_t, vm_offset_t, vm_page_t, vm_prot_t);
+vm_paddr_t moea64_extract(mmu_t, pmap_t, vm_offset_t);
+vm_page_t moea64_extract_and_hold(mmu_t, pmap_t, vm_offset_t, vm_prot_t);
+void moea64_init(mmu_t);
+boolean_t moea64_is_modified(mmu_t, vm_page_t);
+boolean_t moea64_ts_referenced(mmu_t, vm_page_t);
+vm_offset_t moea64_map(mmu_t, vm_offset_t *, vm_offset_t, vm_offset_t, int);
+boolean_t moea64_page_exists_quick(mmu_t, pmap_t, vm_page_t);
+int moea64_page_wired_mappings(mmu_t, vm_page_t);
+void moea64_pinit(mmu_t, pmap_t);
+void moea64_pinit0(mmu_t, pmap_t);
+void moea64_protect(mmu_t, pmap_t, vm_offset_t, vm_offset_t, vm_prot_t);
+void moea64_qenter(mmu_t, vm_offset_t, vm_page_t *, int);
+void moea64_qremove(mmu_t, vm_offset_t, int);
+void moea64_release(mmu_t, pmap_t);
+void moea64_remove(mmu_t, pmap_t, vm_offset_t, vm_offset_t);
+void moea64_remove_all(mmu_t, vm_page_t);
+void moea64_remove_write(mmu_t, vm_page_t);
+void moea64_zero_page(mmu_t, vm_page_t);
+void moea64_zero_page_area(mmu_t, vm_page_t, int, int);
+void moea64_zero_page_idle(mmu_t, vm_page_t);
+void moea64_activate(mmu_t, struct thread *);
+void moea64_deactivate(mmu_t, struct thread *);
+void *moea64_mapdev(mmu_t, vm_offset_t, vm_size_t);
+void moea64_unmapdev(mmu_t, vm_offset_t, vm_size_t);
+vm_offset_t moea64_kextract(mmu_t, vm_offset_t);
+void moea64_kenter(mmu_t, vm_offset_t, vm_offset_t);
+boolean_t moea64_dev_direct_mapped(mmu_t, vm_offset_t, vm_size_t);
+boolean_t moea64_page_executable(mmu_t, vm_page_t);
+
+static mmu_method_t moea64_bridge_methods[] = {
+ MMUMETHOD(mmu_change_wiring, moea64_change_wiring),
+ MMUMETHOD(mmu_clear_modify, moea64_clear_modify),
+ MMUMETHOD(mmu_clear_reference, moea64_clear_reference),
+ MMUMETHOD(mmu_copy_page, moea64_copy_page),
+ MMUMETHOD(mmu_enter, moea64_enter),
+ MMUMETHOD(mmu_enter_object, moea64_enter_object),
+ MMUMETHOD(mmu_enter_quick, moea64_enter_quick),
+ MMUMETHOD(mmu_extract, moea64_extract),
+ MMUMETHOD(mmu_extract_and_hold, moea64_extract_and_hold),
+ MMUMETHOD(mmu_init, moea64_init),
+ MMUMETHOD(mmu_is_modified, moea64_is_modified),
+ MMUMETHOD(mmu_ts_referenced, moea64_ts_referenced),
+ MMUMETHOD(mmu_map, moea64_map),
+ MMUMETHOD(mmu_page_exists_quick,moea64_page_exists_quick),
+ MMUMETHOD(mmu_page_wired_mappings,moea64_page_wired_mappings),
+ MMUMETHOD(mmu_pinit, moea64_pinit),
+ MMUMETHOD(mmu_pinit0, moea64_pinit0),
+ MMUMETHOD(mmu_protect, moea64_protect),
+ MMUMETHOD(mmu_qenter, moea64_qenter),
+ MMUMETHOD(mmu_qremove, moea64_qremove),
+ MMUMETHOD(mmu_release, moea64_release),
+ MMUMETHOD(mmu_remove, moea64_remove),
+ MMUMETHOD(mmu_remove_all, moea64_remove_all),
+ MMUMETHOD(mmu_remove_write, moea64_remove_write),
+ MMUMETHOD(mmu_zero_page, moea64_zero_page),
+ MMUMETHOD(mmu_zero_page_area, moea64_zero_page_area),
+ MMUMETHOD(mmu_zero_page_idle, moea64_zero_page_idle),
+ MMUMETHOD(mmu_activate, moea64_activate),
+ MMUMETHOD(mmu_deactivate, moea64_deactivate),
+
+ /* Internal interfaces */
+ MMUMETHOD(mmu_bootstrap, moea64_bridge_bootstrap),
+ MMUMETHOD(mmu_cpu_bootstrap, moea64_bridge_cpu_bootstrap),
+ MMUMETHOD(mmu_mapdev, moea64_mapdev),
+ MMUMETHOD(mmu_unmapdev, moea64_unmapdev),
+ MMUMETHOD(mmu_kextract, moea64_kextract),
+ MMUMETHOD(mmu_kenter, moea64_kenter),
+ MMUMETHOD(mmu_dev_direct_mapped,moea64_dev_direct_mapped),
+ MMUMETHOD(mmu_page_executable, moea64_page_executable),
+
+ { 0, 0 }
+};
+
+static mmu_def_t oea64_bridge_mmu = {
+ MMU_TYPE_G5,
+ moea64_bridge_methods,
+ 0
+};
+MMU_DEF(oea64_bridge_mmu);
+
+static __inline u_int
+va_to_pteg(uint64_t vsid, vm_offset_t addr)
+{
+ u_int hash;
+
+ hash = vsid ^ (((uint64_t)addr & ADDR_PIDX) >>
+ ADDR_PIDX_SHFT);
+ return (hash & moea64_pteg_mask);
+}
+
+static __inline struct pvo_head *
+pa_to_pvoh(vm_offset_t pa, vm_page_t *pg_p)
+{
+ struct vm_page *pg;
+
+ pg = PHYS_TO_VM_PAGE(pa);
+
+ if (pg_p != NULL)
+ *pg_p = pg;
+
+ if (pg == NULL)
+ return (&moea64_pvo_unmanaged);
+
+ return (&pg->md.mdpg_pvoh);
+}
+
+static __inline struct pvo_head *
+vm_page_to_pvoh(vm_page_t m)
+{
+
+ return (&m->md.mdpg_pvoh);
+}
+
+static __inline void
+moea64_attr_clear(vm_page_t m, u_int64_t ptebit)
+{
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ m->md.mdpg_attrs &= ~ptebit;
+}
+
+static __inline u_int64_t
+moea64_attr_fetch(vm_page_t m)
+{
+
+ return (m->md.mdpg_attrs);
+}
+
+static __inline void
+moea64_attr_save(vm_page_t m, u_int64_t ptebit)
+{
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ m->md.mdpg_attrs |= ptebit;
+}
+
+static __inline int
+moea64_pte_compare(const struct lpte *pt, const struct lpte *pvo_pt)
+{
+ if (pt->pte_hi == pvo_pt->pte_hi)
+ return (1);
+
+ return (0);
+}
+
+static __inline int
+moea64_pte_match(struct lpte *pt, uint64_t vsid, vm_offset_t va, int which)
+{
+ return (pt->pte_hi & ~LPTE_VALID) ==
+ ((vsid << LPTE_VSID_SHIFT) |
+ ((uint64_t)(va >> ADDR_API_SHFT64) & LPTE_API) | which);
+}
+
+static __inline void
+moea64_pte_create(struct lpte *pt, uint64_t vsid, vm_offset_t va,
+ uint64_t pte_lo)
+{
+ ASSERT_TABLE_LOCK();
+
+ /*
+ * Construct a PTE. Default to IMB initially. Valid bit only gets
+ * set when the real pte is set in memory.
+ *
+ * Note: Don't set the valid bit for correct operation of tlb update.
+ */
+ pt->pte_hi = (vsid << LPTE_VSID_SHIFT) |
+ (((uint64_t)(va & ADDR_PIDX) >> ADDR_API_SHFT64) & LPTE_API);
+
+ pt->pte_lo = pte_lo;
+}
+
+static __inline void
+moea64_pte_synch(struct lpte *pt, struct lpte *pvo_pt)
+{
+
+ ASSERT_TABLE_LOCK();
+
+ pvo_pt->pte_lo |= pt->pte_lo & (LPTE_REF | LPTE_CHG);
+}
+
+static __inline void
+moea64_pte_clear(struct lpte *pt, pmap_t pmap, vm_offset_t va, u_int64_t ptebit)
+{
+ ASSERT_TABLE_LOCK();
+
+ /*
+ * As shown in Section 7.6.3.2.3
+ */
+ pt->pte_lo &= ~ptebit;
+ TLBIE(pmap,va);
+}
+
+static __inline void
+moea64_pte_set(struct lpte *pt, struct lpte *pvo_pt)
+{
+
+ ASSERT_TABLE_LOCK();
+ pvo_pt->pte_hi |= LPTE_VALID;
+
+ /*
+ * Update the PTE as defined in section 7.6.3.1.
+ * Note that the REF/CHG bits are from pvo_pt and thus should have
+ * been saved so this routine can restore them (if desired).
+ */
+ pt->pte_lo = pvo_pt->pte_lo;
+ EIEIO();
+ pt->pte_hi = pvo_pt->pte_hi;
+ SYNC();
+ moea64_pte_valid++;
+}
+
+static __inline void
+moea64_pte_unset(struct lpte *pt, struct lpte *pvo_pt, pmap_t pmap, vm_offset_t va)
+{
+ ASSERT_TABLE_LOCK();
+ pvo_pt->pte_hi &= ~LPTE_VALID;
+
+ /*
+ * Force the reg & chg bits back into the PTEs.
+ */
+ SYNC();
+
+ /*
+ * Invalidate the pte.
+ */
+ pt->pte_hi &= ~LPTE_VALID;
+
+ TLBIE(pmap,va);
+
+ /*
+ * Save the reg & chg bits.
+ */
+ moea64_pte_synch(pt, pvo_pt);
+ moea64_pte_valid--;
+}
+
+static __inline void
+moea64_pte_change(struct lpte *pt, struct lpte *pvo_pt, pmap_t pmap, vm_offset_t va)
+{
+
+ /*
+ * Invalidate the PTE
+ */
+ moea64_pte_unset(pt, pvo_pt, pmap, va);
+ moea64_pte_set(pt, pvo_pt);
+}
+
+static __inline uint64_t
+moea64_calc_wimg(vm_offset_t pa)
+{
+ uint64_t pte_lo;
+ int i;
+
+ /*
+ * Assume the page is cache inhibited and access is guarded unless
+ * it's in our available memory array.
+ */
+ pte_lo = LPTE_I | LPTE_G;
+ for (i = 0; i < pregions_sz; i++) {
+ if ((pa >= pregions[i].mr_start) &&
+ (pa < (pregions[i].mr_start + pregions[i].mr_size))) {
+ pte_lo &= ~(LPTE_I | LPTE_G);
+ pte_lo |= LPTE_M;
+ break;
+ }
+ }
+
+ return pte_lo;
+}
+
+/*
+ * Quick sort callout for comparing memory regions.
+ */
+static int mr_cmp(const void *a, const void *b);
+static int om_cmp(const void *a, const void *b);
+
+static int
+mr_cmp(const void *a, const void *b)
+{
+ const struct mem_region *regiona;
+ const struct mem_region *regionb;
+
+ regiona = a;
+ regionb = b;
+ if (regiona->mr_start < regionb->mr_start)
+ return (-1);
+ else if (regiona->mr_start > regionb->mr_start)
+ return (1);
+ else
+ return (0);
+}
+
+static int
+om_cmp(const void *a, const void *b)
+{
+ const struct ofw_map *mapa;
+ const struct ofw_map *mapb;
+
+ mapa = a;
+ mapb = b;
+ if (mapa->om_pa_hi < mapb->om_pa_hi)
+ return (-1);
+ else if (mapa->om_pa_hi > mapb->om_pa_hi)
+ return (1);
+ else if (mapa->om_pa_lo < mapb->om_pa_lo)
+ return (-1);
+ else if (mapa->om_pa_lo > mapb->om_pa_lo)
+ return (1);
+ else
+ return (0);
+}
+
+static void
+moea64_bridge_cpu_bootstrap(mmu_t mmup, int ap)
+{
+ int i = 0;
+
+ /*
+ * Initialize segment registers and MMU
+ */
+
+ mtmsr(mfmsr() & ~PSL_DR & ~PSL_IR); isync();
+ for (i = 0; i < 16; i++) {
+ mtsrin(i << ADDR_SR_SHFT, kernel_pmap->pm_sr[i]);
+ }
+ __asm __volatile ("sync; mtsdr1 %0; isync"
+ :: "r"((u_int)moea64_pteg_table
+ | (32 - cntlzw(moea64_pteg_mask >> 11))));
+ tlbia();
+}
+
+static void
+moea64_bridge_bootstrap(mmu_t mmup, vm_offset_t kernelstart, vm_offset_t kernelend)
+{
+ ihandle_t mmui;
+ phandle_t chosen;
+ phandle_t mmu;
+ int sz;
+ int i, j;
+ int ofw_mappings;
+ vm_size_t size, physsz, hwphyssz;
+ vm_offset_t pa, va, off;
+ uint32_t msr;
+
+ /* We don't have a direct map since there is no BAT */
+ hw_direct_map = 0;
+
+ /* Make sure battable is zero, since we have no BAT */
+ for (i = 0; i < 16; i++) {
+ battable[i].batu = 0;
+ battable[i].batl = 0;
+ }
+
+ /* Get physical memory regions from firmware */
+ mem_regions(&pregions, &pregions_sz, &regions, &regions_sz);
+ CTR0(KTR_PMAP, "moea64_bootstrap: physical memory");
+
+ qsort(pregions, pregions_sz, sizeof(*pregions), mr_cmp);
+ if (sizeof(phys_avail)/sizeof(phys_avail[0]) < regions_sz)
+ panic("moea64_bootstrap: phys_avail too small");
+ qsort(regions, regions_sz, sizeof(*regions), mr_cmp);
+ phys_avail_count = 0;
+ physsz = 0;
+ hwphyssz = 0;
+ TUNABLE_ULONG_FETCH("hw.physmem", (u_long *) &hwphyssz);
+ for (i = 0, j = 0; i < regions_sz; i++, j += 2) {
+ CTR3(KTR_PMAP, "region: %#x - %#x (%#x)", regions[i].mr_start,
+ regions[i].mr_start + regions[i].mr_size,
+ regions[i].mr_size);
+ if (hwphyssz != 0 &&
+ (physsz + regions[i].mr_size) >= hwphyssz) {
+ if (physsz < hwphyssz) {
+ phys_avail[j] = regions[i].mr_start;
+ phys_avail[j + 1] = regions[i].mr_start +
+ hwphyssz - physsz;
+ physsz = hwphyssz;
+ phys_avail_count++;
+ }
+ break;
+ }
+ phys_avail[j] = regions[i].mr_start;
+ phys_avail[j + 1] = regions[i].mr_start + regions[i].mr_size;
+ phys_avail_count++;
+ physsz += regions[i].mr_size;
+ }
+ physmem = btoc(physsz);
+
+ /*
+ * Allocate PTEG table.
+ */
+#ifdef PTEGCOUNT
+ moea64_pteg_count = PTEGCOUNT;
+#else
+ moea64_pteg_count = 0x1000;
+
+ while (moea64_pteg_count < physmem)
+ moea64_pteg_count <<= 1;
+
+ moea64_pteg_count >>= 1;
+#endif /* PTEGCOUNT */
+
+ size = moea64_pteg_count * sizeof(struct lpteg);
+ CTR2(KTR_PMAP, "moea64_bootstrap: %d PTEGs, %d bytes",
+ moea64_pteg_count, size);
+
+ /*
+ * We now need to allocate memory. This memory, to be allocated,
+ * has to reside in a page table. The page table we are about to
+ * allocate. We don't have BAT. So drop to data real mode for a minute
+ * as a measure of last resort. We do this a couple times.
+ */
+
+ moea64_pteg_table = (struct lpteg *)moea64_bootstrap_alloc(size, size);
+ DISABLE_TRANS(msr);
+ bzero((void *)moea64_pteg_table, moea64_pteg_count * sizeof(struct lpteg));
+ ENABLE_TRANS(msr);
+
+ moea64_pteg_mask = moea64_pteg_count - 1;
+
+ CTR1(KTR_PMAP, "moea64_bootstrap: PTEG table at %p", moea64_pteg_table);
+
+ /*
+ * Allocate pv/overflow lists.
+ */
+ size = sizeof(struct pvo_head) * moea64_pteg_count;
+
+ moea64_pvo_table = (struct pvo_head *)moea64_bootstrap_alloc(size,
+ PAGE_SIZE);
+ CTR1(KTR_PMAP, "moea64_bootstrap: PVO table at %p", moea64_pvo_table);
+
+ DISABLE_TRANS(msr);
+ for (i = 0; i < moea64_pteg_count; i++)
+ LIST_INIT(&moea64_pvo_table[i]);
+ ENABLE_TRANS(msr);
+
+ /*
+ * Initialize the lock that synchronizes access to the pteg and pvo
+ * tables.
+ */
+ mtx_init(&moea64_table_mutex, "pmap table", NULL, MTX_DEF |
+ MTX_RECURSE);
+
+ /*
+ * Initialise the unmanaged pvo pool.
+ */
+ moea64_bpvo_pool = (struct pvo_entry *)moea64_bootstrap_alloc(
+ BPVO_POOL_SIZE*sizeof(struct pvo_entry), 0);
+ moea64_bpvo_pool_index = 0;
+
+ /*
+ * Make sure kernel vsid is allocated as well as VSID 0.
+ */
+ moea64_vsid_bitmap[(KERNEL_VSIDBITS & (NPMAPS - 1)) / VSID_NBPW]
+ |= 1 << (KERNEL_VSIDBITS % VSID_NBPW);
+ moea64_vsid_bitmap[0] |= 1;
+
+ /*
+ * Initialize the kernel pmap (which is statically allocated).
+ */
+ for (i = 0; i < 16; i++)
+ kernel_pmap->pm_sr[i] = EMPTY_SEGMENT + i;
+
+ kernel_pmap->pmap_phys = kernel_pmap;
+ kernel_pmap->pm_active = ~0;
+
+ PMAP_LOCK_INIT(kernel_pmap);
+
+ /*
+ * Now map in all the other buffers we allocated earlier
+ */
+
+ DISABLE_TRANS(msr);
+ size = moea64_pteg_count * sizeof(struct lpteg);
+ off = (vm_offset_t)(moea64_pteg_table);
+ for (pa = off; pa < off + size; pa += PAGE_SIZE)
+ moea64_kenter(mmup, pa, pa);
+ size = sizeof(struct pvo_head) * moea64_pteg_count;
+ off = (vm_offset_t)(moea64_pvo_table);
+ for (pa = off; pa < off + size; pa += PAGE_SIZE)
+ moea64_kenter(mmup, pa, pa);
+ size = BPVO_POOL_SIZE*sizeof(struct pvo_entry);
+ off = (vm_offset_t)(moea64_bpvo_pool);
+ for (pa = off; pa < off + size; pa += PAGE_SIZE)
+ moea64_kenter(mmup, pa, pa);
+ ENABLE_TRANS(msr);
+
+ /*
+ * Map certain important things, like ourselves and the exception
+ * vectors
+ */
+
+ DISABLE_TRANS(msr);
+ for (pa = kernelstart & ~PAGE_MASK; pa < kernelend; pa += PAGE_SIZE)
+ moea64_kenter(mmup, pa, pa);
+ for (pa = EXC_RSVD; pa < EXC_LAST; pa += PAGE_SIZE)
+ moea64_kenter(mmup, pa, pa);
+ ENABLE_TRANS(msr);
+
+ if (!ofw_real_mode) {
+ /*
+ * Set up the Open Firmware pmap and add its mappings.
+ */
+
+ moea64_pinit(mmup, &ofw_pmap);
+ ofw_pmap.pm_sr[KERNEL_SR] = kernel_pmap->pm_sr[KERNEL_SR];
+ ofw_pmap.pm_sr[KERNEL2_SR] = kernel_pmap->pm_sr[KERNEL2_SR];
+
+ if ((chosen = OF_finddevice("/chosen")) == -1)
+ panic("moea64_bootstrap: can't find /chosen");
+ OF_getprop(chosen, "mmu", &mmui, 4);
+ if ((mmu = OF_instance_to_package(mmui)) == -1)
+ panic("moea64_bootstrap: can't get mmu package");
+ if ((sz = OF_getproplen(mmu, "translations")) == -1)
+ panic("moea64_bootstrap: can't get ofw translation count");
+
+ bzero(translations, sz);
+ if (OF_getprop(mmu, "translations", translations, sz) == -1)
+ panic("moea64_bootstrap: can't get ofw translations");
+
+ CTR0(KTR_PMAP, "moea64_bootstrap: translations");
+ sz /= sizeof(*translations);
+ qsort(translations, sz, sizeof (*translations), om_cmp);
+
+ for (i = 0, ofw_mappings = 0; i < sz; i++) {
+ CTR3(KTR_PMAP, "translation: pa=%#x va=%#x len=%#x",
+ (uint32_t)(translations[i].om_pa_lo), translations[i].om_va,
+ translations[i].om_len);
+
+ if (translations[i].om_pa_lo % PAGE_SIZE)
+ panic("OFW translation not page-aligned!");
+
+ if (translations[i].om_pa_hi)
+ panic("OFW translations above 32-bit boundary!");
+
+ /* Now enter the pages for this mapping */
+
+ /*
+ * Lock the ofw pmap. pmap_kenter(), which we use for the
+ * pages the kernel also needs, does its own locking.
+ */
+ PMAP_LOCK(&ofw_pmap);
+ DISABLE_TRANS(msr);
+ for (off = 0; off < translations[i].om_len; off += PAGE_SIZE) {
+ struct vm_page m;
+
+ /* Map low memory mappings into the kernel pmap, too.
+ * These are typically mappings made by the loader,
+ * so we need them if we want to keep executing. */
+
+ if (translations[i].om_va + off < SEGMENT_LENGTH)
+ moea64_kenter(mmup, translations[i].om_va + off,
+ translations[i].om_va + off);
+
+ m.phys_addr = translations[i].om_pa_lo + off;
+ moea64_enter_locked(&ofw_pmap,
+ translations[i].om_va + off, &m, VM_PROT_ALL, 1);
+
+ ofw_mappings++;
+ }
+ ENABLE_TRANS(msr);
+ PMAP_UNLOCK(&ofw_pmap);
+ }
+ }
+
+#ifdef SMP
+ TLBSYNC();
+#endif
+
+ /*
+ * Calculate the last available physical address.
+ */
+ for (i = 0; phys_avail[i + 2] != 0; i += 2)
+ ;
+ Maxmem = powerpc_btop(phys_avail[i + 1]);
+
+ /*
+ * Initialize MMU and remap early physical mappings
+ */
+ moea64_bridge_cpu_bootstrap(mmup,0);
+ mtmsr(mfmsr() | PSL_DR | PSL_IR); isync();
+ pmap_bootstrapped++;
+ bs_remap_earlyboot();
+
+ /*
+ * Set the start and end of kva.
+ */
+ virtual_avail = VM_MIN_KERNEL_ADDRESS;
+ virtual_end = VM_MAX_KERNEL_ADDRESS;
+
+ /*
+ * Allocate some stupid buffer regions.
+ */
+
+ pvo_allocator_start = virtual_avail;
+ virtual_avail += SEGMENT_LENGTH/4;
+ pvo_allocator_end = virtual_avail;
+
+ /*
+ * Allocate some things for page zeroing
+ */
+
+ mtx_init(&moea64_scratchpage_mtx, "pvo zero page", NULL, MTX_DEF);
+ for (i = 0; i < 2; i++) {
+ moea64_scratchpage_va[i] = virtual_avail;
+ virtual_avail += PAGE_SIZE;
+
+ moea64_kenter(mmup,moea64_scratchpage_va[i],kernelstart);
+
+ LOCK_TABLE();
+ moea64_scratchpage_pvo[i] = moea64_pvo_find_va(kernel_pmap,
+ moea64_scratchpage_va[i],&j);
+ moea64_scratchpage_pte[i] = moea64_pvo_to_pte(
+ moea64_scratchpage_pvo[i],j);
+ UNLOCK_TABLE();
+ }
+
+ /*
+ * Allocate a kernel stack with a guard page for thread0 and map it
+ * into the kernel page map.
+ */
+ pa = moea64_bootstrap_alloc(KSTACK_PAGES * PAGE_SIZE, PAGE_SIZE);
+ va = virtual_avail + KSTACK_GUARD_PAGES * PAGE_SIZE;
+ virtual_avail = va + KSTACK_PAGES * PAGE_SIZE;
+ CTR2(KTR_PMAP, "moea_bootstrap: kstack0 at %#x (%#x)", pa, va);
+ thread0.td_kstack = va;
+ thread0.td_kstack_pages = KSTACK_PAGES;
+ for (i = 0; i < KSTACK_PAGES; i++) {
+ moea64_kenter(mmup, va, pa);;
+ pa += PAGE_SIZE;
+ va += PAGE_SIZE;
+ }
+
+ /*
+ * Allocate virtual address space for the message buffer.
+ */
+ pa = msgbuf_phys = moea64_bootstrap_alloc(MSGBUF_SIZE, PAGE_SIZE);
+ msgbufp = (struct msgbuf *)virtual_avail;
+ va = virtual_avail;
+ virtual_avail += round_page(MSGBUF_SIZE);
+ while (va < virtual_avail) {
+ moea64_kenter(mmup, va, pa);;
+ pa += PAGE_SIZE;
+ va += PAGE_SIZE;
+ }
+}
+
+/*
+ * Activate a user pmap. The pmap must be activated before it's address
+ * space can be accessed in any way.
+ */
+void
+moea64_activate(mmu_t mmu, struct thread *td)
+{
+ pmap_t pm, pmr;
+
+ /*
+ * Load all the data we need up front to encourage the compiler to
+ * not issue any loads while we have interrupts disabled below.
+ */
+ pm = &td->td_proc->p_vmspace->vm_pmap;
+ pmr = pm->pmap_phys;
+
+ pm->pm_active |= PCPU_GET(cpumask);
+ PCPU_SET(curpmap, pmr);
+}
+
+void
+moea64_deactivate(mmu_t mmu, struct thread *td)
+{
+ pmap_t pm;
+
+ pm = &td->td_proc->p_vmspace->vm_pmap;
+ pm->pm_active &= ~(PCPU_GET(cpumask));
+ PCPU_SET(curpmap, NULL);
+}
+
+void
+moea64_change_wiring(mmu_t mmu, pmap_t pm, vm_offset_t va, boolean_t wired)
+{
+ struct pvo_entry *pvo;
+
+ PMAP_LOCK(pm);
+ pvo = moea64_pvo_find_va(pm, va & ~ADDR_POFF, NULL);
+
+ if (pvo != NULL) {
+ if (wired) {
+ if ((pvo->pvo_vaddr & PVO_WIRED) == 0)
+ pm->pm_stats.wired_count++;
+ pvo->pvo_vaddr |= PVO_WIRED;
+ } else {
+ if ((pvo->pvo_vaddr & PVO_WIRED) != 0)
+ pm->pm_stats.wired_count--;
+ pvo->pvo_vaddr &= ~PVO_WIRED;
+ }
+ }
+ PMAP_UNLOCK(pm);
+}
+
+/*
+ * Zero a page of physical memory by temporarily mapping it into the tlb.
+ */
+void
+moea64_zero_page(mmu_t mmu, vm_page_t m)
+{
+ moea64_zero_page_area(mmu,m,0,PAGE_SIZE);
+}
+
+/*
+ * This goes through and sets the physical address of our
+ * special scratch PTE to the PA we want to zero or copy. Because
+ * of locking issues (this can get called in pvo_enter() by
+ * the UMA allocator), we can't use most other utility functions here
+ */
+
+static __inline
+void moea64_set_scratchpage_pa(int which, vm_offset_t pa) {
+ moea64_scratchpage_pvo[which]->pvo_pte.lpte.pte_lo &=
+ (~LPTE_WIMG & ~LPTE_RPGN);
+ moea64_scratchpage_pvo[which]->pvo_pte.lpte.pte_lo |=
+ moea64_calc_wimg(pa) | (uint64_t)pa;
+
+ moea64_scratchpage_pte[which]->pte_hi &= ~LPTE_VALID;
+ TLBIE(kernel_pmap, moea64_scratchpage_va[which]);
+
+ moea64_scratchpage_pte[which]->pte_lo =
+ moea64_scratchpage_pvo[which]->pvo_pte.lpte.pte_lo;
+ EIEIO();
+
+ moea64_scratchpage_pte[which]->pte_hi |= LPTE_VALID;
+ TLBIE(kernel_pmap, moea64_scratchpage_va[which]);
+}
+
+void
+moea64_copy_page(mmu_t mmu, vm_page_t msrc, vm_page_t mdst)
+{
+ vm_offset_t dst;
+ vm_offset_t src;
+
+ dst = VM_PAGE_TO_PHYS(mdst);
+ src = VM_PAGE_TO_PHYS(msrc);
+
+ mtx_lock(&moea64_scratchpage_mtx);
+
+ moea64_set_scratchpage_pa(0,src);
+ moea64_set_scratchpage_pa(1,dst);
+
+ kcopy((void *)moea64_scratchpage_va[0],
+ (void *)moea64_scratchpage_va[1], PAGE_SIZE);
+
+ __syncicache((void *)moea64_scratchpage_va[1],PAGE_SIZE);
+
+ mtx_unlock(&moea64_scratchpage_mtx);
+}
+
+void
+moea64_zero_page_area(mmu_t mmu, vm_page_t m, int off, int size)
+{
+ vm_offset_t pa = VM_PAGE_TO_PHYS(m);
+
+ if (!moea64_initialized)
+ panic("moea64_zero_page: can't zero pa %#x", pa);
+ if (size + off > PAGE_SIZE)
+ panic("moea64_zero_page: size + off > PAGE_SIZE");
+
+ mtx_lock(&moea64_scratchpage_mtx);
+
+ moea64_set_scratchpage_pa(0,pa);
+ bzero((caddr_t)moea64_scratchpage_va[0] + off, size);
+ __syncicache((void *)moea64_scratchpage_va[0],PAGE_SIZE);
+
+ mtx_unlock(&moea64_scratchpage_mtx);
+}
+
+void
+moea64_zero_page_idle(mmu_t mmu, vm_page_t m)
+{
+
+ moea64_zero_page(mmu, m);
+}
+
+/*
+ * Map the given physical page at the specified virtual address in the
+ * target pmap with the protection requested. If specified the page
+ * will be wired down.
+ */
+void
+moea64_enter(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_page_t m,
+ vm_prot_t prot, boolean_t wired)
+{
+
+ vm_page_lock_queues();
+ PMAP_LOCK(pmap);
+ moea64_enter_locked(pmap, va, m, prot, wired);
+ vm_page_unlock_queues();
+ PMAP_UNLOCK(pmap);
+}
+
+/*
+ * Map the given physical page at the specified virtual address in the
+ * target pmap with the protection requested. If specified the page
+ * will be wired down.
+ *
+ * The page queues and pmap must be locked.
+ */
+
+static void
+moea64_enter_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
+ boolean_t wired)
+{
+ struct pvo_head *pvo_head;
+ uma_zone_t zone;
+ vm_page_t pg;
+ uint64_t pte_lo;
+ u_int pvo_flags;
+ int error;
+
+ if (!moea64_initialized) {
+ pvo_head = &moea64_pvo_kunmanaged;
+ pg = NULL;
+ zone = moea64_upvo_zone;
+ pvo_flags = 0;
+ } else {
+ pvo_head = vm_page_to_pvoh(m);
+ pg = m;
+ zone = moea64_mpvo_zone;
+ pvo_flags = PVO_MANAGED;
+ }
+
+ if (pmap_bootstrapped)
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ PMAP_LOCK_ASSERT(pmap, MA_OWNED);
+
+ /* XXX change the pvo head for fake pages */
+ if ((m->flags & PG_FICTITIOUS) == PG_FICTITIOUS) {
+ pvo_flags &= ~PVO_MANAGED;
+ pvo_head = &moea64_pvo_kunmanaged;
+ zone = moea64_upvo_zone;
+ }
+
+ pte_lo = moea64_calc_wimg(VM_PAGE_TO_PHYS(m));
+
+ if (prot & VM_PROT_WRITE) {
+ pte_lo |= LPTE_BW;
+ if (pmap_bootstrapped)
+ vm_page_flag_set(m, PG_WRITEABLE);
+ } else
+ pte_lo |= LPTE_BR;
+
+ if (prot & VM_PROT_EXECUTE)
+ pvo_flags |= VM_PROT_EXECUTE;
+
+ if (wired)
+ pvo_flags |= PVO_WIRED;
+
+ if ((m->flags & PG_FICTITIOUS) != 0)
+ pvo_flags |= PVO_FAKE;
+
+ error = moea64_pvo_enter(pmap, zone, pvo_head, va, VM_PAGE_TO_PHYS(m),
+ pte_lo, pvo_flags, 0);
+
+ if (pmap == kernel_pmap)
+ TLBIE(pmap, va);
+
+ /*
+ * Flush the page from the instruction cache if this page is
+ * mapped executable and cacheable.
+ */
+ if ((pte_lo & (LPTE_I | LPTE_G | LPTE_NOEXEC)) == 0) {
+ moea64_syncicache(pmap, va, VM_PAGE_TO_PHYS(m));
+ }
+}
+
+static void
+moea64_syncicache(pmap_t pmap, vm_offset_t va, vm_offset_t pa)
+{
+ /*
+ * This is much trickier than on older systems because
+ * we can't sync the icache on physical addresses directly
+ * without a direct map. Instead we check a couple of cases
+ * where the memory is already mapped in and, failing that,
+ * use the same trick we use for page zeroing to create
+ * a temporary mapping for this physical address.
+ */
+
+ if (!pmap_bootstrapped) {
+ /*
+ * If PMAP is not bootstrapped, we are likely to be
+ * in real mode.
+ */
+ __syncicache((void *)pa,PAGE_SIZE);
+ } else if (pmap == kernel_pmap) {
+ __syncicache((void *)va,PAGE_SIZE);
+ } else {
+ /* Use the scratch page to set up a temp mapping */
+
+ mtx_lock(&moea64_scratchpage_mtx);
+
+ moea64_set_scratchpage_pa(1,pa);
+ __syncicache((void *)moea64_scratchpage_va[1],PAGE_SIZE);
+
+ mtx_unlock(&moea64_scratchpage_mtx);
+ }
+}
+
+/*
+ * Maps a sequence of resident pages belonging to the same object.
+ * The sequence begins with the given page m_start. This page is
+ * mapped at the given virtual address start. Each subsequent page is
+ * mapped at a virtual address that is offset from start by the same
+ * amount as the page is offset from m_start within the object. The
+ * last page in the sequence is the page with the largest offset from
+ * m_start that can be mapped at a virtual address less than the given
+ * virtual address end. Not every virtual page between start and end
+ * is mapped; only those for which a resident page exists with the
+ * corresponding offset from m_start are mapped.
+ */
+void
+moea64_enter_object(mmu_t mmu, pmap_t pm, vm_offset_t start, vm_offset_t end,
+ vm_page_t m_start, vm_prot_t prot)
+{
+ vm_page_t m;
+ vm_pindex_t diff, psize;
+
+ psize = atop(end - start);
+ m = m_start;
+ PMAP_LOCK(pm);
+ while (m != NULL && (diff = m->pindex - m_start->pindex) < psize) {
+ moea64_enter_locked(pm, start + ptoa(diff), m, prot &
+ (VM_PROT_READ | VM_PROT_EXECUTE), FALSE);
+ m = TAILQ_NEXT(m, listq);
+ }
+ PMAP_UNLOCK(pm);
+}
+
+void
+moea64_enter_quick(mmu_t mmu, pmap_t pm, vm_offset_t va, vm_page_t m,
+ vm_prot_t prot)
+{
+ PMAP_LOCK(pm);
+ moea64_enter_locked(pm, va, m, prot & (VM_PROT_READ | VM_PROT_EXECUTE),
+ FALSE);
+ PMAP_UNLOCK(pm);
+
+}
+
+vm_paddr_t
+moea64_extract(mmu_t mmu, pmap_t pm, vm_offset_t va)
+{
+ struct pvo_entry *pvo;
+ vm_paddr_t pa;
+
+ PMAP_LOCK(pm);
+ pvo = moea64_pvo_find_va(pm, va & ~ADDR_POFF, NULL);
+ if (pvo == NULL)
+ pa = 0;
+ else
+ pa = (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) | (va & ADDR_POFF);
+ PMAP_UNLOCK(pm);
+ return (pa);
+}
+
+/*
+ * Atomically extract and hold the physical page with the given
+ * pmap and virtual address pair if that mapping permits the given
+ * protection.
+ */
+vm_page_t
+moea64_extract_and_hold(mmu_t mmu, pmap_t pmap, vm_offset_t va, vm_prot_t prot)
+{
+ struct pvo_entry *pvo;
+ vm_page_t m;
+
+ m = NULL;
+ vm_page_lock_queues();
+ PMAP_LOCK(pmap);
+ pvo = moea64_pvo_find_va(pmap, va & ~ADDR_POFF, NULL);
+ if (pvo != NULL && (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) &&
+ ((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) == LPTE_RW ||
+ (prot & VM_PROT_WRITE) == 0)) {
+ m = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
+ vm_page_hold(m);
+ }
+ vm_page_unlock_queues();
+ PMAP_UNLOCK(pmap);
+ return (m);
+}
+
+static void *
+moea64_uma_page_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
+{
+ /*
+ * This entire routine is a horrible hack to avoid bothering kmem
+ * for new KVA addresses. Because this can get called from inside
+ * kmem allocation routines, calling kmem for a new address here
+ * can lead to multiply locking non-recursive mutexes.
+ */
+ static vm_pindex_t color;
+ vm_offset_t va;
+
+ vm_page_t m;
+ int pflags, needed_lock;
+
+ *flags = UMA_SLAB_PRIV;
+ needed_lock = !PMAP_LOCKED(kernel_pmap);
+
+ if (needed_lock)
+ PMAP_LOCK(kernel_pmap);
+
+ if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT)
+ pflags = VM_ALLOC_INTERRUPT | VM_ALLOC_WIRED;
+ else
+ pflags = VM_ALLOC_SYSTEM | VM_ALLOC_WIRED;
+ if (wait & M_ZERO)
+ pflags |= VM_ALLOC_ZERO;
+
+ for (;;) {
+ m = vm_page_alloc(NULL, color++, pflags | VM_ALLOC_NOOBJ);
+ if (m == NULL) {
+ if (wait & M_NOWAIT)
+ return (NULL);
+ VM_WAIT;
+ } else
+ break;
+ }
+
+ va = pvo_allocator_start;
+ pvo_allocator_start += PAGE_SIZE;
+
+ if (pvo_allocator_start >= pvo_allocator_end)
+ panic("Ran out of PVO allocator buffer space!");
+
+ /* Now call pvo_enter in recursive mode */
+ moea64_pvo_enter(kernel_pmap, moea64_upvo_zone,
+ &moea64_pvo_kunmanaged, va, VM_PAGE_TO_PHYS(m), LPTE_M,
+ PVO_WIRED | PVO_BOOTSTRAP, 1);
+
+ TLBIE(kernel_pmap, va);
+
+ if (needed_lock)
+ PMAP_UNLOCK(kernel_pmap);
+
+ if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
+ bzero((void *)va, PAGE_SIZE);
+
+ return (void *)va;
+}
+
+void
+moea64_init(mmu_t mmu)
+{
+
+ CTR0(KTR_PMAP, "moea64_init");
+
+ moea64_upvo_zone = uma_zcreate("UPVO entry", sizeof (struct pvo_entry),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
+ UMA_ZONE_VM | UMA_ZONE_NOFREE);
+ moea64_mpvo_zone = uma_zcreate("MPVO entry", sizeof(struct pvo_entry),
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR,
+ UMA_ZONE_VM | UMA_ZONE_NOFREE);
+
+ if (!hw_direct_map) {
+ uma_zone_set_allocf(moea64_upvo_zone,moea64_uma_page_alloc);
+ uma_zone_set_allocf(moea64_mpvo_zone,moea64_uma_page_alloc);
+ }
+
+ moea64_initialized = TRUE;
+}
+
+boolean_t
+moea64_is_modified(mmu_t mmu, vm_page_t m)
+{
+
+ if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0)
+ return (FALSE);
+
+ return (moea64_query_bit(m, LPTE_CHG));
+}
+
+void
+moea64_clear_reference(mmu_t mmu, vm_page_t m)
+{
+
+ if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0)
+ return;
+ moea64_clear_bit(m, LPTE_REF, NULL);
+}
+
+void
+moea64_clear_modify(mmu_t mmu, vm_page_t m)
+{
+
+ if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0)
+ return;
+ moea64_clear_bit(m, LPTE_CHG, NULL);
+}
+
+/*
+ * Clear the write and modified bits in each of the given page's mappings.
+ */
+void
+moea64_remove_write(mmu_t mmu, vm_page_t m)
+{
+ struct pvo_entry *pvo;
+ struct lpte *pt;
+ pmap_t pmap;
+ uint64_t lo;
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0 ||
+ (m->flags & PG_WRITEABLE) == 0)
+ return;
+ lo = moea64_attr_fetch(m);
+ SYNC();
+ LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+ pmap = pvo->pvo_pmap;
+ PMAP_LOCK(pmap);
+ if ((pvo->pvo_pte.lpte.pte_lo & LPTE_PP) != LPTE_BR) {
+ LOCK_TABLE();
+ pt = moea64_pvo_to_pte(pvo, -1);
+ pvo->pvo_pte.lpte.pte_lo &= ~LPTE_PP;
+ pvo->pvo_pte.lpte.pte_lo |= LPTE_BR;
+ if (pt != NULL) {
+ moea64_pte_synch(pt, &pvo->pvo_pte.lpte);
+ lo |= pvo->pvo_pte.lpte.pte_lo;
+ pvo->pvo_pte.lpte.pte_lo &= ~LPTE_CHG;
+ moea64_pte_change(pt, &pvo->pvo_pte.lpte,
+ pvo->pvo_pmap, pvo->pvo_vaddr);
+ }
+ UNLOCK_TABLE();
+ }
+ PMAP_UNLOCK(pmap);
+ }
+ if ((lo & LPTE_CHG) != 0) {
+ moea64_attr_clear(m, LPTE_CHG);
+ vm_page_dirty(m);
+ }
+ vm_page_flag_clear(m, PG_WRITEABLE);
+}
+
+/*
+ * moea64_ts_referenced:
+ *
+ * Return a count of reference bits for a page, clearing those bits.
+ * It is not necessary for every reference bit to be cleared, but it
+ * is necessary that 0 only be returned when there are truly no
+ * reference bits set.
+ *
+ * XXX: The exact number of bits to check and clear is a matter that
+ * should be tested and standardized at some point in the future for
+ * optimal aging of shared pages.
+ */
+boolean_t
+moea64_ts_referenced(mmu_t mmu, vm_page_t m)
+{
+ int count;
+
+ if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) != 0)
+ return (0);
+
+ count = moea64_clear_bit(m, LPTE_REF, NULL);
+
+ return (count);
+}
+
+/*
+ * Map a wired page into kernel virtual address space.
+ */
+void
+moea64_kenter(mmu_t mmu, vm_offset_t va, vm_offset_t pa)
+{
+ uint64_t pte_lo;
+ int error;
+
+ if (!pmap_bootstrapped) {
+ if (va >= VM_MIN_KERNEL_ADDRESS && va < VM_MAX_KERNEL_ADDRESS)
+ panic("Trying to enter an address in KVA -- %#x!\n",pa);
+ }
+
+ pte_lo = moea64_calc_wimg(pa);
+
+ PMAP_LOCK(kernel_pmap);
+ error = moea64_pvo_enter(kernel_pmap, moea64_upvo_zone,
+ &moea64_pvo_kunmanaged, va, pa, pte_lo,
+ PVO_WIRED | VM_PROT_EXECUTE, 0);
+
+ TLBIE(kernel_pmap, va);
+
+ if (error != 0 && error != ENOENT)
+ panic("moea64_kenter: failed to enter va %#x pa %#x: %d", va,
+ pa, error);
+
+ /*
+ * Flush the memory from the instruction cache.
+ */
+ if ((pte_lo & (LPTE_I | LPTE_G)) == 0) {
+ __syncicache((void *)va, PAGE_SIZE);
+ }
+ PMAP_UNLOCK(kernel_pmap);
+}
+
+/*
+ * Extract the physical page address associated with the given kernel virtual
+ * address.
+ */
+vm_offset_t
+moea64_kextract(mmu_t mmu, vm_offset_t va)
+{
+ struct pvo_entry *pvo;
+ vm_paddr_t pa;
+
+ PMAP_LOCK(kernel_pmap);
+ pvo = moea64_pvo_find_va(kernel_pmap, va & ~ADDR_POFF, NULL);
+ KASSERT(pvo != NULL, ("moea64_kextract: no addr found"));
+ pa = (pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) | (va & ADDR_POFF);
+ PMAP_UNLOCK(kernel_pmap);
+ return (pa);
+}
+
+/*
+ * Remove a wired page from kernel virtual address space.
+ */
+void
+moea64_kremove(mmu_t mmu, vm_offset_t va)
+{
+ moea64_remove(mmu, kernel_pmap, va, va + PAGE_SIZE);
+}
+
+/*
+ * Map a range of physical addresses into kernel virtual address space.
+ *
+ * The value passed in *virt is a suggested virtual address for the mapping.
+ * Architectures which can support a direct-mapped physical to virtual region
+ * can return the appropriate address within that region, leaving '*virt'
+ * unchanged. We cannot and therefore do not; *virt is updated with the
+ * first usable address after the mapped region.
+ */
+vm_offset_t
+moea64_map(mmu_t mmu, vm_offset_t *virt, vm_offset_t pa_start,
+ vm_offset_t pa_end, int prot)
+{
+ vm_offset_t sva, va;
+
+ sva = *virt;
+ va = sva;
+ for (; pa_start < pa_end; pa_start += PAGE_SIZE, va += PAGE_SIZE)
+ moea64_kenter(mmu, va, pa_start);
+ *virt = va;
+
+ return (sva);
+}
+
+/*
+ * Returns true if the pmap's pv is one of the first
+ * 16 pvs linked to from this page. This count may
+ * be changed upwards or downwards in the future; it
+ * is only necessary that true be returned for a small
+ * subset of pmaps for proper page aging.
+ */
+boolean_t
+moea64_page_exists_quick(mmu_t mmu, pmap_t pmap, vm_page_t m)
+{
+ int loops;
+ struct pvo_entry *pvo;
+
+ if (!moea64_initialized || (m->flags & PG_FICTITIOUS))
+ return FALSE;
+
+ loops = 0;
+ LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+ if (pvo->pvo_pmap == pmap)
+ return (TRUE);
+ if (++loops >= 16)
+ break;
+ }
+
+ return (FALSE);
+}
+
+/*
+ * Return the number of managed mappings to the given physical page
+ * that are wired.
+ */
+int
+moea64_page_wired_mappings(mmu_t mmu, vm_page_t m)
+{
+ struct pvo_entry *pvo;
+ int count;
+
+ count = 0;
+ if (!moea64_initialized || (m->flags & PG_FICTITIOUS) != 0)
+ return (count);
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+ LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink)
+ if ((pvo->pvo_vaddr & PVO_WIRED) != 0)
+ count++;
+ return (count);
+}
+
+static u_int moea64_vsidcontext;
+
+void
+moea64_pinit(mmu_t mmu, pmap_t pmap)
+{
+ int i, mask;
+ u_int entropy;
+
+ PMAP_LOCK_INIT(pmap);
+
+ entropy = 0;
+ __asm __volatile("mftb %0" : "=r"(entropy));
+
+ if (pmap_bootstrapped)
+ pmap->pmap_phys = (pmap_t)moea64_kextract(mmu, (vm_offset_t)pmap);
+ else
+ pmap->pmap_phys = pmap;
+
+ /*
+ * Allocate some segment registers for this pmap.
+ */
+ for (i = 0; i < NPMAPS; i += VSID_NBPW) {
+ u_int hash, n;
+
+ /*
+ * Create a new value by mutiplying by a prime and adding in
+ * entropy from the timebase register. This is to make the
+ * VSID more random so that the PT hash function collides
+ * less often. (Note that the prime casues gcc to do shifts
+ * instead of a multiply.)
+ */
+ moea64_vsidcontext = (moea64_vsidcontext * 0x1105) + entropy;
+ hash = moea64_vsidcontext & (NPMAPS - 1);
+ if (hash == 0) /* 0 is special, avoid it */
+ continue;
+ n = hash >> 5;
+ mask = 1 << (hash & (VSID_NBPW - 1));
+ hash = (moea64_vsidcontext & 0xfffff);
+ if (moea64_vsid_bitmap[n] & mask) { /* collision? */
+ /* anything free in this bucket? */
+ if (moea64_vsid_bitmap[n] == 0xffffffff) {
+ entropy = (moea64_vsidcontext >> 20);
+ continue;
+ }
+ i = ffs(~moea64_vsid_bitmap[i]) - 1;
+ mask = 1 << i;
+ hash &= 0xfffff & ~(VSID_NBPW - 1);
+ hash |= i;
+ }
+ moea64_vsid_bitmap[n] |= mask;
+ for (i = 0; i < 16; i++) {
+ pmap->pm_sr[i] = VSID_MAKE(i, hash);
+ }
+ return;
+ }
+
+ panic("moea64_pinit: out of segments");
+}
+
+/*
+ * Initialize the pmap associated with process 0.
+ */
+void
+moea64_pinit0(mmu_t mmu, pmap_t pm)
+{
+ moea64_pinit(mmu, pm);
+ bzero(&pm->pm_stats, sizeof(pm->pm_stats));
+}
+
+/*
+ * Set the physical protection on the specified range of this map as requested.
+ */
+void
+moea64_protect(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva,
+ vm_prot_t prot)
+{
+ struct pvo_entry *pvo;
+ struct lpte *pt;
+ int pteidx;
+
+ CTR4(KTR_PMAP, "moea64_protect: pm=%p sva=%#x eva=%#x prot=%#x", pm, sva,
+ eva, prot);
+
+
+ KASSERT(pm == &curproc->p_vmspace->vm_pmap || pm == kernel_pmap,
+ ("moea64_protect: non current pmap"));
+
+ if ((prot & VM_PROT_READ) == VM_PROT_NONE) {
+ moea64_remove(mmu, pm, sva, eva);
+ return;
+ }
+
+ vm_page_lock_queues();
+ PMAP_LOCK(pm);
+ for (; sva < eva; sva += PAGE_SIZE) {
+ pvo = moea64_pvo_find_va(pm, sva, &pteidx);
+ if (pvo == NULL)
+ continue;
+
+ /*
+ * Grab the PTE pointer before we diddle with the cached PTE
+ * copy.
+ */
+ LOCK_TABLE();
+ pt = moea64_pvo_to_pte(pvo, pteidx);
+
+ /*
+ * Change the protection of the page.
+ */
+ pvo->pvo_pte.lpte.pte_lo &= ~LPTE_PP;
+ pvo->pvo_pte.lpte.pte_lo |= LPTE_BR;
+ pvo->pvo_pte.lpte.pte_lo &= ~LPTE_NOEXEC;
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ pvo->pvo_pte.lpte.pte_lo |= LPTE_NOEXEC;
+
+ /*
+ * If the PVO is in the page table, update that pte as well.
+ */
+ if (pt != NULL) {
+ moea64_pte_change(pt, &pvo->pvo_pte.lpte,
+ pvo->pvo_pmap, pvo->pvo_vaddr);
+ if ((pvo->pvo_pte.lpte.pte_lo &
+ (LPTE_I | LPTE_G | LPTE_NOEXEC)) == 0) {
+ moea64_syncicache(pm, sva,
+ pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
+ }
+ }
+ UNLOCK_TABLE();
+ }
+ vm_page_unlock_queues();
+ PMAP_UNLOCK(pm);
+}
+
+/*
+ * Map a list of wired pages into kernel virtual address space. This is
+ * intended for temporary mappings which do not need page modification or
+ * references recorded. Existing mappings in the region are overwritten.
+ */
+void
+moea64_qenter(mmu_t mmu, vm_offset_t va, vm_page_t *m, int count)
+{
+ while (count-- > 0) {
+ moea64_kenter(mmu, va, VM_PAGE_TO_PHYS(*m));
+ va += PAGE_SIZE;
+ m++;
+ }
+}
+
+/*
+ * Remove page mappings from kernel virtual address space. Intended for
+ * temporary mappings entered by moea64_qenter.
+ */
+void
+moea64_qremove(mmu_t mmu, vm_offset_t va, int count)
+{
+ while (count-- > 0) {
+ moea64_kremove(mmu, va);
+ va += PAGE_SIZE;
+ }
+}
+
+void
+moea64_release(mmu_t mmu, pmap_t pmap)
+{
+ int idx, mask;
+
+ /*
+ * Free segment register's VSID
+ */
+ if (pmap->pm_sr[0] == 0)
+ panic("moea64_release");
+
+ idx = VSID_TO_HASH(pmap->pm_sr[0]) & (NPMAPS-1);
+ mask = 1 << (idx % VSID_NBPW);
+ idx /= VSID_NBPW;
+ moea64_vsid_bitmap[idx] &= ~mask;
+ PMAP_LOCK_DESTROY(pmap);
+}
+
+/*
+ * Remove the given range of addresses from the specified map.
+ */
+void
+moea64_remove(mmu_t mmu, pmap_t pm, vm_offset_t sva, vm_offset_t eva)
+{
+ struct pvo_entry *pvo;
+ int pteidx;
+
+ vm_page_lock_queues();
+ PMAP_LOCK(pm);
+ for (; sva < eva; sva += PAGE_SIZE) {
+ pvo = moea64_pvo_find_va(pm, sva, &pteidx);
+ if (pvo != NULL) {
+ moea64_pvo_remove(pvo, pteidx);
+ }
+ }
+ vm_page_unlock_queues();
+ PMAP_UNLOCK(pm);
+}
+
+/*
+ * Remove physical page from all pmaps in which it resides. moea64_pvo_remove()
+ * will reflect changes in pte's back to the vm_page.
+ */
+void
+moea64_remove_all(mmu_t mmu, vm_page_t m)
+{
+ struct pvo_head *pvo_head;
+ struct pvo_entry *pvo, *next_pvo;
+ pmap_t pmap;
+
+ mtx_assert(&vm_page_queue_mtx, MA_OWNED);
+
+ pvo_head = vm_page_to_pvoh(m);
+ for (pvo = LIST_FIRST(pvo_head); pvo != NULL; pvo = next_pvo) {
+ next_pvo = LIST_NEXT(pvo, pvo_vlink);
+
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+ pmap = pvo->pvo_pmap;
+ PMAP_LOCK(pmap);
+ moea64_pvo_remove(pvo, -1);
+ PMAP_UNLOCK(pmap);
+ }
+ vm_page_flag_clear(m, PG_WRITEABLE);
+}
+
+/*
+ * Allocate a physical page of memory directly from the phys_avail map.
+ * Can only be called from moea64_bootstrap before avail start and end are
+ * calculated.
+ */
+static vm_offset_t
+moea64_bootstrap_alloc(vm_size_t size, u_int align)
+{
+ vm_offset_t s, e;
+ int i, j;
+
+ size = round_page(size);
+ for (i = 0; phys_avail[i + 1] != 0; i += 2) {
+ if (align != 0)
+ s = (phys_avail[i] + align - 1) & ~(align - 1);
+ else
+ s = phys_avail[i];
+ e = s + size;
+
+ if (s < phys_avail[i] || e > phys_avail[i + 1])
+ continue;
+
+ if (s == phys_avail[i]) {
+ phys_avail[i] += size;
+ } else if (e == phys_avail[i + 1]) {
+ phys_avail[i + 1] -= size;
+ } else {
+ for (j = phys_avail_count * 2; j > i; j -= 2) {
+ phys_avail[j] = phys_avail[j - 2];
+ phys_avail[j + 1] = phys_avail[j - 1];
+ }
+
+ phys_avail[i + 3] = phys_avail[i + 1];
+ phys_avail[i + 1] = s;
+ phys_avail[i + 2] = e;
+ phys_avail_count++;
+ }
+
+ return (s);
+ }
+ panic("moea64_bootstrap_alloc: could not allocate memory");
+}
+
+static void
+tlbia(void)
+{
+ vm_offset_t i;
+
+ for (i = 0; i < 0xFF000; i += 0x00001000)
+ TLBIE(NULL,i);
+}
+
+static int
+moea64_pvo_enter(pmap_t pm, uma_zone_t zone, struct pvo_head *pvo_head,
+ vm_offset_t va, vm_offset_t pa, uint64_t pte_lo, int flags, int recurse)
+{
+ struct pvo_entry *pvo;
+ uint64_t vsid;
+ int first;
+ u_int ptegidx;
+ int i;
+ int bootstrap;
+
+ /*
+ * One nasty thing that can happen here is that the UMA calls to
+ * allocate new PVOs need to map more memory, which calls pvo_enter(),
+ * which calls UMA...
+ *
+ * We break the loop by detecting recursion and allocating out of
+ * the bootstrap pool.
+ */
+
+ moea64_pvo_enter_calls++;
+ first = 0;
+ bootstrap = (flags & PVO_BOOTSTRAP);
+
+ if (!moea64_initialized)
+ bootstrap = 1;
+
+ /*
+ * Compute the PTE Group index.
+ */
+ va &= ~ADDR_POFF;
+ vsid = va_to_vsid(pm, va);
+ ptegidx = va_to_pteg(vsid, va);
+
+ /*
+ * Remove any existing mapping for this page. Reuse the pvo entry if
+ * there is a mapping.
+ */
+ if (!recurse)
+ LOCK_TABLE();
+
+ LIST_FOREACH(pvo, &moea64_pvo_table[ptegidx], pvo_olink) {
+ if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va) {
+ if ((pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN) == pa &&
+ (pvo->pvo_pte.lpte.pte_lo & LPTE_PP) ==
+ (pte_lo & LPTE_PP)) {
+ if (!recurse)
+ UNLOCK_TABLE();
+ return (0);
+ }
+ moea64_pvo_remove(pvo, -1);
+ break;
+ }
+ }
+
+ /*
+ * If we aren't overwriting a mapping, try to allocate.
+ */
+ if (bootstrap) {
+ if (moea64_bpvo_pool_index >= BPVO_POOL_SIZE) {
+ panic("moea64_enter: bpvo pool exhausted, %d, %d, %d",
+ moea64_bpvo_pool_index, BPVO_POOL_SIZE,
+ BPVO_POOL_SIZE * sizeof(struct pvo_entry));
+ }
+ pvo = &moea64_bpvo_pool[moea64_bpvo_pool_index];
+ moea64_bpvo_pool_index++;
+ bootstrap = 1;
+ } else {
+ pvo = uma_zalloc(zone, M_NOWAIT);
+ }
+
+ if (pvo == NULL) {
+ if (!recurse)
+ UNLOCK_TABLE();
+ return (ENOMEM);
+ }
+
+ moea64_pvo_entries++;
+ pvo->pvo_vaddr = va;
+ pvo->pvo_pmap = pm;
+ LIST_INSERT_HEAD(&moea64_pvo_table[ptegidx], pvo, pvo_olink);
+ pvo->pvo_vaddr &= ~ADDR_POFF;
+
+ if (!(flags & VM_PROT_EXECUTE))
+ pte_lo |= LPTE_NOEXEC;
+ if (flags & PVO_WIRED)
+ pvo->pvo_vaddr |= PVO_WIRED;
+ if (pvo_head != &moea64_pvo_kunmanaged)
+ pvo->pvo_vaddr |= PVO_MANAGED;
+ if (bootstrap)
+ pvo->pvo_vaddr |= PVO_BOOTSTRAP;
+ if (flags & PVO_FAKE)
+ pvo->pvo_vaddr |= PVO_FAKE;
+
+ moea64_pte_create(&pvo->pvo_pte.lpte, vsid, va,
+ (uint64_t)(pa) | pte_lo);
+
+ /*
+ * Remember if the list was empty and therefore will be the first
+ * item.
+ */
+ if (LIST_FIRST(pvo_head) == NULL)
+ first = 1;
+ LIST_INSERT_HEAD(pvo_head, pvo, pvo_vlink);
+
+ if (pvo->pvo_pte.lpte.pte_lo & PVO_WIRED)
+ pm->pm_stats.wired_count++;
+ pm->pm_stats.resident_count++;
+
+ /*
+ * We hope this succeeds but it isn't required.
+ */
+ i = moea64_pte_insert(ptegidx, &pvo->pvo_pte.lpte);
+ if (i >= 0) {
+ PVO_PTEGIDX_SET(pvo, i);
+ } else {
+ panic("moea64_pvo_enter: overflow");
+ moea64_pte_overflow++;
+ }
+
+ if (!recurse)
+ UNLOCK_TABLE();
+
+ return (first ? ENOENT : 0);
+}
+
+static void
+moea64_pvo_remove(struct pvo_entry *pvo, int pteidx)
+{
+ struct lpte *pt;
+
+ /*
+ * If there is an active pte entry, we need to deactivate it (and
+ * save the ref & cfg bits).
+ */
+ LOCK_TABLE();
+ pt = moea64_pvo_to_pte(pvo, pteidx);
+ if (pt != NULL) {
+ moea64_pte_unset(pt, &pvo->pvo_pte.lpte, pvo->pvo_pmap,
+ pvo->pvo_vaddr);
+ PVO_PTEGIDX_CLR(pvo);
+ } else {
+ moea64_pte_overflow--;
+ }
+ UNLOCK_TABLE();
+
+ /*
+ * Update our statistics.
+ */
+ pvo->pvo_pmap->pm_stats.resident_count--;
+ if (pvo->pvo_pte.lpte.pte_lo & PVO_WIRED)
+ pvo->pvo_pmap->pm_stats.wired_count--;
+
+ /*
+ * Save the REF/CHG bits into their cache if the page is managed.
+ */
+ if ((pvo->pvo_vaddr & (PVO_MANAGED|PVO_FAKE)) == PVO_MANAGED) {
+ struct vm_page *pg;
+
+ pg = PHYS_TO_VM_PAGE(pvo->pvo_pte.lpte.pte_lo & LPTE_RPGN);
+ if (pg != NULL) {
+ moea64_attr_save(pg, pvo->pvo_pte.lpte.pte_lo &
+ (LPTE_REF | LPTE_CHG));
+ }
+ }
+
+ /*
+ * Remove this PVO from the PV list.
+ */
+ LIST_REMOVE(pvo, pvo_vlink);
+
+ /*
+ * Remove this from the overflow list and return it to the pool
+ * if we aren't going to reuse it.
+ */
+ LIST_REMOVE(pvo, pvo_olink);
+ if (!(pvo->pvo_vaddr & PVO_BOOTSTRAP))
+ uma_zfree(pvo->pvo_vaddr & PVO_MANAGED ? moea64_mpvo_zone :
+ moea64_upvo_zone, pvo);
+ moea64_pvo_entries--;
+ moea64_pvo_remove_calls++;
+}
+
+static __inline int
+moea64_pvo_pte_index(const struct pvo_entry *pvo, int ptegidx)
+{
+ int pteidx;
+
+ /*
+ * We can find the actual pte entry without searching by grabbing
+ * the PTEG index from 3 unused bits in pte_lo[11:9] and by
+ * noticing the HID bit.
+ */
+ pteidx = ptegidx * 8 + PVO_PTEGIDX_GET(pvo);
+ if (pvo->pvo_pte.lpte.pte_hi & LPTE_HID)
+ pteidx ^= moea64_pteg_mask * 8;
+
+ return (pteidx);
+}
+
+static struct pvo_entry *
+moea64_pvo_find_va(pmap_t pm, vm_offset_t va, int *pteidx_p)
+{
+ struct pvo_entry *pvo;
+ int ptegidx;
+ uint64_t vsid;
+
+ va &= ~ADDR_POFF;
+ vsid = va_to_vsid(pm, va);
+ ptegidx = va_to_pteg(vsid, va);
+
+ LOCK_TABLE();
+ LIST_FOREACH(pvo, &moea64_pvo_table[ptegidx], pvo_olink) {
+ if (pvo->pvo_pmap == pm && PVO_VADDR(pvo) == va) {
+ if (pteidx_p)
+ *pteidx_p = moea64_pvo_pte_index(pvo, ptegidx);
+ break;
+ }
+ }
+ UNLOCK_TABLE();
+
+ return (pvo);
+}
+
+static struct lpte *
+moea64_pvo_to_pte(const struct pvo_entry *pvo, int pteidx)
+{
+ struct lpte *pt;
+
+ /*
+ * If we haven't been supplied the ptegidx, calculate it.
+ */
+ if (pteidx == -1) {
+ int ptegidx;
+ uint64_t vsid;
+
+ vsid = va_to_vsid(pvo->pvo_pmap, pvo->pvo_vaddr);
+ ptegidx = va_to_pteg(vsid, pvo->pvo_vaddr);
+ pteidx = moea64_pvo_pte_index(pvo, ptegidx);
+ }
+
+ pt = &moea64_pteg_table[pteidx >> 3].pt[pteidx & 7];
+
+ if ((pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) &&
+ !PVO_PTEGIDX_ISSET(pvo)) {
+ panic("moea64_pvo_to_pte: pvo %p has valid pte in pvo but no "
+ "valid pte index", pvo);
+ }
+
+ if ((pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) == 0 &&
+ PVO_PTEGIDX_ISSET(pvo)) {
+ panic("moea64_pvo_to_pte: pvo %p has valid pte index in pvo "
+ "pvo but no valid pte", pvo);
+ }
+
+ if ((pt->pte_hi ^ (pvo->pvo_pte.lpte.pte_hi & ~LPTE_VALID)) ==
+ LPTE_VALID) {
+ if ((pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) == 0) {
+ panic("moea64_pvo_to_pte: pvo %p has valid pte in "
+ "moea64_pteg_table %p but invalid in pvo", pvo, pt);
+ }
+
+ if (((pt->pte_lo ^ pvo->pvo_pte.lpte.pte_lo) &
+ ~(LPTE_CHG|LPTE_REF)) != 0) {
+ panic("moea64_pvo_to_pte: pvo %p pte does not match "
+ "pte %p in moea64_pteg_table difference is %#x",
+ pvo, pt,
+ (uint32_t)(pt->pte_lo ^ pvo->pvo_pte.lpte.pte_lo));
+ }
+
+ ASSERT_TABLE_LOCK();
+ return (pt);
+ }
+
+ if (pvo->pvo_pte.lpte.pte_hi & LPTE_VALID) {
+ panic("moea64_pvo_to_pte: pvo %p has invalid pte %p in "
+ "moea64_pteg_table but valid in pvo", pvo, pt);
+ }
+
+ return (NULL);
+}
+
+static int
+moea64_pte_insert(u_int ptegidx, struct lpte *pvo_pt)
+{
+ struct lpte *pt;
+ int i;
+
+ ASSERT_TABLE_LOCK();
+
+ /*
+ * First try primary hash.
+ */
+ for (pt = moea64_pteg_table[ptegidx].pt, i = 0; i < 8; i++, pt++) {
+ if ((pt->pte_hi & LPTE_VALID) == 0) {
+ pvo_pt->pte_hi &= ~LPTE_HID;
+ moea64_pte_set(pt, pvo_pt);
+ return (i);
+ }
+ }
+
+ /*
+ * Now try secondary hash.
+ */
+ ptegidx ^= moea64_pteg_mask;
+
+ for (pt = moea64_pteg_table[ptegidx].pt, i = 0; i < 8; i++, pt++) {
+ if ((pt->pte_hi & LPTE_VALID) == 0) {
+ pvo_pt->pte_hi |= LPTE_HID;
+ moea64_pte_set(pt, pvo_pt);
+ return (i);
+ }
+ }
+
+ panic("moea64_pte_insert: overflow");
+ return (-1);
+}
+
+static boolean_t
+moea64_query_bit(vm_page_t m, u_int64_t ptebit)
+{
+ struct pvo_entry *pvo;
+ struct lpte *pt;
+
+#if 0
+ if (moea64_attr_fetch(m) & ptebit)
+ return (TRUE);
+#endif
+
+ LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+
+ /*
+ * See if we saved the bit off. If so, cache it and return
+ * success.
+ */
+ if (pvo->pvo_pte.lpte.pte_lo & ptebit) {
+ moea64_attr_save(m, ptebit);
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+ return (TRUE);
+ }
+ }
+
+ /*
+ * No luck, now go through the hard part of looking at the PTEs
+ * themselves. Sync so that any pending REF/CHG bits are flushed to
+ * the PTEs.
+ */
+ SYNC();
+ LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+
+ /*
+ * See if this pvo has a valid PTE. if so, fetch the
+ * REF/CHG bits from the valid PTE. If the appropriate
+ * ptebit is set, cache it and return success.
+ */
+ LOCK_TABLE();
+ pt = moea64_pvo_to_pte(pvo, -1);
+ if (pt != NULL) {
+ moea64_pte_synch(pt, &pvo->pvo_pte.lpte);
+ if (pvo->pvo_pte.lpte.pte_lo & ptebit) {
+ UNLOCK_TABLE();
+
+ moea64_attr_save(m, ptebit);
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+ return (TRUE);
+ }
+ }
+ UNLOCK_TABLE();
+ }
+
+ return (FALSE);
+}
+
+static u_int
+moea64_clear_bit(vm_page_t m, u_int64_t ptebit, u_int64_t *origbit)
+{
+ u_int count;
+ struct pvo_entry *pvo;
+ struct lpte *pt;
+ uint64_t rv;
+
+ /*
+ * Clear the cached value.
+ */
+ rv = moea64_attr_fetch(m);
+ moea64_attr_clear(m, ptebit);
+
+ /*
+ * Sync so that any pending REF/CHG bits are flushed to the PTEs (so
+ * we can reset the right ones). note that since the pvo entries and
+ * list heads are accessed via BAT0 and are never placed in the page
+ * table, we don't have to worry about further accesses setting the
+ * REF/CHG bits.
+ */
+ SYNC();
+
+ /*
+ * For each pvo entry, clear the pvo's ptebit. If this pvo has a
+ * valid pte clear the ptebit from the valid pte.
+ */
+ count = 0;
+ LIST_FOREACH(pvo, vm_page_to_pvoh(m), pvo_vlink) {
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+
+ LOCK_TABLE();
+ pt = moea64_pvo_to_pte(pvo, -1);
+ if (pt != NULL) {
+ moea64_pte_synch(pt, &pvo->pvo_pte.lpte);
+ if (pvo->pvo_pte.lpte.pte_lo & ptebit) {
+ count++;
+ moea64_pte_clear(pt, pvo->pvo_pmap, PVO_VADDR(pvo), ptebit);
+ }
+ }
+ UNLOCK_TABLE();
+ rv |= pvo->pvo_pte.lpte.pte_lo;
+ pvo->pvo_pte.lpte.pte_lo &= ~ptebit;
+ MOEA_PVO_CHECK(pvo); /* sanity check */
+ }
+
+ if (origbit != NULL) {
+ *origbit = rv;
+ }
+
+ return (count);
+}
+
+boolean_t
+moea64_dev_direct_mapped(mmu_t mmu, vm_offset_t pa, vm_size_t size)
+{
+ return (EFAULT);
+}
+
+boolean_t
+moea64_page_executable(mmu_t mmu, vm_page_t pg)
+{
+ return (!moea64_query_bit(pg, LPTE_NOEXEC));
+}
+
+/*
+ * Map a set of physical memory pages into the kernel virtual
+ * address space. Return a pointer to where it is mapped. This
+ * routine is intended to be used for mapping device memory,
+ * NOT real memory.
+ */
+void *
+moea64_mapdev(mmu_t mmu, vm_offset_t pa, vm_size_t size)
+{
+ vm_offset_t va, tmpva, ppa, offset;
+
+ ppa = trunc_page(pa);
+ offset = pa & PAGE_MASK;
+ size = roundup(offset + size, PAGE_SIZE);
+
+ va = kmem_alloc_nofault(kernel_map, size);
+
+ if (!va)
+ panic("moea64_mapdev: Couldn't alloc kernel virtual memory");
+
+ for (tmpva = va; size > 0;) {
+ moea64_kenter(mmu, tmpva, ppa);
+ size -= PAGE_SIZE;
+ tmpva += PAGE_SIZE;
+ ppa += PAGE_SIZE;
+ }
+
+ return ((void *)(va + offset));
+}
+
+void
+moea64_unmapdev(mmu_t mmu, vm_offset_t va, vm_size_t size)
+{
+ vm_offset_t base, offset;
+
+ base = trunc_page(va);
+ offset = va & PAGE_MASK;
+ size = roundup(offset + size, PAGE_SIZE);
+
+ kmem_free(kernel_map, base, size);
+}
+
diff --git a/sys/powerpc/aim/mp_cpudep.c b/sys/powerpc/aim/mp_cpudep.c
index cfdb53d..e226d3b 100644
--- a/sys/powerpc/aim/mp_cpudep.c
+++ b/sys/powerpc/aim/mp_cpudep.c
@@ -35,7 +35,6 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/smp.h>
-#include <machine/bat.h>
#include <machine/bus.h>
#include <machine/cpu.h>
#include <machine/hid.h>
@@ -250,8 +249,10 @@ cpudep_ap_bootstrap(void)
mtmsr(msr);
isync();
- reg = l3_enable();
- reg = l2_enable();
+ if (l3cr_config != 0)
+ reg = l3_enable();
+ if (l2cr_config != 0)
+ reg = l2_enable();
reg = l1d_enable();
reg = l1i_enable();
diff --git a/sys/powerpc/aim/ofw_machdep.c b/sys/powerpc/aim/ofw_machdep.c
index 0d5f03b..977f81a 100644
--- a/sys/powerpc/aim/ofw_machdep.c
+++ b/sys/powerpc/aim/ofw_machdep.c
@@ -62,6 +62,12 @@ __FBSDID("$FreeBSD$");
static struct mem_region OFmem[OFMEM_REGIONS + 1], OFavail[OFMEM_REGIONS + 3];
static struct mem_region OFfree[OFMEM_REGIONS + 3];
+struct mem_region64 {
+ vm_offset_t mr_start_hi;
+ vm_offset_t mr_start_lo;
+ vm_size_t mr_size;
+};
+
extern register_t ofmsr[5];
extern struct pmap ofw_pmap;
static int (*ofwcall)(void *);
@@ -141,24 +147,86 @@ void
mem_regions(struct mem_region **memp, int *memsz,
struct mem_region **availp, int *availsz)
{
- int phandle;
+ phandle_t phandle;
int asz, msz, fsz;
int i, j;
int still_merging;
+ cell_t address_cells;
+
+ asz = msz = 0;
+
+ /*
+ * Get #address-cells from root node, defaulting to 1 if it cannot
+ * be found.
+ */
+ phandle = OF_finddevice("/");
+ if (OF_getprop(phandle, "#address-cells", &address_cells,
+ sizeof(address_cells)) < sizeof(address_cells))
+ address_cells = 1;
/*
* Get memory.
*/
if ((phandle = OF_finddevice("/memory")) == -1
- || (msz = OF_getprop(phandle, "reg",
- OFmem, sizeof OFmem[0] * OFMEM_REGIONS))
- <= 0
|| (asz = OF_getprop(phandle, "available",
- OFavail, sizeof OFavail[0] * OFMEM_REGIONS))
- <= 0)
- panic("no memory?");
+ OFavail, sizeof OFavail[0] * OFMEM_REGIONS)) <= 0)
+ {
+ if (ofw_real_mode) {
+ /* XXX MAMBO */
+ printf("Physical memory unknown -- guessing 128 MB\n");
+
+ /* Leave the first 0xA000000 bytes for the kernel */
+ OFavail[0].mr_start = 0xA00000;
+ OFavail[0].mr_size = 0x75FFFFF;
+ asz = sizeof(OFavail[0]);
+ } else {
+ panic("no memory?");
+ }
+ }
+
+ if (address_cells == 2) {
+ struct mem_region64 OFmem64[OFMEM_REGIONS + 1];
+ if ((phandle == -1) || (msz = OF_getprop(phandle, "reg",
+ OFmem64, sizeof OFmem64[0] * OFMEM_REGIONS)) <= 0) {
+ if (ofw_real_mode) {
+ /* XXX MAMBO */
+ OFmem64[0].mr_start_hi = 0;
+ OFmem64[0].mr_start_lo = 0x0;
+ OFmem64[0].mr_size = 0x7FFFFFF;
+ msz = sizeof(OFmem64[0]);
+ } else {
+ panic("Physical memory map not found");
+ }
+ }
+
+ for (i = 0, j = 0; i < msz/sizeof(OFmem64[0]); i++) {
+ if (OFmem64[i].mr_start_hi == 0) {
+ OFmem[i].mr_start = OFmem64[i].mr_start_lo;
+ OFmem[i].mr_size = OFmem64[i].mr_size;
+
+ /*
+ * Check for memory regions extending above 32-bit
+ * memory space, and restrict them to stay there.
+ */
+ if (((uint64_t)OFmem[i].mr_start +
+ (uint64_t)OFmem[i].mr_size) >
+ BUS_SPACE_MAXADDR_32BIT) {
+ OFmem[i].mr_size = BUS_SPACE_MAXADDR_32BIT -
+ OFmem[i].mr_start;
+ }
+ j++;
+ }
+ }
+ msz = j*sizeof(OFmem[0]);
+ } else {
+ if ((msz = OF_getprop(phandle, "reg",
+ OFmem, sizeof OFmem[0] * OFMEM_REGIONS)) <= 0)
+ panic("Physical memory map not found");
+ }
+
*memp = OFmem;
*memsz = msz / sizeof(struct mem_region);
+
/*
* OFavail may have overlapping regions - collapse these
@@ -268,8 +336,10 @@ openfirmware(void *args)
/*
* Clear battable[] translations
*/
- __asm __volatile("mtdbatu 2, %0\n"
- "mtdbatu 3, %0" : : "r" (0));
+ if (!ppc64) {
+ __asm __volatile("mtdbatu 2, %0\n"
+ "mtdbatu 3, %0" : : "r" (0));
+ }
isync();
}
@@ -469,3 +539,4 @@ mem_valid(vm_offset_t addr, int len)
return (EFAULT);
}
+
diff --git a/sys/powerpc/aim/swtch.S b/sys/powerpc/aim/swtch.S
index 672fe6b..619bf89 100644
--- a/sys/powerpc/aim/swtch.S
+++ b/sys/powerpc/aim/swtch.S
@@ -155,6 +155,12 @@ cpu_switchin:
mtsr USER_SR,%r5
isync
lwz %r1,PCB_SP(%r3) /* Load the stack pointer */
+ /*
+ * Perform a dummy stwcx. to clear any reservations we may have
+ * inherited from the previous thread. It doesn't matter if the
+ * stwcx succeeds or not. pcb_context[0] can be clobbered.
+ */
+ stwcx. %r1, 0, %r3
blr
/*
diff --git a/sys/powerpc/aim/trap_subr.S b/sys/powerpc/aim/trap_subr.S
index 58e0663..0c62d83 100644
--- a/sys/powerpc/aim/trap_subr.S
+++ b/sys/powerpc/aim/trap_subr.S
@@ -223,10 +223,54 @@
lwz %r3,(savearea+CPUSAVE_SRR0)(%r2); /* restore srr0 */ \
mtsrr0 %r3; \
lwz %r3,(savearea+CPUSAVE_SRR1)(%r2); /* restore srr1 */ \
+ \
+ /* Make sure HV bit of MSR propagated to SRR1 */ \
+ mfmsr %r2; \
+ or %r3,%r2,%r3; \
+ \
mtsrr1 %r3; \
mfsprg2 %r2; /* restore r2 & r3 */ \
mfsprg3 %r3
+/*
+ * The next two routines are 64-bit glue code. The first is used to test if
+ * we are on a 64-bit system. By copying it to the illegal instruction
+ * handler, we can test for 64-bit mode by trying to execute a 64-bit
+ * instruction and seeing what happens. The second gets copied in front
+ * of all the other handlers to restore 32-bit bridge mode when traps
+ * are taken.
+ */
+
+/* 64-bit test code. Sets SPRG2 to 0 if an illegal instruction is executed */
+
+ .globl CNAME(testppc64),CNAME(testppc64size)
+CNAME(testppc64):
+ mtsprg1 %r31
+ mfsrr0 %r31
+ addi %r31, %r31, 4
+ mtsrr0 %r31
+
+ li %r31, 0
+ mtsprg2 %r31
+ mfsprg1 %r31
+
+ rfi
+CNAME(testppc64size) = .-CNAME(testppc64)
+
+
+/* 64-bit bridge mode restore snippet. Gets copied in front of everything else
+ * on 64-bit systems. */
+
+ .globl CNAME(restorebridge),CNAME(restorebridgesize)
+CNAME(restorebridge):
+ mtsprg1 %r31
+ mfmsr %r31
+ clrldi %r31,%r31,1
+ mtmsrd %r31
+ mfsprg1 %r31
+ isync
+CNAME(restorebridgesize) = .-CNAME(restorebridge)
+
#ifdef SMP
/*
* Processor reset exception handler. These are typically
@@ -270,6 +314,17 @@ CNAME(trapcode):
CNAME(trapsize) = .-CNAME(trapcode)
/*
+ * 64-bit version of trapcode. Identical, except it calls generictrap64.
+ */
+ .globl CNAME(trapcode64)
+CNAME(trapcode64):
+ mtsprg1 %r1 /* save SP */
+ mflr %r1 /* Save the old LR in r1 */
+ mtsprg2 %r1 /* And then in SPRG2 */
+ li %r1, 0x20 /* How to get the vector from LR */
+ bla generictrap64 /* LR & SPRG3 is exception # */
+
+/*
* For ALI: has to save DSISR and DAR
*/
.globl CNAME(alitrap),CNAME(alisize)
@@ -405,9 +460,7 @@ disitrap:
stw %r30,(PC_DBSAVE +CPUSAVE_R30)(%r1) /* save r30 */
lwz %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) /* get r31 */
stw %r31,(PC_DBSAVE +CPUSAVE_R31)(%r1) /* save r31 */
- lis %r1,(tmpstk+TMPSTKSZ-16)@ha /* get new SP */
- addi %r1,%r1,(tmpstk+TMPSTKSZ-16)@l
- b dbtrap
+ bla dbtrap
#endif
/* XXX need stack probe here */
@@ -433,6 +486,14 @@ realtrap:
* SPRG2 - Original LR
*/
+generictrap64:
+ mtsprg3 %r31
+ mfmsr %r31
+ clrldi %r31,%r31,1
+ mtmsrd %r31
+ mfsprg3 %r31
+ isync
+
generictrap:
/* Save R1 for computing the exception vector */
mtsprg3 %r1
@@ -504,8 +565,15 @@ CNAME(asttrapexit):
b trapexit /* test ast ret value ? */
1:
FRAME_LEAVE(PC_TEMPSAVE)
+
+ .globl CNAME(rfi_patch1) /* replace rfi with rfid on ppc64 */
+CNAME(rfi_patch1):
rfi
+ .globl CNAME(rfid_patch)
+CNAME(rfid_patch):
+ rfid
+
#if defined(KDB)
/*
* Deliberate entry to dbtrap
@@ -561,11 +629,13 @@ dbtrap:
mflr %r28
mfcr %r29
lwz %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1)
- mtlr %r31
+ mtsprg3 %r31 /* SPRG3 was clobbered by FRAME_LEAVE */
mfsprg1 %r1
b realtrap
dbleave:
FRAME_LEAVE(PC_DBSAVE)
+ .globl CNAME(rfi_patch2) /* replace rfi with rfid on ppc64 */
+CNAME(rfi_patch2):
rfi
/*
diff --git a/sys/powerpc/aim/uio_machdep.c b/sys/powerpc/aim/uio_machdep.c
deleted file mode 100644
index 070ad98..0000000
--- a/sys/powerpc/aim/uio_machdep.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*-
- * Copyright (c) 2004 Alan L. Cox <alc@cs.rice.edu>
- * Copyright (c) 1982, 1986, 1991, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- * All or some portions of this file are derived from material licensed
- * to the University of California by American Telephone and Telegraph
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/systm.h>
-#include <sys/uio.h>
-
-#include <vm/vm.h>
-#include <vm/vm_page.h>
-
-#include <machine/md_var.h>
-#include <machine/vmparam.h>
-
-/*
- * Implement uiomove(9) from physical memory using the direct map to
- * avoid the creation and destruction of ephemeral mappings.
- */
-int
-uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
-{
- struct thread *td = curthread;
- struct iovec *iov;
- void *cp;
- vm_offset_t page_offset;
- size_t cnt;
- int error = 0;
- int save = 0;
-
- KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
- ("uiomove_fromphys: mode"));
- KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
- ("uiomove_fromphys proc"));
- save = td->td_pflags & TDP_DEADLKTREAT;
- td->td_pflags |= TDP_DEADLKTREAT;
- while (n > 0 && uio->uio_resid) {
- iov = uio->uio_iov;
- cnt = iov->iov_len;
- if (cnt == 0) {
- uio->uio_iov++;
- uio->uio_iovcnt--;
- continue;
- }
- if (cnt > n)
- cnt = n;
- page_offset = offset & PAGE_MASK;
- cnt = min(cnt, PAGE_SIZE - page_offset);
- cp = (char *)VM_PAGE_TO_PHYS(ma[offset >> PAGE_SHIFT]) +
- page_offset;
- switch (uio->uio_segflg) {
- case UIO_USERSPACE:
- if (ticks - PCPU_GET(switchticks) >= hogticks)
- uio_yield();
- if (uio->uio_rw == UIO_READ)
- error = copyout(cp, iov->iov_base, cnt);
- else
- error = copyin(iov->iov_base, cp, cnt);
- if (error)
- goto out;
- if (uio->uio_rw == UIO_WRITE &&
- pmap_page_executable(ma[offset >> PAGE_SHIFT]))
- __syncicache(cp, cnt);
- break;
- case UIO_SYSSPACE:
- if (uio->uio_rw == UIO_READ)
- bcopy(cp, iov->iov_base, cnt);
- else
- bcopy(iov->iov_base, cp, cnt);
- break;
- case UIO_NOCOPY:
- break;
- }
- iov->iov_base = (char *)iov->iov_base + cnt;
- iov->iov_len -= cnt;
- uio->uio_resid -= cnt;
- uio->uio_offset += cnt;
- offset += cnt;
- n -= cnt;
- }
-out:
- if (save == 0)
- td->td_pflags &= ~TDP_DEADLKTREAT;
- return (error);
-}
diff --git a/sys/powerpc/aim/uma_machdep.c b/sys/powerpc/aim/uma_machdep.c
index 89d092a..dc03a26 100644
--- a/sys/powerpc/aim/uma_machdep.c
+++ b/sys/powerpc/aim/uma_machdep.c
@@ -35,9 +35,13 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
+#include <vm/vm_kern.h>
#include <vm/vm_pageout.h>
+#include <vm/vm_extern.h>
+#include <vm/uma.h>
#include <vm/uma.h>
#include <vm/uma_int.h>
+#include <machine/md_var.h>
#include <machine/vmparam.h>
static int hw_uma_mdpages;
@@ -51,6 +55,13 @@ uma_small_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait)
void *va;
vm_page_t m;
int pflags;
+
+ if (!hw_direct_map) {
+ *flags = UMA_SLAB_KMEM;
+ va = (void *)kmem_malloc(kmem_map, bytes, wait);
+
+ return va;
+ }
*flags = UMA_SLAB_PRIV;
if ((wait & (M_NOWAIT|M_USE_RESERVE)) == M_NOWAIT)
@@ -83,6 +94,12 @@ uma_small_free(void *mem, int size, u_int8_t flags)
{
vm_page_t m;
+ if (!hw_direct_map) {
+ kmem_free(kmem_map, (vm_offset_t)mem, size);
+
+ return;
+ }
+
m = PHYS_TO_VM_PAGE((u_int32_t)mem);
m->wire_count--;
vm_page_free(m);
diff --git a/sys/powerpc/aim/vm_machdep.c b/sys/powerpc/aim/vm_machdep.c
index 9b0faf3..e20ba7b 100644
--- a/sys/powerpc/aim/vm_machdep.c
+++ b/sys/powerpc/aim/vm_machdep.c
@@ -101,6 +101,37 @@
#include <vm/vm_extern.h>
/*
+ * On systems without a direct mapped region (e.g. PPC64),
+ * we use the same code as the Book E implementation. Since
+ * we need to have runtime detection of this, define some machinery
+ * for sf_bufs in this case, and ignore it on systems with direct maps.
+ */
+
+#ifndef NSFBUFS
+#define NSFBUFS (512 + maxusers * 16)
+#endif
+
+static void sf_buf_init(void *arg);
+SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL);
+
+LIST_HEAD(sf_head, sf_buf);
+
+/* A hash table of active sendfile(2) buffers */
+static struct sf_head *sf_buf_active;
+static u_long sf_buf_hashmask;
+
+#define SF_BUF_HASH(m) (((m) - vm_page_array) & sf_buf_hashmask)
+
+static TAILQ_HEAD(, sf_buf) sf_buf_freelist;
+static u_int sf_buf_alloc_want;
+
+/*
+ * A lock used to synchronize access to the hash table and free list
+ */
+static struct mtx sf_buf_lock;
+
+
+/*
* Finish a fork operation, with process p2 nearly set up.
* Copy and update the pcb, set up the stack so that the child
* ready to run and return to user mode.
@@ -202,24 +233,122 @@ cpu_reset()
}
/*
- * Allocate an sf_buf for the given vm_page. On this machine, however, there
- * is no sf_buf object. Instead, an opaque pointer to the given vm_page is
- * returned.
+ * Allocate a pool of sf_bufs (sendfile(2) or "super-fast" if you prefer. :-))
*/
-struct sf_buf *
-sf_buf_alloc(struct vm_page *m, int pri)
+static void
+sf_buf_init(void *arg)
{
+ struct sf_buf *sf_bufs;
+ vm_offset_t sf_base;
+ int i;
+
+ /* Don't bother on systems with a direct map */
- return ((struct sf_buf *)m);
+ if (hw_direct_map)
+ return;
+
+ nsfbufs = NSFBUFS;
+ TUNABLE_INT_FETCH("kern.ipc.nsfbufs", &nsfbufs);
+
+ sf_buf_active = hashinit(nsfbufs, M_TEMP, &sf_buf_hashmask);
+ TAILQ_INIT(&sf_buf_freelist);
+ sf_base = kmem_alloc_nofault(kernel_map, nsfbufs * PAGE_SIZE);
+ sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, M_NOWAIT | M_ZERO);
+
+ for (i = 0; i < nsfbufs; i++) {
+ sf_bufs[i].kva = sf_base + i * PAGE_SIZE;
+ TAILQ_INSERT_TAIL(&sf_buf_freelist, &sf_bufs[i], free_entry);
+ }
+ sf_buf_alloc_want = 0;
+ mtx_init(&sf_buf_lock, "sf_buf", NULL, MTX_DEF);
+}
+
+/*
+ * Get an sf_buf from the freelist. Will block if none are available.
+ */
+struct sf_buf *
+sf_buf_alloc(struct vm_page *m, int flags)
+{
+ struct sf_head *hash_list;
+ struct sf_buf *sf;
+ int error;
+
+ if (hw_direct_map) {
+ /* Shortcut the direct mapped case */
+
+ return ((struct sf_buf *)m);
+ }
+
+ hash_list = &sf_buf_active[SF_BUF_HASH(m)];
+ mtx_lock(&sf_buf_lock);
+ LIST_FOREACH(sf, hash_list, list_entry) {
+ if (sf->m == m) {
+ sf->ref_count++;
+ if (sf->ref_count == 1) {
+ TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry);
+ nsfbufsused++;
+ nsfbufspeak = imax(nsfbufspeak, nsfbufsused);
+ }
+ goto done;
+ }
+ }
+
+ while ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) {
+ if (flags & SFB_NOWAIT)
+ goto done;
+
+ sf_buf_alloc_want++;
+ mbstat.sf_allocwait++;
+ error = msleep(&sf_buf_freelist, &sf_buf_lock,
+ (flags & SFB_CATCH) ? PCATCH | PVM : PVM, "sfbufa", 0);
+ sf_buf_alloc_want--;
+
+ /*
+ * If we got a signal, don't risk going back to sleep.
+ */
+ if (error)
+ goto done;
+ }
+
+ TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry);
+ if (sf->m != NULL)
+ LIST_REMOVE(sf, list_entry);
+
+ LIST_INSERT_HEAD(hash_list, sf, list_entry);
+ sf->ref_count = 1;
+ sf->m = m;
+ nsfbufsused++;
+ nsfbufspeak = imax(nsfbufspeak, nsfbufsused);
+ pmap_qenter(sf->kva, &sf->m, 1);
+done:
+ mtx_unlock(&sf_buf_lock);
+ return (sf);
}
/*
- * Free the sf_buf. In fact, do nothing because there are no resources
- * associated with the sf_buf.
+ * Detatch mapped page and release resources back to the system.
+ *
+ * Remove a reference from the given sf_buf, adding it to the free
+ * list when its reference count reaches zero. A freed sf_buf still,
+ * however, retains its virtual-to-physical mapping until it is
+ * recycled or reactivated by sf_buf_alloc(9).
*/
void
sf_buf_free(struct sf_buf *sf)
{
+ if (hw_direct_map)
+ return;
+
+ mtx_lock(&sf_buf_lock);
+ sf->ref_count--;
+ if (sf->ref_count == 0) {
+ TAILQ_INSERT_TAIL(&sf_buf_freelist, sf, free_entry);
+ nsfbufsused--;
+
+ if (sf_buf_alloc_want > 0)
+ wakeup_one(&sf_buf_freelist);
+ }
+ mtx_unlock(&sf_buf_lock);
}
/*
diff --git a/sys/powerpc/booke/machdep.c b/sys/powerpc/booke/machdep.c
index e42aa8c..bd72603 100644
--- a/sys/powerpc/booke/machdep.c
+++ b/sys/powerpc/booke/machdep.c
@@ -176,6 +176,9 @@ int cacheline_size = 32;
SYSCTL_INT(_machdep, CPU_CACHELINE, cacheline_size,
CTLFLAG_RD, &cacheline_size, 0, "");
+int hw_direct_map = 0;
+int ppc64 = 0;
+
static void cpu_e500_startup(void *);
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_e500_startup, NULL);
diff --git a/sys/powerpc/booke/pmap.c b/sys/powerpc/booke/pmap.c
index 136279d..223c42c 100644
--- a/sys/powerpc/booke/pmap.c
+++ b/sys/powerpc/booke/pmap.c
@@ -39,7 +39,7 @@
* 0x0000_0000 - 0xafff_ffff : user process
* 0xb000_0000 - 0xbfff_ffff : pmap_mapdev()-ed area (PCI/PCIE etc.)
* 0xc000_0000 - 0xc0ff_ffff : kernel reserved
- * 0xc000_0000 - kernelend : kernel code+data, env, metadata etc.
+ * 0xc000_0000 - data_end : kernel code+data, env, metadata etc.
* 0xc100_0000 - 0xfeef_ffff : KVA
* 0xc100_0000 - 0xc100_3fff : reserved for page zero/copy
* 0xc100_4000 - 0xc200_3fff : reserved for ptbl bufs
@@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_pager.h>
#include <vm/uma.h>
+#include <machine/bootinfo.h>
#include <machine/cpu.h>
#include <machine/pcb.h>
#include <machine/powerpc.h>
@@ -107,8 +108,19 @@ __FBSDID("$FreeBSD$");
#endif
extern struct mtx sched_lock;
+extern int dumpsys_minidump;
+
+extern unsigned char _etext[];
+extern unsigned char _end[];
+
/* Kernel physical load address. */
extern uint32_t kernload;
+vm_offset_t kernstart;
+vm_size_t kernsize;
+
+/* Message buffer and tables. */
+static vm_offset_t data_start;
+static vm_size_t data_end;
struct mem_region availmem_regions[MEM_REGIONS];
int availmem_regions_sz;
@@ -304,6 +316,11 @@ static void mmu_booke_kenter(mmu_t, vm_offset_t, vm_offset_t);
static void mmu_booke_kremove(mmu_t, vm_offset_t);
static boolean_t mmu_booke_dev_direct_mapped(mmu_t, vm_offset_t, vm_size_t);
static boolean_t mmu_booke_page_executable(mmu_t, vm_page_t);
+static vm_offset_t mmu_booke_dumpsys_map(mmu_t, struct pmap_md *,
+ vm_size_t, vm_size_t *);
+static void mmu_booke_dumpsys_unmap(mmu_t, struct pmap_md *,
+ vm_size_t, vm_offset_t);
+static struct pmap_md *mmu_booke_scan_md(mmu_t, struct pmap_md *);
static mmu_method_t mmu_booke_methods[] = {
/* pmap dispatcher interface */
@@ -352,6 +369,11 @@ static mmu_method_t mmu_booke_methods[] = {
MMUMETHOD(mmu_page_executable, mmu_booke_page_executable),
MMUMETHOD(mmu_unmapdev, mmu_booke_unmapdev),
+ /* dumpsys() support */
+ MMUMETHOD(mmu_dumpsys_map, mmu_booke_dumpsys_map),
+ MMUMETHOD(mmu_dumpsys_unmap, mmu_booke_dumpsys_unmap),
+ MMUMETHOD(mmu_scan_md, mmu_booke_scan_md),
+
{ 0, 0 }
};
@@ -884,7 +906,7 @@ pte_find(mmu_t mmu, pmap_t pmap, vm_offset_t va)
* This is called during e500_init, before the system is really initialized.
*/
static void
-mmu_booke_bootstrap(mmu_t mmu, vm_offset_t kernelstart, vm_offset_t kernelend)
+mmu_booke_bootstrap(mmu_t mmu, vm_offset_t start, vm_offset_t kernelend)
{
vm_offset_t phys_kernelend;
struct mem_region *mp, *mp1;
@@ -904,47 +926,52 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t kernelstart, vm_offset_t kernelend)
tlb0_get_tlbconf();
/* Align kernel start and end address (kernel image). */
- kernelstart = trunc_page(kernelstart);
- kernelend = round_page(kernelend);
+ kernstart = trunc_page(start);
+ data_start = round_page(kernelend);
+ kernsize = data_start - kernstart;
+
+ data_end = data_start;
/* Allocate space for the message buffer. */
- msgbufp = (struct msgbuf *)kernelend;
- kernelend += MSGBUF_SIZE;
+ msgbufp = (struct msgbuf *)data_end;
+ data_end += MSGBUF_SIZE;
debugf(" msgbufp at 0x%08x end = 0x%08x\n", (uint32_t)msgbufp,
- kernelend);
+ data_end);
- kernelend = round_page(kernelend);
+ data_end = round_page(data_end);
/* Allocate space for ptbl_bufs. */
- ptbl_bufs = (struct ptbl_buf *)kernelend;
- kernelend += sizeof(struct ptbl_buf) * PTBL_BUFS;
+ ptbl_bufs = (struct ptbl_buf *)data_end;
+ data_end += sizeof(struct ptbl_buf) * PTBL_BUFS;
debugf(" ptbl_bufs at 0x%08x end = 0x%08x\n", (uint32_t)ptbl_bufs,
- kernelend);
+ data_end);
- kernelend = round_page(kernelend);
+ data_end = round_page(data_end);
/* Allocate PTE tables for kernel KVA. */
- kernel_pdir = kernelend;
+ kernel_pdir = data_end;
kernel_ptbls = (VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS +
PDIR_SIZE - 1) / PDIR_SIZE;
- kernelend += kernel_ptbls * PTBL_PAGES * PAGE_SIZE;
+ data_end += kernel_ptbls * PTBL_PAGES * PAGE_SIZE;
debugf(" kernel ptbls: %d\n", kernel_ptbls);
- debugf(" kernel pdir at 0x%08x end = 0x%08x\n", kernel_pdir, kernelend);
+ debugf(" kernel pdir at 0x%08x end = 0x%08x\n", kernel_pdir, data_end);
- debugf(" kernelend: 0x%08x\n", kernelend);
- if (kernelend - kernelstart > 0x1000000) {
- kernelend = (kernelend + 0x3fffff) & ~0x3fffff;
- tlb1_mapin_region(kernelstart + 0x1000000,
- kernload + 0x1000000, kernelend - kernelstart - 0x1000000);
+ debugf(" data_end: 0x%08x\n", data_end);
+ if (data_end - kernstart > 0x1000000) {
+ data_end = (data_end + 0x3fffff) & ~0x3fffff;
+ tlb1_mapin_region(kernstart + 0x1000000,
+ kernload + 0x1000000, data_end - kernstart - 0x1000000);
} else
- kernelend = (kernelend + 0xffffff) & ~0xffffff;
+ data_end = (data_end + 0xffffff) & ~0xffffff;
- debugf(" updated kernelend: 0x%08x\n", kernelend);
+ debugf(" updated data_end: 0x%08x\n", data_end);
+
+ kernsize += data_end - data_start;
/*
* Clear the structures - note we can only do it safely after the
* possible additional TLB1 translations are in place (above) so that
- * all range up to the currently calculated 'kernelend' is covered.
+ * all range up to the currently calculated 'data_end' is covered.
*/
memset((void *)ptbl_bufs, 0, sizeof(struct ptbl_buf) * PTBL_SIZE);
memset((void *)kernel_pdir, 0, kernel_ptbls * PTBL_PAGES * PAGE_SIZE);
@@ -952,7 +979,7 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t kernelstart, vm_offset_t kernelend)
/*******************************************************/
/* Set the start and end of kva. */
/*******************************************************/
- virtual_avail = kernelend;
+ virtual_avail = round_page(data_end);
virtual_end = VM_MAX_KERNEL_ADDRESS;
/* Allocate KVA space for page zero/copy operations. */
@@ -980,12 +1007,11 @@ mmu_booke_bootstrap(mmu_t mmu, vm_offset_t kernelstart, vm_offset_t kernelend)
ptbl_buf_pool_vabase, virtual_avail);
/* Calculate corresponding physical addresses for the kernel region. */
- phys_kernelend = kernload + (kernelend - kernelstart);
+ phys_kernelend = kernload + kernsize;
debugf("kernel image and allocated data:\n");
debugf(" kernload = 0x%08x\n", kernload);
- debugf(" kernelstart = 0x%08x\n", kernelstart);
- debugf(" kernelend = 0x%08x\n", kernelend);
- debugf(" kernel size = 0x%08x\n", kernelend - kernelstart);
+ debugf(" kernstart = 0x%08x\n", kernstart);
+ debugf(" kernsize = 0x%08x\n", kernsize);
if (sizeof(phys_avail) / sizeof(phys_avail[0]) < availmem_regions_sz)
panic("mmu_booke_bootstrap: phys_avail too small");
@@ -2287,6 +2313,140 @@ mmu_booke_dev_direct_mapped(mmu_t mmu, vm_offset_t pa, vm_size_t size)
return (EFAULT);
}
+vm_offset_t
+mmu_booke_dumpsys_map(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
+ vm_size_t *sz)
+{
+ vm_paddr_t pa, ppa;
+ vm_offset_t va;
+ vm_size_t gran;
+
+ /* Raw physical memory dumps don't have a virtual address. */
+ if (md->md_vaddr == ~0UL) {
+ /* We always map a 256MB page at 256M. */
+ gran = 256 * 1024 * 1024;
+ pa = md->md_paddr + ofs;
+ ppa = pa & ~(gran - 1);
+ ofs = pa - ppa;
+ va = gran;
+ tlb1_set_entry(va, ppa, gran, _TLB_ENTRY_IO);
+ if (*sz > (gran - ofs))
+ *sz = gran - ofs;
+ return (va + ofs);
+ }
+
+ /* Minidumps are based on virtual memory addresses. */
+ va = md->md_vaddr + ofs;
+ if (va >= kernstart + kernsize) {
+ gran = PAGE_SIZE - (va & PAGE_MASK);
+ if (*sz > gran)
+ *sz = gran;
+ }
+ return (va);
+}
+
+void
+mmu_booke_dumpsys_unmap(mmu_t mmu, struct pmap_md *md, vm_size_t ofs,
+ vm_offset_t va)
+{
+
+ /* Raw physical memory dumps don't have a virtual address. */
+ if (md->md_vaddr == ~0UL) {
+ tlb1_idx--;
+ tlb1[tlb1_idx].mas1 = 0;
+ tlb1[tlb1_idx].mas2 = 0;
+ tlb1[tlb1_idx].mas3 = 0;
+ tlb1_write_entry(tlb1_idx);
+ return;
+ }
+
+ /* Minidumps are based on virtual memory addresses. */
+ /* Nothing to do... */
+}
+
+struct pmap_md *
+mmu_booke_scan_md(mmu_t mmu, struct pmap_md *prev)
+{
+ static struct pmap_md md;
+ struct bi_mem_region *mr;
+ pte_t *pte;
+ vm_offset_t va;
+
+ if (dumpsys_minidump) {
+ md.md_paddr = ~0UL; /* Minidumps use virtual addresses. */
+ if (prev == NULL) {
+ /* 1st: kernel .data and .bss. */
+ md.md_index = 1;
+ md.md_vaddr = trunc_page((uintptr_t)_etext);
+ md.md_size = round_page((uintptr_t)_end) - md.md_vaddr;
+ return (&md);
+ }
+ switch (prev->md_index) {
+ case 1:
+ /* 2nd: msgbuf and tables (see pmap_bootstrap()). */
+ md.md_index = 2;
+ md.md_vaddr = data_start;
+ md.md_size = data_end - data_start;
+ break;
+ case 2:
+ /* 3rd: kernel VM. */
+ va = prev->md_vaddr + prev->md_size;
+ /* Find start of next chunk (from va). */
+ while (va < virtual_end) {
+ /* Don't dump the buffer cache. */
+ if (va >= kmi.buffer_sva &&
+ va < kmi.buffer_eva) {
+ va = kmi.buffer_eva;
+ continue;
+ }
+ pte = pte_find(mmu, kernel_pmap, va);
+ if (pte != NULL && PTE_ISVALID(pte))
+ break;
+ va += PAGE_SIZE;
+ }
+ if (va < virtual_end) {
+ md.md_vaddr = va;
+ va += PAGE_SIZE;
+ /* Find last page in chunk. */
+ while (va < virtual_end) {
+ /* Don't run into the buffer cache. */
+ if (va == kmi.buffer_sva)
+ break;
+ pte = pte_find(mmu, kernel_pmap, va);
+ if (pte == NULL || !PTE_ISVALID(pte))
+ break;
+ va += PAGE_SIZE;
+ }
+ md.md_size = va - md.md_vaddr;
+ break;
+ }
+ md.md_index = 3;
+ /* FALLTHROUGH */
+ default:
+ return (NULL);
+ }
+ } else { /* minidumps */
+ mr = bootinfo_mr();
+ if (prev == NULL) {
+ /* first physical chunk. */
+ md.md_paddr = mr->mem_base;
+ md.md_size = mr->mem_size;
+ md.md_vaddr = ~0UL;
+ md.md_index = 1;
+ } else if (md.md_index < bootinfo->bi_mem_reg_no) {
+ md.md_paddr = mr[md.md_index].mem_base;
+ md.md_size = mr[md.md_index].mem_size;
+ md.md_vaddr = ~0UL;
+ md.md_index++;
+ } else {
+ /* There's no next physical chunk. */
+ return (NULL);
+ }
+ }
+
+ return (&md);
+}
+
/*
* Map a set of physical memory pages into the kernel virtual address space.
* Return a pointer to where it is mapped. This routine is intended to be used
diff --git a/sys/powerpc/conf/GENERIC b/sys/powerpc/conf/GENERIC
index b87f899..a85ded0 100644
--- a/sys/powerpc/conf/GENERIC
+++ b/sys/powerpc/conf/GENERIC
@@ -140,7 +140,6 @@ device ulpt # Printer
device umass # Disks/Mass storage - Requires scbus and da0
device ums # Mouse
device urio # Diamond Rio 500 MP3 player
-device uscanner # Scanners
# USB Ethernet
device aue # ADMtek USB Ethernet
device axe # ASIX Electronics USB Ethernet
diff --git a/sys/powerpc/include/elf.h b/sys/powerpc/include/elf.h
index 422a86a..1224fbb 100644
--- a/sys/powerpc/include/elf.h
+++ b/sys/powerpc/include/elf.h
@@ -77,8 +77,9 @@ __ElfType(Auxinfo);
#define AT_DCACHEBSIZE 10 /* Data cache block size for the processor. */
#define AT_ICACHEBSIZE 11 /* Instruction cache block size for the uP. */
#define AT_UCACHEBSIZE 12 /* Cache block size, or `0' if cache not unified. */
+#define AT_EXECPATH 13 /* Path to the executable. */
-#define AT_COUNT 13 /* Count of defined aux entry types. */
+#define AT_COUNT 14 /* Count of defined aux entry types. */
/*
* Relocation types.
diff --git a/sys/powerpc/include/hid.h b/sys/powerpc/include/hid.h
index d9fd6fe..41602fd 100644
--- a/sys/powerpc/include/hid.h
+++ b/sys/powerpc/include/hid.h
@@ -47,6 +47,7 @@
#define HID0_SLEEP 0x00200000 /* Enable sleep mode */
#define HID0_DPM 0x00100000 /* Enable Dynamic power management */
#define HID0_RISEG 0x00080000 /* Read I-SEG */
+#define HID0_TG 0x00040000 /* Timebase Granularity (OEA64) */
#define HID0_BHTCLR 0x00040000 /* Clear branch history table (7450) */
#define HID0_EIEC 0x00040000 /* Enable internal error checking */
#define HID0_XAEN 0x00020000 /* Enable eXtended Addressing (7450) */
@@ -146,4 +147,6 @@
* 7457: XBSEN = Extended BAT Block Size Enable
*/
+#define HID5_970_DCBZ_SIZE_HI 0x01000000 /* dcbz does a 32-byte store */
+
#endif /* _POWERPC_HID_H_ */
diff --git a/sys/powerpc/include/intr.h b/sys/powerpc/include/intr.h
index 8bc417c..72c8542 100644
--- a/sys/powerpc/include/intr.h
+++ b/sys/powerpc/include/intr.h
@@ -63,48 +63,11 @@
#ifndef LOCORE
-#if 0
-/*
- * Interrupt handler chains. intr_establish() inserts a handler into
- * the list. The handler is called with its (single) argument.
- */
-struct intrhand {
- int (*ih_fun)(void *);
- void *ih_arg;
- u_long ih_count;
- struct intrhand *ih_next;
- int ih_level;
- int ih_irq;
-};
-#endif
-
-void setsoftclock(void);
-void clearsoftclock(void);
-void setsoftnet(void);
-void clearsoftnet(void);
-
void do_pending_int(void);
-static __inline void softintr(int);
-
extern u_int cpl, ipending, tickspending;
extern int imask[];
-/* Following code should be implemented with lwarx/stwcx to avoid
- * the disable/enable. i need to read the manual once more.... */
-static __inline void
-softintr(int ipl)
-{
- unsigned int msrsave;
-
- msrsave = mfmsr();
- mtmsr(msrsave & ~PSL_EE);
-
- ipending |= 1 << ipl;
-
- mtmsr(msrsave);
-}
-
#define ICU_LEN 64
/* Soft interrupt masks. */
@@ -113,46 +76,6 @@ softintr(int ipl)
#define SIR_SERIAL 30
#define SPL_CLOCK 31
-#if 0
-
-/*
- * Hardware interrupt masks
- */
-
-#define splbio() splraise(imask[IPL_BIO])
-#define splnet() splraise(imask[IPL_NET])
-#define spltty() splraise(imask[IPL_TTY])
-#define splaudio() splraise(imask[IPL_AUDIO])
-#define splclock() splraise(imask[IPL_CLOCK])
-#define splstatclock() splclock()
-#define splserial() splraise(imask[IPL_SERIAL])
-
-#define spllpt() spltty()
-
-/*
- * Software interrupt masks
- *
- * NOTE: splsoftclock() is used by hardclock() to lower the priority from
- * clock to softclock before it calls softclock().
- */
-#define spllowersoftclock() spllower(imask[IPL_SOFTCLOCK])
-#define splsoftclock() splraise(imask[IPL_SOFTCLOCK])
-#define splsoftnet() splraise(imask[IPL_SOFTNET])
-#define splsoftserial() splraise(imask[IPL_SOFTSERIAL])
-
-/*
- * Miscellaneous
- */
-#define splimp() splraise(imask[IPL_IMP])
-#define splhigh() splraise(imask[IPL_HIGH])
-#define spl0() spllower(0)
-
-#endif /* 0 */
-
-#define setsoftclock() softintr(SIR_CLOCK)
-#define setsoftnet() softintr(SIR_NET)
-#define setsoftserial() softintr(SIR_SERIAL)
-
#define CNT_IRQ0 0
#define CNT_CLOCK 64
#define CNT_SOFTCLOCK 65
diff --git a/sys/powerpc/include/md_var.h b/sys/powerpc/include/md_var.h
index c554f5f..709e4a9 100644
--- a/sys/powerpc/include/md_var.h
+++ b/sys/powerpc/include/md_var.h
@@ -46,6 +46,8 @@ extern u_long ns_per_tick;
extern int powerpc_pow_enabled;
extern int cacheline_size;
+extern int ppc64;
+extern int hw_direct_map;
void __syncicache(void *, int);
diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h
index 2b2d6af..5e6d9c6 100644
--- a/sys/powerpc/include/pmap.h
+++ b/sys/powerpc/include/pmap.h
@@ -71,6 +71,13 @@
#include <machine/pte.h>
#include <machine/tlb.h>
+struct pmap_md {
+ u_int md_index;
+ vm_paddr_t md_paddr;
+ vm_offset_t md_vaddr;
+ vm_size_t md_size;
+};
+
#if defined(AIM)
#if !defined(NPMAPS)
@@ -179,6 +186,11 @@ extern vm_offset_t msgbuf_phys;
extern int pmap_bootstrapped;
+extern vm_offset_t pmap_dumpsys_map(struct pmap_md *, vm_size_t, vm_size_t *);
+extern void pmap_dumpsys_unmap(struct pmap_md *, vm_size_t, vm_offset_t);
+
+extern struct pmap_md *pmap_scan_md(struct pmap_md *);
+
#endif
#endif /* !_MACHINE_PMAP_H_ */
diff --git a/sys/powerpc/include/sf_buf.h b/sys/powerpc/include/sf_buf.h
index 162f5a6..7ddb981 100644
--- a/sys/powerpc/include/sf_buf.h
+++ b/sys/powerpc/include/sf_buf.h
@@ -32,33 +32,9 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <vm/vm_page.h>
+#include <machine/md_var.h>
#include <sys/queue.h>
-#if defined(AIM)
-/*
- * On this machine, the only purpose for which sf_buf is used is to implement
- * an opaque pointer required by the machine-independent parts of the kernel.
- * That pointer references the vm_page that is "mapped" by the sf_buf. The
- * actual mapping is provided by the direct virtual-to-physical mapping.
- */
-struct sf_buf;
-
-static __inline vm_offset_t
-sf_buf_kva(struct sf_buf *sf)
-{
-
- return (VM_PAGE_TO_PHYS((vm_page_t)sf));
-}
-
-static __inline vm_page_t
-sf_buf_page(struct sf_buf *sf)
-{
-
- return ((vm_page_t)sf);
-}
-
-#elif defined(E500)
-
struct vm_page;
struct sf_buf {
@@ -69,9 +45,22 @@ struct sf_buf {
int ref_count; /* usage of this mapping */
};
+/*
+ * On 32-bit OEA, the only purpose for which sf_buf is used is to implement
+ * an opaque pointer required by the machine-independent parts of the kernel.
+ * That pointer references the vm_page that is "mapped" by the sf_buf. The
+ * actual mapping is provided by the direct virtual-to-physical mapping.
+ *
+ * On OEA64 and Book-E, we need to do something a little more complicated. Use
+ * the runtime-detected hw_direct_map to pick between the two cases. Our
+ * friends in vm_machdep.c will do the same to ensure nothing gets confused.
+ */
+
static __inline vm_offset_t
sf_buf_kva(struct sf_buf *sf)
{
+ if (hw_direct_map)
+ return (VM_PAGE_TO_PHYS((vm_page_t)sf));
return (sf->kva);
}
@@ -79,10 +68,10 @@ sf_buf_kva(struct sf_buf *sf)
static __inline struct vm_page *
sf_buf_page(struct sf_buf *sf)
{
+ if (hw_direct_map)
+ return ((vm_page_t)sf);
return (sf->m);
}
-#endif
-
#endif /* !_MACHINE_SF_BUF_H_ */
diff --git a/sys/powerpc/include/spr.h b/sys/powerpc/include/spr.h
index 70a0012..84fab0d 100644
--- a/sys/powerpc/include/spr.h
+++ b/sys/powerpc/include/spr.h
@@ -43,6 +43,44 @@
( { register_t val; \
__asm __volatile("mfspr %0,%1" : "=r"(val) : "K"(reg)); \
val; } )
+
+/* The following routines allow manipulation of the full 64-bit width
+ * of SPRs on 64 bit CPUs in bridge mode */
+
+#define mtspr64(reg,valhi,vallo,scratch) \
+ __asm __volatile(" \
+ mfmsr %0; \
+ insrdi %0,1,1,0; \
+ mtmsrd %0; \
+ isync; \
+ \
+ sld %1,%1,%4; \
+ or %1,%1,%2; \
+ mtspr %3,%1; \
+ srd %1,%1,%4; \
+ \
+ clrldi %0,%0,1; \
+ mtmsrd %0; \
+ isync;" \
+ : "=r"(scratch), "=r"(valhi) : "r"(vallo), "K"(reg), "r"(32))
+
+#define mfspr64upper(reg,scratch) \
+ ( { register_t val; \
+ __asm __volatile(" \
+ mfmsr %0; \
+ insrdi %0,1,1,0; \
+ mtmsrd %0; \
+ isync; \
+ \
+ mfspr %1,%2; \
+ srd %1,%1,%3; \
+ \
+ clrldi %0,%0,1; \
+ mtmsrd %0; \
+ isync;" \
+ : "=r"(scratch), "=r"(val) : "K"(reg), "r"(32)); \
+ val; } )
+
#endif /* _LOCORE */
/*
@@ -112,7 +150,11 @@
#define IBM401E2 0x0025
#define IBM401F2 0x0026
#define IBM401G2 0x0027
+#define IBM970 0x0039
+#define IBM970FX 0x003c
#define IBMPOWER3 0x0041
+#define IBM970MP 0x0044
+#define IBM970GX 0x0045
#define MPC860 0x0050
#define MPC8240 0x0081
#define IBM405GP 0x4011
@@ -349,6 +391,8 @@
#define SPR_SRR3 0x3df /* 4.. Save/Restore Register 3 */
#define SPR_HID0 0x3f0 /* ..8 Hardware Implementation Register 0 */
#define SPR_HID1 0x3f1 /* ..8 Hardware Implementation Register 1 */
+#define SPR_HID4 0x3f4 /* ..8 Hardware Implementation Register 4 */
+#define SPR_HID5 0x3f6 /* ..8 Hardware Implementation Register 5 */
#if defined(AIM)
#define SPR_DBSR 0x3f0 /* 4.. Debug Status Register */
@@ -564,6 +608,8 @@
#define SVR_MPC8533E 0x8034
#define SVR_MPC8541 0x8072
#define SVR_MPC8541E 0x807a
+#define SVR_MPC8548 0x8031
+#define SVR_MPC8548E 0x8039
#define SVR_MPC8555 0x8071
#define SVR_MPC8555E 0x8079
#define SVR_MPC8572 0x80e0
diff --git a/sys/powerpc/include/sysarch.h b/sys/powerpc/include/sysarch.h
new file mode 100644
index 0000000..c46d100
--- /dev/null
+++ b/sys/powerpc/include/sysarch.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 1993 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_SYSARCH_H_
+#define _MACHINE_SYSARCH_H_
+
+#ifndef _KERNEL
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int sysarch(int, void *);
+__END_DECLS
+#endif
+
+#endif /* !_MACHINE_SYSARCH_H_ */
diff --git a/sys/powerpc/include/vmparam.h b/sys/powerpc/include/vmparam.h
index 489159d..5af62eb 100644
--- a/sys/powerpc/include/vmparam.h
+++ b/sys/powerpc/include/vmparam.h
@@ -106,6 +106,13 @@
*/
#define UMA_MD_SMALL_ALLOC
+/*
+ * On 64-bit systems in bridge mode, we have no direct map, so we fake
+ * the small_alloc() calls. But we need the VM to be in a reasonable
+ * state first.
+ */
+#define UMA_MD_SMALL_ALLOC_NEEDS_VM
+
#else
/*
diff --git a/sys/powerpc/mpc85xx/mpc85xx.c b/sys/powerpc/mpc85xx/mpc85xx.c
index de9c771..b6de50d 100644
--- a/sys/powerpc/mpc85xx/mpc85xx.c
+++ b/sys/powerpc/mpc85xx/mpc85xx.c
@@ -61,7 +61,7 @@ ccsr_write4(uintptr_t addr, uint32_t val)
__asm __volatile("eieio; sync");
}
-static __inline int
+int
law_getmax(void)
{
uint32_t ver;
@@ -69,6 +69,8 @@ law_getmax(void)
ver = SVR_VER(mfspr(SPR_SVR));
if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
return (12);
+ else if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
+ return (10);
else
return (8);
}
@@ -132,7 +134,8 @@ cpu_reset(void)
{
uint32_t ver = SVR_VER(mfspr(SPR_SVR));
- if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
+ if (ver == SVR_MPC8572E || ver == SVR_MPC8572 ||
+ ver == SVR_MPC8548E || ver == SVR_MPC8548)
/* Systems with dedicated reset register */
ccsr_write4(OCP85XX_RSTCR, 2);
else {
diff --git a/sys/powerpc/mpc85xx/mpc85xx.h b/sys/powerpc/mpc85xx/mpc85xx.h
index 4d31b58..e558489 100644
--- a/sys/powerpc/mpc85xx/mpc85xx.h
+++ b/sys/powerpc/mpc85xx/mpc85xx.h
@@ -33,5 +33,6 @@ uint32_t ccsr_read4(uintptr_t addr);
void ccsr_write4(uintptr_t addr, uint32_t val);
int law_enable(int trgt, u_long addr, u_long size);
int law_disable(int trgt, u_long addr, u_long size);
+int law_getmax(void);
#endif /* _MPC85XX_H_ */
diff --git a/sys/powerpc/mpc85xx/ocpbus.c b/sys/powerpc/mpc85xx/ocpbus.c
index ae56fb0..ddc2e74 100644
--- a/sys/powerpc/mpc85xx/ocpbus.c
+++ b/sys/powerpc/mpc85xx/ocpbus.c
@@ -114,8 +114,6 @@ devclass_t ocpbus_devclass;
DRIVER_MODULE(ocpbus, nexus, ocpbus_driver, ocpbus_devclass, 0, 0);
-static int law_max = 0;
-
static device_t
ocpbus_mk_child(device_t dev, int type, int unit)
{
@@ -189,16 +187,6 @@ ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp)
static int
ocpbus_probe(device_t dev)
{
- struct ocpbus_softc *sc;
- uint32_t ver;
-
- sc = device_get_softc(dev);
-
- ver = SVR_VER(mfspr(SPR_SVR));
- if (ver == SVR_MPC8572E || ver == SVR_MPC8572)
- law_max = 12;
- else
- law_max = 8;
device_set_desc(dev, "On-Chip Peripherals bus");
return (BUS_PROBE_DEFAULT);
@@ -208,7 +196,7 @@ static int
ocpbus_attach(device_t dev)
{
struct ocpbus_softc *sc;
- int error, i, tgt;
+ int error, i, tgt, law_max;
uint32_t sr;
u_long start, end;
@@ -261,6 +249,7 @@ ocpbus_attach(device_t dev)
* Clear local access windows. Skip DRAM entries, so we don't shoot
* ourselves in the foot.
*/
+ law_max = law_getmax();
for (i = 0; i < law_max; i++) {
sr = ccsr_read4(OCP85XX_LAWSR(i));
if ((sr & 0x80000000) == 0)
diff --git a/sys/powerpc/ofw/ofw_real.c b/sys/powerpc/ofw/ofw_real.c
new file mode 100644
index 0000000..c5f11b0
--- /dev/null
+++ b/sys/powerpc/ofw/ofw_real.c
@@ -0,0 +1,922 @@
+/* $NetBSD: Locore.c,v 1.7 2000/08/20 07:04:59 tsubai Exp $ */
+
+/*-
+ * Copyright (C) 1995, 1996 Wolfgang Solfrank.
+ * Copyright (C) 1995, 1996 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (C) 2000 Benno Rice.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/systm.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/stdarg.h>
+#include <machine/bus.h>
+#include <machine/pmap.h>
+#include <machine/ofw_machdep.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofwvar.h>
+#include "ofw_if.h"
+
+static void ofw_real_init(ofw_t, void *openfirm);
+static int ofw_real_test(ofw_t, const char *name);
+static phandle_t ofw_real_peer(ofw_t, phandle_t node);
+static phandle_t ofw_real_child(ofw_t, phandle_t node);
+static phandle_t ofw_real_parent(ofw_t, phandle_t node);
+static phandle_t ofw_real_instance_to_package(ofw_t, ihandle_t instance);
+static ssize_t ofw_real_getproplen(ofw_t, phandle_t package,
+ const char *propname);
+static ssize_t ofw_real_getprop(ofw_t, phandle_t package, const char *propname,
+ void *buf, size_t buflen);
+static int ofw_real_nextprop(ofw_t, phandle_t package, const char *previous,
+ char *buf, size_t);
+static int ofw_real_setprop(ofw_t, phandle_t package, char *propname,
+ void *buf, size_t len);
+static ssize_t ofw_real_canon(ofw_t, const char *device, char *buf, size_t len);
+static phandle_t ofw_real_finddevice(ofw_t, const char *device);
+static ssize_t ofw_real_instance_to_path(ofw_t, ihandle_t instance, char *buf,
+ size_t len);
+static ssize_t ofw_real_package_to_path(ofw_t, phandle_t package, char *buf,
+ size_t len);
+static int ofw_real_call_method(ofw_t, ihandle_t instance, const char *method,
+ int nargs, int nreturns, unsigned long *args_and_returns);
+static ihandle_t ofw_real_open(ofw_t, const char *device);
+static void ofw_real_close(ofw_t, ihandle_t instance);
+static ssize_t ofw_real_read(ofw_t, ihandle_t instance, void *addr, size_t len);
+static ssize_t ofw_real_write(ofw_t, ihandle_t instance, const void *addr,
+ size_t len);
+static int ofw_real_seek(ofw_t, ihandle_t instance, u_int64_t pos);
+static caddr_t ofw_real_claim(ofw_t, void *virt, size_t size, u_int align);
+static void ofw_real_release(ofw_t, void *virt, size_t size);
+static void ofw_real_enter(ofw_t);
+static void ofw_real_exit(ofw_t);
+
+static ofw_method_t ofw_real_methods[] = {
+ OFWMETHOD(ofw_init, ofw_real_init),
+ OFWMETHOD(ofw_peer, ofw_real_peer),
+ OFWMETHOD(ofw_child, ofw_real_child),
+ OFWMETHOD(ofw_parent, ofw_real_parent),
+ OFWMETHOD(ofw_instance_to_package, ofw_real_instance_to_package),
+ OFWMETHOD(ofw_getproplen, ofw_real_getproplen),
+ OFWMETHOD(ofw_getprop, ofw_real_getprop),
+ OFWMETHOD(ofw_nextprop, ofw_real_nextprop),
+ OFWMETHOD(ofw_setprop, ofw_real_setprop),
+ OFWMETHOD(ofw_canon, ofw_real_canon),
+ OFWMETHOD(ofw_finddevice, ofw_real_finddevice),
+ OFWMETHOD(ofw_instance_to_path, ofw_real_instance_to_path),
+ OFWMETHOD(ofw_package_to_path, ofw_real_package_to_path),
+
+ OFWMETHOD(ofw_test, ofw_real_test),
+ OFWMETHOD(ofw_call_method, ofw_real_call_method),
+ OFWMETHOD(ofw_open, ofw_real_open),
+ OFWMETHOD(ofw_close, ofw_real_close),
+ OFWMETHOD(ofw_read, ofw_real_read),
+ OFWMETHOD(ofw_write, ofw_real_write),
+ OFWMETHOD(ofw_seek, ofw_real_seek),
+ OFWMETHOD(ofw_claim, ofw_real_claim),
+ OFWMETHOD(ofw_release, ofw_real_release),
+ OFWMETHOD(ofw_enter, ofw_real_enter),
+ OFWMETHOD(ofw_exit, ofw_real_exit),
+
+ { 0, 0 }
+};
+
+static ofw_def_t ofw_real = {
+ OFW_STD_REAL,
+ ofw_real_methods,
+ 0
+};
+OFW_DEF(ofw_real);
+
+MALLOC_DEFINE(M_OFWREAL, "ofwreal", "Open Firmware Real Mode Bounce Page");
+
+static int (*openfirmware)(void *);
+
+static vm_offset_t of_bounce_phys;
+static caddr_t of_bounce_virt;
+static off_t of_bounce_offset;
+static size_t of_bounce_size;
+static struct mtx of_bounce_mtx;
+
+/*
+ * After the VM is up, allocate a wired, low memory bounce page.
+ */
+
+static void ofw_real_bounce_alloc(void *);
+
+SYSINIT(ofw_real_bounce_alloc, SI_SUB_VM, SI_ORDER_ANY,
+ ofw_real_bounce_alloc, NULL);
+
+static void
+ofw_real_start(void)
+{
+ mtx_lock(&of_bounce_mtx);
+ of_bounce_offset = 0;
+}
+
+static void
+ofw_real_stop(void)
+{
+ mtx_unlock(&of_bounce_mtx);
+}
+
+static void
+ofw_real_bounce_alloc(void *junk)
+{
+ /*
+ * Check that ofw_real is actually in use before allocating wads
+ * of memory. Do this by checking if our mutex has been set up.
+ */
+ if (!mtx_initialized(&of_bounce_mtx))
+ return;
+
+ /*
+ * Allocate a page of contiguous, wired physical memory that can
+ * fit into a 32-bit address space.
+ */
+
+ mtx_lock(&of_bounce_mtx);
+
+ of_bounce_virt = contigmalloc(PAGE_SIZE, M_OFWREAL, 0,
+ 0, BUS_SPACE_MAXADDR_32BIT, PAGE_SIZE, PAGE_SIZE);
+ of_bounce_phys = vtophys(of_bounce_virt);
+ of_bounce_size = PAGE_SIZE;
+
+ mtx_unlock(&of_bounce_mtx);
+}
+
+static cell_t
+ofw_real_map(const void *buf, size_t len)
+{
+ cell_t phys;
+
+ mtx_assert(&of_bounce_mtx, MA_OWNED);
+
+ if (of_bounce_virt == NULL) {
+ if (!pmap_bootstrapped)
+ return (cell_t)buf;
+
+ /*
+ * XXX: It is possible for us to get called before the VM has
+ * come online, but after the MMU is up. We don't have the
+ * bounce buffer yet, but can no longer presume a 1:1 mapping.
+ * Grab the physical address of the buffer, and hope it is
+ * in range if this happens.
+ */
+ return (cell_t)vtophys(buf);
+ }
+
+ /*
+ * Make sure the bounce page offset satisfies any reasonable
+ * alignment constraint.
+ */
+ of_bounce_offset += of_bounce_offset % sizeof(register_t);
+
+ if (of_bounce_offset + len > of_bounce_size) {
+ panic("Oversize Open Firmware call!");
+ return 0;
+ }
+
+ memcpy(of_bounce_virt + of_bounce_offset, buf, len);
+ phys = of_bounce_phys + of_bounce_offset;
+
+ of_bounce_offset += len;
+
+ return phys;
+}
+
+static void
+ofw_real_unmap(cell_t physaddr, void *buf, size_t len)
+{
+ mtx_assert(&of_bounce_mtx, MA_OWNED);
+
+ if (of_bounce_virt == NULL)
+ return;
+
+ memcpy(buf,of_bounce_virt + (physaddr - of_bounce_phys),len);
+}
+
+/* Initialiser */
+
+static void
+ofw_real_init(ofw_t ofw, void *openfirm)
+{
+ openfirmware = (int (*)(void *))openfirm;
+
+ mtx_init(&of_bounce_mtx, "OF Bounce Page", MTX_DEF, 0);
+ of_bounce_virt = NULL;
+}
+
+/*
+ * Generic functions
+ */
+
+/* Test to see if a service exists. */
+static int
+ofw_real_test(ofw_t ofw, const char *name)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t service;
+ cell_t missing;
+ } args = {
+ (cell_t)"test",
+ 1,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.service = ofw_real_map(name, strlen(name) + 1);
+ if (args.service == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_stop();
+ return (args.missing);
+}
+
+/*
+ * Device tree functions
+ */
+
+/* Return the next sibling of this node or 0. */
+static phandle_t
+ofw_real_peer(ofw_t ofw, phandle_t node)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t node;
+ cell_t next;
+ } args = {
+ (cell_t)"peer",
+ 1,
+ 1,
+ };
+
+ args.node = node;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.next);
+}
+
+/* Return the first child of this node or 0. */
+static phandle_t
+ofw_real_child(ofw_t ofw, phandle_t node)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t node;
+ cell_t child;
+ } args = {
+ (cell_t)"child",
+ 1,
+ 1,
+ };
+
+ args.node = node;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.child);
+}
+
+/* Return the parent of this node or 0. */
+static phandle_t
+ofw_real_parent(ofw_t ofw, phandle_t node)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t node;
+ cell_t parent;
+ } args = {
+ (cell_t)"parent",
+ 1,
+ 1,
+ };
+
+ args.node = node;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.parent);
+}
+
+/* Return the package handle that corresponds to an instance handle. */
+static phandle_t
+ofw_real_instance_to_package(ofw_t ofw, ihandle_t instance)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t package;
+ } args = {
+ (cell_t)"instance-to-package",
+ 1,
+ 1,
+ };
+
+ args.instance = instance;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.package);
+}
+
+/* Get the length of a property of a package. */
+static ssize_t
+ofw_real_getproplen(ofw_t ofw, phandle_t package, const char *propname)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t propname;
+ cell_t proplen;
+ } args = {
+ (cell_t)"getproplen",
+ 2,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.package = package;
+ args.propname = ofw_real_map(propname, strlen(propname) + 1);
+ if (args.propname == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_stop();
+ return (args.proplen);
+}
+
+/* Get the value of a property of a package. */
+static ssize_t
+ofw_real_getprop(ofw_t ofw, phandle_t package, const char *propname, void *buf,
+ size_t buflen)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t propname;
+ cell_t buf;
+ cell_t buflen;
+ cell_t size;
+ } args = {
+ (cell_t)"getprop",
+ 4,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.package = package;
+ args.propname = ofw_real_map(propname, strlen(propname) + 1);
+ args.buf = ofw_real_map(buf, buflen);
+ args.buflen = buflen;
+ if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_unmap(args.buf, buf, buflen);
+
+ ofw_real_stop();
+ return (args.size);
+}
+
+/* Get the next property of a package. */
+static int
+ofw_real_nextprop(ofw_t ofw, phandle_t package, const char *previous,
+ char *buf, size_t size)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t previous;
+ cell_t buf;
+ cell_t flag;
+ } args = {
+ (cell_t)"nextprop",
+ 3,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.package = package;
+ args.previous = ofw_real_map(previous, strlen(previous) + 1);
+ args.buf = ofw_real_map(buf, size);
+ if (args.previous == 0 || args.buf == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_unmap(args.buf, buf, size);
+
+ ofw_real_stop();
+ return (args.flag);
+}
+
+/* Set the value of a property of a package. */
+/* XXX Has a bug on FirePower */
+static int
+ofw_real_setprop(ofw_t ofw, phandle_t package, char *propname, void *buf,
+ size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t propname;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"setprop",
+ 4,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.package = package;
+ args.propname = ofw_real_map(propname, strlen(propname) + 1);
+ args.buf = ofw_real_map(buf, len);
+ args.len = len;
+ if (args.propname == 0 || args.buf == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_stop();
+ return (args.size);
+}
+
+/* Convert a device specifier to a fully qualified pathname. */
+static ssize_t
+ofw_real_canon(ofw_t ofw, const char *device, char *buf, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t device;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"canon",
+ 3,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.device = ofw_real_map(device, strlen(device) + 1);
+ args.buf = ofw_real_map(buf, len);
+ args.len = len;
+ if (args.device == 0 || args.buf == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_unmap(args.buf, buf, len);
+
+ ofw_real_stop();
+ return (args.size);
+}
+
+/* Return a package handle for the specified device. */
+static phandle_t
+ofw_real_finddevice(ofw_t ofw, const char *device)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t device;
+ cell_t package;
+ } args = {
+ (cell_t)"finddevice",
+ 1,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.device = ofw_real_map(device, strlen(device) + 1);
+ if (args.device == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_stop();
+ return (args.package);
+}
+
+/* Return the fully qualified pathname corresponding to an instance. */
+static ssize_t
+ofw_real_instance_to_path(ofw_t ofw, ihandle_t instance, char *buf, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"instance-to-path",
+ 3,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.instance = instance;
+ args.buf = ofw_real_map(buf, len);
+ args.len = len;
+ if (args.buf == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_unmap(args.buf, buf, len);
+
+ ofw_real_stop();
+ return (args.size);
+}
+
+/* Return the fully qualified pathname corresponding to a package. */
+static ssize_t
+ofw_real_package_to_path(ofw_t ofw, phandle_t package, char *buf, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t package;
+ cell_t buf;
+ cell_t len;
+ cell_t size;
+ } args = {
+ (cell_t)"package-to-path",
+ 3,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.package = package;
+ args.buf = ofw_real_map(buf, len);
+ args.len = len;
+ if (args.buf == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_unmap(args.buf, buf, len);
+
+ ofw_real_stop();
+ return (args.size);
+}
+
+/* Call the method in the scope of a given instance. */
+static int
+ofw_real_call_method(ofw_t ofw, ihandle_t instance, const char *method,
+ int nargs, int nreturns, unsigned long *args_and_returns)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t method;
+ cell_t instance;
+ cell_t args_n_results[12];
+ } args = {
+ (cell_t)"call-method",
+ 2,
+ 1,
+ };
+ cell_t *cp;
+ unsigned long *ap;
+ int n;
+
+ if (nargs > 6)
+ return (-1);
+
+ ofw_real_start();
+ args.nargs = nargs + 2;
+ args.nreturns = nreturns + 1;
+ args.method = ofw_real_map(method, strlen(method) + 1);
+ args.instance = instance;
+
+ ap = args_and_returns;
+ for (cp = args.args_n_results + (n = nargs); --n >= 0;)
+ *--cp = *(ap++);
+ if (args.method == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_stop();
+ if (args.args_n_results[nargs])
+ return (args.args_n_results[nargs]);
+ for (cp = args.args_n_results + nargs + (n = args.nreturns); --n > 0;)
+ *(ap++) = *--cp;
+ return (0);
+}
+
+/*
+ * Device I/O functions
+ */
+
+/* Open an instance for a device. */
+static ihandle_t
+ofw_real_open(ofw_t ofw, const char *device)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t device;
+ cell_t instance;
+ } args = {
+ (cell_t)"open",
+ 1,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.device = ofw_real_map(device, strlen(device) + 1);
+ if (args.device == 0 || openfirmware(&args) == -1
+ || args.instance == 0) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_stop();
+ return (args.instance);
+}
+
+/* Close an instance. */
+static void
+ofw_real_close(ofw_t ofw, ihandle_t instance)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ } args = {
+ (cell_t)"close",
+ 1,
+ };
+
+ args.instance = instance;
+ openfirmware(&args);
+}
+
+/* Read from an instance. */
+static ssize_t
+ofw_real_read(ofw_t ofw, ihandle_t instance, void *addr, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t addr;
+ cell_t len;
+ cell_t actual;
+ } args = {
+ (cell_t)"read",
+ 3,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.instance = instance;
+ args.addr = ofw_real_map(addr, len);
+ args.len = len;
+ if (args.addr == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_unmap(args.addr, addr, len);
+
+ ofw_real_stop();
+ return (args.actual);
+}
+
+/* Write to an instance. */
+static ssize_t
+ofw_real_write(ofw_t ofw, ihandle_t instance, const void *addr, size_t len)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t addr;
+ cell_t len;
+ cell_t actual;
+ } args = {
+ (cell_t)"write",
+ 3,
+ 1,
+ };
+
+ ofw_real_start();
+
+ args.instance = instance;
+ args.addr = ofw_real_map(addr, len);
+ args.len = len;
+ if (args.addr == 0 || openfirmware(&args) == -1) {
+ ofw_real_stop();
+ return (-1);
+ }
+ ofw_real_stop();
+ return (args.actual);
+}
+
+/* Seek to a position. */
+static int
+ofw_real_seek(ofw_t ofw, ihandle_t instance, u_int64_t pos)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t instance;
+ cell_t poshi;
+ cell_t poslo;
+ cell_t status;
+ } args = {
+ (cell_t)"seek",
+ 3,
+ 1,
+ };
+
+ args.instance = instance;
+ args.poshi = pos >> 32;
+ args.poslo = pos;
+ if (openfirmware(&args) == -1)
+ return (-1);
+ return (args.status);
+}
+
+/*
+ * Memory functions
+ */
+
+/* Claim an area of memory. */
+static caddr_t
+ofw_real_claim(ofw_t ofw, void *virt, size_t size, u_int align)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t virt;
+ cell_t size;
+ cell_t align;
+ cell_t baseaddr;
+ } args = {
+ (cell_t)"claim",
+ 3,
+ 1,
+ };
+
+ args.virt = (cell_t)virt;
+ args.size = size;
+ args.align = align;
+ if (openfirmware(&args) == -1)
+ return ((void *)-1);
+ return ((void *)args.baseaddr);
+}
+
+/* Release an area of memory. */
+static void
+ofw_real_release(ofw_t ofw, void *virt, size_t size)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ cell_t virt;
+ cell_t size;
+ } args = {
+ (cell_t)"release",
+ 2,
+ };
+
+ args.virt = (cell_t)virt;
+ args.size = size;
+ openfirmware(&args);
+}
+
+/*
+ * Control transfer functions
+ */
+
+/* Suspend and drop back to the Open Firmware interface. */
+static void
+ofw_real_enter(ofw_t ofw)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ } args = {
+ (cell_t)"enter",
+ };
+
+ openfirmware(&args);
+ /* We may come back. */
+}
+
+/* Shut down and drop back to the Open Firmware interface. */
+static void
+ofw_real_exit(ofw_t ofw)
+{
+ static struct {
+ cell_t name;
+ cell_t nargs;
+ cell_t nreturns;
+ } args = {
+ (cell_t)"exit",
+ };
+
+ openfirmware(&args);
+ for (;;) /* just in case */
+ ;
+}
+
diff --git a/sys/powerpc/ofw/ofw_syscons.c b/sys/powerpc/ofw/ofw_syscons.c
index 1080dad..5ab5939 100644
--- a/sys/powerpc/ofw/ofw_syscons.c
+++ b/sys/powerpc/ofw/ofw_syscons.c
@@ -216,6 +216,7 @@ ofwfb_configure(int flags)
phandle_t chosen;
ihandle_t stdout;
phandle_t node;
+ bus_addr_t fb_phys;
int depth;
int disable;
int len;
@@ -270,10 +271,16 @@ ofwfb_configure(int flags)
OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride));
/*
- * XXX the physical address of the frame buffer is assumed to be
- * BAT-mapped so it can be accessed directly
+ * Grab the physical address of the framebuffer, and then map it
+ * into our memory space. If the MMU is not yet up, it will be
+ * remapped for us when relocation turns on.
+ *
+ * XXX We assume #address-cells is 1 at this point.
*/
- OF_getprop(node, "address", &sc->sc_addr, sizeof(sc->sc_addr));
+ OF_getprop(node, "address", &fb_phys, sizeof(fb_phys));
+
+ bus_space_map(&bs_be_tag, fb_phys, sc->sc_height * sc->sc_stride,
+ 0, &sc->sc_addr);
/*
* Get the PCI addresses of the adapter. The node may be the
@@ -283,8 +290,8 @@ ofwfb_configure(int flags)
len = OF_getprop(node, "assigned-addresses", sc->sc_pciaddrs,
sizeof(sc->sc_pciaddrs));
if (len == -1) {
- len = OF_getprop(OF_parent(node), "assigned-addresses", sc->sc_pciaddrs,
- sizeof(sc->sc_pciaddrs));
+ len = OF_getprop(OF_parent(node), "assigned-addresses",
+ sc->sc_pciaddrs, sizeof(sc->sc_pciaddrs));
}
if (len != -1) {
@@ -941,13 +948,17 @@ ofwfb_scidentify(driver_t *driver, device_t parent)
static int
ofwfb_scprobe(device_t dev)
{
- /* This is a fake device, so make sure there is no OF node for it */
- if (ofw_bus_get_node(dev) != -1)
- return ENXIO;
-
+ int error;
+
device_set_desc(dev, "System console");
- return (sc_probe_unit(device_get_unit(dev),
- device_get_flags(dev) | SC_AUTODETECT_KBD));
+
+ error = sc_probe_unit(device_get_unit(dev),
+ device_get_flags(dev) | SC_AUTODETECT_KBD);
+ if (error != 0)
+ return (error);
+
+ /* This is a fake device, so make sure we added it ourselves */
+ return (BUS_PROBE_NOWILDCARD);
}
static int
diff --git a/sys/powerpc/powermac/ata_macio.c b/sys/powerpc/powermac/ata_macio.c
index 482f76e..320e86e 100644
--- a/sys/powerpc/powermac/ata_macio.c
+++ b/sys/powerpc/powermac/ata_macio.c
@@ -259,6 +259,10 @@ ata_macio_setmode(device_t parent, device_t dev)
mode = ata_limit_mode(dev, mode, sc->max_mode);
+ /* XXX Some controllers don't work correctly with ATAPI DMA */
+ if (atadev->param.config & ATA_PROTO_ATAPI)
+ mode = ata_limit_mode(dev, mode, ATA_PIO_MAX);
+
if (ata_controlcmd(dev, ATA_SETFEATURES, ATA_SF_SETXFER, 0, mode))
return;
diff --git a/sys/powerpc/powermac/cpcht.c b/sys/powerpc/powermac/cpcht.c
new file mode 100644
index 0000000..b8ab22f
--- /dev/null
+++ b/sys/powerpc/powermac/cpcht.c
@@ -0,0 +1,625 @@
+/*-
+ * Copyright (C) 2008 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/kernel.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <machine/bus.h>
+#include <machine/md_var.h>
+#include <machine/pio.h>
+#include <machine/resource.h>
+
+#include <sys/rman.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <powerpc/powermac/cpchtvar.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include "pcib_if.h"
+
+#include "opt_isa.h"
+
+#ifdef DEV_ISA
+#include <isa/isavar.h>
+#endif
+
+static MALLOC_DEFINE(M_CPCHT, "cpcht", "CPC HT device information");
+
+/*
+ * HT Driver methods.
+ */
+static int cpcht_probe(device_t);
+static int cpcht_attach(device_t);
+static ofw_bus_get_devinfo_t cpcht_get_devinfo;
+
+
+static device_method_t cpcht_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, cpcht_probe),
+ DEVMETHOD(device_attach, cpcht_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource,bus_generic_activate_resource),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_devinfo, cpcht_get_devinfo),
+ DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
+ DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
+ DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
+ DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
+ DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
+
+ { 0, 0 }
+};
+
+static driver_t cpcht_driver = {
+ "cpcht",
+ cpcht_methods,
+ 0
+};
+
+static devclass_t cpcht_devclass;
+
+DRIVER_MODULE(cpcht, nexus, cpcht_driver, cpcht_devclass, 0, 0);
+
+static int
+cpcht_probe(device_t dev)
+{
+ const char *type, *compatible;
+
+ type = ofw_bus_get_type(dev);
+ compatible = ofw_bus_get_compat(dev);
+
+ if (type == NULL || compatible == NULL)
+ return (ENXIO);
+
+ if (strcmp(type, "ht") != 0)
+ return (ENXIO);
+
+ if (strcmp(compatible, "u3-ht") == 0) {
+ device_set_desc(dev, "IBM CPC925 HyperTransport Tunnel");
+ return (0);
+ } else if (strcmp(compatible,"u4-ht") == 0) {
+ device_set_desc(dev, "IBM CPC945 HyperTransport Tunnel");
+ return (0);
+ }
+
+ return (ENXIO);
+}
+
+static int
+cpcht_attach(device_t dev)
+{
+ phandle_t root, child;
+ device_t cdev;
+ struct ofw_bus_devinfo *dinfo;
+ u_int32_t reg[6];
+
+ root = ofw_bus_get_node(dev);
+
+ if (OF_getprop(root, "reg", reg, sizeof(reg)) < 8)
+ return (ENXIO);
+
+ for (child = OF_child(root); child != 0; child = OF_peer(child)) {
+ dinfo = malloc(sizeof(*dinfo), M_CPCHT, M_WAITOK | M_ZERO);
+
+ if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) {
+ free(dinfo, M_CPCHT);
+ continue;
+ }
+ cdev = device_add_child(dev, NULL, -1);
+ if (cdev == NULL) {
+ device_printf(dev, "<%s>: device_add_child failed\n",
+ dinfo->obd_name);
+ ofw_bus_gen_destroy_devinfo(dinfo);
+ free(dinfo, M_CPCHT);
+ continue;
+ }
+ device_set_ivars(cdev, dinfo);
+ }
+
+ return (bus_generic_attach(dev));
+}
+
+static const struct ofw_bus_devinfo *
+cpcht_get_devinfo(device_t dev, device_t child)
+{
+ return (device_get_ivars(child));
+}
+
+#ifdef DEV_ISA
+
+/*
+ * CPC ISA Device interface.
+ */
+static int cpcisa_probe(device_t);
+
+/*
+ * Driver methods.
+ */
+static device_method_t cpcisa_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, cpcisa_probe),
+ DEVMETHOD(device_attach, isab_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource,bus_generic_activate_resource),
+
+ {0,0}
+};
+
+static driver_t cpcisa_driver = {
+ "isab",
+ cpcisa_methods,
+ 0
+};
+
+DRIVER_MODULE(cpcisa, cpcht, cpcisa_driver, isab_devclass, 0, 0);
+
+static int
+cpcisa_probe(device_t dev)
+{
+ const char *type;
+
+ type = ofw_bus_get_type(dev);
+
+ if (type == NULL)
+ return (ENXIO);
+
+ if (strcmp(type, "isa") != 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "HyperTransport-ISA bridge");
+
+ return (0);
+}
+
+#endif /* DEV_ISA */
+
+/*
+ * CPC PCI Device interface.
+ */
+static int cpcpci_probe(device_t);
+static int cpcpci_attach(device_t);
+
+/*
+ * Bus interface.
+ */
+static int cpcpci_read_ivar(device_t, device_t, int,
+ uintptr_t *);
+static struct resource * cpcpci_alloc_resource(device_t bus,
+ device_t child, int type, int *rid, u_long start,
+ u_long end, u_long count, u_int flags);
+static int cpcpci_activate_resource(device_t bus, device_t child,
+ int type, int rid, struct resource *res);
+
+/*
+ * pcib interface.
+ */
+static int cpcpci_maxslots(device_t);
+static u_int32_t cpcpci_read_config(device_t, u_int, u_int, u_int,
+ u_int, int);
+static void cpcpci_write_config(device_t, u_int, u_int, u_int,
+ u_int, u_int32_t, int);
+static int cpcpci_route_interrupt(device_t, device_t, int);
+
+/*
+ * ofw_bus interface
+ */
+
+static phandle_t cpcpci_get_node(device_t bus, device_t child);
+
+/*
+ * Driver methods.
+ */
+static device_method_t cpcpci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, cpcpci_probe),
+ DEVMETHOD(device_attach, cpcpci_attach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_read_ivar, cpcpci_read_ivar),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, cpcpci_alloc_resource),
+ DEVMETHOD(bus_activate_resource, cpcpci_activate_resource),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, cpcpci_maxslots),
+ DEVMETHOD(pcib_read_config, cpcpci_read_config),
+ DEVMETHOD(pcib_write_config, cpcpci_write_config),
+ DEVMETHOD(pcib_route_interrupt, cpcpci_route_interrupt),
+
+ /* ofw_bus interface */
+ DEVMETHOD(ofw_bus_get_node, cpcpci_get_node),
+ { 0, 0 }
+};
+
+static driver_t cpcpci_driver = {
+ "pcib",
+ cpcpci_methods,
+ sizeof(struct cpcpci_softc)
+};
+
+static devclass_t cpcpci_devclass;
+
+DRIVER_MODULE(cpcpci, cpcht, cpcpci_driver, cpcpci_devclass, 0, 0);
+
+static int
+cpcpci_probe(device_t dev)
+{
+ const char *type;
+
+ type = ofw_bus_get_type(dev);
+
+ if (type == NULL)
+ return (ENXIO);
+
+ if (strcmp(type, "pci") != 0)
+ return (ENXIO);
+
+ device_set_desc(dev, "HyperTransport-PCI bridge");
+
+ return (0);
+}
+
+static int
+cpcpci_attach(device_t dev)
+{
+ struct cpcpci_softc *sc;
+ phandle_t node;
+ u_int32_t reg[2], busrange[2], config_base;
+ struct cpcpci_range *rp, *io, *mem[2];
+ struct cpcpci_range fakeio;
+ int nmem, i;
+
+ node = ofw_bus_get_node(dev);
+ sc = device_get_softc(dev);
+
+ if (OF_getprop(OF_parent(node), "reg", reg, sizeof(reg)) < 8)
+ return (ENXIO);
+
+ if (OF_getprop(node, "bus-range", busrange, sizeof(busrange)) != 8)
+ return (ENXIO);
+
+ sc->sc_dev = dev;
+ sc->sc_node = node;
+ sc->sc_bus = busrange[0];
+ config_base = reg[1];
+ if (sc->sc_bus)
+ config_base += 0x01000000UL + (sc->sc_bus << 16);
+ sc->sc_data = (vm_offset_t)pmap_mapdev(config_base, PAGE_SIZE << 4);
+
+ bzero(sc->sc_range, sizeof(sc->sc_range));
+ sc->sc_nrange = OF_getprop(node, "ranges", sc->sc_range,
+ sizeof(sc->sc_range));
+
+ if (sc->sc_nrange == -1) {
+ device_printf(dev, "could not get ranges\n");
+ return (ENXIO);
+ }
+
+ sc->sc_range[6].pci_hi = 0;
+ io = NULL;
+ nmem = 0;
+
+ for (rp = sc->sc_range; rp->pci_hi != 0; rp++) {
+ switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) {
+ case OFW_PCI_PHYS_HI_SPACE_CONFIG:
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_IO:
+ io = rp;
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_MEM32:
+ mem[nmem] = rp;
+ nmem++;
+ break;
+ case OFW_PCI_PHYS_HI_SPACE_MEM64:
+ break;
+ }
+ }
+
+ if (io == NULL) {
+ /*
+ * On at least some machines, the I/O port range is
+ * not exported in the OF device tree. So hardcode it.
+ */
+
+ fakeio.host_lo = 0;
+ fakeio.pci_lo = reg[1];
+ fakeio.size_lo = 0x00400000;
+ if (sc->sc_bus)
+ fakeio.pci_lo += 0x02000000UL + (sc->sc_bus << 14);
+ io = &fakeio;
+ }
+ sc->sc_io_rman.rm_type = RMAN_ARRAY;
+ sc->sc_io_rman.rm_descr = "CPC 9xx PCI I/O Ports";
+ sc->sc_iostart = io->host_lo;
+ if (rman_init(&sc->sc_io_rman) != 0 ||
+ rman_manage_region(&sc->sc_io_rman, io->pci_lo,
+ io->pci_lo + io->size_lo - 1) != 0) {
+ device_printf(dev, "failed to set up io range management\n");
+ return (ENXIO);
+ }
+
+ if (nmem == 0) {
+ device_printf(dev, "can't find mem ranges\n");
+ return (ENXIO);
+ }
+ sc->sc_mem_rman.rm_type = RMAN_ARRAY;
+ sc->sc_mem_rman.rm_descr = "CPC 9xx PCI Memory";
+ if (rman_init(&sc->sc_mem_rman) != 0) {
+ device_printf(dev,
+ "failed to init mem range resources\n");
+ return (ENXIO);
+ }
+ for (i = 0; i < nmem; i++) {
+ if (rman_manage_region(&sc->sc_mem_rman, mem[i]->pci_lo,
+ mem[i]->pci_lo + mem[i]->size_lo - 1) != 0) {
+ device_printf(dev,
+ "failed to set up memory range management\n");
+ return (ENXIO);
+ }
+ }
+
+ ofw_bus_setup_iinfo(node, &sc->sc_pci_iinfo, sizeof(cell_t));
+
+ device_add_child(dev, "pci", device_get_unit(dev));
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+cpcpci_maxslots(device_t dev)
+{
+
+ return (PCI_SLOTMAX);
+}
+
+static u_int32_t
+cpcpci_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
+ int width)
+{
+ struct cpcpci_softc *sc;
+ vm_offset_t caoff;
+
+ sc = device_get_softc(dev);
+ caoff = sc->sc_data +
+ (((((slot & 0x1f) << 3) | (func & 0x07)) << 8) | reg);
+
+ switch (width) {
+ case 1:
+ return (in8rb(caoff));
+ break;
+ case 2:
+ return (in16rb(caoff));
+ break;
+ case 4:
+ return (in32rb(caoff));
+ break;
+ }
+
+ return (0xffffffff);
+}
+
+static void
+cpcpci_write_config(device_t dev, u_int bus, u_int slot, u_int func,
+ u_int reg, u_int32_t val, int width)
+{
+ struct cpcpci_softc *sc;
+ vm_offset_t caoff;
+
+ sc = device_get_softc(dev);
+ caoff = sc->sc_data +
+ (((((slot & 0x1f) << 3) | (func & 0x07)) << 8) | reg);
+
+ switch (width) {
+ case 1:
+ out8rb(caoff, val);
+ break;
+ case 2:
+ out16rb(caoff, val);
+ break;
+ case 4:
+ out32rb(caoff, val);
+ break;
+ }
+}
+
+static int
+cpcpci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct cpcpci_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ switch (which) {
+ case PCIB_IVAR_DOMAIN:
+ *result = device_get_unit(dev);
+ return (0);
+ case PCIB_IVAR_BUS:
+ *result = sc->sc_bus;
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
+static struct resource *
+cpcpci_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ u_long start, u_long end, u_long count, u_int flags)
+{
+ struct cpcpci_softc *sc;
+ struct resource *rv;
+ struct rman *rm;
+ int needactivate;
+
+ needactivate = flags & RF_ACTIVE;
+ flags &= ~RF_ACTIVE;
+
+ sc = device_get_softc(bus);
+
+ switch (type) {
+ case SYS_RES_MEMORY:
+ rm = &sc->sc_mem_rman;
+ break;
+
+ case SYS_RES_IOPORT:
+ rm = &sc->sc_io_rman;
+ if (rm == NULL)
+ return (NULL);
+ break;
+
+ case SYS_RES_IRQ:
+ return (bus_alloc_resource(bus, type, rid, start, end, count,
+ flags));
+
+ default:
+ device_printf(bus, "unknown resource request from %s\n",
+ device_get_nameunit(child));
+ return (NULL);
+ }
+
+ rv = rman_reserve_resource(rm, start, end, count, flags, child);
+ if (rv == NULL) {
+ device_printf(bus, "failed to reserve resource for %s\n",
+ device_get_nameunit(child));
+ return (NULL);
+ }
+
+ rman_set_rid(rv, *rid);
+
+ if (needactivate) {
+ if (bus_activate_resource(child, type, *rid, rv) != 0) {
+ device_printf(bus,
+ "failed to activate resource for %s\n",
+ device_get_nameunit(child));
+ rman_release_resource(rv);
+ return (NULL);
+ }
+ }
+
+ return (rv);
+}
+
+static int
+cpcpci_activate_resource(device_t bus, device_t child, int type, int rid,
+ struct resource *res)
+{
+ void *p;
+ struct cpcpci_softc *sc;
+
+ sc = device_get_softc(bus);
+
+ if (type == SYS_RES_IRQ)
+ return (bus_activate_resource(bus, type, rid, res));
+
+ if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) {
+ vm_offset_t start;
+
+ start = (vm_offset_t)rman_get_start(res);
+ /*
+ * For i/o-ports, convert the start address to the
+ * CPC PCI i/o window
+ */
+ if (type == SYS_RES_IOPORT)
+ start += sc->sc_iostart;
+
+ if (bootverbose)
+ printf("cpcpci mapdev: start %x, len %ld\n", start,
+ rman_get_size(res));
+
+ p = pmap_mapdev(start, (vm_size_t)rman_get_size(res));
+ if (p == NULL)
+ return (ENOMEM);
+ rman_set_virtual(res, p);
+ rman_set_bustag(res, &bs_le_tag);
+ rman_set_bushandle(res, (u_long)p);
+ }
+
+ return (rman_activate_resource(res));
+}
+
+static phandle_t
+cpcpci_get_node(device_t bus, device_t dev)
+{
+ struct cpcpci_softc *sc;
+
+ sc = device_get_softc(bus);
+ /* We only have one child, the PCI bus, which needs our own node. */
+ return (sc->sc_node);
+}
+
+static int
+cpcpci_route_interrupt(device_t bus, device_t dev, int pin)
+{
+ struct cpcpci_softc *sc;
+ struct ofw_pci_register reg;
+ uint32_t pintr, mintr;
+ uint8_t maskbuf[sizeof(reg) + sizeof(pintr)];
+
+ sc = device_get_softc(bus);
+ pintr = pin;
+ if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, &reg,
+ sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf))
+ return (mintr);
+
+ /* Maybe it's a real interrupt, not an intpin */
+ if (pin > 4)
+ return (pin);
+
+ device_printf(bus, "could not route pin %d for device %d.%d\n",
+ pin, pci_get_slot(dev), pci_get_function(dev));
+ return (PCI_INVALID_IRQ);
+}
+
diff --git a/sys/powerpc/powermac/cpchtvar.h b/sys/powerpc/powermac/cpchtvar.h
new file mode 100644
index 0000000..270345f
--- /dev/null
+++ b/sys/powerpc/powermac/cpchtvar.h
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (C) 2008 Nathan Whitehorn
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _POWERPC_POWERMAC_CPCHTVAR_H_
+#define _POWERPC_POWERMAC_CPCHTVAR_H_
+
+struct cpcpci_range {
+ u_int32_t pci_hi;
+ u_int32_t pci_mid;
+ u_int32_t pci_lo;
+ u_int32_t junk;
+ u_int32_t host_hi;
+ u_int32_t host_lo;
+ u_int32_t size_hi;
+ u_int32_t size_lo;
+};
+
+struct cpcpci_softc {
+ device_t sc_dev;
+ phandle_t sc_node;
+ vm_offset_t sc_data;
+ int sc_bus;
+ struct cpcpci_range sc_range[6];
+ int sc_nrange;
+ int sc_iostart;
+ struct rman sc_io_rman;
+ struct rman sc_mem_rman;
+ bus_space_tag_t sc_iot;
+ bus_space_tag_t sc_memt;
+ bus_dma_tag_t sc_dmat;
+ struct ofw_bus_iinfo sc_pci_iinfo;
+};
+
+#endif /* _POWERPC_POWERMAC_CPCHTVAR_H_ */
diff --git a/sys/powerpc/powerpc/bus_machdep.c b/sys/powerpc/powerpc/bus_machdep.c
index 42e5baa..742454b 100644
--- a/sys/powerpc/powerpc/bus_machdep.c
+++ b/sys/powerpc/powerpc/bus_machdep.c
@@ -42,12 +42,25 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
#include <machine/bus.h>
#include <machine/pio.h>
+#include <machine/md_var.h>
#define TODO panic("%s: not implemented", __func__)
+#define MAX_EARLYBOOT_MAPPINGS 6
+
+static struct {
+ bus_addr_t addr;
+ bus_size_t size;
+} earlyboot_mappings[MAX_EARLYBOOT_MAPPINGS];
+static int earlyboot_map_idx = 0;
+
+void bs_remap_earlyboot(void);
+
static __inline void *
__ppc_ba(bus_space_handle_t bsh, bus_size_t ofs)
{
@@ -58,10 +71,44 @@ static int
bs_gen_map(bus_addr_t addr, bus_size_t size __unused, int flags __unused,
bus_space_handle_t *bshp)
{
- *bshp = addr;
+ /*
+ * Record what we did if we haven't enabled the MMU yet. We
+ * will need to remap it as soon as the MMU comes up.
+ */
+ if (!pmap_bootstrapped) {
+ KASSERT(earlyboot_map_idx < MAX_EARLYBOOT_MAPPINGS,
+ ("%s: too many early boot mapping requests", __func__));
+ earlyboot_mappings[earlyboot_map_idx].addr = addr;
+ earlyboot_mappings[earlyboot_map_idx].size = size;
+ earlyboot_map_idx++;
+ *bshp = addr;
+ } else {
+ *bshp = (bus_space_handle_t)pmap_mapdev(addr,size);
+ }
+
return (0);
}
+void
+bs_remap_earlyboot(void)
+{
+ int i;
+ vm_offset_t pa, spa;
+
+ if (hw_direct_map)
+ return;
+
+ for (i = 0; i < earlyboot_map_idx; i++) {
+ spa = earlyboot_mappings[i].addr;
+
+ pa = trunc_page(spa);
+ while (pa < spa + earlyboot_mappings[i].size) {
+ pmap_kenter(pa,pa);
+ pa += PAGE_SIZE;
+ }
+ }
+}
+
static void
bs_gen_unmap(bus_size_t size __unused)
{
diff --git a/sys/powerpc/powerpc/cpu.c b/sys/powerpc/powerpc/cpu.c
index 4724313..a15ef58 100644
--- a/sys/powerpc/powerpc/cpu.c
+++ b/sys/powerpc/powerpc/cpu.c
@@ -91,6 +91,10 @@ static const struct cputab models[] = {
{ "Motorola PowerPC 620", MPC620, REVFMT_HEX },
{ "Motorola PowerPC 750", MPC750, REVFMT_MAJMIN },
{ "IBM PowerPC 750FX", IBM750FX, REVFMT_MAJMIN },
+ { "IBM PowerPC 970", IBM970, REVFMT_MAJMIN },
+ { "IBM PowerPC 970FX", IBM970FX, REVFMT_MAJMIN },
+ { "IBM PowerPC 970GX", IBM970GX, REVFMT_MAJMIN },
+ { "IBM PowerPC 970MP", IBM970MP, REVFMT_MAJMIN },
{ "Motorola PowerPC 7400", MPC7400, REVFMT_MAJMIN },
{ "Motorola PowerPC 7410", MPC7410, REVFMT_MAJMIN },
{ "Motorola PowerPC 7450", MPC7450, REVFMT_MAJMIN },
diff --git a/sys/powerpc/powerpc/dump_machdep.c b/sys/powerpc/powerpc/dump_machdep.c
new file mode 100644
index 0000000..acda560
--- /dev/null
+++ b/sys/powerpc/powerpc/dump_machdep.c
@@ -0,0 +1,303 @@
+/*-
+ * Copyright (c) 2002 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR 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/systm.h>
+#include <sys/conf.h>
+#include <sys/cons.h>
+#include <sys/kernel.h>
+#include <sys/kerneldump.h>
+#include <sys/sysctl.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/elf.h>
+#include <machine/md_var.h>
+
+CTASSERT(sizeof(struct kerneldumpheader) == 512);
+
+/*
+ * Don't touch the first SIZEOF_METADATA bytes on the dump device. This
+ * is to protect us from metadata and to protect metadata from us.
+ */
+#define SIZEOF_METADATA (64*1024)
+
+#define MD_ALIGN(x) (((off_t)(x) + PAGE_MASK) & ~PAGE_MASK)
+#define DEV_ALIGN(x) (((off_t)(x) + (DEV_BSIZE-1)) & ~(DEV_BSIZE-1))
+
+typedef int callback_t(struct pmap_md *, int, void *);
+
+static struct kerneldumpheader kdh;
+static off_t dumplo, fileofs;
+
+/* Handle buffered writes. */
+static char buffer[DEV_BSIZE];
+static size_t fragsz;
+
+int dumpsys_minidump = 1;
+SYSCTL_INT(_debug, OID_AUTO, minidump, CTLFLAG_RD, &dumpsys_minidump, 0,
+ "Kernel makes compressed crash dumps");
+
+static int
+buf_write(struct dumperinfo *di, char *ptr, size_t sz)
+{
+ size_t len;
+ int error;
+
+ while (sz) {
+ len = DEV_BSIZE - fragsz;
+ if (len > sz)
+ len = sz;
+ bcopy(ptr, buffer + fragsz, len);
+ fragsz += len;
+ ptr += len;
+ sz -= len;
+ if (fragsz == DEV_BSIZE) {
+ error = di->dumper(di->priv, buffer, 0, dumplo,
+ DEV_BSIZE);
+ if (error)
+ return error;
+ dumplo += DEV_BSIZE;
+ fragsz = 0;
+ }
+ }
+
+ return (0);
+}
+
+static int
+buf_flush(struct dumperinfo *di)
+{
+ int error;
+
+ if (fragsz == 0)
+ return (0);
+
+ error = di->dumper(di->priv, buffer, 0, dumplo, DEV_BSIZE);
+ dumplo += DEV_BSIZE;
+ fragsz = 0;
+ return (error);
+}
+
+static int
+cb_dumpdata(struct pmap_md *md, int seqnr, void *arg)
+{
+ struct dumperinfo *di = (struct dumperinfo*)arg;
+ vm_offset_t va;
+ size_t counter, ofs, resid, sz;
+ int c, error, twiddle;
+
+ error = 0;
+ counter = 0; /* Update twiddle every 16MB */
+ twiddle = 0;
+
+ ofs = 0; /* Logical offset within the chunk */
+ resid = md->md_size;
+
+ printf(" chunk %d: %lu bytes ", seqnr, (u_long)resid);
+
+ while (resid) {
+ sz = (resid > DFLTPHYS) ? DFLTPHYS : resid;
+ va = pmap_dumpsys_map(md, ofs, &sz);
+ counter += sz;
+ if (counter >> 24) {
+ printf("%c\b", "|/-\\"[twiddle++ & 3]);
+ counter &= (1<<24) - 1;
+ }
+ error = di->dumper(di->priv, (void*)va, 0, dumplo, sz);
+ pmap_dumpsys_unmap(md, ofs, va);
+ if (error)
+ break;
+ dumplo += sz;
+ resid -= sz;
+ ofs += sz;
+
+ /* Check for user abort. */
+ c = cncheckc();
+ if (c == 0x03)
+ return (ECANCELED);
+ if (c != -1)
+ printf("(CTRL-C to abort) ");
+ }
+ printf("... %s\n", (error) ? "fail" : "ok");
+ return (error);
+}
+
+static int
+cb_dumphdr(struct pmap_md *md, int seqnr, void *arg)
+{
+ struct dumperinfo *di = (struct dumperinfo*)arg;
+ Elf32_Phdr phdr;
+ int error;
+
+ bzero(&phdr, sizeof(phdr));
+ phdr.p_type = PT_LOAD;
+ phdr.p_flags = PF_R; /* XXX */
+ phdr.p_offset = fileofs;
+ phdr.p_vaddr = md->md_vaddr;
+ phdr.p_paddr = md->md_paddr;
+ phdr.p_filesz = md->md_size;
+ phdr.p_memsz = md->md_size;
+ phdr.p_align = PAGE_SIZE;
+
+ error = buf_write(di, (char*)&phdr, sizeof(phdr));
+ fileofs += phdr.p_filesz;
+ return (error);
+}
+
+static int
+cb_size(struct pmap_md *md, int seqnr, void *arg)
+{
+ uint32_t *sz = (uint32_t*)arg;
+
+ *sz += md->md_size;
+ return (0);
+}
+
+static int
+foreach_chunk(callback_t cb, void *arg)
+{
+ struct pmap_md *md;
+ int error, seqnr;
+
+ seqnr = 0;
+ md = pmap_scan_md(NULL);
+ while (md != NULL) {
+ error = (*cb)(md, seqnr++, arg);
+ if (error)
+ return (-error);
+ md = pmap_scan_md(md);
+ }
+ return (seqnr);
+}
+
+void
+dumpsys(struct dumperinfo *di)
+{
+ Elf32_Ehdr ehdr;
+ uint32_t dumpsize;
+ off_t hdrgap;
+ size_t hdrsz;
+ int error;
+
+ bzero(&ehdr, sizeof(ehdr));
+ ehdr.e_ident[EI_MAG0] = ELFMAG0;
+ ehdr.e_ident[EI_MAG1] = ELFMAG1;
+ ehdr.e_ident[EI_MAG2] = ELFMAG2;
+ ehdr.e_ident[EI_MAG3] = ELFMAG3;
+ ehdr.e_ident[EI_CLASS] = ELFCLASS32;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ ehdr.e_ident[EI_DATA] = ELFDATA2LSB;
+#else
+ ehdr.e_ident[EI_DATA] = ELFDATA2MSB;
+#endif
+ ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+ ehdr.e_ident[EI_OSABI] = ELFOSABI_STANDALONE; /* XXX big picture? */
+ ehdr.e_type = ET_CORE;
+ ehdr.e_machine = EM_PPC;
+ ehdr.e_phoff = sizeof(ehdr);
+ ehdr.e_ehsize = sizeof(ehdr);
+ ehdr.e_phentsize = sizeof(Elf32_Phdr);
+ ehdr.e_shentsize = sizeof(Elf32_Shdr);
+
+ /* Calculate dump size. */
+ dumpsize = 0L;
+ ehdr.e_phnum = foreach_chunk(cb_size, &dumpsize);
+ hdrsz = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
+ fileofs = MD_ALIGN(hdrsz);
+ dumpsize += fileofs;
+ hdrgap = fileofs - DEV_ALIGN(hdrsz);
+
+ /* For block devices, determine the dump offset on the device. */
+ if (di->mediasize > 0) {
+ if (di->mediasize <
+ SIZEOF_METADATA + dumpsize + sizeof(kdh) * 2) {
+ error = ENOSPC;
+ goto fail;
+ }
+ dumplo = di->mediaoffset + di->mediasize - dumpsize;
+ dumplo -= sizeof(kdh) * 2;
+ } else
+ dumplo = 0;
+
+ mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_POWERPC_VERSION, dumpsize,
+ di->blocksize);
+
+ printf("Dumping %u MB (%d chunks)\n", dumpsize >> 20,
+ ehdr.e_phnum);
+
+ /* Dump leader */
+ error = di->dumper(di->priv, &kdh, 0, dumplo, sizeof(kdh));
+ if (error)
+ goto fail;
+ dumplo += sizeof(kdh);
+
+ /* Dump ELF header */
+ error = buf_write(di, (char*)&ehdr, sizeof(ehdr));
+ if (error)
+ goto fail;
+
+ /* Dump program headers */
+ error = foreach_chunk(cb_dumphdr, di);
+ if (error < 0)
+ goto fail;
+ buf_flush(di);
+
+ /*
+ * All headers are written using blocked I/O, so we know the
+ * current offset is (still) block aligned. Skip the alignement
+ * in the file to have the segment contents aligned at page
+ * boundary. We cannot use MD_ALIGN on dumplo, because we don't
+ * care and may very well be unaligned within the dump device.
+ */
+ dumplo += hdrgap;
+
+ /* Dump memory chunks (updates dumplo) */
+ error = foreach_chunk(cb_dumpdata, di);
+ if (error < 0)
+ goto fail;
+
+ /* Dump trailer */
+ error = di->dumper(di->priv, &kdh, 0, dumplo, sizeof(kdh));
+ if (error)
+ goto fail;
+
+ /* Signal completion, signoff and exit stage left. */
+ di->dumper(di->priv, NULL, 0, 0, 0);
+ printf("\nDump complete\n");
+ return;
+
+ fail:
+ if (error < 0)
+ error = -error;
+
+ if (error == ECANCELED)
+ printf("\nDump aborted\n");
+ else
+ printf("\n** DUMP FAILED (ERROR %d) **\n", error);
+}
diff --git a/sys/powerpc/powerpc/elf_machdep.c b/sys/powerpc/powerpc/elf_machdep.c
index 69ac55b..4946b44 100644
--- a/sys/powerpc/powerpc/elf_machdep.c
+++ b/sys/powerpc/powerpc/elf_machdep.c
@@ -87,7 +87,8 @@ static Elf32_Brandinfo freebsd_brand_info = {
.interp_path = "/libexec/ld-elf.so.1",
.sysvec = &elf32_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(elf32, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -102,7 +103,8 @@ static Elf32_Brandinfo freebsd_brand_oinfo = {
.interp_path = "/usr/libexec/ld-elf.so.1",
.sysvec = &elf32_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf32_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(oelf32, SI_SUB_EXEC, SI_ORDER_ANY,
diff --git a/sys/powerpc/powerpc/mem.c b/sys/powerpc/powerpc/mem.c
index b3c320b..22d99c4 100644
--- a/sys/powerpc/powerpc/mem.c
+++ b/sys/powerpc/powerpc/mem.c
@@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm.h>
#include <vm/pmap.h>
#include <vm/vm_extern.h>
+#include <vm/vm_page.h>
#include <machine/memdev.h>
@@ -77,6 +78,8 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
int error = 0;
vm_offset_t va, eva, off, v;
vm_prot_t prot;
+ struct vm_page m;
+ vm_page_t marr;
vm_size_t cnt;
cnt = 0;
@@ -102,14 +105,18 @@ kmem_direct_mapped: v = uio->uio_offset;
cnt = min(cnt, PAGE_SIZE - off);
cnt = min(cnt, iov->iov_len);
- if (mem_valid(v, cnt)
- && pmap_dev_direct_mapped(v, cnt)) {
+ if (mem_valid(v, cnt)) {
error = EFAULT;
break;
}
-
- uiomove((void *)v, cnt, uio);
- break;
+
+ if (!pmap_dev_direct_mapped(v, cnt)) {
+ error = uiomove((void *)v, cnt, uio);
+ } else {
+ m.phys_addr = trunc_page(v);
+ marr = &m;
+ error = uiomove_fromphys(&marr, off, cnt, uio);
+ }
}
else if (dev2unit(dev) == CDEV_MINOR_KMEM) {
va = uio->uio_offset;
diff --git a/sys/powerpc/powerpc/mmu_if.m b/sys/powerpc/powerpc/mmu_if.m
index 4a8ffa8..4a5a37c 100644
--- a/sys/powerpc/powerpc/mmu_if.m
+++ b/sys/powerpc/powerpc/mmu_if.m
@@ -105,6 +105,11 @@ CODE {
{
return;
}
+
+ static struct pmap_md *mmu_null_scan_md(mmu_t mmu, struct pmap_md *p)
+ {
+ return (NULL);
+ }
};
@@ -697,6 +702,18 @@ METHOD void bootstrap {
vm_offset_t _end;
};
+/**
+ * @brief Set up the MMU on the current CPU. Only called by the PMAP layer
+ * for alternate CPUs on SMP systems.
+ *
+ * @param _ap Set to 1 if the CPU being set up is an AP
+ *
+ */
+METHOD void cpu_bootstrap {
+ mmu_t _mmu;
+ int _ap;
+};
+
/**
* @brief Create a kernel mapping for a given physical address range.
@@ -783,3 +800,50 @@ METHOD boolean_t page_executable {
vm_page_t _pg;
};
+
+/**
+ * @brief Create temporary memory mapping for use by dumpsys().
+ *
+ * @param _md The memory chunk in which the mapping lies.
+ * @param _ofs The offset within the chunk of the mapping.
+ * @param _sz The requested size of the mapping.
+ *
+ * @retval vm_offset_t The virtual address of the mapping.
+ *
+ * The sz argument is modified to reflect the actual size of the
+ * mapping.
+ */
+METHOD vm_offset_t dumpsys_map {
+ mmu_t _mmu;
+ struct pmap_md *_md;
+ vm_size_t _ofs;
+ vm_size_t *_sz;
+};
+
+
+/**
+ * @brief Remove temporary dumpsys() mapping.
+ *
+ * @param _md The memory chunk in which the mapping lies.
+ * @param _ofs The offset within the chunk of the mapping.
+ * @param _va The virtual address of the mapping.
+ */
+METHOD void dumpsys_unmap {
+ mmu_t _mmu;
+ struct pmap_md *_md;
+ vm_size_t _ofs;
+ vm_offset_t _va;
+};
+
+
+/**
+ * @brief Scan/iterate memory chunks.
+ *
+ * @param _prev The previously returned chunk or NULL.
+ *
+ * @retval The next (or first when _prev is NULL) chunk.
+ */
+METHOD struct pmap_md * scan_md {
+ mmu_t _mmu;
+ struct pmap_md *_prev;
+} DEFAULT mmu_null_scan_md;
diff --git a/sys/powerpc/powerpc/pmap_dispatch.c b/sys/powerpc/powerpc/pmap_dispatch.c
index 33e94d1..af657d4 100644
--- a/sys/powerpc/powerpc/pmap_dispatch.c
+++ b/sys/powerpc/powerpc/pmap_dispatch.c
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_page.h>
#include <machine/mmuvar.h>
+#include <machine/smp.h>
#include "mmu_if.h"
@@ -406,6 +407,16 @@ pmap_bootstrap(vm_offset_t start, vm_offset_t end)
MMU_BOOTSTRAP(mmu_obj, start, end);
}
+void
+pmap_cpu_bootstrap(int ap)
+{
+ /*
+ * No KTR here because our console probably doesn't work yet
+ */
+
+ return (MMU_CPU_BOOTSTRAP(mmu_obj, ap));
+}
+
void *
pmap_mapdev(vm_offset_t pa, vm_size_t size)
{
@@ -454,6 +465,30 @@ pmap_page_executable(vm_page_t pg)
return (MMU_PAGE_EXECUTABLE(mmu_obj, pg));
}
+vm_offset_t
+pmap_dumpsys_map(struct pmap_md *md, vm_size_t ofs, vm_size_t *sz)
+{
+
+ CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, md, ofs, *sz);
+ return (MMU_DUMPSYS_MAP(mmu_obj, md, ofs, sz));
+}
+
+void
+pmap_dumpsys_unmap(struct pmap_md *md, vm_size_t ofs, vm_offset_t va)
+{
+
+ CTR4(KTR_PMAP, "%s(%p, %#x, %#x)", __func__, md, ofs, va);
+ return (MMU_DUMPSYS_UNMAP(mmu_obj, md, ofs, va));
+}
+
+struct pmap_md *
+pmap_scan_md(struct pmap_md *prev)
+{
+
+ CTR2(KTR_PMAP, "%s(%p)", __func__, prev);
+ return (MMU_SCAN_MD(mmu_obj, prev));
+}
+
/*
* MMU install routines. Highest priority wins, equal priority also
* overrides allowing last-set to win.
diff --git a/sys/powerpc/booke/uio_machdep.c b/sys/powerpc/powerpc/uio_machdep.c
index 2a88fd2..2a88fd2 100644
--- a/sys/powerpc/booke/uio_machdep.c
+++ b/sys/powerpc/powerpc/uio_machdep.c
diff --git a/sys/security/mac/mac_atalk.c b/sys/security/mac/mac_atalk.c
index 0992ee5..d45d29c 100644
--- a/sys/security/mac/mac_atalk.c
+++ b/sys/security/mac/mac_atalk.c
@@ -1,9 +1,12 @@
/*-
- * Copyright (c) 2007 Robert N. M. Watson
+ * Copyright (c) 2007-2009 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert Watson for the TrustedBSD Project.
*
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -61,6 +64,7 @@ mac_netatalk_aarp_send(struct ifnet *ifp, struct mbuf *m)
mlabel = mac_mbuf_to_label(m);
MAC_IFNET_LOCK(ifp);
- MAC_PERFORM(netatalk_aarp_send, ifp, ifp->if_label, m, mlabel);
+ MAC_PERFORM_NOSLEEP(netatalk_aarp_send, ifp, ifp->if_label, m,
+ mlabel);
MAC_IFNET_UNLOCK(ifp);
}
diff --git a/sys/security/mac/mac_audit.c b/sys/security/mac/mac_audit.c
index 9bc2e27..62cfbdf 100644
--- a/sys/security/mac/mac_audit.c
+++ b/sys/security/mac/mac_audit.c
@@ -66,7 +66,7 @@ mac_cred_check_setaudit(struct ucred *cred, struct auditinfo *ai)
{
int error;
- MAC_CHECK(cred_check_setaudit, cred, ai);
+ MAC_CHECK_NOSLEEP(cred_check_setaudit, cred, ai);
MAC_CHECK_PROBE2(cred_check_setaudit, error, cred, ai);
return (error);
@@ -80,7 +80,7 @@ mac_cred_check_setaudit_addr(struct ucred *cred, struct auditinfo_addr *aia)
{
int error;
- MAC_CHECK(cred_check_setaudit_addr, cred, aia);
+ MAC_CHECK_NOSLEEP(cred_check_setaudit_addr, cred, aia);
MAC_CHECK_PROBE2(cred_check_setaudit_addr, error, cred, aia);
return (error);
@@ -93,7 +93,7 @@ mac_cred_check_setauid(struct ucred *cred, uid_t auid)
{
int error;
- MAC_CHECK(cred_check_setauid, cred, auid);
+ MAC_CHECK_NOSLEEP(cred_check_setauid, cred, auid);
MAC_CHECK_PROBE2(cred_check_setauid, error, cred, auid);
return (error);
@@ -107,7 +107,7 @@ mac_system_check_audit(struct ucred *cred, void *record, int length)
{
int error;
- MAC_CHECK(system_check_audit, cred, record, length);
+ MAC_CHECK_NOSLEEP(system_check_audit, cred, record, length);
MAC_CHECK_PROBE3(system_check_audit, error, cred, record, length);
return (error);
@@ -138,7 +138,7 @@ mac_system_check_auditon(struct ucred *cred, int cmd)
{
int error;
- MAC_CHECK(system_check_auditon, cred, cmd);
+ MAC_CHECK_NOSLEEP(system_check_auditon, cred, cmd);
MAC_CHECK_PROBE2(system_check_auditon, error, cred, cmd);
return (error);
diff --git a/sys/security/mac/mac_cred.c b/sys/security/mac/mac_cred.c
index 41c6e66..b6dcf9d 100644
--- a/sys/security/mac/mac_cred.c
+++ b/sys/security/mac/mac_cred.c
@@ -100,7 +100,7 @@ void
mac_cred_label_free(struct label *label)
{
- MAC_PERFORM(cred_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(cred_destroy_label, label);
mac_labelzone_free(label);
}
@@ -127,7 +127,7 @@ void
mac_cred_associate_nfsd(struct ucred *cred)
{
- MAC_PERFORM(cred_associate_nfsd, cred);
+ MAC_PERFORM_NOSLEEP(cred_associate_nfsd, cred);
}
/*
@@ -138,7 +138,7 @@ void
mac_cred_create_swapper(struct ucred *cred)
{
- MAC_PERFORM(cred_create_swapper, cred);
+ MAC_PERFORM_NOSLEEP(cred_create_swapper, cred);
}
/*
@@ -149,7 +149,7 @@ void
mac_cred_create_init(struct ucred *cred)
{
- MAC_PERFORM(cred_create_init, cred);
+ MAC_PERFORM_NOSLEEP(cred_create_init, cred);
}
int
@@ -182,7 +182,7 @@ void
mac_cred_copy(struct ucred *src, struct ucred *dest)
{
- MAC_PERFORM(cred_copy_label, src->cr_label, dest->cr_label);
+ MAC_PERFORM_NOSLEEP(cred_copy_label, src->cr_label, dest->cr_label);
}
/*
@@ -194,7 +194,7 @@ void
mac_cred_relabel(struct ucred *cred, struct label *newlabel)
{
- MAC_PERFORM(cred_relabel, cred, newlabel);
+ MAC_PERFORM_NOSLEEP(cred_relabel, cred, newlabel);
}
MAC_CHECK_PROBE_DEFINE2(cred_check_relabel, "struct ucred *",
@@ -205,7 +205,7 @@ mac_cred_check_relabel(struct ucred *cred, struct label *newlabel)
{
int error;
- MAC_CHECK(cred_check_relabel, cred, newlabel);
+ MAC_CHECK_NOSLEEP(cred_check_relabel, cred, newlabel);
MAC_CHECK_PROBE2(cred_check_relabel, error, cred, newlabel);
return (error);
@@ -218,7 +218,7 @@ mac_cred_check_setuid(struct ucred *cred, uid_t uid)
{
int error;
- MAC_CHECK(cred_check_setuid, cred, uid);
+ MAC_CHECK_NOSLEEP(cred_check_setuid, cred, uid);
MAC_CHECK_PROBE2(cred_check_setuid, error, cred, uid);
return (error);
@@ -231,7 +231,7 @@ mac_cred_check_seteuid(struct ucred *cred, uid_t euid)
{
int error;
- MAC_CHECK(cred_check_seteuid, cred, euid);
+ MAC_CHECK_NOSLEEP(cred_check_seteuid, cred, euid);
MAC_CHECK_PROBE2(cred_check_seteuid, error, cred, euid);
return (error);
@@ -244,7 +244,7 @@ mac_cred_check_setgid(struct ucred *cred, gid_t gid)
{
int error;
- MAC_CHECK(cred_check_setgid, cred, gid);
+ MAC_CHECK_NOSLEEP(cred_check_setgid, cred, gid);
MAC_CHECK_PROBE2(cred_check_setgid, error, cred, gid);
return (error);
@@ -257,7 +257,7 @@ mac_cred_check_setegid(struct ucred *cred, gid_t egid)
{
int error;
- MAC_CHECK(cred_check_setegid, cred, egid);
+ MAC_CHECK_NOSLEEP(cred_check_setegid, cred, egid);
MAC_CHECK_PROBE2(cred_check_setegid, error, cred, egid);
return (error);
@@ -271,7 +271,7 @@ mac_cred_check_setgroups(struct ucred *cred, int ngroups, gid_t *gidset)
{
int error;
- MAC_CHECK(cred_check_setgroups, cred, ngroups, gidset);
+ MAC_CHECK_NOSLEEP(cred_check_setgroups, cred, ngroups, gidset);
MAC_CHECK_PROBE3(cred_check_setgroups, error, cred, ngroups, gidset);
return (error);
@@ -285,7 +285,7 @@ mac_cred_check_setreuid(struct ucred *cred, uid_t ruid, uid_t euid)
{
int error;
- MAC_CHECK(cred_check_setreuid, cred, ruid, euid);
+ MAC_CHECK_NOSLEEP(cred_check_setreuid, cred, ruid, euid);
MAC_CHECK_PROBE3(cred_check_setreuid, error, cred, ruid, euid);
return (error);
@@ -299,7 +299,7 @@ mac_cred_check_setregid(struct ucred *cred, gid_t rgid, gid_t egid)
{
int error;
- MAC_CHECK(cred_check_setregid, cred, rgid, egid);
+ MAC_CHECK_NOSLEEP(cred_check_setregid, cred, rgid, egid);
MAC_CHECK_PROBE3(cred_check_setregid, error, cred, rgid, egid);
return (error);
@@ -314,7 +314,7 @@ mac_cred_check_setresuid(struct ucred *cred, uid_t ruid, uid_t euid,
{
int error;
- MAC_CHECK(cred_check_setresuid, cred, ruid, euid, suid);
+ MAC_CHECK_NOSLEEP(cred_check_setresuid, cred, ruid, euid, suid);
MAC_CHECK_PROBE4(cred_check_setresuid, error, cred, ruid, euid,
suid);
@@ -330,7 +330,7 @@ mac_cred_check_setresgid(struct ucred *cred, gid_t rgid, gid_t egid,
{
int error;
- MAC_CHECK(cred_check_setresgid, cred, rgid, egid, sgid);
+ MAC_CHECK_NOSLEEP(cred_check_setresgid, cred, rgid, egid, sgid);
MAC_CHECK_PROBE4(cred_check_setresgid, error, cred, rgid, egid,
sgid);
@@ -345,7 +345,7 @@ mac_cred_check_visible(struct ucred *cr1, struct ucred *cr2)
{
int error;
- MAC_CHECK(cred_check_visible, cr1, cr2);
+ MAC_CHECK_NOSLEEP(cred_check_visible, cr1, cr2);
MAC_CHECK_PROBE2(cred_check_visible, error, cr1, cr2);
return (error);
diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c
index f434df8..1806e4a 100644
--- a/sys/security/mac/mac_framework.c
+++ b/sys/security/mac/mac_framework.c
@@ -76,10 +76,11 @@ __FBSDID("$FreeBSD$");
#include <sys/condvar.h>
#include <sys/kernel.h>
#include <sys/lock.h>
-#include <sys/mutex.h>
#include <sys/mac.h>
#include <sys/module.h>
+#include <sys/rwlock.h>
#include <sys/sdt.h>
+#include <sys/sx.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
@@ -154,164 +155,125 @@ SYSCTL_QUAD(_security_mac, OID_AUTO, labeled, CTLFLAG_RD, &mac_labeled, 0,
MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
/*
- * mac_static_policy_list holds a list of policy modules that are not loaded
- * while the system is "live", and cannot be unloaded. These policies can be
- * invoked without holding the busy count.
+ * MAC policy modules are placed in one of two lists: mac_static_policy_list,
+ * for policies that are loaded early and cannot be unloaded, and
+ * mac_policy_list, which holds policies either loaded later in the boot
+ * cycle or that may be unloaded. The static policy list does not require
+ * locks to iterate over, but the dynamic list requires synchronization.
+ * Support for dynamic policy loading can be compiled out using the
+ * MAC_STATIC kernel option.
*
- * mac_policy_list stores the list of dynamic policies. A busy count is
- * maintained for the list, stored in mac_policy_busy. The busy count is
- * protected by mac_policy_mtx; the list may be modified only while the busy
- * count is 0, requiring that the lock be held to prevent new references to
- * the list from being acquired. For almost all operations, incrementing the
- * busy count is sufficient to guarantee consistency, as the list cannot be
- * modified while the busy count is elevated. For a few special operations
- * involving a change to the list of active policies, the mtx itself must be
- * held. A condition variable, mac_policy_cv, is used to signal potential
- * exclusive consumers that they should try to acquire the lock if a first
- * attempt at exclusive access fails.
- *
- * This design intentionally avoids fairness, and may starve attempts to
- * acquire an exclusive lock on a busy system. This is required because we
- * do not ever want acquiring a read reference to perform an unbounded length
- * sleep. Read references are acquired in ithreads, network isrs, etc, and
- * any unbounded blocking could lead quickly to deadlock.
- *
- * Another reason for never blocking on read references is that the MAC
- * Framework may recurse: if a policy calls a VOP, for example, this might
- * lead to vnode life cycle operations (such as init/destroy).
- *
- * If the kernel option MAC_STATIC has been compiled in, all locking becomes
- * a no-op, and the global list of policies is not allowed to change after
- * early boot.
- *
- * XXXRW: Currently, we signal mac_policy_cv every time the framework becomes
- * unbusy and there is a thread waiting to enter it exclusively. Since it
- * may take some time before the thread runs, we may issue a lot of signals.
- * We should instead keep track of the fact that we've signalled, taking into
- * account that the framework may be busy again by the time the thread runs,
- * requiring us to re-signal.
+ * The dynamic policy list is protected by two locks: modifying the list
+ * requires both locks to be held exclusively. One of the locks,
+ * mac_policy_rw, is acquired over policy entry points that will never sleep;
+ * the other, mac_policy_sx, is acquire over policy entry points that may
+ * sleep. The former category will be used when kernel locks may be held
+ * over calls to the MAC Framework, during network processing in ithreads,
+ * etc. The latter will tend to involve potentially blocking memory
+ * allocations, extended attribute I/O, etc.
*/
#ifndef MAC_STATIC
-static struct mtx mac_policy_mtx;
-static struct cv mac_policy_cv;
-static int mac_policy_count;
-static int mac_policy_wait;
+static struct rwlock mac_policy_rw; /* Non-sleeping entry points. */
+static struct sx mac_policy_sx; /* Sleeping entry points. */
#endif
+
struct mac_policy_list_head mac_policy_list;
struct mac_policy_list_head mac_static_policy_list;
-/*
- * We manually invoke WITNESS_WARN() to allow Witness to generate warnings
- * even if we don't end up ever triggering the wait at run-time. The
- * consumer of the exclusive interface must not hold any locks (other than
- * potentially Giant) since we may sleep for long (potentially indefinite)
- * periods of time waiting for the framework to become quiescent so that a
- * policy list change may be made.
- */
+static void mac_policy_xlock(void);
+static void mac_policy_xlock_assert(void);
+static void mac_policy_xunlock(void);
+
void
-mac_policy_grab_exclusive(void)
+mac_policy_slock_nosleep(void)
{
#ifndef MAC_STATIC
if (!mac_late)
return;
- WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
- "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
- mtx_lock(&mac_policy_mtx);
- while (mac_policy_count != 0) {
- mac_policy_wait++;
- cv_wait(&mac_policy_cv, &mac_policy_mtx);
- mac_policy_wait--;
- }
+ rw_rlock(&mac_policy_rw);
#endif
}
void
-mac_policy_assert_exclusive(void)
+mac_policy_slock_sleep(void)
{
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
+ "mac_policy_slock_sleep");
+
#ifndef MAC_STATIC
if (!mac_late)
return;
- mtx_assert(&mac_policy_mtx, MA_OWNED);
- KASSERT(mac_policy_count == 0,
- ("mac_policy_assert_exclusive(): not exclusive"));
+ sx_slock(&mac_policy_sx);
#endif
}
void
-mac_policy_release_exclusive(void)
+mac_policy_sunlock_nosleep(void)
{
-#ifndef MAC_STATIC
- int dowakeup;
+#ifndef MAC_STATIC
if (!mac_late)
return;
- KASSERT(mac_policy_count == 0,
- ("mac_policy_release_exclusive(): not exclusive"));
- dowakeup = (mac_policy_wait != 0);
- mtx_unlock(&mac_policy_mtx);
- if (dowakeup)
- cv_signal(&mac_policy_cv);
+ rw_runlock(&mac_policy_rw);
#endif
}
void
-mac_policy_list_busy(void)
+mac_policy_sunlock_sleep(void)
{
#ifndef MAC_STATIC
if (!mac_late)
return;
- mtx_lock(&mac_policy_mtx);
- mac_policy_count++;
- mtx_unlock(&mac_policy_mtx);
+ sx_sunlock(&mac_policy_sx);
#endif
}
-int
-mac_policy_list_conditional_busy(void)
+static void
+mac_policy_xlock(void)
{
-#ifndef MAC_STATIC
- int ret;
+ WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
+ "mac_policy_xlock()");
+
+#ifndef MAC_STATIC
if (!mac_late)
- return (1);
-
- mtx_lock(&mac_policy_mtx);
- if (!LIST_EMPTY(&mac_policy_list)) {
- mac_policy_count++;
- ret = 1;
- } else
- ret = 0;
- mtx_unlock(&mac_policy_mtx);
- return (ret);
-#else
- return (1);
+ return;
+
+ sx_xlock(&mac_policy_sx);
+ rw_wlock(&mac_policy_rw);
#endif
}
-void
-mac_policy_list_unbusy(void)
+static void
+mac_policy_xunlock(void)
{
-#ifndef MAC_STATIC
- int dowakeup;
+#ifndef MAC_STATIC
if (!mac_late)
return;
- mtx_lock(&mac_policy_mtx);
- mac_policy_count--;
- KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
- dowakeup = (mac_policy_count == 0 && mac_policy_wait != 0);
- mtx_unlock(&mac_policy_mtx);
+ rw_wunlock(&mac_policy_rw);
+ sx_xunlock(&mac_policy_sx);
+#endif
+}
+
+static void
+mac_policy_xlock_assert(void)
+{
- if (dowakeup)
- cv_signal(&mac_policy_cv);
+#ifndef MAC_STATIC
+ if (!mac_late)
+ return;
+
+ rw_assert(&mac_policy_rw, RA_WLOCKED);
+ sx_assert(&mac_policy_sx, SA_XLOCKED);
#endif
}
@@ -327,8 +289,8 @@ mac_init(void)
mac_labelzone_init();
#ifndef MAC_STATIC
- mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
- cv_init(&mac_policy_cv, "mac_policy_cv");
+ rw_init(&mac_policy_rw, "mac_policy_rw");
+ sx_init(&mac_policy_sx, "mac_policy_sx");
#endif
}
@@ -393,7 +355,7 @@ mac_policy_updateflags(void)
{
struct mac_policy_conf *mpc;
- mac_policy_assert_exclusive();
+ mac_policy_xlock_assert();
mac_labeled = 0;
LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list)
@@ -414,7 +376,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
* We don't technically need exclusive access while !mac_late, but
* hold it for assertion consistency.
*/
- mac_policy_grab_exclusive();
+ mac_policy_xlock();
/*
* If the module can potentially be unloaded, or we're loading late,
@@ -479,7 +441,7 @@ mac_policy_register(struct mac_policy_conf *mpc)
mpc->mpc_name);
out:
- mac_policy_release_exclusive();
+ mac_policy_xunlock();
return (error);
}
@@ -491,9 +453,9 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
* If we fail the load, we may get a request to unload. Check to see
* if we did the run-time registration, and if not, silently succeed.
*/
- mac_policy_grab_exclusive();
+ mac_policy_xlock();
if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
- mac_policy_release_exclusive();
+ mac_policy_xunlock();
return (0);
}
#if 0
@@ -501,7 +463,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
* Don't allow unloading modules with private data.
*/
if (mpc->mpc_field_off != NULL) {
- MAC_POLICY_LIST_UNLOCK();
+ mac_policy_xunlock();
return (EBUSY);
}
#endif
@@ -510,7 +472,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
* its own definition.
*/
if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
- mac_policy_release_exclusive();
+ mac_policy_xunlock();
return (EBUSY);
}
if (mpc->mpc_ops->mpo_destroy != NULL)
@@ -519,8 +481,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc)
LIST_REMOVE(mpc, mpc_list);
mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
mac_policy_updateflags();
-
- mac_policy_release_exclusive();
+ mac_policy_xunlock();
SDT_PROBE(mac, kernel, policy, unregister, mpc, 0, 0, 0, 0);
printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
diff --git a/sys/security/mac/mac_inet.c b/sys/security/mac/mac_inet.c
index b62938b..df21a16 100644
--- a/sys/security/mac/mac_inet.c
+++ b/sys/security/mac/mac_inet.c
@@ -84,9 +84,12 @@ mac_inpcb_label_alloc(int flag)
label = mac_labelzone_alloc(flag);
if (label == NULL)
return (NULL);
- MAC_CHECK(inpcb_init_label, label, flag);
+ if (flag & M_WAITOK)
+ MAC_CHECK(inpcb_init_label, label, flag);
+ else
+ MAC_CHECK_NOSLEEP(inpcb_init_label, label, flag);
if (error) {
- MAC_PERFORM(inpcb_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(inpcb_destroy_label, label);
mac_labelzone_free(label);
return (NULL);
}
@@ -116,9 +119,12 @@ mac_ipq_label_alloc(int flag)
if (label == NULL)
return (NULL);
- MAC_CHECK(ipq_init_label, label, flag);
+ if (flag & M_WAITOK)
+ MAC_CHECK(ipq_init_label, label, flag);
+ else
+ MAC_CHECK_NOSLEEP(ipq_init_label, label, flag);
if (error) {
- MAC_PERFORM(ipq_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(ipq_destroy_label, label);
mac_labelzone_free(label);
return (NULL);
}
@@ -142,7 +148,7 @@ static void
mac_inpcb_label_free(struct label *label)
{
- MAC_PERFORM(inpcb_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(inpcb_destroy_label, label);
mac_labelzone_free(label);
}
@@ -160,7 +166,7 @@ static void
mac_ipq_label_free(struct label *label)
{
- MAC_PERFORM(ipq_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(ipq_destroy_label, label);
mac_labelzone_free(label);
}
@@ -178,7 +184,8 @@ void
mac_inpcb_create(struct socket *so, struct inpcb *inp)
{
- MAC_PERFORM(inpcb_create, so, so->so_label, inp, inp->inp_label);
+ MAC_PERFORM_NOSLEEP(inpcb_create, so, so->so_label, inp,
+ inp->inp_label);
}
void
@@ -188,7 +195,7 @@ mac_ipq_reassemble(struct ipq *q, struct mbuf *m)
label = mac_mbuf_to_label(m);
- MAC_PERFORM(ipq_reassemble, q, q->ipq_label, m, label);
+ MAC_PERFORM_NOSLEEP(ipq_reassemble, q, q->ipq_label, m, label);
}
void
@@ -199,7 +206,7 @@ mac_netinet_fragment(struct mbuf *m, struct mbuf *frag)
mlabel = mac_mbuf_to_label(m);
fraglabel = mac_mbuf_to_label(frag);
- MAC_PERFORM(netinet_fragment, m, mlabel, frag, fraglabel);
+ MAC_PERFORM_NOSLEEP(netinet_fragment, m, mlabel, frag, fraglabel);
}
void
@@ -209,7 +216,7 @@ mac_ipq_create(struct mbuf *m, struct ipq *q)
label = mac_mbuf_to_label(m);
- MAC_PERFORM(ipq_create, m, label, q, q->ipq_label);
+ MAC_PERFORM_NOSLEEP(ipq_create, m, label, q, q->ipq_label);
}
void
@@ -220,7 +227,8 @@ mac_inpcb_create_mbuf(struct inpcb *inp, struct mbuf *m)
INP_LOCK_ASSERT(inp);
mlabel = mac_mbuf_to_label(m);
- MAC_PERFORM(inpcb_create_mbuf, inp, inp->inp_label, m, mlabel);
+ MAC_PERFORM_NOSLEEP(inpcb_create_mbuf, inp, inp->inp_label, m,
+ mlabel);
}
int
@@ -232,7 +240,7 @@ mac_ipq_match(struct mbuf *m, struct ipq *q)
label = mac_mbuf_to_label(m);
result = 1;
- MAC_BOOLEAN(ipq_match, &&, m, label, q, q->ipq_label);
+ MAC_BOOLEAN_NOSLEEP(ipq_match, &&, m, label, q, q->ipq_label);
return (result);
}
@@ -245,7 +253,7 @@ mac_netinet_arp_send(struct ifnet *ifp, struct mbuf *m)
mlabel = mac_mbuf_to_label(m);
MAC_IFNET_LOCK(ifp);
- MAC_PERFORM(netinet_arp_send, ifp, ifp->if_label, m, mlabel);
+ MAC_PERFORM_NOSLEEP(netinet_arp_send, ifp, ifp->if_label, m, mlabel);
MAC_IFNET_UNLOCK(ifp);
}
@@ -257,7 +265,7 @@ mac_netinet_icmp_reply(struct mbuf *mrecv, struct mbuf *msend)
mrecvlabel = mac_mbuf_to_label(mrecv);
msendlabel = mac_mbuf_to_label(msend);
- MAC_PERFORM(netinet_icmp_reply, mrecv, mrecvlabel, msend,
+ MAC_PERFORM_NOSLEEP(netinet_icmp_reply, mrecv, mrecvlabel, msend,
msendlabel);
}
@@ -268,7 +276,7 @@ mac_netinet_icmp_replyinplace(struct mbuf *m)
label = mac_mbuf_to_label(m);
- MAC_PERFORM(netinet_icmp_replyinplace, m, label);
+ MAC_PERFORM_NOSLEEP(netinet_icmp_replyinplace, m, label);
}
void
@@ -279,7 +287,8 @@ mac_netinet_igmp_send(struct ifnet *ifp, struct mbuf *m)
mlabel = mac_mbuf_to_label(m);
MAC_IFNET_LOCK(ifp);
- MAC_PERFORM(netinet_igmp_send, ifp, ifp->if_label, m, mlabel);
+ MAC_PERFORM_NOSLEEP(netinet_igmp_send, ifp, ifp->if_label, m,
+ mlabel);
MAC_IFNET_UNLOCK(ifp);
}
@@ -290,7 +299,7 @@ mac_netinet_tcp_reply(struct mbuf *m)
label = mac_mbuf_to_label(m);
- MAC_PERFORM(netinet_tcp_reply, m, label);
+ MAC_PERFORM_NOSLEEP(netinet_tcp_reply, m, label);
}
void
@@ -300,7 +309,7 @@ mac_ipq_update(struct mbuf *m, struct ipq *q)
label = mac_mbuf_to_label(m);
- MAC_PERFORM(ipq_update, m, label, q, q->ipq_label);
+ MAC_PERFORM_NOSLEEP(ipq_update, m, label, q, q->ipq_label);
}
MAC_CHECK_PROBE_DEFINE2(inpcb_check_deliver, "struct inpcb *",
@@ -316,7 +325,8 @@ mac_inpcb_check_deliver(struct inpcb *inp, struct mbuf *m)
label = mac_mbuf_to_label(m);
- MAC_CHECK(inpcb_check_deliver, inp, inp->inp_label, m, label);
+ MAC_CHECK_NOSLEEP(inpcb_check_deliver, inp, inp->inp_label, m,
+ label);
MAC_CHECK_PROBE2(inpcb_check_deliver, error, inp, m);
return (error);
@@ -332,7 +342,7 @@ mac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp)
INP_LOCK_ASSERT(inp);
- MAC_CHECK(inpcb_check_visible, cred, inp, inp->inp_label);
+ MAC_CHECK_NOSLEEP(inpcb_check_visible, cred, inp, inp->inp_label);
MAC_CHECK_PROBE2(inpcb_check_visible, error, cred, inp);
return (error);
@@ -344,7 +354,9 @@ mac_inpcb_sosetlabel(struct socket *so, struct inpcb *inp)
INP_WLOCK_ASSERT(inp);
SOCK_LOCK_ASSERT(so);
- MAC_PERFORM(inpcb_sosetlabel, so, so->so_label, inp, inp->inp_label);
+
+ MAC_PERFORM_NOSLEEP(inpcb_sosetlabel, so, so->so_label, inp,
+ inp->inp_label);
}
void
@@ -358,7 +370,7 @@ mac_netinet_firewall_reply(struct mbuf *mrecv, struct mbuf *msend)
mrecvlabel = mac_mbuf_to_label(mrecv);
msendlabel = mac_mbuf_to_label(msend);
- MAC_PERFORM(netinet_firewall_reply, mrecv, mrecvlabel, msend,
+ MAC_PERFORM_NOSLEEP(netinet_firewall_reply, mrecv, mrecvlabel, msend,
msendlabel);
}
@@ -368,8 +380,10 @@ mac_netinet_firewall_send(struct mbuf *m)
struct label *label;
M_ASSERTPKTHDR(m);
+
label = mac_mbuf_to_label(m);
- MAC_PERFORM(netinet_firewall_send, m, label);
+
+ MAC_PERFORM_NOSLEEP(netinet_firewall_send, m, label);
}
/*
@@ -386,7 +400,7 @@ mac_syncache_destroy(struct label **label)
{
if (*label != NULL) {
- MAC_PERFORM(syncache_destroy_label, *label);
+ MAC_PERFORM_NOSLEEP(syncache_destroy_label, *label);
mac_labelzone_free(*label);
*label = NULL;
}
@@ -408,9 +422,9 @@ mac_syncache_init(struct label **label)
* MAC_PERFORM so we can propagate allocation failures back
* to the syncache code.
*/
- MAC_CHECK(syncache_init_label, *label, M_NOWAIT);
+ MAC_CHECK_NOSLEEP(syncache_init_label, *label, M_NOWAIT);
if (error) {
- MAC_PERFORM(syncache_destroy_label, *label);
+ MAC_PERFORM_NOSLEEP(syncache_destroy_label, *label);
mac_labelzone_free(*label);
}
return (error);
@@ -424,7 +438,8 @@ mac_syncache_create(struct label *label, struct inpcb *inp)
{
INP_WLOCK_ASSERT(inp);
- MAC_PERFORM(syncache_create, label, inp);
+
+ MAC_PERFORM_NOSLEEP(syncache_create, label, inp);
}
void
@@ -433,6 +448,8 @@ mac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m)
struct label *mlabel;
M_ASSERTPKTHDR(m);
+
mlabel = mac_mbuf_to_label(m);
- MAC_PERFORM(syncache_create_mbuf, sc_label, m, mlabel);
+
+ MAC_PERFORM_NOSLEEP(syncache_create_mbuf, sc_label, m, mlabel);
}
diff --git a/sys/security/mac/mac_inet6.c b/sys/security/mac/mac_inet6.c
index 9201b36..f804fe3 100644
--- a/sys/security/mac/mac_inet6.c
+++ b/sys/security/mac/mac_inet6.c
@@ -1,9 +1,12 @@
/*-
- * Copyright (c) 2007-2008 Robert N. M. Watson
+ * Copyright (c) 2007-2009 Robert N. M. Watson
* All rights reserved.
*
* This software was developed by Robert Watson for the TrustedBSD Project.
*
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -67,9 +70,12 @@ mac_ip6q_label_alloc(int flag)
if (label == NULL)
return (NULL);
- MAC_CHECK(ip6q_init_label, label, flag);
+ if (flag & M_WAITOK)
+ MAC_CHECK(ip6q_init_label, label, flag);
+ else
+ MAC_CHECK_NOSLEEP(ip6q_init_label, label, flag);
if (error) {
- MAC_PERFORM(ip6q_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(ip6q_destroy_label, label);
mac_labelzone_free(label);
return (NULL);
}
@@ -93,7 +99,7 @@ static void
mac_ip6q_label_free(struct label *label)
{
- MAC_PERFORM(ip6q_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(ip6q_destroy_label, label);
mac_labelzone_free(label);
}
@@ -114,7 +120,7 @@ mac_ip6q_reassemble(struct ip6q *q6, struct mbuf *m)
label = mac_mbuf_to_label(m);
- MAC_PERFORM(ip6q_reassemble, q6, q6->ip6q_label, m, label);
+ MAC_PERFORM_NOSLEEP(ip6q_reassemble, q6, q6->ip6q_label, m, label);
}
void
@@ -124,7 +130,7 @@ mac_ip6q_create(struct mbuf *m, struct ip6q *q6)
label = mac_mbuf_to_label(m);
- MAC_PERFORM(ip6q_create, m, label, q6, q6->ip6q_label);
+ MAC_PERFORM_NOSLEEP(ip6q_create, m, label, q6, q6->ip6q_label);
}
int
@@ -136,7 +142,7 @@ mac_ip6q_match(struct mbuf *m, struct ip6q *q6)
label = mac_mbuf_to_label(m);
result = 1;
- MAC_BOOLEAN(ip6q_match, &&, m, label, q6, q6->ip6q_label);
+ MAC_BOOLEAN_NOSLEEP(ip6q_match, &&, m, label, q6, q6->ip6q_label);
return (result);
}
@@ -148,7 +154,7 @@ mac_ip6q_update(struct mbuf *m, struct ip6q *q6)
label = mac_mbuf_to_label(m);
- MAC_PERFORM(ip6q_update, m, label, q6, q6->ip6q_label);
+ MAC_PERFORM_NOSLEEP(ip6q_update, m, label, q6, q6->ip6q_label);
}
void
@@ -158,5 +164,6 @@ mac_netinet6_nd6_send(struct ifnet *ifp, struct mbuf *m)
mlabel = mac_mbuf_to_label(m);
- MAC_PERFORM(netinet6_nd6_send, ifp, ifp->if_label, m, mlabel);
+ MAC_PERFORM_NOSLEEP(netinet6_nd6_send, ifp, ifp->if_label, m,
+ mlabel);
}
diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h
index 34336fc..280c8b8 100644
--- a/sys/security/mac/mac_internal.h
+++ b/sys/security/mac/mac_internal.h
@@ -194,12 +194,10 @@ extern struct mtx mac_ifnet_mtx;
*/
int mac_error_select(int error1, int error2);
-void mac_policy_grab_exclusive(void);
-void mac_policy_assert_exclusive(void);
-void mac_policy_release_exclusive(void);
-void mac_policy_list_busy(void);
-int mac_policy_list_conditional_busy(void);
-void mac_policy_list_unbusy(void);
+void mac_policy_slock_nosleep(void);
+void mac_policy_slock_sleep(void);
+void mac_policy_sunlock_nosleep(void);
+void mac_policy_sunlock_sleep(void);
struct label *mac_labelzone_alloc(int flags);
void mac_labelzone_free(struct label *label);
@@ -255,13 +253,16 @@ int vn_setlabel(struct vnode *vp, struct label *intlabel,
struct ucred *cred);
/*
+ * MAC Framework composition macros invoke all registered MAC policies for a
+ * specific entry point. They come in two forms: one which permits policies
+ * to sleep/block, and another that does not.
+ *
* MAC_CHECK performs the designated check by walking the policy module list
* and checking with each as to how it feels about the request. Note that it
* returns its value via 'error' in the scope of the caller.
*/
#define MAC_CHECK(check, args...) do { \
struct mac_policy_conf *mpc; \
- int entrycount; \
\
error = 0; \
LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
@@ -270,14 +271,37 @@ int vn_setlabel(struct vnode *vp, struct label *intlabel,
mpc->mpc_ops->mpo_ ## check (args), \
error); \
} \
- if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \
+ if (!LIST_EMPTY(&mac_policy_list)) { \
+ mac_policy_slock_sleep(); \
+ LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
+ if (mpc->mpc_ops->mpo_ ## check != NULL) \
+ error = mac_error_select( \
+ mpc->mpc_ops->mpo_ ## check (args), \
+ error); \
+ } \
+ mac_policy_sunlock_sleep(); \
+ } \
+} while (0)
+
+#define MAC_CHECK_NOSLEEP(check, args...) do { \
+ struct mac_policy_conf *mpc; \
+ \
+ error = 0; \
+ LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
+ if (mpc->mpc_ops->mpo_ ## check != NULL) \
+ error = mac_error_select( \
+ mpc->mpc_ops->mpo_ ## check (args), \
+ error); \
+ } \
+ if (!LIST_EMPTY(&mac_policy_list)) { \
+ mac_policy_slock_nosleep(); \
LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
if (mpc->mpc_ops->mpo_ ## check != NULL) \
error = mac_error_select( \
mpc->mpc_ops->mpo_ ## check (args), \
error); \
} \
- mac_policy_list_unbusy(); \
+ mac_policy_sunlock_nosleep(); \
} \
} while (0)
@@ -288,9 +312,8 @@ int vn_setlabel(struct vnode *vp, struct label *intlabel,
* EPERM. Note that it returns its value via 'error' in the scope of the
* caller.
*/
-#define MAC_GRANT(check, args...) do { \
+#define MAC_GRANT_NOSLEEP(check, args...) do { \
struct mac_policy_conf *mpc; \
- int entrycount; \
\
error = EPERM; \
LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
@@ -299,7 +322,8 @@ int vn_setlabel(struct vnode *vp, struct label *intlabel,
error = 0; \
} \
} \
- if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \
+ if (!LIST_EMPTY(&mac_policy_list)) { \
+ mac_policy_slock_nosleep(); \
LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
if (mpc->mpc_ops->mpo_ ## check != NULL) { \
if (mpc->mpc_ops->mpo_ ## check (args) \
@@ -307,7 +331,7 @@ int vn_setlabel(struct vnode *vp, struct label *intlabel,
error = 0; \
} \
} \
- mac_policy_list_unbusy(); \
+ mac_policy_sunlock_nosleep(); \
} \
} while (0)
@@ -320,21 +344,41 @@ int vn_setlabel(struct vnode *vp, struct label *intlabel,
*/
#define MAC_BOOLEAN(operation, composition, args...) do { \
struct mac_policy_conf *mpc; \
- int entrycount; \
\
LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
if (mpc->mpc_ops->mpo_ ## operation != NULL) \
result = result composition \
mpc->mpc_ops->mpo_ ## operation (args); \
} \
- if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \
+ if (!LIST_EMPTY(&mac_policy_list)) { \
+ mac_policy_slock_sleep(); \
+ LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
+ if (mpc->mpc_ops->mpo_ ## operation != NULL) \
+ result = result composition \
+ mpc->mpc_ops->mpo_ ## operation \
+ (args); \
+ } \
+ mac_policy_sunlock_sleep(); \
+ } \
+} while (0)
+
+#define MAC_BOOLEAN_NOSLEEP(operation, composition, args...) do { \
+ struct mac_policy_conf *mpc; \
+ \
+ LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
+ if (mpc->mpc_ops->mpo_ ## operation != NULL) \
+ result = result composition \
+ mpc->mpc_ops->mpo_ ## operation (args); \
+ } \
+ if (!LIST_EMPTY(&mac_policy_list)) { \
+ mac_policy_slock_nosleep(); \
LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
if (mpc->mpc_ops->mpo_ ## operation != NULL) \
result = result composition \
mpc->mpc_ops->mpo_ ## operation \
(args); \
} \
- mac_policy_list_unbusy(); \
+ mac_policy_sunlock_nosleep(); \
} \
} while (0)
@@ -425,18 +469,35 @@ int vn_setlabel(struct vnode *vp, struct label *intlabel,
*/
#define MAC_PERFORM(operation, args...) do { \
struct mac_policy_conf *mpc; \
- int entrycount; \
\
LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
if (mpc->mpc_ops->mpo_ ## operation != NULL) \
mpc->mpc_ops->mpo_ ## operation (args); \
} \
- if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \
+ if (!LIST_EMPTY(&mac_policy_list)) { \
+ mac_policy_slock_sleep(); \
+ LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
+ if (mpc->mpc_ops->mpo_ ## operation != NULL) \
+ mpc->mpc_ops->mpo_ ## operation (args); \
+ } \
+ mac_policy_sunlock_sleep(); \
+ } \
+} while (0)
+
+#define MAC_PERFORM_NOSLEEP(operation, args...) do { \
+ struct mac_policy_conf *mpc; \
+ \
+ LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
+ if (mpc->mpc_ops->mpo_ ## operation != NULL) \
+ mpc->mpc_ops->mpo_ ## operation (args); \
+ } \
+ if (!LIST_EMPTY(&mac_policy_list)) { \
+ mac_policy_slock_nosleep(); \
LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
if (mpc->mpc_ops->mpo_ ## operation != NULL) \
mpc->mpc_ops->mpo_ ## operation (args); \
} \
- mac_policy_list_unbusy(); \
+ mac_policy_sunlock_nosleep(); \
} \
} while (0)
diff --git a/sys/security/mac/mac_net.c b/sys/security/mac/mac_net.c
index 4fccbd7..697d02a 100644
--- a/sys/security/mac/mac_net.c
+++ b/sys/security/mac/mac_net.c
@@ -153,9 +153,12 @@ mac_mbuf_tag_init(struct m_tag *tag, int flag)
label = (struct label *) (tag + 1);
mac_init_label(label);
- MAC_CHECK(mbuf_init_label, label, flag);
+ if (flag & M_WAITOK)
+ MAC_CHECK(mbuf_init_label, label, flag);
+ else
+ MAC_CHECK_NOSLEEP(mbuf_init_label, label, flag);
if (error) {
- MAC_PERFORM(mbuf_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(mbuf_destroy_label, label);
mac_destroy_label(label);
}
return (error);
@@ -188,7 +191,7 @@ static void
mac_bpfdesc_label_free(struct label *label)
{
- MAC_PERFORM(bpfdesc_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(bpfdesc_destroy_label, label);
mac_labelzone_free(label);
}
@@ -206,7 +209,7 @@ static void
mac_ifnet_label_free(struct label *label)
{
- MAC_PERFORM(ifnet_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(ifnet_destroy_label, label);
mac_labelzone_free(label);
}
@@ -227,7 +230,7 @@ mac_mbuf_tag_destroy(struct m_tag *tag)
label = (struct label *)(tag+1);
- MAC_PERFORM(mbuf_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(mbuf_destroy_label, label);
mac_destroy_label(label);
}
@@ -247,7 +250,7 @@ mac_mbuf_tag_copy(struct m_tag *src, struct m_tag *dest)
* mac_mbuf_tag_init() is called on the target tag in m_tag_copy(),
* so we don't need to call it here.
*/
- MAC_PERFORM(mbuf_copy_label, src_label, dest_label);
+ MAC_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label);
}
void
@@ -258,14 +261,14 @@ mac_mbuf_copy(struct mbuf *m_from, struct mbuf *m_to)
src_label = mac_mbuf_to_label(m_from);
dest_label = mac_mbuf_to_label(m_to);
- MAC_PERFORM(mbuf_copy_label, src_label, dest_label);
+ MAC_PERFORM_NOSLEEP(mbuf_copy_label, src_label, dest_label);
}
static void
mac_ifnet_copy_label(struct label *src, struct label *dest)
{
- MAC_PERFORM(ifnet_copy_label, src, dest);
+ MAC_PERFORM_NOSLEEP(ifnet_copy_label, src, dest);
}
static int
@@ -294,7 +297,7 @@ mac_ifnet_create(struct ifnet *ifp)
{
MAC_IFNET_LOCK(ifp);
- MAC_PERFORM(ifnet_create, ifp, ifp->if_label);
+ MAC_PERFORM_NOSLEEP(ifnet_create, ifp, ifp->if_label);
MAC_IFNET_UNLOCK(ifp);
}
@@ -302,7 +305,7 @@ void
mac_bpfdesc_create(struct ucred *cred, struct bpf_d *d)
{
- MAC_PERFORM(bpfdesc_create, cred, d, d->bd_label);
+ MAC_PERFORM_NOSLEEP(bpfdesc_create, cred, d, d->bd_label);
}
void
@@ -314,7 +317,7 @@ mac_bpfdesc_create_mbuf(struct bpf_d *d, struct mbuf *m)
label = mac_mbuf_to_label(m);
- MAC_PERFORM(bpfdesc_create_mbuf, d, d->bd_label, m, label);
+ MAC_PERFORM_NOSLEEP(bpfdesc_create_mbuf, d, d->bd_label, m, label);
}
void
@@ -325,7 +328,7 @@ mac_ifnet_create_mbuf(struct ifnet *ifp, struct mbuf *m)
label = mac_mbuf_to_label(m);
MAC_IFNET_LOCK(ifp);
- MAC_PERFORM(ifnet_create_mbuf, ifp, ifp->if_label, m, label);
+ MAC_PERFORM_NOSLEEP(ifnet_create_mbuf, ifp, ifp->if_label, m, label);
MAC_IFNET_UNLOCK(ifp);
}
@@ -340,7 +343,8 @@ mac_bpfdesc_check_receive(struct bpf_d *d, struct ifnet *ifp)
BPFD_LOCK_ASSERT(d);
MAC_IFNET_LOCK(ifp);
- MAC_CHECK(bpfdesc_check_receive, d, d->bd_label, ifp, ifp->if_label);
+ MAC_CHECK_NOSLEEP(bpfdesc_check_receive, d, d->bd_label, ifp,
+ ifp->if_label);
MAC_CHECK_PROBE2(bpfdesc_check_receive, error, d, ifp);
MAC_IFNET_UNLOCK(ifp);
@@ -361,7 +365,8 @@ mac_ifnet_check_transmit(struct ifnet *ifp, struct mbuf *m)
label = mac_mbuf_to_label(m);
MAC_IFNET_LOCK(ifp);
- MAC_CHECK(ifnet_check_transmit, ifp, ifp->if_label, m, label);
+ MAC_CHECK_NOSLEEP(ifnet_check_transmit, ifp, ifp->if_label, m,
+ label);
MAC_CHECK_PROBE2(ifnet_check_transmit, error, ifp, m);
MAC_IFNET_UNLOCK(ifp);
@@ -458,14 +463,16 @@ mac_ifnet_ioctl_set(struct ucred *cred, struct ifreq *ifr, struct ifnet *ifp)
}
MAC_IFNET_LOCK(ifp);
- MAC_CHECK(ifnet_check_relabel, cred, ifp, ifp->if_label, intlabel);
+ MAC_CHECK_NOSLEEP(ifnet_check_relabel, cred, ifp, ifp->if_label,
+ intlabel);
if (error) {
MAC_IFNET_UNLOCK(ifp);
mac_ifnet_label_free(intlabel);
return (error);
}
- MAC_PERFORM(ifnet_relabel, cred, ifp, ifp->if_label, intlabel);
+ MAC_PERFORM_NOSLEEP(ifnet_relabel, cred, ifp, ifp->if_label,
+ intlabel);
MAC_IFNET_UNLOCK(ifp);
mac_ifnet_label_free(intlabel);
diff --git a/sys/security/mac/mac_pipe.c b/sys/security/mac/mac_pipe.c
index 921fd20..160a944 100644
--- a/sys/security/mac/mac_pipe.c
+++ b/sys/security/mac/mac_pipe.c
@@ -84,7 +84,7 @@ void
mac_pipe_label_free(struct label *label)
{
- MAC_PERFORM(pipe_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(pipe_destroy_label, label);
mac_labelzone_free(label);
}
@@ -102,7 +102,7 @@ void
mac_pipe_copy_label(struct label *src, struct label *dest)
{
- MAC_PERFORM(pipe_copy_label, src, dest);
+ MAC_PERFORM_NOSLEEP(pipe_copy_label, src, dest);
}
int
@@ -130,7 +130,7 @@ void
mac_pipe_create(struct ucred *cred, struct pipepair *pp)
{
- MAC_PERFORM(pipe_create, cred, pp, pp->pp_label);
+ MAC_PERFORM_NOSLEEP(pipe_create, cred, pp, pp->pp_label);
}
static void
@@ -138,7 +138,7 @@ mac_pipe_relabel(struct ucred *cred, struct pipepair *pp,
struct label *newlabel)
{
- MAC_PERFORM(pipe_relabel, cred, pp, pp->pp_label, newlabel);
+ MAC_PERFORM_NOSLEEP(pipe_relabel, cred, pp, pp->pp_label, newlabel);
}
MAC_CHECK_PROBE_DEFINE4(pipe_check_ioctl, "struct ucred *",
@@ -152,7 +152,8 @@ mac_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
mtx_assert(&pp->pp_mtx, MA_OWNED);
- MAC_CHECK(pipe_check_ioctl, cred, pp, pp->pp_label, cmd, data);
+ MAC_CHECK_NOSLEEP(pipe_check_ioctl, cred, pp, pp->pp_label, cmd,
+ data);
MAC_CHECK_PROBE4(pipe_check_ioctl, error, cred, pp, cmd, data);
return (error);
@@ -168,7 +169,7 @@ mac_pipe_check_poll(struct ucred *cred, struct pipepair *pp)
mtx_assert(&pp->pp_mtx, MA_OWNED);
- MAC_CHECK(pipe_check_poll, cred, pp, pp->pp_label);
+ MAC_CHECK_NOSLEEP(pipe_check_poll, cred, pp, pp->pp_label);
MAC_CHECK_PROBE2(pipe_check_poll, error, cred, pp);
return (error);
@@ -184,7 +185,7 @@ mac_pipe_check_read(struct ucred *cred, struct pipepair *pp)
mtx_assert(&pp->pp_mtx, MA_OWNED);
- MAC_CHECK(pipe_check_read, cred, pp, pp->pp_label);
+ MAC_CHECK_NOSLEEP(pipe_check_read, cred, pp, pp->pp_label);
MAC_CHECK_PROBE2(pipe_check_read, error, cred, pp);
return (error);
@@ -201,7 +202,8 @@ mac_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
mtx_assert(&pp->pp_mtx, MA_OWNED);
- MAC_CHECK(pipe_check_relabel, cred, pp, pp->pp_label, newlabel);
+ MAC_CHECK_NOSLEEP(pipe_check_relabel, cred, pp, pp->pp_label,
+ newlabel);
MAC_CHECK_PROBE3(pipe_check_relabel, error, cred, pp, newlabel);
return (error);
@@ -217,7 +219,7 @@ mac_pipe_check_stat(struct ucred *cred, struct pipepair *pp)
mtx_assert(&pp->pp_mtx, MA_OWNED);
- MAC_CHECK(pipe_check_stat, cred, pp, pp->pp_label);
+ MAC_CHECK_NOSLEEP(pipe_check_stat, cred, pp, pp->pp_label);
MAC_CHECK_PROBE2(pipe_check_stat, error, cred, pp);
return (error);
@@ -233,7 +235,7 @@ mac_pipe_check_write(struct ucred *cred, struct pipepair *pp)
mtx_assert(&pp->pp_mtx, MA_OWNED);
- MAC_CHECK(pipe_check_write, cred, pp, pp->pp_label);
+ MAC_CHECK_NOSLEEP(pipe_check_write, cred, pp, pp->pp_label);
MAC_CHECK_PROBE2(pipe_check_write, error, cred, pp);
return (error);
diff --git a/sys/security/mac/mac_posix_sem.c b/sys/security/mac/mac_posix_sem.c
index 2e3560d..74a9ad9 100644
--- a/sys/security/mac/mac_posix_sem.c
+++ b/sys/security/mac/mac_posix_sem.c
@@ -80,7 +80,7 @@ static void
mac_posixsem_label_free(struct label *label)
{
- MAC_PERFORM(posixsem_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(posixsem_destroy_label, label);
mac_labelzone_free(label);
}
@@ -98,7 +98,7 @@ void
mac_posixsem_create(struct ucred *cred, struct ksem *ks)
{
- MAC_PERFORM(posixsem_create, cred, ks, ks->ks_label);
+ MAC_PERFORM_NOSLEEP(posixsem_create, cred, ks, ks->ks_label);
}
MAC_CHECK_PROBE_DEFINE2(posixsem_check_open, "struct ucred *",
@@ -109,7 +109,7 @@ mac_posixsem_check_open(struct ucred *cred, struct ksem *ks)
{
int error;
- MAC_CHECK(posixsem_check_open, cred, ks, ks->ks_label);
+ MAC_CHECK_NOSLEEP(posixsem_check_open, cred, ks, ks->ks_label);
MAC_CHECK_PROBE2(posixsem_check_open, error, cred, ks);
return (error);
@@ -124,8 +124,8 @@ mac_posixsem_check_getvalue(struct ucred *active_cred, struct ucred *file_cred,
{
int error;
- MAC_CHECK(posixsem_check_getvalue, active_cred, file_cred, ks,
- ks->ks_label);
+ MAC_CHECK_NOSLEEP(posixsem_check_getvalue, active_cred, file_cred,
+ ks, ks->ks_label);
MAC_CHECK_PROBE3(posixsem_check_getvalue, error, active_cred,
file_cred, ks);
@@ -141,7 +141,7 @@ mac_posixsem_check_post(struct ucred *active_cred, struct ucred *file_cred,
{
int error;
- MAC_CHECK(posixsem_check_post, active_cred, file_cred, ks,
+ MAC_CHECK_NOSLEEP(posixsem_check_post, active_cred, file_cred, ks,
ks->ks_label);
MAC_CHECK_PROBE3(posixsem_check_post, error, active_cred, file_cred,
ks);
@@ -158,7 +158,7 @@ mac_posixsem_check_stat(struct ucred *active_cred, struct ucred *file_cred,
{
int error;
- MAC_CHECK(posixsem_check_stat, active_cred, file_cred, ks,
+ MAC_CHECK_NOSLEEP(posixsem_check_stat, active_cred, file_cred, ks,
ks->ks_label);
MAC_CHECK_PROBE3(posixsem_check_stat, error, active_cred, file_cred,
ks);
@@ -174,7 +174,7 @@ mac_posixsem_check_unlink(struct ucred *cred, struct ksem *ks)
{
int error;
- MAC_CHECK(posixsem_check_unlink, cred, ks, ks->ks_label);
+ MAC_CHECK_NOSLEEP(posixsem_check_unlink, cred, ks, ks->ks_label);
MAC_CHECK_PROBE2(posixsem_check_unlink, error, cred, ks);
return (error);
@@ -189,7 +189,7 @@ mac_posixsem_check_wait(struct ucred *active_cred, struct ucred *file_cred,
{
int error;
- MAC_CHECK(posixsem_check_wait, active_cred, file_cred, ks,
+ MAC_CHECK_NOSLEEP(posixsem_check_wait, active_cred, file_cred, ks,
ks->ks_label);
MAC_CHECK_PROBE3(posixsem_check_wait, error, active_cred, file_cred,
ks);
diff --git a/sys/security/mac/mac_posix_shm.c b/sys/security/mac/mac_posix_shm.c
index 913cb43..bb9d9dd 100644
--- a/sys/security/mac/mac_posix_shm.c
+++ b/sys/security/mac/mac_posix_shm.c
@@ -79,7 +79,7 @@ static void
mac_posixshm_label_free(struct label *label)
{
- MAC_PERFORM(posixshm_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(posixshm_destroy_label, label);
mac_labelzone_free(label);
}
@@ -97,7 +97,7 @@ void
mac_posixshm_create(struct ucred *cred, struct shmfd *shmfd)
{
- MAC_PERFORM(posixshm_create, cred, shmfd, shmfd->shm_label);
+ MAC_PERFORM_NOSLEEP(posixshm_create, cred, shmfd, shmfd->shm_label);
}
MAC_CHECK_PROBE_DEFINE4(posixshm_check_mmap, "struct ucred *",
@@ -109,8 +109,8 @@ mac_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd, int prot,
{
int error;
- MAC_CHECK(posixshm_check_mmap, cred, shmfd, shmfd->shm_label, prot,
- flags);
+ MAC_CHECK_NOSLEEP(posixshm_check_mmap, cred, shmfd, shmfd->shm_label,
+ prot, flags);
MAC_CHECK_PROBE4(posixshm_check_mmap, error, cred, shmfd, prot,
flags);
@@ -125,7 +125,7 @@ mac_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd)
{
int error;
- MAC_CHECK(posixshm_check_open, cred, shmfd, shmfd->shm_label);
+ MAC_CHECK_NOSLEEP(posixshm_check_open, cred, shmfd, shmfd->shm_label);
MAC_CHECK_PROBE2(posixshm_check_open, error, cred, shmfd);
return (error);
@@ -140,7 +140,7 @@ mac_posixshm_check_stat(struct ucred *active_cred, struct ucred *file_cred,
{
int error;
- MAC_CHECK(posixshm_check_stat, active_cred, file_cred, shmfd,
+ MAC_CHECK_NOSLEEP(posixshm_check_stat, active_cred, file_cred, shmfd,
shmfd->shm_label);
MAC_CHECK_PROBE3(posixshm_check_stat, error, active_cred, file_cred,
shmfd);
@@ -157,8 +157,8 @@ mac_posixshm_check_truncate(struct ucred *active_cred, struct ucred *file_cred,
{
int error;
- MAC_CHECK(posixshm_check_truncate, active_cred, file_cred, shmfd,
- shmfd->shm_label);
+ MAC_CHECK_NOSLEEP(posixshm_check_truncate, active_cred, file_cred,
+ shmfd, shmfd->shm_label);
MAC_CHECK_PROBE3(posixshm_check_truncate, error, active_cred,
file_cred, shmfd);
@@ -173,7 +173,8 @@ mac_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd)
{
int error;
- MAC_CHECK(posixshm_check_unlink, cred, shmfd, shmfd->shm_label);
+ MAC_CHECK_NOSLEEP(posixshm_check_unlink, cred, shmfd,
+ shmfd->shm_label);
MAC_CHECK_PROBE2(posixshm_check_unlink, error, cred, shmfd);
return (error);
diff --git a/sys/security/mac/mac_priv.c b/sys/security/mac/mac_priv.c
index f12b020..afd64b9 100644
--- a/sys/security/mac/mac_priv.c
+++ b/sys/security/mac/mac_priv.c
@@ -72,7 +72,7 @@ mac_priv_check(struct ucred *cred, int priv)
{
int error;
- MAC_CHECK(priv_check, cred, priv);
+ MAC_CHECK_NOSLEEP(priv_check, cred, priv);
MAC_CHECK_PROBE2(priv_check, error, cred, priv);
return (error);
@@ -89,7 +89,7 @@ mac_priv_grant(struct ucred *cred, int priv)
{
int error;
- MAC_GRANT(priv_grant, cred, priv);
+ MAC_GRANT_NOSLEEP(priv_grant, cred, priv);
MAC_GRANT_PROBE2(priv_grant, error, cred, priv);
return (error);
diff --git a/sys/security/mac/mac_process.c b/sys/security/mac/mac_process.c
index 7faa7ae..1c8ec64 100644
--- a/sys/security/mac/mac_process.c
+++ b/sys/security/mac/mac_process.c
@@ -112,7 +112,7 @@ static void
mac_proc_label_free(struct label *label)
{
- MAC_PERFORM(proc_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(proc_destroy_label, label);
mac_labelzone_free(label);
}
@@ -386,7 +386,7 @@ mac_proc_check_debug(struct ucred *cred, struct proc *p)
PROC_LOCK_ASSERT(p, MA_OWNED);
- MAC_CHECK(proc_check_debug, cred, p);
+ MAC_CHECK_NOSLEEP(proc_check_debug, cred, p);
MAC_CHECK_PROBE2(proc_check_debug, error, cred, p);
return (error);
@@ -401,7 +401,7 @@ mac_proc_check_sched(struct ucred *cred, struct proc *p)
PROC_LOCK_ASSERT(p, MA_OWNED);
- MAC_CHECK(proc_check_sched, cred, p);
+ MAC_CHECK_NOSLEEP(proc_check_sched, cred, p);
MAC_CHECK_PROBE2(proc_check_sched, error, cred, p);
return (error);
@@ -417,7 +417,7 @@ mac_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
PROC_LOCK_ASSERT(p, MA_OWNED);
- MAC_CHECK(proc_check_signal, cred, p, signum);
+ MAC_CHECK_NOSLEEP(proc_check_signal, cred, p, signum);
MAC_CHECK_PROBE3(proc_check_signal, error, cred, p, signum);
return (error);
@@ -432,7 +432,7 @@ mac_proc_check_wait(struct ucred *cred, struct proc *p)
PROC_LOCK_ASSERT(p, MA_OWNED);
- MAC_CHECK(proc_check_wait, cred, p);
+ MAC_CHECK_NOSLEEP(proc_check_wait, cred, p);
MAC_CHECK_PROBE2(proc_check_wait, error, cred, p);
return (error);
diff --git a/sys/security/mac/mac_socket.c b/sys/security/mac/mac_socket.c
index e73ce12..fa24499 100644
--- a/sys/security/mac/mac_socket.c
+++ b/sys/security/mac/mac_socket.c
@@ -100,9 +100,12 @@ mac_socket_label_alloc(int flag)
if (label == NULL)
return (NULL);
- MAC_CHECK(socket_init_label, label, flag);
+ if (flag & M_WAITOK)
+ MAC_CHECK(socket_init_label, label, flag);
+ else
+ MAC_CHECK_NOSLEEP(socket_init_label, label, flag);
if (error) {
- MAC_PERFORM(socket_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(socket_destroy_label, label);
mac_labelzone_free(label);
return (NULL);
}
@@ -119,9 +122,12 @@ mac_socketpeer_label_alloc(int flag)
if (label == NULL)
return (NULL);
- MAC_CHECK(socketpeer_init_label, label, flag);
+ if (flag & M_WAITOK)
+ MAC_CHECK(socketpeer_init_label, label, flag);
+ else
+ MAC_CHECK_NOSLEEP(socketpeer_init_label, label, flag);
if (error) {
- MAC_PERFORM(socketpeer_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(socketpeer_destroy_label, label);
mac_labelzone_free(label);
return (NULL);
}
@@ -153,7 +159,7 @@ void
mac_socket_label_free(struct label *label)
{
- MAC_PERFORM(socket_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(socket_destroy_label, label);
mac_labelzone_free(label);
}
@@ -161,7 +167,7 @@ static void
mac_socketpeer_label_free(struct label *label)
{
- MAC_PERFORM(socketpeer_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(socketpeer_destroy_label, label);
mac_labelzone_free(label);
}
@@ -181,7 +187,7 @@ void
mac_socket_copy_label(struct label *src, struct label *dest)
{
- MAC_PERFORM(socket_copy_label, src, dest);
+ MAC_PERFORM_NOSLEEP(socket_copy_label, src, dest);
}
int
@@ -220,7 +226,7 @@ void
mac_socket_create(struct ucred *cred, struct socket *so)
{
- MAC_PERFORM(socket_create, cred, so, so->so_label);
+ MAC_PERFORM_NOSLEEP(socket_create, cred, so, so->so_label);
}
void
@@ -229,7 +235,7 @@ mac_socket_newconn(struct socket *oldso, struct socket *newso)
SOCK_LOCK_ASSERT(oldso);
- MAC_PERFORM(socket_newconn, oldso, oldso->so_label, newso,
+ MAC_PERFORM_NOSLEEP(socket_newconn, oldso, oldso->so_label, newso,
newso->so_label);
}
@@ -240,7 +246,8 @@ mac_socket_relabel(struct ucred *cred, struct socket *so,
SOCK_LOCK_ASSERT(so);
- MAC_PERFORM(socket_relabel, cred, so, so->so_label, newlabel);
+ MAC_PERFORM_NOSLEEP(socket_relabel, cred, so, so->so_label,
+ newlabel);
}
void
@@ -252,7 +259,7 @@ mac_socketpeer_set_from_mbuf(struct mbuf *m, struct socket *so)
label = mac_mbuf_to_label(m);
- MAC_PERFORM(socketpeer_set_from_mbuf, m, label, so,
+ MAC_PERFORM_NOSLEEP(socketpeer_set_from_mbuf, m, label, so,
so->so_peerlabel);
}
@@ -265,8 +272,8 @@ mac_socketpeer_set_from_socket(struct socket *oldso, struct socket *newso)
* is the original, and one is the new. However, it's called in both
* directions, so we can't assert the lock here currently.
*/
- MAC_PERFORM(socketpeer_set_from_socket, oldso, oldso->so_label,
- newso, newso->so_peerlabel);
+ MAC_PERFORM_NOSLEEP(socketpeer_set_from_socket, oldso,
+ oldso->so_label, newso, newso->so_peerlabel);
}
void
@@ -278,7 +285,7 @@ mac_socket_create_mbuf(struct socket *so, struct mbuf *m)
label = mac_mbuf_to_label(m);
- MAC_PERFORM(socket_create_mbuf, so, so->so_label, m, label);
+ MAC_PERFORM_NOSLEEP(socket_create_mbuf, so, so->so_label, m, label);
}
MAC_CHECK_PROBE_DEFINE2(socket_check_accept, "struct ucred *",
@@ -291,7 +298,7 @@ mac_socket_check_accept(struct ucred *cred, struct socket *so)
SOCK_LOCK_ASSERT(so);
- MAC_CHECK(socket_check_accept, cred, so, so->so_label);
+ MAC_CHECK_NOSLEEP(socket_check_accept, cred, so, so->so_label);
MAC_CHECK_PROBE2(socket_check_accept, error, cred, so);
return (error);
@@ -308,7 +315,7 @@ mac_socket_check_bind(struct ucred *cred, struct socket *so,
SOCK_LOCK_ASSERT(so);
- MAC_CHECK(socket_check_bind, cred, so, so->so_label, sa);
+ MAC_CHECK_NOSLEEP(socket_check_bind, cred, so, so->so_label, sa);
MAC_CHECK_PROBE3(socket_check_bind, error, cred, so, sa);
return (error);
@@ -325,7 +332,7 @@ mac_socket_check_connect(struct ucred *cred, struct socket *so,
SOCK_LOCK_ASSERT(so);
- MAC_CHECK(socket_check_connect, cred, so, so->so_label, sa);
+ MAC_CHECK_NOSLEEP(socket_check_connect, cred, so, so->so_label, sa);
MAC_CHECK_PROBE3(socket_check_connect, error, cred, so, sa);
return (error);
@@ -339,7 +346,7 @@ mac_socket_check_create(struct ucred *cred, int domain, int type, int proto)
{
int error;
- MAC_CHECK(socket_check_create, cred, domain, type, proto);
+ MAC_CHECK_NOSLEEP(socket_check_create, cred, domain, type, proto);
MAC_CHECK_PROBE4(socket_check_create, error, cred, domain, type,
proto);
@@ -359,7 +366,7 @@ mac_socket_check_deliver(struct socket *so, struct mbuf *m)
label = mac_mbuf_to_label(m);
- MAC_CHECK(socket_check_deliver, so, so->so_label, m, label);
+ MAC_CHECK_NOSLEEP(socket_check_deliver, so, so->so_label, m, label);
MAC_CHECK_PROBE2(socket_check_deliver, error, so, m);
return (error);
@@ -375,7 +382,7 @@ mac_socket_check_listen(struct ucred *cred, struct socket *so)
SOCK_LOCK_ASSERT(so);
- MAC_CHECK(socket_check_listen, cred, so, so->so_label);
+ MAC_CHECK_NOSLEEP(socket_check_listen, cred, so, so->so_label);
MAC_CHECK_PROBE2(socket_check_listen, error, cred, so);
return (error);
@@ -391,7 +398,7 @@ mac_socket_check_poll(struct ucred *cred, struct socket *so)
SOCK_LOCK_ASSERT(so);
- MAC_CHECK(socket_check_poll, cred, so, so->so_label);
+ MAC_CHECK_NOSLEEP(socket_check_poll, cred, so, so->so_label);
MAC_CHECK_PROBE2(socket_check_poll, error, cred, so);
return (error);
@@ -407,7 +414,7 @@ mac_socket_check_receive(struct ucred *cred, struct socket *so)
SOCK_LOCK_ASSERT(so);
- MAC_CHECK(socket_check_receive, cred, so, so->so_label);
+ MAC_CHECK_NOSLEEP(socket_check_receive, cred, so, so->so_label);
MAC_CHECK_PROBE2(socket_check_receive, error, cred, so);
return (error);
@@ -424,7 +431,8 @@ mac_socket_check_relabel(struct ucred *cred, struct socket *so,
SOCK_LOCK_ASSERT(so);
- MAC_CHECK(socket_check_relabel, cred, so, so->so_label, newlabel);
+ MAC_CHECK_NOSLEEP(socket_check_relabel, cred, so, so->so_label,
+ newlabel);
MAC_CHECK_PROBE3(socket_check_relabel, error, cred, so, newlabel);
return (error);
@@ -440,7 +448,7 @@ mac_socket_check_send(struct ucred *cred, struct socket *so)
SOCK_LOCK_ASSERT(so);
- MAC_CHECK(socket_check_send, cred, so, so->so_label);
+ MAC_CHECK_NOSLEEP(socket_check_send, cred, so, so->so_label);
MAC_CHECK_PROBE2(socket_check_send, error, cred, so);
return (error);
@@ -456,7 +464,7 @@ mac_socket_check_stat(struct ucred *cred, struct socket *so)
SOCK_LOCK_ASSERT(so);
- MAC_CHECK(socket_check_stat, cred, so, so->so_label);
+ MAC_CHECK_NOSLEEP(socket_check_stat, cred, so, so->so_label);
MAC_CHECK_PROBE2(socket_check_stat, error, cred, so);
return (error);
@@ -472,7 +480,7 @@ mac_socket_check_visible(struct ucred *cred, struct socket *so)
SOCK_LOCK_ASSERT(so);
- MAC_CHECK(socket_check_visible, cred, so, so->so_label);
+ MAC_CHECK_NOSLEEP(socket_check_visible, cred, so, so->so_label);
MAC_CHECK_PROBE2(socket_check_visible, error, cred, so);
return (error);
diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c
index c4b0606..905c43b 100644
--- a/sys/security/mac/mac_syscalls.c
+++ b/sys/security/mac/mac_syscalls.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1999-2002, 2006 Robert N. M. Watson
+ * Copyright (c) 1999-2002, 2006, 2009 Robert N. M. Watson
* Copyright (c) 2001 Ilmar S. Habibulin
* Copyright (c) 2001-2005 Networks Associates Technology, Inc.
* Copyright (c) 2005-2006 SPARTA, Inc.
@@ -17,6 +17,9 @@
* This software was enhanced by SPARTA ISSO under SPAWAR contract
* N66001-04-C-6019 ("SEFOS").
*
+ * This software was developed at the University of Cambridge Computer
+ * Laboratory with support from a grant from Google, Inc.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -617,7 +620,7 @@ mac_syscall(struct thread *td, struct mac_syscall_args *uap)
{
struct mac_policy_conf *mpc;
char target[MAC_MAX_POLICY_NAME];
- int entrycount, error;
+ int error;
error = copyinstr(uap->policy, target, sizeof(target), NULL);
if (error)
@@ -633,7 +636,8 @@ mac_syscall(struct thread *td, struct mac_syscall_args *uap)
}
}
- if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
+ if (!LIST_EMPTY(&mac_policy_list)) {
+ mac_policy_slock_sleep();
LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
if (strcmp(mpc->mpc_name, target) == 0 &&
mpc->mpc_ops->mpo_syscall != NULL) {
@@ -642,7 +646,7 @@ mac_syscall(struct thread *td, struct mac_syscall_args *uap)
break;
}
}
- mac_policy_list_unbusy();
+ mac_policy_sunlock_sleep();
}
out:
return (error);
diff --git a/sys/security/mac/mac_system.c b/sys/security/mac/mac_system.c
index a8e351e..4a377c0 100644
--- a/sys/security/mac/mac_system.c
+++ b/sys/security/mac/mac_system.c
@@ -78,7 +78,7 @@ mac_kenv_check_dump(struct ucred *cred)
{
int error;
- MAC_CHECK(kenv_check_dump, cred);
+ MAC_CHECK_NOSLEEP(kenv_check_dump, cred);
MAC_CHECK_PROBE1(kenv_check_dump, error, cred);
return (error);
@@ -91,7 +91,7 @@ mac_kenv_check_get(struct ucred *cred, char *name)
{
int error;
- MAC_CHECK(kenv_check_get, cred, name);
+ MAC_CHECK_NOSLEEP(kenv_check_get, cred, name);
MAC_CHECK_PROBE2(kenv_check_get, error, cred, name);
return (error);
@@ -105,7 +105,7 @@ mac_kenv_check_set(struct ucred *cred, char *name, char *value)
{
int error;
- MAC_CHECK(kenv_check_set, cred, name, value);
+ MAC_CHECK_NOSLEEP(kenv_check_set, cred, name, value);
MAC_CHECK_PROBE3(kenv_check_set, error, cred, name, value);
return (error);
@@ -118,7 +118,7 @@ mac_kenv_check_unset(struct ucred *cred, char *name)
{
int error;
- MAC_CHECK(kenv_check_unset, cred, name);
+ MAC_CHECK_NOSLEEP(kenv_check_unset, cred, name);
MAC_CHECK_PROBE2(kenv_check_unset, error, cred, name);
return (error);
@@ -146,7 +146,7 @@ mac_kld_check_stat(struct ucred *cred)
{
int error;
- MAC_CHECK(kld_check_stat, cred);
+ MAC_CHECK_NOSLEEP(kld_check_stat, cred);
MAC_CHECK_PROBE1(kld_check_stat, error, cred);
return (error);
@@ -178,7 +178,7 @@ mac_system_check_reboot(struct ucred *cred, int howto)
{
int error;
- MAC_CHECK(system_check_reboot, cred, howto);
+ MAC_CHECK_NOSLEEP(system_check_reboot, cred, howto);
MAC_CHECK_PROBE2(system_check_reboot, error, cred, howto);
return (error);
@@ -229,7 +229,7 @@ mac_system_check_sysctl(struct ucred *cred, struct sysctl_oid *oidp,
* XXXMAC: We would very much like to assert the SYSCTL_LOCK here,
* but since it's not exported from kern_sysctl.c, we can't.
*/
- MAC_CHECK(system_check_sysctl, cred, oidp, arg1, arg2, req);
+ MAC_CHECK_NOSLEEP(system_check_sysctl, cred, oidp, arg1, arg2, req);
MAC_CHECK_PROBE3(system_check_sysctl, error, cred, oidp, req);
return (error);
diff --git a/sys/security/mac/mac_sysv_msg.c b/sys/security/mac/mac_sysv_msg.c
index 1053871..a1d21d9 100644
--- a/sys/security/mac/mac_sysv_msg.c
+++ b/sys/security/mac/mac_sysv_msg.c
@@ -107,7 +107,7 @@ static void
mac_sysv_msgmsg_label_free(struct label *label)
{
- MAC_PERFORM(sysvmsg_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(sysvmsg_destroy_label, label);
mac_labelzone_free(label);
}
@@ -125,7 +125,7 @@ static void
mac_sysv_msgqueue_label_free(struct label *label)
{
- MAC_PERFORM(sysvmsq_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(sysvmsq_destroy_label, label);
mac_labelzone_free(label);
}
@@ -144,7 +144,7 @@ mac_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr,
struct msg *msgptr)
{
- MAC_PERFORM(sysvmsg_create, cred, msqkptr, msqkptr->label,
+ MAC_PERFORM_NOSLEEP(sysvmsg_create, cred, msqkptr, msqkptr->label,
msgptr, msgptr->label);
}
@@ -152,21 +152,21 @@ void
mac_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr)
{
- MAC_PERFORM(sysvmsq_create, cred, msqkptr, msqkptr->label);
+ MAC_PERFORM_NOSLEEP(sysvmsq_create, cred, msqkptr, msqkptr->label);
}
void
mac_sysvmsg_cleanup(struct msg *msgptr)
{
- MAC_PERFORM(sysvmsg_cleanup, msgptr->label);
+ MAC_PERFORM_NOSLEEP(sysvmsg_cleanup, msgptr->label);
}
void
mac_sysvmsq_cleanup(struct msqid_kernel *msqkptr)
{
- MAC_PERFORM(sysvmsq_cleanup, msqkptr->label);
+ MAC_PERFORM_NOSLEEP(sysvmsq_cleanup, msqkptr->label);
}
MAC_CHECK_PROBE_DEFINE3(sysvmsq_check_msgmsq, "struct ucred *",
@@ -178,7 +178,7 @@ mac_sysvmsq_check_msgmsq(struct ucred *cred, struct msg *msgptr,
{
int error;
- MAC_CHECK(sysvmsq_check_msgmsq, cred, msgptr, msgptr->label,
+ MAC_CHECK_NOSLEEP(sysvmsq_check_msgmsq, cred, msgptr, msgptr->label,
msqkptr, msqkptr->label);
MAC_CHECK_PROBE3(sysvmsq_check_msgmsq, error, cred, msgptr, msqkptr);
@@ -193,7 +193,7 @@ mac_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr)
{
int error;
- MAC_CHECK(sysvmsq_check_msgrcv, cred, msgptr, msgptr->label);
+ MAC_CHECK_NOSLEEP(sysvmsq_check_msgrcv, cred, msgptr, msgptr->label);
MAC_CHECK_PROBE2(sysvmsq_check_msgrcv, error, cred, msgptr);
return (error);
@@ -207,7 +207,8 @@ mac_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr)
{
int error;
- MAC_CHECK(sysvmsq_check_msgrmid, cred, msgptr, msgptr->label);
+ MAC_CHECK_NOSLEEP(sysvmsq_check_msgrmid, cred, msgptr,
+ msgptr->label);
MAC_CHECK_PROBE2(sysvmsq_check_msgrmid, error, cred, msgptr);
return (error);
@@ -221,7 +222,8 @@ mac_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr)
{
int error;
- MAC_CHECK(sysvmsq_check_msqget, cred, msqkptr, msqkptr->label);
+ MAC_CHECK_NOSLEEP(sysvmsq_check_msqget, cred, msqkptr,
+ msqkptr->label);
MAC_CHECK_PROBE2(sysvmsq_check_msqget, error, cred, msqkptr);
return (error);
@@ -235,7 +237,8 @@ mac_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr)
{
int error;
- MAC_CHECK(sysvmsq_check_msqsnd, cred, msqkptr, msqkptr->label);
+ MAC_CHECK_NOSLEEP(sysvmsq_check_msqsnd, cred, msqkptr,
+ msqkptr->label);
MAC_CHECK_PROBE2(sysvmsq_check_msqsnd, error, cred, msqkptr);
return (error);
@@ -249,7 +252,8 @@ mac_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr)
{
int error;
- MAC_CHECK(sysvmsq_check_msqrcv, cred, msqkptr, msqkptr->label);
+ MAC_CHECK_NOSLEEP(sysvmsq_check_msqrcv, cred, msqkptr,
+ msqkptr->label);
MAC_CHECK_PROBE2(sysvmsq_check_msqrcv, error, cred, msqkptr);
return (error);
@@ -264,7 +268,8 @@ mac_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
{
int error;
- MAC_CHECK(sysvmsq_check_msqctl, cred, msqkptr, msqkptr->label, cmd);
+ MAC_CHECK_NOSLEEP(sysvmsq_check_msqctl, cred, msqkptr,
+ msqkptr->label, cmd);
MAC_CHECK_PROBE3(sysvmsq_check_msqctl, error, cred, msqkptr, cmd);
return (error);
diff --git a/sys/security/mac/mac_sysv_sem.c b/sys/security/mac/mac_sysv_sem.c
index 9fc13fa..add17da 100644
--- a/sys/security/mac/mac_sysv_sem.c
+++ b/sys/security/mac/mac_sysv_sem.c
@@ -86,7 +86,7 @@ static void
mac_sysv_sem_label_free(struct label *label)
{
- MAC_PERFORM(sysvsem_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(sysvsem_destroy_label, label);
mac_labelzone_free(label);
}
@@ -104,14 +104,14 @@ void
mac_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr)
{
- MAC_PERFORM(sysvsem_create, cred, semakptr, semakptr->label);
+ MAC_PERFORM_NOSLEEP(sysvsem_create, cred, semakptr, semakptr->label);
}
void
mac_sysvsem_cleanup(struct semid_kernel *semakptr)
{
- MAC_PERFORM(sysvsem_cleanup, semakptr->label);
+ MAC_PERFORM_NOSLEEP(sysvsem_cleanup, semakptr->label);
}
MAC_CHECK_PROBE_DEFINE3(sysvsem_check_semctl, "struct ucred *",
@@ -123,8 +123,8 @@ mac_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr,
{
int error;
- MAC_CHECK(sysvsem_check_semctl, cred, semakptr, semakptr->label,
- cmd);
+ MAC_CHECK_NOSLEEP(sysvsem_check_semctl, cred, semakptr,
+ semakptr->label, cmd);
MAC_CHECK_PROBE3(sysvsem_check_semctl, error, cred, semakptr, cmd);
return (error);
@@ -138,7 +138,8 @@ mac_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr)
{
int error;
- MAC_CHECK(sysvsem_check_semget, cred, semakptr, semakptr->label);
+ MAC_CHECK_NOSLEEP(sysvsem_check_semget, cred, semakptr,
+ semakptr->label);
return (error);
}
@@ -152,8 +153,8 @@ mac_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr,
{
int error;
- MAC_CHECK(sysvsem_check_semop, cred, semakptr, semakptr->label,
- accesstype);
+ MAC_CHECK_NOSLEEP(sysvsem_check_semop, cred, semakptr,
+ semakptr->label, accesstype);
MAC_CHECK_PROBE3(sysvsem_check_semop, error, cred, semakptr,
accesstype);
diff --git a/sys/security/mac/mac_sysv_shm.c b/sys/security/mac/mac_sysv_shm.c
index d42cb0b..57c2264 100644
--- a/sys/security/mac/mac_sysv_shm.c
+++ b/sys/security/mac/mac_sysv_shm.c
@@ -86,7 +86,7 @@ static void
mac_sysv_shm_label_free(struct label *label)
{
- MAC_PERFORM(sysvshm_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(sysvshm_destroy_label, label);
mac_labelzone_free(label);
}
@@ -104,14 +104,15 @@ void
mac_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr)
{
- MAC_PERFORM(sysvshm_create, cred, shmsegptr, shmsegptr->label);
+ MAC_PERFORM_NOSLEEP(sysvshm_create, cred, shmsegptr,
+ shmsegptr->label);
}
void
mac_sysvshm_cleanup(struct shmid_kernel *shmsegptr)
{
- MAC_PERFORM(sysvshm_cleanup, shmsegptr->label);
+ MAC_PERFORM_NOSLEEP(sysvshm_cleanup, shmsegptr->label);
}
MAC_CHECK_PROBE_DEFINE3(sysvshm_check_shmat, "struct ucred *",
@@ -123,8 +124,8 @@ mac_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
{
int error;
- MAC_CHECK(sysvshm_check_shmat, cred, shmsegptr, shmsegptr->label,
- shmflg);
+ MAC_CHECK_NOSLEEP(sysvshm_check_shmat, cred, shmsegptr,
+ shmsegptr->label, shmflg);
MAC_CHECK_PROBE3(sysvshm_check_shmat, error, cred, shmsegptr,
shmflg);
@@ -140,8 +141,8 @@ mac_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
{
int error;
- MAC_CHECK(sysvshm_check_shmctl, cred, shmsegptr, shmsegptr->label,
- cmd);
+ MAC_CHECK_NOSLEEP(sysvshm_check_shmctl, cred, shmsegptr,
+ shmsegptr->label, cmd);
MAC_CHECK_PROBE3(sysvshm_check_shmctl, error, cred, shmsegptr, cmd);
return (error);
@@ -155,7 +156,8 @@ mac_sysvshm_check_shmdt(struct ucred *cred, struct shmid_kernel *shmsegptr)
{
int error;
- MAC_CHECK(sysvshm_check_shmdt, cred, shmsegptr, shmsegptr->label);
+ MAC_CHECK_NOSLEEP(sysvshm_check_shmdt, cred, shmsegptr,
+ shmsegptr->label);
MAC_CHECK_PROBE2(sysvshm_check_shmdt, error, cred, shmsegptr);
return (error);
@@ -170,8 +172,8 @@ mac_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
{
int error;
- MAC_CHECK(sysvshm_check_shmget, cred, shmsegptr, shmsegptr->label,
- shmflg);
+ MAC_CHECK_NOSLEEP(sysvshm_check_shmget, cred, shmsegptr,
+ shmsegptr->label, shmflg);
MAC_CHECK_PROBE3(sysvshm_check_shmget, error, cred, shmsegptr,
shmflg);
diff --git a/sys/security/mac/mac_vfs.c b/sys/security/mac/mac_vfs.c
index 01afb81..0cb0f15 100644
--- a/sys/security/mac/mac_vfs.c
+++ b/sys/security/mac/mac_vfs.c
@@ -150,7 +150,7 @@ static void
mac_devfs_label_free(struct label *label)
{
- MAC_PERFORM(devfs_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(devfs_destroy_label, label);
mac_labelzone_free(label);
}
@@ -168,7 +168,7 @@ static void
mac_mount_label_free(struct label *label)
{
- MAC_PERFORM(mount_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(mount_destroy_label, label);
mac_labelzone_free(label);
}
@@ -186,7 +186,7 @@ void
mac_vnode_label_free(struct label *label)
{
- MAC_PERFORM(vnode_destroy_label, label);
+ MAC_PERFORM_NOSLEEP(vnode_destroy_label, label);
mac_labelzone_free(label);
}
@@ -204,7 +204,7 @@ void
mac_vnode_copy_label(struct label *src, struct label *dest)
{
- MAC_PERFORM(vnode_copy_label, src, dest);
+ MAC_PERFORM_NOSLEEP(vnode_copy_label, src, dest);
}
int
@@ -232,7 +232,8 @@ void
mac_devfs_update(struct mount *mp, struct devfs_dirent *de, struct vnode *vp)
{
- MAC_PERFORM(devfs_update, mp, de, de->de_label, vp, vp->v_label);
+ MAC_PERFORM_NOSLEEP(devfs_update, mp, de, de->de_label, vp,
+ vp->v_label);
}
void
@@ -240,7 +241,7 @@ mac_devfs_vnode_associate(struct mount *mp, struct devfs_dirent *de,
struct vnode *vp)
{
- MAC_PERFORM(devfs_vnode_associate, mp, mp->mnt_label, de,
+ MAC_PERFORM_NOSLEEP(devfs_vnode_associate, mp, mp->mnt_label, de,
de->de_label, vp, vp->v_label);
}
@@ -261,8 +262,8 @@ void
mac_vnode_associate_singlelabel(struct mount *mp, struct vnode *vp)
{
- MAC_PERFORM(vnode_associate_singlelabel, mp, mp->mnt_label, vp,
- vp->v_label);
+ MAC_PERFORM_NOSLEEP(vnode_associate_singlelabel, mp, mp->mnt_label,
+ vp, vp->v_label);
}
/*
@@ -360,8 +361,9 @@ mac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp,
ASSERT_VOP_LOCKED(vp, "mac_vnode_execve_will_transition");
result = 0;
- MAC_BOOLEAN(vnode_execve_will_transition, ||, old, vp, vp->v_label,
- interpvplabel, imgp, imgp->execlabel);
+ /* No sleeping since the process lock will be held by the caller. */
+ MAC_BOOLEAN_NOSLEEP(vnode_execve_will_transition, ||, old, vp,
+ vp->v_label, interpvplabel, imgp, imgp->execlabel);
return (result);
}
@@ -960,7 +962,7 @@ mac_mount_check_stat(struct ucred *cred, struct mount *mount)
{
int error;
- MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_label);
+ MAC_CHECK_NOSLEEP(mount_check_stat, cred, mount, mount->mnt_label);
MAC_CHECK_PROBE2(mount_check_stat, error, cred, mount);
return (error);
@@ -971,7 +973,8 @@ mac_devfs_create_device(struct ucred *cred, struct mount *mp,
struct cdev *dev, struct devfs_dirent *de)
{
- MAC_PERFORM(devfs_create_device, cred, mp, dev, de, de->de_label);
+ MAC_PERFORM_NOSLEEP(devfs_create_device, cred, mp, dev, de,
+ de->de_label);
}
void
@@ -979,8 +982,8 @@ mac_devfs_create_symlink(struct ucred *cred, struct mount *mp,
struct devfs_dirent *dd, struct devfs_dirent *de)
{
- MAC_PERFORM(devfs_create_symlink, cred, mp, dd, dd->de_label, de,
- de->de_label);
+ MAC_PERFORM_NOSLEEP(devfs_create_symlink, cred, mp, dd,
+ dd->de_label, de, de->de_label);
}
void
@@ -988,8 +991,8 @@ mac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
struct devfs_dirent *de)
{
- MAC_PERFORM(devfs_create_directory, mp, dirname, dirnamelen, de,
- de->de_label);
+ MAC_PERFORM_NOSLEEP(devfs_create_directory, mp, dirname, dirnamelen,
+ de, de->de_label);
}
/*
diff --git a/sys/security/mac_biba/mac_biba.c b/sys/security/mac_biba/mac_biba.c
index 41c1eea..97c3cbe 100644
--- a/sys/security/mac_biba/mac_biba.c
+++ b/sys/security/mac_biba/mac_biba.c
@@ -2892,11 +2892,11 @@ biba_vnode_check_open(struct ucred *cred, struct vnode *vp,
obj = SLOT(vplabel);
/* XXX privilege override for admin? */
- if (accmode & (VREAD | VEXEC | VSTAT)) {
+ if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
if (!biba_dominate_effective(obj, subj))
return (EACCES);
}
- if (accmode & (VWRITE | VAPPEND | VADMIN)) {
+ if (accmode & VMODIFY_PERMS) {
if (!biba_dominate_effective(subj, obj))
return (EACCES);
}
diff --git a/sys/security/mac_bsdextended/mac_bsdextended.c b/sys/security/mac_bsdextended/mac_bsdextended.c
index ee72df4..cc36851 100644
--- a/sys/security/mac_bsdextended/mac_bsdextended.c
+++ b/sys/security/mac_bsdextended/mac_bsdextended.c
@@ -478,9 +478,9 @@ ugidfw_accmode2mbi(accmode_t accmode)
mbi |= MBI_WRITE;
if (accmode & VREAD)
mbi |= MBI_READ;
- if (accmode & VADMIN)
+ if (accmode & VADMIN_PERMS)
mbi |= MBI_ADMIN;
- if (accmode & VSTAT)
+ if (accmode & VSTAT_PERMS)
mbi |= MBI_STAT;
if (accmode & VAPPEND)
mbi |= MBI_APPEND;
diff --git a/sys/security/mac_mls/mac_mls.c b/sys/security/mac_mls/mac_mls.c
index 81030d7..6d13505 100644
--- a/sys/security/mac_mls/mac_mls.c
+++ b/sys/security/mac_mls/mac_mls.c
@@ -2515,11 +2515,11 @@ mls_vnode_check_open(struct ucred *cred, struct vnode *vp,
obj = SLOT(vplabel);
/* XXX privilege override for admin? */
- if (accmode & (VREAD | VEXEC | VSTAT)) {
+ if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
if (!mls_dominate_effective(subj, obj))
return (EACCES);
}
- if (accmode & (VWRITE | VAPPEND | VADMIN)) {
+ if (accmode & VMODIFY_PERMS) {
if (!mls_dominate_effective(obj, subj))
return (EACCES);
}
diff --git a/sys/security/mac_portacl/mac_portacl.c b/sys/security/mac_portacl/mac_portacl.c
index aceda69..f54319a 100644
--- a/sys/security/mac_portacl/mac_portacl.c
+++ b/sys/security/mac_portacl/mac_portacl.c
@@ -341,10 +341,12 @@ sysctl_rules(SYSCTL_HANDLER_ARGS)
int error;
new_string = NULL;
- if (req->newptr == NULL) {
+ if (req->newptr != NULL) {
new_string = malloc(MAC_RULE_STRING_LEN, M_PORTACL,
M_WAITOK | M_ZERO);
+ mtx_lock(&rule_mtx);
strcpy(new_string, rule_string);
+ mtx_unlock(&rule_mtx);
string = new_string;
} else
string = rule_string;
diff --git a/sys/sparc64/central/central.c b/sys/sparc64/central/central.c
index 48cf065..4ded549 100644
--- a/sys/sparc64/central/central.c
+++ b/sys/sparc64/central/central.c
@@ -76,14 +76,15 @@ static device_method_t central_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, central_print_child),
DEVMETHOD(bus_probe_nomatch, central_probe_nomatch),
- DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_alloc_resource, central_alloc_resource),
- DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_get_resource_list, central_get_resource_list),
+ DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_get_resource_list, central_get_resource_list),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, central_get_devinfo),
@@ -93,7 +94,7 @@ static device_method_t central_methods[] = {
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
- { NULL, NULL }
+ KOBJMETHOD_END
};
static driver_t central_driver = {
diff --git a/sys/sparc64/conf/GENERIC b/sys/sparc64/conf/GENERIC
index 0c051fb..46c363e 100644
--- a/sys/sparc64/conf/GENERIC
+++ b/sys/sparc64/conf/GENERIC
@@ -230,7 +230,6 @@ device ukbd # Keyboard
#device umass # Disks/Mass storage - Requires scbus and da
device ums # Mouse
#device urio # Diamond Rio 500 MP3 player
-#device uscanner # Scanners
# USB Ethernet, requires mii
#device aue # ADMtek USB Ethernet
#device axe # ASIX Electronics USB Ethernet
diff --git a/sys/sparc64/ebus/ebus.c b/sys/sparc64/ebus/ebus.c
index 9baa7a8..3bafaae 100644
--- a/sys/sparc64/ebus/ebus.c
+++ b/sys/sparc64/ebus/ebus.c
@@ -109,14 +109,14 @@ static device_method_t ebus_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, ebus_print_child),
DEVMETHOD(bus_probe_nomatch, ebus_probe_nomatch),
- DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_alloc_resource, ebus_alloc_resource),
- DEVMETHOD(bus_get_resource_list, ebus_get_resource_list),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
DEVMETHOD(bus_release_resource, ebus_release_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_get_resource_list, ebus_get_resource_list),
DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
/* ofw_bus interface */
@@ -127,7 +127,7 @@ static device_method_t ebus_methods[] = {
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
- { 0, 0 }
+ KOBJMETHOD_END
};
static driver_t ebus_driver = {
diff --git a/sys/sparc64/fhc/fhc.c b/sys/sparc64/fhc/fhc.c
index 84edbd4..91416ec 100644
--- a/sys/sparc64/fhc/fhc.c
+++ b/sys/sparc64/fhc/fhc.c
@@ -90,14 +90,15 @@ static device_method_t fhc_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, fhc_print_child),
DEVMETHOD(bus_probe_nomatch, fhc_probe_nomatch),
- DEVMETHOD(bus_setup_intr, fhc_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_alloc_resource, fhc_alloc_resource),
- DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_get_resource_list, fhc_get_resource_list),
+ DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
+ DEVMETHOD(bus_setup_intr, fhc_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_get_resource_list, fhc_get_resource_list),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, fhc_get_devinfo),
@@ -107,7 +108,7 @@ static device_method_t fhc_methods[] = {
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
- { NULL, NULL }
+ KOBJMETHOD_END
};
static driver_t fhc_driver = {
@@ -165,9 +166,7 @@ fhc_attach(device_t dev)
int central;
int error;
int i;
- int nintr;
- int nreg;
- int rid;
+ int j;
sc = device_get_softc(dev);
node = ofw_bus_get_node(dev);
@@ -177,9 +176,9 @@ fhc_attach(device_t dev)
central = 1;
for (i = 0; i < FHC_NREG; i++) {
- rid = i;
+ j = i;
sc->sc_memres[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
- &rid, RF_ACTIVE);
+ &j, RF_ACTIVE);
if (sc->sc_memres[i] == NULL) {
device_printf(dev, "cannot allocate resource %d\n", i);
error = ENXIO;
@@ -239,7 +238,8 @@ fhc_attach(device_t dev)
/*
* Hunt through all the interrupt mapping regs and register
* our interrupt controller for the corresponding interrupt
- * vectors.
+ * vectors. We do this early in order to be able to catch
+ * stray interrupts.
*/
for (i = FHC_FANFAIL; i <= FHC_TOD; i++) {
fica = malloc(sizeof(*fica), M_DEVBUF, M_NOWAIT);
@@ -259,11 +259,13 @@ fhc_attach(device_t dev)
* the IGN and the IGN is constant for all devices
* on that FireHose controller.
*/
- if (intr_controller_register(INTMAP_VEC(sc->sc_ign,
+ j = intr_controller_register(INTMAP_VEC(sc->sc_ign,
INTINO(bus_read_4(fica->fica_memres, FHC_IMAP))),
- &fhc_ic, fica) != 0)
- panic("%s: could not register interrupt "
- "controller for map %d", __func__, i);
+ &fhc_ic, fica);
+ if (j != 0)
+ device_printf(dev, "could not register "
+ "interrupt controller for map %d (%d)\n",
+ i, j);
}
} else {
snprintf(ledname, sizeof(ledname), "board%d", board);
@@ -276,9 +278,9 @@ fhc_attach(device_t dev)
free(fdi, M_DEVBUF);
continue;
}
- nreg = OF_getprop_alloc(child, "reg", sizeof(*reg),
+ i = OF_getprop_alloc(child, "reg", sizeof(*reg),
(void **)&reg);
- if (nreg == -1) {
+ if (i == -1) {
device_printf(dev, "<%s>: incomplete\n",
fdi->fdi_obdinfo.obd_name);
ofw_bus_gen_destroy_devinfo(&fdi->fdi_obdinfo);
@@ -286,19 +288,19 @@ fhc_attach(device_t dev)
continue;
}
resource_list_init(&fdi->fdi_rl);
- for (i = 0; i < nreg; i++)
- resource_list_add(&fdi->fdi_rl, SYS_RES_MEMORY, i,
- reg[i].sbr_offset, reg[i].sbr_offset +
- reg[i].sbr_size, reg[i].sbr_size);
+ for (j = 0; j < i; j++)
+ resource_list_add(&fdi->fdi_rl, SYS_RES_MEMORY, j,
+ reg[j].sbr_offset, reg[j].sbr_offset +
+ reg[j].sbr_size, reg[j].sbr_size);
free(reg, M_OFWPROP);
if (central == 1) {
- nintr = OF_getprop_alloc(child, "interrupts",
+ i = OF_getprop_alloc(child, "interrupts",
sizeof(*intr), (void **)&intr);
- if (nintr != -1) {
- for (i = 0; i < nintr; i++) {
- iv = INTMAP_VEC(sc->sc_ign, intr[i]);
+ if (i != -1) {
+ for (j = 0; j < i; j++) {
+ iv = INTMAP_VEC(sc->sc_ign, intr[j]);
resource_list_add(&fdi->fdi_rl,
- SYS_RES_IRQ, i, iv, iv, 1);
+ SYS_RES_IRQ, j, iv, iv, 1);
}
free(intr, M_OFWPROP);
}
diff --git a/sys/sparc64/include/elf.h b/sys/sparc64/include/elf.h
index 108ade1..c0fcbee 100644
--- a/sys/sparc64/include/elf.h
+++ b/sys/sparc64/include/elf.h
@@ -78,16 +78,14 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-/*
- * The following non-standard values are used in Linux ELF binaries.
- */
#define AT_NOTELF 10 /* Program is not ELF ?? */
#define AT_UID 11 /* Real uid. */
#define AT_EUID 12 /* Effective uid. */
#define AT_GID 13 /* Real gid. */
#define AT_EGID 14 /* Effective gid. */
+#define AT_EXECPATH 15 /* Path to the executable. */
-#define AT_COUNT 15 /* Count of defined aux entry types. */
+#define AT_COUNT 16 /* Count of defined aux entry types. */
/* Define "machine" characteristics */
#if __ELF_WORD_SIZE == 32
diff --git a/sys/sparc64/include/trap.h b/sys/sparc64/include/trap.h
index f73340c..dd0e6dc 100644
--- a/sys/sparc64/include/trap.h
+++ b/sys/sparc64/include/trap.h
@@ -91,7 +91,7 @@
#ifndef LOCORE
void sun4u_set_traptable(void *tba_addr);
-extern const char *trap_msg[];
+extern const char *const trap_msg[];
#endif
#endif
diff --git a/sys/sparc64/isa/isa.c b/sys/sparc64/isa/isa.c
index be76e01..724b4a8 100644
--- a/sys/sparc64/isa/isa.c
+++ b/sys/sparc64/isa/isa.c
@@ -118,7 +118,7 @@ isa_init(device_t dev)
static const struct {
const char *name;
uint32_t id;
-} ofw_isa_pnp_map[] = {
+} const ofw_isa_pnp_map[] = {
{ "SUNW,lomh", 0x0000ae4e }, /* SUN0000 */
{ "dma", 0x0002d041 }, /* PNP0200 */
{ "floppy", 0x0007d041 }, /* PNP0700 */
@@ -130,6 +130,7 @@ static const struct {
{ "rmc-comm", 0x0300ae4e }, /* SUN0003 */
{ "kb_ps2", 0x0303d041 }, /* PNP0303 */
{ "kdmouse", 0x030fd041 }, /* PNP0F03 */
+ { "bscbus", 0x0400ae4e }, /* SUN0004 */
{ "power", 0x0c0cd041 }, /* PNP0C0C */
{ NULL, 0x0 }
};
diff --git a/sys/sparc64/isa/ofw_isa.c b/sys/sparc64/isa/ofw_isa.c
index de90869..de5e4ce 100644
--- a/sys/sparc64/isa/ofw_isa.c
+++ b/sys/sparc64/isa/ofw_isa.c
@@ -40,8 +40,8 @@ __FBSDID("$FreeBSD$");
#include <sys/systm.h>
#include <sys/bus.h>
-#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
#include <machine/bus.h>
#include <machine/resource.h>
diff --git a/sys/sparc64/pci/apb.c b/sys/sparc64/pci/apb.c
index ba0698c..ad4dfca 100644
--- a/sys/sparc64/pci/apb.c
+++ b/sys/sparc64/pci/apb.c
@@ -90,9 +90,9 @@ static device_method_t apb_methods[] = {
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, apb_alloc_resource),
- DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
@@ -105,7 +105,7 @@ static device_method_t apb_methods[] = {
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_node, ofw_pcib_gen_get_node),
- { 0, 0 }
+ KOBJMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/sys/sparc64/pci/ofw_pcib.c b/sys/sparc64/pci/ofw_pcib.c
index 8a5b991..3be57e3 100644
--- a/sys/sparc64/pci/ofw_pcib.c
+++ b/sys/sparc64/pci/ofw_pcib.c
@@ -71,9 +71,9 @@ static device_method_t ofw_pcib_methods[] = {
DEVMETHOD(bus_read_ivar, pcib_read_ivar),
DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
- DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
@@ -86,7 +86,7 @@ static device_method_t ofw_pcib_methods[] = {
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_node, ofw_pcib_gen_get_node),
- { 0, 0 }
+ KOBJMETHOD_END
};
static devclass_t pcib_devclass;
diff --git a/sys/sparc64/pci/ofw_pcibus.c b/sys/sparc64/pci/ofw_pcibus.c
index 65a498a..bd2c7a6 100644
--- a/sys/sparc64/pci/ofw_pcibus.c
+++ b/sys/sparc64/pci/ofw_pcibus.c
@@ -68,8 +68,7 @@ static device_probe_t ofw_pcibus_probe;
static device_attach_t ofw_pcibus_attach;
static pci_assign_interrupt_t ofw_pcibus_assign_interrupt;
static ofw_bus_get_devinfo_t ofw_pcibus_get_devinfo;
-static int ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child,
- char *buf, size_t buflen);
+static bus_child_pnpinfo_str_t ofw_pcibus_pnpinfo_str;
static device_method_t ofw_pcibus_methods[] = {
/* Device interface */
@@ -77,7 +76,7 @@ static device_method_t ofw_pcibus_methods[] = {
DEVMETHOD(device_attach, ofw_pcibus_attach),
/* Bus interface */
- DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_child_pnpinfo_str_method),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_pcibus_pnpinfo_str),
/* PCI interface */
DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt),
@@ -90,7 +89,7 @@ static device_method_t ofw_pcibus_methods[] = {
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
- { 0, 0 }
+ KOBJMETHOD_END
};
struct ofw_pcibus_devinfo {
@@ -306,16 +305,15 @@ ofw_pcibus_get_devinfo(device_t bus, device_t dev)
}
static int
-ofw_pcibus_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf,
+ofw_pcibus_pnpinfo_str(device_t dev, device_t child, char *buf,
size_t buflen)
{
- pci_child_pnpinfo_str_method(cbdev, child, buf, buflen);
+ pci_child_pnpinfo_str_method(dev, child, buf, buflen);
if (ofw_bus_get_node(child) != -1) {
- strlcat(buf, " ", buflen); /* Separate info */
- ofw_bus_gen_child_pnpinfo_str(cbdev, child, buf, buflen);
+ strlcat(buf, " ", buflen); /* Separate info. */
+ ofw_bus_gen_child_pnpinfo_str(dev, child, buf, buflen);
}
return (0);
}
-
diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
index 505eec4..c8caec2 100644
--- a/sys/sparc64/pci/psycho.c
+++ b/sys/sparc64/pci/psycho.c
@@ -83,7 +83,7 @@ static void psycho_set_intr(struct psycho_softc *, u_int, bus_addr_t,
driver_filter_t, driver_intr_t);
static int psycho_find_intrmap(struct psycho_softc *, u_int, bus_addr_t *,
bus_addr_t *, u_long *);
-static driver_filter_t psycho_dmasync;
+static driver_filter_t psycho_dma_sync_stub;
static void psycho_intr_enable(void *);
static void psycho_intr_disable(void *);
static void psycho_intr_assign(void *);
@@ -150,7 +150,7 @@ static device_method_t psycho_methods[] = {
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_node, psycho_get_node),
- { 0, 0 }
+ KOBJMETHOD_END
};
static devclass_t psycho_devclass;
@@ -175,7 +175,7 @@ struct psycho_icarg {
bus_addr_t pica_clr;
};
-struct psycho_dmasync {
+struct psycho_dma_sync {
struct psycho_softc *pds_sc;
driver_filter_t *pds_handler; /* handler to call */
void *pds_arg; /* argument for the handler */
@@ -232,14 +232,14 @@ struct psycho_desc {
const char *pd_name;
};
-static const struct psycho_desc psycho_compats[] = {
+static const struct psycho_desc const psycho_compats[] = {
{ "pci108e,8000", PSYCHO_MODE_PSYCHO, "Psycho compatible" },
{ "pci108e,a000", PSYCHO_MODE_SABRE, "Sabre compatible" },
{ "pci108e,a001", PSYCHO_MODE_SABRE, "Hummingbird compatible" },
{ NULL, 0, NULL }
};
-static const struct psycho_desc psycho_models[] = {
+static const struct psycho_desc const psycho_models[] = {
{ "SUNW,psycho", PSYCHO_MODE_PSYCHO, "Psycho" },
{ "SUNW,sabre", PSYCHO_MODE_SABRE, "Sabre" },
{ NULL, 0, NULL }
@@ -296,8 +296,8 @@ psycho_attach(device_t dev)
phandle_t child, node;
uint32_t dvmabase, prop, prop_array[2];
int32_t rev;
- u_int ver;
- int i, n, nrange, rid;
+ u_int rerun, ver;
+ int i, n;
node = ofw_bus_get_node(dev);
sc = device_get_softc(dev);
@@ -315,7 +315,7 @@ psycho_attach(device_t dev)
* (2) the shared Psycho configuration registers
*/
if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
- rid = 2;
+ i = 2;
sc->sc_pcictl =
bus_get_resource_start(dev, SYS_RES_MEMORY, 0) -
bus_get_resource_start(dev, SYS_RES_MEMORY, 2);
@@ -332,18 +332,18 @@ psycho_attach(device_t dev)
/* NOTREACHED */
}
} else {
- rid = 0;
+ i = 0;
sc->sc_pcictl = PSR_PCICTL0;
sc->sc_half = 0;
}
- sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
(sc->sc_mode == PSYCHO_MODE_PSYCHO ? RF_SHAREABLE : 0) |
RF_ACTIVE);
if (sc->sc_mem_res == NULL)
panic("%s: could not allocate registers", __func__);
/*
- * Match other Psycho's that are already configured against
+ * Match other Psychos that are already configured against
* the base physical address. This will be the same for a
* pair of devices that share register space.
*/
@@ -363,6 +363,8 @@ psycho_attach(device_t dev)
panic("%s: could not malloc mutex", __func__);
mtx_init(sc->sc_mtx, "pcib_mtx", NULL, MTX_SPIN);
} else {
+ if (sc->sc_mode != PSYCHO_MODE_PSYCHO)
+ panic("%s: no partner expected", __func__);
if (mtx_initialized(osc->sc_mtx) == 0)
panic("%s: mutex not initialized", __func__);
sc->sc_mtx = osc->sc_mtx;
@@ -408,16 +410,17 @@ psycho_attach(device_t dev)
case 0:
dr |= DIAG_RTRY_DIS;
dr &= ~DIAG_DWSYNC_DIS;
- /* XXX need to also disable rerun of the streaming buffers. */
+ rerun = 0;
break;
case 1:
csr &= ~PCICTL_ARB_PARK;
dr |= DIAG_RTRY_DIS | DIAG_DWSYNC_DIS;
- /* XXX need to also disable rerun of the streaming buffers. */
+ rerun = 0;
break;
default:
dr |= DIAG_DWSYNC_DIS;
dr &= ~DIAG_RTRY_DIS;
+ rerun = 1;
break;
}
@@ -460,13 +463,12 @@ psycho_attach(device_t dev)
rman_manage_region(&sc->sc_pci_mem_rman, 0, PSYCHO_MEM_SIZE) != 0)
panic("%s: failed to set up memory rman", __func__);
- nrange = OF_getprop_alloc(node, "ranges", sizeof(*range),
- (void **)&range);
+ n = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range);
/*
* Make sure that the expected ranges are present. The
* OFW_PCI_CS_MEM64 one is not currently used though.
*/
- if (nrange != PSYCHO_NRANGE)
+ if (n != PSYCHO_NRANGE)
panic("%s: unsupported number of ranges", __func__);
/*
* Find the addresses of the various bus spaces.
@@ -493,7 +495,8 @@ psycho_attach(device_t dev)
/*
* Hunt through all the interrupt mapping regs and register
* our interrupt controller for the corresponding interrupt
- * vectors.
+ * vectors. We do this early in order to be able to catch
+ * stray interrupts.
*/
for (n = 0; n <= PSYCHO_MAX_INO; n++) {
if (psycho_find_intrmap(sc, n, &intrmap, &intrclr,
@@ -523,22 +526,23 @@ psycho_attach(device_t dev)
INTMAP_ENABLE(INTMAP_VEC(sc->sc_ign, n),
PCPU_GET(mid)));
#endif
- if (intr_controller_register(INTMAP_VEC(sc->sc_ign, n),
- &psycho_ic, pica) != 0)
- panic("%s: could not register interrupt "
- "controller for INO %d", __func__, n);
+ i = intr_controller_register(INTMAP_VEC(sc->sc_ign, n),
+ &psycho_ic, pica);
+ if (i != 0)
+ device_printf(dev, "could not register "
+ "interrupt controller for INO %d (%d)\n",
+ n, i);
}
- if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
- /* Initialize the counter-timer. */
+ if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
sparc64_counter_init(device_get_nameunit(dev),
rman_get_bustag(sc->sc_mem_res),
rman_get_bushandle(sc->sc_mem_res), PSR_TC0);
- }
/*
* Set up IOMMU and PCI configuration if we're the first
- * of a pair of Psycho's to arrive here.
+ * of a pair of Psychos to arrive here or a Hummingbird
+ * or Sabre.
*
* We should calculate a TSB size based on amount of RAM
* and number of bus controllers and number and type of
@@ -556,10 +560,10 @@ psycho_attach(device_t dev)
else
sc->sc_is->is_pmaxaddr =
IOMMU_MAXADDR(PSYCHO_IOMMU_BITS);
- sc->sc_is->is_sb[0] = 0;
- sc->sc_is->is_sb[1] = 0;
+ sc->sc_is->is_sb[0] = sc->sc_is->is_sb[1] = 0;
if (OF_getproplen(node, "no-streaming-cache") < 0)
sc->sc_is->is_sb[0] = sc->sc_pcictl + PCR_STRBUF;
+ sc->sc_is->is_flags |= (rerun != 1) ? IOMMU_RERUN_DISABLE : 0;
psycho_iommu_init(sc, 3, dvmabase);
} else {
/* Just copy IOMMU state, config tag and address. */
@@ -694,12 +698,20 @@ psycho_set_intr(struct psycho_softc *sc, u_int index, bus_addr_t intrmap,
rid = index;
sc->sc_irq_res[index] = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ,
&rid, RF_ACTIVE);
+ if (sc->sc_irq_res[index] == NULL && intrmap >= PSR_POWER_INT_MAP) {
+ /*
+ * These interrupts aren't mandatory and not available
+ * with all controllers (not even Psychos).
+ */
+ return;
+ }
if (sc->sc_irq_res[index] == NULL ||
INTIGN(vec = rman_get_start(sc->sc_irq_res[index])) != sc->sc_ign ||
INTVEC(PSYCHO_READ8(sc, intrmap)) != vec ||
intr_vectors[vec].iv_ic != &psycho_ic ||
- bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC,
- filt, intr, sc, &sc->sc_ihand[index]) != 0)
+ bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
+ INTR_TYPE_MISC | INTR_FAST, filt, intr, sc,
+ &sc->sc_ihand[index]) != 0)
panic("%s: failed to set up interrupt %d", __func__, index);
}
@@ -1065,9 +1077,9 @@ psycho_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
}
static int
-psycho_dmasync(void *arg)
+psycho_dma_sync_stub(void *arg)
{
- struct psycho_dmasync *pds = arg;
+ struct psycho_dma_sync *pds = arg;
(void)PCIB_READ_CONFIG(pds->pds_ppb, pds->pds_bus, pds->pds_slot,
pds->pds_func, PCIR_VENDOR, 2);
@@ -1125,7 +1137,7 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
devclass_t pci_devclass;
device_t cdev, pdev, pcidev;
struct psycho_softc *sc;
- struct psycho_dmasync *pds;
+ struct psycho_dma_sync *pds;
u_long vec;
int error;
@@ -1142,17 +1154,12 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
}
/*
- * The Sabre-APB-combination has a bug where it does not drain
- * DMA write data for devices behind additional PCI-PCI bridges
- * underneath the APB PCI-PCI bridge. The workaround is to do
- * a read on the farest PCI-PCI bridge followed by a read of the
- * PCI DMA write sync register of the Sabre.
- * XXX installing the wrapper for an affected device and the
- * actual workaround in psycho_dmasync() should be moved to
- * psycho(4)-specific bus_dma_tag_create() and bus_dmamap_sync()
- * methods, respectively, once DMA tag creation is newbus'ified,
- * so the workaround isn't only applied for interrupt handlers
- * but also for polling(4) callbacks.
+ * The Sabre-APB-combination does not automatically flush DMA
+ * write data for devices behind additional PCI-PCI bridges
+ * underneath the APB PCI-PCI bridge. The procedure for a
+ * manual flush is to do a PIO read on the far side of the
+ * farthest PCI-PCI bridge followed by a read of the PCI DMA
+ * write sync register of the Sabre.
*/
if (sc->sc_mode == PSYCHO_MODE_SABRE) {
pds = malloc(sizeof(*pds), M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -1191,20 +1198,20 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
pds->pds_func = pci_get_function(pcidev);
if (bootverbose)
device_printf(dev, "installed DMA sync "
- "workaround for device %d.%d on bus %d\n",
+ "wrapper for device %d.%d on bus %d\n",
pds->pds_slot, pds->pds_func,
pds->pds_bus);
if (intr == NULL) {
pds->pds_handler = filt;
error = bus_generic_setup_intr(dev, child,
- ires, flags, psycho_dmasync, intr, pds,
- cookiep);
+ ires, flags, psycho_dma_sync_stub, intr,
+ pds, cookiep);
} else {
pds->pds_handler = (driver_filter_t *)intr;
error = bus_generic_setup_intr(dev, child,
ires, flags, filt,
- (driver_intr_t *)psycho_dmasync, pds,
- cookiep);
+ (driver_intr_t *)psycho_dma_sync_stub,
+ pds, cookiep);
}
} else
error = bus_generic_setup_intr(dev, child, ires,
@@ -1226,7 +1233,7 @@ psycho_teardown_intr(device_t dev, device_t child, struct resource *vec,
void *cookie)
{
struct psycho_softc *sc;
- struct psycho_dmasync *pds;
+ struct psycho_dma_sync *pds;
int error;
sc = device_get_softc(dev);
@@ -1314,8 +1321,8 @@ psycho_activate_resource(device_t bus, device_t child, int type, int rid,
type, rid, r));
if (type == SYS_RES_MEMORY) {
/*
- * Need to memory-map the device space, as some drivers depend
- * on the virtual address being set and useable.
+ * Need to memory-map the device space, as some drivers
+ * depend on the virtual address being set and usable.
*/
error = sparc64_bus_mem_map(rman_get_bustag(r),
rman_get_bushandle(r), rman_get_size(r), 0, 0, &p);
diff --git a/sys/sparc64/pci/psychovar.h b/sys/sparc64/pci/psychovar.h
index ef4286b..04d81ad 100644
--- a/sys/sparc64/pci/psychovar.h
+++ b/sys/sparc64/pci/psychovar.h
@@ -49,8 +49,8 @@ struct psycho_softc {
phandle_t sc_node; /* Firmware node */
u_int sc_mode;
-#define PSYCHO_MODE_SABRE 1
-#define PSYCHO_MODE_PSYCHO 2
+#define PSYCHO_MODE_SABRE 0
+#define PSYCHO_MODE_PSYCHO 1
/* Bus A or B of a psycho pair? */
u_int sc_half;
diff --git a/sys/sparc64/pci/schizo.c b/sys/sparc64/pci/schizo.c
index 2425294..7085171 100644
--- a/sys/sparc64/pci/schizo.c
+++ b/sys/sparc64/pci/schizo.c
@@ -148,7 +148,7 @@ static device_method_t schizo_methods[] = {
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_node, schizo_get_node),
- { 0, 0 }
+ KOBJMETHOD_END
};
static devclass_t schizo_devclass;
@@ -449,14 +449,17 @@ schizo_attach(device_t dev)
tc_init(tc);
}
- /* Set up the IOMMU. Both Schizo and Tomatillo have one per PBM. */
+ /*
+ * Set up the IOMMU. Schizo, Tomatillo and XMITS all have
+ * one per PBM. Schizo and XMITS additionally have a streaming
+ * buffer, in Schizo version < 5 (i.e. revision < 2.3) it's
+ * affected by several errata and basically unusable though.
+ */
sc->sc_is.is_pmaxaddr = IOMMU_MAXADDR(STX_IOMMU_BITS);
- sc->sc_is.is_sb[0] = 0;
- sc->sc_is.is_sb[1] = 0;
-#ifdef notyet
- if (OF_getproplen(node, "no-streaming-cache") < 0)
+ sc->sc_is.is_sb[0] = sc->sc_is.is_sb[1] = 0;
+ if (OF_getproplen(node, "no-streaming-cache") < 0 &&
+ !(sc->sc_mode == SCHIZO_MODE_SCZ && sc->sc_ver < 5))
sc->sc_is.is_sb[0] = STX_PCI_STRBUF;
-#endif
#define TSBCASE(x) \
case (IOTSB_BASESZ << (x)) << (IO_PAGE_SHIFT - IOTTE_SHIFT): \
@@ -1154,8 +1157,9 @@ schizo_setup_intr(device_t dev, device_t child, struct resource *ires,
"controller for vector 0x%lx (%d)\n", vec, error);
return (error);
}
- device_printf(dev, "belatedly registered as interrupt "
- "controller for vector 0x%lx\n", vec);
+ if (bootverbose)
+ device_printf(dev, "belatedly registered as "
+ "interrupt controller for vector 0x%lx\n", vec);
} else {
device_printf(dev,
"invalid interrupt controller for vector 0x%lx\n", vec);
diff --git a/sys/sparc64/sbus/dma_sbus.c b/sys/sparc64/sbus/dma_sbus.c
index 4623995..b4c2e5e 100644
--- a/sys/sparc64/sbus/dma_sbus.c
+++ b/sys/sparc64/sbus/dma_sbus.c
@@ -122,14 +122,15 @@ static device_method_t dma_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, dma_print_child),
DEVMETHOD(bus_probe_nomatch, dma_probe_nomatch),
- DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
- DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_get_resource_list, dma_get_resource_list),
+ DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_get_resource_list, dma_get_resource_list),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, dma_get_devinfo),
@@ -139,7 +140,7 @@ static device_method_t dma_methods[] = {
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
- { 0, 0 }
+ KOBJMETHOD_END
};
static driver_t dma_driver = {
diff --git a/sys/sparc64/sbus/sbus.c b/sys/sparc64/sbus/sbus.c
index d6b8393..dd36f03 100644
--- a/sys/sparc64/sbus/sbus.c
+++ b/sys/sparc64/sbus/sbus.c
@@ -190,7 +190,7 @@ static bus_deactivate_resource_t sbus_deactivate_resource;
static bus_get_dma_tag_t sbus_get_dma_tag;
static ofw_bus_get_devinfo_t sbus_get_devinfo;
-static int sbus_inlist(const char *, const char **);
+static int sbus_inlist(const char *, const char *const *);
static struct sbus_devinfo * sbus_setup_dinfo(device_t, struct sbus_softc *,
phandle_t);
static void sbus_destroy_dinfo(struct sbus_devinfo *);
@@ -217,16 +217,16 @@ static device_method_t sbus_methods[] = {
DEVMETHOD(bus_print_child, sbus_print_child),
DEVMETHOD(bus_probe_nomatch, sbus_probe_nomatch),
DEVMETHOD(bus_read_ivar, sbus_read_ivar),
- DEVMETHOD(bus_setup_intr, sbus_setup_intr),
- DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_alloc_resource, sbus_alloc_resource),
DEVMETHOD(bus_activate_resource, sbus_activate_resource),
DEVMETHOD(bus_deactivate_resource, sbus_deactivate_resource),
DEVMETHOD(bus_release_resource, sbus_release_resource),
- DEVMETHOD(bus_get_resource_list, sbus_get_resource_list),
+ DEVMETHOD(bus_setup_intr, sbus_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
- DEVMETHOD(bus_get_dma_tag, sbus_get_dma_tag),
+ DEVMETHOD(bus_get_resource_list, sbus_get_resource_list),
DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
+ DEVMETHOD(bus_get_dma_tag, sbus_get_dma_tag),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, sbus_get_devinfo),
@@ -236,7 +236,7 @@ static device_method_t sbus_methods[] = {
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
- { 0, 0 }
+ KOBJMETHOD_END
};
static driver_t sbus_driver = {
@@ -266,14 +266,14 @@ struct sbus_icarg {
bus_addr_t sica_clr;
};
-static const char *sbus_order_first[] = {
+static const char *const sbus_order_first[] = {
"auxio",
"dma",
NULL
};
static int
-sbus_inlist(const char *name, const char **list)
+sbus_inlist(const char *name, const char *const *list)
{
int i;
@@ -313,32 +313,33 @@ sbus_attach(device_t dev)
bus_size_t size;
u_long vec;
phandle_t child, node;
- int clock, i, intr, rid;
+ uint32_t prop;
+ int i, j;
sc = device_get_softc(dev);
sc->sc_dev = dev;
node = ofw_bus_get_node(dev);
- rid = 0;
- sc->sc_sysio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ i = 0;
+ sc->sc_sysio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i,
RF_ACTIVE);
if (sc->sc_sysio_res == NULL)
panic("%s: cannot allocate device memory", __func__);
- if (OF_getprop(node, "interrupts", &intr, sizeof(intr)) == -1)
+ if (OF_getprop(node, "interrupts", &prop, sizeof(prop)) == -1)
panic("%s: cannot get IGN", __func__);
- sc->sc_ign = INTIGN(intr);
+ sc->sc_ign = INTIGN(prop);
sc->sc_cbustag = sbus_alloc_bustag(sc);
/*
* Record clock frequency for synchronous SCSI.
* IS THIS THE CORRECT DEFAULT??
*/
- if (OF_getprop(node, "clock-frequency", &clock, sizeof(clock)) == -1)
- clock = 25000000;
- sc->sc_clockfreq = clock;
- clock /= 1000;
- device_printf(dev, "clock %d.%03d MHz\n", clock / 1000, clock % 1000);
+ if (OF_getprop(node, "clock-frequency", &prop, sizeof(prop)) == -1)
+ prop = 25000000;
+ sc->sc_clockfreq = prop;
+ prop /= 1000;
+ device_printf(dev, "clock %d.%03d MHz\n", prop / 1000, prop % 1000);
/*
* Collect address translations from the OBP.
@@ -362,9 +363,9 @@ sbus_attach(device_t dev)
sc->sc_rd[i].rd_slot = range[i].cspace;
sc->sc_rd[i].rd_coffset = range[i].coffset;
sc->sc_rd[i].rd_cend = sc->sc_rd[i].rd_coffset + size;
- rid = resource_list_add_next(rl, SYS_RES_MEMORY, phys,
+ j = resource_list_add_next(rl, SYS_RES_MEMORY, phys,
phys + size - 1, size);
- if ((res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ if ((res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &j,
RF_ACTIVE)) == NULL)
panic("%s: cannot allocate decoded range", __func__);
sc->sc_rd[i].rd_bushandle = rman_get_bushandle(res);
@@ -381,11 +382,12 @@ sbus_attach(device_t dev)
/*
* Get the SBus burst transfer size if burst transfers are supported.
- * XXX: is the default correct?
*/
- if (OF_getprop(node, "burst-sizes", &sc->sc_burst,
+ if (OF_getprop(node, "up-burst-sizes", &sc->sc_burst,
sizeof(sc->sc_burst)) == -1 || sc->sc_burst == 0)
- sc->sc_burst = SBUS_BURST_DEF;
+ sc->sc_burst =
+ (SBUS_BURST64_DEF << SBUS_BURST64_SHIFT) | SBUS_BURST_DEF;
+
/* initalise the IOMMU */
@@ -421,6 +423,7 @@ sbus_attach(device_t dev)
/*
* Hunt through all the interrupt mapping regs and register our
* interrupt controller for the corresponding interrupt vectors.
+ * We do this early in order to be able to catch stray interrupts.
*/
for (i = 0; i <= SBUS_MAX_INO; i++) {
if (sbus_find_intrmap(sc, i, &intrmap, &intrclr) == 0)
@@ -439,31 +442,32 @@ sbus_attach(device_t dev)
(u_long)intrmap, (u_long)SYSIO_READ8(sc, intrmap),
(u_long)intrclr);
#endif
- if (intr_controller_register(INTMAP_VEC(sc->sc_ign, i),
- &sbus_ic, sica) != 0)
- panic("%s: could not register interrupt controller "
- "for INO %d", __func__, i);
+ j = intr_controller_register(INTMAP_VEC(sc->sc_ign, i),
+ &sbus_ic, sica);
+ if (j != 0)
+ device_printf(dev, "could not register interrupt "
+ "controller for INO %d (%d)\n", i, j);
}
/* Enable the over-temperature and power-fail interrupts. */
- rid = 4;
- sc->sc_ot_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ i = 4;
+ sc->sc_ot_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
RF_ACTIVE);
if (sc->sc_ot_ires == NULL ||
INTIGN(vec = rman_get_start(sc->sc_ot_ires)) != sc->sc_ign ||
INTVEC(SYSIO_READ8(sc, SBR_THERM_INT_MAP)) != vec ||
intr_vectors[vec].iv_ic != &sbus_ic ||
- bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC,
+ bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC | INTR_FAST,
NULL, sbus_overtemp, sc, &sc->sc_ot_ihand) != 0)
panic("%s: failed to set up temperature interrupt", __func__);
- rid = 3;
- sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ i = 3;
+ sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &i,
RF_ACTIVE);
if (sc->sc_pf_ires == NULL ||
INTIGN(vec = rman_get_start(sc->sc_pf_ires)) != sc->sc_ign ||
INTVEC(SYSIO_READ8(sc, SBR_POWER_INT_MAP)) != vec ||
intr_vectors[vec].iv_ic != &sbus_ic ||
- bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC,
+ bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC | INTR_FAST,
NULL, sbus_pwrfail, sc, &sc->sc_pf_ihand) != 0)
panic("%s: failed to set up power fail interrupt", __func__);
@@ -849,8 +853,8 @@ sbus_activate_resource(device_t bus, device_t child, int type, int rid,
}
if (type == SYS_RES_MEMORY) {
/*
- * Need to memory-map the device space, as some drivers depend
- * on the virtual address being set and useable.
+ * Need to memory-map the device space, as some drivers
+ * depend on the virtual address being set and usable.
*/
error = sparc64_bus_mem_map(rman_get_bustag(r),
rman_get_bushandle(r), rman_get_size(r), 0, 0, &p);
diff --git a/sys/sparc64/sbus/sbusvar.h b/sys/sparc64/sbus/sbusvar.h
index e4f2895..8d6a54e 100644
--- a/sys/sparc64/sbus/sbusvar.h
+++ b/sys/sparc64/sbus/sbusvar.h
@@ -77,7 +77,7 @@
*/
#ifndef _SPARC64_SBUS_SBUSVAR_H_
-#define _SPARC64_SBUS_SBUSVAR_H_
+#define _SPARC64_SBUS_SBUSVAR_H_
/*
* Macros for probe order
@@ -88,18 +88,24 @@
/*
* PROM-reported DMA burst sizes for the SBus
*/
-#define SBUS_BURST_1 0x1
-#define SBUS_BURST_2 0x2
-#define SBUS_BURST_4 0x4
-#define SBUS_BURST_8 0x8
-#define SBUS_BURST_16 0x10
-#define SBUS_BURST_32 0x20
-#define SBUS_BURST_64 0x40
+#define SBUS_BURST_1 (1 << 0)
+#define SBUS_BURST_2 (1 << 1)
+#define SBUS_BURST_4 (1 << 2)
+#define SBUS_BURST_8 (1 << 3)
+#define SBUS_BURST_16 (1 << 4)
+#define SBUS_BURST_32 (1 << 5)
+#define SBUS_BURST_64 (1 << 6)
+#define SBUS_BURST_MASK ((1 << SBUS_BURST_SIZE) - 1)
+#define SBUS_BURST_SIZE 16
+#define SBUS_BURST64_MASK (SBUS_BURST_MASK << SBUS_BURST64_SHIFT)
+#define SBUS_BURST64_SHIFT 16
/* Used if no burst sizes are specified for the bus. */
#define SBUS_BURST_DEF \
(SBUS_BURST_1 | SBUS_BURST_2 | SBUS_BURST_4 | SBUS_BURST_8 | \
- SBUS_BURST_16)
+ SBUS_BURST_16 | SBUS_BURST_32 | SBUS_BURST_64)
+#define SBUS_BURST64_DEF \
+ (SBUS_BURST_8 | SBUS_BURST_16 | SBUS_BURST_32 | SBUS_BURST_64)
enum sbus_device_ivars {
SBUS_IVAR_BURSTSZ,
@@ -111,7 +117,7 @@ enum sbus_device_ivars {
/*
* Simplified accessors for sbus devices
*/
-#define SBUS_ACCESSOR(var, ivar, type) \
+#define SBUS_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(sbus, var, SBUS, ivar, type)
SBUS_ACCESSOR(burstsz, BURSTSZ, int)
diff --git a/sys/sparc64/sparc64/db_disasm.c b/sys/sparc64/sparc64/db_disasm.c
index 1c244e0..a20219e 100644
--- a/sys/sparc64/sparc64/db_disasm.c
+++ b/sys/sparc64/sparc64/db_disasm.c
@@ -82,14 +82,14 @@ struct sparc_insn {
const char* format;
};
-static const char* regs[] = {
+static const char *const regs[] = {
"g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7",
"o0", "o1", "o2", "o3", "o4", "o5", "sp", "o7",
"l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
"i0", "i1", "i2", "i3", "i4", "i5", "fp", "i7"
};
-static const char* priv_regs[] = {
+static const char *const priv_regs[] = {
"tpc", "tnpc", "tstate", "tt", "tick", "tba", "pstate", "tl",
"pil", "cwp", "cansave", "canrestore", "cleanwin", "otherwin",
"wstate", "fq",
@@ -97,18 +97,18 @@ static const char* priv_regs[] = {
"", "", "", "", "", "", "", "ver"
};
-static const char* state_regs[] = {
+static const char *const state_regs[] = {
"y", "", "ccr", "asi", "tick", "pc", "fprs", "asr",
"", "", "", "", "", "", "", "",
"pcr", "pic", "dcr", "gsr", "set_softint", "clr_softint", "softint",
"tick_cmpr", "sys_tick", "sys_tick_cmpr", "", "", "", "", "", "", ""
};
-static const char* ccodes[] = {
+static const char *const ccodes[] = {
"fcc0", "fcc1", "fcc2", "fcc3", "icc", "", "xcc", ""
};
-static const char* prefetch[] = {
+static const char *const prefetch[] = {
"n_reads", "one_read", "n_writes", "one_write", "page"
};
diff --git a/sys/sparc64/sparc64/eeprom.c b/sys/sparc64/sparc64/eeprom.c
index c707018..223b96c 100644
--- a/sys/sparc64/sparc64/eeprom.c
+++ b/sys/sparc64/sparc64/eeprom.c
@@ -91,7 +91,7 @@ static device_method_t eeprom_methods[] = {
DEVMETHOD(clock_gettime, mk48txx_gettime),
DEVMETHOD(clock_settime, mk48txx_settime),
- { 0, 0 }
+ KOBJMETHOD_END
};
static driver_t eeprom_driver = {
diff --git a/sys/sparc64/sparc64/elf_machdep.c b/sys/sparc64/sparc64/elf_machdep.c
index a956c5c..b0a6998 100644
--- a/sys/sparc64/sparc64/elf_machdep.c
+++ b/sys/sparc64/sparc64/elf_machdep.c
@@ -99,7 +99,8 @@ static Elf64_Brandinfo freebsd_brand_info = {
.interp_path = "/libexec/ld-elf.so.1",
.sysvec = &elf64_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf64_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY,
@@ -114,7 +115,8 @@ static Elf64_Brandinfo freebsd_brand_oinfo = {
.interp_path = "/usr/libexec/ld-elf.so.1",
.sysvec = &elf64_freebsd_sysvec,
.interp_newpath = NULL,
- .flags = BI_CAN_EXEC_DYN,
+ .brand_note = &elf64_freebsd_brandnote,
+ .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE
};
SYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY,
diff --git a/sys/sparc64/sparc64/jbusppm.c b/sys/sparc64/sparc64/jbusppm.c
index 902424c..c08b64d 100644
--- a/sys/sparc64/sparc64/jbusppm.c
+++ b/sys/sparc64/sparc64/jbusppm.c
@@ -78,7 +78,7 @@ static device_method_t jbusppm_methods[] = {
DEVMETHOD(device_probe, jbusppm_probe),
DEVMETHOD(device_attach, jbusppm_attach),
- { NULL, NULL }
+ KOBJMETHOD_END
};
static devclass_t jbusppm_devclass;
diff --git a/sys/sparc64/sparc64/mp_machdep.c b/sys/sparc64/sparc64/mp_machdep.c
index 5470c11..ee4ffe7 100644
--- a/sys/sparc64/sparc64/mp_machdep.c
+++ b/sys/sparc64/sparc64/mp_machdep.c
@@ -413,8 +413,6 @@ cpu_mp_shutdown(void)
break;
}
}
- /* XXX: delay a bit to allow the CPUs to actually enter the PROM. */
- DELAY(100000);
critical_exit();
}
@@ -505,11 +503,7 @@ spitfire_ipi_send(u_int mid, u_long d0, u_long d1, u_long d2)
*/
DELAY(2);
}
- if (
-#ifdef KDB
- kdb_active ||
-#endif
- panicstr != NULL)
+ if (kdb_active != 0 || panicstr != NULL)
printf("%s: couldn't send IPI to module 0x%u\n",
__func__, mid);
else
@@ -581,11 +575,7 @@ cheetah_ipi_selected(u_int cpus, u_long d0, u_long d1, u_long d2)
*/
DELAY(2 * mp_ncpus);
}
- if (
-#ifdef KDB
- kdb_active ||
-#endif
- panicstr != NULL)
+ if (kdb_active != 0 || panicstr != NULL)
printf("%s: couldn't send IPI (cpus=0x%u ids=0x%lu)\n",
__func__, cpus, ids);
else
diff --git a/sys/sparc64/sparc64/nexus.c b/sys/sparc64/sparc64/nexus.c
index 6784cde..58c0805 100644
--- a/sys/sparc64/sparc64/nexus.c
+++ b/sys/sparc64/sparc64/nexus.c
@@ -122,12 +122,12 @@ static device_method_t nexus_methods[] = {
DEVMETHOD(bus_release_resource, nexus_release_resource),
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
-#ifdef SMP
- DEVMETHOD(bus_bind_intr, nexus_bind_intr),
-#endif
DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_get_resource_list, nexus_get_resource_list),
+#ifdef SMP
+ DEVMETHOD(bus_bind_intr, nexus_bind_intr),
+#endif
DEVMETHOD(bus_get_dma_tag, nexus_get_dma_tag),
/* ofw_bus interface */
@@ -138,7 +138,7 @@ static device_method_t nexus_methods[] = {
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
- { 0, 0 }
+ KOBJMETHOD_END
};
static devclass_t nexus_devclass;
diff --git a/sys/sparc64/sparc64/rtc.c b/sys/sparc64/sparc64/rtc.c
index fe7f17e..5bd196b 100644
--- a/sys/sparc64/sparc64/rtc.c
+++ b/sys/sparc64/sparc64/rtc.c
@@ -89,7 +89,7 @@ static device_method_t rtc_ebus_methods[] = {
DEVMETHOD(clock_gettime, mc146818_gettime),
DEVMETHOD(clock_settime, mc146818_settime),
- { 0, 0 }
+ KOBJMETHOD_END
};
static driver_t rtc_ebus_driver = {
diff --git a/sys/sparc64/sparc64/sc_machdep.c b/sys/sparc64/sparc64/sc_machdep.c
index f56f669..107ebd2 100644
--- a/sys/sparc64/sparc64/sc_machdep.c
+++ b/sys/sparc64/sparc64/sc_machdep.c
@@ -57,7 +57,7 @@ static device_method_t sc_methods[] = {
DEVMETHOD(device_probe, sc_probe),
DEVMETHOD(device_attach, sc_attach),
- { 0, 0 }
+ KOBJMETHOD_END
};
static driver_t sc_driver = {
diff --git a/sys/sparc64/sparc64/schppm.c b/sys/sparc64/sparc64/schppm.c
index 7431062..ac0ff75 100644
--- a/sys/sparc64/sparc64/schppm.c
+++ b/sys/sparc64/sparc64/schppm.c
@@ -73,7 +73,7 @@ static device_method_t schppm_methods[] = {
DEVMETHOD(device_probe, schppm_probe),
DEVMETHOD(device_attach, schppm_attach),
- { NULL, NULL }
+ KOBJMETHOD_END
};
static devclass_t schppm_devclass;
diff --git a/sys/sparc64/sparc64/trap.c b/sys/sparc64/sparc64/trap.c
index c10dbc4..702e4f1 100644
--- a/sys/sparc64/sparc64/trap.c
+++ b/sys/sparc64/sparc64/trap.c
@@ -71,7 +71,6 @@ __FBSDID("$FreeBSD$");
#include <security/audit/audit.h>
#include <dev/ofw/openfirm.h>
-#include <machine/ofw_machdep.h>
#include <vm/vm.h>
#include <vm/pmap.h>
@@ -84,7 +83,7 @@ __FBSDID("$FreeBSD$");
#include <machine/cpu.h>
#include <machine/frame.h>
#include <machine/intr_machdep.h>
-#include <machine/pcb.h>
+#include <machine/ofw_machdep.h>
#include <machine/smp.h>
#include <machine/trap.h>
#include <machine/tstate.h>
@@ -114,7 +113,7 @@ extern char fas_nofault_end[];
extern char *syscallnames[];
-const char *trap_msg[] = {
+const char *const trap_msg[] = {
"reserved",
"instruction access exception",
"instruction access error",
@@ -329,15 +328,12 @@ trap(struct trapframe *tf)
KASSERT((tf->tf_type & T_KERNEL) != 0,
("trap: kernel trap isn't"));
-#ifdef KDB
if (kdb_active) {
kdb_reenter();
return;
}
-#endif
switch (tf->tf_type & ~T_KERNEL) {
-#ifdef KDB
case T_BREAKPOINT:
case T_KSTACK_FAULT:
error = (kdb_trap(tf->tf_type, 0, tf) == 0);
@@ -349,7 +345,6 @@ trap(struct trapframe *tf)
error = db_watch_trap(tf);
break;
#endif
-#endif
case T_DATA_MISS:
case T_DATA_PROTECTION:
case T_INSTRUCTION_MISS:
@@ -409,7 +404,6 @@ static int
trap_pfault(struct thread *td, struct trapframe *tf)
{
struct vmspace *vm;
- struct pcb *pcb;
struct proc *p;
vm_offset_t va;
vm_prot_t prot;
@@ -429,7 +423,6 @@ trap_pfault(struct thread *td, struct trapframe *tf)
rv = KERN_SUCCESS;
ctx = TLB_TAR_CTX(tf->tf_tar);
- pcb = td->td_pcb;
type = tf->tf_type & ~T_KERNEL;
va = TLB_TAR_VA(tf->tf_tar);
@@ -559,11 +552,6 @@ syscall(struct trapframe *tf)
PCPU_INC(cnt.v_syscall);
- narg = 0;
- error = 0;
- reg = 0;
- regcnt = REG_MAXARGS;
-
td->td_pticks = 0;
td->td_frame = tf;
if (td->td_ucred != p->p_ucred)
@@ -577,6 +565,8 @@ syscall(struct trapframe *tf)
tpc = tf->tf_tpc;
TF_DONE(tf);
+ reg = 0;
+ regcnt = REG_MAXARGS;
if (p->p_sysent->sv_prepsyscall) {
/*
* The prep code is MP aware.
diff --git a/sys/sparc64/sparc64/upa.c b/sys/sparc64/sparc64/upa.c
index 06ae244..7e81c89 100644
--- a/sys/sparc64/sparc64/upa.c
+++ b/sys/sparc64/sparc64/upa.c
@@ -135,6 +135,7 @@ static device_method_t upa_methods[] = {
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
DEVMETHOD(bus_get_resource_list, upa_get_resource_list),
+ DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
/* ofw_bus interface */
DEVMETHOD(ofw_bus_get_devinfo, upa_get_devinfo),
@@ -144,7 +145,7 @@ static device_method_t upa_methods[] = {
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
- { NULL, NULL }
+ KOBJMETHOD_END
};
static devclass_t upa_devclass;
@@ -241,7 +242,7 @@ upa_attach(device_t dev)
"pci108e,8001") == 0 &&
((bus_get_resource_start(children[j],
SYS_RES_MEMORY, 0) >> 20) & 1) == 1) {
- schizo = children[j];
+ schizo = children[j];
break;
}
}
@@ -287,9 +288,10 @@ upa_attach(device_t dev)
goto fail;
}
- /*
+ /*
* Hunt through all the interrupt mapping regs and register our
* interrupt controller for the corresponding interrupt vectors.
+ * We do this early in order to be able to catch stray interrupts.
*/
for (i = UPA_INO_BASE; i <= UPA_INO_MAX; i++) {
imr = 0;
@@ -312,10 +314,11 @@ upa_attach(device_t dev)
device_printf(dev, "intr map (INO %d) IMR%d: %#lx\n",
i, imr, (u_long)UPA_READ(sc, imr, 0x0));
#endif
- if (intr_controller_register(INTMAP_VEC(sc->sc_ign, i),
- &upa_ic, uica) != 0)
- panic("%s: could not register interrupt controller "
- "for INO %d", __func__, i);
+ j = intr_controller_register(INTMAP_VEC(sc->sc_ign, i),
+ &upa_ic, uica);
+ if (j != 0)
+ device_printf(dev, "could not register interrupt "
+ "controller for INO %d (%d)\n", i, j);
}
/* Make sure the power level is appropriate for normal operation. */
@@ -345,13 +348,13 @@ upa_attach(device_t dev)
device_printf(dev,
"could not determine upa-portid of child 0x%lx\n",
(unsigned long)child);
- continue;
+ continue;
}
if (portid > 1) {
device_printf(dev,
"upa-portid %d of child 0x%lx invalid\n", portid,
(unsigned long)child);
- continue;
+ continue;
}
if ((udi = upa_setup_dinfo(dev, sc, child, portid)) == NULL)
continue;
@@ -493,12 +496,12 @@ upa_setup_intr(device_t dev, device_t child, struct resource *ires, int flags,
/*
* Make sure the vector is fully specified and we registered
* our interrupt controller for it.
- */
+ */
vec = rman_get_start(ires);
if (INTIGN(vec) != sc->sc_ign || intr_vectors[vec].iv_ic != &upa_ic) {
device_printf(dev, "invalid interrupt vector 0x%lx\n", vec);
- return (EINVAL);
- }
+ return (EINVAL);
+ }
return (bus_generic_setup_intr(dev, child, ires, flags, filt, func,
arg, cookiep));
}
diff --git a/sys/sun4v/conf/GENERIC b/sys/sun4v/conf/GENERIC
index fac7e04..2291087 100644
--- a/sys/sun4v/conf/GENERIC
+++ b/sys/sun4v/conf/GENERIC
@@ -191,7 +191,6 @@ device ulpt # Printer
#device umass # Disks/Mass storage - Requires scbus and da
device ums # Mouse
#device urio # Diamond Rio 500 MP3 player
-#device uscanner # Scanners
# USB Ethernet, requires mii
#device aue # ADMtek USB Ethernet
#device axe # ASIX Electronics USB Ethernet
diff --git a/sys/sun4v/include/elf.h b/sys/sun4v/include/elf.h
index 108ade1..c0fcbee 100644
--- a/sys/sun4v/include/elf.h
+++ b/sys/sun4v/include/elf.h
@@ -78,16 +78,14 @@ __ElfType(Auxinfo);
#define AT_BASE 7 /* Interpreter's base address. */
#define AT_FLAGS 8 /* Flags (unused). */
#define AT_ENTRY 9 /* Where interpreter should transfer control. */
-/*
- * The following non-standard values are used in Linux ELF binaries.
- */
#define AT_NOTELF 10 /* Program is not ELF ?? */
#define AT_UID 11 /* Real uid. */
#define AT_EUID 12 /* Effective uid. */
#define AT_GID 13 /* Real gid. */
#define AT_EGID 14 /* Effective gid. */
+#define AT_EXECPATH 15 /* Path to the executable. */
-#define AT_COUNT 15 /* Count of defined aux entry types. */
+#define AT_COUNT 16 /* Count of defined aux entry types. */
/* Define "machine" characteristics */
#if __ELF_WORD_SIZE == 32
diff --git a/sys/sun4v/include/trap.h b/sys/sun4v/include/trap.h
index 42efb8b..8922a35 100644
--- a/sys/sun4v/include/trap.h
+++ b/sys/sun4v/include/trap.h
@@ -144,7 +144,7 @@
#ifndef LOCORE
-extern const char *trap_msg[];
+extern const char *const trap_msg[];
extern void set_mmfsa_traptable(void *, uint64_t);
extern void trap_init(void);
#endif
diff --git a/sys/sun4v/sun4v/trap.c b/sys/sun4v/sun4v/trap.c
index bac4f55..ffa0e8c 100644
--- a/sys/sun4v/sun4v/trap.c
+++ b/sys/sun4v/sun4v/trap.c
@@ -81,7 +81,6 @@
#include <machine/cpu.h>
#include <machine/frame.h>
#include <machine/intr_machdep.h>
-#include <machine/pcb.h>
#include <machine/smp.h>
#include <machine/trap.h>
#include <machine/tstate.h>
@@ -119,7 +118,7 @@ extern char fas_nofault_end[];
extern char *syscallnames[];
-const char *trap_msg[] = {
+const char *const trap_msg[] = {
"reserved",
"instruction access exception",
"instruction access error",
@@ -390,21 +389,17 @@ trap(struct trapframe *tf, int64_t type, uint64_t data)
("trap: kernel trap isn't - trap: %ld:%s: 0x%lx at 0x%lx on cpu=%d\n",
trapno, trap_msg[trapno], data, tf->tf_tpc, curcpu));
-#ifdef KDB
if (kdb_active) {
kdb_reenter();
return;
}
-#endif
switch (trapno) {
-#ifdef KDB
case T_BREAKPOINT:
case T_KSTACK_FAULT:
error = (kdb_trap(trapno, 0, tf) == 0);
TF_DONE(tf);
break;
-#endif
case T_DATA_MISS:
case T_DATA_PROTECTION:
case T_INSTRUCTION_MISS:
@@ -460,7 +455,6 @@ static int
trap_pfault(struct thread *td, struct trapframe *tf, int64_t type, uint64_t data)
{
struct vmspace *vm;
- struct pcb *pcb;
struct proc *p;
vm_offset_t va;
vm_prot_t prot;
@@ -475,7 +469,6 @@ trap_pfault(struct thread *td, struct trapframe *tf, int64_t type, uint64_t data
rv = KERN_SUCCESS;
ctx = TLB_TAR_CTX(data);
- pcb = td->td_pcb;
type = type & ~T_KERNEL;
va = TLB_TAR_VA(data);
@@ -603,11 +596,6 @@ syscall(struct trapframe *tf)
PCPU_INC(cnt.v_syscall);
- narg = 0;
- error = 0;
- reg = 0;
- regcnt = REG_MAXARGS;
-
td->td_pticks = 0;
td->td_frame = tf;
if (td->td_ucred != p->p_ucred)
@@ -621,6 +609,8 @@ syscall(struct trapframe *tf)
tpc = tf->tf_tpc;
TF_DONE(tf);
+ reg = 0;
+ regcnt = REG_MAXARGS;
if (p->p_sysent->sv_prepsyscall) {
/*
* The prep code is MP aware.
diff --git a/sys/sys/_pthreadtypes.h b/sys/sys/_pthreadtypes.h
index 6337540..76049ee 100644
--- a/sys/sys/_pthreadtypes.h
+++ b/sys/sys/_pthreadtypes.h
@@ -61,7 +61,10 @@ struct pthread_spinlock;
* or assignment operators for the types pthread_attr_t, pthread_cond_t,
* pthread_condattr_t, pthread_mutex_t, pthread_mutexattr_t.
*/
+#ifndef _PTHREAD_T_DECLARED
typedef struct pthread *pthread_t;
+#define _PTHREAD_T_DECLARED
+#endif
typedef struct pthread_attr *pthread_attr_t;
typedef struct pthread_mutex *pthread_mutex_t;
typedef struct pthread_mutex_attr *pthread_mutexattr_t;
diff --git a/sys/sys/aio.h b/sys/sys/aio.h
index a474b8d..5a8779b 100644
--- a/sys/sys/aio.h
+++ b/sys/sys/aio.h
@@ -19,7 +19,6 @@
#ifndef _SYS_AIO_H_
#define _SYS_AIO_H_
-#include <sys/time.h>
#include <sys/types.h>
#include <sys/signal.h>
@@ -79,6 +78,8 @@ typedef struct aiocb {
#ifndef _KERNEL
+struct timespec;
+
__BEGIN_DECLS
/*
* Asynchronously read from a file
@@ -123,7 +124,9 @@ int aio_cancel(int, struct aiocb *);
*/
int aio_suspend(const struct aiocb * const[], int, const struct timespec *);
+#ifdef __BSD_VISIBLE
int aio_waitcomplete(struct aiocb **, struct timespec *);
+#endif
int aio_fsync(int op, struct aiocb *aiocbp);
__END_DECLS
diff --git a/sys/sys/buf.h b/sys/sys/buf.h
index 7c3dd4e..7ca6ffa 100644
--- a/sys/sys/buf.h
+++ b/sys/sys/buf.h
@@ -443,6 +443,7 @@ buf_countdeps(struct buf *bp, int i)
*/
#define GB_LOCK_NOWAIT 0x0001 /* Fail if we block on a buf lock. */
#define GB_NOCREAT 0x0002 /* Don't create a buf if not found. */
+#define GB_NOWAIT_BD 0x0004 /* Do not wait for bufdaemon */
#ifdef _KERNEL
extern int nbuf; /* The number of buffer headers */
@@ -487,7 +488,7 @@ struct buf * getpbuf(int *);
struct buf *incore(struct bufobj *, daddr_t);
struct buf *gbincore(struct bufobj *, daddr_t);
struct buf *getblk(struct vnode *, daddr_t, int, int, int, int);
-struct buf *geteblk(int);
+struct buf *geteblk(int, int);
int bufwait(struct buf *);
int bufwrite(struct buf *);
void bufdone(struct buf *);
diff --git a/sys/sys/dtrace_bsd.h b/sys/sys/dtrace_bsd.h
index e0adbe6..f323284 100644
--- a/sys/sys/dtrace_bsd.h
+++ b/sys/sys/dtrace_bsd.h
@@ -32,8 +32,11 @@
#define _SYS_DTRACE_BSD_H
/* Forward definitions: */
+struct mbuf;
struct trapframe;
struct thread;
+struct vattr;
+struct vnode;
/*
* Cyclic clock function type definition used to hook the cyclic
@@ -93,6 +96,55 @@ typedef void (*dtrace_malloc_probe_func_t)(u_int32_t, uintptr_t arg0,
extern dtrace_malloc_probe_func_t dtrace_malloc_probe;
+/* dtnfsclient NFSv3 access cache provider hooks. */
+typedef void (*dtrace_nfsclient_accesscache_flush_probe_func_t)(uint32_t,
+ struct vnode *);
+extern dtrace_nfsclient_accesscache_flush_probe_func_t
+ dtrace_nfsclient_accesscache_flush_done_probe;
+
+typedef void (*dtrace_nfsclient_accesscache_get_probe_func_t)(uint32_t,
+ struct vnode *, uid_t, uint32_t);
+extern dtrace_nfsclient_accesscache_get_probe_func_t
+ dtrace_nfsclient_accesscache_get_hit_probe,
+ dtrace_nfsclient_accesscache_get_miss_probe;
+
+typedef void (*dtrace_nfsclient_accesscache_load_probe_func_t)(uint32_t,
+ struct vnode *, uid_t, uint32_t, int);
+extern dtrace_nfsclient_accesscache_load_probe_func_t
+ dtrace_nfsclient_accesscache_load_done_probe;
+
+/* dtnfsclient NFSv[23] attribute cache provider hooks. */
+typedef void (*dtrace_nfsclient_attrcache_flush_probe_func_t)(uint32_t,
+ struct vnode *);
+extern dtrace_nfsclient_attrcache_flush_probe_func_t
+ dtrace_nfsclient_attrcache_flush_done_probe;
+
+typedef void (*dtrace_nfsclient_attrcache_get_hit_probe_func_t)(uint32_t,
+ struct vnode *, struct vattr *);
+extern dtrace_nfsclient_attrcache_get_hit_probe_func_t
+ dtrace_nfsclient_attrcache_get_hit_probe;
+
+typedef void (*dtrace_nfsclient_attrcache_get_miss_probe_func_t)(uint32_t,
+ struct vnode *);
+extern dtrace_nfsclient_attrcache_get_miss_probe_func_t
+ dtrace_nfsclient_attrcache_get_miss_probe;
+
+typedef void (*dtrace_nfsclient_attrcache_load_probe_func_t)(uint32_t,
+ struct vnode *, struct vattr *, int);
+extern dtrace_nfsclient_attrcache_load_probe_func_t
+ dtrace_nfsclient_attrcache_load_done_probe;
+
+/* dtnfsclient NFSv[23] RPC provider hooks. */
+typedef void (*dtrace_nfsclient_nfs23_start_probe_func_t)(uint32_t,
+ struct vnode *, struct mbuf *, struct ucred *, int);
+extern dtrace_nfsclient_nfs23_start_probe_func_t
+ dtrace_nfsclient_nfs23_start_probe;
+
+typedef void (*dtrace_nfsclient_nfs23_done_probe_func_t)(uint32_t,
+ struct vnode *, struct mbuf *, struct ucred *, int, int);
+extern dtrace_nfsclient_nfs23_done_probe_func_t
+ dtrace_nfsclient_nfs23_done_probe;
+
/*
* Functions which allow the dtrace module to check that the kernel
* hooks have been compiled with sufficient space for it's private
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
index 34c0b3a..f642c71 100644
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -427,6 +427,7 @@ typedef struct {
* built, these entries will need to be adjusted.
*/
#define DT_ADDRRNGLO 0x6ffffe00
+#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */
#define DT_CONFIG 0x6ffffefa /* configuration information */
#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */
#define DT_AUDIT 0x6ffffefc /* object auditing */
@@ -466,6 +467,12 @@ typedef struct {
executable contains code using a static
thread-local storage scheme. */
+/* Values for DT_FLAGS_1 */
+#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */
+#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */
+#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */
+#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */
+
/* Values for n_type. Used in core files. */
#define NT_PRSTATUS 1 /* Process status. */
#define NT_FPREGSET 2 /* Floating point registers. */
diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h
index 011a7ae..e6acc00 100644
--- a/sys/sys/imgact.h
+++ b/sys/sys/imgact.h
@@ -66,6 +66,9 @@ struct image_params {
size_t auxarg_size;
struct image_args *args; /* system call arguments */
struct sysentvec *sysent; /* system entry vector */
+ char *execpath;
+ unsigned long execpathp;
+ char *freepath;
};
#ifdef _KERNEL
diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
index deb5b10..60979d9 100644
--- a/sys/sys/imgact_elf.h
+++ b/sys/sys/imgact_elf.h
@@ -55,6 +55,13 @@ typedef struct {
} __ElfN(Auxargs);
typedef struct {
+ Elf_Note hdr;
+ const char * vendor;
+ int flags;
+#define BN_CAN_FETCH_OSREL 0x0001
+} Elf_Brandnote;
+
+typedef struct {
int brand;
int machine;
const char *compat_3_brand; /* pre Binutils 2.10 method (FBSD 3) */
@@ -63,7 +70,9 @@ typedef struct {
struct sysentvec *sysvec;
const char *interp_newpath;
int flags;
+ Elf_Brandnote *brand_note;
#define BI_CAN_EXEC_DYN 0x0001
+#define BI_BRAND_NOTE 0x0002
} __ElfN(Brandinfo);
__ElfType(Auxargs);
@@ -81,7 +90,7 @@ int __elfN(coredump)(struct thread *, struct vnode *, off_t);
void __elfN(dump_thread)(struct thread *, void *, size_t *);
extern int __elfN(fallback_brand);
-
+extern Elf_Brandnote __elfN(freebsd_brandnote);
#endif /* _KERNEL */
#endif /* !_SYS_IMGACT_ELF_H_ */
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
index 4212603..4560456 100644
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -7,7 +7,6 @@
* ----------------------------------------------------------------------------
*
* $FreeBSD$
- *
*/
#ifndef _SYS_JAIL_H_
@@ -32,7 +31,7 @@ struct jail {
struct in_addr *ip4;
struct in6_addr *ip6;
};
-#define JAIL_API_VERSION 2
+#define JAIL_API_VERSION 2
/*
* For all xprison structs, always keep the pr_version an int and
@@ -54,8 +53,8 @@ struct xprison {
int pr_state;
cpusetid_t pr_cpusetid;
char pr_path[MAXPATHLEN];
- char pr_host[MAXHOSTNAMELEN];
- char pr_name[MAXHOSTNAMELEN];
+ char pr_host[MAXHOSTNAMELEN];
+ char pr_name[MAXHOSTNAMELEN];
uint32_t pr_ip4s;
uint32_t pr_ip6s;
#if 0
@@ -128,8 +127,8 @@ struct prison {
char pr_path[MAXPATHLEN]; /* (c) chroot path */
struct cpuset *pr_cpuset; /* (p) cpuset */
struct vnode *pr_root; /* (c) vnode to rdir */
- char pr_host[MAXHOSTNAMELEN]; /* (p) jail hostname */
- char pr_name[MAXHOSTNAMELEN]; /* (c) admin jail name */
+ char pr_host[MAXHOSTNAMELEN]; /* (p) jail hostname */
+ char pr_name[MAXHOSTNAMELEN]; /* (c) admin jail name */
void *pr_linux; /* (p) linux abi */
int pr_securelevel; /* (p) securelevel */
struct task pr_task; /* (d) destroy task */
diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h
index 16fab6c..fa397c4 100644
--- a/sys/sys/kernel.h
+++ b/sys/sys/kernel.h
@@ -163,6 +163,7 @@ enum sysinit_sub_id {
SI_SUB_SWAP = 0xc000000, /* swap */
SI_SUB_INTRINSIC_POST = 0xd000000, /* proc 0 cleanup*/
SI_SUB_SYSCALLS = 0xd800000, /* register system calls */
+ SI_SUB_VIMAGE_DONE = 0xdc00000, /* vnet registration complete */
SI_SUB_KTHREAD_INIT = 0xe000000, /* init process*/
SI_SUB_KTHREAD_PAGE = 0xe400000, /* pageout daemon*/
SI_SUB_KTHREAD_VM = 0xe800000, /* vm daemon*/
diff --git a/sys/sys/kerneldump.h b/sys/sys/kerneldump.h
index 3f3eacd..e3421de 100644
--- a/sys/sys/kerneldump.h
+++ b/sys/sys/kerneldump.h
@@ -67,12 +67,13 @@ struct kerneldumpheader {
#define KERNELDUMPVERSION 1
uint32_t architectureversion;
#define KERNELDUMP_ALPHA_VERSION 1
-#define KERNELDUMP_I386_VERSION 2
-#define KERNELDUMP_IA64_VERSION 1
-#define KERNELDUMP_SPARC64_VERSION 1
#define KERNELDUMP_AMD64_VERSION 2
-#define KERNELDUMP_ARM_VERSION 1
-#define KERNELDUMP_TEXT_VERSION 1
+#define KERNELDUMP_ARM_VERSION 1
+#define KERNELDUMP_I386_VERSION 2
+#define KERNELDUMP_IA64_VERSION 1
+#define KERNELDUMP_POWERPC_VERSION 1
+#define KERNELDUMP_SPARC64_VERSION 1
+#define KERNELDUMP_TEXT_VERSION 1
uint64_t dumplength; /* excl headers */
uint64_t dumptime;
uint32_t blocksize;
diff --git a/sys/sys/lock_profile.h b/sys/sys/lock_profile.h
index 2d9df3b..7b36ed5 100644
--- a/sys/sys/lock_profile.h
+++ b/sys/sys/lock_profile.h
@@ -43,11 +43,13 @@ LIST_HEAD(lpohead, lock_profile_object);
u_int64_t nanoseconds(void);
#endif
-extern int lock_prof_enable;
+extern volatile int lock_prof_enable;
void lock_profile_obtain_lock_success(struct lock_object *lo, int contested,
uint64_t waittime, const char *file, int line);
void lock_profile_release_lock(struct lock_object *lo);
+void lock_profile_thread_exit(struct thread *td);
+
static inline void
lock_profile_obtain_lock_failed(struct lock_object *lo, int *contested,
@@ -61,21 +63,10 @@ lock_profile_obtain_lock_failed(struct lock_object *lo, int *contested,
#else /* !LOCK_PROFILING */
-static inline void
-lock_profile_release_lock(struct lock_object *lo)
-{
-}
-
-static inline void
-lock_profile_obtain_lock_failed(struct lock_object *lo, int *contested, uint64_t *waittime)
-{
-}
-
-static inline void
-lock_profile_obtain_lock_success(struct lock_object *lo, int contested, uint64_t waittime,
- const char *file, int line)
-{
-}
+#define lock_profile_release_lock(lo)
+#define lock_profile_obtain_lock_failed(lo, contested, waittime)
+#define lock_profile_obtain_lock_success(lo, contested, waittime, file, line)
+#define lock_profile_thread_exit(td)
#endif /* !LOCK_PROFILING */
diff --git a/sys/sys/mbuf.h b/sys/sys/mbuf.h
index 05b28de2..e7f0b7e 100644
--- a/sys/sys/mbuf.h
+++ b/sys/sys/mbuf.h
@@ -199,6 +199,7 @@ struct mbuf {
#define M_PROTO6 0x00080000 /* protocol-specific */
#define M_PROTO7 0x00100000 /* protocol-specific */
#define M_PROTO8 0x00200000 /* protocol-specific */
+#define M_FLOWID 0x00400000 /* flowid is valid */
/*
* For RELENG_{6,7} steal these flags for limited multiple routing table
* support. In RELENG_8 and beyond, use just one flag and a tag.
diff --git a/sys/sys/memrange.h b/sys/sys/memrange.h
index ace778d..c90104f 100644
--- a/sys/sys/memrange.h
+++ b/sys/sys/memrange.h
@@ -52,6 +52,7 @@ struct mem_range_ops
void (*init)(struct mem_range_softc *sc);
int (*set)(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg);
void (*initAP)(struct mem_range_softc *sc);
+ void (*reinit)(struct mem_range_softc *sc);
};
struct mem_range_softc
@@ -68,4 +69,3 @@ extern int mem_range_attr_get(struct mem_range_desc *mrd, int *arg);
extern int mem_range_attr_set(struct mem_range_desc *mrd, int *arg);
#endif
-
diff --git a/sys/sys/param.h b/sys/sys/param.h
index e8b26c7..f02853c 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -57,7 +57,7 @@
* is created, otherwise 1.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 800070 /* Master, propagated to newvers */
+#define __FreeBSD_version 800077 /* Master, propagated to newvers */
#ifndef LOCORE
#include <sys/types.h>
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index b2bfadd..b2cb011 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -345,7 +345,7 @@ do { \
#define TDP_OLDMASK 0x00000001 /* Need to restore mask after suspend. */
#define TDP_INKTR 0x00000002 /* Thread is currently in KTR code. */
#define TDP_INKTRACE 0x00000004 /* Thread is currently in KTRACE code. */
-#define TDP_UNUSED8 0x00000008 /* available */
+#define TDP_BUFNEED 0x00000008 /* Do not recurse into the buf flush */
#define TDP_COWINPROGRESS 0x00000010 /* Snapshot copy-on-write in progress. */
#define TDP_ALTSTACK 0x00000020 /* Have alternate signal stack. */
#define TDP_DEADLKTREAT 0x00000040 /* Lock aquisition - deadlock treatment. */
diff --git a/sys/sys/sem.h b/sys/sys/sem.h
index ecd78a3..d8d6e92 100644
--- a/sys/sys/sem.h
+++ b/sys/sys/sem.h
@@ -117,7 +117,9 @@ void semexit(struct proc *p);
#else /* ! _KERNEL */
__BEGIN_DECLS
+#if __BSD_VISIBLE
int semsys(int, ...);
+#endif
int semctl(int, int, int, ...);
int semget(key_t, int, int);
int semop(int, struct sembuf *, size_t);
diff --git a/sys/sys/shm.h b/sys/sys/shm.h
index c4b1369..e6f2f76 100644
--- a/sys/sys/shm.h
+++ b/sys/sys/shm.h
@@ -138,7 +138,9 @@ typedef __size_t size_t;
#endif
__BEGIN_DECLS
+#ifdef __BSD_VISIBLE
int shmsys(int, ...);
+#endif
void *shmat(int, const void *, int);
int shmget(key_t, size_t, int);
int shmctl(int, int, struct shmid_ds *);
diff --git a/sys/sys/smp.h b/sys/sys/smp.h
index 8306d52..500516f 100644
--- a/sys/sys/smp.h
+++ b/sys/sys/smp.h
@@ -122,6 +122,9 @@ void forward_signal(struct thread *);
void forward_roundrobin(void);
int restart_cpus(cpumask_t);
int stop_cpus(cpumask_t);
+#if defined(__amd64__)
+int suspend_cpus(cpumask_t);
+#endif
void smp_rendezvous_action(void);
extern struct mtx smp_ipi_mtx;
diff --git a/sys/sys/stat.h b/sys/sys/stat.h
index b310641..856d674 100644
--- a/sys/sys/stat.h
+++ b/sys/sys/stat.h
@@ -312,8 +312,13 @@ int chflags(const char *, unsigned long);
int chmod(const char *, mode_t);
#if __BSD_VISIBLE
int fchflags(int, unsigned long);
+#endif
+#if __POSIX_VISIBLE >= 200112
int fchmod(int, mode_t);
#endif
+#if __POSIX_VISIBLE >= 200809
+int fchmodat(int, const char *, mode_t, int);
+#endif
int fstat(int, struct stat *);
#if __BSD_VISIBLE
int lchflags(const char *, int);
@@ -334,6 +339,8 @@ mode_t umask(mode_t);
int fstatat(int, const char *, struct stat *, int);
int mkdirat(int, const char *, mode_t);
int mkfifoat(int, const char *, mode_t);
+#endif
+#if __BSD_VISIBLE || __XSI_VISIBLE >= 700
int mknodat(int, const char *, mode_t, dev_t);
#endif
__END_DECLS
diff --git a/sys/sys/syslog.h b/sys/sys/syslog.h
index fe2d0fe..6f12831 100644
--- a/sys/sys/syslog.h
+++ b/sys/sys/syslog.h
@@ -193,7 +193,9 @@ void closelog(void);
void openlog(const char *, int, int);
int setlogmask(int);
void syslog(int, const char *, ...) __printflike(2, 3);
+#if __BSD_VISIBLE
void vsyslog(int, const char *, __va_list) __printflike(2, 0);
+#endif
__END_DECLS
#endif /* !_KERNEL */
diff --git a/sys/sys/termios.h b/sys/sys/termios.h
index bc071fb..192c3f2 100644
--- a/sys/sys/termios.h
+++ b/sys/sys/termios.h
@@ -273,10 +273,10 @@ int tcsendbreak(int, int);
pid_t tcgetsid(int);
#endif
-#ifndef _POSIX_SOURCE
+#if __BSD_VISIBLE
void cfmakeraw(struct termios *);
int cfsetspeed(struct termios *, speed_t);
-#endif /* !_POSIX_SOURCE */
+#endif
__END_DECLS
#endif /* !_KERNEL */
diff --git a/sys/sys/time.h b/sys/sys/time.h
index 7512840..0185c31 100644
--- a/sys/sys/time.h
+++ b/sys/sys/time.h
@@ -316,17 +316,25 @@ int tvtohz(struct timeval *tv);
#include <time.h>
#include <sys/cdefs.h>
+#include <sys/select.h>
__BEGIN_DECLS
+int setitimer(int, const struct itimerval *, struct itimerval *);
+int utimes(const char *, const struct timeval *);
+
+#if __BSD_VISIBLE
int adjtime(const struct timeval *, struct timeval *);
int futimes(int, const struct timeval *);
-int getitimer(int, struct itimerval *);
-int gettimeofday(struct timeval *, struct timezone *);
+int futimesat(int, const char *, const struct timeval [2]);
int lutimes(const char *, const struct timeval *);
-int setitimer(int, const struct itimerval *, struct itimerval *);
int settimeofday(const struct timeval *, const struct timezone *);
-int utimes(const char *, const struct timeval *);
-int futimesat(int, const char *, const struct timeval [2]);
+#endif
+
+#if __XSI_VISIBLE
+int getitimer(int, struct itimerval *);
+int gettimeofday(struct timeval *, struct timezone *);
+#endif
+
__END_DECLS
#endif /* !_KERNEL */
diff --git a/sys/sys/uio.h b/sys/sys/uio.h
index c46cc6f..871f93a 100644
--- a/sys/sys/uio.h
+++ b/sys/sys/uio.h
@@ -106,8 +106,10 @@ int uiomoveco(void *cp, int n, struct uio *uio, int disposable);
__BEGIN_DECLS
ssize_t readv(int, const struct iovec *, int);
ssize_t writev(int, const struct iovec *, int);
+#if __BSD_VISIBLE
ssize_t preadv(int, const struct iovec *, int, off_t);
ssize_t pwritev(int, const struct iovec *, int, off_t);
+#endif
__END_DECLS
#endif /* _KERNEL */
diff --git a/sys/sys/vimage.h b/sys/sys/vimage.h
index ea51e49..7781b47 100644
--- a/sys/sys/vimage.h
+++ b/sys/sys/vimage.h
@@ -35,6 +35,15 @@
#include <sys/queue.h>
+#if defined(VIMAGE) && defined(VIMAGE_GLOBALS)
+#error "You cannot have both option VIMAGE and option VIMAGE_GLOBALS!"
+#endif
+
+typedef int vnet_attach_fn(const void *);
+typedef int vnet_detach_fn(const void *);
+
+#ifndef VIMAGE_GLOBALS
+
struct kld_sym_lookup;
struct vnet_symmap {
@@ -42,27 +51,78 @@ struct vnet_symmap {
void *base;
size_t size;
};
+typedef struct vnet_symmap vnet_symmap_t;
struct vnet_modinfo {
+ u_int vmi_id;
+ u_int vmi_dependson;
char *vmi_name;
+ vnet_attach_fn *vmi_iattach;
+ vnet_detach_fn *vmi_idetach;
+ size_t vmi_struct_size;
struct vnet_symmap *vmi_symmap;
};
+typedef struct vnet_modinfo vnet_modinfo_t;
struct vnet_modlink {
- TAILQ_ENTRY(vnet_modlink) vml_mod_le;
+ TAILQ_ENTRY(vnet_modlink) vml_mod_le;
const struct vnet_modinfo *vml_modinfo;
+ const void *vml_iarg;
+ const char *vml_iname;
};
-#define VNET_MOD_DECLARE(m_name_uc, m_name_lc, m_iattach, m_idetach, \
- m_dependson, m_symmap) \
- static const struct vnet_modinfo vnet_##m_name_lc##_modinfo = { \
- .vmi_name = #m_name_lc, \
- .vmi_symmap = m_symmap \
-};
+#define VNET_SYMMAP(mod, name) \
+ { #name, &(vnet_ ## mod ## _0._ ## name), \
+ sizeof(vnet_ ## mod ## _0._ ## name) }
-#if defined(VIMAGE) && defined(VIMAGE_GLOBALS)
-#error "You cannot have both option VIMAGE and option VIMAGE_GLOBALS!"
-#endif
+#define VNET_SYMMAP_END { NULL, 0 }
+
+/* stateful modules */
+#define VNET_MOD_NET 0 /* MUST be 0 - implicit dependency */
+#define VNET_MOD_NETGRAPH 1
+#define VNET_MOD_INET 2
+#define VNET_MOD_INET6 3
+#define VNET_MOD_IPSEC 4
+#define VNET_MOD_IPFW 5
+#define VNET_MOD_DUMMYNET 6
+#define VNET_MOD_PF 7
+#define VNET_MOD_ALTQ 8
+#define VNET_MOD_IPX 9
+#define VNET_MOD_ATALK 10
+#define VNET_MOD_ACCF_HTTP 11
+#define VNET_MOD_IGMP 12
+
+/* stateless modules */
+#define VNET_MOD_NG_ETHER 20
+#define VNET_MOD_NG_IFACE 21
+#define VNET_MOD_NG_EIFACE 22
+#define VNET_MOD_ESP 23
+#define VNET_MOD_IPIP 24
+#define VNET_MOD_AH 25
+#define VNET_MOD_IPCOMP 26
+#define VNET_MOD_GIF 27
+#define VNET_MOD_ARP 28
+#define VNET_MOD_RTABLE 29
+#define VNET_MOD_LOIF 30
+#define VNET_MOD_DOMAIN 31
+#define VNET_MOD_DYNAMIC_START 32
+#define VNET_MOD_MAX 64
+
+/* Sysctl virtualization macros need these name mappings bellow */
+#define V_MOD_vnet_net VNET_MOD_NET
+#define V_MOD_vnet_netgraph VNET_MOD_NETGRAPH
+#define V_MOD_vnet_inet VNET_MOD_INET
+#define V_MOD_vnet_inet6 VNET_MOD_INET6
+#define V_MOD_vnet_ipfw VNET_MOD_IPFW
+#define V_MOD_vnet_pf VNET_MOD_PF
+#define V_MOD_vnet_gif VNET_MOD_GIF
+#define V_MOD_vnet_ipsec VNET_MOD_IPSEC
+
+int vi_symlookup(struct kld_sym_lookup *, char *);
+void vnet_mod_register(const struct vnet_modinfo *);
+void vnet_mod_register_multi(const struct vnet_modinfo *, void *, char *);
+
+#endif /* !VIMAGE_GLOBALS */
#ifdef VIMAGE_GLOBALS
#define VSYM(base, sym) (sym)
@@ -74,13 +134,8 @@ struct vnet_modlink {
#endif
#endif
-#define VNET_SYMMAP(mod, name) \
- { #name, &(vnet_ ## mod ## _0._ ## name), \
- sizeof(vnet_ ## mod ## _0._ ## name) }
-
-#define VNET_SYMMAP_END { NULL, 0 }
-
/* Non-VIMAGE null-macros */
+#define IS_DEFAULT_VNET(arg) 1
#define CURVNET_SET(arg)
#define CURVNET_SET_QUIET(arg)
#define CURVNET_RESTORE()
@@ -109,9 +164,6 @@ struct vnet_modlink {
#define G_hostname VPROCG(hostname) /* global hostname */
#define V_domainname VPROCG(domainname)
-int vi_symlookup(struct kld_sym_lookup *, char *);
-void vnet_mod_register(const struct vnet_modinfo *);
-
/*
* Size-guards for the vimage structures.
* If you need to update the values you MUST increment __FreeBSD_version.
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 53f45c6..0a3d1dc 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -135,7 +135,7 @@ struct vnode {
*/
LIST_HEAD(, namecache) v_cache_src; /* c Cache entries from us */
TAILQ_HEAD(, namecache) v_cache_dst; /* c Cache entries to us */
- struct vnode *v_dd; /* c .. vnode */
+ struct namecache *v_cache_dd; /* c Cache entry for .. vnode */
/*
* clustering stuff
@@ -308,15 +308,48 @@ struct vattr {
#define IO_SEQSHIFT 16 /* seq heuristic in upper 16 bits */
/*
- * Flags for accmode_t.
+ * Flags for accmode_t.
*/
-#define VEXEC 000100 /* execute/search permission */
-#define VWRITE 000200 /* write permission */
-#define VREAD 000400 /* read permission */
-#define VADMIN 010000 /* permission to administer */
-#define VSTAT 020000 /* permission to retrieve attrs */
-#define VAPPEND 040000 /* permission to write/append */
-#define VALLPERM (VEXEC | VWRITE | VREAD | VADMIN | VSTAT | VAPPEND)
+#define VEXEC 000000000100 /* execute/search permission */
+#define VWRITE 000000000200 /* write permission */
+#define VREAD 000000000400 /* read permission */
+#define VADMIN 000000010000 /* being the file owner */
+#define VAPPEND 000000040000 /* permission to write/append */
+/*
+ * VEXPLICIT_DENY makes VOP_ACCESS(9) return EPERM or EACCES only
+ * if permission was denied explicitly, by a "deny" rule in NFS4 ACL,
+ * and 0 otherwise. This never happens with ordinary unix access rights
+ * or POSIX.1e ACLs. Obviously, VEXPLICIT_DENY must be OR-ed with
+ * some other V* constant.
+ */
+#define VEXPLICIT_DENY 000000100000
+#define VREAD_NAMED_ATTRS 000000200000 /* not used */
+#define VWRITE_NAMED_ATTRS 000000400000 /* not used */
+#define VDELETE_CHILD 000001000000
+#define VREAD_ATTRIBUTES 000002000000 /* permission to stat(2) */
+#define VWRITE_ATTRIBUTES 000004000000 /* change {m,c,a}time */
+#define VDELETE 000010000000
+#define VREAD_ACL 000020000000 /* read ACL and file mode */
+#define VWRITE_ACL 000040000000 /* change ACL and/or file mode */
+#define VWRITE_OWNER 000100000000 /* change file owner */
+#define VSYNCHRONIZE 000200000000 /* not used */
+
+/*
+ * Permissions that were traditionally granted only to the file owner.
+ */
+#define VADMIN_PERMS (VADMIN | VWRITE_ATTRIBUTES | VWRITE_ACL | \
+ VWRITE_OWNER)
+
+/*
+ * Permissions that were traditionally granted to everyone.
+ */
+#define VSTAT_PERMS (VREAD_ATTRIBUTES | VREAD_ACL)
+
+/*
+ * Permissions that allow to change the state of the file in any way.
+ */
+#define VMODIFY_PERMS (VWRITE | VAPPEND | VADMIN_PERMS | VDELETE_CHILD | \
+ VDELETE)
/*
* Token indicating no attribute value yet assigned.
@@ -379,14 +412,6 @@ extern struct uma_zone *namei_zone;
extern int prtactive; /* nonzero to call vprint() */
extern struct vattr va_null; /* predefined null vattr structure */
-/*
- * Macro/function to check for client cache inconsistency w.r.t. leasing.
- */
-#define LEASE_READ 0x1 /* Check lease for readers */
-#define LEASE_WRITE 0x2 /* Check lease for modifiers */
-
-extern void (*lease_updatetime)(int deltat);
-
#define VI_LOCK(vp) mtx_lock(&(vp)->v_interlock)
#define VI_LOCK_FLAGS(vp, flags) mtx_lock_flags(&(vp)->v_interlock, (flags))
#define VI_TRYLOCK(vp) mtx_trylock(&(vp)->v_interlock)
@@ -554,8 +579,6 @@ struct uio;
struct vattr;
struct vnode;
-extern int (*lease_check_hook)(struct vop_lease_args *);
-
/* cache_* may belong in namei.h. */
void cache_enter(struct vnode *dvp, struct vnode *vp,
struct componentname *cnp);
@@ -574,7 +597,6 @@ int insmntque1(struct vnode *vp, struct mount *mp,
void (*dtr)(struct vnode *, void *), void *dtr_arg);
int insmntque(struct vnode *vp, struct mount *mp);
u_quad_t init_va_filerev(void);
-int lease_check(struct vop_lease_args *ap);
int speedup_syncer(void);
#define textvp_fullpath(p, rb, rfb) \
vn_fullpath(FIRST_THREAD_IN_PROC(p), (p)->p_textvp, rb, rfb)
diff --git a/sys/tools/vnode_if.awk b/sys/tools/vnode_if.awk
index b250c92..86c6bdc 100644
--- a/sys/tools/vnode_if.awk
+++ b/sys/tools/vnode_if.awk
@@ -165,12 +165,18 @@ if (hfile) {
if (cfile) {
printc(common_head \
+ "#include \"opt_kdtrace.h\"\n" \
+ "\n" \
"#include <sys/param.h>\n" \
"#include <sys/event.h>\n" \
+ "#include <sys/kernel.h>\n" \
"#include <sys/mount.h>\n" \
+ "#include <sys/sdt.h>\n" \
"#include <sys/systm.h>\n" \
"#include <sys/vnode.h>\n" \
"\n" \
+ "SDT_PROVIDER_DECLARE(vfs);\n" \
+ "\n" \
"struct vnodeop_desc vop_default_desc = {\n" \
" \"default\",\n" \
" 0,\n" \
@@ -348,6 +354,10 @@ while ((getline < srcfile) > 0) {
printc("\tVDESC_NO_OFFSET");
printc("};");
+ printc("\n");
+ printc("SDT_PROBE_DEFINE2(vfs, vop, " name ", entry, \"struct vnode *\", \"struct " name "_args *\");\n");
+ printc("SDT_PROBE_DEFINE3(vfs, vop, " name ", return, \"struct vnode *\", \"struct " name "_args *\", \"int\");\n");
+
# Print out function.
printc("\nint\n" uname "_AP(struct " name "_args *a)");
printc("{");
@@ -364,6 +374,7 @@ while ((getline < srcfile) > 0) {
printc("\t vop->"name" == NULL && vop->vop_bypass == NULL)")
printc("\t\tvop = vop->vop_default;")
printc("\tVNASSERT(vop != NULL, a->a_" args[0]", (\"No "name"(%p, %p)\", a->a_" args[0]", a));")
+ printc("\tSDT_PROBE(vfs, vop, " name ", entry, a->a_" args[0] ", a, 0, 0, 0);\n");
for (i = 0; i < numargs; ++i)
add_debug_code(name, args[i], "Entry", "\t");
add_pre(name);
@@ -372,6 +383,7 @@ while ((getline < srcfile) > 0) {
printc("\telse")
printc("\t\trc = vop->vop_bypass(&a->a_gen);")
printc(ctrstr);
+ printc("\tSDT_PROBE(vfs, vop, " name ", return, a->a_" args[0] ", a, rc, 0, 0);\n");
printc("\tif (rc == 0) {");
for (i = 0; i < numargs; ++i)
add_debug_code(name, args[i], "OK", "\t\t");
diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c
index b45532e..a6e73f5 100644
--- a/sys/ufs/ffs/ffs_snapshot.c
+++ b/sys/ufs/ffs/ffs_snapshot.c
@@ -278,7 +278,6 @@ restart:
return (error);
goto restart;
}
- VOP_LEASE(nd.ni_dvp, td, KERNCRED, LEASE_WRITE);
error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vat);
VOP_UNLOCK(nd.ni_dvp, 0);
if (error) {
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 15ceef8..5d959ac4 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -3309,7 +3309,7 @@ newdirrem(bp, dp, ip, isrmdir, prevdirremp)
* the number of freefile and freeblks structures.
*/
ACQUIRE_LOCK(&lk);
- if (num_dirrem > max_softdeps / 2)
+ if (!(ip->i_flags & SF_SNAPSHOT) && num_dirrem > max_softdeps / 2)
(void) request_cleanup(ITOV(dp)->v_mount, FLUSH_REMOVE);
num_dirrem += 1;
FREE_LOCK(&lk);
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 73535fc..94752c7 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -1451,6 +1451,7 @@ ffs_vgetf(mp, ino, flags, vpp, ffs_flags)
ip->i_fs = fs;
ip->i_dev = dev;
ip->i_number = ino;
+ ip->i_ea_refs = 0;
#ifdef QUOTA
{
int i;
@@ -1844,7 +1845,9 @@ ffs_bufwrite(struct buf *bp)
("bufwrite: needs chained iodone (%p)", bp->b_iodone));
/* get a new block */
- newbp = geteblk(bp->b_bufsize);
+ newbp = geteblk(bp->b_bufsize, GB_NOWAIT_BD);
+ if (newbp == NULL)
+ goto normal_write;
/*
* set it to be identical to the old block. We have to
@@ -1884,6 +1887,7 @@ ffs_bufwrite(struct buf *bp)
}
/* Let the normal bufwrite do the rest for us */
+normal_write:
return (bufwrite(bp));
}
diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c
index ca2efa6..1abb994 100644
--- a/sys/ufs/ffs/ffs_vnops.c
+++ b/sys/ufs/ffs/ffs_vnops.c
@@ -1225,6 +1225,35 @@ ffs_rdextattr(u_char **p, struct vnode *vp, struct thread *td, int extra)
return (0);
}
+static void
+ffs_lock_ea(struct vnode *vp)
+{
+ struct inode *ip;
+
+ ip = VTOI(vp);
+ VI_LOCK(vp);
+ while (ip->i_flag & IN_EA_LOCKED) {
+ ip->i_flag |= IN_EA_LOCKWAIT;
+ msleep(&ip->i_ea_refs, &vp->v_interlock, PINOD + 2, "ufs_ea",
+ 0);
+ }
+ ip->i_flag |= IN_EA_LOCKED;
+ VI_UNLOCK(vp);
+}
+
+static void
+ffs_unlock_ea(struct vnode *vp)
+{
+ struct inode *ip;
+
+ ip = VTOI(vp);
+ VI_LOCK(vp);
+ if (ip->i_flag & IN_EA_LOCKWAIT)
+ wakeup(&ip->i_ea_refs);
+ ip->i_flag &= ~(IN_EA_LOCKED | IN_EA_LOCKWAIT);
+ VI_UNLOCK(vp);
+}
+
static int
ffs_open_ea(struct vnode *vp, struct ucred *cred, struct thread *td)
{
@@ -1234,14 +1263,22 @@ ffs_open_ea(struct vnode *vp, struct ucred *cred, struct thread *td)
ip = VTOI(vp);
- if (ip->i_ea_area != NULL)
- return (EBUSY);
+ ffs_lock_ea(vp);
+ if (ip->i_ea_area != NULL) {
+ ip->i_ea_refs++;
+ ffs_unlock_ea(vp);
+ return (0);
+ }
dp = ip->i_din2;
error = ffs_rdextattr(&ip->i_ea_area, vp, td, 0);
- if (error)
+ if (error) {
+ ffs_unlock_ea(vp);
return (error);
+ }
ip->i_ea_len = dp->di_extsize;
ip->i_ea_error = 0;
+ ip->i_ea_refs++;
+ ffs_unlock_ea(vp);
return (0);
}
@@ -1258,11 +1295,16 @@ ffs_close_ea(struct vnode *vp, int commit, struct ucred *cred, struct thread *td
struct ufs2_dinode *dp;
ip = VTOI(vp);
- if (ip->i_ea_area == NULL)
+
+ ffs_lock_ea(vp);
+ if (ip->i_ea_area == NULL) {
+ ffs_unlock_ea(vp);
return (EINVAL);
+ }
dp = ip->i_din2;
error = ip->i_ea_error;
if (commit && error == 0) {
+ ASSERT_VOP_ELOCKED(vp, "ffs_close_ea commit");
if (cred == NOCRED)
cred = vp->v_mount->mnt_cred;
liovec.iov_base = ip->i_ea_area;
@@ -1279,10 +1321,13 @@ ffs_close_ea(struct vnode *vp, int commit, struct ucred *cred, struct thread *td
error = ffs_truncate(vp, 0, IO_EXT, cred, td);
error = ffs_extwrite(vp, &luio, IO_EXT | IO_SYNC, cred);
}
- free(ip->i_ea_area, M_TEMP);
- ip->i_ea_area = NULL;
- ip->i_ea_len = 0;
- ip->i_ea_error = 0;
+ if (--ip->i_ea_refs == 0) {
+ free(ip->i_ea_area, M_TEMP);
+ ip->i_ea_area = NULL;
+ ip->i_ea_len = 0;
+ ip->i_ea_error = 0;
+ }
+ ffs_unlock_ea(vp);
return (error);
}
@@ -1392,7 +1437,6 @@ vop_deleteextattr {
uint32_t ealength, ul;
int ealen, olen, eapad1, eapad2, error, i, easize;
u_char *eae, *p;
- int stand_alone;
ip = VTOI(ap->a_vp);
fs = ip->i_fs;
@@ -1409,19 +1453,19 @@ vop_deleteextattr {
error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
ap->a_cred, ap->a_td, VWRITE);
if (error) {
+
+ /*
+ * ffs_lock_ea is not needed there, because the vnode
+ * must be exclusively locked.
+ */
if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
ip->i_ea_error = error;
return (error);
}
- if (ip->i_ea_area == NULL) {
- error = ffs_open_ea(ap->a_vp, ap->a_cred, ap->a_td);
- if (error)
- return (error);
- stand_alone = 1;
- } else {
- stand_alone = 0;
- }
+ error = ffs_open_ea(ap->a_vp, ap->a_cred, ap->a_td);
+ if (error)
+ return (error);
ealength = eapad1 = ealen = eapad2 = 0;
@@ -1434,8 +1478,7 @@ vop_deleteextattr {
if (olen == -1) {
/* delete but nonexistent */
free(eae, M_TEMP);
- if (stand_alone)
- ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
+ ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
return(ENOATTR);
}
bcopy(p, &ul, sizeof ul);
@@ -1446,9 +1489,8 @@ vop_deleteextattr {
}
if (easize > NXADDR * fs->fs_bsize) {
free(eae, M_TEMP);
- if (stand_alone)
- ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
- else if (ip->i_ea_error == 0)
+ ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
+ if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
ip->i_ea_error = ENOSPC;
return(ENOSPC);
}
@@ -1456,8 +1498,7 @@ vop_deleteextattr {
ip->i_ea_area = eae;
ip->i_ea_len = easize;
free(p, M_TEMP);
- if (stand_alone)
- error = ffs_close_ea(ap->a_vp, 1, ap->a_cred, ap->a_td);
+ error = ffs_close_ea(ap->a_vp, 1, ap->a_cred, ap->a_td);
return(error);
}
@@ -1482,7 +1523,7 @@ vop_getextattr {
struct fs *fs;
u_char *eae, *p;
unsigned easize;
- int error, ealen, stand_alone;
+ int error, ealen;
ip = VTOI(ap->a_vp);
fs = ip->i_fs;
@@ -1495,14 +1536,10 @@ vop_getextattr {
if (error)
return (error);
- if (ip->i_ea_area == NULL) {
- error = ffs_open_ea(ap->a_vp, ap->a_cred, ap->a_td);
- if (error)
- return (error);
- stand_alone = 1;
- } else {
- stand_alone = 0;
- }
+ error = ffs_open_ea(ap->a_vp, ap->a_cred, ap->a_td);
+ if (error)
+ return (error);
+
eae = ip->i_ea_area;
easize = ip->i_ea_len;
@@ -1516,8 +1553,8 @@ vop_getextattr {
error = uiomove(p, ealen, ap->a_uio);
} else
error = ENOATTR;
- if (stand_alone)
- ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
+
+ ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
return(error);
}
@@ -1542,7 +1579,7 @@ vop_listextattr {
u_char *eae, *p, *pe, *pn;
unsigned easize;
uint32_t ul;
- int error, ealen, stand_alone;
+ int error, ealen;
ip = VTOI(ap->a_vp);
fs = ip->i_fs;
@@ -1555,14 +1592,9 @@ vop_listextattr {
if (error)
return (error);
- if (ip->i_ea_area == NULL) {
- error = ffs_open_ea(ap->a_vp, ap->a_cred, ap->a_td);
- if (error)
- return (error);
- stand_alone = 1;
- } else {
- stand_alone = 0;
- }
+ error = ffs_open_ea(ap->a_vp, ap->a_cred, ap->a_td);
+ if (error)
+ return (error);
eae = ip->i_ea_area;
easize = ip->i_ea_len;
@@ -1586,8 +1618,7 @@ vop_listextattr {
error = uiomove(p, ealen + 1, ap->a_uio);
}
}
- if (stand_alone)
- ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
+ ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
return(error);
}
@@ -1612,7 +1643,6 @@ vop_setextattr {
uint32_t ealength, ul;
int ealen, olen, eapad1, eapad2, error, i, easize;
u_char *eae, *p;
- int stand_alone;
ip = VTOI(ap->a_vp);
fs = ip->i_fs;
@@ -1633,19 +1663,19 @@ vop_setextattr {
error = extattr_check_cred(ap->a_vp, ap->a_attrnamespace,
ap->a_cred, ap->a_td, VWRITE);
if (error) {
+
+ /*
+ * ffs_lock_ea is not needed there, because the vnode
+ * must be exclusively locked.
+ */
if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
ip->i_ea_error = error;
return (error);
}
- if (ip->i_ea_area == NULL) {
- error = ffs_open_ea(ap->a_vp, ap->a_cred, ap->a_td);
- if (error)
- return (error);
- stand_alone = 1;
- } else {
- stand_alone = 0;
- }
+ error = ffs_open_ea(ap->a_vp, ap->a_cred, ap->a_td);
+ if (error)
+ return (error);
ealen = ap->a_uio->uio_resid;
ealength = sizeof(uint32_t) + 3 + strlen(ap->a_name);
@@ -1677,9 +1707,8 @@ vop_setextattr {
}
if (easize > NXADDR * fs->fs_bsize) {
free(eae, M_TEMP);
- if (stand_alone)
- ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
- else if (ip->i_ea_error == 0)
+ ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
+ if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
ip->i_ea_error = ENOSPC;
return(ENOSPC);
}
@@ -1695,9 +1724,8 @@ vop_setextattr {
error = uiomove(p, ealen, ap->a_uio);
if (error) {
free(eae, M_TEMP);
- if (stand_alone)
- ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
- else if (ip->i_ea_error == 0)
+ ffs_close_ea(ap->a_vp, 0, ap->a_cred, ap->a_td);
+ if (ip->i_ea_area != NULL && ip->i_ea_error == 0)
ip->i_ea_error = error;
return(error);
}
@@ -1708,8 +1736,7 @@ vop_setextattr {
ip->i_ea_area = eae;
ip->i_ea_len = easize;
free(p, M_TEMP);
- if (stand_alone)
- error = ffs_close_ea(ap->a_vp, 1, ap->a_cred, ap->a_td);
+ error = ffs_close_ea(ap->a_vp, 1, ap->a_cred, ap->a_td);
return(error);
}
diff --git a/sys/ufs/ufs/inode.h b/sys/ufs/ufs/inode.h
index 39f46d0a..5c4732d 100644
--- a/sys/ufs/ufs/inode.h
+++ b/sys/ufs/ufs/inode.h
@@ -94,6 +94,7 @@ struct inode {
u_char *i_ea_area; /* Pointer to malloced copy of EA area */
unsigned i_ea_len; /* Length of i_ea_area */
int i_ea_error; /* First errno in transaction */
+ int i_ea_refs; /* Number of users of EA area */
/*
* Copies from the on-disk dinode itself.
@@ -125,6 +126,8 @@ struct inode {
#define IN_SPACECOUNTED 0x0080 /* Blocks to be freed in free count. */
#define IN_LAZYACCESS 0x0100 /* Process IN_ACCESS after the
suspension finished */
+#define IN_EA_LOCKED 0x0200
+#define IN_EA_LOCKWAIT 0x0400
#define i_devvp i_ump->um_devvp
#define i_umbufobj i_ump->um_bo
diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h
index 0a54372..475a20e 100644
--- a/sys/vm/vm_extern.h
+++ b/sys/vm/vm_extern.h
@@ -42,19 +42,6 @@ struct vnode;
#ifdef _KERNEL
-#ifdef TYPEDEF_FOR_UAP
-int getpagesize(struct thread *, void *, int *);
-int madvise(struct thread *, void *, int *);
-int mincore(struct thread *, void *, int *);
-int mprotect(struct thread *, void *, int *);
-int msync(struct thread *, void *, int *);
-int munmap(struct thread *, void *, int *);
-int obreak(struct thread *, void *, int *);
-int sbrk(struct thread *, void *, int *);
-int sstk(struct thread *, void *, int *);
-int swapon(struct thread *, void *, int *);
-#endif /* TYPEDEF_FOR_UAP */
-
int kernacc(void *, int, int);
vm_offset_t kmem_alloc(vm_map_t, vm_size_t);
vm_offset_t kmem_alloc_nofault(vm_map_t, vm_size_t);
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index f395be8..718c890 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -2217,6 +2217,16 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end,
*
*/
if (entry->wired_count == 0) {
+ if ((entry->protection & (VM_PROT_READ|VM_PROT_EXECUTE))
+ == 0) {
+ if ((flags & VM_MAP_WIRE_HOLESOK) == 0) {
+ end = entry->end;
+ rv = KERN_INVALID_ADDRESS;
+ goto done;
+ }
+ entry->eflags |= MAP_ENTRY_WIRE_SKIPPED;
+ goto next_entry;
+ }
entry->wired_count++;
saved_start = entry->start;
saved_end = entry->end;
@@ -2274,6 +2284,7 @@ vm_map_wire(vm_map_t map, vm_offset_t start, vm_offset_t end,
* Check the map for holes in the specified region.
* If VM_MAP_WIRE_HOLESOK was specified, skip this check.
*/
+ next_entry:
if (((flags & VM_MAP_WIRE_HOLESOK) == 0) &&
(entry->end < end && (entry->next == &map->header ||
entry->next->start > entry->end))) {
@@ -2295,6 +2306,8 @@ done:
}
entry = first_entry;
while (entry != &map->header && entry->start < end) {
+ if ((entry->eflags & MAP_ENTRY_WIRE_SKIPPED) != 0)
+ goto next_entry_done;
if (rv == KERN_SUCCESS) {
if (user_wire)
entry->eflags |= MAP_ENTRY_USER_WIRED;
@@ -2317,9 +2330,10 @@ done:
entry->object.vm_object->type == OBJT_DEVICE);
}
}
+ next_entry_done:
KASSERT(entry->eflags & MAP_ENTRY_IN_TRANSITION,
("vm_map_wire: in-transition flag missing"));
- entry->eflags &= ~MAP_ENTRY_IN_TRANSITION;
+ entry->eflags &= ~(MAP_ENTRY_IN_TRANSITION|MAP_ENTRY_WIRE_SKIPPED);
if (entry->eflags & MAP_ENTRY_NEEDS_WAKEUP) {
entry->eflags &= ~MAP_ENTRY_NEEDS_WAKEUP;
need_wakeup = TRUE;
diff --git a/sys/vm/vm_map.h b/sys/vm/vm_map.h
index 34b183b..70c3a0b 100644
--- a/sys/vm/vm_map.h
+++ b/sys/vm/vm_map.h
@@ -137,6 +137,8 @@ struct vm_map_entry {
#define MAP_ENTRY_GROWS_DOWN 0x1000 /* Top-down stacks */
#define MAP_ENTRY_GROWS_UP 0x2000 /* Bottom-up stacks */
+#define MAP_ENTRY_WIRE_SKIPPED 0x4000
+
#ifdef _KERNEL
static __inline u_char
vm_map_entry_behavior(vm_map_entry_t entry)
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index 2d668c4..6cc0acc 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -620,10 +620,6 @@ mprotect(td, uap)
addr = (vm_offset_t) uap->addr;
size = uap->len;
prot = uap->prot & VM_PROT_ALL;
-#if defined(VM_PROT_READ_IS_EXEC)
- if (prot & VM_PROT_READ)
- prot |= VM_PROT_EXECUTE;
-#endif
pageoff = (addr & PAGE_MASK);
addr -= pageoff;
@@ -1441,14 +1437,6 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
if (flags & MAP_NOCORE)
docow |= MAP_DISABLE_COREDUMP;
-#if defined(VM_PROT_READ_IS_EXEC)
- if (prot & VM_PROT_READ)
- prot |= VM_PROT_EXECUTE;
-
- if (maxprot & VM_PROT_READ)
- maxprot |= VM_PROT_EXECUTE;
-#endif
-
if (flags & MAP_STACK)
rv = vm_map_stack(map, *addr, size, prot, maxprot,
docow | MAP_STACK_GROWS_DOWN);
diff --git a/sys/vm/vm_reserv.c b/sys/vm/vm_reserv.c
index 4ea9079..d9e908f 100644
--- a/sys/vm/vm_reserv.c
+++ b/sys/vm/vm_reserv.c
@@ -138,8 +138,8 @@ static vm_reserv_t vm_reserv_array;
* The partially-populated reservation queue
*
* This queue enables the fast recovery of an unused cached or free small page
- * from a partially-populated reservation. The head of this queue is either
- * the least-recently-populated or most-recently-depopulated reservation.
+ * from a partially-populated reservation. The reservation at the head of
+ * this queue is the least-recently-changed, partially-populated reservation.
*
* Access to this queue is synchronized by the free page queue lock.
*/
@@ -209,7 +209,7 @@ sysctl_vm_reserv_partpopq(SYSCTL_HANDLER_ARGS)
/*
* Reduces the given reservation's population count. If the population count
* becomes zero, the reservation is destroyed. Additionally, moves the
- * reservation to the head of the partially-populated reservations queue if the
+ * reservation to the tail of the partially-populated reservations queue if the
* population count is non-zero.
*
* The free page queue lock must be held.
@@ -235,7 +235,7 @@ vm_reserv_depopulate(vm_reserv_t rv)
vm_reserv_freed++;
} else {
rv->inpartpopq = TRUE;
- TAILQ_INSERT_HEAD(&vm_rvq_partpop, rv, partpopq);
+ TAILQ_INSERT_TAIL(&vm_rvq_partpop, rv, partpopq);
}
}
diff --git a/sys/vm/vm_unix.c b/sys/vm/vm_unix.c
index cd98be9..6bb9917 100644
--- a/sys/vm/vm_unix.c
+++ b/sys/vm/vm_unix.c
@@ -117,7 +117,7 @@ obreak(td, uap)
goto done;
}
rv = vm_map_insert(&vm->vm_map, NULL, 0, old, new,
- VM_PROT_ALL, VM_PROT_ALL, 0);
+ VM_PROT_RW, VM_PROT_ALL, 0);
if (rv != KERN_SUCCESS) {
error = ENOMEM;
goto done;
diff --git a/sys/xen/evtchn/evtchn.c b/sys/xen/evtchn/evtchn.c
index 61b738b..59d24b2 100644
--- a/sys/xen/evtchn/evtchn.c
+++ b/sys/xen/evtchn/evtchn.c
@@ -512,7 +512,7 @@ bind_interdomain_evtchn_to_irqhandler(unsigned int remote_domain,
int
bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
const char *devname, driver_filter_t filter, driver_intr_t handler,
- unsigned long irqflags, unsigned int *irqp)
+ void *arg, unsigned long irqflags, unsigned int *irqp)
{
unsigned int irq;
int error;
diff --git a/sys/xen/reboot.c b/sys/xen/reboot.c
index 892dfbf..04ba132 100644
--- a/sys/xen/reboot.c
+++ b/sys/xen/reboot.c
@@ -176,9 +176,9 @@ xen_suspend()
/*
* Bind us to CPU 0 and stop any other VCPUs.
*/
- mtx_lock_spin(&sched_lock);
+ thread_lock(curthread);
sched_bind(curthread, 0);
- mtx_unlock_spin(&sched_lock);
+ thread_unlock(curthread);
KASSERT(PCPU_GET(cpuid) == 0, ("xen_suspend: not running on cpu 0"));
map = PCPU_GET(other_cpus) & ~stopped_cpus;
@@ -188,8 +188,10 @@ xen_suspend()
if (DEVICE_SUSPEND(root_bus) != 0) {
printf("xen_suspend: device_suspend failed\n");
+#ifdef SMP
if (map)
restart_cpus(map);
+#endif
return;
}
@@ -253,7 +255,9 @@ xen_suspend()
DEVICE_RESUME(root_bus);
#ifdef SMP
+ thread_lock(curthread);
sched_unbind(curthread);
+ thread_unlock(curthread);
if (map)
restart_cpus(map);
#endif
diff --git a/tools/build/options/WITHOUT_SLIP b/tools/build/options/WITHOUT_SLIP
deleted file mode 100644
index a0f4cb2..0000000
--- a/tools/build/options/WITHOUT_SLIP
+++ /dev/null
@@ -1,4 +0,0 @@
-.\" $FreeBSD$
-Set to not build
-.Xr sliplogin 8
-and related programs.
diff --git a/tools/regression/bin/sh/builtins/alias.0 b/tools/regression/bin/sh/builtins/alias.0
index 39c748a..d9b2796 100644
--- a/tools/regression/bin/sh/builtins/alias.0
+++ b/tools/regression/bin/sh/builtins/alias.0
@@ -3,4 +3,7 @@ set -e
unalias -a
alias foo=bar
+alias bar=
+alias quux="1 2 3"
alias
+alias foo
diff --git a/tools/regression/bin/sh/builtins/alias.0.stdout b/tools/regression/bin/sh/builtins/alias.0.stdout
index 1d5d296..52efaf0 100644
--- a/tools/regression/bin/sh/builtins/alias.0.stdout
+++ b/tools/regression/bin/sh/builtins/alias.0.stdout
@@ -1 +1,4 @@
-foo='bar'
+bar=''
+foo=bar
+quux='1 2 3'
+foo=bar
diff --git a/tools/regression/bin/sh/builtins/read1.0 b/tools/regression/bin/sh/builtins/read1.0
new file mode 100644
index 0000000..06a68fa
--- /dev/null
+++ b/tools/regression/bin/sh/builtins/read1.0
@@ -0,0 +1,26 @@
+# $FreeBSD$
+set -e
+
+echo "1 2 3" | { read a; echo "x${a}x"; }
+echo "1 2 3" | { read a b; echo "x${a}x${b}x"; }
+echo "1 2 3" | { read a b c; echo "x${a}x${b}x${c}x"; }
+echo "1 2 3" | { read a b c d; echo "x${a}x${b}x${c}x${d}x"; }
+
+echo " 1 2 3 " | { read a b c; echo "x${a}x${b}x${c}x"; }
+echo " 1 2 3 " | { unset IFS; read a b c; echo "x${a}x${b}x${c}x"; }
+echo " 1 2 3 " | { IFS=$(printf ' \t\n') read a b c; echo "x${a}x${b}x${c}x"; }
+echo " 1 2 3 " | { IFS= read a b; echo "x${a}x${b}x"; }
+
+echo " 1,2 3 " | { IFS=' ,' read a b c; echo "x${a}x${b}x${c}x"; }
+echo ", 2 ,3" | { IFS=' ,' read a b c; echo "x${a}x${b}x${c}x"; }
+echo " 1 ,,3" | { IFS=' ,' read a b c; echo "x${a}x${b}x${c}x"; }
+echo " 1 , , 3" | { IFS=' ,' read a b c; echo "x${a}x${b}x${c}x"; }
+echo " 1 ,2 3," | { IFS=' ,' read a b c; echo "x${a}x${b}x${c}x"; }
+echo " 1 ,2 3,," | { IFS=' ,' read a b c; echo "x${a}x${b}x${c}x"; }
+
+echo " 1,2 3 " | { IFS=', ' read a b c; echo "x${a}x${b}x${c}x"; }
+echo ", 2 ,3" | { IFS=', ' read a b c; echo "x${a}x${b}x${c}x"; }
+echo " 1 ,,3" | { IFS=', ' read a b c; echo "x${a}x${b}x${c}x"; }
+echo " 1 , , 3" | { IFS=', ' read a b c; echo "x${a}x${b}x${c}x"; }
+echo " 1 ,2 3," | { IFS=', ' read a b c; echo "x${a}x${b}x${c}x"; }
+echo " 1 ,2 3,," | { IFS=', ' read a b c; echo "x${a}x${b}x${c}x"; }
diff --git a/tools/regression/bin/sh/builtins/read1.0.stdout b/tools/regression/bin/sh/builtins/read1.0.stdout
new file mode 100644
index 0000000..dbcb1af
--- /dev/null
+++ b/tools/regression/bin/sh/builtins/read1.0.stdout
@@ -0,0 +1,20 @@
+x1 2 3x
+x1x2 3x
+x1x2x3x
+x1x2x3xx
+x1x2x3x
+x1x2x3x
+x1x2x3x
+x 1 2 3 xx
+x1x2x3x
+xx2x3x
+x1xx3x
+x1xx3x
+x1x2x3x
+x1x2x3,,x
+x1x2x3x
+xx2x3x
+x1xx3x
+x1xx3x
+x1x2x3x
+x1x2x3,,x
diff --git a/tools/regression/include/tgmath/Makefile b/tools/regression/include/tgmath/Makefile
index 64626c5..53e3b9a 100644
--- a/tools/regression/include/tgmath/Makefile
+++ b/tools/regression/include/tgmath/Makefile
@@ -1,7 +1,8 @@
# $FreeBSD$
PROG= tgmath
-CFLAGS+= -fno-builtin -std=c99
+CSTD= c99
+CFLAGS+= -fno-builtin
NO_MAN=
.include <bsd.prog.mk>
diff --git a/tools/regression/lib/libc/stdio/test-getdelim.c b/tools/regression/lib/libc/stdio/test-getdelim.c
index 3488d63..1102c20 100644
--- a/tools/regression/lib/libc/stdio/test-getdelim.c
+++ b/tools/regression/lib/libc/stdio/test-getdelim.c
@@ -100,7 +100,7 @@ main(int argc, char *argv[])
assert(line[0] == '\0' && line[1] == '\0');
/* Third line: EOF */
line[0] = 'X';
- assert(getline(&line, &linecap, fp) == 0);
+ assert(getline(&line, &linecap, fp) == -1);
assert(line[0] == '\0');
free(line);
assert(feof(fp));
@@ -139,7 +139,7 @@ main(int argc, char *argv[])
free(line);
line = NULL;
linecap = 0;
- assert(getline(&line, &linecap, fp) == 0);
+ assert(getline(&line, &linecap, fp) == -1);
assert(line[0] == '\0');
assert(linecap > 0);
assert(errno == 0);
diff --git a/tools/regression/mac/mac_portacl/LICENSE b/tools/regression/mac/mac_portacl/LICENSE
new file mode 100644
index 0000000..c95c149
--- /dev/null
+++ b/tools/regression/mac/mac_portacl/LICENSE
@@ -0,0 +1,27 @@
+$FreeBSD$
+
+License for all mac_portacl regression tests:
+
+Copyright (c) 2009 Pawel Jakub Dawidek <pjd@FreeBSD.org>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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.
diff --git a/tools/regression/mac/mac_portacl/misc.sh b/tools/regression/mac/mac_portacl/misc.sh
new file mode 100755
index 0000000..0fabe15
--- /dev/null
+++ b/tools/regression/mac/mac_portacl/misc.sh
@@ -0,0 +1,97 @@
+#!/bin/sh
+# $FreeBSD$
+
+sysctl security.mac.portacl >/dev/null 2>&1
+if [ $? -ne 0 ]; then
+ echo "1..1"
+ echo "not ok 1 # MAC_PORTACL is unavailable."
+ exit 0
+fi
+
+ntest=1
+
+check_bind() {
+ idtype=${1}
+ name=${2}
+ proto=${3}
+ port=${4}
+
+ [ "${proto}" = "udp" ] && udpflag="-u"
+
+ out=`(
+ case "${idtype}" in
+ uid|gid)
+ ( echo -n | su -m ${name} -c "nc ${udpflag} -o -l 127.0.0.1 $port" 2>&1 ) &
+ ;;
+ jail)
+ kill $$
+ ;;
+ *)
+ kill $$
+ esac
+ sleep 0.3
+ echo | nc ${udpflag} -o 127.0.0.1 $port >/dev/null 2>&1
+ wait
+ )`
+ case "${out}" in
+ "nc: Permission denied"*|"nc: Operation not permitted"*)
+ echo fl
+ ;;
+ "")
+ echo ok
+ ;;
+ *)
+ echo ${out}
+ ;;
+ esac
+}
+
+bind_test() {
+ expect_without_rule=${1}
+ expect_with_rule=${2}
+ idtype=${3}
+ name=${4}
+ proto=${5}
+ port=${6}
+
+ sysctl security.mac.portacl.rules= >/dev/null
+ out=`check_bind ${idtype} ${name} ${proto} ${port}`
+ if [ "${out}" = "${expect_without_rule}" ]; then
+ echo "ok ${ntest}"
+ elif [ "${out}" = "ok" -o "${out}" = "fl" ]; then
+ echo "not ok ${ntest}"
+ else
+ echo "not ok ${ntest} # ${out}"
+ fi
+ ntest=$((ntest+1))
+
+ if [ "${idtype}" = "uid" ]; then
+ idstr=`id -u ${name}`
+ elif [ "${idtype}" = "gid" ]; then
+ idstr=`id -g ${name}`
+ else
+ idstr=${name}
+ fi
+ sysctl security.mac.portacl.rules=${idtype}:${idstr}:${proto}:${port} >/dev/null
+ out=`check_bind ${idtype} ${name} ${proto} ${port}`
+ if [ "${out}" = "${expect_with_rule}" ]; then
+ echo "ok ${ntest}"
+ elif [ "${out}" = "ok" -o "${out}" = "fl" ]; then
+ echo "not ok ${ntest}"
+ else
+ echo "not ok ${ntest} # ${out}"
+ fi
+ ntest=$((ntest+1))
+
+ sysctl security.mac.portacl.rules= >/dev/null
+}
+
+reserved_high=`sysctl -n net.inet.ip.portrange.reservedhigh`
+suser_exempt=`sysctl -n security.mac.portacl.suser_exempt`
+port_high=`sysctl -n security.mac.portacl.port_high`
+
+restore_settings() {
+ sysctl -n net.inet.ip.portrange.reservedhigh=${reserved_high} >/dev/null
+ sysctl -n security.mac.portacl.suser_exempt=${suser_exempt} >/dev/null
+ sysctl -n security.mac.portacl.port_high=${port_high} >/dev/null
+}
diff --git a/tools/regression/mac/mac_portacl/nobody.t b/tools/regression/mac/mac_portacl/nobody.t
new file mode 100755
index 0000000..c0754eb
--- /dev/null
+++ b/tools/regression/mac/mac_portacl/nobody.t
@@ -0,0 +1,67 @@
+#!/bin/sh
+# $FreeBSD$
+
+dir=`dirname $0`
+. ${dir}/misc.sh
+
+echo "1..64"
+
+# security.mac.portacl.suser_exempt value doesn't affect unprivileged users
+# behaviour.
+# mac_portacl has no impact on ports <= net.inet.ip.portrange.reservedhigh.
+
+sysctl security.mac.portacl.suser_exempt=1 >/dev/null
+sysctl net.inet.ip.portrange.reservedhigh=78 >/dev/null
+
+bind_test fl fl uid nobody tcp 77
+bind_test ok ok uid nobody tcp 7777
+bind_test fl fl uid nobody udp 77
+bind_test ok ok uid nobody udp 7777
+
+bind_test fl fl gid nobody tcp 77
+bind_test ok ok gid nobody tcp 7777
+bind_test fl fl gid nobody udp 77
+bind_test ok ok gid nobody udp 7777
+
+sysctl security.mac.portacl.suser_exempt=0 >/dev/null
+
+bind_test fl fl uid nobody tcp 77
+bind_test ok ok uid nobody tcp 7777
+bind_test fl fl uid nobody udp 77
+bind_test ok ok uid nobody udp 7777
+
+bind_test fl fl gid nobody tcp 77
+bind_test ok ok gid nobody tcp 7777
+bind_test fl fl gid nobody udp 77
+bind_test ok ok gid nobody udp 7777
+
+# Verify if security.mac.portacl.port_high works.
+
+sysctl security.mac.portacl.port_high=7778 >/dev/null
+
+bind_test fl fl uid nobody tcp 77
+bind_test fl ok uid nobody tcp 7777
+bind_test fl fl uid nobody udp 77
+bind_test fl ok uid nobody udp 7777
+
+bind_test fl fl gid nobody tcp 77
+bind_test fl ok gid nobody tcp 7777
+bind_test fl fl gid nobody udp 77
+bind_test fl ok gid nobody udp 7777
+
+# Verify if mac_portacl rules work.
+
+sysctl net.inet.ip.portrange.reservedhigh=76 >/dev/null
+sysctl security.mac.portacl.port_high=7776 >/dev/null
+
+bind_test fl ok uid nobody tcp 77
+bind_test ok ok uid nobody tcp 7777
+bind_test fl ok uid nobody udp 77
+bind_test ok ok uid nobody udp 7777
+
+bind_test fl ok gid nobody tcp 77
+bind_test ok ok gid nobody tcp 7777
+bind_test fl ok gid nobody udp 77
+bind_test ok ok gid nobody udp 7777
+
+restore_settings
diff --git a/tools/regression/mac/mac_portacl/root.t b/tools/regression/mac/mac_portacl/root.t
new file mode 100755
index 0000000..626bdfa
--- /dev/null
+++ b/tools/regression/mac/mac_portacl/root.t
@@ -0,0 +1,51 @@
+#!/bin/sh
+# $FreeBSD$
+
+dir=`dirname $0`
+. ${dir}/misc.sh
+
+echo "1..48"
+
+# Verify if security.mac.portacl.suser_exempt=1 really exempts super-user.
+
+sysctl security.mac.portacl.suser_exempt=1 >/dev/null
+
+bind_test ok ok uid root tcp 77
+bind_test ok ok uid root tcp 7777
+bind_test ok ok uid root udp 77
+bind_test ok ok uid root udp 7777
+
+bind_test ok ok gid root tcp 77
+bind_test ok ok gid root tcp 7777
+bind_test ok ok gid root udp 77
+bind_test ok ok gid root udp 7777
+
+# Verify if security.mac.portacl.suser_exempt=0 really doesn't exempt super-user.
+
+sysctl security.mac.portacl.suser_exempt=0 >/dev/null
+
+bind_test fl ok uid root tcp 77
+bind_test ok ok uid root tcp 7777
+bind_test fl ok uid root udp 77
+bind_test ok ok uid root udp 7777
+
+bind_test fl ok gid root tcp 77
+bind_test ok ok gid root tcp 7777
+bind_test fl ok gid root udp 77
+bind_test ok ok gid root udp 7777
+
+# Verify if security.mac.portacl.port_high works for super-user.
+
+sysctl security.mac.portacl.port_high=7778 >/dev/null
+
+bind_test fl ok uid root tcp 77
+bind_test fl ok uid root tcp 7777
+bind_test fl ok uid root udp 77
+bind_test fl ok uid root udp 7777
+
+bind_test fl ok gid root tcp 77
+bind_test fl ok gid root tcp 7777
+bind_test fl ok gid root udp 77
+bind_test fl ok gid root udp 7777
+
+restore_settings
diff --git a/tools/tools/nanobsd/rescue/AMD64 b/tools/tools/nanobsd/rescue/AMD64
index 02233bc..6a476a3 100644
--- a/tools/tools/nanobsd/rescue/AMD64
+++ b/tools/tools/nanobsd/rescue/AMD64
@@ -296,7 +296,6 @@ device ums # Mouse
device ural # Ralink Technology RT2500USB wireless NICs
device rum # Ralink Technology RT2501USB wireless NICs
device urio # Diamond Rio 500 MP3 player
-device uscanner # Scanners
# USB Serial devices
device ucom # Generic com ttys
device uark # Technologies ARK3116 based serial adapters
diff --git a/tools/tools/nanobsd/rescue/I386 b/tools/tools/nanobsd/rescue/I386
index 95b542c..3f8df45 100644
--- a/tools/tools/nanobsd/rescue/I386
+++ b/tools/tools/nanobsd/rescue/I386
@@ -310,7 +310,6 @@ device ural # Ralink Technology RT2500USB wireless NICs
device rum # Ralink Technology RT2501USB wireless NICs
device zyd # ZyDAS zb1211/zb1211b wireless NICs
device urio # Diamond Rio 500 MP3 player
-device uscanner # Scanners
# USB Serial devices
device ucom # Generic com ttys
device u3g # USB-based 3G modems (Option, Huawei, Sierra)
diff --git a/tools/tools/sysbuild/sysbuild.sh b/tools/tools/sysbuild/sysbuild.sh
index c9ae016..c3689ab 100644
--- a/tools/tools/sysbuild/sysbuild.sh
+++ b/tools/tools/sysbuild/sysbuild.sh
@@ -214,6 +214,7 @@ ports_build() (
ports_prefetch() (
(
set +x
+ true > /tmp/_.plist
ports_recurse $PORTS_WE_WANT
# Now checksump/fetch them
@@ -420,8 +421,7 @@ log_it Installworld
> /mnt/_.iw 2>&1
log_it distribution
-(cd /usr/src/etc && make -m /usr/src/share/mk distribution \
- DESTDIR=/mnt ${SRCCONF} ) \
+(cd /usr/src/etc && make -m /usr/src/share/mk distribution DESTDIR=/mnt ${SRCCONF} ) \
> /mnt/_.dist 2>&1
log_it Installkernel
@@ -512,6 +512,12 @@ if [ "x$SERCONS" != "xfalse" ] ; then
fi
log_it move config files
+(
+ cd /mnt
+ mkdir root/configfiles_dist
+ find ${CONFIGFILES} -print | cpio -dumpv root/configfiles_dist
+)
+
(cd / && find ${CONFIGFILES} -print | cpio -dumpv /mnt)
log_it final_root
diff --git a/usr.bin/ar/ar.c b/usr.bin/ar/ar.c
index e910e30..35a0380 100644
--- a/usr.bin/ar/ar.c
+++ b/usr.bin/ar/ar.c
@@ -108,8 +108,11 @@ main(int argc, char **argv)
if ((bsdar->progname = getprogname()) == NULL)
bsdar->progname = "ar";
- if (strcmp(bsdar->progname, "ranlib") == 0 ||
- strcmp(bsdar->progname, "bsdranlib") == 0) {
+ /* Act like ranlib if our name ends in "ranlib"; this
+ * accomodates arm-freebsd7.1-ranlib, bsdranlib, etc. */
+ len = strlen(bsdar->progname);
+ if (len >= strlen("ranlib") &&
+ strcmp(bsdar->progname + len - strlen("ranlib"), "ranlib") == 0) {
while ((opt = getopt_long(argc, argv, "tV", longopts,
NULL)) != -1) {
switch(opt) {
diff --git a/usr.bin/calendar/calendars/calendar.freebsd b/usr.bin/calendar/calendars/calendar.freebsd
index c46bc73..20baac2 100644
--- a/usr.bin/calendar/calendars/calendar.freebsd
+++ b/usr.bin/calendar/calendars/calendar.freebsd
@@ -28,6 +28,7 @@
01/22 Johann Visagie <wjv@FreeBSD.org> born in Cape Town, South Africa, 1970
01/23 Hideyuki KURASHINA <rushani@FreeBSD.org> born in Niigata, Japan, 1982
01/24 Matteo Riondato <matteo@FreeBSD.org> born in Padova, Italy, 1986
+01/24 Fabien Thomas <fabient@FreeBSD.org> born in Avignon, France, 1971
01/25 Bernd Walter <ticso@FreeBSD.org> born in Moers, Nordrhein-Westfalen, Germany, 1974
01/26 Andrew Gallatin <gallatin@FreeBSD.org> born in Buffalo, New York, United States, 1970
01/27 Nick Sayer <nsayer@FreeBSD.org> born in San Diego, California, United States, 1968
@@ -144,6 +145,7 @@
05/23 Munechika Sumikawa <sumikawa@FreeBSD.org> born in Osaka, Osaka, Japan, 1972
05/24 Duncan McLennan Barclay <dmlb@FreeBSD.org> born in London, Middlesex, United Kingdom, 1970
05/24 Oliver Lehmann <oliver@FreeBSD.org> born in Karlsburg, Germany, 1981
+05/25 Roman Divacky <rdivacky@FreeBSD.org> born in Brno, Czech Republic, 1983
05/25 Tom Rhodes <trhodes@FreeBSD.org> born in Ellwood City, Pennsylvania, United States, 1981
05/26 Jim Pirzyk <pirzyk@FreeBSD.org> born in Chicago, Illinois, United States, 1968
05/27 Ollivier Robert <roberto@FreeBSD.org> born in Paris, France, 1967
diff --git a/usr.bin/cut/cut.1 b/usr.bin/cut/cut.1
index a6ebddd..780b537 100644
--- a/usr.bin/cut/cut.1
+++ b/usr.bin/cut/cut.1
@@ -112,7 +112,7 @@ The
specifies fields, separated in the input by the field delimiter character
(see the
.Fl d
-option.)
+option).
Output fields are separated by a single occurrence of the field delimiter
character.
.It Fl n
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
index 079d272..3d8b93a 100644
--- a/usr.bin/kdump/kdump.c
+++ b/usr.bin/kdump/kdump.c
@@ -67,7 +67,9 @@ extern int errno;
#ifdef NETATALK
#include <netatalk/at.h>
#endif
+#include <arpa/inet.h>
#include <netinet/in.h>
+#include <ctype.h>
#include <dlfcn.h>
#include <err.h>
#include <grp.h>
@@ -98,6 +100,7 @@ void ktrsockaddr(struct sockaddr *);
void ktrstat(struct stat *);
void ktrstruct(char *, size_t);
void usage(void);
+void sockfamilyname(int);
const char *ioctlname(u_long);
int timestamp, decimal, fancy = 1, suppressdata, tail, threads, maxdata,
diff --git a/usr.bin/locate/locate/fastfind.c b/usr.bin/locate/locate/fastfind.c
index e132dbd..d9ab2d0 100644
--- a/usr.bin/locate/locate/fastfind.c
+++ b/usr.bin/locate/locate/fastfind.c
@@ -216,6 +216,8 @@ fastfind
count += c - OFFSET;
}
+ if (count < 0 || count > MAXPATHLEN)
+ errx(1, "corrupted database: %s", database);
/* overlay old path */
p = path + count;
foundchar = p - 1;
diff --git a/usr.bin/locate/locate/util.c b/usr.bin/locate/locate/util.c
index 944ca88..9cd02b0 100644
--- a/usr.bin/locate/locate/util.c
+++ b/usr.bin/locate/locate/util.c
@@ -237,7 +237,7 @@ getwm(p)
} u;
register int i;
- for (i = 0; i < INTSIZE; i++)
+ for (i = 0; i < (int)INTSIZE; i++)
u.buf[i] = *p++;
i = u.i;
@@ -245,7 +245,7 @@ getwm(p)
if (i > MAXPATHLEN || i < -(MAXPATHLEN)) {
i = ntohl(i);
if (i > MAXPATHLEN || i < -(MAXPATHLEN))
- errx(1, "integer out of +-MAXPATHLEN (%d): %d",
+ errx(1, "integer out of +-MAXPATHLEN (%d): %u",
MAXPATHLEN, abs(i) < abs(htonl(i)) ? i : htonl(i));
}
return(i);
@@ -270,7 +270,7 @@ getwf(fp)
if (word > MAXPATHLEN || word < -(MAXPATHLEN)) {
word = ntohl(word);
if (word > MAXPATHLEN || word < -(MAXPATHLEN))
- errx(1, "integer out of +-MAXPATHLEN (%d): %d",
+ errx(1, "integer out of +-MAXPATHLEN (%d): %u",
MAXPATHLEN, abs(word) < abs(htonl(word)) ? word :
htonl(word));
}
diff --git a/usr.bin/login/login.c b/usr.bin/login/login.c
index 549e015..2a42924 100644
--- a/usr.bin/login/login.c
+++ b/usr.bin/login/login.c
@@ -245,8 +245,8 @@ main(int argc, char *argv[])
(void)snprintf(tname, sizeof(tname), "%s??", _PATH_TTY);
ttyn = tname;
}
- if ((tty = strrchr(ttyn, '/')) != NULL)
- ++tty;
+ if (strncmp(ttyn, _PATH_DEV, sizeof _PATH_DEV - 1) == 0)
+ tty = ttyn + sizeof _PATH_DEV - 1;
else
tty = ttyn;
diff --git a/usr.bin/make/globals.h b/usr.bin/make/globals.h
index c2e1f11..6f75eaf 100644
--- a/usr.bin/make/globals.h
+++ b/usr.bin/make/globals.h
@@ -81,6 +81,7 @@ extern Boolean noExecute; /* True if should execute nothing */
extern Boolean allPrecious; /* True if every target is precious */
extern Boolean is_posix; /* .POSIX target seen */
extern Boolean mfAutoDeps; /* .MAKEFILEDEPS target seen */
+extern Boolean remakingMakefiles; /* True if remaking makefiles is in progress */
/* True if should continue on unaffected portions of the graph
* when have an error in one portion */
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c
index 6ccc59b..0e16506 100644
--- a/usr.bin/make/main.c
+++ b/usr.bin/make/main.c
@@ -124,6 +124,7 @@ Lst create = Lst_Initializer(create);
Boolean allPrecious; /* .PRECIOUS given on line by itself */
Boolean is_posix; /* .POSIX target seen */
Boolean mfAutoDeps; /* .MAKEFILEDEPS target seen */
+Boolean remakingMakefiles; /* True if remaking makefiles is in progress */
Boolean beSilent; /* -s flag */
Boolean beVerbose; /* -v flag */
Boolean beQuiet; /* -Q flag */
@@ -732,41 +733,6 @@ Remake_Makefiles(void)
Suff_FindDeps(gn);
/*
- * ! dependencies as well as
- * dependencies with .FORCE, .EXEC and .PHONY attributes
- * are skipped to prevent infinite loops
- */
- if (gn->type & (OP_FORCE | OP_EXEC | OP_PHONY)) {
- DEBUGF(MAKE, ("skipping (force, exec or phony).\n",
- gn->name));
- continue;
- }
-
- /*
- * Skip :: targets that have commands and no children
- * because such targets are always out-of-date
- */
- if ((gn->type & OP_DOUBLEDEP) &&
- !Lst_IsEmpty(&gn->commands) &&
- Lst_IsEmpty(&gn->children)) {
- DEBUGF(MAKE, ("skipping (doubledep, no sources "
- "and has commands).\n"));
- continue;
- }
-
- /*
- * Skip targets without sources and without commands
- */
- if (Lst_IsEmpty(&gn->commands) &&
- Lst_IsEmpty(&gn->children)) {
- DEBUGF(MAKE,
- ("skipping (no sources and no commands).\n"));
- continue;
- }
-
- DEBUGF(MAKE, ("\n"));
-
- /*
* -t, -q and -n has no effect unless the makefile is
* specified as one of the targets explicitly in the
* command line
@@ -787,7 +753,9 @@ Remake_Makefiles(void)
* Check and remake the makefile
*/
mtime = Dir_MTime(gn);
+ remakingMakefiles = TRUE;
Compat_Make(gn, gn);
+ remakingMakefiles = FALSE;
/*
* Restore -t, -q and -n behaviour
diff --git a/usr.bin/make/make.1 b/usr.bin/make/make.1
index 736f279..a4e837c 100644
--- a/usr.bin/make/make.1
+++ b/usr.bin/make/make.1
@@ -1629,7 +1629,7 @@ To prevent infinite loops the following source Makefile targets are ignored:
.Bl -bullet
.It
.Ic ::
-targets that have no prerequisites but have commands
+targets that have no prerequisites
.It
.Ic !
targets
diff --git a/usr.bin/make/make.c b/usr.bin/make/make.c
index 835e855..a6ddc85 100644
--- a/usr.bin/make/make.c
+++ b/usr.bin/make/make.c
@@ -211,11 +211,15 @@ Make_OODate(GNode *gn)
} else {
DEBUGF(MAKE, (".EXEC node..."));
}
- oodate = TRUE;
- } else if ((gn->mtime < gn->cmtime) ||
- ((gn->cmtime == 0) &&
- ((gn->mtime==0) || (gn->type & OP_DOUBLEDEP)))) {
+ if (remakingMakefiles) {
+ DEBUGF(MAKE, ("skipping (remaking makefiles)..."));
+ oodate = FALSE;
+ } else {
+ oodate = TRUE;
+ }
+ } else if (gn->mtime < gn->cmtime ||
+ (gn->cmtime == 0 && (gn->mtime == 0 || (gn->type & OP_DOUBLEDEP)))) {
/*
* A node whose modification time is less than that of its
* youngest child or that has no children (cmtime == 0) and
@@ -226,12 +230,24 @@ Make_OODate(GNode *gn)
if (gn->mtime < gn->cmtime) {
DEBUGF(MAKE, ("modified before source (%s)...",
gn->cmtime_gn ? gn->cmtime_gn->path : "???"));
+ oodate = TRUE;
} else if (gn->mtime == 0) {
DEBUGF(MAKE, ("non-existent and no sources..."));
+ if (remakingMakefiles && Lst_IsEmpty(&gn->commands)) {
+ DEBUGF(MAKE, ("skipping (no commands and remaking makefiles)..."));
+ oodate = FALSE;
+ } else {
+ oodate = TRUE;
+ }
} else {
DEBUGF(MAKE, (":: operator and no sources..."));
+ if (remakingMakefiles) {
+ DEBUGF(MAKE, ("skipping (remaking makefiles)..."));
+ oodate = FALSE;
+ } else {
+ oodate = TRUE;
+ }
}
- oodate = TRUE;
} else
oodate = FALSE;
diff --git a/usr.bin/ministat/ministat.c b/usr.bin/ministat/ministat.c
index 5873ca7..720922e 100644
--- a/usr.bin/ministat/ministat.c
+++ b/usr.bin/ministat/ministat.c
@@ -136,7 +136,7 @@ struct dataset {
double *points;
unsigned lpoints;
double sy, syy;
- int n;
+ unsigned n;
};
static struct dataset *
@@ -191,8 +191,6 @@ Avg(struct dataset *ds)
static double
Median(struct dataset *ds)
{
- int even, i;
- struct point *p1, *p2;
return (ds->points[ds->n / 2]);
}
@@ -317,8 +315,8 @@ static void
PlotSet(struct dataset *ds, int val)
{
struct plot *pl;
- struct point *pp;
- int i, j, m, x, n;
+ int i, j, m, x;
+ unsigned n;
int bar;
pl = &plot;
diff --git a/usr.bin/ncal/ncal.1 b/usr.bin/ncal/ncal.1
index ccb711b..5fa6131 100644
--- a/usr.bin/ncal/ncal.1
+++ b/usr.bin/ncal/ncal.1
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 23, 2005
+.Dd March 14, 2009
.Dt CAL 1
.Os
.Sh NAME
@@ -142,7 +142,3 @@ command and manual were written by
.Sh BUGS
The assignment of Julian\(enGregorian switching dates to
country codes is historically naive for many countries.
-.Pp
-The
-.Nm
-utility does not recognize multibyte characters.
diff --git a/usr.bin/ncal/ncal.c b/usr.bin/ncal/ncal.c
index 1b125d6..b9aaee8 100644
--- a/usr.bin/ncal/ncal.c
+++ b/usr.bin/ncal/ncal.c
@@ -40,6 +40,8 @@ static const char rcsid[] =
#include <sysexits.h>
#include <time.h>
#include <unistd.h>
+#include <wchar.h>
+#include <wctype.h>
/* Width of one month with backward compatibility */
#define MONTH_WIDTH_B_J 27
@@ -53,13 +55,13 @@ static const char rcsid[] =
typedef struct date date;
struct monthlines {
- char name[MAX_WIDTH + 1];
+ wchar_t name[MAX_WIDTH + 1];
char lines[7][MAX_WIDTH + 1];
char weeks[MAX_WIDTH + 1];
};
struct weekdays {
- char names[7][4];
+ wchar_t names[7][4];
};
/* The switches from Julian to Gregorian in some countries */
@@ -159,6 +161,7 @@ int nswitch; /* user defined switch date */
int nswitchb; /* switch date for backward compatibility */
char *center(char *s, char *t, int w);
+wchar_t *wcenter(wchar_t *s, wchar_t *t, int w);
void mkmonth(int year, int month, int jd_flag, struct monthlines * monthl);
void mkmonthb(int year, int month, int jd_flag, struct monthlines * monthl);
void mkweekdays(struct weekdays * wds);
@@ -418,9 +421,9 @@ printmonth(int y, int m, int jd_flag)
mkmonth(y, m - 1, jd_flag, &month);
mkweekdays(&wds);
- printf(" %s %d\n", month.name, y);
+ printf(" %ls %d\n", month.name, y);
for (i = 0; i != 7; i++)
- printf("%.2s%s\n", wds.names[i], month.lines[i]);
+ printf("%.2ls%s\n", wds.names[i], month.lines[i]);
if (flag_weeks)
printf(" %s\n", month.weeks);
}
@@ -430,7 +433,7 @@ printmonthb(int y, int m, int jd_flag)
{
struct monthlines month;
struct weekdays wds;
- char s[MAX_WIDTH], t[MAX_WIDTH];
+ wchar_t s[MAX_WIDTH], t[MAX_WIDTH];
int i;
int mw;
@@ -439,16 +442,17 @@ printmonthb(int y, int m, int jd_flag)
mw = jd_flag ? MONTH_WIDTH_B_J : MONTH_WIDTH_B;
- sprintf(s, "%s %d", month.name, y);
- printf("%s\n", center(t, s, mw));
+ swprintf(s, MAX_WIDTH, L"%ls %d", month.name, y);
+ wprintf(L"%ls\n", wcenter(t, s, mw));
if (jd_flag)
- printf(" %s %s %s %s %s %s %.2s\n", wds.names[6], wds.names[0],
+ wprintf(L" %ls %ls %ls %ls %ls %ls %.2ls\n",
+ wds.names[6], wds.names[0],
wds.names[1], wds.names[2], wds.names[3],
wds.names[4], wds.names[5]);
else
- printf("%s%s%s%s%s%s%.2s\n", wds.names[6], wds.names[0],
- wds.names[1], wds.names[2], wds.names[3],
+ wprintf(L"%ls%ls%ls%ls%ls%ls%.2ls\n", wds.names[6],
+ wds.names[0], wds.names[1], wds.names[2], wds.names[3],
wds.names[4], wds.names[5]);
for (i = 0; i != 6; i++)
@@ -475,17 +479,17 @@ printyear(int y, int jd_flag)
printf("%s\n", center(t, s, mpl * mw));
for (j = 0; j != 12; j += mpl) {
- printf(" %-*s%-*s",
+ printf(" %-*ls%-*ls",
mw, year[j].name,
mw, year[j + 1].name);
if (mpl == 3)
- printf("%s\n", year[j + 2].name);
+ printf("%ls\n", year[j + 2].name);
else
- printf("%-*s%s\n",
+ printf("%-*ls%ls\n",
mw, year[j + 2].name,
year[j + 3].name);
for (i = 0; i != 7; i++) {
- printf("%.2s%-*s%-*s",
+ printf("%.2ls%-*s%-*s",
wds.names[i],
mw, year[j].lines[i],
mw, year[j + 1].lines[i]);
@@ -518,6 +522,7 @@ printyearb(int y, int jd_flag)
struct monthlines year[12];
struct weekdays wds;
char s[80], t[80];
+ wchar_t ws[80], wt[80];
int i, j;
int mpl;
int mw;
@@ -532,17 +537,17 @@ printyearb(int y, int jd_flag)
printf("%s\n\n", center(t, s, mw * mpl + mpl));
for (j = 0; j != 12; j += mpl) {
- printf("%-*s ", mw, center(s, year[j].name, mw));
+ printf("%-*ls ", mw, wcenter(ws, year[j].name, mw));
if (mpl == 2)
- printf("%s\n", center(s, year[j + 1].name, mw));
+ printf("%ls\n", wcenter(ws, year[j + 1].name, mw));
else
- printf("%-*s %s\n", mw,
- center(s, year[j + 1].name, mw),
- center(t, year[j + 2].name, mw));
+ printf("%-*ls %ls\n", mw,
+ wcenter(ws, year[j + 1].name, mw),
+ wcenter(wt, year[j + 2].name, mw));
if (mpl == 2)
- printf(" %s %s %s %s %s %s %s "
- " %s %s %s %s %s %s %.2s\n",
+ wprintf(L" %ls %ls %ls %ls %ls %ls %ls "
+ " %ls %ls %ls %ls %ls %ls %.2ls\n",
wds.names[6], wds.names[0], wds.names[1],
wds.names[2], wds.names[3], wds.names[4],
wds.names[5],
@@ -550,9 +555,9 @@ printyearb(int y, int jd_flag)
wds.names[2], wds.names[3], wds.names[4],
wds.names[5]);
else
- printf("%s%s%s%s%s%s%s "
- "%s%s%s%s%s%s%s "
- "%s%s%s%s%s%s%.2s\n",
+ wprintf(L"%ls%ls%ls%ls%ls%ls%ls "
+ "%ls%ls%ls%ls%ls%ls%ls "
+ "%ls%ls%ls%ls%ls%ls%.2ls\n",
wds.names[6], wds.names[0], wds.names[1],
wds.names[2], wds.names[3], wds.names[4],
wds.names[5],
@@ -596,8 +601,9 @@ mkmonth(int y, int m, int jd_flag, struct monthlines *mlines)
/* Set name of month. */
memset(&tm, 0, sizeof(tm));
tm.tm_mon = m;
- strftime(mlines->name, sizeof(mlines->name), "%OB", &tm);
- mlines->name[0] = toupper((unsigned char)mlines->name[0]);
+ wcsftime(mlines->name, sizeof(mlines->name) / sizeof(mlines->name[0]),
+ L"%OB", &tm);
+ mlines->name[0] = towupper(mlines->name[0]);
/*
* Set first and last to the day number of the first day of this
@@ -688,8 +694,9 @@ mkmonthb(int y, int m, int jd_flag, struct monthlines *mlines)
/* Set name of month centered */
memset(&tm, 0, sizeof(tm));
tm.tm_mon = m;
- strftime(mlines->name, sizeof(mlines->name), "%OB", &tm);
- mlines->name[0] = toupper((unsigned char)mlines->name[0]);
+ wcsftime(mlines->name, sizeof(mlines->name) / sizeof(mlines->name[0]),
+ L"%OB", &tm);
+ mlines->name[0] = towupper(mlines->name[0]);
/*
* Set first and last to the day number of the first day of this
@@ -754,18 +761,18 @@ mkweekdays(struct weekdays *wds)
{
int i, len;
struct tm tm;
- char buf[20];
+ wchar_t buf[20];
memset(&tm, 0, sizeof(tm));
for (i = 0; i != 7; i++) {
tm.tm_wday = (i+1) % 7;
- strftime(buf, sizeof(buf), "%a", &tm);
- len = strlen(buf);
+ wcsftime(buf, sizeof(buf), L"%a", &tm);
+ len = wcslen(buf);
if (len > 2)
len = 2;
- strcpy(wds->names[i], " ");
- strncpy(wds->names[i] + 2 - len, buf, len);
+ wcscpy(wds->names[i], L" ");
+ wcsncpy(wds->names[i] + 2 - len, buf, len);
}
}
@@ -858,6 +865,17 @@ center(char *s, char *t, int w)
return (s);
}
+/* Center string t in string s of length w by putting enough leading blanks */
+wchar_t *
+wcenter(wchar_t *s, wchar_t *t, int w)
+{
+ char blanks[80];
+
+ memset(blanks, ' ', sizeof(blanks));
+ swprintf(s, MAX_WIDTH, L"%.*s%ls", (int)(w - wcslen(t)) / 2, blanks, t);
+ return (s);
+}
+
int
parsemonth(const char *s, int *m, int *y)
{
diff --git a/usr.bin/netstat/inet.c b/usr.bin/netstat/inet.c
index 9d82ef3..8be6840 100644
--- a/usr.bin/netstat/inet.c
+++ b/usr.bin/netstat/inet.c
@@ -257,7 +257,7 @@ pcblist_kvm(u_long off, char **bufp, int istcp)
if (istcp) {
if (inp->inp_ppcb == NULL)
bzero(&xt.xt_tp, sizeof xt.xt_tp);
- else if (inp->inp_vflag & INP_TIMEWAIT) {
+ else if (inp->inp_flags & INP_TIMEWAIT) {
bzero(&xt.xt_tp, sizeof xt.xt_tp);
xt.xt_tp.t_state = TCPS_TIME_WAIT;
} else
diff --git a/usr.bin/netstat/main.c b/usr.bin/netstat/main.c
index 6eb313a..8b25ff5 100644
--- a/usr.bin/netstat/main.c
+++ b/usr.bin/netstat/main.c
@@ -82,8 +82,8 @@ static struct nlist nl[] = {
{ .n_name = "_rt_tables"},
#define N_MRTSTAT 3
{ .n_name = "_mrtstat" },
-#define N_MFCTABLE 4
- { .n_name = "_mfctable" },
+#define N_MFCHASHTBL 4
+ { .n_name = "_mfchashtbl" },
#define N_VIFTABLE 5
{ .n_name = "_viftable" },
#define N_IPX 6
@@ -182,6 +182,8 @@ static struct nlist nl[] = {
{ .n_name = "_rip6stat" },
#define N_SCTPSTAT 53
{ .n_name = "_sctpstat" },
+#define N_MFCTABLESIZE 54
+ { .n_name = "_mfctablesize" },
{ .n_name = NULL },
};
@@ -550,7 +552,8 @@ main(int argc, char *argv[])
#endif
} else {
if (af == AF_INET || af == AF_UNSPEC)
- mroutepr(nl[N_MFCTABLE].n_value,
+ mroutepr(nl[N_MFCHASHTBL].n_value,
+ nl[N_MFCTABLESIZE].n_value,
nl[N_VIFTABLE].n_value);
#ifdef INET6
if (af == AF_INET6 || af == AF_UNSPEC)
diff --git a/usr.bin/netstat/mroute.c b/usr.bin/netstat/mroute.c
index dbce318..6ea4b58 100644
--- a/usr.bin/netstat/mroute.c
+++ b/usr.bin/netstat/mroute.c
@@ -67,124 +67,9 @@ __FBSDID("$FreeBSD$");
#include <stdlib.h>
#include "netstat.h"
-static void print_bw_meter(struct bw_meter *bw_meter, int *banner_printed);
-void
-mroutepr(u_long mfcaddr, u_long vifaddr)
-{
- struct mfc *mfctable[MFCTBLSIZ];
- struct vif viftable[MAXVIFS];
- struct mfc mfc, *m;
- struct vif *v;
- vifi_t vifi;
- int i;
- int banner_printed;
- int saved_numeric_addr;
- vifi_t maxvif = 0;
- size_t len;
-
- len = sizeof(mfctable);
- if (live) {
- if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, NULL,
- 0) < 0) {
- warn("sysctl: net.inet.ip.mfctable");
- return;
- }
- } else
- kread(mfcaddr, (char *)mfctable, sizeof(mfctable));
-
- len = sizeof(viftable);
- if (live) {
- if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL,
- 0) < 0) {
- warn("sysctl: net.inet.ip.viftable");
- return;
- }
- } else
- kread(vifaddr, (char *)viftable, sizeof(viftable));
-
- saved_numeric_addr = numeric_addr;
- numeric_addr = 1;
-
- banner_printed = 0;
- for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) {
- if (v->v_lcl_addr.s_addr == 0)
- continue;
-
- maxvif = vifi;
- if (!banner_printed) {
- printf("\nIPv4 Virtual Interface Table\n"
- " Vif Thresh Rate Local-Address "
- "Remote-Address Pkts-In Pkts-Out\n");
- banner_printed = 1;
- }
-
- printf(" %2u %6u %4d %-15.15s",
- /* opposite math of add_vif() */
- vifi, v->v_threshold, v->v_rate_limit * 1000 / 1024,
- routename(v->v_lcl_addr.s_addr));
- printf(" %-15.15s", (v->v_flags & VIFF_TUNNEL) ?
- routename(v->v_rmt_addr.s_addr) : "");
-
- printf(" %9lu %9lu\n", v->v_pkt_in, v->v_pkt_out);
- }
- if (!banner_printed)
- printf("\nIPv4 Virtual Interface Table is empty\n");
-
- banner_printed = 0;
- for (i = 0; i < MFCTBLSIZ; ++i) {
- m = mfctable[i];
- while(m) {
- /* XXX KVM */
- kread((u_long)m, (char *)&mfc, sizeof mfc);
-
- if (!banner_printed) {
- printf("\nIPv4 Multicast Forwarding Table\n"
- " Origin Group "
- " Packets In-Vif Out-Vifs:Ttls\n");
- banner_printed = 1;
- }
-
- printf(" %-15.15s", routename(mfc.mfc_origin.s_addr));
- printf(" %-15.15s", routename(mfc.mfc_mcastgrp.s_addr));
- printf(" %9lu", mfc.mfc_pkt_cnt);
- printf(" %3d ", mfc.mfc_parent);
- for (vifi = 0; vifi <= maxvif; vifi++) {
- if (mfc.mfc_ttls[vifi] > 0)
- printf(" %u:%u", vifi,
- mfc.mfc_ttls[vifi]);
- }
- printf("\n");
-
- /* Print the bw meter information */
- {
- struct bw_meter bw_meter, *bwm;
- int banner_printed2 = 0;
-
- bwm = mfc.mfc_bw_meter;
- while (bwm) {
- /* XXX KVM */
- kread((u_long)bwm, (char *)&bw_meter,
- sizeof bw_meter);
- print_bw_meter(&bw_meter,
- &banner_printed2);
- bwm = bw_meter.bm_mfc_next;
- }
-#if 0 /* Don't ever print it? */
- if (! banner_printed2)
- printf("\n No Bandwidth Meters\n");
-#endif
- }
-
- m = mfc.mfc_next;
- }
- }
- if (!banner_printed)
- printf("\nIPv4 Multicast Forwarding Table is empty\n");
-
- printf("\n");
- numeric_addr = saved_numeric_addr;
-}
+static void print_bw_meter(struct bw_meter *, int *);
+static void print_mfc(struct mfc *, int, int *);
static void
print_bw_meter(struct bw_meter *bw_meter, int *banner_printed)
@@ -262,6 +147,193 @@ print_bw_meter(struct bw_meter *bw_meter, int *banner_printed)
printf("\n");
}
+static void
+print_mfc(struct mfc *m, int maxvif, int *banner_printed)
+{
+ struct bw_meter bw_meter, *bwm;
+ int bw_banner_printed;
+ int error;
+ vifi_t vifi;
+
+ bw_banner_printed = 0;
+
+ if (! *banner_printed) {
+ printf("\nIPv4 Multicast Forwarding Table\n"
+ " Origin Group "
+ " Packets In-Vif Out-Vifs:Ttls\n");
+ *banner_printed = 1;
+ }
+
+ printf(" %-15.15s", routename(m->mfc_origin.s_addr));
+ printf(" %-15.15s", routename(m->mfc_mcastgrp.s_addr));
+ printf(" %9lu", m->mfc_pkt_cnt);
+ printf(" %3d ", m->mfc_parent);
+ for (vifi = 0; vifi <= maxvif; vifi++) {
+ if (m->mfc_ttls[vifi] > 0)
+ printf(" %u:%u", vifi, m->mfc_ttls[vifi]);
+ }
+ printf("\n");
+
+ /*
+ * XXX We break the rules and try to use KVM to read the
+ * bandwidth meters, they are not retrievable via sysctl yet.
+ */
+ bwm = m->mfc_bw_meter;
+ while (bwm != NULL) {
+ error = kread((u_long)bwm, (char *)&bw_meter,
+ sizeof(bw_meter));
+ if (error)
+ break;
+ print_bw_meter(&bw_meter, &bw_banner_printed);
+ bwm = bw_meter.bm_mfc_next;
+ }
+}
+
+void
+mroutepr(u_long pmfchashtbl, u_long pmfctablesize, u_long pviftbl)
+{
+ struct vif viftable[MAXVIFS];
+ struct vif *v;
+ struct mfc *m;
+ int banner_printed;
+ int saved_numeric_addr;
+ size_t len;
+ vifi_t vifi, maxvif;
+
+ saved_numeric_addr = numeric_addr;
+ numeric_addr = 1;
+
+ /*
+ * TODO:
+ * The VIF table will move to hanging off the struct if_info for
+ * each IPv4 configured interface. Currently it is statically
+ * allocated, and retrieved either using KVM or an opaque SYSCTL.
+ *
+ * This can't happen until the API documented in multicast(4)
+ * is itself refactored. The historical reason why VIFs use
+ * a separate ifindex space is entirely due to the legacy
+ * capability of the MROUTING code to create IPIP tunnels on
+ * the fly to support DVMRP. When gif(4) became available, this
+ * functionality was deprecated, as PIM does not use it.
+ */
+ maxvif = 0;
+
+ len = sizeof(viftable);
+ if (live) {
+ if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL,
+ 0) < 0) {
+ warn("sysctl: net.inet.ip.viftable");
+ return;
+ }
+ } else
+ kread(pviftbl, (char *)viftable, sizeof(viftable));
+
+ banner_printed = 0;
+ for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) {
+ if (v->v_lcl_addr.s_addr == 0)
+ continue;
+
+ maxvif = vifi;
+ if (!banner_printed) {
+ printf("\nIPv4 Virtual Interface Table\n"
+ " Vif Thresh Local-Address "
+ "Remote-Address Pkts-In Pkts-Out\n");
+ banner_printed = 1;
+ }
+
+ printf(" %2u %6u %-15.15s",
+ /* opposite math of add_vif() */
+ vifi, v->v_threshold,
+ routename(v->v_lcl_addr.s_addr));
+ printf(" %-15.15s", (v->v_flags & VIFF_TUNNEL) ?
+ routename(v->v_rmt_addr.s_addr) : "");
+
+ printf(" %9lu %9lu\n", v->v_pkt_in, v->v_pkt_out);
+ }
+ if (!banner_printed)
+ printf("\nIPv4 Virtual Interface Table is empty\n");
+
+ banner_printed = 0;
+
+ /*
+ * TODO:
+ * The MFC table will move into the AF_INET radix trie in future.
+ * In 8.x, it becomes a dynamically allocated structure referenced
+ * by a hashed LIST, allowing more than 256 entries w/o kernel tuning.
+ *
+ * If retrieved via opaque SYSCTL, the kernel will coalesce it into
+ * a static table for us.
+ * If retrieved via KVM, the hash list pointers must be followed.
+ */
+ if (live) {
+ struct mfc *mfctable;
+
+ len = 0;
+ if (sysctlbyname("net.inet.ip.mfctable", NULL, &len, NULL,
+ 0) < 0) {
+ warn("sysctl: net.inet.ip.mfctable");
+ return;
+ }
+
+ mfctable = malloc(len);
+ if (mfctable == NULL) {
+ warnx("malloc %lu bytes", (u_long)len);
+ return;
+ }
+ if (sysctlbyname("net.inet.ip.mfctable", mfctable, &len, NULL,
+ 0) < 0) {
+ free(mfctable);
+ warn("sysctl: net.inet.ip.mfctable");
+ return;
+ }
+
+ m = mfctable;
+ while (len >= sizeof(*m)) {
+ print_mfc(m++, maxvif, &banner_printed);
+ len -= sizeof(*m);
+ }
+ if (len != 0)
+ warnx("print_mfc: %lu trailing bytes", (u_long)len);
+
+ free(mfctable);
+ } else {
+ LIST_HEAD(, mfc) *mfchashtbl;
+ u_long i, mfctablesize;
+ struct mfc mfc;
+ int error;
+
+ error = kread(pmfctablesize, (char *)&mfctablesize,
+ sizeof(u_long));
+ if (error) {
+ warn("kread: mfctablesize");
+ return;
+ }
+
+ len = sizeof(*mfchashtbl) * mfctablesize;
+ mfchashtbl = malloc(len);
+ if (mfchashtbl == NULL) {
+ warnx("malloc %lu bytes", (u_long)len);
+ return;
+ }
+ kread(pmfchashtbl, (char *)&mfchashtbl, len);
+
+ for (i = 0; i < mfctablesize; i++) {
+ LIST_FOREACH(m, &mfchashtbl[i], mfc_hash) {
+ kread((u_long)m, (char *)&mfc, sizeof(mfc));
+ print_mfc(m, maxvif, &banner_printed);
+ }
+ }
+
+ free(mfchashtbl);
+ }
+
+ if (!banner_printed)
+ printf("\nIPv4 Multicast Forwarding Table is empty\n");
+
+ printf("\n");
+ numeric_addr = saved_numeric_addr;
+}
+
void
mrt_stats(u_long mstaddr)
{
diff --git a/usr.bin/netstat/netstat.h b/usr.bin/netstat/netstat.h
index da76ff1..483bd6c 100644
--- a/usr.bin/netstat/netstat.h
+++ b/usr.bin/netstat/netstat.h
@@ -160,6 +160,6 @@ void tp_protopr(u_long, const char *, int, int);
void tp_inproto(u_long);
void tp_stats(caddr_t, caddr_t);
-void mroutepr(u_long, u_long);
+void mroutepr(u_long, u_long, u_long);
void mrt_stats(u_long);
void bpf_stats(char *);
diff --git a/usr.bin/su/su.c b/usr.bin/su/su.c
index 36d8326..5dcb24a 100644
--- a/usr.bin/su/su.c
+++ b/usr.bin/su/su.c
@@ -231,7 +231,7 @@ main(int argc, char *argv[])
if (strlen(user) > MAXLOGNAME - 1) {
#ifdef USE_BSM_AUDIT
if (audit_submit(AUE_su, auid,
- 1, EPERM, "username too long: '%s'", user))
+ EPERM, 1, "username too long: '%s'", user))
errx(1, "Permission denied");
#endif
errx(1, "username too long");
@@ -264,7 +264,7 @@ main(int argc, char *argv[])
pwd = getpwuid(ruid);
if (pwd == NULL) {
#ifdef USE_BSM_AUDIT
- if (audit_submit(AUE_su, auid, 1, EPERM,
+ if (audit_submit(AUE_su, auid, EPERM, 1,
"unable to determine invoking subject: '%s'", username))
errx(1, "Permission denied");
#endif
@@ -305,7 +305,7 @@ main(int argc, char *argv[])
retcode = pam_authenticate(pamh, 0);
if (retcode != PAM_SUCCESS) {
#ifdef USE_BSM_AUDIT
- if (audit_submit(AUE_su, auid, 1, EPERM, "bad su %s to %s on %s",
+ if (audit_submit(AUE_su, auid, EPERM, 1, "bad su %s to %s on %s",
username, user, mytty))
errx(1, "Permission denied");
#endif
@@ -326,7 +326,7 @@ main(int argc, char *argv[])
pwd = getpwnam(user);
if (pwd == NULL) {
#ifdef USE_BSM_AUDIT
- if (audit_submit(AUE_su, auid, 1, EPERM,
+ if (audit_submit(AUE_su, auid, EPERM, 1,
"unknown subject: %s", user))
errx(1, "Permission denied");
#endif
@@ -342,7 +342,7 @@ main(int argc, char *argv[])
aerr = pam_strerror(pamh, retcode);
if (aerr == NULL)
aerr = "Unknown PAM error";
- if (audit_submit(AUE_su, auid, 1, EPERM,
+ if (audit_submit(AUE_su, auid, EPERM, 1,
"pam_chauthtok: %s", aerr))
errx(1, "Permission denied");
#endif
@@ -353,7 +353,7 @@ main(int argc, char *argv[])
}
if (retcode != PAM_SUCCESS) {
#ifdef USE_BSM_AUDIT
- if (audit_submit(AUE_su, auid, 1, EPERM, "pam_acct_mgmt: %s",
+ if (audit_submit(AUE_su, auid, EPERM, 1, "pam_acct_mgmt: %s",
pam_strerror(pamh, retcode)))
errx(1, "Permission denied");
#endif
@@ -368,7 +368,7 @@ main(int argc, char *argv[])
else {
if (ruid != 0) {
#ifdef USE_BSM_AUDIT
- if (audit_submit(AUE_su, auid, 1, EPERM,
+ if (audit_submit(AUE_su, auid, EPERM, 1,
"only root may use -c"))
errx(1, "Permission denied");
#endif
diff --git a/usr.bin/systat/netstat.c b/usr.bin/systat/netstat.c
index 0bafc5a..14fc495 100644
--- a/usr.bin/systat/netstat.c
+++ b/usr.bin/systat/netstat.c
@@ -222,7 +222,7 @@ again:
if (nports && !checkport(&inpcb))
continue;
if (istcp) {
- if (inpcb.inp_vflag & INP_TIMEWAIT) {
+ if (inpcb.inp_flags & INP_TIMEWAIT) {
bzero(&sockb, sizeof(sockb));
enter_kvm(&inpcb, &sockb, TCPS_TIME_WAIT,
"tcp");
diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile
index c9fefd8..d8659a7 100644
--- a/usr.sbin/Makefile
+++ b/usr.sbin/Makefile
@@ -129,8 +129,6 @@ SUBDIR= ${_ac} \
powerd \
${_ppp} \
${_pppctl} \
- ${_pppd} \
- ${_pppstats} \
${_praliases} \
${_praudit} \
procctl \
@@ -166,8 +164,6 @@ SUBDIR= ${_ac} \
setfmac \
setpmac \
${_sicontrol} \
- ${_sliplogin} \
- ${_slstat} \
smbmsg \
snapinfo \
${_spkrtest} \
@@ -183,6 +179,7 @@ SUBDIR= ${_ac} \
${_traceroute6} \
trpt \
tzsetup \
+ ${_uathload} \
ugidfw \
${_usbdevs} \
${_usbconfig} \
@@ -363,8 +360,6 @@ _portsnap= portsnap
.if ${MK_PPP} != "no"
_ppp= ppp
#_pppctl handled below
-_pppd= pppd
-_pppstats= pppstats
.endif
.if ${MK_QUOTAS} != "no"
@@ -385,11 +380,6 @@ _praliases= praliases
_sendmail= sendmail
.endif
-.if ${MK_SLIP} != "no"
-_sliplogin= sliplogin
-_slstat= slstat
-.endif
-
.if ${MK_SYSINSTALL} != "no"
.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" || \
${MACHINE_ARCH} == "sparc64"
@@ -406,6 +396,9 @@ _crunch= crunch
.endif
.if ${MK_USB} != "no"
+.if ${MACHINE_ARCH} != "ia64"
+_uathload= uathload
+.endif
#_usbdevs= usbdevs
_usbconfig= usbconfig
.endif
diff --git a/usr.sbin/chown/chgrp.1 b/usr.sbin/chown/chgrp.1
index 0b3a789..71b6806 100644
--- a/usr.sbin/chown/chgrp.1
+++ b/usr.sbin/chown/chgrp.1
@@ -61,7 +61,7 @@ The following options are available:
If the
.Fl R
option is specified, symbolic links on the command line are followed.
-(Symbolic links encountered in the tree traversal are not followed).
+(Symbolic links encountered in the tree traversal are not followed.)
.It Fl L
If the
.Fl R
diff --git a/usr.sbin/eeprom/ofw_options.c b/usr.sbin/eeprom/ofw_options.c
index c7a8dbd..eb7437f 100644
--- a/usr.sbin/eeprom/ofw_options.c
+++ b/usr.sbin/eeprom/ofw_options.c
@@ -52,18 +52,18 @@ __FBSDID("$FreeBSD$");
struct ofwo_extabent {
const char *ex_prop;
- int (*ex_handler)(struct ofwo_extabent *, int, const void *,
- int, const char *);
+ int (*ex_handler)(const struct ofwo_extabent *, int,
+ const void *, int, const char *);
};
-static int ofwo_oemlogo(struct ofwo_extabent *, int, const void *, int,
- const char *);
-static int ofwo_secmode(struct ofwo_extabent *, int, const void *, int,
- const char *);
-static int ofwo_secpwd(struct ofwo_extabent *, int, const void *, int,
- const char *);
+static int ofwo_oemlogo(const struct ofwo_extabent *, int, const void *,
+ int, const char *);
+static int ofwo_secmode(const struct ofwo_extabent *, int, const void *,
+ int, const char *);
+static int ofwo_secpwd(const struct ofwo_extabent *, int, const void *,
+ int, const char *);
-static struct ofwo_extabent ofwo_extab[] = {
+static const struct ofwo_extabent const ofwo_extab[] = {
{ "oem-logo", ofwo_oemlogo },
{ "security-mode", ofwo_secmode },
{ "security-password", ofwo_secpwd },
@@ -81,8 +81,8 @@ ofwo_printprop(const char *prop, const char* buf, int buflen)
}
static int
-ofwo_oemlogo(struct ofwo_extabent *exent, int fd, const void *buf, int buflen,
- const char *val)
+ofwo_oemlogo(const struct ofwo_extabent *exent, int fd, const void *buf,
+ int buflen, const char *val)
{
int lfd;
char logo[OFWO_LOGO + 1];
@@ -117,8 +117,8 @@ ofwo_oemlogo(struct ofwo_extabent *exent, int fd, const void *buf, int buflen,
}
static int
-ofwo_secmode(struct ofwo_extabent *exent, int fd, const void *buf, int buflen,
- const char *val)
+ofwo_secmode(const struct ofwo_extabent *exent, int fd, const void *buf,
+ int buflen, const char *val)
{
int res;
@@ -145,8 +145,8 @@ ofwo_secmode(struct ofwo_extabent *exent, int fd, const void *buf, int buflen,
}
static int
-ofwo_secpwd(struct ofwo_extabent *exent, int fd __unused,
- const void *buf __unused, __unused int buflen, const char *val)
+ofwo_secpwd(const struct ofwo_extabent *exent, int fd, const void *buf,
+ int buflen, const char *val)
{
void *pbuf;
int len, pblen, rv;
@@ -246,14 +246,14 @@ ofwo_dump(void)
int fd, len, nlen, pblen;
phandle_t optnode;
char prop[OFWO_MAXPROP + 1];
- struct ofwo_extabent *ex;
+ const struct ofwo_extabent *ex;
pblen = 0;
pbuf = NULL;
fd = ofw_open(O_RDONLY);
optnode = ofw_optnode(fd);
for (nlen = ofw_firstprop(fd, optnode, prop, sizeof(prop)); nlen != 0;
- nlen = ofw_nextprop(fd, optnode, prop, prop, sizeof(prop))) {
+ nlen = ofw_nextprop(fd, optnode, prop, prop, sizeof(prop))) {
len = ofw_getprop_alloc(fd, optnode, prop, &pbuf, &pblen, 1);
if (len < 0)
continue;
@@ -277,7 +277,7 @@ ofwo_action(const char *prop, const char *val)
{
void *pbuf;
int fd, len, pblen, rv;
- struct ofwo_extabent *ex;
+ const struct ofwo_extabent *ex;
pblen = 0;
rv = EX_OK;
@@ -300,7 +300,7 @@ ofwo_action(const char *prop, const char *val)
rv = (*ex->ex_handler)(ex, fd, pbuf, len, val);
else if (val)
rv = ofwo_setstr(fd, pbuf, len, prop, val);
- else
+ else
ofwo_printprop(prop, (char *)pbuf, len);
out:
if (pbuf != NULL)
diff --git a/usr.sbin/fifolog/fifolog_create/fifolog.1 b/usr.sbin/fifolog/fifolog_create/fifolog.1
index e754577..7db58e7 100644
--- a/usr.sbin/fifolog/fifolog_create/fifolog.1
+++ b/usr.sbin/fifolog/fifolog_create/fifolog.1
@@ -28,7 +28,7 @@
.Os
.Dt FIFOLOG 1
.Sh NAME
-.Nm fifolog_create , fifolog_write , fifolog_read
+.Nm fifolog_create , fifolog_writer , fifolog_reader
.Nd "initialize, write, seek and extract data from a fifolog"
.Sh SYNOPSIS
.Nm fifolog_create
@@ -84,7 +84,7 @@ of hand-work all but the first record can be easily recovered.)
If the
.Ar file
does not already exist,
-.Nm
+.Nm fifolog_create
will attempt to create and
.Xr ftruncate 2
it to the specified size, defaulting to 86400 records of 512 bytes
diff --git a/usr.sbin/gstat/gstat.8 b/usr.sbin/gstat/gstat.8
index d062025..9ac6789 100644
--- a/usr.sbin/gstat/gstat.8
+++ b/usr.sbin/gstat/gstat.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 20, 2006
+.Dd March 12, 2009
.Dt GSTAT 8
.Os
.Sh NAME
@@ -32,7 +32,7 @@
.Nd print statistics about GEOM disks
.Sh SYNOPSIS
.Nm
-.Op Fl acd
+.Op Fl abcd
.Op Fl f Ar filter
.Op Fl I Ar interval
.Sh DESCRIPTION
@@ -47,7 +47,9 @@ The options are as follows:
.It Fl a
Only display providers that are at least 0.1% busy.
.It Fl b
-Batch mode. Collect numbers, print and exit.
+Batch mode.
+Collect numbers, print and exit.
+Default if stdout is not a tty.
.It Fl c
Enable display of
.Xr geom 4
@@ -92,15 +94,3 @@ A
.Nm
utility appeared in
.Fx 5.0 .
-.Sh BUGS
-The
-.Nm
-utility only works interactively.
-It should probably detect when it is run non-interactively and produce
-simple
-.Tn ASCII
-text output.
-Otherwise, this utility should probably be folded into
-.Xr systat 1
-which only works interactively and is the obvious utility to run for
-various other forms of system statistics.
diff --git a/usr.sbin/gstat/gstat.c b/usr.sbin/gstat/gstat.c
index bef33ab..39054eb 100644
--- a/usr.sbin/gstat/gstat.c
+++ b/usr.sbin/gstat/gstat.c
@@ -99,6 +99,10 @@ main(int argc, char **argv)
maxx = -1;
curx = -1;
loop = 1;
+ /* Turn on batch mode if output is not tty. */
+ if (!isatty(fileno(stdout)))
+ flag_b = 1;
+
f_s[0] = '\0';
while ((i = getopt(argc, argv, "adcf:I:b")) != -1) {
switch (i) {
@@ -318,9 +322,11 @@ main(int argc, char **argv)
if (!flag_b)
attron(COLOR_PAIR(i));
PRINTMSG(" %6.1lf", (double)ld[7]);
- if (!flag_b)
+ if (!flag_b) {
attroff(COLOR_PAIR(i));
- PRINTMSG("|");
+ PRINTMSG("|");
+ } else
+ PRINTMSG(" ");
if (gid == NULL) {
PRINTMSG(" ??");
} else if (gid->lg_what == ISPROVIDER) {
diff --git a/usr.sbin/jexec/jexec.c b/usr.sbin/jexec/jexec.c
index 9d788dd..7237b5a 100644
--- a/usr.sbin/jexec/jexec.c
+++ b/usr.sbin/jexec/jexec.c
@@ -119,8 +119,8 @@ lookup_jail(int jid, char *jailname)
j = len;
for (i = 0; i < 4; i++) {
- if (len <= 0)
- exit(0);
+ if (len == 0)
+ return (-1);
p = q = malloc(len);
if (p == NULL)
err(1, "malloc()");
@@ -174,27 +174,21 @@ lookup_jail(int jid, char *jailname)
/* NOTREACHED */
break;
}
- /* Possible match. */
- if (id > 0) {
- /* Do we have a jail ID to match as well? */
- if (jid > 0) {
- if (jid == id) {
- xid = id;
- count++;
- }
- } else {
- xid = id;
- count++;
- }
+ /* Possible match; see if we have a jail ID to match as well. */
+ if (id > 0 && (jid <= 0 || id == jid)) {
+ xid = id;
+ count++;
}
}
free(p);
- if (count != 1)
+ if (count == 1)
+ return (xid);
+ else if (count > 1)
errx(1, "Could not uniquely identify the jail.");
-
- return (xid);
+ else
+ return (-1);
}
#define GET_USER_INFO do { \
diff --git a/usr.sbin/mergemaster/mergemaster.8 b/usr.sbin/mergemaster/mergemaster.8
index aaf7e54..2bff4be 100644
--- a/usr.sbin/mergemaster/mergemaster.8
+++ b/usr.sbin/mergemaster/mergemaster.8
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd January 2, 2009
+.Dd March 18, 2009
.Dt MERGEMASTER 8
.Os
.Sh NAME
@@ -32,14 +32,14 @@
.Nd merge configuration files, et al during an upgrade
.Sh SYNOPSIS
.Nm
-.Op Fl achiprsvCPU
-.Op Fl A Ar Target architecture
-.Op Fl D Ar /destdir/path
+.Op Fl scrvahipFCPU
.Op Fl m Ar /path/to/sources
.Op Fl t Ar /path/to/temp/root
.Op Fl d
.Op Fl u Ar N
.Op Fl w Ar N
+.Op Fl A Ar Target architecture
+.Op Fl D Ar /destdir/path
.Sh DESCRIPTION
The
.Nm
@@ -82,15 +82,23 @@ merge by hand later.
By default it creates the temporary root in
.Pa /var/tmp/temproot
and compares the
-.Xr cvs 1
-version $Id/$FreeBSD strings for files that have them, deleting
+Version Control System (VCS) Id strings ($FreeBSD)
+for files that have them, deleting
the temporary file if the strings match.
If there is
-no $Id string, or if the strings are different it
+no Id string, or if the strings are different it
compares the files themselves.
You can
-also specify that the script ignore the $Id strings and
-compare every file.
+also specify that the script ignore the Id strings and
+compare every file with the
+.Op Fl s
+option.
+Using the
+.Op Fl F
+option
+.Nm
+will install the new file for you if they differ only by
+VCS strings.
.Pp
The merge menu option is designed to let you easily combine your
customizations from the old version of a file into the new one.
@@ -117,11 +125,13 @@ After
installing an updated version of this file you should
probably run
.Xr pwd_mkdb 8
-with the -p option to rebuild your password databases
+with the
+.Op Fl p
+option to rebuild your password databases
and recreate
.Pa /etc/passwd .
.Pp
-The script uses the owner and group id's
+The script uses the owner and group ids
that the files are created with by
.Pa /usr/src/etc/Makefile ,
and file permissions as specified by the umask.
@@ -158,9 +168,9 @@ and therefore can override both files.
The options are as follows:
.Bl -tag -width Fl
.It Fl s
-Perform a strict comparison, diff'ing every pair of files.
+Perform a strict comparison, diffing every pair of files.
This comparison is performed line by line,
-without regard to CVS $Id's.
+without regard to VCS Ids.
.It Fl c
Use context diffs instead of unified diffs.
.It Fl r
@@ -189,8 +199,11 @@ directory exists, it creates a new one in a previously
non-existent directory.
This option unsets the verbose flag,
but is compatible with all other options.
-Setting -a makes
--w superfluous.
+Setting
+.Op Fl a
+makes
+.Op Fl w
+superfluous.
.It Fl h
Display usage and help information.
.It Fl i
@@ -202,6 +215,9 @@ Compares only files known to be essential to the success of
{build|install}world,
including
.Pa /etc/make.conf .
+.It Fl F
+If the files differ only by VCS Id ($FreeBSD)
+install the new file.
.It Fl C
After a standard
.Nm
@@ -213,6 +229,8 @@ Preserve files that you replace in
or another directory you specify in your
.Nm
rc file.
+.It Fl U
+Attempt to auto upgrade files that have not been user modified.
.It Fl m Ar /path/to/sources
Specify the path to the directory where you want to do the
.Xr make 1 .
@@ -234,7 +252,9 @@ instead of the default
.It Fl d
Add the date and time to the name of the temporary
root directory.
-If -t is specified, this option must
+If
+.Op Fl t
+is specified, this option must
follow it if you want the date added too.
.It Fl u Ar N
Specify a numeric umask.
@@ -250,8 +270,6 @@ Specify an alternative
architecture name.
.It Fl D Ar /path
Specify the destination directory for the installed files.
-.It Fl U
-Attempt to auto upgrade files that have not been user modified.
.El
.Sh ENVIRONMENT
The
@@ -314,12 +332,15 @@ with all values commented out:
# Specify the destination directory for the installed files
#DESTDIR=
#
-# Strict comparison bypasses the CVS $Id tests and compares every file
+# Strict comparison skips the VCS Id test and compares every file
#STRICT=no
#
# Type of diff, such as unified, context, etc.
#DIFF_FLAG='-u'
#
+# Install the new file if it differs only by VCS Id ($FreeBSD)
+#FREEBSD_ID=
+#
# Verbose mode includes more details and additional checks
#VERBOSE=
#
@@ -345,7 +366,7 @@ with all values commented out:
#IGNORE_FILES='/etc/motd /etc/printcap foo bar'
#
# Additional options for diff. This will get unset when using -s.
-#DIFF_OPTIONS='-I$\&FreeBSD:.*[$]' # Ignores CVS Id tags
+#DIFF_OPTIONS='-Bb' # Ignore changes in whitespace
#
# Location to store the list of mtree values for AUTO_UPGRADE purposes
#MTREEDB='/var/db'
@@ -382,7 +403,7 @@ Typically all you will need to do is type
.Nm
at the prompt and the script will do all the work for you.
.Pp
-To use context diff's and have
+To use context diffs and have
.Nm
explain more things as it goes along, use:
.Pp
@@ -401,7 +422,6 @@ comparison, use:
.Pp
.Dl # mergemaster -sw 110
.Sh SEE ALSO
-.Xr cvs 1 ,
.Xr diff 1 ,
.Xr make 1 ,
.Xr more 1 ,
diff --git a/usr.sbin/mergemaster/mergemaster.sh b/usr.sbin/mergemaster/mergemaster.sh
index 2f2f55b..e444996 100755
--- a/usr.sbin/mergemaster/mergemaster.sh
+++ b/usr.sbin/mergemaster/mergemaster.sh
@@ -15,8 +15,8 @@ PATH=/bin:/usr/bin:/usr/sbin
display_usage () {
VERSION_NUMBER=`grep "[$]FreeBSD:" $0 | cut -d ' ' -f 4`
echo "mergemaster version ${VERSION_NUMBER}"
- echo 'Usage: mergemaster [-scrvahipCP] [-m /path]'
- echo ' [-t /path] [-d] [-u N] [-w N] [-D /path]'
+ echo 'Usage: mergemaster [-scrvahipFCPU]'
+ echo ' [-m /path] [-t /path] [-d] [-u N] [-w N] [-A arch] [-D /path]'
echo "Options:"
echo " -s Strict comparison (diff every pair of files)"
echo " -c Use context diff instead of unified diff"
@@ -26,8 +26,11 @@ display_usage () {
echo " -h Display more complete help"
echo ' -i Automatically install files that do not exist in destination directory'
echo ' -p Pre-buildworld mode, only compares crucial files'
+ echo ' -F Install files that differ only by revision control Id ($FreeBSD)'
echo ' -C Compare local rc.conf variables to the defaults'
echo ' -P Preserve files that are overwritten'
+ echo " -U Attempt to auto upgrade files that have not been user modified"
+ echo ''
echo " -m /path/directory Specify location of source to do the make in"
echo " -t /path/directory Specify temp root directory"
echo " -d Add date and time to directory name (e.g., /var/tmp/temproot.`date +%m%d.%H.%M`)"
@@ -35,7 +38,6 @@ display_usage () {
echo " -w N Specify a screen width in columns to sdiff"
echo " -A architecture Alternative architecture name to pass to make"
echo ' -D /path/directory Specify the destination directory to install files to'
- echo " -U Attempt to auto upgrade files that have not been user modified."
echo ''
}
@@ -263,11 +265,14 @@ MTREEFILE="${MTREEDB}/mergemaster.mtree"
# Check the command line options
#
-while getopts ":ascrvhipCPm:t:du:w:D:A:U" COMMAND_LINE_ARGUMENT ; do
+while getopts ":ascrvhipCPm:t:du:w:D:A:FU" COMMAND_LINE_ARGUMENT ; do
case "${COMMAND_LINE_ARGUMENT}" in
A)
ARCHSTRING='TARGET_ARCH='${OPTARG}
;;
+ F)
+ FREEBSD_ID=yes
+ ;;
U)
AUTO_UPGRADE=yes
;;
@@ -671,7 +676,7 @@ find ${TEMPROOT} -type f -size 0 -delete 2>/dev/null
# Build the mtree database in a temporary location.
MTREENEW=`mktemp -t mergemaster.mtree`
case "${PRE_WORLD}" in
-'') mtree -ci -p ${TEMPROOT} -k size,md5digest > ${DESTDIR}${MTREENEW} 2>/dev/null
+'') mtree -ci -p ${TEMPROOT} -k size,md5digest > ${MTREENEW} 2>/dev/null
;;
*) # We don't want to mess with the mtree database on a pre-world run.
;;
@@ -1020,6 +1025,19 @@ for COMPFILE in `find . -type f -size +0`; do
# Use more if not.
# Use unified diffs by default. Context diffs give me a headache. :)
#
+ # If the user chose the -F option, test for that before proceeding
+ #
+ if [ -n "$FREEBSD_ID" ]; then
+ if diff -q -I'[$]FreeBSD:.*$' "${DESTDIR}${COMPFILE#.}" "${COMPFILE}" > \
+ /dev/null 2>&1; then
+ if mm_install "${COMPFILE}"; then
+ echo "*** Updated revision control Id for ${DESTDIR}${COMPFILE#.}"
+ else
+ echo "*** Problem installing ${COMPFILE}, it will remain to merge by hand later"
+ fi
+ continue
+ fi
+ fi
case "${AUTO_RUN}" in
'')
# prompt user to install/delete/merge changes
@@ -1032,15 +1050,15 @@ for COMPFILE in `find . -type f -size +0`; do
esac # Auto run test
fi # Yes, the files are different
fi # Yes, the file still remains to be checked
-done # This is for the do way up there at the beginning of the comparison
+done # This is for the for way up there at the beginning of the comparison
echo ''
echo "*** Comparison complete"
-if [ -f "${DESTDIR}${MTREENEW}" ]; then
+if [ -f "${MTREENEW}" ]; then
echo "*** Saving mtree database for future upgrades"
- test -e "${MTREEFILE}" && unlink ${MTREEFILE}
- mv ${DESTDIR}${MTREENEW} ${DESTDIR}${MTREEFILE}
+ test -e "${DESTDIR}${MTREEFILE}" && unlink ${DESTDIR}${MTREEFILE}
+ mv ${MTREENEW} ${DESTDIR}${MTREEFILE}
fi
echo ''
diff --git a/usr.sbin/portsnap/phttpget/phttpget.c b/usr.sbin/portsnap/phttpget/phttpget.c
index e109124..1bf6d9d 100644
--- a/usr.sbin/portsnap/phttpget/phttpget.c
+++ b/usr.sbin/portsnap/phttpget/phttpget.c
@@ -317,6 +317,7 @@ main(int argc, char *argv[])
int chunked; /* != if transfer-encoding is chunked */
off_t clen; /* Chunk length */
int firstreq = 0; /* # of first request for this connection */
+ int val; /* Value used for setsockopt call */
/* Check that the arguments are sensible */
if (argc < 2)
@@ -370,6 +371,11 @@ main(int argc, char *argv[])
setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO,
(void *)&timo, (socklen_t)sizeof(timo));
+ /* ... disable SIGPIPE generation ... */
+ val = 1;
+ setsockopt(sd, SOL_SOCKET, SO_NOSIGPIPE,
+ (void *)&val, sizeof(int));
+
/* ... and connect to the server. */
if(connect(sd, res->ai_addr, res->ai_addrlen)) {
close(sd);
diff --git a/usr.sbin/pppd/Makefile b/usr.sbin/pppd/Makefile
deleted file mode 100644
index 2df0330..0000000
--- a/usr.sbin/pppd/Makefile
+++ /dev/null
@@ -1,56 +0,0 @@
-# $FreeBSD$
-
-.include <bsd.own.mk>
-
-# I once used this extensively, but no longer have a modem. Feel free
-# to ask me questions about it, but I disclaim ownership now. -Peter
-
-PROG= pppd
-MAN= pppd.8
-SRCS= main.c magic.c fsm.c lcp.c ipcp.c ipxcp.c upap.c chap.c ccp.c \
- demand.c auth.c options.c sys-bsd.c
-BINMODE=4550
-BINOWN= root
-BINGRP= dialer
-
-CFLAGS+= -DHAVE_PATHS_H
-
-DPADD= ${LIBCRYPT} ${LIBUTIL} ${LIBMD}
-LDADD= -lcrypt -lutil -lmd
-
-# Support SPX/IPX - not quite ready
-#CFLAGS+= -DIPX_CHANGE
-#SRCS+= ipxcp.c
-
-# Callback Control Protocol
-CFLAGS+= -DCBCP_SUPPORT
-SRCS+= cbcp.c
-
-# Filter support
-CFLAGS+= -DPPP_FILTER
-DPADD+= ${LIBPCAP}
-LDADD+= -lpcap
-
-# MS-CHAP support. Requires the DES library.
-.if ${MK_OPENSSL} != "no" && !defined(RELEASE_CRUNCH)
-CFLAGS+= -DCHAPMS
-SRCS+= chap_ms.c
-LDADD+= -lcrypto
-DPADD+= ${LIBCRYPTO}
-.endif
-
-.if ${MK_INET6_SUPPORT} != "no"
-CFLAGS+=-DINET6
-SRCS+= eui64.c ipv6cp.c
-.endif
-
-.if defined(RELEASE_CRUNCH)
-# We must create these objects because crunchgen will link them,
-# and we don't want any unused symbols to spoil the final link.
-SRCS+= chap_ms.c
-chap_ms.o:
- >null_${.PREFIX}.c
- cc -c -o ${.TARGET} null_${.PREFIX}.c
-.endif
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/pppd/RELNOTES b/usr.sbin/pppd/RELNOTES
deleted file mode 100644
index 1c1e3922..0000000
--- a/usr.sbin/pppd/RELNOTES
+++ /dev/null
@@ -1,726 +0,0 @@
-# $FreeBSD$
-
-This is the README file for ppp-2.3, a package which implements the
-Point-to-Point Protocol (PPP) to provide Internet connections over
-serial lines.
-
-
-Introduction.
-*************
-
-The Point-to-Point Protocol (PPP) provides a standard way to establish
-a network connection over a serial link. At present, this package
-supports IP and the protocols layered above IP, such as TCP and UDP.
-The Linux port of this package also has support for IPX.
-
-This software consists of two parts:
-
-- Kernel code, which establishes a network interface and passes
-packets between the serial port, the kernel networking code and the
-PPP daemon (pppd). This code is implemented using STREAMS modules on
-SunOS 4.x, Solaris 2.x, System V Release 4, and OSF/1, and as a
-line discipline under Ultrix, NextStep, NetBSD, FreeBSD, and Linux.
-
-- The PPP daemon (pppd), which negotiates with the peer to establish
-the link and sets up the ppp network interface. Pppd includes support
-for authentication, so you can control which other systems may make a
-PPP connection and what IP addresses they may use.
-
-
-Installation.
-*************
-
-The file SETUP contains general information about setting up your
-system for using PPP. There is also a README file for each supported
-system, which contains more specific details for installing PPP on
-that system. The supported systems, and the corresponding README
-files, are:
-
- Digital Unix (OSF/1) README.osf
- Linux README.linux
- NetBSD, FreeBSD README.bsd
- NeXTStep README.next
- Solaris 2 README.sol2
- SunOS 4.x README.sunos4
- System V Release 4 README.svr4
- Ultrix 4.x README.ultrix
-
-Unfortunately, AIX 4 is no longer supported, since I don't have a
-maintainer for the AIX 4 port. If you want to volunteer, contact me.
-The Ultrix port is untested, as I no longer have access to an Ultrix
-box.
-
-In each case you start by running the ./configure script. This works
-out which operating system you are using and creates symbolic links to
-the appropriate makefiles. You then run `make' to compile the
-user-level code, and (as root) `make install' to install the
-user-level programs pppd, chat and pppstats.
-
-The procedures for installing the kernel code vary from system to
-system. On some systems, the kernel code can be loaded into a running
-kernel using a `modload' facility. On others, the kernel image has to
-be recompiled and the system rebooted. See the README.* files for
-details.
-
-N.B. Since 2.3.0, leaving the permitted IP addresses column of the
-pap-secrets or chap-secrets file empty means that no addresses are
-permitted. You need to put a "*" in that column to allow the peer to
-use any IP address. (This only applies where the peer is
-authenticating itself to you, of course.)
-
-
-What's new in ppp-2.3.5.
-************************
-
-* Minor corrections to the Digital UNIX and NetBSD ports.
-
-* A workaround to avoid tickling a bug in the `se' serial port driver
-on Sun PCI Ultra machines running Solaris.
-
-* Fixed a bug in the negotiation of the Microsoft WINS server address
-option.
-
-* Fixed a bug in the Linux port where it would fail for kernel
-versions above 2.1.99.
-
-
-What was new in ppp-2.3.4.
-**************************
-
-* The NeXT port has been updated, thanks to Steve Perkins.
-
-* ppp-2.3.4 compiles and works under Solaris 2.6, using either gcc or
-cc.
-
-* With the Solaris, SVR4 and SunOS ports, you can control the choice
-of C compiler, C compiler options, and installation directories by
-editing the svr4/Makedefs or sunos4/Makedefs file.
-
-* Until now, we have been using the number 24 to identify Deflate
-compression in the CCP negotiations, which was the number in the draft
-RFC describing Deflate. The number actually assigned to Deflate is
-26. The code has been changed to use 26, but to allow the use of 24
-for now for backwards compatibility. (This can be disabled with the
-`nodeflatedraft' option to pppd.)
-
-* Fixed some bugs in the linux driver and deflate compressor which
-were causing compression problems, including corrupting long
-incompressible packets sometimes.
-
-* Fixes to the PAM and shadow password support in pppd, from Al
-Longyear and others.
-
-* Pppd now sets some environment variables for scripts it invokes
-(ip-up/down, auth-ip/down), giving information about the connection.
-The variables it sets are PEERNAME, IPLOCAL, IPREMOTE, UID, DEVICE,
-SPEED, and IFNAME.
-
-* Pppd now has an `updetach' option, which will cause it to detach
-from its controlling terminal once the link has come up (i.e. once it
-is available for IP traffic).
-
-
-What was new in ppp-2.3.3.
-**************************
-
-* Fixed compilation problems under SunOS.
-
-* Fixed a bug introduced into chat in 2.3.2, and compilation problems
-introduced into the MS-CHAP implementation in 2.3.2.
-
-* The linux kernel driver has been updated for recent 2.1-series
-kernel changes, and it now will ask kerneld to load compression
-modules when required, if the kernel is configured to support kerneld.
-
-* Pppd should now compile correctly under linux on systems with glibc.
-
-
-What was new in ppp-2.3.2.
-**************************
-
-* In 2.3.1, I made a change which was intended to make pppd able to
-detect loss of CD during or immediately after the connection script
-runs. Unfortunately, this had the side-effect that the connection
-script wouldn't work at all on some systems. This change has been
-reversed.
-
-* Fix compilation problems in the Linux kernel driver.
-
-
-What was new in ppp-2.3.1.
-**************************
-
-* Enhancements to chat, thanks to Francis Demierre. Chat can now
-accept comments in the chat script file, and has new SAY, HANGUP,
-CLR_ABORT and CLR_REPORT keywords.
-
-* Fixed a bug which causes 2.3.0 to crash Solaris systems.
-
-* Bug-fixes and restructuring of the Linux kernel driver.
-
-* The holdoff behaviour of pppd has been changed slightly: now, if
-the link comes up for IP (or other network protocol) traffic, we
-consider that the link has been successfully established, and don't
-enforce the holdoff period after the link goes down.
-
-* Pppd should now correctly wait for CD (carrier detect) from the
-modem, even when the serial port initially had CLOCAL set, and it
-should also detect loss of CD during or immediately after the
-connection script runs.
-
-* Under linux, pppd will work with older 2.2.0* version kernel
-drivers, although demand-dialling is not supported with them.
-
-* Minor bugfixes for pppd.
-
-
-What was new in ppp-2.3.
-************************
-
-* Demand-dialling. Pppd now has a mode where it will establish the
-network interface immediately when it starts, but not actually bring
-the link up until it sees some data to be sent. Look for the demand
-option description in the pppd man page. Demand-dialling is not
-supported under Ultrix or NeXTStep.
-
-* Idle timeout. Pppd will optionally terminate the link if no data
-packets are sent or received within a certain time interval.
-
-* Pppd now runs the /etc/ppp/auth-up script, if it exists, when the
-peer successfully authenticates itself, and /etc/ppp/auth-down when
-the connection is subsequently terminated. This can be useful for
-accounting purposes.
-
-* A new packet compression scheme, Deflate, has been implemented.
-This uses the same compression method as `gzip'. This method is free
-of patent or copyright restrictions, and it achieves better
-compression than BSD-Compress. It does consume more CPU cycles for
-compression than BSD-Compress, but this shouldn't be a problem for
-links running at 100kbit/s or less.
-
-* There is no code in this distribution which is covered by Brad
-Clements' restrictive copyright notice. The STREAMS modules for SunOS
-and OSF/1 have been rewritten, based on the Solaris 2 modules, which
-were written from scratch without any Clements code.
-
-* Pppstats has been reworked to clean up the output format somewhat.
-It also has a new -d option which displays data rate in kbyte/s for
-those columns which would normally display bytes.
-
-* Pppd options beginning with - or + have been renamed, e.g. -ip
-became noip, +chap became require-chap, etc. The old options are
-still accepted for compatibility but may be removed in future.
-
-* Pppd now has some options (such as the new `noauth' option) which
-can only be specified if it is being run by root, or in an
-"privileged" options file: /etc/ppp/options or an options file in the
-/etc/ppp/peers directory. There is a new "call" option to read
-options from a file in /etc/ppp/peers, making it possible for non-root
-users to make unauthenticated connections, but only to certain trusted
-peers. My intention is to make the `auth' option the default in a
-future release.
-
-* Several minor new features have been added to pppd, including the
-maxconnect and welcome options. Pppd will now terminate the
-connection when there are no network control protocols running. The
-allowed IP address(es) field in the secrets files can now specify
-subnets (with a notation like 123.45.67.89/24) and addresses which are
-not acceptable (put a ! on the front).
-
-* Numerous bugs have been fixed (no doubt some have been introduced :-)
-Thanks to those who reported bugs in ppp-2.2.
-
-
-Patents.
-********
-
-The BSD-Compress algorithm used for packet compression is the same as
-that used in the Unix "compress" command. It is apparently covered by
-U.S. patents 4,814,746 (owned by IBM) and 4,558,302 (owned by Unisys),
-and corresponding patents in various other countries (but not
-Australia). If this is of concern, you can build the package without
-including BSD-Compress. To do this, edit net/ppp-comp.h to change the
-definition of DO_BSD_COMPRESS to 0. The bsd-comp.c files are then no
-longer needed, so the references to bsd-comp.o may optionally be
-removed from the Makefiles.
-
-
-Contacts.
-*********
-
-The comp.protocols.ppp newsgroup is a useful place to get help if you
-have trouble getting your ppp connections to work. Please do not send
-me questions of the form "please help me get connected to my ISP" -
-I'm sorry, but I simply do not have the time to answer all the
-questions like this that I get.
-
-If you find bugs in this package, please report them to the maintainer
-for the port for the operating system you are using:
-
-Digital Unix (OSF/1) Farrell Woods <ftw@zk3.dec.com>
-Linux Al Longyear <longyear@pobox.com>
-NetBSD Matthew Green <mrg@eterna.com.au
-FreeBSD Peter Wemm <peter@haywire.DIALix.COM>
-NeXTStep Steve Perkins <perkins@cps.msu.edu>
-Solaris 2 Paul Mackerras <Paul.Mackerras@cs.anu.edu.au>
-SunOS 4.x Paul Mackerras <Paul.Mackerras@cs.anu.edu.au>
-System V Release 4 Matthias Apitz <Matthias.Apitz@SOFTCON.de>
-Ultrix 4.x Paul Mackerras (for want of anybody better :-)
-
-
-Copyrights:
-***********
-
-All of the code can be freely used and redistributed.
-
-
-Distribution:
-*************
-
-The primary site for releases of this software is:
-
- ftp://cs.anu.edu.au/pub/software/ppp/
-
--------------------------
-This is the README file for ppp-2.2, a package which implements the
-Point-to-Point Protocol (PPP) to provide Internet connections over
-serial lines.
-
-
-Introduction.
-*************
-
-The Point-to-Point Protocol (PPP) provides a standard way to transmit
-datagrams over a serial link, as well as a standard way for the
-machines at either end of the link (the `peers') to negotiate various
-optional characteristics of the link. Using PPP, a serial link can be
-used to transmit Internet Protocol (IP) datagrams, allowing TCP/IP
-connections between the peers. PPP is defined in several RFC (Request
-For Comments) documents, in particular RFCs 1661, 1662, 1332 and 1334.
-Other RFCs describe standard ways to transmit datagrams from other
-network protocols (e.g., DECnet, OSI, Appletalk), but this package
-only supports IP.
-
-This software consists of two parts:
-
-- Kernel code, which establishes a network interface and passes
-packets between the serial port, the kernel networking code and the
-PPP daemon (pppd). This code is implemented using STREAMS modules on
-SunOS 4.x, AIX 4.1 and OSF/1, and as a line discipline under Ultrix,
-NextStep, NetBSD, FreeBSD, and Linux.
-
-- The PPP daemon (pppd), which negotiates with the peer to establish
-the link and sets up the ppp network interface. Pppd includes support
-for authentication, so you can control which other systems may make a
-PPP connection and what IP addresses they may use.
-
-
-What is new in ppp-2.2.
-***********************
-
-* More systems are now supported:
-
- AIX 4, thanks to Charlie Wick,
- OSF/1 on DEC Alpha, thanks to Steve Tate (srt@zaphod.csci.unt.edu),
- NextStep 3.2 and 3.3, thanks to Philip-Andrew Prindeville
- (philipp@res.enst.fr) and Steve Perkins (perkins@cps.msu.edu),
- Solaris 2,
-
-in addition to NetBSD 1.0, SunOS 4.x, Ultrix 4.x, FreeBSD 2.0, and
-Linux.
-
-* Packet compression has been implemented. This version implements
-CCP (Compression Control Protocol) and the BSD-Compress compression
-scheme according to the current draft RFCs. This means that incoming
-and outgoing packets can be compressed with the LZW scheme (same as
-the `compress' command) using a code size of up to 15 bits.
-
-* Some bug fixes to the LCP protocol code. In particular, pppd now
-correctly replies with a Configure-NAK (instead of a Configure-Reject)
-if the peer asks for CHAP and pppd is willing to do PAP but not CHAP.
-
-* The ip-up and ip-down scripts are now run with the real user ID set
-to root, and with an empty environment. Clearing the environment
-fixes a security hole.
-
-* The kernel code on NetBSD, FreeBSD, NextStep and Ultrix has been
-restructured to make it easier to implement PPP over devices other
-than asynchronous tty ports (for example, synchronous serial ports).
-
-* pppd now looks at the list of interfaces in the system to determine
-what the netmask should be. In most cases, this should eliminate the
-need to use the `netmask' option.
-
-* There is a new `papcrypt' option to pppd, which specifies that
-secrets in /etc/ppp/pap-secrets used for authenticating the peer are
-encrypted, so pppd always encrypts the peer's password before
-comparing it with the secret from /etc/ppp/pap-secrets. This gives
-better security.
-
-
-Patents.
-********
-
-The BSD-Compress algorithm used for packet compression is the same as
-that used in the Unix "compress" command. It is apparently covered by
-U.S. patents 4,814,746 (owned by IBM) and 4,558,302 (owned by Unisys),
-and corresponding patents in various other countries (but not
-Australia). If this is of concern, you can build the package without
-including BSD-Compress. To do this, edit net/ppp-comp.h to change the
-definition of DO_BSD_COMPRESS to 0. The bsd-comp.c files are then no
-longer needed, so the references to bsd-comp.o may optionally be
-removed from the Makefiles.
-
-
-Contacts.
-*********
-
-Bugs in the the SunOS, NetBSD and Ultrix ports and bugs in pppd, chat
-or pppstats should be reported to:
-
- paulus@cs.anu.edu.au
- Paul Mackerras
- Dept. of Computer Science
- Australian National University
- Canberra ACT 0200
- AUSTRALIA
-
-Bugs in other ports should be reported to the maintainer for that port
-(see the appropriate README.* file) or to the above. Unfortunately,
-Charlie Wick is not in a position to provide support for the AIX 4
-port, so if you find bugs in it, send them to me.
-
-Thanks to:
-
- Brad Parker (brad@fcr.com)
- Greg Christy (gmc@quotron.com)
- Drew D. Perkins (ddp@andrew.cmu.edu)
- Rick Adams (rick@seismo.ARPA)
- Chris Torek (chris@mimsy.umd.edu, umcp-cs!chris).
-
-
-Copyrights:
-
-Most of the code can be freely used and redistributed. The STREAMS
-code for SunOS 4.x, OSF/1 and AIX 4 is under a more restrictive
-copyright:
-
- This code is Copyright (C) 1989, 1990 By Brad K. Clements,
- All Rights Reserved.
-
- You may use this code for your personal use, to provide a non-profit
- service to others, or to use as a test platform for a commercial
- implementation.
-
- You may NOT use this code in a commercial product, nor to provide a
- commercial service, nor may you sell this code without express
- written permission of the author.
-
- Otherwise, Enjoy!
-
-This copyright applies to (parts of) the following files:
-
- sunos/ppp_async.c
- sunos/ppp_if.c
- aix4/ppp_async.c
- aix4/ppp_if.c
- net/ppp_str.h
- pppd/sys-str.c
- pppd/sys-osf.c
- pppd/sys-aix4.c
--------------------------
- pppd-2.1.1 release notes
- Paul Mackerras 27 May 1994
-
-This file details the new and changed features in pppd since version 1.3.
-Briefly:
- - the protocol code has been updated to conform with
- RFCs 1548, 1549, 1332 and 1334
- - security has been improved
- - functionality has been improved in various ways.
-
-
-NEW FEATURES
-
-* The option negotiation automaton has been updated to RFC1548. LCP
-now rejects the Quality Protocol option, since LQR is not implemented
-yet. IPCP now uses the IP-Address option, and falls back to the old
-IP-Addresses option if the IP-Address option is rejected. IPCP also
-uses the new form of the VJ-Compression option.
-
-RFC1548 defines the "passive" option to mean that the automaton
-outputs configure-request packets initially, but does not close down
-if no answer is received. A valid configure-request received will
-restart the negotiation. The "silent" option has been added with the
-old meaning of "passive", i.e. the automaton will not output
-configure-requests until it receives a valid one from the peer.
-
-* More systems are supported: in addition to SunOS 4.x and BSD/Net-2
-derived systems, Ultrix and Linux are supported, thanks to Robert
-Olsson, Per Sundstrom, Michael Callahan and Al Longyear.
-
-* Options can be taken from files as well as the command line. pppd
-reads options from the files /etc/ppp/options and ~/.ppprc before
-looking at the command line, and /etc/ppp/options.<ttyname> after
-interpreting the options on the command line. An options file is
-parsed into a series of words, delimited by whitespace. Whitespace
-can be included in a word by enclosing the word in quotes (").
-Backslash (\) quotes the following character. A hash (#) starts a
-comment, which continues until the end of the line. In addition, the
-`file' option causes pppd to read options from a file. pppd will
-report and error and exit if ~/.ppprc or the file given as the
-argument to the `file' option cannot be read by the user who invoked
-pppd.
-
-* On those systems, such as NetBSD, where the serial line speed is
-stored in the termios structure in bits per second (i.e. B9600 ==
-9600), it is possible to set any speed.
-
-* If desired, pppd will output LCP echo-request frames periodically
-while the link is up, and take the link down if no replies are
-received to a user-configurable number of echo-requests. This can be
-used to detect that the serial connection has been broken on those
-systems which don't have hardware modem control lines.
-
-AUTHENTICATION
-
-Previous versions of pppd have provided no control over which IP
-addresses the peer can use. Thus it is possible for the peer to
-impersonate another host on the local network, leading to various
-security holes. In addition, the authentication mechanisms were quite
-weak: if the peer refused to agree to authenticate, pppd would print a
-warning message but still allow the link to come up. The CHAP
-implementation also appeared to be quite broken (has anybody actually
-used it?).
-
-This new version of pppd addresses these problems. My aim has been to
-provide system administrators with sufficient access control that PPP
-access to a server machine can be provided to legitimate users without
-fear of compromising the security of the server or the network it's
-on. In part this is provided by the /etc/ppp/options file, where the
-administrator can place options to require authentication which cannot
-be disabled by users. Thus the new pppd can made setuid-root and run
-by users.
-
-The behaviour where pppd refuses to run unless the /etc/ppp/options
-file is present and readable by pppd is now the default behaviour. If
-you really want pppd to run without the presence of the
-/etc/ppp/options file, you will have to include -DREQ_SYSOPTIONS=0 on
-the compilation command line.
-
-The options related to authentication are:
-
- auth Require authentication from the peer. If neither
- +chap or +pap is also given, either CHAP or PAP
- authentication will be accepted.
- +chap Require CHAP authentication from the peer.
- +pap Require PAP authentication from the peer.
- -chap Don't agree to authenticate ourselves with the peer
- using CHAP.
- -pap Don't agree to authenticate ourselves using PAP.
- +ua <f> Get username and password for authenticating ourselves
- with the peer using PAP from file <f>.
- name <n> Use <n> as the local name for authentication.
- usehostname Use this machine's hostname as the local name for
- authentication.
- remotename <n> Use <n> as the name of the peer for authentication.
- login If the peer authenticates using PAP, check the
- supplied username and password against the system
- password database, and make a wtmp entry.
- user <n> Use <n> as the username for authenticating ourselves
- using PAP.
-
-The defaults are to agree to authenticate if requested, and to not
-require authentication from the peer. However, pppd will not agree to
-authenticate itself with a particular protocol if it has no secrets
-which could be used to do so.
-
-Authentication is based on secrets, which are selected from secrets
-files (/etc/ppp/pap-secrets for PAP, /etc/ppp/chap-secrets for CHAP).
-Both secrets files have the same format, and both can store secrets
-for several combinations of server (authenticating peer) and client
-(peer being authenticated). Note that each end can be both a server
-and client, and that different protocols can be used in the two
-directions if desired.
-
-A secrets file is parsed into words as for an options file. A secret
-is specified by a line containing at least 3 words, in the order
-client, server, secret. Any following words on the same line are
-taken to be a list of acceptable IP addresses for that client. If
-there are only 3 words on the line, it is assumed that any IP address
-is OK; to disallow all IP addresses, use "-". If the secret starts
-with an `@', what follows is assumed to be the name of a file from
-which to read the secret. A "*" as the client or server name matches
-any name. When selecting a secret, pppd takes the best match, i.e.
-the match with the fewest wildcards.
-
-Thus a secrets file contains both secrets for use in authenticating
-other hosts, plus secrets which we use for authenticating ourselves to
-others. Which secret to use is chosen based on the names of the host
-(the `local name') and its peer (the `remote name'). The local name
-is set as follows:
-
- if the `usehostname' option is given,
- then the local name is the hostname of this machine
- (with the domain appended, if given)
-
- else if the `name' option is given,
- then use the argument of the first `name' option seen
-
- else if the local IP address is specified with a
- host name (e.g. `sirius:')
- then use that host name
-
- else use the hostname of this machine
- (with the domain appended, if given)
-
-When authenticating ourselves using PAP, there is also a `username'
-which is the local name by default, but can be set with the `user'
-option or the `+ua' option.
-
-The remote name is set as follows:
-
- if the `remotename' option is given,
- then use the argument of the last `remotename' option seen
-
- else if the remote IP address is specified with a
- host name (e.g. `avago:')
- then use that host name
-
- else the remote name is the null string "".
-
-Secrets are selected from the PAP secrets file as follows:
-
-- For authenticating the peer, look for a secret with client ==
-username specified in the PAP authenticate-request, and server ==
-local name.
-
-- For authenticating ourselves to the peer, look for a secret with
-client == our username, server == remote name.
-
-When authenticating the peer with PAP, a secret of "" matches any
-password supplied by the peer. If the password doesn't match the
-secret, the password is encrypted using crypt() and checked against
-the secret again; thus secrets for authenticating the peer can be
-stored in encrypted form. If the `login' option was specified, the
-username and password are also checked against the system password
-database. Thus, the system administrator can set up the pap-secrets
-file to allow PPP access only to certain users, and to restrict the
-set of IP addresses that each user can use.
-
-Secrets are selected from the CHAP secrets file as follows:
-
-- For authenticating the peer, look for a secret with client == name
-specified in the CHAP-Response message, and server == local name.
-
-- For authenticating ourselves to the peer, look for a secret with
-client == local name, and server == name specified in the
-CHAP-Challenge message.
-
-Authentication must be satisfactorily completed before IPCP (or any
-other Network Control Protocol) can be started. If authentication
-fails, pppd will terminated the link (by closing LCP). If IPCP
-negotiates an unacceptable IP address for the remote host, IPCP will
-be closed. IP packets cannot be sent or received until IPCP is
-successfully opened.
-
-(some examples needed here perhaps)
-
-
-ROUTING
-
-Setting the addresses on a ppp interface is sufficient to create a
-host route to the remote end of the link. Sometimes it is desirable
-to add a default route through the remote host, as in the case of a
-machine whose only connection to the Internet is through the ppp
-interface. The `defaultroute' option causes pppd to create such a
-default route when IPCP comes up, and delete it when the link is
-terminated.
-
-In some cases it is desirable to use proxy ARP, for example on a
-server machine connected to a LAN, in order to allow other hosts to
-communicate with the remote host. The `proxyarp' option causes pppd
-to look for a network interface (an interface supporting broadcast and
-ARP, which is up and not a point-to-point or loopback interface) on
-the same subnet as the remote host. If found, pppd creates a
-permanent, published ARP entry with the IP address of the remote host
-and the hardware address of the network interface found.
-
-
-OTHER NEW AND CHANGED OPTIONS
-
- modem Use modem control lines (not fully implemented
- yet)
- local Don't use modem control lines
- persist Keep reopening connection (not fully
- implemented yet)
-
- lcp-restart <n> Set timeout for LCP retransmissions to <n>
- seconds (default 3 seconds)
- lcp-max-terminate <n> Set maximum number of LCP terminate-request
- transmissions (default 2)
- lcp-max-configure <n> Set maximum number of LCP configure-request
- transmissions (default 10)
- lcp-max-failure <n> Set maximum number of LCP configure-Naks sent
- before converting to configure-rejects
- (default 10)
-
- ipcp-restart <n> Set timeout for IPCP retransmissions to <n>
- seconds (default 3 seconds)
- ipcp-max-terminate <n> Set maximum number of IPCP
- terminate-request transmissions (default 2)
- ipcp-max-configure <n> Set maximum number of IPCP
- configure-request transmissions (default 10)
- ipcp-max-failure <n> Set maximum number of IPCP configure-Naks
- sent before converting to configure-rejects
- (default 10)
-
- upap-restart <n> Set timeout for PAP retransmissions to
- <n> seconds (default 3 seconds)
- upap-max-authreq <n> Set maximum number of Authenticate-request
- retransmissions (default 10)
-
- chap-restart <n> Set timeout for CHAP retransmissions to
- <n> seconds (default 3 seconds)
- chap-max-challenge <n> Set maximum number of CHAP Challenge
- retransmissions (default 10)
- chap-interval <n> Set the interval between CHAP rechallenges
- (default 0, meaning infinity)
-
-The -ua option no longer exists.
-
-
-SOFTWARE RESTRUCTURING
-
-Many of the source files for pppd have changed significantly from
-ppp-1.3, upon which it is based. In particular:
-
-- the macros for system-dependent operations in pppd.h have mostly
-been removed. Instead these operations are performed by procedures in
-sys-bsd.c (for BSD-4.4ish systems like NetBSD, 386BSD, etc.) or
-sys-str.c (for SunOS-based systems using STREAMS). (I got sick of
-having to recompile everything every time I wanted to change one of
-those horrible macros.)
-
-- most of the system-dependent code in main.c has also been removed to
-sys-bsd.c and sys-str.c.
-
-- the option processing code in main.c has been removed to options.c.
-
-- the authentication code in main.c has been removed to auth.c, which
-also contains substantial amounts of new code.
-
-- fsm.c has changed significantly, and lcp.c, ipcp.c, and upap.c have
-changed somewhat. chap.c has also changed significantly.
-
-
-STILL TO DO
-
-* sort out appropriate modem control and implement the persist option
-properly; add an `answer' option for auto-answering a modem.
-
-* add an inactivity timeout and demand dialing.
-
-* implement link quality monitoring.
-
-* implement other network control protocols.
diff --git a/usr.sbin/pppd/auth.c b/usr.sbin/pppd/auth.c
deleted file mode 100644
index a0062da..0000000
--- a/usr.sbin/pppd/auth.c
+++ /dev/null
@@ -1,1637 +0,0 @@
-/*
- * auth.c - PPP authentication and phase control.
- *
- * Copyright (c) 1993 The Australian National University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the Australian National University. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-#include <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <paths.h>
-#include <pwd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <utmp.h>
-#include <fcntl.h>
-#if defined(_PATH_LASTLOG) && defined(_linux_)
-#include <lastlog.h>
-#endif
-
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <sys/time.h>
-#include <utmp.h>
-
-#ifdef USE_PAM
-#include <security/pam_appl.h>
-#endif
-
-#ifdef HAS_SHADOW
-#include <shadow.h>
-#ifndef PW_PPP
-#define PW_PPP PW_LOGIN
-#endif
-#endif
-
-#include "pppd.h"
-#include "fsm.h"
-#include "lcp.h"
-#include "ipcp.h"
-#include "upap.h"
-#include "chap.h"
-#ifdef CBCP_SUPPORT
-#include "cbcp.h"
-#endif
-#include "pathnames.h"
-
-/* Used for storing a sequence of words. Usually malloced. */
-struct wordlist {
- struct wordlist *next;
- char word[1];
-};
-
-/* Bits in scan_authfile return value */
-#define NONWILD_SERVER 1
-#define NONWILD_CLIENT 2
-
-#define ISWILD(word) (word[0] == '*' && word[1] == 0)
-
-#define FALSE 0
-#define TRUE 1
-
-/* The name by which the peer authenticated itself to us. */
-char peer_authname[MAXNAMELEN];
-
-/* Records which authentication operations haven't completed yet. */
-static int auth_pending[NUM_PPP];
-
-/* Set if we have successfully called plogin() */
-static int logged_in;
-
-/* Set if not wild or blank */
-static int non_wildclient;
-
-/* Set if we have run the /etc/ppp/auth-up script. */
-static int did_authup;
-
-/* List of addresses which the peer may use. */
-static struct wordlist *addresses[NUM_PPP];
-
-/* Number of network protocols which we have opened. */
-static int num_np_open;
-
-/* Number of network protocols which have come up. */
-static int num_np_up;
-
-/* Set if we got the contents of passwd[] from the pap-secrets file. */
-static int passwd_from_file;
-
-/* Bits in auth_pending[] */
-#define PAP_WITHPEER 1
-#define PAP_PEER 2
-#define CHAP_WITHPEER 4
-#define CHAP_PEER 8
-
-extern char *crypt(const char *, const char *);
-
-/* Prototypes for procedures local to this file. */
-
-static void network_phase(int);
-static void check_idle(void *);
-static void connect_time_expired(void *);
-static int plogin(char *, char *, char **, int *);
-static void plogout(void);
-static int null_login(int);
-static int get_pap_passwd(char *);
-static int have_pap_secret(void);
-static int have_chap_secret(char *, char *, u_int32_t);
-static int ip_addr_check(u_int32_t, struct wordlist *);
-static int scan_authfile(FILE *, char *, char *, u_int32_t, char *,
- struct wordlist **, char *);
-static void free_wordlist(struct wordlist *);
-static void auth_set_ip_addr(int);
-static void auth_script(char *);
-static void set_allowed_addrs(int, struct wordlist *);
-
-/*
- * An Open on LCP has requested a change from Dead to Establish phase.
- * Do what's necessary to bring the physical layer up.
- */
-void
-link_required(unit)
- int unit;
-{
-}
-
-/*
- * LCP has terminated the link; go to the Dead phase and take the
- * physical layer down.
- */
-void
-link_terminated(unit)
- int unit;
-{
- extern time_t etime, stime;
- extern int minutes;
-
- if (phase == PHASE_DEAD)
- return;
- if (logged_in)
- plogout();
- phase = PHASE_DEAD;
- etime = time((time_t *) NULL);
- minutes = (etime-stime)/60;
- syslog(LOG_NOTICE, "Connection terminated, connected for %d minutes\n",
- minutes > 1 ? minutes : 1);
-}
-
-/*
- * LCP has gone down; it will either die or try to re-establish.
- */
-void
-link_down(unit)
- int unit;
-{
- int i;
- struct protent *protp;
-
- if (did_authup) {
- auth_script(_PATH_AUTHDOWN);
- did_authup = 0;
- }
- for (i = 0; (protp = protocols[i]) != NULL; ++i) {
- if (!protp->enabled_flag)
- continue;
- if (protp->protocol != PPP_LCP && protp->lowerdown != NULL)
- (*protp->lowerdown)(unit);
- if (protp->protocol < 0xC000 && protp->close != NULL)
- (*protp->close)(unit, "LCP down");
- }
- num_np_open = 0;
- num_np_up = 0;
- if (phase != PHASE_DEAD)
- phase = PHASE_TERMINATE;
-}
-
-/*
- * The link is established.
- * Proceed to the Dead, Authenticate or Network phase as appropriate.
- */
-void
-link_established(unit)
- int unit;
-{
- int auth;
- lcp_options *wo = &lcp_wantoptions[unit];
- lcp_options *go = &lcp_gotoptions[unit];
- lcp_options *ho = &lcp_hisoptions[unit];
- int i;
- struct protent *protp;
-
- /*
- * Tell higher-level protocols that LCP is up.
- */
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if (protp->protocol != PPP_LCP && protp->enabled_flag
- && protp->lowerup != NULL)
- (*protp->lowerup)(unit);
-
- if (auth_required && !(go->neg_chap || go->neg_upap)) {
- /*
- * We wanted the peer to authenticate itself, and it refused:
- * treat it as though it authenticated with PAP using a username
- * of "" and a password of "". If that's not OK, boot it out.
- */
- if (!wo->neg_upap || !null_login(unit)) {
- syslog(LOG_WARNING, "peer refused to authenticate");
- lcp_close(unit, "peer refused to authenticate");
- return;
- }
- }
-
- phase = PHASE_AUTHENTICATE;
- auth = 0;
- if (go->neg_chap) {
- ChapAuthPeer(unit, our_name, go->chap_mdtype);
- auth |= CHAP_PEER;
- } else if (go->neg_upap) {
- upap_authpeer(unit);
- auth |= PAP_PEER;
- }
- if (ho->neg_chap) {
- ChapAuthWithPeer(unit, user, ho->chap_mdtype);
- auth |= CHAP_WITHPEER;
- } else if (ho->neg_upap) {
- if (passwd[0] == 0) {
- passwd_from_file = 1;
- if (!get_pap_passwd(passwd))
- syslog(LOG_ERR, "No secret found for PAP login");
- }
- upap_authwithpeer(unit, user, passwd);
- auth |= PAP_WITHPEER;
- }
- auth_pending[unit] = auth;
-
- if (!auth)
- network_phase(unit);
-}
-
-/*
- * Proceed to the network phase.
- */
-static void
-network_phase(unit)
- int unit;
-{
- int i;
- struct protent *protp;
- lcp_options *go = &lcp_gotoptions[unit];
-
- /*
- * If the peer had to authenticate, run the auth-up script now.
- */
- if ((go->neg_chap || go->neg_upap) && !did_authup) {
- auth_script(_PATH_AUTHUP);
- did_authup = 1;
- }
-
-#ifdef CBCP_SUPPORT
- /*
- * If we negotiated callback, do it now.
- */
- if (go->neg_cbcp) {
- phase = PHASE_CALLBACK;
- (*cbcp_protent.open)(unit);
- return;
- }
-#endif
-
- phase = PHASE_NETWORK;
-#if 0
- if (!demand)
- set_filters(&pass_filter, &active_filter);
-#endif
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if (protp->protocol < 0xC000 && protp->enabled_flag
- && protp->open != NULL) {
- (*protp->open)(unit);
- if (protp->protocol != PPP_CCP)
- ++num_np_open;
- }
-
- if (num_np_open == 0)
- /* nothing to do */
- lcp_close(0, "No network protocols running");
-}
-
-/*
- * The peer has failed to authenticate himself using `protocol'.
- */
-void
-auth_peer_fail(unit, protocol)
- int unit, protocol;
-{
- /*
- * Authentication failure: take the link down
- */
- lcp_close(unit, "Authentication failed");
-}
-
-/*
- * The peer has been successfully authenticated using `protocol'.
- */
-void
-auth_peer_success(unit, protocol, name, namelen)
- int unit, protocol;
- char *name;
- int namelen;
-{
- int bit;
-
- switch (protocol) {
- case PPP_CHAP:
- bit = CHAP_PEER;
- break;
- case PPP_PAP:
- bit = PAP_PEER;
- break;
- default:
- syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",
- protocol);
- return;
- }
-
- /*
- * Save the authenticated name of the peer for later.
- */
- if (namelen > sizeof(peer_authname) - 1)
- namelen = sizeof(peer_authname) - 1;
- BCOPY(name, peer_authname, namelen);
- peer_authname[namelen] = 0;
-
- /*
- * If we have overridden addresses based on auth info
- * then set that information now before continuing.
- */
- auth_set_ip_addr(unit);
-
- script_setenv("PEERNAME", peer_authname);
-
- /*
- * If there is no more authentication still to be done,
- * proceed to the network (or callback) phase.
- */
- if ((auth_pending[unit] &= ~bit) == 0)
- network_phase(unit);
-}
-
-/*
- * We have failed to authenticate ourselves to the peer using `protocol'.
- */
-void
-auth_withpeer_fail(unit, protocol)
- int unit, protocol;
-{
- if (passwd_from_file)
- BZERO(passwd, MAXSECRETLEN);
- /*
- * We've failed to authenticate ourselves to our peer.
- * He'll probably take the link down, and there's not much
- * we can do except wait for that.
- */
-}
-
-/*
- * We have successfully authenticated ourselves with the peer using `protocol'.
- */
-void
-auth_withpeer_success(unit, protocol)
- int unit, protocol;
-{
- int bit;
-
- switch (protocol) {
- case PPP_CHAP:
- bit = CHAP_WITHPEER;
- break;
- case PPP_PAP:
- if (passwd_from_file)
- BZERO(passwd, MAXSECRETLEN);
- bit = PAP_WITHPEER;
- break;
- default:
- syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",
- protocol);
- bit = 0;
- }
-
- /*
- * If we have overridden addresses based on auth info
- * then set that information now before continuing.
- */
- auth_set_ip_addr(unit);
-
- /*
- * If there is no more authentication still being done,
- * proceed to the network (or callback) phase.
- */
- if ((auth_pending[unit] &= ~bit) == 0)
- network_phase(unit);
-}
-
-
-/*
- * np_up - a network protocol has come up.
- */
-void
-np_up(unit, proto)
- int unit, proto;
-{
- if (num_np_up == 0) {
- /*
- * At this point we consider that the link has come up successfully.
- */
- need_holdoff = 0;
-
- if (idle_time_limit > 0)
- TIMEOUT(check_idle, NULL, idle_time_limit);
-
- /*
- * Set a timeout to close the connection once the maximum
- * connect time has expired.
- */
- if (maxconnect > 0)
- TIMEOUT(connect_time_expired, 0, maxconnect);
-
- /*
- * Detach now, if the updetach option was given.
- */
- if (nodetach == -1)
- detach();
- }
- ++num_np_up;
-}
-
-/*
- * np_down - a network protocol has gone down.
- */
-void
-np_down(unit, proto)
- int unit, proto;
-{
- if (--num_np_up == 0 && idle_time_limit > 0) {
- UNTIMEOUT(check_idle, NULL);
- }
-}
-
-/*
- * np_finished - a network protocol has finished using the link.
- */
-void
-np_finished(unit, proto)
- int unit, proto;
-{
- if (--num_np_open <= 0) {
- /* no further use for the link: shut up shop. */
- lcp_close(0, "No network protocols running");
- }
-}
-
-/*
- * check_idle - check whether the link has been idle for long
- * enough that we can shut it down.
- */
-static void
-check_idle(arg)
- void *arg;
-{
- struct ppp_idle idle;
- time_t itime;
-
- if (!get_idle_time(0, &idle))
- return;
- itime = MIN(idle.xmit_idle, idle.recv_idle);
- if (itime >= idle_time_limit) {
- /* link is idle: shut it down. */
- syslog(LOG_INFO, "Terminating connection due to lack of activity.");
- lcp_close(0, "Link inactive");
- } else {
- TIMEOUT(check_idle, NULL, idle_time_limit - itime);
- }
-}
-
-/*
- * connect_time_expired - log a message and close the connection.
- */
-static void
-connect_time_expired(arg)
- void *arg;
-{
- syslog(LOG_INFO, "Connect time expired");
- lcp_close(0, "Connect time expired"); /* Close connection */
-}
-
-/*
- * auth_check_options - called to check authentication options.
- */
-void
-auth_check_options()
-{
- lcp_options *wo = &lcp_wantoptions[0];
- int can_auth;
- ipcp_options *ipwo = &ipcp_wantoptions[0];
- u_int32_t remote;
-
- /* Default our_name to hostname, and user to our_name */
- if (our_name[0] == 0 || usehostname)
- strcpy(our_name, hostname);
- if (user[0] == 0)
- strcpy(user, our_name);
-
- /* If authentication is required, ask peer for CHAP or PAP. */
- if (auth_required && !wo->neg_chap && !wo->neg_upap) {
- wo->neg_chap = 1;
- wo->neg_upap = 1;
- }
-
- /*
- * Check whether we have appropriate secrets to use
- * to authenticate the peer.
- */
- can_auth = wo->neg_upap && (uselogin || have_pap_secret());
- if (!can_auth && wo->neg_chap) {
- remote = ipwo->accept_remote? 0: ipwo->hisaddr;
- can_auth = have_chap_secret(remote_name, our_name, remote);
- }
-
- if (auth_required && !can_auth) {
- option_error("peer authentication required but no suitable secret(s) found\n");
- if (remote_name[0] == 0)
- option_error("for authenticating any peer to us (%s)\n", our_name);
- else
- option_error("for authenticating peer %s to us (%s)\n",
- remote_name, our_name);
- exit(1);
- }
-
- /*
- * Check whether the user tried to override certain values
- * set by root.
- */
- if (!auth_required && auth_req_info.priv > 0) {
- if (!default_device && devnam_info.priv == 0) {
- option_error("can't override device name when noauth option used");
- exit(1);
- }
- if ((connector != NULL && connector_info.priv == 0)
- || (disconnector != NULL && disconnector_info.priv == 0)
- || (welcomer != NULL && welcomer_info.priv == 0)) {
- option_error("can't override connect, disconnect or welcome");
- option_error("option values when noauth option used");
- exit(1);
- }
- }
-}
-
-/*
- * auth_reset - called when LCP is starting negotiations to recheck
- * authentication options, i.e. whether we have appropriate secrets
- * to use for authenticating ourselves and/or the peer.
- */
-void
-auth_reset(unit)
- int unit;
-{
- lcp_options *go = &lcp_gotoptions[unit];
- lcp_options *ao = &lcp_allowoptions[0];
- ipcp_options *ipwo = &ipcp_wantoptions[0];
- u_int32_t remote;
-
- ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL));
- ao->neg_chap = !refuse_chap
- && have_chap_secret(user, remote_name, (u_int32_t)0);
-
- if (go->neg_upap && !uselogin && !have_pap_secret())
- go->neg_upap = 0;
- if (go->neg_chap) {
- remote = ipwo->accept_remote? 0: ipwo->hisaddr;
- if (!have_chap_secret(remote_name, our_name, remote))
- go->neg_chap = 0;
- }
-}
-
-
-/*
- * check_passwd - Check the user name and passwd against the PAP secrets
- * file. If requested, also check against the system password database,
- * and login the user if OK.
- *
- * returns:
- * UPAP_AUTHNAK: Authentication failed.
- * UPAP_AUTHACK: Authentication succeeded.
- * In either case, msg points to an appropriate message.
- */
-int
-check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen)
- int unit;
- char *auser;
- int userlen;
- char *apasswd;
- int passwdlen;
- char **msg;
- int *msglen;
-{
- int ret;
- char *filename;
- FILE *f;
- struct wordlist *addrs;
- u_int32_t remote;
- ipcp_options *ipwo = &ipcp_wantoptions[unit];
- char passwd[256], user[256];
- char secret[MAXWORDLEN];
- static int attempts = 0;
- int len;
-
- /*
- * Make copies of apasswd and auser, then null-terminate them.
- */
- len = MIN(passwdlen, sizeof(passwd) - 1);
- BCOPY(apasswd, passwd, len);
- passwd[len] = '\0';
- len = MIN(userlen, sizeof(user) - 1);
- BCOPY(auser, user, len);
- user[len] = '\0';
- *msg = (char *) 0;
-
- /*
- * Open the file of pap secrets and scan for a suitable secret
- * for authenticating this user.
- */
- filename = _PATH_UPAPFILE;
- addrs = NULL;
- ret = UPAP_AUTHACK;
- f = fopen(filename, "r");
- if (f == NULL) {
- syslog(LOG_ERR, "Can't open PAP password file %s: %m", filename);
- ret = UPAP_AUTHNAK;
-
- } else {
- check_access(f, filename);
- remote = ipwo->accept_remote? 0: ipwo->hisaddr;
- if (scan_authfile(f, user, our_name, remote,
- secret, &addrs, filename) < 0) {
- warn("no PAP secret found for %s", user);
- } else {
- if (secret[0] != 0) {
- /* password given in pap-secrets - must match */
- if ((cryptpap || strcmp(passwd, secret) != 0)
- && strcmp(crypt(passwd, secret), secret) != 0) {
- ret = UPAP_AUTHNAK;
- warn("PAP authentication failure for %s", user);
- }
- }
- }
- fclose(f);
- }
-
- if (uselogin && ret == UPAP_AUTHACK) {
- ret = plogin(user, passwd, msg, msglen);
- if (ret == UPAP_AUTHNAK) {
- syslog(LOG_WARNING, "PAP login failure for %s", user);
- }
- }
-
- if (ret == UPAP_AUTHNAK) {
- if (*msg == (char *) 0)
- *msg = "Login incorrect";
- *msglen = strlen(*msg);
- /*
- * Frustrate passwd stealer programs.
- * Allow 10 tries, but start backing off after 3 (stolen from login).
- * On 10'th, drop the connection.
- */
- if (attempts++ >= 10) {
- syslog(LOG_WARNING, "%d LOGIN FAILURES ON %s, %s",
- attempts, devnam, user);
- quit();
- }
- if (attempts > 3)
- sleep((u_int) (attempts - 3) * 5);
- if (addrs != NULL)
- free_wordlist(addrs);
-
- } else {
- attempts = 0; /* Reset count */
- if (*msg == (char *) 0)
- *msg = "Login ok";
- *msglen = strlen(*msg);
- set_allowed_addrs(unit, addrs);
- }
-
- BZERO(passwd, sizeof(passwd));
- BZERO(secret, sizeof(secret));
-
- return ret;
-}
-
-/*
- * Check if an "entry" is in the file "fname" - used by ppplogin.
- * Taken from libexec/ftpd/ftpd.c
- * Returns: 0 if not found, 1 if found, 2 if file can't be opened for reading.
- */
-static int
-checkfile(fname, name)
- char *fname;
- char *name;
-{
- FILE *fd;
- int found = 0;
- char *p, line[BUFSIZ];
-
- if ((fd = fopen(fname, "r")) != NULL) {
- while (fgets(line, sizeof(line), fd) != NULL)
- if ((p = strchr(line, '\n')) != NULL) {
- *p = '\0';
- if (line[0] == '#')
- continue;
- if (strcmp(line, name) == 0) {
- found = 1;
- break;
- }
- }
- (void) fclose(fd);
- } else {
- return(2);
- }
- return (found);
-}
-
-/*
- * This function is needed for PAM.
- */
-
-#ifdef USE_PAM
-static char *PAM_username = "";
-static char *PAM_password = "";
-
-#ifdef PAM_ESTABLISH_CRED /* new PAM defines :(^ */
-#define MY_PAM_STRERROR(err_code) (char *) pam_strerror(pamh,err_code)
-#else
-#define MY_PAM_STRERROR(err_code) (char *) pam_strerror(err_code)
-#endif
-
-static int pam_conv (int num_msg,
- const struct pam_message **msg,
- struct pam_response **resp,
- void *appdata_ptr)
-{
- int count = 0, replies = 0;
- struct pam_response *reply = NULL;
- int size = 0;
-
- for (count = 0; count < num_msg; count++)
- {
- size += sizeof (struct pam_response);
- reply = realloc (reply, size); /* ANSI: is malloc() if reply==NULL */
- if (!reply)
- return PAM_CONV_ERR;
-
- switch (msg[count]->msg_style)
- {
- case PAM_PROMPT_ECHO_ON:
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies++].resp = strdup(PAM_username); /* never NULL */
- break;
-
- case PAM_PROMPT_ECHO_OFF:
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies++].resp = strdup(PAM_password); /* never NULL */
- break;
-
- case PAM_TEXT_INFO:
- reply[replies].resp_retcode = PAM_SUCCESS;
- reply[replies++].resp = NULL;
- break;
-
- case PAM_ERROR_MSG:
- default:
- free (reply);
- return PAM_CONV_ERR;
- }
- }
-
- if (resp)
- *resp = reply;
- else
- free (reply);
-
- return PAM_SUCCESS;
-}
-#endif
-
-/*
- * plogin - Check the user name and password against the system
- * password database, and login the user if OK.
- *
- * returns:
- * UPAP_AUTHNAK: Login failed.
- * UPAP_AUTHACK: Login succeeded.
- * In either case, msg points to an appropriate message.
- *
- * UPAP_AUTHACK should only be returned *after* wtmp and utmp are updated.
- */
-
-static int
-plogin(user, passwd, msg, msglen)
- char *user;
- char *passwd;
- char **msg;
- int *msglen;
-{
-
-#ifdef USE_PAM
-
- struct pam_conv pam_conversation;
- pam_handle_t *pamh;
- int pam_error;
-/*
- * Fill the pam_conversion structure
- */
- memset (&pam_conversation, '\0', sizeof (struct pam_conv));
- pam_conversation.conv = &pam_conv;
-
- pam_error = pam_start ("ppp", user, &pam_conversation, &pamh);
-
- if (pam_error != PAM_SUCCESS) {
- *msg = MY_PAM_STRERROR (pam_error);
- return UPAP_AUTHNAK;
- }
-/*
- * Define the fields for the credintial validation
- */
- (void) pam_set_item (pamh, PAM_TTY, devnam);
- PAM_username = user;
- PAM_password = passwd;
-/*
- * Validate the user
- */
- pam_error = pam_authenticate (pamh, PAM_SILENT);
- if (pam_error == PAM_SUCCESS) {
- pam_error = pam_acct_mgmt (pamh, PAM_SILENT);
-
- /* start a session for this user. Session closed when link ends. */
- if (pam_error == PAM_SUCCESS)
- (void) pam_open_session (pamh, PAM_SILENT);
- }
-
- *msg = MY_PAM_STRERROR (pam_error);
-
- PAM_username =
- PAM_password = "";
-/*
- * Clean up the mess
- */
- (void) pam_end (pamh, pam_error);
-
- if (pam_error != PAM_SUCCESS)
- return UPAP_AUTHNAK;
-/*
- * Use the non-PAM methods directly
- */
-#else /* #ifdef USE_PAM */
-
- struct passwd *pw;
- struct utmp utmp;
- struct timeval tp;
- char *tty;
-
-#ifdef HAS_SHADOW
- struct spwd *spwd;
- struct spwd *getspnam();
-#endif
-
- pw = getpwnam(user);
- endpwent();
- if (pw == NULL) {
- return (UPAP_AUTHNAK);
- }
-/*
- * Check that the user is not listed in /etc/ppp/ppp.deny
- * and that the user's shell is listed in /etc/ppp/ppp.shells
- * if /etc/ppp/ppp.shells exists.
- */
-
- if (checkfile(_PATH_PPPDENY, user) == 1) {
- syslog(LOG_WARNING, "upap user %s: login denied in %s",
- user, _PATH_PPPDENY);
- return (UPAP_AUTHNAK);
- }
-
- if (checkfile(_PATH_PPPSHELLS, pw->pw_shell) == 0) {
- syslog(LOG_WARNING, "upap user %s: shell %s not in %s",
- user, pw->pw_shell, _PATH_PPPSHELLS);
- return (UPAP_AUTHNAK);
- }
-
-#ifdef HAS_SHADOW
- spwd = getspnam(user);
- endspent();
- if (spwd) {
- /* check the age of the password entry */
- long now = time(NULL) / 86400L;
-
- if ((spwd->sp_expire > 0 && now >= spwd->sp_expire)
- || ((spwd->sp_max >= 0 && spwd->sp_max < 10000)
- && spwd->sp_lstchg >= 0
- && now >= spwd->sp_lstchg + spwd->sp_max)) {
- syslog(LOG_WARNING, "Password for %s has expired", user);
- return (UPAP_AUTHNAK);
- }
- pw->pw_passwd = spwd->sp_pwdp;
- }
-#endif
-
- /*
- * If no passwd, don't let them login.
- */
- if (pw->pw_passwd == NULL || *pw->pw_passwd == '\0'
- || strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd) != 0)
- return (UPAP_AUTHNAK);
-
- if (pw->pw_expire) {
- (void)gettimeofday(&tp, (struct timezone *)NULL);
- if (tp.tv_sec >= pw->pw_expire) {
- syslog(LOG_INFO, "pap user %s account expired", user);
- return (UPAP_AUTHNAK);
- }
- }
-
- /* These functions are not enabled for PAM. The reason for this is that */
- /* there is not necessarily a "passwd" entry for this user. That is */
- /* real purpose of 'PAM' -- to virtualize the account data from the */
- /* application. If you want to do the same thing, write the entry in */
- /* the 'session' hook. */
-
- /* Log in wtmp and utmp using login() */
-
- tty = devnam;
- if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0)
- tty += 5;
-
- if (logout(tty)) /* Already entered (by login?) */
- logwtmp(tty, "", "");
-
-#if defined(_PATH_LASTLOG)
- {
- struct lastlog ll;
- int fd;
-
- if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) {
- (void)lseek(fd, (off_t)(pw->pw_uid * sizeof(ll)), SEEK_SET);
- memset((void *)&ll, 0, sizeof(ll));
- ll.ll_time = _time_to_time32(time(0));
- (void)strncpy(ll.ll_line, tty, sizeof(ll.ll_line));
- (void)write(fd, (char *)&ll, sizeof(ll));
- (void)close(fd);
- }
- }
-#endif
-
- memset((void *)&utmp, 0, sizeof(utmp));
- utmp.ut_time = time(NULL);
- (void)strncpy(utmp.ut_name, user, sizeof(utmp.ut_name));
- (void)strncpy(utmp.ut_host, ":PPP", sizeof(utmp.ut_host));
- (void)strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line));
- login(&utmp); /* This logs us in wtmp too */
-
-#endif /* #ifdef USE_PAM */
-
- syslog(LOG_INFO, "user %s logged in", user);
- logged_in = TRUE;
-
- return (UPAP_AUTHACK);
-}
-
-/*
- * plogout - Logout the user.
- */
-static void
-plogout()
-{
-#ifdef USE_PAM
- struct pam_conv pam_conversation;
- pam_handle_t *pamh;
- int pam_error;
-/*
- * Fill the pam_conversion structure. The PAM specification states that the
- * session must be able to be closed by a totally different handle from which
- * it was created. Hold the PAM group to their own specification!
- */
- memset (&pam_conversation, '\0', sizeof (struct pam_conv));
- pam_conversation.conv = &pam_conv;
-
- pam_error = pam_start ("ppp", user, &pam_conversation, &pamh);
- if (pam_error == PAM_SUCCESS) {
- (void) pam_set_item (pamh, PAM_TTY, devnam);
- (void) pam_close_session (pamh, PAM_SILENT);
- (void) pam_end (pamh, PAM_SUCCESS);
- }
-
-#else
- char *tty;
-
- tty = devnam;
- if (strncmp(tty, _PATH_DEV, sizeof _PATH_DEV - 1) == 0)
- tty += 5;
- logwtmp(tty, "", ""); /* Wipe out wtmp logout entry */
- logout(tty); /* Wipe out utmp */
-#endif
-
- logged_in = FALSE;
-}
-
-
-/*
- * null_login - Check if a username of "" and a password of "" are
- * acceptable, and iff so, set the list of acceptable IP addresses
- * and return 1.
- */
-static int
-null_login(unit)
- int unit;
-{
- char *filename;
- FILE *f;
- int i, ret;
- struct wordlist *addrs;
- char secret[MAXWORDLEN];
-
- /*
- * Open the file of pap secrets and scan for a suitable secret.
- * We don't accept a wildcard client.
- */
- filename = _PATH_UPAPFILE;
- addrs = NULL;
- f = fopen(filename, "r");
- if (f == NULL)
- return 0;
- check_access(f, filename);
-
- i = scan_authfile(f, "", our_name, (u_int32_t)0, secret, &addrs, filename);
- ret = i >= 0 && (i & NONWILD_CLIENT) != 0 && secret[0] == 0;
- BZERO(secret, sizeof(secret));
-
- if (ret)
- set_allowed_addrs(unit, addrs);
- else
- free_wordlist(addrs);
-
- fclose(f);
- return ret;
-}
-
-
-/*
- * get_pap_passwd - get a password for authenticating ourselves with
- * our peer using PAP. Returns 1 on success, 0 if no suitable password
- * could be found.
- */
-static int
-get_pap_passwd(passwd)
- char *passwd;
-{
- char *filename;
- FILE *f;
- int ret;
- struct wordlist *addrs;
- char secret[MAXWORDLEN];
-
- filename = _PATH_UPAPFILE;
- addrs = NULL;
- f = fopen(filename, "r");
- if (f == NULL)
- return 0;
- check_access(f, filename);
- ret = scan_authfile(f, user,
- remote_name[0]? remote_name: NULL,
- (u_int32_t)0, secret, NULL, filename);
- fclose(f);
- if (ret < 0)
- return 0;
- if (passwd != NULL) {
- strncpy(passwd, secret, MAXSECRETLEN);
- passwd[MAXSECRETLEN-1] = 0;
- }
- BZERO(secret, sizeof(secret));
- return 1;
-}
-
-
-/*
- * have_pap_secret - check whether we have a PAP file with any
- * secrets that we could possibly use for authenticating the peer.
- */
-static int
-have_pap_secret()
-{
- FILE *f;
- int ret;
- char *filename;
- ipcp_options *ipwo = &ipcp_wantoptions[0];
- u_int32_t remote;
-
- filename = _PATH_UPAPFILE;
- f = fopen(filename, "r");
- if (f == NULL)
- return 0;
-
- remote = ipwo->accept_remote? 0: ipwo->hisaddr;
- ret = scan_authfile(f, NULL, our_name, remote, NULL, NULL, filename);
- fclose(f);
- if (ret < 0)
- return 0;
-
- return 1;
-}
-
-
-/*
- * have_chap_secret - check whether we have a CHAP file with a
- * secret that we could possibly use for authenticating `client'
- * on `server'. Either can be the null string, meaning we don't
- * know the identity yet.
- */
-static int
-have_chap_secret(client, server, remote)
- char *client;
- char *server;
- u_int32_t remote;
-{
- FILE *f;
- int ret;
- char *filename;
-
- filename = _PATH_CHAPFILE;
- f = fopen(filename, "r");
- if (f == NULL)
- return 0;
-
- if (client[0] == 0)
- client = NULL;
- else if (server[0] == 0)
- server = NULL;
-
- ret = scan_authfile(f, client, server, remote, NULL, NULL, filename);
- fclose(f);
- if (ret < 0)
- return 0;
-
- return 1;
-}
-
-
-/*
- * get_secret - open the CHAP secret file and return the secret
- * for authenticating the given client on the given server.
- * (We could be either client or server).
- */
-int
-get_secret(unit, client, server, secret, secret_len, save_addrs)
- int unit;
- char *client;
- char *server;
- char *secret;
- int *secret_len;
- int save_addrs;
-{
- FILE *f;
- int ret, len;
- char *filename;
- struct wordlist *addrs;
- char secbuf[MAXWORDLEN];
-
- filename = _PATH_CHAPFILE;
- addrs = NULL;
- secbuf[0] = 0;
-
- f = fopen(filename, "r");
- if (f == NULL) {
- syslog(LOG_ERR, "Can't open chap secret file %s: %m", filename);
- return 0;
- }
- check_access(f, filename);
-
- ret = scan_authfile(f, client, server, (u_int32_t)0,
- secbuf, &addrs, filename);
- fclose(f);
- if (ret < 0)
- return 0;
-
- if (save_addrs)
- set_allowed_addrs(unit, addrs);
-
- len = strlen(secbuf);
- if (len > MAXSECRETLEN) {
- syslog(LOG_ERR, "Secret for %s on %s is too long", client, server);
- len = MAXSECRETLEN;
- }
- BCOPY(secbuf, secret, len);
- BZERO(secbuf, sizeof(secbuf));
- *secret_len = len;
-
- return 1;
-}
-
-/*
- * set_allowed_addrs() - set the list of allowed addresses.
- */
-static void
-set_allowed_addrs(unit, addrs)
- int unit;
- struct wordlist *addrs;
-{
- if (addresses[unit] != NULL)
- free_wordlist(addresses[unit]);
- addresses[unit] = addrs;
-
- /*
- * If there's only one authorized address we might as well
- * ask our peer for that one right away
- */
- if (addrs != NULL && addrs->next == NULL) {
- char *p = addrs->word;
- struct ipcp_options *wo = &ipcp_wantoptions[unit];
- u_int32_t a;
- struct hostent *hp;
-
- if (*p != '!' && *p != '-' && strchr(p, '/') == NULL) {
- hp = gethostbyname(p);
- if (hp != NULL && hp->h_addrtype == AF_INET)
- a = *(u_int32_t *)hp->h_addr;
- else
- a = inet_addr(p);
- if (a != (u_int32_t) -1)
- wo->hisaddr = a;
- }
- }
-}
-
-static void
-auth_set_ip_addr(unit)
- int unit;
-{
- struct wordlist *addrs;
-
- if (non_wildclient && (addrs = addresses[unit]) != NULL) {
- for (; addrs != NULL; addrs = addrs->next) {
- /* Look for address overrides, and set them if we have any */
- if (strchr(addrs->word, ':') != NULL) {
- if (setipaddr(addrs->word))
- break;
- }
- }
- }
-}
-
-/*
- * auth_ip_addr - check whether the peer is authorized to use
- * a given IP address. Returns 1 if authorized, 0 otherwise.
- */
-int
-auth_ip_addr(unit, addr)
- int unit;
- u_int32_t addr;
-{
- return ip_addr_check(addr, addresses[unit]);
-}
-
-static int
-ip_addr_check(addr, addrs)
- u_int32_t addr;
- struct wordlist *addrs;
-{
- int x, y;
- u_int32_t a, mask, ah;
- int accept;
- char *ptr_word, *ptr_mask;
- struct hostent *hp;
- struct netent *np;
-
- /* don't allow loopback or multicast address */
- if (bad_ip_adrs(addr))
- return 0;
-
- if (addrs == NULL)
- return !auth_required; /* no addresses authorized */
-
- x = y = 0;
- for (; addrs != NULL; addrs = addrs->next) {
- y++;
- /* "-" means no addresses authorized, "*" means any address allowed */
- ptr_word = addrs->word;
- if (strcmp(ptr_word, "-") == 0)
- break;
- if (strcmp(ptr_word, "*") == 0)
- return 1;
-
- /*
- * A colon in the string means that we wish to force a specific
- * local:remote address, but we ignore these for now.
- */
- if (strchr(addrs->word, ':') != NULL)
- x++;
- else {
-
- accept = 1;
- if (*ptr_word == '!') {
- accept = 0;
- ++ptr_word;
- }
-
- mask = ~ (u_int32_t) 0;
- ptr_mask = strchr (ptr_word, '/');
- if (ptr_mask != NULL) {
- int bit_count;
-
- bit_count = (int) strtol (ptr_mask+1, (char **) 0, 10);
- if (bit_count <= 0 || bit_count > 32) {
- syslog (LOG_WARNING,
- "invalid address length %s in auth. address list",
- ptr_mask);
- continue;
- }
- *ptr_mask = '\0';
- mask <<= 32 - bit_count;
- }
-
- hp = gethostbyname(ptr_word);
- if (hp != NULL && hp->h_addrtype == AF_INET) {
- a = *(u_int32_t *)hp->h_addr;
- } else {
- np = getnetbyname (ptr_word);
- if (np != NULL && np->n_addrtype == AF_INET) {
- a = htonl (*(u_int32_t *)np->n_net);
- if (ptr_mask == NULL) {
- /* calculate appropriate mask for net */
- ah = ntohl(a);
- if (IN_CLASSA(ah))
- mask = IN_CLASSA_NET;
- else if (IN_CLASSB(ah))
- mask = IN_CLASSB_NET;
- else if (IN_CLASSC(ah))
- mask = IN_CLASSC_NET;
- }
- } else {
- a = inet_addr (ptr_word);
- }
- }
-
- if (ptr_mask != NULL)
- *ptr_mask = '/';
-
- if (a == (u_int32_t)-1L)
- syslog (LOG_WARNING,
- "unknown host %s in auth. address list",
- addrs->word);
- else
- /* Here a and addr are in network byte order,
- and mask is in host order. */
- if (((addr ^ a) & htonl(mask)) == 0)
- return accept;
- } /* else */
- }
- return x == y; /* not in list => can't have it */
-}
-
-/*
- * bad_ip_adrs - return 1 if the IP address is one we don't want
- * to use, such as an address in the loopback net or a multicast address.
- * addr is in network byte order.
- */
-int
-bad_ip_adrs(addr)
- u_int32_t addr;
-{
- addr = ntohl(addr);
- return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET
- || IN_MULTICAST(addr) || IN_BADCLASS(addr);
-}
-
-/*
- * check_access - complain if a secret file has too-liberal permissions.
- */
-void
-check_access(f, filename)
- FILE *f;
- char *filename;
-{
- struct stat sbuf;
-
- if (fstat(fileno(f), &sbuf) < 0) {
- syslog(LOG_WARNING, "cannot stat secret file %s: %m", filename);
- } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) {
- syslog(LOG_WARNING, "Warning - secret file %s has world and/or group access", filename);
- }
-}
-
-
-/*
- * scan_authfile - Scan an authorization file for a secret suitable
- * for authenticating `client' on `server'. The return value is -1
- * if no secret is found, otherwise >= 0. The return value has
- * NONWILD_CLIENT set if the secret didn't have "*" for the client, and
- * NONWILD_SERVER set if the secret didn't have "*" for the server.
- * Any following words on the line (i.e. address authorization
- * info) are placed in a wordlist and returned in *addrs.
- */
-static int
-scan_authfile(f, client, server, ipaddr, secret, addrs, filename)
- FILE *f;
- char *client;
- char *server;
- u_int32_t ipaddr;
- char *secret;
- struct wordlist **addrs;
- char *filename;
-{
- int newline, xxx;
- int got_flag, best_flag;
- FILE *sf;
- struct wordlist *ap, *addr_list, *alist, *alast;
- char word[MAXWORDLEN];
- char atfile[MAXWORDLEN];
- char lsecret[MAXWORDLEN];
-
- if (addrs != NULL)
- *addrs = NULL;
- addr_list = NULL;
- if (!getword(f, word, &newline, filename))
- return -1; /* file is empty??? */
- newline = 1;
- best_flag = -1;
- for (;;) {
- /*
- * Skip until we find a word at the start of a line.
- */
- while (!newline && getword(f, word, &newline, filename))
- ;
- if (!newline)
- break; /* got to end of file */
-
- /*
- * Got a client - check if it's a match or a wildcard.
- */
- got_flag = 0;
- if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) {
- newline = 0;
- continue;
- }
- if (!ISWILD(word))
- got_flag = NONWILD_CLIENT;
-
- /*
- * Now get a server and check if it matches.
- */
- if (!getword(f, word, &newline, filename))
- break;
- if (newline)
- continue;
- if (server != NULL && strcmp(word, server) != 0 && !ISWILD(word))
- continue;
- if (!ISWILD(word))
- got_flag |= NONWILD_SERVER;
-
- /*
- * Got some sort of a match - see if it's better than what
- * we have already.
- */
- if (got_flag <= best_flag)
- continue;
-
- /*
- * Get the secret.
- */
- if (!getword(f, word, &newline, filename))
- break;
- if (newline)
- continue;
-
- /*
- * Special syntax: @filename means read secret from file.
- */
- if (word[0] == '@') {
- strcpy(atfile, word+1);
- if ((sf = fopen(atfile, "r")) == NULL) {
- syslog(LOG_WARNING, "can't open indirect secret file %s",
- atfile);
- continue;
- }
- check_access(sf, atfile);
- if (!getword(sf, word, &xxx, atfile)) {
- syslog(LOG_WARNING, "no secret in indirect secret file %s",
- atfile);
- fclose(sf);
- continue;
- }
- fclose(sf);
- }
- if (secret != NULL)
- strcpy(lsecret, word);
-
- /*
- * Now read address authorization info and make a wordlist.
- */
- alist = alast = NULL;
- for (;;) {
- if (!getword(f, word, &newline, filename) || newline)
- break;
- ap = (struct wordlist *) malloc(sizeof(struct wordlist)
- + strlen(word));
- if (ap == NULL)
- novm("authorized addresses");
- ap->next = NULL;
- strcpy(ap->word, word);
- if (alist == NULL)
- alist = ap;
- else
- alast->next = ap;
- alast = ap;
- }
-
- /*
- * Check if the given IP address is allowed by the wordlist.
- */
- if (ipaddr != 0 && !ip_addr_check(ipaddr, alist)) {
- free_wordlist(alist);
- continue;
- }
-
- /*
- * This is the best so far; remember it.
- */
- best_flag = got_flag;
- if (addr_list)
- free_wordlist(addr_list);
- addr_list = alist;
- if (secret != NULL)
- strcpy(secret, lsecret);
-
- if (!newline)
- break;
- }
-
- if (addrs != NULL)
- *addrs = addr_list;
- else if (addr_list != NULL)
- free_wordlist(addr_list);
-
- non_wildclient = (best_flag & NONWILD_CLIENT) && client != NULL &&
- *client != '\0';
- return best_flag;
-}
-
-/*
- * free_wordlist - release memory allocated for a wordlist.
- */
-static void
-free_wordlist(wp)
- struct wordlist *wp;
-{
- struct wordlist *next;
-
- while (wp != NULL) {
- next = wp->next;
- free(wp);
- wp = next;
- }
-}
-
-/*
- * auth_script - execute a script with arguments
- * interface-name peer-name real-user tty speed
- */
-static void
-auth_script(script)
- char *script;
-{
- char strspeed[32];
- struct passwd *pw;
- char struid[32];
- char *user_name;
- char *argv[7];
-
- if ((pw = getpwuid(getuid())) != NULL && pw->pw_name != NULL)
- user_name = pw->pw_name;
- else {
- sprintf(struid, "%d", getuid());
- user_name = struid;
- }
- sprintf(strspeed, "%d", baud_rate);
-
- argv[0] = script;
- argv[1] = ifname;
- argv[2] = peer_authname;
- argv[3] = user_name;
- argv[4] = devnam;
- argv[5] = strspeed;
- argv[6] = NULL;
-
- run_program(script, argv, 0);
-}
diff --git a/usr.sbin/pppd/cbcp.c b/usr.sbin/pppd/cbcp.c
deleted file mode 100644
index 7bcfcab..0000000
--- a/usr.sbin/pppd/cbcp.c
+++ /dev/null
@@ -1,411 +0,0 @@
-/*
- * cbcp - Call Back Configuration Protocol.
- *
- * Copyright (c) 1995 Pedro Roque Marques
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Pedro Roque Marques. The name of the author may not be used to
- * endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <syslog.h>
-
-#include "pppd.h"
-#include "cbcp.h"
-#include "fsm.h"
-#include "lcp.h"
-#include "ipcp.h"
-
-/*
- * Protocol entry points.
- */
-static void cbcp_init(int unit);
-static void cbcp_open(int unit);
-static void cbcp_lowerup(int unit);
-static void cbcp_input(int unit, u_char *pkt, int len);
-static void cbcp_protrej(int unit);
-static int cbcp_printpkt(u_char *pkt, int len,
- void (*printer)(void *, char *, ...),
- void *arg);
-
-struct protent cbcp_protent = {
- PPP_CBCP,
- cbcp_init,
- cbcp_input,
- cbcp_protrej,
- cbcp_lowerup,
- NULL,
- cbcp_open,
- NULL,
- cbcp_printpkt,
- NULL,
- 0,
- "CBCP",
- NULL,
- NULL,
- NULL
-};
-
-cbcp_state cbcp[NUM_PPP];
-
-/* internal prototypes */
-
-static void cbcp_recvreq(cbcp_state *us, char *pckt, int len);
-static void cbcp_resp(cbcp_state *us);
-static void cbcp_up(cbcp_state *us);
-static void cbcp_recvack(cbcp_state *us, char *pckt, int len);
-static void cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len);
-
-/* init state */
-static void
-cbcp_init(int iface)
-{
- cbcp_state *us;
-
- us = &cbcp[iface];
- memset(us, 0, sizeof(cbcp_state));
- us->us_unit = iface;
- us->us_type |= (1 << CB_CONF_NO);
-}
-
-/* lower layer is up */
-static void
-cbcp_lowerup(int iface)
-{
- cbcp_state *us = &cbcp[iface];
-
- syslog(LOG_DEBUG, "cbcp_lowerup");
- syslog(LOG_DEBUG, "want: %d", us->us_type);
-
- if (us->us_type == CB_CONF_USER)
- syslog(LOG_DEBUG, "phone no: %s", us->us_number);
-}
-
-static void
-cbcp_open(int unit)
-{
- syslog(LOG_DEBUG, "cbcp_open");
-}
-
-/* process an incomming packet */
-static void
-cbcp_input(int unit, u_char *inpacket, int pktlen)
-{
- u_char *inp;
- u_char code, id;
- u_short len;
-
- cbcp_state *us = &cbcp[unit];
-
- inp = inpacket;
-
- if (pktlen < CBCP_MINLEN) {
- syslog(LOG_ERR, "CBCP packet is too small");
- return;
- }
-
- GETCHAR(code, inp);
- GETCHAR(id, inp);
- GETSHORT(len, inp);
-
- if (len < CBCP_MINLEN || len > pktlen) {
- syslog(LOG_ERR, "CBCP packet: invalid length");
- return;
- }
-
- len -= CBCP_MINLEN;
-
- switch(code) {
- case CBCP_REQ:
- us->us_id = id;
- cbcp_recvreq(us, inp, len);
- break;
-
- case CBCP_RESP:
- syslog(LOG_DEBUG, "CBCP_RESP received");
- break;
-
- case CBCP_ACK:
- if (id != us->us_id)
- syslog(LOG_DEBUG, "id doesn't match: expected %d recv %d",
- us->us_id, id);
-
- cbcp_recvack(us, inp, len);
- break;
-
- default:
- break;
- }
-}
-
-/* protocol was rejected by foe */
-void cbcp_protrej(int iface)
-{
-}
-
-char *cbcp_codenames[] = {
- "Request", "Response", "Ack"
-};
-
-char *cbcp_optionnames[] = {
- "NoCallback",
- "UserDefined",
- "AdminDefined",
- "List"
-};
-
-/* pretty print a packet */
-static int
-cbcp_printpkt(u_char *p, int plen, void (*printer)(void *, char *, ...),
- void *arg)
-{
- int code, opt, id, len, olen, delay;
- u_char *pstart;
-
- if (plen < HEADERLEN)
- return 0;
- pstart = p;
- GETCHAR(code, p);
- GETCHAR(id, p);
- GETSHORT(len, p);
- if (len < HEADERLEN || len > plen)
- return 0;
-
- if (code >= 1 && code <= sizeof(cbcp_codenames) / sizeof(char *))
- printer(arg, " %s", cbcp_codenames[code-1]);
- else
- printer(arg, " code=0x%x", code);
-
- printer(arg, " id=0x%x", id);
- len -= HEADERLEN;
-
- switch (code) {
- case CBCP_REQ:
- case CBCP_RESP:
- case CBCP_ACK:
- while(len >= 2) {
- GETCHAR(opt, p);
- GETCHAR(olen, p);
-
- if (olen < 2 || olen > len) {
- break;
- }
-
- printer(arg, " <");
- len -= olen;
-
- if (opt >= 1 && opt <= sizeof(cbcp_optionnames) / sizeof(char *))
- printer(arg, " %s", cbcp_optionnames[opt-1]);
- else
- printer(arg, " option=0x%x", opt);
-
- if (olen > 2) {
- GETCHAR(delay, p);
- printer(arg, " delay = %d", delay);
- }
-
- if (olen > 3) {
- int addrt;
- char str[256];
-
- GETCHAR(addrt, p);
- memcpy(str, p, olen - 4);
- str[olen - 4] = 0;
- printer(arg, " number = %s", str);
- }
- printer(arg, ">");
- break;
- }
-
- default:
- break;
- }
-
- for (; len > 0; --len) {
- GETCHAR(code, p);
- printer(arg, " %.2x", code);
- }
-
- return p - pstart;
-}
-
-/* received CBCP request */
-static void
-cbcp_recvreq(cbcp_state *us, char *pckt, int pcktlen)
-{
- u_char type, opt_len, delay, addr_type;
- char address[256];
- int len = pcktlen;
-
- address[0] = 0;
-
- while (len > 1) {
- syslog(LOG_DEBUG, "length: %d", len);
-
- GETCHAR(type, pckt);
- GETCHAR(opt_len, pckt);
-
- if (len < opt_len)
- break;
- len -= opt_len;
-
- if (opt_len > 2)
- GETCHAR(delay, pckt);
-
- us->us_allowed |= (1 << type);
-
- switch(type) {
- case CB_CONF_NO:
- syslog(LOG_DEBUG, "no callback allowed");
- break;
-
- case CB_CONF_USER:
- syslog(LOG_DEBUG, "user callback allowed");
- if (opt_len > 4) {
- GETCHAR(addr_type, pckt);
- memcpy(address, pckt, opt_len - 4);
- address[opt_len - 4] = 0;
- if (address[0])
- syslog(LOG_DEBUG, "address: %s", address);
- }
- break;
-
- case CB_CONF_ADMIN:
- syslog(LOG_DEBUG, "user admin defined allowed");
- break;
-
- case CB_CONF_LIST:
- break;
- }
- }
-
- cbcp_resp(us);
-}
-
-static void
-cbcp_resp(cbcp_state *us)
-{
- u_char cb_type;
- u_char buf[256];
- u_char *bufp = buf;
- int len = 0;
-
- cb_type = us->us_allowed & us->us_type;
- syslog(LOG_DEBUG, "cbcp_resp cb_type=%d", cb_type);
-
-#if 0
- if (!cb_type)
- lcp_down(us->us_unit);
-#endif
-
- if (cb_type & ( 1 << CB_CONF_USER ) ) {
- syslog(LOG_DEBUG, "cbcp_resp CONF_USER");
- PUTCHAR(CB_CONF_USER, bufp);
- len = 3 + 1 + strlen(us->us_number) + 1;
- PUTCHAR(len , bufp);
- PUTCHAR(5, bufp); /* delay */
- PUTCHAR(1, bufp);
- BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
- cbcp_send(us, CBCP_RESP, buf, len);
- return;
- }
-
- if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
- syslog(LOG_DEBUG, "cbcp_resp CONF_ADMIN");
- PUTCHAR(CB_CONF_ADMIN, bufp);
- len = 3;
- PUTCHAR(len, bufp);
- PUTCHAR(5, bufp); /* delay */
- cbcp_send(us, CBCP_RESP, buf, len);
- return;
- }
-
- if (cb_type & ( 1 << CB_CONF_NO ) ) {
- syslog(LOG_DEBUG, "cbcp_resp CONF_NO");
- PUTCHAR(CB_CONF_NO, bufp);
- len = 2;
- PUTCHAR(len , bufp);
- cbcp_send(us, CBCP_RESP, buf, len);
- (*ipcp_protent.open)(us->us_unit);
- return;
- }
-}
-
-static void
-cbcp_send(cbcp_state *us, u_char code, u_char *buf, int len)
-{
- u_char *outp;
- int outlen;
-
- outp = outpacket_buf;
-
- outlen = 4 + len;
-
- MAKEHEADER(outp, PPP_CBCP);
-
- PUTCHAR(code, outp);
- PUTCHAR(us->us_id, outp);
- PUTSHORT(outlen, outp);
-
- if (len)
- BCOPY(buf, outp, len);
-
- output(us->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
-}
-
-static void
-cbcp_recvack(cbcp_state *us, char *pckt, int len)
-{
- u_char type, delay, addr_type;
- int opt_len;
- char address[256];
-
- if (len > 1) {
- GETCHAR(type, pckt);
- GETCHAR(opt_len, pckt);
-
- if (opt_len > len)
- return;
-
- if (opt_len > 2)
- GETCHAR(delay, pckt);
-
- if (opt_len > 4) {
- GETCHAR(addr_type, pckt);
- memcpy(address, pckt, opt_len - 4);
- address[opt_len - 4] = 0;
- if (address[0])
- syslog(LOG_DEBUG, "peer will call: %s", address);
- }
- }
-
- cbcp_up(us);
-}
-
-extern int persist;
-
-/* ok peer will do callback */
-static void
-cbcp_up(cbcp_state *us)
-{
- persist = 0;
- lcp_close(0, "Call me back, please");
-}
diff --git a/usr.sbin/pppd/cbcp.h b/usr.sbin/pppd/cbcp.h
deleted file mode 100644
index c2ab3f6..0000000
--- a/usr.sbin/pppd/cbcp.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef CBCP_H
-#define CBCP_H
-
-typedef struct cbcp_state {
- int us_unit; /* Interface unit number */
- u_char us_id; /* Current id */
- u_char us_allowed;
- int us_type;
- char *us_number; /* Telefone Number */
-} cbcp_state;
-
-extern cbcp_state cbcp[];
-
-extern struct protent cbcp_protent;
-
-#define CBCP_MINLEN 4
-
-#define CBCP_REQ 1
-#define CBCP_RESP 2
-#define CBCP_ACK 3
-
-#define CB_CONF_NO 1
-#define CB_CONF_USER 2
-#define CB_CONF_ADMIN 3
-#define CB_CONF_LIST 4
-#endif
diff --git a/usr.sbin/pppd/ccp.c b/usr.sbin/pppd/ccp.c
deleted file mode 100644
index ba88135..0000000
--- a/usr.sbin/pppd/ccp.c
+++ /dev/null
@@ -1,1113 +0,0 @@
-/*
- * ccp.c - PPP Compression Control Protocol.
- *
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies. This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
- *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-#include <string.h>
-#include <syslog.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-
-#include "pppd.h"
-#include "fsm.h"
-#include "ccp.h"
-#include <net/ppp_comp.h>
-
-/*
- * Protocol entry points from main code.
- */
-static void ccp_init(int unit);
-static void ccp_open(int unit);
-static void ccp_close(int unit, char *);
-static void ccp_lowerup(int unit);
-static void ccp_lowerdown(int);
-static void ccp_input(int unit, u_char *pkt, int len);
-static void ccp_protrej(int unit);
-static int ccp_printpkt(u_char *pkt, int len,
- void (*printer)(void *, char *, ...),
- void *arg);
-static void ccp_datainput(int unit, u_char *pkt, int len);
-
-struct protent ccp_protent = {
- PPP_CCP,
- ccp_init,
- ccp_input,
- ccp_protrej,
- ccp_lowerup,
- ccp_lowerdown,
- ccp_open,
- ccp_close,
- ccp_printpkt,
- ccp_datainput,
- 1,
- "CCP",
- NULL,
- NULL,
- NULL
-};
-
-fsm ccp_fsm[NUM_PPP];
-ccp_options ccp_wantoptions[NUM_PPP]; /* what to request the peer to use */
-ccp_options ccp_gotoptions[NUM_PPP]; /* what the peer agreed to do */
-ccp_options ccp_allowoptions[NUM_PPP]; /* what we'll agree to do */
-ccp_options ccp_hisoptions[NUM_PPP]; /* what we agreed to do */
-
-/*
- * Callbacks for fsm code.
- */
-static void ccp_resetci(fsm *);
-static int ccp_cilen(fsm *);
-static void ccp_addci(fsm *, u_char *, int *);
-static int ccp_ackci(fsm *, u_char *, int);
-static int ccp_nakci(fsm *, u_char *, int);
-static int ccp_rejci(fsm *, u_char *, int);
-static int ccp_reqci(fsm *, u_char *, int *, int);
-static void ccp_up(fsm *);
-static void ccp_down(fsm *);
-static int ccp_extcode(fsm *, int, int, u_char *, int);
-static void ccp_rack_timeout(void *);
-static char *method_name(ccp_options *, ccp_options *);
-
-static fsm_callbacks ccp_callbacks = {
- ccp_resetci,
- ccp_cilen,
- ccp_addci,
- ccp_ackci,
- ccp_nakci,
- ccp_rejci,
- ccp_reqci,
- ccp_up,
- ccp_down,
- NULL,
- NULL,
- NULL,
- NULL,
- ccp_extcode,
- "CCP"
-};
-
-/*
- * Do we want / did we get any compression?
- */
-#define ANY_COMPRESS(opt) ((opt).deflate || (opt).bsd_compress \
- || (opt).predictor_1 || (opt).predictor_2)
-
-/*
- * Local state (mainly for handling reset-reqs and reset-acks).
- */
-static int ccp_localstate[NUM_PPP];
-#define RACK_PENDING 1 /* waiting for reset-ack */
-#define RREQ_REPEAT 2 /* send another reset-req if no reset-ack */
-
-#define RACKTIMEOUT 1 /* second */
-
-static int all_rejected[NUM_PPP]; /* we rejected all peer's options */
-
-/*
- * ccp_init - initialize CCP.
- */
-static void
-ccp_init(unit)
- int unit;
-{
- fsm *f = &ccp_fsm[unit];
-
- f->unit = unit;
- f->protocol = PPP_CCP;
- f->callbacks = &ccp_callbacks;
- fsm_init(f);
-
- memset(&ccp_wantoptions[unit], 0, sizeof(ccp_options));
- memset(&ccp_gotoptions[unit], 0, sizeof(ccp_options));
- memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options));
- memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options));
-
- ccp_wantoptions[0].deflate = 1;
- ccp_wantoptions[0].deflate_size = DEFLATE_MAX_SIZE;
- ccp_wantoptions[0].deflate_correct = 1;
- ccp_wantoptions[0].deflate_draft = 1;
- ccp_allowoptions[0].deflate = 1;
- ccp_allowoptions[0].deflate_size = DEFLATE_MAX_SIZE;
- ccp_allowoptions[0].deflate_correct = 1;
- ccp_allowoptions[0].deflate_draft = 1;
-
- ccp_wantoptions[0].bsd_compress = 1;
- ccp_wantoptions[0].bsd_bits = BSD_MAX_BITS;
- ccp_allowoptions[0].bsd_compress = 1;
- ccp_allowoptions[0].bsd_bits = BSD_MAX_BITS;
-
- ccp_allowoptions[0].predictor_1 = 1;
-}
-
-/*
- * ccp_open - CCP is allowed to come up.
- */
-static void
-ccp_open(unit)
- int unit;
-{
- fsm *f = &ccp_fsm[unit];
-
- if (f->state != OPENED)
- ccp_flags_set(unit, 1, 0);
-
- /*
- * Find out which compressors the kernel supports before
- * deciding whether to open in silent mode.
- */
- ccp_resetci(f);
- if (!ANY_COMPRESS(ccp_gotoptions[unit]))
- f->flags |= OPT_SILENT;
-
- fsm_open(f);
-}
-
-/*
- * ccp_close - Terminate CCP.
- */
-static void
-ccp_close(unit, reason)
- int unit;
- char *reason;
-{
- ccp_flags_set(unit, 0, 0);
- fsm_close(&ccp_fsm[unit], reason);
-}
-
-/*
- * ccp_lowerup - we may now transmit CCP packets.
- */
-static void
-ccp_lowerup(unit)
- int unit;
-{
- fsm_lowerup(&ccp_fsm[unit]);
-}
-
-/*
- * ccp_lowerdown - we may not transmit CCP packets.
- */
-static void
-ccp_lowerdown(unit)
- int unit;
-{
- fsm_lowerdown(&ccp_fsm[unit]);
-}
-
-/*
- * ccp_input - process a received CCP packet.
- */
-static void
-ccp_input(unit, p, len)
- int unit;
- u_char *p;
- int len;
-{
- fsm *f = &ccp_fsm[unit];
- int oldstate;
-
- /*
- * Check for a terminate-request so we can print a message.
- */
- oldstate = f->state;
- fsm_input(f, p, len);
- if (oldstate == OPENED && p[0] == TERMREQ && f->state != OPENED)
- syslog(LOG_NOTICE, "Compression disabled by peer.");
-
- /*
- * If we get a terminate-ack and we're not asking for compression,
- * close CCP.
- */
- if (oldstate == REQSENT && p[0] == TERMACK
- && !ANY_COMPRESS(ccp_gotoptions[unit]))
- ccp_close(unit, "No compression negotiated");
-}
-
-/*
- * Handle a CCP-specific code.
- */
-static int
-ccp_extcode(f, code, id, p, len)
- fsm *f;
- int code, id;
- u_char *p;
- int len;
-{
- switch (code) {
- case CCP_RESETREQ:
- if (f->state != OPENED)
- break;
- /* send a reset-ack, which the transmitter will see and
- reset its compression state. */
- fsm_sdata(f, CCP_RESETACK, id, NULL, 0);
- break;
-
- case CCP_RESETACK:
- if (ccp_localstate[f->unit] & RACK_PENDING && id == f->reqid) {
- ccp_localstate[f->unit] &= ~(RACK_PENDING | RREQ_REPEAT);
- UNTIMEOUT(ccp_rack_timeout, f);
- }
- break;
-
- default:
- return 0;
- }
-
- return 1;
-}
-
-/*
- * ccp_protrej - peer doesn't talk CCP.
- */
-static void
-ccp_protrej(unit)
- int unit;
-{
- ccp_flags_set(unit, 0, 0);
- fsm_lowerdown(&ccp_fsm[unit]);
-}
-
-/*
- * ccp_resetci - initialize at start of negotiation.
- */
-static void
-ccp_resetci(f)
- fsm *f;
-{
- ccp_options *go = &ccp_gotoptions[f->unit];
- u_char opt_buf[16];
-
- *go = ccp_wantoptions[f->unit];
- all_rejected[f->unit] = 0;
-
- /*
- * Check whether the kernel knows about the various
- * compression methods we might request.
- */
- if (go->bsd_compress) {
- opt_buf[0] = CI_BSD_COMPRESS;
- opt_buf[1] = CILEN_BSD_COMPRESS;
- opt_buf[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, BSD_MIN_BITS);
- if (ccp_test(f->unit, opt_buf, CILEN_BSD_COMPRESS, 0) <= 0)
- go->bsd_compress = 0;
- }
- if (go->deflate) {
- if (go->deflate_correct) {
- opt_buf[0] = CI_DEFLATE;
- opt_buf[1] = CILEN_DEFLATE;
- opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
- opt_buf[3] = DEFLATE_CHK_SEQUENCE;
- if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
- go->deflate_correct = 0;
- }
- if (go->deflate_draft) {
- opt_buf[0] = CI_DEFLATE_DRAFT;
- opt_buf[1] = CILEN_DEFLATE;
- opt_buf[2] = DEFLATE_MAKE_OPT(DEFLATE_MIN_SIZE);
- opt_buf[3] = DEFLATE_CHK_SEQUENCE;
- if (ccp_test(f->unit, opt_buf, CILEN_DEFLATE, 0) <= 0)
- go->deflate_draft = 0;
- }
- if (!go->deflate_correct && !go->deflate_draft)
- go->deflate = 0;
- }
- if (go->predictor_1) {
- opt_buf[0] = CI_PREDICTOR_1;
- opt_buf[1] = CILEN_PREDICTOR_1;
- if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_1, 0) <= 0)
- go->predictor_1 = 0;
- }
- if (go->predictor_2) {
- opt_buf[0] = CI_PREDICTOR_2;
- opt_buf[1] = CILEN_PREDICTOR_2;
- if (ccp_test(f->unit, opt_buf, CILEN_PREDICTOR_2, 0) <= 0)
- go->predictor_2 = 0;
- }
-}
-
-/*
- * ccp_cilen - Return total length of our configuration info.
- */
-static int
-ccp_cilen(f)
- fsm *f;
-{
- ccp_options *go = &ccp_gotoptions[f->unit];
-
- return (go->bsd_compress? CILEN_BSD_COMPRESS: 0)
- + (go->deflate? CILEN_DEFLATE: 0)
- + (go->predictor_1? CILEN_PREDICTOR_1: 0)
- + (go->predictor_2? CILEN_PREDICTOR_2: 0);
-}
-
-/*
- * ccp_addci - put our requests in a packet.
- */
-static void
-ccp_addci(f, p, lenp)
- fsm *f;
- u_char *p;
- int *lenp;
-{
- int res;
- ccp_options *go = &ccp_gotoptions[f->unit];
- u_char *p0 = p;
-
- /*
- * Add the compression types that we can receive, in decreasing
- * preference order. Get the kernel to allocate the first one
- * in case it gets Acked.
- */
- if (go->deflate) {
- p[0] = go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT;
- p[1] = CILEN_DEFLATE;
- p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
- p[3] = DEFLATE_CHK_SEQUENCE;
- for (;;) {
- res = ccp_test(f->unit, p, CILEN_DEFLATE, 0);
- if (res > 0) {
- p += CILEN_DEFLATE;
- break;
- }
- if (res < 0 || go->deflate_size <= DEFLATE_MIN_SIZE) {
- go->deflate = 0;
- break;
- }
- --go->deflate_size;
- p[2] = DEFLATE_MAKE_OPT(go->deflate_size);
- }
- if (p != p0 && go->deflate_correct && go->deflate_draft) {
- p[0] = CI_DEFLATE_DRAFT;
- p[1] = CILEN_DEFLATE;
- p[2] = p[2 - CILEN_DEFLATE];
- p[3] = DEFLATE_CHK_SEQUENCE;
- p += CILEN_DEFLATE;
- }
- }
- if (go->bsd_compress) {
- p[0] = CI_BSD_COMPRESS;
- p[1] = CILEN_BSD_COMPRESS;
- p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
- if (p != p0) {
- p += CILEN_BSD_COMPRESS; /* not the first option */
- } else {
- for (;;) {
- res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 0);
- if (res > 0) {
- p += CILEN_BSD_COMPRESS;
- break;
- }
- if (res < 0 || go->bsd_bits <= BSD_MIN_BITS) {
- go->bsd_compress = 0;
- break;
- }
- --go->bsd_bits;
- p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits);
- }
- }
- }
- /* XXX Should Predictor 2 be preferable to Predictor 1? */
- if (go->predictor_1) {
- p[0] = CI_PREDICTOR_1;
- p[1] = CILEN_PREDICTOR_1;
- if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 0) <= 0) {
- go->predictor_1 = 0;
- } else {
- p += CILEN_PREDICTOR_1;
- }
- }
- if (go->predictor_2) {
- p[0] = CI_PREDICTOR_2;
- p[1] = CILEN_PREDICTOR_2;
- if (p == p0 && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 0) <= 0) {
- go->predictor_2 = 0;
- } else {
- p += CILEN_PREDICTOR_2;
- }
- }
-
- go->method = (p > p0)? p0[0]: -1;
-
- *lenp = p - p0;
-}
-
-/*
- * ccp_ackci - process a received configure-ack, and return
- * 1 iff the packet was OK.
- */
-static int
-ccp_ackci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- ccp_options *go = &ccp_gotoptions[f->unit];
- u_char *p0 = p;
-
- if (go->deflate) {
- if (len < CILEN_DEFLATE
- || p[0] != (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
- || p[1] != CILEN_DEFLATE
- || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
- || p[3] != DEFLATE_CHK_SEQUENCE)
- return 0;
- p += CILEN_DEFLATE;
- len -= CILEN_DEFLATE;
- /* XXX Cope with first/fast ack */
- if (len == 0)
- return 1;
- if (go->deflate_correct && go->deflate_draft) {
- if (len < CILEN_DEFLATE
- || p[0] != CI_DEFLATE_DRAFT
- || p[1] != CILEN_DEFLATE
- || p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
- || p[3] != DEFLATE_CHK_SEQUENCE)
- return 0;
- p += CILEN_DEFLATE;
- len -= CILEN_DEFLATE;
- }
- }
- if (go->bsd_compress) {
- if (len < CILEN_BSD_COMPRESS
- || p[0] != CI_BSD_COMPRESS || p[1] != CILEN_BSD_COMPRESS
- || p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
- return 0;
- p += CILEN_BSD_COMPRESS;
- len -= CILEN_BSD_COMPRESS;
- /* XXX Cope with first/fast ack */
- if (p == p0 && len == 0)
- return 1;
- }
- if (go->predictor_1) {
- if (len < CILEN_PREDICTOR_1
- || p[0] != CI_PREDICTOR_1 || p[1] != CILEN_PREDICTOR_1)
- return 0;
- p += CILEN_PREDICTOR_1;
- len -= CILEN_PREDICTOR_1;
- /* XXX Cope with first/fast ack */
- if (p == p0 && len == 0)
- return 1;
- }
- if (go->predictor_2) {
- if (len < CILEN_PREDICTOR_2
- || p[0] != CI_PREDICTOR_2 || p[1] != CILEN_PREDICTOR_2)
- return 0;
- p += CILEN_PREDICTOR_2;
- len -= CILEN_PREDICTOR_2;
- /* XXX Cope with first/fast ack */
- if (p == p0 && len == 0)
- return 1;
- }
-
- if (len != 0)
- return 0;
- return 1;
-}
-
-/*
- * ccp_nakci - process received configure-nak.
- * Returns 1 iff the nak was OK.
- */
-static int
-ccp_nakci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- ccp_options *go = &ccp_gotoptions[f->unit];
- ccp_options no; /* options we've seen already */
- ccp_options try; /* options to ask for next time */
-
- memset(&no, 0, sizeof(no));
- try = *go;
-
- if (go->deflate && len >= CILEN_DEFLATE
- && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
- && p[1] == CILEN_DEFLATE) {
- no.deflate = 1;
- /*
- * Peer wants us to use a different code size or something.
- * Stop asking for Deflate if we don't understand his suggestion.
- */
- if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
- || DEFLATE_SIZE(p[2]) < DEFLATE_MIN_SIZE
- || p[3] != DEFLATE_CHK_SEQUENCE)
- try.deflate = 0;
- else if (DEFLATE_SIZE(p[2]) < go->deflate_size)
- try.deflate_size = DEFLATE_SIZE(p[2]);
- p += CILEN_DEFLATE;
- len -= CILEN_DEFLATE;
- if (go->deflate_correct && go->deflate_draft
- && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
- && p[1] == CILEN_DEFLATE) {
- p += CILEN_DEFLATE;
- len -= CILEN_DEFLATE;
- }
- }
-
- if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
- && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
- no.bsd_compress = 1;
- /*
- * Peer wants us to use a different number of bits
- * or a different version.
- */
- if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION)
- try.bsd_compress = 0;
- else if (BSD_NBITS(p[2]) < go->bsd_bits)
- try.bsd_bits = BSD_NBITS(p[2]);
- p += CILEN_BSD_COMPRESS;
- len -= CILEN_BSD_COMPRESS;
- }
-
- /*
- * Predictor-1 and 2 have no options, so they can't be Naked.
- *
- * XXX What should we do with any remaining options?
- */
-
- if (len != 0)
- return 0;
-
- if (f->state != OPENED)
- *go = try;
- return 1;
-}
-
-/*
- * ccp_rejci - reject some of our suggested compression methods.
- */
-static int
-ccp_rejci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- ccp_options *go = &ccp_gotoptions[f->unit];
- ccp_options try; /* options to request next time */
-
- try = *go;
-
- /*
- * Cope with empty configure-rejects by ceasing to send
- * configure-requests.
- */
- if (len == 0 && all_rejected[f->unit])
- return -1;
-
- if (go->deflate && len >= CILEN_DEFLATE
- && p[0] == (go->deflate_correct? CI_DEFLATE: CI_DEFLATE_DRAFT)
- && p[1] == CILEN_DEFLATE) {
- if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
- || p[3] != DEFLATE_CHK_SEQUENCE)
- return 0; /* Rej is bad */
- if (go->deflate_correct)
- try.deflate_correct = 0;
- else
- try.deflate_draft = 0;
- p += CILEN_DEFLATE;
- len -= CILEN_DEFLATE;
- if (go->deflate_correct && go->deflate_draft
- && len >= CILEN_DEFLATE && p[0] == CI_DEFLATE_DRAFT
- && p[1] == CILEN_DEFLATE) {
- if (p[2] != DEFLATE_MAKE_OPT(go->deflate_size)
- || p[3] != DEFLATE_CHK_SEQUENCE)
- return 0; /* Rej is bad */
- try.deflate_draft = 0;
- p += CILEN_DEFLATE;
- len -= CILEN_DEFLATE;
- }
- if (!try.deflate_correct && !try.deflate_draft)
- try.deflate = 0;
- }
- if (go->bsd_compress && len >= CILEN_BSD_COMPRESS
- && p[0] == CI_BSD_COMPRESS && p[1] == CILEN_BSD_COMPRESS) {
- if (p[2] != BSD_MAKE_OPT(BSD_CURRENT_VERSION, go->bsd_bits))
- return 0;
- try.bsd_compress = 0;
- p += CILEN_BSD_COMPRESS;
- len -= CILEN_BSD_COMPRESS;
- }
- if (go->predictor_1 && len >= CILEN_PREDICTOR_1
- && p[0] == CI_PREDICTOR_1 && p[1] == CILEN_PREDICTOR_1) {
- try.predictor_1 = 0;
- p += CILEN_PREDICTOR_1;
- len -= CILEN_PREDICTOR_1;
- }
- if (go->predictor_2 && len >= CILEN_PREDICTOR_2
- && p[0] == CI_PREDICTOR_2 && p[1] == CILEN_PREDICTOR_2) {
- try.predictor_2 = 0;
- p += CILEN_PREDICTOR_2;
- len -= CILEN_PREDICTOR_2;
- }
-
- if (len != 0)
- return 0;
-
- if (f->state != OPENED)
- *go = try;
-
- return 1;
-}
-
-/*
- * ccp_reqci - processed a received configure-request.
- * Returns CONFACK, CONFNAK or CONFREJ and the packet modified
- * appropriately.
- */
-static int
-ccp_reqci(f, p, lenp, dont_nak)
- fsm *f;
- u_char *p;
- int *lenp;
- int dont_nak;
-{
- int ret, newret, res;
- u_char *p0, *retp;
- int len, clen, type, nb;
- ccp_options *ho = &ccp_hisoptions[f->unit];
- ccp_options *ao = &ccp_allowoptions[f->unit];
-
- ret = CONFACK;
- retp = p0 = p;
- len = *lenp;
-
- memset(ho, 0, sizeof(ccp_options));
- ho->method = (len > 0)? p[0]: -1;
-
- while (len > 0) {
- newret = CONFACK;
- if (len < 2 || p[1] < 2 || p[1] > len) {
- /* length is bad */
- clen = len;
- newret = CONFREJ;
-
- } else {
- type = p[0];
- clen = p[1];
-
- switch (type) {
- case CI_DEFLATE:
- case CI_DEFLATE_DRAFT:
- if (!ao->deflate || clen != CILEN_DEFLATE
- || (!ao->deflate_correct && type == CI_DEFLATE)
- || (!ao->deflate_draft && type == CI_DEFLATE_DRAFT)) {
- newret = CONFREJ;
- break;
- }
-
- ho->deflate = 1;
- ho->deflate_size = nb = DEFLATE_SIZE(p[2]);
- if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL
- || p[3] != DEFLATE_CHK_SEQUENCE
- || nb > ao->deflate_size || nb < DEFLATE_MIN_SIZE) {
- newret = CONFNAK;
- if (!dont_nak) {
- p[2] = DEFLATE_MAKE_OPT(ao->deflate_size);
- p[3] = DEFLATE_CHK_SEQUENCE;
- /* fall through to test this #bits below */
- } else
- break;
- }
-
- /*
- * Check whether we can do Deflate with the window
- * size they want. If the window is too big, reduce
- * it until the kernel can cope and nak with that.
- * We only check this for the first option.
- */
- if (p == p0) {
- for (;;) {
- res = ccp_test(f->unit, p, CILEN_DEFLATE, 1);
- if (res > 0)
- break; /* it's OK now */
- if (res < 0 || nb == DEFLATE_MIN_SIZE || dont_nak) {
- newret = CONFREJ;
- p[2] = DEFLATE_MAKE_OPT(ho->deflate_size);
- break;
- }
- newret = CONFNAK;
- --nb;
- p[2] = DEFLATE_MAKE_OPT(nb);
- }
- }
- break;
-
- case CI_BSD_COMPRESS:
- if (!ao->bsd_compress || clen != CILEN_BSD_COMPRESS) {
- newret = CONFREJ;
- break;
- }
-
- ho->bsd_compress = 1;
- ho->bsd_bits = nb = BSD_NBITS(p[2]);
- if (BSD_VERSION(p[2]) != BSD_CURRENT_VERSION
- || nb > ao->bsd_bits || nb < BSD_MIN_BITS) {
- newret = CONFNAK;
- if (!dont_nak) {
- p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, ao->bsd_bits);
- /* fall through to test this #bits below */
- } else
- break;
- }
-
- /*
- * Check whether we can do BSD-Compress with the code
- * size they want. If the code size is too big, reduce
- * it until the kernel can cope and nak with that.
- * We only check this for the first option.
- */
- if (p == p0) {
- for (;;) {
- res = ccp_test(f->unit, p, CILEN_BSD_COMPRESS, 1);
- if (res > 0)
- break;
- if (res < 0 || nb == BSD_MIN_BITS || dont_nak) {
- newret = CONFREJ;
- p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION,
- ho->bsd_bits);
- break;
- }
- newret = CONFNAK;
- --nb;
- p[2] = BSD_MAKE_OPT(BSD_CURRENT_VERSION, nb);
- }
- }
- break;
-
- case CI_PREDICTOR_1:
- if (!ao->predictor_1 || clen != CILEN_PREDICTOR_1) {
- newret = CONFREJ;
- break;
- }
-
- ho->predictor_1 = 1;
- if (p == p0
- && ccp_test(f->unit, p, CILEN_PREDICTOR_1, 1) <= 0) {
- newret = CONFREJ;
- }
- break;
-
- case CI_PREDICTOR_2:
- if (!ao->predictor_2 || clen != CILEN_PREDICTOR_2) {
- newret = CONFREJ;
- break;
- }
-
- ho->predictor_2 = 1;
- if (p == p0
- && ccp_test(f->unit, p, CILEN_PREDICTOR_2, 1) <= 0) {
- newret = CONFREJ;
- }
- break;
-
- default:
- newret = CONFREJ;
- }
- }
-
- if (newret == CONFNAK && dont_nak)
- newret = CONFREJ;
- if (!(newret == CONFACK || (newret == CONFNAK && ret == CONFREJ))) {
- /* we're returning this option */
- if (newret == CONFREJ && ret == CONFNAK)
- retp = p0;
- ret = newret;
- if (p != retp)
- BCOPY(p, retp, clen);
- retp += clen;
- }
-
- p += clen;
- len -= clen;
- }
-
- if (ret != CONFACK) {
- if (ret == CONFREJ && *lenp == retp - p0)
- all_rejected[f->unit] = 1;
- else
- *lenp = retp - p0;
- }
- return ret;
-}
-
-/*
- * Make a string name for a compression method (or 2).
- */
-static char *
-method_name(opt, opt2)
- ccp_options *opt, *opt2;
-{
- static char result[64];
-
- if (!ANY_COMPRESS(*opt))
- return "(none)";
- switch (opt->method) {
- case CI_DEFLATE:
- case CI_DEFLATE_DRAFT:
- if (opt2 != NULL && opt2->deflate_size != opt->deflate_size)
- sprintf(result, "Deflate%s (%d/%d)",
- (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
- opt->deflate_size, opt2->deflate_size);
- else
- sprintf(result, "Deflate%s (%d)",
- (opt->method == CI_DEFLATE_DRAFT? "(old#)": ""),
- opt->deflate_size);
- break;
- case CI_BSD_COMPRESS:
- if (opt2 != NULL && opt2->bsd_bits != opt->bsd_bits)
- sprintf(result, "BSD-Compress (%d/%d)", opt->bsd_bits,
- opt2->bsd_bits);
- else
- sprintf(result, "BSD-Compress (%d)", opt->bsd_bits);
- break;
- case CI_PREDICTOR_1:
- return "Predictor 1";
- case CI_PREDICTOR_2:
- return "Predictor 2";
- default:
- sprintf(result, "Method %d", opt->method);
- }
- return result;
-}
-
-/*
- * CCP has come up - inform the kernel driver and log a message.
- */
-static void
-ccp_up(f)
- fsm *f;
-{
- ccp_options *go = &ccp_gotoptions[f->unit];
- ccp_options *ho = &ccp_hisoptions[f->unit];
- char method1[64];
-
- ccp_flags_set(f->unit, 1, 1);
- if (ANY_COMPRESS(*go)) {
- if (ANY_COMPRESS(*ho)) {
- if (go->method == ho->method) {
- syslog(LOG_NOTICE, "%s compression enabled",
- method_name(go, ho));
- } else {
- strcpy(method1, method_name(go, NULL));
- syslog(LOG_NOTICE, "%s / %s compression enabled",
- method1, method_name(ho, NULL));
- }
- } else
- syslog(LOG_NOTICE, "%s receive compression enabled",
- method_name(go, NULL));
- } else if (ANY_COMPRESS(*ho))
- syslog(LOG_NOTICE, "%s transmit compression enabled",
- method_name(ho, NULL));
-}
-
-/*
- * CCP has gone down - inform the kernel driver.
- */
-static void
-ccp_down(f)
- fsm *f;
-{
- if (ccp_localstate[f->unit] & RACK_PENDING)
- UNTIMEOUT(ccp_rack_timeout, f);
- ccp_localstate[f->unit] = 0;
- ccp_flags_set(f->unit, 1, 0);
-}
-
-/*
- * Print the contents of a CCP packet.
- */
-static char *ccp_codenames[] = {
- "ConfReq", "ConfAck", "ConfNak", "ConfRej",
- "TermReq", "TermAck", "CodeRej",
- NULL, NULL, NULL, NULL, NULL, NULL,
- "ResetReq", "ResetAck",
-};
-
-static int
-ccp_printpkt(p, plen, printer, arg)
- u_char *p;
- int plen;
- void (*printer)(void *, char *, ...);
- void *arg;
-{
- u_char *p0, *optend;
- int code, id, len;
- int optlen;
-
- p0 = p;
- if (plen < HEADERLEN)
- return 0;
- code = p[0];
- id = p[1];
- len = (p[2] << 8) + p[3];
- if (len < HEADERLEN || len > plen)
- return 0;
-
- if (code >= 1 && code <= sizeof(ccp_codenames) / sizeof(char *)
- && ccp_codenames[code-1] != NULL)
- printer(arg, " %s", ccp_codenames[code-1]);
- else
- printer(arg, " code=0x%x", code);
- printer(arg, " id=0x%x", id);
- len -= HEADERLEN;
- p += HEADERLEN;
-
- switch (code) {
- case CONFREQ:
- case CONFACK:
- case CONFNAK:
- case CONFREJ:
- /* print list of possible compression methods */
- while (len >= 2) {
- code = p[0];
- optlen = p[1];
- if (optlen < 2 || optlen > len)
- break;
- printer(arg, " <");
- len -= optlen;
- optend = p + optlen;
- switch (code) {
- case CI_DEFLATE:
- case CI_DEFLATE_DRAFT:
- if (optlen >= CILEN_DEFLATE) {
- printer(arg, "deflate%s %d",
- (code == CI_DEFLATE_DRAFT? "(old#)": ""),
- DEFLATE_SIZE(p[2]));
- if (DEFLATE_METHOD(p[2]) != DEFLATE_METHOD_VAL)
- printer(arg, " method %d", DEFLATE_METHOD(p[2]));
- if (p[3] != DEFLATE_CHK_SEQUENCE)
- printer(arg, " check %d", p[3]);
- p += CILEN_DEFLATE;
- }
- break;
- case CI_BSD_COMPRESS:
- if (optlen >= CILEN_BSD_COMPRESS) {
- printer(arg, "bsd v%d %d", BSD_VERSION(p[2]),
- BSD_NBITS(p[2]));
- p += CILEN_BSD_COMPRESS;
- }
- break;
- case CI_PREDICTOR_1:
- if (optlen >= CILEN_PREDICTOR_1) {
- printer(arg, "predictor 1");
- p += CILEN_PREDICTOR_1;
- }
- break;
- case CI_PREDICTOR_2:
- if (optlen >= CILEN_PREDICTOR_2) {
- printer(arg, "predictor 2");
- p += CILEN_PREDICTOR_2;
- }
- break;
- }
- while (p < optend)
- printer(arg, " %.2x", *p++);
- printer(arg, ">");
- }
- break;
-
- case TERMACK:
- case TERMREQ:
- if (len > 0 && *p >= ' ' && *p < 0x7f) {
- print_string(p, len, printer, arg);
- p += len;
- len = 0;
- }
- break;
- }
-
- /* dump out the rest of the packet in hex */
- while (--len >= 0)
- printer(arg, " %.2x", *p++);
-
- return p - p0;
-}
-
-/*
- * We have received a packet that the decompressor failed to
- * decompress. Here we would expect to issue a reset-request, but
- * Motorola has a patent on resetting the compressor as a result of
- * detecting an error in the decompressed data after decompression.
- * (See US patent 5,130,993; international patent publication number
- * WO 91/10289; Australian patent 73296/91.)
- *
- * So we ask the kernel whether the error was detected after
- * decompression; if it was, we take CCP down, thus disabling
- * compression :-(, otherwise we issue the reset-request.
- */
-static void
-ccp_datainput(unit, pkt, len)
- int unit;
- u_char *pkt;
- int len;
-{
- fsm *f;
-
- f = &ccp_fsm[unit];
- if (f->state == OPENED) {
- if (ccp_fatal_error(unit)) {
- /*
- * Disable compression by taking CCP down.
- */
- syslog(LOG_ERR, "Lost compression sync: disabling compression");
- ccp_close(unit, "Lost compression sync");
- } else {
- /*
- * Send a reset-request to reset the peer's compressor.
- * We don't do that if we are still waiting for an
- * acknowledgement to a previous reset-request.
- */
- if (!(ccp_localstate[f->unit] & RACK_PENDING)) {
- fsm_sdata(f, CCP_RESETREQ, f->reqid = ++f->id, NULL, 0);
- TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
- ccp_localstate[f->unit] |= RACK_PENDING;
- } else
- ccp_localstate[f->unit] |= RREQ_REPEAT;
- }
- }
-}
-
-/*
- * Timeout waiting for reset-ack.
- */
-static void
-ccp_rack_timeout(arg)
- void *arg;
-{
- fsm *f = arg;
-
- if (f->state == OPENED && ccp_localstate[f->unit] & RREQ_REPEAT) {
- fsm_sdata(f, CCP_RESETREQ, f->reqid, NULL, 0);
- TIMEOUT(ccp_rack_timeout, f, RACKTIMEOUT);
- ccp_localstate[f->unit] &= ~RREQ_REPEAT;
- } else
- ccp_localstate[f->unit] &= ~RACK_PENDING;
-}
-
diff --git a/usr.sbin/pppd/ccp.h b/usr.sbin/pppd/ccp.h
deleted file mode 100644
index a03ac4d..0000000
--- a/usr.sbin/pppd/ccp.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * ccp.h - Definitions for PPP Compression Control Protocol.
- *
- * Copyright (c) 1994 The Australian National University.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation is hereby granted, provided that the above copyright
- * notice appears in all copies. This software is provided without any
- * warranty, express or implied. The Australian National University
- * makes no representations about the suitability of this software for
- * any purpose.
- *
- * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
- * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
- * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
- * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- *
- * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
- * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
- * OR MODIFICATIONS.
- *
- * $FreeBSD$
- */
-
-typedef struct ccp_options {
- u_int bsd_compress: 1; /* do BSD Compress? */
- u_int deflate: 1; /* do Deflate? (RFC code) */
- u_int baddeflate: 1; /* do Deflate? (Magnalink!) */
- u_int predictor_1: 1; /* do Predictor-1? */
- u_int predictor_2: 1; /* do Predictor-2? */
- u_int deflate_correct: 1; /* use correct code for deflate? */
- u_int deflate_draft: 1; /* use draft RFC code for deflate? */
- u_short bsd_bits; /* # bits/code for BSD Compress */
- u_short deflate_size; /* lg(window size) for Deflate */
- u_short baddeflate_size; /* lg(window size) for Deflate */
- short method; /* code for chosen compression method */
-} ccp_options;
-
-extern fsm ccp_fsm[];
-extern ccp_options ccp_wantoptions[];
-extern ccp_options ccp_gotoptions[];
-extern ccp_options ccp_allowoptions[];
-extern ccp_options ccp_hisoptions[];
-
-extern struct protent ccp_protent;
diff --git a/usr.sbin/pppd/chap.c b/usr.sbin/pppd/chap.c
deleted file mode 100644
index 055dc7b..0000000
--- a/usr.sbin/pppd/chap.c
+++ /dev/null
@@ -1,870 +0,0 @@
-/*
- * chap.c - Challenge Handshake Authentication Protocol.
- *
- * Copyright (c) 1993 The Australian National University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the Australian National University. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Copyright (c) 1991 Gregory M. Christy.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Gregory M. Christy. The name of the author may not be used to
- * endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-/*
- * TODO:
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <syslog.h>
-#include <md5.h>
-
-#include "pppd.h"
-#include "chap.h"
-#include "md5.h"
-#ifdef CHAPMS
-#include "chap_ms.h"
-#endif
-
-/*
- * Protocol entry points.
- */
-static void ChapInit(int);
-static void ChapLowerUp(int);
-static void ChapLowerDown(int);
-static void ChapInput(int, u_char *, int);
-static void ChapProtocolReject(int);
-static int ChapPrintPkt(u_char *, int,
- void (*)(void *, char *, ...), void *);
-
-struct protent chap_protent = {
- PPP_CHAP,
- ChapInit,
- ChapInput,
- ChapProtocolReject,
- ChapLowerUp,
- ChapLowerDown,
- NULL,
- NULL,
- ChapPrintPkt,
- NULL,
- 1,
- "CHAP",
- NULL,
- NULL,
- NULL
-};
-
-chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */
-
-static void ChapChallengeTimeout(void *);
-static void ChapResponseTimeout(void *);
-static void ChapReceiveChallenge(chap_state *, u_char *, int, int);
-static void ChapRechallenge(void *);
-static void ChapReceiveResponse(chap_state *, u_char *, int, int);
-static void ChapReceiveSuccess(chap_state *, u_char *, int, int);
-static void ChapReceiveFailure(chap_state *, u_char *, int, int);
-static void ChapSendStatus(chap_state *, int);
-static void ChapSendChallenge(chap_state *);
-static void ChapSendResponse(chap_state *);
-static void ChapGenChallenge(chap_state *);
-
-extern double drand48(void);
-extern void srand48(long);
-
-/*
- * ChapInit - Initialize a CHAP unit.
- */
-static void
-ChapInit(unit)
- int unit;
-{
- chap_state *cstate = &chap[unit];
-
- BZERO(cstate, sizeof(*cstate));
- cstate->unit = unit;
- cstate->clientstate = CHAPCS_INITIAL;
- cstate->serverstate = CHAPSS_INITIAL;
- cstate->timeouttime = CHAP_DEFTIMEOUT;
- cstate->max_transmits = CHAP_DEFTRANSMITS;
- /* random number generator is initialized in magic_init */
-}
-
-
-/*
- * ChapAuthWithPeer - Authenticate us with our peer (start client).
- *
- */
-void
-ChapAuthWithPeer(unit, our_name, digest)
- int unit;
- char *our_name;
- int digest;
-{
- chap_state *cstate = &chap[unit];
-
- cstate->resp_name = our_name;
- cstate->resp_type = digest;
-
- if (cstate->clientstate == CHAPCS_INITIAL ||
- cstate->clientstate == CHAPCS_PENDING) {
- /* lower layer isn't up - wait until later */
- cstate->clientstate = CHAPCS_PENDING;
- return;
- }
-
- /*
- * We get here as a result of LCP coming up.
- * So even if CHAP was open before, we will
- * have to re-authenticate ourselves.
- */
- cstate->clientstate = CHAPCS_LISTEN;
-}
-
-
-/*
- * ChapAuthPeer - Authenticate our peer (start server).
- */
-void
-ChapAuthPeer(unit, our_name, digest)
- int unit;
- char *our_name;
- int digest;
-{
- chap_state *cstate = &chap[unit];
-
- cstate->chal_name = our_name;
- cstate->chal_type = digest;
-
- if (cstate->serverstate == CHAPSS_INITIAL ||
- cstate->serverstate == CHAPSS_PENDING) {
- /* lower layer isn't up - wait until later */
- cstate->serverstate = CHAPSS_PENDING;
- return;
- }
-
- ChapGenChallenge(cstate);
- ChapSendChallenge(cstate); /* crank it up dude! */
- cstate->serverstate = CHAPSS_INITIAL_CHAL;
-}
-
-
-/*
- * ChapChallengeTimeout - Timeout expired on sending challenge.
- */
-static void
-ChapChallengeTimeout(arg)
- void *arg;
-{
- chap_state *cstate = (chap_state *) arg;
-
- /* if we aren't sending challenges, don't worry. then again we */
- /* probably shouldn't be here either */
- if (cstate->serverstate != CHAPSS_INITIAL_CHAL &&
- cstate->serverstate != CHAPSS_RECHALLENGE)
- return;
-
- if (cstate->chal_transmits >= cstate->max_transmits) {
- /* give up on peer */
- syslog(LOG_ERR, "Peer failed to respond to CHAP challenge");
- cstate->serverstate = CHAPSS_BADAUTH;
- auth_peer_fail(cstate->unit, PPP_CHAP);
- return;
- }
-
- ChapSendChallenge(cstate); /* Re-send challenge */
-}
-
-
-/*
- * ChapResponseTimeout - Timeout expired on sending response.
- */
-static void
-ChapResponseTimeout(arg)
- void *arg;
-{
- chap_state *cstate = (chap_state *) arg;
-
- /* if we aren't sending a response, don't worry. */
- if (cstate->clientstate != CHAPCS_RESPONSE)
- return;
-
- ChapSendResponse(cstate); /* re-send response */
-}
-
-
-/*
- * ChapRechallenge - Time to challenge the peer again.
- */
-static void
-ChapRechallenge(arg)
- void *arg;
-{
- chap_state *cstate = (chap_state *) arg;
-
- /* if we aren't sending a response, don't worry. */
- if (cstate->serverstate != CHAPSS_OPEN)
- return;
-
- ChapGenChallenge(cstate);
- ChapSendChallenge(cstate);
- cstate->serverstate = CHAPSS_RECHALLENGE;
-}
-
-
-/*
- * ChapLowerUp - The lower layer is up.
- *
- * Start up if we have pending requests.
- */
-static void
-ChapLowerUp(unit)
- int unit;
-{
- chap_state *cstate = &chap[unit];
-
- if (cstate->clientstate == CHAPCS_INITIAL)
- cstate->clientstate = CHAPCS_CLOSED;
- else if (cstate->clientstate == CHAPCS_PENDING)
- cstate->clientstate = CHAPCS_LISTEN;
-
- if (cstate->serverstate == CHAPSS_INITIAL)
- cstate->serverstate = CHAPSS_CLOSED;
- else if (cstate->serverstate == CHAPSS_PENDING) {
- ChapGenChallenge(cstate);
- ChapSendChallenge(cstate);
- cstate->serverstate = CHAPSS_INITIAL_CHAL;
- }
-}
-
-
-/*
- * ChapLowerDown - The lower layer is down.
- *
- * Cancel all timeouts.
- */
-static void
-ChapLowerDown(unit)
- int unit;
-{
- chap_state *cstate = &chap[unit];
-
- /* Timeout(s) pending? Cancel if so. */
- if (cstate->serverstate == CHAPSS_INITIAL_CHAL ||
- cstate->serverstate == CHAPSS_RECHALLENGE)
- UNTIMEOUT(ChapChallengeTimeout, cstate);
- else if (cstate->serverstate == CHAPSS_OPEN
- && cstate->chal_interval != 0)
- UNTIMEOUT(ChapRechallenge, cstate);
- if (cstate->clientstate == CHAPCS_RESPONSE)
- UNTIMEOUT(ChapResponseTimeout, cstate);
-
- cstate->clientstate = CHAPCS_INITIAL;
- cstate->serverstate = CHAPSS_INITIAL;
-}
-
-
-/*
- * ChapProtocolReject - Peer doesn't grok CHAP.
- */
-static void
-ChapProtocolReject(unit)
- int unit;
-{
- chap_state *cstate = &chap[unit];
-
- if (cstate->serverstate != CHAPSS_INITIAL &&
- cstate->serverstate != CHAPSS_CLOSED)
- auth_peer_fail(unit, PPP_CHAP);
- if (cstate->clientstate != CHAPCS_INITIAL &&
- cstate->clientstate != CHAPCS_CLOSED)
- auth_withpeer_fail(unit, PPP_CHAP);
- ChapLowerDown(unit); /* shutdown chap */
-}
-
-
-/*
- * ChapInput - Input CHAP packet.
- */
-static void
-ChapInput(unit, inpacket, packet_len)
- int unit;
- u_char *inpacket;
- int packet_len;
-{
- chap_state *cstate = &chap[unit];
- u_char *inp;
- u_char code, id;
- int len;
-
- /*
- * Parse header (code, id and length).
- * If packet too short, drop it.
- */
- inp = inpacket;
- if (packet_len < CHAP_HEADERLEN) {
- CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short header."));
- return;
- }
- GETCHAR(code, inp);
- GETCHAR(id, inp);
- GETSHORT(len, inp);
- if (len < CHAP_HEADERLEN) {
- CHAPDEBUG((LOG_INFO, "ChapInput: rcvd illegal length."));
- return;
- }
- if (len > packet_len) {
- CHAPDEBUG((LOG_INFO, "ChapInput: rcvd short packet."));
- return;
- }
- len -= CHAP_HEADERLEN;
-
- /*
- * Action depends on code (as in fact it usually does :-).
- */
- switch (code) {
- case CHAP_CHALLENGE:
- ChapReceiveChallenge(cstate, inp, id, len);
- break;
-
- case CHAP_RESPONSE:
- ChapReceiveResponse(cstate, inp, id, len);
- break;
-
- case CHAP_FAILURE:
- ChapReceiveFailure(cstate, inp, id, len);
- break;
-
- case CHAP_SUCCESS:
- ChapReceiveSuccess(cstate, inp, id, len);
- break;
-
- default: /* Need code reject? */
- syslog(LOG_WARNING, "Unknown CHAP code (%d) received.", code);
- break;
- }
-}
-
-
-/*
- * ChapReceiveChallenge - Receive Challenge and send Response.
- */
-static void
-ChapReceiveChallenge(cstate, inp, id, len)
- chap_state *cstate;
- u_char *inp;
- int id;
- int len;
-{
- int rchallenge_len;
- u_char *rchallenge;
- int secret_len;
- char secret[MAXSECRETLEN];
- char rhostname[256];
- MD5_CTX mdContext;
- u_char hash[MD5_SIGNATURE_SIZE];
-
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.", id));
- if (cstate->clientstate == CHAPCS_CLOSED ||
- cstate->clientstate == CHAPCS_PENDING) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: in state %d",
- cstate->clientstate));
- return;
- }
-
- if (len < 2) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet."));
- return;
- }
-
- GETCHAR(rchallenge_len, inp);
- len -= sizeof (u_char) + rchallenge_len; /* now name field length */
- if (len < 0) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: rcvd short packet."));
- return;
- }
- rchallenge = inp;
- INCPTR(rchallenge_len, inp);
-
- if (len >= sizeof(rhostname))
- len = sizeof(rhostname) - 1;
- BCOPY(inp, rhostname, len);
- rhostname[len] = '\000';
-
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: received name field '%s'",
- rhostname));
-
- /* Microsoft doesn't send their name back in the PPP packet */
- if (remote_name[0] != 0 && (explicit_remote || rhostname[0] == 0)) {
- strncpy(rhostname, remote_name, sizeof(rhostname));
- rhostname[sizeof(rhostname) - 1] = 0;
- CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: using '%s' as remote name",
- rhostname));
- }
-
- /* get secret for authenticating ourselves with the specified host */
- if (!get_secret(cstate->unit, cstate->resp_name, rhostname,
- secret, &secret_len, 0)) {
- secret_len = 0; /* assume null secret if can't find one */
- syslog(LOG_WARNING, "No CHAP secret found for authenticating us to %s",
- rhostname);
- }
-
- /* cancel response send timeout if necessary */
- if (cstate->clientstate == CHAPCS_RESPONSE)
- UNTIMEOUT(ChapResponseTimeout, cstate);
-
- cstate->resp_id = id;
- cstate->resp_transmits = 0;
-
- /* generate MD based on negotiated type */
- switch (cstate->resp_type) {
-
- case CHAP_DIGEST_MD5:
- MD5Init(&mdContext);
- MD5Update(&mdContext, &cstate->resp_id, 1);
- MD5Update(&mdContext, secret, secret_len);
- MD5Update(&mdContext, rchallenge, rchallenge_len);
- MD5Final(hash, &mdContext);
- BCOPY(hash, cstate->response, MD5_SIGNATURE_SIZE);
- cstate->resp_length = MD5_SIGNATURE_SIZE;
- break;
-
-#ifdef CHAPMS
- case CHAP_MICROSOFT:
- ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len);
- break;
-#endif
-
- default:
- CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->resp_type));
- return;
- }
-
- BZERO(secret, sizeof(secret));
- ChapSendResponse(cstate);
-}
-
-
-/*
- * ChapReceiveResponse - Receive and process response.
- */
-static void
-ChapReceiveResponse(cstate, inp, id, len)
- chap_state *cstate;
- u_char *inp;
- int id;
- int len;
-{
- u_char *remmd, remmd_len;
- int secret_len, old_state;
- int code;
- char rhostname[256];
- MD5_CTX mdContext;
- char secret[MAXSECRETLEN];
- u_char hash[MD5_SIGNATURE_SIZE];
-
- CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: Rcvd id %d.", id));
-
- if (cstate->serverstate == CHAPSS_CLOSED ||
- cstate->serverstate == CHAPSS_PENDING) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: in state %d",
- cstate->serverstate));
- return;
- }
-
- if (id != cstate->chal_id)
- return; /* doesn't match ID of last challenge */
-
- /*
- * If we have received a duplicate or bogus Response,
- * we have to send the same answer (Success/Failure)
- * as we did for the first Response we saw.
- */
- if (cstate->serverstate == CHAPSS_OPEN) {
- ChapSendStatus(cstate, CHAP_SUCCESS);
- return;
- }
- if (cstate->serverstate == CHAPSS_BADAUTH) {
- ChapSendStatus(cstate, CHAP_FAILURE);
- return;
- }
-
- if (len < 2) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet."));
- return;
- }
- GETCHAR(remmd_len, inp); /* get length of MD */
- remmd = inp; /* get pointer to MD */
- INCPTR(remmd_len, inp);
-
- len -= sizeof (u_char) + remmd_len;
- if (len < 0) {
- CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: rcvd short packet."));
- return;
- }
-
- UNTIMEOUT(ChapChallengeTimeout, cstate);
-
- if (len >= sizeof(rhostname))
- len = sizeof(rhostname) - 1;
- BCOPY(inp, rhostname, len);
- rhostname[len] = '\000';
-
- CHAPDEBUG((LOG_INFO, "ChapReceiveResponse: received name field: %s",
- rhostname));
-
- /*
- * Get secret for authenticating them with us,
- * do the hash ourselves, and compare the result.
- */
- code = CHAP_FAILURE;
- if (!get_secret(cstate->unit, rhostname, cstate->chal_name,
- secret, &secret_len, 1)) {
- syslog(LOG_WARNING, "No CHAP secret found for authenticating %s",
- rhostname);
- } else {
-
- /* generate MD based on negotiated type */
- switch (cstate->chal_type) {
-
- case CHAP_DIGEST_MD5: /* only MD5 is defined for now */
- if (remmd_len != MD5_SIGNATURE_SIZE)
- break; /* it's not even the right length */
- MD5Init(&mdContext);
- MD5Update(&mdContext, &cstate->chal_id, 1);
- MD5Update(&mdContext, secret, secret_len);
- MD5Update(&mdContext, cstate->challenge, cstate->chal_len);
- MD5Final(hash, &mdContext);
-
- /* compare local and remote MDs and send the appropriate status */
- if (memcmp (hash, remmd, MD5_SIGNATURE_SIZE) == 0)
- code = CHAP_SUCCESS; /* they are the same! */
- break;
-
- default:
- CHAPDEBUG((LOG_INFO, "unknown digest type %d", cstate->chal_type));
- }
- }
-
- BZERO(secret, sizeof(secret));
- ChapSendStatus(cstate, code);
-
- if (code == CHAP_SUCCESS) {
- old_state = cstate->serverstate;
- cstate->serverstate = CHAPSS_OPEN;
- if (old_state == CHAPSS_INITIAL_CHAL) {
- auth_peer_success(cstate->unit, PPP_CHAP, rhostname, len);
- }
- if (cstate->chal_interval != 0)
- TIMEOUT(ChapRechallenge, cstate, cstate->chal_interval);
- syslog(LOG_NOTICE, "CHAP peer authentication succeeded for %s",
- rhostname);
-
- } else {
- syslog(LOG_ERR, "CHAP peer authentication failed for remote host %s",
- rhostname);
- cstate->serverstate = CHAPSS_BADAUTH;
- auth_peer_fail(cstate->unit, PPP_CHAP);
- }
-}
-
-/*
- * ChapReceiveSuccess - Receive Success
- */
-static void
-ChapReceiveSuccess(cstate, inp, id, len)
- chap_state *cstate;
- u_char *inp;
- u_char id;
- int len;
-{
-
- CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: Rcvd id %d.", id));
-
- if (cstate->clientstate == CHAPCS_OPEN)
- /* presumably an answer to a duplicate response */
- return;
-
- if (cstate->clientstate != CHAPCS_RESPONSE) {
- /* don't know what this is */
- CHAPDEBUG((LOG_INFO, "ChapReceiveSuccess: in state %d\n",
- cstate->clientstate));
- return;
- }
-
- UNTIMEOUT(ChapResponseTimeout, cstate);
-
- /*
- * Print message.
- */
- if (len > 0)
- PRINTMSG(inp, len);
-
- cstate->clientstate = CHAPCS_OPEN;
-
- auth_withpeer_success(cstate->unit, PPP_CHAP);
-}
-
-
-/*
- * ChapReceiveFailure - Receive failure.
- */
-static void
-ChapReceiveFailure(cstate, inp, id, len)
- chap_state *cstate;
- u_char *inp;
- u_char id;
- int len;
-{
- CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.", id));
-
- if (cstate->clientstate != CHAPCS_RESPONSE) {
- /* don't know what this is */
- CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: in state %d\n",
- cstate->clientstate));
- return;
- }
-
- UNTIMEOUT(ChapResponseTimeout, cstate);
-
- /*
- * Print message.
- */
- if (len > 0)
- PRINTMSG(inp, len);
-
- syslog(LOG_ERR, "CHAP authentication failed");
- auth_withpeer_fail(cstate->unit, PPP_CHAP);
-}
-
-
-/*
- * ChapSendChallenge - Send an Authenticate challenge.
- */
-static void
-ChapSendChallenge(cstate)
- chap_state *cstate;
-{
- u_char *outp;
- int chal_len, name_len;
- int outlen;
-
- chal_len = cstate->chal_len;
- name_len = strlen(cstate->chal_name);
- outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len;
- outp = outpacket_buf;
-
- MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */
-
- PUTCHAR(CHAP_CHALLENGE, outp);
- PUTCHAR(cstate->chal_id, outp);
- PUTSHORT(outlen, outp);
-
- PUTCHAR(chal_len, outp); /* put length of challenge */
- BCOPY(cstate->challenge, outp, chal_len);
- INCPTR(chal_len, outp);
-
- BCOPY(cstate->chal_name, outp, name_len); /* append hostname */
-
- output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
-
- CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.", cstate->chal_id));
-
- TIMEOUT(ChapChallengeTimeout, cstate, cstate->timeouttime);
- ++cstate->chal_transmits;
-}
-
-
-/*
- * ChapSendStatus - Send a status response (ack or nak).
- */
-static void
-ChapSendStatus(cstate, code)
- chap_state *cstate;
- int code;
-{
- u_char *outp;
- int outlen, msglen;
- char msg[256];
-
- if (code == CHAP_SUCCESS)
- sprintf(msg, "Welcome to %s.", hostname);
- else
- sprintf(msg, "I don't like you. Go 'way.");
- msglen = strlen(msg);
-
- outlen = CHAP_HEADERLEN + msglen;
- outp = outpacket_buf;
-
- MAKEHEADER(outp, PPP_CHAP); /* paste in a header */
-
- PUTCHAR(code, outp);
- PUTCHAR(cstate->chal_id, outp);
- PUTSHORT(outlen, outp);
- BCOPY(msg, outp, msglen);
- output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
-
- CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.", code,
- cstate->chal_id));
-}
-
-/*
- * ChapGenChallenge is used to generate a pseudo-random challenge string of
- * a pseudo-random length between min_len and max_len. The challenge
- * string and its length are stored in *cstate, and various other fields of
- * *cstate are initialized.
- */
-
-static void
-ChapGenChallenge(cstate)
- chap_state *cstate;
-{
- int chal_len;
- u_char *ptr = cstate->challenge;
- unsigned int i;
-
- /* pick a random challenge length between MIN_CHALLENGE_LENGTH and
- MAX_CHALLENGE_LENGTH */
- chal_len = (unsigned) ((drand48() *
- (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) +
- MIN_CHALLENGE_LENGTH);
- cstate->chal_len = chal_len;
- cstate->chal_id = ++cstate->id;
- cstate->chal_transmits = 0;
-
- /* generate a random string */
- for (i = 0; i < chal_len; i++ )
- *ptr++ = (char) (drand48() * 0xff);
-}
-
-/*
- * ChapSendResponse - send a response packet with values as specified
- * in *cstate.
- */
-/* ARGSUSED */
-static void
-ChapSendResponse(cstate)
- chap_state *cstate;
-{
- u_char *outp;
- int outlen, md_len, name_len;
-
- md_len = cstate->resp_length;
- name_len = strlen(cstate->resp_name);
- outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len;
- outp = outpacket_buf;
-
- MAKEHEADER(outp, PPP_CHAP);
-
- PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */
- PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */
- PUTSHORT(outlen, outp); /* packet length */
-
- PUTCHAR(md_len, outp); /* length of MD */
- BCOPY(cstate->response, outp, md_len); /* copy MD to buffer */
- INCPTR(md_len, outp);
-
- BCOPY(cstate->resp_name, outp, name_len); /* append our name */
-
- /* send the packet */
- output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN);
-
- cstate->clientstate = CHAPCS_RESPONSE;
- TIMEOUT(ChapResponseTimeout, cstate, cstate->timeouttime);
- ++cstate->resp_transmits;
-}
-
-/*
- * ChapPrintPkt - print the contents of a CHAP packet.
- */
-static char *ChapCodenames[] = {
- "Challenge", "Response", "Success", "Failure"
-};
-
-static int
-ChapPrintPkt(p, plen, printer, arg)
- u_char *p;
- int plen;
- void (*printer)(void *, char *, ...);
- void *arg;
-{
- int code, id, len;
- int clen, nlen;
- u_char x;
-
- if (plen < CHAP_HEADERLEN)
- return 0;
- GETCHAR(code, p);
- GETCHAR(id, p);
- GETSHORT(len, p);
- if (len < CHAP_HEADERLEN || len > plen)
- return 0;
-
- if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *))
- printer(arg, " %s", ChapCodenames[code-1]);
- else
- printer(arg, " code=0x%x", code);
- printer(arg, " id=0x%x", id);
- len -= CHAP_HEADERLEN;
- switch (code) {
- case CHAP_CHALLENGE:
- case CHAP_RESPONSE:
- if (len < 1)
- break;
- clen = p[0];
- if (len < clen + 1)
- break;
- ++p;
- nlen = len - clen - 1;
- printer(arg, " <");
- for (; clen > 0; --clen) {
- GETCHAR(x, p);
- printer(arg, "%.2x", x);
- }
- printer(arg, ">, name = ");
- print_string((char *)p, nlen, printer, arg);
- break;
- case CHAP_FAILURE:
- case CHAP_SUCCESS:
- printer(arg, " ");
- print_string((char *)p, len, printer, arg);
- break;
- default:
- for (clen = len; clen > 0; --clen) {
- GETCHAR(x, p);
- printer(arg, " %.2x", x);
- }
- }
-
- return len + CHAP_HEADERLEN;
-}
diff --git a/usr.sbin/pppd/chap.h b/usr.sbin/pppd/chap.h
deleted file mode 100644
index be8c90d..0000000
--- a/usr.sbin/pppd/chap.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * chap.h - Challenge Handshake Authentication Protocol definitions.
- *
- * Copyright (c) 1993 The Australian National University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the Australian National University. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Copyright (c) 1991 Gregory M. Christy
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the author.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
- */
-
-#ifndef __CHAP_INCLUDE__
-
-/* Code + ID + length */
-#define CHAP_HEADERLEN 4
-
-/*
- * CHAP codes.
- */
-
-#define CHAP_DIGEST_MD5 5 /* use MD5 algorithm */
-#define MD5_SIGNATURE_SIZE 16 /* 16 bytes in a MD5 message digest */
-#define CHAP_MICROSOFT 0x80 /* use Microsoft-compatible alg. */
-#define MS_CHAP_RESPONSE_LEN 49 /* Response length for MS-CHAP */
-
-#define CHAP_CHALLENGE 1
-#define CHAP_RESPONSE 2
-#define CHAP_SUCCESS 3
-#define CHAP_FAILURE 4
-
-/*
- * Challenge lengths (for challenges we send) and other limits.
- */
-#define MIN_CHALLENGE_LENGTH 32
-#define MAX_CHALLENGE_LENGTH 64
-#define MAX_RESPONSE_LENGTH 64 /* sufficient for MD5 or MS-CHAP */
-
-/*
- * Each interface is described by a chap structure.
- */
-
-typedef struct chap_state {
- int unit; /* Interface unit number */
- int clientstate; /* Client state */
- int serverstate; /* Server state */
- u_char challenge[MAX_CHALLENGE_LENGTH]; /* last challenge string sent */
- u_char chal_len; /* challenge length */
- u_char chal_id; /* ID of last challenge */
- u_char chal_type; /* hash algorithm for challenges */
- u_char id; /* Current id */
- char *chal_name; /* Our name to use with challenge */
- int chal_interval; /* Time until we challenge peer again */
- int timeouttime; /* Timeout time in seconds */
- int max_transmits; /* Maximum # of challenge transmissions */
- int chal_transmits; /* Number of transmissions of challenge */
- int resp_transmits; /* Number of transmissions of response */
- u_char response[MAX_RESPONSE_LENGTH]; /* Response to send */
- u_char resp_length; /* length of response */
- u_char resp_id; /* ID for response messages */
- u_char resp_type; /* hash algorithm for responses */
- char *resp_name; /* Our name to send with response */
-} chap_state;
-
-
-/*
- * Client (peer) states.
- */
-#define CHAPCS_INITIAL 0 /* Lower layer down, not opened */
-#define CHAPCS_CLOSED 1 /* Lower layer up, not opened */
-#define CHAPCS_PENDING 2 /* Auth us to peer when lower up */
-#define CHAPCS_LISTEN 3 /* Listening for a challenge */
-#define CHAPCS_RESPONSE 4 /* Sent response, waiting for status */
-#define CHAPCS_OPEN 5 /* We've received Success */
-
-/*
- * Server (authenticator) states.
- */
-#define CHAPSS_INITIAL 0 /* Lower layer down, not opened */
-#define CHAPSS_CLOSED 1 /* Lower layer up, not opened */
-#define CHAPSS_PENDING 2 /* Auth peer when lower up */
-#define CHAPSS_INITIAL_CHAL 3 /* We've sent the first challenge */
-#define CHAPSS_OPEN 4 /* We've sent a Success msg */
-#define CHAPSS_RECHALLENGE 5 /* We've sent another challenge */
-#define CHAPSS_BADAUTH 6 /* We've sent a Failure msg */
-
-/*
- * Timeouts.
- */
-#define CHAP_DEFTIMEOUT 3 /* Timeout time in seconds */
-#define CHAP_DEFTRANSMITS 10 /* max # times to send challenge */
-
-extern chap_state chap[];
-
-void ChapAuthWithPeer(int, char *, int);
-void ChapAuthPeer(int, char *, int);
-
-extern struct protent chap_protent;
-
-#define __CHAP_INCLUDE__
-#endif /* __CHAP_INCLUDE__ */
diff --git a/usr.sbin/pppd/chap_ms.c b/usr.sbin/pppd/chap_ms.c
deleted file mode 100644
index 5fce6e3..0000000
--- a/usr.sbin/pppd/chap_ms.c
+++ /dev/null
@@ -1,335 +0,0 @@
-/*
- * chap_ms.c - Microsoft MS-CHAP compatible implementation.
- *
- * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
- * http://www.strataware.com/
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Eric Rosenquist. The name of the author may not be used to
- * endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-/*
- * Modifications by Lauri Pesonen / lpesonen@clinet.fi, april 1997
- *
- * Implemented LANManager type password response to MS-CHAP challenges.
- * Now pppd provides both NT style and LANMan style blocks, and the
- * prefered is set by option "ms-lanman". Default is to use NT.
- * The hash text (StdText) was taken from Win95 RASAPI32.DLL.
- *
- * You should also use DOMAIN\\USERNAME as described in README.MSCHAP80
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-#ifdef CHAPMS
-
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <syslog.h>
-#include <unistd.h>
-#ifdef HAVE_CRYPT_H
-#include <crypt.h>
-#endif
-
-#include "pppd.h"
-#include "chap.h"
-#include "chap_ms.h"
-#include "md4.h"
-
-#ifndef USE_CRYPT
-#include <openssl/des.h>
-#endif
-
-typedef struct {
- u_char LANManResp[24];
- u_char NTResp[24];
- u_char UseNT; /* If 1, ignore the LANMan response field */
-} MS_ChapResponse;
-/* We use MS_CHAP_RESPONSE_LEN, rather than sizeof(MS_ChapResponse),
- in case this struct gets padded. */
-
-
-static void ChallengeResponse(u_char *, u_char *, u_char *);
-static void DesEncrypt(u_char *, u_char *, u_char *);
-static void MakeKey(u_char *, u_char *);
-static u_char Get7Bits(u_char *, int);
-static void ChapMS_NT(char *, int, char *, int, MS_ChapResponse *);
-#ifdef MSLANMAN
-static void ChapMS_LANMan(char *, int, char *, int, MS_ChapResponse *);
-#endif
-
-#ifdef USE_CRYPT
-static void Expand(u_char *, u_char *);
-static void Collapse(u_char *, u_char *);
-#endif
-
-static void
-ChallengeResponse(challenge, pwHash, response)
- u_char *challenge; /* IN 8 octets */
- u_char *pwHash; /* IN 16 octets */
- u_char *response; /* OUT 24 octets */
-{
- char ZPasswordHash[21];
-
- BZERO(ZPasswordHash, sizeof(ZPasswordHash));
- BCOPY(pwHash, ZPasswordHash, MD4_SIGNATURE_SIZE);
-
-#if 0
- log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG);
-#endif
-
- DesEncrypt(challenge, ZPasswordHash + 0, response + 0);
- DesEncrypt(challenge, ZPasswordHash + 7, response + 8);
- DesEncrypt(challenge, ZPasswordHash + 14, response + 16);
-
-#if 0
- log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG);
-#endif
-}
-
-
-#ifdef USE_CRYPT
-static void
-DesEncrypt(clear, key, cipher)
- u_char *clear; /* IN 8 octets */
- u_char *key; /* IN 7 octets */
- u_char *cipher; /* OUT 8 octets */
-{
- u_char des_key[8];
- u_char crypt_key[66];
- u_char des_input[66];
-
- MakeKey(key, des_key);
-
- Expand(des_key, crypt_key);
- setkey(crypt_key);
-
-#if 0
- CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X",
- clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
-#endif
-
- Expand(clear, des_input);
- encrypt(des_input, 0);
- Collapse(des_input, cipher);
-
-#if 0
- CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X",
- cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
-#endif
-}
-
-#else /* USE_CRYPT */
-
-static void
-DesEncrypt(clear, key, cipher)
- u_char *clear; /* IN 8 octets */
- u_char *key; /* IN 7 octets */
- u_char *cipher; /* OUT 8 octets */
-{
- des_cblock des_key;
- des_key_schedule key_schedule;
-
- MakeKey(key, des_key);
-
- des_set_key(&des_key, key_schedule);
-
-#if 0
- CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet input : %02X%02X%02X%02X%02X%02X%02X%02X",
- clear[0], clear[1], clear[2], clear[3], clear[4], clear[5], clear[6], clear[7]));
-#endif
-
- des_ecb_encrypt((des_cblock *)clear, (des_cblock *)cipher, key_schedule, 1);
-
-#if 0
- CHAPDEBUG((LOG_INFO, "DesEncrypt: 8 octet output: %02X%02X%02X%02X%02X%02X%02X%02X",
- cipher[0], cipher[1], cipher[2], cipher[3], cipher[4], cipher[5], cipher[6], cipher[7]));
-#endif
-}
-
-#endif /* USE_CRYPT */
-
-
-static u_char Get7Bits(input, startBit)
- u_char *input;
- int startBit;
-{
- register unsigned int word;
-
- word = (unsigned)input[startBit / 8] << 8;
- word |= (unsigned)input[startBit / 8 + 1];
-
- word >>= 15 - (startBit % 8 + 7);
-
- return word & 0xFE;
-}
-
-#ifdef USE_CRYPT
-
-/* in == 8-byte string (expanded version of the 56-bit key)
- * out == 64-byte string where each byte is either 1 or 0
- * Note that the low-order "bit" is always ignored by by setkey()
- */
-static void Expand(in, out)
- u_char *in;
- u_char *out;
-{
- int j, c;
- int i;
-
- for(i = 0; i < 64; in++){
- c = *in;
- for(j = 7; j >= 0; j--)
- *out++ = (c >> j) & 01;
- i += 8;
- }
-}
-
-/* The inverse of Expand
- */
-static void Collapse(in, out)
- u_char *in;
- u_char *out;
-{
- int j;
- int i;
- unsigned int c;
-
- for (i = 0; i < 64; i += 8, out++) {
- c = 0;
- for (j = 7; j >= 0; j--, in++)
- c |= *in << j;
- *out = c & 0xff;
- }
-}
-#endif
-
-static void MakeKey(key, des_key)
- u_char *key; /* IN 56 bit DES key missing parity bits */
- u_char *des_key; /* OUT 64 bit DES key with parity bits added */
-{
- des_key[0] = Get7Bits(key, 0);
- des_key[1] = Get7Bits(key, 7);
- des_key[2] = Get7Bits(key, 14);
- des_key[3] = Get7Bits(key, 21);
- des_key[4] = Get7Bits(key, 28);
- des_key[5] = Get7Bits(key, 35);
- des_key[6] = Get7Bits(key, 42);
- des_key[7] = Get7Bits(key, 49);
-
-#ifndef USE_CRYPT
- des_set_odd_parity((des_cblock *)des_key);
-#endif
-
-#if 0
- CHAPDEBUG((LOG_INFO, "MakeKey: 56-bit input : %02X%02X%02X%02X%02X%02X%02X",
- key[0], key[1], key[2], key[3], key[4], key[5], key[6]));
- CHAPDEBUG((LOG_INFO, "MakeKey: 64-bit output: %02X%02X%02X%02X%02X%02X%02X%02X",
- des_key[0], des_key[1], des_key[2], des_key[3], des_key[4], des_key[5], des_key[6], des_key[7]));
-#endif
-}
-
-static void
-ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, response)
- char *rchallenge;
- int rchallenge_len;
- char *secret;
- int secret_len;
- MS_ChapResponse *response;
-{
- int i;
- MD4_CTX md4Context;
- u_char hash[MD4_SIGNATURE_SIZE];
- u_char unicodePassword[MAX_NT_PASSWORD * 2];
-
- /* Initialize the Unicode version of the secret (== password). */
- /* This implicitly supports 8-bit ISO8859/1 characters. */
- BZERO(unicodePassword, sizeof(unicodePassword));
- for (i = 0; i < secret_len; i++)
- unicodePassword[i * 2] = (u_char)secret[i];
-
- MD4Init(&md4Context);
- MD4Update(&md4Context, unicodePassword, secret_len * 2); /* Unicode is 2 bytes/char */
-
- MD4Final(hash, &md4Context); /* Tell MD4 we're done */
-
- ChallengeResponse(rchallenge, hash, response->NTResp);
-}
-
-#ifdef MSLANMAN
-static u_char *StdText = (u_char *)"KGS!@#$%"; /* key from rasapi32.dll */
-
-static void
-ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, response)
- char *rchallenge;
- int rchallenge_len;
- char *secret;
- int secret_len;
- MS_ChapResponse *response;
-{
- int i;
- u_char UcasePassword[MAX_NT_PASSWORD]; /* max is actually 14 */
- u_char PasswordHash[MD4_SIGNATURE_SIZE];
-
- /* LANMan password is case insensitive */
- BZERO(UcasePassword, sizeof(UcasePassword));
- for (i = 0; i < secret_len; i++)
- UcasePassword[i] = (u_char)toupper(secret[i]);
- DesEncrypt( StdText, UcasePassword + 0, PasswordHash + 0 );
- DesEncrypt( StdText, UcasePassword + 7, PasswordHash + 8 );
- ChallengeResponse(rchallenge, PasswordHash, response->LANManResp);
-}
-#endif
-
-void
-ChapMS(cstate, rchallenge, rchallenge_len, secret, secret_len)
- chap_state *cstate;
- char *rchallenge;
- int rchallenge_len;
- char *secret;
- int secret_len;
-{
- MS_ChapResponse response;
-#ifdef MSLANMAN
- extern int ms_lanman;
-#endif
-
-#if 0
- CHAPDEBUG((LOG_INFO, "ChapMS: secret is '%.*s'", secret_len, secret));
-#endif
- BZERO(&response, sizeof(response));
-
- /* Calculate both always */
- ChapMS_NT(rchallenge, rchallenge_len, secret, secret_len, &response);
-
-#ifdef MSLANMAN
- ChapMS_LANMan(rchallenge, rchallenge_len, secret, secret_len, &response);
-
- /* prefered method is set by option */
- response.UseNT = !ms_lanman;
-#else
- response.UseNT = 1;
-#endif
-
- BCOPY(&response, cstate->response, MS_CHAP_RESPONSE_LEN);
- cstate->resp_length = MS_CHAP_RESPONSE_LEN;
-}
-
-#endif /* CHAPMS */
diff --git a/usr.sbin/pppd/chap_ms.h b/usr.sbin/pppd/chap_ms.h
deleted file mode 100644
index 6ef03c8..0000000
--- a/usr.sbin/pppd/chap_ms.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * chap.h - Challenge Handshake Authentication Protocol definitions.
- *
- * Copyright (c) 1995 Eric Rosenquist, Strata Software Limited.
- * http://www.strataware.com/
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Eric Rosenquist. The name of the author may not be used to
- * endorse or promote products derived from this software without
- * specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
- */
-
-#ifndef __CHAPMS_INCLUDE__
-
-#define MD4_SIGNATURE_SIZE 16 /* 16 bytes in a MD4 message digest */
-#define MAX_NT_PASSWORD 256 /* Maximum number of (Unicode) chars in an NT password */
-
-void ChapMS(chap_state *, char *, int, char *, int);
-
-#define __CHAPMS_INCLUDE__
-#endif /* __CHAPMS_INCLUDE__ */
diff --git a/usr.sbin/pppd/demand.c b/usr.sbin/pppd/demand.c
deleted file mode 100644
index b86c81f..0000000
--- a/usr.sbin/pppd/demand.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- * demand.c - Support routines for demand-dialling.
- *
- * Copyright (c) 1993 The Australian National University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the Australian National University. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <syslog.h>
-#include <netdb.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#ifdef PPP_FILTER
-#include <net/if.h>
-#include <net/bpf.h>
-#include <pcap.h>
-#endif
-
-#include "pppd.h"
-#include "fsm.h"
-#include "ipcp.h"
-#include "lcp.h"
-
-char *frame;
-int framelen;
-int framemax;
-int escape_flag;
-int flush_flag;
-int fcs;
-
-struct packet {
- int length;
- struct packet *next;
- unsigned char data[1];
-};
-
-struct packet *pend_q;
-struct packet *pend_qtail;
-
-static int active_packet(unsigned char *, int);
-
-/*
- * demand_conf - configure the interface for doing dial-on-demand.
- */
-void
-demand_conf()
-{
- int i;
- struct protent *protp;
-
-/* framemax = lcp_allowoptions[0].mru;
- if (framemax < PPP_MRU) */
- framemax = PPP_MRU;
- framemax += PPP_HDRLEN + PPP_FCSLEN;
- frame = malloc(framemax);
- if (frame == NULL)
- novm("demand frame");
- framelen = 0;
- pend_q = NULL;
- escape_flag = 0;
- flush_flag = 0;
- fcs = PPP_INITFCS;
-
- ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
- ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
-
-#ifdef PPP_FILTER
- set_filters(&pass_filter, &active_filter);
-#endif
-
- /*
- * Call the demand_conf procedure for each protocol that's got one.
- */
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if (protp->enabled_flag && protp->demand_conf != NULL)
- if (!((*protp->demand_conf)(0)))
- die(1);
-}
-
-
-/*
- * demand_block - set each network protocol to block further packets.
- */
-void
-demand_block()
-{
- int i;
- struct protent *protp;
-
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if (protp->enabled_flag && protp->demand_conf != NULL)
- sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
- get_loop_output();
-}
-
-/*
- * demand_discard - set each network protocol to discard packets
- * with an error.
- */
-void
-demand_discard()
-{
- struct packet *pkt, *nextpkt;
- int i;
- struct protent *protp;
-
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if (protp->enabled_flag && protp->demand_conf != NULL)
- sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
- get_loop_output();
-
- /* discard all saved packets */
- for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
- nextpkt = pkt->next;
- free(pkt);
- }
- pend_q = NULL;
- framelen = 0;
- flush_flag = 0;
- escape_flag = 0;
- fcs = PPP_INITFCS;
-}
-
-/*
- * demand_unblock - set each enabled network protocol to pass packets.
- */
-void
-demand_unblock()
-{
- int i;
- struct protent *protp;
-
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if (protp->enabled_flag && protp->demand_conf != NULL)
- sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
-}
-
-/*
- * FCS lookup table as calculated by genfcstab.
- */
-static u_short fcstab[256] = {
- 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
- 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
- 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
- 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
- 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
- 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
- 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
- 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
- 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
- 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
- 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
- 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
- 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
- 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
- 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
- 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
- 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
- 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
- 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
- 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
- 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
- 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
- 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
- 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
- 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
- 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
- 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
- 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
- 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
- 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
- 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
- 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-};
-
-/*
- * loop_chars - process characters received from the loopback.
- * Calls loop_frame when a complete frame has been accumulated.
- * Return value is 1 if we need to bring up the link, 0 otherwise.
- */
-int
-loop_chars(p, n)
- unsigned char *p;
- int n;
-{
- int c, rv;
-
- rv = 0;
- for (; n > 0; --n) {
- c = *p++;
- if (c == PPP_FLAG) {
- if (!escape_flag && !flush_flag
- && framelen > 2 && fcs == PPP_GOODFCS) {
- framelen -= 2;
- if (loop_frame(frame, framelen))
- rv = 1;
- }
- framelen = 0;
- flush_flag = 0;
- escape_flag = 0;
- fcs = PPP_INITFCS;
- continue;
- }
- if (flush_flag)
- continue;
- if (escape_flag) {
- c ^= PPP_TRANS;
- escape_flag = 0;
- } else if (c == PPP_ESCAPE) {
- escape_flag = 1;
- continue;
- }
- if (framelen >= framemax) {
- flush_flag = 1;
- continue;
- }
- frame[framelen++] = c;
- fcs = PPP_FCS(fcs, c);
- }
- return rv;
-}
-
-/*
- * loop_frame - given a frame obtained from the loopback,
- * decide whether to bring up the link or not, and, if we want
- * to transmit this frame later, put it on the pending queue.
- * Return value is 1 if we need to bring up the link, 0 otherwise.
- * We assume that the kernel driver has already applied the
- * pass_filter, so we won't get packets it rejected.
- * We apply the active_filter to see if we want this packet to
- * bring up the link.
- */
-int
-loop_frame(frame, len)
- unsigned char *frame;
- int len;
-{
- struct packet *pkt;
-
- /* log_packet(frame, len, "from loop: ", LOG_DEBUG); */
- if (len < PPP_HDRLEN)
- return 0;
- if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
- return 0; /* shouldn't get any of these anyway */
- if (!active_packet(frame, len))
- return 0;
-
- pkt = (struct packet *) malloc(sizeof(struct packet) + len);
- if (pkt != NULL) {
- pkt->length = len;
- pkt->next = NULL;
- memcpy(pkt->data, frame, len);
- if (pend_q == NULL)
- pend_q = pkt;
- else
- pend_qtail->next = pkt;
- pend_qtail = pkt;
- }
- return 1;
-}
-
-/*
- * demand_rexmit - Resend all those frames which we got via the
- * loopback, now that the real serial link is up.
- */
-void
-demand_rexmit(proto)
- int proto;
-{
- struct packet *pkt, *prev, *nextpkt;
-
- prev = NULL;
- pkt = pend_q;
- pend_q = NULL;
- for (; pkt != NULL; pkt = nextpkt) {
- nextpkt = pkt->next;
- if (PPP_PROTOCOL(pkt->data) == proto) {
- output(0, pkt->data, pkt->length);
- free(pkt);
- } else {
- if (prev == NULL)
- pend_q = pkt;
- else
- prev->next = pkt;
- prev = pkt;
- }
- }
- pend_qtail = prev;
- if (prev != NULL)
- prev->next = NULL;
-}
-
-/*
- * Scan a packet to decide whether it is an "active" packet,
- * that is, whether it is worth bringing up the link for.
- */
-static int
-active_packet(p, len)
- unsigned char *p;
- int len;
-{
- int proto, i;
- struct protent *protp;
-
- if (len < PPP_HDRLEN)
- return 0;
- proto = PPP_PROTOCOL(p);
-#ifdef PPP_FILTER
- if (active_filter.bf_len != 0
- && bpf_filter(active_filter.bf_insns, frame, len, len) == 0)
- return 0;
-#endif
- for (i = 0; (protp = protocols[i]) != NULL; ++i) {
- if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
- if (!protp->enabled_flag)
- return 0;
- if (protp->active_pkt == NULL)
- return 1;
- return (*protp->active_pkt)(p, len);
- }
- }
- return 0; /* not a supported protocol !!?? */
-}
diff --git a/usr.sbin/pppd/eui64.c b/usr.sbin/pppd/eui64.c
deleted file mode 100644
index 28335a3..0000000
--- a/usr.sbin/pppd/eui64.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- eui64.c - EUI64 routines for IPv6CP.
- Copyright (C) 1999 Tommi Komulainen <Tommi.Komulainen@iki.fi>
-
- Redistribution and use in source and binary forms are permitted
- provided that the above copyright notice and this paragraph are
- duplicated in all such forms and that any documentation,
- advertising materials, and other materials related to such
- distribution and use acknowledge that the software was developed
- by Tommi Komulainen. The name of the author may not be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
-
- $Id: eui64.c,v 1.3 1999/08/25 04:15:51 paulus Exp $
-*/
-
-#ifndef lint
-#define RCSID "$Id: eui64.c,v 1.3 1999/08/25 04:15:51 paulus Exp $"
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "pppd.h"
-
-#ifdef RCSID
-static const char rcsid[] = RCSID;
-#endif
-
-/*
- * eui64_ntoa - Make an ascii representation of an interface identifier
- */
-char *
-eui64_ntoa(e)
- eui64_t e;
-{
- static char buf[32];
-
- snprintf(buf, 32, "%02x%02x:%02x%02x:%02x%02x:%02x%02x",
- e.e8[0], e.e8[1], e.e8[2], e.e8[3],
- e.e8[4], e.e8[5], e.e8[6], e.e8[7]);
- return buf;
-}
diff --git a/usr.sbin/pppd/eui64.h b/usr.sbin/pppd/eui64.h
deleted file mode 100644
index 4b4b505..0000000
--- a/usr.sbin/pppd/eui64.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/* $FreeBSD$ */
-/*
- eui64.h - EUI64 routines for IPv6CP.
- Copyright (C) 1999 Tommi Komulainen <Tommi.Komulainen@iki.fi>
-
- Redistribution and use in source and binary forms are permitted
- provided that the above copyright notice and this paragraph are
- duplicated in all such forms and that any documentation,
- advertising materials, and other materials related to such
- distribution and use acknowledge that the software was developed
- by Tommi Komulainen. The name of the author may not be used
- to endorse or promote products derived from this software without
- specific prior written permission.
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-
-
- $Id: eui64.h,v 1.3 1999/09/30 19:56:37 masputra Exp $
-*/
-
-#ifndef __EUI64_H__
-#define __EUI64_H__
-
-#if !defined(INET6)
-#error "this file should only be included when INET6 is defined"
-#endif /* not defined(INET6) */
-
-#if defined(SOL2)
-#include <netinet/in.h>
-
-typedef union {
- uint8_t e8[8]; /* lower 64-bit IPv6 address */
- uint32_t e32[2]; /* lower 64-bit IPv6 address */
-} eui64_t;
-
-/*
- * Declare the two below, since in.h only defines them when _KERNEL
- * is declared - which shouldn't be true when dealing with user-land programs
- */
-#define s6_addr8 _S6_un._S6_u8
-#define s6_addr32 _S6_un._S6_u32
-
-#else /* else if not defined(SOL2) */
-
-/*
- * TODO:
- *
- * Maybe this should be done by processing struct in6_addr directly...
- */
-typedef union
-{
- u_int8_t e8[8];
- u_int16_t e16[4];
- u_int32_t e32[2];
-} eui64_t;
-
-#endif /* defined(SOL2) */
-
-#define eui64_iszero(e) (((e).e32[0] | (e).e32[1]) == 0)
-#define eui64_equals(e, o) (((e).e32[0] == (o).e32[0]) && \
- ((e).e32[1] == (o).e32[1]))
-#define eui64_zero(e) (e).e32[0] = (e).e32[1] = 0;
-
-#define eui64_copy(s, d) memcpy(&(d), &(s), sizeof(eui64_t))
-
-#define eui64_magic(e) do { \
- (e).e32[0] = magic(); \
- (e).e32[1] = magic(); \
- (e).e8[0] &= ~2; \
- } while (0)
-#define eui64_magic_nz(x) do { \
- eui64_magic(x); \
- } while (eui64_iszero(x))
-#define eui64_magic_ne(x, y) do { \
- eui64_magic(x); \
- } while (eui64_equals(x, y))
-
-#define eui64_get(ll, cp) do { \
- eui64_copy((*cp), (ll)); \
- (cp) += sizeof(eui64_t); \
- } while (0)
-
-#define eui64_put(ll, cp) do { \
- eui64_copy((ll), (*cp)); \
- (cp) += sizeof(eui64_t); \
- } while (0)
-
-#define eui64_set32(e, l) do { \
- (e).e32[0] = 0; \
- (e).e32[1] = htonl(l); \
- } while (0)
-#define eui64_setlo32(e, l) eui64_set32(e, l)
-
-char *eui64_ntoa(eui64_t); /* Returns ascii representation of id */
-
-#endif /* __EUI64_H__ */
-
diff --git a/usr.sbin/pppd/fsm.c b/usr.sbin/pppd/fsm.c
deleted file mode 100644
index 0b586b7..0000000
--- a/usr.sbin/pppd/fsm.c
+++ /dev/null
@@ -1,798 +0,0 @@
-/*
- * fsm.c - {Link, IP} Control Protocol Finite State Machine.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-/*
- * TODO:
- * Randomize fsm id on link/init.
- * Deal with variable outgoing MTU.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <syslog.h>
-
-#include "pppd.h"
-#include "fsm.h"
-
-static void fsm_timeout(void *);
-static void fsm_rconfreq(fsm *, int, u_char *, int);
-static void fsm_rconfack(fsm *, int, u_char *, int);
-static void fsm_rconfnakrej(fsm *, int, int, u_char *, int);
-static void fsm_rtermreq(fsm *, int, u_char *, int);
-static void fsm_rtermack(fsm *);
-static void fsm_rcoderej(fsm *, u_char *, int);
-static void fsm_sconfreq(fsm *, int);
-
-#define PROTO_NAME(f) ((f)->callbacks->proto_name)
-
-int peer_mru[NUM_PPP];
-
-
-/*
- * fsm_init - Initialize fsm.
- *
- * Initialize fsm state.
- */
-void
-fsm_init(f)
- fsm *f;
-{
- f->state = INITIAL;
- f->flags = 0;
- f->id = 0; /* XXX Start with random id? */
- f->timeouttime = DEFTIMEOUT;
- f->maxconfreqtransmits = DEFMAXCONFREQS;
- f->maxtermtransmits = DEFMAXTERMREQS;
- f->maxnakloops = DEFMAXNAKLOOPS;
- f->term_reason_len = 0;
-}
-
-
-/*
- * fsm_lowerup - The lower layer is up.
- */
-void
-fsm_lowerup(f)
- fsm *f;
-{
- switch( f->state ){
- case INITIAL:
- f->state = CLOSED;
- break;
-
- case STARTING:
- if( f->flags & OPT_SILENT )
- f->state = STOPPED;
- else {
- /* Send an initial configure-request */
- fsm_sconfreq(f, 0);
- f->state = REQSENT;
- }
- break;
-
- default:
- FSMDEBUG((LOG_INFO, "%s: Up event in state %d!",
- PROTO_NAME(f), f->state));
- }
-}
-
-
-/*
- * fsm_lowerdown - The lower layer is down.
- *
- * Cancel all timeouts and inform upper layers.
- */
-void
-fsm_lowerdown(f)
- fsm *f;
-{
- switch( f->state ){
- case CLOSED:
- f->state = INITIAL;
- break;
-
- case STOPPED:
- f->state = STARTING;
- if( f->callbacks->starting )
- (*f->callbacks->starting)(f);
- break;
-
- case CLOSING:
- f->state = INITIAL;
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- break;
-
- case STOPPING:
- case REQSENT:
- case ACKRCVD:
- case ACKSENT:
- f->state = STARTING;
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- break;
-
- case OPENED:
- if( f->callbacks->down )
- (*f->callbacks->down)(f);
- f->state = STARTING;
- break;
-
- default:
- FSMDEBUG((LOG_INFO, "%s: Down event in state %d!",
- PROTO_NAME(f), f->state));
- }
-}
-
-
-/*
- * fsm_open - Link is allowed to come up.
- */
-void
-fsm_open(f)
- fsm *f;
-{
- switch( f->state ){
- case INITIAL:
- f->state = STARTING;
- if( f->callbacks->starting )
- (*f->callbacks->starting)(f);
- break;
-
- case CLOSED:
- if( f->flags & OPT_SILENT )
- f->state = STOPPED;
- else {
- /* Send an initial configure-request */
- fsm_sconfreq(f, 0);
- f->state = REQSENT;
- }
- break;
-
- case CLOSING:
- f->state = STOPPING;
- /* FALLTHROUGH */
- case STOPPED:
- case OPENED:
- if( f->flags & OPT_RESTART ){
- fsm_lowerdown(f);
- fsm_lowerup(f);
- }
- break;
- }
-}
-
-
-/*
- * fsm_close - Start closing connection.
- *
- * Cancel timeouts and either initiate close or possibly go directly to
- * the CLOSED state.
- */
-void
-fsm_close(f, reason)
- fsm *f;
- char *reason;
-{
- f->term_reason = reason;
- f->term_reason_len = (reason == NULL? 0: strlen(reason));
- switch( f->state ){
- case STARTING:
- f->state = INITIAL;
- break;
- case STOPPED:
- f->state = CLOSED;
- break;
- case STOPPING:
- f->state = CLOSING;
- break;
-
- case REQSENT:
- case ACKRCVD:
- case ACKSENT:
- case OPENED:
- if( f->state != OPENED )
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- else if( f->callbacks->down )
- (*f->callbacks->down)(f); /* Inform upper layers we're down */
-
- /* Init restart counter, send Terminate-Request */
- f->retransmits = f->maxtermtransmits;
- fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
- (u_char *) f->term_reason, f->term_reason_len);
- TIMEOUT(fsm_timeout, f, f->timeouttime);
- --f->retransmits;
-
- f->state = CLOSING;
- break;
- }
-}
-
-
-/*
- * fsm_timeout - Timeout expired.
- */
-static void
-fsm_timeout(arg)
- void *arg;
-{
- fsm *f = (fsm *) arg;
-
- switch (f->state) {
- case CLOSING:
- case STOPPING:
- if( f->retransmits <= 0 ){
- /*
- * We've waited for an ack long enough. Peer probably heard us.
- */
- f->state = (f->state == CLOSING)? CLOSED: STOPPED;
- if( f->callbacks->finished )
- (*f->callbacks->finished)(f);
- } else {
- /* Send Terminate-Request */
- fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
- (u_char *) f->term_reason, f->term_reason_len);
- TIMEOUT(fsm_timeout, f, f->timeouttime);
- --f->retransmits;
- }
- break;
-
- case REQSENT:
- case ACKRCVD:
- case ACKSENT:
- if (f->retransmits <= 0) {
- syslog(LOG_WARNING, "%s: timeout sending Config-Requests",
- PROTO_NAME(f));
- f->state = STOPPED;
- if( (f->flags & OPT_PASSIVE) == 0 && f->callbacks->finished )
- (*f->callbacks->finished)(f);
-
- } else {
- /* Retransmit the configure-request */
- if (f->callbacks->retransmit)
- (*f->callbacks->retransmit)(f);
- fsm_sconfreq(f, 1); /* Re-send Configure-Request */
- if( f->state == ACKRCVD )
- f->state = REQSENT;
- }
- break;
-
- default:
- FSMDEBUG((LOG_INFO, "%s: Timeout event in state %d!",
- PROTO_NAME(f), f->state));
- }
-}
-
-
-/*
- * fsm_input - Input packet.
- */
-void
-fsm_input(f, inpacket, l)
- fsm *f;
- u_char *inpacket;
- int l;
-{
- u_char *inp;
- u_char code, id;
- int len;
-
- /*
- * Parse header (code, id and length).
- * If packet too short, drop it.
- */
- inp = inpacket;
- if (l < HEADERLEN) {
- FSMDEBUG((LOG_WARNING, "fsm_input(%x): Rcvd short header.",
- f->protocol));
- return;
- }
- GETCHAR(code, inp);
- GETCHAR(id, inp);
- GETSHORT(len, inp);
- if (len < HEADERLEN) {
- FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd illegal length.",
- f->protocol));
- return;
- }
- if (len > l) {
- FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd short packet.",
- f->protocol));
- return;
- }
- len -= HEADERLEN; /* subtract header length */
-
- if( f->state == INITIAL || f->state == STARTING ){
- FSMDEBUG((LOG_INFO, "fsm_input(%x): Rcvd packet in state %d.",
- f->protocol, f->state));
- return;
- }
-
- /*
- * Action depends on code.
- */
- switch (code) {
- case CONFREQ:
- fsm_rconfreq(f, id, inp, len);
- break;
-
- case CONFACK:
- fsm_rconfack(f, id, inp, len);
- break;
-
- case CONFNAK:
- case CONFREJ:
- fsm_rconfnakrej(f, code, id, inp, len);
- break;
-
- case TERMREQ:
- fsm_rtermreq(f, id, inp, len);
- break;
-
- case TERMACK:
- fsm_rtermack(f);
- break;
-
- case CODEREJ:
- fsm_rcoderej(f, inp, len);
- break;
-
- default:
- if( !f->callbacks->extcode
- || !(*f->callbacks->extcode)(f, code, id, inp, len) )
- fsm_sdata(f, CODEREJ, ++f->id, inpacket, len + HEADERLEN);
- break;
- }
-}
-
-
-/*
- * fsm_rconfreq - Receive Configure-Request.
- */
-static void
-fsm_rconfreq(f, id, inp, len)
- fsm *f;
- u_char id;
- u_char *inp;
- int len;
-{
- int code, reject_if_disagree;
-
- FSMDEBUG((LOG_INFO, "fsm_rconfreq(%s): Rcvd id %d.", PROTO_NAME(f), id));
- switch( f->state ){
- case CLOSED:
- /* Go away, we're closed */
- fsm_sdata(f, TERMACK, id, NULL, 0);
- return;
- case CLOSING:
- case STOPPING:
- return;
-
- case OPENED:
- /* Go down and restart negotiation */
- if( f->callbacks->down )
- (*f->callbacks->down)(f); /* Inform upper layers */
- fsm_sconfreq(f, 0); /* Send initial Configure-Request */
- break;
-
- case STOPPED:
- /* Negotiation started by our peer */
- fsm_sconfreq(f, 0); /* Send initial Configure-Request */
- f->state = REQSENT;
- break;
- }
-
- /*
- * Pass the requested configuration options
- * to protocol-specific code for checking.
- */
- if (f->callbacks->reqci){ /* Check CI */
- reject_if_disagree = (f->nakloops >= f->maxnakloops);
- code = (*f->callbacks->reqci)(f, inp, &len, reject_if_disagree);
- } else if (len)
- code = CONFREJ; /* Reject all CI */
- else
- code = CONFACK;
-
- /* send the Ack, Nak or Rej to the peer */
- fsm_sdata(f, code, id, inp, len);
-
- if (code == CONFACK) {
- if (f->state == ACKRCVD) {
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- f->state = OPENED;
- if (f->callbacks->up)
- (*f->callbacks->up)(f); /* Inform upper layers */
- } else
- f->state = ACKSENT;
- f->nakloops = 0;
-
- } else {
- /* we sent CONFACK or CONFREJ */
- if (f->state != ACKRCVD)
- f->state = REQSENT;
- if( code == CONFNAK )
- ++f->nakloops;
- }
-}
-
-
-/*
- * fsm_rconfack - Receive Configure-Ack.
- */
-static void
-fsm_rconfack(f, id, inp, len)
- fsm *f;
- int id;
- u_char *inp;
- int len;
-{
- FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d.",
- PROTO_NAME(f), id));
-
- if (id != f->reqid || f->seen_ack) /* Expected id? */
- return; /* Nope, toss... */
- if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len):
- (len == 0)) ){
- /* Ack is bad - ignore it */
- log_packet(inp, len, "Received bad configure-ack: ", LOG_ERR);
- FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)",
- PROTO_NAME(f), len));
- return;
- }
- f->seen_ack = 1;
-
- switch (f->state) {
- case CLOSED:
- case STOPPED:
- fsm_sdata(f, TERMACK, id, NULL, 0);
- break;
-
- case REQSENT:
- f->state = ACKRCVD;
- f->retransmits = f->maxconfreqtransmits;
- break;
-
- case ACKRCVD:
- /* Huh? an extra valid Ack? oh well... */
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- fsm_sconfreq(f, 0);
- f->state = REQSENT;
- break;
-
- case ACKSENT:
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- f->state = OPENED;
- f->retransmits = f->maxconfreqtransmits;
- if (f->callbacks->up)
- (*f->callbacks->up)(f); /* Inform upper layers */
- break;
-
- case OPENED:
- /* Go down and restart negotiation */
- if (f->callbacks->down)
- (*f->callbacks->down)(f); /* Inform upper layers */
- fsm_sconfreq(f, 0); /* Send initial Configure-Request */
- f->state = REQSENT;
- break;
- }
-}
-
-
-/*
- * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
- */
-static void
-fsm_rconfnakrej(f, code, id, inp, len)
- fsm *f;
- int code, id;
- u_char *inp;
- int len;
-{
- int (*proc)(fsm *, u_char *, int);
- int ret;
-
- FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d.",
- PROTO_NAME(f), id));
-
- if (id != f->reqid || f->seen_ack) /* Expected id? */
- return; /* Nope, toss... */
- proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci;
- if (!proc || !(ret = proc(f, inp, len))) {
- /* Nak/reject is bad - ignore it */
- log_packet(inp, len, "Received bad configure-nak/rej: ", LOG_ERR);
- FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)",
- PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len));
- return;
- }
- f->seen_ack = 1;
-
- switch (f->state) {
- case CLOSED:
- case STOPPED:
- fsm_sdata(f, TERMACK, id, NULL, 0);
- break;
-
- case REQSENT:
- case ACKSENT:
- /* They didn't agree to what we wanted - try another request */
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- if (ret < 0)
- f->state = STOPPED; /* kludge for stopping CCP */
- else
- fsm_sconfreq(f, 0); /* Send Configure-Request */
- break;
-
- case ACKRCVD:
- /* Got a Nak/reject when we had already had an Ack?? oh well... */
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- fsm_sconfreq(f, 0);
- f->state = REQSENT;
- break;
-
- case OPENED:
- /* Go down and restart negotiation */
- if (f->callbacks->down)
- (*f->callbacks->down)(f); /* Inform upper layers */
- fsm_sconfreq(f, 0); /* Send initial Configure-Request */
- f->state = REQSENT;
- break;
- }
-}
-
-
-/*
- * fsm_rtermreq - Receive Terminate-Req.
- */
-static void
-fsm_rtermreq(f, id, p, len)
- fsm *f;
- int id;
- u_char *p;
- int len;
-{
- char str[80];
-
- FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d.",
- PROTO_NAME(f), id));
-
- switch (f->state) {
- case ACKRCVD:
- case ACKSENT:
- f->state = REQSENT; /* Start over but keep trying */
- break;
-
- case OPENED:
- if (len > 0) {
- fmtmsg(str, sizeof(str), "%0.*v", len, p);
- syslog(LOG_INFO, "%s terminated by peer (%s)", PROTO_NAME(f), str);
- } else
- syslog(LOG_INFO, "%s terminated by peer", PROTO_NAME(f));
- if (f->callbacks->down)
- (*f->callbacks->down)(f); /* Inform upper layers */
- f->retransmits = 0;
- f->state = STOPPING;
- TIMEOUT(fsm_timeout, f, f->timeouttime);
- break;
- }
-
- fsm_sdata(f, TERMACK, id, NULL, 0);
-}
-
-
-/*
- * fsm_rtermack - Receive Terminate-Ack.
- */
-static void
-fsm_rtermack(f)
- fsm *f;
-{
- FSMDEBUG((LOG_INFO, "fsm_rtermack(%s).", PROTO_NAME(f)));
-
- switch (f->state) {
- case CLOSING:
- UNTIMEOUT(fsm_timeout, f);
- f->state = CLOSED;
- if( f->callbacks->finished )
- (*f->callbacks->finished)(f);
- break;
- case STOPPING:
- UNTIMEOUT(fsm_timeout, f);
- f->state = STOPPED;
- if( f->callbacks->finished )
- (*f->callbacks->finished)(f);
- break;
-
- case ACKRCVD:
- f->state = REQSENT;
- break;
-
- case OPENED:
- if (f->callbacks->down)
- (*f->callbacks->down)(f); /* Inform upper layers */
- fsm_sconfreq(f, 0);
- break;
- }
-}
-
-
-/*
- * fsm_rcoderej - Receive a Code-Reject.
- */
-static void
-fsm_rcoderej(f, inp, len)
- fsm *f;
- u_char *inp;
- int len;
-{
- u_char code, id;
-
- FSMDEBUG((LOG_INFO, "fsm_rcoderej(%s).", PROTO_NAME(f)));
-
- if (len < HEADERLEN) {
- FSMDEBUG((LOG_INFO, "fsm_rcoderej: Rcvd short Code-Reject packet!"));
- return;
- }
- GETCHAR(code, inp);
- GETCHAR(id, inp);
- syslog(LOG_WARNING, "%s: Rcvd Code-Reject for code %d, id %d",
- PROTO_NAME(f), code, id);
-
- if( f->state == ACKRCVD )
- f->state = REQSENT;
-}
-
-
-/*
- * fsm_protreject - Peer doesn't speak this protocol.
- *
- * Treat this as a catastrophic error (RXJ-).
- */
-void
-fsm_protreject(f)
- fsm *f;
-{
- switch( f->state ){
- case CLOSING:
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- /* FALLTHROUGH */
- case CLOSED:
- f->state = CLOSED;
- if( f->callbacks->finished )
- (*f->callbacks->finished)(f);
- break;
-
- case STOPPING:
- case REQSENT:
- case ACKRCVD:
- case ACKSENT:
- UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */
- /* FALLTHROUGH */
- case STOPPED:
- f->state = STOPPED;
- if( f->callbacks->finished )
- (*f->callbacks->finished)(f);
- break;
-
- case OPENED:
- if( f->callbacks->down )
- (*f->callbacks->down)(f);
-
- /* Init restart counter, send Terminate-Request */
- f->retransmits = f->maxtermtransmits;
- fsm_sdata(f, TERMREQ, f->reqid = ++f->id,
- (u_char *) f->term_reason, f->term_reason_len);
- TIMEOUT(fsm_timeout, f, f->timeouttime);
- --f->retransmits;
-
- f->state = STOPPING;
- break;
-
- default:
- FSMDEBUG((LOG_INFO, "%s: Protocol-reject event in state %d!",
- PROTO_NAME(f), f->state));
- }
-}
-
-
-/*
- * fsm_sconfreq - Send a Configure-Request.
- */
-static void
-fsm_sconfreq(f, retransmit)
- fsm *f;
- int retransmit;
-{
- u_char *outp;
- int cilen;
-
- if( f->state != REQSENT && f->state != ACKRCVD && f->state != ACKSENT ){
- /* Not currently negotiating - reset options */
- if( f->callbacks->resetci )
- (*f->callbacks->resetci)(f);
- f->nakloops = 0;
- }
-
- if( !retransmit ){
- /* New request - reset retransmission counter, use new ID */
- f->retransmits = f->maxconfreqtransmits;
- f->reqid = ++f->id;
- }
-
- f->seen_ack = 0;
-
- /*
- * Make up the request packet
- */
- outp = outpacket_buf + PPP_HDRLEN + HEADERLEN;
- if( f->callbacks->cilen && f->callbacks->addci ){
- cilen = (*f->callbacks->cilen)(f);
- if( cilen > peer_mru[f->unit] - HEADERLEN )
- cilen = peer_mru[f->unit] - HEADERLEN;
- if (f->callbacks->addci)
- (*f->callbacks->addci)(f, outp, &cilen);
- } else
- cilen = 0;
-
- /* send the request to our peer */
- fsm_sdata(f, CONFREQ, f->reqid, outp, cilen);
-
- /* start the retransmit timer */
- --f->retransmits;
- TIMEOUT(fsm_timeout, f, f->timeouttime);
-
- FSMDEBUG((LOG_INFO, "%s: sending Configure-Request, id %d",
- PROTO_NAME(f), f->reqid));
-}
-
-
-/*
- * fsm_sdata - Send some data.
- *
- * Used for all packets sent to our peer by this module.
- */
-void
-fsm_sdata(f, code, id, data, datalen)
- fsm *f;
- u_char code, id;
- u_char *data;
- int datalen;
-{
- u_char *outp;
- int outlen;
-
- /* Adjust length to be smaller than MTU */
- outp = outpacket_buf;
- if (datalen > peer_mru[f->unit] - HEADERLEN)
- datalen = peer_mru[f->unit] - HEADERLEN;
- if (datalen && data != outp + PPP_HDRLEN + HEADERLEN)
- BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen);
- outlen = datalen + HEADERLEN;
- MAKEHEADER(outp, f->protocol);
- PUTCHAR(code, outp);
- PUTCHAR(id, outp);
- PUTSHORT(outlen, outp);
- output(f->unit, outpacket_buf, outlen + PPP_HDRLEN);
-
- FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d, id %d.",
- PROTO_NAME(f), code, id));
-}
diff --git a/usr.sbin/pppd/fsm.h b/usr.sbin/pppd/fsm.h
deleted file mode 100644
index 053c833..0000000
--- a/usr.sbin/pppd/fsm.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * fsm.h - {Link, IP} Control Protocol Finite State Machine definitions.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
- */
-
-/*
- * Packet header = Code, id, length.
- */
-#define HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short))
-
-
-/*
- * CP (LCP, IPCP, etc.) codes.
- */
-#define CONFREQ 1 /* Configuration Request */
-#define CONFACK 2 /* Configuration Ack */
-#define CONFNAK 3 /* Configuration Nak */
-#define CONFREJ 4 /* Configuration Reject */
-#define TERMREQ 5 /* Termination Request */
-#define TERMACK 6 /* Termination Ack */
-#define CODEREJ 7 /* Code Reject */
-
-
-/*
- * Each FSM is described by an fsm structure and fsm callbacks.
- */
-typedef struct fsm {
- int unit; /* Interface unit number */
- int protocol; /* Data Link Layer Protocol field value */
- int state; /* State */
- int flags; /* Contains option bits */
- u_char id; /* Current id */
- u_char reqid; /* Current request id */
- u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */
- int timeouttime; /* Timeout time in milliseconds */
- int maxconfreqtransmits; /* Maximum Configure-Request transmissions */
- int retransmits; /* Number of retransmissions left */
- int maxtermtransmits; /* Maximum Terminate-Request transmissions */
- int nakloops; /* Number of nak loops since last ack */
- int maxnakloops; /* Maximum number of nak loops tolerated */
- struct fsm_callbacks *callbacks; /* Callback routines */
- char *term_reason; /* Reason for closing protocol */
- int term_reason_len; /* Length of term_reason */
-} fsm;
-
-
-typedef struct fsm_callbacks {
- void (*resetci) /* Reset our Configuration Information */
- (fsm *);
- int (*cilen) /* Length of our Configuration Information */
- (fsm *);
- void (*addci) /* Add our Configuration Information */
- (fsm *, u_char *, int *);
- int (*ackci) /* ACK our Configuration Information */
- (fsm *, u_char *, int);
- int (*nakci) /* NAK our Configuration Information */
- (fsm *, u_char *, int);
- int (*rejci) /* Reject our Configuration Information */
- (fsm *, u_char *, int);
- int (*reqci) /* Request peer's Configuration Information */
- (fsm *, u_char *, int *, int);
- void (*up) /* Called when fsm reaches OPENED state */
- (fsm *);
- void (*down) /* Called when fsm leaves OPENED state */
- (fsm *);
- void (*starting) /* Called when we want the lower layer */
- (fsm *);
- void (*finished) /* Called when we don't want the lower layer */
- (fsm *);
- void (*protreject) /* Called when Protocol-Reject received */
- (int);
- void (*retransmit) /* Retransmission is necessary */
- (fsm *);
- int (*extcode) /* Called when unknown code received */
- (fsm *, int, int, u_char *, int);
- char *proto_name; /* String name for protocol (for messages) */
-} fsm_callbacks;
-
-
-/*
- * Link states.
- */
-#define INITIAL 0 /* Down, hasn't been opened */
-#define STARTING 1 /* Down, been opened */
-#define CLOSED 2 /* Up, hasn't been opened */
-#define STOPPED 3 /* Open, waiting for down event */
-#define CLOSING 4 /* Terminating the connection, not open */
-#define STOPPING 5 /* Terminating, but open */
-#define REQSENT 6 /* We've sent a Config Request */
-#define ACKRCVD 7 /* We've received a Config Ack */
-#define ACKSENT 8 /* We've sent a Config Ack */
-#define OPENED 9 /* Connection available */
-
-
-/*
- * Flags - indicate options controlling FSM operation
- */
-#define OPT_PASSIVE 1 /* Don't die if we don't get a response */
-#define OPT_RESTART 2 /* Treat 2nd OPEN as DOWN, UP */
-#define OPT_SILENT 4 /* Wait for peer to speak first */
-
-
-/*
- * Timeouts.
- */
-#define DEFTIMEOUT 3 /* Timeout time in seconds */
-#define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */
-#define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */
-#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */
-
-
-/*
- * Prototypes
- */
-void fsm_init(fsm *);
-void fsm_lowerup(fsm *);
-void fsm_lowerdown(fsm *);
-void fsm_open(fsm *);
-void fsm_close(fsm *, char *);
-void fsm_input(fsm *, u_char *, int);
-void fsm_protreject(fsm *);
-void fsm_sdata(fsm *, int, int, u_char *, int);
-
-
-/*
- * Variables
- */
-extern int peer_mru[]; /* currently negotiated peer MRU (per unit) */
diff --git a/usr.sbin/pppd/ipcp.c b/usr.sbin/pppd/ipcp.c
deleted file mode 100644
index 3369757..0000000
--- a/usr.sbin/pppd/ipcp.c
+++ /dev/null
@@ -1,1531 +0,0 @@
-/*
- * ipcp.c - PPP IP Control Protocol.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-/*
- * TODO:
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <netdb.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include "pppd.h"
-#include "fsm.h"
-#include "ipcp.h"
-#include "pathnames.h"
-
-/* global vars */
-ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
-ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
-ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
-ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
-
-/* local vars */
-static int cis_received[NUM_PPP]; /* # Conf-Reqs received */
-static int default_route_set[NUM_PPP]; /* Have set up a default route */
-static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */
-
-/*
- * Callbacks for fsm code. (CI = Configuration Information)
- */
-static void ipcp_resetci(fsm *); /* Reset our CI */
-static int ipcp_cilen(fsm *); /* Return length of our CI */
-static void ipcp_addci(fsm *, u_char *, int *); /* Add our CI */
-static int ipcp_ackci(fsm *, u_char *, int); /* Peer ack'd our CI */
-static int ipcp_nakci(fsm *, u_char *, int); /* Peer nak'd our CI */
-static int ipcp_rejci(fsm *, u_char *, int); /* Peer rej'd our CI */
-static int ipcp_reqci(fsm *, u_char *, int *, int); /* Rcv CI */
-static void ipcp_up(fsm *); /* We're UP */
-static void ipcp_down(fsm *); /* We're DOWN */
-static void ipcp_script(fsm *, char *); /* Run an up/down script */
-static void ipcp_finished(fsm *); /* Don't need lower layer */
-
-fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
-
-static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
- ipcp_resetci, /* Reset our Configuration Information */
- ipcp_cilen, /* Length of our Configuration Information */
- ipcp_addci, /* Add our Configuration Information */
- ipcp_ackci, /* ACK our Configuration Information */
- ipcp_nakci, /* NAK our Configuration Information */
- ipcp_rejci, /* Reject our Configuration Information */
- ipcp_reqci, /* Request peer's Configuration Information */
- ipcp_up, /* Called when fsm reaches OPENED state */
- ipcp_down, /* Called when fsm leaves OPENED state */
- NULL, /* Called when we want the lower layer up */
- ipcp_finished, /* Called when we want the lower layer down */
- NULL, /* Called when Protocol-Reject received */
- NULL, /* Retransmission is necessary */
- NULL, /* Called to handle protocol-specific codes */
- "IPCP" /* String name of protocol */
-};
-
-/*
- * Protocol entry points from main code.
- */
-static void ipcp_init(int);
-static void ipcp_open(int);
-static void ipcp_close(int, char *);
-static void ipcp_lowerup(int);
-static void ipcp_lowerdown(int);
-static void ipcp_input(int, u_char *, int);
-static void ipcp_protrej(int);
-static int ipcp_printpkt(u_char *, int,
- void (*) (void *, char *, ...), void *);
-static void ip_check_options(void);
-static int ip_demand_conf(int);
-static int ip_active_pkt(u_char *, int);
-
-struct protent ipcp_protent = {
- PPP_IPCP,
- ipcp_init,
- ipcp_input,
- ipcp_protrej,
- ipcp_lowerup,
- ipcp_lowerdown,
- ipcp_open,
- ipcp_close,
- ipcp_printpkt,
- NULL,
- 1,
- "IPCP",
- ip_check_options,
- ip_demand_conf,
- ip_active_pkt
-};
-
-static void ipcp_clear_addrs(int);
-
-/*
- * Lengths of configuration options.
- */
-#define CILEN_VOID 2
-#define CILEN_COMPRESS 4 /* min length for compression protocol opt. */
-#define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */
-#define CILEN_ADDR 6 /* new-style single address option */
-#define CILEN_ADDRS 10 /* old-style dual address option */
-
-
-#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
- (x) == CONFNAK ? "NAK" : "REJ")
-
-
-/*
- * Make a string representation of a network IP address.
- */
-char *
-ip_ntoa(ipaddr)
-u_int32_t ipaddr;
-{
- static char b[64];
-
- ipaddr = ntohl(ipaddr);
-
- sprintf(b, "%d.%d.%d.%d",
- (u_char)(ipaddr >> 24),
- (u_char)(ipaddr >> 16),
- (u_char)(ipaddr >> 8),
- (u_char)(ipaddr));
- return b;
-}
-
-
-/*
- * ipcp_init - Initialize IPCP.
- */
-static void
-ipcp_init(unit)
- int unit;
-{
- fsm *f = &ipcp_fsm[unit];
- ipcp_options *wo = &ipcp_wantoptions[unit];
- ipcp_options *ao = &ipcp_allowoptions[unit];
-
- f->unit = unit;
- f->protocol = PPP_IPCP;
- f->callbacks = &ipcp_callbacks;
- fsm_init(&ipcp_fsm[unit]);
-
- memset(wo, 0, sizeof(*wo));
- memset(ao, 0, sizeof(*ao));
-
- wo->neg_addr = 1;
- wo->neg_vj = 1;
- wo->vj_protocol = IPCP_VJ_COMP;
- wo->maxslotindex = MAX_STATES - 1; /* really max index */
- wo->cflag = 1;
-
- /* max slots and slot-id compression are currently hardwired in */
- /* ppp_if.c to 16 and 1, this needs to be changed (among other */
- /* things) gmc */
-
- ao->neg_addr = 1;
- ao->neg_vj = 1;
- ao->maxslotindex = MAX_STATES - 1;
- ao->cflag = 1;
-
- /*
- * XXX These control whether the user may use the proxyarp
- * and defaultroute options.
- */
- ao->proxy_arp = 1;
- ao->default_route = 1;
-}
-
-
-/*
- * ipcp_open - IPCP is allowed to come up.
- */
-static void
-ipcp_open(unit)
- int unit;
-{
- fsm_open(&ipcp_fsm[unit]);
-}
-
-
-/*
- * ipcp_close - Take IPCP down.
- */
-static void
-ipcp_close(unit, reason)
- int unit;
- char *reason;
-{
- fsm_close(&ipcp_fsm[unit], reason);
-}
-
-
-/*
- * ipcp_lowerup - The lower layer is up.
- */
-static void
-ipcp_lowerup(unit)
- int unit;
-{
- fsm_lowerup(&ipcp_fsm[unit]);
-}
-
-
-/*
- * ipcp_lowerdown - The lower layer is down.
- */
-static void
-ipcp_lowerdown(unit)
- int unit;
-{
- fsm_lowerdown(&ipcp_fsm[unit]);
-}
-
-
-/*
- * ipcp_input - Input IPCP packet.
- */
-static void
-ipcp_input(unit, p, len)
- int unit;
- u_char *p;
- int len;
-{
- fsm_input(&ipcp_fsm[unit], p, len);
-}
-
-
-/*
- * ipcp_protrej - A Protocol-Reject was received for IPCP.
- *
- * Pretend the lower layer went down, so we shut up.
- */
-static void
-ipcp_protrej(unit)
- int unit;
-{
- fsm_lowerdown(&ipcp_fsm[unit]);
-}
-
-
-/*
- * ipcp_resetci - Reset our CI.
- */
-static void
-ipcp_resetci(f)
- fsm *f;
-{
- ipcp_options *wo = &ipcp_wantoptions[f->unit];
-
- wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
- if (wo->ouraddr == 0)
- wo->accept_local = 1;
- if (wo->hisaddr == 0)
- wo->accept_remote = 1;
- ipcp_gotoptions[f->unit] = *wo;
- cis_received[f->unit] = 0;
-}
-
-
-/*
- * ipcp_cilen - Return length of our CI.
- */
-static int
-ipcp_cilen(f)
- fsm *f;
-{
- ipcp_options *go = &ipcp_gotoptions[f->unit];
- ipcp_options *wo = &ipcp_wantoptions[f->unit];
- ipcp_options *ho = &ipcp_hisoptions[f->unit];
-
-#define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
-#define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
-
- /*
- * First see if we want to change our options to the old
- * forms because we have received old forms from the peer.
- */
- if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
- /* use the old style of address negotiation */
- go->neg_addr = 1;
- go->old_addrs = 1;
- }
- if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
- /* try an older style of VJ negotiation */
- if (cis_received[f->unit] == 0) {
- /* keep trying the new style until we see some CI from the peer */
- go->neg_vj = 1;
- } else {
- /* use the old style only if the peer did */
- if (ho->neg_vj && ho->old_vj) {
- go->neg_vj = 1;
- go->old_vj = 1;
- go->vj_protocol = ho->vj_protocol;
- }
- }
- }
-
- return (LENCIADDR(go->neg_addr, go->old_addrs) +
- LENCIVJ(go->neg_vj, go->old_vj));
-}
-
-
-/*
- * ipcp_addci - Add our desired CIs to a packet.
- */
-static void
-ipcp_addci(f, ucp, lenp)
- fsm *f;
- u_char *ucp;
- int *lenp;
-{
- ipcp_options *go = &ipcp_gotoptions[f->unit];
- int len = *lenp;
-
-#define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
- if (neg) { \
- int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
- if (len >= vjlen) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(vjlen, ucp); \
- PUTSHORT(val, ucp); \
- if (!old) { \
- PUTCHAR(maxslotindex, ucp); \
- PUTCHAR(cflag, ucp); \
- } \
- len -= vjlen; \
- } else \
- neg = 0; \
- }
-
-#define ADDCIADDR(opt, neg, old, val1, val2) \
- if (neg) { \
- int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
- if (len >= addrlen) { \
- u_int32_t l; \
- PUTCHAR(opt, ucp); \
- PUTCHAR(addrlen, ucp); \
- l = ntohl(val1); \
- PUTLONG(l, ucp); \
- if (old) { \
- l = ntohl(val2); \
- PUTLONG(l, ucp); \
- } \
- len -= addrlen; \
- } else \
- neg = 0; \
- }
-
- ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
- go->old_addrs, go->ouraddr, go->hisaddr);
-
- ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
- go->maxslotindex, go->cflag);
-
- *lenp -= len;
-}
-
-
-/*
- * ipcp_ackci - Ack our CIs.
- *
- * Returns:
- * 0 - Ack was bad.
- * 1 - Ack was good.
- */
-static int
-ipcp_ackci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- ipcp_options *go = &ipcp_gotoptions[f->unit];
- u_short cilen, citype, cishort;
- u_int32_t cilong;
- u_char cimaxslotindex, cicflag;
-
- /*
- * CIs must be in exactly the same order that we sent...
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
-
-#define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
- if (neg) { \
- int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
- if ((len -= vjlen) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != vjlen || \
- citype != opt) \
- goto bad; \
- GETSHORT(cishort, p); \
- if (cishort != val) \
- goto bad; \
- if (!old) { \
- GETCHAR(cimaxslotindex, p); \
- if (cimaxslotindex != maxslotindex) \
- goto bad; \
- GETCHAR(cicflag, p); \
- if (cicflag != cflag) \
- goto bad; \
- } \
- }
-
-#define ACKCIADDR(opt, neg, old, val1, val2) \
- if (neg) { \
- int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
- u_int32_t l; \
- if ((len -= addrlen) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != addrlen || \
- citype != opt) \
- goto bad; \
- GETLONG(l, p); \
- cilong = htonl(l); \
- if (val1 != cilong) \
- goto bad; \
- if (old) { \
- GETLONG(l, p); \
- cilong = htonl(l); \
- if (val2 != cilong) \
- goto bad; \
- } \
- }
-
- ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
- go->old_addrs, go->ouraddr, go->hisaddr);
-
- ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
- go->maxslotindex, go->cflag);
-
- /*
- * If there are any remaining CIs, then this packet is bad.
- */
- if (len != 0)
- goto bad;
- return (1);
-
-bad:
- IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!"));
- return (0);
-}
-
-/*
- * ipcp_nakci - Peer has sent a NAK for some of our CIs.
- * This should not modify any state if the Nak is bad
- * or if IPCP is in the OPENED state.
- *
- * Returns:
- * 0 - Nak was bad.
- * 1 - Nak was good.
- */
-static int
-ipcp_nakci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- ipcp_options *go = &ipcp_gotoptions[f->unit];
- u_char cimaxslotindex, cicflag;
- u_char citype, cilen, *next;
- u_short cishort;
- u_int32_t ciaddr1, ciaddr2, l;
- ipcp_options no; /* options we've seen Naks for */
- ipcp_options try; /* options to request next time */
-
- BZERO(&no, sizeof(no));
- try = *go;
-
- /*
- * Any Nak'd CIs must be in exactly the same order that we sent.
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
-#define NAKCIADDR(opt, neg, old, code) \
- if (go->neg && \
- len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
- p[1] == cilen && \
- p[0] == opt) { \
- len -= cilen; \
- INCPTR(2, p); \
- GETLONG(l, p); \
- ciaddr1 = htonl(l); \
- if (old) { \
- GETLONG(l, p); \
- ciaddr2 = htonl(l); \
- no.old_addrs = 1; \
- } else \
- ciaddr2 = 0; \
- no.neg = 1; \
- code \
- }
-
-#define NAKCIVJ(opt, neg, code) \
- if (go->neg && \
- ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
- len >= cilen && \
- p[0] == opt) { \
- len -= cilen; \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- no.neg = 1; \
- code \
- }
-
- /*
- * Accept the peer's idea of {our,his} address, if different
- * from our idea, only if the accept_{local,remote} flag is set.
- */
- NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
- if (go->accept_local && ciaddr1) { /* Do we know our address? */
- try.ouraddr = ciaddr1;
- IPCPDEBUG((LOG_INFO, "local IP address %s",
- ip_ntoa(ciaddr1)));
- }
- if (go->accept_remote && ciaddr2) { /* Does he know his? */
- try.hisaddr = ciaddr2;
- IPCPDEBUG((LOG_INFO, "remote IP address %s",
- ip_ntoa(ciaddr2)));
- }
- );
-
- /*
- * Accept the peer's value of maxslotindex provided that it
- * is less than what we asked for. Turn off slot-ID compression
- * if the peer wants. Send old-style compress-type option if
- * the peer wants.
- */
- NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
- if (cilen == CILEN_VJ) {
- GETCHAR(cimaxslotindex, p);
- GETCHAR(cicflag, p);
- if (cishort == IPCP_VJ_COMP) {
- try.old_vj = 0;
- if (cimaxslotindex < go->maxslotindex)
- try.maxslotindex = cimaxslotindex;
- if (!cicflag)
- try.cflag = 0;
- } else {
- try.neg_vj = 0;
- }
- } else {
- if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
- try.old_vj = 1;
- try.vj_protocol = cishort;
- } else {
- try.neg_vj = 0;
- }
- }
- );
-
- /*
- * There may be remaining CIs, if the peer is requesting negotiation
- * on an option that we didn't include in our request packet.
- * If they want to negotiate about IP addresses, we comply.
- * If they want us to ask for compression, we refuse.
- */
- while (len > CILEN_VOID) {
- GETCHAR(citype, p);
- GETCHAR(cilen, p);
- if( (len -= cilen) < 0 )
- goto bad;
- next = p + cilen - 2;
-
- switch (citype) {
- case CI_COMPRESSTYPE:
- if (go->neg_vj || no.neg_vj ||
- (cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
- goto bad;
- no.neg_vj = 1;
- break;
- case CI_ADDRS:
- if ((go->neg_addr && go->old_addrs) || no.old_addrs
- || cilen != CILEN_ADDRS)
- goto bad;
- try.neg_addr = 1;
- try.old_addrs = 1;
- GETLONG(l, p);
- ciaddr1 = htonl(l);
- if (ciaddr1 && go->accept_local)
- try.ouraddr = ciaddr1;
- GETLONG(l, p);
- ciaddr2 = htonl(l);
- if (ciaddr2 && go->accept_remote)
- try.hisaddr = ciaddr2;
- no.old_addrs = 1;
- break;
- case CI_ADDR:
- if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
- goto bad;
- try.old_addrs = 0;
- GETLONG(l, p);
- ciaddr1 = htonl(l);
- if (ciaddr1 && go->accept_local)
- try.ouraddr = ciaddr1;
- if (try.ouraddr != 0)
- try.neg_addr = 1;
- no.neg_addr = 1;
- break;
- }
- p = next;
- }
-
- /* If there is still anything left, this packet is bad. */
- if (len != 0)
- goto bad;
-
- /*
- * OK, the Nak is good. Now we can update state.
- */
- if (f->state != OPENED)
- *go = try;
-
- return 1;
-
-bad:
- IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!"));
- return 0;
-}
-
-
-/*
- * ipcp_rejci - Reject some of our CIs.
- */
-static int
-ipcp_rejci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- ipcp_options *go = &ipcp_gotoptions[f->unit];
- u_char cimaxslotindex, ciflag, cilen;
- u_short cishort;
- u_int32_t cilong;
- ipcp_options try; /* options to request next time */
-
- try = *go;
- /*
- * Any Rejected CIs must be in exactly the same order that we sent.
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
-#define REJCIADDR(opt, neg, old, val1, val2) \
- if (go->neg && \
- len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
- p[1] == cilen && \
- p[0] == opt) { \
- u_int32_t l; \
- len -= cilen; \
- INCPTR(2, p); \
- GETLONG(l, p); \
- cilong = htonl(l); \
- /* Check rejected value. */ \
- if (cilong != val1) \
- goto bad; \
- if (old) { \
- GETLONG(l, p); \
- cilong = htonl(l); \
- /* Check rejected value. */ \
- if (cilong != val2) \
- goto bad; \
- } \
- try.neg = 0; \
- }
-
-#define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
- if (go->neg && \
- p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
- len >= p[1] && \
- p[0] == opt) { \
- len -= p[1]; \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- /* Check rejected value. */ \
- if (cishort != val) \
- goto bad; \
- if (!old) { \
- GETCHAR(cimaxslotindex, p); \
- if (cimaxslotindex != maxslot) \
- goto bad; \
- GETCHAR(ciflag, p); \
- if (ciflag != cflag) \
- goto bad; \
- } \
- try.neg = 0; \
- }
-
- REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,
- go->old_addrs, go->ouraddr, go->hisaddr);
-
- REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
- go->maxslotindex, go->cflag);
-
- /*
- * If there are any remaining CIs, then this packet is bad.
- */
- if (len != 0)
- goto bad;
- /*
- * Now we can update state.
- */
- if (f->state != OPENED)
- *go = try;
- return 1;
-
-bad:
- IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!"));
- return 0;
-}
-
-
-/*
- * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
- *
- * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
- * appropriately. If reject_if_disagree is non-zero, doesn't return
- * CONFNAK; returns CONFREJ if it can't return CONFACK.
- */
-static int
-ipcp_reqci(f, inp, len, reject_if_disagree)
- fsm *f;
- u_char *inp; /* Requested CIs */
- int *len; /* Length of requested CIs */
- int reject_if_disagree;
-{
- ipcp_options *wo = &ipcp_wantoptions[f->unit];
- ipcp_options *ho = &ipcp_hisoptions[f->unit];
- ipcp_options *ao = &ipcp_allowoptions[f->unit];
- ipcp_options *go = &ipcp_gotoptions[f->unit];
- u_char *cip, *next; /* Pointer to current and next CIs */
- u_short cilen, citype; /* Parsed len, type */
- u_short cishort; /* Parsed short value */
- u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */
- int rc = CONFACK; /* Final packet return code */
- int orc; /* Individual option return code */
- u_char *p; /* Pointer to next char to parse */
- u_char *ucp = inp; /* Pointer to current output char */
- int l = *len; /* Length left */
- u_char maxslotindex, cflag;
- int d;
-
- cis_received[f->unit] = 1;
-
- /*
- * Reset all his options.
- */
- BZERO(ho, sizeof(*ho));
-
- /*
- * Process all his options.
- */
- next = inp;
- while (l) {
- orc = CONFACK; /* Assume success */
- cip = p = next; /* Remember begining of CI */
- if (l < 2 || /* Not enough data for CI header or */
- p[1] < 2 || /* CI length too small or */
- p[1] > l) { /* CI length too big? */
- IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!"));
- orc = CONFREJ; /* Reject bad CI */
- cilen = l; /* Reject till end of packet */
- l = 0; /* Don't loop again */
- goto endswitch;
- }
- GETCHAR(citype, p); /* Parse CI type */
- GETCHAR(cilen, p); /* Parse CI length */
- l -= cilen; /* Adjust remaining length */
- next += cilen; /* Step to next CI */
-
- switch (citype) { /* Check CI type */
- case CI_ADDRS:
- IPCPDEBUG((LOG_INFO, "ipcp: received ADDRS "));
- if (!ao->neg_addr ||
- cilen != CILEN_ADDRS) { /* Check CI length */
- orc = CONFREJ; /* Reject CI */
- break;
- }
-
- /*
- * If he has no address, or if we both have his address but
- * disagree about it, then NAK it with our idea.
- * In particular, if we don't know his address, but he does,
- * then accept it.
- */
- GETLONG(tl, p); /* Parse source address (his) */
- ciaddr1 = htonl(tl);
- IPCPDEBUG((LOG_INFO, "(%s:", ip_ntoa(ciaddr1)));
- if (ciaddr1 != wo->hisaddr
- && (ciaddr1 == 0 || !wo->accept_remote)) {
- orc = CONFNAK;
- if (!reject_if_disagree) {
- DECPTR(sizeof(u_int32_t), p);
- tl = ntohl(wo->hisaddr);
- PUTLONG(tl, p);
- }
- } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
- /*
- * If neither we nor he knows his address, reject the option.
- */
- orc = CONFREJ;
- wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
- break;
- }
-
- /*
- * If he doesn't know our address, or if we both have our address
- * but disagree about it, then NAK it with our idea.
- */
- GETLONG(tl, p); /* Parse desination address (ours) */
- ciaddr2 = htonl(tl);
- IPCPDEBUG((LOG_INFO, "%s)", ip_ntoa(ciaddr2)));
- if (ciaddr2 != wo->ouraddr) {
- if (ciaddr2 == 0 || !wo->accept_local) {
- orc = CONFNAK;
- if (!reject_if_disagree) {
- DECPTR(sizeof(u_int32_t), p);
- tl = ntohl(wo->ouraddr);
- PUTLONG(tl, p);
- }
- } else {
- go->ouraddr = ciaddr2; /* accept peer's idea */
- }
- }
-
- ho->neg_addr = 1;
- ho->old_addrs = 1;
- ho->hisaddr = ciaddr1;
- ho->ouraddr = ciaddr2;
- break;
-
- case CI_ADDR:
- IPCPDEBUG((LOG_INFO, "ipcp: received ADDR "));
-
- if (!ao->neg_addr ||
- cilen != CILEN_ADDR) { /* Check CI length */
- orc = CONFREJ; /* Reject CI */
- break;
- }
-
- /*
- * If he has no address, or if we both have his address but
- * disagree about it, then NAK it with our idea.
- * In particular, if we don't know his address, but he does,
- * then accept it.
- */
- GETLONG(tl, p); /* Parse source address (his) */
- ciaddr1 = htonl(tl);
- IPCPDEBUG((LOG_INFO, "(%s)", ip_ntoa(ciaddr1)));
- if (ciaddr1 != wo->hisaddr
- && (ciaddr1 == 0 || !wo->accept_remote)) {
- orc = CONFNAK;
- if (!reject_if_disagree) {
- DECPTR(sizeof(u_int32_t), p);
- tl = ntohl(wo->hisaddr);
- PUTLONG(tl, p);
- }
- } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
- /*
- * Don't ACK an address of 0.0.0.0 - reject it instead.
- */
- orc = CONFREJ;
- wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
- break;
- }
-
- ho->neg_addr = 1;
- ho->hisaddr = ciaddr1;
- break;
-
- case CI_MS_DNS1:
- case CI_MS_DNS2:
- /* Microsoft primary or secondary DNS request */
- d = citype == CI_MS_DNS2;
- IPCPDEBUG((LOG_INFO, "ipcp: received DNS%d Request ", d+1));
-
- /* If we do not have a DNS address then we cannot send it */
- if (ao->dnsaddr[d] == 0 ||
- cilen != CILEN_ADDR) { /* Check CI length */
- orc = CONFREJ; /* Reject CI */
- break;
- }
- GETLONG(tl, p);
- if (htonl(tl) != ao->dnsaddr[d]) {
- DECPTR(sizeof(u_int32_t), p);
- tl = ntohl(ao->dnsaddr[d]);
- PUTLONG(tl, p);
- orc = CONFNAK;
- }
- break;
-
- case CI_MS_WINS1:
- case CI_MS_WINS2:
- /* Microsoft primary or secondary WINS request */
- d = citype == CI_MS_WINS2;
- IPCPDEBUG((LOG_INFO, "ipcp: received WINS%d Request ", d+1));
-
- /* If we do not have a DNS address then we cannot send it */
- if (ao->winsaddr[d] == 0 ||
- cilen != CILEN_ADDR) { /* Check CI length */
- orc = CONFREJ; /* Reject CI */
- break;
- }
- GETLONG(tl, p);
- if (htonl(tl) != ao->winsaddr[d]) {
- DECPTR(sizeof(u_int32_t), p);
- tl = ntohl(ao->winsaddr[d]);
- PUTLONG(tl, p);
- orc = CONFNAK;
- }
- break;
-
- case CI_COMPRESSTYPE:
- IPCPDEBUG((LOG_INFO, "ipcp: received COMPRESSTYPE "));
- if (!ao->neg_vj ||
- (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
- orc = CONFREJ;
- break;
- }
- GETSHORT(cishort, p);
- IPCPDEBUG((LOG_INFO, "(%d)", cishort));
-
- if (!(cishort == IPCP_VJ_COMP ||
- (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
- orc = CONFREJ;
- break;
- }
-
- ho->neg_vj = 1;
- ho->vj_protocol = cishort;
- if (cilen == CILEN_VJ) {
- GETCHAR(maxslotindex, p);
- if (maxslotindex > ao->maxslotindex) {
- orc = CONFNAK;
- if (!reject_if_disagree){
- DECPTR(1, p);
- PUTCHAR(ao->maxslotindex, p);
- }
- }
- GETCHAR(cflag, p);
- if (cflag && !ao->cflag) {
- orc = CONFNAK;
- if (!reject_if_disagree){
- DECPTR(1, p);
- PUTCHAR(wo->cflag, p);
- }
- }
- ho->maxslotindex = maxslotindex;
- ho->cflag = cflag;
- } else {
- ho->old_vj = 1;
- ho->maxslotindex = MAX_STATES - 1;
- ho->cflag = 1;
- }
- break;
-
- default:
- orc = CONFREJ;
- break;
- }
-
-endswitch:
- IPCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc)));
-
- if (orc == CONFACK && /* Good CI */
- rc != CONFACK) /* but prior CI wasnt? */
- continue; /* Don't send this one */
-
- if (orc == CONFNAK) { /* Nak this CI? */
- if (reject_if_disagree) /* Getting fed up with sending NAKs? */
- orc = CONFREJ; /* Get tough if so */
- else {
- if (rc == CONFREJ) /* Rejecting prior CI? */
- continue; /* Don't send this one */
- if (rc == CONFACK) { /* Ack'd all prior CIs? */
- rc = CONFNAK; /* Not anymore... */
- ucp = inp; /* Backup */
- }
- }
- }
-
- if (orc == CONFREJ && /* Reject this CI */
- rc != CONFREJ) { /* but no prior ones? */
- rc = CONFREJ;
- ucp = inp; /* Backup */
- }
-
- /* Need to move CI? */
- if (ucp != cip)
- BCOPY(cip, ucp, cilen); /* Move it */
-
- /* Update output pointer */
- INCPTR(cilen, ucp);
- }
-
- /*
- * If we aren't rejecting this packet, and we want to negotiate
- * their address, and they didn't send their address, then we
- * send a NAK with a CI_ADDR option appended. We assume the
- * input buffer is long enough that we can append the extra
- * option safely.
- */
- if (rc != CONFREJ && !ho->neg_addr &&
- wo->req_addr && !reject_if_disagree) {
- if (rc == CONFACK) {
- rc = CONFNAK;
- ucp = inp; /* reset pointer */
- wo->req_addr = 0; /* don't ask again */
- }
- PUTCHAR(CI_ADDR, ucp);
- PUTCHAR(CILEN_ADDR, ucp);
- tl = ntohl(wo->hisaddr);
- PUTLONG(tl, ucp);
- }
-
- *len = ucp - inp; /* Compute output length */
- IPCPDEBUG((LOG_INFO, "ipcp: returning Configure-%s", CODENAME(rc)));
- return (rc); /* Return final code */
-}
-
-
-/*
- * ip_check_options - check that any IP-related options are OK,
- * and assign appropriate defaults.
- */
-static void
-ip_check_options()
-{
- struct hostent *hp;
- u_int32_t local;
- ipcp_options *wo = &ipcp_wantoptions[0];
-
- /*
- * Default our local IP address based on our hostname.
- * If local IP address already given, don't bother.
- */
- if (wo->ouraddr == 0 && !disable_defaultip) {
- /*
- * Look up our hostname (possibly with domain name appended)
- * and take the first IP address as our local IP address.
- * If there isn't an IP address for our hostname, too bad.
- */
- wo->accept_local = 1; /* don't insist on this default value */
- if ((hp = gethostbyname(hostname)) != NULL) {
- local = *(u_int32_t *)hp->h_addr;
- if (local != 0 && !bad_ip_adrs(local))
- wo->ouraddr = local;
- }
- }
-
- if (demand && wo->hisaddr == 0) {
- option_error("remote IP address required for demand-dialling\n");
- exit(1);
- }
-#if 0
- if (demand && wo->accept_remote) {
- option_error("ipcp-accept-remote is incompatible with demand\n");
- exit(1);
- }
-#endif
-}
-
-
-/*
- * ip_demand_conf - configure the interface as though
- * IPCP were up, for use with dial-on-demand.
- */
-static int
-ip_demand_conf(u)
- int u;
-{
- ipcp_options *wo = &ipcp_wantoptions[u];
-
- if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
- return 0;
- if (!sifup(u))
- return 0;
- if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
- return 0;
- if (wo->default_route)
- if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
- default_route_set[u] = 1;
- if (wo->proxy_arp)
- if (sifproxyarp(u, wo->hisaddr))
- proxy_arp_set[u] = 1;
-
- syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(wo->ouraddr));
- syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(wo->hisaddr));
-
- return 1;
-}
-
-
-/*
- * ipcp_up - IPCP has come UP.
- *
- * Configure the IP network interface appropriately and bring it up.
- */
-static void
-ipcp_up(f)
- fsm *f;
-{
- u_int32_t mask;
- ipcp_options *ho = &ipcp_hisoptions[f->unit];
- ipcp_options *go = &ipcp_gotoptions[f->unit];
- ipcp_options *wo = &ipcp_wantoptions[f->unit];
-
- np_up(f->unit, PPP_IP);
- IPCPDEBUG((LOG_INFO, "ipcp: up"));
-
- /*
- * We must have a non-zero IP address for both ends of the link.
- */
- if (!ho->neg_addr)
- ho->hisaddr = wo->hisaddr;
-
- if (ho->hisaddr == 0) {
- syslog(LOG_ERR, "Could not determine remote IP address");
- ipcp_close(f->unit, "Could not determine remote IP address");
- return;
- }
- if (go->ouraddr == 0) {
- syslog(LOG_ERR, "Could not determine local IP address");
- ipcp_close(f->unit, "Could not determine local IP address");
- return;
- }
- script_setenv("IPLOCAL", ip_ntoa(go->ouraddr));
- script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr));
-
- /*
- * Check that the peer is allowed to use the IP address it wants.
- */
- if (!auth_ip_addr(f->unit, ho->hisaddr)) {
- syslog(LOG_ERR, "Peer is not authorized to use remote address %s",
- ip_ntoa(ho->hisaddr));
- ipcp_close(f->unit, "Unauthorized remote IP address");
- return;
- }
-
- /* set tcp compression */
- sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
-
- /*
- * If we are doing dial-on-demand, the interface is already
- * configured, so we put out any saved-up packets, then set the
- * interface to pass IP packets.
- */
- if (demand) {
- if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
- if (go->ouraddr != wo->ouraddr)
- syslog(LOG_WARNING, "Local IP address changed to %s",
- ip_ntoa(go->ouraddr));
- if (ho->hisaddr != wo->hisaddr)
- syslog(LOG_WARNING, "Remote IP address changed to %s",
- ip_ntoa(ho->hisaddr));
- ipcp_clear_addrs(f->unit);
-
- /* Set the interface to the new addresses */
- mask = GetMask(go->ouraddr);
- if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
- IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
- ipcp_close(f->unit, "Interface configuration failed");
- return;
- }
-
- /* assign a default route through the interface if required */
- if (ipcp_wantoptions[f->unit].default_route)
- if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
- default_route_set[f->unit] = 1;
-
- /* Make a proxy ARP entry if requested. */
- if (ipcp_wantoptions[f->unit].proxy_arp)
- if (sifproxyarp(f->unit, ho->hisaddr))
- proxy_arp_set[f->unit] = 1;
-
- }
- demand_rexmit(PPP_IP);
- sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
-
- } else {
- /*
- * Set IP addresses and (if specified) netmask.
- */
- mask = GetMask(go->ouraddr);
-
-#if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
- if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
- IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
- ipcp_close(f->unit, "Interface configuration failed");
- return;
- }
-#endif
-
- /* bring the interface up for IP */
- if (!sifup(f->unit)) {
- IPCPDEBUG((LOG_WARNING, "sifup failed"));
- ipcp_close(f->unit, "Interface configuration failed");
- return;
- }
-
-#if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
- if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
- IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
- ipcp_close(f->unit, "Interface configuration failed");
- return;
- }
-#endif
- sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
-
- /* assign a default route through the interface if required */
- if (ipcp_wantoptions[f->unit].default_route)
- if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
- default_route_set[f->unit] = 1;
-
- /* Make a proxy ARP entry if requested. */
- if (ipcp_wantoptions[f->unit].proxy_arp)
- if (sifproxyarp(f->unit, ho->hisaddr))
- proxy_arp_set[f->unit] = 1;
-
- syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(go->ouraddr));
- syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(ho->hisaddr));
- }
-
- /*
- * Execute the ip-up script, like this:
- * /etc/ppp/ip-up interface tty speed local-IP remote-IP
- */
- ipcp_script(f, _PATH_IPUP);
-
-}
-
-
-/*
- * ipcp_down - IPCP has gone DOWN.
- *
- * Take the IP network interface down, clear its addresses
- * and delete routes through it.
- */
-static void
-ipcp_down(f)
- fsm *f;
-{
- IPCPDEBUG((LOG_INFO, "ipcp: down"));
- np_down(f->unit, PPP_IP);
- sifvjcomp(f->unit, 0, 0, 0);
-
- /*
- * If we are doing dial-on-demand, set the interface
- * to queue up outgoing packets (for now).
- */
- if (demand) {
- sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
- } else {
- sifdown(f->unit);
- ipcp_clear_addrs(f->unit);
- }
-
- /* Execute the ip-down script */
- ipcp_script(f, _PATH_IPDOWN);
-}
-
-
-/*
- * ipcp_clear_addrs() - clear the interface addresses, routes,
- * proxy arp entries, etc.
- */
-static void
-ipcp_clear_addrs(unit)
- int unit;
-{
- u_int32_t ouraddr, hisaddr;
-
- ouraddr = ipcp_gotoptions[unit].ouraddr;
- hisaddr = ipcp_hisoptions[unit].hisaddr;
- if (proxy_arp_set[unit]) {
- cifproxyarp(unit, hisaddr);
- proxy_arp_set[unit] = 0;
- }
- if (default_route_set[unit]) {
- cifdefaultroute(unit, ouraddr, hisaddr);
- default_route_set[unit] = 0;
- }
- cifaddr(unit, ouraddr, hisaddr);
-}
-
-
-/*
- * ipcp_finished - possibly shut down the lower layers.
- */
-static void
-ipcp_finished(f)
- fsm *f;
-{
- np_finished(f->unit, PPP_IP);
-}
-
-
-/*
- * ipcp_script - Execute a script with arguments
- * interface-name tty-name speed local-IP remote-IP.
- */
-static void
-ipcp_script(f, script)
- fsm *f;
- char *script;
-{
- char strspeed[32], strlocal[32], strremote[32];
- char *argv[8];
-
- sprintf(strspeed, "%d", baud_rate);
- strcpy(strlocal, ip_ntoa(ipcp_gotoptions[f->unit].ouraddr));
- strcpy(strremote, ip_ntoa(ipcp_hisoptions[f->unit].hisaddr));
-
- argv[0] = script;
- argv[1] = ifname;
- argv[2] = devnam;
- argv[3] = strspeed;
- argv[4] = strlocal;
- argv[5] = strremote;
- argv[6] = ipparam;
- argv[7] = NULL;
- run_program(script, argv, 0);
-}
-
-/*
- * ipcp_printpkt - print the contents of an IPCP packet.
- */
-static char *ipcp_codenames[] = {
- "ConfReq", "ConfAck", "ConfNak", "ConfRej",
- "TermReq", "TermAck", "CodeRej"
-};
-
-static int
-ipcp_printpkt(p, plen, printer, arg)
- u_char *p;
- int plen;
- void (*printer)(void *, char *, ...);
- void *arg;
-{
- int code, id, len, olen;
- u_char *pstart, *optend;
- u_short cishort;
- u_int32_t cilong;
-
- if (plen < HEADERLEN)
- return 0;
- pstart = p;
- GETCHAR(code, p);
- GETCHAR(id, p);
- GETSHORT(len, p);
- if (len < HEADERLEN || len > plen)
- return 0;
-
- if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))
- printer(arg, " %s", ipcp_codenames[code-1]);
- else
- printer(arg, " code=0x%x", code);
- printer(arg, " id=0x%x", id);
- len -= HEADERLEN;
- switch (code) {
- case CONFREQ:
- case CONFACK:
- case CONFNAK:
- case CONFREJ:
- /* print option list */
- while (len >= 2) {
- GETCHAR(code, p);
- GETCHAR(olen, p);
- p -= 2;
- if (olen < 2 || olen > len) {
- break;
- }
- printer(arg, " <");
- len -= olen;
- optend = p + olen;
- switch (code) {
- case CI_ADDRS:
- if (olen == CILEN_ADDRS) {
- p += 2;
- GETLONG(cilong, p);
- printer(arg, "addrs %I", htonl(cilong));
- GETLONG(cilong, p);
- printer(arg, " %I", htonl(cilong));
- }
- break;
- case CI_COMPRESSTYPE:
- if (olen >= CILEN_COMPRESS) {
- p += 2;
- GETSHORT(cishort, p);
- printer(arg, "compress ");
- switch (cishort) {
- case IPCP_VJ_COMP:
- printer(arg, "VJ");
- break;
- case IPCP_VJ_COMP_OLD:
- printer(arg, "old-VJ");
- break;
- default:
- printer(arg, "0x%x", cishort);
- }
- }
- break;
- case CI_ADDR:
- if (olen == CILEN_ADDR) {
- p += 2;
- GETLONG(cilong, p);
- printer(arg, "addr %I", htonl(cilong));
- }
- break;
- case CI_MS_DNS1:
- case CI_MS_DNS2:
- p += 2;
- GETLONG(cilong, p);
- printer(arg, "ms-dns %I", htonl(cilong));
- break;
- case CI_MS_WINS1:
- case CI_MS_WINS2:
- p += 2;
- GETLONG(cilong, p);
- printer(arg, "ms-wins %I", htonl(cilong));
- break;
- }
- while (p < optend) {
- GETCHAR(code, p);
- printer(arg, " %.2x", code);
- }
- printer(arg, ">");
- }
- break;
-
- case TERMACK:
- case TERMREQ:
- if (len > 0 && *p >= ' ' && *p < 0x7f) {
- printer(arg, " ");
- print_string(p, len, printer, arg);
- p += len;
- len = 0;
- }
- break;
- }
-
- /* print the rest of the bytes in the packet */
- for (; len > 0; --len) {
- GETCHAR(code, p);
- printer(arg, " %.2x", code);
- }
-
- return p - pstart;
-}
-
-/*
- * ip_active_pkt - see if this IP packet is worth bringing the link up for.
- * We don't bring the link up for IP fragments or for TCP FIN packets
- * with no data.
- */
-#define IP_HDRLEN 20 /* bytes */
-#define IP_OFFMASK 0x1fff
-#define IPPROTO_TCP 6
-#define TCP_HDRLEN 20
-#define TH_FIN 0x01
-
-/*
- * We use these macros because the IP header may be at an odd address,
- * and some compilers might use word loads to get th_off or ip_hl.
- */
-
-#define net_short(x) (((x)[0] << 8) + (x)[1])
-#define get_iphl(x) (((unsigned char *)(x))[0] & 0xF)
-#define get_ipoff(x) net_short((unsigned char *)(x) + 6)
-#define get_ipproto(x) (((unsigned char *)(x))[9])
-#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4)
-#define get_tcpflags(x) (((unsigned char *)(x))[13])
-
-static int
-ip_active_pkt(pkt, len)
- u_char *pkt;
- int len;
-{
- u_char *tcp;
- int hlen;
-
- len -= PPP_HDRLEN;
- pkt += PPP_HDRLEN;
- if (len < IP_HDRLEN)
- return 0;
- if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
- return 0;
- if (get_ipproto(pkt) != IPPROTO_TCP)
- return 1;
- hlen = get_iphl(pkt) * 4;
- if (len < hlen + TCP_HDRLEN)
- return 0;
- tcp = pkt + hlen;
- if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
- return 0;
- return 1;
-}
diff --git a/usr.sbin/pppd/ipcp.h b/usr.sbin/pppd/ipcp.h
deleted file mode 100644
index 73f8b7e..0000000
--- a/usr.sbin/pppd/ipcp.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * ipcp.h - IP Control Protocol definitions.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
- */
-
-/*
- * Options.
- */
-#define CI_ADDRS 1 /* IP Addresses */
-#define CI_COMPRESSTYPE 2 /* Compression Type */
-#define CI_ADDR 3
-
-#define CI_MS_DNS1 129 /* Primary DNS value */
-#define CI_MS_WINS1 130 /* Primary WINS value */
-#define CI_MS_DNS2 131 /* Secondary DNS value */
-#define CI_MS_WINS2 132 /* Secondary WINS value */
-
-#define MAX_STATES 16 /* from slcompress.h */
-
-#define IPCP_VJMODE_OLD 1 /* "old" mode (option # = 0x0037) */
-#define IPCP_VJMODE_RFC1172 2 /* "old-rfc"mode (option # = 0x002d) */
-#define IPCP_VJMODE_RFC1332 3 /* "new-rfc"mode (option # = 0x002d, */
- /* maxslot and slot number compression) */
-
-#define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/
-#define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */
- /* compression option*/
-
-typedef struct ipcp_options {
- int neg_addr : 1; /* Negotiate IP Address? */
- int old_addrs : 1; /* Use old (IP-Addresses) option? */
- int req_addr : 1; /* Ask peer to send IP address? */
- int default_route : 1; /* Assign default route through interface? */
- int proxy_arp : 1; /* Make proxy ARP entry for peer? */
- int neg_vj : 1; /* Van Jacobson Compression? */
- int old_vj : 1; /* use old (short) form of VJ option? */
- int accept_local : 1; /* accept peer's value for ouraddr */
- int accept_remote : 1; /* accept peer's value for hisaddr */
- u_short vj_protocol; /* protocol value to use in VJ option */
- u_char maxslotindex, cflag; /* values for RFC1332 VJ compression neg. */
- u_int32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */
- u_int32_t dnsaddr[2]; /* Primary and secondary MS DNS entries */
- u_int32_t winsaddr[2]; /* Primary and secondary MS WINS entries */
-} ipcp_options;
-
-extern fsm ipcp_fsm[];
-extern ipcp_options ipcp_wantoptions[];
-extern ipcp_options ipcp_gotoptions[];
-extern ipcp_options ipcp_allowoptions[];
-extern ipcp_options ipcp_hisoptions[];
-
-char *ip_ntoa(u_int32_t);
-
-extern struct protent ipcp_protent;
diff --git a/usr.sbin/pppd/ipv6cp.c b/usr.sbin/pppd/ipv6cp.c
deleted file mode 100644
index 27ba3a9..0000000
--- a/usr.sbin/pppd/ipv6cp.c
+++ /dev/null
@@ -1,1422 +0,0 @@
-/*
- ipv6cp.c - PPP IPV6 Control Protocol.
- Copyright (C) 1999 Tommi Komulainen <Tommi.Komulainen@iki.fi>
-
- Redistribution and use in source and binary forms are permitted
- provided that the above copyright notice and this paragraph are
- duplicated in all such forms. The name of the author may not be
- used to endorse or promote products derived from this software
- without specific prior written permission.
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-*/
-
-/* Original version, based on RFC2023 :
-
- Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt,
- Alain.Durand@imag.fr, IMAG,
- Jean-Luc.Richier@imag.fr, IMAG-LSR.
-
- Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE,
- Alain.Durand@imag.fr, IMAG,
- Jean-Luc.Richier@imag.fr, IMAG-LSR.
-
- Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt
- Économique ayant pour membres BULL S.A. et l'INRIA).
-
- Ce logiciel informatique est disponible aux conditions
- usuelles dans la recherche, c'est-à-dire qu'il peut
- être utilisé, copié, modifié, distribué à l'unique
- condition que ce texte soit conservé afin que
- l'origine de ce logiciel soit reconnue.
-
- Le nom de l'Institut National de Recherche en Informatique
- et en Automatique (INRIA), de l'IMAG, ou d'une personne morale
- ou physique ayant participé à l'élaboration de ce logiciel ne peut
- être utilisé sans son accord préalable explicite.
-
- Ce logiciel est fourni tel quel sans aucune garantie,
- support ou responsabilité d'aucune sorte.
- Ce logiciel est dérivé de sources d'origine
- "University of California at Berkeley" et
- "Digital Equipment Corporation" couvertes par des copyrights.
-
- L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG)
- est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National
- Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant
- sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR).
-
- This work has been done in the context of GIE DYADE (joint R & D venture
- between BULL S.A. and INRIA).
-
- This software is available with usual "research" terms
- with the aim of retain credits of the software.
- Permission to use, copy, modify and distribute this software for any
- purpose and without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies,
- and the name of INRIA, IMAG, or any contributor not be used in advertising
- or publicity pertaining to this material without the prior explicit
- permission. The software is provided "as is" without any
- warranties, support or liabilities of any kind.
- This software is derived from source code from
- "University of California at Berkeley" and
- "Digital Equipment Corporation" protected by copyrights.
-
- Grenoble's Institute of Computer Science and Applied Mathematics (IMAG)
- is a federation of seven research units funded by the CNRS, National
- Polytechnic Institute of Grenoble and University Joseph Fourier.
- The research unit in Software, Systems, Networks (LSR) is member of IMAG.
-*/
-
-/*
- * Derived from :
- *
- *
- * ipcp.c - PPP IP Control Protocol.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $Id: ipv6cp.c,v 1.7 1999/10/08 01:08:18 masputra Exp $
- */
-
-#ifndef lint
-#define RCSID "$Id: ipv6cp.c,v 1.7 1999/10/08 01:08:18 masputra Exp $"
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * TODO:
- *
- * Proxy Neighbour Discovery.
- *
- * Better defines for selecting the ordering of
- * interface up / set address. (currently checks for __linux__,
- * since SVR4 && (SNI || __USLC__) didn't work properly)
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-#include "pppd.h"
-#include "fsm.h"
-#include "ipcp.h"
-#include "ipv6cp.h"
-#include "magic.h"
-#include "pathnames.h"
-
-#define s6_addr32 __u6_addr.__u6_addr32
-
-#ifdef RCSID
-static const char rcsid[] = RCSID;
-#endif
-
-/* global vars */
-ipv6cp_options ipv6cp_wantoptions[NUM_PPP]; /* Options that we want to request */
-ipv6cp_options ipv6cp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
-ipv6cp_options ipv6cp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
-ipv6cp_options ipv6cp_hisoptions[NUM_PPP]; /* Options that we ack'd */
-int no_ifaceid_neg = 0;
-
-/* local vars */
-static int ipv6cp_is_up;
-
-/*
- * Callbacks for fsm code. (CI = Configuration Information)
- */
-static void ipv6cp_resetci(fsm *); /* Reset our CI */
-static int ipv6cp_cilen(fsm *); /* Return length of our CI */
-static void ipv6cp_addci(fsm *, u_char *, int *); /* Add our CI */
-static int ipv6cp_ackci(fsm *, u_char *, int); /* Peer ack'd our CI */
-static int ipv6cp_nakci(fsm *, u_char *, int); /* Peer nak'd our CI */
-static int ipv6cp_rejci(fsm *, u_char *, int); /* Peer rej'd our CI */
-static int ipv6cp_reqci(fsm *, u_char *, int *, int); /* Rcv CI */
-static void ipv6cp_up(fsm *); /* We're UP */
-static void ipv6cp_down(fsm *); /* We're DOWN */
-static void ipv6cp_finished(fsm *); /* Don't need lower layer */
-
-fsm ipv6cp_fsm[NUM_PPP]; /* IPV6CP fsm structure */
-
-static fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */
- ipv6cp_resetci, /* Reset our Configuration Information */
- ipv6cp_cilen, /* Length of our Configuration Information */
- ipv6cp_addci, /* Add our Configuration Information */
- ipv6cp_ackci, /* ACK our Configuration Information */
- ipv6cp_nakci, /* NAK our Configuration Information */
- ipv6cp_rejci, /* Reject our Configuration Information */
- ipv6cp_reqci, /* Request peer's Configuration Information */
- ipv6cp_up, /* Called when fsm reaches OPENED state */
- ipv6cp_down, /* Called when fsm leaves OPENED state */
- NULL, /* Called when we want the lower layer up */
- ipv6cp_finished, /* Called when we want the lower layer down */
- NULL, /* Called when Protocol-Reject received */
- NULL, /* Retransmission is necessary */
- NULL, /* Called to handle protocol-specific codes */
- "IPV6CP" /* String name of protocol */
-};
-
-
-/*
- * Protocol entry points from main code.
- */
-static void ipv6cp_init(int);
-static void ipv6cp_open(int);
-static void ipv6cp_close(int, char *);
-static void ipv6cp_lowerup(int);
-static void ipv6cp_lowerdown(int);
-static void ipv6cp_input(int, u_char *, int);
-static void ipv6cp_protrej(int);
-static int ipv6cp_printpkt(u_char *, int,
- void (*)(void *, char *, ...), void *);
-static void ipv6_check_options(void);
-static int ipv6_demand_conf(int);
-static int ipv6_active_pkt(u_char *, int);
-
-struct protent ipv6cp_protent = {
- PPP_IPV6CP,
- ipv6cp_init,
- ipv6cp_input,
- ipv6cp_protrej,
- ipv6cp_lowerup,
- ipv6cp_lowerdown,
- ipv6cp_open,
- ipv6cp_close,
- ipv6cp_printpkt,
- NULL,
- 0,
- "IPV6CP",
- ipv6_check_options,
- ipv6_demand_conf,
- ipv6_active_pkt
-};
-
-static void ipv6cp_clear_addrs(int, eui64_t, eui64_t);
-static void ipv6cp_script(char *);
-
-/*
- * Lengths of configuration options.
- */
-#define CILEN_VOID 2
-#define CILEN_COMPRESS 4 /* length for RFC2023 compress opt. */
-#define CILEN_IFACEID 10 /* RFC2472, interface identifier */
-
-#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
- (x) == CONFNAK ? "NAK" : "REJ")
-
-/*
- * This state variable is used to ensure that we don't
- * run an ipcp-up/down script while one is already running.
- */
-static enum script_state {
- s_down,
- s_up,
-} ipv6cp_script_state;
-
-/*
- * setifaceid - set the interface identifiers manually
- */
-int
-setifaceid(argv)
- char **argv;
-{
- char *comma, *arg;
- ipv6cp_options *wo = &ipv6cp_wantoptions[0];
- struct in6_addr addr;
-
-#define VALIDID(a) ( (((a).s6_addr32[0] == 0) && ((a).s6_addr32[1] == 0)) && \
- (((a).s6_addr32[2] != 0) || ((a).s6_addr32[3] != 0)) )
-
- arg = *argv;
- if ((comma = strchr(arg, ',')) == NULL)
- comma = arg + strlen(arg);
-
- /*
- * If comma first character, then no local identifier
- */
- if (comma != arg) {
- *comma = '\0';
-
- if (inet_pton(AF_INET6, arg, &addr) == 0 || !VALIDID(addr)) {
- option_error("Illegal interface identifier (local): %s", arg);
- return 0;
- }
-
- eui64_copy(addr.s6_addr32[2], wo->ourid);
- wo->opt_local = 1;
- *comma = ',';
- }
-
- /*
- * If comma last character, the no remote identifier
- */
- if (*comma != 0 && *++comma != '\0') {
- if (inet_pton(AF_INET6, comma, &addr) == 0 || !VALIDID(addr)) {
- option_error("Illegal interface identifier (remote): %s", comma);
- return 0;
- }
- eui64_copy(addr.s6_addr32[2], wo->hisid);
- wo->opt_remote = 1;
- }
-
- ipv6cp_protent.enabled_flag = 1;
- return 1;
-}
-
-/*
- * Make a string representation of a network address.
- */
-char *
-llv6_ntoa(ifaceid)
- eui64_t ifaceid;
-{
- static char b[64];
-
- sprintf(b, "fe80::%s", eui64_ntoa(ifaceid));
- return b;
-}
-
-
-/*
- * ipv6cp_init - Initialize IPV6CP.
- */
-static void
-ipv6cp_init(unit)
- int unit;
-{
- fsm *f = &ipv6cp_fsm[unit];
- ipv6cp_options *wo = &ipv6cp_wantoptions[unit];
- ipv6cp_options *ao = &ipv6cp_allowoptions[unit];
-
- f->unit = unit;
- f->protocol = PPP_IPV6CP;
- f->callbacks = &ipv6cp_callbacks;
- fsm_init(&ipv6cp_fsm[unit]);
-
- memset(wo, 0, sizeof(*wo));
- memset(ao, 0, sizeof(*ao));
-
- wo->accept_local = 1;
- wo->neg_ifaceid = 1;
- ao->neg_ifaceid = 1;
-
-#ifdef IPV6CP_COMP
- wo->neg_vj = 1;
- ao->neg_vj = 1;
- wo->vj_protocol = IPV6CP_COMP;
-#endif
-
-}
-
-
-/*
- * ipv6cp_open - IPV6CP is allowed to come up.
- */
-static void
-ipv6cp_open(unit)
- int unit;
-{
- fsm_open(&ipv6cp_fsm[unit]);
-}
-
-
-/*
- * ipv6cp_close - Take IPV6CP down.
- */
-static void
-ipv6cp_close(unit, reason)
- int unit;
- char *reason;
-{
- fsm_close(&ipv6cp_fsm[unit], reason);
-}
-
-
-/*
- * ipv6cp_lowerup - The lower layer is up.
- */
-static void
-ipv6cp_lowerup(unit)
- int unit;
-{
- fsm_lowerup(&ipv6cp_fsm[unit]);
-}
-
-
-/*
- * ipv6cp_lowerdown - The lower layer is down.
- */
-static void
-ipv6cp_lowerdown(unit)
- int unit;
-{
- fsm_lowerdown(&ipv6cp_fsm[unit]);
-}
-
-
-/*
- * ipv6cp_input - Input IPV6CP packet.
- */
-static void
-ipv6cp_input(unit, p, len)
- int unit;
- u_char *p;
- int len;
-{
- fsm_input(&ipv6cp_fsm[unit], p, len);
-}
-
-
-/*
- * ipv6cp_protrej - A Protocol-Reject was received for IPV6CP.
- *
- * Pretend the lower layer went down, so we shut up.
- */
-static void
-ipv6cp_protrej(unit)
- int unit;
-{
- fsm_lowerdown(&ipv6cp_fsm[unit]);
-}
-
-
-/*
- * ipv6cp_resetci - Reset our CI.
- */
-static void
-ipv6cp_resetci(f)
- fsm *f;
-{
- ipv6cp_options *wo = &ipv6cp_wantoptions[f->unit];
- ipv6cp_options *go = &ipv6cp_gotoptions[f->unit];
-
- wo->req_ifaceid = wo->neg_ifaceid && ipv6cp_allowoptions[f->unit].neg_ifaceid;
-
- if (!wo->opt_local) {
- eui64_magic_nz(wo->ourid);
- }
-
- *go = *wo;
- eui64_zero(go->hisid); /* last proposed interface identifier */
-}
-
-
-/*
- * ipv6cp_cilen - Return length of our CI.
- */
-static int
-ipv6cp_cilen(f)
- fsm *f;
-{
- ipv6cp_options *go = &ipv6cp_gotoptions[f->unit];
-
-#define LENCIVJ(neg) (neg ? CILEN_COMPRESS : 0)
-#define LENCIIFACEID(neg) (neg ? CILEN_IFACEID : 0)
-
- return (LENCIIFACEID(go->neg_ifaceid) +
- LENCIVJ(go->neg_vj));
-}
-
-
-/*
- * ipv6cp_addci - Add our desired CIs to a packet.
- */
-static void
-ipv6cp_addci(f, ucp, lenp)
- fsm *f;
- u_char *ucp;
- int *lenp;
-{
- ipv6cp_options *go = &ipv6cp_gotoptions[f->unit];
- int len = *lenp;
-
-#define ADDCIVJ(opt, neg, val) \
- if (neg) { \
- int vjlen = CILEN_COMPRESS; \
- if (len >= vjlen) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(vjlen, ucp); \
- PUTSHORT(val, ucp); \
- len -= vjlen; \
- } else \
- neg = 0; \
- }
-
-#define ADDCIIFACEID(opt, neg, val1) \
- if (neg) { \
- int idlen = CILEN_IFACEID; \
- if (len >= idlen) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(idlen, ucp); \
- eui64_put(val1, ucp); \
- len -= idlen; \
- } else \
- neg = 0; \
- }
-
- ADDCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid);
-
- ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol);
-
- *lenp -= len;
-}
-
-
-/*
- * ipv6cp_ackci - Ack our CIs.
- *
- * Returns:
- * 0 - Ack was bad.
- * 1 - Ack was good.
- */
-static int
-ipv6cp_ackci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- ipv6cp_options *go = &ipv6cp_gotoptions[f->unit];
- u_short cilen, citype, cishort;
- eui64_t ifaceid;
-
- /*
- * CIs must be in exactly the same order that we sent...
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
-
-#define ACKCIVJ(opt, neg, val) \
- if (neg) { \
- int vjlen = CILEN_COMPRESS; \
- if ((len -= vjlen) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != vjlen || \
- citype != opt) \
- goto bad; \
- GETSHORT(cishort, p); \
- if (cishort != val) \
- goto bad; \
- }
-
-#define ACKCIIFACEID(opt, neg, val1) \
- if (neg) { \
- int idlen = CILEN_IFACEID; \
- if ((len -= idlen) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != idlen || \
- citype != opt) \
- goto bad; \
- eui64_get(ifaceid, p); \
- if (! eui64_equals(val1, ifaceid)) \
- goto bad; \
- }
-
- ACKCIIFACEID(CI_IFACEID, go->neg_ifaceid, go->ourid);
-
- ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol);
-
- /*
- * If there are any remaining CIs, then this packet is bad.
- */
- if (len != 0)
- goto bad;
- return (1);
-
-bad:
- IPV6CPDEBUG(("ipv6cp_ackci: received bad Ack!"));
- return (0);
-}
-
-/*
- * ipv6cp_nakci - Peer has sent a NAK for some of our CIs.
- * This should not modify any state if the Nak is bad
- * or if IPV6CP is in the OPENED state.
- *
- * Returns:
- * 0 - Nak was bad.
- * 1 - Nak was good.
- */
-static int
-ipv6cp_nakci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- ipv6cp_options *go = &ipv6cp_gotoptions[f->unit];
- u_char citype, cilen, *next;
- u_short cishort;
- eui64_t ifaceid;
- ipv6cp_options no; /* options we've seen Naks for */
- ipv6cp_options try; /* options to request next time */
-
- BZERO(&no, sizeof(no));
- try = *go;
-
- /*
- * Any Nak'd CIs must be in exactly the same order that we sent.
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
-#define NAKCIIFACEID(opt, neg, code) \
- if (go->neg && \
- len >= (cilen = CILEN_IFACEID) && \
- p[1] == cilen && \
- p[0] == opt) { \
- len -= cilen; \
- INCPTR(2, p); \
- eui64_get(ifaceid, p); \
- no.neg = 1; \
- code \
- }
-
-#define NAKCIVJ(opt, neg, code) \
- if (go->neg && \
- ((cilen = p[1]) == CILEN_COMPRESS) && \
- len >= cilen && \
- p[0] == opt) { \
- len -= cilen; \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- no.neg = 1; \
- code \
- }
-
- /*
- * Accept the peer's idea of {our,his} interface identifier, if different
- * from our idea, only if the accept_{local,remote} flag is set.
- */
- NAKCIIFACEID(CI_IFACEID, neg_ifaceid,
- if (go->accept_local) {
- while (eui64_iszero(ifaceid) ||
- eui64_equals(ifaceid, go->hisid)) /* bad luck */
- eui64_magic(ifaceid);
- try.ourid = ifaceid;
- IPV6CPDEBUG(("local LL address %s", llv6_ntoa(ifaceid)));
- }
- );
-
-#ifdef IPV6CP_COMP
- NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
- {
- if (cishort == IPV6CP_COMP) {
- try.vj_protocol = cishort;
- } else {
- try.neg_vj = 0;
- }
- }
- );
-#else
- NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
- {
- try.neg_vj = 0;
- }
- );
-#endif
-
- /*
- * There may be remaining CIs, if the peer is requesting negotiation
- * on an option that we didn't include in our request packet.
- * If they want to negotiate about interface identifier, we comply.
- * If they want us to ask for compression, we refuse.
- */
- while (len > CILEN_VOID) {
- GETCHAR(citype, p);
- GETCHAR(cilen, p);
- if( (len -= cilen) < 0 )
- goto bad;
- next = p + cilen - 2;
-
- switch (citype) {
- case CI_COMPRESSTYPE:
- if (go->neg_vj || no.neg_vj ||
- (cilen != CILEN_COMPRESS))
- goto bad;
- no.neg_vj = 1;
- break;
- case CI_IFACEID:
- if (go->neg_ifaceid || no.neg_ifaceid || cilen != CILEN_IFACEID)
- goto bad;
- try.neg_ifaceid = 1;
- eui64_get(ifaceid, p);
- if (go->accept_local) {
- while (eui64_iszero(ifaceid) ||
- eui64_equals(ifaceid, go->hisid)) /* bad luck */
- eui64_magic(ifaceid);
- try.ourid = ifaceid;
- }
- no.neg_ifaceid = 1;
- break;
- }
- p = next;
- }
-
- /* If there is still anything left, this packet is bad. */
- if (len != 0)
- goto bad;
-
- /*
- * OK, the Nak is good. Now we can update state.
- */
- if (f->state != OPENED)
- *go = try;
-
- return 1;
-
-bad:
- IPV6CPDEBUG(("ipv6cp_nakci: received bad Nak!"));
- return 0;
-}
-
-
-/*
- * ipv6cp_rejci - Reject some of our CIs.
- */
-static int
-ipv6cp_rejci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- ipv6cp_options *go = &ipv6cp_gotoptions[f->unit];
- u_char cilen;
- u_short cishort;
- eui64_t ifaceid;
- ipv6cp_options try; /* options to request next time */
-
- try = *go;
- /*
- * Any Rejected CIs must be in exactly the same order that we sent.
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
-#define REJCIIFACEID(opt, neg, val1) \
- if (go->neg && \
- len >= (cilen = CILEN_IFACEID) && \
- p[1] == cilen && \
- p[0] == opt) { \
- len -= cilen; \
- INCPTR(2, p); \
- eui64_get(ifaceid, p); \
- /* Check rejected value. */ \
- if (! eui64_equals(ifaceid, val1)) \
- goto bad; \
- try.neg = 0; \
- }
-
-#define REJCIVJ(opt, neg, val) \
- if (go->neg && \
- p[1] == CILEN_COMPRESS && \
- len >= p[1] && \
- p[0] == opt) { \
- len -= p[1]; \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- /* Check rejected value. */ \
- if (cishort != val) \
- goto bad; \
- try.neg = 0; \
- }
-
- REJCIIFACEID(CI_IFACEID, neg_ifaceid, go->ourid);
-
- REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol);
-
- /*
- * If there are any remaining CIs, then this packet is bad.
- */
- if (len != 0)
- goto bad;
- /*
- * Now we can update state.
- */
- if (f->state != OPENED)
- *go = try;
- return 1;
-
-bad:
- IPV6CPDEBUG(("ipv6cp_rejci: received bad Reject!"));
- return 0;
-}
-
-
-/*
- * ipv6cp_reqci - Check the peer's requested CIs and send appropriate response.
- *
- * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
- * appropriately. If reject_if_disagree is non-zero, doesn't return
- * CONFNAK; returns CONFREJ if it can't return CONFACK.
- */
-static int
-ipv6cp_reqci(f, inp, len, reject_if_disagree)
- fsm *f;
- u_char *inp; /* Requested CIs */
- int *len; /* Length of requested CIs */
- int reject_if_disagree;
-{
- ipv6cp_options *wo = &ipv6cp_wantoptions[f->unit];
- ipv6cp_options *ho = &ipv6cp_hisoptions[f->unit];
- ipv6cp_options *ao = &ipv6cp_allowoptions[f->unit];
- ipv6cp_options *go = &ipv6cp_gotoptions[f->unit];
- u_char *cip, *next; /* Pointer to current and next CIs */
- u_short cilen, citype; /* Parsed len, type */
- u_short cishort; /* Parsed short value */
- eui64_t ifaceid; /* Parsed interface identifier */
- int rc = CONFACK; /* Final packet return code */
- int orc; /* Individual option return code */
- u_char *p; /* Pointer to next char to parse */
- u_char *ucp = inp; /* Pointer to current output char */
- int l = *len; /* Length left */
-
- /*
- * Reset all his options.
- */
- BZERO(ho, sizeof(*ho));
-
- /*
- * Process all his options.
- */
- next = inp;
- while (l) {
- orc = CONFACK; /* Assume success */
- cip = p = next; /* Remember begining of CI */
- if (l < 2 || /* Not enough data for CI header or */
- p[1] < 2 || /* CI length too small or */
- p[1] > l) { /* CI length too big? */
- IPV6CPDEBUG(("ipv6cp_reqci: bad CI length!"));
- orc = CONFREJ; /* Reject bad CI */
- cilen = l; /* Reject till end of packet */
- l = 0; /* Don't loop again */
- goto endswitch;
- }
- GETCHAR(citype, p); /* Parse CI type */
- GETCHAR(cilen, p); /* Parse CI length */
- l -= cilen; /* Adjust remaining length */
- next += cilen; /* Step to next CI */
-
- switch (citype) { /* Check CI type */
- case CI_IFACEID:
- IPV6CPDEBUG(("ipv6cp: received interface identifier "));
-
- if (!ao->neg_ifaceid ||
- cilen != CILEN_IFACEID) { /* Check CI length */
- orc = CONFREJ; /* Reject CI */
- break;
- }
-
- /*
- * If he has no interface identifier, or if we both have same
- * identifier then NAK it with new idea.
- * In particular, if we don't know his identifier, but he does,
- * then accept it.
- */
- eui64_get(ifaceid, p);
- IPV6CPDEBUG(("(%s)", llv6_ntoa(ifaceid)));
- if (eui64_iszero(ifaceid) && eui64_iszero(go->ourid)) {
- orc = CONFREJ; /* Reject CI */
- break;
- }
- if (!eui64_iszero(wo->hisid) &&
- !eui64_equals(ifaceid, wo->hisid) &&
- eui64_iszero(go->hisid)) {
-
- orc = CONFNAK;
- ifaceid = wo->hisid;
- go->hisid = ifaceid;
- DECPTR(sizeof(ifaceid), p);
- eui64_put(ifaceid, p);
- } else
- if (eui64_iszero(ifaceid) || eui64_equals(ifaceid, go->ourid)) {
- orc = CONFNAK;
- if (eui64_iszero(go->hisid)) /* first time, try option */
- ifaceid = wo->hisid;
- while (eui64_iszero(ifaceid) ||
- eui64_equals(ifaceid, go->ourid)) /* bad luck */
- eui64_magic(ifaceid);
- go->hisid = ifaceid;
- DECPTR(sizeof(ifaceid), p);
- eui64_put(ifaceid, p);
- }
-
- ho->neg_ifaceid = 1;
- ho->hisid = ifaceid;
- break;
-
- case CI_COMPRESSTYPE:
- IPV6CPDEBUG(("ipv6cp: received COMPRESSTYPE "));
- if (!ao->neg_vj ||
- (cilen != CILEN_COMPRESS)) {
- orc = CONFREJ;
- break;
- }
- GETSHORT(cishort, p);
- IPV6CPDEBUG(("(%d)", cishort));
-
-#ifdef IPV6CP_COMP
- if (!(cishort == IPV6CP_COMP)) {
- orc = CONFREJ;
- break;
- }
-#else
- orc = CONFREJ;
- break;
-#endif
-
- ho->neg_vj = 1;
- ho->vj_protocol = cishort;
- break;
-
- default:
- orc = CONFREJ;
- break;
- }
-
-endswitch:
- IPV6CPDEBUG((" (%s)\n", CODENAME(orc)));
-
- if (orc == CONFACK && /* Good CI */
- rc != CONFACK) /* but prior CI wasnt? */
- continue; /* Don't send this one */
-
- if (orc == CONFNAK) { /* Nak this CI? */
- if (reject_if_disagree) /* Getting fed up with sending NAKs? */
- orc = CONFREJ; /* Get tough if so */
- else {
- if (rc == CONFREJ) /* Rejecting prior CI? */
- continue; /* Don't send this one */
- if (rc == CONFACK) { /* Ack'd all prior CIs? */
- rc = CONFNAK; /* Not anymore... */
- ucp = inp; /* Backup */
- }
- }
- }
-
- if (orc == CONFREJ && /* Reject this CI */
- rc != CONFREJ) { /* but no prior ones? */
- rc = CONFREJ;
- ucp = inp; /* Backup */
- }
-
- /* Need to move CI? */
- if (ucp != cip)
- BCOPY(cip, ucp, cilen); /* Move it */
-
- /* Update output pointer */
- INCPTR(cilen, ucp);
- }
-
- /*
- * If we aren't rejecting this packet, and we want to negotiate
- * their identifier and they didn't send their identifier, then we
- * send a NAK with a CI_IFACEID option appended. We assume the
- * input buffer is long enough that we can append the extra
- * option safely.
- */
- if (rc != CONFREJ && !ho->neg_ifaceid &&
- wo->req_ifaceid && !reject_if_disagree) {
- if (rc == CONFACK) {
- rc = CONFNAK;
- ucp = inp; /* reset pointer */
- wo->req_ifaceid = 0; /* don't ask again */
- }
- PUTCHAR(CI_IFACEID, ucp);
- PUTCHAR(CILEN_IFACEID, ucp);
- eui64_put(wo->hisid, ucp);
- }
-
- *len = ucp - inp; /* Compute output length */
- IPV6CPDEBUG(("ipv6cp: returning Configure-%s", CODENAME(rc)));
- return (rc); /* Return final code */
-}
-
-
-/*
- * ipv6_check_options - check that any IP-related options are OK,
- * and assign appropriate defaults.
- */
-static void
-ipv6_check_options()
-{
- ipv6cp_options *wo = &ipv6cp_wantoptions[0];
-
-#if defined(SOL2)
- /*
- * Persistent link-local id is only used when user has not explicitly
- * configure/hard-code the id
- */
- if ((wo->use_persistent) && (!wo->opt_local) && (!wo->opt_remote)) {
-
- /*
- * On systems where there are no Ethernet interfaces used, there
- * may be other ways to obtain a persistent id. Right now, it
- * will fall back to using magic [see eui64_magic] below when
- * an EUI-48 from MAC address can't be obtained. Other possibilities
- * include obtaining EEPROM serial numbers, or some other unique
- * yet persistent number. On Sparc platforms, this is possible,
- * but too bad there's no standards yet for x86 machines.
- */
- if (ether_to_eui64(&wo->ourid)) {
- wo->opt_local = 1;
- }
- }
-#endif
-
- if (!wo->opt_local) { /* init interface identifier */
- if (wo->use_ip && eui64_iszero(wo->ourid)) {
- eui64_setlo32(wo->ourid, ntohl(ipcp_wantoptions[0].ouraddr));
- if (!eui64_iszero(wo->ourid))
- wo->opt_local = 1;
- }
-
- while (eui64_iszero(wo->ourid))
- eui64_magic(wo->ourid);
- }
-
- if (!wo->opt_remote) {
- if (wo->use_ip && eui64_iszero(wo->hisid)) {
- eui64_setlo32(wo->hisid, ntohl(ipcp_wantoptions[0].hisaddr));
- if (!eui64_iszero(wo->hisid))
- wo->opt_remote = 1;
- }
- }
-
- if (demand && (eui64_iszero(wo->ourid) || eui64_iszero(wo->hisid))) {
- option_error("local/remote LL address required for demand-dialling\n");
- exit(1);
- }
-}
-
-
-/*
- * ipv6_demand_conf - configure the interface as though
- * IPV6CP were up, for use with dial-on-demand.
- */
-static int
-ipv6_demand_conf(u)
- int u;
-{
- ipv6cp_options *wo = &ipv6cp_wantoptions[u];
-
-#if defined(__linux__) || defined(SOL2) || (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
-#if defined(SOL2)
- if (!sif6up(u))
- return 0;
-#else
- if (!sifup(u))
- return 0;
-#endif /* defined(SOL2) */
-#endif
- if (!sif6addr(u, wo->ourid, wo->hisid))
- return 0;
-#if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
- if (!sifup(u))
- return 0;
-#endif
- if (!sifnpmode(u, PPP_IPV6, NPMODE_QUEUE))
- return 0;
-
- syslog(LOG_NOTICE, "ipv6_demand_conf");
- syslog(LOG_NOTICE, "local LL address %s", llv6_ntoa(wo->ourid));
- syslog(LOG_NOTICE, "remote LL address %s", llv6_ntoa(wo->hisid));
-
- return 1;
-}
-
-
-/*
- * ipv6cp_up - IPV6CP has come UP.
- *
- * Configure the IPv6 network interface appropriately and bring it up.
- */
-static void
-ipv6cp_up(f)
- fsm *f;
-{
- ipv6cp_options *ho = &ipv6cp_hisoptions[f->unit];
- ipv6cp_options *go = &ipv6cp_gotoptions[f->unit];
- ipv6cp_options *wo = &ipv6cp_wantoptions[f->unit];
-
- IPV6CPDEBUG(("ipv6cp: up"));
-
- /*
- * We must have a non-zero LL address for both ends of the link.
- */
- if (!ho->neg_ifaceid)
- ho->hisid = wo->hisid;
-
- if(!no_ifaceid_neg) {
- if (eui64_iszero(ho->hisid)) {
- syslog(LOG_ERR, "Could not determine remote LL address");
- ipv6cp_close(f->unit, "Could not determine remote LL address");
- return;
- }
- if (eui64_iszero(go->ourid)) {
- syslog(LOG_ERR, "Could not determine local LL address");
- ipv6cp_close(f->unit, "Could not determine local LL address");
- return;
- }
- if (eui64_equals(go->ourid, ho->hisid)) {
- syslog(LOG_ERR, "local and remote LL addresses are equal");
- ipv6cp_close(f->unit, "local and remote LL addresses are equal");
- return;
- }
- }
- script_setenv("LLLOCAL", llv6_ntoa(go->ourid));
- script_setenv("LLREMOTE", llv6_ntoa(ho->hisid));
-
-#ifdef IPV6CP_COMP
- /* set tcp compression */
- sif6comp(f->unit, ho->neg_vj);
-#endif
-
- /*
- * If we are doing dial-on-demand, the interface is already
- * configured, so we put out any saved-up packets, then set the
- * interface to pass IPv6 packets.
- */
- if (demand) {
- if (! eui64_equals(go->ourid, wo->ourid) ||
- ! eui64_equals(ho->hisid, wo->hisid)) {
- if (! eui64_equals(go->ourid, wo->ourid))
- warn("Local LL address changed to %s",
- llv6_ntoa(go->ourid));
- if (! eui64_equals(ho->hisid, wo->hisid))
- warn("Remote LL address changed to %s",
- llv6_ntoa(ho->hisid));
- ipv6cp_clear_addrs(f->unit, go->ourid, ho->hisid);
-
- /* Set the interface to the new addresses */
- if (!sif6addr(f->unit, go->ourid, ho->hisid)) {
- if (debug)
- warn("sif6addr failed");
- ipv6cp_close(f->unit, "Interface configuration failed");
- return;
- }
-
- }
- demand_rexmit(PPP_IPV6);
- sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS);
-
- } else {
- /*
- * Set LL addresses
- */
-#if !defined(__linux__) && !defined(SOL2) && !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
- if (!sif6addr(f->unit, go->ourid, ho->hisid)) {
- if (debug)
- warn("sif6addr failed");
- ipv6cp_close(f->unit, "Interface configuration failed");
- return;
- }
-#endif
-
- /* bring the interface up for IPv6 */
-#if defined(SOL2)
- if (!sif6up(f->unit)) {
- if (debug)
- warn("sifup failed (IPV6)");
- ipv6cp_close(f->unit, "Interface configuration failed");
- return;
- }
-#else
- if (!sifup(f->unit)) {
- if (debug)
- warn("sifup failed (IPV6)");
- ipv6cp_close(f->unit, "Interface configuration failed");
- return;
- }
-#endif /* defined(SOL2) */
-
-#if defined(__linux__) || defined(SOL2) || (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
- if (!sif6addr(f->unit, go->ourid, ho->hisid)) {
- if (debug)
- warn("sif6addr failed");
- ipv6cp_close(f->unit, "Interface configuration failed");
- return;
- }
-#endif
- sifnpmode(f->unit, PPP_IPV6, NPMODE_PASS);
-
- syslog(LOG_NOTICE, "local LL address %s", llv6_ntoa(go->ourid));
- syslog(LOG_NOTICE, "remote LL address %s", llv6_ntoa(ho->hisid));
- }
-
- np_up(f->unit, PPP_IPV6);
- ipv6cp_is_up = 1;
-
- /*
- * Execute the ipv6-up script, like this:
- * /etc/ppp/ipv6-up interface tty speed local-LL remote-LL
- */
- if (ipv6cp_script_state == s_down) {
- ipv6cp_script_state = s_up;
- ipv6cp_script(_PATH_IPV6UP);
- }
-}
-
-
-/*
- * ipv6cp_down - IPV6CP has gone DOWN.
- *
- * Take the IPv6 network interface down, clear its addresses
- * and delete routes through it.
- */
-static void
-ipv6cp_down(f)
- fsm *f;
-{
- IPV6CPDEBUG(("ipv6cp: down"));
- if (ipv6cp_is_up) {
- ipv6cp_is_up = 0;
- np_down(f->unit, PPP_IPV6);
- }
-#ifdef IPV6CP_COMP
- sif6comp(f->unit, 0);
-#endif
-
- /*
- * If we are doing dial-on-demand, set the interface
- * to queue up outgoing packets (for now).
- */
- if (demand) {
- sifnpmode(f->unit, PPP_IPV6, NPMODE_QUEUE);
- } else {
- sifnpmode(f->unit, PPP_IPV6, NPMODE_DROP);
-#if !defined(__linux__) && !(defined(SVR4) && (defined(SNI) || defined(__USLC)))
-#if defined(SOL2)
- sif6down(f->unit);
-#else
- sifdown(f->unit);
-#endif /* defined(SOL2) */
-#endif
- ipv6cp_clear_addrs(f->unit,
- ipv6cp_gotoptions[f->unit].ourid,
- ipv6cp_hisoptions[f->unit].hisid);
-#if defined(__linux__) || (defined(SVR4) && (defined(SNI) || defined(__USLC)))
- sifdown(f->unit);
-#endif
- }
-
- /* Execute the ipv6-down script */
- if (ipv6cp_script_state == s_up) {
- ipv6cp_script_state = s_down;
- ipv6cp_script(_PATH_IPV6DOWN);
- }
-}
-
-
-/*
- * ipv6cp_clear_addrs() - clear the interface addresses, routes,
- * proxy neighbour discovery entries, etc.
- */
-static void
-ipv6cp_clear_addrs(unit, ourid, hisid)
- int unit;
- eui64_t ourid;
- eui64_t hisid;
-{
- cif6addr(unit, ourid, hisid);
-}
-
-
-/*
- * ipv6cp_finished - possibly shut down the lower layers.
- */
-static void
-ipv6cp_finished(f)
- fsm *f;
-{
- np_finished(f->unit, PPP_IPV6);
-}
-
-
-/*
- * ipv6cp_script - Execute a script with arguments
- * interface-name tty-name speed local-LL remote-LL.
- */
-static void
-ipv6cp_script(script)
- char *script;
-{
- char strspeed[32], strlocal[32], strremote[32];
- char *argv[8];
-
- sprintf(strspeed, "%d", baud_rate);
- strcpy(strlocal, llv6_ntoa(ipv6cp_gotoptions[0].ourid));
- strcpy(strremote, llv6_ntoa(ipv6cp_hisoptions[0].hisid));
-
- argv[0] = script;
- argv[1] = ifname;
- argv[2] = devnam;
- argv[3] = strspeed;
- argv[4] = strlocal;
- argv[5] = strremote;
- argv[6] = ipparam;
- argv[7] = NULL;
-
- run_program(script, argv, 0);
-}
-
-/*
- * ipv6cp_printpkt - print the contents of an IPV6CP packet.
- */
-static char *ipv6cp_codenames[] = {
- "ConfReq", "ConfAck", "ConfNak", "ConfRej",
- "TermReq", "TermAck", "CodeRej"
-};
-
-static int
-ipv6cp_printpkt(p, plen, printer, arg)
- u_char *p;
- int plen;
- void (*printer)(void *, char *, ...);
- void *arg;
-{
- int code, id, len, olen;
- u_char *pstart, *optend;
- u_short cishort;
- eui64_t ifaceid;
-
- if (plen < HEADERLEN)
- return 0;
- pstart = p;
- GETCHAR(code, p);
- GETCHAR(id, p);
- GETSHORT(len, p);
- if (len < HEADERLEN || len > plen)
- return 0;
-
- if (code >= 1 && code <= sizeof(ipv6cp_codenames) / sizeof(char *))
- printer(arg, " %s", ipv6cp_codenames[code-1]);
- else
- printer(arg, " code=0x%x", code);
- printer(arg, " id=0x%x", id);
- len -= HEADERLEN;
- switch (code) {
- case CONFREQ:
- case CONFACK:
- case CONFNAK:
- case CONFREJ:
- /* print option list */
- while (len >= 2) {
- GETCHAR(code, p);
- GETCHAR(olen, p);
- p -= 2;
- if (olen < 2 || olen > len) {
- break;
- }
- printer(arg, " <");
- len -= olen;
- optend = p + olen;
- switch (code) {
- case CI_COMPRESSTYPE:
- if (olen >= CILEN_COMPRESS) {
- p += 2;
- GETSHORT(cishort, p);
- printer(arg, "compress ");
- printer(arg, "0x%x", cishort);
- }
- break;
- case CI_IFACEID:
- if (olen == CILEN_IFACEID) {
- p += 2;
- eui64_get(ifaceid, p);
- printer(arg, "addr %s", llv6_ntoa(ifaceid));
- }
- break;
- }
- while (p < optend) {
- GETCHAR(code, p);
- printer(arg, " %.2x", code);
- }
- printer(arg, ">");
- }
- break;
-
- case TERMACK:
- case TERMREQ:
- if (len > 0 && *p >= ' ' && *p < 0x7f) {
- printer(arg, " ");
- print_string(p, len, printer, arg);
- p += len;
- len = 0;
- }
- break;
- }
-
- /* print the rest of the bytes in the packet */
- for (; len > 0; --len) {
- GETCHAR(code, p);
- printer(arg, " %.2x", code);
- }
-
- return p - pstart;
-}
-
-/*
- * ipv6_active_pkt - see if this IP packet is worth bringing the link up for.
- * We don't bring the link up for IP fragments or for TCP FIN packets
- * with no data.
- */
-#define IP6_HDRLEN 40 /* bytes */
-#define IP6_NHDR_FRAG 44 /* fragment IPv6 header */
-#define IPPROTO_TCP 6
-#define TCP_HDRLEN 20
-#define TH_FIN 0x01
-
-/*
- * We use these macros because the IP header may be at an odd address,
- * and some compilers might use word loads to get th_off or ip_hl.
- */
-
-#define get_ip6nh(x) (((unsigned char *)(x))[6])
-#define get_tcpoff(x) (((unsigned char *)(x))[12] >> 4)
-#define get_tcpflags(x) (((unsigned char *)(x))[13])
-
-static int
-ipv6_active_pkt(pkt, len)
- u_char *pkt;
- int len;
-{
- u_char *tcp;
-
- len -= PPP_HDRLEN;
- pkt += PPP_HDRLEN;
- if (len < IP6_HDRLEN)
- return 0;
- if (get_ip6nh(pkt) == IP6_NHDR_FRAG)
- return 0;
- if (get_ip6nh(pkt) != IPPROTO_TCP)
- return 1;
- if (len < IP6_HDRLEN + TCP_HDRLEN)
- return 0;
- tcp = pkt + IP6_HDRLEN;
- if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == IP6_HDRLEN + get_tcpoff(tcp) * 4)
- return 0;
- return 1;
-}
diff --git a/usr.sbin/pppd/ipv6cp.h b/usr.sbin/pppd/ipv6cp.h
deleted file mode 100644
index 39f9444..0000000
--- a/usr.sbin/pppd/ipv6cp.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- ipv6cp.h - PPP IPV6 Control Protocol.
- Copyright (C) 1999 Tommi Komulainen <Tommi.Komulainen@iki.fi>
-
- Redistribution and use in source and binary forms are permitted
- provided that the above copyright notice and this paragraph are
- duplicated in all such forms. The name of the author may not be
- used to endorse or promote products derived from this software
- without specific prior written permission.
- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
-*/
-
-/* Original version, based on RFC2023 :
-
- Copyright (c) 1995, 1996, 1997 Francis.Dupont@inria.fr, INRIA Rocquencourt,
- Alain.Durand@imag.fr, IMAG,
- Jean-Luc.Richier@imag.fr, IMAG-LSR.
-
- Copyright (c) 1998, 1999 Francis.Dupont@inria.fr, GIE DYADE,
- Alain.Durand@imag.fr, IMAG,
- Jean-Luc.Richier@imag.fr, IMAG-LSR.
-
- Ce travail a été fait au sein du GIE DYADE (Groupement d'Intérêt
- Économique ayant pour membres BULL S.A. et l'INRIA).
-
- Ce logiciel informatique est disponible aux conditions
- usuelles dans la recherche, c'est-à-dire qu'il peut
- être utilisé, copié, modifié, distribué à l'unique
- condition que ce texte soit conservé afin que
- l'origine de ce logiciel soit reconnue.
-
- Le nom de l'Institut National de Recherche en Informatique
- et en Automatique (INRIA), de l'IMAG, ou d'une personne morale
- ou physique ayant participé à l'élaboration de ce logiciel ne peut
- être utilisé sans son accord préalable explicite.
-
- Ce logiciel est fourni tel quel sans aucune garantie,
- support ou responsabilité d'aucune sorte.
- Ce logiciel est dérivé de sources d'origine
- "University of California at Berkeley" et
- "Digital Equipment Corporation" couvertes par des copyrights.
-
- L'Institut d'Informatique et de Mathématiques Appliquées de Grenoble (IMAG)
- est une fédération d'unités mixtes de recherche du CNRS, de l'Institut National
- Polytechnique de Grenoble et de l'Université Joseph Fourier regroupant
- sept laboratoires dont le laboratoire Logiciels, Systèmes, Réseaux (LSR).
-
- This work has been done in the context of GIE DYADE (joint R & D venture
- between BULL S.A. and INRIA).
-
- This software is available with usual "research" terms
- with the aim of retain credits of the software.
- Permission to use, copy, modify and distribute this software for any
- purpose and without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies,
- and the name of INRIA, IMAG, or any contributor not be used in advertising
- or publicity pertaining to this material without the prior explicit
- permission. The software is provided "as is" without any
- warranties, support or liabilities of any kind.
- This software is derived from source code from
- "University of California at Berkeley" and
- "Digital Equipment Corporation" protected by copyrights.
-
- Grenoble's Institute of Computer Science and Applied Mathematics (IMAG)
- is a federation of seven research units funded by the CNRS, National
- Polytechnic Institute of Grenoble and University Joseph Fourier.
- The research unit in Software, Systems, Networks (LSR) is member of IMAG.
-*/
-
-/*
- * Derived from :
- *
- *
- * ipcp.h - IP Control Protocol definitions.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $Id: ipv6cp.h,v 1.3 1999/09/30 19:57:45 masputra Exp $
- * $FreeBSD$
- */
-
-/*
- * Options.
- */
-#define CI_IFACEID 1 /* Interface Identifier */
-#define CI_COMPRESSTYPE 2 /* Compression Type */
-
-/* No compression types yet defined.
- *#define IPV6CP_COMP 0x004f
- */
-typedef struct ipv6cp_options {
- int neg_ifaceid; /* Negotiate interface identifier? */
- int req_ifaceid; /* Ask peer to send interface identifier? */
- int accept_local; /* accept peer's value for iface id? */
- int opt_local; /* ourtoken set by option */
- int opt_remote; /* histoken set by option */
- int use_ip; /* use IP as interface identifier */
-#if defined(SOL2)
- int use_persistent; /* use uniquely persistent value for address */
-#endif /* defined(SOL2) */
- int neg_vj; /* Van Jacobson Compression? */
- u_short vj_protocol; /* protocol value to use in VJ option */
- eui64_t ourid, hisid; /* Interface identifiers */
-} ipv6cp_options;
-
-extern fsm ipv6cp_fsm[];
-extern ipv6cp_options ipv6cp_wantoptions[];
-extern ipv6cp_options ipv6cp_gotoptions[];
-extern ipv6cp_options ipv6cp_allowoptions[];
-extern ipv6cp_options ipv6cp_hisoptions[];
-
-extern struct protent ipv6cp_protent;
-
-extern int setifaceid(char **arg);
diff --git a/usr.sbin/pppd/ipxcp.c b/usr.sbin/pppd/ipxcp.c
deleted file mode 100644
index ea7f127..0000000
--- a/usr.sbin/pppd/ipxcp.c
+++ /dev/null
@@ -1,1399 +0,0 @@
-/*
- * ipxcp.c - PPP IPX Control Protocol.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifdef IPX_CHANGE
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-/*
- * TODO:
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include "pppd.h"
-#include "fsm.h"
-#include "ipxcp.h"
-#include "pathnames.h"
-
-/* global vars */
-ipxcp_options ipxcp_wantoptions[NUM_PPP]; /* Options that we want to request */
-ipxcp_options ipxcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
-ipxcp_options ipxcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
-ipxcp_options ipxcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
-
-#define wo (&ipxcp_wantoptions[0])
-#define ao (&ipxcp_allowoptions[0])
-#define go (&ipxcp_gotoptions[0])
-#define ho (&ipxcp_hisoptions[0])
-
-/*
- * Callbacks for fsm code. (CI = Configuration Information)
- */
-static void ipxcp_resetci(fsm *); /* Reset our CI */
-static int ipxcp_cilen(fsm *); /* Return length of our CI */
-static void ipxcp_addci(fsm *, u_char *, int *); /* Add our CI */
-static int ipxcp_ackci(fsm *, u_char *, int); /* Peer ack'd our CI */
-static int ipxcp_nakci(fsm *, u_char *, int); /* Peer nak'd our CI */
-static int ipxcp_rejci(fsm *, u_char *, int); /* Peer rej'd our CI */
-static int ipxcp_reqci(fsm *, u_char *, int *, int); /* Rcv CI */
-static void ipxcp_up(fsm *); /* We're UP */
-static void ipxcp_down(fsm *); /* We're DOWN */
-static void ipxcp_script(fsm *, char *); /* Run an up/down script */
-
-fsm ipxcp_fsm[NUM_PPP]; /* IPXCP fsm structure */
-
-static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */
- ipxcp_resetci, /* Reset our Configuration Information */
- ipxcp_cilen, /* Length of our Configuration Information */
- ipxcp_addci, /* Add our Configuration Information */
- ipxcp_ackci, /* ACK our Configuration Information */
- ipxcp_nakci, /* NAK our Configuration Information */
- ipxcp_rejci, /* Reject our Configuration Information */
- ipxcp_reqci, /* Request peer's Configuration Information */
- ipxcp_up, /* Called when fsm reaches OPENED state */
- ipxcp_down, /* Called when fsm leaves OPENED state */
- NULL, /* Called when we want the lower layer up */
- NULL, /* Called when we want the lower layer down */
- NULL, /* Called when Protocol-Reject received */
- NULL, /* Retransmission is necessary */
- NULL, /* Called to handle protocol-specific codes */
- "IPXCP" /* String name of protocol */
-};
-
-/*
- * Protocol entry points.
- */
-
-static void ipxcp_init(int);
-static void ipxcp_open(int);
-static void ipxcp_close(int, char *);
-static void ipxcp_lowerup(int);
-static void ipxcp_lowerdown(int);
-static void ipxcp_input(int, u_char *, int);
-static void ipxcp_protrej(int);
-static int ipxcp_printpkt(u_char *, int,
- void (*)(void *, char *, ...), void *);
-
-struct protent ipxcp_protent = {
- PPP_IPXCP,
- ipxcp_init,
- ipxcp_input,
- ipxcp_protrej,
- ipxcp_lowerup,
- ipxcp_lowerdown,
- ipxcp_open,
- ipxcp_close,
- ipxcp_printpkt,
- NULL,
- 0,
- "IPXCP",
- NULL,
- NULL,
- NULL
-};
-
-/*
- * Lengths of configuration options.
- */
-
-#define CILEN_VOID 2
-#define CILEN_COMPLETE 2 /* length of complete option */
-#define CILEN_NETN 6 /* network number length option */
-#define CILEN_NODEN 8 /* node number length option */
-#define CILEN_PROTOCOL 4 /* Minimum length of routing protocol */
-#define CILEN_NAME 3 /* Minimum length of router name */
-#define CILEN_COMPRESS 4 /* Minimum length of compression protocol */
-
-#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
- (x) == CONFNAK ? "NAK" : "REJ")
-
-/* Used in printing the node number */
-#define NODE(base) base[0], base[1], base[2], base[3], base[4], base[5]
-
-/* Used to generate the proper bit mask */
-#define BIT(num) (1 << (num))
-
-/*
- * Convert from internal to external notation
- */
-
-static short int
-to_external(internal)
-short int internal;
-{
- short int external;
-
- if (internal & IPX_NONE)
- external = IPX_NONE;
- else
- external = RIP_SAP;
-
- return external;
-}
-
-/*
- * Make a string representation of a network IP address.
- */
-
-char *
-ipx_ntoa(ipxaddr)
-u_int32_t ipxaddr;
-{
- static char b[64];
- sprintf(b, "%x", ipxaddr);
- return b;
-}
-
-
-/*
- * ipxcp_init - Initialize IPXCP.
- */
-static void
-ipxcp_init(unit)
- int unit;
-{
- fsm *f = &ipxcp_fsm[unit];
-
- f->unit = unit;
- f->protocol = PPP_IPXCP;
- f->callbacks = &ipxcp_callbacks;
- fsm_init(&ipxcp_fsm[unit]);
-
- memset (wo->name, 0, sizeof (wo->name));
- memset (wo->our_node, 0, sizeof (wo->our_node));
- memset (wo->his_node, 0, sizeof (wo->his_node));
-
- wo->neg_nn = 1;
- wo->neg_complete = 1;
- wo->network = 0;
-
- ao->neg_node = 1;
- ao->neg_nn = 1;
- ao->neg_name = 1;
- ao->neg_complete = 1;
- ao->neg_router = 1;
-
- ao->accept_local = 0;
- ao->accept_remote = 0;
- ao->accept_network = 0;
-
- wo->tried_rip = 0;
- wo->tried_nlsp = 0;
-}
-
-/*
- * Copy the node number
- */
-
-static void
-copy_node (src, dst)
-u_char *src, *dst;
-{
- memcpy (dst, src, sizeof (ipxcp_wantoptions[0].our_node));
-}
-
-/*
- * Compare node numbers
- */
-
-static int
-compare_node (src, dst)
-u_char *src, *dst;
-{
- return memcmp (dst, src, sizeof (ipxcp_wantoptions[0].our_node)) == 0;
-}
-
-/*
- * Is the node number zero?
- */
-
-static int
-zero_node (node)
-u_char *node;
-{
- int indx;
- for (indx = 0; indx < sizeof (ipxcp_wantoptions[0].our_node); ++indx)
- if (node [indx] != 0)
- return 0;
- return 1;
-}
-
-/*
- * Increment the node number
- */
-
-static void
-inc_node (node)
-u_char *node;
-{
- u_char *outp;
- u_int32_t magic_num;
-
- outp = node;
- magic_num = magic();
- *outp++ = '\0';
- *outp++ = '\0';
- PUTLONG (magic_num, outp);
-}
-
-/*
- * ipxcp_open - IPXCP is allowed to come up.
- */
-static void
-ipxcp_open(unit)
- int unit;
-{
- fsm_open(&ipxcp_fsm[unit]);
-}
-
-/*
- * ipxcp_close - Take IPXCP down.
- */
-static void
-ipxcp_close(unit, reason)
- int unit;
- char *reason;
-{
- fsm_close(&ipxcp_fsm[unit], reason);
-}
-
-
-/*
- * ipxcp_lowerup - The lower layer is up.
- */
-static void
-ipxcp_lowerup(unit)
- int unit;
-{
- fsm_lowerup(&ipxcp_fsm[unit]);
-}
-
-
-/*
- * ipxcp_lowerdown - The lower layer is down.
- */
-static void
-ipxcp_lowerdown(unit)
- int unit;
-{
- fsm_lowerdown(&ipxcp_fsm[unit]);
-}
-
-
-/*
- * ipxcp_input - Input IPXCP packet.
- */
-static void
-ipxcp_input(unit, p, len)
- int unit;
- u_char *p;
- int len;
-{
- fsm_input(&ipxcp_fsm[unit], p, len);
-}
-
-
-/*
- * ipxcp_protrej - A Protocol-Reject was received for IPXCP.
- *
- * Pretend the lower layer went down, so we shut up.
- */
-static void
-ipxcp_protrej(unit)
- int unit;
-{
- fsm_lowerdown(&ipxcp_fsm[unit]);
-}
-
-
-/*
- * ipxcp_resetci - Reset our CI.
- */
-static void
-ipxcp_resetci(f)
- fsm *f;
-{
- wo->req_node = wo->neg_node && ao->neg_node;
- wo->req_nn = wo->neg_nn && ao->neg_nn;
-
- if (wo->our_network == 0) {
- wo->neg_node = 1;
- ao->accept_network = 1;
- }
-/*
- * If our node number is zero then change it.
- */
- if (zero_node (wo->our_node)) {
- inc_node (wo->our_node);
- ao->accept_local = 1;
- wo->neg_node = 1;
- }
-/*
- * If his node number is zero then change it.
- */
- if (zero_node (wo->his_node)) {
- inc_node (wo->his_node);
- ao->accept_remote = 1;
- }
-/*
- * If no routing agent was specified then we do RIP/SAP according to the
- * RFC documents. If you have specified something then OK. Otherwise, we
- * do RIP/SAP.
- */
- if (ao->router == 0) {
- ao->router |= BIT(RIP_SAP);
- wo->router |= BIT(RIP_SAP);
- }
-
- /* Always specify a routing protocol unless it was REJected. */
- wo->neg_router = 1;
-/*
- * Start with these default values
- */
- *go = *wo;
-}
-
-/*
- * ipxcp_cilen - Return length of our CI.
- */
-
-static int
-ipxcp_cilen(f)
- fsm *f;
-{
- int len;
-
- len = go->neg_nn ? CILEN_NETN : 0;
- len += go->neg_node ? CILEN_NODEN : 0;
- len += go->neg_name ? CILEN_NAME + strlen (go->name) - 1 : 0;
-
- /* RFC says that defaults should not be included. */
- if (go->neg_router && to_external(go->router) != RIP_SAP)
- len += CILEN_PROTOCOL;
-
- return (len);
-}
-
-
-/*
- * ipxcp_addci - Add our desired CIs to a packet.
- */
-static void
-ipxcp_addci(f, ucp, lenp)
- fsm *f;
- u_char *ucp;
- int *lenp;
-{
-/*
- * Add the options to the record.
- */
- if (go->neg_nn) {
- PUTCHAR (IPX_NETWORK_NUMBER, ucp);
- PUTCHAR (CILEN_NETN, ucp);
- PUTLONG (go->our_network, ucp);
- }
-
- if (go->neg_node) {
- int indx;
- PUTCHAR (IPX_NODE_NUMBER, ucp);
- PUTCHAR (CILEN_NODEN, ucp);
- for (indx = 0; indx < sizeof (go->our_node); ++indx)
- PUTCHAR (go->our_node[indx], ucp);
- }
-
- if (go->neg_name) {
- int cilen = strlen (go->name);
- int indx;
- PUTCHAR (IPX_ROUTER_NAME, ucp);
- PUTCHAR (CILEN_NAME + cilen - 1, ucp);
- for (indx = 0; indx < cilen; ++indx)
- PUTCHAR (go->name [indx], ucp);
- }
-
- if (go->neg_router) {
- short external = to_external (go->router);
- if (external != RIP_SAP) {
- PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
- PUTCHAR (CILEN_PROTOCOL, ucp);
- PUTSHORT (external, ucp);
- }
- }
-}
-
-/*
- * ipxcp_ackci - Ack our CIs.
- *
- * Returns:
- * 0 - Ack was bad.
- * 1 - Ack was good.
- */
-static int
-ipxcp_ackci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- u_short cilen, citype, cishort;
- u_char cichar;
- u_int32_t cilong;
-
-#define ACKCIVOID(opt, neg) \
- if (neg) { \
- if ((len -= CILEN_VOID) < 0) \
- break; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_VOID || \
- citype != opt) \
- break; \
- }
-
-#define ACKCICOMPLETE(opt,neg) ACKCIVOID(opt, neg)
-
-#define ACKCICHARS(opt, neg, val, cnt) \
- if (neg) { \
- int indx, count = cnt; \
- len -= (count + 2); \
- if (len < 0) \
- break; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != (count + 2) || \
- citype != opt) \
- break; \
- for (indx = 0; indx < count; ++indx) {\
- GETCHAR(cichar, p); \
- if (cichar != ((u_char *) &val)[indx]) \
- break; \
- }\
- if (indx != count) \
- break; \
- }
-
-#define ACKCINODE(opt,neg,val) ACKCICHARS(opt,neg,val,sizeof(val))
-#define ACKCINAME(opt,neg,val) ACKCICHARS(opt,neg,val,strlen(val))
-
-#define ACKCINETWORK(opt, neg, val) \
- if (neg) { \
- if ((len -= CILEN_NETN) < 0) \
- break; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_NETN || \
- citype != opt) \
- break; \
- GETLONG(cilong, p); \
- if (cilong != val) \
- break; \
- }
-
-#define ACKCIPROTO(opt, neg, val) \
- if (neg) { \
- if (len < 2) \
- break; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_PROTOCOL || citype != opt) \
- break; \
- len -= cilen; \
- if (len < 0) \
- break; \
- GETSHORT(cishort, p); \
- if (cishort != to_external (val) || cishort == RIP_SAP) \
- break; \
- }
-/*
- * Process the ACK frame in the order in which the frame was assembled
- */
- do {
- ACKCINETWORK (IPX_NETWORK_NUMBER, go->neg_nn, go->our_network);
- ACKCINODE (IPX_NODE_NUMBER, go->neg_node, go->our_node);
- ACKCINAME (IPX_ROUTER_NAME, go->neg_name, go->name);
- ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
- ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
- ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
-/*
- * This is the end of the record.
- */
- if (len == 0)
- return (1);
- } while (0);
-/*
- * The frame is invalid
- */
- IPXCPDEBUG((LOG_INFO, "ipxcp_ackci: received bad Ack!"));
- return (0);
-}
-
-/*
- * ipxcp_nakci - Peer has sent a NAK for some of our CIs.
- * This should not modify any state if the Nak is bad
- * or if IPXCP is in the OPENED state.
- *
- * Returns:
- * 0 - Nak was bad.
- * 1 - Nak was good.
- */
-
-static int
-ipxcp_nakci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- u_char citype, cilen, *next;
- u_short s;
- u_int32_t l;
- ipxcp_options no; /* options we've seen Naks for */
- ipxcp_options try; /* options to request next time */
-
- BZERO(&no, sizeof(no));
- try = *go;
-
- while (len > CILEN_VOID) {
- GETCHAR (citype, p);
- GETCHAR (cilen, p);
- len -= cilen;
- if (len < 0)
- goto bad;
- next = &p [cilen - CILEN_VOID];
-
- switch (citype) {
- case IPX_NETWORK_NUMBER:
- if (!go->neg_nn || no.neg_nn || (cilen != CILEN_NETN))
- goto bad;
- no.neg_nn = 1;
-
- GETLONG(l, p);
- IPXCPDEBUG((LOG_INFO, "local IP address %d", l));
- if (l && ao->accept_network)
- try.our_network = l;
- break;
-
- case IPX_NODE_NUMBER:
- if (!go->neg_node || no.neg_node || (cilen != CILEN_NODEN))
- goto bad;
- no.neg_node = 1;
-
- IPXCPDEBUG((LOG_INFO,
- "local node number %02X%02X%02X%02X%02X%02X",
- NODE(p)));
-
- if (!zero_node (p) && ao->accept_local &&
- ! compare_node (p, ho->his_node))
- copy_node (p, try.our_node);
- break;
-
- /* This has never been sent. Ignore the NAK frame */
- case IPX_COMPRESSION_PROTOCOL:
- goto bad;
-
- case IPX_ROUTER_PROTOCOL:
- if (!go->neg_router || (cilen < CILEN_PROTOCOL))
- goto bad;
-
- GETSHORT (s, p);
- if (s > 15) /* This is just bad, but ignore for now. */
- break;
-
- s = BIT(s);
- if (no.router & s) /* duplicate NAKs are always bad */
- goto bad;
-
- if (no.router == 0) /* Reset on first NAK only */
- try.router = 0;
-
- no.router |= s;
- try.router |= s;
- try.neg_router = 1;
-
- IPXCPDEBUG((LOG_INFO, "Router protocol number %d", s));
- break;
-
- /* These, according to the RFC, must never be NAKed. */
- case IPX_ROUTER_NAME:
- case IPX_COMPLETE:
- goto bad;
-
- /* These are for options which we have not seen. */
- default:
- break;
- }
- p = next;
- }
-
- /* If there is still anything left, this packet is bad. */
- if (len != 0)
- goto bad;
-
- /*
- * Do not permit the peer to force a router protocol which we do not
- * support. However, default to the condition that will accept "NONE".
- */
- try.router &= (ao->router | BIT(IPX_NONE));
- if (try.router == 0 && ao->router != 0)
- try.router = BIT(IPX_NONE);
-
- if (try.router != 0)
- try.neg_router = 1;
-
- /*
- * OK, the Nak is good. Now we can update state.
- */
- if (f->state != OPENED)
- *go = try;
-
- return 1;
-
-bad:
- IPXCPDEBUG((LOG_INFO, "ipxcp_nakci: received bad Nak!"));
- return 0;
-}
-
-/*
- * ipxcp_rejci - Reject some of our CIs.
- */
-static int
-ipxcp_rejci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- u_short cilen, citype, cishort;
- u_char cichar;
- u_int32_t cilong;
- ipxcp_options try; /* options to request next time */
-
-#define REJCINETWORK(opt, neg, val) \
- if (neg && p[0] == opt) { \
- if ((len -= CILEN_NETN) < 0) \
- break; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_NETN || \
- citype != opt) \
- break; \
- GETLONG(cilong, p); \
- if (cilong != val) \
- break; \
- IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected long opt %d", opt)); \
- neg = 0; \
- }
-
-#define REJCICHARS(opt, neg, val, cnt) \
- if (neg && p[0] == opt) { \
- int indx, count = cnt; \
- len -= (count + 2); \
- if (len < 0) \
- break; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != (count + 2) || \
- citype != opt) \
- break; \
- for (indx = 0; indx < count; ++indx) {\
- GETCHAR(cichar, p); \
- if (cichar != ((u_char *) &val)[indx]) \
- break; \
- }\
- if (indx != count) \
- break; \
- IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected opt %d", opt)); \
- neg = 0; \
- }
-
-#define REJCINODE(opt,neg,val) REJCICHARS(opt,neg,val,sizeof(val))
-#define REJCINAME(opt,neg,val) REJCICHARS(opt,neg,val,strlen(val))
-
-#define REJCIVOID(opt, neg) \
- if (neg && p[0] == opt) { \
- if ((len -= CILEN_VOID) < 0) \
- break; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_VOID || citype != opt) \
- break; \
- IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected void opt %d", opt)); \
- neg = 0; \
- }
-
-/* a reject for RIP/SAP is invalid since we don't send it and you can't
- reject something which is not sent. (You can NAK, but you can't REJ.) */
-#define REJCIPROTO(opt, neg, val, bit) \
- if (neg && p[0] == opt) { \
- if ((len -= CILEN_PROTOCOL) < 0) \
- break; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_PROTOCOL) \
- break; \
- GETSHORT(cishort, p); \
- if (cishort != to_external (val) || cishort == RIP_SAP) \
- break; \
- IPXCPDEBUG((LOG_INFO, "ipxcp_rejci short opt %d", opt)); \
- neg = 0; \
- }
-/*
- * Any Rejected CIs must be in exactly the same order that we sent.
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
- try = *go;
-
- do {
- REJCINETWORK (IPX_NETWORK_NUMBER, try.neg_nn, try.our_network);
- REJCINODE (IPX_NODE_NUMBER, try.neg_node, try.our_node);
- REJCINAME (IPX_ROUTER_NAME, try.neg_name, try.name);
- REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0);
-/*
- * This is the end of the record.
- */
- if (len == 0) {
- if (f->state != OPENED)
- *go = try;
- return (1);
- }
- } while (0);
-/*
- * The frame is invalid at this point.
- */
- IPXCPDEBUG((LOG_INFO, "ipxcp_rejci: received bad Reject!"));
- return 0;
-}
-
-/*
- * ipxcp_reqci - Check the peer's requested CIs and send appropriate response.
- *
- * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
- * appropriately. If reject_if_disagree is non-zero, doesn't return
- * CONFNAK; returns CONFREJ if it can't return CONFACK.
- */
-static int
-ipxcp_reqci(f, inp, len, reject_if_disagree)
- fsm *f;
- u_char *inp; /* Requested CIs */
- int *len; /* Length of requested CIs */
- int reject_if_disagree;
-{
- u_char *cip, *next; /* Pointer to current and next CIs */
- u_short cilen, citype; /* Parsed len, type */
- u_short cishort; /* Parsed short value */
- u_int32_t cinetwork; /* Parsed address values */
- int rc = CONFACK; /* Final packet return code */
- int orc; /* Individual option return code */
- u_char *p; /* Pointer to next char to parse */
- u_char *ucp = inp; /* Pointer to current output char */
- int l = *len; /* Length left */
-
- /*
- * Reset all his options.
- */
- BZERO(ho, sizeof(*ho));
-
- /*
- * Process all his options.
- */
- next = inp;
- while (l) {
- orc = CONFACK; /* Assume success */
- cip = p = next; /* Remember begining of CI */
- if (l < 2 || /* Not enough data for CI header or */
- p[1] < 2 || /* CI length too small or */
- p[1] > l) { /* CI length too big? */
- IPXCPDEBUG((LOG_INFO, "ipxcp_reqci: bad CI length!"));
- orc = CONFREJ; /* Reject bad CI */
- cilen = l; /* Reject till end of packet */
- l = 0; /* Don't loop again */
- goto endswitch;
- }
- GETCHAR(citype, p); /* Parse CI type */
- GETCHAR(cilen, p); /* Parse CI length */
- l -= cilen; /* Adjust remaining length */
- next += cilen; /* Step to next CI */
-
- switch (citype) { /* Check CI type */
-/*
- * The network number must match. Choose the larger of the two.
- */
- case IPX_NETWORK_NUMBER:
- IPXCPDEBUG((LOG_INFO, "ipxcp: received Network Number request"));
-
- /* if we wont negotiate the network number or the length is wrong
- then reject the option */
- if ( !ao->neg_nn || cilen != CILEN_NETN ) {
- orc = CONFREJ;
- break;
- }
- GETLONG(cinetwork, p);
- IPXCPDEBUG((LOG_INFO,"Remote proposed IPX network number is %8Lx",tl));
-
- /* If the network numbers match then acknowledge them. */
- if (cinetwork != 0) {
- ho->his_network = cinetwork;
- ho->neg_nn = 1;
- if (wo->our_network == cinetwork)
- break;
-/*
- * If the network number is not given or we don't accept their change or
- * the network number is too small then NAK it.
- */
- if (! ao->accept_network || cinetwork < wo->our_network) {
- DECPTR (sizeof (u_int32_t), p);
- PUTLONG (wo->our_network, p);
- orc = CONFNAK;
- }
- break;
- }
-/*
- * The peer sent '0' for the network. Give it ours if we have one.
- */
- if (go->our_network != 0) {
- DECPTR (sizeof (u_int32_t), p);
- PUTLONG (wo->our_network, p);
- orc = CONFNAK;
-/*
- * We don't have one. Reject the value.
- */
- } else
- orc = CONFREJ;
-
- break;
-/*
- * The node number is required
- */
- case IPX_NODE_NUMBER:
- IPXCPDEBUG((LOG_INFO, "ipxcp: received Node Number request"));
-
- /* if we wont negotiate the node number or the length is wrong
- then reject the option */
- if ( cilen != CILEN_NODEN ) {
- orc = CONFREJ;
- break;
- }
-
- copy_node (p, ho->his_node);
- ho->neg_node = 1;
-/*
- * If the remote does not have a number and we do then NAK it with the value
- * which we have for it. (We never have a default value of zero.)
- */
- if (zero_node (ho->his_node)) {
- orc = CONFNAK;
- copy_node (wo->his_node, p);
- INCPTR (sizeof (wo->his_node), p);
- break;
- }
-/*
- * If you have given me the expected network node number then I'll accept
- * it now.
- */
- if (compare_node (wo->his_node, ho->his_node)) {
- orc = CONFACK;
- ho->neg_node = 1;
- INCPTR (sizeof (wo->his_node), p);
- break;
- }
-/*
- * If his node number is the same as ours then ask him to try the next
- * value.
- */
- if (compare_node (ho->his_node, go->our_node)) {
- inc_node (ho->his_node);
- orc = CONFNAK;
- copy_node (ho->his_node, p);
- INCPTR (sizeof (wo->his_node), p);
- break;
- }
-/*
- * If we don't accept a new value then NAK it.
- */
- if (! ao->accept_remote) {
- copy_node (wo->his_node, p);
- INCPTR (sizeof (wo->his_node), p);
- orc = CONFNAK;
- break;
- }
- orc = CONFACK;
- ho->neg_node = 1;
- INCPTR (sizeof (wo->his_node), p);
- break;
-/*
- * Compression is not desired at this time. It is always rejected.
- */
- case IPX_COMPRESSION_PROTOCOL:
- IPXCPDEBUG((LOG_INFO, "ipxcp: received Compression Protocol request "));
- orc = CONFREJ;
- break;
-/*
- * The routing protocol is a bitmask of various types. Any combination
- * of the values RIP_SAP and NLSP are permissible. 'IPX_NONE' for no
- * routing protocol must be specified only once.
- */
- case IPX_ROUTER_PROTOCOL:
- if ( !ao->neg_router || cilen < CILEN_PROTOCOL ) {
- orc = CONFREJ;
- break;
- }
-
- GETSHORT (cishort, p);
- IPXCPDEBUG((LOG_INFO,
- "Remote router protocol number 0x%04x",
- cishort));
-
- if (wo->neg_router == 0) {
- wo->neg_router = 1;
- wo->router = BIT(IPX_NONE);
- }
-
- if ((cishort == IPX_NONE && ho->router != 0) ||
- (ho->router & BIT(IPX_NONE))) {
- orc = CONFREJ;
- break;
- }
-
- cishort = BIT(cishort);
- if (ho->router & cishort) {
- orc = CONFREJ;
- break;
- }
-
- ho->router |= cishort;
- ho->neg_router = 1;
-
- /* Finally do not allow a router protocol which we do not
- support. */
-
- if ((cishort & (ao->router | BIT(IPX_NONE))) == 0) {
- int protocol;
-
- if (cishort == BIT(NLSP) &&
- (ao->router & BIT(RIP_SAP)) &&
- !wo->tried_rip) {
- protocol = RIP_SAP;
- wo->tried_rip = 1;
- } else
- protocol = IPX_NONE;
-
- DECPTR (sizeof (u_int16_t), p);
- PUTSHORT (protocol, p);
- orc = CONFNAK;
- }
- break;
-/*
- * The router name is advisorary. Just accept it if it is not too large.
- */
- case IPX_ROUTER_NAME:
- IPXCPDEBUG((LOG_INFO, "ipxcp: received Router Name request"));
- if (cilen >= CILEN_NAME) {
- int name_size = cilen - CILEN_NAME;
- if (name_size > sizeof (ho->name))
- name_size = sizeof (ho->name) - 1;
- memset (ho->name, 0, sizeof (ho->name));
- memcpy (ho->name, p, name_size);
- ho->name [name_size] = '\0';
- ho->neg_name = 1;
- orc = CONFACK;
- break;
- }
- orc = CONFREJ;
- break;
-/*
- * This is advisorary.
- */
- case IPX_COMPLETE:
- IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
- if (cilen != CILEN_COMPLETE)
- orc = CONFREJ;
- else {
- ho->neg_complete = 1;
- orc = CONFACK;
- }
- break;
-/*
- * All other entries are not known at this time.
- */
- default:
- IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
- orc = CONFREJ;
- break;
- }
-
-endswitch:
- IPXCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc)));
-
- if (orc == CONFACK && /* Good CI */
- rc != CONFACK) /* but prior CI wasnt? */
- continue; /* Don't send this one */
-
- if (orc == CONFNAK) { /* Nak this CI? */
- if (reject_if_disagree) /* Getting fed up with sending NAKs? */
- orc = CONFREJ; /* Get tough if so */
- if (rc == CONFREJ) /* Rejecting prior CI? */
- continue; /* Don't send this one */
- if (rc == CONFACK) { /* Ack'd all prior CIs? */
- rc = CONFNAK; /* Not anymore... */
- ucp = inp; /* Backup */
- }
- }
-
- if (orc == CONFREJ && /* Reject this CI */
- rc != CONFREJ) { /* but no prior ones? */
- rc = CONFREJ;
- ucp = inp; /* Backup */
- }
-
- /* Need to move CI? */
- if (ucp != cip)
- BCOPY(cip, ucp, cilen); /* Move it */
-
- /* Update output pointer */
- INCPTR(cilen, ucp);
- }
-
- /*
- * If we aren't rejecting this packet, and we want to negotiate
- * their address, and they didn't send their address, then we
- * send a NAK with an IPX_NODE_NUMBER option appended. We assume the
- * input buffer is long enough that we can append the extra
- * option safely.
- */
-
- if (rc != CONFREJ && !ho->neg_node &&
- wo->req_nn && !reject_if_disagree) {
- if (rc == CONFACK) {
- rc = CONFNAK;
- wo->req_nn = 0; /* don't ask again */
- ucp = inp; /* reset pointer */
- }
-
- if (zero_node (wo->his_node))
- inc_node (wo->his_node);
-
- PUTCHAR (IPX_NODE_NUMBER, ucp);
- PUTCHAR (CILEN_NODEN, ucp);
- copy_node (wo->his_node, ucp);
- INCPTR (sizeof (wo->his_node), ucp);
- }
-
- *len = ucp - inp; /* Compute output length */
- IPXCPDEBUG((LOG_INFO, "ipxcp: returning Configure-%s", CODENAME(rc)));
- return (rc); /* Return final code */
-}
-
-/*
- * ipxcp_up - IPXCP has come UP.
- *
- * Configure the IP network interface appropriately and bring it up.
- */
-
-static void
-ipxcp_up(f)
- fsm *f;
-{
- int unit = f->unit;
-
- IPXCPDEBUG((LOG_INFO, "ipxcp: up"));
-
- /* The default router protocol is RIP/SAP. */
- if (ho->router == 0)
- ho->router = BIT(RIP_SAP);
-
- if (go->router == 0)
- go->router = BIT(RIP_SAP);
-
- /* Fetch the network number */
- if (!ho->neg_nn)
- ho->his_network = wo->his_network;
-
- if (!ho->neg_node)
- copy_node (wo->his_node, ho->his_node);
-
- if (!wo->neg_node && !go->neg_node)
- copy_node (wo->our_node, go->our_node);
-
- if (zero_node (go->our_node)) {
- static char errmsg[] = "Could not determine local IPX node address";
- IPXCPDEBUG((LOG_ERR, errmsg));
- ipxcp_close(f->unit, errmsg);
- return;
- }
-
- go->network = go->our_network;
- if (ho->his_network != 0 && ho->his_network > go->network)
- go->network = ho->his_network;
-
- if (go->network == 0) {
- static char errmsg[] = "Can not determine network number";
- IPXCPDEBUG((LOG_ERR, errmsg));
- ipxcp_close (unit, errmsg);
- return;
- }
-
- /* bring the interface up */
- if (!sifup(unit)) {
- IPXCPDEBUG((LOG_WARNING, "sifup failed"));
- ipxcp_close(unit, "Interface configuration failed");
- return;
- }
-
- /* set the network number for IPX */
- if (!sipxfaddr(unit, go->network, go->our_node)) {
- IPXCPDEBUG((LOG_WARNING, "sipxfaddr failed"));
- ipxcp_close(unit, "Interface configuration failed");
- return;
- }
-
- /*
- * Execute the ipx-up script, like this:
- * /etc/ppp/ipx-up interface tty speed local-IPX remote-IPX
- */
-
- ipxcp_script (f, _PATH_IPXUP);
-}
-
-/*
- * ipxcp_down - IPXCP has gone DOWN.
- *
- * Take the IP network interface down, clear its addresses
- * and delete routes through it.
- */
-
-static void
-ipxcp_down(f)
- fsm *f;
-{
- IPXCPDEBUG((LOG_INFO, "ipxcp: down"));
-
- cipxfaddr (f->unit);
- sifdown(f->unit);
- ipxcp_script (f, _PATH_IPXDOWN);
-}
-
-
-/*
- * ipxcp_script - Execute a script with arguments
- * interface-name tty-name speed local-IPX remote-IPX networks.
- */
-static void
-ipxcp_script(f, script)
- fsm *f;
- char *script;
-{
- char strspeed[32], strlocal[32], strremote[32];
- char strnetwork[32], strpid[32];
- char *argv[14], strproto_lcl[32], strproto_rmt[32];
-
- sprintf (strpid, "%d", getpid());
- sprintf (strspeed, "%d", baud_rate);
-
- strproto_lcl[0] = '\0';
- if (go->neg_router && ((go->router & BIT(IPX_NONE)) == 0)) {
- if (go->router & BIT(RIP_SAP))
- strcpy (strproto_lcl, "RIP ");
- if (go->router & BIT(NLSP))
- strcat (strproto_lcl, "NLSP ");
- }
-
- if (strproto_lcl[0] == '\0')
- strcpy (strproto_lcl, "NONE ");
-
- strproto_lcl[strlen (strproto_lcl)-1] = '\0';
-
- strproto_rmt[0] = '\0';
- if (ho->neg_router && ((ho->router & BIT(IPX_NONE)) == 0)) {
- if (ho->router & BIT(RIP_SAP))
- strcpy (strproto_rmt, "RIP ");
- if (ho->router & BIT(NLSP))
- strcat (strproto_rmt, "NLSP ");
- }
-
- if (strproto_rmt[0] == '\0')
- strcpy (strproto_rmt, "NONE ");
-
- strproto_rmt[strlen (strproto_rmt)-1] = '\0';
-
- strcpy (strnetwork, ipx_ntoa (go->network));
-
- sprintf (strlocal,
- "%02X%02X%02X%02X%02X%02X",
- NODE(go->our_node));
-
- sprintf (strremote,
- "%02X%02X%02X%02X%02X%02X",
- NODE(ho->his_node));
-
- argv[0] = script;
- argv[1] = ifname;
- argv[2] = devnam;
- argv[3] = strspeed;
- argv[4] = strnetwork;
- argv[5] = strlocal;
- argv[6] = strremote;
- argv[7] = strproto_lcl;
- argv[8] = strproto_rmt;
- argv[9] = go->name;
- argv[10] = ho->name;
- argv[11] = ipparam;
- argv[12] = strpid;
- argv[13] = NULL;
- run_program(script, argv, 0);
-}
-
-/*
- * ipxcp_printpkt - print the contents of an IPXCP packet.
- */
-static char *ipxcp_codenames[] = {
- "ConfReq", "ConfAck", "ConfNak", "ConfRej",
- "TermReq", "TermAck", "CodeRej"
-};
-
-static int
-ipxcp_printpkt(p, plen, printer, arg)
- u_char *p;
- int plen;
- void (*printer)(void *, char *, ...);
- void *arg;
-{
- int code, id, len, olen;
- u_char *pstart, *optend;
- u_short cishort;
- u_int32_t cilong;
-
- if (plen < HEADERLEN)
- return 0;
- pstart = p;
- GETCHAR(code, p);
- GETCHAR(id, p);
- GETSHORT(len, p);
- if (len < HEADERLEN || len > plen)
- return 0;
-
- if (code >= 1 && code <= sizeof(ipxcp_codenames) / sizeof(char *))
- printer(arg, " %s", ipxcp_codenames[code-1]);
- else
- printer(arg, " code=0x%x", code);
- printer(arg, " id=0x%x", id);
- len -= HEADERLEN;
- switch (code) {
- case CONFREQ:
- case CONFACK:
- case CONFNAK:
- case CONFREJ:
- /* print option list */
- while (len >= 2) {
- GETCHAR(code, p);
- GETCHAR(olen, p);
- p -= 2;
- if (olen < CILEN_VOID || olen > len) {
- break;
- }
- printer(arg, " <");
- len -= olen;
- optend = p + olen;
- switch (code) {
- case IPX_NETWORK_NUMBER:
- if (olen == CILEN_NETN) {
- p += 2;
- GETLONG(cilong, p);
- printer (arg, "network %s", ipx_ntoa (cilong));
- }
- break;
- case IPX_NODE_NUMBER:
- if (olen == CILEN_NODEN) {
- p += 2;
- printer (arg, "node ");
- while (p < optend) {
- GETCHAR(code, p);
- printer(arg, "%.2x", (int) (unsigned int) (unsigned char) code);
- }
- }
- break;
- case IPX_COMPRESSION_PROTOCOL:
- if (olen == CILEN_COMPRESS) {
- p += 2;
- GETSHORT (cishort, p);
- printer (arg, "compression %d", (int) cishort);
- }
- break;
- case IPX_ROUTER_PROTOCOL:
- if (olen == CILEN_PROTOCOL) {
- p += 2;
- GETSHORT (cishort, p);
- printer (arg, "router proto %d", (int) cishort);
- }
- break;
- case IPX_ROUTER_NAME:
- if (olen >= CILEN_NAME) {
- p += 2;
- printer (arg, "router name \"");
- while (p < optend) {
- GETCHAR(code, p);
- if (code >= 0x20 && code <= 0x7E)
- printer (arg, "%c", (int) (unsigned int) (unsigned char) code);
- else
- printer (arg, " \\%.2x", (int) (unsigned int) (unsigned char) code);
- }
- printer (arg, "\"");
- }
- break;
- case IPX_COMPLETE:
- if (olen == CILEN_COMPLETE) {
- p += 2;
- printer (arg, "complete");
- }
- break;
- default:
- break;
- }
-
- while (p < optend) {
- GETCHAR(code, p);
- printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code);
- }
- printer(arg, ">");
- }
- break;
-
- case TERMACK:
- case TERMREQ:
- if (len > 0 && *p >= ' ' && *p < 0x7f) {
- printer(arg, " ");
- print_string(p, len, printer, arg);
- p += len;
- len = 0;
- }
- break;
- }
-
- /* print the rest of the bytes in the packet */
- for (; len > 0; --len) {
- GETCHAR(code, p);
- printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code);
- }
-
- return p - pstart;
-}
-#endif /* ifdef IPX_CHANGE */
diff --git a/usr.sbin/pppd/ipxcp.h b/usr.sbin/pppd/ipxcp.h
deleted file mode 100644
index 0890181..0000000
--- a/usr.sbin/pppd/ipxcp.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * ipxcp.h - IPX Control Protocol definitions.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
- */
-
-/*
- * Options.
- */
-#define IPX_NETWORK_NUMBER 1 /* IPX Network Number */
-#define IPX_NODE_NUMBER 2
-#define IPX_COMPRESSION_PROTOCOL 3
-#define IPX_ROUTER_PROTOCOL 4
-#define IPX_ROUTER_NAME 5
-#define IPX_COMPLETE 6
-
-/* Values for the router protocol */
-#define IPX_NONE 0
-#define RIP_SAP 2
-#define NLSP 4
-
-typedef struct ipxcp_options {
- int neg_node : 1; /* Negotiate IPX node number? */
- int req_node : 1; /* Ask peer to send IPX node number? */
-
- int neg_nn : 1; /* Negotiate IPX network number? */
- int req_nn : 1; /* Ask peer to send IPX network number */
-
- int neg_name : 1; /* Negotiate IPX router name */
- int neg_complete : 1; /* Negotiate completion */
- int neg_router : 1; /* Negotiate IPX router number */
-
- int accept_local : 1; /* accept peer's value for ournode */
- int accept_remote : 1; /* accept peer's value for hisnode */
- int accept_network : 1; /* accept network number */
-
- int tried_nlsp : 1; /* I have suggested NLSP already */
- int tried_rip : 1; /* I have suggested RIP/SAP already */
-
- u_int32_t his_network; /* base network number */
- u_int32_t our_network; /* our value for network number */
- u_int32_t network; /* the final network number */
-
- u_char his_node[6]; /* peer's node number */
- u_char our_node[6]; /* our node number */
- u_char name [48]; /* name of the router */
- int router; /* routing protocol */
-} ipxcp_options;
-
-extern fsm ipxcp_fsm[];
-extern ipxcp_options ipxcp_wantoptions[];
-extern ipxcp_options ipxcp_gotoptions[];
-extern ipxcp_options ipxcp_allowoptions[];
-extern ipxcp_options ipxcp_hisoptions[];
-
-extern struct protent ipxcp_protent;
diff --git a/usr.sbin/pppd/lcp.c b/usr.sbin/pppd/lcp.c
deleted file mode 100644
index a10a460..0000000
--- a/usr.sbin/pppd/lcp.c
+++ /dev/null
@@ -1,1859 +0,0 @@
-/*
- * lcp.c - PPP Link Control Protocol.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-/*
- * TODO:
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <syslog.h>
-#include <assert.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <netinet/in.h>
-
-#include "pppd.h"
-#include "fsm.h"
-#include "lcp.h"
-#include "chap.h"
-#include "magic.h"
-
-/* global vars */
-fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/
-lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */
-lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
-lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
-lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
-u_int32_t xmit_accm[NUM_PPP][8]; /* extended transmit ACCM */
-
-static u_int32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */
-static u_int32_t lcp_echo_number = 0; /* ID number of next echo frame */
-static u_int32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */
-
-static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */
-
-/*
- * Callbacks for fsm code. (CI = Configuration Information)
- */
-static void lcp_resetci(fsm *); /* Reset our CI */
-static int lcp_cilen(fsm *); /* Return length of our CI */
-static void lcp_addci(fsm *, u_char *, int *); /* Add our CI to pkt */
-static int lcp_ackci(fsm *, u_char *, int); /* Peer ack'd our CI */
-static int lcp_nakci(fsm *, u_char *, int); /* Peer nak'd our CI */
-static int lcp_rejci(fsm *, u_char *, int); /* Peer rej'd our CI */
-static int lcp_reqci(fsm *, u_char *, int *, int); /* Rcv peer CI */
-static void lcp_up(fsm *); /* We're UP */
-static void lcp_down(fsm *); /* We're DOWN */
-static void lcp_starting(fsm *); /* We need lower layer up */
-static void lcp_finished(fsm *); /* We need lower layer down */
-static int lcp_extcode(fsm *, int, int, u_char *, int);
-static void lcp_rprotrej(fsm *, u_char *, int);
-
-/*
- * routines to send LCP echos to peer
- */
-
-static void lcp_echo_lowerup(int);
-static void lcp_echo_lowerdown(int);
-static void LcpEchoTimeout(void *);
-static void lcp_received_echo_reply(fsm *, int, u_char *, int);
-static void LcpSendEchoRequest(fsm *);
-static void LcpLinkFailure(fsm *);
-static void LcpEchoCheck(fsm *);
-
-static fsm_callbacks lcp_callbacks = { /* LCP callback routines */
- lcp_resetci, /* Reset our Configuration Information */
- lcp_cilen, /* Length of our Configuration Information */
- lcp_addci, /* Add our Configuration Information */
- lcp_ackci, /* ACK our Configuration Information */
- lcp_nakci, /* NAK our Configuration Information */
- lcp_rejci, /* Reject our Configuration Information */
- lcp_reqci, /* Request peer's Configuration Information */
- lcp_up, /* Called when fsm reaches OPENED state */
- lcp_down, /* Called when fsm leaves OPENED state */
- lcp_starting, /* Called when we want the lower layer up */
- lcp_finished, /* Called when we want the lower layer down */
- NULL, /* Called when Protocol-Reject received */
- NULL, /* Retransmission is necessary */
- lcp_extcode, /* Called to handle LCP-specific codes */
- "LCP" /* String name of protocol */
-};
-
-/*
- * Protocol entry points.
- * Some of these are called directly.
- */
-
-static void lcp_init(int);
-static void lcp_input(int, u_char *, int);
-static void lcp_protrej(int);
-static int lcp_printpkt(u_char *, int,
- void (*)(void *, char *, ...), void *);
-
-struct protent lcp_protent = {
- PPP_LCP,
- lcp_init,
- lcp_input,
- lcp_protrej,
- lcp_lowerup,
- lcp_lowerdown,
- lcp_open,
- lcp_close,
- lcp_printpkt,
- NULL,
- 1,
- "LCP",
- NULL,
- NULL,
- NULL
-};
-
-int lcp_loopbackfail = DEFLOOPBACKFAIL;
-
-/*
- * Length of each type of configuration option (in octets)
- */
-#define CILEN_VOID 2
-#define CILEN_CHAR 3
-#define CILEN_SHORT 4 /* CILEN_VOID + sizeof(short) */
-#define CILEN_CHAP 5 /* CILEN_VOID + sizeof(short) + 1 */
-#define CILEN_LONG 6 /* CILEN_VOID + sizeof(long) */
-#define CILEN_LQR 8 /* CILEN_VOID + sizeof(short) + sizeof(long) */
-#define CILEN_CBCP 3
-
-#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
- (x) == CONFNAK ? "NAK" : "REJ")
-
-
-/*
- * lcp_init - Initialize LCP.
- */
-static void
-lcp_init(unit)
- int unit;
-{
- fsm *f = &lcp_fsm[unit];
- lcp_options *wo = &lcp_wantoptions[unit];
- lcp_options *ao = &lcp_allowoptions[unit];
-
- f->unit = unit;
- f->protocol = PPP_LCP;
- f->callbacks = &lcp_callbacks;
-
- fsm_init(f);
-
- wo->passive = 0;
- wo->silent = 0;
- wo->restart = 0; /* Set to 1 in kernels or multi-line
- implementations */
- wo->neg_mru = 1;
- wo->mru = DEFMRU;
- wo->neg_asyncmap = 0;
- wo->asyncmap = 0;
- wo->neg_chap = 0; /* Set to 1 on server */
- wo->neg_upap = 0; /* Set to 1 on server */
- wo->chap_mdtype = CHAP_DIGEST_MD5;
- wo->neg_magicnumber = 1;
- wo->neg_pcompression = 1;
- wo->neg_accompression = 1;
- wo->neg_lqr = 0; /* no LQR implementation yet */
- wo->neg_cbcp = 0;
-
- ao->neg_mru = 1;
- ao->mru = MAXMRU;
- ao->neg_asyncmap = 1;
- ao->asyncmap = 0;
- ao->neg_chap = 1;
- ao->chap_mdtype = CHAP_DIGEST_MD5;
- ao->neg_upap = 1;
- ao->neg_magicnumber = 1;
- ao->neg_pcompression = 1;
- ao->neg_accompression = 1;
- ao->neg_lqr = 0; /* no LQR implementation yet */
-#ifdef CBCP_SUPPORT
- ao->neg_cbcp = 1;
-#else
- ao->neg_cbcp = 0;
-#endif
-
- memset(xmit_accm[unit], 0, sizeof(xmit_accm[0]));
- xmit_accm[unit][3] = 0x60000000;
-}
-
-
-/*
- * lcp_open - LCP is allowed to come up.
- */
-void
-lcp_open(unit)
- int unit;
-{
- fsm *f = &lcp_fsm[unit];
- lcp_options *wo = &lcp_wantoptions[unit];
-
- f->flags = 0;
- if (wo->passive)
- f->flags |= OPT_PASSIVE;
- if (wo->silent)
- f->flags |= OPT_SILENT;
- fsm_open(f);
-}
-
-
-/*
- * lcp_close - Take LCP down.
- */
-void
-lcp_close(unit, reason)
- int unit;
- char *reason;
-{
- fsm *f = &lcp_fsm[unit];
-
- if (phase != PHASE_DEAD)
- phase = PHASE_TERMINATE;
- if (f->state == STOPPED && f->flags & (OPT_PASSIVE|OPT_SILENT)) {
- /*
- * This action is not strictly according to the FSM in RFC1548,
- * but it does mean that the program terminates if you do a
- * lcp_close() in passive/silent mode when a connection hasn't
- * been established.
- */
- f->state = CLOSED;
- lcp_finished(f);
-
- } else
- fsm_close(&lcp_fsm[unit], reason);
-}
-
-
-/*
- * lcp_lowerup - The lower layer is up.
- */
-void
-lcp_lowerup(unit)
- int unit;
-{
- lcp_options *wo = &lcp_wantoptions[unit];
-
- /*
- * Don't use A/C or protocol compression on transmission,
- * but accept A/C and protocol compressed packets
- * if we are going to ask for A/C and protocol compression.
- */
- ppp_set_xaccm(unit, xmit_accm[unit]);
- ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0);
- ppp_recv_config(unit, PPP_MRU, 0xffffffff,
- wo->neg_pcompression, wo->neg_accompression);
- peer_mru[unit] = PPP_MRU;
- lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0];
-
- fsm_lowerup(&lcp_fsm[unit]);
-}
-
-
-/*
- * lcp_lowerdown - The lower layer is down.
- */
-void
-lcp_lowerdown(unit)
- int unit;
-{
- fsm_lowerdown(&lcp_fsm[unit]);
-}
-
-
-/*
- * lcp_input - Input LCP packet.
- */
-static void
-lcp_input(unit, p, len)
- int unit;
- u_char *p;
- int len;
-{
- fsm *f = &lcp_fsm[unit];
-
- fsm_input(f, p, len);
-}
-
-
-/*
- * lcp_extcode - Handle a LCP-specific code.
- */
-static int
-lcp_extcode(f, code, id, inp, len)
- fsm *f;
- int code, id;
- u_char *inp;
- int len;
-{
- u_char *magp;
-
- switch( code ){
- case PROTREJ:
- lcp_rprotrej(f, inp, len);
- break;
-
- case ECHOREQ:
- if (f->state != OPENED)
- break;
- LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d", id));
- magp = inp;
- PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp);
- fsm_sdata(f, ECHOREP, id, inp, len);
- break;
-
- case ECHOREP:
- lcp_received_echo_reply(f, id, inp, len);
- break;
-
- case DISCREQ:
- break;
-
- default:
- return 0;
- }
- return 1;
-}
-
-
-/*
- * lcp_rprotrej - Receive a Protocol-Reject.
- *
- * Figure out which protocol is rejected and inform it.
- */
-static void
-lcp_rprotrej(f, inp, len)
- fsm *f;
- u_char *inp;
- int len;
-{
- int i;
- struct protent *protp;
- u_short prot;
-
- LCPDEBUG((LOG_INFO, "lcp_rprotrej."));
-
- if (len < sizeof (u_short)) {
- LCPDEBUG((LOG_INFO,
- "lcp_rprotrej: Rcvd short Protocol-Reject packet!"));
- return;
- }
-
- GETSHORT(prot, inp);
-
- LCPDEBUG((LOG_INFO,
- "lcp_rprotrej: Rcvd Protocol-Reject packet for %x!",
- prot));
-
- /*
- * Protocol-Reject packets received in any state other than the LCP
- * OPENED state SHOULD be silently discarded.
- */
- if( f->state != OPENED ){
- LCPDEBUG((LOG_INFO, "Protocol-Reject discarded: LCP in state %d",
- f->state));
- return;
- }
-
- /*
- * Upcall the proper Protocol-Reject routine.
- */
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if (protp->protocol == prot && protp->enabled_flag) {
- (*protp->protrej)(f->unit);
- return;
- }
-
- syslog(LOG_WARNING, "Protocol-Reject for unsupported protocol 0x%x",
- prot);
-}
-
-
-/*
- * lcp_protrej - A Protocol-Reject was received.
- */
-/*ARGSUSED*/
-static void
-lcp_protrej(unit)
- int unit;
-{
- /*
- * Can't reject LCP!
- */
- LCPDEBUG((LOG_WARNING,
- "lcp_protrej: Received Protocol-Reject for LCP!"));
- fsm_protreject(&lcp_fsm[unit]);
-}
-
-
-/*
- * lcp_sprotrej - Send a Protocol-Reject for some protocol.
- */
-void
-lcp_sprotrej(unit, p, len)
- int unit;
- u_char *p;
- int len;
-{
- /*
- * Send back the protocol and the information field of the
- * rejected packet. We only get here if LCP is in the OPENED state.
- */
- p += 2;
- len -= 2;
-
- fsm_sdata(&lcp_fsm[unit], PROTREJ, ++lcp_fsm[unit].id,
- p, len);
-}
-
-
-/*
- * lcp_resetci - Reset our CI.
- */
-static void
-lcp_resetci(f)
- fsm *f;
-{
- lcp_wantoptions[f->unit].magicnumber = magic();
- lcp_wantoptions[f->unit].numloops = 0;
- lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit];
- peer_mru[f->unit] = PPP_MRU;
- auth_reset(f->unit);
-}
-
-
-/*
- * lcp_cilen - Return length of our CI.
- */
-static int
-lcp_cilen(f)
- fsm *f;
-{
- lcp_options *go = &lcp_gotoptions[f->unit];
-
-#define LENCIVOID(neg) ((neg) ? CILEN_VOID : 0)
-#define LENCICHAP(neg) ((neg) ? CILEN_CHAP : 0)
-#define LENCISHORT(neg) ((neg) ? CILEN_SHORT : 0)
-#define LENCILONG(neg) ((neg) ? CILEN_LONG : 0)
-#define LENCILQR(neg) ((neg) ? CILEN_LQR: 0)
-#define LENCICBCP(neg) ((neg) ? CILEN_CBCP: 0)
- /*
- * NB: we only ask for one of CHAP and UPAP, even if we will
- * accept either.
- */
- return (LENCISHORT(go->neg_mru && go->mru != DEFMRU) +
- LENCILONG(go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) +
- LENCICHAP(go->neg_chap) +
- LENCISHORT(!go->neg_chap && go->neg_upap) +
- LENCILQR(go->neg_lqr) +
- LENCICBCP(go->neg_cbcp) +
- LENCILONG(go->neg_magicnumber) +
- LENCIVOID(go->neg_pcompression) +
- LENCIVOID(go->neg_accompression));
-}
-
-
-/*
- * lcp_addci - Add our desired CIs to a packet.
- */
-static void
-lcp_addci(f, ucp, lenp)
- fsm *f;
- u_char *ucp;
- int *lenp;
-{
- lcp_options *go = &lcp_gotoptions[f->unit];
- u_char *start_ucp = ucp;
-
-#define ADDCIVOID(opt, neg) \
- if (neg) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(CILEN_VOID, ucp); \
- }
-#define ADDCISHORT(opt, neg, val) \
- if (neg) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(CILEN_SHORT, ucp); \
- PUTSHORT(val, ucp); \
- }
-#define ADDCICHAP(opt, neg, val, digest) \
- if (neg) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(CILEN_CHAP, ucp); \
- PUTSHORT(val, ucp); \
- PUTCHAR(digest, ucp); \
- }
-#define ADDCILONG(opt, neg, val) \
- if (neg) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(CILEN_LONG, ucp); \
- PUTLONG(val, ucp); \
- }
-#define ADDCILQR(opt, neg, val) \
- if (neg) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(CILEN_LQR, ucp); \
- PUTSHORT(PPP_LQR, ucp); \
- PUTLONG(val, ucp); \
- }
-#define ADDCICHAR(opt, neg, val) \
- if (neg) { \
- PUTCHAR(opt, ucp); \
- PUTCHAR(CILEN_CHAR, ucp); \
- PUTCHAR(val, ucp); \
- }
-
- ADDCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
- ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
- go->asyncmap);
- ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
- ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
- ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
- ADDCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
- ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
- ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
- ADDCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
-
- if (ucp - start_ucp != *lenp) {
- /* this should never happen, because peer_mtu should be 1500 */
- syslog(LOG_ERR, "Bug in lcp_addci: wrong length");
- }
-}
-
-
-/*
- * lcp_ackci - Ack our CIs.
- * This should not modify any state if the Ack is bad.
- *
- * Returns:
- * 0 - Ack was bad.
- * 1 - Ack was good.
- */
-static int
-lcp_ackci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- lcp_options *go = &lcp_gotoptions[f->unit];
- u_char cilen, citype, cichar;
- u_short cishort;
- u_int32_t cilong;
-
- /*
- * CIs must be in exactly the same order that we sent.
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
-#define ACKCIVOID(opt, neg) \
- if (neg) { \
- if ((len -= CILEN_VOID) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_VOID || \
- citype != opt) \
- goto bad; \
- }
-#define ACKCISHORT(opt, neg, val) \
- if (neg) { \
- if ((len -= CILEN_SHORT) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_SHORT || \
- citype != opt) \
- goto bad; \
- GETSHORT(cishort, p); \
- if (cishort != val) \
- goto bad; \
- }
-#define ACKCICHAR(opt, neg, val) \
- if (neg) { \
- if ((len -= CILEN_CHAR) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_CHAR || \
- citype != opt) \
- goto bad; \
- GETCHAR(cichar, p); \
- if (cichar != val) \
- goto bad; \
- }
-#define ACKCICHAP(opt, neg, val, digest) \
- if (neg) { \
- if ((len -= CILEN_CHAP) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_CHAP || \
- citype != opt) \
- goto bad; \
- GETSHORT(cishort, p); \
- if (cishort != val) \
- goto bad; \
- GETCHAR(cichar, p); \
- if (cichar != digest) \
- goto bad; \
- }
-#define ACKCILONG(opt, neg, val) \
- if (neg) { \
- if ((len -= CILEN_LONG) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_LONG || \
- citype != opt) \
- goto bad; \
- GETLONG(cilong, p); \
- if (cilong != val) \
- goto bad; \
- }
-#define ACKCILQR(opt, neg, val) \
- if (neg) { \
- if ((len -= CILEN_LQR) < 0) \
- goto bad; \
- GETCHAR(citype, p); \
- GETCHAR(cilen, p); \
- if (cilen != CILEN_LQR || \
- citype != opt) \
- goto bad; \
- GETSHORT(cishort, p); \
- if (cishort != PPP_LQR) \
- goto bad; \
- GETLONG(cilong, p); \
- if (cilong != val) \
- goto bad; \
- }
-
- ACKCISHORT(CI_MRU, go->neg_mru && go->mru != DEFMRU, go->mru);
- ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF,
- go->asyncmap);
- ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype);
- ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP);
- ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period);
- ACKCICHAR(CI_CALLBACK, go->neg_cbcp, CBCP_OPT);
- ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber);
- ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression);
- ACKCIVOID(CI_ACCOMPRESSION, go->neg_accompression);
-
- /*
- * If there are any remaining CIs, then this packet is bad.
- */
- if (len != 0)
- goto bad;
- return (1);
-bad:
- LCPDEBUG((LOG_WARNING, "lcp_acki: received bad Ack!"));
- return (0);
-}
-
-
-/*
- * lcp_nakci - Peer has sent a NAK for some of our CIs.
- * This should not modify any state if the Nak is bad
- * or if LCP is in the OPENED state.
- *
- * Returns:
- * 0 - Nak was bad.
- * 1 - Nak was good.
- */
-static int
-lcp_nakci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- lcp_options *go = &lcp_gotoptions[f->unit];
- lcp_options *wo = &lcp_wantoptions[f->unit];
- u_char citype, cichar, *next;
- u_short cishort;
- u_int32_t cilong;
- lcp_options no; /* options we've seen Naks for */
- lcp_options try; /* options to request next time */
- int looped_back = 0;
- int cilen;
-
- BZERO(&no, sizeof(no));
- try = *go;
-
- /*
- * Any Nak'd CIs must be in exactly the same order that we sent.
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
-#define NAKCIVOID(opt, neg, code) \
- if (go->neg && \
- len >= CILEN_VOID && \
- p[1] == CILEN_VOID && \
- p[0] == opt) { \
- len -= CILEN_VOID; \
- INCPTR(CILEN_VOID, p); \
- no.neg = 1; \
- code \
- }
-#define NAKCICHAP(opt, neg, code) \
- if (go->neg && \
- len >= CILEN_CHAP && \
- p[1] == CILEN_CHAP && \
- p[0] == opt) { \
- len -= CILEN_CHAP; \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- GETCHAR(cichar, p); \
- no.neg = 1; \
- code \
- }
-#define NAKCICHAR(opt, neg, code) \
- if (go->neg && \
- len >= CILEN_CHAR && \
- p[1] == CILEN_CHAR && \
- p[0] == opt) { \
- len -= CILEN_CHAR; \
- INCPTR(2, p); \
- GETCHAR(cichar, p); \
- no.neg = 1; \
- code \
- }
-#define NAKCISHORT(opt, neg, code) \
- if (go->neg && \
- len >= CILEN_SHORT && \
- p[1] == CILEN_SHORT && \
- p[0] == opt) { \
- len -= CILEN_SHORT; \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- no.neg = 1; \
- code \
- }
-#define NAKCILONG(opt, neg, code) \
- if (go->neg && \
- len >= CILEN_LONG && \
- p[1] == CILEN_LONG && \
- p[0] == opt) { \
- len -= CILEN_LONG; \
- INCPTR(2, p); \
- GETLONG(cilong, p); \
- no.neg = 1; \
- code \
- }
-#define NAKCILQR(opt, neg, code) \
- if (go->neg && \
- len >= CILEN_LQR && \
- p[1] == CILEN_LQR && \
- p[0] == opt) { \
- len -= CILEN_LQR; \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- GETLONG(cilong, p); \
- no.neg = 1; \
- code \
- }
-
- /*
- * We don't care if they want to send us smaller packets than
- * we want. Therefore, accept any MRU less than what we asked for,
- * but then ignore the new value when setting the MRU in the kernel.
- * If they send us a bigger MRU than what we asked, accept it, up to
- * the limit of the default MRU we'd get if we didn't negotiate.
- */
- if (go->neg_mru && go->mru != DEFMRU) {
- NAKCISHORT(CI_MRU, neg_mru,
- if (cishort <= wo->mru || cishort <= DEFMRU)
- try.mru = cishort;
- );
- }
-
- /*
- * Add any characters they want to our (receive-side) asyncmap.
- */
- if (go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF) {
- NAKCILONG(CI_ASYNCMAP, neg_asyncmap,
- try.asyncmap = go->asyncmap | cilong;
- );
- }
-
- /*
- * If they've nak'd our authentication-protocol, check whether
- * they are proposing a different protocol, or a different
- * hash algorithm for CHAP.
- */
- if ((go->neg_chap || go->neg_upap)
- && len >= CILEN_SHORT
- && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT && p[1] <= len) {
- cilen = p[1];
- len -= cilen;
- no.neg_chap = go->neg_chap;
- no.neg_upap = go->neg_upap;
- INCPTR(2, p);
- GETSHORT(cishort, p);
- if (cishort == PPP_PAP && cilen == CILEN_SHORT) {
- /*
- * If we were asking for CHAP, they obviously don't want to do it.
- * If we weren't asking for CHAP, then we were asking for PAP,
- * in which case this Nak is bad.
- */
- if (!go->neg_chap)
- goto bad;
- try.neg_chap = 0;
-
- } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) {
- GETCHAR(cichar, p);
- if (go->neg_chap) {
- /*
- * We were asking for CHAP/MD5; they must want a different
- * algorithm. If they can't do MD5, we'll have to stop
- * asking for CHAP.
- */
- if (cichar != go->chap_mdtype)
- try.neg_chap = 0;
- } else {
- /*
- * Stop asking for PAP if we were asking for it.
- */
- try.neg_upap = 0;
- }
-
- } else {
- /*
- * We don't recognize what they're suggesting.
- * Stop asking for what we were asking for.
- */
- if (go->neg_chap)
- try.neg_chap = 0;
- else
- try.neg_upap = 0;
- p += cilen - CILEN_SHORT;
- }
- }
-
- /*
- * If they can't cope with our link quality protocol, we'll have
- * to stop asking for LQR. We haven't got any other protocol.
- * If they Nak the reporting period, take their value XXX ?
- */
- NAKCILQR(CI_QUALITY, neg_lqr,
- if (cishort != PPP_LQR)
- try.neg_lqr = 0;
- else
- try.lqr_period = cilong;
- );
-
- /*
- * Only implementing CBCP...not the rest of the callback options
- */
- NAKCICHAR(CI_CALLBACK, neg_cbcp,
- try.neg_cbcp = 0;
- );
-
- /*
- * Check for a looped-back line.
- */
- NAKCILONG(CI_MAGICNUMBER, neg_magicnumber,
- try.magicnumber = magic();
- looped_back = 1;
- );
-
- /*
- * Peer shouldn't send Nak for protocol compression or
- * address/control compression requests; they should send
- * a Reject instead. If they send a Nak, treat it as a Reject.
- */
- NAKCIVOID(CI_PCOMPRESSION, neg_pcompression,
- try.neg_pcompression = 0;
- );
- NAKCIVOID(CI_ACCOMPRESSION, neg_accompression,
- try.neg_accompression = 0;
- );
-
- /*
- * There may be remaining CIs, if the peer is requesting negotiation
- * on an option that we didn't include in our request packet.
- * If we see an option that we requested, or one we've already seen
- * in this packet, then this packet is bad.
- * If we wanted to respond by starting to negotiate on the requested
- * option(s), we could, but we don't, because except for the
- * authentication type and quality protocol, if we are not negotiating
- * an option, it is because we were told not to.
- * For the authentication type, the Nak from the peer means
- * `let me authenticate myself with you' which is a bit pointless.
- * For the quality protocol, the Nak means `ask me to send you quality
- * reports', but if we didn't ask for them, we don't want them.
- * An option we don't recognize represents the peer asking to
- * negotiate some option we don't support, so ignore it.
- */
- while (len > CILEN_VOID) {
- GETCHAR(citype, p);
- GETCHAR(cilen, p);
- if (cilen < CILEN_VOID || (len -= cilen) < 0)
- goto bad;
- next = p + cilen - 2;
-
- switch (citype) {
- case CI_MRU:
- if ((go->neg_mru && go->mru != DEFMRU)
- || no.neg_mru || cilen != CILEN_SHORT)
- goto bad;
- GETSHORT(cishort, p);
- if (cishort < DEFMRU)
- try.mru = cishort;
- break;
- case CI_ASYNCMAP:
- if ((go->neg_asyncmap && go->asyncmap != 0xFFFFFFFF)
- || no.neg_asyncmap || cilen != CILEN_LONG)
- goto bad;
- break;
- case CI_AUTHTYPE:
- if (go->neg_chap || no.neg_chap || go->neg_upap || no.neg_upap)
- goto bad;
- break;
- case CI_MAGICNUMBER:
- if (go->neg_magicnumber || no.neg_magicnumber ||
- cilen != CILEN_LONG)
- goto bad;
- break;
- case CI_PCOMPRESSION:
- if (go->neg_pcompression || no.neg_pcompression
- || cilen != CILEN_VOID)
- goto bad;
- break;
- case CI_ACCOMPRESSION:
- if (go->neg_accompression || no.neg_accompression
- || cilen != CILEN_VOID)
- goto bad;
- break;
- case CI_QUALITY:
- if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR)
- goto bad;
- break;
- }
- p = next;
- }
-
- /* If there is still anything left, this packet is bad. */
- if (len != 0)
- goto bad;
-
- /*
- * OK, the Nak is good. Now we can update state.
- */
- if (f->state != OPENED) {
- if (looped_back) {
- if (++try.numloops >= lcp_loopbackfail) {
- syslog(LOG_NOTICE, "Serial line is looped back.");
- lcp_close(f->unit, "Loopback detected");
- }
- } else
- try.numloops = 0;
- *go = try;
- }
-
- return 1;
-
-bad:
- LCPDEBUG((LOG_WARNING, "lcp_nakci: received bad Nak!"));
- return 0;
-}
-
-
-/*
- * lcp_rejci - Peer has Rejected some of our CIs.
- * This should not modify any state if the Reject is bad
- * or if LCP is in the OPENED state.
- *
- * Returns:
- * 0 - Reject was bad.
- * 1 - Reject was good.
- */
-static int
-lcp_rejci(f, p, len)
- fsm *f;
- u_char *p;
- int len;
-{
- lcp_options *go = &lcp_gotoptions[f->unit];
- u_char cichar;
- u_short cishort;
- u_int32_t cilong;
- lcp_options try; /* options to request next time */
-
- try = *go;
-
- /*
- * Any Rejected CIs must be in exactly the same order that we sent.
- * Check packet length and CI length at each step.
- * If we find any deviations, then this packet is bad.
- */
-#define REJCIVOID(opt, neg) \
- if (go->neg && \
- len >= CILEN_VOID && \
- p[1] == CILEN_VOID && \
- p[0] == opt) { \
- len -= CILEN_VOID; \
- INCPTR(CILEN_VOID, p); \
- try.neg = 0; \
- LCPDEBUG((LOG_INFO, "lcp_rejci rejected void opt %d", opt)); \
- }
-#define REJCISHORT(opt, neg, val) \
- if (go->neg && \
- len >= CILEN_SHORT && \
- p[1] == CILEN_SHORT && \
- p[0] == opt) { \
- len -= CILEN_SHORT; \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- /* Check rejected value. */ \
- if (cishort != val) \
- goto bad; \
- try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci rejected short opt %d", opt)); \
- }
-#define REJCICHAP(opt, neg, val, digest) \
- if (go->neg && \
- len >= CILEN_CHAP && \
- p[1] == CILEN_CHAP && \
- p[0] == opt) { \
- len -= CILEN_CHAP; \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- GETCHAR(cichar, p); \
- /* Check rejected value. */ \
- if (cishort != val || cichar != digest) \
- goto bad; \
- try.neg = 0; \
- try.neg_upap = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci rejected chap opt %d", opt)); \
- }
-#define REJCILONG(opt, neg, val) \
- if (go->neg && \
- len >= CILEN_LONG && \
- p[1] == CILEN_LONG && \
- p[0] == opt) { \
- len -= CILEN_LONG; \
- INCPTR(2, p); \
- GETLONG(cilong, p); \
- /* Check rejected value. */ \
- if (cilong != val) \
- goto bad; \
- try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci rejected long opt %d", opt)); \
- }
-#define REJCILQR(opt, neg, val) \
- if (go->neg && \
- len >= CILEN_LQR && \
- p[1] == CILEN_LQR && \
- p[0] == opt) { \
- len -= CILEN_LQR; \
- INCPTR(2, p); \
- GETSHORT(cishort, p); \
- GETLONG(cilong, p); \
- /* Check rejected value. */ \
- if (cishort != PPP_LQR || cilong != val) \
- goto bad; \
- try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci rejected LQR opt %d", opt)); \
- }
-#define REJCICBCP(opt, neg, val) \
- if (go->neg && \
- len >= CILEN_CBCP && \
- p[1] == CILEN_CBCP && \
- p[0] == opt) { \
- len -= CILEN_CBCP; \
- INCPTR(2, p); \
- GETCHAR(cichar, p); \
- /* Check rejected value. */ \
- if (cichar != val) \
- goto bad; \
- try.neg = 0; \
- LCPDEBUG((LOG_INFO,"lcp_rejci rejected Callback opt %d", opt)); \
- }
-
- REJCISHORT(CI_MRU, neg_mru, go->mru);
- REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap);
- REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype);
- if (!go->neg_chap) {
- REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP);
- }
- REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period);
- REJCICBCP(CI_CALLBACK, neg_cbcp, CBCP_OPT);
- REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber);
- REJCIVOID(CI_PCOMPRESSION, neg_pcompression);
- REJCIVOID(CI_ACCOMPRESSION, neg_accompression);
-
- /*
- * If there are any remaining CIs, then this packet is bad.
- */
- if (len != 0)
- goto bad;
- /*
- * Now we can update state.
- */
- if (f->state != OPENED)
- *go = try;
- return 1;
-
-bad:
- LCPDEBUG((LOG_WARNING, "lcp_rejci: received bad Reject!"));
- return 0;
-}
-
-
-/*
- * lcp_reqci - Check the peer's requested CIs and send appropriate response.
- *
- * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
- * appropriately. If reject_if_disagree is non-zero, doesn't return
- * CONFNAK; returns CONFREJ if it can't return CONFACK.
- */
-static int
-lcp_reqci(f, inp, lenp, reject_if_disagree)
- fsm *f;
- u_char *inp; /* Requested CIs */
- int *lenp; /* Length of requested CIs */
- int reject_if_disagree;
-{
- lcp_options *go = &lcp_gotoptions[f->unit];
- lcp_options *ho = &lcp_hisoptions[f->unit];
- lcp_options *ao = &lcp_allowoptions[f->unit];
- u_char *cip, *next; /* Pointer to current and next CIs */
- int cilen, citype, cichar; /* Parsed len, type, char value */
- u_short cishort; /* Parsed short value */
- u_int32_t cilong; /* Parse long value */
- int rc = CONFACK; /* Final packet return code */
- int orc; /* Individual option return code */
- u_char *p; /* Pointer to next char to parse */
- u_char *rejp; /* Pointer to next char in reject frame */
- u_char *nakp; /* Pointer to next char in Nak frame */
- int l = *lenp; /* Length left */
-
- /*
- * Reset all his options.
- */
- BZERO(ho, sizeof(*ho));
-
- /*
- * Process all his options.
- */
- next = inp;
- nakp = nak_buffer;
- rejp = inp;
- while (l) {
- orc = CONFACK; /* Assume success */
- cip = p = next; /* Remember begining of CI */
- if (l < 2 || /* Not enough data for CI header or */
- p[1] < 2 || /* CI length too small or */
- p[1] > l) { /* CI length too big? */
- LCPDEBUG((LOG_WARNING, "lcp_reqci: bad CI length!"));
- orc = CONFREJ; /* Reject bad CI */
- cilen = l; /* Reject till end of packet */
- l = 0; /* Don't loop again */
- citype = 0;
- goto endswitch;
- }
- GETCHAR(citype, p); /* Parse CI type */
- GETCHAR(cilen, p); /* Parse CI length */
- l -= cilen; /* Adjust remaining length */
- next += cilen; /* Step to next CI */
-
- switch (citype) { /* Check CI type */
- case CI_MRU:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MRU"));
- if (!ao->neg_mru || /* Allow option? */
- cilen != CILEN_SHORT) { /* Check CI length */
- orc = CONFREJ; /* Reject CI */
- break;
- }
- GETSHORT(cishort, p); /* Parse MRU */
- LCPDEBUG((LOG_INFO, "(%d)", cishort));
-
- /*
- * He must be able to receive at least our minimum.
- * No need to check a maximum. If he sends a large number,
- * we'll just ignore it.
- */
- if (cishort < MINMRU) {
- orc = CONFNAK; /* Nak CI */
- PUTCHAR(CI_MRU, nakp);
- PUTCHAR(CILEN_SHORT, nakp);
- PUTSHORT(MINMRU, nakp); /* Give him a hint */
- break;
- }
- ho->neg_mru = 1; /* Remember he sent MRU */
- ho->mru = cishort; /* And remember value */
- break;
-
- case CI_ASYNCMAP:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ASYNCMAP"));
- if (!ao->neg_asyncmap ||
- cilen != CILEN_LONG) {
- orc = CONFREJ;
- break;
- }
- GETLONG(cilong, p);
- LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong));
-
- /*
- * Asyncmap must have set at least the bits
- * which are set in lcp_allowoptions[unit].asyncmap.
- */
- if ((ao->asyncmap & ~cilong) != 0) {
- orc = CONFNAK;
- PUTCHAR(CI_ASYNCMAP, nakp);
- PUTCHAR(CILEN_LONG, nakp);
- PUTLONG(ao->asyncmap | cilong, nakp);
- break;
- }
- ho->neg_asyncmap = 1;
- ho->asyncmap = cilong;
- break;
-
- case CI_AUTHTYPE:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd AUTHTYPE"));
- if (cilen < CILEN_SHORT ||
- !(ao->neg_upap || ao->neg_chap)) {
- /*
- * Reject the option if we're not willing to authenticate.
- */
- orc = CONFREJ;
- break;
- }
- GETSHORT(cishort, p);
- LCPDEBUG((LOG_INFO, "(%x)", cishort));
-
- /*
- * Authtype must be UPAP or CHAP.
- *
- * Note: if both ao->neg_upap and ao->neg_chap are set,
- * and the peer sends a Configure-Request with two
- * authenticate-protocol requests, one for CHAP and one
- * for UPAP, then we will reject the second request.
- * Whether we end up doing CHAP or UPAP depends then on
- * the ordering of the CIs in the peer's Configure-Request.
- */
-
- if (cishort == PPP_PAP) {
- if (ho->neg_chap || /* we've already accepted CHAP */
- cilen != CILEN_SHORT) {
- LCPDEBUG((LOG_WARNING,
- "lcp_reqci: rcvd AUTHTYPE PAP, rejecting..."));
- orc = CONFREJ;
- break;
- }
- if (!ao->neg_upap) { /* we don't want to do PAP */
- orc = CONFNAK; /* NAK it and suggest CHAP */
- PUTCHAR(CI_AUTHTYPE, nakp);
- PUTCHAR(CILEN_CHAP, nakp);
- PUTSHORT(PPP_CHAP, nakp);
- PUTCHAR(ao->chap_mdtype, nakp);
- break;
- }
- ho->neg_upap = 1;
- break;
- }
- if (cishort == PPP_CHAP) {
- if (ho->neg_upap || /* we've already accepted PAP */
- cilen != CILEN_CHAP) {
- LCPDEBUG((LOG_INFO,
- "lcp_reqci: rcvd AUTHTYPE CHAP, rejecting..."));
- orc = CONFREJ;
- break;
- }
- if (!ao->neg_chap) { /* we don't want to do CHAP */
- orc = CONFNAK; /* NAK it and suggest PAP */
- PUTCHAR(CI_AUTHTYPE, nakp);
- PUTCHAR(CILEN_SHORT, nakp);
- PUTSHORT(PPP_PAP, nakp);
- break;
- }
- GETCHAR(cichar, p); /* get digest type*/
- if (cichar != CHAP_DIGEST_MD5
-#ifdef CHAPMS
- && cichar != CHAP_MICROSOFT
-#endif
- ) {
- orc = CONFNAK;
- PUTCHAR(CI_AUTHTYPE, nakp);
- PUTCHAR(CILEN_CHAP, nakp);
- PUTSHORT(PPP_CHAP, nakp);
- PUTCHAR(ao->chap_mdtype, nakp);
- break;
- }
- ho->chap_mdtype = cichar; /* save md type */
- ho->neg_chap = 1;
- break;
- }
-
- /*
- * We don't recognize the protocol they're asking for.
- * Nak it with something we're willing to do.
- * (At this point we know ao->neg_upap || ao->neg_chap.)
- */
- orc = CONFNAK;
- PUTCHAR(CI_AUTHTYPE, nakp);
- if (ao->neg_chap) {
- PUTCHAR(CILEN_CHAP, nakp);
- PUTSHORT(PPP_CHAP, nakp);
- PUTCHAR(ao->chap_mdtype, nakp);
- } else {
- PUTCHAR(CILEN_SHORT, nakp);
- PUTSHORT(PPP_PAP, nakp);
- }
- break;
-
- case CI_QUALITY:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd QUALITY"));
- if (!ao->neg_lqr ||
- cilen != CILEN_LQR) {
- orc = CONFREJ;
- break;
- }
-
- GETSHORT(cishort, p);
- GETLONG(cilong, p);
- LCPDEBUG((LOG_INFO, "(%x %x)", cishort, (unsigned int) cilong));
-
- /*
- * Check the protocol and the reporting period.
- * XXX When should we Nak this, and what with?
- */
- if (cishort != PPP_LQR) {
- orc = CONFNAK;
- PUTCHAR(CI_QUALITY, nakp);
- PUTCHAR(CILEN_LQR, nakp);
- PUTSHORT(PPP_LQR, nakp);
- PUTLONG(ao->lqr_period, nakp);
- break;
- }
- break;
-
- case CI_MAGICNUMBER:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd MAGICNUMBER"));
- if (!(ao->neg_magicnumber || go->neg_magicnumber) ||
- cilen != CILEN_LONG) {
- orc = CONFREJ;
- break;
- }
- GETLONG(cilong, p);
- LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong));
-
- /*
- * He must have a different magic number.
- */
- if (go->neg_magicnumber &&
- cilong == go->magicnumber) {
- cilong = magic(); /* Don't put magic() inside macro! */
- orc = CONFNAK;
- PUTCHAR(CI_MAGICNUMBER, nakp);
- PUTCHAR(CILEN_LONG, nakp);
- PUTLONG(cilong, nakp);
- break;
- }
- ho->neg_magicnumber = 1;
- ho->magicnumber = cilong;
- break;
-
-
- case CI_PCOMPRESSION:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd PCOMPRESSION"));
- if (!ao->neg_pcompression ||
- cilen != CILEN_VOID) {
- orc = CONFREJ;
- break;
- }
- ho->neg_pcompression = 1;
- break;
-
- case CI_ACCOMPRESSION:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd ACCOMPRESSION"));
- if (!ao->neg_accompression ||
- cilen != CILEN_VOID) {
- orc = CONFREJ;
- break;
- }
- ho->neg_accompression = 1;
- break;
-
- default:
- LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd unknown option %d",
- citype));
- orc = CONFREJ;
- break;
- }
-
-endswitch:
- LCPDEBUG((LOG_INFO, " (%s)", CODENAME(orc)));
- if (orc == CONFACK && /* Good CI */
- rc != CONFACK) /* but prior CI wasnt? */
- continue; /* Don't send this one */
-
- if (orc == CONFNAK) { /* Nak this CI? */
- if (reject_if_disagree /* Getting fed up with sending NAKs? */
- && citype != CI_MAGICNUMBER) {
- orc = CONFREJ; /* Get tough if so */
- } else {
- if (rc == CONFREJ) /* Rejecting prior CI? */
- continue; /* Don't send this one */
- rc = CONFNAK;
- }
- }
- if (orc == CONFREJ) { /* Reject this CI */
- rc = CONFREJ;
- if (cip != rejp) /* Need to move rejected CI? */
- BCOPY(cip, rejp, cilen); /* Move it */
- INCPTR(cilen, rejp); /* Update output pointer */
- }
- }
-
- /*
- * If we wanted to send additional NAKs (for unsent CIs), the
- * code would go here. The extra NAKs would go at *nakp.
- * At present there are no cases where we want to ask the
- * peer to negotiate an option.
- */
-
- switch (rc) {
- case CONFACK:
- *lenp = next - inp;
- break;
- case CONFNAK:
- /*
- * Copy the Nak'd options from the nak_buffer to the caller's buffer.
- */
- *lenp = nakp - nak_buffer;
- BCOPY(nak_buffer, inp, *lenp);
- break;
- case CONFREJ:
- *lenp = rejp - inp;
- break;
- }
-
- LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.", CODENAME(rc)));
- return (rc); /* Return final code */
-}
-
-
-/*
- * lcp_up - LCP has come UP.
- */
-static void
-lcp_up(f)
- fsm *f;
-{
- lcp_options *wo = &lcp_wantoptions[f->unit];
- lcp_options *ho = &lcp_hisoptions[f->unit];
- lcp_options *go = &lcp_gotoptions[f->unit];
- lcp_options *ao = &lcp_allowoptions[f->unit];
-
- if (!go->neg_magicnumber)
- go->magicnumber = 0;
- if (!ho->neg_magicnumber)
- ho->magicnumber = 0;
-
- /*
- * Set our MTU to the smaller of the MTU we wanted and
- * the MRU our peer wanted. If we negotiated an MRU,
- * set our MRU to the larger of value we wanted and
- * the value we got in the negotiation.
- */
- ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)),
- (ho->neg_asyncmap? ho->asyncmap: 0xffffffff),
- ho->neg_pcompression, ho->neg_accompression);
- ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU),
- (go->neg_asyncmap? go->asyncmap: 0xffffffff),
- go->neg_pcompression, go->neg_accompression);
-
- if (ho->neg_mru)
- peer_mru[f->unit] = ho->mru;
-
- lcp_echo_lowerup(f->unit); /* Enable echo messages */
-
- link_established(f->unit);
-}
-
-
-/*
- * lcp_down - LCP has gone DOWN.
- *
- * Alert other protocols.
- */
-static void
-lcp_down(f)
- fsm *f;
-{
- lcp_options *go = &lcp_gotoptions[f->unit];
-
- lcp_echo_lowerdown(f->unit);
-
- link_down(f->unit);
-
- ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0);
- ppp_recv_config(f->unit, PPP_MRU,
- (go->neg_asyncmap? go->asyncmap: 0xffffffff),
- go->neg_pcompression, go->neg_accompression);
- peer_mru[f->unit] = PPP_MRU;
-}
-
-
-/*
- * lcp_starting - LCP needs the lower layer up.
- */
-static void
-lcp_starting(f)
- fsm *f;
-{
- link_required(f->unit);
-}
-
-
-/*
- * lcp_finished - LCP has finished with the lower layer.
- */
-static void
-lcp_finished(f)
- fsm *f;
-{
- link_terminated(f->unit);
-}
-
-
-/*
- * lcp_printpkt - print the contents of an LCP packet.
- */
-static char *lcp_codenames[] = {
- "ConfReq", "ConfAck", "ConfNak", "ConfRej",
- "TermReq", "TermAck", "CodeRej", "ProtRej",
- "EchoReq", "EchoRep", "DiscReq"
-};
-
-static int
-lcp_printpkt(p, plen, printer, arg)
- u_char *p;
- int plen;
- void (*printer)(void *, char *, ...);
- void *arg;
-{
- int code, id, len, olen;
- u_char *pstart, *optend;
- u_short cishort;
- u_int32_t cilong;
-
- if (plen < HEADERLEN)
- return 0;
- pstart = p;
- GETCHAR(code, p);
- GETCHAR(id, p);
- GETSHORT(len, p);
- if (len < HEADERLEN || len > plen)
- return 0;
-
- if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *))
- printer(arg, " %s", lcp_codenames[code-1]);
- else
- printer(arg, " code=0x%x", code);
- printer(arg, " id=0x%x", id);
- len -= HEADERLEN;
- switch (code) {
- case CONFREQ:
- case CONFACK:
- case CONFNAK:
- case CONFREJ:
- /* print option list */
- while (len >= 2) {
- GETCHAR(code, p);
- GETCHAR(olen, p);
- p -= 2;
- if (olen < 2 || olen > len) {
- break;
- }
- printer(arg, " <");
- len -= olen;
- optend = p + olen;
- switch (code) {
- case CI_MRU:
- if (olen == CILEN_SHORT) {
- p += 2;
- GETSHORT(cishort, p);
- printer(arg, "mru %d", cishort);
- }
- break;
- case CI_ASYNCMAP:
- if (olen == CILEN_LONG) {
- p += 2;
- GETLONG(cilong, p);
- printer(arg, "asyncmap 0x%x", cilong);
- }
- break;
- case CI_AUTHTYPE:
- if (olen >= CILEN_SHORT) {
- p += 2;
- printer(arg, "auth ");
- GETSHORT(cishort, p);
- switch (cishort) {
- case PPP_PAP:
- printer(arg, "pap");
- break;
- case PPP_CHAP:
- printer(arg, "chap");
- break;
- default:
- printer(arg, "0x%x", cishort);
- }
- }
- break;
- case CI_QUALITY:
- if (olen >= CILEN_SHORT) {
- p += 2;
- printer(arg, "quality ");
- GETSHORT(cishort, p);
- switch (cishort) {
- case PPP_LQR:
- printer(arg, "lqr");
- break;
- default:
- printer(arg, "0x%x", cishort);
- }
- }
- break;
- case CI_CALLBACK:
- if (olen >= CILEN_CHAR) {
- p += 2;
- printer(arg, "callback ");
- GETSHORT(cishort, p);
- switch (cishort) {
- case CBCP_OPT:
- printer(arg, "CBCP");
- break;
- default:
- printer(arg, "0x%x", cishort);
- }
- }
- break;
- case CI_MAGICNUMBER:
- if (olen == CILEN_LONG) {
- p += 2;
- GETLONG(cilong, p);
- printer(arg, "magic 0x%x", cilong);
- }
- break;
- case CI_PCOMPRESSION:
- if (olen == CILEN_VOID) {
- p += 2;
- printer(arg, "pcomp");
- }
- break;
- case CI_ACCOMPRESSION:
- if (olen == CILEN_VOID) {
- p += 2;
- printer(arg, "accomp");
- }
- break;
- }
- while (p < optend) {
- GETCHAR(code, p);
- printer(arg, " %.2x", code);
- }
- printer(arg, ">");
- }
- break;
-
- case TERMACK:
- case TERMREQ:
- if (len > 0 && *p >= ' ' && *p < 0x7f) {
- printer(arg, " ");
- print_string(p, len, printer, arg);
- p += len;
- len = 0;
- }
- break;
-
- case ECHOREQ:
- case ECHOREP:
- case DISCREQ:
- if (len >= 4) {
- GETLONG(cilong, p);
- printer(arg, " magic=0x%x", cilong);
- p += 4;
- len -= 4;
- }
- break;
- }
-
- /* print the rest of the bytes in the packet */
- for (; len > 0; --len) {
- GETCHAR(code, p);
- printer(arg, " %.2x", code);
- }
-
- return p - pstart;
-}
-
-/*
- * Time to shut down the link because there is nothing out there.
- */
-
-static
-void LcpLinkFailure (f)
- fsm *f;
-{
- if (f->state == OPENED) {
- syslog(LOG_INFO, "No response to %d echo-requests", lcp_echos_pending);
- syslog(LOG_NOTICE, "Serial link appears to be disconnected.");
- lcp_close(f->unit, "Peer not responding");
- }
-}
-
-/*
- * Timer expired for the LCP echo requests from this process.
- */
-
-static void
-LcpEchoCheck (f)
- fsm *f;
-{
- LcpSendEchoRequest (f);
- if (f->state != OPENED)
- return;
-
- /*
- * Start the timer for the next interval.
- */
- assert (lcp_echo_timer_running==0);
- TIMEOUT (LcpEchoTimeout, f, lcp_echo_interval);
- lcp_echo_timer_running = 1;
-}
-
-/*
- * LcpEchoTimeout - Timer expired on the LCP echo
- */
-
-static void
-LcpEchoTimeout (arg)
- void *arg;
-{
- if (lcp_echo_timer_running != 0) {
- lcp_echo_timer_running = 0;
- LcpEchoCheck ((fsm *) arg);
- }
-}
-
-/*
- * LcpEchoReply - LCP has received a reply to the echo
- */
-
-static void
-lcp_received_echo_reply (f, id, inp, len)
- fsm *f;
- int id; u_char *inp; int len;
-{
- u_int32_t magic;
-
- /* Check the magic number - don't count replies from ourselves. */
- if (len < 4) {
- syslog(LOG_DEBUG, "lcp: received short Echo-Reply, length %d", len);
- return;
- }
- GETLONG(magic, inp);
- if (lcp_gotoptions[f->unit].neg_magicnumber
- && magic == lcp_gotoptions[f->unit].magicnumber) {
- syslog(LOG_WARNING, "appear to have received our own echo-reply!");
- return;
- }
-
- /* Reset the number of outstanding echo frames */
- lcp_echos_pending = 0;
-}
-
-/*
- * LcpSendEchoRequest - Send an echo request frame to the peer
- */
-
-static void
-LcpSendEchoRequest (f)
- fsm *f;
-{
- u_int32_t lcp_magic;
- u_char pkt[4], *pktp;
-
- /*
- * Detect the failure of the peer at this point.
- */
- if (lcp_echo_fails != 0) {
- if (lcp_echos_pending >= lcp_echo_fails) {
- LcpLinkFailure(f);
- lcp_echos_pending = 0;
- }
- }
-
- /*
- * Make and send the echo request frame.
- */
- if (f->state == OPENED) {
- lcp_magic = lcp_gotoptions[f->unit].magicnumber;
- pktp = pkt;
- PUTLONG(lcp_magic, pktp);
- fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt);
- ++lcp_echos_pending;
- }
-}
-
-/*
- * lcp_echo_lowerup - Start the timer for the LCP frame
- */
-
-static void
-lcp_echo_lowerup (unit)
- int unit;
-{
- fsm *f = &lcp_fsm[unit];
-
- /* Clear the parameters for generating echo frames */
- lcp_echos_pending = 0;
- lcp_echo_number = 0;
- lcp_echo_timer_running = 0;
-
- /* If a timeout interval is specified then start the timer */
- if (lcp_echo_interval != 0)
- LcpEchoCheck (f);
-}
-
-/*
- * lcp_echo_lowerdown - Stop the timer for the LCP frame
- */
-
-static void
-lcp_echo_lowerdown (unit)
- int unit;
-{
- fsm *f = &lcp_fsm[unit];
-
- if (lcp_echo_timer_running != 0) {
- UNTIMEOUT (LcpEchoTimeout, f);
- lcp_echo_timer_running = 0;
- }
-}
diff --git a/usr.sbin/pppd/lcp.h b/usr.sbin/pppd/lcp.h
deleted file mode 100644
index 603a32f..0000000
--- a/usr.sbin/pppd/lcp.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * lcp.h - Link Control Protocol definitions.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
- */
-
-/*
- * Options.
- */
-#define CI_MRU 1 /* Maximum Receive Unit */
-#define CI_ASYNCMAP 2 /* Async Control Character Map */
-#define CI_AUTHTYPE 3 /* Authentication Type */
-#define CI_QUALITY 4 /* Quality Protocol */
-#define CI_MAGICNUMBER 5 /* Magic Number */
-#define CI_PCOMPRESSION 7 /* Protocol Field Compression */
-#define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */
-#define CI_CALLBACK 13 /* callback */
-
-/*
- * LCP-specific packet types.
- */
-#define PROTREJ 8 /* Protocol Reject */
-#define ECHOREQ 9 /* Echo Request */
-#define ECHOREP 10 /* Echo Reply */
-#define DISCREQ 11 /* Discard Request */
-#define CBCP_OPT 6 /* Use callback control protocol */
-
-/*
- * The state of options is described by an lcp_options structure.
- */
-typedef struct lcp_options {
- int passive : 1; /* Don't die if we don't get a response */
- int silent : 1; /* Wait for the other end to start first */
- int restart : 1; /* Restart vs. exit after close */
- int neg_mru : 1; /* Negotiate the MRU? */
- int neg_asyncmap : 1; /* Negotiate the async map? */
- int neg_upap : 1; /* Ask for UPAP authentication? */
- int neg_chap : 1; /* Ask for CHAP authentication? */
- int neg_magicnumber : 1; /* Ask for magic number? */
- int neg_pcompression : 1; /* HDLC Protocol Field Compression? */
- int neg_accompression : 1; /* HDLC Address/Control Field Compression? */
- int neg_lqr : 1; /* Negotiate use of Link Quality Reports */
- int neg_cbcp : 1; /* Negotiate use of CBCP */
- u_short mru; /* Value of MRU */
- u_char chap_mdtype; /* which MD type (hashing algorithm) */
- u_int32_t asyncmap; /* Value of async map */
- u_int32_t magicnumber;
- int numloops; /* Number of loops during magic number neg. */
- u_int32_t lqr_period; /* Reporting period for LQR 1/100ths second */
-} lcp_options;
-
-extern fsm lcp_fsm[];
-extern lcp_options lcp_wantoptions[];
-extern lcp_options lcp_gotoptions[];
-extern lcp_options lcp_allowoptions[];
-extern lcp_options lcp_hisoptions[];
-extern u_int32_t xmit_accm[][8];
-
-#define DEFMRU 1500 /* Try for this */
-#define MINMRU 128 /* No MRUs below this */
-#define MAXMRU 16384 /* Normally limit MRU to this */
-
-void lcp_open(int);
-void lcp_close(int, char *);
-void lcp_lowerup(int);
-void lcp_lowerdown(int);
-void lcp_sprotrej(int, u_char *, int); /* send protocol reject */
-
-extern struct protent lcp_protent;
-
-/* Default number of times we receive our magic number from the peer
- before deciding the link is looped-back. */
-#define DEFLOOPBACKFAIL 10
diff --git a/usr.sbin/pppd/magic.c b/usr.sbin/pppd/magic.c
deleted file mode 100644
index b4627b1..0000000
--- a/usr.sbin/pppd/magic.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * magic.c - PPP Magic Number routines.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-#include <stdio.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/time.h>
-
-#include "pppd.h"
-#include "magic.h"
-
-extern long mrand48(void);
-extern void srand48(long);
-
-/*
- * magic_init - Initialize the magic number generator.
- *
- * Attempts to compute a random number seed which will not repeat.
- * The current method uses the current hostid, current process ID
- * and current time, currently.
- */
-void
-magic_init()
-{
- long seed;
- struct timeval t;
-
- gettimeofday(&t, NULL);
- seed = get_host_seed() ^ t.tv_sec ^ t.tv_usec ^ getpid();
- srand48(seed);
-}
-
-/*
- * magic - Returns the next magic number.
- */
-u_int32_t
-magic()
-{
- return (u_int32_t) mrand48();
-}
-
-#ifdef NO_DRAND48
-/*
- * Substitute procedures for those systems which don't have
- * drand48 et al.
- */
-
-double
-drand48()
-{
- return (double)random() / (double)0x7fffffffL; /* 2**31-1 */
-}
-
-long
-mrand48()
-{
- return random();
-}
-
-void
-srand48(seedval)
-long seedval;
-{
- srandom((int)seedval);
-}
-
-#endif
diff --git a/usr.sbin/pppd/magic.h b/usr.sbin/pppd/magic.h
deleted file mode 100644
index c574131..0000000
--- a/usr.sbin/pppd/magic.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * magic.h - PPP Magic Number definitions.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
- */
-
-void magic_init(void); /* Initialize the magic number generator */
-u_int32_t magic(void); /* Returns the next magic number */
diff --git a/usr.sbin/pppd/main.c b/usr.sbin/pppd/main.c
deleted file mode 100644
index 7850726..0000000
--- a/usr.sbin/pppd/main.c
+++ /dev/null
@@ -1,1723 +0,0 @@
-/*
- * main.c - Point-to-Point Protocol main module
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-#include <stdio.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <syslog.h>
-#include <netdb.h>
-#include <utmp.h>
-#include <pwd.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-
-#include "pppd.h"
-#include "magic.h"
-#include "fsm.h"
-#include "lcp.h"
-#include "ipcp.h"
-#ifdef INET6
-#include "ipv6cp.h"
-#endif
-#include "upap.h"
-#include "chap.h"
-#include "ccp.h"
-#include "pathnames.h"
-#include "patchlevel.h"
-
-#ifdef CBCP_SUPPORT
-#include "cbcp.h"
-#endif
-
-#if defined(SUNOS4)
-extern char *strerror();
-#endif
-
-#ifdef IPX_CHANGE
-#include "ipxcp.h"
-#endif /* IPX_CHANGE */
-#ifdef AT_CHANGE
-#include "atcp.h"
-#endif
-
-/* interface vars */
-char ifname[32]; /* Interface name */
-int ifunit; /* Interface unit number */
-
-char *progname; /* Name of this program */
-char hostname[MAXNAMELEN]; /* Our hostname */
-static char pidfilename[MAXPATHLEN]; /* name of pid file */
-static char iffilename[MAXPATHLEN]; /* name of if file */
-static char default_devnam[MAXPATHLEN]; /* name of default device */
-static pid_t pid; /* Our pid */
-static uid_t uid; /* Our real user-id */
-time_t etime,stime; /* End and Start time */
-int minutes; /* connection duration */
-static int conn_running; /* we have a [dis]connector running */
-
-int ttyfd = -1; /* Serial port file descriptor */
-mode_t tty_mode = -1; /* Original access permissions to tty */
-int baud_rate; /* Actual bits/second for serial device */
-int hungup; /* terminal has been hung up */
-int privileged; /* we're running as real uid root */
-int need_holdoff; /* need holdoff period before restarting */
-int detached; /* have detached from terminal */
-
-int phase; /* where the link is at */
-int kill_link;
-int open_ccp_flag;
-
-char **script_env; /* Env. variable values for scripts */
-int s_env_nalloc; /* # words avail at script_env */
-
-u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
-u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
-
-static int n_children; /* # child processes still running */
-
-static int locked; /* lock() has succeeded */
-
-char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n";
-
-/* Prototypes for procedures local to this file. */
-
-static void create_pidfile(void);
-static void cleanup(void);
-static void close_tty(void);
-static void get_input(void);
-static void calltimeout(void);
-static struct timeval *timeleft(struct timeval *);
-static void kill_my_pg(int);
-static void hup(int);
-static void term(int);
-static void chld(int);
-static void toggle_debug(int);
-static void open_ccp(int);
-static void bad_signal(int);
-static void holdoff_end(void *);
-static int device_script(char *, int, int);
-static void reap_kids(void);
-static void pr_log(void *, char *, ...);
-
-extern char *ttyname(int);
-extern char *getlogin(void);
-int main(int, char *[]);
-
-#ifdef ultrix
-#undef O_NONBLOCK
-#define O_NONBLOCK O_NDELAY
-#endif
-
-#ifdef ULTRIX
-#define setlogmask(x)
-#endif
-
-/*
- * PPP Data Link Layer "protocol" table.
- * One entry per supported protocol.
- * The last entry must be NULL.
- */
-struct protent *protocols[] = {
- &lcp_protent,
- &pap_protent,
- &chap_protent,
-#ifdef CBCP_SUPPORT
- &cbcp_protent,
-#endif
- &ipcp_protent,
-#ifdef INET6
- &ipv6cp_protent,
-#endif
- &ccp_protent,
-#ifdef IPX_CHANGE
- &ipxcp_protent,
-#endif
-#ifdef AT_CHANGE
- &atcp_protent,
-#endif
- NULL
-};
-
-int
-main(argc, argv)
- int argc;
- char *argv[];
-{
- int i, n, fdflags;
- struct sigaction sa;
- FILE *iffile;
- char *p;
- struct passwd *pw;
- struct timeval timo;
- sigset_t mask;
- struct protent *protp;
- struct stat statbuf;
- int connect_attempts = 0;
- char numbuf[16];
-
- phase = PHASE_INITIALIZE;
- p = ttyname(0);
- if (p)
- strcpy(devnam, p);
- strcpy(default_devnam, devnam);
-
- script_env = NULL;
-
- /* Initialize syslog facilities */
-#ifdef ULTRIX
- openlog("pppd", LOG_PID);
-#else
- openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP);
- setlogmask(LOG_UPTO(LOG_INFO));
-#endif
-
- if (gethostname(hostname, MAXNAMELEN) < 0 ) {
- option_error("Couldn't get hostname: %m");
- die(1);
- }
- hostname[MAXNAMELEN-1] = 0;
-
- uid = getuid();
- privileged = uid == 0;
- sprintf(numbuf, "%d", uid);
- script_setenv("UID", numbuf);
-
- /*
- * Initialize to the standard option set, then parse, in order,
- * the system options file, the user's options file,
- * the tty's options file, and the command line arguments.
- */
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- (*protp->init)(0);
-
- progname = *argv;
-
- if (!options_from_file(_PATH_SYSOPTIONS, !privileged, 0, 1)
- || !options_from_user())
- exit(1);
- scan_args(argc-1, argv+1); /* look for tty name on command line */
- if (!options_for_tty()
- || !parse_args(argc-1, argv+1))
- exit(1);
-
- /*
- * Check that we are running as root.
- */
- if (geteuid() != 0) {
- option_error("must be root to run %s, since it is not setuid-root",
- argv[0]);
- die(1);
- }
-
- if (!ppp_available()) {
- option_error(no_ppp_msg);
- exit(1);
- }
-
- /*
- * Check that the options given are valid and consistent.
- */
- sys_check_options();
- auth_check_options();
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if (protp->check_options != NULL)
- (*protp->check_options)();
- if (demand && connector == 0) {
- option_error("connect script required for demand-dialling\n");
- exit(1);
- }
-
- script_setenv("DEVICE", devnam);
- sprintf(numbuf, "%d", baud_rate);
- script_setenv("SPEED", numbuf);
-
- /*
- * If the user has specified the default device name explicitly,
- * pretend they hadn't.
- */
- if (!default_device && strcmp(devnam, default_devnam) == 0)
- default_device = 1;
- if (default_device)
- nodetach = 1;
-
- /*
- * Initialize system-dependent stuff and magic number package.
- */
- sys_init();
- magic_init();
- if (debug)
- setlogmask(LOG_UPTO(LOG_DEBUG));
-
- /*
- * Detach ourselves from the terminal, if required,
- * and identify who is running us.
- */
- if (nodetach == 0)
- detach();
- pid = getpid();
- p = getlogin();
- stime = time((time_t *) NULL);
- if (p == NULL) {
- pw = getpwuid(uid);
- if (pw != NULL && pw->pw_name != NULL)
- p = pw->pw_name;
- else
- p = "(unknown)";
- }
- syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %d",
- VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid);
-
- /*
- * Compute mask of all interesting signals and install signal handlers
- * for each. Only one signal handler may be active at a time. Therefore,
- * all other signals should be masked when any handler is executing.
- */
- sigemptyset(&mask);
- sigaddset(&mask, SIGHUP);
- sigaddset(&mask, SIGINT);
- sigaddset(&mask, SIGTERM);
- sigaddset(&mask, SIGCHLD);
-
-#define SIGNAL(s, handler) { \
- sa.sa_handler = handler; \
- if (sigaction(s, &sa, NULL) < 0) { \
- syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \
- die(1); \
- } \
- }
-
- sa.sa_mask = mask;
- sa.sa_flags = 0;
- SIGNAL(SIGHUP, hup); /* Hangup */
- SIGNAL(SIGINT, term); /* Interrupt */
- SIGNAL(SIGTERM, term); /* Terminate */
- SIGNAL(SIGCHLD, chld);
-
- SIGNAL(SIGUSR1, toggle_debug); /* Toggle debug flag */
- SIGNAL(SIGUSR2, open_ccp); /* Reopen CCP */
-
- /*
- * Install a handler for other signals which would otherwise
- * cause pppd to exit without cleaning up.
- */
- SIGNAL(SIGABRT, bad_signal);
- SIGNAL(SIGALRM, bad_signal);
- SIGNAL(SIGFPE, bad_signal);
- SIGNAL(SIGILL, bad_signal);
- SIGNAL(SIGPIPE, bad_signal);
- SIGNAL(SIGQUIT, bad_signal);
- SIGNAL(SIGSEGV, bad_signal);
-#ifdef SIGBUS
- SIGNAL(SIGBUS, bad_signal);
-#endif
-#ifdef SIGEMT
- SIGNAL(SIGEMT, bad_signal);
-#endif
-#ifdef SIGPOLL
- SIGNAL(SIGPOLL, bad_signal);
-#endif
-#ifdef SIGPROF
- SIGNAL(SIGPROF, bad_signal);
-#endif
-#ifdef SIGSYS
- SIGNAL(SIGSYS, bad_signal);
-#endif
-#ifdef SIGTRAP
- SIGNAL(SIGTRAP, bad_signal);
-#endif
-#ifdef SIGVTALRM
- SIGNAL(SIGVTALRM, bad_signal);
-#endif
-#ifdef SIGXCPU
- SIGNAL(SIGXCPU, bad_signal);
-#endif
-#ifdef SIGXFSZ
- SIGNAL(SIGXFSZ, bad_signal);
-#endif
-
- /*
- * Apparently we can get a SIGPIPE when we call syslog, if
- * syslogd has died and been restarted. Ignoring it seems
- * be sufficient.
- */
- signal(SIGPIPE, SIG_IGN);
-
- /*
- * If we're doing dial-on-demand, set up the interface now.
- */
- if (demand) {
- /*
- * Open the loopback channel and set it up to be the ppp interface.
- */
- open_ppp_loopback();
-
- syslog(LOG_INFO, "Using interface ppp%d", ifunit);
- (void) sprintf(ifname, "ppp%d", ifunit);
- script_setenv("IFNAME", ifname);
-
- create_pidfile(); /* write pid to file */
-
- /*
- * Configure the interface and mark it up, etc.
- */
- demand_conf();
- }
-
- for (;;) {
-
- need_holdoff = 1;
-
- if (demand) {
- /*
- * Don't do anything until we see some activity.
- */
- phase = PHASE_DORMANT;
- kill_link = 0;
- demand_unblock();
- for (;;) {
- wait_loop_output(timeleft(&timo));
- calltimeout();
- if (kill_link) {
- if (!persist)
- die(0);
- kill_link = 0;
- }
- if (get_loop_output())
- break;
- reap_kids();
- }
-
- /*
- * Now we want to bring up the link.
- */
- demand_block();
- syslog(LOG_INFO, "Starting link");
- }
-
- /*
- * Lock the device if we've been asked to.
- */
- if (lockflag && !default_device) {
- if (lock(devnam) < 0)
- goto fail;
- locked = 1;
- }
-
- /*
- * Open the serial device and set it up to be the ppp interface.
- * First we open it in non-blocking mode so we can set the
- * various termios flags appropriately. If we aren't dialling
- * out and we want to use the modem lines, we reopen it later
- * in order to wait for the carrier detect signal from the modem.
- */
- while ((ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0)) < 0) {
- if (errno != EINTR)
- syslog(LOG_ERR, "Failed to open %s: %m", devnam);
- if (!persist || errno != EINTR)
- goto fail;
- }
- if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
- || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
- syslog(LOG_WARNING,
- "Couldn't reset non-blocking mode on device: %m");
-
- hungup = 0;
- kill_link = 0;
-
- /*
- * Do the equivalent of `mesg n' to stop broadcast messages.
- */
- if (fstat(ttyfd, &statbuf) < 0
- || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) {
- syslog(LOG_WARNING,
- "Couldn't restrict write permissions to %s: %m", devnam);
- } else
- tty_mode = statbuf.st_mode;
-
- /* run connection script */
- if (connector && connector[0]) {
- MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector));
-
- /*
- * Set line speed, flow control, etc.
- * On most systems we set CLOCAL for now so that we can talk
- * to the modem before carrier comes up. But this has the
- * side effect that we might miss it if CD drops before we
- * get to clear CLOCAL below. On systems where we can talk
- * successfully to the modem with CLOCAL clear and CD down,
- * we can clear CLOCAL at this point.
- */
- set_up_tty(ttyfd, 1);
-
- /* drop dtr to hang up in case modem is off hook */
- if (!default_device && modem) {
- setdtr(ttyfd, FALSE);
- sleep(1);
- setdtr(ttyfd, TRUE);
- }
-
- if (device_script(connector, ttyfd, ttyfd) < 0) {
- syslog(LOG_ERR, "Connect script failed");
- setdtr(ttyfd, FALSE);
- connect_attempts++;
- goto fail;
- }
-
-
- syslog(LOG_INFO, "Serial connection established.");
- sleep(1); /* give it time to set up its terminal */
- }
-
- connect_attempts = 0; /* we made it through ok */
-
- /* set line speed, flow control, etc.; clear CLOCAL if modem option */
- set_up_tty(ttyfd, 0);
-
- /* reopen tty if necessary to wait for carrier */
- if (connector == NULL && modem) {
- while ((i = open(devnam, O_RDWR)) < 0) {
- if (errno != EINTR)
- syslog(LOG_ERR, "Failed to reopen %s: %m", devnam);
- if (!persist || errno != EINTR ||
- hungup || kill_link)
- goto fail;
- }
- close(i);
- }
-
- /* run welcome script, if any */
- if (welcomer && welcomer[0]) {
- if (device_script(welcomer, ttyfd, ttyfd) < 0)
- syslog(LOG_WARNING, "Welcome script failed");
- }
-
- /* set up the serial device as a ppp interface */
- establish_ppp(ttyfd);
-
- if (!demand) {
-
- syslog(LOG_INFO, "Using interface ppp%d", ifunit);
- (void) sprintf(ifname, "ppp%d", ifunit);
-
- create_pidfile(); /* write pid to file */
-
- /* write interface unit number to file */
- for (n = strlen(devnam); n > 0 ; n--)
- if (devnam[n] == '/') {
- n++;
- break;
- }
- (void) sprintf(iffilename, "%s%s.if", _PATH_VARRUN, &devnam[n]);
- if ((iffile = fopen(iffilename, "w")) != NULL) {
- fprintf(iffile, "ppp%d\n", ifunit);
- (void) fclose(iffile);
- } else {
- syslog(LOG_ERR, "Failed to create if file %s: %m", iffilename);
- iffilename[0] = 0;
- }
-
- script_setenv("IFNAME", ifname);
- }
-
- /*
- * Start opening the connection and wait for
- * incoming events (reply, timeout, etc.).
- */
- syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam);
- stime = time((time_t *) NULL);
- lcp_lowerup(0);
- lcp_open(0); /* Start protocol */
- for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) {
- wait_input(timeleft(&timo));
- calltimeout();
- get_input();
- if (kill_link) {
- lcp_close(0, "User request");
- kill_link = 0;
- }
- if (open_ccp_flag) {
- if (phase == PHASE_NETWORK) {
- ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */
- (*ccp_protent.open)(0);
- }
- open_ccp_flag = 0;
- }
- reap_kids(); /* Don't leave dead kids lying around */
- }
-
- /*
- * If we may want to bring the link up again, transfer
- * the ppp unit back to the loopback. Set the
- * real serial device back to its normal mode of operation.
- */
- clean_check();
- if (demand)
- restore_loop();
- disestablish_ppp(ttyfd);
-
- /*
- * Run disconnector script, if requested.
- * XXX we may not be able to do this if the line has hung up!
- */
- if (disconnector && !hungup) {
- set_up_tty(ttyfd, 1);
- if (device_script(disconnector, ttyfd, ttyfd) < 0) {
- syslog(LOG_WARNING, "disconnect script failed");
- } else {
- syslog(LOG_INFO, "Serial link disconnected.");
- }
- }
-
- fail:
- if (ttyfd >= 0)
- close_tty();
- if (locked) {
- unlock();
- locked = 0;
- }
-
- if (!demand) {
- if (pidfilename[0] != 0
- && unlink(pidfilename) < 0 && errno != ENOENT)
- syslog(LOG_WARNING, "unable to delete pid file: %m");
- pidfilename[0] = 0;
-
- if (iffile)
- if (unlink(iffilename) < 0 && errno != ENOENT)
- syslog(LOG_WARNING, "unable to delete if file: %m");
- iffilename[0] = 0;
- }
-
- /* limit to retries? */
- if (max_con_attempts)
- if (connect_attempts >= max_con_attempts)
- break;
-
- if (!persist)
- die(1);
-
- if (demand)
- demand_discard();
- if (holdoff > 0 && need_holdoff) {
- phase = PHASE_HOLDOFF;
- TIMEOUT(holdoff_end, NULL, holdoff);
- do {
- wait_time(timeleft(&timo));
- calltimeout();
- if (kill_link) {
- if (!persist)
- die(0);
- kill_link = 0;
- phase = PHASE_DORMANT; /* allow signal to end holdoff */
- }
- reap_kids();
- } while (phase == PHASE_HOLDOFF);
- }
- }
-
- die(0);
- return 0;
-}
-
-/*
- * detach - detach us from the controlling terminal.
- */
-void
-detach()
-{
- if (detached)
- return;
- if (daemon(0, 0) < 0) {
- perror("Couldn't detach from controlling terminal");
- die(1);
- }
- detached = 1;
- pid = getpid();
- /* update pid file if it has been written already */
- if (pidfilename[0])
- create_pidfile();
-}
-
-/*
- * Create a file containing our process ID.
- */
-static void
-create_pidfile()
-{
- FILE *pidfile;
-
- (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname);
- if ((pidfile = fopen(pidfilename, "w")) != NULL) {
- fprintf(pidfile, "%d\n", pid);
- (void) fclose(pidfile);
- } else {
- syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename);
- pidfilename[0] = 0;
- }
-}
-
-/*
- * holdoff_end - called via a timeout when the holdoff period ends.
- */
-static void
-holdoff_end(arg)
- void *arg;
-{
- phase = PHASE_DORMANT;
-}
-
-/*
- * get_input - called when incoming data is available.
- */
-static void
-get_input()
-{
- int len, i;
- u_char *p;
- u_short protocol;
- struct protent *protp;
-
- p = inpacket_buf; /* point to beginning of packet buffer */
-
- len = read_packet(inpacket_buf);
- if (len < 0)
- return;
-
- if (len == 0) {
- etime = time((time_t *) NULL);
- minutes = (etime-stime)/60;
- syslog(LOG_NOTICE, "Modem hangup, connected for %d minutes", (minutes >1) ? minutes : 1);
- hungup = 1;
- lcp_lowerdown(0); /* serial link is no longer available */
- link_terminated(0);
- return;
- }
-
- if (debug /*&& (debugflags & DBG_INPACKET)*/)
- log_packet(p, len, "rcvd ", LOG_DEBUG);
-
- if (len < PPP_HDRLEN) {
- MAINDEBUG((LOG_INFO, "io(): Received short packet."));
- return;
- }
-
- p += 2; /* Skip address and control */
- GETSHORT(protocol, p);
- len -= PPP_HDRLEN;
-
- /*
- * Toss all non-LCP packets unless LCP is OPEN.
- */
- if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) {
- MAINDEBUG((LOG_INFO,
- "get_input: Received non-LCP packet when LCP not open."));
- return;
- }
-
- /*
- * Until we get past the authentication phase, toss all packets
- * except LCP, LQR and authentication packets.
- */
- if (phase <= PHASE_AUTHENTICATE
- && !(protocol == PPP_LCP || protocol == PPP_LQR
- || protocol == PPP_PAP || protocol == PPP_CHAP)) {
- MAINDEBUG((LOG_INFO, "get_input: discarding proto 0x%x in phase %d",
- protocol, phase));
- return;
- }
-
- /*
- * Upcall the proper protocol input routine.
- */
- for (i = 0; (protp = protocols[i]) != NULL; ++i) {
- if (protp->protocol == protocol && protp->enabled_flag) {
- (*protp->input)(0, p, len);
- return;
- }
- if (protocol == (protp->protocol & ~0x8000) && protp->enabled_flag
- && protp->datainput != NULL) {
- (*protp->datainput)(0, p, len);
- return;
- }
- }
-
- if (debug)
- syslog(LOG_WARNING, "Unsupported protocol (0x%x) received", protocol);
- lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN);
-}
-
-
-/*
- * quit - Clean up state and exit (with an error indication).
- */
-void
-quit()
-{
- die(1);
-}
-
-/*
- * die - like quit, except we can specify an exit status.
- */
-void
-die(status)
- int status;
-{
- cleanup();
- syslog(LOG_INFO, "Exit.");
- exit(status);
-}
-
-/*
- * cleanup - restore anything which needs to be restored before we exit
- */
-/* ARGSUSED */
-static void
-cleanup()
-{
- sys_cleanup();
-
- if (ttyfd >= 0)
- close_tty();
-
- if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT)
- syslog(LOG_WARNING, "unable to delete pid file: %m");
- pidfilename[0] = 0;
-
- if (locked)
- unlock();
-}
-
-/*
- * close_tty - restore the terminal device and close it.
- */
-static void
-close_tty()
-{
- disestablish_ppp(ttyfd);
-
- /* drop dtr to hang up */
- if (modem) {
- setdtr(ttyfd, FALSE);
- /*
- * This sleep is in case the serial port has CLOCAL set by default,
- * and consequently will reassert DTR when we close the device.
- */
- sleep(1);
- }
-
- restore_tty(ttyfd);
-
- if (tty_mode != (mode_t) -1)
- fchmod(ttyfd, tty_mode);
-
- close(ttyfd);
- ttyfd = -1;
-}
-
-
-struct callout {
- struct timeval c_time; /* time at which to call routine */
- void *c_arg; /* argument to routine */
- void (*c_func)(void *); /* routine */
- struct callout *c_next;
-};
-
-static struct callout *callout = NULL; /* Callout list */
-static struct timeval timenow; /* Current time */
-
-/*
- * timeout - Schedule a timeout.
- *
- * Note that this timeout takes the number of seconds, NOT hz (as in
- * the kernel).
- */
-void
-timeout(func, arg, time)
- void (*func)(void *);
- void *arg;
- int time;
-{
- struct callout *newp, *p, **pp;
-
- MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.",
- (long) func, (long) arg, time));
-
- /*
- * Allocate timeout.
- */
- if ((newp = (struct callout *) malloc(sizeof(struct callout))) == NULL) {
- syslog(LOG_ERR, "Out of memory in timeout()!");
- die(1);
- }
- newp->c_arg = arg;
- newp->c_func = func;
- gettimeofday(&timenow, NULL);
- newp->c_time.tv_sec = timenow.tv_sec + time;
- newp->c_time.tv_usec = timenow.tv_usec;
-
- /*
- * Find correct place and link it in.
- */
- for (pp = &callout; (p = *pp); pp = &p->c_next)
- if (newp->c_time.tv_sec < p->c_time.tv_sec
- || (newp->c_time.tv_sec == p->c_time.tv_sec
- && newp->c_time.tv_usec < p->c_time.tv_sec))
- break;
- newp->c_next = p;
- *pp = newp;
-}
-
-
-/*
- * untimeout - Unschedule a timeout.
- */
-void
-untimeout(func, arg)
- void (*func)(void *);
- void *arg;
-{
- struct callout **copp, *freep;
-
- MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg));
-
- /*
- * Find first matching timeout and remove it from the list.
- */
- for (copp = &callout; (freep = *copp); copp = &freep->c_next)
- if (freep->c_func == func && freep->c_arg == arg) {
- *copp = freep->c_next;
- (void) free((char *) freep);
- break;
- }
-}
-
-
-/*
- * calltimeout - Call any timeout routines which are now due.
- */
-static void
-calltimeout()
-{
- struct callout *p;
-
- while (callout != NULL) {
- p = callout;
-
- if (gettimeofday(&timenow, NULL) < 0) {
- syslog(LOG_ERR, "Failed to get time of day: %m");
- die(1);
- }
- if (!(p->c_time.tv_sec < timenow.tv_sec
- || (p->c_time.tv_sec == timenow.tv_sec
- && p->c_time.tv_usec <= timenow.tv_usec)))
- break; /* no, it's not time yet */
-
- callout = p->c_next;
- (*p->c_func)(p->c_arg);
-
- free((char *) p);
- }
-}
-
-
-/*
- * timeleft - return the length of time until the next timeout is due.
- */
-static struct timeval *
-timeleft(tvp)
- struct timeval *tvp;
-{
- if (callout == NULL)
- return NULL;
-
- gettimeofday(&timenow, NULL);
- tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec;
- tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec;
- if (tvp->tv_usec < 0) {
- tvp->tv_usec += 1000000;
- tvp->tv_sec -= 1;
- }
- if (tvp->tv_sec < 0)
- tvp->tv_sec = tvp->tv_usec = 0;
-
- return tvp;
-}
-
-
-/*
- * kill_my_pg - send a signal to our process group, and ignore it ourselves.
- */
-static void
-kill_my_pg(sig)
- int sig;
-{
- struct sigaction act, oldact;
-
- act.sa_handler = SIG_IGN;
- act.sa_flags = 0;
- kill(0, sig);
- sigaction(sig, &act, &oldact);
- sigaction(sig, &oldact, NULL);
-}
-
-
-/*
- * hup - Catch SIGHUP signal.
- *
- * Indicates that the physical layer has been disconnected.
- * We don't rely on this indication; if the user has sent this
- * signal, we just take the link down.
- */
-static void
-hup(sig)
- int sig;
-{
- syslog(LOG_INFO, "Hangup (SIGHUP)");
- kill_link = 1;
- if (conn_running)
- /* Send the signal to the [dis]connector process(es) also */
- kill_my_pg(sig);
-}
-
-
-/*
- * term - Catch SIGTERM signal and SIGINT signal (^C/del).
- *
- * Indicates that we should initiate a graceful disconnect and exit.
- */
-/*ARGSUSED*/
-static void
-term(sig)
- int sig;
-{
- syslog(LOG_INFO, "Terminating on signal %d.", sig);
- persist = 0; /* don't try to restart */
- kill_link = 1;
- if (conn_running)
- /* Send the signal to the [dis]connector process(es) also */
- kill_my_pg(sig);
-}
-
-
-/*
- * chld - Catch SIGCHLD signal.
- * Calls reap_kids to get status for any dead kids.
- */
-static void
-chld(sig)
- int sig;
-{
- reap_kids();
-}
-
-
-/*
- * toggle_debug - Catch SIGUSR1 signal.
- *
- * Toggle debug flag.
- */
-/*ARGSUSED*/
-static void
-toggle_debug(sig)
- int sig;
-{
- debug = !debug;
- if (debug) {
- setlogmask(LOG_UPTO(LOG_DEBUG));
- } else {
- setlogmask(LOG_UPTO(LOG_WARNING));
- }
-}
-
-
-/*
- * open_ccp - Catch SIGUSR2 signal.
- *
- * Try to (re)negotiate compression.
- */
-/*ARGSUSED*/
-static void
-open_ccp(sig)
- int sig;
-{
- open_ccp_flag = 1;
-}
-
-
-/*
- * bad_signal - We've caught a fatal signal. Clean up state and exit.
- */
-static void
-bad_signal(sig)
- int sig;
-{
- static int crashed = 0;
-
- if (crashed)
- _exit(127);
- crashed = 1;
- syslog(LOG_ERR, "Fatal signal %d", sig);
- if (conn_running)
- kill_my_pg(SIGTERM);
- die(1);
-}
-
-
-/*
- * device_script - run a program to connect or disconnect the
- * serial device.
- */
-static int
-device_script(program, in, out)
- char *program;
- int in, out;
-{
- int pid;
- int status;
- int errfd;
-
- conn_running = 1;
- pid = fork();
-
- if (pid < 0) {
- conn_running = 0;
- syslog(LOG_ERR, "Failed to create child process: %m");
- die(1);
- }
-
- if (pid == 0) {
- sys_close();
- closelog();
- if (in == out) {
- if (in != 0) {
- dup2(in, 0);
- close(in);
- }
- dup2(0, 1);
- } else {
- if (out == 0)
- out = dup(out);
- if (in != 0) {
- dup2(in, 0);
- close(in);
- }
- if (out != 1) {
- dup2(out, 1);
- close(out);
- }
- }
- if (nodetach == 0) {
- close(2);
- errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0600);
- if (errfd >= 0 && errfd != 2) {
- dup2(errfd, 2);
- close(errfd);
- }
- }
- setuid(getuid());
- setgid(getgid());
- execl("/bin/sh", "sh", "-c", program, (char *)0);
- syslog(LOG_ERR, "could not exec /bin/sh: %m");
- _exit(99);
- /* NOTREACHED */
- }
-
- while (waitpid(pid, &status, 0) < 0) {
- if (errno == EINTR)
- continue;
- syslog(LOG_ERR, "error waiting for (dis)connection process: %m");
- die(1);
- }
- conn_running = 0;
-
- return (status == 0 ? 0 : -1);
-}
-
-
-/*
- * run-program - execute a program with given arguments,
- * but don't wait for it.
- * If the program can't be executed, logs an error unless
- * must_exist is 0 and the program file doesn't exist.
- */
-int
-run_program(prog, args, must_exist)
- char *prog;
- char **args;
- int must_exist;
-{
- int pid;
-
- pid = fork();
- if (pid == -1) {
- syslog(LOG_ERR, "Failed to create child process for %s: %m", prog);
- return -1;
- }
- if (pid == 0) {
- int new_fd;
-
- /* Leave the current location */
- (void) setsid(); /* No controlling tty. */
- (void) umask (S_IRWXG|S_IRWXO);
- (void) chdir ("/"); /* no current directory. */
- setuid(geteuid());
- setgid(getegid());
-
- /* Ensure that nothing of our device environment is inherited. */
- sys_close();
- closelog();
- close (0);
- close (1);
- close (2);
- close (ttyfd); /* tty interface to the ppp device */
-
- /* Don't pass handles to the PPP device, even by accident. */
- new_fd = open (_PATH_DEVNULL, O_RDWR);
- if (new_fd >= 0) {
- if (new_fd != 0) {
- dup2 (new_fd, 0); /* stdin <- /dev/null */
- close (new_fd);
- }
- dup2 (0, 1); /* stdout -> /dev/null */
- dup2 (0, 2); /* stderr -> /dev/null */
- }
-
-#ifdef BSD
- /* Force the priority back to zero if pppd is running higher. */
- if (setpriority (PRIO_PROCESS, 0, 0) < 0)
- syslog (LOG_WARNING, "can't reset priority to 0: %m");
-#endif
-
- /* SysV recommends a second fork at this point. */
-
- /* run the program; give it a null environment */
- execve(prog, args, script_env);
- if (must_exist || errno != ENOENT)
- syslog(LOG_WARNING, "Can't execute %s: %m", prog);
- _exit(-1);
- }
- MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid));
- ++n_children;
- return 0;
-}
-
-
-/*
- * reap_kids - get status from any dead child processes,
- * and log a message for abnormal terminations.
- */
-static void
-reap_kids()
-{
- int pid, status;
-
- if (n_children == 0)
- return;
- if ((pid = waitpid(-1, &status, WNOHANG)) == -1) {
- if (errno != ECHILD)
- syslog(LOG_ERR, "Error waiting for child process: %m");
- return;
- }
- if (pid > 0) {
- --n_children;
- if (WIFSIGNALED(status)) {
- syslog(LOG_WARNING, "Child process %d terminated with signal %d",
- pid, WTERMSIG(status));
- }
- }
-}
-
-
-/*
- * log_packet - format a packet and log it.
- */
-
-char line[256]; /* line to be logged accumulated here */
-char *linep;
-
-void
-log_packet(p, len, prefix, level)
- u_char *p;
- int len;
- char *prefix;
- int level;
-{
- strcpy(line, prefix);
- linep = line + strlen(line);
- format_packet(p, len, pr_log, NULL);
- if (linep != line)
- syslog(level, "%s", line);
-}
-
-/*
- * format_packet - make a readable representation of a packet,
- * calling `printer(arg, format, ...)' to output it.
- */
-void
-format_packet(p, len, printer, arg)
- u_char *p;
- int len;
- void (*printer)(void *, char *, ...);
- void *arg;
-{
- int i, n;
- u_short proto;
- u_char x;
- struct protent *protp;
-
- if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) {
- p += 2;
- GETSHORT(proto, p);
- len -= PPP_HDRLEN;
- for (i = 0; (protp = protocols[i]) != NULL; ++i)
- if (proto == protp->protocol)
- break;
- if (protp != NULL) {
- printer(arg, "[%s", protp->name);
- n = (*protp->printpkt)(p, len, printer, arg);
- printer(arg, "]");
- p += n;
- len -= n;
- } else {
- printer(arg, "[proto=0x%x]", proto);
- }
- }
-
- for (; len > 0; --len) {
- GETCHAR(x, p);
- printer(arg, " %.2x", x);
- }
-}
-
-static void
-pr_log __V((void *arg, char *fmt, ...))
-{
- int n;
- va_list pvar;
- char buf[256];
-
-#if __STDC__
- va_start(pvar, fmt);
-#else
- void *arg;
- char *fmt;
- va_start(pvar);
- arg = va_arg(pvar, void *);
- fmt = va_arg(pvar, char *);
-#endif
-
- n = vfmtmsg(buf, sizeof(buf), fmt, pvar);
- va_end(pvar);
-
- if (linep + n + 1 > line + sizeof(line)) {
- syslog(LOG_DEBUG, "%s", line);
- linep = line;
- }
- strcpy(linep, buf);
- linep += n;
-}
-
-/*
- * print_string - print a readable representation of a string using
- * printer.
- */
-void
-print_string(p, len, printer, arg)
- char *p;
- int len;
- void (*printer)(void *, char *, ...);
- void *arg;
-{
- int c;
-
- printer(arg, "\"");
- for (; len > 0; --len) {
- c = *p++;
- if (' ' <= c && c <= '~') {
- if (c == '\\' || c == '"')
- printer(arg, "\\");
- printer(arg, "%c", c);
- } else {
- switch (c) {
- case '\n':
- printer(arg, "\\n");
- break;
- case '\r':
- printer(arg, "\\r");
- break;
- case '\t':
- printer(arg, "\\t");
- break;
- default:
- printer(arg, "\\%.3o", c);
- }
- }
- }
- printer(arg, "\"");
-}
-
-/*
- * novm - log an error message saying we ran out of memory, and die.
- */
-void
-novm(msg)
- char *msg;
-{
- syslog(LOG_ERR, "Virtual memory exhausted allocating %s\n", msg);
- die(1);
-}
-
-/*
- * fmtmsg - format a message into a buffer. Like sprintf except we
- * also specify the length of the output buffer, and we handle
- * %r (recursive format), %m (error message) and %I (IP address) formats.
- * Doesn't do floating-point formats.
- * Returns the number of chars put into buf.
- */
-int
-fmtmsg __V((char *buf, int buflen, char *fmt, ...))
-{
- va_list args;
- int n;
-
-#if __STDC__
- va_start(args, fmt);
-#else
- char *buf;
- int buflen;
- char *fmt;
- va_start(args);
- buf = va_arg(args, char *);
- buflen = va_arg(args, int);
- fmt = va_arg(args, char *);
-#endif
- n = vfmtmsg(buf, buflen, fmt, args);
- va_end(args);
- return n;
-}
-
-/*
- * vfmtmsg - like fmtmsg, takes a va_list instead of a list of args.
- */
-#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
-
-int
-vfmtmsg(buf, buflen, fmt, args)
- char *buf;
- int buflen;
- char *fmt;
- va_list args;
-{
- int c, i, n;
- int width, prec, fillch;
- int base, len, neg, quoted;
- unsigned long val = 0;
- char *str, *f, *buf0;
- unsigned char *p;
- char num[32];
- time_t t;
- static char hexchars[] = "0123456789abcdef";
-
- buf0 = buf;
- --buflen;
- while (buflen > 0) {
- for (f = fmt; *f != '%' && *f != 0; ++f)
- ;
- if (f > fmt) {
- len = f - fmt;
- if (len > buflen)
- len = buflen;
- memcpy(buf, fmt, len);
- buf += len;
- buflen -= len;
- fmt = f;
- }
- if (*fmt == 0)
- break;
- c = *++fmt;
- width = prec = 0;
- fillch = ' ';
- if (c == '0') {
- fillch = '0';
- c = *++fmt;
- }
- if (c == '*') {
- width = va_arg(args, int);
- c = *++fmt;
- } else {
- while (isdigit(c)) {
- width = width * 10 + c - '0';
- c = *++fmt;
- }
- }
- if (c == '.') {
- c = *++fmt;
- if (c == '*') {
- prec = va_arg(args, int);
- c = *++fmt;
- } else {
- while (isdigit(c)) {
- prec = prec * 10 + c - '0';
- c = *++fmt;
- }
- }
- }
- str = 0;
- base = 0;
- neg = 0;
- ++fmt;
- switch (c) {
- case 'd':
- i = va_arg(args, int);
- if (i < 0) {
- neg = 1;
- val = -i;
- } else
- val = i;
- base = 10;
- break;
- case 'o':
- val = va_arg(args, unsigned int);
- base = 8;
- break;
- case 'x':
- val = va_arg(args, unsigned int);
- base = 16;
- break;
- case 'p':
- val = (unsigned long) va_arg(args, void *);
- base = 16;
- neg = 2;
- break;
- case 's':
- str = va_arg(args, char *);
- break;
- case 'c':
- num[0] = va_arg(args, int);
- num[1] = 0;
- str = num;
- break;
- case 'm':
- str = strerror(errno);
- break;
- case 'I':
- str = ip_ntoa(va_arg(args, u_int32_t));
- break;
- case 'r':
- f = va_arg(args, char *);
-#if !defined(__powerpc__) && !defined(__amd64__)
- n = vfmtmsg(buf, buflen + 1, f, va_arg(args, va_list));
-#else
- /* On the powerpc, a va_list is an array of 1 structure */
- n = vfmtmsg(buf, buflen + 1, f, va_arg(args, void *));
-#endif
- buf += n;
- buflen -= n;
- continue;
- case 't':
- time(&t);
- str = ctime(&t);
- str += 4; /* chop off the day name */
- str[15] = 0; /* chop off year and newline */
- break;
- case 'v': /* "visible" string */
- case 'q': /* quoted string */
- quoted = c == 'q';
- p = va_arg(args, unsigned char *);
- if (fillch == '0' && prec > 0) {
- n = prec;
- } else {
- n = strlen((char *)p);
- if (prec > 0 && prec < n)
- n = prec;
- }
- while (n > 0 && buflen > 0) {
- c = *p++;
- --n;
- if (!quoted && c >= 0x80) {
- OUTCHAR('M');
- OUTCHAR('-');
- c -= 0x80;
- }
- if (quoted && (c == '"' || c == '\\'))
- OUTCHAR('\\');
- if (c < 0x20 || (0x7f <= c && c < 0xa0)) {
- if (quoted) {
- OUTCHAR('\\');
- switch (c) {
- case '\t': OUTCHAR('t'); break;
- case '\n': OUTCHAR('n'); break;
- case '\b': OUTCHAR('b'); break;
- case '\f': OUTCHAR('f'); break;
- default:
- OUTCHAR('x');
- OUTCHAR(hexchars[c >> 4]);
- OUTCHAR(hexchars[c & 0xf]);
- }
- } else {
- if (c == '\t')
- OUTCHAR(c);
- else {
- OUTCHAR('^');
- OUTCHAR(c ^ 0x40);
- }
- }
- } else
- OUTCHAR(c);
- }
- continue;
- default:
- *buf++ = '%';
- if (c != '%')
- --fmt; /* so %z outputs %z etc. */
- --buflen;
- continue;
- }
- if (base != 0) {
- str = num + sizeof(num);
- *--str = 0;
- while (str > num + neg) {
- *--str = hexchars[val % base];
- val = val / base;
- if (--prec <= 0 && val == 0)
- break;
- }
- switch (neg) {
- case 1:
- *--str = '-';
- break;
- case 2:
- *--str = 'x';
- *--str = '0';
- break;
- }
- len = num + sizeof(num) - 1 - str;
- } else {
- len = strlen(str);
- if (prec > 0 && len > prec)
- len = prec;
- }
- if (width > 0) {
- if (width > buflen)
- width = buflen;
- if ((n = width - len) > 0) {
- buflen -= n;
- for (; n > 0; --n)
- *buf++ = fillch;
- }
- }
- if (len > buflen)
- len = buflen;
- memcpy(buf, str, len);
- buf += len;
- buflen -= len;
- }
- *buf = 0;
- return buf - buf0;
-}
-
-/*
- * script_setenv - set an environment variable value to be used
- * for scripts that we run (e.g. ip-up, auth-up, etc.)
- */
-void
-script_setenv(var, value)
- char *var, *value;
-{
- int vl = strlen(var);
- int i;
- char *p, *newstring;
-
- newstring = (char *) malloc(vl + strlen(value) + 2);
- if (newstring == 0)
- return;
- strcpy(newstring, var);
- newstring[vl] = '=';
- strcpy(newstring+vl+1, value);
-
- /* check if this variable is already set */
- if (script_env != 0) {
- for (i = 0; (p = script_env[i]) != 0; ++i) {
- if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
- free(p);
- script_env[i] = newstring;
- return;
- }
- }
- } else {
- i = 0;
- script_env = (char **) malloc(16 * sizeof(char *));
- if (script_env == 0)
- return;
- s_env_nalloc = 16;
- }
-
- /* reallocate script_env with more space if needed */
- if (i + 1 >= s_env_nalloc) {
- int new_n = i + 17;
- char **newenv = (char **) realloc((void *)script_env,
- new_n * sizeof(char *));
- if (newenv == 0)
- return;
- script_env = newenv;
- s_env_nalloc = new_n;
- }
-
- script_env[i] = newstring;
- script_env[i+1] = 0;
-}
-
-/*
- * script_unsetenv - remove a variable from the environment
- * for scripts.
- */
-void
-script_unsetenv(var)
- char *var;
-{
- int vl = strlen(var);
- int i;
- char *p;
-
- if (script_env == 0)
- return;
- for (i = 0; (p = script_env[i]) != 0; ++i) {
- if (strncmp(p, var, vl) == 0 && p[vl] == '=') {
- free(p);
- while ((script_env[i] = script_env[i+1]) != 0)
- ++i;
- break;
- }
- }
-}
diff --git a/usr.sbin/pppd/options.c b/usr.sbin/pppd/options.c
deleted file mode 100644
index fa3cf93..0000000
--- a/usr.sbin/pppd/options.c
+++ /dev/null
@@ -1,2683 +0,0 @@
-/*
- * options.c - handles option processing for PPP.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-#include <ctype.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <termios.h>
-#include <syslog.h>
-#include <string.h>
-#include <netdb.h>
-#include <paths.h>
-#include <pwd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#ifdef PPP_FILTER
-#include <pcap.h>
-#include <pcap-int.h> /* XXX: To get struct pcap */
-#endif
-
-#include "pppd.h"
-#include "pathnames.h"
-#include "patchlevel.h"
-#include "fsm.h"
-#include "lcp.h"
-#include "ipcp.h"
-#include "upap.h"
-#include "chap.h"
-#include "ccp.h"
-#ifdef CBCP_SUPPORT
-#include "cbcp.h"
-#endif
-
-#ifdef INET6
-#include "ipv6cp.h"
-#endif
-
-#ifdef IPX_CHANGE
-#include "ipxcp.h"
-#endif /* IPX_CHANGE */
-
-#include <net/ppp_comp.h>
-
-#define FALSE 0
-#define TRUE 1
-
-#if defined(ultrix) || defined(NeXT)
-char *strdup(char *);
-#endif
-
-#ifndef GIDSET_TYPE
-#define GIDSET_TYPE gid_t
-#endif
-
-/*
- * Option variables and default values.
- */
-#ifdef PPP_FILTER
-int dflag = 0; /* Tell libpcap we want debugging */
-#endif
-int debug = 0; /* Debug flag */
-int kdebugflag = 0; /* Tell kernel to print debug messages */
-int default_device = 1; /* Using /dev/tty or equivalent */
-char devnam[MAXPATHLEN] = _PATH_TTY; /* Device name */
-int crtscts = 0; /* Use hardware flow control */
-int modem = 1; /* Use modem control lines */
-int inspeed = 0; /* Input/Output speed requested */
-u_int32_t netmask = 0; /* IP netmask to set on interface */
-int lockflag = 0; /* Create lock file to lock the serial dev */
-int nodetach = 0; /* Don't detach from controlling tty */
-char *connector = NULL; /* Script to establish physical link */
-char *disconnector = NULL; /* Script to disestablish physical link */
-char *welcomer = NULL; /* Script to run after phys link estab. */
-int max_con_attempts = 0; /* Maximum connect tries in non-demand mode */
-int maxconnect = 0; /* Maximum connect time */
-char user[MAXNAMELEN]; /* Username for PAP */
-char passwd[MAXSECRETLEN]; /* Password for PAP */
-int auth_required = 0; /* Peer is required to authenticate */
-int defaultroute = 0; /* assign default route through interface */
-int proxyarp = 0; /* Set up proxy ARP entry for peer */
-int persist = 0; /* Reopen link after it goes down */
-int uselogin = 0; /* Use /etc/passwd for checking PAP */
-int lcp_echo_interval = 0; /* Interval between LCP echo-requests */
-int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */
-char our_name[MAXNAMELEN]; /* Our name for authentication purposes */
-char remote_name[MAXNAMELEN]; /* Peer's name for authentication */
-int explicit_remote = 0; /* User specified explicit remote name */
-int usehostname = 0; /* Use hostname for our_name */
-int disable_defaultip = 0; /* Don't use hostname for default IP adrs */
-int demand = 0; /* do dial-on-demand */
-char *ipparam = NULL; /* Extra parameter for ip up/down scripts */
-int cryptpap; /* Passwords in pap-secrets are encrypted */
-int idle_time_limit = 0; /* Disconnect if idle for this many seconds */
-int holdoff = 30; /* # seconds to pause before reconnecting */
-int refuse_pap = 0; /* Set to say we won't do PAP */
-int refuse_chap = 0; /* Set to say we won't do CHAP */
-
-#ifdef MSLANMAN
-int ms_lanman = 0; /* Nonzero if use LanMan password instead of NT */
- /* Has meaning only with MS-CHAP challenges */
-#endif
-
-struct option_info auth_req_info;
-struct option_info connector_info;
-struct option_info disconnector_info;
-struct option_info welcomer_info;
-struct option_info devnam_info;
-#ifdef PPP_FILTER
-struct bpf_program pass_filter;/* Filter program for packets to pass */
-struct bpf_program active_filter; /* Filter program for link-active pkts */
-pcap_t pc; /* Fake struct pcap so we can compile expr */
-#endif
-
-/*
- * Prototypes
- */
-static int setdevname(char *, int);
-static int setspeed(char *);
-static int setdebug(char **);
-static int setkdebug(char **);
-static int setpassive(char **);
-static int setsilent(char **);
-static int noopt(char **);
-static int setnovj(char **);
-static int setnovjccomp(char **);
-static int setvjslots(char **);
-static int reqpap(char **);
-static int nopap(char **);
-#ifdef OLD_OPTIONS
-static int setupapfile(char **);
-#endif
-static int nochap(char **);
-static int reqchap(char **);
-static int noaccomp(char **);
-static int noasyncmap(char **);
-static int noip(char **);
-static int nomagicnumber(char **);
-static int setasyncmap(char **);
-static int setescape(char **);
-static int setmru(char **);
-static int setmtu(char **);
-#ifdef CBCP_SUPPORT
-static int setcbcp(char **);
-#endif
-static int nomru(char **);
-static int nopcomp(char **);
-static int setconnector(char **);
-static int setdisconnector(char **);
-static int setwelcomer(char **);
-static int setmaxcon(char **);
-static int setmaxconnect(char **);
-static int setdomain(char **);
-static int setnetmask(char **);
-static int setcrtscts(char **);
-static int setnocrtscts(char **);
-static int setxonxoff(char **);
-static int setnodetach(char **);
-static int setupdetach(char **);
-static int setmodem(char **);
-static int setlocal(char **);
-static int setlock(char **);
-static int setname(char **);
-static int setuser(char **);
-static int setremote(char **);
-static int setauth(char **);
-static int setnoauth(char **);
-static int readfile(char **);
-static int callfile(char **);
-static int setdefaultroute(char **);
-static int setnodefaultroute(char **);
-static int setproxyarp(char **);
-static int setnoproxyarp(char **);
-static int setpersist(char **);
-static int setnopersist(char **);
-static int setdologin(char **);
-static int setusehostname(char **);
-static int setnoipdflt(char **);
-static int setlcptimeout(char **);
-static int setlcpterm(char **);
-static int setlcpconf(char **);
-static int setlcpfails(char **);
-static int setipcptimeout(char **);
-static int setipcpterm(char **);
-static int setipcpconf(char **);
-static int setipcpfails(char **);
-static int setpaptimeout(char **);
-static int setpapreqs(char **);
-static int setpapreqtime(char **);
-static int setchaptimeout(char **);
-static int setchapchal(char **);
-static int setchapintv(char **);
-static int setipcpaccl(char **);
-static int setipcpaccr(char **);
-static int setlcpechointv(char **);
-static int setlcpechofails(char **);
-static int noccp(char **);
-static int setbsdcomp(char **);
-static int setnobsdcomp(char **);
-static int setdeflate(char **);
-static int setnodeflate(char **);
-static int setnodeflatedraft(char **);
-static int setdemand(char **);
-static int setpred1comp(char **);
-static int setnopred1comp(char **);
-static int setipparam(char **);
-static int setpapcrypt(char **);
-static int setidle(char **);
-static int setholdoff(char **);
-static int setdnsaddr(char **);
-static int resetipv6proto(char **);
-static int resetipxproto(char **);
-static int setwinsaddr(char **);
-static int showversion(char **);
-static int showhelp(char **);
-
-#ifdef PPP_FILTER
-static int setpdebug(char **);
-static int setpassfilter(char **);
-static int setactivefilter(char **);
-#endif
-
-#ifdef INET6
-static int setipv6cp_accept_local(char **);
-static int setipv6cp_use_ip(char **);
-#if defined(SOL2)
-static int setipv6cp_use_persistent(char **);
-#endif
-static int setipv6cptimeout(char **);
-static int setipv6cpterm(char **);
-static int setipv6cpconf(char **);
-static int setipv6cpfails(char **);
-static int setipv6proto(char **);
-#endif /* INET6 */
-
-#ifdef IPX_CHANGE
-static int setipxproto(char **);
-static int setipxanet(char **);
-static int setipxalcl(char **);
-static int setipxarmt(char **);
-static int setipxnetwork(char **);
-static int setipxnode(char **);
-static int setipxrouter(char **);
-static int setipxname(char **);
-static int setipxcptimeout(char **);
-static int setipxcpterm(char **);
-static int setipxcpconf(char **);
-static int setipxcpfails(char **);
-#endif /* IPX_CHANGE */
-
-#ifdef MSLANMAN
-static int setmslanman(char **);
-#endif
-
-static int number_option(char *, u_int32_t *, int);
-static int int_option(char *, int *);
-static int readable(int fd);
-
-/*
- * Valid arguments.
- */
-static struct cmd {
- char *cmd_name;
- int num_args;
- int (*cmd_func)(char **);
-} cmds[] = {
- {"-all", 0, noopt}, /* Don't request/allow any options (useless) */
- {"noaccomp", 0, noaccomp}, /* Disable Address/Control compression */
- {"-ac", 0, noaccomp}, /* Disable Address/Control compress */
- {"default-asyncmap", 0, noasyncmap}, /* Disable asyncmap negoatiation */
- {"-am", 0, noasyncmap}, /* Disable asyncmap negotiation */
- {"-as", 1, setasyncmap}, /* set the desired async map */
- {"-d", 0, setdebug}, /* Increase debugging level */
- {"nodetach", 0, setnodetach}, /* Don't detach from controlling tty */
- {"-detach", 0, setnodetach}, /* don't fork */
- {"updetach", 0, setupdetach}, /* Detach once an NP has come up */
- {"noip", 0, noip}, /* Disable IP and IPCP */
- {"-ip", 0, noip}, /* Disable IP and IPCP */
- {"nomagic", 0, nomagicnumber}, /* Disable magic number negotiation */
- {"-mn", 0, nomagicnumber}, /* Disable magic number negotiation */
- {"default-mru", 0, nomru}, /* Disable MRU negotiation */
- {"-mru", 0, nomru}, /* Disable mru negotiation */
- {"-p", 0, setpassive}, /* Set passive mode */
- {"nopcomp", 0, nopcomp}, /* Disable protocol field compression */
- {"-pc", 0, nopcomp}, /* Disable protocol field compress */
-#if OLD_OPTIONS
- {"+ua", 1, setupapfile}, /* Get PAP user and password from file */
-#endif
- {"require-pap", 0, reqpap}, /* Require PAP authentication from peer */
- {"+pap", 0, reqpap}, /* Require PAP auth from peer */
- {"refuse-pap", 0, nopap}, /* Don't agree to auth to peer with PAP */
- {"-pap", 0, nopap}, /* Don't allow UPAP authentication with peer */
- {"require-chap", 0, reqchap}, /* Require CHAP authentication from peer */
- {"+chap", 0, reqchap}, /* Require CHAP authentication from peer */
- {"refuse-chap", 0, nochap}, /* Don't agree to auth to peer with CHAP */
- {"-chap", 0, nochap}, /* Don't allow CHAP authentication with peer */
- {"novj", 0, setnovj}, /* Disable VJ compression */
- {"-vj", 0, setnovj}, /* disable VJ compression */
- {"novjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */
- {"-vjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */
- {"vj-max-slots", 1, setvjslots}, /* Set maximum VJ header slots */
- {"asyncmap", 1, setasyncmap}, /* set the desired async map */
- {"escape", 1, setescape}, /* set chars to escape on transmission */
- {"connect", 1, setconnector}, /* A program to set up a connection */
- {"disconnect", 1, setdisconnector}, /* program to disconnect serial dev. */
- {"welcome", 1, setwelcomer},/* Script to welcome client */
- {"connect-max-attempts", 1, setmaxcon}, /* maximum # connect attempts */
- {"maxconnect", 1, setmaxconnect}, /* specify a maximum connect time */
- {"crtscts", 0, setcrtscts}, /* set h/w flow control */
- {"nocrtscts", 0, setnocrtscts}, /* clear h/w flow control */
- {"-crtscts", 0, setnocrtscts}, /* clear h/w flow control */
- {"xonxoff", 0, setxonxoff}, /* set s/w flow control */
- {"debug", 0, setdebug}, /* Increase debugging level */
- {"kdebug", 1, setkdebug}, /* Enable kernel-level debugging */
- {"domain", 1, setdomain}, /* Add given domain name to hostname*/
- {"mru", 1, setmru}, /* Set MRU value for negotiation */
- {"mtu", 1, setmtu}, /* Set our MTU */
-#ifdef CBCP_SUPPORT
- {"callback", 1, setcbcp}, /* Ask for callback */
-#endif
- {"netmask", 1, setnetmask}, /* set netmask */
- {"passive", 0, setpassive}, /* Set passive mode */
- {"silent", 0, setsilent}, /* Set silent mode */
- {"modem", 0, setmodem}, /* Use modem control lines */
- {"local", 0, setlocal}, /* Don't use modem control lines */
- {"lock", 0, setlock}, /* Lock serial device (with lock file) */
- {"name", 1, setname}, /* Set local name for authentication */
- {"user", 1, setuser}, /* Set name for auth with peer */
- {"usehostname", 0, setusehostname}, /* Must use hostname for auth. */
- {"remotename", 1, setremote}, /* Set remote name for authentication */
- {"auth", 0, setauth}, /* Require authentication from peer */
- {"noauth", 0, setnoauth}, /* Don't require peer to authenticate */
- {"file", 1, readfile}, /* Take options from a file */
- {"call", 1, callfile}, /* Take options from a privileged file */
- {"defaultroute", 0, setdefaultroute}, /* Add default route */
- {"nodefaultroute", 0, setnodefaultroute}, /* disable defaultroute option */
- {"-defaultroute", 0, setnodefaultroute}, /* disable defaultroute option */
- {"proxyarp", 0, setproxyarp}, /* Add proxy ARP entry */
- {"noproxyarp", 0, setnoproxyarp}, /* disable proxyarp option */
- {"-proxyarp", 0, setnoproxyarp}, /* disable proxyarp option */
- {"persist", 0, setpersist}, /* Keep on reopening connection after close */
- {"nopersist", 0, setnopersist}, /* Turn off persist option */
- {"demand", 0, setdemand}, /* Dial on demand */
- {"login", 0, setdologin}, /* Use system password database for UPAP */
- {"noipdefault", 0, setnoipdflt}, /* Don't use name for default IP adrs */
- {"lcp-echo-failure", 1, setlcpechofails}, /* consecutive echo failures */
- {"lcp-echo-interval", 1, setlcpechointv}, /* time for lcp echo events */
- {"lcp-restart", 1, setlcptimeout}, /* Set timeout for LCP */
- {"lcp-max-terminate", 1, setlcpterm}, /* Set max #xmits for term-reqs */
- {"lcp-max-configure", 1, setlcpconf}, /* Set max #xmits for conf-reqs */
- {"lcp-max-failure", 1, setlcpfails}, /* Set max #conf-naks for LCP */
- {"ipcp-restart", 1, setipcptimeout}, /* Set timeout for IPCP */
- {"ipcp-max-terminate", 1, setipcpterm}, /* Set max #xmits for term-reqs */
- {"ipcp-max-configure", 1, setipcpconf}, /* Set max #xmits for conf-reqs */
- {"ipcp-max-failure", 1, setipcpfails}, /* Set max #conf-naks for IPCP */
- {"pap-restart", 1, setpaptimeout}, /* Set retransmit timeout for PAP */
- {"pap-max-authreq", 1, setpapreqs}, /* Set max #xmits for auth-reqs */
- {"pap-timeout", 1, setpapreqtime}, /* Set time limit for peer PAP auth. */
- {"chap-restart", 1, setchaptimeout}, /* Set timeout for CHAP */
- {"chap-max-challenge", 1, setchapchal}, /* Set max #xmits for challenge */
- {"chap-interval", 1, setchapintv}, /* Set interval for rechallenge */
- {"ipcp-accept-local", 0, setipcpaccl}, /* Accept peer's address for us */
- {"ipcp-accept-remote", 0, setipcpaccr}, /* Accept peer's address for it */
- {"noccp", 0, noccp}, /* Disable CCP negotiation */
- {"-ccp", 0, noccp}, /* Disable CCP negotiation */
- {"bsdcomp", 1, setbsdcomp}, /* request BSD-Compress */
- {"nobsdcomp", 0, setnobsdcomp}, /* don't allow BSD-Compress */
- {"-bsdcomp", 0, setnobsdcomp}, /* don't allow BSD-Compress */
- {"deflate", 1, setdeflate}, /* request Deflate compression */
- {"nodeflate", 0, setnodeflate}, /* don't allow Deflate compression */
- {"-deflate", 0, setnodeflate}, /* don't allow Deflate compression */
- {"nodeflatedraft", 0, setnodeflatedraft}, /* don't use draft deflate # */
- {"predictor1", 0, setpred1comp}, /* request Predictor-1 */
- {"nopredictor1", 0, setnopred1comp},/* don't allow Predictor-1 */
- {"-predictor1", 0, setnopred1comp}, /* don't allow Predictor-1 */
- {"ipparam", 1, setipparam}, /* set ip script parameter */
- {"papcrypt", 0, setpapcrypt}, /* PAP passwords encrypted */
- {"idle", 1, setidle}, /* idle time limit (seconds) */
- {"holdoff", 1, setholdoff}, /* set holdoff time (seconds) */
-/* backwards compat hack */
- {"dns1", 1, setdnsaddr}, /* DNS address for the peer's use */
- {"dns2", 1, setdnsaddr}, /* DNS address for the peer's use */
-/* end compat hack */
- {"ms-dns", 1, setdnsaddr}, /* DNS address for the peer's use */
- {"ms-wins", 1, setwinsaddr}, /* Nameserver for SMB over TCP/IP for peer */
- {"noipv6", 0, resetipv6proto}, /* Disable IPv6 and IPv6CP */
- {"-ipv6", 0, resetipv6proto}, /* Disable IPv6 and IPv6CP */
- {"noipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */
- {"-ipx", 0, resetipxproto}, /* Disable IPXCP (and IPX) */
- {"--version", 0, showversion}, /* Show version number */
- {"--help", 0, showhelp}, /* Show brief listing of options */
- {"-h", 0, showhelp}, /* ditto */
-
-#ifdef PPP_FILTER
- {"pdebug", 1, setpdebug}, /* libpcap debugging */
- {"pass-filter", 1, setpassfilter}, /* set filter for packets to pass */
- {"active-filter", 1, setactivefilter}, /* set filter for active pkts */
-#endif
-
-#ifdef INET6
- {"ipv6", 1, setifaceid}, /* Set interface id for IPV6" */
- {"+ipv6", 0, setipv6proto}, /* Enable IPv6 and IPv6CP */
- {"ipv6cp-accept-local", 0, setipv6cp_accept_local}, /* Accept peer's iface id for us */
- {"ipv6cp-use-ipaddr", 0, setipv6cp_use_ip}, /* Use IPv4 addr as iface id */
-#if defined(SOL2)
- {"ipv6cp-use-persistent", 0, setipv6cp_use_persistent}, /* Use uniquely-available persistent value for link local addr */
-#endif
- {"ipv6cp-restart", 1, setipv6cptimeout}, /* Set timeout for IPv6CP */
- {"ipv6cp-max-terminate", 1, setipv6cpterm}, /* max #xmits for term-reqs */
- {"ipv6cp-max-configure", 1, setipv6cpconf}, /* max #xmits for conf-reqs */
- {"ipv6cp-max-failure", 1, setipv6cpfails}, /* max #conf-naks for IPv6CP */
-#endif
-
-#ifdef IPX_CHANGE
- {"ipx-network", 1, setipxnetwork}, /* IPX network number */
- {"ipxcp-accept-network", 0, setipxanet}, /* Accept peer netowrk */
- {"ipx-node", 1, setipxnode}, /* IPX node number */
- {"ipxcp-accept-local", 0, setipxalcl}, /* Accept our address */
- {"ipxcp-accept-remote", 0, setipxarmt}, /* Accept peer's address */
- {"ipx-routing", 1, setipxrouter}, /* IPX routing proto number */
- {"ipx-router-name", 1, setipxname}, /* IPX router name */
- {"ipxcp-restart", 1, setipxcptimeout}, /* Set timeout for IPXCP */
- {"ipxcp-max-terminate", 1, setipxcpterm}, /* max #xmits for term-reqs */
- {"ipxcp-max-configure", 1, setipxcpconf}, /* max #xmits for conf-reqs */
- {"ipxcp-max-failure", 1, setipxcpfails}, /* max #conf-naks for IPXCP */
-#if 0
- {"ipx-compression", 1, setipxcompression}, /* IPX compression number */
-#endif
- {"ipx", 0, setipxproto}, /* Enable IPXCP (and IPX) */
- {"+ipx", 0, setipxproto}, /* Enable IPXCP (and IPX) */
-#endif /* IPX_CHANGE */
-
-#ifdef MSLANMAN
- {"ms-lanman", 0, setmslanman}, /* Use LanMan psswd when using MS-CHAP */
-#endif
-
- {NULL, 0, NULL}
-};
-
-
-#ifndef IMPLEMENTATION
-#define IMPLEMENTATION ""
-#endif
-
-static const char usage_string[] = "\
-pppd version %s patch level %d%s\n\
-Usage: %s [ options ], where options are:\n\
- <device> Communicate over the named device\n\
- <speed> Set the baud rate to <speed>\n\
- <loc>:<rem> Set the local and/or remote interface IP\n\
- addresses. Either one may be omitted.\n\
- asyncmap <n> Set the desired async map to hex <n>\n\
- auth Require authentication from peer\n\
- connect <p> Invoke shell command <p> to set up the serial line\n\
- crtscts Use hardware RTS/CTS flow control\n\
- defaultroute Add default route through interface\n\
- file <f> Take options from file <f>\n\
- modem Use modem control lines\n\
- mru <n> Set MRU value to <n> for negotiation\n\
-See pppd(8) for more options.\n\
-";
-
-static char *current_option; /* the name of the option being parsed */
-static int privileged_option; /* set iff the current option came from root */
-static char *option_source; /* string saying where the option came from */
-
-/*
- * parse_args - parse a string of arguments from the command line.
- */
-int
-parse_args(argc, argv)
- int argc;
- char **argv;
-{
- char *arg;
- struct cmd *cmdp;
- int ret;
-
- privileged_option = privileged;
- option_source = "command line";
- while (argc > 0) {
- arg = *argv++;
- --argc;
-
- /*
- * First see if it's a command.
- */
- for (cmdp = cmds; cmdp->cmd_name; cmdp++)
- if (!strcmp(arg, cmdp->cmd_name))
- break;
-
- if (cmdp->cmd_name != NULL) {
- if (argc < cmdp->num_args) {
- option_error("too few parameters for option %s", arg);
- return 0;
- }
- current_option = arg;
- if (!(*cmdp->cmd_func)(argv))
- return 0;
- argc -= cmdp->num_args;
- argv += cmdp->num_args;
-
- } else {
- /*
- * Maybe a tty name, speed or IP address?
- */
- if ((ret = setdevname(arg, 0)) == 0
- && (ret = setspeed(arg)) == 0
- && (ret = setipaddr(arg)) == 0) {
- option_error("unrecognized option '%s'", arg);
- usage();
- return 0;
- }
- if (ret < 0) /* error */
- return 0;
- }
- }
- return 1;
-}
-
-/*
- * scan_args - scan the command line arguments to get the tty name,
- * if specified.
- */
-void
-scan_args(argc, argv)
- int argc;
- char **argv;
-{
- char *arg;
- struct cmd *cmdp;
-
- while (argc > 0) {
- arg = *argv++;
- --argc;
-
- /* Skip options and their arguments */
- for (cmdp = cmds; cmdp->cmd_name; cmdp++)
- if (!strcmp(arg, cmdp->cmd_name))
- break;
-
- if (cmdp->cmd_name != NULL) {
- argc -= cmdp->num_args;
- argv += cmdp->num_args;
- continue;
- }
-
- /* Check if it's a tty name and copy it if so */
- (void) setdevname(arg, 1);
- }
-}
-
-/*
- * usage - print out a message telling how to use the program.
- */
-void
-usage()
-{
- if (phase == PHASE_INITIALIZE)
- fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION,
- progname);
-}
-
-/*
- * showhelp - print out usage message and exit.
- */
-static int
-showhelp(argv)
- char **argv;
-{
- if (phase == PHASE_INITIALIZE) {
- usage();
- exit(0);
- }
- return 0;
-}
-
-/*
- * showversion - print out the version number and exit.
- */
-static int
-showversion(argv)
- char **argv;
-{
- if (phase == PHASE_INITIALIZE) {
- fprintf(stderr, "pppd version %s patch level %d%s\n",
- VERSION, PATCHLEVEL, IMPLEMENTATION);
- exit(0);
- }
- return 0;
-}
-
-/*
- * options_from_file - Read a string of options from a file,
- * and interpret them.
- */
-int
-options_from_file(filename, must_exist, check_prot, priv)
- char *filename;
- int must_exist;
- int check_prot;
- int priv;
-{
- FILE *f;
- int i, newline, ret;
- struct cmd *cmdp;
- int oldpriv;
- char *argv[MAXARGS];
- char args[MAXARGS][MAXWORDLEN];
- char cmd[MAXWORDLEN];
-
- if ((f = fopen(filename, "r")) == NULL) {
- if (!must_exist && errno == ENOENT)
- return 1;
- option_error("Can't open options file %s: %m", filename);
- return 0;
- }
- if (check_prot && !readable(fileno(f))) {
- option_error("Can't open options file %s: access denied", filename);
- fclose(f);
- return 0;
- }
-
- oldpriv = privileged_option;
- privileged_option = priv;
- ret = 0;
- while (getword(f, cmd, &newline, filename)) {
- /*
- * First see if it's a command.
- */
- for (cmdp = cmds; cmdp->cmd_name; cmdp++)
- if (!strcmp(cmd, cmdp->cmd_name))
- break;
-
- if (cmdp->cmd_name != NULL) {
- for (i = 0; i < cmdp->num_args; ++i) {
- if (!getword(f, args[i], &newline, filename)) {
- option_error(
- "In file %s: too few parameters for option '%s'",
- filename, cmd);
- goto err;
- }
- argv[i] = args[i];
- }
- current_option = cmd;
- if (!(*cmdp->cmd_func)(argv))
- goto err;
-
- } else {
- /*
- * Maybe a tty name, speed or IP address?
- */
- if ((i = setdevname(cmd, 0)) == 0
- && (i = setspeed(cmd)) == 0
- && (i = setipaddr(cmd)) == 0) {
- option_error("In file %s: unrecognized option '%s'",
- filename, cmd);
- goto err;
- }
- if (i < 0) /* error */
- goto err;
- }
- }
- ret = 1;
-
-err:
- fclose(f);
- privileged_option = oldpriv;
- return ret;
-}
-
-/*
- * options_from_user - See if the use has a ~/.ppprc file,
- * and if so, interpret options from it.
- */
-int
-options_from_user()
-{
- char *user, *path, *file;
- int ret;
- struct passwd *pw;
-
- pw = getpwuid(getuid());
- if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0)
- return 1;
- file = _PATH_USEROPT;
- path = malloc(strlen(user) + strlen(file) + 2);
- if (path == NULL)
- novm("init file name");
- strcpy(path, user);
- strcat(path, "/");
- strcat(path, file);
- ret = options_from_file(path, 0, 1, privileged);
- free(path);
- return ret;
-}
-
-/*
- * options_for_tty - See if an options file exists for the serial
- * device, and if so, interpret options from it.
- */
-int
-options_for_tty()
-{
- char *dev, *path, *p;
- int ret;
-
- dev = devnam;
- if (strncmp(dev, _PATH_DEV, sizeof _PATH_DEV - 1) == 0)
- dev += 5;
- if (strcmp(dev, "tty") == 0)
- return 1; /* don't look for /etc/ppp/options.tty */
- path = malloc(strlen(_PATH_TTYOPT) + strlen(dev) + 1);
- if (path == NULL)
- novm("tty init file name");
- strcpy(path, _PATH_TTYOPT);
- /* Turn slashes into dots, for Solaris case (e.g. /dev/term/a) */
- for (p = path + strlen(path); *dev != 0; ++dev)
- *p++ = (*dev == '/'? '.': *dev);
- *p = 0;
- ret = options_from_file(path, 0, 0, 1);
- free(path);
- return ret;
-}
-
-/*
- * option_error - print a message about an error in an option.
- * The message is logged, and also sent to
- * stderr if phase == PHASE_INITIALIZE.
- */
-void
-option_error __V((char *fmt, ...))
-{
- va_list args;
- char buf[256];
-
-#if __STDC__
- va_start(args, fmt);
-#else
- char *fmt;
- va_start(args);
- fmt = va_arg(args, char *);
-#endif
- vfmtmsg(buf, sizeof(buf), fmt, args);
- va_end(args);
- if (phase == PHASE_INITIALIZE)
- fprintf(stderr, "%s: %s\n", progname, buf);
- syslog(LOG_ERR, "%s", buf);
-}
-
-/*
- * readable - check if a file is readable by the real user.
- */
-static int
-readable(fd)
- int fd;
-{
- uid_t uid;
- int ngroups, i;
- struct stat sbuf;
- GIDSET_TYPE groups[NGROUPS_MAX];
-
- uid = getuid();
- if (uid == 0)
- return 1;
- if (fstat(fd, &sbuf) != 0)
- return 0;
- if (sbuf.st_uid == uid)
- return sbuf.st_mode & S_IRUSR;
- if (sbuf.st_gid == getgid())
- return sbuf.st_mode & S_IRGRP;
- ngroups = getgroups(NGROUPS_MAX, groups);
- for (i = 0; i < ngroups; ++i)
- if (sbuf.st_gid == groups[i])
- return sbuf.st_mode & S_IRGRP;
- return sbuf.st_mode & S_IROTH;
-}
-
-/*
- * Read a word from a file.
- * Words are delimited by white-space or by quotes (" or ').
- * Quotes, white-space and \ may be escaped with \.
- * \<newline> is ignored.
- */
-int
-getword(f, word, newlinep, filename)
- FILE *f;
- char *word;
- int *newlinep;
- char *filename;
-{
- int c, len, escape;
- int quoted, comment;
- int value, digit, got, n;
-
-#define isoctal(c) ((c) >= '0' && (c) < '8')
-
- *newlinep = 0;
- len = 0;
- escape = 0;
- comment = 0;
-
- /*
- * First skip white-space and comments.
- */
- for (;;) {
- c = getc(f);
- if (c == EOF)
- break;
-
- /*
- * A newline means the end of a comment; backslash-newline
- * is ignored. Note that we cannot have escape && comment.
- */
- if (c == '\n') {
- if (!escape) {
- *newlinep = 1;
- comment = 0;
- } else
- escape = 0;
- continue;
- }
-
- /*
- * Ignore characters other than newline in a comment.
- */
- if (comment)
- continue;
-
- /*
- * If this character is escaped, we have a word start.
- */
- if (escape)
- break;
-
- /*
- * If this is the escape character, look at the next character.
- */
- if (c == '\\') {
- escape = 1;
- continue;
- }
-
- /*
- * If this is the start of a comment, ignore the rest of the line.
- */
- if (c == '#') {
- comment = 1;
- continue;
- }
-
- /*
- * A non-whitespace character is the start of a word.
- */
- if (!isspace(c))
- break;
- }
-
- /*
- * Save the delimiter for quoted strings.
- */
- if (!escape && (c == '"' || c == '\'')) {
- quoted = c;
- c = getc(f);
- } else
- quoted = 0;
-
- /*
- * Process characters until the end of the word.
- */
- while (c != EOF) {
- if (escape) {
- /*
- * This character is escaped: backslash-newline is ignored,
- * various other characters indicate particular values
- * as for C backslash-escapes.
- */
- escape = 0;
- if (c == '\n') {
- c = getc(f);
- continue;
- }
-
- got = 0;
- switch (c) {
- case 'a':
- value = '\a';
- break;
- case 'b':
- value = '\b';
- break;
- case 'f':
- value = '\f';
- break;
- case 'n':
- value = '\n';
- break;
- case 'r':
- value = '\r';
- break;
- case 's':
- value = ' ';
- break;
- case 't':
- value = '\t';
- break;
-
- default:
- if (isoctal(c)) {
- /*
- * \ddd octal sequence
- */
- value = 0;
- for (n = 0; n < 3 && isoctal(c); ++n) {
- value = (value << 3) + (c & 07);
- c = getc(f);
- }
- got = 1;
- break;
- }
-
- if (c == 'x') {
- /*
- * \x<hex_string> sequence
- */
- value = 0;
- c = getc(f);
- for (n = 0; n < 2 && isxdigit(c); ++n) {
- digit = toupper(c) - '0';
- if (digit > 10)
- digit += '0' + 10 - 'A';
- value = (value << 4) + digit;
- c = getc (f);
- }
- got = 1;
- break;
- }
-
- /*
- * Otherwise the character stands for itself.
- */
- value = c;
- break;
- }
-
- /*
- * Store the resulting character for the escape sequence.
- */
- if (len < MAXWORDLEN-1)
- word[len] = value;
- ++len;
-
- if (!got)
- c = getc(f);
- continue;
-
- }
-
- /*
- * Not escaped: see if we've reached the end of the word.
- */
- if (quoted) {
- if (c == quoted)
- break;
- } else {
- if (isspace(c) || c == '#') {
- ungetc (c, f);
- break;
- }
- }
-
- /*
- * Backslash starts an escape sequence.
- */
- if (c == '\\') {
- escape = 1;
- c = getc(f);
- continue;
- }
-
- /*
- * An ordinary character: store it in the word and get another.
- */
- if (len < MAXWORDLEN-1)
- word[len] = c;
- ++len;
-
- c = getc(f);
- }
-
- /*
- * End of the word: check for errors.
- */
- if (c == EOF) {
- if (ferror(f)) {
- if (errno == 0)
- errno = EIO;
- option_error("Error reading %s: %m", filename);
- die(1);
- }
- /*
- * If len is zero, then we didn't find a word before the
- * end of the file.
- */
- if (len == 0)
- return 0;
- }
-
- /*
- * Warn if the word was too long, and append a terminating null.
- */
- if (len >= MAXWORDLEN) {
- option_error("warning: word in file %s too long (%.20s...)",
- filename, word);
- len = MAXWORDLEN - 1;
- }
- word[len] = 0;
-
- return 1;
-
-#undef isoctal
-
-}
-
-/*
- * number_option - parse an unsigned numeric parameter for an option.
- */
-static int
-number_option(str, valp, base)
- char *str;
- u_int32_t *valp;
- int base;
-{
- char *ptr;
-
- *valp = strtoul(str, &ptr, base);
- if (ptr == str) {
- option_error("invalid numeric parameter '%s' for %s option",
- str, current_option);
- return 0;
- }
- return 1;
-}
-
-
-/*
- * int_option - like number_option, but valp is int *,
- * the base is assumed to be 0, and *valp is not changed
- * if there is an error.
- */
-static int
-int_option(str, valp)
- char *str;
- int *valp;
-{
- u_int32_t v;
-
- if (!number_option(str, &v, 0))
- return 0;
- *valp = (int) v;
- return 1;
-}
-
-
-/*
- * The following procedures parse options.
- */
-
-/*
- * readfile - take commands from a file.
- */
-static int
-readfile(argv)
- char **argv;
-{
- return options_from_file(*argv, 1, 1, privileged_option);
-}
-
-/*
- * callfile - take commands from /etc/ppp/peers/<name>.
- * Name may not contain /../, start with / or ../, or end in /..
- */
-static int
-callfile(argv)
- char **argv;
-{
- char *fname, *arg, *p;
- int l, ok;
-
- arg = *argv;
- ok = 1;
- if (arg[0] == '/' || arg[0] == 0)
- ok = 0;
- else {
- for (p = arg; *p != 0; ) {
- if (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == 0)) {
- ok = 0;
- break;
- }
- while (*p != '/' && *p != 0)
- ++p;
- if (*p == '/')
- ++p;
- }
- }
- if (!ok) {
- option_error("call option value may not contain .. or start with /");
- return 0;
- }
-
- l = strlen(arg) + strlen(_PATH_PEERFILES) + 1;
- if ((fname = (char *) malloc(l)) == NULL)
- novm("call file name");
- strcpy(fname, _PATH_PEERFILES);
- strcat(fname, arg);
-
- ok = options_from_file(fname, 1, 1, 1);
-
- free(fname);
- return ok;
-}
-
-
-/*
- * setdebug - Set debug (command line argument).
- */
-static int
-setdebug(argv)
- char **argv;
-{
- debug++;
- return (1);
-}
-
-/*
- * setkdebug - Set kernel debugging level.
- */
-static int
-setkdebug(argv)
- char **argv;
-{
- return int_option(*argv, &kdebugflag);
-}
-
-#ifdef PPP_FILTER
-/*
- * setpdebug - Set libpcap debugging level.
- */
-static int
-setpdebug(argv)
- char **argv;
-{
- return int_option(*argv, &dflag);
-}
-
-/*
- * setpassfilter - Set the pass filter for packets
- */
-static int
-setpassfilter(argv)
- char **argv;
-{
- pc.linktype = DLT_PPP;
- pc.snapshot = PPP_HDRLEN;
-
- if (pcap_compile(&pc, &pass_filter, *argv, 1, netmask) == 0)
- return 1;
- option_error("error in pass-filter expression: %s\n", pcap_geterr(&pc));
- return 0;
-}
-
-/*
- * setactivefilter - Set the active filter for packets
- */
-static int
-setactivefilter(argv)
- char **argv;
-{
- pc.linktype = DLT_PPP;
- pc.snapshot = PPP_HDRLEN;
-
- if (pcap_compile(&pc, &active_filter, *argv, 1, netmask) == 0)
- return 1;
- option_error("error in active-filter expression: %s\n", pcap_geterr(&pc));
- return 0;
-}
-#endif
-
-/*
- * noopt - Disable all options.
- */
-static int
-noopt(argv)
- char **argv;
-{
- BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
- BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
- BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options));
- BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options));
-
-#ifdef IPX_CHANGE
- BZERO((char *) &ipxcp_wantoptions[0], sizeof (struct ipxcp_options));
- BZERO((char *) &ipxcp_allowoptions[0], sizeof (struct ipxcp_options));
-#endif /* IPX_CHANGE */
-
- return (1);
-}
-
-/*
- * noaccomp - Disable Address/Control field compression negotiation.
- */
-static int
-noaccomp(argv)
- char **argv;
-{
- lcp_wantoptions[0].neg_accompression = 0;
- lcp_allowoptions[0].neg_accompression = 0;
- return (1);
-}
-
-
-/*
- * noasyncmap - Disable async map negotiation.
- */
-static int
-noasyncmap(argv)
- char **argv;
-{
- lcp_wantoptions[0].neg_asyncmap = 0;
- lcp_allowoptions[0].neg_asyncmap = 0;
- return (1);
-}
-
-
-/*
- * noip - Disable IP and IPCP.
- */
-static int
-noip(argv)
- char **argv;
-{
- ipcp_protent.enabled_flag = 0;
- return (1);
-}
-
-
-/*
- * nomagicnumber - Disable magic number negotiation.
- */
-static int
-nomagicnumber(argv)
- char **argv;
-{
- lcp_wantoptions[0].neg_magicnumber = 0;
- lcp_allowoptions[0].neg_magicnumber = 0;
- return (1);
-}
-
-
-/*
- * nomru - Disable mru negotiation.
- */
-static int
-nomru(argv)
- char **argv;
-{
- lcp_wantoptions[0].neg_mru = 0;
- lcp_allowoptions[0].neg_mru = 0;
- return (1);
-}
-
-
-/*
- * setmru - Set MRU for negotiation.
- */
-static int
-setmru(argv)
- char **argv;
-{
- u_int32_t mru;
-
- if (!number_option(*argv, &mru, 0))
- return 0;
- lcp_wantoptions[0].mru = mru;
- lcp_wantoptions[0].neg_mru = 1;
- return (1);
-}
-
-
-/*
- * setmru - Set the largest MTU we'll use.
- */
-static int
-setmtu(argv)
- char **argv;
-{
- u_int32_t mtu;
-
- if (!number_option(*argv, &mtu, 0))
- return 0;
- if (mtu < MINMRU || mtu > MAXMRU) {
- option_error("mtu option value of %u is too %s", mtu,
- (mtu < MINMRU? "small": "large"));
- return 0;
- }
- lcp_allowoptions[0].mru = mtu;
- return (1);
-}
-
-#ifdef CBCP_SUPPORT
-static int
-setcbcp(argv)
- char **argv;
-{
- lcp_wantoptions[0].neg_cbcp = 1;
- cbcp_protent.enabled_flag = 1;
- cbcp[0].us_number = strdup(*argv);
- if (cbcp[0].us_number == 0)
- novm("callback number");
- cbcp[0].us_type |= (1 << CB_CONF_USER);
- cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
- return (1);
-}
-#endif
-
-/*
- * nopcomp - Disable Protocol field compression negotiation.
- */
-static int
-nopcomp(argv)
- char **argv;
-{
- lcp_wantoptions[0].neg_pcompression = 0;
- lcp_allowoptions[0].neg_pcompression = 0;
- return (1);
-}
-
-
-/*
- * setpassive - Set passive mode (don't give up if we time out sending
- * LCP configure-requests).
- */
-static int
-setpassive(argv)
- char **argv;
-{
- lcp_wantoptions[0].passive = 1;
- return (1);
-}
-
-
-/*
- * setsilent - Set silent mode (don't start sending LCP configure-requests
- * until we get one from the peer).
- */
-static int
-setsilent(argv)
- char **argv;
-{
- lcp_wantoptions[0].silent = 1;
- return 1;
-}
-
-
-/*
- * nopap - Disable PAP authentication with peer.
- */
-static int
-nopap(argv)
- char **argv;
-{
- refuse_pap = 1;
- return (1);
-}
-
-
-/*
- * reqpap - Require PAP authentication from peer.
- */
-static int
-reqpap(argv)
- char **argv;
-{
- lcp_wantoptions[0].neg_upap = 1;
- setauth(NULL);
- return 1;
-}
-
-#if OLD_OPTIONS
-/*
- * setupapfile - specifies UPAP info for authenticating with peer.
- */
-static int
-setupapfile(argv)
- char **argv;
-{
- FILE * ufile;
- int l;
-
- lcp_allowoptions[0].neg_upap = 1;
-
- /* open user info file */
- if ((ufile = fopen(*argv, "r")) == NULL) {
- option_error("unable to open user login data file %s", *argv);
- return 0;
- }
- if (!readable(fileno(ufile))) {
- option_error("%s: access denied", *argv);
- return 0;
- }
- check_access(ufile, *argv);
-
- /* get username */
- if (fgets(user, MAXNAMELEN - 1, ufile) == NULL
- || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){
- option_error("unable to read user login data file %s", *argv);
- return 0;
- }
- fclose(ufile);
-
- /* get rid of newlines */
- l = strlen(user);
- if (l > 0 && user[l-1] == '\n')
- user[l-1] = 0;
- l = strlen(passwd);
- if (l > 0 && passwd[l-1] == '\n')
- passwd[l-1] = 0;
-
- return (1);
-}
-#endif
-
-/*
- * nochap - Disable CHAP authentication with peer.
- */
-static int
-nochap(argv)
- char **argv;
-{
- refuse_chap = 1;
- return (1);
-}
-
-
-/*
- * reqchap - Require CHAP authentication from peer.
- */
-static int
-reqchap(argv)
- char **argv;
-{
- lcp_wantoptions[0].neg_chap = 1;
- setauth(NULL);
- return (1);
-}
-
-
-/*
- * setnovj - disable vj compression
- */
-static int
-setnovj(argv)
- char **argv;
-{
- ipcp_wantoptions[0].neg_vj = 0;
- ipcp_allowoptions[0].neg_vj = 0;
- return (1);
-}
-
-
-/*
- * setnovjccomp - disable VJ connection-ID compression
- */
-static int
-setnovjccomp(argv)
- char **argv;
-{
- ipcp_wantoptions[0].cflag = 0;
- ipcp_allowoptions[0].cflag = 0;
- return 1;
-}
-
-
-/*
- * setvjslots - set maximum number of connection slots for VJ compression
- */
-static int
-setvjslots(argv)
- char **argv;
-{
- int value;
-
- if (!int_option(*argv, &value))
- return 0;
- if (value < 2 || value > 16) {
- option_error("vj-max-slots value must be between 2 and 16");
- return 0;
- }
- ipcp_wantoptions [0].maxslotindex =
- ipcp_allowoptions[0].maxslotindex = value - 1;
- return 1;
-}
-
-
-/*
- * setconnector - Set a program to connect to a serial line
- */
-static int
-setconnector(argv)
- char **argv;
-{
- connector = strdup(*argv);
- if (connector == NULL)
- novm("connect script");
- connector_info.priv = privileged_option;
- connector_info.source = option_source;
-
- return (1);
-}
-
-/*
- * setdisconnector - Set a program to disconnect from the serial line
- */
-static int
-setdisconnector(argv)
- char **argv;
-{
- disconnector = strdup(*argv);
- if (disconnector == NULL)
- novm("disconnect script");
- disconnector_info.priv = privileged_option;
- disconnector_info.source = option_source;
-
- return (1);
-}
-
-/*
- * setwelcomer - Set a program to welcome a client after connection
- */
-static int
-setwelcomer(argv)
- char **argv;
-{
- welcomer = strdup(*argv);
- if (welcomer == NULL)
- novm("welcome script");
- welcomer_info.priv = privileged_option;
- welcomer_info.source = option_source;
-
- return (1);
-}
-
-static int
-setmaxcon(argv)
- char **argv;
-{
- return int_option(*argv, &max_con_attempts);
-}
-
-/*
- * setmaxconnect - Set the maximum connect time
- */
-static int
-setmaxconnect(argv)
- char **argv;
-{
- int value;
-
- if (!int_option(*argv, &value))
- return 0;
- if (value < 0) {
- option_error("maxconnect time must be positive");
- return 0;
- }
- if (maxconnect > 0 && (value == 0 || value > maxconnect)) {
- option_error("maxconnect time cannot be increased");
- return 0;
- }
- maxconnect = value;
- return 1;
-}
-
-/*
- * setdomain - Set domain name to append to hostname
- */
-static int
-setdomain(argv)
- char **argv;
-{
- if (!privileged_option) {
- option_error("using the domain option requires root privilege");
- return 0;
- }
- gethostname(hostname, MAXNAMELEN);
- if (**argv != 0) {
- if (**argv != '.')
- strncat(hostname, ".", MAXNAMELEN - strlen(hostname));
- strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
- }
- hostname[MAXNAMELEN-1] = 0;
- return (1);
-}
-
-
-/*
- * setasyncmap - add bits to asyncmap (what we request peer to escape).
- */
-static int
-setasyncmap(argv)
- char **argv;
-{
- u_int32_t asyncmap;
-
- if (!number_option(*argv, &asyncmap, 16))
- return 0;
- lcp_wantoptions[0].asyncmap |= asyncmap;
- lcp_wantoptions[0].neg_asyncmap = 1;
- return(1);
-}
-
-
-/*
- * setescape - add chars to the set we escape on transmission.
- */
-static int
-setescape(argv)
- char **argv;
-{
- int n, ret;
- char *p, *endp;
-
- p = *argv;
- ret = 1;
- while (*p) {
- n = strtol(p, &endp, 16);
- if (p == endp) {
- option_error("escape parameter contains invalid hex number '%s'",
- p);
- return 0;
- }
- p = endp;
- if (n < 0 || (0x20 <= n && n <= 0x3F) || n == 0x5E || n > 0xFF) {
- option_error("can't escape character 0x%x", n);
- ret = 0;
- } else
- xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
- while (*p == ',' || *p == ' ')
- ++p;
- }
- return ret;
-}
-
-
-/*
- * setspeed - Set the speed.
- */
-static int
-setspeed(arg)
- char *arg;
-{
- char *ptr;
- int spd;
-
- spd = strtol(arg, &ptr, 0);
- if (ptr == arg || *ptr != 0 || spd == 0)
- return 0;
- inspeed = spd;
- return 1;
-}
-
-
-/*
- * setdevname - Set the device name.
- */
-static int
-setdevname(cp, quiet)
- char *cp;
- int quiet;
-{
- struct stat statbuf;
- char dev[MAXPATHLEN];
-
- if (*cp == 0)
- return 0;
-
- if (strncmp(_PATH_DEV, cp, sizeof _PATH_DEV - 1) != 0) {
- strcpy(dev, _PATH_DEV);
- strncat(dev, cp, MAXPATHLEN - sizeof _PATH_DEV - 1);
- dev[MAXPATHLEN-1] = 0;
- cp = dev;
- }
-
- /*
- * Check if there is a device by this name.
- */
- if (stat(cp, &statbuf) < 0) {
- if (errno == ENOENT || quiet)
- return 0;
- option_error("Couldn't stat %s: %m", cp);
- return -1;
- }
-
- (void) strncpy(devnam, cp, MAXPATHLEN);
- devnam[MAXPATHLEN-1] = 0;
- default_device = FALSE;
- devnam_info.priv = privileged_option;
- devnam_info.source = option_source;
-
- return 1;
-}
-
-
-/*
- * setipaddr - Set the IP address
- */
-int
-setipaddr(arg)
- char *arg;
-{
- struct hostent *hp;
- char *colon;
- u_int32_t local, remote;
- ipcp_options *wo = &ipcp_wantoptions[0];
-
- /*
- * IP address pair separated by ":".
- */
- if ((colon = strchr(arg, ':')) == NULL)
- return 0;
-
- /*
- * If colon first character, then no local addr.
- */
- if (colon != arg) {
- *colon = '\0';
- if ((local = inet_addr(arg)) == -1) {
- if ((hp = gethostbyname(arg)) == NULL) {
- option_error("unknown host: %s", arg);
- return -1;
- } else {
- local = *(u_int32_t *)hp->h_addr;
- }
- }
- if (bad_ip_adrs(local)) {
- option_error("bad local IP address %s", ip_ntoa(local));
- return -1;
- }
- if (local != 0)
- wo->ouraddr = local;
- *colon = ':';
- }
-
- /*
- * If colon last character, then no remote addr.
- */
- if (*++colon != '\0') {
- if ((remote = inet_addr(colon)) == -1) {
- if ((hp = gethostbyname(colon)) == NULL) {
- option_error("unknown host: %s", colon);
- return -1;
- } else {
- remote = *(u_int32_t *)hp->h_addr;
- if (remote_name[0] == 0) {
- strncpy(remote_name, colon, MAXNAMELEN);
- remote_name[MAXNAMELEN-1] = 0;
- }
- }
- }
- if (bad_ip_adrs(remote)) {
- option_error("bad remote IP address %s", ip_ntoa(remote));
- return -1;
- }
- if (remote != 0)
- wo->hisaddr = remote;
- }
-
- return 1;
-}
-
-
-/*
- * setnoipdflt - disable setipdefault()
- */
-static int
-setnoipdflt(argv)
- char **argv;
-{
- disable_defaultip = 1;
- return 1;
-}
-
-
-/*
- * setipcpaccl - accept peer's idea of our address
- */
-static int
-setipcpaccl(argv)
- char **argv;
-{
- ipcp_wantoptions[0].accept_local = 1;
- return 1;
-}
-
-
-/*
- * setipcpaccr - accept peer's idea of its address
- */
-static int
-setipcpaccr(argv)
- char **argv;
-{
- ipcp_wantoptions[0].accept_remote = 1;
- return 1;
-}
-
-
-/*
- * setnetmask - set the netmask to be used on the interface.
- */
-static int
-setnetmask(argv)
- char **argv;
-{
- struct in_addr mask;
-
- if (!inet_aton(*argv, &mask) || (netmask & ~mask.s_addr)) {
- fprintf(stderr, "Invalid netmask %s\n", *argv);
- return (0);
- }
-
- netmask = mask.s_addr;
- return (1);
-}
-
-static int
-setcrtscts(argv)
- char **argv;
-{
- crtscts = 1;
- return (1);
-}
-
-static int
-setnocrtscts(argv)
- char **argv;
-{
- crtscts = -1;
- return (1);
-}
-
-static int
-setxonxoff(argv)
- char **argv;
-{
- lcp_wantoptions[0].asyncmap |= 0x000A0000; /* escape ^S and ^Q */
- lcp_wantoptions[0].neg_asyncmap = 1;
-
- crtscts = -2;
- return (1);
-}
-
-static int
-setnodetach(argv)
- char **argv;
-{
- nodetach = 1;
- return (1);
-}
-
-static int
-setupdetach(argv)
- char **argv;
-{
- nodetach = -1;
- return (1);
-}
-
-static int
-setdemand(argv)
- char **argv;
-{
- demand = 1;
- persist = 1;
- return 1;
-}
-
-static int
-setmodem(argv)
- char **argv;
-{
- modem = 1;
- return 1;
-}
-
-static int
-setlocal(argv)
- char **argv;
-{
- modem = 0;
- return 1;
-}
-
-static int
-setlock(argv)
- char **argv;
-{
- lockflag = 1;
- return 1;
-}
-
-static int
-setusehostname(argv)
- char **argv;
-{
- usehostname = 1;
- return 1;
-}
-
-static int
-setname(argv)
- char **argv;
-{
- if (!privileged_option) {
- option_error("using the name option requires root privilege");
- return 0;
- }
- strncpy(our_name, argv[0], MAXNAMELEN);
- our_name[MAXNAMELEN-1] = 0;
- return 1;
-}
-
-static int
-setuser(argv)
- char **argv;
-{
- strncpy(user, argv[0], MAXNAMELEN);
- user[MAXNAMELEN-1] = 0;
- return 1;
-}
-
-static int
-setremote(argv)
- char **argv;
-{
- strncpy(remote_name, argv[0], MAXNAMELEN);
- remote_name[MAXNAMELEN-1] = 0;
- return 1;
-}
-
-static int
-setauth(argv)
- char **argv;
-{
- auth_required = 1;
- if (privileged_option > auth_req_info.priv) {
- auth_req_info.priv = privileged_option;
- auth_req_info.source = option_source;
- }
- return 1;
-}
-
-static int
-setnoauth(argv)
- char **argv;
-{
- if (auth_required && privileged_option < auth_req_info.priv) {
- option_error("cannot override auth option set by %s",
- auth_req_info.source);
- return 0;
- }
- auth_required = 0;
- return 1;
-}
-
-static int
-setdefaultroute(argv)
- char **argv;
-{
- if (!ipcp_allowoptions[0].default_route) {
- option_error("defaultroute option is disabled");
- return 0;
- }
- ipcp_wantoptions[0].default_route = 1;
- return 1;
-}
-
-static int
-setnodefaultroute(argv)
- char **argv;
-{
- ipcp_allowoptions[0].default_route = 0;
- ipcp_wantoptions[0].default_route = 0;
- return 1;
-}
-
-static int
-setproxyarp(argv)
- char **argv;
-{
- if (!ipcp_allowoptions[0].proxy_arp) {
- option_error("proxyarp option is disabled");
- return 0;
- }
- ipcp_wantoptions[0].proxy_arp = 1;
- return 1;
-}
-
-static int
-setnoproxyarp(argv)
- char **argv;
-{
- ipcp_wantoptions[0].proxy_arp = 0;
- ipcp_allowoptions[0].proxy_arp = 0;
- return 1;
-}
-
-static int
-setpersist(argv)
- char **argv;
-{
- persist = 1;
- return 1;
-}
-
-static int
-setnopersist(argv)
- char **argv;
-{
- persist = 0;
- return 1;
-}
-
-static int
-setdologin(argv)
- char **argv;
-{
- uselogin = 1;
- return 1;
-}
-
-/*
- * Functions to set the echo interval for modem-less monitors
- */
-
-static int
-setlcpechointv(argv)
- char **argv;
-{
- return int_option(*argv, &lcp_echo_interval);
-}
-
-static int
-setlcpechofails(argv)
- char **argv;
-{
- return int_option(*argv, &lcp_echo_fails);
-}
-
-/*
- * Functions to set timeouts, max transmits, etc.
- */
-static int
-setlcptimeout(argv)
- char **argv;
-{
- return int_option(*argv, &lcp_fsm[0].timeouttime);
-}
-
-static int
-setlcpterm(argv)
- char **argv;
-{
- return int_option(*argv, &lcp_fsm[0].maxtermtransmits);
-}
-
-static int
-setlcpconf(argv)
- char **argv;
-{
- return int_option(*argv, &lcp_fsm[0].maxconfreqtransmits);
-}
-
-static int
-setlcpfails(argv)
- char **argv;
-{
- return int_option(*argv, &lcp_fsm[0].maxnakloops);
-}
-
-static int
-setipcptimeout(argv)
- char **argv;
-{
- return int_option(*argv, &ipcp_fsm[0].timeouttime);
-}
-
-static int
-setipcpterm(argv)
- char **argv;
-{
- return int_option(*argv, &ipcp_fsm[0].maxtermtransmits);
-}
-
-static int
-setipcpconf(argv)
- char **argv;
-{
- return int_option(*argv, &ipcp_fsm[0].maxconfreqtransmits);
-}
-
-static int
-setipcpfails(argv)
- char **argv;
-{
- return int_option(*argv, &lcp_fsm[0].maxnakloops);
-}
-
-static int
-setpaptimeout(argv)
- char **argv;
-{
- return int_option(*argv, &upap[0].us_timeouttime);
-}
-
-static int
-setpapreqtime(argv)
- char **argv;
-{
- return int_option(*argv, &upap[0].us_reqtimeout);
-}
-
-static int
-setpapreqs(argv)
- char **argv;
-{
- return int_option(*argv, &upap[0].us_maxtransmits);
-}
-
-static int
-setchaptimeout(argv)
- char **argv;
-{
- return int_option(*argv, &chap[0].timeouttime);
-}
-
-static int
-setchapchal(argv)
- char **argv;
-{
- return int_option(*argv, &chap[0].max_transmits);
-}
-
-static int
-setchapintv(argv)
- char **argv;
-{
- return int_option(*argv, &chap[0].chal_interval);
-}
-
-static int
-noccp(argv)
- char **argv;
-{
- ccp_protent.enabled_flag = 0;
- return 1;
-}
-
-static int
-setbsdcomp(argv)
- char **argv;
-{
- int rbits, abits;
- char *str, *endp;
-
- str = *argv;
- abits = rbits = strtol(str, &endp, 0);
- if (endp != str && *endp == ',') {
- str = endp + 1;
- abits = strtol(str, &endp, 0);
- }
- if (*endp != 0 || endp == str) {
- option_error("invalid parameter '%s' for bsdcomp option", *argv);
- return 0;
- }
- if ((rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS))
- || (abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS))) {
- option_error("bsdcomp option values must be 0 or %d .. %d",
- BSD_MIN_BITS, BSD_MAX_BITS);
- return 0;
- }
- if (rbits > 0) {
- ccp_wantoptions[0].bsd_compress = 1;
- ccp_wantoptions[0].bsd_bits = rbits;
- } else
- ccp_wantoptions[0].bsd_compress = 0;
- if (abits > 0) {
- ccp_allowoptions[0].bsd_compress = 1;
- ccp_allowoptions[0].bsd_bits = abits;
- } else
- ccp_allowoptions[0].bsd_compress = 0;
- return 1;
-}
-
-static int
-setnobsdcomp(argv)
- char **argv;
-{
- ccp_wantoptions[0].bsd_compress = 0;
- ccp_allowoptions[0].bsd_compress = 0;
- return 1;
-}
-
-static int
-setdeflate(argv)
- char **argv;
-{
- int rbits, abits;
- char *str, *endp;
-
- str = *argv;
- abits = rbits = strtol(str, &endp, 0);
- if (endp != str && *endp == ',') {
- str = endp + 1;
- abits = strtol(str, &endp, 0);
- }
- if (*endp != 0 || endp == str) {
- option_error("invalid parameter '%s' for deflate option", *argv);
- return 0;
- }
- if ((rbits != 0 && (rbits < DEFLATE_MIN_SIZE || rbits > DEFLATE_MAX_SIZE))
- || (abits != 0 && (abits < DEFLATE_MIN_SIZE
- || abits > DEFLATE_MAX_SIZE))) {
- option_error("deflate option values must be 0 or %d .. %d",
- DEFLATE_MIN_SIZE, DEFLATE_MAX_SIZE);
- return 0;
- }
- if (rbits > 0) {
- ccp_wantoptions[0].deflate = 1;
- ccp_wantoptions[0].deflate_size = rbits;
- } else
- ccp_wantoptions[0].deflate = 0;
- if (abits > 0) {
- ccp_allowoptions[0].deflate = 1;
- ccp_allowoptions[0].deflate_size = abits;
- } else
- ccp_allowoptions[0].deflate = 0;
-
- /* XXX copy over settings for switch compatibility */
- ccp_wantoptions[0].baddeflate = ccp_wantoptions[0].deflate;
- ccp_wantoptions[0].baddeflate_size = ccp_wantoptions[0].deflate_size;
- ccp_allowoptions[0].baddeflate = ccp_allowoptions[0].deflate;
- ccp_allowoptions[0].baddeflate_size = ccp_allowoptions[0].deflate_size;
-
- return 1;
-}
-
-static int
-setnodeflate(argv)
- char **argv;
-{
- ccp_wantoptions[0].deflate = 0;
- ccp_allowoptions[0].deflate = 0;
- return 1;
-}
-
-static int
-setnodeflatedraft(argv)
- char **argv;
-{
- ccp_wantoptions[0].deflate_draft = 0;
- ccp_allowoptions[0].deflate_draft = 0;
- return 1;
-}
-
-static int
-setpred1comp(argv)
- char **argv;
-{
- ccp_wantoptions[0].predictor_1 = 1;
- ccp_allowoptions[0].predictor_1 = 1;
- return 1;
-}
-
-static int
-setnopred1comp(argv)
- char **argv;
-{
- ccp_wantoptions[0].predictor_1 = 0;
- ccp_allowoptions[0].predictor_1 = 0;
- return 1;
-}
-
-static int
-setipparam(argv)
- char **argv;
-{
- ipparam = strdup(*argv);
- if (ipparam == NULL)
- novm("ipparam string");
-
- return 1;
-}
-
-static int
-setpapcrypt(argv)
- char **argv;
-{
- cryptpap = 1;
- return 1;
-}
-
-static int
-setidle(argv)
- char **argv;
-{
- return int_option(*argv, &idle_time_limit);
-}
-
-static int
-setholdoff(argv)
- char **argv;
-{
- return int_option(*argv, &holdoff);
-}
-
-/*
- * setdnsaddr - set the dns address(es)
- */
-static int
-setdnsaddr(argv)
- char **argv;
-{
- u_int32_t dns;
- struct hostent *hp;
-
- dns = inet_addr(*argv);
- if (dns == -1) {
- if ((hp = gethostbyname(*argv)) == NULL) {
- option_error("invalid address parameter '%s' for ms-dns option",
- *argv);
- return 0;
- }
- dns = *(u_int32_t *)hp->h_addr;
- }
-
- /* if there is no primary then update it. */
- if (ipcp_allowoptions[0].dnsaddr[0] == 0)
- ipcp_allowoptions[0].dnsaddr[0] = dns;
-
- /* always set the secondary address value to the same value. */
- ipcp_allowoptions[0].dnsaddr[1] = dns;
-
- return (1);
-}
-
-/*
- * setwinsaddr - set the wins address(es)
- * This is primrarly used with the Samba package under UNIX or for pointing
- * the caller to the existing WINS server on a Windows NT platform.
- */
-static int
-setwinsaddr(argv)
- char **argv;
-{
- u_int32_t wins;
- struct hostent *hp;
-
- wins = inet_addr(*argv);
- if (wins == -1) {
- if ((hp = gethostbyname(*argv)) == NULL) {
- option_error("invalid address parameter '%s' for ms-wins option",
- *argv);
- return 0;
- }
- wins = *(u_int32_t *)hp->h_addr;
- }
-
- /* if there is no primary then update it. */
- if (ipcp_allowoptions[0].winsaddr[0] == 0)
- ipcp_allowoptions[0].winsaddr[0] = wins;
-
- /* always set the secondary address value to the same value. */
- ipcp_allowoptions[0].winsaddr[1] = wins;
-
- return (1);
-}
-
-#ifdef INET6
-static int
-setipv6cp_accept_local(argv)
- char **argv;
-{
- ipv6cp_allowoptions[0].accept_local = 1;
- return 1;
-}
-
-static int
-setipv6cp_use_ip(argv)
- char **argv;
-{
- ipv6cp_allowoptions[0].use_ip = 1;
- return 1;
-}
-
-#if defined(SOL2)
-static int
-setipv6cp_use_persistent(argv)
- char **argv;
-{
- ipv6cp_wantoptions[0].use_persistent = 1;
- return 1;
-}
-#endif
-
-static int
-setipv6cptimeout(argv)
- char **argv;
-{
- return int_option(*argv, &ipv6cp_fsm[0].timeouttime);
-}
-
-static int
-setipv6cpterm(argv)
- char **argv;
-{
- return int_option(*argv, &ipv6cp_fsm[0].maxtermtransmits);
-}
-
-static int
-setipv6cpconf(argv)
- char **argv;
-{
- return int_option(*argv, &ipv6cp_fsm[0].maxconfreqtransmits);
-}
-
-static int
-setipv6cpfails(argv)
- char **argv;
-{
- return int_option(*argv, &ipv6cp_fsm[0].maxnakloops);
-}
-
-static int
-setipv6proto(argv)
- char **argv;
-{
- ipv6cp_protent.enabled_flag = 1;
- return 1;
-}
-
-static int
-resetipv6proto(argv)
- char **argv;
-{
- ipv6cp_protent.enabled_flag = 0;
- return 1;
-}
-#else
-static int
-resetipv6proto(argv)
- char **argv;
-{
- return 1;
-}
-#endif /* INET6 */
-
-#ifdef IPX_CHANGE
-static int
-setipxrouter (argv)
- char **argv;
-{
- ipxcp_wantoptions[0].neg_router = 1;
- ipxcp_allowoptions[0].neg_router = 1;
- return int_option(*argv, &ipxcp_wantoptions[0].router);
-}
-
-static int
-setipxname (argv)
- char **argv;
-{
- char *dest = ipxcp_wantoptions[0].name;
- char *src = *argv;
- int count;
- char ch;
-
- ipxcp_wantoptions[0].neg_name = 1;
- ipxcp_allowoptions[0].neg_name = 1;
- memset (dest, '\0', sizeof (ipxcp_wantoptions[0].name));
-
- count = 0;
- while (*src) {
- ch = *src++;
- if (! isalnum (ch) && ch != '_') {
- option_error("IPX router name must be alphanumeric or _");
- return 0;
- }
-
- if (count >= sizeof (ipxcp_wantoptions[0].name)) {
- option_error("IPX router name is limited to %d characters",
- sizeof (ipxcp_wantoptions[0].name) - 1);
- return 0;
- }
-
- dest[count++] = toupper (ch);
- }
-
- return 1;
-}
-
-static int
-setipxcptimeout (argv)
- char **argv;
-{
- return int_option(*argv, &ipxcp_fsm[0].timeouttime);
-}
-
-static int
-setipxcpterm (argv)
- char **argv;
-{
- return int_option(*argv, &ipxcp_fsm[0].maxtermtransmits);
-}
-
-static int
-setipxcpconf (argv)
- char **argv;
-{
- return int_option(*argv, &ipxcp_fsm[0].maxconfreqtransmits);
-}
-
-static int
-setipxcpfails (argv)
- char **argv;
-{
- return int_option(*argv, &ipxcp_fsm[0].maxnakloops);
-}
-
-static int
-setipxnetwork(argv)
- char **argv;
-{
- u_int32_t v;
-
- if (!number_option(*argv, &v, 16))
- return 0;
-
- ipxcp_wantoptions[0].our_network = (int) v;
- ipxcp_wantoptions[0].neg_nn = 1;
- return 1;
-}
-
-static int
-setipxanet(argv)
- char **argv;
-{
- ipxcp_wantoptions[0].accept_network = 1;
- ipxcp_allowoptions[0].accept_network = 1;
- return 1;
-}
-
-static int
-setipxalcl(argv)
- char **argv;
-{
- ipxcp_wantoptions[0].accept_local = 1;
- ipxcp_allowoptions[0].accept_local = 1;
- return 1;
-}
-
-static int
-setipxarmt(argv)
- char **argv;
-{
- ipxcp_wantoptions[0].accept_remote = 1;
- ipxcp_allowoptions[0].accept_remote = 1;
- return 1;
-}
-
-static u_char *
-setipxnodevalue(src,dst)
-u_char *src, *dst;
-{
- int indx;
- int item;
-
- for (;;) {
- if (!isxdigit (*src))
- break;
-
- for (indx = 0; indx < 5; ++indx) {
- dst[indx] <<= 4;
- dst[indx] |= (dst[indx + 1] >> 4) & 0x0F;
- }
-
- item = toupper (*src) - '0';
- if (item > 9)
- item -= 7;
-
- dst[5] = (dst[5] << 4) | item;
- ++src;
- }
- return src;
-}
-
-static int
-setipxnode(argv)
- char **argv;
-{
- char *end;
-
- memset (&ipxcp_wantoptions[0].our_node[0], 0, 6);
- memset (&ipxcp_wantoptions[0].his_node[0], 0, 6);
-
- end = setipxnodevalue (*argv, &ipxcp_wantoptions[0].our_node[0]);
- if (*end == ':')
- end = setipxnodevalue (++end, &ipxcp_wantoptions[0].his_node[0]);
-
- if (*end == '\0') {
- ipxcp_wantoptions[0].neg_node = 1;
- return 1;
- }
-
- option_error("invalid parameter '%s' for ipx-node option", *argv);
- return 0;
-}
-
-static int
-setipxproto(argv)
- char **argv;
-{
- ipxcp_protent.enabled_flag = 1;
- return 1;
-}
-
-static int
-resetipxproto(argv)
- char **argv;
-{
- ipxcp_protent.enabled_flag = 0;
- return 1;
-}
-#else
-
-static int
-resetipxproto(argv)
- char **argv;
-{
- return 1;
-}
-#endif /* IPX_CHANGE */
-
-#ifdef MSLANMAN
-static int
-setmslanman(argv)
- char **argv;
-{
- ms_lanman = 1;
- return (1);
-}
-#endif
diff --git a/usr.sbin/pppd/patchlevel.h b/usr.sbin/pppd/patchlevel.h
deleted file mode 100644
index bc49c58..0000000
--- a/usr.sbin/pppd/patchlevel.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/* $FreeBSD$ */
-#define PATCHLEVEL 5
-
-#define VERSION "2.3"
-#define IMPLEMENTATION ""
-#define DATE "4 May 1998"
diff --git a/usr.sbin/pppd/pathnames.h b/usr.sbin/pppd/pathnames.h
deleted file mode 100644
index 5d09b0b..0000000
--- a/usr.sbin/pppd/pathnames.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * define path names
- *
- * $FreeBSD$
- */
-
-#ifdef HAVE_PATHS_H
-#include <paths.h>
-
-#else
-#define _PATH_VARRUN "/etc/ppp/"
-#define _PATH_DEVNULL "/dev/null"
-#endif
-
-#define _PATH_UPAPFILE "/etc/ppp/pap-secrets"
-#define _PATH_CHAPFILE "/etc/ppp/chap-secrets"
-#define _PATH_SYSOPTIONS "/etc/ppp/options"
-#define _PATH_IPUP "/etc/ppp/ip-up"
-#define _PATH_IPDOWN "/etc/ppp/ip-down"
-#define _PATH_AUTHUP "/etc/ppp/auth-up"
-#define _PATH_AUTHDOWN "/etc/ppp/auth-down"
-#define _PATH_TTYOPT "/etc/ppp/options."
-#define _PATH_CONNERRS "/var/log/connect-errors"
-#define _PATH_USEROPT ".ppprc"
-#define _PATH_PEERFILES "/etc/ppp/peers/"
-#define _PATH_PPPDENY "/etc/ppp/ppp.deny"
-#define _PATH_PPPSHELLS "/etc/ppp/ppp.shells"
-
-#ifdef INET6
-#define _PATH_IPV6UP "/etc/ppp/ipv6-up"
-#define _PATH_IPV6DOWN "/etc/ppp/ipv6-down"
-#endif
-
-#ifdef IPX_CHANGE
-#define _PATH_IPXUP "/etc/ppp/ipx-up"
-#define _PATH_IPXDOWN "/etc/ppp/ipx-down"
-#endif /* IPX_CHANGE */
diff --git a/usr.sbin/pppd/pppd.8 b/usr.sbin/pppd/pppd.8
deleted file mode 100644
index ba55f21..0000000
--- a/usr.sbin/pppd/pppd.8
+++ /dev/null
@@ -1,1247 +0,0 @@
-.\" manual page [] for pppd 2.3
-.\" $FreeBSD$
-.\" SH section heading
-.\" SS subsection heading
-.\" LP paragraph
-.\" IP indented paragraph
-.\" TP hanging label
-.TH PPPD 8
-.SH NAME
-pppd \- Point to Point Protocol daemon
-.SH SYNOPSIS
-.B pppd
-[
-.I tty_name
-] [
-.I speed
-] [
-.I options
-]
-.SH DESCRIPTION
-.LP
-The Point-to-Point Protocol (PPP) provides a method for transmitting
-datagrams over serial point-to-point links. PPP
-is composed of three parts: a method for encapsulating datagrams over
-serial links, an extensible Link Control Protocol (LCP), and
-a family of Network Control Protocols (NCP) for establishing
-and configuring different network-layer protocols.
-.LP
-The encapsulation scheme is provided by driver code in the kernel.
-Pppd provides the basic LCP, authentication support, and an NCP for
-establishing and configuring the Internet Protocol (IP) (called the IP
-Control Protocol, IPCP).
-.SH FREQUENTLY USED OPTIONS
-.TP
-.I <tty_name>
-Communicate over the named device. The string "/dev/" is prepended if
-necessary. If no device name is given, or if the name of the terminal
-connected to the standard input is given, pppd
-will use that terminal, and will not fork to put itself in the
-background. This option is privileged if the \fInoauth\fR option is
-used.
-.TP
-.I <speed>
-Set the baud rate to <speed> (a decimal number). On systems such as
-4.4BSD and NetBSD, any speed can be specified, providing that it is
-supported by the serial device driver. Other systems
-(e.g. SunOS, Linux) allow only a limited set of speeds.
-.TP
-.B active-filter \fIfilter-expression
-Specifies a packet filter to be applied to data packets to determine
-which packets are to be regarded as link activity, and therefore reset
-the idle timer, or cause the link to be brought up in demand-dialling
-mode. This option is useful in conjunction with the
-\fBidle\fR option if there are packets being sent or received
-regularly over the link (for example, routing information packets)
-which would otherwise prevent the link from ever appearing to be idle.
-The \fIfilter-expression\fR syntax is as described for tcpdump(1),
-except that qualifiers which are inappropriate for a PPP link, such as
-\fBether\fR and \fBarp\fR, are not permitted. Generally the filter
-expression should be enclosed in single-quotes to prevent whitespace
-in the expression from being interpreted by the shell.
-This option
-only available
-if both the kernel and pppd were compiled with PPP_FILTER defined.
-.TP
-.B asyncmap \fI<map>
-Set the async character map to <map>. This map describes which
-control characters cannot be successfully received over the serial
-line. Pppd will ask the peer to send these characters as a 2-byte
-escape sequence. The argument is a 32 bit hex number with each bit
-representing a character to escape. Bit 0 (00000001) represents the
-character 0x00; bit 31 (80000000) represents the character 0x1f or ^_.
-If multiple \fIasyncmap\fR options are given, the values are ORed
-together. If no \fIasyncmap\fR option is given, no async character
-map will be negotiated for the receive direction; the peer should then
-escape \fIall\fR control characters. To escape transmitted
-characters, use the \fIescape\fR option.
-.TP
-.B auth
-Require the peer to authenticate itself before allowing network
-packets to be sent or received.
-.TP
-.B call \fIname
-Read options from the file /etc/ppp/peers/\fIname\fR. This file may
-contain privileged options, such as \fInoauth\fR, even if pppd
-is not being run by root. The \fIname\fR string may not begin with /
-or include .. as a pathname component. The format of the options file
-is described below.
-.TP
-.B connect \fIscript
-Use the executable or shell command specified by \fIscript\fR to set
-up the serial line. This script would typically use the chat(8)
-program to dial the modem and start the remote ppp session. This
-option is privileged if the \fInoauth\fR option is used.
-.TP
-.B connect-max-attempts \fI<n>
-Attempt dial-out connection to remote system no more than specified number
-of times (default = 1). If the connection is not made, pppd will exit.
-Requires that \fBpersist\fR has been specified.
-.TP
-.B crtscts
-Use hardware flow control (i.e. RTS/CTS) to control the flow of data
-on the serial port. If neither the \fIcrtscts\fR nor the
-\fInocrtscts\fR option is given, the hardware flow control setting
-for the serial port is left unchanged.
-.TP
-.B defaultroute
-Add a default route to the system routing tables, using the peer as
-the gateway, when IPCP negotiation is successfully completed.
-This entry is removed when the PPP connection is broken. This option
-is privileged if the \fInodefaultroute\fR option has been specified.
-.TP
-.B disconnect \fIscript
-Run the executable or shell command specified by \fIscript\fR after
-pppd has terminated the link. This script could, for example, issue
-commands to the modem to cause it to hang up if hardware modem control
-signals were not available. The disconnect script is not run if the
-modem has already hung up. This option is privileged if the
-\fInoauth\fR option is used.
-.TP
-.B escape \fIxx,yy,...
-Specifies that certain characters should be escaped on transmission
-(regardless of whether the peer requests them to be escaped with its
-async control character map). The characters to be escaped are
-specified as a list of hex numbers separated by commas. Note that
-almost any character can be specified for the \fIescape\fR option,
-unlike the \fIasyncmap\fR option which only allows control characters
-to be specified. The characters which may not be escaped are those
-with hex values 0x20 - 0x3f or 0x5e.
-.TP
-.B file \fIname
-Read options from file \fIname\fR (the format is described below).
-The file must be readable by the user who has invoked pppd.
-.TP
-.B lock
-Specifies that pppd should create a UUCP-style lock file for the
-serial device to ensure exclusive access to the device.
-.TP
-.B mru \fIn
-Set the MRU [Maximum Receive Unit] value to \fIn\fR.
-Pppd
-will ask the peer to send packets of no more than \fIn\fR bytes. The
-minimum MRU value is 128. The default MRU value is 1500. A value of
-296 is recommended for slow links (40 bytes for TCP/IP header + 256
-bytes of data). (Note that for IPv6 MRU must be at least 1280)
-.TP
-.B mtu \fIn
-Set the MTU [Maximum Transmit Unit] value to \fIn\fR. Unless the
-peer requests a smaller value via MRU negotiation, pppd will
-request that the kernel networking code send data packets of no more
-than \fIn\fR bytes through the PPP network interface. (Note that for
-IPv6 MTU must be at least 1280)
-.TP
-.B passive
-Enables the "passive" option in the LCP. With this option, pppd will
-attempt to initiate a connection; if no reply is received from the
-peer, pppd will then just wait passively for a valid LCP packet from
-the peer, instead of exiting, as it would without this option.
-.SH OPTIONS
-.TP
-.I <local_IP_address>\fB:\fI<remote_IP_address>
-Set the local and/or remote interface IP addresses. Either one may be
-omitted. The IP addresses can be specified with a host name or in
-decimal dot notation (e.g. 150.234.56.78). The default local
-address is the (first) IP address of the system (unless the
-\fInoipdefault\fR
-option is given). The remote address will be obtained from the peer
-if not specified in any option. Thus, in simple cases, this option is
-not required. If a local and/or remote IP address is specified with
-this option, pppd
-will not accept a different value from the peer in the IPCP
-negotiation, unless the \fIipcp-accept-local\fR and/or
-\fIipcp-accept-remote\fR options are given, respectively.
-.TP
-.B ipv6 \fI<local_interface_identifier>\fR,\fI<remote_interface_identifier>
-Set the local and/or remote 64-bit interface identifier. Either one may be
-omitted. The identifier must be specified in standard ascii notation of
-IPv6 addresses (e.g. ::dead:beef). If the
-\fIipv6cp-use-ipaddr\fR
-option is given, the local identifier is the local IPv4 address (see above).
-On systems which supports a unique persistent id, such as EUI-48 derived
-from the Ethernet MAC address, \fIipv6cp-use-persistent\fR option can be
-used to replace the \fIipv6 <local>,<remote>\fR option. Otherwise the
-identifier is randomized.
-.TP
-.B bsdcomp \fInr,nt
-Request that the peer compress packets that it sends, using the
-BSD-Compress scheme, with a maximum code size of \fInr\fR bits, and
-agree to compress packets sent to the peer with a maximum code size of
-\fInt\fR bits. If \fInt\fR is not specified, it defaults to the value
-given for \fInr\fR. Values in the range 9 to 15 may be used for
-\fInr\fR and \fInt\fR; larger values give better compression but
-consume more kernel memory for compression dictionaries.
-Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables
-compression in the corresponding direction. Use \fInobsdcomp\fR or
-\fIbsdcomp 0\fR to disable BSD-Compress compression entirely.
-.TP
-.B callback \fIphone_number
-Request a call-back to the \fIphone_number\fR. This only works if the peer
-is speaking the Call Back Configuration Protocol. Do not put this into the
-main options file if you sometimes connect to servers that don't support
-it.
-.TP
-.B chap-interval \fIn
-If this option is given, pppd will rechallenge the peer every \fIn\fR
-seconds.
-.TP
-.B chap-max-challenge \fIn
-Set the maximum number of CHAP challenge transmissions to \fIn\fR
-(default 10).
-.TP
-.B chap-restart \fIn
-Set the CHAP restart interval (retransmission timeout for challenges)
-to \fIn\fR seconds (default 3).
-.TP
-.B debug
-Enables connection debugging facilities.
-If this option is given, pppd will log the contents of all
-control packets sent or received in a readable form. The packets are
-logged through syslog with facility \fIdaemon\fR and level
-\fIdebug\fR. This information can be directed to a file by setting up
-/etc/syslog.conf appropriately (see syslog.conf(5)).
-.TP
-.B default-asyncmap
-Disable asyncmap negotiation, forcing all control characters to be
-escaped for both the transmit and the receive direction.
-.TP
-.B default-mru
-Disable MRU [Maximum Receive Unit] negotiation. With this option,
-pppd will use the default MRU value of 1500 bytes for both the
-transmit and receive direction.
-.TP
-.B deflate \fInr,nt
-Request that the peer compress packets that it sends, using the
-Deflate scheme, with a maximum window size of \fI2**nr\fR bytes, and
-agree to compress packets sent to the peer with a maximum window size
-of \fI2**nt\fR bytes. If \fInt\fR is not specified, it defaults to
-the value given for \fInr\fR. Values in the range 8 to 15 may be used
-for \fInr\fR and \fInt\fR; larger values give better compression but
-consume more kernel memory for compression dictionaries.
-Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables
-compression in the corresponding direction. Use \fInodeflate\fR or
-\fIdeflate 0\fR to disable Deflate compression entirely. (Note: pppd
-requests Deflate compression in preference to BSD-Compress if the peer
-can do either.)
-.TP
-.B demand
-Initiate the link only on demand, i.e. when data traffic is present.
-With this option, the remote IP address must be specified by the user
-on the command line or in an options file. Pppd will initially
-configure the interface and enable it for IP traffic without
-connecting to the peer. When traffic is available, pppd will
-connect to the peer and perform negotiation, authentication, etc.
-When this is completed, pppd will commence passing data packets
-(i.e., IP packets) across the link.
-
-The \fIdemand\fR option implies the \fIpersist\fR option. If this
-behaviour is not desired, use the \fInopersist\fR option after the
-\fIdemand\fR option. The \fIidle\fR and \fIholdoff\fR
-options are also useful in conjunction with the \fIdemand\fR option.
-.TP
-.B domain \fId
-Append the domain name \fId\fR to the local host name for authentication
-purposes. For example, if gethostname() returns the name porsche, but
-the fully qualified domain name is porsche.Quotron.COM, you could
-specify \fIdomain Quotron.COM\fR. Pppd would then use the name
-\fIporsche.Quotron.COM\fR for looking up secrets in the secrets file,
-and as the default name to send to the peer when authenticating itself
-to the peer. This option is privileged.
-.TP
-.B holdoff \fIn
-Specifies how many seconds to wait before re-initiating the link after
-it terminates. This option only has any effect if the \fIpersist\fR
-or \fIdemand\fR option is used. The holdoff period is not applied if
-the link was terminated because it was idle.
-.TP
-.B idle \fIn
-Specifies that pppd should disconnect if the link is idle for \fIn\fR
-seconds. The link is idle when no data packets (i.e. IP packets) are
-being sent or received. Note: it is not advisable to use this option
-with the \fIpersist\fR option without the \fIdemand\fR option.
-If the \fBactive-filter\fR
-option is given, data packets which are rejected by the specified
-activity filter also count as the link being idle.
-.TP
-.B ipcp-accept-local
-With this option, pppd will accept the peer's idea of our local IP
-address, even if the local IP address was specified in an option.
-.TP
-.B ipcp-accept-remote
-With this option, pppd will accept the peer's idea of its (remote) IP
-address, even if the remote IP address was specified in an option.
-.TP
-.B ipcp-max-configure \fIn
-Set the maximum number of IPCP configure-request transmissions to
-\fIn\fR (default 10).
-.TP
-.B ipcp-max-failure \fIn
-Set the maximum number of IPCP configure-NAKs returned before starting
-to send configure-Rejects instead to \fIn\fR (default 10).
-.TP
-.B ipcp-max-terminate \fIn
-Set the maximum number of IPCP terminate-request transmissions to
-\fIn\fR (default 3).
-.TP
-.B ipcp-restart \fIn
-Set the IPCP restart interval (retransmission timeout) to \fIn\fR
-seconds (default 3).
-.TP
-.B ipparam \fIstring
-Provides an extra parameter to the ip-up and ip-down scripts. If this
-option is given, the \fIstring\fR supplied is given as the 6th
-parameter to those scripts.
-.TP
-.B ipv6cp-max-configure \fIn
-Set the maximum number of IPv6CP configure-request transmissions to
-\fIn\fR (default 10).
-.TP
-.B ipv6cp-max-failure \fIn
-Set the maximum number of IPv6CP configure-NAKs returned before starting
-to send configure-Rejects instead to \fIn\fR (default 10).
-.TP
-.B ipv6cp-max-terminate \fIn
-Set the maximum number of IPv6CP terminate-request transmissions to
-\fIn\fR (default 3).
-.TP
-.B ipv6cp-restart \fIn
-Set the IPv6CP restart interval (retransmission timeout) to \fIn\fR
-seconds (default 3).
-.TP
-.B ipx
-Enable the IPXCP and IPX protocols. This option is presently only
-supported under Linux, and only if your kernel has been configured to
-include IPX support.
-.TP
-.B ipx-network \fIn
-Set the IPX network number in the IPXCP configure request frame to
-\fIn\fR, a hexadecimal number (without a leading 0x). There is no
-valid default. If this option is not specified, the network number is
-obtained from the peer. If the peer does not have the network number,
-the IPX protocol will not be started.
-.TP
-.B ipx-node \fIn\fB:\fIm
-Set the IPX node numbers.
-The two node numbers are separated from each
-other with a colon character.
-The first number \fIn\fR is the local
-node number.
-The second number \fIm\fR is the peer's node number.
-Each
-node number is a hexadecimal number, at most 10 digits long.
-The node
-numbers on the ipx-network must be unique.
-There is no valid
-default.
-If this option is not specified then the node numbers are
-obtained from the peer.
-.TP
-.B ipx-router-name \fI<string>
-Set the name of the router.
-This is a string and is sent to the peer
-as information data.
-.TP
-.B ipx-routing \fIn
-Set the routing protocol to be received by this option.
-More than one
-instance of \fIipx-routing\fR may be specified.
-The '\fInone\fR'
-option (0) may be specified as the only instance of ipx-routing.
-The
-values may be \fI0\fR for \fINONE\fR, \fI2\fR for \fIRIP/SAP\fR, and
-\fI4\fR for \fINLSP\fR.
-.TP
-.B ipxcp-accept-local
-Accept the peer's NAK for the node number specified in the ipx-node
-option.
-If a node number was specified, and non-zero, the default is
-to insist that the value be used.
-If you include this option then you
-will permit the peer to override the entry of the node number.
-.TP
-.B ipxcp-accept-network
-Accept the peer's NAK for the network number specified in the
-ipx-network option.
-If a network number was specified, and non-zero, the
-default is to insist that the value be used.
-If you include this
-option then you will permit the peer to override the entry of the node
-number.
-.TP
-.B ipxcp-accept-remote
-Use the peer's network number specified in the configure request
-frame.
-If a node number was specified for the peer and this option was
-not specified, the peer will be forced to use the value which you have
-specified.
-.TP
-.B ipxcp-max-configure \fIn
-Set the maximum number of IPXCP configure request frames which the
-system will send to \fIn\fR.
-The default is 10.
-.TP
-.B ipxcp-max-failure \fIn
-Set the maximum number of IPXCP NAK frames which the local system will
-send before it rejects the options.
-The default value is 3.
-.TP
-.B ipxcp-max-terminate \fIn
-Set the maximum number of IPXCP terminate request frames before the
-local system considers that the peer is not listening to them.
-The
-default value is 3.
-.TP
-.B kdebug \fIn
-Enable debugging code in the kernel-level PPP driver. The argument
-\fIn\fR is a number which is the sum of the following values: 1 to
-enable general debug messages, 2 to request that the contents of
-received packets be printed, and 4 to request that the contents of
-transmitted packets be printed. On most systems, messages printed by
-the kernel are logged by syslog(1) to a file as directed in the
-/etc/syslog.conf configuration file.
-.TP
-.B lcp-echo-failure \fIn
-If this option is given, pppd will presume the peer to be dead
-if \fIn\fR LCP echo-requests are sent without receiving a valid LCP
-echo-reply. If this happens, pppd will terminate the
-connection. Use of this option requires a non-zero value for the
-\fIlcp-echo-interval\fR parameter. This option can be used to enable
-pppd to terminate after the physical connection has been broken
-(e.g., the modem has hung up) in situations where no hardware modem
-control lines are available.
-.TP
-.B lcp-echo-interval \fIn
-If this option is given, pppd will send an LCP echo-request frame to
-the peer every \fIn\fR seconds. Normally the peer should respond to
-the echo-request by sending an echo-reply. This option can be used
-with the \fIlcp-echo-failure\fR option to detect that the peer is no
-longer connected.
-.TP
-.B lcp-max-configure \fIn
-Set the maximum number of LCP configure-request transmissions to
-\fIn\fR (default 10).
-.TP
-.B lcp-max-failure \fIn
-Set the maximum number of LCP configure-NAKs returned before starting
-to send configure-Rejects instead to \fIn\fR (default 10).
-.TP
-.B lcp-max-terminate \fIn
-Set the maximum number of LCP terminate-request transmissions to
-\fIn\fR (default 3).
-.TP
-.B lcp-restart \fIn
-Set the LCP restart interval (retransmission timeout) to \fIn\fR
-seconds (default 3).
-.TP
-.B local
-Don't use the modem control lines. With this option, pppd will ignore
-the state of the CD (Carrier Detect) signal from the modem and will
-not change the state of the DTR (Data Terminal Ready) signal.
-.TP
-.B login
-Use the system password database for authenticating the peer using
-PAP, and record the user in the system wtmp file. Note that the peer
-must have an entry in the /etc/ppp/pap-secrets file as well as the
-system password database to be allowed access.
-.TP
-.B maxconnect \fIn
-Terminate the connection when it has been available for network
-traffic for \fIn\fR seconds (i.e. \fIn\fR seconds after the first
-network control protocol comes up).
-.TP
-.B modem
-Use the modem control lines. This option is the default. With this
-option, pppd will wait for the CD (Carrier Detect) signal from the
-modem to be asserted when opening the serial device (unless a connect
-script is specified), and it will drop the DTR (Data Terminal Ready)
-signal briefly when the connection is terminated and before executing
-the connect script. On Ultrix, this option implies hardware flow
-control, as for the \fIcrtscts\fR option.
-.TP
-.B ms-dns \fI<addr>
-If pppd is acting as a server for Microsoft Windows clients, this
-option allows pppd to supply one or two DNS (Domain Name Server)
-addresses to the clients. The first instance of this option specifies
-the primary DNS address; the second instance (if given) specifies the
-secondary DNS address. (This option was present in some older
-versions of pppd under the name \fBdns-addr\fR.)
-.TP
-.B ms-wins \fI<addr>
-If pppd is acting as a server for Microsoft Windows or "Samba"
-clients, this option allows pppd to supply one or two WINS (Windows
-Internet Name Services) server addresses to the clients. The first
-instance of this option specifies the primary WINS address; the second
-instance (if given) specifies the secondary WINS address.
-.TP
-.B name \fIname
-Set the name of the local system for authentication purposes to
-\fIname\fR. This is a privileged option. With this option, pppd will
-use lines in the secrets files which have \fIname\fR as the second
-field when looking for a secret to use in authenticating the peer. In
-addition, unless overridden with the \fIuser\fR option, \fIname\fR
-will be used as the name to send to the peer when authenticating the
-local system to the peer. (Note that pppd does not append the domain
-name to \fIname\fR.)
-.TP
-.B netmask \fIn
-Set the interface netmask to \fIn\fR, a 32 bit netmask in "decimal dot"
-notation (e.g. 255.255.255.0). If this option is given, the value
-specified is ORed with the default netmask. The default netmask is
-chosen based on the negotiated remote IP address; it is the
-appropriate network mask for the class of the remote IP address, ORed
-with the netmasks for any non point-to-point network interfaces in the
-system which are on the same network.
-.TP
-.B noaccomp
-Disable Address/Control compression in both directions (send and
-receive).
-.TP
-.B noauth
-Do not require the peer to authenticate itself. This option is
-privileged if the \fIauth\fR option is specified in /etc/ppp/options.
-.TP
-.B nobsdcomp
-Disables BSD-Compress compression; \fBpppd\fR will not request or
-agree to compress packets using the BSD-Compress scheme.
-.TP
-.B noccp
-Disable CCP (Compression Control Protocol) negotiation. This option
-should only be required if the peer is buggy and gets confused by
-requests from pppd for CCP negotiation.
-.TP
-.B nocrtscts
-Disable hardware flow control (i.e. RTS/CTS) on the serial port. If
-neither the \fIcrtscts\fR nor the \fInocrtscts\fR option is given,
-the hardware flow control setting for the serial port is left
-unchanged.
-.TP
-.B nodefaultroute
-Disable the \fIdefaultroute\fR option. The system administrator who
-wishes to prevent users from creating default routes with pppd
-can do so by placing this option in the /etc/ppp/options file.
-.TP
-.B nodeflate
-Disables Deflate compression; pppd will not request or agree to
-compress packets using the Deflate scheme.
-.TP
-.B nodetach
-Don't detach from the controlling terminal. Without this option, if a
-serial device other than the terminal on the standard input is
-specified, pppd will fork to become a background process.
-.TP
-.B noip
-Disable IPCP negotiation and IP communication. This option should
-only be required if the peer is buggy and gets confused by requests
-from pppd for IPCP negotiation.
-.TP
-.B noipv6
-Disable IPv6CP negotiation and IPv6 communication. This option should
-only be required if the peer is buggy and gets confused by requests
-from pppd for IPv6CP negotiation.
-.TP
-.B noipdefault
-Disables the default behaviour when no local IP address is specified,
-which is to determine (if possible) the local IP address from the
-hostname. With this option, the peer will have to supply the local IP
-address during IPCP negotiation (unless it specified explicitly on the
-command line or in an options file).
-.TP
-.B noipx
-Disable the IPXCP and IPX protocols. This option should only be
-required if the peer is buggy and gets confused by requests from pppd
-for IPXCP negotiation.
-.TP
-.B nomagic
-Disable magic number negotiation. With this option, pppd cannot
-detect a looped-back line. This option should only be needed if the
-peer is buggy.
-.TP
-.B nopcomp
-Disable protocol field compression negotiation in both the receive and
-the transmit direction.
-.TP
-.B nopersist
-Exit once a connection has been made and terminated. This is the
-default unless the \fIpersist\fR or \fIdemand\fR option has been
-specified.
-.TP
-.B nopredictor1
-Do not accept or agree to Predictor-1 compression.
-.TP
-.B noproxyarp
-Disable the \fIproxyarp\fR option. The system administrator who
-wishes to prevent users from creating proxy ARP entries with pppd can
-do so by placing this option in the /etc/ppp/options file.
-.TP
-.B novj
-Disable Van Jacobson style TCP/IP header compression in both the
-transmit and the receive direction.
-.TP
-.B novjccomp
-Disable the connection-ID compression option in Van Jacobson style
-TCP/IP header compression. With this option, pppd will not omit the
-connection-ID byte from Van Jacobson compressed TCP/IP headers, nor
-ask the peer to do so.
-.TP
-.B papcrypt
-Indicates that all secrets in the /etc/ppp/pap-secrets file which are
-used for checking the identity of the peer are encrypted, and thus
-pppd should not accept a password which, before encryption, is
-identical to the secret from the /etc/ppp/pap-secrets file.
-.TP
-.B pap-max-authreq \fIn
-Set the maximum number of PAP authenticate-request transmissions to
-\fIn\fR (default 10).
-.TP
-.B pap-restart \fIn
-Set the PAP restart interval (retransmission timeout) to \fIn\fR
-seconds (default 3).
-.TP
-.B pap-timeout \fIn
-Set the maximum time that pppd will wait for the peer to authenticate
-itself with PAP to \fIn\fR seconds (0 means no limit).
-.TP
-.B pass-filter \fIfilter-expression
-Specifies a packet filter to applied to data packets being sent or
-received to determine which packets should be allowed to pass.
-Packets which are rejected by the filter are silently discarded. This
-option can be used to prevent specific network daemons (such as
-routed) using up link bandwidth, or to provide a basic firewall
-capability.
-The \fIfilter-expression\fR syntax is as described for tcpdump(1),
-except that qualifiers which are inappropriate for a PPP link, such as
-\fBether\fR and \fBarp\fR, are not permitted. Generally the filter
-expression should be enclosed in single-quotes to prevent whitespace
-in the expression from being interpreted by the shell. Note that it
-is possible to apply different constraints to incoming and outgoing
-packets using the \fBinbound\fR and \fBoutbound\fR qualifiers.
-This
-option is currently only available under NetBSD, and then only if both
-the kernel and pppd were compiled with PPP_FILTER defined.
-.TP
-.B persist
-Do not exit after a connection is terminated; instead try to reopen
-the connection.
-.TP
-.B predictor1
-Request that the peer compress frames that it sends using Predictor-1
-compression, and agree to compress transmitted frames with Predictor-1
-if requested. This option has no effect unless the kernel driver
-supports Predictor-1 compression.
-.TP
-.B proxyarp
-Add an entry to this system's ARP [Address Resolution Protocol] table
-with the IP address of the peer and the Ethernet address of this
-system. This will have the effect of making the peer appear to other
-systems to be on the local ethernet.
-.TP
-.B remotename \fIname
-Set the assumed name of the remote system for authentication purposes
-to \fIname\fR.
-.TP
-.B refuse-chap
-With this option, pppd will not agree to authenticate itself to the
-peer using CHAP.
-.TP
-.B refuse-pap
-With this option, pppd will not agree to authenticate itself to the
-peer using PAP.
-.TP
-.B require-chap
-Require the peer to authenticate itself using CHAP [Challenge
-Handshake Authentication Protocol] authentication.
-.TP
-.B require-pap
-Require the peer to authenticate itself using PAP [Password
-Authentication Protocol] authentication.
-.TP
-.B silent
-With this option, pppd will not transmit LCP packets to initiate a
-connection until a valid LCP packet is received from the peer (as for
-the `passive' option with ancient versions of pppd).
-.TP
-.B usehostname
-Enforce the use of the hostname (with domain name appended, if given)
-as the name of the local system for authentication purposes (overrides
-the \fIname\fR option).
-.TP
-.B user \fIname
-Sets the name used for authenticating the local system to the peer to
-\fIname\fR.
-.TP
-.B vj-max-slots \fIn
-Sets the number of connection slots to be used by the Van Jacobson
-TCP/IP header compression and decompression code to \fIn\fR, which
-must be between 2 and 16 (inclusive).
-.TP
-.B welcome \fIscript
-Run the executable or shell command specified by \fIscript\fR before
-initiating PPP negotiation, after the connect script (if any) has
-completed. This option is privileged if the \fInoauth\fR option is
-used.
-.TP
-.B xonxoff
-Use software flow control (i.e. XON/XOFF) to control the flow of data on
-the serial port.
-.SH OPTIONS FILES
-Options can be taken from files as well as the command line. Pppd
-reads options from the files /etc/ppp/options, ~/.ppprc and
-/etc/ppp/options.\fIttyname\fR (in that order) before processing the
-options on the command line. (In fact, the command-line options are
-scanned to find the terminal name before the options.\fIttyname\fR
-file is read.) In forming the name of the options.\fIttyname\fR file,
-the initial /dev/ is removed from the terminal name, and any remaining
-/ characters are replaced with dots.
-.PP
-An options file is parsed into a series of words, delimited by
-whitespace. Whitespace can be included in a word by enclosing the
-word in double-quotes ("). A backslash (\\) quotes the following character.
-A hash (#) starts a comment, which continues until the end of the
-line. There is no restriction on using the \fIfile\fR or \fIcall\fR
-options within an options file.
-.SH SECURITY
-.I pppd
-provides system administrators with sufficient access control that PPP
-access to a server machine can be provided to legitimate users without
-fear of compromising the security of the server or the network it's
-on. In part this is provided by the /etc/ppp/options file, where the
-administrator can place options to restrict the ways in which pppd can
-be used, and in part by the PAP and CHAP secrets files, where the
-administrator can restrict the set of IP addresses which individual
-users may use.
-.PP
-The normal way that pppd should be set up is to have the \fIauth\fR
-option in the /etc/ppp/options file. (This may become the default in
-later releases.) If users wish to use pppd to dial out to a peer
-which will refuse to authenticate itself (such as an internet service
-provider), the system administrator should create an options file
-under /etc/ppp/peers containing the \fInoauth\fR option, the name of
-the serial port to use, and the \fIconnect\fR option (if required),
-plus any other appropriate options. In this way, pppd can be set up
-to allow non-privileged users to make unauthenticated connections only
-to trusted peers.
-.PP
-As indicated above, some security-sensitive options are privileged,
-which means that they may not be used by an ordinary non-privileged
-user running a setuid-root pppd, either on the command line, in the
-user's ~/.ppprc file, or in an options file read using the \fIfile\fR
-option. Privileged options may be used in /etc/ppp/options file or in
-an options file read using the \fIcall\fR option. If pppd is being
-run by the root user, privileged options can be used without
-restriction.
-.SH AUTHENTICATION
-Authentication is the process whereby one peer convinces the other of
-its identity. This involves the first peer sending its name to the
-other, together with some kind of secret information which could only
-come from the genuine authorized user of that name. In such an
-exchange, we will call the first peer the "client" and the other the
-"server". The client has a name by which it identifies itself to the
-server, and the server also has a name by which it identifies itself
-to the client. Generally the genuine client shares some secret (or
-password) with the server, and authenticates itself by proving that it
-knows that secret. Very often, the names used for authentication
-correspond to the internet hostnames of the peers, but this is not
-essential.
-.LP
-At present, pppd supports two authentication protocols: the Password
-Authentication Protocol (PAP) and the Challenge Handshake
-Authentication Protocol (CHAP). PAP involves the client sending its
-name and a cleartext password to the server to authenticate itself.
-In contrast, the server initiates the CHAP authentication exchange by
-sending a challenge to the client (the challenge packet includes the
-server's name). The client must respond with a response which
-includes its name plus a hash value derived from the shared secret and
-the challenge, in order to prove that it knows the secret.
-.LP
-The PPP protocol, being symmetrical, allows both peers to require the
-other to authenticate itself. In that case, two separate and
-independent authentication exchanges will occur. The two exchanges
-could use different authentication protocols, and in principle,
-different names could be used in the two exchanges.
-.LP
-The default behaviour of pppd is to agree to authenticate if
-requested, and to not require authentication from the peer. However,
-pppd will not agree to authenticate itself with a particular protocol
-if it has no secrets which could be used to do so.
-.LP
-Pppd stores secrets for use in authentication in secrets
-files (/etc/ppp/pap-secrets for PAP, /etc/ppp/chap-secrets for CHAP).
-Both secrets files have the same format. The secrets files can
-contain secrets for pppd to use in authenticating itself to other
-systems, as well as secrets for pppd to use when authenticating other
-systems to itself.
-.LP
-Each line in a secrets file contains one secret. A given secret is
-specific to a particular combination of client and server - it can
-only be used by that client to authenticate itself to that server.
-Thus each line in a secrets file has at least 3 fields: the name of
-the client, the name of the server, and the secret. These fields may
-be followed by a list of the IP addresses that the specified client
-may use when connecting to the specified server.
-.LP
-A secrets file is parsed into words as for an options file, so the
-client name, server name and secrets fields must each be one word,
-with any embedded spaces or other special characters quoted or
-escaped. Any following words on the same line are taken to be a list
-of acceptable IP addresses for that client, or an
-override for "local:remote" addresses (the same format used on the
-command line or in the options file) when on a line that contains a
-specific client name (not a wildcard nor empty).
-If there are only 3 words
-on the line, or if the first word is "-", then all IP addresses are
-disallowed. To allow any address, use "*".
-A word starting with "!" indicates that the
-specified address is \fInot\fR acceptable. An address may be followed
-by "/" and a number \fIn\fR, to indicate a whole subnet, i.e. all
-addresses which have the same value in the most significant \fIn\fR
-bits. Note that case is significant in the client and server names
-and in the secret.
-.LP
-If the secret starts with an `@', what follows is assumed to be the
-name of a file from which to read the secret. A "*" as the client or
-server name matches any name. When selecting a secret, pppd takes the
-best match, i.e. the match with the fewest wildcards.
-.LP
-Thus a secrets file contains both secrets for use in authenticating
-other hosts, plus secrets which we use for authenticating ourselves to
-others. When pppd is authenticating the peer (checking the peer's
-identity), it chooses a secret with the peer's name in the first
-field and the name of the local system in the second field. The
-name of the local system defaults to the hostname, with the domain
-name appended if the \fIdomain\fR option is used. This default can be
-overridden with the \fIname\fR option, except when the
-\fIusehostname\fR option is used.
-.LP
-When pppd is choosing a secret to use in authenticating itself to the
-peer, it first determines what name it is going to use to identify
-itself to the peer. This name can be specified by the user with the
-\fIuser\fR option. If this option is not used, the name defaults to
-the name of the local system, determined as described in the previous
-paragraph. Then pppd looks for a secret with this name in the first
-field and the peer's name in the second field. Pppd will know the
-name of the peer if CHAP authentication is being used, because the
-peer will have sent it in the challenge packet. However, if PAP is being
-used, pppd will have to determine the peer's name from the options
-specified by the user. The user can specify the peer's name directly
-with the \fIremotename\fR option. Otherwise, if the remote IP address
-was specified by a name (rather than in numeric form), that name will
-be used as the peer's name. Failing that, pppd will use the null
-string as the peer's name.
-.LP
-When authenticating the peer with PAP, the supplied password is first
-compared with the secret from the secrets file. If the password
-doesn't match the secret, the password is encrypted using crypt() and
-checked against the secret again. Thus secrets for authenticating the
-peer can be stored in encrypted form if desired. If the
-\fIpapcrypt\fR option is given, the first (unencrypted) comparison is
-omitted, for better security.
-.LP
-Furthermore, if the \fIlogin\fR option was specified, the username and
-password are also checked against the system password database. Thus,
-the system administrator can set up the pap-secrets file to allow PPP
-access only to certain users, and to restrict the set of IP addresses
-that each user can use. Typically, when using the \fIlogin\fR option,
-the secret in /etc/ppp/pap-secrets would be "", which will match any
-password supplied by the peer. This avoids the need to have the same
-secret in two places.
-.LP
-Additional checks are performed when the \fBlogin\fR option is used.
-If the file /etc/ppp/ppp.deny exists, and the user is listed in it,
-the authentication fails. If the file /etc/ppp/ppp.shells exists and
-the user's normal login shell is not listed, the authentication fails.
-.LP
-Authentication must be satisfactorily completed before IPCP (or any
-other Network Control Protocol) can be started. If the peer is
-required to authenticate itself, and fails to do so, pppd will
-terminated the link (by closing LCP). If IPCP negotiates an
-unacceptable IP address for the remote host, IPCP will be closed. IP
-packets can only be sent or received when IPCP is open.
-.LP
-In some cases it is desirable to allow some hosts which can't
-authenticate themselves to connect and use one of a restricted set of
-IP addresses, even when the local host generally requires
-authentication. If the peer refuses to authenticate itself when
-requested, pppd takes that as equivalent to authenticating with PAP
-using the empty string for the username and password. Thus, by adding
-a line to the pap-secrets file which specifies the empty string for
-the client and password, it is possible to allow restricted access to
-hosts which refuse to authenticate themselves.
-.SH ROUTING
-.LP
-When IPCP negotiation is completed successfully, pppd will inform the
-kernel of the local and remote IP addresses for the ppp interface.
-This is sufficient to create a host route to the remote end of the
-link, which will enable the peers to exchange IP packets.
-Communication with other machines generally requires further
-modification to routing tables and/or ARP (Address Resolution
-Protocol) tables. In most cases the \fIdefaultroute\fR and/or
-\fIproxyarp\fR options are sufficient for this, but in some cases
-further intervention is required. The /etc/ppp/ip-up script can be
-used for this.
-.LP
-Sometimes it is desirable to add a default route through the remote
-host, as in the case of a machine whose only connection to the
-Internet is through the ppp interface. The \fIdefaultroute\fR option
-causes pppd to create such a default route when IPCP comes up, and
-delete it when the link is terminated.
-.LP
-In some cases it is desirable to use proxy ARP, for example on a
-server machine connected to a LAN, in order to allow other hosts to
-communicate with the remote host. The \fIproxyarp\fR option causes
-pppd to look for a network interface on the same subnet as the remote
-host (an interface supporting broadcast and ARP, which is up and not a
-point-to-point or loopback interface). If found, pppd creates a
-permanent, published ARP entry with the IP address of the remote host
-and the hardware address of the network interface found.
-.LP
-When the \fIdemand\fR option is used, the interface IP addresses have
-already been set at the point when IPCP comes up. If pppd has not
-been able to negotiate the same addresses that it used to configure
-the interface (for example when the peer is an ISP that uses dynamic
-IP address assignment), pppd has to change the interface IP addresses
-to the negotiated addresses. This may disrupt existing connections,
-and the use of demand dialling with peers that do dynamic IP address
-assignment is not recommended.
-.SH EXAMPLES
-.LP
-The following examples assume that the /etc/ppp/options file contains
-the \fIauth\fR option (as in the default /etc/ppp/options file in the
-ppp distribution).
-.LP
-Probably the most common use of pppd is to dial out to an ISP. This
-can be done with a command such as
-.IP
-pppd call isp
-.LP
-where the /etc/ppp/peers/isp file is set up by the system
-administrator to contain something like this:
-.IP
-ttyS0 19200 crtscts
-.br
-connect '/usr/sbin/chat -v -f /etc/ppp/chat-isp'
-.br
-noauth
-.LP
-In this example, we are using chat to dial the ISP's modem and go
-through any logon sequence required. The /etc/ppp/chat-isp file
-contains the script used by chat; it could for example contain
-something like this:
-.IP
-ABORT "NO CARRIER"
-.br
-ABORT "NO DIALTONE"
-.br
-ABORT "ERROR"
-.br
-ABORT "NO ANSWER"
-.br
-ABORT "BUSY"
-.br
-ABORT "Username/Password Incorrect"
-.br
-"" "at"
-.br
-OK "at&d0&c1"
-.br
-OK "atdt2468135"
-.br
-"name:" "^Umyuserid"
-.br
-"word:" "\\qmypassword"
-.br
-"ispts" "\\q^Uppp"
-.br
-"~-^Uppp-~"
-.LP
-See the chat(8) man page for details of chat scripts.
-.LP
-Pppd can also be used to provide a dial-in ppp service for users. If
-the users already have login accounts, the simplest way to set up the
-ppp service is to let the users log in to their accounts and run pppd
-(installed setuid-root) with a command such as
-.IP
-pppd proxyarp
-.LP
-To allow a user to use the PPP facilities, you need to allocate an IP
-address for that user's machine and create an entry in
-/etc/ppp/pap-secrets or /etc/ppp/chap-secrets (depending on which
-authentication method the PPP implementation on the user's machine
-supports), so that the user's
-machine can authenticate itself. For example, if Joe has a machine
-called "joespc" which is to be allowed to dial in to the machine
-called "server" and use the IP address joespc.my.net, you would add an
-entry like this to /etc/ppp/pap-secrets or /etc/ppp/chap-secrets:
-.IP
-joespc server "joe's secret" joespc.my.net
-.LP
-Alternatively, you can create a username called (for example) "ppp",
-whose login shell is pppd and whose home directory is /etc/ppp.
-Options to be used when pppd is run this way can be put in
-/etc/ppp/.ppprc.
-.LP
-If your serial connection is any more complicated than a piece of
-wire, you may need to arrange for some control characters to be
-escaped. In particular, it is often useful to escape XON (^Q) and
-XOFF (^S), using \fIasyncmap a0000\fR. If the path includes a telnet,
-you probably should escape ^] as well (\fIasyncmap 200a0000\fR). If
-the path includes an rlogin, you will need to use the \fIescape ff\fR
-option on the end which is running the rlogin client, since many
-rlogin implementations are not transparent; they will remove the
-sequence [0xff, 0xff, 0x73, 0x73, followed by any 8 bytes] from the
-stream.
-.SH DIAGNOSTICS
-.LP
-Messages are sent to the syslog daemon using facility LOG_DAEMON.
-(This can be overriden by recompiling pppd with the macro
-LOG_PPP defined as the desired facility.) In order to see the error
-and debug messages, you will need to edit your /etc/syslog.conf file
-to direct the messages to the desired output device or file.
-.LP
-The \fIdebug\fR option causes the contents of all control packets sent
-or received to be logged, that is, all LCP, PAP, CHAP or IPCP packets.
-This can be useful if the PPP negotiation does not succeed or if
-authentication fails.
-If debugging is enabled at compile time, the \fIdebug\fR option also
-causes other debugging messages to be logged.
-.LP
-Debugging can also be enabled or disabled by sending a SIGUSR1 signal
-to the pppd process. This signal acts as a toggle.
-.SH SCRIPTS
-Pppd invokes scripts at various stages in its processing which can be
-used to perform site-specific ancillary processing. These scripts are
-usually shell scripts, but could be executable code files instead.
-Pppd does not wait for the scripts to finish. The scripts are
-executed as root (with the real and effective user-id set to 0), so
-that they can do things such as update routing tables or run
-privileged daemons. Be careful that the contents of these scripts do
-not compromise your system's security. Pppd runs the scripts with
-standard input, output and error redirected to /dev/null, and with an
-environment that is empty except for some environment variables that
-give information about the link. The environment variables that pppd
-sets are:
-.TP
-.B DEVICE
-The name of the serial tty device being used.
-.TP
-.B IFNAME
-The name of the network interface being used.
-.TP
-.B IPLOCAL
-The IP address for the local end of the link. This is only set when
-IPCP has come up.
-.TP
-.B IPREMOTE
-The IP address for the remote end of the link. This is only set when
-IPCP has come up.
-.TP
-.B PEERNAME
-The authenticated name of the peer. This is only set if the peer
-authenticates itself.
-.TP
-.B SPEED
-The baud rate of the tty device.
-.TP
-.B UID
-The real user-id of the user who invoked pppd.
-.P
-Pppd invokes the following scripts, if they exist. It is not an error
-if they don't exist.
-.TP
-.B /etc/ppp/auth-up
-A program or script which is executed after the remote system
-successfully authenticates itself. It is executed with the parameters
-.IP
-\fIinterface-name peer-name user-name tty-device speed\fR
-.IP
-Note that this script is not executed if the peer doesn't authenticate
-itself, for example when the \fInoauth\fR option is used.
-.TP
-.B /etc/ppp/auth-down
-A program or script which is executed when the link goes down, if
-/etc/ppp/auth-up was previously executed. It is executed in the same
-manner with the same parameters as /etc/ppp/auth-up.
-.TP
-.B /etc/ppp/ip-up
-A program or script which is executed when the link is available for
-sending and receiving IP packets (that is, IPCP has come up). It is
-executed with the parameters
-.IP
-\fIinterface-name tty-device speed local-IP-address
-remote-IP-address ipparam\fR
-.TP
-.B /etc/ppp/ip-down
-A program or script which is executed when the link is no longer
-available for sending and receiving IP packets. This script can be
-used for undoing the effects of the /etc/ppp/ip-up script. It is
-invoked in the same manner and with the same parameters as the ip-up
-script.
-.TP
-.B /etc/ppp/ipv6-up
-Like /etc/ppp/ip-up, except that it is executed when the link is available
-for sending and receiving IPv6 packets. It is executed with the parameters
-.IP
-\fIinterface-name tty-device speed local-link-local-address
-remote-link-local-address ipparam\fR
-.TP
-.B /etc/ppp/ipv6-down
-Similar to /etc/ppp/ip-down, but it is executed when IPv6 packets can no
-longer be transmitted on the link. It is executed with the same parameters
-as the ipv6-up script.
-.TP
-.B /etc/ppp/ipx-up
-A program or script which is executed when the link is available for
-sending and receiving IPX packets (that is, IPXCP has come up). It is
-executed with the parameters
-.IP
-\fIinterface-name tty-device speed network-number local-IPX-node-address
-remote-IPX-node-address local-IPX-routing-protocol remote-IPX-routing-protocol
-local-IPX-router-name remote-IPX-router-name ipparam pppd-pid\fR
-.IP
-The local-IPX-routing-protocol and remote-IPX-routing-protocol field
-may be one of the following:
-.IP
-NONE to indicate that there is no routing protocol
-.br
-RIP to indicate that RIP/SAP should be used
-.br
-NLSP to indicate that Novell NLSP should be used
-.br
-RIP NLSP to indicate that both RIP/SAP and NLSP should be used
-.TP
-.B /etc/ppp/ipx-down
-A program or script which is executed when the link is no longer
-available for sending and receiving IPX packets. This script can be
-used for undoing the effects of the /etc/ppp/ipx-up script. It is
-invoked in the same manner and with the same parameters as the ipx-up
-script.
-.SH FILES
-.TP
-.B /var/run/ppp\fIn\fB.pid \fR(BSD or Linux), \fB/etc/ppp/ppp\fIn\fB.pid \fR(others)
-Process-ID for pppd process on ppp interface unit \fIn\fR.
-.TP
-.B /etc/ppp/pap-secrets
-Usernames, passwords and IP addresses for PAP authentication. This
-file should be owned by root and not readable or writable by any other
-user. Pppd will log a warning if this is not the case.
-.TP
-.B /etc/ppp/chap-secrets
-Names, secrets and IP addresses for CHAP authentication. As for
-/etc/ppp/pap-secrets, this file should be owned by root and not
-readable or writable by any other user. Pppd will log a warning if
-this is not the case.
-.TP
-.B /etc/ppp/options
-System default options for pppd, read before user default options or
-command-line options.
-.TP
-.B ~/.ppprc
-User default options, read before /etc/ppp/options.\fIttyname\fR.
-.TP
-.B /etc/ppp/options.\fIttyname
-System default options for the serial port being used, read after
-~/.ppprc. In forming the \fIttyname\fR part of this
-filename, an initial /dev/ is stripped from the port name (if
-present), and any slashes in the remaining part are converted to
-dots.
-.TP
-.B /etc/ppp/peers
-A directory containing options files which may contain privileged
-options, even if pppd was invoked by a user other than root. The
-system administrator can create options files in this directory to
-permit non-privileged users to dial out without requiring the peer to
-authenticate, but only to certain trusted peers.
-.TP
-.B /etc/ppp/ppp.deny
-Lists users who may not use the system password PAP authentication.
-.TP
-.B /etc/ppp/ppp.shells
-Lists user shells which are approved for system password PAP authentication
-logins.
-.TP
-.B /usr/share/examples/pppd/
-Sample pppd configuration files.
-.SH SEE ALSO
-.IR chat(8),
-.IR ppp(8)
-.TP
-.B RFC1144
-Jacobson, V.
-\fICompressing TCP/IP headers for low-speed serial links.\fR
-February 1990.
-.TP
-.B RFC1321
-Rivest, R.
-.I The MD5 Message-Digest Algorithm.
-April 1992.
-.TP
-.B RFC1332
-McGregor, G.
-.I PPP Internet Protocol Control Protocol (IPCP).
-May 1992.
-.TP
-.B RFC1334
-Lloyd, B.; Simpson, W.A.
-.I PPP authentication protocols.
-October 1992.
-.TP
-.B RFC1661
-Simpson, W.A.
-.I The Point\-to\-Point Protocol (PPP).
-July 1994.
-.TP
-.B RFC1662
-Simpson, W.A.
-.I PPP in HDLC-like Framing.
-July 1994.
-.SH NOTES
-The following signals have the specified effect when sent to pppd.
-.TP
-.B SIGINT, SIGTERM
-These signals cause pppd to terminate the link (by closing LCP),
-restore the serial device settings, and exit.
-.TP
-.B SIGHUP
-This signal causes pppd to terminate the link, restore the serial
-device settings, and close the serial device. If the \fIpersist\fR or
-\fIdemand\fR option has been specified, pppd will try to reopen the
-serial device and start another connection (after the holdoff period).
-Otherwise pppd will exit. If this signal is received during the
-holdoff period, it causes pppd to end the holdoff period immediately.
-.TP
-.B SIGUSR1
-This signal toggles the state of the \fIdebug\fR option.
-.TP
-.B SIGUSR2
-This signal causes pppd to renegotiate compression. This can be
-useful to re-enable compression after it has been disabled as a result
-of a fatal decompression error. (Fatal decompression errors generally
-indicate a bug in one or other implementation.)
-
-.SH AUTHORS
-Paul Mackerras (Paul.Mackerras@cs.anu.edu.au), based on earlier work by
-Drew Perkins,
-Brad Clements,
-Karl Fox,
-Greg Christy,
-and
-Brad Parker.
diff --git a/usr.sbin/pppd/pppd.h b/usr.sbin/pppd/pppd.h
deleted file mode 100644
index a547fb7..0000000
--- a/usr.sbin/pppd/pppd.h
+++ /dev/null
@@ -1,509 +0,0 @@
-/*
- * pppd.h - PPP daemon global declarations.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
- */
-
-/*
- * TODO:
- */
-
-#ifndef __PPPD_H__
-#define __PPPD_H__
-
-#include <stdio.h> /* for FILE */
-#include <sys/param.h> /* for MAXPATHLEN and BSD4_4, if defined */
-#include <sys/types.h> /* for u_int32_t, if defined */
-#include <sys/time.h> /* for struct timeval */
-#include <net/ppp_defs.h>
-
-#if __STDC__
-#include <stdarg.h>
-#define __V(x) x
-#else
-#include <varargs.h>
-#define __V(x) (va_alist) va_dcl
-#define const
-#endif
-
-#ifdef INET6
-#include "eui64.h"
-#endif
-
-/*
- * Limits.
- */
-
-#define NUM_PPP 1 /* One PPP interface supported (per process) */
-#define MAXWORDLEN 1024 /* max length of word in file (incl null) */
-#define MAXARGS 1 /* max # args to a command */
-#define MAXNAMELEN 256 /* max length of hostname or name for auth */
-#define MAXSECRETLEN 256 /* max length of password or secret */
-
-/*
- * Global variables.
- */
-
-extern int hungup; /* Physical layer has disconnected */
-extern int ifunit; /* Interface unit number */
-extern char ifname[]; /* Interface name */
-extern int ttyfd; /* Serial device file descriptor */
-extern char hostname[]; /* Our hostname */
-extern u_char outpacket_buf[]; /* Buffer for outgoing packets */
-extern int phase; /* Current state of link - see values below */
-extern int baud_rate; /* Current link speed in bits/sec */
-extern char *progname; /* Name of this program */
-extern int redirect_stderr;/* Connector's stderr should go to file */
-extern char peer_authname[];/* Authenticated name of peer */
-extern int privileged; /* We were run by real-uid root */
-extern int need_holdoff; /* Need holdoff period after link terminates */
-extern char **script_env; /* Environment variables for scripts */
-extern int detached; /* Have detached from controlling tty */
-
-/*
- * Variables set by command-line options.
- */
-
-extern int debug; /* Debug flag */
-extern int kdebugflag; /* Tell kernel to print debug messages */
-extern int default_device; /* Using /dev/tty or equivalent */
-extern char devnam[]; /* Device name */
-extern int crtscts; /* Use hardware flow control */
-extern int modem; /* Use modem control lines */
-extern int inspeed; /* Input/Output speed requested */
-extern u_int32_t netmask; /* IP netmask to set on interface */
-extern int lockflag; /* Create lock file to lock the serial dev */
-extern int nodetach; /* Don't detach from controlling tty */
-extern char *connector; /* Script to establish physical link */
-extern char *disconnector; /* Script to disestablish physical link */
-extern char *welcomer; /* Script to welcome client after connection */
-extern int max_con_attempts;/* Maximum number of times to try dialing */
-extern int maxconnect; /* Maximum connect time (seconds) */
-extern char user[]; /* Our name for authenticating ourselves */
-extern char passwd[]; /* Password for PAP */
-extern int auth_required; /* Peer is required to authenticate */
-extern int proxyarp; /* Set up proxy ARP entry for peer */
-extern int persist; /* Reopen link after it goes down */
-extern int uselogin; /* Use /etc/passwd for checking PAP */
-extern int lcp_echo_interval; /* Interval between LCP echo-requests */
-extern int lcp_echo_fails; /* Tolerance to unanswered echo-requests */
-extern char our_name[]; /* Our name for authentication purposes */
-extern char remote_name[]; /* Peer's name for authentication */
-extern int explicit_remote;/* remote_name specified with remotename opt */
-extern int usehostname; /* Use hostname for our_name */
-extern int disable_defaultip; /* Don't use hostname for default IP adrs */
-extern int demand; /* Do dial-on-demand */
-extern char *ipparam; /* Extra parameter for ip up/down scripts */
-extern int cryptpap; /* Others' PAP passwords are encrypted */
-extern int idle_time_limit;/* Shut down link if idle for this long */
-extern int holdoff; /* Dead time before restarting */
-extern int refuse_pap; /* Don't wanna auth. ourselves with PAP */
-extern int refuse_chap; /* Don't wanna auth. ourselves with CHAP */
-#ifdef PPP_FILTER
-extern struct bpf_program pass_filter; /* Filter for pkts to pass */
-extern struct bpf_program active_filter; /* Filter for link-active pkts */
-#endif
-
-
-#ifdef MSLANMAN
-extern int ms_lanman; /* Nonzero if use LanMan password instead of NT */
- /* Has meaning only with MS-CHAP challenges */
-#endif
-
-/*
- * Values for phase.
- */
-#define PHASE_DEAD 0
-#define PHASE_INITIALIZE 1
-#define PHASE_DORMANT 2
-#define PHASE_ESTABLISH 3
-#define PHASE_AUTHENTICATE 4
-#define PHASE_CALLBACK 5
-#define PHASE_NETWORK 6
-#define PHASE_TERMINATE 7
-#define PHASE_HOLDOFF 8
-
-/*
- * The following struct gives the addresses of procedures to call
- * for a particular protocol.
- */
-struct protent {
- u_short protocol; /* PPP protocol number */
- /* Initialization procedure */
- void (*init)(int unit);
- /* Process a received packet */
- void (*input)(int unit, u_char *pkt, int len);
- /* Process a received protocol-reject */
- void (*protrej)(int unit);
- /* Lower layer has come up */
- void (*lowerup)(int unit);
- /* Lower layer has gone down */
- void (*lowerdown)(int unit);
- /* Open the protocol */
- void (*open)(int unit);
- /* Close the protocol */
- void (*close)(int unit, char *reason);
- /* Print a packet in readable form */
- int (*printpkt)(u_char *pkt, int len,
- void (*printer)(void *, char *, ...),
- void *arg);
- /* Process a received data packet */
- void (*datainput)(int unit, u_char *pkt, int len);
- int enabled_flag; /* 0 iff protocol is disabled */
- char *name; /* Text name of protocol */
- /* Check requested options, assign defaults */
- void (*check_options)(void);
- /* Configure interface for demand-dial */
- int (*demand_conf)(int unit);
- /* Say whether to bring up link for this pkt */
- int (*active_pkt)(u_char *pkt, int len);
-};
-
-/* Table of pointers to supported protocols */
-extern struct protent *protocols[];
-
-/*
- * Prototypes.
- */
-
-/* Procedures exported from main.c. */
-void detach(void); /* Detach from controlling tty */
-void die(int); /* Cleanup and exit */
-void quit(void); /* like die(1) */
-void novm(char *); /* Say we ran out of memory, and die */
-void timeout(void (*func)(void *), void *arg, int t);
- /* Call func(arg) after t seconds */
-void untimeout(void (*func)(void *), void *arg);
- /* Cancel call to func(arg) */
-int run_program(char *prog, char **args, int must_exist);
- /* Run program prog with args in child */
-void demuxprotrej(int, int);
- /* Demultiplex a Protocol-Reject */
-void format_packet(u_char *, int, void (*) (void *, char *, ...),
- void *); /* Format a packet in human-readable form */
-void log_packet(u_char *, int, char *, int);
- /* Format a packet and log it with syslog */
-void print_string(char *, int, void (*) (void *, char *, ...),
- void *); /* Format a string for output */
-int fmtmsg(char *, int, char *, ...); /* sprintf++ */
-int vfmtmsg(char *, int, char *, va_list); /* vsprintf++ */
-void script_setenv(char *, char *); /* set script env var */
-void script_unsetenv(char *); /* unset script env var */
-
-/* Procedures exported from auth.c */
-void link_required(int); /* we are starting to use the link */
-void link_terminated(int); /* we are finished with the link */
-void link_down(int); /* the LCP layer has left the Opened state */
-void link_established(int); /* the link is up; authenticate now */
-void np_up(int, int); /* a network protocol has come up */
-void np_down(int, int); /* a network protocol has gone down */
-void np_finished(int, int); /* a network protocol no longer needs link */
-void auth_peer_fail(int, int);
- /* peer failed to authenticate itself */
-void auth_peer_success(int, int, char *, int);
- /* peer successfully authenticated itself */
-void auth_withpeer_fail(int, int);
- /* we failed to authenticate ourselves */
-void auth_withpeer_success(int, int);
- /* we successfully authenticated ourselves */
-void auth_check_options(void);
- /* check authentication options supplied */
-void auth_reset(int); /* check what secrets we have */
-int check_passwd(int, char *, int, char *, int, char **, int *);
- /* Check peer-supplied username/password */
-int get_secret(int, char *, char *, char *, int *, int);
- /* get "secret" for chap */
-int auth_ip_addr(int, u_int32_t);
- /* check if IP address is authorized */
-int bad_ip_adrs(u_int32_t);
- /* check if IP address is unreasonable */
-void check_access(FILE *, char *);
- /* check permissions on secrets file */
-
-/* Procedures exported from demand.c */
-void demand_conf(void); /* config interface(s) for demand-dial */
-void demand_block(void); /* set all NPs to queue up packets */
-void demand_unblock(void); /* set all NPs to pass packets */
-void demand_discard(void); /* set all NPs to discard packets */
-void demand_rexmit(int); /* retransmit saved frames for an NP */
-int loop_chars(unsigned char *, int); /* process chars from loopback */
-int loop_frame(unsigned char *, int); /* process frame from loopback */
-
-/* Procedures exported from sys-*.c */
-void sys_init(void); /* Do system-dependent initialization */
-void sys_cleanup(void); /* Restore system state before exiting */
-void sys_check_options(void); /* Check options specified */
-void sys_close(void); /* Clean up in a child before execing */
-int ppp_available(void); /* Test whether ppp kernel support exists */
-void open_ppp_loopback(void); /* Open loopback for demand-dialling */
-void establish_ppp(int); /* Turn serial port into a ppp interface */
-void restore_loop(void); /* Transfer ppp unit back to loopback */
-void disestablish_ppp(int); /* Restore port to normal operation */
-void clean_check(void); /* Check if line was 8-bit clean */
-void set_up_tty(int, int); /* Set up port's speed, parameters, etc. */
-void restore_tty(int); /* Restore port's original parameters */
-void setdtr(int, int); /* Raise or lower port's DTR line */
-void output(int, u_char *, int); /* Output a PPP packet */
-void wait_input(struct timeval *);
- /* Wait for input, with timeout */
-void wait_loop_output(struct timeval *);
- /* Wait for pkt from loopback, with timeout */
-void wait_time(struct timeval *); /* Wait for given length of time */
-int read_packet(u_char *); /* Read PPP packet */
-int get_loop_output(void); /* Read pkts from loopback */
-void ppp_send_config(int, int, u_int32_t, int, int);
- /* Configure i/f transmit parameters */
-void ppp_set_xaccm(int, ext_accm);
- /* Set extended transmit ACCM */
-void ppp_recv_config(int, int, u_int32_t, int, int);
- /* Configure i/f receive parameters */
-int ccp_test(int, u_char *, int, int);
- /* Test support for compression scheme */
-void ccp_flags_set(int, int, int);
- /* Set kernel CCP state */
-int ccp_fatal_error(int); /* Test for fatal decomp error in kernel */
-int get_idle_time(int, struct ppp_idle *);
- /* Find out how long link has been idle */
-int sifvjcomp(int, int, int, int);
- /* Configure VJ TCP header compression */
-int sifup(int); /* Configure i/f up (for IP) */
-int sifnpmode(int u, int proto, enum NPmode mode);
- /* Set mode for handling packets for proto */
-int sifdown(int); /* Configure i/f down (for IP) */
-int sifaddr(int, u_int32_t, u_int32_t, u_int32_t);
- /* Configure IP addresses for i/f */
-int cifaddr(int, u_int32_t, u_int32_t);
- /* Reset i/f IP addresses */
-#ifdef INET6
-int sif6addr(int, eui64_t, eui64_t);
- /* Configure IPv6 addresses for i/f */
-int cif6addr(int, eui64_t, eui64_t);
- /* Remove an IPv6 address from i/f */
-#endif
-int sifdefaultroute(int, u_int32_t, u_int32_t);
- /* Create default route through i/f */
-int cifdefaultroute(int, u_int32_t, u_int32_t);
- /* Delete default route through i/f */
-int sifproxyarp(int, u_int32_t);
- /* Add proxy ARP entry for peer */
-int cifproxyarp(int, u_int32_t);
- /* Delete proxy ARP entry for peer */
-u_int32_t GetMask(u_int32_t); /* Get appropriate netmask for address */
-int lock(char *); /* Create lock file for device */
-void unlock(void); /* Delete previously-created lock file */
-int daemon(int, int); /* Detach us from terminal session */
-void logwtmp(const char *, const char *, const char *);
- /* Write entry to wtmp file */
-int get_host_seed(void); /* Get host-dependent random number seed */
-#ifdef PPP_FILTER
-int set_filters(struct bpf_program *pass, struct bpf_program *active);
- /* Set filter programs in kernel */
-#endif
-
-/* Procedures exported from options.c */
-int parse_args(int argc, char **argv);
- /* Parse options from arguments given */
-void usage(void); /* Print a usage message */
-int options_from_file(char *filename, int must_exist, int check_prot,
- int privileged);
- /* Parse options from an options file */
-int options_from_user(void); /* Parse options from user's .ppprc */
-int options_for_tty(void); /* Parse options from /etc/ppp/options.tty */
-void scan_args(int argc, char **argv);
- /* Look for tty name in command-line args */
-int getword(FILE *f, char *word, int *newlinep, char *filename);
- /* Read a word from a file */
-void option_error(char *fmt, ...);
- /* Print an error message about an option */
-int setipaddr(char *); /* set IP addresses */
-
-
-/*
- * This structure is used to store information about certain
- * options, such as where the option value came from (/etc/ppp/options,
- * command line, etc.) and whether it came from a privileged source.
- */
-
-struct option_info {
- int priv; /* was value set by sysadmin? */
- char *source; /* where option came from */
-};
-
-extern struct option_info auth_req_info;
-extern struct option_info connector_info;
-extern struct option_info disconnector_info;
-extern struct option_info welcomer_info;
-extern struct option_info devnam_info;
-
-/*
- * Inline versions of get/put char/short/long.
- * Pointer is advanced; we assume that both arguments
- * are lvalues and will already be in registers.
- * cp MUST be u_char *.
- */
-#define GETCHAR(c, cp) { \
- (c) = *(cp)++; \
-}
-#define PUTCHAR(c, cp) { \
- *(cp)++ = (u_char) (c); \
-}
-
-
-#define GETSHORT(s, cp) { \
- (s) = *(cp)++ << 8; \
- (s) |= *(cp)++; \
-}
-#define PUTSHORT(s, cp) { \
- *(cp)++ = (u_char) ((s) >> 8); \
- *(cp)++ = (u_char) (s); \
-}
-
-#define GETLONG(l, cp) { \
- (l) = *(cp)++ << 8; \
- (l) |= *(cp)++; (l) <<= 8; \
- (l) |= *(cp)++; (l) <<= 8; \
- (l) |= *(cp)++; \
-}
-#define PUTLONG(l, cp) { \
- *(cp)++ = (u_char) ((l) >> 24); \
- *(cp)++ = (u_char) ((l) >> 16); \
- *(cp)++ = (u_char) ((l) >> 8); \
- *(cp)++ = (u_char) (l); \
-}
-
-#define INCPTR(n, cp) ((cp) += (n))
-#define DECPTR(n, cp) ((cp) -= (n))
-
-#undef FALSE
-#define FALSE 0
-#undef TRUE
-#define TRUE 1
-
-/*
- * System dependent definitions for user-level 4.3BSD UNIX implementation.
- */
-
-#define DEMUXPROTREJ(u, p) demuxprotrej(u, p)
-
-#define TIMEOUT(r, f, t) timeout((r), (f), (t))
-#define UNTIMEOUT(r, f) untimeout((r), (f))
-
-#define BCOPY(s, d, l) memcpy(d, s, l)
-#define BZERO(s, n) memset(s, 0, n)
-#define EXIT(u) quit()
-
-#define PRINTMSG(m, l) { m[l] = '\0'; syslog(LOG_INFO, "Remote message: %s", m); }
-
-/*
- * MAKEHEADER - Add Header fields to a packet.
- */
-#define MAKEHEADER(p, t) { \
- PUTCHAR(PPP_ALLSTATIONS, p); \
- PUTCHAR(PPP_UI, p); \
- PUTSHORT(t, p); }
-
-
-#ifdef DEBUGALL
-#define DEBUGMAIN 1
-#define DEBUGFSM 1
-#define DEBUGLCP 1
-#define DEBUGIPCP 1
-#define DEBUGUPAP 1
-#define DEBUGCHAP 1
-#endif
-
-#ifndef LOG_PPP /* we use LOG_LOCAL2 for syslog by default */
-#if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUGSYS) \
- || defined(DEBUGLCP) || defined(DEBUGIPCP) || defined(DEBUGUPAP) \
- || defined(DEBUGCHAP) || defined(DEBUG)
-#define LOG_PPP LOG_LOCAL2
-#else
-#define LOG_PPP LOG_DAEMON
-#endif
-#endif /* LOG_PPP */
-
-#ifdef DEBUGMAIN
-#define MAINDEBUG(x) if (debug) syslog x
-#else
-#define MAINDEBUG(x)
-#endif
-
-#ifdef DEBUGSYS
-#define SYSDEBUG(x) if (debug) syslog x
-#else
-#define SYSDEBUG(x)
-#endif
-
-#ifdef DEBUGFSM
-#define FSMDEBUG(x) if (debug) syslog x
-#else
-#define FSMDEBUG(x)
-#endif
-
-#ifdef DEBUGLCP
-#define LCPDEBUG(x) if (debug) syslog x
-#else
-#define LCPDEBUG(x)
-#endif
-
-#ifdef DEBUGIPCP
-#define IPCPDEBUG(x) if (debug) syslog x
-#else
-#define IPCPDEBUG(x)
-#endif
-
-#ifdef DEBUGIPV6CP
-#define IPV6CPDEBUG(x) if (debug) syslog x
-#else
-#define IPV6CPDEBUG(x)
-#endif
-
-#ifdef DEBUGUPAP
-#define UPAPDEBUG(x) if (debug) syslog x
-#else
-#define UPAPDEBUG(x)
-#endif
-
-#ifdef DEBUGCHAP
-#define CHAPDEBUG(x) if (debug) syslog x
-#else
-#define CHAPDEBUG(x)
-#endif
-
-#ifdef DEBUGIPXCP
-#define IPXCPDEBUG(x) if (debug) syslog x
-#else
-#define IPXCPDEBUG(x)
-#endif
-
-#ifndef SIGTYPE
-#if defined(sun) || defined(SYSV) || defined(POSIX_SOURCE)
-#define SIGTYPE void
-#else
-#define SIGTYPE int
-#endif /* defined(sun) || defined(SYSV) || defined(POSIX_SOURCE) */
-#endif /* SIGTYPE */
-
-#ifndef MIN
-#define MIN(a, b) ((a) < (b)? (a): (b))
-#endif
-#ifndef MAX
-#define MAX(a, b) ((a) > (b)? (a): (b))
-#endif
-
-#endif /* __PPP_H__ */
diff --git a/usr.sbin/pppd/sys-bsd.c b/usr.sbin/pppd/sys-bsd.c
deleted file mode 100644
index cbde7a4..0000000
--- a/usr.sbin/pppd/sys-bsd.c
+++ /dev/null
@@ -1,1697 +0,0 @@
-/*
- * sys-bsd.c - System-dependent procedures for setting up
- * PPP interfaces on bsd-4.4-ish systems (including 386BSD, NetBSD, etc.)
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * Copyright (c) 1995 The Australian National University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University and The Australian National University.
- * The names of the Universities may not be used to endorse or promote
- * products derived from this software without specific prior written
- * permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-/* $NetBSD: sys-bsd.c,v 1.1.1.3 1997/09/26 18:53:04 christos Exp $ */
-
-/*
- * TODO:
- */
-
-#include <stdio.h>
-#include <syslog.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <signal.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <sys/module.h>
-#ifdef NetBSD1_2
-#include <util.h>
-#endif
-#ifdef PPP_FILTER
-#include <net/bpf.h>
-#endif
-
-#include <net/if.h>
-#include <net/ppp_defs.h>
-#include <net/if_ppp.h>
-#include <net/route.h>
-#include <net/if_dl.h>
-#include <netinet/in.h>
-#include <net/if_var.h>
-#include <netinet6/in6_var.h>
-#include <netinet6/nd6.h>
-#include <ifaddrs.h>
-
-#ifdef IPX_CHANGE
-#include <netipx/ipx.h>
-#endif
-
-#if RTM_VERSION >= 3
-#include <sys/param.h>
-#if defined(NetBSD) && (NetBSD >= 199703)
-#include <netinet/if_inarp.h>
-#else /* NetBSD 1.2D or later */
-#ifdef __FreeBSD__
-#include <netinet/if_ether.h>
-#else
-#include <net/if_ether.h>
-#endif
-#endif
-#endif
-
-#include <ifaddrs.h>
-
-#include "pppd.h"
-#include "fsm.h"
-#include "ipcp.h"
-
-static int initdisc = -1; /* Initial TTY discipline for ppp_fd */
-static int initfdflags = -1; /* Initial file descriptor flags for ppp_fd */
-static int ppp_fd = -1; /* fd which is set to PPP discipline */
-static int rtm_seq;
-
-static int restore_term; /* 1 => we've munged the terminal */
-static struct termios inittermios; /* Initial TTY termios */
-static struct winsize wsinfo; /* Initial window size info */
-
-static char *lock_file; /* name of lock file created */
-
-static int loop_slave = -1;
-static int loop_master;
-static char loop_name[20];
-
-static unsigned char inbuf[512]; /* buffer for chars read from loopback */
-
-static int sockfd; /* socket for doing interface ioctls */
-#ifdef INET6
-static int sock6_fd = -1; /* socket for doing ipv6 interface ioctls */
-#endif /* INET6 */
-
-static int if_is_up; /* the interface is currently up */
-static u_int32_t ifaddrs[2]; /* local and remote addresses we set */
-static u_int32_t default_route_gateway; /* gateway addr for default route */
-static u_int32_t proxy_arp_addr; /* remote addr for proxy arp */
-
-/* Prototypes for procedures local to this file. */
-static int dodefaultroute(u_int32_t, int);
-static int get_ether_addr(u_int32_t, struct sockaddr_dl *);
-
-
-/*
- * sys_init - System-dependent initialization.
- */
-void
-sys_init()
-{
- /* Get an internet socket for doing socket ioctl's on. */
- if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "Couldn't create IP socket: %m");
- die(1);
- }
-
-#ifdef INET6
- if ((sock6_fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
- /* check it at runtime */
- sock6_fd = -1;
- }
-#endif
-}
-
-/*
- * sys_cleanup - restore any system state we modified before exiting:
- * mark the interface down, delete default route and/or proxy arp entry.
- * This should call die() because it's called from die().
- */
-void
-sys_cleanup()
-{
- struct ifreq ifr;
-
- if (if_is_up) {
- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
- if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) >= 0
- && ((ifr.ifr_flags & IFF_UP) != 0)) {
- ifr.ifr_flags &= ~IFF_UP;
- ioctl(sockfd, SIOCSIFFLAGS, &ifr);
- }
- }
- if (ifaddrs[0] != 0)
- cifaddr(0, ifaddrs[0], ifaddrs[1]);
- if (default_route_gateway)
- cifdefaultroute(0, 0, default_route_gateway);
- if (proxy_arp_addr)
- cifproxyarp(0, proxy_arp_addr);
-}
-
-/*
- * sys_close - Clean up in a child process before execing.
- */
-void
-sys_close()
-{
- if (sockfd >= 0)
- close(sockfd);
-#ifdef INET6
- if (sock6_fd >= 0)
- close(sock6_fd);
-#endif
- if (loop_slave >= 0) {
- close(loop_slave);
- close(loop_master);
- }
-}
-
-/*
- * sys_check_options - check the options that the user specified
- */
-void
-sys_check_options()
-{
-}
-
-/*
- * ppp_available - check whether the system has the ppp module loaded
- * or compiled in. If it doesn't, and we're actually root (not just SUID
- * root) try loading it before giving up.
- */
-int
-ppp_available()
-{
- const char *modname = "if_ppp";
- extern char *no_ppp_msg;
-
- if (modfind(modname) != -1) {
- return 1;
- }
-
- if (getuid() == 0 && kldload(modname) != -1)
- return 1;
-
- no_ppp_msg = "\
-This system lacks kernel support for PPP. To include PPP support\n\
-in the kernel, please add \"device ppp\" to your kernel config or \n\
-load the if_ppp module.\n";
-
- return 0;
-}
-
-/*
- * establish_ppp - Turn the serial port into a ppp interface.
- */
-void
-establish_ppp(fd)
- int fd;
-{
- int pppdisc = PPPDISC;
- int x;
-
- if (demand) {
- /*
- * Demand mode - prime the old ppp device to relinquish the unit.
- */
- if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) {
- syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
- die(1);
- }
- }
-
- /*
- * Save the old line discipline of fd, and set it to PPP.
- */
- if (ioctl(fd, TIOCGETD, &initdisc) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCGETD): %m");
- die(1);
- }
- if (ioctl(fd, TIOCSETD, &pppdisc) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
- die(1);
- }
-
- if (!demand) {
- /*
- * Find out which interface we were given.
- */
- if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
- die(1);
- }
- } else {
- /*
- * Check that we got the same unit again.
- */
- if (ioctl(fd, PPPIOCGUNIT, &x) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
- die(1);
- }
- if (x != ifunit) {
- syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
- ifunit, x);
- die(1);
- }
- x = TTYDISC;
- ioctl(loop_slave, TIOCSETD, &x);
- }
-
- ppp_fd = fd;
-
- /*
- * Enable debug in the driver if requested.
- */
- if (kdebugflag) {
- if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
- } else {
- x |= (kdebugflag & 0xFF) * SC_DEBUG;
- if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
- syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
- }
- }
-
- /*
- * Set device for non-blocking reads.
- */
- if ((initfdflags = fcntl(fd, F_GETFL)) == -1
- || fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) {
- syslog(LOG_WARNING, "Couldn't set device to non-blocking mode: %m");
- }
-}
-
-/*
- * restore_loop - reattach the ppp unit to the loopback.
- */
-void
-restore_loop()
-{
- int x;
-
- /*
- * Transfer the ppp interface back to the loopback.
- */
- if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) {
- syslog(LOG_ERR, "ioctl(transfer ppp unit): %m");
- die(1);
- }
- x = PPPDISC;
- if (ioctl(loop_slave, TIOCSETD, &x) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
- die(1);
- }
-
- /*
- * Check that we got the same unit again.
- */
- if (ioctl(loop_slave, PPPIOCGUNIT, &x) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
- die(1);
- }
- if (x != ifunit) {
- syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d",
- ifunit, x);
- die(1);
- }
- ppp_fd = loop_slave;
-}
-
-
-/*
- * disestablish_ppp - Restore the serial port to normal operation.
- * This shouldn't call die() because it's called from die().
- */
-void
-disestablish_ppp(fd)
- int fd;
-{
- /* Reset non-blocking mode on fd. */
- if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0)
- syslog(LOG_WARNING, "Couldn't restore device fd flags: %m");
- initfdflags = -1;
-
- /* Restore old line discipline. */
- if (initdisc >= 0 && ioctl(fd, TIOCSETD, &initdisc) < 0)
- syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
- initdisc = -1;
-
- if (fd == ppp_fd)
- ppp_fd = -1;
-}
-
-/*
- * Check whether the link seems not to be 8-bit clean.
- */
-void
-clean_check()
-{
- int x;
- char *s;
-
- if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) {
- s = NULL;
- switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) {
- case SC_RCV_B7_0:
- s = "bit 7 set to 1";
- break;
- case SC_RCV_B7_1:
- s = "bit 7 set to 0";
- break;
- case SC_RCV_EVNP:
- s = "odd parity";
- break;
- case SC_RCV_ODDP:
- s = "even parity";
- break;
- }
- if (s != NULL) {
- syslog(LOG_WARNING, "Serial link is not 8-bit clean:");
- syslog(LOG_WARNING, "All received characters had %s", s);
- }
- }
-}
-
-/*
- * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity,
- * at the requested speed, etc. If `local' is true, set CLOCAL
- * regardless of whether the modem option was specified.
- *
- * For *BSD, we assume that speed_t values numerically equal bits/second.
- */
-void
-set_up_tty(fd, local)
- int fd, local;
-{
- struct termios tios;
-
- if (tcgetattr(fd, &tios) < 0) {
- syslog(LOG_ERR, "tcgetattr: %m");
- die(1);
- }
-
- if (!restore_term) {
- inittermios = tios;
- ioctl(fd, TIOCGWINSZ, &wsinfo);
- }
-
- tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL);
- if (crtscts > 0 && !local)
- tios.c_cflag |= CRTSCTS;
- else if (crtscts < 0)
- tios.c_cflag &= ~CRTSCTS;
-
- tios.c_cflag |= CS8 | CREAD | HUPCL;
- if (local || !modem)
- tios.c_cflag |= CLOCAL;
- tios.c_iflag = IGNBRK | IGNPAR;
- tios.c_oflag = 0;
- tios.c_lflag = 0;
- tios.c_cc[VMIN] = 1;
- tios.c_cc[VTIME] = 0;
-
- if (crtscts == -2) {
- tios.c_iflag |= IXON | IXOFF;
- tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */
- tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */
- }
-
- if (inspeed) {
- cfsetospeed(&tios, inspeed);
- cfsetispeed(&tios, inspeed);
- } else {
- inspeed = cfgetospeed(&tios);
- /*
- * We can't proceed if the serial port speed is 0,
- * since that implies that the serial port is disabled.
- */
- if (inspeed == 0) {
- syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate",
- devnam);
- die(1);
- }
- }
- baud_rate = inspeed;
-
- if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
- syslog(LOG_ERR, "tcsetattr: %m");
- die(1);
- }
-
- restore_term = 1;
-}
-
-/*
- * restore_tty - restore the terminal to the saved settings.
- */
-void
-restore_tty(fd)
- int fd;
-{
- if (restore_term) {
- if (!default_device) {
- /*
- * Turn off echoing, because otherwise we can get into
- * a loop with the tty and the modem echoing to each other.
- * We presume we are the sole user of this tty device, so
- * when we close it, it will revert to its defaults anyway.
- */
- inittermios.c_lflag &= ~(ECHO | ECHONL);
- }
- if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0)
- if (errno != ENXIO)
- syslog(LOG_WARNING, "tcsetattr: %m");
- ioctl(fd, TIOCSWINSZ, &wsinfo);
- restore_term = 0;
- }
-}
-
-/*
- * setdtr - control the DTR line on the serial port.
- * This is called from die(), so it shouldn't call die().
- */
-void
-setdtr(fd, on)
-int fd, on;
-{
- int modembits = TIOCM_DTR;
-
- ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits);
-}
-
-#ifdef INET6
-/*
- * sif6addr - Config the interface with an IPv6 link-local address
- */
-int
-sif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64)
-{
- int ifindex;
- struct in6_aliasreq addreq6;
-
- if (sock6_fd < 0) {
- syslog(LOG_ERR, "No IPv6 socket available");
- die(1);
- /*NOTREACHED*/
- }
-
- /* actually, this part is not kame local - RFC2553 conformant */
- ifindex = if_nametoindex(ifname);
- if (ifindex == 0) {
- syslog(LOG_ERR, "sifaddr6: no interface %s", ifname);
- return 0;
- }
-
- memset(&addreq6, 0, sizeof(addreq6));
- strlcpy(addreq6.ifra_name, ifname, sizeof(addreq6.ifra_name));
-
- /* my addr */
- addreq6.ifra_addr.sin6_family = AF_INET6;
- addreq6.ifra_addr.sin6_len = sizeof(struct sockaddr_in6);
- addreq6.ifra_addr.sin6_addr.s6_addr[0] = 0xfe;
- addreq6.ifra_addr.sin6_addr.s6_addr[1] = 0x80;
- memcpy(&addreq6.ifra_addr.sin6_addr.s6_addr[8], &our_eui64,
- sizeof(our_eui64));
- /* KAME ifindex hack */
- *(u_int16_t *)&addreq6.ifra_addr.sin6_addr.s6_addr[2] = htons(ifindex);
-
- /* his addr */
- addreq6.ifra_dstaddr.sin6_family = AF_INET6;
- addreq6.ifra_dstaddr.sin6_len = sizeof(struct sockaddr_in6);
- addreq6.ifra_dstaddr.sin6_addr.s6_addr[0] = 0xfe;
- addreq6.ifra_dstaddr.sin6_addr.s6_addr[1] = 0x80;
- memcpy(&addreq6.ifra_dstaddr.sin6_addr.s6_addr[8], &his_eui64,
- sizeof(our_eui64));
- /* KAME ifindex hack */
- *(u_int16_t *)&addreq6.ifra_dstaddr.sin6_addr.s6_addr[2] = htons(ifindex);
-
- /* prefix mask: 128bit */
- addreq6.ifra_prefixmask.sin6_family = AF_INET6;
- addreq6.ifra_prefixmask.sin6_len = sizeof(struct sockaddr_in6);
- memset(&addreq6.ifra_prefixmask.sin6_addr, 0xff,
- sizeof(addreq6.ifra_prefixmask.sin6_addr));
-
- /* address lifetime (infty) */
- addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
- addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
-
- if (ioctl(sock6_fd, SIOCAIFADDR_IN6, &addreq6) < 0) {
- syslog(LOG_ERR, "sif6addr: ioctl(SIOCAIFADDR_IN6): %m");
- return 0;
- }
-
- return 1;
-}
-
-
-/*
- * cif6addr - Remove IPv6 address from interface
- */
-int
-cif6addr(int unit, eui64_t our_eui64, eui64_t his_eui64)
-{
- int ifindex;
- struct in6_ifreq delreq6;
-
- if (sock6_fd < 0) {
- syslog(LOG_ERR, "No IPv6 socket available");
- die(1);
- /*NOTREACHED*/
- }
-
- /* actually, this part is not kame local - RFC2553 conformant */
- ifindex = if_nametoindex(ifname);
- if (ifindex == 0) {
- syslog(LOG_ERR, "cifaddr6: no interface %s", ifname);
- return 0;
- }
-
- memset(&delreq6, 0, sizeof(delreq6));
- strlcpy(delreq6.ifr_name, ifname, sizeof(delreq6.ifr_name));
-
- /* my addr */
- delreq6.ifr_ifru.ifru_addr.sin6_family = AF_INET6;
- delreq6.ifr_ifru.ifru_addr.sin6_len = sizeof(struct sockaddr_in6);
- delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[0] = 0xfe;
- delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[1] = 0x80;
- memcpy(&delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[8], &our_eui64,
- sizeof(our_eui64));
- /* KAME ifindex hack */
- *(u_int16_t *)&delreq6.ifr_ifru.ifru_addr.sin6_addr.s6_addr[2] =
- htons(ifindex);
-
- if (ioctl(sock6_fd, SIOCDIFADDR_IN6, &delreq6) < 0) {
- syslog(LOG_ERR, "cif6addr: ioctl(SIOCDIFADDR_IN6): %m");
- return 0;
- }
-
- return 1;
-}
-#endif /* INET6 */
-
-/*
- * open_ppp_loopback - open the device we use for getting
- * packets in demand mode, and connect it to a ppp interface.
- * Here we use a pty.
- */
-void
-open_ppp_loopback()
-{
- int flags;
- struct termios tios;
- int pppdisc = PPPDISC;
-
- if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0) {
- syslog(LOG_ERR, "No free pty for loopback");
- die(1);
- }
- SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name));
-
- if (tcgetattr(loop_slave, &tios) == 0) {
- tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB);
- tios.c_cflag |= CS8 | CREAD;
- tios.c_iflag = IGNPAR;
- tios.c_oflag = 0;
- tios.c_lflag = 0;
- if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0)
- syslog(LOG_WARNING, "couldn't set attributes on loopback: %m");
- }
-
- if ((flags = fcntl(loop_master, F_GETFL)) != -1)
- if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1)
- syslog(LOG_WARNING, "couldn't set loopback to nonblock: %m");
-
- ppp_fd = loop_slave;
- if (ioctl(ppp_fd, TIOCSETD, &pppdisc) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
- die(1);
- }
-
- /*
- * Find out which interface we were given.
- */
- if (ioctl(ppp_fd, PPPIOCGUNIT, &ifunit) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m");
- die(1);
- }
-
- /*
- * Enable debug in the driver if requested.
- */
- if (kdebugflag) {
- if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &flags) < 0) {
- syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m");
- } else {
- flags |= (kdebugflag & 0xFF) * SC_DEBUG;
- if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &flags) < 0)
- syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m");
- }
- }
-
-}
-
-
-/*
- * output - Output PPP packet.
- */
-void
-output(unit, p, len)
- int unit;
- u_char *p;
- int len;
-{
- if (debug)
- log_packet(p, len, "sent ", LOG_DEBUG);
-
- if (write(ttyfd, p, len) < 0) {
- if (errno != EIO)
- syslog(LOG_ERR, "write: %m");
- }
-}
-
-
-/*
- * wait_input - wait until there is data available on ttyfd,
- * for the length of time specified by *timo (indefinite
- * if timo is NULL).
- */
-void
-wait_input(timo)
- struct timeval *timo;
-{
- fd_set ready;
- int n;
-
- if (ttyfd >= FD_SETSIZE) {
- syslog(LOG_ERR, "descriptor too big");
- die(1);
- }
- FD_ZERO(&ready);
- FD_SET(ttyfd, &ready);
- n = select(ttyfd+1, &ready, NULL, &ready, timo);
- if (n < 0 && errno != EINTR) {
- syslog(LOG_ERR, "select: %m");
- die(1);
- }
-}
-
-
-/*
- * wait_loop_output - wait until there is data available on the
- * loopback, for the length of time specified by *timo (indefinite
- * if timo is NULL).
- */
-void
-wait_loop_output(timo)
- struct timeval *timo;
-{
- fd_set ready;
- int n;
-
- if (loop_master >= FD_SETSIZE) {
- syslog(LOG_ERR, "descriptor too big");
- die(1);
- }
- FD_ZERO(&ready);
- FD_SET(loop_master, &ready);
- n = select(loop_master + 1, &ready, NULL, &ready, timo);
- if (n < 0 && errno != EINTR) {
- syslog(LOG_ERR, "select: %m");
- die(1);
- }
-}
-
-
-/*
- * wait_time - wait for a given length of time or until a
- * signal is received.
- */
-void
-wait_time(timo)
- struct timeval *timo;
-{
- int n;
-
- n = select(0, NULL, NULL, NULL, timo);
- if (n < 0 && errno != EINTR) {
- syslog(LOG_ERR, "select: %m");
- die(1);
- }
-}
-
-
-/*
- * read_packet - get a PPP packet from the serial device.
- */
-int
-read_packet(buf)
- u_char *buf;
-{
- int len;
-
- if ((len = read(ttyfd, buf, PPP_MTU + PPP_HDRLEN)) < 0) {
- if (errno == EWOULDBLOCK || errno == EINTR)
- return -1;
- syslog(LOG_ERR, "read: %m");
- die(1);
- }
- return len;
-}
-
-
-/*
- * get_loop_output - read characters from the loopback, form them
- * into frames, and detect when we want to bring the real link up.
- * Return value is 1 if we need to bring up the link, 0 otherwise.
- */
-int
-get_loop_output()
-{
- int rv = 0;
- int n;
-
- while ((n = read(loop_master, inbuf, sizeof(inbuf))) >= 0) {
- if (loop_chars(inbuf, n))
- rv = 1;
- }
-
- if (n == 0) {
- syslog(LOG_ERR, "eof on loopback");
- die(1);
- } else if (errno != EWOULDBLOCK){
- syslog(LOG_ERR, "read from loopback: %m");
- die(1);
- }
-
- return rv;
-}
-
-
-/*
- * ppp_send_config - configure the transmit characteristics of
- * the ppp interface.
- */
-void
-ppp_send_config(unit, mtu, asyncmap, pcomp, accomp)
- int unit, mtu;
- u_int32_t asyncmap;
- int pcomp, accomp;
-{
- u_int x;
- struct ifreq ifr;
-
- strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
- ifr.ifr_mtu = mtu;
- if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) {
- syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m");
- quit();
- }
-
- if (ioctl(ppp_fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m");
- quit();
- }
-
- if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
- quit();
- }
- x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT;
- x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC;
- if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
- quit();
- }
-}
-
-
-/*
- * ppp_set_xaccm - set the extended transmit ACCM for the interface.
- */
-void
-ppp_set_xaccm(unit, accm)
- int unit;
- ext_accm accm;
-{
- if (ioctl(ppp_fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY)
- syslog(LOG_WARNING, "ioctl(set extended ACCM): %m");
-}
-
-
-/*
- * ppp_recv_config - configure the receive-side characteristics of
- * the ppp interface.
- */
-void
-ppp_recv_config(unit, mru, asyncmap, pcomp, accomp)
- int unit, mru;
- u_int32_t asyncmap;
- int pcomp, accomp;
-{
- int x;
-
- if (ioctl(ppp_fd, PPPIOCSMRU, (caddr_t) &mru) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m");
- quit();
- }
- if (ioctl(ppp_fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m");
- quit();
- }
- if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
- quit();
- }
- x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC;
- if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
- quit();
- }
-}
-
-/*
- * ccp_test - ask kernel whether a given compression method
- * is acceptable for use. Returns 1 if the method and parameters
- * are OK, 0 if the method is known but the parameters are not OK
- * (e.g. code size should be reduced), or -1 if the method is unknown.
- */
-int
-ccp_test(unit, opt_ptr, opt_len, for_transmit)
- int unit, opt_len, for_transmit;
- u_char *opt_ptr;
-{
- struct ppp_option_data data;
-
- data.ptr = opt_ptr;
- data.length = opt_len;
- data.transmit = for_transmit;
- if (ioctl(ttyfd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0)
- return 1;
- return (errno == ENOBUFS)? 0: -1;
-}
-
-/*
- * ccp_flags_set - inform kernel about the current state of CCP.
- */
-void
-ccp_flags_set(unit, isopen, isup)
- int unit, isopen, isup;
-{
- int x;
-
- if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
- return;
- }
- x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN;
- x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP;
- if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0)
- syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
-}
-
-/*
- * ccp_fatal_error - returns 1 if decompression was disabled as a
- * result of an error detected after decompression of a packet,
- * 0 otherwise. This is necessary because of patent nonsense.
- */
-int
-ccp_fatal_error(unit)
- int unit;
-{
- int x;
-
- if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m");
- return 0;
- }
- return x & SC_DC_FERROR;
-}
-
-/*
- * get_idle_time - return how long the link has been idle.
- */
-int
-get_idle_time(u, ip)
- int u;
- struct ppp_idle *ip;
-{
- return ioctl(ppp_fd, PPPIOCGIDLE, ip) >= 0;
-}
-
-
-#ifdef PPP_FILTER
-/*
- * set_filters - transfer the pass and active filters to the kernel.
- */
-int
-set_filters(pass, active)
- struct bpf_program *pass, *active;
-{
- int ret = 1;
-
- if (pass->bf_len > 0) {
- if (ioctl(ppp_fd, PPPIOCSPASS, pass) < 0) {
- syslog(LOG_ERR, "Couldn't set pass-filter in kernel: %m");
- ret = 0;
- }
- }
- if (active->bf_len > 0) {
- if (ioctl(ppp_fd, PPPIOCSACTIVE, active) < 0) {
- syslog(LOG_ERR, "Couldn't set active-filter in kernel: %m");
- ret = 0;
- }
- }
- return ret;
-}
-#endif
-
-/*
- * sifvjcomp - config tcp header compression
- */
-int
-sifvjcomp(u, vjcomp, cidcomp, maxcid)
- int u, vjcomp, cidcomp, maxcid;
-{
- u_int x;
-
- if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m");
- return 0;
- }
- x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP;
- x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID;
- if (ioctl(ppp_fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
- return 0;
- }
- if (vjcomp && ioctl(ppp_fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) {
- syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m");
- return 0;
- }
- return 1;
-}
-
-/*
- * sifup - Config the interface up and enable IP packets to pass.
- */
-int
-sifup(u)
- int u;
-{
- struct ifreq ifr;
-
- strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
- if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
- syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
- return 0;
- }
- ifr.ifr_flags |= IFF_UP;
- if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
- syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
- return 0;
- }
- if_is_up = 1;
- return 1;
-}
-
-/*
- * sifnpmode - Set the mode for handling packets for a given NP.
- */
-int
-sifnpmode(u, proto, mode)
- int u;
- int proto;
- enum NPmode mode;
-{
- struct npioctl npi;
-
- npi.protocol = proto;
- npi.mode = mode;
- if (ioctl(ppp_fd, PPPIOCSNPMODE, &npi) < 0) {
- syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode);
- return 0;
- }
- return 1;
-}
-
-/*
- * sifdown - Config the interface down and disable IP.
- */
-int
-sifdown(u)
- int u;
-{
- struct ifreq ifr;
- int rv;
- struct npioctl npi;
-
- rv = 1;
- npi.protocol = PPP_IP;
- npi.mode = NPMODE_ERROR;
- ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi);
- /* ignore errors, because ppp_fd might have been closed by now. */
-
- strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
- if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
- syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
- rv = 0;
- } else {
- ifr.ifr_flags &= ~IFF_UP;
- if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
- syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m");
- rv = 0;
- } else
- if_is_up = 0;
- }
- return rv;
-}
-
-/*
- * SET_SA_FAMILY - set the sa_family field of a struct sockaddr,
- * if it exists.
- */
-#define SET_SA_FAMILY(addr, family) \
- BZERO((char *) &(addr), sizeof(addr)); \
- addr.sa_family = (family); \
- addr.sa_len = sizeof(addr);
-
-/*
- * sifaddr - Config the interface IP addresses and netmask.
- */
-int
-sifaddr(u, o, h, m)
- int u;
- u_int32_t o, h, m;
-{
- struct ifaliasreq ifra;
- struct ifreq ifr;
-
- strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
- SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
- ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
- SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
- ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
- if (m != 0) {
- SET_SA_FAMILY(ifra.ifra_mask, AF_INET);
- ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m;
- } else
- BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
- BZERO(&ifr, sizeof(ifr));
- strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
- if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifr) < 0) {
- if (errno != EADDRNOTAVAIL)
- syslog(LOG_WARNING, "Couldn't remove interface address: %m");
- }
- if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) {
- if (errno != EEXIST) {
- syslog(LOG_ERR, "Couldn't set interface address: %m");
- return 0;
- }
- syslog(LOG_WARNING,
- "Couldn't set interface address: Address %s already exists",
- ip_ntoa(o));
- }
- ifaddrs[0] = o;
- ifaddrs[1] = h;
- return 1;
-}
-
-/*
- * cifaddr - Clear the interface IP addresses, and delete routes
- * through the interface if possible.
- */
-int
-cifaddr(u, o, h)
- int u;
- u_int32_t o, h;
-{
- struct ifaliasreq ifra;
-
- ifaddrs[0] = 0;
- strncpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name));
- SET_SA_FAMILY(ifra.ifra_addr, AF_INET);
- ((struct sockaddr_in *) &ifra.ifra_addr)->sin_addr.s_addr = o;
- SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET);
- ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h;
- BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask));
- if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) {
- if (errno != EADDRNOTAVAIL)
- syslog(LOG_WARNING, "Couldn't delete interface address: %m");
- return 0;
- }
- return 1;
-}
-
-/*
- * sifdefaultroute - assign a default route through the address given.
- */
-int
-sifdefaultroute(u, l, g)
- int u;
- u_int32_t l, g;
-{
- return dodefaultroute(g, 's');
-}
-
-/*
- * cifdefaultroute - delete a default route through the address given.
- */
-int
-cifdefaultroute(u, l, g)
- int u;
- u_int32_t l, g;
-{
- return dodefaultroute(g, 'c');
-}
-
-/*
- * dodefaultroute - talk to a routing socket to add/delete a default route.
- */
-static int
-dodefaultroute(g, cmd)
- u_int32_t g;
- int cmd;
-{
- int routes;
- struct {
- struct rt_msghdr hdr;
- struct sockaddr_in dst;
- struct sockaddr_in gway;
- struct sockaddr_in mask;
- } rtmsg;
-
- if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
- syslog(LOG_ERR, "Couldn't %s default route: socket: %m",
- cmd=='s'? "add": "delete");
- return 0;
- }
-
- memset(&rtmsg, 0, sizeof(rtmsg));
- rtmsg.hdr.rtm_type = cmd == 's'? RTM_ADD: RTM_DELETE;
- rtmsg.hdr.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
- rtmsg.hdr.rtm_version = RTM_VERSION;
- rtmsg.hdr.rtm_seq = ++rtm_seq;
- rtmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
- rtmsg.dst.sin_len = sizeof(rtmsg.dst);
- rtmsg.dst.sin_family = AF_INET;
- rtmsg.gway.sin_len = sizeof(rtmsg.gway);
- rtmsg.gway.sin_family = AF_INET;
- rtmsg.gway.sin_addr.s_addr = g;
- rtmsg.mask.sin_len = sizeof(rtmsg.dst);
- rtmsg.mask.sin_family = AF_INET;
-
- rtmsg.hdr.rtm_msglen = sizeof(rtmsg);
- if (write(routes, &rtmsg, sizeof(rtmsg)) < 0) {
- syslog(LOG_ERR, "Couldn't %s default route: %m",
- cmd=='s'? "add": "delete");
- close(routes);
- return 0;
- }
-
- close(routes);
- default_route_gateway = (cmd == 's')? g: 0;
- return 1;
-}
-
-#if RTM_VERSION >= 3
-
-/*
- * sifproxyarp - Make a proxy ARP entry for the peer.
- */
-static struct {
- struct rt_msghdr hdr;
- struct sockaddr_inarp dst;
- struct sockaddr_dl hwa;
- char extra[128];
-} arpmsg;
-
-static int arpmsg_valid;
-
-int
-sifproxyarp(unit, hisaddr)
- int unit;
- u_int32_t hisaddr;
-{
- int routes;
-
- /*
- * Get the hardware address of an interface on the same subnet
- * as our local address.
- */
- memset(&arpmsg, 0, sizeof(arpmsg));
- if (!get_ether_addr(hisaddr, &arpmsg.hwa)) {
- syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
- return 0;
- }
-
- if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
- syslog(LOG_ERR, "Couldn't add proxy arp entry: socket: %m");
- return 0;
- }
-
- arpmsg.hdr.rtm_type = RTM_ADD;
- arpmsg.hdr.rtm_flags = RTF_ANNOUNCE | RTF_HOST | RTF_STATIC;
- arpmsg.hdr.rtm_version = RTM_VERSION;
- arpmsg.hdr.rtm_seq = ++rtm_seq;
- arpmsg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY;
- arpmsg.hdr.rtm_inits = RTV_EXPIRE;
- arpmsg.dst.sin_len = sizeof(struct sockaddr_inarp);
- arpmsg.dst.sin_family = AF_INET;
- arpmsg.dst.sin_addr.s_addr = hisaddr;
- arpmsg.dst.sin_other = SIN_PROXY;
-
- arpmsg.hdr.rtm_msglen = (char *) &arpmsg.hwa - (char *) &arpmsg
- + arpmsg.hwa.sdl_len;
- if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
- syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
- close(routes);
- return 0;
- }
-
- close(routes);
- arpmsg_valid = 1;
- proxy_arp_addr = hisaddr;
- return 1;
-}
-
-/*
- * cifproxyarp - Delete the proxy ARP entry for the peer.
- */
-int
-cifproxyarp(unit, hisaddr)
- int unit;
- u_int32_t hisaddr;
-{
- int routes;
-
- if (!arpmsg_valid)
- return 0;
- arpmsg_valid = 0;
-
- arpmsg.hdr.rtm_type = RTM_DELETE;
- arpmsg.hdr.rtm_seq = ++rtm_seq;
-
- if ((routes = socket(PF_ROUTE, SOCK_RAW, AF_INET)) < 0) {
- syslog(LOG_ERR, "Couldn't delete proxy arp entry: socket: %m");
- return 0;
- }
-
- if (write(routes, &arpmsg, arpmsg.hdr.rtm_msglen) < 0) {
- syslog(LOG_ERR, "Couldn't delete proxy arp entry: %m");
- close(routes);
- return 0;
- }
-
- close(routes);
- proxy_arp_addr = 0;
- return 1;
-}
-
-#else /* RTM_VERSION */
-
-/*
- * sifproxyarp - Make a proxy ARP entry for the peer.
- */
-int
-sifproxyarp(unit, hisaddr)
- int unit;
- u_int32_t hisaddr;
-{
- struct arpreq arpreq;
- struct {
- struct sockaddr_dl sdl;
- char space[128];
- } dls;
-
- BZERO(&arpreq, sizeof(arpreq));
-
- /*
- * Get the hardware address of an interface on the same subnet
- * as our local address.
- */
- if (!get_ether_addr(hisaddr, &dls.sdl)) {
- syslog(LOG_ERR, "Cannot determine ethernet address for proxy ARP");
- return 0;
- }
-
- arpreq.arp_ha.sa_len = sizeof(struct sockaddr);
- arpreq.arp_ha.sa_family = AF_UNSPEC;
- BCOPY(LLADDR(&dls.sdl), arpreq.arp_ha.sa_data, dls.sdl.sdl_alen);
- SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
- ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
- arpreq.arp_flags = ATF_PERM | ATF_PUBL;
- if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) {
- syslog(LOG_ERR, "Couldn't add proxy arp entry: %m");
- return 0;
- }
-
- proxy_arp_addr = hisaddr;
- return 1;
-}
-
-/*
- * cifproxyarp - Delete the proxy ARP entry for the peer.
- */
-int
-cifproxyarp(unit, hisaddr)
- int unit;
- u_int32_t hisaddr;
-{
- struct arpreq arpreq;
-
- BZERO(&arpreq, sizeof(arpreq));
- SET_SA_FAMILY(arpreq.arp_pa, AF_INET);
- ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr;
- if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) {
- syslog(LOG_WARNING, "Couldn't delete proxy arp entry: %m");
- return 0;
- }
- proxy_arp_addr = 0;
- return 1;
-}
-#endif /* RTM_VERSION */
-
-#ifdef IPX_CHANGE
-/********************************************************************
- *
- * sipxfaddr - Config the interface IPX networknumber
- */
-
-int
-sipxfaddr (int unit, unsigned long int network, unsigned char * node )
- {
- int result = 1;
-
- int skfd;
- struct sockaddr_ipx ipx_addr;
- struct ifreq ifr;
- struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
- union ipx_net_u net;
-
- skfd = socket (AF_IPX, SOCK_DGRAM, 0);
- if (skfd < 0)
- {
- syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
- result = 0;
- }
- else
- {
- memset (&ifr, '\0', sizeof (ifr));
- strcpy (ifr.ifr_name, ifname);
-
- memcpy (sipx->sipx_addr.x_host.c_host, node, 6);
- sipx->sipx_len = sizeof(sipx);
- sipx->sipx_family = AF_IPX;
- sipx->sipx_port = 0;
- memset(&net, 0, sizeof(net));
- net.long_e = htonl (network);
- sipx->sipx_addr.x_net = net.net_e;
-/*
- * Set the IPX device
- */
- if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
- {
- result = 0;
- if (errno != EEXIST)
- {
- syslog (LOG_DEBUG,
- "ioctl(SIOCAIFADDR, CRTITF): %m(%d)", errno);
- }
- else
- {
- syslog (LOG_WARNING,
- "ioctl(SIOCAIFADDR, CRTITF): Address already exists");
- }
- }
- close (skfd);
- }
- return result;
- }
-
-/********************************************************************
- *
- * cipxfaddr - Clear the information for the IPX network. The IPX routes
- * are removed and the device is no longer able to pass IPX
- * frames.
- */
-
-int cipxfaddr (int unit)
- {
- int result = 1;
-
- int skfd;
- struct sockaddr_ipx ipx_addr;
- struct ifreq ifr;
- struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &ifr.ifr_addr;
-
- skfd = socket (AF_IPX, SOCK_DGRAM, 0);
- if (skfd < 0)
- {
- syslog (LOG_DEBUG, "socket(AF_IPX): %m(%d)", errno);
- result = 0;
- }
- else
- {
- memset (&ifr, '\0', sizeof (ifr));
- strcpy (ifr.ifr_name, ifname);
-
- sipx->sipx_len = sizeof(sipx);
- sipx->sipx_family = AF_IPX;
-/*
- * Set the IPX device
- */
- if (ioctl(skfd, SIOCSIFADDR, (caddr_t) &ifr) < 0)
- {
- syslog (LOG_INFO,
- "ioctl(SIOCAIFADDR, IPX_DLTITF): %m(%d)", errno);
- result = 0;
- }
- close (skfd);
- }
- return result;
- }
-#endif
-
-/*
- * get_ether_addr - get the hardware address of an interface on the
- * the same subnet as ipaddr.
- */
-static int
-get_ether_addr(ipaddr, hwaddr)
- u_int32_t ipaddr;
- struct sockaddr_dl *hwaddr;
-{
- u_int32_t ina, mask;
- struct sockaddr_dl *dla;
- struct ifaddrs *ifap, *ifa, *ifp;
-
- /*
- * Scan through looking for an interface with an Internet
- * address on the same subnet as `ipaddr'.
- */
- if (getifaddrs(&ifap) != 0) {
- syslog(LOG_ERR, "getifaddrs: %m");
- return 0;
- }
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- if (ifa->ifa_addr->sa_family != AF_INET)
- continue;
- ina = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr.s_addr;
- /*
- * Check that the interface is up, and not point-to-point
- * or loopback.
- */
- if ((ifa->ifa_flags &
- (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP))
- != (IFF_UP|IFF_BROADCAST))
- continue;
- /*
- * Get its netmask and check that it's on the right subnet.
- */
- mask = ((struct sockaddr_in *) ifa->ifa_netmask)->sin_addr.s_addr;
- if ((ipaddr & mask) != (ina & mask))
- continue;
- break;
- }
- if (!ifa) {
- freeifaddrs(ifap);
- return 0;
- }
- syslog(LOG_INFO, "found interface %s for proxy arp", ifa->ifa_name);
-
- /*
- * Now scan through again looking for a link-level address
- * for this interface.
- */
- ifp = ifa;
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- if (strcmp(ifp->ifa_name, ifa->ifa_name) != 0)
- continue;
- if (ifa->ifa_addr->sa_family != AF_LINK)
- continue;
- /*
- * Found the link-level address - copy it out
- */
- dla = (struct sockaddr_dl *) ifa->ifa_addr;
- BCOPY(dla, hwaddr, dla->sdl_len);
- freeifaddrs(ifap);
- return 1;
- }
-
- freeifaddrs(ifap);
- return 0;
-}
-
-/*
- * Return user specified netmask, modified by any mask we might determine
- * for address `addr' (in network byte order).
- * Here we scan through the system's list of interfaces, looking for
- * any non-point-to-point interfaces which might appear to be on the same
- * network as `addr'. If we find any, we OR in their netmask to the
- * user-specified netmask.
- */
-u_int32_t
-GetMask(addr)
- u_int32_t addr;
-{
- u_int32_t mask, nmask, ina;
- struct ifaddrs *ifap, *ifa;
-
- addr = ntohl(addr);
- if (IN_CLASSA(addr)) /* determine network mask for address class */
- nmask = IN_CLASSA_NET;
- else if (IN_CLASSB(addr))
- nmask = IN_CLASSB_NET;
- else
- nmask = IN_CLASSC_NET;
- /* class D nets are disallowed by bad_ip_adrs */
- mask = netmask | htonl(nmask);
-
- /*
- * Scan through the system's network interfaces.
- */
- if (getifaddrs(&ifap) != 0) {
- syslog(LOG_WARNING, "getifaddrs: %m");
- return mask;
- }
- for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
- /*
- * Check the interface's internet address.
- */
- if (ifa->ifa_addr->sa_family != AF_INET)
- continue;
- ina = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
- if ((ntohl(ina) & nmask) != (addr & nmask))
- continue;
- /*
- * Check that the interface is up, and not point-to-point or loopback.
- */
- if ((ifa->ifa_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) != IFF_UP)
- continue;
- /*
- * Get its netmask and OR it into our mask.
- */
- mask |= ((struct sockaddr_in *)&ifa->ifa_netmask)->sin_addr.s_addr;
- }
-
- freeifaddrs(ifap);
- return mask;
-}
-
-/*
- * Use the hostid as part of the random number seed.
- */
-int
-get_host_seed()
-{
- return gethostid();
-}
-
-/*
- * lock - create a lock file for the named lock device
- */
-#define LOCK_PREFIX "/var/spool/lock/LCK.."
-
-int
-lock(dev)
- char *dev;
-{
- char hdb_lock_buffer[12];
- int fd, pid, n;
- char *p;
-
- if ((p = strrchr(dev, '/')) != NULL)
- dev = p + 1;
- lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1);
- if (lock_file == NULL)
- novm("lock file name");
- strcat(strcpy(lock_file, LOCK_PREFIX), dev);
-
- while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) {
- if (errno == EEXIST
- && (fd = open(lock_file, O_RDONLY, 0)) >= 0) {
- /* Read the lock file to find out who has the device locked */
- n = read(fd, hdb_lock_buffer, 11);
- if (n <= 0) {
- syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file);
- close(fd);
- } else {
- hdb_lock_buffer[n] = 0;
- pid = atoi(hdb_lock_buffer);
- if (kill(pid, 0) == -1 && errno == ESRCH) {
- /* pid no longer exists - remove the lock file */
- if (unlink(lock_file) == 0) {
- close(fd);
- syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)",
- dev, pid);
- continue;
- } else
- syslog(LOG_WARNING, "Couldn't remove stale lock on %s",
- dev);
- } else
- syslog(LOG_NOTICE, "Device %s is locked by pid %d",
- dev, pid);
- }
- close(fd);
- } else
- syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file);
- free(lock_file);
- lock_file = NULL;
- return -1;
- }
-
- sprintf(hdb_lock_buffer, "%10d\n", getpid());
- write(fd, hdb_lock_buffer, 11);
-
- close(fd);
- return 0;
-}
-
-/*
- * unlock - remove our lockfile
- */
-void
-unlock()
-{
- if (lock_file) {
- unlink(lock_file);
- free(lock_file);
- lock_file = NULL;
- }
-}
diff --git a/usr.sbin/pppd/upap.c b/usr.sbin/pppd/upap.c
deleted file mode 100644
index af25a58..0000000
--- a/usr.sbin/pppd/upap.c
+++ /dev/null
@@ -1,618 +0,0 @@
-/*
- * upap.c - User/Password Authentication Protocol.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-/*
- * TODO:
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <syslog.h>
-
-#include "pppd.h"
-#include "upap.h"
-
-/*
- * Protocol entry points.
- */
-static void upap_init(int);
-static void upap_lowerup(int);
-static void upap_lowerdown(int);
-static void upap_input(int, u_char *, int);
-static void upap_protrej(int);
-static int upap_printpkt(u_char *, int,
- void (*)(void *, char *, ...), void *);
-
-struct protent pap_protent = {
- PPP_PAP,
- upap_init,
- upap_input,
- upap_protrej,
- upap_lowerup,
- upap_lowerdown,
- NULL,
- NULL,
- upap_printpkt,
- NULL,
- 1,
- "PAP",
- NULL,
- NULL,
- NULL
-};
-
-upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */
-
-static void upap_timeout(void *);
-static void upap_reqtimeout(void *);
-static void upap_rauthreq(upap_state *, u_char *, int, int);
-static void upap_rauthack(upap_state *, u_char *, int, int);
-static void upap_rauthnak(upap_state *, u_char *, int, int);
-static void upap_sauthreq(upap_state *);
-static void upap_sresp(upap_state *, int, int, char *, int);
-
-
-/*
- * upap_init - Initialize a UPAP unit.
- */
-static void
-upap_init(unit)
- int unit;
-{
- upap_state *u = &upap[unit];
-
- u->us_unit = unit;
- u->us_user = NULL;
- u->us_userlen = 0;
- u->us_passwd = NULL;
- u->us_passwdlen = 0;
- u->us_clientstate = UPAPCS_INITIAL;
- u->us_serverstate = UPAPSS_INITIAL;
- u->us_id = 0;
- u->us_timeouttime = UPAP_DEFTIMEOUT;
- u->us_maxtransmits = 10;
- u->us_reqtimeout = UPAP_DEFREQTIME;
-}
-
-
-/*
- * upap_authwithpeer - Authenticate us with our peer (start client).
- *
- * Set new state and send authenticate's.
- */
-void
-upap_authwithpeer(unit, user, password)
- int unit;
- char *user, *password;
-{
- upap_state *u = &upap[unit];
-
- /* Save the username and password we're given */
- u->us_user = user;
- u->us_userlen = strlen(user);
- u->us_passwd = password;
- u->us_passwdlen = strlen(password);
- u->us_transmits = 0;
-
- /* Lower layer up yet? */
- if (u->us_clientstate == UPAPCS_INITIAL ||
- u->us_clientstate == UPAPCS_PENDING) {
- u->us_clientstate = UPAPCS_PENDING;
- return;
- }
-
- upap_sauthreq(u); /* Start protocol */
-}
-
-
-/*
- * upap_authpeer - Authenticate our peer (start server).
- *
- * Set new state.
- */
-void
-upap_authpeer(unit)
- int unit;
-{
- upap_state *u = &upap[unit];
-
- /* Lower layer up yet? */
- if (u->us_serverstate == UPAPSS_INITIAL ||
- u->us_serverstate == UPAPSS_PENDING) {
- u->us_serverstate = UPAPSS_PENDING;
- return;
- }
-
- u->us_serverstate = UPAPSS_LISTEN;
- if (u->us_reqtimeout > 0)
- TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
-}
-
-
-/*
- * upap_timeout - Retransmission timer for sending auth-reqs expired.
- */
-static void
-upap_timeout(arg)
- void *arg;
-{
- upap_state *u = (upap_state *) arg;
-
- if (u->us_clientstate != UPAPCS_AUTHREQ)
- return;
-
- if (u->us_transmits >= u->us_maxtransmits) {
- /* give up in disgust */
- syslog(LOG_ERR, "No response to PAP authenticate-requests");
- u->us_clientstate = UPAPCS_BADAUTH;
- auth_withpeer_fail(u->us_unit, PPP_PAP);
- return;
- }
-
- upap_sauthreq(u); /* Send Authenticate-Request */
-}
-
-
-/*
- * upap_reqtimeout - Give up waiting for the peer to send an auth-req.
- */
-static void
-upap_reqtimeout(arg)
- void *arg;
-{
- upap_state *u = (upap_state *) arg;
-
- if (u->us_serverstate != UPAPSS_LISTEN)
- return; /* huh?? */
-
- auth_peer_fail(u->us_unit, PPP_PAP);
- u->us_serverstate = UPAPSS_BADAUTH;
-}
-
-
-/*
- * upap_lowerup - The lower layer is up.
- *
- * Start authenticating if pending.
- */
-static void
-upap_lowerup(unit)
- int unit;
-{
- upap_state *u = &upap[unit];
-
- if (u->us_clientstate == UPAPCS_INITIAL)
- u->us_clientstate = UPAPCS_CLOSED;
- else if (u->us_clientstate == UPAPCS_PENDING) {
- upap_sauthreq(u); /* send an auth-request */
- }
-
- if (u->us_serverstate == UPAPSS_INITIAL)
- u->us_serverstate = UPAPSS_CLOSED;
- else if (u->us_serverstate == UPAPSS_PENDING) {
- u->us_serverstate = UPAPSS_LISTEN;
- if (u->us_reqtimeout > 0)
- TIMEOUT(upap_reqtimeout, u, u->us_reqtimeout);
- }
-}
-
-
-/*
- * upap_lowerdown - The lower layer is down.
- *
- * Cancel all timeouts.
- */
-static void
-upap_lowerdown(unit)
- int unit;
-{
- upap_state *u = &upap[unit];
-
- if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */
- UNTIMEOUT(upap_timeout, u); /* Cancel timeout */
- if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0)
- UNTIMEOUT(upap_reqtimeout, u);
-
- u->us_clientstate = UPAPCS_INITIAL;
- u->us_serverstate = UPAPSS_INITIAL;
-}
-
-
-/*
- * upap_protrej - Peer doesn't speak this protocol.
- *
- * This shouldn't happen. In any case, pretend lower layer went down.
- */
-static void
-upap_protrej(unit)
- int unit;
-{
- upap_state *u = &upap[unit];
-
- if (u->us_clientstate == UPAPCS_AUTHREQ) {
- syslog(LOG_ERR, "PAP authentication failed due to protocol-reject");
- auth_withpeer_fail(unit, PPP_PAP);
- }
- if (u->us_serverstate == UPAPSS_LISTEN) {
- syslog(LOG_ERR, "PAP authentication of peer failed (protocol-reject)");
- auth_peer_fail(unit, PPP_PAP);
- }
- upap_lowerdown(unit);
-}
-
-
-/*
- * upap_input - Input UPAP packet.
- */
-static void
-upap_input(unit, inpacket, l)
- int unit;
- u_char *inpacket;
- int l;
-{
- upap_state *u = &upap[unit];
- u_char *inp;
- u_char code, id;
- int len;
-
- /*
- * Parse header (code, id and length).
- * If packet too short, drop it.
- */
- inp = inpacket;
- if (l < UPAP_HEADERLEN) {
- UPAPDEBUG((LOG_INFO, "pap_input: rcvd short header."));
- return;
- }
- GETCHAR(code, inp);
- GETCHAR(id, inp);
- GETSHORT(len, inp);
- if (len < UPAP_HEADERLEN) {
- UPAPDEBUG((LOG_INFO, "pap_input: rcvd illegal length."));
- return;
- }
- if (len > l) {
- UPAPDEBUG((LOG_INFO, "pap_input: rcvd short packet."));
- return;
- }
- len -= UPAP_HEADERLEN;
-
- /*
- * Action depends on code.
- */
- switch (code) {
- case UPAP_AUTHREQ:
- upap_rauthreq(u, inp, id, len);
- break;
-
- case UPAP_AUTHACK:
- upap_rauthack(u, inp, id, len);
- break;
-
- case UPAP_AUTHNAK:
- upap_rauthnak(u, inp, id, len);
- break;
-
- default: /* XXX Need code reject */
- break;
- }
-}
-
-
-/*
- * upap_rauth - Receive Authenticate.
- */
-static void
-upap_rauthreq(u, inp, id, len)
- upap_state *u;
- u_char *inp;
- int id;
- int len;
-{
- u_char ruserlen, rpasswdlen;
- char *ruser, *rpasswd;
- int retcode;
- char *msg;
- int msglen;
-
- UPAPDEBUG((LOG_INFO, "pap_rauth: Rcvd id %d.", id));
-
- if (u->us_serverstate < UPAPSS_LISTEN)
- return;
-
- /*
- * If we receive a duplicate authenticate-request, we are
- * supposed to return the same status as for the first request.
- */
- if (u->us_serverstate == UPAPSS_OPEN) {
- upap_sresp(u, UPAP_AUTHACK, id, "", 0); /* return auth-ack */
- return;
- }
- if (u->us_serverstate == UPAPSS_BADAUTH) {
- upap_sresp(u, UPAP_AUTHNAK, id, "", 0); /* return auth-nak */
- return;
- }
-
- /*
- * Parse user/passwd.
- */
- if (len < sizeof (u_char)) {
- UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet."));
- return;
- }
- GETCHAR(ruserlen, inp);
- len -= sizeof (u_char) + ruserlen + sizeof (u_char);
- if (len < 0) {
- UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet."));
- return;
- }
- ruser = (char *) inp;
- INCPTR(ruserlen, inp);
- GETCHAR(rpasswdlen, inp);
- if (len < rpasswdlen) {
- UPAPDEBUG((LOG_INFO, "pap_rauth: rcvd short packet."));
- return;
- }
- rpasswd = (char *) inp;
-
- /*
- * Check the username and password given.
- */
- retcode = check_passwd(u->us_unit, ruser, ruserlen, rpasswd,
- rpasswdlen, &msg, &msglen);
- BZERO(rpasswd, rpasswdlen);
-
- upap_sresp(u, retcode, id, msg, msglen);
-
- if (retcode == UPAP_AUTHACK) {
- u->us_serverstate = UPAPSS_OPEN;
- auth_peer_success(u->us_unit, PPP_PAP, ruser, ruserlen);
- } else {
- u->us_serverstate = UPAPSS_BADAUTH;
- auth_peer_fail(u->us_unit, PPP_PAP);
- }
-
- if (u->us_reqtimeout > 0)
- UNTIMEOUT(upap_reqtimeout, u);
-}
-
-
-/*
- * upap_rauthack - Receive Authenticate-Ack.
- */
-static void
-upap_rauthack(u, inp, id, len)
- upap_state *u;
- u_char *inp;
- int id;
- int len;
-{
- u_char msglen;
- char *msg;
-
- UPAPDEBUG((LOG_INFO, "pap_rauthack: Rcvd id %d.", id));
- if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
- return;
-
- /*
- * Parse message.
- */
- if (len < sizeof (u_char)) {
- UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet."));
- return;
- }
- GETCHAR(msglen, inp);
- len -= sizeof (u_char);
- if (len < msglen) {
- UPAPDEBUG((LOG_INFO, "pap_rauthack: rcvd short packet."));
- return;
- }
- msg = (char *) inp;
- PRINTMSG(msg, msglen);
-
- u->us_clientstate = UPAPCS_OPEN;
-
- auth_withpeer_success(u->us_unit, PPP_PAP);
-}
-
-
-/*
- * upap_rauthnak - Receive Authenticate-Nakk.
- */
-static void
-upap_rauthnak(u, inp, id, len)
- upap_state *u;
- u_char *inp;
- int id;
- int len;
-{
- u_char msglen;
- char *msg;
-
- UPAPDEBUG((LOG_INFO, "pap_rauthnak: Rcvd id %d.", id));
- if (u->us_clientstate != UPAPCS_AUTHREQ) /* XXX */
- return;
-
- /*
- * Parse message.
- */
- if (len < sizeof (u_char)) {
- UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet."));
- return;
- }
- GETCHAR(msglen, inp);
- len -= sizeof (u_char);
- if (len < msglen) {
- UPAPDEBUG((LOG_INFO, "pap_rauthnak: rcvd short packet."));
- return;
- }
- msg = (char *) inp;
- PRINTMSG(msg, msglen);
-
- u->us_clientstate = UPAPCS_BADAUTH;
-
- syslog(LOG_ERR, "PAP authentication failed");
- auth_withpeer_fail(u->us_unit, PPP_PAP);
-}
-
-
-/*
- * upap_sauthreq - Send an Authenticate-Request.
- */
-static void
-upap_sauthreq(u)
- upap_state *u;
-{
- u_char *outp;
- int outlen;
-
- outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) +
- u->us_userlen + u->us_passwdlen;
- outp = outpacket_buf;
-
- MAKEHEADER(outp, PPP_PAP);
-
- PUTCHAR(UPAP_AUTHREQ, outp);
- PUTCHAR(++u->us_id, outp);
- PUTSHORT(outlen, outp);
- PUTCHAR(u->us_userlen, outp);
- BCOPY(u->us_user, outp, u->us_userlen);
- INCPTR(u->us_userlen, outp);
- PUTCHAR(u->us_passwdlen, outp);
- BCOPY(u->us_passwd, outp, u->us_passwdlen);
-
- output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
-
- UPAPDEBUG((LOG_INFO, "pap_sauth: Sent id %d.", u->us_id));
-
- TIMEOUT(upap_timeout, u, u->us_timeouttime);
- ++u->us_transmits;
- u->us_clientstate = UPAPCS_AUTHREQ;
-}
-
-
-/*
- * upap_sresp - Send a response (ack or nak).
- */
-static void
-upap_sresp(u, code, id, msg, msglen)
- upap_state *u;
- u_char code, id;
- char *msg;
- int msglen;
-{
- u_char *outp;
- int outlen;
-
- outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen;
- outp = outpacket_buf;
- MAKEHEADER(outp, PPP_PAP);
-
- PUTCHAR(code, outp);
- PUTCHAR(id, outp);
- PUTSHORT(outlen, outp);
- PUTCHAR(msglen, outp);
- BCOPY(msg, outp, msglen);
- output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN);
-
- UPAPDEBUG((LOG_INFO, "pap_sresp: Sent code %d, id %d.", code, id));
-}
-
-/*
- * upap_printpkt - print the contents of a PAP packet.
- */
-static char *upap_codenames[] = {
- "AuthReq", "AuthAck", "AuthNak"
-};
-
-static int
-upap_printpkt(p, plen, printer, arg)
- u_char *p;
- int plen;
- void (*printer)(void *, char *, ...);
- void *arg;
-{
- int code, id, len;
- int mlen, ulen, wlen;
- char *user, *pwd, *msg;
- u_char *pstart;
-
- if (plen < UPAP_HEADERLEN)
- return 0;
- pstart = p;
- GETCHAR(code, p);
- GETCHAR(id, p);
- GETSHORT(len, p);
- if (len < UPAP_HEADERLEN || len > plen)
- return 0;
-
- if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *))
- printer(arg, " %s", upap_codenames[code-1]);
- else
- printer(arg, " code=0x%x", code);
- printer(arg, " id=0x%x", id);
- len -= UPAP_HEADERLEN;
- switch (code) {
- case UPAP_AUTHREQ:
- if (len < 1)
- break;
- ulen = p[0];
- if (len < ulen + 2)
- break;
- wlen = p[ulen + 1];
- if (len < ulen + wlen + 2)
- break;
- user = (char *) (p + 1);
- pwd = (char *) (p + ulen + 2);
- p += ulen + wlen + 2;
- len -= ulen + wlen + 2;
- printer(arg, " user=");
- print_string(user, ulen, printer, arg);
- printer(arg, " password=");
- print_string(pwd, wlen, printer, arg);
- break;
- case UPAP_AUTHACK:
- case UPAP_AUTHNAK:
- if (len < 1)
- break;
- mlen = p[0];
- if (len < mlen + 1)
- break;
- msg = (char *) (p + 1);
- p += mlen + 1;
- len -= mlen + 1;
- printer(arg, " ");
- print_string(msg, mlen, printer, arg);
- break;
- }
-
- /* print the rest of the bytes in the packet */
- for (; len > 0; --len) {
- GETCHAR(code, p);
- printer(arg, " %.2x", code);
- }
-
- return p - pstart;
-}
diff --git a/usr.sbin/pppd/upap.h b/usr.sbin/pppd/upap.h
deleted file mode 100644
index 82ce604..0000000
--- a/usr.sbin/pppd/upap.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * upap.h - User/Password Authentication Protocol definitions.
- *
- * Copyright (c) 1989 Carnegie Mellon University.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by Carnegie Mellon University. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
- */
-
-/*
- * Packet header = Code, id, length.
- */
-#define UPAP_HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short))
-
-
-/*
- * UPAP codes.
- */
-#define UPAP_AUTHREQ 1 /* Authenticate-Request */
-#define UPAP_AUTHACK 2 /* Authenticate-Ack */
-#define UPAP_AUTHNAK 3 /* Authenticate-Nak */
-
-
-/*
- * Each interface is described by upap structure.
- */
-typedef struct upap_state {
- int us_unit; /* Interface unit number */
- char *us_user; /* User */
- int us_userlen; /* User length */
- char *us_passwd; /* Password */
- int us_passwdlen; /* Password length */
- int us_clientstate; /* Client state */
- int us_serverstate; /* Server state */
- u_char us_id; /* Current id */
- int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */
- int us_transmits; /* Number of auth-reqs sent */
- int us_maxtransmits; /* Maximum number of auth-reqs to send */
- int us_reqtimeout; /* Time to wait for auth-req from peer */
-} upap_state;
-
-
-/*
- * Client states.
- */
-#define UPAPCS_INITIAL 0 /* Connection down */
-#define UPAPCS_CLOSED 1 /* Connection up, haven't requested auth */
-#define UPAPCS_PENDING 2 /* Connection down, have requested auth */
-#define UPAPCS_AUTHREQ 3 /* We've sent an Authenticate-Request */
-#define UPAPCS_OPEN 4 /* We've received an Ack */
-#define UPAPCS_BADAUTH 5 /* We've received a Nak */
-
-/*
- * Server states.
- */
-#define UPAPSS_INITIAL 0 /* Connection down */
-#define UPAPSS_CLOSED 1 /* Connection up, haven't requested auth */
-#define UPAPSS_PENDING 2 /* Connection down, have requested auth */
-#define UPAPSS_LISTEN 3 /* Listening for an Authenticate */
-#define UPAPSS_OPEN 4 /* We've sent an Ack */
-#define UPAPSS_BADAUTH 5 /* We've sent a Nak */
-
-
-/*
- * Timeouts.
- */
-#define UPAP_DEFTIMEOUT 3 /* Timeout (seconds) for retransmitting req */
-#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */
-
-extern upap_state upap[];
-
-void upap_authwithpeer(int, char *, char *);
-void upap_authpeer(int);
-
-extern struct protent pap_protent;
diff --git a/usr.sbin/pppstats/Makefile b/usr.sbin/pppstats/Makefile
deleted file mode 100644
index da34dc9..0000000
--- a/usr.sbin/pppstats/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-# $FreeBSD$
-
-PROG= pppstats
-MAN= pppstats.8
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/pppstats/pppstats.8 b/usr.sbin/pppstats/pppstats.8
deleted file mode 100644
index 5b28ea0..0000000
--- a/usr.sbin/pppstats/pppstats.8
+++ /dev/null
@@ -1,218 +0,0 @@
-.\" @(#) $FreeBSD$
-.TH PPPSTATS 8 "26 June 1995"
-.SH NAME
-pppstats \- print PPP statistics
-.SH SYNOPSIS
-.B pppstats
-[
-.B -a
-] [
-.B -v
-] [
-.B -r
-] [
-.B -z
-] [
-.B -c
-.I <count>
-] [
-.B -w
-.I <secs>
-] [
-.I interface
-]
-.ti 12
-.SH DESCRIPTION
-The
-.B pppstats
-utility reports PPP-related statistics at regular intervals for the
-specified PPP interface. If the interface is unspecified, it will
-default to ppp0.
-The display is split horizontally
-into input and output sections containing columns of statistics
-describing the properties and volume of packets received and
-transmitted by the interface.
-.PP
-The options are as follows:
-.TP
-.B -a
-Display absolute values rather than deltas. With this option, all
-reports show statistics for the time since the link was initiated.
-Without this option, the second and subsequent reports show statistics
-for the time since the last report.
-.TP
-.B -c \fIcount
-Repeat the display
-.I count
-times. If this option is not specified, the default repeat count is 1
-if the
-.B -w
-option is not specified, otherwise infinity.
-.TP
-.B -r
-Display additional statistics summarizing the compression ratio
-achieved by the packet compression algorithm in use.
-.TP
-.B -v
-Display additional statistics relating to the performance of the Van
-Jacobson TCP header compression algorithm.
-.TP
-.B -w \fIwait
-Pause
-.I wait
-seconds between each display. If this option is not specified, the
-default interval is 5 seconds.
-.TP
-.B -z
-Instead of the standard display, show statistics indicating the
-performance of the packet compression algorithm in use.
-.PP
-The following fields are printed on the input side when the
-.B -z
-option is not used:
-.TP
-.B IN
-The total number of bytes received by this interface.
-.TP
-.B PACK
-The total number of packets received by this interface.
-.TP
-.B VJCOMP
-The number of header-compressed TCP packets received by this interface.
-.TP
-.B VJUNC
-The number of header-uncompressed TCP packets received by this
-interface. Not reported when the
-.B -r
-option is specified.
-.TP
-.B VJERR
-The number of corrupted or bogus header-compressed TCP packets
-received by this interface. Not reported when the
-.B -r
-option is specified.
-.TP
-.B VJTOSS
-The number of VJ header-compressed TCP packets dropped on reception by
-this interface because of preceding errors. Only reported when the
-.B -v
-option is specified.
-.TP
-.B NON-VJ
-The total number of non-TCP packets received by this interface.
-Only
-reported when the
-.B -v
-option is specified.
-.TP
-.B RATIO
-The compression ratio achieved for received packets by the
-packet compression scheme in use, defined as the uncompressed size
-divided by the compressed size.
-Only reported when the
-.B -r
-option is specified.
-.TP
-.B UBYTE
-The total number of bytes received, after decompression of compressed
-packets. Only reported when the
-.B -r
-option is specified.
-.PP
-The following fields are printed on the output side:
-.TP
-.B OUT
-The total number of bytes transmitted from this interface.
-.TP
-.B PACK
-The total number of packets transmitted from this interface.
-.TP
-.B VJCOMP
-The number of TCP packets transmitted from this interface with
-VJ-compressed TCP headers.
-.TP
-.B VJUNC
-The number of TCP packets transmitted from this interface with
-VJ-uncompressed TCP headers.
-Not reported when the
-.B -r
-option is specified.
-.TP
-.B NON-VJ
-The total number of non-TCP packets transmitted from this interface.
-Not reported when the
-.B -r
-option is specified.
-.TP
-.B VJSRCH
-The number of searches for the cached header entry for a VJ header
-compressed TCP packet. Only reported when the
-.B -v
-option is specified.
-.TP
-.B VJMISS
-The number of failed searches for the cached header entry for a
-VJ header compressed TCP packet. Only reported when the
-.B -v
-option is specified.
-.TP
-.B RATIO
-The compression ratio achieved for transmitted packets by the
-packet compression scheme in use, defined as the size
-before compression divided by the compressed size.
-Only reported when the
-.B -r
-option is specified.
-.TP
-.B UBYTE
-The total number of bytes to be transmitted, before packet compression
-is applied. Only reported when the
-.B -r
-option is specified.
-.PP
-When the
-.B -z
-option is specified,
-.B pppstats
-instead displays the following fields, relating to the packet
-compression algorithm currently in use. If packet compression is not
-in use, these fields will all display zeroes. The fields displayed on
-the input side are:
-.TP
-.B COMPRESSED BYTE
-The number of bytes of compressed packets received.
-.TP
-.B COMPRESSED PACK
-The number of compressed packets received.
-.TP
-.B INCOMPRESSIBLE BYTE
-The number of bytes of incompressible packets (that is, those which
-were transmitted in uncompressed form) received.
-.TP
-.B INCOMPRESSIBLE PACK
-The number of incompressible packets received.
-.TP
-.B COMP RATIO
-The recent compression ratio for incoming packets, defined as the
-uncompressed size divided by the compressed size (including both
-compressible and incompressible packets).
-.PP
-The fields displayed on the output side are:
-.TP
-.B COMPRESSED BYTE
-The number of bytes of compressed packets transmitted.
-.TP
-.B COMPRESSED PACK
-The number of compressed packets transmitted.
-.TP
-.B INCOMPRESSIBLE BYTE
-The number of bytes of incompressible packets transmitted (that is,
-those which were transmitted in uncompressed form).
-.TP
-.B INCOMPRESSIBLE PACK
-The number of incompressible packets transmitted.
-.TP
-.B COMP RATIO
-The recent compression ratio for outgoing packets.
-.SH SEE ALSO
-pppd(8)
diff --git a/usr.sbin/pppstats/pppstats.c b/usr.sbin/pppstats/pppstats.c
deleted file mode 100644
index b9d5a09..0000000
--- a/usr.sbin/pppstats/pppstats.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * print PPP statistics:
- * pppstats [-a|-d] [-v|-r|-z] [-c count] [-w wait] [interface]
- *
- * -a Show absolute values rather than deltas
- * -d Show data rate (kB/s) rather than bytes
- * -v Show more stats for VJ TCP header compression
- * -r Show compression ratio
- * -z Show compression statistics instead of default display
- *
- * History:
- * perkins@cps.msu.edu: Added compression statistics and alternate
- * display. 11/94
- * Brad Parker (brad@cayman.com) 6/92
- *
- * from the original "slstats" by Van Jacobson
- *
- * Copyright (c) 1989 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef lint
-static char rcsid[] = "$FreeBSD$";
-#endif
-
-#include <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <signal.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <net/ppp_defs.h>
-
-#ifndef STREAMS
-#include <sys/socket.h> /* *BSD, Linux, NeXT, Ultrix etc. */
-#include <net/if.h>
-#include <net/if_ppp.h>
-
-#else /* STREAMS */
-#include <sys/stropts.h> /* SVR4, Solaris 2, SunOS 4, OSF/1, etc. */
-#include <net/pppio.h>
-
-#endif /* STREAMS */
-
-int vflag, rflag, zflag; /* select type of display */
-int aflag; /* print absolute values, not deltas */
-int dflag; /* print data rates, not bytes */
-int interval, count;
-int infinite;
-int unit;
-int s; /* socket or /dev/ppp file descriptor */
-int signalled; /* set if alarm goes off "early" */
-char *progname;
-char *interface;
-
-#if defined(SUNOS4) || defined(ULTRIX) || defined(NeXT)
-extern int optind;
-extern char *optarg;
-#endif
-
-static void usage(void);
-static void catchalarm(int);
-static void get_ppp_stats(struct ppp_stats *);
-static void get_ppp_cstats(struct ppp_comp_stats *);
-static void intpr(void);
-
-int main(int, char *argv[]);
-
-static void
-usage()
-{
- fprintf(stderr, "usage: %s [-a|-d] [-v|-r|-z] [-c count] [-w wait] [interface]\n",
- progname);
- exit(1);
-}
-
-/*
- * Called if an interval expires before intpr has completed a loop.
- * Sets a flag to not wait for the alarm.
- */
-static void
-catchalarm(arg)
- int arg;
-{
- signalled = 1;
-}
-
-
-#ifndef STREAMS
-static void
-get_ppp_stats(curp)
- struct ppp_stats *curp;
-{
- struct ifpppstatsreq req;
-
- memset (&req, 0, sizeof (req));
-
-#ifdef _linux_
- req.stats_ptr = (caddr_t) &req.stats;
-#undef ifr_name
-#define ifr_name ifr__name
-#endif
-
- strncpy(req.ifr_name, interface, sizeof(req.ifr_name));
- if (ioctl(s, SIOCGPPPSTATS, &req) < 0) {
- fprintf(stderr, "%s: ", progname);
- if (errno == ENOTTY)
- fprintf(stderr, "kernel support missing\n");
- else
- perror("couldn't get PPP statistics");
- exit(1);
- }
- *curp = req.stats;
-}
-
-static void
-get_ppp_cstats(csp)
- struct ppp_comp_stats *csp;
-{
- struct ifpppcstatsreq creq;
-
- memset (&creq, 0, sizeof (creq));
-
-#ifdef _linux_
- creq.stats_ptr = (caddr_t) &creq.stats;
-#undef ifr_name
-#define ifr_name ifr__name
-#endif
-
- strncpy(creq.ifr_name, interface, sizeof(creq.ifr_name));
- if (ioctl(s, SIOCGPPPCSTATS, &creq) < 0) {
- fprintf(stderr, "%s: ", progname);
- if (errno == ENOTTY) {
- fprintf(stderr, "no kernel compression support\n");
- if (zflag)
- exit(1);
- rflag = 0;
- } else {
- perror("couldn't get PPP compression stats");
- exit(1);
- }
- }
-
-#ifdef _linux_
- if (creq.stats.c.bytes_out == 0)
- creq.stats.c.ratio = 0.0;
- else
- creq.stats.c.ratio = (double) creq.stats.c.in_count /
- (double) creq.stats.c.bytes_out;
-
- if (creq.stats.d.bytes_out == 0)
- creq.stats.d.ratio = 0.0;
- else
- creq.stats.d.ratio = (double) creq.stats.d.in_count /
- (double) creq.stats.d.bytes_out;
-#endif
-
- *csp = creq.stats;
-}
-
-#else /* STREAMS */
-
-int
-strioctl(fd, cmd, ptr, ilen, olen)
- int fd, cmd, ilen, olen;
- char *ptr;
-{
- struct strioctl str;
-
- str.ic_cmd = cmd;
- str.ic_timout = 0;
- str.ic_len = ilen;
- str.ic_dp = ptr;
- if (ioctl(fd, I_STR, &str) == -1)
- return -1;
- if (str.ic_len != olen)
- fprintf(stderr, "strioctl: expected %d bytes, got %d for cmd %x\n",
- olen, str.ic_len, cmd);
- return 0;
-}
-
-static void
-get_ppp_stats(curp)
- struct ppp_stats *curp;
-{
- if (strioctl(s, PPPIO_GETSTAT, curp, 0, sizeof(*curp)) < 0) {
- fprintf(stderr, "%s: ", progname);
- if (errno == EINVAL)
- fprintf(stderr, "kernel support missing\n");
- else
- perror("couldn't get PPP statistics");
- exit(1);
- }
-}
-
-static void
-get_ppp_cstats(csp)
- struct ppp_comp_stats *csp;
-{
- if (strioctl(s, PPPIO_GETCSTAT, csp, 0, sizeof(*csp)) < 0) {
- fprintf(stderr, "%s: ", progname);
- if (errno == ENOTTY) {
- fprintf(stderr, "no kernel compression support\n");
- if (zflag)
- exit(1);
- rflag = 0;
- } else {
- perror("couldn't get PPP compression statistics");
- exit(1);
- }
- }
-}
-
-#endif /* STREAMS */
-
-#define MAX0(a) ((int)(a) > 0? (a): 0)
-#define V(offset) MAX0(cur.offset - old.offset)
-#define W(offset) MAX0(ccs.offset - ocs.offset)
-
-#define RATIO(c, i, u) ((c) == 0? 1.0: (u) / ((double)(c) + (i)))
-#define CRATE(x) RATIO(W(x.comp_bytes), W(x.inc_bytes), W(x.unc_bytes))
-
-#define KBPS(n) ((n) / (interval * 1000.0))
-
-/*
- * Print a running summary of interface statistics.
- * Repeat display every interval seconds, showing statistics
- * collected over that interval. Assumes that interval is non-zero.
- * First line printed is cumulative.
- */
-static void
-intpr()
-{
- register int line = 0;
- sigset_t oldmask, mask;
- char *bunit;
- int ratef = 0;
- struct ppp_stats cur, old;
- struct ppp_comp_stats ccs, ocs;
-
- memset(&old, 0, sizeof(old));
- memset(&ocs, 0, sizeof(ocs));
-
- while (1) {
- get_ppp_stats(&cur);
- if (zflag || rflag)
- get_ppp_cstats(&ccs);
-
- (void)signal(SIGALRM, catchalarm);
- signalled = 0;
- (void)alarm(interval);
-
- if ((line % 20) == 0) {
- if (zflag) {
- printf("IN: COMPRESSED INCOMPRESSIBLE COMP | ");
- printf("OUT: COMPRESSED INCOMPRESSIBLE COMP\n");
- bunit = dflag? "KB/S": "BYTE";
- printf(" %s PACK %s PACK RATIO | ", bunit, bunit);
- printf(" %s PACK %s PACK RATIO", bunit, bunit);
- } else {
- printf("%8.8s %6.6s %6.6s",
- "IN", "PACK", "VJCOMP");
-
- if (!rflag)
- printf(" %6.6s %6.6s", "VJUNC", "VJERR");
- if (vflag)
- printf(" %6.6s %6.6s", "VJTOSS", "NON-VJ");
- if (rflag)
- printf(" %6.6s %6.6s", "RATIO", "UBYTE");
- printf(" | %8.8s %6.6s %6.6s",
- "OUT", "PACK", "VJCOMP");
-
- if (!rflag)
- printf(" %6.6s %6.6s", "VJUNC", "NON-VJ");
- if (vflag)
- printf(" %6.6s %6.6s", "VJSRCH", "VJMISS");
- if (rflag)
- printf(" %6.6s %6.6s", "RATIO", "UBYTE");
- }
- putchar('\n');
- }
-
- if (zflag) {
- if (ratef) {
- printf("%8.3f %6u %8.3f %6u %6.2f",
- KBPS(W(d.comp_bytes)),
- W(d.comp_packets),
- KBPS(W(d.inc_bytes)),
- W(d.inc_packets),
- ccs.d.ratio / 256.0);
- printf(" | %8.3f %6u %8.3f %6u %6.2f",
- KBPS(W(c.comp_bytes)),
- W(c.comp_packets),
- KBPS(W(c.inc_bytes)),
- W(c.inc_packets),
- ccs.c.ratio / 256.0);
- } else {
- printf("%8u %6u %8u %6u %6.2f",
- W(d.comp_bytes),
- W(d.comp_packets),
- W(d.inc_bytes),
- W(d.inc_packets),
- ccs.d.ratio / 256.0);
- printf(" | %8u %6u %8u %6u %6.2f",
- W(c.comp_bytes),
- W(c.comp_packets),
- W(c.inc_bytes),
- W(c.inc_packets),
- ccs.c.ratio / 256.0);
- }
-
- } else {
- if (ratef)
- printf("%8.3f", KBPS(V(p.ppp_ibytes)));
- else
- printf("%8u", V(p.ppp_ibytes));
- printf(" %6u %6u",
- V(p.ppp_ipackets),
- V(vj.vjs_compressedin));
- if (!rflag)
- printf(" %6u %6u",
- V(vj.vjs_uncompressedin),
- V(vj.vjs_errorin));
- if (vflag)
- printf(" %6u %6u",
- V(vj.vjs_tossed),
- V(p.ppp_ipackets) - V(vj.vjs_compressedin)
- - V(vj.vjs_uncompressedin) - V(vj.vjs_errorin));
- if (rflag) {
- printf(" %6.2f ", CRATE(d));
- if (ratef)
- printf("%6.2f", KBPS(W(d.unc_bytes)));
- else
- printf("%6u", W(d.unc_bytes));
- }
- if (ratef)
- printf(" | %8.3f", KBPS(V(p.ppp_obytes)));
- else
- printf(" | %8u", V(p.ppp_obytes));
- printf(" %6u %6u",
- V(p.ppp_opackets),
- V(vj.vjs_compressed));
- if (!rflag)
- printf(" %6u %6u",
- V(vj.vjs_packets) - V(vj.vjs_compressed),
- V(p.ppp_opackets) - V(vj.vjs_packets));
- if (vflag)
- printf(" %6u %6u",
- V(vj.vjs_searches),
- V(vj.vjs_misses));
- if (rflag) {
- printf(" %6.2f ", CRATE(c));
- if (ratef)
- printf("%6.2f", KBPS(W(c.unc_bytes)));
- else
- printf("%6u", W(c.unc_bytes));
- }
-
- }
-
- putchar('\n');
- fflush(stdout);
- line++;
-
- count--;
- if (!infinite && !count)
- break;
-
- sigemptyset(&mask);
- sigaddset(&mask, SIGALRM);
- sigprocmask(SIG_BLOCK, &mask, &oldmask);
- if (!signalled) {
- sigemptyset(&mask);
- sigsuspend(&mask);
- }
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
- signalled = 0;
- (void)alarm(interval);
-
- if (!aflag) {
- old = cur;
- ocs = ccs;
- ratef = dflag;
- }
- }
-}
-
-int
-main(argc, argv)
- int argc;
- char *argv[];
-{
- int c;
-#ifdef STREAMS
- char *dev;
-#endif
-
- interface = "ppp0";
- if ((progname = strrchr(argv[0], '/')) == NULL)
- progname = argv[0];
- else
- ++progname;
-
- while ((c = getopt(argc, argv, "advrzc:w:")) != -1) {
- switch (c) {
- case 'a':
- ++aflag;
- break;
- case 'd':
- ++dflag;
- break;
- case 'v':
- ++vflag;
- break;
- case 'r':
- ++rflag;
- break;
- case 'z':
- ++zflag;
- break;
- case 'c':
- count = atoi(optarg);
- if (count <= 0)
- usage();
- break;
- case 'w':
- interval = atoi(optarg);
- if (interval <= 0)
- usage();
- break;
- default:
- usage();
- }
- }
- argc -= optind;
- argv += optind;
-
- if (!interval && count)
- interval = 5;
- if (interval && !count)
- infinite = 1;
- if (!interval && !count)
- count = 1;
- if (aflag)
- dflag = 0;
-
- if (argc > 1)
- usage();
- if (argc > 0)
- interface = argv[0];
-
- if (sscanf(interface, "ppp%d", &unit) != 1) {
- fprintf(stderr, "%s: invalid interface '%s' specified\n",
- progname, interface);
- }
-
-#ifndef STREAMS
- {
- struct ifreq ifr;
-
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- fprintf(stderr, "%s: ", progname);
- perror("couldn't create IP socket");
- exit(1);
- }
-
-#ifdef _linux_
-#undef ifr_name
-#define ifr_name ifr_ifrn.ifrn_name
-#endif
- strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
- if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
- fprintf(stderr, "%s: nonexistent interface '%s' specified\n",
- progname, interface);
- exit(1);
- }
- }
-
-#else /* STREAMS */
-#ifdef __osf__
- dev = "/dev/streams/ppp";
-#else
- dev = "/dev/ppp";
-#endif
- if ((s = open(dev, O_RDONLY)) < 0) {
- fprintf(stderr, "%s: couldn't open ", progname);
- perror(dev);
- exit(1);
- }
- if (strioctl(s, PPPIO_ATTACH, &unit, sizeof(int), 0) < 0) {
- fprintf(stderr, "%s: ppp%d is not available\n", progname, unit);
- exit(1);
- }
-
-#endif /* STREAMS */
-
- intpr();
- exit(0);
-}
diff --git a/usr.sbin/sliplogin/Makefile b/usr.sbin/sliplogin/Makefile
deleted file mode 100644
index 0236f1e..0000000
--- a/usr.sbin/sliplogin/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# @(#)Makefile 8.1 (Berkeley) 7/19/93
-# $FreeBSD$
-
-PROG= sliplogin
-MAN= sliplogin.8
-BINOWN= root
-BINGRP= network
-BINMODE=4550
-PRECIOUSPROG=
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/sliplogin/sliplogin.8 b/usr.sbin/sliplogin/sliplogin.8
deleted file mode 100644
index 1f6960b..0000000
--- a/usr.sbin/sliplogin/sliplogin.8
+++ /dev/null
@@ -1,317 +0,0 @@
-.\" Copyright (c) 1990, 1991, 1993
-.\" The Regents of the University of California. All rights reserved.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" @(#)sliplogin.8 8.2 (Berkeley) 1/5/94
-.\" $FreeBSD$
-.\"
-.Dd January 5, 1994
-.Dt SLIPLOGIN 8
-.Os
-.Sh NAME
-.Nm sliplogin
-.Nd attach a serial line network interface
-.Sh SYNOPSIS
-.Nm
-.Op Ar loginname Op Ar device
-.Sh DESCRIPTION
-The
-.Nm
-utility is used to turn the terminal line on standard input (or
-.Ar device )
-into a Serial Line IP
-.Pq Tn SLIP
-link to a remote host.
-To do this, the program
-searches the file
-.Pa /etc/sliphome/slip.hosts
-for an entry matching
-.Ar loginname
-(which defaults to the current login name if omitted).
-If a matching entry is found, the line is configured appropriately
-for slip (8-bit transparent i/o) and converted to
-.Tn SLIP
-line discipline using the optional line discipline parameters.
-.Pp
-The optional line discipline parameters consist of one or more of
-the following;
-.Sq normal ,
-.Sq compress ,
-.Sq noicmp ,
-or
-.Sq autocomp
-which correspond respectively to
-.Sq use normal line discipline
-(no header compression),
-.Sq enable VJ header compression ,
-.Sq throw away ICMP packets ,
-and
-.Sq auto enable VJ header compression
-(only if the remote end of the link also supports it).
-.Pp
-Then a shell script is invoked to initialize the slip
-interface with the appropriate local and remote
-.Tn IP
-address,
-netmask, etc.
-.Pp
-The usual initialization script is
-.Pa /etc/sliphome/slip.login
-but, if particular hosts need special initialization, the file
-.Pa /etc/sliphome/slip.login. Ns Ar loginname
-will be executed instead if it exists.
-The script is invoked with the parameters
-.Bl -tag -width slipunit
-.It Em slipunit
-The unit number of the slip interface assigned to this line.
-E.g.,
-.Sy 0
-for
-.Sy sl0 .
-.It Em speed
-The speed of the line.
-.It Em args
-The arguments from the
-.Pa /etc/sliphome/slip.hosts
-entry, in order starting with
-.Ar loginname .
-.El
-.Pp
-Only the super-user may attach a network interface.
-The interface is
-automatically detached when the other end hangs up or the
-.Nm
-process dies.
-If the kernel slip
-module has been configured for it, all routes through that interface will
-also disappear at the same time.
-If there is other processing a site
-would like done on hangup, the file
-.Pa /etc/sliphome/slip.logout
-or
-.Pa /etc/sliphome/slip.logout. Ns Ar loginname
-is executed if it exists.
-It is given the same arguments as the login script.
-.Ss Format of /etc/sliphome/slip.hosts
-Comments (lines starting with a `#') and blank lines (or started
-with space) are ignored.
-Other lines must start with a
-.Ar loginname
-but the remaining arguments can be whatever is appropriate for the
-.Pa slip.login
-file that will be executed for that name.
-Arguments are separated by white space and follow normal
-.Xr sh 1
-quoting conventions (however,
-.Ar loginname
-cannot be quoted).
-Usually, lines have the form
-.Bd -literal -offset indent
-loginname local-address remote-address netmask opt-args
-.Ed
-.Pp
-where
-.Em local-address
-and
-.Em remote-address
-are the IP host names or addresses of the local and remote ends of the
-slip line and
-.Em netmask
-is the appropriate IP netmask.
-These arguments are passed
-directly to
-.Xr ifconfig 8 .
-.Em Opt-args
-are optional arguments used to configure the line.
-.Sh FreeBSD Additions
-An additional SLIP configuration file (if present) is
-.Pa /etc/sliphome/slip.slparms .
-If particular hosts need different configurations, the file
-.Pa /etc/sliphome/slip.slparms. Ns Ar loginname
-will be parsed instead if it exists.
-.Ss Format of /etc/sliphome/slip.slparms*
-Comments (lines starting with a `#') and blank lines (or started with
-space) are ignored.
-This file contains from one to three numeric parameters separated with spaces,
-in order:
-.Ar keepalive ,
-.Ar outfill
-and
-.Ar slunit .
-.Bl -tag -width keepalive
-.It Ar keepalive
-Set SLIP "keep alive" timeout in seconds.
-If FRAME_END is not received in
-this amount of time,
-.Nm
-closes the line and exits.
-The default value is no timeout (zero).
-.It Ar outfill
-Set SLIP "out fill" timeout in seconds.
-It forces at least one FRAME_END
-to be sent during this time period, which is necessary for the "keep alive"
-timeout on the remote side.
-The default value is no timeout (zero).
-.It Ar slunit
-Set the SLIP unit number directly.
-Use with caution, because no check is made
-for two interfaces with same number.
-By default sliplogin dynamically assigns the unit number.
-.El
-.Pp
-If latter two parameters are omitted, they will not affect the
-corresponding SLIP configuration.
-If any of first two parameters is equal to zero, it will not affect
-the corresponding SLIP configuration.
-.Sh FILES
-.Bl -tag -width indent
-.It Pa /etc/sliphome/slip.hosts
-list of host login names and parameters.
-.It Pa /etc/sliphome/slip.login
-script executed when a connection is made.
-.It Pa /etc/sliphome/slip.login. Ns Ar loginname
-script executed when a connection is made by
-.Ar loginname .
-.It Pa /etc/sliphome/slip.logout
-script executed when a connection is lost.
-.It Pa /etc/sliphome/slip.logout. Ns Ar loginname
-script executed when a connection is lost by
-.Ar loginname .
-.It Pa /etc/sliphome/slip.slparms
-extra parameters file.
-.It Pa /etc/sliphome/slip.slparms. Ns Ar loginname
-extra parameters file for
-.Ar loginname .
-.It Pa /var/run/ Ns Ar ttyXn Ns Pa .if
-contains the name of the network interface used by the sliplogin process on
-.Ar ttyXn .
-.It Pa /var/run/ Ns Ar slX Ns Pa .pid
-contains the PID of the sliplogin process which is using interface
-.Ar slX .
-.El
-.Sh EXAMPLES
-The normal use of
-.Nm
-is to create a
-.Pa /etc/passwd
-entry for each legal, remote slip site with
-.Nm
-as the shell for that entry.
-E.g.,
-.Bd -literal
-Sfoo:ikhuy6:2010:1:slip line to foo:/tmp:/usr/sbin/sliplogin
-.Ed
-.Pp
-(Our convention is to name the account used by remote host
-.Ar hostname
-as
-.Em Shostname . )
-Then an entry is added to
-.Pa slip.hosts
-that looks like:
-.Pp
-.Bd -literal -offset indent -compact
-Sfoo `hostname` foo netmask
-.Ed
-.Pp
-where
-.Em `hostname`
-will be evaluated by
-.Xr sh 1
-to the local host name and
-.Em netmask
-is the local host IP netmask.
-.Pp
-Note that
-.Nm
-must be setuid to root and, while not a security hole, moral defectives
-can use it to place terminal lines in an unusable state and/or deny
-access to legitimate users of a remote slip line.
-To prevent this,
-.Nm
-is installed as user
-.Em root ,
-group
-.Em network
-and mode 4550 so that only members of group
-.Em network
-may run
-.Nm .
-The system administrator should make sure that all legitimate users
-are a member of the correct group.
-.Sh DIAGNOSTICS
-The
-.Nm
-utility logs various information to the system log daemon,
-.Xr syslogd 8 ,
-with a facility code of
-.Em daemon .
-The messages are listed here, grouped by severity level.
-.Pp
-.Sy Error Severity
-.Bl -tag -width Ds -compact
-.It Sy ioctl (TCGETS): Em reason
-A
-.Dv TCGETS
-.Fn ioctl
-to get the line parameters failed.
-.Pp
-.It Sy ioctl (TCSETS): Em reason
-A
-.Dv TCSETS
-.Fn ioctl
-to set the line parameters failed.
-.Pp
-.It Sy /etc/sliphome/slip.hosts: Em reason
-The
-.Pa /etc/sliphome/slip.hosts
-file could not be opened.
-.Pp
-.It Sy access denied for Em user
-No entry for
-.Em user
-was found in
-.Pa /etc/sliphome/slip.hosts .
-.El
-.Pp
-.Sy Notice Severity
-.Bl -tag -width Ds -compact
-.It Sy "attaching slip unit" Em unit Sy for Ar loginname
-.Tn SLIP
-unit
-.Em unit
-was successfully attached.
-.El
-.Sh SEE ALSO
-.Xr slattach 8 ,
-.Xr syslogd 8
-.Pp
-.Pa /usr/share/examples/sliplogin
-.Sh HISTORY
-The
-.Nm
-utility appeared in
-.Bx 4.3 Reno .
diff --git a/usr.sbin/sliplogin/sliplogin.c b/usr.sbin/sliplogin/sliplogin.c
deleted file mode 100644
index dafdfd4..0000000
--- a/usr.sbin/sliplogin/sliplogin.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static 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[] = "@(#)sliplogin.c 8.2 (Berkeley) 2/1/94";
-static char rscid[] = "@(#)$FreeBSD$";
-#endif /* not lint */
-
-/*
- * sliplogin.c
- * [MUST BE RUN SUID, SLOPEN DOES A SUSER()!]
- *
- * This program initializes its own tty port to be an async TCP/IP interface.
- * It sets the line discipline to slip, invokes a shell script to initialize
- * the network interface, then pauses forever waiting for hangup.
- *
- * It is a remote descendant of several similar programs with incestuous ties:
- * - Kirk Smith's slipconf, modified by Richard Johnsson @ DEC WRL.
- * - slattach, probably by Rick Adams but touched by countless hordes.
- * - the original sliplogin for 4.2bsd, Doug Kingston the mover behind it.
- *
- * There are two forms of usage:
- *
- * "sliplogin"
- * Invoked simply as "sliplogin", the program looks up the username
- * in the file /etc/slip.hosts.
- * If an entry is found, the line on fd0 is configured for SLIP operation
- * as specified in the file.
- *
- * "sliplogin IPhostlogin </dev/ttyb"
- * Invoked by root with a username, the name is looked up in the
- * /etc/slip.hosts file and if found fd0 is configured as in case 1.
- */
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <syslog.h>
-#include <netdb.h>
-
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <net/slip.h>
-#include <net/if.h>
-#include <netinet/in.h>
-
-#include <stdio.h>
-#include <errno.h>
-#include <ctype.h>
-#include <paths.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <signal.h>
-#include "pathnames.h"
-
-extern char **environ;
-
-static char *restricted_environ[] = {
- "PATH=" _PATH_STDPATH,
- NULL
-};
-
-int unit;
-int slip_mode;
-speed_t speed;
-int uid;
-int keepal;
-int outfill;
-int slunit;
-char loginargs[BUFSIZ];
-char loginfile[MAXPATHLEN];
-char loginname[BUFSIZ];
-static char raddr[32]; /* remote address */
-char ifname[IFNAMSIZ]; /* interface name */
-static char pidfilename[MAXPATHLEN]; /* name of pid file */
-static char iffilename[MAXPATHLEN]; /* name of if file */
-static pid_t pid; /* our pid */
-
-char *
-make_ipaddr(void)
-{
-static char address[20] ="";
-struct hostent *he;
-unsigned long ipaddr;
-
-address[0] = '\0';
-if ((he = gethostbyname(raddr)) != NULL) {
- ipaddr = ntohl(*(long *)he->h_addr_list[0]);
- sprintf(address, "%lu.%lu.%lu.%lu",
- ipaddr >> 24,
- (ipaddr & 0x00ff0000) >> 16,
- (ipaddr & 0x0000ff00) >> 8,
- (ipaddr & 0x000000ff));
- }
-
-return address;
-}
-
-struct slip_modes {
- char *sm_name;
- int sm_or_flag;
- int sm_and_flag;
-} modes[] = {
- "normal", 0 , 0 ,
- "compress", IFF_LINK0, IFF_LINK2,
- "noicmp", IFF_LINK1, 0 ,
- "autocomp", IFF_LINK2, IFF_LINK0,
-};
-
-void
-findid(name)
- char *name;
-{
- FILE *fp;
- static char slopt[5][16];
- static char laddr[16];
- static char mask[16];
- char slparmsfile[MAXPATHLEN];
- char user[16];
- char buf[128];
- int i, j, n;
-
- environ = restricted_environ; /* minimal protection for system() */
-
- (void)strncpy(loginname, name, sizeof(loginname)-1);
- loginname[sizeof(loginname)-1] = '\0';
-
- if ((fp = fopen(_PATH_ACCESS, "r")) == NULL) {
- accfile_err:
- syslog(LOG_ERR, "%s: %m\n", _PATH_ACCESS);
- exit(1);
- }
- while (fgets(loginargs, sizeof(loginargs) - 1, fp)) {
- if (ferror(fp))
- goto accfile_err;
- if (loginargs[0] == '#' || isspace(loginargs[0]))
- continue;
- n = sscanf(loginargs, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n",
- user, laddr, raddr, mask, slopt[0], slopt[1],
- slopt[2], slopt[3], slopt[4]);
- if (n < 4) {
- syslog(LOG_ERR, "%s: wrong format\n", _PATH_ACCESS);
- exit(1);
- }
- if (strcmp(user, name) != 0)
- continue;
-
- (void) fclose(fp);
-
- slip_mode = 0;
- for (i = 0; i < n - 4; i++) {
- for (j = 0; j < sizeof(modes)/sizeof(struct slip_modes);
- j++) {
- if (strcmp(modes[j].sm_name, slopt[i]) == 0) {
- slip_mode |= (modes[j].sm_or_flag);
- slip_mode &= ~(modes[j].sm_and_flag);
- break;
- }
- }
- }
-
- /*
- * we've found the guy we're looking for -- see if
- * there's a login file we can use. First check for
- * one specific to this host. If none found, try for
- * a generic one.
- */
- (void)snprintf(loginfile, sizeof(loginfile), "%s.%s",
- _PATH_SLIP_LOGIN, name);
- if (access(loginfile, R_OK|X_OK) != 0) {
- (void)strncpy(loginfile, _PATH_SLIP_LOGIN,
- sizeof(loginfile) - 1);
- loginfile[sizeof(loginfile) - 1] = '\0';
- if (access(loginfile, R_OK|X_OK)) {
- syslog(LOG_ERR,
- "access denied for %s - no %s\n",
- name, _PATH_SLIP_LOGIN);
- exit(5);
- }
- }
- (void)snprintf(slparmsfile, sizeof(slparmsfile), "%s.%s", _PATH_SLPARMS, name);
- if (access(slparmsfile, R_OK|X_OK) != 0) {
- (void)strncpy(slparmsfile, _PATH_SLPARMS, sizeof(slparmsfile)-1);
- slparmsfile[sizeof(slparmsfile)-1] = '\0';
- if (access(slparmsfile, R_OK|X_OK))
- *slparmsfile = '\0';
- }
- keepal = outfill = 0;
- slunit = -1;
- if (*slparmsfile) {
- if ((fp = fopen(slparmsfile, "r")) == NULL) {
- slfile_err:
- syslog(LOG_ERR, "%s: %m\n", slparmsfile);
- exit(1);
- }
- n = 0;
- while (fgets(buf, sizeof(buf) - 1, fp) != NULL) {
- if (ferror(fp))
- goto slfile_err;
- if (buf[0] == '#' || isspace(buf[0]))
- continue;
- n = sscanf(buf, "%d %d %d", &keepal, &outfill, &slunit);
- if (n < 1) {
- slwrong_fmt:
- syslog(LOG_ERR, "%s: wrong format\n", slparmsfile);
- exit(1);
- }
- (void) fclose(fp);
- break;
- }
- if (n == 0)
- goto slwrong_fmt;
- }
-
- return;
- }
- syslog(LOG_ERR, "SLIP access denied for %s\n", name);
- exit(4);
- /* NOTREACHED */
-}
-
-char *
-sigstr(s)
- int s;
-{
- static char buf[32];
-
- switch (s) {
- case SIGHUP: return("HUP");
- case SIGINT: return("INT");
- case SIGQUIT: return("QUIT");
- case SIGILL: return("ILL");
- case SIGTRAP: return("TRAP");
- case SIGIOT: return("IOT");
- case SIGEMT: return("EMT");
- case SIGFPE: return("FPE");
- case SIGKILL: return("KILL");
- case SIGBUS: return("BUS");
- case SIGSEGV: return("SEGV");
- case SIGSYS: return("SYS");
- case SIGPIPE: return("PIPE");
- case SIGALRM: return("ALRM");
- case SIGTERM: return("TERM");
- case SIGURG: return("URG");
- case SIGSTOP: return("STOP");
- case SIGTSTP: return("TSTP");
- case SIGCONT: return("CONT");
- case SIGCHLD: return("CHLD");
- case SIGTTIN: return("TTIN");
- case SIGTTOU: return("TTOU");
- case SIGIO: return("IO");
- case SIGXCPU: return("XCPU");
- case SIGXFSZ: return("XFSZ");
- case SIGVTALRM: return("VTALRM");
- case SIGPROF: return("PROF");
- case SIGWINCH: return("WINCH");
-#ifdef SIGLOST
- case SIGLOST: return("LOST");
-#endif
- case SIGUSR1: return("USR1");
- case SIGUSR2: return("USR2");
- }
- (void)snprintf(buf, sizeof(buf), "sig %d", s);
- return(buf);
-}
-
-void
-hup_handler(s)
- int s;
-{
- char logoutfile[MAXPATHLEN];
-
- (void) close(0);
- seteuid(0);
- (void)snprintf(logoutfile, sizeof(logoutfile), "%s.%s",
- _PATH_SLIP_LOGOUT, loginname);
- if (access(logoutfile, R_OK|X_OK) != 0) {
- (void)strncpy(logoutfile, _PATH_SLIP_LOGOUT,
- sizeof(logoutfile) - 1);
- logoutfile[sizeof(logoutfile) - 1] = '\0';
- }
- if (access(logoutfile, R_OK|X_OK) == 0) {
- char logincmd[2*MAXPATHLEN+32];
-
- (void) snprintf(logincmd, sizeof(logincmd), "%s %d %ld %s", logoutfile, unit, speed, loginargs);
- (void) system(logincmd);
- }
- syslog(LOG_INFO, "closed %s slip unit %d (%s)\n", loginname, unit,
- sigstr(s));
- if (unlink(pidfilename) < 0 && errno != ENOENT)
- syslog(LOG_WARNING, "unable to delete pid file: %m");
- if (unlink(iffilename) < 0 && errno != ENOENT)
- syslog(LOG_WARNING, "unable to delete if file: %m");
- exit(1);
- /* NOTREACHED */
-}
-
-
-/* Modify the slip line mode and add any compression or no-icmp flags. */
-void line_flags(unit)
- int unit;
-{
- struct ifreq ifr;
- int s;
-
- /* open a socket as the handle to the interface */
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0) {
- syslog(LOG_ERR, "socket: %m");
- exit(1);
- }
- sprintf(ifr.ifr_name, "sl%d", unit);
-
- /* get the flags for the interface */
- if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) {
- syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m");
- exit(1);
- }
-
- /* Assert any compression or no-icmp flags. */
-#define SLMASK (~(IFF_LINK0 | IFF_LINK1 | IFF_LINK2))
- ifr.ifr_flags &= SLMASK;
- ifr.ifr_flags |= slip_mode;
- if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) {
- syslog(LOG_ERR, "ioctl (SIOCSIFFLAGS): %m");
- exit(1);
- }
- close(s);
-}
-
-
-int
-main(argc, argv)
- int argc;
- char *argv[];
-{
- int fd, s, ldisc;
- char *name;
- struct termios tios;
- char logincmd[2*BUFSIZ+32];
-
- FILE *pidfile; /* pid file */
- FILE *iffile; /* interfaces file */
- char *p;
- int n;
- char devnam[MAXPATHLEN] = _PATH_TTY; /* Device name */
-
- if ((name = strrchr(argv[0], '/')) == NULL)
- name = argv[0];
- s = getdtablesize();
- for (fd = 3 ; fd < s ; fd++)
- (void) close(fd);
- openlog(name, LOG_PID|LOG_PERROR, LOG_DAEMON);
- uid = getuid();
- if (argc > 1) {
- findid(argv[1]);
-
- /*
- * Disassociate from current controlling terminal, if any,
- * and ensure that the slip line is our controlling terminal.
- */
- if (daemon(1, 1)) {
- syslog(LOG_ERR, "daemon(1, 1): %m");
- exit(1);
- }
- if (argc > 2) {
- if ((fd = open(argv[2], O_RDWR)) == -1) {
- syslog(LOG_ERR, "open %s: %m", argv[2]);
- exit(2);
- }
- (void) dup2(fd, 0);
- if (fd > 2)
- close(fd);
- }
- if (ioctl(0, TIOCSCTTY, 0) == -1) {
- syslog(LOG_ERR, "ioctl (TIOCSCTTY): %m");
- exit(1);
- }
- if (tcsetpgrp(0, getpid()) < 0) {
- syslog(LOG_ERR, "tcsetpgrp failed: %m");
- exit(1);
- }
- } else {
- if ((name = getlogin()) == NULL) {
- syslog(LOG_ERR, "access denied - login name not found\n");
- exit(1);
- }
- findid(name);
- }
- (void) fchmod(0, 0600);
- (void) fprintf(stderr, "starting slip login for %s\n", loginname);
- (void) fprintf(stderr, "your address is %s\n\n", make_ipaddr());
-
- (void) fflush(stderr);
- sleep(1);
-
- /* set up the line parameters */
- if (tcgetattr(0, &tios) < 0) {
- syslog(LOG_ERR, "tcgetattr: %m");
- exit(1);
- }
- cfmakeraw(&tios);
- if (tcsetattr(0, TCSAFLUSH, &tios) < 0) {
- syslog(LOG_ERR, "tcsetattr: %m");
- exit(1);
- }
- speed = cfgetispeed(&tios);
-
- ldisc = SLIPDISC;
- if (ioctl(0, TIOCSETD, &ldisc) < 0) {
- syslog(LOG_ERR, "ioctl(TIOCSETD): %m");
- exit(1);
- }
- if (slunit >= 0 && ioctl(0, SLIOCSUNIT, &slunit) < 0) {
- syslog(LOG_ERR, "ioctl (SLIOCSUNIT): %m");
- exit(1);
- }
- /* find out what unit number we were assigned */
- if (ioctl(0, SLIOCGUNIT, &unit) < 0) {
- syslog(LOG_ERR, "ioctl (SLIOCGUNIT): %m");
- exit(1);
- }
- (void) signal(SIGHUP, hup_handler);
- (void) signal(SIGTERM, hup_handler);
-
- if (keepal > 0) {
- (void) signal(SIGURG, hup_handler);
- if (ioctl(0, SLIOCSKEEPAL, &keepal) < 0) {
- syslog(LOG_ERR, "ioctl(SLIOCSKEEPAL): %m");
- exit(1);
- }
- }
- if (outfill > 0 && ioctl(0, SLIOCSOUTFILL, &outfill) < 0) {
- syslog(LOG_ERR, "ioctl(SLIOCSOUTFILL): %m");
- exit(1);
- }
-
- /* write pid to file */
- pid = getpid();
- (void) sprintf(ifname, "sl%d", unit);
- (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname);
- if ((pidfile = fopen(pidfilename, "w")) != NULL) {
- fprintf(pidfile, "%d\n", pid);
- (void) fclose(pidfile);
- } else {
- syslog(LOG_ERR, "Failed to create pid file %s: %m",
- pidfilename);
- pidfilename[0] = 0;
- }
-
- /* write interface unit number to file */
- p = ttyname(0);
- if (p)
- strcpy(devnam, p);
- for (n = strlen(devnam); n > 0; n--)
- if (devnam[n] == '/') {
- n++;
- break;
- }
- (void) sprintf(iffilename, "%s%s.if", _PATH_VARRUN, &devnam[n]);
- if ((iffile = fopen(iffilename, "w")) != NULL) {
- fprintf(iffile, "sl%d\n", unit);
- (void) fclose(iffile);
- } else {
- syslog(LOG_ERR, "Failed to create if file %s: %m", iffilename);
- iffilename[0] = 0;
- }
-
-
- syslog(LOG_INFO, "attaching slip unit %d for %s\n", unit, loginname);
- (void)snprintf(logincmd, sizeof(logincmd), "%s %d %ld %s", loginfile, unit, speed,
- loginargs);
- /*
- * aim stdout and errout at /dev/null so logincmd output won't
- * babble into the slip tty line.
- */
- (void) close(1);
- if ((fd = open(_PATH_DEVNULL, O_WRONLY)) != 1) {
- if (fd < 0) {
- syslog(LOG_ERR, "open %s: %m", _PATH_DEVNULL);
- exit(1);
- }
- (void) dup2(fd, 1);
- (void) close(fd);
- }
- (void) dup2(1, 2);
-
- /*
- * Run login and logout scripts as root (real and effective);
- * current route(8) is setuid root, and checks the real uid
- * to see whether changes are allowed (or just "route get").
- */
- (void) setuid(0);
- if (s = system(logincmd)) {
- syslog(LOG_ERR, "%s login failed: exit status %d from %s",
- loginname, s, loginfile);
- exit(6);
- }
-
- /* Handle any compression or no-icmp flags. */
- line_flags(unit);
-
- /* reset uid to users' to allow the user to give a signal. */
- seteuid(uid);
- /* twiddle thumbs until we get a signal */
- while (1)
- sigpause(0);
-
- /* NOTREACHED */
-}
diff --git a/usr.sbin/slstat/Makefile b/usr.sbin/slstat/Makefile
deleted file mode 100644
index 650e221..0000000
--- a/usr.sbin/slstat/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# from: @(#)Makefile 5.6 (Berkeley) 4/23/91
-# $FreeBSD$
-
-PROG= slstat
-MAN= slstat.8
-
-WARNS?= 2
-
-.include <bsd.prog.mk>
diff --git a/usr.sbin/slstat/slstat.8 b/usr.sbin/slstat/slstat.8
deleted file mode 100644
index e85e2a8..0000000
--- a/usr.sbin/slstat/slstat.8
+++ /dev/null
@@ -1,125 +0,0 @@
-.\" Copyright (c) 1986 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.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\" From: @(#)slstat.8 6.8 (Berkeley) 6/20/91
-.\" $FreeBSD$
-.\"
-.Dd October 11, 1996
-.Dt SLSTAT 8
-.Os
-.Sh NAME
-.Nm slstat
-.Nd report serial line IP statistics
-.Sh SYNOPSIS
-.Nm
-.Op Fl i Ar interval
-.Op Fl vr
-.Op Ar unit
-.Sh DESCRIPTION
-The
-.Nm
-utility
-reports certain kernel statistics kept about serial line internet
-protocol traffic.
-.Pp
-The options are as follows:
-.Bl -tag -width indent
-.It Fl i
-Repeat the display indefinitely every
-.Ar interval
-seconds.
-If no
-.Ar interval
-is specified, the default is 5 seconds.
-.It Fl v
-Verbose display of extra fields of information.
-.It Fl r
-Display all values in rate per second rather than amount per interval.
-.It Ar unit
-Is number specifying the
-.Tn SLIP
-interface, or a
-.Tn SLIP
-interface name.
-The default unit is
-.Sy 0
-for interface
-.Sy sl0 .
-.El
-.Pp
-By default,
-.Nm
-displays the following information:
-.Pp
-.Bl -tag -width indent
-.It in
-bytes received
-.It out
-bytes sent
-.It pack
-packets received or sent
-.It comp
-compressed packets received or sent
-.It uncomp
-uncompressed packets received or sent
-.It unknwn
-inbound packets of unknown type
-.It toss
-inbound packets tossed because of error
-.It other
-all other inbound or outbound ip packets
-.It err
-input or output errors
-.It search
-searches for connection state
-.It miss
-times we could not find a connection state
-.It coll
-collisions with end of clists.
-If you get many collisions (more than one or two
-a day) you probably do not have enough clists
-and you should increase
-.Dv nclist
-in param.c.
-.El
-.Sh EXAMPLES
-The command:
-.Dl slstat -i 5
-will print what the system is doing every five
-seconds.
-.Sh SEE ALSO
-.Xr fstat 1 ,
-.Xr netstat 1 ,
-.Xr nfsstat 1 ,
-.Xr ps 1 ,
-.Xr systat 1 ,
-.Xr iostat 8 ,
-.Xr pppstats 8 ,
-.Xr pstat 8
-.Pp
-The sections starting with ``Interpreting system activity'' in
-.%T "Installing and Operating 4.3BSD" .
diff --git a/usr.sbin/slstat/slstat.c b/usr.sbin/slstat/slstat.c
deleted file mode 100644
index ff017f4..0000000
--- a/usr.sbin/slstat/slstat.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * print serial line IP statistics:
- * slstat [-i interval] [-v] [interface]
- *
- * Copyright (c) 1989, 1990, 1991, 1992 Regents of the University of
- * California. All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that the above copyright notice and this paragraph are
- * duplicated in all such forms and that any documentation,
- * advertising materials, and other materials related to such
- * distribution and use acknowledge that the software was developed
- * by the University of California, Berkeley. The name of the
- * University may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Van Jacobson (van@ee.lbl.gov), Dec 31, 1989:
- * - Initial distribution.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/sysctl.h>
-#include <sys/time.h>
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <net/if.h>
-#include <net/if_var.h>
-#include <net/if_mib.h>
-#include <net/if_types.h>
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/ip.h>
-#include <net/slcompress.h>
-#include <net/if_slvar.h>
-
-static void usage(void);
-static void intpr(void);
-static void catchalarm(int);
-
-#define INTERFACE_PREFIX "sl%d"
-char interface[IFNAMSIZ];
-
-int rflag;
-int vflag;
-unsigned interval = 5;
-int unit;
-int name[6];
-
-int
-main(int argc, char *argv[])
-{
- int c, i;
- size_t len;
- int maxifno;
- int indx;
- struct ifmibdata ifmd;
-
- while ((c = getopt(argc, argv, "vri:")) != -1) {
- switch(c) {
- case 'v':
- ++vflag;
- break;
- case 'r':
- ++rflag;
- break;
- case 'i':
- interval = atoi(optarg);
- if (interval <= 0)
- usage();
- break;
- default:
- usage();
- }
- }
- if (optind >= argc)
- sprintf(interface, INTERFACE_PREFIX, unit);
- else if (isdigit(argv[optind][0])) {
- unit = atoi(argv[optind]);
- if (unit < 0)
- usage();
- sprintf(interface, INTERFACE_PREFIX, unit);
- } else if (strncmp(argv[optind], "sl", 2) == 0
- && isdigit(argv[optind][2])
- && sscanf(argv[optind], "sl%d", &unit) == 1) {
- strncpy(interface, argv[optind], IFNAMSIZ);
- } else
- usage();
-
- name[0] = CTL_NET;
- name[1] = PF_LINK;
- name[2] = NETLINK_GENERIC;
- name[3] = IFMIB_SYSTEM;
- name[4] = IFMIB_IFCOUNT;
- len = sizeof maxifno;
- if (sysctl(name, 5, &maxifno, &len, 0, 0) < 0)
- err(1, "sysctl net.link.generic.system.ifcount");
-
- name[3] = IFMIB_IFDATA;
- name[5] = IFDATA_GENERAL;
- len = sizeof ifmd;
- for (i = 1; ; i++) {
- name[4] = i;
-
- if (sysctl(name, 6, &ifmd, &len, 0, 0) < 0) {
- if (errno == ENOENT)
- continue;
-
- err(1, "sysctl");
- }
- if (strncmp(interface, ifmd.ifmd_name, IFNAMSIZ) == 0
- && ifmd.ifmd_data.ifi_type == IFT_SLIP) {
- indx = i;
- break;
- }
- if (i >= maxifno)
- errx(1, "interface %s does not exist", interface);
- }
-
- name[4] = indx;
- name[5] = IFDATA_LINKSPECIFIC;
- intpr();
- exit(0);
-}
-
-#define V(offset) ((line % 20)? ((sc->offset - osc->offset) / \
- (rflag ? interval : 1)) : sc->offset)
-#define AMT (sizeof(*sc) - 2 * sizeof(sc->sc_comp.tstate))
-
-static void
-usage()
-{
- fprintf(stderr, "usage: slstat [-i interval] [-vr] [unit]\n");
- exit(1);
-}
-
-u_char signalled; /* set if alarm goes off "early" */
-
-/*
- * Print a running summary of interface statistics.
- * Repeat display every interval seconds, showing statistics
- * collected over that interval. Assumes that interval is non-zero.
- * First line printed at top of screen is always cumulative.
- */
-static void
-intpr()
-{
- register int line = 0;
- int oldmask;
- struct sl_softc *sc, *osc;
- size_t len;
-
- sc = (struct sl_softc *)malloc(AMT);
- osc = (struct sl_softc *)malloc(AMT);
- bzero((char *)osc, AMT);
- len = AMT;
-
- while (1) {
- if (sysctl(name, 6, sc, &len, 0, 0) < 0 &&
- (errno != ENOMEM || len != AMT))
- err(1, "sysctl linkspecific");
-
- (void)signal(SIGALRM, catchalarm);
- signalled = 0;
- (void)alarm(interval);
-
- if ((line % 20) == 0) {
- printf("%8.8s %6.6s %6.6s %6.6s %6.6s",
- "in", "pack", "comp", "uncomp", "unknwn");
- if (vflag)
- printf(" %6.6s %6.6s %6.6s",
- "toss", "other", "err");
- printf(" | %8.8s %6.6s %6.6s %6.6s %6.6s",
- "out", "pack", "comp", "uncomp", "other");
- if (vflag)
- printf(" %6.6s %6.6s %6.6s %6.6s",
- "search", "miss", "err", "coll");
- putchar('\n');
- }
- printf("%8lu %6ld %6u %6u %6u",
- V(sc_ifp->if_ibytes),
- V(sc_ifp->if_ipackets),
- V(sc_comp.sls_compressedin),
- V(sc_comp.sls_uncompressedin),
- V(sc_comp.sls_errorin));
- if (vflag)
- printf(" %6u %6lu %6lu",
- V(sc_comp.sls_tossed),
- V(sc_ifp->if_ipackets) -
- V(sc_comp.sls_compressedin) -
- V(sc_comp.sls_uncompressedin) -
- V(sc_comp.sls_errorin),
- V(sc_ifp->if_ierrors));
- printf(" | %8lu %6ld %6u %6u %6lu",
- V(sc_ifp->if_obytes) / (rflag ? interval : 1),
- V(sc_ifp->if_opackets),
- V(sc_comp.sls_compressed),
- V(sc_comp.sls_packets) - V(sc_comp.sls_compressed),
- V(sc_ifp->if_opackets) - V(sc_comp.sls_packets));
- if (vflag)
- printf(" %6u %6u %6lu %6lu",
- V(sc_comp.sls_searches),
- V(sc_comp.sls_misses),
- V(sc_ifp->if_oerrors),
- V(sc_ifp->if_collisions));
- putchar('\n');
- fflush(stdout);
- line++;
- oldmask = sigblock(sigmask(SIGALRM));
- if (! signalled) {
- sigpause(0);
- }
- sigsetmask(oldmask);
- signalled = 0;
- (void)alarm(interval);
- bcopy((char *)sc, (char *)osc, AMT);
- }
-}
-
-/*
- * Called if an interval expires before sidewaysintpr has completed a loop.
- * Sets a flag to not wait for the alarm.
- */
-static void
-catchalarm(sig)
- int sig __unused;
-{
- signalled = 1;
-}
diff --git a/usr.sbin/sysinstall/config.c b/usr.sbin/sysinstall/config.c
index 7693833..ff4c1f9 100644
--- a/usr.sbin/sysinstall/config.c
+++ b/usr.sbin/sysinstall/config.c
@@ -428,8 +428,12 @@ configRC_conf(void)
while(fgets(line, sizeof(line), rcOld)) {
if(line[0] == '#' || variable_check2(line) != 0)
fprintf(rcSite, "%s", line);
- else
- fprintf(rcSite, "#REMOVED: %s", line);
+ else {
+ if (variable_get(VAR_KEEPRCCONF) != NULL)
+ fprintf(rcSite, "%s", line);
+ else
+ fprintf(rcSite, "#REMOVED: %s", line);
+ }
}
fclose(rcOld);
} else if (write_header) {
diff --git a/usr.sbin/sysinstall/devices.c b/usr.sbin/sysinstall/devices.c
index c4438e1..30c57bd 100644
--- a/usr.sbin/sysinstall/devices.c
+++ b/usr.sbin/sysinstall/devices.c
@@ -154,6 +154,7 @@ static struct _devname {
NETWORK("txp", "3Com 3cR990 Ethernet card"),
NETWORK("ti", "Alteon Networks PCI Gigabit Ethernet card"),
NETWORK("tl", "Texas Instruments ThunderLAN PCI Ethernet card"),
+ NETWORK("uath", "Atheros AR5005UG and AR5005UX USB wireless adapter"),
NETWORK("upgt", "Conexant/Intersil PrismGT USB wireless adapter"),
NETWORK("ural", "Ralink Technology RT2500USB 802.11 wireless adapter"),
NETWORK("urtw", "Realtek 8187L USB wireless adapter"),
diff --git a/usr.sbin/sysinstall/dispatch.c b/usr.sbin/sysinstall/dispatch.c
index 3a891c9..79d9cf3 100644
--- a/usr.sbin/sysinstall/dispatch.c
+++ b/usr.sbin/sysinstall/dispatch.c
@@ -47,6 +47,7 @@ static int dispatch_systemExecute(dialogMenuItem *unused);
static int dispatch_msgConfirm(dialogMenuItem *unused);
static int dispatch_mediaOpen(dialogMenuItem *unused);
static int dispatch_mediaClose(dialogMenuItem *unused);
+static int cfgModuleFire(dialogMenuItem *self);
static struct _word {
char *name;
@@ -90,6 +91,7 @@ static struct _word {
{ "installVarDefaults", installVarDefaults },
{ "loadConfig", dispatch_load_file },
{ "loadFloppyConfig", dispatch_load_floppy },
+ { "loadCDROMConfig", dispatch_load_cdrom },
{ "mediaOpen", dispatch_mediaOpen },
{ "mediaClose", dispatch_mediaClose },
{ "mediaSetCDROM", mediaSetCDROM },
@@ -242,8 +244,9 @@ dispatchCommand(char *str)
msgConfirm("Null or zero-length string passed to dispatchCommand");
return DITEM_FAILURE;
}
- /* If it's got a newline, trim it */
- if ((cp = index(str, '\n')) != NULL)
+
+ /* Fixup DOS abuse */
+ if ((cp = index(str, '\r')) != NULL)
*cp = '\0';
/* If it's got a `=' sign in there, assume it's a variable setting */
@@ -294,9 +297,12 @@ dispatch_load_fp(FILE *fp)
INITQUE(*head);
while (fgets(buf, sizeof buf, fp)) {
-
- if ((cp = strchr(buf, '\n')) != NULL)
+ /* Fix up DOS abuse */
+ if ((cp = index(buf, '\r')) != NULL)
*cp = '\0';
+ /* If it's got a new line, trim it */
+ if ((cp = index(buf, '\n')) != NULL)
+ *cp = '\0';
if (*buf == '\0' || *buf == '#')
continue;
@@ -326,7 +332,7 @@ dispatch_execute(qelement *head)
while (!EMPTYQUE(*head)) {
item = (command_buffer *) head->q_forw;
-
+
if (DITEM_STATUS(dispatchCommand(item->string)) != DITEM_SUCCESS) {
msgConfirm("Command `%s' failed - rest of script aborted.\n",
item->string);
@@ -401,8 +407,7 @@ dispatch_load_floppy(dialogMenuItem *self)
mediaClose();
cp = variable_get_value(VAR_INSTALL_CFG,
- "Specify the name of a configuration file\n"
- "residing on a MSDOS or UFS floppy.", 0);
+ "Specify the name of a configuration file", 0);
if (!cp || !*cp) {
variable_unset(VAR_INSTALL_CFG);
what |= DITEM_FAILURE;
@@ -443,3 +448,189 @@ dispatch_load_floppy(dialogMenuItem *self)
return what;
}
+int
+dispatch_load_cdrom(dialogMenuItem *self)
+{
+ int what = DITEM_SUCCESS;
+ extern char *distWanted;
+ char *cp;
+ FILE *fp;
+ qelement *list;
+
+ mediaClose();
+ cp = variable_get_value(VAR_INSTALL_CFG,
+ "Specify the name of a configuration file\n"
+ "residing on the CDROM.", 0);
+ if (!cp || !*cp) {
+ variable_unset(VAR_INSTALL_CFG);
+ what |= DITEM_FAILURE;
+ return what;
+ }
+
+ distWanted = cp;
+ /* Try to open the floppy drive */
+ if (DITEM_STATUS(mediaSetCDROM(NULL)) == DITEM_FAILURE) {
+ msgConfirm("Unable to set media device to CDROM.");
+ what |= DITEM_FAILURE;
+ mediaClose();
+ return what;
+ }
+
+ if (!DEVICE_INIT(mediaDevice)) {
+ msgConfirm("Unable to CDROM filesystem.");
+ what |= DITEM_FAILURE;
+ mediaClose();
+ return what;
+ }
+
+ fp = DEVICE_GET(mediaDevice, cp, TRUE);
+ if (fp) {
+ list = dispatch_load_fp(fp);
+ fclose(fp);
+ mediaClose();
+
+ what |= dispatch_execute(list);
+ }
+ else {
+ if (!variable_get(VAR_NO_ERROR))
+ msgConfirm("Configuration file '%s' not found.", cp);
+ variable_unset(VAR_INSTALL_CFG);
+ what |= DITEM_FAILURE;
+ mediaClose();
+ }
+ return what;
+}
+
+/*
+ * Create a menu based on available disk devices
+ */
+int
+dispatch_load_menu(dialogMenuItem *self)
+{
+ DMenu *menu;
+ Device **devlist;
+ char *err;
+ int what, i, j, msize, count;
+ DeviceType dtypes[] = {DEVICE_TYPE_FLOPPY, DEVICE_TYPE_CDROM, DEVICE_TYPE_DOS, DEVICE_TYPE_UFS};
+
+ fprintf(stderr, "dispatch_load_menu called\n");
+
+ msize = sizeof(DMenu) + (sizeof(dialogMenuItem) * 2);
+ count = 0;
+ err = NULL;
+ what = DITEM_SUCCESS;
+
+ if ((menu = malloc(msize)) == NULL) {
+ err = "Failed to allocate memory for menu";
+ goto errout;
+ }
+
+ bcopy(&MenuConfig, menu, sizeof(DMenu));
+
+ bzero(&menu->items[count], sizeof(menu->items[0]));
+ menu->items[count].prompt = strdup("X Exit");
+ menu->items[count].title = strdup("Exit this menu (returning to previous)");
+ menu->items[count].fire = dmenuExit;
+ count++;
+
+ for (i = 0; i < sizeof(dtypes) / sizeof(dtypes[0]); i++) {
+ if ((devlist = deviceFind(NULL, dtypes[i])) == NULL) {
+ fprintf(stderr, "No devices found for type %d\n", dtypes[i]);
+ continue;
+ }
+
+ for (j = 0; devlist[j] != NULL; j++) {
+ fprintf(stderr, "device type %d device name %s\n", dtypes[i], devlist[j]->name);
+ msize += sizeof(dialogMenuItem);
+ if ((menu = realloc(menu, msize)) == NULL) {
+ err = "Failed to allocate memory for menu item";
+ goto errout;
+ }
+
+ bzero(&menu->items[count], sizeof(menu->items[0]));
+ menu->items[count].fire = cfgModuleFire;
+
+ menu->items[count].prompt = strdup(devlist[j]->name);
+ menu->items[count].title = strdup(devlist[j]->description);
+ /* XXX: dialog(3) sucks */
+ menu->items[count].aux = (long)devlist[j];
+ count++;
+ }
+ }
+
+ menu->items[count].prompt = NULL;
+ menu->items[count].title = NULL;
+
+ dmenuOpenSimple(menu, FALSE);
+
+ errout:
+ for (i = 0; i < count; i++) {
+ free(menu->items[i].prompt);
+ free(menu->items[i].title);
+ }
+
+ free(menu);
+
+ if (err != NULL) {
+ what |= DITEM_FAILURE;
+ if (!variable_get(VAR_NO_ERROR))
+ msgConfirm(err);
+ }
+
+ return (what);
+
+}
+
+static int
+cfgModuleFire(dialogMenuItem *self) {
+ Device *d;
+ FILE *fp;
+ int what = DITEM_SUCCESS;
+ extern char *distWanted;
+ qelement *list;
+ char *cp;
+
+ d = (Device *)self->aux;
+
+ msgDebug("cfgModuleFire: User selected %s (%s)\n", self->prompt, d->devname);
+
+ mediaClose();
+
+ cp = variable_get_value(VAR_INSTALL_CFG,
+ "Specify the name of a configuration file", 0);
+ if (!cp || !*cp) {
+ variable_unset(VAR_INSTALL_CFG);
+ what |= DITEM_FAILURE;
+ return what;
+ }
+
+ distWanted = cp;
+
+ mediaDevice = d;
+ if (!DEVICE_INIT(mediaDevice)) {
+ msgConfirm("Unable to mount filesystem.");
+ what |= DITEM_FAILURE;
+ mediaClose();
+ return what;
+ }
+ msgDebug("getting fp for %s\n", cp);
+
+ fp = DEVICE_GET(mediaDevice, cp, TRUE);
+ if (fp) {
+ msgDebug("opened OK, processing..\n");
+
+ list = dispatch_load_fp(fp);
+ fclose(fp);
+ mediaClose();
+
+ what |= dispatch_execute(list);
+ } else {
+ if (!variable_get(VAR_NO_ERROR))
+ msgConfirm("Configuration file '%s' not found.", cp);
+ variable_unset(VAR_INSTALL_CFG);
+ what |= DITEM_FAILURE;
+ mediaClose();
+ }
+
+ return(what);
+ }
diff --git a/usr.sbin/sysinstall/menus.c b/usr.sbin/sysinstall/menus.c
index 459d664..9269216 100644
--- a/usr.sbin/sysinstall/menus.c
+++ b/usr.sbin/sysinstall/menus.c
@@ -152,7 +152,9 @@ DMenu MenuIndex = {
{ " Console settings", "Customize system console behavior.", NULL, dmenuSubmenu, NULL, &MenuSyscons },
#endif
{ " Configure", "The system configuration menu.", NULL, dmenuSubmenu, NULL, &MenuConfigure },
- { " Defaults, Load", "Load default settings.", NULL, dispatch_load_floppy },
+ { " Defaults, Load (FDD)","Load default settings from floppy.", NULL, dispatch_load_floppy },
+ { " Defaults, Load (CD)", "Load default settings from CDROM.", NULL, dispatch_load_cdrom },
+ { " Defaults, Load", "Load default settings (all devices).", NULL, dispatch_load_menu },
#ifdef WITH_MICE
{ " Device, Mouse", "The mouse configuration menu.", NULL, dmenuSubmenu, NULL, &MenuMouse },
#endif
@@ -256,7 +258,7 @@ DMenu MenuInitial = {
{ "Options", "View/Set various installation options", NULL, optionsEditor },
{ "Fixit", "Repair mode with CDROM/DVD/floppy or start shell", NULL, dmenuSubmenu, NULL, &MenuFixit },
{ "Upgrade", "Upgrade an existing system", NULL, installUpgrade },
- { "Load Config","Load default install configuration", NULL, dispatch_load_floppy },
+ { "Load Config..","Load default install configuration", NULL, dispatch_load_menu },
{ "Index", "Glossary of functions", NULL, dmenuSubmenu, NULL, &MenuIndex },
{ NULL } },
};
@@ -818,6 +820,17 @@ DMenu MenuKLD = {
{ { NULL } },
};
+/* Prototype config file load menu */
+DMenu MenuConfig = {
+ DMENU_NORMAL_TYPE,
+ "Config Menu",
+ "Please select the device to load your configuration file from.\n"
+ "Note that a USB key will show up as daNs1.",
+ NULL,
+ NULL,
+ { { NULL } },
+};
+
/* The media selection menu */
DMenu MenuMedia = {
DMENU_NORMAL_TYPE | DMENU_SELECTION_RETURNS,
diff --git a/usr.sbin/sysinstall/modules.c b/usr.sbin/sysinstall/modules.c
index 859994a..211c51e 100644
--- a/usr.sbin/sysinstall/modules.c
+++ b/usr.sbin/sysinstall/modules.c
@@ -132,17 +132,13 @@ kldBrowser(dialogMenuItem *self)
err = NULL;
if (DITEM_STATUS(mediaSetFloppy(NULL)) == DITEM_FAILURE) {
- msgConfirm("Unable to set media device to floppy.");
- what |= DITEM_FAILURE;
- mediaClose();
- return what;
+ err = "Unable to set media device to floppy.";
+ goto errout;
}
if (!DEVICE_INIT(mediaDevice)) {
- msgConfirm("Unable to mount floppy filesystem.");
- what |= DITEM_FAILURE;
- mediaClose();
- return what;
+ err = "Unable to mount floppy filesystem.";
+ goto errout;
}
msize = sizeof(DMenu) + (sizeof(dialogMenuItem) * 2);
@@ -191,11 +187,10 @@ kldBrowser(dialogMenuItem *self)
dmenuOpenSimple(menu, FALSE);
- mediaClose();
-
deviceRescan();
errout:
+ mediaClose();
for (i = 0; i < count; i++)
free(menu->items[i].prompt);
diff --git a/usr.sbin/sysinstall/sysinstall.8 b/usr.sbin/sysinstall/sysinstall.8
index ab1cc12..7cb55aa 100644
--- a/usr.sbin/sysinstall/sysinstall.8
+++ b/usr.sbin/sysinstall/sysinstall.8
@@ -534,7 +534,16 @@ functions.
.Pp
.Sy Variables :
None
-.It installExpress
+.It installConfigure
+Commit any rc.conf changes to disk.
+.Pp
+.Sy Variables :
+.Bl -tag -width indent
+.It keeprcconf
+Preserve existing rc.conf parameters.
+This is useful if you have a post-install script which modifies rc.conf.
+.El
+ .It installExpress
Start an "express" installation, asking few questions of
the user.
.Pp
@@ -894,3 +903,6 @@ for these tasks.
.Pp
This utility is a prototype which lasted several years past
its expiration date and is greatly in need of death.
+.Pp
+There are a (great) number of undocumented variables.
+UTSL.
diff --git a/usr.sbin/sysinstall/sysinstall.h b/usr.sbin/sysinstall/sysinstall.h
index 6165160..6f860f5 100644
--- a/usr.sbin/sysinstall/sysinstall.h
+++ b/usr.sbin/sysinstall/sysinstall.h
@@ -191,6 +191,7 @@
#define VAR_HOME_SIZE "homeSize"
#define VAR_TERM "TERM"
#define VAR_CONSTERM "_consterm"
+#define VAR_KEEPRCCONF "keeprcconf"
#ifdef PC98
#define DEFAULT_COUNTRY "jp"
@@ -433,6 +434,7 @@ extern DMenu MenuIndex; /* Index menu */
extern DMenu MenuOptions; /* Installation options */
extern DMenu MenuOptionsLanguage; /* Language options menu */
extern DMenu MenuKLD; /* Prototype KLD menu */
+extern DMenu MenuConfig; /* Prototype config menu */
extern DMenu MenuMedia; /* Media type menu */
#ifdef WITH_MICE
extern DMenu MenuMouse; /* Mouse type menu */
@@ -577,8 +579,10 @@ extern int diskGetSelectCount(Device ***devs);
/* dispatch.c */
extern int dispatchCommand(char *command);
extern int dispatch_load_floppy(dialogMenuItem *self);
+extern int dispatch_load_cdrom(dialogMenuItem *self);
extern int dispatch_load_file_int(int);
extern int dispatch_load_file(dialogMenuItem *self);
+extern int dispatch_load_menu(dialogMenuItem *self);
/* dist.c */
diff --git a/usr.sbin/sysinstall/user.c b/usr.sbin/sysinstall/user.c
index 3bba68e..2ac2b8b 100644
--- a/usr.sbin/sysinstall/user.c
+++ b/usr.sbin/sysinstall/user.c
@@ -698,6 +698,7 @@ userAddUser(dialogMenuItem *self)
CLEAR(ugroup);
CLEAR(gecos);
CLEAR(passwd);
+ CLEAR(confpasswd);
CLEAR(umemb);
CLEAR(homedir);
CLEAR(shell);
diff --git a/usr.sbin/tcpdump/tcpdump/Makefile b/usr.sbin/tcpdump/tcpdump/Makefile
index 9ea718a..6f072b7 100644
--- a/usr.sbin/tcpdump/tcpdump/Makefile
+++ b/usr.sbin/tcpdump/tcpdump/Makefile
@@ -7,28 +7,31 @@ TCPDUMP_DISTDIR?= ${.CURDIR}/../../../contrib/tcpdump
PROG= tcpdump
-SRCS = addrtoname.c af.c cpack.c gmpls.c oui.c gmt2local.c ipproto.c \
- nlpid.c l2vpn.c machdep.c parsenfsfh.c \
+SRCS = addrtoname.c af.c checksum.c cpack.c gmpls.c oui.c gmt2local.c \
+ ipproto.c nlpid.c l2vpn.c machdep.c parsenfsfh.c \
print-802_11.c print-ap1394.c print-ah.c print-arcnet.c \
print-aodv.c print-arp.c print-ascii.c print-atalk.c print-atm.c \
print-beep.c print-bfd.c print-bgp.c print-bootp.c print-cdp.c \
- print-chdlc.c print-cip.c print-cnfp.c print-dccp.c print-decnet.c \
- print-domain.c print-dvmrp.c print-enc.c print-egp.c \
- print-eap.c print-eigrp.c\
+ print-cfm.c print-chdlc.c print-cip.c print-cnfp.c print-dccp.c \
+ print-decnet.c print-domain.c print-dtp.c print-dvmrp.c print-enc.c \
+ print-egp.c print-eap.c print-eigrp.c \
print-esp.c print-ether.c print-fddi.c print-fr.c \
print-gre.c print-hsrp.c print-icmp.c print-igmp.c \
print-igrp.c print-ip.c print-ipcomp.c print-ipfc.c \
print-ipx.c print-isakmp.c print-isoclns.c print-juniper.c print-krb.c \
- print-l2tp.c print-lane.c print-ldp.c print-llc.c \
+ print-l2tp.c print-lane.c print-ldp.c print-lldp.c print-llc.c \
print-lmp.c print-lspping.c \
- print-lwres.c print-mobile.c print-mpls.c print-msdp.c \
+ print-lwapp.c print-lwres.c print-mobile.c print-mpls.c print-msdp.c \
+ print-mpcp.c \
print-nfs.c print-ntp.c print-null.c print-olsr.c print-ospf.c \
print-pgm.c print-pim.c print-ppp.c print-pppoe.c \
print-pptp.c print-radius.c print-raw.c print-rip.c \
- print-rsvp.c print-rx.c print-sctp.c print-sip.c print-sl.c print-sll.c \
+ print-rrcp.c print-rsvp.c print-rx.c print-sctp.c print-sflow.c \
+ print-sip.c print-sl.c print-sll.c \
print-slow.c print-snmp.c print-stp.c print-sunatm.c print-sunrpc.c \
print-symantec.c print-syslog.c print-tcp.c print-telnet.c print-tftp.c \
- print-timed.c print-token.c print-udp.c print-vjc.c print-vrrp.c \
+ print-timed.c print-token.c print-udld.c print-udp.c print-vjc.c \
+ print-vqp.c print-vrrp.c print-vtp.c \
print-wb.c print-zephyr.c setsignal.c tcpdump.c util.c \
print-smb.c smbutil.c \
version.c
diff --git a/usr.sbin/uathload/Makefile b/usr.sbin/uathload/Makefile
new file mode 100644
index 0000000..3083704
--- /dev/null
+++ b/usr.sbin/uathload/Makefile
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+PROG= uathload
+MAN= uathload.8
+
+SRCS= uathload.c ar5523.bin
+
+WARNS?= 4
+
+CLEANFILES= ar5523.bin
+
+ar5523.bin: ${.CURDIR}/../../sys/contrib/dev/uath/ar5523.bin.uu
+ uudecode -p ${.CURDIR}/../../sys/contrib/dev/uath/ar5523.bin.uu > ${.TARGET}
+
+ar5523.o: ar5523.bin
+ ${LD} -b binary -d -warn-common -r -d -o ${.TARGET} ar5523.bin
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/uathload/uathload.8 b/usr.sbin/uathload/uathload.8
new file mode 100644
index 0000000..e07cfa2
--- /dev/null
+++ b/usr.sbin/uathload/uathload.8
@@ -0,0 +1,69 @@
+.\"
+.\" Copyright (c) 2009 Weongyo Jeong.
+.\" 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$
+.\"
+.Dd April 7, 2009
+.Dt UATHLOAD 8
+.Os
+.Sh NAME
+.Nm uathload
+.Nd "firmware loader for Atheros USB wireless driver"
+.Sh SYNOPSIS
+.Nm
+.Op Fl v
+.Op Fl d Ar ugen-device
+.Op Ar firmware-file
+.Sh DESCRIPTION
+The
+.Nm
+utility provides a way to load the firmware for Atheros USB wireless
+devices with AR5005UG and AR5005UX chipsets.
+.Pp
+The following options are accepted.
+.Bl -tag -width ".Fl f Ar file"
+.It Fl d Ar ugen-device
+Use a specific
+.Xr ugen 4
+device.
+.It Fl v
+Enable debugging messages.
+.El
+.Pp
+If
+.Ar firmware-file
+is specified
+.Nm
+tries to load it instead of the built-in firmware image.
+.Sh EXAMPLES
+Load the built-in firmware image into a specific
+.Xr ugen 4
+device:
+.Pp
+.Dl "uathload -d /dev/ugen0.2"
+.Sh SEE ALSO
+.Xr uath 4
+.Sh AUTHORS
+.An Weongyo Jeong
diff --git a/usr.sbin/uathload/uathload.c b/usr.sbin/uathload/uathload.c
new file mode 100644
index 0000000..64ae661
--- /dev/null
+++ b/usr.sbin/uathload/uathload.c
@@ -0,0 +1,233 @@
+/*-
+ * Copyright (c) 2006 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Atheros AR5523 USB Station Firmware downloader.
+ *
+ * uathload -d ugen-device [firmware-file]
+ *
+ * Intended to be called from devd on device discovery.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/endian.h>
+#include <sys/mman.h>
+
+#include <sys/ioctl.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_ioctl.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <paths.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+
+/* all fields are big endian */
+struct uath_fwmsg {
+ uint32_t flags;
+#define UATH_WRITE_BLOCK (1 << 4)
+
+ uint32_t len;
+#define UATH_MAX_FWBLOCK_SIZE 2048
+
+ uint32_t total;
+ uint32_t remain;
+ uint32_t rxtotal;
+ uint32_t pad[123];
+} __packed;
+
+#define UATH_DATA_TIMEOUT 10000
+#define UATH_CMD_TIMEOUT 1000
+
+#define VERBOSE(_fmt, ...) do { \
+ if (verbose) { \
+ printf(_fmt, __VA_ARGS__); \
+ fflush(stdout); \
+ } \
+} while (0)
+
+extern uint8_t _binary_ar5523_bin_start;
+extern uint8_t _binary_ar5523_bin_end;
+
+static int
+getdevname(const char *devname, char *msgdev, char *datadev)
+{
+ char *bn, *dn;
+
+ dn = dirname(devname);
+ if (dn == NULL)
+ return (-1);
+ bn = basename(devname);
+ if (bn == NULL || strncmp(bn, "ugen", 4))
+ return (-1);
+ bn += 4;
+
+ /* NB: pipes are hardcoded */
+ snprintf(msgdev, 256, "%s/usb/%s.1", dn, bn);
+ snprintf(datadev, 256, "%s/usb/%s.2", dn, bn);
+ return (0);
+}
+
+static void
+usage(void)
+{
+ errx(-1, "usage: uathload [-v] -d devname [firmware]");
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *fwname, *devname;
+ char msgdev[256], datadev[256];
+ struct uath_fwmsg txmsg, rxmsg;
+ char *txdata;
+ struct stat sb;
+ int msg, data, fw, timeout, b, c;
+ int bufsize = 512, verbose = 0;
+ ssize_t len;
+
+ devname = NULL;
+ while ((c = getopt(argc, argv, "d:v")) != -1) {
+ switch (c) {
+ case 'd':
+ devname = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage();
+ /*NOTREACHED*/
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (devname == NULL)
+ errx(-1, "No device name; use -d to specify the ugen device");
+ if (argc > 1)
+ usage();
+
+ if (argc == 1) {
+ fwname = argv[0];
+ fw = open(fwname, O_RDONLY, 0);
+ if (fw < 0)
+ err(-1, "open(%s)", fwname);
+ if (fstat(fw, &sb) < 0)
+ err(-1, "fstat(%s)", fwname);
+ txdata = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fw, 0);
+ if (txdata == MAP_FAILED)
+ err(-1, "mmap(%s)", fwname);
+ len = sb.st_size;
+ } else {
+ fwname = "ar5523.bin (builtin)";
+ fw = -1;
+ txdata = &_binary_ar5523_bin_start;
+ len = &_binary_ar5523_bin_end - &_binary_ar5523_bin_start;
+ }
+ /* XXX verify device is an AR5005 part */
+ if (getdevname(devname, msgdev, datadev))
+ err(-1, "getdevname error");
+
+ msg = open(msgdev, O_RDWR, 0);
+ if (msg < 0)
+ err(-1, "open(%s)", msgdev);
+ timeout = UATH_DATA_TIMEOUT;
+ if (ioctl(msg, USB_SET_RX_TIMEOUT, &timeout) < 0)
+ err(-1, "%s: USB_SET_RX_TIMEOUT(%u)", msgdev, UATH_DATA_TIMEOUT);
+ if (ioctl(msg, USB_SET_RX_BUFFER_SIZE, &bufsize) < 0)
+ err(-1, "%s: USB_SET_RX_BUFFER_SIZE(%u)", msgdev, bufsize);
+
+ data = open(datadev, O_WRONLY, 0);
+ if (data < 0)
+ err(-1, "open(%s)", datadev);
+ timeout = UATH_DATA_TIMEOUT;
+ if (ioctl(data, USB_SET_TX_TIMEOUT, &timeout) < 0)
+ err(-1, "%s: USB_SET_TX_TIMEOUT(%u)", datadev,
+ UATH_DATA_TIMEOUT);
+
+ VERBOSE("Load firmware %s to %s\n", fwname, devname);
+
+ bzero(&txmsg, sizeof (struct uath_fwmsg));
+ txmsg.flags = htobe32(UATH_WRITE_BLOCK);
+ txmsg.total = htobe32(len);
+
+ b = 0;
+ while (len > 0) {
+ int mlen;
+
+ mlen = len;
+ if (mlen > UATH_MAX_FWBLOCK_SIZE)
+ mlen = UATH_MAX_FWBLOCK_SIZE;
+ txmsg.remain = htobe32(len - mlen);
+ txmsg.len = htobe32(mlen);
+
+ /* send firmware block meta-data */
+ VERBOSE("send block %2u: %zd bytes remaining", b, len - mlen);
+ if (write(msg, &txmsg, sizeof(txmsg)) != sizeof(txmsg)) {
+ VERBOSE("%s", "\n");
+ err(-1, "error sending msg (%s)", msgdev);
+ break;
+ }
+
+ /* send firmware block data */
+ VERBOSE("%s", "\n : data...");
+ if (write(data, txdata, mlen) != mlen) {
+ VERBOSE("%s", "\n");
+ err(-1, "error sending data (%s)", datadev);
+ break;
+ }
+
+ /* wait for ack from firmware */
+ VERBOSE("%s", "\n : wait for ack...");
+ bzero(&rxmsg, sizeof(rxmsg));
+ if (read(msg, &rxmsg, sizeof(rxmsg)) != sizeof(rxmsg)) {
+ VERBOSE("%s", "\n");
+ err(-1, "error reading msg (%s)", msgdev);
+ break;
+ }
+
+ VERBOSE("flags=0x%x total=%d\n",
+ be32toh(rxmsg.flags), be32toh(rxmsg.rxtotal));
+ len -= mlen;
+ txdata += mlen;
+ b++;
+ }
+ sleep(1);
+ close(fw);
+ close(msg);
+ close(data);
+ return 0;
+}
diff --git a/usr.sbin/usbconfig/usbconfig.c b/usr.sbin/usbconfig/usbconfig.c
index 5227544..810e183 100644
--- a/usr.sbin/usbconfig/usbconfig.c
+++ b/usr.sbin/usbconfig/usbconfig.c
@@ -501,7 +501,6 @@ main(int argc, char **argv)
{
struct libusb20_backend *pbe;
struct options *opt = &options;
- char *cp;
int n;
int t;
OpenPOWER on IntegriCloud